|
@@ -1,5 +1,6 @@
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
|
+import 'package:path_provider/path_provider.dart';
|
|
|
import '../../services/api_service.dart';
|
|
import '../../services/api_service.dart';
|
|
|
import '../../providers/app_provider.dart';
|
|
import '../../providers/app_provider.dart';
|
|
|
|
|
|
|
@@ -27,10 +28,7 @@ class _ExportPageState extends ConsumerState<ExportPage> {
|
|
|
} else {
|
|
} else {
|
|
|
data = await api.exportChapter(null, null, '全部导出');
|
|
data = await api.exportChapter(null, null, '全部导出');
|
|
|
}
|
|
}
|
|
|
- setState(() {
|
|
|
|
|
- _result = data;
|
|
|
|
|
- _exporting = false;
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ setState(() { _result = data; _exporting = false; });
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
setState(() => _exporting = false);
|
|
setState(() => _exporting = false);
|
|
|
if (mounted) {
|
|
if (mounted) {
|
|
@@ -41,10 +39,28 @@ class _ExportPageState extends ConsumerState<ExportPage> {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @override
|
|
|
|
|
- Widget build(BuildContext context) {
|
|
|
|
|
|
|
+ Future<void> _downloadFile(String filename, String label) async {
|
|
|
final api = ref.read(apiServiceProvider);
|
|
final api = ref.read(apiServiceProvider);
|
|
|
|
|
+ try {
|
|
|
|
|
+ final dir = await getApplicationDocumentsDirectory();
|
|
|
|
|
+ final savePath = '${dir.path}/$filename';
|
|
|
|
|
+ await api.downloadExport(filename, savePath);
|
|
|
|
|
+ if (mounted) {
|
|
|
|
|
+ ScaffoldMessenger.of(context).showSnackBar(
|
|
|
|
|
+ SnackBar(content: Text('$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(
|
|
return Scaffold(
|
|
|
appBar: AppBar(title: Text(widget.cartName != null ? '导出: ${widget.cartName}' : '导出')),
|
|
appBar: AppBar(title: Text(widget.cartName != null ? '导出: ${widget.cartName}' : '导出')),
|
|
|
body: Center(
|
|
body: Center(
|
|
@@ -59,16 +75,11 @@ class _ExportPageState extends ConsumerState<ExportPage> {
|
|
|
const Text('将生成学生版和教师版两份 docx 文件'),
|
|
const Text('将生成学生版和教师版两份 docx 文件'),
|
|
|
const SizedBox(height: 24),
|
|
const SizedBox(height: 24),
|
|
|
SizedBox(
|
|
SizedBox(
|
|
|
- width: 200,
|
|
|
|
|
- height: 48,
|
|
|
|
|
|
|
+ width: 200, height: 48,
|
|
|
child: FilledButton.icon(
|
|
child: FilledButton.icon(
|
|
|
onPressed: _exporting ? null : _doExport,
|
|
onPressed: _exporting ? null : _doExport,
|
|
|
icon: _exporting
|
|
icon: _exporting
|
|
|
- ? const SizedBox(
|
|
|
|
|
- width: 20,
|
|
|
|
|
- height: 20,
|
|
|
|
|
- child: CircularProgressIndicator(strokeWidth: 2),
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ ? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2))
|
|
|
: const Icon(Icons.file_download),
|
|
: const Icon(Icons.file_download),
|
|
|
label: Text(_exporting ? '生成中...' : '导出 docx'),
|
|
label: Text(_exporting ? '生成中...' : '导出 docx'),
|
|
|
),
|
|
),
|
|
@@ -78,29 +89,26 @@ class _ExportPageState extends ConsumerState<ExportPage> {
|
|
|
const SizedBox(height: 24),
|
|
const SizedBox(height: 24),
|
|
|
Text('导出成功!共 ${_result!['count']} 题'),
|
|
Text('导出成功!共 ${_result!['count']} 题'),
|
|
|
const SizedBox(height: 16),
|
|
const SizedBox(height: 16),
|
|
|
- // Download links
|
|
|
|
|
FilledButton.tonal(
|
|
FilledButton.tonal(
|
|
|
- onPressed: () {
|
|
|
|
|
- // Launch download URL
|
|
|
|
|
- },
|
|
|
|
|
- child: const Row(
|
|
|
|
|
|
|
+ onPressed: () => _downloadFile(_result!['student'] as String, '学生版'),
|
|
|
|
|
+ child: Row(
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
children: [
|
|
children: [
|
|
|
- Icon(Icons.download),
|
|
|
|
|
- SizedBox(width: 8),
|
|
|
|
|
- Text('学生版: ...'),
|
|
|
|
|
|
|
+ const Icon(Icons.download, size: 18),
|
|
|
|
|
+ const SizedBox(width: 8),
|
|
|
|
|
+ Text('学生版: ${_result!['student']}'),
|
|
|
],
|
|
],
|
|
|
),
|
|
),
|
|
|
),
|
|
),
|
|
|
const SizedBox(height: 8),
|
|
const SizedBox(height: 8),
|
|
|
FilledButton.tonal(
|
|
FilledButton.tonal(
|
|
|
- onPressed: () {},
|
|
|
|
|
- child: const Row(
|
|
|
|
|
|
|
+ onPressed: () => _downloadFile(_result!['teacher'] as String, '教师版'),
|
|
|
|
|
+ child: Row(
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
children: [
|
|
children: [
|
|
|
- Icon(Icons.download),
|
|
|
|
|
- SizedBox(width: 8),
|
|
|
|
|
- Text('教师版: ...'),
|
|
|
|
|
|
|
+ const Icon(Icons.download, size: 18),
|
|
|
|
|
+ const SizedBox(width: 8),
|
|
|
|
|
+ Text('教师版: ${_result!['teacher']}'),
|
|
|
],
|
|
],
|
|
|
),
|
|
),
|
|
|
),
|
|
),
|