feat: AI 意图路由/草稿存储 + Prompts 模块化 + UI 视觉统一 + AI 同意门 + 资源更新

后端:
- 新增 ai_intent_router 意图路由
- 新增 AiEntryDraft 草稿存储 + EF 迁移
- 新增 Prompts 模块化(global/modules/rag/router)
- AI Agent handlers 扩展

前端:
- 新增 AI 同意门 (ai_consent_gate/provider/details_page)
- HealthMetricVisuals 视觉统一
- 设备扫描/管理页面优化
- agent 插图替换 + 趋势指标图标

配置:
- DeepSeek 模型改 deepseek-v4-flash
- .gitignore 加 artifacts/audit
- build.gradle.kts 签名配置调整
This commit is contained in:
MingNian
2026-07-28 15:03:38 +08:00
parent 25a4078688
commit b4bc15b9b9
88 changed files with 5527 additions and 1240 deletions

View File

@@ -10,6 +10,7 @@ import '../providers/auth_provider.dart';
import '../providers/chat_provider.dart';
import '../providers/conversation_history_provider.dart';
import 'app_toast.dart';
import 'authenticated_network_image.dart';
import '../providers/data_providers.dart';
import 'drawer_shell.dart';
@@ -136,9 +137,7 @@ class _AccountHeader extends StatelessWidget {
width: 66,
height: 66,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 2),
boxShadow: [
BoxShadow(
color: const Color(0xFF7C5CFF).withValues(alpha: 0.16),
@@ -147,10 +146,33 @@ class _AccountHeader extends StatelessWidget {
),
],
),
child: const Icon(
Icons.person_rounded,
color: Color(0xFF94A3B8),
size: 34,
child: Stack(
fit: StackFit.expand,
children: [
ClipOval(
clipBehavior: Clip.antiAlias,
child: ColoredBox(
color: const Color(0xFFF1F5F9),
child: user?.avatarUrl?.toString().isNotEmpty == true
? AuthenticatedNetworkImage(
imageUrl: user.avatarUrl.toString(),
fit: BoxFit.cover,
width: 66,
height: 66,
errorBuilder: (_, _, _) => const Icon(
Icons.person_rounded,
color: Color(0xFF94A3B8),
size: 34,
),
)
: const Icon(
Icons.person_rounded,
color: Color(0xFF94A3B8),
size: 34,
),
),
),
],
),
),
),
@@ -208,11 +230,6 @@ class _HealthDashboard extends StatelessWidget {
Widget build(BuildContext context) {
return _Panel(
title: '健康仪表盘',
trailing: _TextAction(
label: '详情',
light: true,
onTap: () => pushRoute(ref, 'trend'),
),
titleColor: Colors.white,
backgroundPainter: const _HealthDashboardBackgroundPainter(),
child: latestHealth.when(
@@ -313,7 +330,7 @@ class _MetricTile extends StatelessWidget {
onTap: onTap,
borderRadius: BorderRadius.circular(18),
child: Container(
height: elderMode ? 112 : 100,
height: elderMode ? 108 : 100,
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 10),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.22),
@@ -627,13 +644,11 @@ class _LightSection extends StatelessWidget {
class _Panel extends StatelessWidget {
final String title;
final Widget child;
final Widget? trailing;
final CustomPainter? backgroundPainter;
final Color titleColor;
const _Panel({
required this.title,
required this.child,
this.trailing,
this.backgroundPainter,
this.titleColor = AppColors.textPrimary,
});
@@ -664,20 +679,13 @@ class _Panel extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Text(
title,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: titleColor,
),
),
),
?trailing,
],
Text(
title,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: titleColor,
),
),
const SizedBox(height: 12),
child,
@@ -708,45 +716,6 @@ class _HealthDashboardBackgroundPainter extends CustomPainter {
bool shouldRepaint(_HealthDashboardBackgroundPainter oldDelegate) => false;
}
class _TextAction extends StatelessWidget {
final String label;
final VoidCallback onTap;
final bool light;
const _TextAction({
required this.label,
required this.onTap,
this.light = false,
});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(999),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 11, vertical: 6),
decoration: BoxDecoration(
color: light
? Colors.white.withValues(alpha: 0.24)
: const Color(0xFFEDE9FE),
borderRadius: BorderRadius.circular(999),
border: light
? Border.all(color: Colors.white.withValues(alpha: 0.34))
: null,
),
child: Text(
label,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w700,
color: light ? Colors.white : Color(0xFF6D28D9),
),
),
),
);
}
}
class _IconButton extends StatelessWidget {
final IconData icon;
final VoidCallback onTap;