|
|
|
@ -141,6 +141,34 @@ |
|
|
|
</template> |
|
|
|
</t-table> |
|
|
|
<div class="table-footer" v-if="simTotal"><t-pagination v-model:current="simPageNum" :total="simTotal" :page-size="10" @current-change="loadSim" /></div> |
|
|
|
<div |
|
|
|
v-if="pendingSimOrder && isPendingSimOrderActionable" |
|
|
|
class="pending-sim-order" |
|
|
|
> |
|
|
|
<div> |
|
|
|
<strong>待支付通信卡充值</strong> |
|
|
|
<small> |
|
|
|
{{ cardLabel(pendingSimOrder.simCardId) }} |
|
|
|
· {{ pendingSimOrder.amountGb != null ? `${pendingSimOrder.amountGb} GB` : '--' }} |
|
|
|
· {{ moneyFromFen(pendingSimOrder.totalFeeFen) }} |
|
|
|
· {{ payStatusName(pendingSimOrder.paymentStatus) }} |
|
|
|
</small> |
|
|
|
</div> |
|
|
|
<div class="account-card-actions" style="margin-top:0"> |
|
|
|
<t-button |
|
|
|
variant="text" |
|
|
|
theme="primary" |
|
|
|
:loading="payingPendingSim" |
|
|
|
@click="payPendingSimOrder" |
|
|
|
>去支付</t-button> |
|
|
|
<t-button |
|
|
|
variant="text" |
|
|
|
theme="danger" |
|
|
|
:loading="cancellingPendingSim" |
|
|
|
@click="cancelPendingSimOrder" |
|
|
|
>取消</t-button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="account-subsection-title"><h3>通信卡充值记录</h3><span>共 {{ simRechargeTotal }} 条</span></div> |
|
|
|
<t-table row-key="id" :data="simRechargeLogs" :columns="simRechargeColumns" empty="暂无通信卡充值记录"> |
|
|
|
<template #simCardId="{ row }">{{ cardLabel(row.simCardId) }}</template> |
|
|
|
@ -298,6 +326,9 @@ const simRechargeOpen = ref(false) |
|
|
|
const simRechargeCard = ref(null) |
|
|
|
const selectedSimPackageId = ref(0) |
|
|
|
const simRecharging = ref(false) |
|
|
|
const pendingSimOrder = ref(null) |
|
|
|
const payingPendingSim = ref(false) |
|
|
|
const cancellingPendingSim = ref(false) |
|
|
|
const editOpen = ref(false); const saving = ref(false); const editForm = ref({ name: '', email: '' }) |
|
|
|
|
|
|
|
const orderColumns = [ |
|
|
|
@ -366,6 +397,10 @@ const profileInitial = computed(() => profileName.value === '--' ? '-' : profile |
|
|
|
const invoiceOrderOptions = computed(() => [{ label: '请选择已支付订单', value: 0 }, ...invoiceOrders.value.map((order) => ({ label: `${order.id} · ${money(order.totalPrice)}`, value: order.id }))]) |
|
|
|
const activeSimCount = computed(() => simCards.value.filter((card) => simStatus(card).cls === 'normal').length) |
|
|
|
const warnSimCount = computed(() => simTotal.value - activeSimCount.value) |
|
|
|
const isPendingSimOrderActionable = computed(() => { |
|
|
|
const status = pendingSimOrder.value?.paymentStatus |
|
|
|
return status === 'unpaid' || status === 'processing' |
|
|
|
}) |
|
|
|
|
|
|
|
function applyPage(targetRef, page) { |
|
|
|
const records = page?.records || [] |
|
|
|
@ -511,6 +546,64 @@ function openSimRecharge(card) { |
|
|
|
selectedSimPackageId.value = simPackages.value[0]?.id || 0 |
|
|
|
simRechargeOpen.value = true |
|
|
|
} |
|
|
|
function mapPendingSimOrder(order) { |
|
|
|
if (!order?.id) return null |
|
|
|
return { |
|
|
|
id: order.id, |
|
|
|
simCardId: order.simCardId, |
|
|
|
amountGb: order.amountGb, |
|
|
|
totalFeeFen: order.totalFeeFen ?? order.totalPriceFen ?? null, |
|
|
|
paymentStatus: order.paymentStatus || order.payStatus || 'unpaid' |
|
|
|
} |
|
|
|
} |
|
|
|
function clearPendingSimOrderIfSettled(status) { |
|
|
|
if (status === 'paid' || status === 'cancelled' || status === 'closed') { |
|
|
|
pendingSimOrder.value = null |
|
|
|
} |
|
|
|
} |
|
|
|
async function refreshPendingSimOrder(orderId) { |
|
|
|
if (!orderId) return |
|
|
|
try { |
|
|
|
const order = await request.get(urls.SIM_RECHARGE_ORDER(orderId)) |
|
|
|
const mapped = mapPendingSimOrder(order) |
|
|
|
pendingSimOrder.value = mapped |
|
|
|
clearPendingSimOrderIfSettled(mapped?.paymentStatus) |
|
|
|
} catch { |
|
|
|
// keep local pending if refresh fails |
|
|
|
} |
|
|
|
} |
|
|
|
async function payPendingSimOrder() { |
|
|
|
if (!pendingSimOrder.value?.id || !isPendingSimOrderActionable.value) return |
|
|
|
payingPendingSim.value = true |
|
|
|
try { |
|
|
|
const payment = await createPayment('sim_recharge_order', pendingSimOrder.value.id) |
|
|
|
ui.toast(describePayment(payment)) |
|
|
|
await refreshPendingSimOrder(pendingSimOrder.value.id) |
|
|
|
await loadSim() |
|
|
|
} catch (error) { |
|
|
|
ui.toast(error.message || '发起支付失败') |
|
|
|
await refreshPendingSimOrder(pendingSimOrder.value?.id) |
|
|
|
} finally { |
|
|
|
payingPendingSim.value = false |
|
|
|
} |
|
|
|
} |
|
|
|
async function cancelPendingSimOrder() { |
|
|
|
if (!pendingSimOrder.value?.id || !isPendingSimOrderActionable.value) return |
|
|
|
const ok = await ui.confirm('取消该通信卡充值订单?', '仅待支付/支付中订单可取消。', ['订单将关闭', '可重新选择套餐充值']) |
|
|
|
if (!ok) return |
|
|
|
cancellingPendingSim.value = true |
|
|
|
try { |
|
|
|
await request.delete(urls.SIM_RECHARGE_ORDER(pendingSimOrder.value.id)) |
|
|
|
pendingSimOrder.value = null |
|
|
|
ui.toast('充值订单已取消') |
|
|
|
await loadSim() |
|
|
|
} catch (error) { |
|
|
|
ui.toast(error.message || '取消失败') |
|
|
|
await refreshPendingSimOrder(pendingSimOrder.value?.id) |
|
|
|
} finally { |
|
|
|
cancellingPendingSim.value = false |
|
|
|
} |
|
|
|
} |
|
|
|
async function submitSimRecharge() { |
|
|
|
if (!simRechargeCard.value?.id) return |
|
|
|
if (!selectedSimPackageId.value) { |
|
|
|
@ -525,12 +618,19 @@ async function submitSimRecharge() { |
|
|
|
{ packageId: Number(selectedSimPackageId.value) } |
|
|
|
) |
|
|
|
orderCreated = true |
|
|
|
pendingSimOrder.value = mapPendingSimOrder(order) |
|
|
|
const payment = await createPayment('sim_recharge_order', order.id) |
|
|
|
ui.toast(describePayment(payment)) |
|
|
|
simRechargeOpen.value = false |
|
|
|
await refreshPendingSimOrder(order.id) |
|
|
|
await loadSim() |
|
|
|
} catch (error) { |
|
|
|
ui.toast(error.message || '充值下单失败') |
|
|
|
const message = error.message || '充值下单失败' |
|
|
|
if (!orderCreated && /pending|未结|待支付|已有/.test(message) && pendingSimOrder.value?.simCardId === simRechargeCard.value?.id) { |
|
|
|
ui.toast(`${message};可先完成或取消上方待支付订单`) |
|
|
|
} else { |
|
|
|
ui.toast(message) |
|
|
|
} |
|
|
|
if (orderCreated) { |
|
|
|
simRechargeOpen.value = false |
|
|
|
await loadSim() |
|
|
|
@ -611,6 +711,28 @@ onMounted(load) |
|
|
|
display: block; |
|
|
|
margin-bottom: 12px; |
|
|
|
} |
|
|
|
.pending-sim-order { |
|
|
|
margin: 12px 0 4px; |
|
|
|
padding: 12px 14px; |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: space-between; |
|
|
|
gap: 12px; |
|
|
|
border: 1px solid #f0d7a8; |
|
|
|
border-radius: 5px; |
|
|
|
background: #fff8ea; |
|
|
|
} |
|
|
|
.pending-sim-order strong { |
|
|
|
display: block; |
|
|
|
color: #8a5a12; |
|
|
|
font-size: 12px; |
|
|
|
} |
|
|
|
.pending-sim-order small { |
|
|
|
display: block; |
|
|
|
margin-top: 4px; |
|
|
|
color: #95631d; |
|
|
|
font-size: 11px; |
|
|
|
} |
|
|
|
.traffic-order-summary :deep(.t-select) { |
|
|
|
margin: 10px 0 14px; |
|
|
|
} |
|
|
|
|