feat(medication): 重构AI分析为结构化展示并支持喝水提醒个性化配置
- 将药品AI分析从Markdown流式输出重构为结构化数据展示(V2) - 新增适合人群、不适合人群、主要成分、副作用等分类卡片展示 - 优化AI分析UI布局,采用卡片式设计提升可读性 - 新增药品跳过功能,支持用户标记本次用药为已跳过 - 修复喝水提醒逻辑,支持用户开关控制和自定义时间段配置 - 优化个人资料编辑页面键盘适配,避免输入框被遮挡 - 统一API响应码处理,兼容200和0两种成功状态码 - 更新版本号至1.0.28 BREAKING CHANGE: 药品AI分析接口从流式Markdown输出改为结构化JSON格式,旧版本分析结果将不再显示
This commit is contained in:
@@ -20,6 +20,7 @@ import React, { useEffect, useMemo, useState } from 'react';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Alert,
|
||||
Keyboard,
|
||||
KeyboardAvoidingView,
|
||||
Modal,
|
||||
Platform,
|
||||
@@ -31,6 +32,7 @@ import {
|
||||
TouchableOpacity,
|
||||
View
|
||||
} from 'react-native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
|
||||
|
||||
interface UserProfile {
|
||||
@@ -80,8 +82,9 @@ export default function EditProfileScreen() {
|
||||
const [pickerDate, setPickerDate] = useState<Date>(new Date());
|
||||
const [editingField, setEditingField] = useState<string | null>(null);
|
||||
const [tempValue, setTempValue] = useState<string>('');
|
||||
|
||||
// 输入框字符串
|
||||
|
||||
// 键盘高度状态
|
||||
const [keyboardHeight, setKeyboardHeight] = useState(0);
|
||||
|
||||
// 从本地存储加载(身高/体重等本地字段)
|
||||
const loadLocalProfile = async () => {
|
||||
@@ -128,6 +131,34 @@ export default function EditProfileScreen() {
|
||||
loadLocalProfile();
|
||||
}, []);
|
||||
|
||||
// 键盘事件监听器 - 只在名称和体重输入框显示时监听
|
||||
useEffect(() => {
|
||||
// 只有在编辑名称或体重字段时才需要监听键盘(这两个字段使用 TextInput)
|
||||
const needsKeyboardHandling = editingField === 'name' || editingField === 'weight';
|
||||
|
||||
if (!needsKeyboardHandling) {
|
||||
setKeyboardHeight(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const showEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
|
||||
const hideEvent = Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';
|
||||
|
||||
const handleShow = (event: any) => {
|
||||
const height = event?.endCoordinates?.height ?? 0;
|
||||
setKeyboardHeight(height);
|
||||
};
|
||||
const handleHide = () => setKeyboardHeight(0);
|
||||
|
||||
const showSub = Keyboard.addListener(showEvent, handleShow);
|
||||
const hideSub = Keyboard.addListener(hideEvent, handleHide);
|
||||
|
||||
return () => {
|
||||
showSub.remove();
|
||||
hideSub.remove();
|
||||
};
|
||||
}, [editingField]);
|
||||
|
||||
// 获取最大心率数据
|
||||
useEffect(() => {
|
||||
const loadMaximumHeartRate = async () => {
|
||||
@@ -439,6 +470,7 @@ export default function EditProfileScreen() {
|
||||
field={editingField}
|
||||
value={tempValue}
|
||||
profile={profile}
|
||||
keyboardHeight={keyboardHeight}
|
||||
onClose={() => {
|
||||
setEditingField(null);
|
||||
setTempValue('');
|
||||
@@ -557,11 +589,12 @@ function ProfileCard({ icon, iconUri, iconColor, title, value, onPress, disabled
|
||||
);
|
||||
}
|
||||
|
||||
function EditModal({ visible, field, value, profile, onClose, onSave, colors, textColor, placeholderColor, t }: {
|
||||
function EditModal({ visible, field, value, profile, keyboardHeight, onClose, onSave, colors, textColor, placeholderColor, t }: {
|
||||
visible: boolean;
|
||||
field: string | null;
|
||||
value: string;
|
||||
profile: UserProfile;
|
||||
keyboardHeight: number;
|
||||
onClose: () => void;
|
||||
onSave: (field: string, value: string) => void;
|
||||
colors: any;
|
||||
@@ -569,6 +602,7 @@ function EditModal({ visible, field, value, profile, onClose, onSave, colors, te
|
||||
placeholderColor: string;
|
||||
t: (key: string) => string;
|
||||
}) {
|
||||
const insets = useSafeAreaInsets();
|
||||
const [inputValue, setInputValue] = useState(value);
|
||||
const [selectedGender, setSelectedGender] = useState(profile.gender || 'female');
|
||||
const [selectedActivity, setSelectedActivity] = useState(profile.activityLevel || 1);
|
||||
@@ -685,7 +719,10 @@ function EditModal({ visible, field, value, profile, onClose, onSave, colors, te
|
||||
return (
|
||||
<Modal visible={visible} transparent animationType="fade" onRequestClose={onClose}>
|
||||
<Pressable style={styles.modalBackdrop} onPress={onClose} />
|
||||
<View style={styles.editModalSheet}>
|
||||
<View style={[
|
||||
styles.editModalSheet,
|
||||
{ paddingBottom: Math.max(keyboardHeight, insets.bottom) + 12 }
|
||||
]}>
|
||||
<View style={styles.modalHandle} />
|
||||
{renderContent()}
|
||||
<View style={styles.modalButtons}>
|
||||
|
||||
Reference in New Issue
Block a user