234 lines
9.3 KiB
Vue
234 lines
9.3 KiB
Vue
<template>
|
|
<SettlementPageFrame>
|
|
<SettlementPageHeader
|
|
icon="el-icon-s-operation"
|
|
title="流程总览"
|
|
description="财务结算全流程闭环:汇总查询、预览核对、创建结算单、提交审批和审批回调。"
|
|
endpoint="推荐调用流程"
|
|
>
|
|
<template #actions>
|
|
<button type="button" class="settlement-btn settlement-btn--primary" :disabled="loading" @click="loadData">
|
|
<i class="el-icon-refresh" />{{ loading ? '刷新中...' : '刷新数据' }}
|
|
</button>
|
|
</template>
|
|
</SettlementPageHeader>
|
|
|
|
<div class="settlement-metric-grid">
|
|
<SettlementMetricCard label="结算单总数" :value="settlementRows.length" suffix="个" icon="el-icon-tickets" />
|
|
<SettlementMetricCard label="销售金额合计" :value="money(totals.sales)" variant="emerald" icon="el-icon-wallet" />
|
|
<SettlementMetricCard label="结算金额合计" :value="money(totals.settlement)" variant="amber" icon="el-icon-s-order" />
|
|
<SettlementMetricCard label="平台收入合计" :value="money(totals.income)" variant="violet" icon="el-icon-s-marketing" />
|
|
</div>
|
|
|
|
<section class="settlement-card settlement-card--padded" style="margin-bottom: 24px;">
|
|
<div class="settlement-card-heading" style="margin-bottom: 22px;">
|
|
<i class="el-icon-s-operation" />
|
|
<span>结算流程闭环</span>
|
|
<small class="settlement-card-subtitle">· 点击任一节点进入对应功能</small>
|
|
</div>
|
|
<div class="settlement-flow-grid">
|
|
<div v-for="step in flowSteps" :key="step.index" class="settlement-flow-node" style="cursor: pointer;" @click="goStep(step.route)">
|
|
<div class="settlement-flow-icon">
|
|
<i :class="step.icon" />
|
|
<span class="settlement-flow-index">{{ step.index }}</span>
|
|
</div>
|
|
<div class="settlement-card settlement-card--hover settlement-flow-content">
|
|
<h3>{{ step.title }}</h3>
|
|
<strong>{{ step.subtitle }}</strong>
|
|
<p>{{ step.description }}</p>
|
|
<code class="settlement-flow-endpoint">{{ step.endpoint }}</code>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div style="display: flex; flex-wrap: wrap; gap: 18px; margin-top: 21px; padding-top: 17px; color: #64748b; font-size: 12px; border-top: 1px solid #e2e8f0;">
|
|
<span><i class="el-icon-s-data" style="color: #0ea5e9;" /> 数据查询</span>
|
|
<span><i class="el-icon-document-add" style="color: #f59e0b;" /> 结算单操作</span>
|
|
<span><i class="el-icon-circle-check" style="color: #10b981;" /> 审批记账</span>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="settlement-two-column">
|
|
<section class="settlement-card settlement-card--padded">
|
|
<div class="settlement-card-heading" style="margin-bottom: 9px;">
|
|
<i class="el-icon-data-analysis" />
|
|
<span>状态分布</span>
|
|
</div>
|
|
<div v-for="item in statusRows" :key="item.status" class="settlement-status-row">
|
|
<SettlementStatusBadge :status="item.status" />
|
|
<div class="settlement-progress-track">
|
|
<div class="settlement-progress-value" :class="item.color" :style="{ width: item.width }" />
|
|
</div>
|
|
<span class="settlement-progress-number">{{ item.value }}</span>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="settlement-card settlement-card--padded">
|
|
<div class="settlement-card-heading">
|
|
<i class="el-icon-video-play" />
|
|
<span>快速操作</span>
|
|
</div>
|
|
<button v-for="item in quickActions" :key="item.title" type="button" class="settlement-quick-action" @click="goStep(item.route)">
|
|
<b><i :class="item.icon" style="margin-right: 6px; color: #0284c7;" />{{ item.title }}</b>
|
|
<span>{{ item.description }}</span>
|
|
</button>
|
|
</section>
|
|
</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">· {{ settlementRows.length }} 条</small>
|
|
</div>
|
|
<button type="button" class="settlement-btn settlement-btn--ghost" @click="goStep('FinancialSettlementStatementList')">
|
|
查看全部<i class="el-icon-arrow-right" style="margin: 0 0 0 5px;" />
|
|
</button>
|
|
</div>
|
|
<div class="settlement-table-wrap">
|
|
<table class="settlement-table">
|
|
<thead>
|
|
<tr>
|
|
<th>结算单号</th>
|
|
<th>对手方</th>
|
|
<th>账期</th>
|
|
<th>类型</th>
|
|
<th class="is-number">销售金额</th>
|
|
<th>状态</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="row in recentSettlements" :key="row.id" style="cursor: pointer;" @click="goDetail(row)">
|
|
<td class="is-mono" style="font-weight: 700;">{{ row.no }}</td>
|
|
<td>{{ row.name }}</td>
|
|
<td class="is-mono is-muted">{{ row.start }} ~ {{ row.end }}</td>
|
|
<td><span class="settlement-pill">{{ row.periodType }}</span></td>
|
|
<td class="is-number">{{ row.sales }}</td>
|
|
<td><SettlementStatusBadge :status="row.status" /></td>
|
|
</tr>
|
|
<tr v-if="!loading && !recentSettlements.length">
|
|
<td colspan="6" 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 { settlementListAPI } from '@/api/FinancialSettlementCenter'
|
|
import {
|
|
getAccountingOrgId,
|
|
getItems,
|
|
getPayload,
|
|
money,
|
|
normalizeSettlement
|
|
} from './settlementHelpers'
|
|
import { flowSteps } from './settlementMockData'
|
|
|
|
export default {
|
|
name: 'ProcessOverview',
|
|
components: {
|
|
SettlementPageFrame,
|
|
SettlementPageHeader,
|
|
SettlementMetricCard,
|
|
SettlementStatusBadge
|
|
},
|
|
data() {
|
|
return {
|
|
loading: false,
|
|
flowSteps: flowSteps.map((step, index) => ({
|
|
...step,
|
|
route: [
|
|
'FinancialSettlementSummaryQuery',
|
|
'FinancialSettlementStatementPreview',
|
|
'FinancialCreateSettlementStatement',
|
|
'FinancialSubmitforApproval',
|
|
'FinancialApprovalCallback'
|
|
][index]
|
|
})),
|
|
settlementRows: [],
|
|
quickActions: [
|
|
{ icon: 'el-icon-view', title: '1. 预览结算单', description: '查看账期明细,检查重复', route: 'FinancialSettlementStatementPreview' },
|
|
{ icon: 'el-icon-circle-plus-outline', title: '2. 创建结算单', description: '生成草稿状态结算单', route: 'FinancialCreateSettlementStatement' },
|
|
{ icon: 'el-icon-s-promotion', title: '3. 提交审批', description: '送审并等待审批结果', route: 'FinancialSubmitforApproval' },
|
|
{ icon: 'el-icon-circle-check', title: '4. 审批回调', description: '处理审批结果并完成记账', route: 'FinancialApprovalCallback' }
|
|
]
|
|
}
|
|
},
|
|
computed: {
|
|
totals() {
|
|
return this.settlementRows.reduce((result, row) => ({
|
|
sales: result.sales + row.salesAmount,
|
|
settlement: result.settlement + row.settlementAmount,
|
|
income: result.income + row.incomeAmount
|
|
}), { sales: 0, settlement: 0, income: 0 })
|
|
},
|
|
recentSettlements() {
|
|
return this.settlementRows.slice(0, 5)
|
|
},
|
|
statusRows() {
|
|
const statusList = ['draft', 'approving', 'approved', 'settled', 'rejected', 'failed', 'cancelled']
|
|
const colorMap = {
|
|
approving: 'settlement-progress-value--amber',
|
|
approved: 'settlement-progress-value--emerald',
|
|
rejected: 'settlement-progress-value--rose',
|
|
failed: 'settlement-progress-value--rose'
|
|
}
|
|
const total = this.settlementRows.length
|
|
return statusList.map(status => {
|
|
const count = this.settlementRows.filter(row => row.status === status).length
|
|
const ratio = total ? (count / total) * 100 : 0
|
|
return {
|
|
status,
|
|
width: `${ratio}%`,
|
|
value: `${count} (${ratio.toFixed(0)}%)`,
|
|
color: colorMap[status] || ''
|
|
}
|
|
})
|
|
}
|
|
},
|
|
mounted() {
|
|
this.loadData()
|
|
},
|
|
methods: {
|
|
money,
|
|
async loadData() {
|
|
const accountingOrgid = getAccountingOrgId(this.$route)
|
|
if (!accountingOrgid) {
|
|
this.$message.warning('未获取到核算机构 ID')
|
|
return
|
|
}
|
|
|
|
this.loading = true
|
|
try {
|
|
const payload = getPayload(await settlementListAPI({
|
|
accounting_orgid: accountingOrgid,
|
|
current_page: 1,
|
|
page_size: 100
|
|
}))
|
|
this.settlementRows = getItems(payload).map(normalizeSettlement)
|
|
} catch (error) {
|
|
this.$message.error(error.message || '结算单概览加载失败')
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
goStep(route) {
|
|
if (route) this.$router.push({ name: route })
|
|
},
|
|
goDetail(row) {
|
|
this.$router.push({
|
|
name: 'FinancialSettlementStatementDetails',
|
|
query: { id: row.id }
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|