feat(finance): show customer credit balances
This commit is contained in:
@@ -13,11 +13,15 @@ export interface FinanceAccount {
|
|||||||
actualBalance: string
|
actualBalance: string
|
||||||
frozenBalance: string
|
frozenBalance: string
|
||||||
availableBalance: string
|
availableBalance: string
|
||||||
|
creditLimit: string
|
||||||
|
creditUsed: string
|
||||||
|
creditFrozen: string
|
||||||
|
availableCredit: string
|
||||||
version: number
|
version: number
|
||||||
updatedAt: string
|
updatedAt: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AccountChangeType = 'RECHARGE' | 'DEDUCTION' | 'FREEZE' | 'UNFREEZE' | 'CONSUMPTION'
|
export type AccountChangeType = 'RECHARGE' | 'DEDUCTION' | 'FREEZE' | 'UNFREEZE' | 'CONSUMPTION' | 'CREDIT_LIMIT'
|
||||||
|
|
||||||
export interface AccountLedgerEntry {
|
export interface AccountLedgerEntry {
|
||||||
ledgerId: string
|
ledgerId: string
|
||||||
@@ -27,7 +31,10 @@ export interface AccountLedgerEntry {
|
|||||||
actualBalanceAfter: string
|
actualBalanceAfter: string
|
||||||
frozenBalanceAfter: string
|
frozenBalanceAfter: string
|
||||||
availableBalanceAfter: string
|
availableBalanceAfter: string
|
||||||
sourceType: 'CLIENT_RECHARGE' | 'MANUAL_RECHARGE' | 'MANUAL_DEDUCTION'
|
creditLimitAfter: string
|
||||||
|
creditUsedAfter: string
|
||||||
|
availableCreditAfter: string
|
||||||
|
sourceType: 'CLIENT_RECHARGE' | 'MANUAL_RECHARGE' | 'MANUAL_DEDUCTION' | 'CREDIT_LIMIT_ADJUSTMENT' | string
|
||||||
sourceNo: string
|
sourceNo: string
|
||||||
operatorName: string | null
|
operatorName: string | null
|
||||||
remark: string | null
|
remark: string | null
|
||||||
|
|||||||
@@ -27,7 +27,10 @@ test('activates the account route and maps read and recharge permissions indepen
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('renders server balances, ledger and recharge states without internal identifiers', () => {
|
test('renders server balances, ledger and recharge states without internal identifiers', () => {
|
||||||
for (const field of ['actualBalance', 'frozenBalance', 'availableBalance']) assert.match(viewSource, new RegExp(`account\\?\\.${field}`))
|
for (const field of ['actualBalance', 'frozenBalance', 'availableBalance', 'creditLimit', 'creditUsed', 'availableCredit']) assert.match(viewSource, new RegExp(`account\\?\\.${field}`))
|
||||||
|
for (const field of ['creditUsedAfter', 'availableCreditAfter']) assert.match(viewSource, new RegExp(`row\\.${field}`))
|
||||||
|
assert.match(viewSource, /实际可用资金与可用授信合计/)
|
||||||
|
assert.match(viewSource, /CREDIT_LIMIT: '授信调整'/)
|
||||||
assert.match(viewSource, /row-key="businessNo"/)
|
assert.match(viewSource, /row-key="businessNo"/)
|
||||||
assert.match(viewSource, /row-key="requestNo"/)
|
assert.match(viewSource, /row-key="requestNo"/)
|
||||||
assert.match(viewSource, /empty-text="暂无资金流水"/)
|
assert.match(viewSource, /empty-text="暂无资金流水"/)
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ const amountValid = computed(() => {
|
|||||||
const canSubmit = computed(() => amountValid.value && channelReady.value && Boolean(voucherFile.value) && !submitting.value)
|
const canSubmit = computed(() => amountValid.value && channelReady.value && Boolean(voucherFile.value) && !submitting.value)
|
||||||
|
|
||||||
const changeLabels: Record<AccountChangeType, string> = {
|
const changeLabels: Record<AccountChangeType, string> = {
|
||||||
RECHARGE: '充值', DEDUCTION: '扣款', FREEZE: '冻结', UNFREEZE: '解冻', CONSUMPTION: '消费',
|
RECHARGE: '充值', DEDUCTION: '扣款', FREEZE: '冻结', UNFREEZE: '解冻', CONSUMPTION: '消费', CREDIT_LIMIT: '授信调整',
|
||||||
}
|
}
|
||||||
const statusLabels: Record<RechargeStatus, string> = { PENDING: '待审核', APPROVED: '已通过', REJECTED: '已驳回' }
|
const statusLabels: Record<RechargeStatus, string> = { PENDING: '待审核', APPROVED: '已通过', REJECTED: '已驳回' }
|
||||||
const methodLabels: Record<RechargePaymentMethod, string> = { WECHAT: '微信支付', ALIPAY: '支付宝' }
|
const methodLabels: Record<RechargePaymentMethod, string> = { WECHAT: '微信支付', ALIPAY: '支付宝' }
|
||||||
@@ -208,7 +208,7 @@ onMounted(() => { void loadAccountData() })
|
|||||||
<template>
|
<template>
|
||||||
<div v-loading="pageLoading" class="finance-account-page" :aria-busy="pageLoading">
|
<div v-loading="pageLoading" class="finance-account-page" :aria-busy="pageLoading">
|
||||||
<div class="account-heading">
|
<div class="account-heading">
|
||||||
<div><h2>资金账户</h2><p>查看本企业 CNY 资金余额、账户流水和充值申请状态。</p></div>
|
<div><h2>资金账户</h2><p>查看本企业 CNY 资金、授信额度、账户流水和充值申请状态。</p></div>
|
||||||
<el-button v-if="canRecharge" type="primary" @click="openRecharge"><CircleDollarSign :size="17" />账户充值</el-button>
|
<el-button v-if="canRecharge" type="primary" @click="openRecharge"><CircleDollarSign :size="17" />账户充值</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -220,7 +220,10 @@ onMounted(() => { void loadAccountData() })
|
|||||||
<section class="balance-grid" aria-label="账户余额">
|
<section class="balance-grid" aria-label="账户余额">
|
||||||
<article><span>实际余额</span><strong>¥ {{ formatAmount(account?.actualBalance) }}</strong><small>当前账户实际资金</small></article>
|
<article><span>实际余额</span><strong>¥ {{ formatAmount(account?.actualBalance) }}</strong><small>当前账户实际资金</small></article>
|
||||||
<article><span>冻结金额</span><strong>¥ {{ formatAmount(account?.frozenBalance) }}</strong><small>暂不可使用的资金</small></article>
|
<article><span>冻结金额</span><strong>¥ {{ formatAmount(account?.frozenBalance) }}</strong><small>暂不可使用的资金</small></article>
|
||||||
<article class="balance-available"><span>可用余额</span><strong>¥ {{ formatAmount(account?.availableBalance) }}</strong><small>可用于后续业务支付</small></article>
|
<article class="balance-available"><span>总可用余额</span><strong>¥ {{ formatAmount(account?.availableBalance) }}</strong><small>实际可用资金与可用授信合计</small></article>
|
||||||
|
<article><span>授信额度</span><strong>¥ {{ formatAmount(account?.creditLimit) }}</strong><small>平台配置的授信上限</small></article>
|
||||||
|
<article><span>已用授信</span><strong>¥ {{ formatAmount(account?.creditUsed) }}</strong><small>已结算使用的授信</small></article>
|
||||||
|
<article><span>可用授信</span><strong>¥ {{ formatAmount(account?.availableCredit) }}</strong><small>扣除已用和冻结后的授信</small></article>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="account-card">
|
<section class="account-card">
|
||||||
@@ -232,6 +235,8 @@ onMounted(() => { void loadAccountData() })
|
|||||||
<el-table-column label="实际余额" width="145" align="right"><template #default="{ row }">¥ {{ formatAmount(row.actualBalanceAfter) }}</template></el-table-column>
|
<el-table-column label="实际余额" width="145" align="right"><template #default="{ row }">¥ {{ formatAmount(row.actualBalanceAfter) }}</template></el-table-column>
|
||||||
<el-table-column label="冻结金额" width="145" align="right"><template #default="{ row }">¥ {{ formatAmount(row.frozenBalanceAfter) }}</template></el-table-column>
|
<el-table-column label="冻结金额" width="145" align="right"><template #default="{ row }">¥ {{ formatAmount(row.frozenBalanceAfter) }}</template></el-table-column>
|
||||||
<el-table-column label="可用余额" width="145" align="right"><template #default="{ row }">¥ {{ formatAmount(row.availableBalanceAfter) }}</template></el-table-column>
|
<el-table-column label="可用余额" width="145" align="right"><template #default="{ row }">¥ {{ formatAmount(row.availableBalanceAfter) }}</template></el-table-column>
|
||||||
|
<el-table-column label="已用授信" width="145" align="right"><template #default="{ row }">¥ {{ formatAmount(row.creditUsedAfter) }}</template></el-table-column>
|
||||||
|
<el-table-column label="可用授信" width="145" align="right"><template #default="{ row }">¥ {{ formatAmount(row.availableCreditAfter) }}</template></el-table-column>
|
||||||
<el-table-column prop="operatorName" label="操作人" min-width="130"><template #default="{ row }">{{ row.operatorName || '—' }}</template></el-table-column>
|
<el-table-column prop="operatorName" label="操作人" min-width="130"><template #default="{ row }">{{ row.operatorName || '—' }}</template></el-table-column>
|
||||||
<el-table-column prop="remark" label="备注" min-width="180"><template #default="{ row }">{{ row.remark || '—' }}</template></el-table-column>
|
<el-table-column prop="remark" label="备注" min-width="180"><template #default="{ row }">{{ row.remark || '—' }}</template></el-table-column>
|
||||||
<el-table-column label="发生时间" width="170"><template #default="{ row }">{{ formatDateTime(row.createdAt) }}</template></el-table-column>
|
<el-table-column label="发生时间" width="170"><template #default="{ row }">{{ formatDateTime(row.createdAt) }}</template></el-table-column>
|
||||||
|
|||||||
Reference in New Issue
Block a user