feat(miniprogram): 用药提醒时间选择器 + 家人编辑功能
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

- 用药提醒页:时间输入改为 Taro TimePicker 原生选择器
- 家人列表页:每个就诊人增加编辑按钮入口
- 家人添加页:支持编辑模式(URL 传 id + Storage 传数据 + updatePatient API)
This commit is contained in:
iven
2026-04-24 12:50:42 +08:00
parent 3a333535ea
commit 37ff907815
4 changed files with 64 additions and 26 deletions

View File

@@ -1,19 +1,31 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { View, Text, Input, Picker } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { createPatient } from '../../../services/patient';
import Taro, { useRouter } from '@tarojs/taro';
import { createPatient, updatePatient, Patient } from '../../../services/patient';
import './index.scss';
const RELATION_OPTIONS = ['本人', '配偶', '父母', '子女', '其他'];
const GENDER_OPTIONS = ['男', '女'];
export default function FamilyAdd() {
const [name, setName] = useState('');
const [relationIdx, setRelationIdx] = useState(0);
const [genderIdx, setGenderIdx] = useState(0);
const [birthDate, setBirthDate] = useState('');
const router = useRouter();
const editId = router.params.id || '';
const editData = Taro.getStorageSync('edit_patient') as Patient | null;
const [name, setName] = useState(editData?.name || '');
const [relationIdx, setRelationIdx] = useState(
editData?.relation ? RELATION_OPTIONS.indexOf(editData.relation) : 0
);
const [genderIdx, setGenderIdx] = useState(
editData?.gender === 'female' ? 1 : 0
);
const [birthDate, setBirthDate] = useState(editData?.birthday || '');
const [submitting, setSubmitting] = useState(false);
useEffect(() => {
return () => { Taro.removeStorageSync('edit_patient'); };
}, []);
const handleSubmit = async () => {
if (!name.trim()) {
Taro.showToast({ title: '请输入姓名', icon: 'none' });
@@ -21,17 +33,25 @@ export default function FamilyAdd() {
}
setSubmitting(true);
try {
await createPatient({
name: name.trim(),
gender: GENDER_OPTIONS[genderIdx] === '男' ? 'male' : 'female',
birthday: birthDate || undefined,
});
Taro.showToast({ title: '添加成功', icon: 'success' });
setTimeout(() => {
Taro.navigateBack();
}, 1000);
if (editId && editData) {
await updatePatient(editId, {
name: name.trim(),
gender: GENDER_OPTIONS[genderIdx] === '男' ? 'male' : 'female',
birthday: birthDate || undefined,
relation: RELATION_OPTIONS[relationIdx],
}, editData.version);
Taro.showToast({ title: '修改成功', icon: 'success' });
} else {
await createPatient({
name: name.trim(),
gender: GENDER_OPTIONS[genderIdx] === '男' ? 'male' : 'female',
birthday: birthDate || undefined,
});
Taro.showToast({ title: '添加成功', icon: 'success' });
}
setTimeout(() => Taro.navigateBack(), 1000);
} catch {
Taro.showToast({ title: '添加失败', icon: 'none' });
Taro.showToast({ title: editId ? '修改失败' : '添加失败', icon: 'none' });
} finally {
setSubmitting(false);
}
@@ -40,7 +60,6 @@ export default function FamilyAdd() {
return (
<View className='family-add-page'>
<View className='form-card'>
{/* 姓名 */}
<View className='form-item'>
<Text className='form-label'></Text>
<Input
@@ -51,7 +70,6 @@ export default function FamilyAdd() {
/>
</View>
{/* 关系 */}
<View className='form-item'>
<Text className='form-label'></Text>
<Picker
@@ -67,7 +85,6 @@ export default function FamilyAdd() {
</Picker>
</View>
{/* 性别 */}
<View className='form-item'>
<Text className='form-label'></Text>
<Picker
@@ -83,7 +100,6 @@ export default function FamilyAdd() {
</Picker>
</View>
{/* 出生日期 */}
<View className='form-item'>
<Text className='form-label'></Text>
<Picker
@@ -103,7 +119,7 @@ export default function FamilyAdd() {
className={`submit-btn ${submitting ? 'disabled' : ''}`}
onClick={submitting ? undefined : handleSubmit}
>
<Text className='submit-text'>{submitting ? '提交中...' : '确认添加'}</Text>
<Text className='submit-text'>{submitting ? '提交中...' : editId ? '保存修改' : '确认添加'}</Text>
</View>
</View>
);

View File

@@ -68,6 +68,15 @@
font-weight: bold;
}
.family-edit {
font-size: 24px;
color: $pri;
margin-left: 16px;
padding: 6px 16px;
border: 1px solid $pri;
border-radius: 16px;
}
.empty-state {
display: flex;
justify-content: center;

View File

@@ -42,6 +42,11 @@ export default function FamilyList() {
Taro.navigateTo({ url: '/pages/profile/family-add/index' });
};
const goToEdit = (patient: Patient) => {
Taro.setStorageSync('edit_patient', patient);
Taro.navigateTo({ url: `/pages/profile/family-add/index?id=${patient.id}` });
};
const genderText = (g?: string) => {
if (g === 'male') return '男';
if (g === 'female') return '女';
@@ -67,6 +72,7 @@ export default function FamilyList() {
</View>
</View>
{isActive && <Text className='family-check'></Text>}
<Text className='family-edit' onClick={(e) => { e.stopPropagation(); goToEdit(p); }}></Text>
</View>
);
})}

View File

@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
import { View, Text, Input } from '@tarojs/components';
import { View, Text, Input, Picker } from '@tarojs/components';
import Taro from '@tarojs/taro';
import EmptyState from '../../../components/EmptyState';
import './index.scss';
@@ -132,9 +132,16 @@ export default function MedicationReminder() {
</View>
<View className='form-item'>
<Text className='form-label'></Text>
<View className='time-picker-wrap'>
<Text className='time-value'>{formTime}</Text>
</View>
<Picker
mode='time'
value={formTime}
onChange={(e) => setFormTime(e.detail.value)}
>
<View className='time-picker-wrap'>
<Text className='time-value'>{formTime}</Text>
<Text className='time-arrow'></Text>
</View>
</Picker>
</View>
<View className='form-actions'>
<View className='form-cancel' onClick={() => setShowForm(false)}>