| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- import 'package:flutter/material.dart';
- import 'package:flutter/services.dart';
- import 'package:flutter_riverpod/flutter_riverpod.dart';
- import 'package:path_provider/path_provider.dart';
- import '../../services/api_service.dart';
- import '../../providers/app_provider.dart';
- const _channel = MethodChannel('com.tiku/file_picker');
- class ExportPage extends ConsumerStatefulWidget {
- final int? cartId;
- final String? cartName;
- const ExportPage({super.key, this.cartId, this.cartName});
- @override
- ConsumerState<ExportPage> createState() => _ExportPageState();
- }
- class _ExportPageState extends ConsumerState<ExportPage> {
- bool _exporting = false;
- Map<String, dynamic>? _result;
- Future<void> _doExport() async {
- setState(() => _exporting = true);
- final api = ref.read(apiServiceProvider);
- try {
- Map<String, dynamic> data;
- if (widget.cartId != null) {
- data = await api.exportCart(widget.cartId!, widget.cartName ?? '试题篮导出');
- } else {
- data = await api.exportChapter(null, null, '全部导出');
- }
- setState(() { _result = data; _exporting = false; });
- } catch (e) {
- setState(() => _exporting = false);
- if (mounted) {
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(content: Text('导出失败: $e')),
- );
- }
- }
- }
- Future<void> _downloadFile(String filename, String label) async {
- final api = ref.read(apiServiceProvider);
- try {
- // Step 1: download to cache
- final dir = await getApplicationDocumentsDirectory();
- final tmpPath = '${dir.path}/$filename';
- await api.downloadExport(filename, tmpPath);
- // Step 2: let user choose save location
- final saved = await _channel.invokeMethod<bool>('saveFile', {
- 'filePath': tmpPath,
- 'fileName': filename,
- });
- if (mounted) {
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text(saved == true ? '$label 已保存' : '已取消'),
- duration: const Duration(seconds: 2),
- ),
- );
- }
- } catch (e) {
- if (mounted) {
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(content: Text('下载失败: $e')),
- );
- }
- }
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(title: Text(widget.cartName != null ? '导出: ${widget.cartName}' : '导出')),
- body: Center(
- child: Padding(
- padding: const EdgeInsets.all(32),
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- if (_result == null) ...[
- const Icon(Icons.picture_as_pdf, size: 80, color: Colors.blue),
- const SizedBox(height: 24),
- const Text('将生成学生版和教师版两份 docx 文件'),
- const SizedBox(height: 24),
- SizedBox(
- width: 200, height: 48,
- child: FilledButton.icon(
- onPressed: _exporting ? null : _doExport,
- icon: _exporting
- ? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2))
- : const Icon(Icons.file_download),
- label: Text(_exporting ? '生成中...' : '导出 docx'),
- ),
- ),
- ] else ...[
- const Icon(Icons.check_circle, size: 80, color: Colors.green),
- const SizedBox(height: 24),
- Text('导出成功!共 ${_result!['count']} 题'),
- const SizedBox(height: 16),
- FilledButton.tonal(
- onPressed: () => _downloadFile(_result!['student'] as String, '学生版.docx'),
- child: const Row(mainAxisSize: MainAxisSize.min, children: [
- Icon(Icons.download, size: 18), SizedBox(width: 8), Text('学生版'),
- ]),
- ),
- const SizedBox(height: 8),
- FilledButton.tonal(
- onPressed: () => _downloadFile(_result!['teacher'] as String, '教师版.docx'),
- child: const Row(mainAxisSize: MainAxisSize.min, children: [
- Icon(Icons.download, size: 18), SizedBox(width: 8), Text('教师版'),
- ]),
- ),
- const SizedBox(height: 16),
- TextButton(
- onPressed: () => Navigator.pop(context),
- child: const Text('返回'),
- ),
- ],
- ],
- ),
- ),
- ),
- );
- }
- }
|