Compare commits
2 Commits
431b72d49a
...
80540e2191
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80540e2191 | ||
|
|
6ce010e46a |
@@ -34,6 +34,16 @@ public sealed class PromptManager
|
||||
- 对胸痛、胸闷憋气、呼吸困难、意识异常、晕厥、说话不清、一侧肢体无力、血氧明显偏低、血压或血糖严重异常等情况,优先建议及时就医或急诊评估。
|
||||
- 回答用语使用“可能、建议、需要结合医生判断”等表达,避免绝对化结论。
|
||||
- 医疗相关分析末尾用一句自然的话提醒:以上为 AI 预分析,不能替代医生诊断和治疗建议。
|
||||
|
||||
回复格式规则(严格遵守):
|
||||
- 禁止使用 **粗体**、*斜体*、~~删除线~~ 等 Markdown 内联标记
|
||||
- 禁止使用 HTML 标签
|
||||
- 禁止使用 Markdown 表格(|--|--|)
|
||||
- 标题只使用 ### 三级标题,禁止使用 #、##、####
|
||||
- 列表使用 - 开头,每项一行
|
||||
- 数值和单位之间加空格:120 mmHg、6.2 mmol/L
|
||||
- 不要输出任何 $ 开头的占位符
|
||||
- 回复结尾不再重复免责声明,MedicalBoundaryRules 已统一处理
|
||||
""";
|
||||
|
||||
private const string DefaultPrompt = """
|
||||
|
||||
@@ -4,9 +4,11 @@ import 'package:dio/dio.dart';
|
||||
import 'local_database.dart';
|
||||
|
||||
/// API 基础地址。可通过 --dart-define=API_BASE_URL=http://host:5000 覆盖。
|
||||
/// Android 真机 USB: 先执行 adb reverse tcp:5000 tcp:5000 然后 localhost 即可
|
||||
/// Android 真机 WiFi: flutter run --dart-define=API_BASE_URL=http://电脑IP:5000
|
||||
const String baseUrl = String.fromEnvironment(
|
||||
'API_BASE_URL',
|
||||
defaultValue: 'http://localhost:5000',
|
||||
defaultValue: 'http://192.168.1.29:5000',
|
||||
);
|
||||
|
||||
class ApiException implements Exception {
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../../core/app_colors.dart';
|
||||
import '../../core/app_theme.dart';
|
||||
import '../../core/navigation_provider.dart';
|
||||
import '../../providers/auth_provider.dart';
|
||||
import '../../providers/data_providers.dart';
|
||||
|
||||
@@ -247,7 +248,11 @@ class _TrendPageState extends ConsumerState<TrendPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GradientScaffold(
|
||||
appBar: AppBar(title: const Text('健康概览'), centerTitle: true),
|
||||
appBar: AppBar(
|
||||
leading: IconButton(icon: const Icon(Icons.arrow_back), onPressed: () => popRoute(ref)),
|
||||
title: const Text('健康概览'),
|
||||
centerTitle: true,
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _showAddDialog,
|
||||
backgroundColor: _color,
|
||||
|
||||
@@ -1243,10 +1243,16 @@ class ChatMessagesView extends ConsumerWidget {
|
||||
|
||||
/// 清理 AI 返回文本中的异常占位符(Markdown 格式交给 MarkdownBody 渲染)
|
||||
static String _cleanAiText(String text) {
|
||||
return text
|
||||
.replaceAll('\$1', '') // AI 偶尔输出 $1 占位符(正则残留)
|
||||
.replaceAll(RegExp(r'\n{3,}'), '\n\n')
|
||||
.trim();
|
||||
var t = text;
|
||||
// 移除 $1、$2 等占位符
|
||||
t = t.replaceAll(RegExp(r'\$\d+'), '');
|
||||
// 移除残留 HTML 标签
|
||||
t = t.replaceAll(RegExp(r'<[^>]+>'), '');
|
||||
// 行首 # 超过 3 个降为 ###
|
||||
t = t.replaceAllMapped(RegExp(r'^#{4,}\s', multiLine: true), (_) => '### ');
|
||||
// 压缩多余空行
|
||||
t = t.replaceAll(RegExp(r'\n{3,}'), '\n\n');
|
||||
return t.trim();
|
||||
}
|
||||
|
||||
String _freqLabel(String freq) {
|
||||
|
||||
@@ -138,7 +138,10 @@ class _MedicationEditPageState extends ConsumerState<MedicationEditPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GradientScaffold(
|
||||
appBar: AppBar(title: Text(widget.id != null ? '编辑用药' : '添加用药')),
|
||||
appBar: AppBar(
|
||||
leading: IconButton(icon: const Icon(Icons.arrow_back), onPressed: () => popRoute(ref)),
|
||||
title: Text(widget.id != null ? '编辑用药' : '添加用药'),
|
||||
),
|
||||
body: ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: [
|
||||
|
||||
@@ -1381,14 +1381,6 @@ class _HealthArchivePageState extends ConsumerState<HealthArchivePage> {
|
||||
'familyHistory': _familyCtrl.text,
|
||||
});
|
||||
await ref.read(authProvider.notifier).refreshProfile();
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('保存成功'),
|
||||
backgroundColor: AppColors.success,
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (_) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
@@ -1438,6 +1430,21 @@ class _HealthArchivePageState extends ConsumerState<HealthArchivePage> {
|
||||
icon: const Icon(Icons.arrow_back, color: AppColors.textPrimary),
|
||||
onPressed: () => popRoute(ref),
|
||||
),
|
||||
actions: [
|
||||
_saving
|
||||
? const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
),
|
||||
)
|
||||
: TextButton(
|
||||
onPressed: _save,
|
||||
child: const Text('保存', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
@@ -1525,36 +1532,6 @@ class _HealthArchivePageState extends ConsumerState<HealthArchivePage> {
|
||||
const SizedBox(height: 12),
|
||||
_F('家族病史', _familyCtrl, hint: '如: 父亲冠心病'),
|
||||
]),
|
||||
const SizedBox(height: 24),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
gradient: AppColors.primaryGradient,
|
||||
),
|
||||
padding: const EdgeInsets.all(1.5),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: 52,
|
||||
child: ElevatedButton(
|
||||
onPressed: _saving ? null : _save,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.white,
|
||||
foregroundColor: AppColors.primary,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(13),
|
||||
),
|
||||
elevation: 0,
|
||||
),
|
||||
child: Text(
|
||||
_saving ? '保存中...' : '保存档案',
|
||||
style: const TextStyle(
|
||||
fontSize: 17,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 40),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -31,7 +31,10 @@ class _AiAnalysisPageState extends ConsumerState<AiAnalysisPage> {
|
||||
|
||||
if (analysis == null) {
|
||||
return GradientScaffold(
|
||||
appBar: AppBar(title: const Text('报告解读')),
|
||||
appBar: AppBar(
|
||||
leading: IconButton(icon: const Icon(Icons.arrow_back), onPressed: () => popRoute(ref)),
|
||||
title: const Text('报告解读'),
|
||||
),
|
||||
body: const Center(
|
||||
child: CircularProgressIndicator(color: AppColors.primary),
|
||||
),
|
||||
|
||||
@@ -351,7 +351,10 @@ class ReportListPage extends ConsumerWidget {
|
||||
|
||||
if (state.isAnalyzing) {
|
||||
return GradientScaffold(
|
||||
appBar: AppBar(title: const Text('报告管理')),
|
||||
appBar: AppBar(
|
||||
leading: IconButton(icon: const Icon(Icons.arrow_back), onPressed: () => popRoute(ref)),
|
||||
title: const Text('报告管理'),
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -720,7 +723,10 @@ class ReportOriginalPage extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final imageUrl = _absoluteUrl(url);
|
||||
return GradientScaffold(
|
||||
appBar: AppBar(title: Text(title)),
|
||||
appBar: AppBar(
|
||||
leading: IconButton(icon: const Icon(Icons.arrow_back), onPressed: () => Navigator.pop(context)),
|
||||
title: Text(title),
|
||||
),
|
||||
body: Center(
|
||||
child: InteractiveViewer(
|
||||
minScale: 0.7,
|
||||
|
||||
Reference in New Issue
Block a user