From 4872e4d2e6bf86a461c7d1f4271ec2f8286c5d0a Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 22 Apr 2026 12:14:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/src/api/order.ts | 15 + admin/src/api/tcm.ts | 4 +- .../src/components/tcm-prescription/index.vue | 4 +- .../consumer/prescription/order_list.vue | 167 ++++++-- admin/src/views/order/index.vue | 366 ++++++++++++++++-- admin/src/views/tcm/diagnosis/index.vue | 100 +---- .../controller/order/OrderController.php | 123 +++++- .../controller/tcm/DiagnosisController.php | 15 + .../tcm/PrescriptionOrderController.php | 9 +- .../app/adminapi/lists/order/OrderLists.php | 195 +++++++--- .../logic/order/OrderActionLogLogic.php | 130 +++++++ .../app/adminapi/logic/order/OrderLogic.php | 108 +++++- .../logic/tcm/PrescriptionOrderLogic.php | 71 +++- .../adminapi/validate/order/OrderValidate.php | 5 +- .../tcm/PrescriptionOrderValidate.php | 3 +- server/app/common/model/Order.php | 2 +- server/app/common/model/OrderActionLog.php | 15 + .../2026_04_21_order_action_log.sql | 13 + .../2026_04_22_drop_order_assistant_id.sql | 3 + .../2026_04_22_order_assistant_id.sql | 5 + ...026_04_22_prescription_order_logs_menu.sql | 13 + 21 files changed, 1131 insertions(+), 235 deletions(-) create mode 100644 server/app/adminapi/logic/order/OrderActionLogLogic.php create mode 100644 server/app/common/model/OrderActionLog.php create mode 100644 server/database/migrations/2026_04_21_order_action_log.sql create mode 100644 server/database/migrations/2026_04_22_drop_order_assistant_id.sql create mode 100644 server/database/migrations/2026_04_22_order_assistant_id.sql create mode 100644 server/database/migrations/2026_04_22_prescription_order_logs_menu.sql diff --git a/admin/src/api/order.ts b/admin/src/api/order.ts index 5f368c2a..fbaeba45 100644 --- a/admin/src/api/order.ts +++ b/admin/src/api/order.ts @@ -84,3 +84,18 @@ export function orderExport(params: any) { export function searchPatients(params: any) { return request.get({ url: '/tcm.diagnosis/searchPatient', params }) } + +/** 单条订单操作日志(分页) */ +export function orderActionLogs(params: { order_id: number; page_no?: number; page_size?: number }) { + return request.get({ url: '/order.order/actionLogs', params }) +} + +/** 按管理员统计操作次数(时间范围,未传时默认近 7 天) */ +export function orderActionLogStats(params?: { start_time?: string; end_time?: string; limit?: number }) { + return request.get({ url: '/order.order/actionLogStats', params }) +} + +/** 批量将支付单指派给医助 */ +export function orderBatchAssignAssistant(params: { order_ids: number[]; assistant_id: number }) { + return request.post({ url: '/order.order/assignAssistant', params }) +} diff --git a/admin/src/api/tcm.ts b/admin/src/api/tcm.ts index 93b9a07b..5be2ca1b 100644 --- a/admin/src/api/tcm.ts +++ b/admin/src/api/tcm.ts @@ -388,8 +388,8 @@ export function prescriptionOrderLinkPayOrder(params: { return request.post({ url: '/tcm.prescriptionOrder/linkPayOrder', params }) } -/** 将「已发货」且支付审核通过的订单标记为「已完成」 */ -export function prescriptionOrderComplete(params: { id: number }) { +/** 将「已发货/已签收」且支付审核通过的订单结案(3=已完成 或 7-12 业务状态) */ +export function prescriptionOrderComplete(params: { id: number; fulfillment_status: number }) { return request.post({ url: '/tcm.prescriptionOrder/complete', params }) } diff --git a/admin/src/components/tcm-prescription/index.vue b/admin/src/components/tcm-prescription/index.vue index a420516e..669b0b0e 100644 --- a/admin/src/components/tcm-prescription/index.vue +++ b/admin/src/components/tcm-prescription/index.vue @@ -784,8 +784,8 @@ const formData = reactive({ dose_unit: '剂', usage_days: 7, times_per_day: 2, - usage_instruction: '水煎服,一日二次', - usage_time: '饭前', + usage_instruction: '', + usage_time: '饭后', usage_way: '温水送服', dietary_taboo: [], usage_notes: '', diff --git a/admin/src/views/consumer/prescription/order_list.vue b/admin/src/views/consumer/prescription/order_list.vue index 78be33f3..158b6a27 100644 --- a/admin/src/views/consumer/prescription/order_list.vue +++ b/admin/src/views/consumer/prescription/order_list.vue @@ -406,12 +406,21 @@ @@ -802,7 +811,11 @@ - + @@ -1314,6 +1327,35 @@ + + +

请选择本单结案状态。选择「已完成」时,实付将按已关联的支付单金额汇总。

+ + + + +
服用方式: {{ prescriptionViewData.usage_way ? ' ' + prescriptionViewData.usage_way : '' }} -
- 出丸:{{ slipPillGrams === null ? '—' : slipPillGrams }} 克 +
+
每次用量约:{{ slipPerBagDosageText }}
+
+ 出丸:{{ slipPillGrams === null ? '—' : slipPillGrams }} 克 +
忌口:{{ slipDietaryText }}
{{ prescriptionViewData.usage_notes }}
@@ -1878,7 +1923,13 @@ const fulfillmentStatusTabs = [ { label: '已发货', value: 5 }, { label: '已签收', value: 6 }, { label: '已完成', value: 3 }, - { label: '已取消', value: 4 } + { label: '已取消', value: 4 }, + { label: '进行中', value: 7 }, + { label: '暂不制药', value: 8 }, + { label: '拒收', value: 9 }, + { label: '退款', value: 10 }, + { label: '保留药方', value: 11 }, + { label: '制药缓发', value: 12 } ] function handleFulfillmentStatusTabClick(value: number | '') { @@ -2035,7 +2086,13 @@ function fulfillmentText(s: number | undefined) { 3: '已完成', 4: '已取消', 5: '已发货', - 6: '已签收' + 6: '已签收', + 7: '进行中', + 8: '暂不制药', + 9: '拒收', + 10: '退款', + 11: '保留药方', + 12: '制药缓发' } return m[Number(s)] ?? '—' } @@ -2047,6 +2104,9 @@ function fulfillmentTagType(s: number | undefined): 'success' | 'warning' | 'dan if (n === 5) return 'primary' if (n === 4) return 'danger' if (n === 2) return 'warning' + if (n === 7) return 'warning' + if (n === 8 || n === 11 || n === 12) return 'info' + if (n === 9 || n === 10) return 'danger' return 'info' } @@ -2182,9 +2242,10 @@ const workflowActiveStep = computed(() => { const rx = Number(detailData.value.prescription_audit_status) const pay = Number(detailData.value.payment_slip_audit_status) - if (fs === 3) return 5 // 订单完成 + if (fs === 3 || [8, 9, 10, 11, 12].includes(fs)) return 5 // 订单完成 / 业务结案 if (fs === 6) return 4 // 已签收(仍停留在"已发货/送达"环节) if (fs === 5) return 4 // 已发货 + if (fs === 7) return 4 // 进行中 if (fs === 4) { // 已取消 if (rx === 2) return 1 @@ -2218,8 +2279,9 @@ const workflowPayStatus = computed(() => { const workflowFulfillStatus = computed(() => { const fs = Number(detailData.value?.fulfillment_status) - if (fs === 3 || fs === 5 || fs === 6) return 'success' - if (fs === 4) return 'error' + if (fs === 3 || fs === 5 || fs === 6 || fs === 8 || fs === 11 || fs === 12) return 'success' + if (fs === 4 || fs === 9 || fs === 10) return 'error' + if (fs === 7) return 'process' if (workflowActiveStep.value === 3) return 'process' return 'wait' }) @@ -2329,7 +2391,16 @@ const logisticsTracePayload = ref | null>(null) const detailLogs = ref([]) +function canViewPrescriptionOrderLogs() { + const p = userStore.perms || [] + return p.includes('*') || p.includes('tcm.prescriptionOrder/logs') +} + async function fetchLogs(id: number) { + if (!canViewPrescriptionOrderLogs()) { + detailLogs.value = [] + return + } try { const res: any = await prescriptionOrderLogs({ id }) detailLogs.value = res?.data ?? res ?? [] @@ -3082,6 +3153,44 @@ async function submitShip() { } } +const completeOrderStatusOptions = [ + { value: 3, label: '已完成' }, + { value: 7, label: '进行中' }, + { value: 8, label: '暂不制药' }, + { value: 9, label: '拒收' }, + { value: 10, label: '退款' }, + { value: 11, label: '保留药方' }, + { value: 12, label: '制药缓发' } +] as const + +const completeOrderDialogVisible = ref(false) +const completeOrderId = ref(0) +const completeFulfillmentStatus = ref(3) +const completeOrderSubmitting = ref(false) + +async function submitCompleteOrder() { + const id = completeOrderId.value + if (!id) return + completeOrderSubmitting.value = true + try { + await prescriptionOrderComplete({ id, fulfillment_status: completeFulfillmentStatus.value }) + feedback.msgSuccess('订单状态已更新') + completeOrderDialogVisible.value = false + getLists() + if (detailVisible.value && detailData.value?.id === id) { + try { + const r: any = await prescriptionOrderDetail({ id }) + const nd = r?.data ?? r ?? null + if (nd) detailData.value = nd + } catch { /* 静默 */ } + } + } catch { + /* 拦截器已提示 */ + } finally { + completeOrderSubmitting.value = false + } +} + // ─── 补齐支付单(已发货状态)──────────────────────────────────────────── const addPayOrderVisible = ref(false) const addPayOrderSaving = ref(false) @@ -3221,29 +3330,11 @@ async function submitAddPayOrder() { } } -// ─── 完成订单(已发货 + 支付审核通过)──────────────────────────────────────────── -async function confirmComplete(row: { id: number }) { - try { - await ElMessageBox.confirm( - '确认将该订单标记为「已完成」?此操作不可撤销。', - '完成订单', - { type: 'success', confirmButtonText: '确认完成', cancelButtonText: '暂不处理' } - ) - await prescriptionOrderComplete({ id: row.id }) - feedback.msgSuccess('订单已标记为「已完成」') - getLists() - if (detailVisible.value && detailData.value?.id === row.id) { - try { - const r: any = await prescriptionOrderDetail({ id: row.id }) - const nd = r?.data ?? r ?? null - if (nd) detailData.value = nd - } catch { /* 静默 */ } - } - } catch (e: any) { - if (e !== 'cancel' && e !== 'close') { - /* 拦截器已提示 */ - } - } +// ─── 完成订单(已发货/已签收 + 支付审核通过)──────────────────────────────────────────── +function confirmComplete(row: { id: number }) { + completeOrderId.value = row.id + completeFulfillmentStatus.value = 3 + completeOrderDialogVisible.value = true } // ─── 撤回处方审核 ──────────────────────────────────────────── @@ -3327,6 +3418,14 @@ const slipChuwanVisible = computed(() => { return (d.prescription_type || '浓缩水丸') === '浓缩水丸' }) +/** 与详情「用量」、开方时「用量」同一字段:浓缩水丸为每袋 g 数 */ +const slipPerBagDosageText = computed(() => { + const d = prescriptionViewData.value + if (!d || (d.prescription_type || '浓缩水丸') !== '浓缩水丸') return '—' + if (d.dosage_amount == null || d.dosage_amount === '') return '—' + return `${d.dosage_amount}${d.dosage_unit || 'g'}` +}) + const slipPillGrams = computed(() => { const d = prescriptionViewData.value if (!d || (d.prescription_type || '浓缩水丸') !== '浓缩水丸') return null diff --git a/admin/src/views/order/index.vue b/admin/src/views/order/index.vue index d688bb44..ca055cbe 100644 --- a/admin/src/views/order/index.vue +++ b/admin/src/views/order/index.vue @@ -40,15 +40,21 @@ - + + + + + + - + + @@ -67,6 +73,12 @@ 查询 重置 + + 操作统计 + +
+ + 将创建人指给医助 + + 已选 {{ selectedOrderIds.length }} 条 +
+ @@ -202,7 +226,7 @@ 小程序码 @@ -296,6 +320,87 @@ {{ detailData.remark || '无' }} + 操作记录 +

谁在什么时间对本单做了哪些操作(数据来自服务器记录)。

+ + + + + + +
+ +
+ + + + +

统计范围:{{ statsRangeText }}

+ + + + + + 查询 + + + + + + +
+ + +

+ 将 {{ selectedOrderIds.length }} 条支付单的「创建人」改为所选医助,并写入各单操作日志。 +

+ + + +
@@ -305,7 +410,14 @@ width="500px" > - + + 补单支付 @@ -321,7 +433,7 @@ - 创建后将生成订单号,请在企业微信发起收款时将该订单号填写为「商户订单号」,收款成功后系统将自动更新订单状态。 + + + 通过付呗收款的支付单,创建后请按实际对账/审核流程在列表中处理。 + + + +
+ 开启后,新订单的支付状态为「待审核」;未开启则为「待支付」。 +
+
+ + + + @@ -538,8 +684,29 @@