feat(medication): 重构AI分析为结构化展示并支持喝水提醒个性化配置

- 将药品AI分析从Markdown流式输出重构为结构化数据展示(V2)
- 新增适合人群、不适合人群、主要成分、副作用等分类卡片展示
- 优化AI分析UI布局,采用卡片式设计提升可读性
- 新增药品跳过功能,支持用户标记本次用药为已跳过
- 修复喝水提醒逻辑,支持用户开关控制和自定义时间段配置
- 优化个人资料编辑页面键盘适配,避免输入框被遮挡
- 统一API响应码处理,兼容200和0两种成功状态码
- 更新版本号至1.0.28

BREAKING CHANGE: 药品AI分析接口从流式Markdown输出改为结构化JSON格式,旧版本分析结果将不再显示
This commit is contained in:
richarjiang
2025-11-20 10:10:53 +08:00
parent b36922756d
commit 84abfa2506
12 changed files with 913 additions and 293 deletions

View File

@@ -144,7 +144,7 @@ async function doFetch<T>(path: string, options: ApiRequestOptions = {}): Promis
throw error;
}
if (json.code !== undefined && json.code !== 0) {
if (json.code !== undefined && json.code !== 0 && json.code !== 200) {
const errorMessage = (json && (json.message || json.error)) || `HTTP ${response.status}`;
const error = new Error(errorMessage);
// @ts-expect-error augment
@@ -324,4 +324,3 @@ export async function postTextStream(path: string, body: any, callbacks: TextStr
return { abort, requestId };
}

View File

@@ -1,12 +1,12 @@
import { listChallenges } from '@/services/challengesApi';
import { resyncFastingNotifications } from '@/services/fastingNotifications';
import { store } from '@/store';
import { selectActiveFastingPlan, selectActiveFastingSchedule } from '@/store/fastingSlice';
import { getWaterIntakeFromHealthKit } from '@/utils/health';
import AsyncStorage from '@/utils/kvStore';
import { log } from '@/utils/logger';
import { ChallengeNotificationHelpers, WaterNotificationHelpers } from '@/utils/notificationHelpers';
import { getWaterGoalFromStorage } from '@/utils/userPreferences';
import { resyncFastingNotifications } from '@/services/fastingNotifications';
import { selectActiveFastingSchedule, selectActiveFastingPlan } from '@/store/fastingSlice';
import { getWaterGoalFromStorage, getWaterReminderEnabled } from '@/utils/userPreferences';
import dayjs from 'dayjs';
import * as BackgroundTask from 'expo-background-task';
import * as TaskManager from 'expo-task-manager';
@@ -33,6 +33,13 @@ async function executeWaterReminderTask(): Promise<void> {
try {
console.log('执行喝水提醒后台任务...');
// 检查是否开启了喝水提醒
const isEnabled = await getWaterReminderEnabled();
if (!isEnabled) {
console.log('喝水提醒未开启,跳过后台任务');
return;
}
// 获取当前状态,添加错误处理
let state;
try {

View File

@@ -8,7 +8,7 @@ import { getWaterIntakeFromHealthKit } from '@/utils/health';
import AsyncStorage from '@/utils/kvStore';
import { logger } from '@/utils/logger';
import { ChallengeNotificationHelpers, WaterNotificationHelpers } from '@/utils/notificationHelpers';
import { getWaterGoalFromStorage } from '@/utils/userPreferences';
import { getWaterGoalFromStorage, getWaterReminderEnabled } from '@/utils/userPreferences';
import dayjs from 'dayjs';
@@ -39,6 +39,13 @@ async function executeWaterReminderTask(): Promise<void> {
try {
console.log('执行喝水提醒后台任务...');
// 检查是否开启了喝水提醒
const isEnabled = await getWaterReminderEnabled();
if (!isEnabled) {
console.log('喝水提醒未开启,跳过后台任务');
return;
}
let state;
try {
state = store.getState();

View File

@@ -5,6 +5,7 @@
import type {
DailyMedicationStats,
Medication,
MedicationAiAnalysisV2,
MedicationForm,
MedicationRecord,
MedicationStatus,
@@ -328,4 +329,18 @@ export async function analyzeMedicationStream(
callbacks,
{ timeoutMs: 120000 }
);
}
}
/**
* 获取药品 AI 分析 V2 结构化报告
* @param medicationId 药品 ID
* @returns 结构化 AI 分析结果
*/
export async function analyzeMedicationV2(
medicationId: string
): Promise<MedicationAiAnalysisV2> {
return api.post<MedicationAiAnalysisV2>(
`/api/medications/${medicationId}/ai-analysis/v2`,
{}
);
}