feat: UI 系统中心化 + 趋势图重构 + 法律文档 H5 上线

- UI 系统: 新增 design_tokens / module_visuals / app_buttons / app_status_badge / app_toast / ai_content 六个共享模块; 28 个页面接入, SnackBar 全部替换为 AppToast
- 趋势图: 直线折线 + 渐变填充 + 阴影; 去网格线; X 轴日+月份分隔; Y 轴整数刻度最多 4 个; 点击数据点/录入记录显示上方浮层, 选中点变实心
- 法律文档 H5: 后端 wwwroot 托管隐私政策/服务协议/关于/个人信息收集清单/第三方 SDK 清单 + 索引页; Program.cs 启用 UseDefaultFiles + UseStaticFiles
- 其他: auth_provider 登录流程调整; api_client IP 适配; 主页智能体栏间距优化
This commit is contained in:
MingNian
2026-07-08 21:25:07 +08:00
parent 7a93237069
commit 1c020b8ae5
45 changed files with 3480 additions and 1000 deletions

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../core/app_colors.dart';
import '../core/app_module_visuals.dart';
import '../core/app_theme.dart';
import '../core/navigation_provider.dart';
import '../providers/auth_provider.dart';
@@ -9,6 +10,7 @@ import '../providers/data_providers.dart';
import '../widgets/common_widgets.dart';
import '../widgets/app_error_state.dart';
import '../widgets/app_future_view.dart';
import '../widgets/app_toast.dart';
/// 饮食记录列表(趋势+日历+胶囊详情+侧滑编辑删除)
class DietRecordListPage extends ConsumerStatefulWidget {
@@ -687,8 +689,9 @@ class ExercisePlanPage extends ConsumerStatefulWidget {
}
class _ExercisePlanPageState extends ConsumerState<ExercisePlanPage> {
static const _exerciseBlue = Color(0xFF60A5FA);
static const _exerciseViolet = Color(0xFF8B5CF6);
static const _exerciseVisual = AppModuleVisuals.exercise;
static const _exerciseBlue = AppColors.exercise;
static const _exerciseViolet = Color(0xFF059669);
Future<List<Map<String, dynamic>>>? _future;
final Set<String> _busyItems = {};
@@ -718,11 +721,10 @@ class _ExercisePlanPageState extends ConsumerState<ExercisePlanPage> {
} catch (e) {
debugPrint('[ExercisePlan] 打卡失败: $e');
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('只能打卡今天的运动任务'),
backgroundColor: AppTheme.error,
),
AppToast.show(
context,
'只能打卡今天的运动任务',
type: AppToastType.error,
);
}
} finally {
@@ -755,7 +757,7 @@ class _ExercisePlanPageState extends ConsumerState<ExercisePlanPage> {
onPressed: () {
pushRoute(ref, 'exerciseCreate');
},
backgroundColor: const Color(0xFF60A5FA),
backgroundColor: AppColors.exercise,
elevation: 0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
child: const Icon(Icons.add, color: Colors.white),
@@ -881,8 +883,8 @@ class _ExercisePlanOverviewCard extends StatelessWidget {
),
borderRadius: BorderRadius.circular(14),
),
child: const Icon(
Icons.directions_run,
child: Icon(
_ExercisePlanPageState._exerciseVisual.icon,
color: Colors.white,
size: 24,
),
@@ -1302,11 +1304,10 @@ class _ExercisePlanDetailPageState
} catch (e) {
debugPrint('[ExercisePlanDetail] 打卡失败: $e');
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('只能打卡今天的运动任务'),
backgroundColor: AppTheme.error,
),
AppToast.show(
context,
'只能打卡今天的运动任务',
type: AppToastType.error,
);
}
} finally {
@@ -1802,9 +1803,7 @@ class _ExercisePlanCreatePageState
Future<void> _save() async {
final name = _nameCtrl.text.trim();
if (name.isEmpty) {
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('请输入运动名称')));
AppToast.show(context, '请输入运动名称', type: AppToastType.warning);
return;
}
final dur = int.tryParse(_durationCtrl.text) ?? 30;
@@ -2325,12 +2324,7 @@ class _HealthArchivePageState extends ConsumerState<HealthArchivePage> {
await ref.read(authProvider.notifier).refreshProfile();
} catch (_) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('保存失败,请重试'),
backgroundColor: AppColors.error,
),
);
AppToast.show(context, '保存失败,请重试', type: AppToastType.error);
}
} finally {
if (mounted) setState(() => _saving = false);