fix: VLM识别修复 + 饮食CRUD + 侧边栏美化 + UI优化

- VLM: ChatMessage.Content string→object, 修复视觉content双重序列化
- 饮食: diet/medication端点 record→手动JSON解析, 修复循环引用
- 饮食记录: 左滑删除 + 去评分 + AI饮食评语(DeepSeek)
- 侧边栏: 功能区统一Row+Expanded, 服务包compact模式
- 历史对话: 点击加载历史消息
- 登录页: 居中布局, 去底部空白
- UI: 主色加深#6C5CE7, maxWidth:1024防图片超大
This commit is contained in:
MingNian
2026-06-04 16:27:03 +08:00
parent c44917b8e9
commit b944a31983
12 changed files with 413 additions and 305 deletions

View File

@@ -119,51 +119,47 @@ class HealthDrawer extends ConsumerWidget {
const SizedBox(height: 10),
// ════════════ 功能区(横向布)════════════
// ════════════ 功能区(横向布)════════════
_SectionCard(
color: Colors.white,
gradientColors: null,
child: Padding(
padding: const EdgeInsets.fromLTRB(14, 12, 14, 14),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Row(children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
decoration: BoxDecoration(
color: const Color(0xFFF0A060).withAlpha(15),
borderRadius: BorderRadius.circular(6),
),
child: const Row(mainAxisSize: MainAxisSize.min, children: [
Icon(Icons.apps_rounded, size: 13, color: Color(0xFFF0A060)),
SizedBox(width: 4),
Text('功能', style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFFF0A060))),
]),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(16, 14, 16, 6),
child: Row(children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
decoration: BoxDecoration(
color: const Color(0xFFF0A060).withAlpha(15),
borderRadius: BorderRadius.circular(6),
),
]),
),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
_FeatureChip(icon: Icons.description_outlined, label: '报告管理', onTap: () => pushRoute(ref, 'reports')),
_FeatureChip(icon: Icons.calendar_today_outlined, label: '健康日历', onTap: () => pushRoute(ref, 'calendar')),
_FeatureChip(icon: Icons.restaurant_outlined, label: '饮食记录', onTap: () => pushRoute(ref, 'dietRecords')),
_FeatureChip(icon: Icons.event_note_outlined, label: '复查随访', onTap: () => pushRoute(ref, 'followups')),
],
),
],
),
child: const Row(mainAxisSize: MainAxisSize.min, children: [
Icon(Icons.apps_rounded, size: 13, color: Color(0xFFF0A060)),
SizedBox(width: 4),
Text('功能', style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFFF0A060))),
]),
),
]),
),
Padding(
padding: const EdgeInsets.fromLTRB(12, 4, 12, 14),
child: Row(children: [
_FeatureChip(icon: Icons.description_outlined, label: '报告管理', onTap: () => pushRoute(ref, 'reports')),
_FeatureChip(icon: Icons.calendar_today_outlined, label: '健康日历', onTap: () => pushRoute(ref, 'calendar')),
_FeatureChip(icon: Icons.restaurant_outlined, label: '饮食记录', onTap: () => pushRoute(ref, 'dietRecords')),
_FeatureChip(icon: Icons.event_note_outlined, label: '复查随访', onTap: () => pushRoute(ref, 'followups')),
]),
),
],
),
),
const SizedBox(height: 10),
// ════════════ 产品服务包 ════════════
const ServicePackageCard(),
const ServicePackageCard(compact: true),
const SizedBox(height: 10),
@@ -196,7 +192,7 @@ class HealthDrawer extends ConsumerWidget {
),
]),
),
_buildConversationList(ref, conversations),
_buildConversationList(context, ref, conversations),
],
),
),
@@ -253,7 +249,7 @@ class HealthDrawer extends ConsumerWidget {
return metric.toString();
}
Widget _buildConversationList(WidgetRef ref, AsyncValue<List<ConversationItem>> conversations) {
Widget _buildConversationList(BuildContext context, WidgetRef ref, AsyncValue<List<ConversationItem>> conversations) {
return conversations.when(
data: (items) {
if (items.isEmpty) {
@@ -268,7 +264,13 @@ class HealthDrawer extends ConsumerWidget {
padding: const EdgeInsets.fromLTRB(8, 6, 8, 14),
child: Column(
mainAxisSize: MainAxisSize.min,
children: items.map((item) => _ConversationItem(item: item)).toList(),
children: items.map((item) => _ConversationItem(
item: item,
onTap: () {
ref.read(chatProvider.notifier).loadConversation(item.id);
Navigator.of(context).pop(); // 关闭抽屉
},
)).toList(),
),
);
},
@@ -394,22 +396,20 @@ class _FeatureChip extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
child: InkWell(
return Expanded(
child: GestureDetector(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 3),
padding: const EdgeInsets.symmetric(vertical: 10),
decoration: BoxDecoration(
color: _c.withAlpha(10),
borderRadius: BorderRadius.circular(12),
),
child: Row(mainAxisSize: MainAxisSize.min, children: [
Icon(icon, size: 17, color: _c),
const SizedBox(width: 6),
Text(label, style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: _c)),
child: Column(mainAxisSize: MainAxisSize.min, children: [
Icon(icon, size: 18, color: _c),
const SizedBox(height: 6),
Text(label, style: const TextStyle(fontSize: 10, fontWeight: FontWeight.w500, color: Color(0xFF666666))),
]),
),
),
@@ -423,8 +423,9 @@ class _FeatureChip extends StatelessWidget {
class _ConversationItem extends StatelessWidget {
final ConversationItem item;
final VoidCallback? onTap;
const _ConversationItem({required this.item});
const _ConversationItem({required this.item, this.onTap});
@override
Widget build(BuildContext context) {
@@ -436,6 +437,7 @@ class _ConversationItem extends StatelessWidget {
border: Border.all(color: const Color(0xFFEEEEEE)),
),
child: ListTile(
onTap: onTap,
contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 2),
leading: Container(
width: 32, height: 32,