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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user