Merge branch 'long-0507'
This commit is contained in:
@@ -18,12 +18,40 @@ If you're using Codex or another agent-capable tool, additional project-scoped h
|
|||||||
|
|
||||||
## Subagents
|
## Subagents
|
||||||
|
|
||||||
- ALWAYS wait for all subagents to complete before yielding.
|
- ALWAYS wait for every spawned subagent to reach a terminal status before yielding, acting on partial results, or spawning followups.
|
||||||
|
- On Codex, this means calling the `wait` tool with the subagent's thread id (requires `multi_agent_v2`). Do NOT infer completion from elapsed time.
|
||||||
|
- On Claude Code / OpenCode, this means awaiting the Task/agent tool result before continuing.
|
||||||
|
- NEVER cancel or re-spawn a subagent that hasn't finished. If a subagent appears stuck, raise the wait timeout (Codex default 30s, max 1h) before judging it broken.
|
||||||
- Spawn subagents automatically when:
|
- Spawn subagents automatically when:
|
||||||
- Parallelizable work (e.g., install + verify, npm test + typecheck, multiple tasks from plan)
|
- Parallelizable work (e.g., install + verify, npm test + typecheck, multiple tasks from plan)
|
||||||
- Long-running or blocking tasks where a worker can run independently.
|
- Long-running or blocking tasks where a worker can run independently
|
||||||
- Isolation for risky changes or checks
|
- Isolation for risky changes or checks
|
||||||
|
|
||||||
|
### Codex-only — `spawn_agent` parameters
|
||||||
|
|
||||||
|
When calling `spawn_agent`, ALWAYS pass `fork_turns="none"`. Without it the child inherits the parent transcript and sees your prior `spawn_agent(...)` records, then applies the "wait for spawned subagents" rule to itself — causing `wait_agent` self-deadlock.
|
||||||
|
|
||||||
|
```text
|
||||||
|
spawn_agent(agent_type="trellis-implement", message="...", fork_turns="none")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Codex-only — multi-subagent close-loop
|
||||||
|
|
||||||
|
When `wait` returns a `completed` notification, treat it as an event signal — not as "all done". Run this loop:
|
||||||
|
|
||||||
|
1. Maintain an `expected_agents` set of dispatched sub-agent thread IDs.
|
||||||
|
2. After each `wait` update:
|
||||||
|
1. Call `list_agents` to inspect ALL live agents' status.
|
||||||
|
2. For each agent now in a terminal state:
|
||||||
|
- Verify its promised deliverable exists (e.g. `{task_dir}/research/*.md`).
|
||||||
|
- Read or summarize as needed.
|
||||||
|
- `close_agent` to release the slot.
|
||||||
|
- Remove from `expected_agents`.
|
||||||
|
3. If `expected_agents` still contains running agents → keep waiting.
|
||||||
|
4. If `expected_agents` is empty → continue main flow.
|
||||||
|
3. Never `wait` on an agent that has already reported `completed`.
|
||||||
|
4. If a `completed` agent is missing its deliverable, treat it as failed — surface that in your report instead of re-waiting.
|
||||||
|
|
||||||
Managed by Trellis. Edits outside this block are preserved; edits inside may be overwritten by a future `trellis update`.
|
Managed by Trellis. Edits outside this block are preserved; edits inside may be overwritten by a future `trellis update`.
|
||||||
|
|
||||||
<!-- TRELLIS:END -->
|
<!-- TRELLIS:END -->
|
||||||
|
|||||||
@@ -480,6 +480,11 @@ export function prescriptionOrderLogs(params: { id: number }) {
|
|||||||
return request.get({ url: '/tcm.prescriptionOrder/logs', params })
|
return request.get({ url: '/tcm.prescriptionOrder/logs', params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 修改订单金额 */
|
||||||
|
export function prescriptionOrderUpdateAmount(params: { id: number; amount: number }) {
|
||||||
|
return request.post({ url: '/tcm.prescriptionOrder/updateAmount', params })
|
||||||
|
}
|
||||||
|
|
||||||
// ========== 处方库 ==========
|
// ========== 处方库 ==========
|
||||||
|
|
||||||
// 处方库列表
|
// 处方库列表
|
||||||
|
|||||||
@@ -667,7 +667,19 @@
|
|||||||
<el-row :gutter="16" class="mb-5">
|
<el-row :gutter="16" class="mb-5">
|
||||||
<el-col :xs="12" :sm="6">
|
<el-col :xs="12" :sm="6">
|
||||||
<el-card shadow="never" class="stat-card border border-gray-100 bg-gray-50/50">
|
<el-card shadow="never" class="stat-card border border-gray-100 bg-gray-50/50">
|
||||||
<div class="stat-title text-gray-500 text-xs mb-1">总金额</div>
|
<div class="flex items-center justify-between mb-1">
|
||||||
|
<div class="stat-title text-gray-500 text-xs">总金额</div>
|
||||||
|
<el-button
|
||||||
|
v-if="canUpdateAmount(detailData)"
|
||||||
|
v-perms="['tcm.prescriptionOrder/updateAmount']"
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
link
|
||||||
|
@click="openUpdateAmount"
|
||||||
|
>
|
||||||
|
修改
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
<div class="stat-value text-red-500 font-bold text-xl">¥{{ detailData.amount }}</div>
|
<div class="stat-value text-red-500 font-bold text-xl">¥{{ detailData.amount }}</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -1223,6 +1235,48 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
v-model="updateAmountVisible"
|
||||||
|
title="修改订单金额"
|
||||||
|
width="420px"
|
||||||
|
destroy-on-close
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
@closed="resetUpdateAmountDialog"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="updateAmountFormRef"
|
||||||
|
:model="updateAmountForm"
|
||||||
|
:rules="updateAmountRules"
|
||||||
|
label-width="96px"
|
||||||
|
class="pr-2"
|
||||||
|
@submit.prevent="submitUpdateAmount"
|
||||||
|
>
|
||||||
|
<el-form-item label="当前金额">
|
||||||
|
<div class="text-sm text-gray-700 font-medium">¥{{ formatMoney(detailData?.amount) }}</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="新金额" prop="amount">
|
||||||
|
<el-input-number
|
||||||
|
v-model="updateAmountForm.amount"
|
||||||
|
:min="0.01"
|
||||||
|
:step="0.01"
|
||||||
|
:precision="2"
|
||||||
|
controls-position="right"
|
||||||
|
class="w-full"
|
||||||
|
placeholder="请输入新金额"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<div class="text-xs text-gray-400 pl-[96px] -mt-1 leading-relaxed">
|
||||||
|
已完成或已取消订单不可修改。提交成功后会刷新详情与操作日志。
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="updateAmountVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="updateAmountSaving" @click="submitUpdateAmount">
|
||||||
|
确认修改
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 编辑(分步向导与「创建业务订单」弹窗统一) -->
|
<!-- 编辑(分步向导与「创建业务订单」弹窗统一) -->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="editVisible"
|
v-model="editVisible"
|
||||||
@@ -2332,6 +2386,7 @@ import {
|
|||||||
prescriptionOrderLogisticsTrace,
|
prescriptionOrderLogisticsTrace,
|
||||||
prescriptionOrderShip,
|
prescriptionOrderShip,
|
||||||
prescriptionOrderLogs,
|
prescriptionOrderLogs,
|
||||||
|
prescriptionOrderUpdateAmount,
|
||||||
prescriptionOrderAddPayOrder,
|
prescriptionOrderAddPayOrder,
|
||||||
prescriptionOrderComplete,
|
prescriptionOrderComplete,
|
||||||
prescriptionOrderRevokeRxAudit,
|
prescriptionOrderRevokeRxAudit,
|
||||||
@@ -3107,6 +3162,12 @@ function canQuickTrackRow(row: { fulfillment_status?: number }) {
|
|||||||
return fs === 5 || fs === 6
|
return fs === 5 || fs === 6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function canUpdateAmount(row: { id?: number; fulfillment_status?: number } | null | undefined) {
|
||||||
|
if (!row?.id) return false
|
||||||
|
const fs = Number(row.fulfillment_status)
|
||||||
|
return fs !== 3 && fs !== 4
|
||||||
|
}
|
||||||
|
|
||||||
function canUploadGancaoRow(row: {
|
function canUploadGancaoRow(row: {
|
||||||
prescription_audit_status?: number
|
prescription_audit_status?: number
|
||||||
gancao_reciperl_order_no?: string
|
gancao_reciperl_order_no?: string
|
||||||
@@ -3388,6 +3449,29 @@ const logisticsTracePayload = ref<Record<string, any> | null>(null)
|
|||||||
const logisticsTracePhoneTail = ref('')
|
const logisticsTracePhoneTail = ref('')
|
||||||
|
|
||||||
const detailLogs = ref<any[]>([])
|
const detailLogs = ref<any[]>([])
|
||||||
|
const updateAmountVisible = ref(false)
|
||||||
|
const updateAmountSaving = ref(false)
|
||||||
|
const updateAmountFormRef = ref<FormInstance>()
|
||||||
|
const updateAmountForm = reactive({
|
||||||
|
id: 0,
|
||||||
|
amount: undefined as number | undefined
|
||||||
|
})
|
||||||
|
const updateAmountRules: FormRules = {
|
||||||
|
amount: [
|
||||||
|
{ required: true, message: '请输入订单金额', trigger: 'blur' },
|
||||||
|
{
|
||||||
|
validator: (_rule, value, callback) => {
|
||||||
|
const num = Number(value)
|
||||||
|
if (!Number.isFinite(num) || num <= 0) {
|
||||||
|
callback(new Error('订单金额必须大于0'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback()
|
||||||
|
},
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
function canViewPrescriptionOrderLogs() {
|
function canViewPrescriptionOrderLogs() {
|
||||||
const p = userStore.perms || []
|
const p = userStore.perms || []
|
||||||
@@ -3423,6 +3507,7 @@ function logActionText(act: string) {
|
|||||||
revoke_pay_audit: '撤回支付审核',
|
revoke_pay_audit: '撤回支付审核',
|
||||||
gancao_submit: '甘草下单',
|
gancao_submit: '甘草下单',
|
||||||
patch_rx_patient: '处方患者信息',
|
patch_rx_patient: '处方患者信息',
|
||||||
|
update_amount: '修改订单金额',
|
||||||
complete: '完成订单'
|
complete: '完成订单'
|
||||||
}
|
}
|
||||||
return m[act] || act
|
return m[act] || act
|
||||||
@@ -3507,6 +3592,24 @@ function resetPatchRxPatientForm() {
|
|||||||
patchRxPatientForm.phone = ''
|
patchRxPatientForm.phone = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resetUpdateAmountDialog() {
|
||||||
|
updateAmountForm.id = 0
|
||||||
|
updateAmountForm.amount = undefined
|
||||||
|
updateAmountFormRef.value?.clearValidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
function openUpdateAmount() {
|
||||||
|
const row = detailData.value
|
||||||
|
if (!canUpdateAmount(row)) {
|
||||||
|
feedback.msgWarning('当前订单状态不允许修改金额')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updateAmountForm.id = Number(row?.id) || 0
|
||||||
|
updateAmountForm.amount = Number(row?.amount) || undefined
|
||||||
|
updateAmountVisible.value = true
|
||||||
|
nextTick(() => updateAmountFormRef.value?.clearValidate())
|
||||||
|
}
|
||||||
|
|
||||||
async function refreshCurrentPrescriptionOrderDetail() {
|
async function refreshCurrentPrescriptionOrderDetail() {
|
||||||
const id = detailData.value?.id
|
const id = detailData.value?.id
|
||||||
if (!id) return
|
if (!id) return
|
||||||
@@ -3546,6 +3649,37 @@ async function submitPatchRxPatient() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function submitUpdateAmount() {
|
||||||
|
const form = updateAmountFormRef.value
|
||||||
|
if (!form) return
|
||||||
|
try {
|
||||||
|
await form.validate()
|
||||||
|
} catch {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!canUpdateAmount(detailData.value)) {
|
||||||
|
feedback.msgWarning('当前订单状态不允许修改金额')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const orderId = updateAmountForm.id
|
||||||
|
updateAmountSaving.value = true
|
||||||
|
try {
|
||||||
|
await prescriptionOrderUpdateAmount({
|
||||||
|
id: orderId,
|
||||||
|
amount: Number(updateAmountForm.amount)
|
||||||
|
})
|
||||||
|
feedback.msgSuccess('修改成功')
|
||||||
|
updateAmountVisible.value = false
|
||||||
|
await refreshCurrentPrescriptionOrderDetail()
|
||||||
|
await fetchLogs(orderId)
|
||||||
|
getLists()
|
||||||
|
} catch {
|
||||||
|
/* 拦截器已提示 */
|
||||||
|
} finally {
|
||||||
|
updateAmountSaving.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function openDetail(id: number) {
|
async function openDetail(id: number) {
|
||||||
// 修复 Bug:显式彻底清空缓存,防止前一次弹窗的数据残留
|
// 修复 Bug:显式彻底清空缓存,防止前一次弹窗的数据残留
|
||||||
detailData.value = null
|
detailData.value = null
|
||||||
|
|||||||
@@ -677,7 +677,19 @@
|
|||||||
<el-row :gutter="16" class="mb-5">
|
<el-row :gutter="16" class="mb-5">
|
||||||
<el-col :xs="12" :sm="6">
|
<el-col :xs="12" :sm="6">
|
||||||
<el-card shadow="never" class="stat-card border border-gray-100 bg-gray-50/50">
|
<el-card shadow="never" class="stat-card border border-gray-100 bg-gray-50/50">
|
||||||
<div class="stat-title text-gray-500 text-xs mb-1">总金额</div>
|
<div class="flex items-center justify-between mb-1">
|
||||||
|
<div class="stat-title text-gray-500 text-xs">总金额</div>
|
||||||
|
<el-button
|
||||||
|
v-if="canUpdateAmount(detailData)"
|
||||||
|
v-perms="['tcm.prescriptionOrder/updateAmount']"
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
link
|
||||||
|
@click="openUpdateAmount"
|
||||||
|
>
|
||||||
|
修改
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
<div class="stat-value text-red-500 font-bold text-xl">¥{{ detailData.amount }}</div>
|
<div class="stat-value text-red-500 font-bold text-xl">¥{{ detailData.amount }}</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -1221,6 +1233,47 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
v-model="updateAmountVisible"
|
||||||
|
title="修改订单金额"
|
||||||
|
width="92%"
|
||||||
|
destroy-on-close
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
@closed="resetUpdateAmountDialog"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="updateAmountFormRef"
|
||||||
|
:model="updateAmountForm"
|
||||||
|
:rules="updateAmountRules"
|
||||||
|
label-width="84px"
|
||||||
|
@submit.prevent="submitUpdateAmount"
|
||||||
|
>
|
||||||
|
<el-form-item label="当前金额">
|
||||||
|
<div class="text-sm text-gray-700 font-medium">¥{{ formatMoney(detailData?.amount) }}</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="新金额" prop="amount">
|
||||||
|
<el-input-number
|
||||||
|
v-model="updateAmountForm.amount"
|
||||||
|
:min="0.01"
|
||||||
|
:step="0.01"
|
||||||
|
:precision="2"
|
||||||
|
controls-position="right"
|
||||||
|
class="w-full"
|
||||||
|
placeholder="请输入新金额"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<div class="text-xs text-gray-400 pl-[84px] -mt-1 leading-relaxed">
|
||||||
|
已完成或已取消订单不可修改。提交成功后会刷新详情与操作日志。
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="updateAmountVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="updateAmountSaving" @click="submitUpdateAmount">
|
||||||
|
确认修改
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 编辑(分步向导与「创建业务订单」弹窗统一) -->
|
<!-- 编辑(分步向导与「创建业务订单」弹窗统一) -->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="editVisible"
|
v-model="editVisible"
|
||||||
@@ -2342,6 +2395,7 @@ import {
|
|||||||
prescriptionOrderLogisticsTrace,
|
prescriptionOrderLogisticsTrace,
|
||||||
prescriptionOrderShip,
|
prescriptionOrderShip,
|
||||||
prescriptionOrderLogs,
|
prescriptionOrderLogs,
|
||||||
|
prescriptionOrderUpdateAmount,
|
||||||
prescriptionOrderAddPayOrder,
|
prescriptionOrderAddPayOrder,
|
||||||
prescriptionOrderComplete,
|
prescriptionOrderComplete,
|
||||||
prescriptionOrderRevokeRxAudit,
|
prescriptionOrderRevokeRxAudit,
|
||||||
@@ -3133,6 +3187,12 @@ function handleCardMoreCommand(cmd: string, row: Record<string, any>) {
|
|||||||
else if (cmd === 'withdraw') confirmWithdraw(row as any)
|
else if (cmd === 'withdraw') confirmWithdraw(row as any)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function canUpdateAmount(row: { id?: number; fulfillment_status?: number } | null | undefined) {
|
||||||
|
if (!row?.id) return false
|
||||||
|
const fs = Number(row.fulfillment_status)
|
||||||
|
return fs !== 3 && fs !== 4
|
||||||
|
}
|
||||||
|
|
||||||
const detailVisible = ref(false)
|
const detailVisible = ref(false)
|
||||||
const detailLoading = ref(false)
|
const detailLoading = ref(false)
|
||||||
const detailData = ref<Record<string, any> | null>(null)
|
const detailData = ref<Record<string, any> | null>(null)
|
||||||
@@ -3344,6 +3404,29 @@ const logisticsTracePayload = ref<Record<string, any> | null>(null)
|
|||||||
const logisticsTracePhoneTail = ref('')
|
const logisticsTracePhoneTail = ref('')
|
||||||
|
|
||||||
const detailLogs = ref<any[]>([])
|
const detailLogs = ref<any[]>([])
|
||||||
|
const updateAmountVisible = ref(false)
|
||||||
|
const updateAmountSaving = ref(false)
|
||||||
|
const updateAmountFormRef = ref<FormInstance>()
|
||||||
|
const updateAmountForm = reactive({
|
||||||
|
id: 0,
|
||||||
|
amount: undefined as number | undefined
|
||||||
|
})
|
||||||
|
const updateAmountRules: FormRules = {
|
||||||
|
amount: [
|
||||||
|
{ required: true, message: '请输入订单金额', trigger: 'blur' },
|
||||||
|
{
|
||||||
|
validator: (_rule, value, callback) => {
|
||||||
|
const num = Number(value)
|
||||||
|
if (!Number.isFinite(num) || num <= 0) {
|
||||||
|
callback(new Error('订单金额必须大于0'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback()
|
||||||
|
},
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
function canViewPrescriptionOrderLogs() {
|
function canViewPrescriptionOrderLogs() {
|
||||||
const p = userStore.perms || []
|
const p = userStore.perms || []
|
||||||
@@ -3379,6 +3462,7 @@ function logActionText(act: string) {
|
|||||||
revoke_pay_audit: '撤回支付审核',
|
revoke_pay_audit: '撤回支付审核',
|
||||||
gancao_submit: '甘草下单',
|
gancao_submit: '甘草下单',
|
||||||
patch_rx_patient: '处方患者信息',
|
patch_rx_patient: '处方患者信息',
|
||||||
|
update_amount: '修改订单金额',
|
||||||
complete: '完成订单'
|
complete: '完成订单'
|
||||||
}
|
}
|
||||||
return m[act] || act
|
return m[act] || act
|
||||||
@@ -3463,6 +3547,24 @@ function resetPatchRxPatientForm() {
|
|||||||
patchRxPatientForm.phone = ''
|
patchRxPatientForm.phone = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resetUpdateAmountDialog() {
|
||||||
|
updateAmountForm.id = 0
|
||||||
|
updateAmountForm.amount = undefined
|
||||||
|
updateAmountFormRef.value?.clearValidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
function openUpdateAmount() {
|
||||||
|
const row = detailData.value
|
||||||
|
if (!canUpdateAmount(row)) {
|
||||||
|
feedback.msgWarning('当前订单状态不允许修改金额')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updateAmountForm.id = Number(row?.id) || 0
|
||||||
|
updateAmountForm.amount = Number(row?.amount) || undefined
|
||||||
|
updateAmountVisible.value = true
|
||||||
|
nextTick(() => updateAmountFormRef.value?.clearValidate())
|
||||||
|
}
|
||||||
|
|
||||||
async function refreshCurrentPrescriptionOrderDetail() {
|
async function refreshCurrentPrescriptionOrderDetail() {
|
||||||
const id = detailData.value?.id
|
const id = detailData.value?.id
|
||||||
if (!id) return
|
if (!id) return
|
||||||
@@ -3502,6 +3604,37 @@ async function submitPatchRxPatient() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function submitUpdateAmount() {
|
||||||
|
const form = updateAmountFormRef.value
|
||||||
|
if (!form) return
|
||||||
|
try {
|
||||||
|
await form.validate()
|
||||||
|
} catch {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!canUpdateAmount(detailData.value)) {
|
||||||
|
feedback.msgWarning('当前订单状态不允许修改金额')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const orderId = updateAmountForm.id
|
||||||
|
updateAmountSaving.value = true
|
||||||
|
try {
|
||||||
|
await prescriptionOrderUpdateAmount({
|
||||||
|
id: orderId,
|
||||||
|
amount: Number(updateAmountForm.amount)
|
||||||
|
})
|
||||||
|
feedback.msgSuccess('修改成功')
|
||||||
|
updateAmountVisible.value = false
|
||||||
|
await refreshCurrentPrescriptionOrderDetail()
|
||||||
|
await fetchLogs(orderId)
|
||||||
|
getLists()
|
||||||
|
} catch {
|
||||||
|
/* 拦截器已提示 */
|
||||||
|
} finally {
|
||||||
|
updateAmountSaving.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function openDetail(id: number) {
|
async function openDetail(id: number) {
|
||||||
// 修复 Bug:显式彻底清空缓存,防止前一次弹窗的数据残留
|
// 修复 Bug:显式彻底清空缓存,防止前一次弹窗的数据残留
|
||||||
detailData.value = null
|
detailData.value = null
|
||||||
|
|||||||
@@ -105,6 +105,17 @@ class PrescriptionOrderController extends BaseAdminController
|
|||||||
return $this->success('保存成功', $result);
|
return $this->success('保存成功', $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function updateAmount()
|
||||||
|
{
|
||||||
|
$params = (new PrescriptionOrderValidate())->post()->goCheck('updateAmount');
|
||||||
|
$result = PrescriptionOrderLogic::updateAmount($params, $this->adminId, $this->adminInfo);
|
||||||
|
if ($result === false) {
|
||||||
|
return $this->fail(PrescriptionOrderLogic::getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success('修改成功');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改关联处方的患者姓名与手机号(订单详情场景)
|
* 修改关联处方的患者姓名与手机号(订单详情场景)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2642,6 +2642,60 @@ class PrescriptionOrderLogic
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改订单金额
|
||||||
|
*/
|
||||||
|
public static function updateAmount(array $params, int $adminId, array $adminInfo): bool
|
||||||
|
{
|
||||||
|
self::$error = '';
|
||||||
|
$id = (int) $params['id'];
|
||||||
|
$newAmount = round((float) $params['amount'], 2);
|
||||||
|
|
||||||
|
// 查询订单
|
||||||
|
$order = PrescriptionOrder::where('id', $id)->whereNull('delete_time')->find();
|
||||||
|
if (!$order) {
|
||||||
|
self::setError('订单不存在');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据权限检查
|
||||||
|
if (!self::canAccessOrder($order, $adminId, $adminInfo)) {
|
||||||
|
self::setError('无权限操作此订单');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 状态检查:已完成(3)和已取消(4)不允许修改
|
||||||
|
if (in_array((int) $order->fulfillment_status, [3, 4], true)) {
|
||||||
|
self::setError('已完成或已取消的订单不允许修改金额');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$oldAmount = round((float) $order->amount, 2);
|
||||||
|
$oldAmountCents = (int) round($oldAmount * 100);
|
||||||
|
$newAmountCents = (int) round($newAmount * 100);
|
||||||
|
|
||||||
|
// 金额未变化
|
||||||
|
if ($newAmountCents === $oldAmountCents) {
|
||||||
|
self::setError('金额未发生变化');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新金额
|
||||||
|
$order->amount = $newAmount;
|
||||||
|
try {
|
||||||
|
$order->save();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
self::setError($e->getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录日志
|
||||||
|
$summary = sprintf('将订单金额从 ¥%.2f 修改为 ¥%.2f', $oldAmount, $newAmount);
|
||||||
|
self::writeLog($id, $adminId, $adminInfo, 'update_amount', $summary);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static function writeLog(int $orderId, int $adminId, array $adminInfo, string $action, string $summary): void
|
private static function writeLog(int $orderId, int $adminId, array $adminInfo, string $action, string $summary): void
|
||||||
{
|
{
|
||||||
$adminName = $adminInfo['name'] ?? '';
|
$adminName = $adminInfo['name'] ?? '';
|
||||||
|
|||||||
@@ -77,5 +77,13 @@ class PrescriptionOrderValidate extends BaseValidate
|
|||||||
'submitGancaoRecipel' => ['id'],
|
'submitGancaoRecipel' => ['id'],
|
||||||
'previewGancaoRecipel' => ['id'],
|
'previewGancaoRecipel' => ['id'],
|
||||||
'patchPrescriptionPatient' => ['id', 'patient_name', 'phone'],
|
'patchPrescriptionPatient' => ['id', 'patient_name', 'phone'],
|
||||||
|
'updateAmount' => ['id', 'amount'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function updateAmount(): PrescriptionOrderValidate
|
||||||
|
{
|
||||||
|
return $this->only(['id', 'amount'])
|
||||||
|
->append('id', 'require|integer|gt:0')
|
||||||
|
->append('amount', 'require|float|gt:0');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
-- 处方业务订单:修改订单金额
|
||||||
|
-- 执行前确认表前缀为 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', '修改订单金额', '', 60,
|
||||||
|
'tcm.prescriptionOrder/updateAmount', '', '',
|
||||||
|
'', '', 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/updateAmount');
|
||||||
Reference in New Issue
Block a user