import 'package:flutter/material.dart'; import '../../../core/network/ai_api_service.dart'; /// AI写作批改页面 class AIWritingPage extends StatefulWidget { const AIWritingPage({Key? key}) : super(key: key); @override State createState() => _AIWritingPageState(); } class _AIWritingPageState extends State { final TextEditingController _contentController = TextEditingController(); final AIApiService _aiApiService = AIApiService(); String _selectedType = 'essay'; bool _isLoading = false; Map? _correctionResult; String? _error; final List> _writingTypes = [ {'value': 'essay', 'label': '议论文'}, {'value': 'email', 'label': '邮件'}, {'value': 'report', 'label': '报告'}, {'value': 'letter', 'label': '信件'}, {'value': 'story', 'label': '故事'}, ]; @override void dispose() { _contentController.dispose(); super.dispose(); } Future _submitForCorrection() async { if (_contentController.text.trim().isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('请输入要批改的内容')), ); return; } setState(() { _isLoading = true; _error = null; _correctionResult = null; }); try { final result = await _aiApiService.correctWriting( content: _contentController.text.trim(), taskType: _selectedType, ); setState(() { _correctionResult = result; _isLoading = false; }); } catch (e) { setState(() { _error = e.toString(); _isLoading = false; }); } } void _clearContent() { setState(() { _contentController.clear(); _correctionResult = null; _error = null; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('AI写作批改'), backgroundColor: Theme.of(context).primaryColor, foregroundColor: Colors.white, actions: [ IconButton( icon: const Icon(Icons.clear), onPressed: _clearContent, tooltip: '清空内容', ), ], ), body: SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 写作类型选择 Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '写作类型', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 12), Wrap( spacing: 8, children: _writingTypes.map((type) { final isSelected = _selectedType == type['value']; return ChoiceChip( label: Text(type['label']!), selected: isSelected, onSelected: (selected) { if (selected) { setState(() { _selectedType = type['value']!; }); } }, ); }).toList(), ), ], ), ), ), const SizedBox(height: 16), // 内容输入区域 Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '写作内容', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 12), TextField( controller: _contentController, maxLines: 10, decoration: const InputDecoration( hintText: '请输入您的英文写作内容...', border: OutlineInputBorder(), contentPadding: EdgeInsets.all(12), ), ), const SizedBox(height: 16), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _isLoading ? null : _submitForCorrection, style: ElevatedButton.styleFrom( backgroundColor: Theme.of(context).primaryColor, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), ), child: _isLoading ? const Row( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ), SizedBox(width: 8), Text('AI批改中...'), ], ) : const Text( '开始AI批改', style: TextStyle(fontSize: 16), ), ), ), ], ), ), ), const SizedBox(height: 16), // 错误显示 if (_error != null) Card( color: Colors.red.shade50, child: Padding( padding: const EdgeInsets.all(16.0), child: Row( children: [ Icon(Icons.error, color: Colors.red.shade700), const SizedBox(width: 8), Expanded( child: Text( _error!, style: TextStyle(color: Colors.red.shade700), ), ), ], ), ), ), // 批改结果显示 if (_correctionResult != null) Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( Icons.check_circle, color: Colors.green.shade600, ), const SizedBox(width: 8), const Text( 'AI批改结果', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), ], ), const SizedBox(height: 16), // 总体评分 if (_correctionResult!['score'] != null) Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.blue.shade50, borderRadius: BorderRadius.circular(8), ), child: Row( children: [ const Icon(Icons.star, color: Colors.amber), const SizedBox(width: 8), Text( '总体评分: ${_correctionResult!['score']}/100', style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ], ), ), const SizedBox(height: 12), // 批改建议 if (_correctionResult!['suggestions'] != null) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '批改建议:', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), Text( _correctionResult!['suggestions'].toString(), style: const TextStyle(fontSize: 14), ), ], ), // 错误列表 if (_correctionResult!['errors'] != null) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 16), const Text( '发现的错误:', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), ...(_correctionResult!['errors'] as List).map( (error) => Container( margin: const EdgeInsets.only(bottom: 8), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.orange.shade50, borderRadius: BorderRadius.circular(8), border: Border.all( color: Colors.orange.shade200, ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '错误类型: ${error['type'] ?? '未知'}', style: TextStyle( fontWeight: FontWeight.bold, color: Colors.orange.shade700, ), ), if (error['original'] != null) Text('原文: ${error['original']}'), if (error['corrected'] != null) Text( '建议: ${error['corrected']}', style: TextStyle( color: Colors.green.shade700, fontWeight: FontWeight.bold, ), ), if (error['explanation'] != null) Text( '说明: ${error['explanation']}', style: const TextStyle(fontSize: 12), ), ], ), ), ), ], ), ], ), ), ), ], ), ), ); } }