kboss/f/web-kboss/src/views/FinancialSettlementCenter/SettlementStatementPreview.vue
2026-07-28 16:13:32 +08:00

198 lines
7.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<SettlementPageFrame>
<SettlementPageHeader
icon="el-icon-view"
title="结算单预览"
description="创建结算单前预览明细,检查指定账期是否已有结算单,并返回可结算账单明细。"
endpoint="GET /bill/finance_settlement_preview.dspy"
>
<template #actions>
<button type="button" class="settlement-btn settlement-btn--primary" :disabled="loading" @click="loadPreview">
<i class="el-icon-view" />{{ loading ? '预览中...' : '预览' }}
</button>
</template>
</SettlementPageHeader>
<section class="settlement-card settlement-card--padded" style="margin-bottom: 24px;">
<div class="settlement-card-heading" style="margin-bottom: 18px;">
<i class="el-icon-filter" />
<span>预览条件</span>
</div>
<div class="settlement-filter-grid">
<div class="settlement-field">
<label class="settlement-label">对手方类型</label>
<div class="settlement-choice-group">
<button type="button" class="settlement-choice" :class="{ 'is-active': form.counterparty_type === 'supplier' }" @click="form.counterparty_type = 'supplier'">供应商</button>
<button type="button" class="settlement-choice" :class="{ 'is-active': form.counterparty_type === 'reseller' }" @click="form.counterparty_type = 'reseller'">分销商</button>
</div>
</div>
<div class="settlement-field">
<label class="settlement-label">对手方</label>
<input v-model.trim="form.counterparty_orgid" class="settlement-input" type="text" placeholder="请输入供应商或分销商机构 ID">
</div>
<div class="settlement-field">
<label class="settlement-label">账期类型</label>
<div class="settlement-choice-group">
<button type="button" class="settlement-choice" :class="{ 'is-active': form.period_type === 'day' }" @click="form.period_type = 'day'">日结</button>
<button type="button" class="settlement-choice" :class="{ 'is-active': form.period_type === 'month' }" @click="form.period_type = 'month'">月结</button>
</div>
</div>
<div class="settlement-field">
<label class="settlement-label">账期开始</label>
<input v-model="form.period_start" class="settlement-input" type="date">
</div>
<div class="settlement-field">
<label class="settlement-label">账期结束</label>
<input v-model="form.period_end" class="settlement-input" type="date">
</div>
</div>
</section>
<section v-if="previewed && existingSettlement" class="settlement-alert settlement-alert--warning">
<span class="settlement-alert-icon"><i class="el-icon-warning-outline" /></span>
<div class="settlement-alert-content">
<b>该账期已存在结算单</b>
<p>结算单号{{ existingSettlement.no }}当前状态<SettlementStatusBadge :status="existingSettlement.status" /></p>
</div>
</section>
<section v-else-if="previewed" class="settlement-alert">
<span class="settlement-alert-icon"><i class="el-icon-circle-check" /></span>
<div class="settlement-alert-content">
<b>可创建结算单</b>
<p>当前账期未存在结算单可以创建新的结算单</p>
</div>
</section>
<div class="settlement-metric-grid">
<SettlementMetricCard label="销售金额" :value="summary.sales" icon="el-icon-wallet" />
<SettlementMetricCard label="应结算金额" :value="summary.settlement" variant="emerald" icon="el-icon-s-order" />
<SettlementMetricCard label="平台收入" :value="summary.income" variant="amber" icon="el-icon-s-marketing" />
<SettlementMetricCard label="账单数量" :value="summary.billCount" suffix="笔" variant="violet" icon="el-icon-document" />
</div>
<section class="settlement-card">
<div class="settlement-card-head">
<div class="settlement-card-heading">
<i class="el-icon-document" />
<span>可结算账单明细</span>
<small class="settlement-card-subtitle">· {{ billRows.length }} </small>
</div>
</div>
<div class="settlement-table-wrap">
<table class="settlement-table">
<thead>
<tr>
<th>账单 ID</th>
<th>订单 ID</th>
<th>账单日期</th>
<th>销售模式</th>
<th class="is-number">销售金额</th>
<th class="is-number">结算金额</th>
<th class="is-number">平台收入</th>
</tr>
</thead>
<tbody>
<tr v-for="row in billRows" :key="row.billId">
<td class="is-mono">{{ row.billId }}</td>
<td class="is-mono">{{ row.orderId }}</td>
<td><span class="is-mono"><i class="el-icon-date" style="margin-right: 4px; color: #94a3b8;" />{{ row.date }}</span></td>
<td><span class="settlement-pill">{{ row.mode }}</span></td>
<td class="is-number">{{ row.sales }}</td>
<td class="is-number is-emerald">{{ row.settlement }}</td>
<td class="is-number is-amber">{{ row.income }}</td>
</tr>
<tr v-if="previewed && !loading && !billRows.length">
<td colspan="7" style="padding: 42px; color: #94a3b8; text-align: center;">暂无可结算账单</td>
</tr>
</tbody>
</table>
</div>
</section>
</SettlementPageFrame>
</template>
<script>
import SettlementPageFrame from './SettlementPageFrame'
import SettlementPageHeader from './SettlementPageHeader'
import SettlementMetricCard from './SettlementMetricCard'
import SettlementStatusBadge from './SettlementStatusBadge'
import { settlementPreviewAPI } from '@/api/FinancialSettlementCenter'
import {
getAccountingOrgId,
getItems,
getPayload,
getSummary,
normalizeBill,
normalizeSettlement
} from './settlementHelpers'
export default {
name: 'SettlementStatementPreview',
components: {
SettlementPageFrame,
SettlementPageHeader,
SettlementMetricCard,
SettlementStatusBadge
},
data() {
return {
loading: false,
previewed: false,
existingSettlement: null,
billRows: [],
summary: {
sales: '¥0.00',
settlement: '¥0.00',
income: '¥0.00',
billCount: 0
},
form: {
counterparty_type: 'reseller',
counterparty_orgid: '',
period_type: 'month',
period_start: '2026-06-01',
period_end: '2026-06-30',
current_page: 1,
page_size: 50
}
}
},
methods: {
async loadPreview() {
const accountingOrgid = getAccountingOrgId(this.$route)
if (!accountingOrgid) {
this.$message.warning('未获取到核算机构 ID')
return
}
if (!this.form.counterparty_orgid) {
this.$message.warning('请输入对手方机构 ID')
return
}
this.loading = true
try {
const payload = getPayload(await settlementPreviewAPI({
accounting_orgid: accountingOrgid,
counterparty_type: this.form.counterparty_type,
counterparty_orgid: this.form.counterparty_orgid,
period_type: this.form.period_type,
period_start: this.form.period_start,
period_end: this.form.period_end,
current_page: this.form.current_page,
page_size: this.form.page_size
}))
this.summary = getSummary(payload)
this.billRows = getItems(payload).map(normalizeBill)
const existing = payload.existing_settlement || payload.existingSettlement
this.existingSettlement = existing ? normalizeSettlement(existing) : null
this.previewed = true
} catch (error) {
this.$message.error(error.message || '结算单预览失败')
} finally {
this.loading = false
}
}
}
}
</script>