feat(clinic): 添加患者头像和处方图片字段
- 在患者用户模型中添加 avatar 字段 - 在处方模型中添加 image 字段 - 更新新增诊所订单页面的表单结构 - 调整图片上传组件的样式和逻辑 - 优化表单验证规则和提示信息- 修改药方信息展示方式 - 更新页面跳转和数据获取逻辑
This commit is contained in:
@@ -12,6 +12,8 @@ export interface ClinicPatientUser {
|
|||||||
userId?: number;
|
userId?: number;
|
||||||
// 姓名
|
// 姓名
|
||||||
realName?: string;
|
realName?: string;
|
||||||
|
// 头像
|
||||||
|
avatar?: string;
|
||||||
// 年龄
|
// 年龄
|
||||||
age?: string;
|
age?: string;
|
||||||
// 性别
|
// 性别
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ export interface ClinicPrescription {
|
|||||||
treatmentPlan?: string;
|
treatmentPlan?: string;
|
||||||
// 煎药说明
|
// 煎药说明
|
||||||
decoctionInstructions?: string;
|
decoctionInstructions?: string;
|
||||||
|
// 图片
|
||||||
|
image?: string;
|
||||||
// 订单总金额
|
// 订单总金额
|
||||||
orderPrice?: string;
|
orderPrice?: string;
|
||||||
// 单价
|
// 单价
|
||||||
|
|||||||
@@ -1,16 +1,25 @@
|
|||||||
import {useEffect, useState, useRef} from "react";
|
import {useEffect, useState, useRef} from "react";
|
||||||
import {useRouter} from '@tarojs/taro'
|
import {useRouter} from '@tarojs/taro'
|
||||||
import {Loading, CellGroup, Input, Form, Cell,Button, Avatar, Tag, TextArea, ImagePreview} from '@nutui/nutui-react-taro'
|
import {
|
||||||
|
Loading,
|
||||||
|
Button,
|
||||||
|
Form,
|
||||||
|
Cell,
|
||||||
|
Avatar,
|
||||||
|
Input,
|
||||||
|
Space,
|
||||||
|
TextArea
|
||||||
|
} from '@nutui/nutui-react-taro'
|
||||||
import {ArrowRight} from '@nutui/icons-react-taro'
|
import {ArrowRight} from '@nutui/icons-react-taro'
|
||||||
import {View, Text} from '@tarojs/components'
|
import {View, Text} from '@tarojs/components'
|
||||||
import Taro from '@tarojs/taro'
|
import Taro from '@tarojs/taro'
|
||||||
import FixedButton from "@/components/FixedButton";
|
import FixedButton from "@/components/FixedButton";
|
||||||
import navTo from "@/utils/common";
|
import navTo from "@/utils/common";
|
||||||
import {getUser} from "@/api/system/user";
|
|
||||||
import {User} from "@/api/system/user/model";
|
|
||||||
import {ClinicPatientUser} from "@/api/clinic/clinicPatientUser/model";
|
import {ClinicPatientUser} from "@/api/clinic/clinicPatientUser/model";
|
||||||
import {ClinicPrescription} from "@/api/clinic/clinicPrescription/model";
|
import {ClinicPrescription} from "@/api/clinic/clinicPrescription/model";
|
||||||
import {TenantId} from "@/config/app";
|
import {TenantId} from "@/config/app";
|
||||||
|
import {getClinicPatientUser} from "@/api/clinic/clinicPatientUser";
|
||||||
|
import {addClinicOrder} from "@/api/clinic/clinicOrder";
|
||||||
|
|
||||||
// 图片数据接口
|
// 图片数据接口
|
||||||
interface UploadedImageData {
|
interface UploadedImageData {
|
||||||
@@ -24,24 +33,24 @@ interface UploadedImageData {
|
|||||||
|
|
||||||
const AddClinicOrder = () => {
|
const AddClinicOrder = () => {
|
||||||
const {params} = useRouter();
|
const {params} = useRouter();
|
||||||
const [toUser, setToUser] = useState<User>()
|
const [toUser, setToUser] = useState<ClinicPatientUser>()
|
||||||
const [loading, setLoading] = useState<boolean>(false)
|
const [loading, setLoading] = useState<boolean>(false)
|
||||||
const formRef = useRef<any>(null)
|
const formRef = useRef<any>()
|
||||||
const [disabled, setDisabled] = useState<boolean>(false)
|
|
||||||
const [fileList, setFileList] = useState<UploadedImageData[]>([]) // 图片文件列表
|
const [fileList, setFileList] = useState<UploadedImageData[]>([]) // 图片文件列表
|
||||||
const [showBdImgPreview, setShowBdImgPreview] = useState(false)
|
|
||||||
const [fileList2, setFileList2] = useState<UploadedImageData[]>([]) // 图片文件列表
|
|
||||||
|
|
||||||
// 患者和处方状态
|
// 患者和处方状态
|
||||||
const [selectedPatient, setSelectedPatient] = useState<ClinicPatientUser | null>(null)
|
const [selectedPatient, setSelectedPatient] = useState<ClinicPatientUser>()
|
||||||
const [selectedPrescription, setSelectedPrescription] = useState<ClinicPrescription | null>(null)
|
const [selectedPrescription, setSelectedPrescription] = useState<ClinicPrescription>()
|
||||||
|
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState<ClinicPrescription>({
|
||||||
|
userId: undefined,
|
||||||
|
doctorId: undefined,
|
||||||
diagnosis: '',
|
diagnosis: '',
|
||||||
treatmentPlan: '',
|
treatmentPlan: '',
|
||||||
|
orderPrice: '',
|
||||||
decoctionInstructions: '',
|
decoctionInstructions: '',
|
||||||
content: '',
|
items: [],
|
||||||
image: '' // 添加image字段
|
image: '' // 添加image字段
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -51,7 +60,7 @@ const AddClinicOrder = () => {
|
|||||||
|
|
||||||
const reload = async () => {
|
const reload = async () => {
|
||||||
if (toUserId) {
|
if (toUserId) {
|
||||||
getUser(Number(toUserId)).then(data => {
|
getClinicPatientUser(Number(toUserId)).then(data => {
|
||||||
setToUser(data)
|
setToUser(data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -60,6 +69,8 @@ const AddClinicOrder = () => {
|
|||||||
// 设置选中的患者(供其他页面调用)
|
// 设置选中的患者(供其他页面调用)
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const setSelectedPatientFunc = (patient: ClinicPatientUser) => {
|
const setSelectedPatientFunc = (patient: ClinicPatientUser) => {
|
||||||
|
console.log('设置选中的患者:', patient)
|
||||||
|
setToUser(patient)
|
||||||
setSelectedPatient(patient)
|
setSelectedPatient(patient)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +88,6 @@ const AddClinicOrder = () => {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 选择并上传图片
|
// 选择并上传图片
|
||||||
const handleChooseImage = () => {
|
const handleChooseImage = () => {
|
||||||
if (fileList.length >= 5) { // 修正最大图片数量为5
|
if (fileList.length >= 5) { // 修正最大图片数量为5
|
||||||
@@ -218,10 +228,16 @@ const AddClinicOrder = () => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断内容是否为空
|
if (!values.diagnosis) {
|
||||||
if (!values.content) {
|
|
||||||
Taro.showToast({
|
Taro.showToast({
|
||||||
title: `请输入消息内容`,
|
title: `请输入诊断结果`,
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!values.treatmentPlan) {
|
||||||
|
Taro.showToast({
|
||||||
|
title: `请输入治疗方案`,
|
||||||
icon: 'error'
|
icon: 'error'
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
@@ -252,7 +268,7 @@ const AddClinicOrder = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 执行新增或更新操作
|
// 执行新增或更新操作
|
||||||
// await addClinicOrder({});
|
await addClinicOrder({});
|
||||||
|
|
||||||
Taro.showToast({
|
Taro.showToast({
|
||||||
title: `发送成功`,
|
title: `发送成功`,
|
||||||
@@ -327,70 +343,73 @@ const AddClinicOrder = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* 显示已选择的用户(如果有的话) */}
|
{/* 显示已选择的用户(如果有的话) */}
|
||||||
{toUser && (
|
<Cell title={(
|
||||||
<Cell title={(
|
<View className={'flex items-center'}>
|
||||||
<View className={'flex items-center'}>
|
<Avatar src={toUser?.avatar}/>
|
||||||
<Avatar src={toUser.avatar}/>
|
<View className={'ml-2 flex flex-col'}>
|
||||||
<View className={'ml-2 flex flex-col'}>
|
<Text>{toUser?.realName || '请选择'}</Text>
|
||||||
<Text>{toUser.alias || toUser.nickname}</Text>
|
<Text className={'text-gray-300'}>{toUser?.phone}</Text>
|
||||||
<Text className={'text-gray-300'}>{toUser.mobile}</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
)} extra={(
|
</View>
|
||||||
<ArrowRight color="#cccccc" className={'mt-2'} size={20}/>
|
)} extra={(
|
||||||
)}/>
|
<ArrowRight color="#cccccc" className={'mt-2'} size={20}/>
|
||||||
)}
|
)} onClick={() => navTo(`/doctor/orders/selectPatient`, true)}
|
||||||
|
|
||||||
{/* 选择患者 */}
|
|
||||||
<Cell
|
|
||||||
title="选择患者"
|
|
||||||
extra={selectedPatient ? (
|
|
||||||
<View className={'flex items-center'}>
|
|
||||||
<Text className={'mr-2'}>{selectedPatient.realName || '未知患者'}</Text>
|
|
||||||
<ArrowRight color="#cccccc" size={18}/>
|
|
||||||
</View>
|
|
||||||
) : (
|
|
||||||
<Text className={'text-gray-400'}>请选择患者</Text>
|
|
||||||
)}
|
|
||||||
onClick={() => navTo(`/doctor/orders/selectPatient`, true)}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 诊断结果 */}
|
{toUser && (
|
||||||
<CellGroup>
|
<Form
|
||||||
<Cell title="诊断结果">
|
ref={formRef}
|
||||||
<TextArea
|
divider
|
||||||
value={formData.diagnosis}
|
initialValues={formData}
|
||||||
onChange={(value) => handleFormChange('diagnosis', value)}
|
labelPosition={'top'}
|
||||||
placeholder="股骨头坏死"
|
onFinish={(values) => submitSucceed(values)}
|
||||||
rows={2}
|
onFinishFailed={(errors) => submitFailed(errors)}
|
||||||
maxLength={100}
|
>
|
||||||
/>
|
{/* 基本信息 */}
|
||||||
</Cell>
|
<Form.Item
|
||||||
<Cell title="治疗方案">
|
name="diagnosis"
|
||||||
<TextArea
|
label={'诊断结果'}
|
||||||
value={formData.treatmentPlan}
|
required
|
||||||
onChange={(value) => handleFormChange('treatmentPlan', value)}
|
rules={[{required: true, message: '请填写诊断结果'}]}
|
||||||
placeholder="请填写治疗方案"
|
initialValue={formData.diagnosis}
|
||||||
rows={2}
|
>
|
||||||
maxLength={100}
|
<Input placeholder="请输入诊断结果" style={{
|
||||||
/>
|
backgroundColor: '#f9f9f9',
|
||||||
</Cell>
|
padding: '4px',
|
||||||
<Cell title="添加图片" extra={'可上传病例/舌苔/面相等'}>
|
}}/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="treatmentPlan"
|
||||||
|
label={'治疗方案'}
|
||||||
|
required
|
||||||
|
rules={[{required: true, message: '请填写治疗方案'}]}
|
||||||
|
initialValue={formData.treatmentPlan}
|
||||||
|
>
|
||||||
|
<TextArea
|
||||||
|
value={formData.treatmentPlan}
|
||||||
|
onChange={(value) => handleFormChange('treatmentPlan', value)}
|
||||||
|
placeholder="请填写治疗方案"
|
||||||
|
style={{
|
||||||
|
backgroundColor: '#f9f9f9',
|
||||||
|
padding: '4px',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={'拍照上传'}
|
label={'拍照上传'}
|
||||||
name="image"
|
name="image"
|
||||||
required
|
|
||||||
rules={[{message: '请上传照片'}]}
|
rules={[{message: '请上传照片'}]}
|
||||||
>
|
>
|
||||||
<div style={{
|
<View style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
gap: '12px',
|
gap: '8px',
|
||||||
padding: '8px 0'
|
padding: '0'
|
||||||
}}>
|
}}>
|
||||||
{/* 显示已上传的图片 */}
|
{/* 显示已上传的图片 */}
|
||||||
{fileList.map((file) => (
|
{fileList.map((file) => (
|
||||||
<div key={file.uid} style={{
|
<View key={file.uid} style={{
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
width: '80px',
|
width: '80px',
|
||||||
height: '80px',
|
height: '80px',
|
||||||
@@ -426,12 +445,12 @@ const AddClinicOrder = () => {
|
|||||||
>
|
>
|
||||||
×
|
×
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</View>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{/* 添加图片按钮 */}
|
{/* 添加图片按钮 */}
|
||||||
{fileList.length < 5 && (
|
{fileList.length < 5 && (
|
||||||
<div
|
<View
|
||||||
onClick={handleChooseImage}
|
onClick={handleChooseImage}
|
||||||
style={{
|
style={{
|
||||||
width: '80px',
|
width: '80px',
|
||||||
@@ -448,27 +467,19 @@ const AddClinicOrder = () => {
|
|||||||
>
|
>
|
||||||
<span style={{fontSize: '20px', color: '#d9d9d9'}}>+</span>
|
<span style={{fontSize: '20px', color: '#d9d9d9'}}>+</span>
|
||||||
<span style={{fontSize: '10px', marginTop: '2px', color: '#666'}}>
|
<span style={{fontSize: '10px', marginTop: '2px', color: '#666'}}>
|
||||||
添加图片
|
添加图片
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
</View>
|
||||||
{/* 显示上传数量提示 */}
|
<View className="text-xs text-gray-500">
|
||||||
{fileList.length > 0 && (
|
可上传病例/舌苔/面相等,已上传{fileList.length}张图片
|
||||||
<div style={{
|
</View>
|
||||||
width: '100%',
|
|
||||||
fontSize: '12px',
|
|
||||||
color: '#52c41a',
|
|
||||||
textAlign: 'center',
|
|
||||||
marginTop: '4px'
|
|
||||||
}}>
|
|
||||||
已上传{fileList.length}张图片(最多5张)
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Cell>
|
</Form>
|
||||||
</CellGroup>
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{/* 选择处方 */}
|
{/* 选择处方 */}
|
||||||
<Cell
|
<Cell
|
||||||
@@ -483,82 +494,36 @@ const AddClinicOrder = () => {
|
|||||||
)}
|
)}
|
||||||
onClick={() => navTo(`/doctor/orders/selectPrescription`, true)}
|
onClick={() => navTo(`/doctor/orders/selectPrescription`, true)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 药方信息 */}
|
{/* 药方信息 */}
|
||||||
{selectedPrescription && (
|
{selectedPrescription && (
|
||||||
<CellGroup>
|
<>
|
||||||
<Cell title="药方信息">
|
<Cell extra={'药方信息'}>
|
||||||
<View className={'flex flex-wrap'}>
|
<View className={'flex flex-col'}>
|
||||||
{selectedPrescription.items?.map(item => (
|
<View className={'py-3'}>RP: {selectedPrescription.prescriptionType === 0 ? '中药' : '西药'} 共{selectedPrescription.items?.length}味、共{selectedPrescription.orderPrice}元</View>
|
||||||
<Tag key={item.id} className={'mr-2 mb-2'}>{item.medicineName}</Tag>
|
<Space className={'flex flex-wrap'}>
|
||||||
))}
|
{selectedPrescription.items?.map(item => (
|
||||||
|
<Button>{item.medicineName} 105克</Button>
|
||||||
|
))}
|
||||||
|
</Space>
|
||||||
</View>
|
</View>
|
||||||
</Cell>
|
</Cell>
|
||||||
|
|
||||||
{/* 煎药说明 */}
|
{/* 煎药说明 */}
|
||||||
<Cell title="煎药说明">
|
<TextArea
|
||||||
<TextArea
|
value={formData.decoctionInstructions}
|
||||||
value={formData.decoctionInstructions}
|
onChange={(value) => handleFormChange('decoctionInstructions', value)}
|
||||||
onChange={(value) => handleFormChange('decoctionInstructions', value)}
|
placeholder="请填写用药说明"
|
||||||
placeholder="请填写煎药说明"
|
rows={2}
|
||||||
rows={2}
|
maxLength={200}
|
||||||
maxLength={200}
|
/>
|
||||||
/>
|
</>
|
||||||
</Cell>
|
|
||||||
</CellGroup>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 消息内容 */}
|
|
||||||
<CellGroup>
|
|
||||||
<Cell title="消息内容">
|
|
||||||
<TextArea
|
|
||||||
value={formData.content}
|
|
||||||
onChange={(value) => handleFormChange('content', value)}
|
|
||||||
placeholder="请填写要发送的消息内容"
|
|
||||||
rows={3}
|
|
||||||
maxLength={300}
|
|
||||||
/>
|
|
||||||
</Cell>
|
|
||||||
</CellGroup>
|
|
||||||
|
|
||||||
<Form
|
|
||||||
ref={formRef}
|
|
||||||
divider
|
|
||||||
initialValues={formData}
|
|
||||||
labelPosition="left"
|
|
||||||
onFinish={(values) => submitSucceed(values)}
|
|
||||||
onFinishFailed={(errors) => submitFailed(errors)}
|
|
||||||
>
|
|
||||||
<CellGroup style={{padding: '4px 0'}}>
|
|
||||||
<Form.Item name="diagnosis" initialValue={formData.diagnosis}>
|
|
||||||
<Input type="hidden"/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name="treatmentPlan" initialValue={formData.treatmentPlan}>
|
|
||||||
<Input type="hidden"/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name="decoctionInstructions" initialValue={formData.decoctionInstructions}>
|
|
||||||
<Input type="hidden"/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name="content" initialValue={formData.content} required>
|
|
||||||
<Input type="hidden"/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name="image" initialValue={formData.image}>
|
|
||||||
<Input type="hidden"/>
|
|
||||||
</Form.Item>
|
|
||||||
</CellGroup>
|
|
||||||
</Form>
|
|
||||||
|
|
||||||
{/* 底部浮动按钮 */}
|
{/* 底部浮动按钮 */}
|
||||||
<FixedButton text={'立即发送'} onClick={() => formRef.current?.submit()}/>
|
<FixedButton text={'生成处方并发送给患者'} onClick={() => formRef.current?.submit()}/>
|
||||||
|
|
||||||
<ImagePreview
|
|
||||||
autoPlay
|
|
||||||
images={fileList2.filter(file => file.src).map(file => ({ src: file.src! }))}
|
|
||||||
visible={showBdImgPreview}
|
|
||||||
onClose={() => setShowBdImgPreview(false)}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AddClinicOrder;
|
export default AddClinicOrder;
|
||||||
|
|||||||
Reference in New Issue
Block a user