声音功能
This commit is contained in:
@@ -28,6 +28,7 @@ class _BugListPageState extends State<BugListPage> {
|
||||
'resolveTime': '2026-04-15',
|
||||
'reportTime': '2026-03-25',
|
||||
'affectedUsers': '部分用户',
|
||||
'expanded': false, // 添加展开状态
|
||||
},
|
||||
{
|
||||
'id': 2,
|
||||
@@ -39,6 +40,7 @@ class _BugListPageState extends State<BugListPage> {
|
||||
'resolveTime': '2026-04-10',
|
||||
'reportTime': '2026-03-20',
|
||||
'affectedUsers': '大量用户',
|
||||
'expanded': false, // 添加展开状态
|
||||
},
|
||||
{
|
||||
'id': 3,
|
||||
@@ -50,6 +52,7 @@ class _BugListPageState extends State<BugListPage> {
|
||||
'resolveTime': '2026-03-28',
|
||||
'reportTime': '2026-03-15',
|
||||
'affectedUsers': '少数用户',
|
||||
'expanded': false, // 添加展开状态
|
||||
},
|
||||
{
|
||||
'id': 4,
|
||||
@@ -61,6 +64,7 @@ class _BugListPageState extends State<BugListPage> {
|
||||
'resolveTime': '2026-04-20',
|
||||
'reportTime': '2026-03-22',
|
||||
'affectedUsers': '部分用户',
|
||||
'expanded': false, // 添加展开状态
|
||||
},
|
||||
{
|
||||
'id': 5,
|
||||
@@ -72,12 +76,24 @@ class _BugListPageState extends State<BugListPage> {
|
||||
'resolveTime': '2026-03-26',
|
||||
'reportTime': '2026-03-18',
|
||||
'affectedUsers': '少数用户',
|
||||
'expanded': false, // 添加展开状态
|
||||
},
|
||||
];
|
||||
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
bool _isRefreshing = false;
|
||||
|
||||
// 切换bug展开状态
|
||||
void _toggleBugExpanded(int bugId) {
|
||||
setState(() {
|
||||
final bugIndex = _bugs.indexWhere((bug) => bug['id'] == bugId);
|
||||
if (bugIndex != -1) {
|
||||
_bugs[bugIndex]['expanded'] = !_bugs[bugIndex]['expanded'];
|
||||
}
|
||||
});
|
||||
HapticFeedback.lightImpact();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
@@ -231,6 +247,8 @@ class _BugListPageState extends State<BugListPage> {
|
||||
}
|
||||
|
||||
Widget _buildBugItem(Map<String, dynamic> bug) {
|
||||
final bool isExpanded = bug['expanded'] ?? false;
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 16),
|
||||
decoration: BoxDecoration(
|
||||
@@ -352,87 +370,116 @@ class _BugListPageState extends State<BugListPage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 分割线
|
||||
const Divider(height: 1),
|
||||
// 解决方案区域
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[50],
|
||||
borderRadius: const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(12),
|
||||
bottomRight: Radius.circular(12),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.lightbulb_outline,
|
||||
color: AppConstants.primaryColor,
|
||||
size: 16,
|
||||
const SizedBox(height: 12),
|
||||
// 解决方案按钮
|
||||
Container(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () => _toggleBugExpanded(bug['id']),
|
||||
icon: Icon(
|
||||
isExpanded ? Icons.expand_less : Icons.expand_more,
|
||||
size: 18,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'解决方案',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppConstants.primaryColor,
|
||||
label: Text(
|
||||
isExpanded ? '收起解决方案' : '查看解决方案',
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppConstants.primaryColor.withValues(alpha: 0.1),
|
||||
foregroundColor: AppConstants.primaryColor,
|
||||
elevation: 0,
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(
|
||||
color: AppConstants.primaryColor.withValues(alpha: 0.3),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
bug['solution'] ?? '暂无解决方案',
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.black54,
|
||||
height: 1.4,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
// 时间信息
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.schedule,
|
||||
size: 14,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'预计解决: ${bug['resolveTime'] ?? '待定'}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Icon(
|
||||
Icons.report,
|
||||
size: 14,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'报告时间: ${bug['reportTime'] ?? '未知'}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 解决方案区域(可展开/收起)
|
||||
if (isExpanded) ...[
|
||||
const Divider(height: 1),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[50],
|
||||
borderRadius: const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(12),
|
||||
bottomRight: Radius.circular(12),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.lightbulb_outline,
|
||||
color: AppConstants.primaryColor,
|
||||
size: 16,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'解决方案',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppConstants.primaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
bug['solution'] ?? '暂无解决方案',
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.black54,
|
||||
height: 1.4,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
// 时间信息
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.schedule,
|
||||
size: 14,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'预计解决: ${bug['resolveTime'] ?? '待定'}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Icon(
|
||||
Icons.report,
|
||||
size: 14,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'报告时间: ${bug['reportTime'] ?? '未知'}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -6,6 +6,8 @@ import 'package:intl/intl.dart';
|
||||
|
||||
import '../../../constants/app_constants.dart';
|
||||
import '../../../controllers/sqlite_storage_controller.dart';
|
||||
import '../../../controllers/history_controller.dart';
|
||||
import '../../../services/network_listener_service.dart';
|
||||
|
||||
/// 时间: 2026-03-28
|
||||
/// 功能: 答题记录页面
|
||||
@@ -177,28 +179,68 @@ class _DistinguishPageState extends State<DistinguishPage> {
|
||||
|
||||
// 标题
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: AppConstants.primaryColor.withAlpha(20),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.analytics_outlined,
|
||||
color: AppConstants.primaryColor,
|
||||
size: 24,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: AppConstants.primaryColor.withAlpha(20),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.analytics_outlined,
|
||||
color: AppConstants.primaryColor,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const Text(
|
||||
'本次答题记录',
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const Text(
|
||||
'答题记录',
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black87,
|
||||
// 复制内容按钮
|
||||
if (_answerRecords.isNotEmpty)
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppConstants.primaryColor.withAlpha(15),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: AppConstants.primaryColor.withAlpha(50),
|
||||
width: 0.5,
|
||||
),
|
||||
),
|
||||
child: TextButton.icon(
|
||||
onPressed: _copyStatisticsContent,
|
||||
icon: Icon(
|
||||
Icons.copy,
|
||||
size: 16,
|
||||
color: Colors.orange[700],
|
||||
),
|
||||
label: Text(
|
||||
'添加笔记',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.orange[700],
|
||||
),
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 6,
|
||||
),
|
||||
minimumSize: Size.zero,
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
@@ -703,4 +745,153 @@ $_poetryLevel
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 写入统计数据到笔记
|
||||
Future<void> _copyStatisticsContent() async {
|
||||
try {
|
||||
// 生成完整的评估报告内容
|
||||
final StringBuffer content = StringBuffer();
|
||||
content.writeln('🎓 诗词答题记录评估报告');
|
||||
content.writeln('');
|
||||
content.writeln('📊 基础数据统计');
|
||||
content.writeln('━━━━━━━━━━━━━━━━');
|
||||
content.writeln('• 已答题数:$_totalQuestions 题');
|
||||
content.writeln('• 正确数量:$_correctAnswers 题');
|
||||
content.writeln('• 错误数量:$_wrongAnswers 题');
|
||||
content.writeln('• 正确率:${_correctRate.toStringAsFixed(1)}%');
|
||||
content.writeln('• 错误率:${_wrongRate.toStringAsFixed(1)}%');
|
||||
content.writeln('• 平均用时:${_averageTime.toStringAsFixed(1)} 秒/题');
|
||||
content.writeln('');
|
||||
content.writeln('📈 辅助数据');
|
||||
content.writeln('━━━━━━━━━━━━━━━━');
|
||||
content.writeln('• 提示次数:$_hintCount 次');
|
||||
content.writeln('• 跳过次数:$_skipCount 次');
|
||||
content.writeln('');
|
||||
content.writeln('🏆 诗词水平评估');
|
||||
content.writeln('━━━━━━━━━━━━━━━━');
|
||||
content.writeln('$_poetryLevel');
|
||||
content.writeln('');
|
||||
content.writeln('💡 AI评估提示');
|
||||
content.writeln('━━━━━━━━━━━━━━━━');
|
||||
content.writeln('请根据以上答题数据,综合评估我的诗词水平,并给出:');
|
||||
content.writeln('1. 当前诗词水平的详细分析');
|
||||
content.writeln('2. 薄弱环节和改进建议');
|
||||
content.writeln('3. 推荐学习的诗词类型或朝代');
|
||||
content.writeln('4. 适合的诗词学习路径建议');
|
||||
content.writeln('');
|
||||
content.writeln('感谢您的评估!');
|
||||
|
||||
// 保存到笔记
|
||||
final noteId = await HistoryController.saveNote(
|
||||
title: '诗词答题评估_${DateFormat('yyyyMMdd_HHmmss').format(DateTime.now())}',
|
||||
content: content.toString(),
|
||||
category: '答题评估',
|
||||
);
|
||||
|
||||
if (noteId != null) {
|
||||
NetworkListenerService().sendSuccessEvent(
|
||||
NetworkEventType.noteUpdate,
|
||||
data: noteId,
|
||||
);
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('评估报告已保存到笔记'),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('保存笔记失败: $e');
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('保存笔记失败: $e')));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 从答题记录创建笔记
|
||||
Future<void> _createNoteFromRecords() async {
|
||||
try {
|
||||
// 生成答题记录的详细内容
|
||||
final StringBuffer content = StringBuffer();
|
||||
content.writeln('## 答题记录汇总');
|
||||
content.writeln(
|
||||
'生成时间: ${DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now())}',
|
||||
);
|
||||
content.writeln('总记录数: ${_answerRecords.length}');
|
||||
content.writeln('');
|
||||
|
||||
// 统计信息
|
||||
int correctCount = 0;
|
||||
int totalCount = _answerRecords.length;
|
||||
|
||||
for (final record in _answerRecords) {
|
||||
if (record['isCorrect'] == true) {
|
||||
correctCount++;
|
||||
}
|
||||
}
|
||||
|
||||
content.writeln('### 统计信息');
|
||||
content.writeln('- 总题数: $totalCount');
|
||||
content.writeln('- 答对数: $correctCount');
|
||||
content.writeln('- 答错数: ${totalCount - correctCount}');
|
||||
content.writeln(
|
||||
'- 正确率: ${totalCount > 0 ? (correctCount / totalCount * 100).toStringAsFixed(1) : 0}%',
|
||||
);
|
||||
content.writeln('');
|
||||
|
||||
content.writeln('### 详细记录');
|
||||
content.writeln('');
|
||||
|
||||
for (int i = 0; i < _answerRecords.length; i++) {
|
||||
final record = _answerRecords[i];
|
||||
final question = record['question'] ?? '未知题目';
|
||||
final userAnswer = record['userAnswer'] ?? '未知答案';
|
||||
final correctAnswer = record['correctAnswer'] ?? '未知答案';
|
||||
final isCorrect = record['isCorrect'] == true;
|
||||
final answerTime = record['answerTime'] ?? '未知时间';
|
||||
final tags = record['tags'] as List<dynamic>? ?? [];
|
||||
|
||||
content.writeln('#### ${i + 1}. $question');
|
||||
content.writeln('- **你的答案**: $userAnswer');
|
||||
content.writeln('- **正确答案**: $correctAnswer');
|
||||
content.writeln('- **答题结果**: ${isCorrect ? '✅ 正确' : '❌ 错误'}');
|
||||
content.writeln('- **答题时间**: ${_formatTime(answerTime)}');
|
||||
|
||||
if (tags.isNotEmpty) {
|
||||
content.writeln('- **标签**: ${tags.join(', ')}');
|
||||
}
|
||||
|
||||
content.writeln('');
|
||||
}
|
||||
|
||||
final noteId = await HistoryController.saveNote(
|
||||
title: '答题记录_${DateFormat('yyyyMMdd_HHmmss').format(DateTime.now())}',
|
||||
content: content.toString(),
|
||||
category: '答题记录',
|
||||
);
|
||||
|
||||
if (noteId != null) {
|
||||
NetworkListenerService().sendSuccessEvent(
|
||||
NetworkEventType.noteUpdate,
|
||||
data: noteId,
|
||||
);
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(const SnackBar(content: Text('答题记录已保存到笔记')));
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('创建笔记失败: $e');
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('创建笔记失败: $e')));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,10 +25,12 @@ class _AppFunSettingsPageState extends State<AppFunSettingsPage> {
|
||||
bool _darkModeEnabled = false;
|
||||
bool _preloadEnabled = true;
|
||||
bool _notificationEnabled = true;
|
||||
bool _globalTipsEnabled = true; // 添加全局Tips开关状态
|
||||
int _cacheSize = 128;
|
||||
|
||||
static const String _autoRefreshKey = 'auto_refresh_enabled';
|
||||
static const String _debugInfoKey = 'debug_info_enabled';
|
||||
static const String _globalTipsKey = 'global_tips_enabled'; // 添加全局Tips开关key
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -42,6 +44,8 @@ class _AppFunSettingsPageState extends State<AppFunSettingsPage> {
|
||||
setState(() {
|
||||
_autoRefreshEnabled = prefs.getBool(_autoRefreshKey) ?? false;
|
||||
_debugInfoEnabled = prefs.getBool(_debugInfoKey) ?? false;
|
||||
_globalTipsEnabled =
|
||||
prefs.getBool(_globalTipsKey) ?? true; // 加载全局Tips开关状态
|
||||
_preloadEnabled = prefs.getBool('preload_enabled') ?? true;
|
||||
});
|
||||
}
|
||||
@@ -78,6 +82,17 @@ class _AppFunSettingsPageState extends State<AppFunSettingsPage> {
|
||||
}
|
||||
}
|
||||
|
||||
// 设置全局Tips开关
|
||||
Future<void> _setGlobalTips(bool value) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool(_globalTipsKey, value);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_globalTipsEnabled = value;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@@ -143,8 +158,8 @@ class _AppFunSettingsPageState extends State<AppFunSettingsPage> {
|
||||
'全局Tips开关',
|
||||
'显示一些使用技巧',
|
||||
Icons.volume_up,
|
||||
_soundEnabled,
|
||||
(value) => setState(() => _soundEnabled = value),
|
||||
_globalTipsEnabled,
|
||||
(value) => _setGlobalTips(value),
|
||||
),
|
||||
_buildSwitchItem(
|
||||
'声音反馈',
|
||||
@@ -420,6 +435,7 @@ class _AppFunSettingsPageState extends State<AppFunSettingsPage> {
|
||||
setState(() {
|
||||
_soundEnabled = true;
|
||||
_vibrationEnabled = true;
|
||||
_globalTipsEnabled = true; // 重置全局Tips开关为开启
|
||||
_darkModeEnabled = false;
|
||||
_notificationEnabled = true;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user