Files
AI-Health/health_app/lib/widgets/ai_content.dart
MingNian 6e5d3e64cd feat: 健康仪表盘配色调整 + 登录页品牌升级 + iOS 配置 + 隐私文案修订 + 文档清理
## UI 配色
- 健康仪表盘: 背景从蓝紫粉三色渐变改为 #4FACFE 纯色蓝, 白字清晰不抢眼
- app_colors / app_design_tokens / app_theme: 配色体系微调
- 多个 widget 和页面跟随配色更新(health_drawer/admin_drawer/doctor_drawer/enterprise_widgets 等)

## 登录页品牌升级
- 新增品牌素材: drawer_background_v2 / login_background_v2 / health_login_character_transparent
- login_page 重构, 接入新品牌视觉
- app.dart 启动流程调整

## iOS / Android 配置
- Info.plist: 权限描述调整
- AppIcon / LaunchImage: 资源更新
- AndroidManifest: 权限微调

## 隐私文案修订
- privacy.html: 蓝牙设备描述调整为"标准蓝牙血压服务", 移除未上线设备类型表述
- terms.html: 移除"在线医生咨询"相关条款, 服务范围收窄

## 通知中心
- notification_center_page: 重构通知项布局

## 其他
- 删除已完成的计划/spec 文档(ui-system-first-pass / apple-sign-in / secondary-page-color-refresh / notification-preferences-design / ui-design-system)
- 新增 native_navigation_test
- 新增 HANDOFF 交接文档
- home_message_order_test 更新
- .gitignore 调整
2026-07-16 22:30:23 +08:00

82 lines
2.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import '../core/app_colors.dart';
import '../core/app_design_tokens.dart';
class AiContent {
AiContent._();
static String clean(String text) {
var t = text;
t = t.replaceAll(RegExp(r'\$\d+'), '');
t = t.replaceAll(RegExp(r'<[^>]+>'), '');
t = t.replaceAllMapped(RegExp(r'^#{4,}\s', multiLine: true), (_) => '### ');
t = t.replaceAll(RegExp(r'\n{3,}'), '\n\n');
return t.trim();
}
static String plain(String text) {
final cleaned = clean(text);
return cleaned
.replaceAll(RegExp(r'\*\*(.*?)\*\*'), r'$1')
.replaceAll(RegExp(r'__(.*?)__'), r'$1')
.replaceAll(RegExp(r'`([^`]+)`'), r'$1')
.replaceAll(RegExp(r'^\s*[-*]\s+', multiLine: true), '')
.trim();
}
}
class AiMarkdownView extends StatelessWidget {
final String data;
final bool selectable;
final void Function(String text, String? href, String title)? onTapLink;
const AiMarkdownView({
super.key,
required this.data,
this.selectable = true,
this.onTapLink,
});
@override
Widget build(BuildContext context) {
return MarkdownBody(
data: AiContent.clean(data),
selectable: selectable,
onTapLink: onTapLink,
styleSheet: MarkdownStyleSheet(
p: AppTextStyles.chatBody,
a: AppTextStyles.chatBody.copyWith(
color: AppColors.primary,
fontWeight: FontWeight.w600,
decoration: TextDecoration.underline,
decorationColor: AppColors.primary,
),
strong: AppTextStyles.chatBody.copyWith(fontWeight: FontWeight.w600),
h1: AppTextStyles.chatTitle.copyWith(fontSize: 20),
h2: AppTextStyles.chatTitle.copyWith(fontSize: 20),
h3: AppTextStyles.chatTitle.copyWith(fontSize: 19),
listBullet: AppTextStyles.chatBody.copyWith(
fontSize: 21,
fontWeight: FontWeight.w700,
),
listBulletPadding: const EdgeInsets.only(right: 8),
blockquote: AppTextStyles.chatBody.copyWith(
color: AppColors.textSecondary,
),
),
);
}
}
class AiGeneratedNote extends StatelessWidget {
const AiGeneratedNote({super.key});
@override
Widget build(BuildContext context) => const Padding(
padding: EdgeInsets.only(top: 10),
child: Text('内容由 AI 生成', style: AppTextStyles.aiNote),
);
}