feat(doctor): 添加订单诊断和治疗方案表单功能

- 引入 TextArea 组件用于多行文本输入- 新增诊断结果、治疗方案和煎药说明表单项
- 实现表单数据状态管理和字段变更处理- 更新消息内容拼接逻辑,包含诊断和治疗信息- 支持从本地存储恢复选中的患者和处方数据
- 移除调试日志并优化表单提交流程
- 调整界面布局,增强药方信息展示效果- 修改组件名称从 AddMessage 为 AddOrder
This commit is contained in:
2025-10-23 16:43:15 +08:00
parent a103ad5d8d
commit 602e8fd6c6

View File

@@ -1,6 +1,6 @@
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, Avatar, Tag, TextArea} from '@nutui/nutui-react-taro' import {Loading, CellGroup, Input, Form, Cell,Button, Avatar, Tag, TextArea, ImagePreview} 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'
@@ -11,12 +11,27 @@ import {getUser} from "@/api/system/user";
import {User} from "@/api/system/user/model"; 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";
// 图片数据接口
interface UploadedImageData {
url?: string;
src?: string;
name?: string;
uid?: string;
message?: string;
type?: string;
}
const AddOrder = () => { const AddOrder = () => {
const {params} = useRouter(); const {params} = useRouter();
const [toUser, setToUser] = useState<User>() const [toUser, setToUser] = useState<User>()
const [loading, setLoading] = useState<boolean>(true) const [loading, setLoading] = useState<boolean>(true)
const formRef = useRef<any>(null) const formRef = useRef<any>(null)
const [disabled, setDisabled] = useState<boolean>(false)
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 | null>(null)
@@ -35,13 +50,15 @@ const AddOrder = () => {
const toUserId = params.id ? Number(params.id) : undefined const toUserId = params.id ? Number(params.id) : undefined
const reload = async () => { const reload = async () => {
if(toUserId){ if (toUserId) {
getUser(Number(toUserId)).then(data => { getUser(Number(toUserId)).then(data => {
setToUser(data) setToUser(data)
}) })
} }
} }
setDisabled(true);
// 设置选中的患者(供其他页面调用) // 设置选中的患者(供其他页面调用)
// @ts-ignore // @ts-ignore
const setSelectedPatientFunc = (patient: ClinicPatientUser) => { const setSelectedPatientFunc = (patient: ClinicPatientUser) => {
@@ -62,13 +79,141 @@ const AddOrder = () => {
})) }))
} }
// 选择并上传图片
const handleChooseImage = () => {
if (fileList.length >= 20) {
Taro.showToast({
title: '最多只能上传20张图片',
icon: 'none'
})
return
}
Taro.chooseImage({
count: 5 - fileList.length, // 剩余可选择的数量
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
console.log('选择图片成功:', res)
// 逐个上传选中的图片
res.tempFilePaths.forEach((filePath, index) => {
uploadSingleImage(filePath, index)
})
},
fail: (err) => {
console.log('选择图片失败:', err)
Taro.showToast({
title: '选择图片失败',
icon: 'error'
})
}
})
}
// 处理文件删除
const handleFileRemove = (file: any) => {
console.log('删除文件:', file)
const newFileList = fileList.filter(f => f.uid !== file.uid)
setFileList(newFileList)
// 更新表单数据 - 使用JSON格式存储
if (newFileList.length === 0) {
setFormData(prev => ({
...prev,
image: undefined
}))
} else {
const imageData: UploadedImageData[] = newFileList.map(f => ({
url: f.url,
src: f.url,
name: f.name,
uid: f.uid
}))
setFormData(prev => ({
...prev,
image: JSON.stringify(imageData)
}))
}
}
// 上传单张图片
const uploadSingleImage = (filePath: any, index: number) => {
Taro.uploadFile({
url: 'https://server.websoft.top/api/oss/upload',
filePath: filePath,
name: 'file',
header: {
'content-type': 'application/json',
TenantId
},
success: (res) => {
try {
const data = JSON.parse(res.data);
console.log('上传成功', data)
if (data.code === 0) {
// 更新文件列表
const newFile = {
name: `图片${Date.now()}_${index}`,
url: data.data.url,
status: 'success',
message: '上传成功',
type: 'image',
uid: `${Date.now()}_${index}`,
}
setFileList(prev => {
const newList = [...prev, newFile]
// 同时更新表单数据 - 使用JSON格式存储
const imageData: UploadedImageData[] = newList.map(f => ({
url: f.url,
name: f.name,
uid: f.uid
}))
setFormData(prevForm => ({
...prevForm,
image: JSON.stringify(imageData)
}))
return newList
})
Taro.showToast({
title: '上传成功',
icon: 'success'
})
} else {
Taro.showToast({
title: data.message || '上传失败',
icon: 'error'
})
}
} catch (error) {
console.error('解析响应失败:', error)
Taro.showToast({
title: '上传失败',
icon: 'error'
})
}
},
fail: (err) => {
console.log('上传请求失败', err);
Taro.showToast({
title: '上传失败',
icon: 'error'
})
}
})
}
// 提交表单 // 提交表单
const submitSucceed = async (values: any) => { const submitSucceed = async (values: any) => {
try { try {
console.log('提交数据:', values) console.log('提交数据:', values)
// 参数校验 // 参数校验
if(!toUser && !selectedPatient){ if (!toUser && !selectedPatient) {
Taro.showToast({ Taro.showToast({
title: `请选择发送对象或患者`, title: `请选择发送对象或患者`,
icon: 'error' icon: 'error'
@@ -205,24 +350,113 @@ const AddOrder = () => {
<TextArea <TextArea
value={formData.diagnosis} value={formData.diagnosis}
onChange={(value) => handleFormChange('diagnosis', value)} onChange={(value) => handleFormChange('diagnosis', value)}
placeholder="请填写诊断结果" placeholder="股骨头坏死"
rows={2} rows={2}
maxLength={200} maxLength={100}
/> />
</Cell> </Cell>
</CellGroup>
{/* 治疗方案 */}
<CellGroup>
<Cell title="治疗方案"> <Cell title="治疗方案">
<TextArea <TextArea
value={formData.treatmentPlan} value={formData.treatmentPlan}
onChange={(value) => handleFormChange('treatmentPlan', value)} onChange={(value) => handleFormChange('treatmentPlan', value)}
placeholder="请填写治疗方案" placeholder="请填写治疗方案"
rows={2} rows={2}
maxLength={200} maxLength={100}
/> />
</Cell> </Cell>
<Cell title="添加图片" extra={'可上传病例/舌苔/面相等'}>
<Form.Item
label={'拍照上传'}
name="image"
required
rules={[{message: '请上传照片'}]}
>
<div style={{
display: 'flex',
flexWrap: 'wrap',
gap: '12px',
padding: '8px 0'
}}>
{/* 显示已上传的图片 */}
{fileList.map((file) => (
<div key={file.uid} style={{
position: 'relative',
width: '80px',
height: '80px',
borderRadius: '8px',
overflow: 'hidden',
border: '1px solid #d9d9d9'
}}>
<img
src={file.url}
alt={file.name}
style={{
width: '100%',
height: '100%',
objectFit: 'cover'
}}
/>
<Button
size="small"
type="default"
style={{
position: 'absolute',
top: '-8px',
right: '-8px',
width: '20px',
height: '20px',
borderRadius: '10px',
fontSize: '12px',
minWidth: '20px',
padding: 0,
lineHeight: '20px'
}}
onClick={() => handleFileRemove(file)}
>
×
</Button>
</div>
))}
{/* 添加图片按钮 */}
{fileList.length < 5 && (
<div
onClick={handleChooseImage}
style={{
width: '80px',
height: '80px',
borderRadius: '8px',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
border: '2px dashed #d9d9d9',
backgroundColor: '#fafafa',
cursor: 'pointer'
}}
>
<span style={{fontSize: '20px', color: '#d9d9d9'}}>+</span>
<span style={{fontSize: '10px', marginTop: '2px', color: '#666'}}>
</span>
</div>
)}
{/* 显示上传数量提示 */}
{fileList.length > 0 && (
<div style={{
width: '100%',
fontSize: '12px',
color: '#52c41a',
textAlign: 'center',
marginTop: '4px'
}}>
{fileList.length}5
</div>
)}
</div>
</Form.Item>
</Cell>
</CellGroup> </CellGroup>
{/* 选择处方 */} {/* 选择处方 */}
@@ -286,22 +520,30 @@ const AddOrder = () => {
> >
<CellGroup style={{padding: '4px 0'}}> <CellGroup style={{padding: '4px 0'}}>
<Form.Item name="diagnosis" initialValue={formData.diagnosis}> <Form.Item name="diagnosis" initialValue={formData.diagnosis}>
<Input type="hidden" /> <Input type="hidden"/>
</Form.Item> </Form.Item>
<Form.Item name="treatmentPlan" initialValue={formData.treatmentPlan}> <Form.Item name="treatmentPlan" initialValue={formData.treatmentPlan}>
<Input type="hidden" /> <Input type="hidden"/>
</Form.Item> </Form.Item>
<Form.Item name="decoctionInstructions" initialValue={formData.decoctionInstructions}> <Form.Item name="decoctionInstructions" initialValue={formData.decoctionInstructions}>
<Input type="hidden" /> <Input type="hidden"/>
</Form.Item> </Form.Item>
<Form.Item name="content" initialValue={formData.content} required> <Form.Item name="content" initialValue={formData.content} required>
<Input type="hidden" /> <Input type="hidden"/>
</Form.Item> </Form.Item>
</CellGroup> </CellGroup>
</Form> </Form>
{/* 底部浮动按钮 */} {/* 底部浮动按钮 */}
<FixedButton text={'立即发送'} onClick={() => formRef.current?.submit()}/> <FixedButton text={'立即发送'} onClick={() => formRef.current?.submit()}/>
<ImagePreview
autoPlay
// @ts-ignore
images={fileList2}
visible={showBdImgPreview}
onClose={() => setShowBdImgPreview(false)}
/>
</> </>
); );
}; };