diff --git a/src/api/modules/packageSilence.ts b/src/api/modules/packageSilence.ts index 49d7f1d..b03ec4f 100644 --- a/src/api/modules/packageSilence.ts +++ b/src/api/modules/packageSilence.ts @@ -58,6 +58,13 @@ export class PackageSilenceService extends BaseService { static order(id: number): Promise> { return this.get(`${root}/orders/${id}`, undefined, quiet) } + /** 作废待支付延期订单(作废前后端先查单,已支付则按支付成功办理并拒绝作废) */ + static closeOrder( + id: number, + reason?: string + ): Promise> { + return this.post(`${root}/orders/${id}/close`, { reason }, quiet) + } static batches(params: SilenceBatchQuery): Promise> { return this.get(`${root}/batches`, params, quiet) } diff --git a/src/components/business/package-silence/SilenceDetail.vue b/src/components/business/package-silence/SilenceDetail.vue index 06ab7b0..7188bc8 100644 --- a/src/components/business/package-silence/SilenceDetail.vue +++ b/src/components/business/package-silence/SilenceDetail.vue @@ -24,6 +24,10 @@ >支付截止:{{ data.expire_at ? formatDateTime(data.expire_at) : '-' }}

+
+ 作废订单 + 作废后同一套餐可以重新下单;已支付的订单不能作废。 +
+ props.kind === 'orders' && + data.value?.status === 'pending_payment' && + data.value?.payment_method !== 'offline' && + allowed.value && + hasAuth(P.extend) + ) + async function closeOrder() { + if (handling.value || !data.value) return + const scope = pollingScope(user), + path = route.fullPath, + id = silenceId(Number(data.value.id)) + handling.value = true + try { + requireGatewayAccess(canCloseOrder.value) + const { value } = await ElMessageBox.prompt( + '作废后该订单不能再支付,同一套餐可以重新下单。作废前会先向支付渠道确认,已支付的会按支付成功办理延期。可填写作废原因(选填)。', + '作废延期订单', + { + type: 'warning', + confirmButtonText: '确认作废', + cancelButtonText: '取消', + inputPlaceholder: '作废原因(选填)' + } + ) + requireGatewayAccess( + active && canCloseOrder.value && scope === pollingScope(user) && path === route.fullPath + ) + silenceData(await Service.closeOrder(id, value?.trim() || undefined)) + if (active && scope === pollingScope(user) && path === route.fullPath) await load() + } catch (e) { + if (active && e !== 'cancel' && e !== 'close') { + actionError.value = gatewayError(e) + await load() + } + } finally { + handling.value = false + } + } async function handle(row: Record, action: 'retry' | 'close') { if (handling.value) return const scope = pollingScope(user), @@ -281,4 +326,16 @@ margin: 4px; } } + .silence-order-actions { + display: flex; + flex-wrap: wrap; + gap: 12px; + align-items: center; + margin: 12px 0; + } + + .silence-order-tip { + font-size: 13px; + color: var(--el-text-color-secondary); + }