diff --git a/admin/src/api/tcm.ts b/admin/src/api/tcm.ts
index 42303f29..e98308ee 100644
--- a/admin/src/api/tcm.ts
+++ b/admin/src/api/tcm.ts
@@ -500,6 +500,11 @@ export function prescriptionOrderUpdateAmount(params: { id: number; amount: numb
return request.post({ url: '/tcm.prescriptionOrder/updateAmount', params })
}
+/** 设置发货类型:gancao 甘草药房 / direct 洛阳药房 */
+export function prescriptionOrderSetShipMode(params: { id: number; ship_mode: 'gancao' | 'direct' }) {
+ return request.post({ url: '/tcm.prescriptionOrder/setShipMode', params })
+}
+
// ========== 处方库 ==========
// 处方库列表
diff --git a/admin/src/views/consumer/prescription/order_list.vue b/admin/src/views/consumer/prescription/order_list.vue
index 88c7a508..6ae7f2d0 100644
--- a/admin/src/views/consumer/prescription/order_list.vue
+++ b/admin/src/views/consumer/prescription/order_list.vue
@@ -562,6 +562,28 @@
round
class="ml-2"
>甘草 {{ detailData.gancao_reciperl_order_no }}
+
+ 发货类型
+
+ 甘草药房
+ 洛阳药房
+
+ {{ shipModeLabel(detailData.ship_mode) }}
+
-
- 甘草药房直发
- 洛阳药房直发
-
+ {{ shipDialogModeDisplay }}
+ 请在订单详情顶部「发货类型」中设置,此处不可修改
@@ -2571,6 +2595,7 @@ import {
prescriptionOrderShip,
prescriptionOrderLogs,
prescriptionOrderUpdateAmount,
+ prescriptionOrderSetShipMode,
prescriptionOrderAddPayOrder,
prescriptionOrderComplete,
prescriptionOrderRevokeRxAudit,
@@ -3364,6 +3389,70 @@ function canShipRow(row: { fulfillment_status?: number }) {
return Number(row.fulfillment_status) === 2
}
+type ShipMode = 'gancao' | 'direct'
+
+const hasSetShipModePerm = computed(() => {
+ const p = userStore.perms || []
+ return p.includes('*') || p.includes('tcm.prescriptionOrder/setShipMode')
+})
+
+function normalizeShipMode(v: unknown): ShipMode {
+ return String(v || '').toLowerCase() === 'direct' ? 'direct' : 'gancao'
+}
+
+function shipModeLabel(v: unknown): string {
+ return normalizeShipMode(v) === 'direct' ? '洛阳药房' : '甘草药房'
+}
+
+function isShipModeLockedToGancao(row: { gancao_reciperl_order_no?: string | null }) {
+ return String(row.gancao_reciperl_order_no || '').trim() !== ''
+}
+
+function canEditShipMode(row: { fulfillment_status?: number }) {
+ const fs = Number(row.fulfillment_status)
+ return fs !== 3 && fs !== 4
+}
+
+const shipModeSaving = ref(false)
+
+function isSamePrescriptionOrderId(a: unknown, b: unknown) {
+ const na = Number(a)
+ const nb = Number(b)
+ return na > 0 && na === nb
+}
+
+const shipDialogModeDisplay = computed(() => {
+ return normalizeShipMode(shipForm.ship_mode) === 'direct' ? '洛阳药房直发' : '甘草药房直发'
+})
+
+async function onDetailShipModeChange(mode: string | number | boolean | undefined) {
+ const row = detailData.value
+ if (!row?.id) return
+ const next = normalizeShipMode(mode)
+ const prev = normalizeShipMode(row.ship_mode)
+ if (next === prev) return
+ if (!canEditShipMode(row)) {
+ feedback.msgWarning('当前订单状态不可修改发货类型')
+ return
+ }
+ shipModeSaving.value = true
+ try {
+ await prescriptionOrderSetShipMode({ id: row.id, ship_mode: next })
+ if (detailData.value) detailData.value.ship_mode = next
+ if (shipVisible.value && isSamePrescriptionOrderId(shipRowId.value, row.id)) {
+ shipForm.ship_mode = next
+ }
+ await refreshCurrentPrescriptionOrderDetail()
+ feedback.msgSuccess('发货类型已保存')
+ getLists()
+ void fetchLogs(row.id)
+ } catch {
+ /* 拦截器已提示 */
+ } finally {
+ shipModeSaving.value = false
+ }
+}
+
function canAddPayOrderRow(row: { fulfillment_status?: number }) {
// 已发货(5) / 已签收(6) 状态可补齐支付单
const fs = Number(row.fulfillment_status)
@@ -4745,14 +4834,31 @@ const shipForm = reactive({
tracking_number: ''
})
+function resolveShipModeForRow(row: { id: number; ship_mode?: unknown }) {
+ if (isSamePrescriptionOrderId(detailData.value?.id, row.id)) {
+ return normalizeShipMode(detailData.value!.ship_mode)
+ }
+ return normalizeShipMode(row.ship_mode)
+}
+
function openShip(row: { id: number; express_company?: unknown; tracking_number?: unknown; ship_mode?: unknown }) {
- shipRowId.value = row.id
- shipForm.ship_mode = String(row.ship_mode || 'gancao') || 'gancao'
+ shipRowId.value = Number(row.id)
+ shipForm.ship_mode = resolveShipModeForRow(row)
shipForm.express_company = String(row.express_company || 'auto') || 'auto'
shipForm.tracking_number = String(row.tracking_number || '')
shipVisible.value = true
}
+watch(
+ () => detailData.value?.ship_mode,
+ (v) => {
+ if (!shipVisible.value || !shipRowId.value || !isSamePrescriptionOrderId(detailData.value?.id, shipRowId.value)) {
+ return
+ }
+ shipForm.ship_mode = normalizeShipMode(v)
+ }
+)
+
async function submitShip() {
if (!shipForm.tracking_number.trim()) {
feedback.msgError('请先填写快递单号再确认发货')
@@ -4762,7 +4868,7 @@ async function submitShip() {
try {
await prescriptionOrderShip({
id: shipRowId.value,
- ship_mode: shipForm.ship_mode === 'direct' ? 'direct' : 'gancao',
+ ship_mode: normalizeShipMode(shipForm.ship_mode),
express_company: shipForm.express_company || 'auto',
tracking_number: shipForm.tracking_number.trim()
})
diff --git a/server/app/adminapi/controller/tcm/PrescriptionOrderController.php b/server/app/adminapi/controller/tcm/PrescriptionOrderController.php
index 9c8c7b6d..16a95eac 100755
--- a/server/app/adminapi/controller/tcm/PrescriptionOrderController.php
+++ b/server/app/adminapi/controller/tcm/PrescriptionOrderController.php
@@ -124,6 +124,25 @@ class PrescriptionOrderController extends BaseAdminController
return $this->success('修改成功');
}
+ /**
+ * 设置发货类型(甘草 / 洛阳)
+ */
+ public function setShipMode()
+ {
+ $params = (new PrescriptionOrderValidate())->post()->goCheck('setShipMode');
+ $result = PrescriptionOrderLogic::setShipMode(
+ (int) $params['id'],
+ (string) ($params['ship_mode'] ?? 'gancao'),
+ $this->adminId,
+ $this->adminInfo
+ );
+ if ($result === false) {
+ return $this->fail(PrescriptionOrderLogic::getError());
+ }
+
+ return $this->success('已保存', $result);
+ }
+
/**
* 修改关联处方的患者姓名与手机号(订单详情场景)
*/
diff --git a/server/app/adminapi/logic/tcm/PrescriptionOrderLogic.php b/server/app/adminapi/logic/tcm/PrescriptionOrderLogic.php
index 072e0dfe..3faacb1a 100755
--- a/server/app/adminapi/logic/tcm/PrescriptionOrderLogic.php
+++ b/server/app/adminapi/logic/tcm/PrescriptionOrderLogic.php
@@ -677,9 +677,10 @@ class PrescriptionOrderLogic
$rows = Order::whereIn('id', $ids)->whereNull('delete_time')
->field(['id', 'order_no', 'order_type', 'amount', 'status', 'create_time', 'creator_id', 'remark', 'is_exempt'])
->order('id', 'asc')
+ ->where('status', 2)
->select()
->toArray();
-
+
$creatorIds = array_values(array_unique(array_filter(array_map('intval', array_column($rows, 'creator_id')))));
$creatorNames = [];
if ($creatorIds !== []) {
@@ -1664,6 +1665,7 @@ class PrescriptionOrderLogic
$order->express_company = self::normalizeExpressCompany($expressCompany);
$order->tracking_number = $trackingNumber;
+ $order->ship_mode = $shipMode;
// 仅履约中(2)时才推进到已发货(5),已发货(5)则只更新快递信息保持状态
$isFirstShip = false;
if ((int) $order->fulfillment_status === 2) {
@@ -2425,7 +2427,7 @@ class PrescriptionOrderLogic
$linkedPayPaidTotal += (float) ($o['amount'] ?? 0);
}
$linkedPayPaidTotal = round($linkedPayPaidTotal, 2);
-
+
if ($targetFulfillmentStatus === 3) {
$order->fulfillment_status = 3;
$order->paid = $linkedPayPaidTotal;
@@ -3267,6 +3269,72 @@ class PrescriptionOrderLogic
];
}
+ /**
+ * 设置发货类型(甘草 / 洛阳),与确认发货选项一致
+ *
+ * @return array|false
+ */
+ public static function setShipMode(int $id, string $shipMode, int $adminId, array $adminInfo)
+ {
+ self::$error = '';
+
+ $order = PrescriptionOrder::where('id', $id)->whereNull('delete_time')->find();
+ if (!$order) {
+ self::$error = '订单不存在';
+
+ return false;
+ }
+ if (!self::canAccessOrder($order, $adminId, $adminInfo)) {
+ self::$error = '无权限操作';
+
+ return false;
+ }
+ $fs = (int) $order->fulfillment_status;
+ if ($fs === 3 || $fs === 4) {
+ self::$error = '已完成或已取消的订单不可修改发货类型';
+
+ return false;
+ }
+
+ $shipMode = self::normalizeShipMode($shipMode);
+ if ($shipMode === 'direct' && trim((string) $order->gancao_reciperl_order_no) !== '') {
+ self::$error = '已上传甘草药方,发货类型须为甘草药房';
+
+ return false;
+ }
+
+ $oldMode = self::normalizeShipMode((string) ($order->ship_mode ?? 'gancao'));
+ if ($oldMode === $shipMode) {
+ $out = $order->toArray();
+ self::maskInternalCostIfNeeded($out, $adminInfo);
+ self::maskRemarkExtraIfNeeded($out, $adminInfo);
+ self::attachLinkedPayOrders($out);
+
+ return $out;
+ }
+
+ $order->ship_mode = $shipMode;
+
+ try {
+ $order->save();
+ } catch (\Throwable $e) {
+ self::$error = $e->getMessage();
+
+ return false;
+ }
+
+ $oldText = $oldMode === 'direct' ? '洛阳药房' : '甘草药房';
+ $newText = $shipMode === 'direct' ? '洛阳药房' : '甘草药房';
+ self::writeLog($id, $adminId, $adminInfo, 'set_ship_mode', '发货类型:' . $oldText . ' → ' . $newText);
+
+ $out = $order->toArray();
+ self::maskInternalCostIfNeeded($out, $adminInfo);
+ self::maskRemarkExtraIfNeeded($out, $adminInfo);
+ self::attachLinkedPayOrders($out);
+
+ return $out;
+ }
+
/**
* 修改订单金额
*/
diff --git a/server/app/adminapi/validate/tcm/PrescriptionOrderValidate.php b/server/app/adminapi/validate/tcm/PrescriptionOrderValidate.php
index d22a37b5..dd4eef12 100755
--- a/server/app/adminapi/validate/tcm/PrescriptionOrderValidate.php
+++ b/server/app/adminapi/validate/tcm/PrescriptionOrderValidate.php
@@ -78,6 +78,7 @@ class PrescriptionOrderValidate extends BaseValidate
'previewGancaoRecipel' => ['id'],
'patchPrescriptionPatient' => ['id', 'patient_name', 'phone'],
'updateAmount' => ['id', 'amount'],
+ 'setShipMode' => ['id', 'ship_mode'],
];
public function updateAmount(): PrescriptionOrderValidate
diff --git a/server/sql/1.9.20260519/add_prescription_order_set_ship_mode_menu.sql b/server/sql/1.9.20260519/add_prescription_order_set_ship_mode_menu.sql
new file mode 100644
index 00000000..f1b0aa74
--- /dev/null
+++ b/server/sql/1.9.20260519/add_prescription_order_set_ship_mode_menu.sql
@@ -0,0 +1,16 @@
+-- 处方业务订单:设置发货类型(甘草 / 洛阳)
+-- 执行前确认表前缀为 zyt_;若已有相同 perms 则跳过。
+
+SET @po_menu_id := (SELECT id FROM zyt_system_menu WHERE perms = 'tcm.prescriptionOrder/lists' LIMIT 1);
+
+INSERT INTO zyt_system_menu (
+ pid, type, name, icon, sort, perms, paths, component,
+ selected, params, is_cache, is_show, is_disable, create_time, update_time
+)
+SELECT
+ @po_menu_id, 'A', '设置发货类型', '', 61,
+ 'tcm.prescriptionOrder/setShipMode', '', '',
+ '', '', 0, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
+FROM DUAL
+WHERE @po_menu_id IS NOT NULL
+ AND NOT EXISTS (SELECT 1 FROM zyt_system_menu WHERE perms = 'tcm.prescriptionOrder/setShipMode');
diff --git a/server/sql/1.9.20260519/add_prescription_order_ship_mode.sql b/server/sql/1.9.20260519/add_prescription_order_ship_mode.sql
new file mode 100644
index 00000000..86915755
--- /dev/null
+++ b/server/sql/1.9.20260519/add_prescription_order_ship_mode.sql
@@ -0,0 +1,7 @@
+-- 业务订单:发货药方(甘草 / 洛阳),与确认发货 ship_mode 一致
+-- 执行前确认表前缀为 zyt_;若列已存在可跳过。
+
+ALTER TABLE `zyt_tcm_prescription_order`
+ ADD COLUMN `ship_mode` varchar(16) NOT NULL DEFAULT 'gancao'
+ COMMENT '发货药方:gancao=甘草药房 direct=洛阳药房'
+ AFTER `express_company`;