From 32811faf5489e4cbbbac88ce024713226bad8709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Mon, 3 Nov 2025 06:03:15 +0800 Subject: [PATCH] =?UTF-8?q?feat(clinic):=20=E6=B7=BB=E5=8A=A0=E6=82=A3?= =?UTF-8?q?=E8=80=85=E7=AE=A1=E7=90=86=E5=92=8C=E5=A4=84=E6=96=B9=E5=BC=80?= =?UTF-8?q?=E7=AB=8B=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增患者管理页面,支持搜索、查看、编辑备注和删除患者 - 实现选择患者功能,用于处方开立时关联患者信息- 添加处方开立页面,支持诊断结果、治疗方案输入及图片上传- 新增用药订单页面,展示患者的历史处方订单并支持支付 - 在处方模型中增加医生姓名字段,优化处方数据显示- 扩展处方查询参数,支持按医生和用户ID筛选 --- .../clinic/clinicPrescription/model/index.ts | 4 + src/app.config.ts | 7 + src/clinic/clinicDoctorUser/index.config.ts | 3 + src/clinic/clinicDoctorUser/index.tsx | 363 ++++++++++++ .../clinicPatientUser/prescription.config.ts | 4 + src/clinic/clinicPatientUser/prescription.tsx | 142 +++++ .../clinicPatientUser/selectPatient.config.ts | 4 + .../clinicPatientUser/selectPatient.tsx | 285 ++++++++++ src/clinic/clinicPrescription/add.config.ts | 2 +- src/clinic/clinicPrescription/add.tsx | 533 ++++++++++++++++-- .../clinicPrescription/confirm.config.ts | 6 + src/clinic/clinicPrescription/confirm.scss | 286 ++++++++++ src/clinic/clinicPrescription/confirm.tsx | 408 ++++++++++++++ .../clinicPrescription/detail.config.ts | 6 + src/clinic/clinicPrescription/detail.tsx | 190 +++++++ src/clinic/clinicPrescription/index.tsx | 127 ++--- .../selectPatient.config.ts | 4 + .../clinicPrescription/selectPatient.tsx | 285 ++++++++++ .../selectPrescription.config.ts | 4 + .../clinicPrescription/selectPrescription.tsx | 234 ++++++++ src/clinic/index.tsx | 2 +- src/doctor/orders/add.config.ts | 2 +- src/pages/index/Role.scss | 17 + src/pages/index/Role.tsx | 60 ++ src/pages/index/index.scss | 14 +- src/pages/index/index.tsx | 4 +- 26 files changed, 2834 insertions(+), 162 deletions(-) create mode 100644 src/clinic/clinicDoctorUser/index.config.ts create mode 100644 src/clinic/clinicDoctorUser/index.tsx create mode 100644 src/clinic/clinicPatientUser/prescription.config.ts create mode 100644 src/clinic/clinicPatientUser/prescription.tsx create mode 100644 src/clinic/clinicPatientUser/selectPatient.config.ts create mode 100644 src/clinic/clinicPatientUser/selectPatient.tsx create mode 100644 src/clinic/clinicPrescription/confirm.config.ts create mode 100644 src/clinic/clinicPrescription/confirm.scss create mode 100644 src/clinic/clinicPrescription/confirm.tsx create mode 100644 src/clinic/clinicPrescription/detail.config.ts create mode 100644 src/clinic/clinicPrescription/detail.tsx create mode 100644 src/clinic/clinicPrescription/selectPatient.config.ts create mode 100644 src/clinic/clinicPrescription/selectPatient.tsx create mode 100644 src/clinic/clinicPrescription/selectPrescription.config.ts create mode 100644 src/clinic/clinicPrescription/selectPrescription.tsx create mode 100644 src/pages/index/Role.scss create mode 100644 src/pages/index/Role.tsx diff --git a/src/api/clinic/clinicPrescription/model/index.ts b/src/api/clinic/clinicPrescription/model/index.ts index d4fc3c0..da81537 100644 --- a/src/api/clinic/clinicPrescription/model/index.ts +++ b/src/api/clinic/clinicPrescription/model/index.ts @@ -22,6 +22,8 @@ export interface ClinicPrescription { weight?: string; // 医生 doctorId?: number; + // 姓名 + doctorName?: string; // 订单编号 orderNo?: string; // 关联就诊表 @@ -68,5 +70,7 @@ export interface ClinicPrescription { */ export interface ClinicPrescriptionParam extends PageParam { id?: number; + doctorId?: number; + userId?: number; keywords?: string; } diff --git a/src/app.config.ts b/src/app.config.ts index cdb3fac..9bfa313 100644 --- a/src/app.config.ts +++ b/src/app.config.ts @@ -104,10 +104,17 @@ export default { "root": "clinic", "pages": [ "index", + "clinicPatientUser/index", "clinicPatientUser/add", + "clinicPatientUser/selectPatient", + "clinicPatientUser/prescription", + "clinicDoctorUser/index", "clinicDoctorUser/add", "clinicPrescription/index", "clinicPrescription/add", + "clinicPrescription/selectPrescription", + "clinicPrescription/confirm", + "clinicPrescription/detail" ] }, { diff --git a/src/clinic/clinicDoctorUser/index.config.ts b/src/clinic/clinicDoctorUser/index.config.ts new file mode 100644 index 0000000..539f8b2 --- /dev/null +++ b/src/clinic/clinicDoctorUser/index.config.ts @@ -0,0 +1,3 @@ +export default definePageConfig({ + navigationBarTitleText: '患者管理' +}) diff --git a/src/clinic/clinicDoctorUser/index.tsx b/src/clinic/clinicDoctorUser/index.tsx new file mode 100644 index 0000000..20c6be8 --- /dev/null +++ b/src/clinic/clinicDoctorUser/index.tsx @@ -0,0 +1,363 @@ +import {useState, useEffect, useCallback} from 'react' +import {View, Text} from '@tarojs/components' +import Taro, {useDidShow} from '@tarojs/taro' +import {Loading, InfiniteLoading, Empty, Space, Button, SearchBar} from '@nutui/nutui-react-taro' +import {Phone} from '@nutui/icons-react-taro' +import type {ClinicPatientUser as PatientUserType} from "@/api/clinic/clinicPatientUser/model"; +import FixedButton from "@/components/FixedButton"; +import navTo from "@/utils/common"; +import { + pageClinicPatientUser, + removeClinicPatientUser, + updateClinicPatientUser +} from "@/api/clinic/clinicPatientUser"; + +// 扩展患者类型 +interface PatientUser extends PatientUserType { +} + +const PatientIndex = () => { + const [list, setList] = useState([]) + const [loading, setLoading] = useState(false) + const [searchValue, setSearchValue] = useState('') + const [displaySearchValue, setDisplaySearchValue] = useState('') + const [page, setPage] = useState(1) + const [hasMore, setHasMore] = useState(true) + + // 复制手机号 + const copyPhone = (phone: string) => { + Taro.setClipboardData({ + data: phone, + success: () => { + Taro.showToast({ + title: '手机号已复制', + icon: 'success', + duration: 1500 + }); + } + }); + }; + + // 一键拨打 + const makePhoneCall = (phone: string) => { + Taro.makePhoneCall({ + phoneNumber: phone, + fail: () => { + Taro.showToast({ + title: '拨打取消', + icon: 'error' + }); + } + }); + }; + + // 编辑备注 + const editComments = (patient: PatientUser) => { + Taro.showModal({ + title: '编辑备注', + // @ts-ignore + editable: true, + placeholderText: '请输入备注信息', + content: patient.comments || '', + success: async (res) => { + // @ts-ignore + if (res.confirm && res.content !== undefined) { + try { + // 更新备注 + await updateClinicPatientUser({ + ...patient, + // @ts-ignore + comments: res.content.trim() + }); + + Taro.showToast({ + title: '更新成功', + icon: 'success' + }); + + // 刷新列表 + setList([]); + setPage(1); + setHasMore(true); + fetchPatientData(true); + } catch (error) { + console.error('更新备注失败:', error); + Taro.showToast({ + title: '更新失败,请重试', + icon: 'error' + }); + } + } + } + }); + }; + + // 获取患者数据 + const fetchPatientData = useCallback(async (resetPage = false, targetPage?: number) => { + setLoading(true); + try { + const currentPage = resetPage ? 1 : (targetPage || page); + + // 构建API参数 + const params: any = { + page: currentPage + }; + + // 添加搜索关键词 + if (displaySearchValue.trim()) { + params.keywords = displaySearchValue.trim(); + } + + const res = await pageClinicPatientUser(params); + + if (res?.list && res.list.length > 0) { + // 如果是重置页面或第一页,直接设置新数据;否则追加数据 + if (resetPage || currentPage === 1) { + setList(res.list); + } else { + setList(prevList => prevList.concat(res.list)); + } + + // 正确判断是否还有更多数据 + const hasMoreData = res.list.length >= 10; // 假设每页10条数据 + setHasMore(hasMoreData); + } else { + if (resetPage || currentPage === 1) { + setList([]); + } + setHasMore(false); + } + + setPage(currentPage); + } catch (error) { + console.error('获取患者数据失败:', error); + Taro.showToast({ + title: '加载失败,请重试', + icon: 'none' + }); + } finally { + setLoading(false); + } + }, [page, displaySearchValue]); + + const reloadMore = async () => { + if (loading || !hasMore) return; // 防止重复加载 + const nextPage = page + 1; + await fetchPatientData(false, nextPage); + } + + // 防抖搜索功能 + useEffect(() => { + const timer = setTimeout(() => { + setDisplaySearchValue(searchValue); + }, 300); // 300ms 防抖 + + return () => clearTimeout(timer); + }, [searchValue]); + + // 删除患者 + const handleDelete = (patient: PatientUser) => { + removeClinicPatientUser(patient.id).then(() => { + Taro.showToast({ + title: '删除成功', + icon: 'success' + }); + // 刷新数据 + setList([]); + setPage(1); + setHasMore(true); + fetchPatientData(true).then(); + }) + } + + // 初始化数据 + useEffect(() => { + fetchPatientData(true).then(); + }, [displaySearchValue]); + + // 监听页面显示,当从其他页面返回时刷新数据 + useDidShow(() => { + // 刷新数据 + setList([]); + setPage(1); + setHasMore(true); + fetchPatientData(true); + }); + + // 渲染患者项 + const renderPatientItem = (patient: PatientUser) => ( + + + + + + + {patient.realName || '未命名'} + + {patient.age}岁 + {patient.sex == '1' ? '男' : ''}{patient.sex == '2' ? '女' : ''} + + + + + + { + e.stopPropagation(); + makePhoneCall(patient.phone || ''); + }}>联系电话:{patient.phone || '未提供'} + + { + e.stopPropagation(); + makePhoneCall(patient.phone || ''); + }} + /> + { + e.stopPropagation(); + copyPhone(patient.phone || ''); + }} + > + 复制 + + + + + 添加时间:{patient.createTime || '未知'} + + + + + {/* 显示 comments 字段 */} + + 备注:{patient.comments || '暂无'} + { + e.stopPropagation(); + editComments(patient); + }} + > + 编辑 + + + + + + {/* 操作按钮 */} + + + + + + + ); + + // 渲染患者列表 + const renderPatientList = () => { + const isSearching = displaySearchValue.trim().length > 0; + + return ( + + {/* 搜索结果统计 */} + {isSearching && ( + + + 搜索 "{displaySearchValue}" 的结果,共找到 {list.length} 条记录 + + + )} + + + { + // 滚动事件处理 + }} + onScrollToUpper={() => { + // 滚动到顶部事件处理 + }} + loadingText={ + <> + 加载中... + + } + loadMoreText={ + list.length === 0 ? ( + + ) : ( + + 没有更多了 + + ) + } + > + {loading && list.length === 0 ? ( + + + 加载中... + + ) : ( + list.map(renderPatientItem) + )} + + + + ); + }; + + return ( + + {/* 搜索栏 */} + + setSearchValue(value)} + onClear={() => { + setSearchValue(''); + setDisplaySearchValue(''); + }} + clearable + /> + + + {/* 患者列表 */} + {renderPatientList()} + + Taro.navigateTo({url: '/doctor/customer/add'})}/> + + ); +}; + +export default PatientIndex; diff --git a/src/clinic/clinicPatientUser/prescription.config.ts b/src/clinic/clinicPatientUser/prescription.config.ts new file mode 100644 index 0000000..0d461a4 --- /dev/null +++ b/src/clinic/clinicPatientUser/prescription.config.ts @@ -0,0 +1,4 @@ +export default definePageConfig({ + navigationBarTitleText: '用药订单', + navigationBarTextStyle: 'black' +}) diff --git a/src/clinic/clinicPatientUser/prescription.tsx b/src/clinic/clinicPatientUser/prescription.tsx new file mode 100644 index 0000000..7b9d507 --- /dev/null +++ b/src/clinic/clinicPatientUser/prescription.tsx @@ -0,0 +1,142 @@ +import {useState} from "react"; +import Taro, {useDidShow} from '@tarojs/taro' +import {Button, Cell, CellGroup, Space, Empty, ConfigProvider, Tag} from '@nutui/nutui-react-taro' +import {View, Text} from '@tarojs/components' +import {ClinicPrescription} from "@/api/clinic/clinicPrescription/model"; +import { + pageClinicPrescription, + removeClinicPrescription +} from "@/api/clinic/clinicPrescription"; +import {copyText} from "@/utils/common"; +import {ShopGoods} from "@/api/shop/shopGoods/model"; +import {buildSingleGoodsOrder, PaymentHandler} from "@/utils/payment"; + +const ClinicPrescriptionList = () => { + const [list, setList] = useState([]) + const [loading, setLoading] = useState(false) + + const reload = () => { + setLoading(true) + pageClinicPrescription({ + // 添加查询条件 + userId: Taro.getStorageSync('UserId'), + }) + .then(data => { + setList(data?.list || []) + }) + .catch(() => { + Taro.showToast({ + title: '获取数据失败', + icon: 'error' + }); + }) + .finally(() => { + setLoading(false) + }) + } + + + /** + * 统一支付入口 + */ + const onPay = async (goods: ShopGoods) => { + try { + // 构建订单数据 + const orderData = buildSingleGoodsOrder( + ); + + // 执行支付 + await PaymentHandler.pay(orderData, 1); + + } catch (error: any) { + } + }; + + useDidShow(() => { + reload() + }); + + if (list.length === 0 && !loading) { + return ( + + + + + + ) + } + + return ( + <> + + {list.map((item) => ( + + 待支付 + } + onClick={() => copyText(`${item.orderNo}`)} + /> + {item.diagnosis && ( + + {item.diagnosis.length > 20 + ? `${item.diagnosis.substring(0, 20)}...` + : item.diagnosis} + + } + /> + )} + + {item.doctorName} + + } + /> + + + ¥{item.orderPrice || '0.00'} + + } + /> + + {item.createTime} + + } + /> + + + + + + + ))} + + + ) +} + +export default ClinicPrescriptionList; diff --git a/src/clinic/clinicPatientUser/selectPatient.config.ts b/src/clinic/clinicPatientUser/selectPatient.config.ts new file mode 100644 index 0000000..db136c2 --- /dev/null +++ b/src/clinic/clinicPatientUser/selectPatient.config.ts @@ -0,0 +1,4 @@ +export default definePageConfig({ + navigationBarTitleText: '选择患者', + navigationBarTextStyle: 'black' +}) \ No newline at end of file diff --git a/src/clinic/clinicPatientUser/selectPatient.tsx b/src/clinic/clinicPatientUser/selectPatient.tsx new file mode 100644 index 0000000..5fd0faa --- /dev/null +++ b/src/clinic/clinicPatientUser/selectPatient.tsx @@ -0,0 +1,285 @@ +import {useState, useEffect, useCallback} from 'react' +import {View, Text} from '@tarojs/components' +import Taro, {useDidShow} from '@tarojs/taro' +import {Loading, InfiniteLoading, Empty, Space, SearchBar, Button} from '@nutui/nutui-react-taro' +import {Phone} from '@nutui/icons-react-taro' +import type {ClinicPatientUser as PatientUserType} from "@/api/clinic/clinicPatientUser/model"; +import { + pageClinicPatientUser +} from "@/api/clinic/clinicPatientUser"; + +// 患者类型 +interface PatientUser extends PatientUserType { +} + +const SelectPatient = () => { + const [list, setList] = useState([]) + const [loading, setLoading] = useState(false) + const [searchValue, setSearchValue] = useState('') + const [displaySearchValue, setDisplaySearchValue] = useState('') + const [page, setPage] = useState(1) + const [hasMore, setHasMore] = useState(true) + + // 复制手机号 + const copyPhone = (phone: string) => { + Taro.setClipboardData({ + data: phone, + success: () => { + Taro.showToast({ + title: '手机号已复制', + icon: 'success', + duration: 1500 + }); + } + }); + }; + + // 一键拨打 + const makePhoneCall = (phone: string) => { + Taro.makePhoneCall({ + phoneNumber: phone, + fail: () => { + Taro.showToast({ + title: '拨打取消', + icon: 'error' + }); + } + }); + }; + + // 获取患者数据 + const fetchPatientData = useCallback(async (resetPage = false, targetPage?: number) => { + setLoading(true); + try { + const currentPage = resetPage ? 1 : (targetPage || page); + + // 构建API参数 + const params: any = { + page: currentPage + }; + + // 添加搜索关键词 + if (displaySearchValue.trim()) { + params.keywords = displaySearchValue.trim(); + } + + const res = await pageClinicPatientUser(params); + + if (res?.list && res.list.length > 0) { + // 如果是重置页面或第一页,直接设置新数据;否则追加数据 + if (resetPage || currentPage === 1) { + setList(res.list); + } else { + setList(prevList => [...prevList, ...res.list]); + } + + // 正确判断是否还有更多数据 + const hasMoreData = res.list.length >= 10; // 假设每页10条数据 + setHasMore(hasMoreData); + } else { + if (resetPage || currentPage === 1) { + setList([]); + } + setHasMore(false); + } + + setPage(currentPage); + } catch (error) { + console.error('获取患者数据失败:', error); + Taro.showToast({ + title: '加载失败,请重试', + icon: 'none' + }); + } finally { + setLoading(false); + } + }, [page, displaySearchValue]); + + const reloadMore = async () => { + if (loading || !hasMore) return; // 防止重复加载 + const nextPage = page + 1; + await fetchPatientData(false, nextPage); + } + + // 防抖搜索功能 + useEffect(() => { + const timer = setTimeout(() => { + setDisplaySearchValue(searchValue); + }, 300); // 300ms 防抖 + + return () => clearTimeout(timer); + }, [searchValue]); + + // 初始化数据 + useEffect(() => { + fetchPatientData(true).then(); + }, [displaySearchValue]); + + // 监听页面显示,当从其他页面返回时刷新数据 + useDidShow(() => { + // 刷新数据 + setList([]); + setPage(1); + setHasMore(true); + fetchPatientData(true); + }); + + // 选择患者 + const selectPatient = (patient: PatientUser) => { + // 将选中的患者信息传递回上一个页面 + const pages = Taro.getCurrentPages(); + if (pages.length > 1) { + const prevPage = pages[pages.length - 2]; + // @ts-ignore + if (prevPage && typeof prevPage.setSelectedPatient === 'function') { + // @ts-ignore + prevPage.setSelectedPatient(patient); + } + } + + // 同时存储到本地存储,作为备选方案 + try { + Taro.setStorageSync('selectedPatient', JSON.stringify(patient)); + } catch (e) { + console.error('存储患者信息失败:', e); + } + + Taro.navigateBack(); + }; + + // 渲染患者项 + const renderPatientItem = (patient: PatientUser) => ( + + + + + + {patient.realName || '未命名'} + + + + + + { + e.stopPropagation(); + makePhoneCall(patient.phone || ''); + }}>联系电话:{patient.phone || '未提供'} + + { + e.stopPropagation(); + makePhoneCall(patient.phone || ''); + }} + /> + { + e.stopPropagation(); + copyPhone(patient.phone || ''); + }} + > + 复制 + + + + + 添加时间:{patient.createTime || '未知'} + + + + + {/* 显示 comments 字段 */} + + 备注:{patient.comments || '暂无'} + + + + + {/* 选择按钮 */} + + + ); + + // 渲染患者列表 + const renderPatientList = () => { + const isSearching = displaySearchValue.trim().length > 0; + + return ( + + {/* 搜索结果统计 */} + {isSearching && ( + + + 搜索 "{displaySearchValue}" 的结果,共找到 {list.length} 条记录 + + + )} + + + + ) : ( + + 没有更多了 + + ) + } + > + {loading && list.length === 0 ? ( + + + 加载中... + + ) : ( + list.map(renderPatientItem) + )} + + + + ); + }; + + return ( + + {/* 搜索栏 */} + + setSearchValue(value)} + onClear={() => { + setSearchValue(''); + setDisplaySearchValue(''); + }} + clearable + /> + + + {/* 患者列表 */} + {renderPatientList()} + + ); +}; + +export default SelectPatient; \ No newline at end of file diff --git a/src/clinic/clinicPrescription/add.config.ts b/src/clinic/clinicPrescription/add.config.ts index 50a889b..a91274c 100644 --- a/src/clinic/clinicPrescription/add.config.ts +++ b/src/clinic/clinicPrescription/add.config.ts @@ -1,4 +1,4 @@ export default definePageConfig({ - navigationBarTitleText: '新增处方主表', + navigationBarTitleText: '开处方', navigationBarTextStyle: 'black' }) diff --git a/src/clinic/clinicPrescription/add.tsx b/src/clinic/clinicPrescription/add.tsx index 579d1a2..fdfd8e0 100644 --- a/src/clinic/clinicPrescription/add.tsx +++ b/src/clinic/clinicPrescription/add.tsx @@ -1,51 +1,272 @@ import {useEffect, useState, useRef} from "react"; import {useRouter} from '@tarojs/taro' -import {Button, Loading, CellGroup, Input, TextArea, Form} 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 {View, Text} from '@tarojs/components' import Taro from '@tarojs/taro' -import {View} from '@tarojs/components' +import FixedButton from "@/components/FixedButton"; +import navTo from "@/utils/common"; +import {ClinicPatientUser} from "@/api/clinic/clinicPatientUser/model"; import {ClinicPrescription} from "@/api/clinic/clinicPrescription/model"; -import {getClinicPrescription, listClinicPrescription, updateClinicPrescription, addClinicPrescription} from "@/api/clinic/clinicPrescription"; +import {TenantId} from "@/config/app"; +import {getClinicPatientUser} from "@/api/clinic/clinicPatientUser"; -const AddClinicPrescription = () => { +// 图片数据接口 +interface UploadedImageData { + url?: string; + src?: string; + name?: string; + uid?: string; + message?: string; + type?: string; +} + +const AddClinicOrder = () => { const {params} = useRouter(); - const [loading, setLoading] = useState(true) - const [FormData, setFormData] = useState({}) - const formRef = useRef(null) + const [toUser, setToUser] = useState() + const [loading, setLoading] = useState(false) + const formRef = useRef() + const [fileList, setFileList] = useState([]) // 图片文件列表 + + // 患者和处方状态 + const [selectedPatient, setSelectedPatient] = useState() + const [selectedPrescription, setSelectedPrescription] = useState() + + // 表单数据 + const [formData, setFormData] = useState({ + userId: undefined, + doctorId: undefined, + diagnosis: '', + treatmentPlan: '', + orderPrice: '', + decoctionInstructions: '', + items: [], + image: '' // 添加image字段 + }) + + // 判断是编辑还是新增模式 + const isEditMode = !!params.id + const toUserId = params.id ? Number(params.id) : undefined const reload = async () => { - if (params.id) { - const data = await getClinicPrescription(Number(params.id)) - setFormData(data) - } else { - setFormData({}) + if (toUserId) { + getClinicPatientUser(Number(toUserId)).then(data => { + setToUser(data) + }) } } - // 提交表单 + // 设置选中的患者(供其他页面调用) + // @ts-ignore + const setSelectedPatientFunc = (patient: ClinicPatientUser) => { + console.log('设置选中的患者:', patient) + setToUser(patient) + setSelectedPatient(patient) + } + + // 设置选中的处方(供其他页面调用) + // @ts-ignore + const setSelectedPrescriptionFunc = (prescription: ClinicPrescription) => { + setSelectedPrescription(prescription) + } + + // 处理表单字段变化 + const handleFormChange = (field: string, value: string) => { + setFormData(prev => ({ + ...prev, + [field]: value + })) + } + + // 选择并上传图片 + const handleChooseImage = () => { + if (fileList.length >= 5) { // 修正最大图片数量为5 + Taro.showToast({ + title: '最多只能上传5张图片', + 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: '' + })) + } 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': 'multipart/form-data', + TenantId + }, + success: (res) => { + try { + const data = JSON.parse(res.data); + console.log('上传成功', data) + if (data.code === 0 && data.data && data.data.url) { + // 更新文件列表 + 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) => { try { - if (params.id) { - // 编辑模式 - await updateClinicPrescription({ - ...values, - id: Number(params.id) - }) - } else { - // 新增模式 - await addClinicPrescription(values) + console.log('提交数据:', values) + + // 参数校验 + if (!toUser && !selectedPatient) { + Taro.showToast({ + title: `请选择发送对象或患者`, + icon: 'error' + }); + return false; } - Taro.showToast({ - title: `操作成功`, - icon: 'success' + if (!values.diagnosis) { + Taro.showToast({ + title: `请输入诊断结果`, + icon: 'error' + }); + return false; + } + if (!values.treatmentPlan) { + Taro.showToast({ + title: `请输入治疗方案`, + icon: 'error' + }); + return false; + } + + // 构建订单数据 + const orderData = { + patient: toUser || selectedPatient, + prescription: selectedPrescription, + diagnosis: values.diagnosis, + treatmentPlan: values.treatmentPlan, + decoctionInstructions: values.decoctionInstructions || formData.decoctionInstructions, + images: fileList, + orderPrice: selectedPrescription?.orderPrice || '0.00' + } + + // 保存到本地存储 + Taro.setStorageSync('tempOrderData', JSON.stringify(orderData)) + + console.log('跳转到订单确认页,订单数据:', orderData) + + // 跳转到确认页 + Taro.navigateTo({ + url: '/clinic/clinicPrescription/confirm' }) - setTimeout(() => { - return Taro.navigateBack() - }, 1000) - } catch (error) { + } catch (error: any) { + console.error('数据处理失败:', error); Taro.showToast({ - title: `操作失败`, + title: `数据处理失败: ${error.message || error || '未知错误'}`, icon: 'error' }); } @@ -59,7 +280,45 @@ const AddClinicPrescription = () => { reload().then(() => { setLoading(false) }) - }, []); + + // 设置页面实例的方法,供其他页面调用 + try { + // @ts-ignore + if (Taro.getCurrentInstance() && Taro.getCurrentInstance().page) { + // @ts-ignore + Taro.getCurrentInstance().page.setSelectedPatient = setSelectedPatientFunc; + // @ts-ignore + Taro.getCurrentInstance().page.setSelectedPrescription = setSelectedPrescriptionFunc; + } + } catch (error) { + console.error('设置页面实例方法失败:', error); + } + + // 从本地存储获取之前选择的患者和处方 + try { + const storedPatient = Taro.getStorageSync('selectedPatient'); + if (storedPatient) { + const parsedPatient = JSON.parse(storedPatient); + setSelectedPatient(parsedPatient); + Taro.removeStorageSync('selectedPatient'); + } + } catch (error) { + console.error('解析存储的患者数据失败:', error); + Taro.removeStorageSync('selectedPatient'); + } + + try { + const storedPrescription = Taro.getStorageSync('selectedPrescription'); + if (storedPrescription) { + const parsedPrescription = JSON.parse(storedPrescription); + setSelectedPrescription(parsedPrescription); + Taro.removeStorageSync('selectedPrescription'); + } + } catch (error) { + console.error('解析存储的处方数据失败:', error); + Taro.removeStorageSync('selectedPrescription'); + } + }, [isEditMode]); if (loading) { return 加载中 @@ -67,32 +326,188 @@ const AddClinicPrescription = () => { return ( <> -
submitSucceed(values)} - onFinishFailed={(errors) => submitFailed(errors)} - footer={ -
+ + + {toUser?.realName || '请选择'} + {toUser?.phone} + + + )} extra={( + + )} onClick={() => navTo(`/clinic/clinicPatientUser/selectPatient`, true)} + /> + + {toUser && ( + submitSucceed(values)} + onFinishFailed={(errors) => submitFailed(errors)} + > + {/* 基本信息 */} + - -
- } - > - - + + + +