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:
@@ -5,9 +5,11 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../../core/navigation_provider.dart';
|
||||
import '../../core/app_colors.dart';
|
||||
import '../../core/app_module_visuals.dart';
|
||||
import '../../core/app_theme.dart';
|
||||
import '../../providers/auth_provider.dart';
|
||||
import '../../utils/sse_handler.dart';
|
||||
import '../../widgets/app_toast.dart';
|
||||
|
||||
final dietProvider = NotifierProvider<DietNotifier, DietState>(
|
||||
DietNotifier.new,
|
||||
@@ -303,14 +305,11 @@ class DietNotifier extends Notifier<DietState> {
|
||||
}
|
||||
|
||||
// ─────────── 饮食主题色(暖橙系,不再用紫色)───────────
|
||||
const _dietAccent = Color(0xFFF97316);
|
||||
const _dietAccentLight = Color(0xFFFFF3E0);
|
||||
const _dietVisual = AppModuleVisuals.diet;
|
||||
const _dietAccent = AppColors.diet;
|
||||
const _dietAccentLight = AppColors.dietLight;
|
||||
const _dietKcalText = Color(0xFF9A3412);
|
||||
const _dietGradient = LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [Color(0xFFF6D365), Color(0xFFFDA085)],
|
||||
);
|
||||
const _dietGradient = AppColors.dietGradient;
|
||||
|
||||
class DietCapturePage extends ConsumerStatefulWidget {
|
||||
const DietCapturePage({super.key});
|
||||
@@ -362,47 +361,47 @@ class _DietCapturePageState extends ConsumerState<DietCapturePage> {
|
||||
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 24),
|
||||
child: Column(
|
||||
children: [
|
||||
// 图片自适应显示
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
border: Border.all(color: AppColors.borderLight),
|
||||
boxShadow: AppColors.cardShadowLight,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
child: Image.file(
|
||||
File(state.imagePath!),
|
||||
width: screenW - 48,
|
||||
height: 220,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// 图片自适应显示
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
border: Border.all(color: AppColors.borderLight),
|
||||
boxShadow: AppColors.cardShadowLight,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
child: Image.file(
|
||||
File(state.imagePath!),
|
||||
width: screenW - 48,
|
||||
height: 220,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildMealSelector(ref),
|
||||
const SizedBox(height: 16),
|
||||
if (state.isAnalyzing)
|
||||
_buildAnalyzing(state)
|
||||
else if (state.foods.isEmpty)
|
||||
_buildNoFoodHint()
|
||||
else ...[
|
||||
_buildFoodList(ref),
|
||||
const SizedBox(height: 16),
|
||||
_buildMealSelector(ref),
|
||||
const SizedBox(height: 16),
|
||||
if (state.isAnalyzing)
|
||||
_buildAnalyzing(state)
|
||||
else if (state.foods.isEmpty)
|
||||
_buildNoFoodHint()
|
||||
else ...[
|
||||
_buildFoodList(ref),
|
||||
_buildNutritionCard(ref),
|
||||
if (state.commentary != null && state.commentary!.isNotEmpty) ...[
|
||||
const SizedBox(height: 16),
|
||||
_buildNutritionCard(ref),
|
||||
if (state.commentary != null && state.commentary!.isNotEmpty) ...[
|
||||
const SizedBox(height: 16),
|
||||
_buildAiCommentary(state.commentary!),
|
||||
],
|
||||
const SizedBox(height: 20),
|
||||
_buildSaveButton(),
|
||||
_buildAiCommentary(state.commentary!),
|
||||
],
|
||||
const SizedBox(height: 20),
|
||||
_buildSaveButton(),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -931,11 +930,7 @@ class _DietCapturePageState extends ConsumerState<DietCapturePage> {
|
||||
color: _dietAccentLight,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.auto_awesome,
|
||||
size: 20,
|
||||
color: _dietAccent,
|
||||
),
|
||||
child: Icon(_dietVisual.icon, size: 20, color: _dietAccent),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
@@ -981,6 +976,13 @@ class _DietCapturePageState extends ConsumerState<DietCapturePage> {
|
||||
if (mounted) popRoute(ref);
|
||||
} catch (e) {
|
||||
debugPrint('[Diet] 保存记录失败: $e');
|
||||
if (mounted) {
|
||||
AppToast.show(
|
||||
context,
|
||||
'保存失败,请检查网络后重试',
|
||||
type: AppToastType.error,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: const Row(
|
||||
|
||||
Reference in New Issue
Block a user