支持结账多轮协商与按实际消耗双比例结算

允许双方最多 6 轮修改结账方案;哈夫币按实际消耗与 buyer/seller 比例计价,打超从押金扣,押金不足禁止自动完结并引导人工争议。同步收紧结账明细展示密度。
This commit is contained in:
yml2213
2026-07-18 20:35:16 +08:00
parent 98772867a7
commit 1a4776bba0
19 changed files with 713 additions and 140 deletions
@@ -191,6 +191,34 @@ export function useOrderActions(options: UseOrderActionsOptions) {
'abnormal',
].includes(order.value.status)
})
const canCounterCheckout = computed(() => {
if (!order.value?.checkout) return false
return Boolean(order.value.checkout.can_counter)
})
const canAcceptCheckoutProposal = computed(() => {
if (!order.value?.checkout) return false
// 后端 can_accept 已含 shortfall 校验;无字段时按角色状态兜底
if (typeof order.value.checkout.can_accept === 'boolean') {
return order.value.checkout.can_accept
}
return (
(isOwner.value && order.value.status === 'pending_checkout_confirm') ||
(isRenter.value && order.value.status === 'pending_checkout_accept')
)
})
const checkoutShortfallCent = computed(() =>
Number(order.value?.checkout?.shortfall_cent || 0)
)
const checkoutOvershootCent = computed(() =>
Number(order.value?.checkout?.overshoot_amount_cent || 0)
)
const checkoutRoundLabel = computed(() => {
const c = order.value?.checkout
if (!c) return ''
const round = Number(c.round_count || 1)
const max = Number(c.max_rounds || 6)
return `${round}/${max} 轮协商`
})
const canCancelDispute = computed(() => {
return (
!!order.value &&
@@ -365,6 +393,10 @@ export function useOrderActions(options: UseOrderActionsOptions) {
async function handleConfirmCheckout() {
if (!order.value) return
if (checkoutShortfallCent.value > 0) {
options.notifyWarning('押金不足以覆盖打超/赔付,无法自动完结,请修改方案或发起争议由人工处理')
return
}
if (needsConfirm('confirmCheckout')) {
const ok = await options.confirm({
title: '确认结账',
@@ -386,20 +418,29 @@ export function useOrderActions(options: UseOrderActionsOptions) {
async function handleCounterCheckout() {
if (!order.value) return
const reasonText = counterForm.value.reason.trim()
if (!reasonText) {
options.notifyWarning('请填写修改原因')
return
}
if (!canCounterCheckout.value) {
options.notifyWarning('当前不能修改,可能已达 6 轮上限或未轮到你')
return
}
countering.value = true
try {
const reasonText = counterForm.value.reason.trim()
await counterCheckout(order.value.id, {
content: reasonText,
consumableAmountYuan: counterForm.value.consumableAmountYuan,
coin_consumed_m: counterForm.value.coin_consumed_m,
// 号主修正只保留「押金赔付扣除」;与 other 同步写入,兼容旧字段语义
otherAmountYuan: counterForm.value.depositDeductAmountYuan,
depositDeductAmountYuan: counterForm.value.depositDeductAmountYuan,
reason: reasonText,
evidence_urls: linesToList(counterForm.value.evidenceText),
})
options.notifySuccess('结账修正已提交,等待租客确认')
options.notifySuccess(
isOwner.value ? '结账修正已提交,等待租客处理' : '结账还价已提交,等待号主处理'
)
await loadOrder()
options.onCounterCheckoutSuccess?.()
} catch (error) {
@@ -411,20 +452,24 @@ export function useOrderActions(options: UseOrderActionsOptions) {
async function handleAcceptCheckout() {
if (!order.value) return
if (checkoutShortfallCent.value > 0) {
options.notifyWarning('押金不足以覆盖打超/赔付,无法自动完结,请修改方案或发起争议由人工处理')
return
}
if (needsConfirm('acceptCheckout')) {
const ok = await options.confirm({
title: '同意修正',
message: '确定同意号主的结账修正提案吗?同意后订单将完成结算。',
title: '同意结账方案',
message: '确定同意当前结账方案吗?同意后订单将完成结算。',
})
if (!ok) return
}
acceptingCheckout.value = true
try {
await acceptCheckout(order.value.id)
options.notifySuccess('已确认修正结账,订单完成')
options.notifySuccess('已确认结账,订单完成')
await loadOrder()
} catch (error) {
options.notifyError(readError(error, '确认修正失败'))
options.notifyError(readError(error, '确认结账失败'))
} finally {
acceptingCheckout.value = false
}
@@ -634,6 +679,11 @@ export function useOrderActions(options: UseOrderActionsOptions) {
ownerIncomeLabel,
canOpenDispute,
canCancelDispute,
canCounterCheckout,
canAcceptCheckoutProposal,
checkoutShortfallCent,
checkoutOvershootCent,
checkoutRoundLabel,
isCheckoutDisputeStage,
// Methods