feat: 新30号准则P2 — MPM计算器+旧格式双列对比
This commit is contained in:
@@ -92,7 +92,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="new30-net-profit">
|
||||
<div class="new30-net-profit" v-if="new30Format !== 'dual'">
|
||||
<div class="new30-profit-row">
|
||||
<span class="new30-profit-label">合计:</span>
|
||||
<span class="new30-profit-value" :class="{ negative: new30NetProfit < 0 }">
|
||||
@@ -102,9 +102,57 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 双列对比模式 -->
|
||||
<div v-if="new30Format === 'dual' && dualComparisonData" class="dual-comparison">
|
||||
<div class="dual-desc">新旧准则双列对比 — 旧准则(一行到底) vs 新准则(五板块)</div>
|
||||
|
||||
<div class="dual-grid">
|
||||
<!-- 旧准则列 -->
|
||||
<div class="dual-col">
|
||||
<div class="dual-col-header old-col">旧准则格式</div>
|
||||
<el-table :data="dualComparisonData.old_format?.items || []" border stripe size="small" style="width:100%;">
|
||||
<el-table-column prop="name" label="项目" width="180">
|
||||
<template #default="{ row }">
|
||||
<span :style="{ fontWeight: row.is_total ? 700 : row.is_subtotal ? 600 : 400 }">{{ row.name }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="金额" width="140" align="right">
|
||||
<template #default="{ row }">
|
||||
<span :style="{ fontWeight: row.is_total ? 700 : 400 }">
|
||||
{{ row.value != null ? '¥ ' + row.value.toLocaleString() : '-' }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 新准则列 -->
|
||||
<div class="dual-col">
|
||||
<div class="dual-col-header new-col">新30号准则格式</div>
|
||||
<div class="dual-blocks">
|
||||
<div v-for="block in dualComparisonData.new_format?.blocks || []" :key="block.key" class="dual-block">
|
||||
<div class="dual-block-header">
|
||||
<span class="dual-block-name">{{ block.short_name }}</span>
|
||||
<span class="dual-block-subtotal">{{ formatMoney(block.subtotal) }}</span>
|
||||
</div>
|
||||
<div v-for="item in block.items" :key="item.code" class="dual-block-item">
|
||||
<span class="dual-item-name">{{ item.name }}</span>
|
||||
<span class="dual-item-amount">{{ item.effective != null ? formatMoney(item.effective) : '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dual-net-profit">
|
||||
<span>净利润:</span>
|
||||
<span class="dual-net-val">{{ formatMoney(dualComparisonData.new_format?.net_profit) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="new30-footer">
|
||||
<el-button size="small" :type="new30Format === 'new' ? 'primary' : ''" @click="switchNew30Format('new')">新准则</el-button>
|
||||
<el-button size="small" :type="new30Format === 'old' ? 'primary' : ''" @click="switchNew30Format('old')">旧准则对比</el-button>
|
||||
<el-button size="small" :type="new30Format === 'old' ? 'primary' : ''" @click="switchNew30Format('old')">旧准则</el-button>
|
||||
<el-button size="small" :type="new30Format === 'dual' ? 'primary' : ''" @click="switchNew30Format('dual')">双列对比</el-button>
|
||||
<el-button size="small" @click="exportNew30">导出</el-button>
|
||||
<span v-if="new30DemoMode" class="new30-demo-hint">⚠️ 当前显示示例数据,科目打标后显示实际数据</span>
|
||||
</div>
|
||||
@@ -357,20 +405,36 @@ const new30Blocks = ref<any[]>([])
|
||||
const new30NetProfit = ref(0)
|
||||
const new30Format = ref('new')
|
||||
const new30DemoMode = ref(false)
|
||||
const dualComparisonData = ref<any>(null)
|
||||
|
||||
async function loadNew30() {
|
||||
loadingNew30.value = true
|
||||
dualComparisonData.value = null
|
||||
try {
|
||||
const r = await api.get('/reports/profit-statement', {
|
||||
params: { period: reportPeriod.value, format: 'new' }
|
||||
})
|
||||
const params: any = { period: reportPeriod.value }
|
||||
if (new30Format.value === 'dual') {
|
||||
params.format = 'dual'
|
||||
} else {
|
||||
params.format = 'new'
|
||||
}
|
||||
const r = await api.get('/reports/profit-statement', { params })
|
||||
const d = (r as any).data || {}
|
||||
new30Blocks.value = d.blocks || []
|
||||
new30NetProfit.value = d.net_profit ?? 0
|
||||
new30DemoMode.value = !d.all_items_have_data
|
||||
|
||||
if (new30Format.value === 'dual') {
|
||||
dualComparisonData.value = d
|
||||
new30Blocks.value = d.new_format?.blocks || []
|
||||
new30NetProfit.value = d.new_format?.net_profit ?? 0
|
||||
new30DemoMode.value = !d.new_format?.all_items_have_data
|
||||
} else {
|
||||
dualComparisonData.value = null
|
||||
new30Blocks.value = d.blocks || []
|
||||
new30NetProfit.value = d.net_profit ?? 0
|
||||
new30DemoMode.value = !d.all_items_have_data
|
||||
}
|
||||
} catch (e) {
|
||||
new30Blocks.value = []
|
||||
new30NetProfit.value = 0
|
||||
dualComparisonData.value = null
|
||||
ElMessage.error('加载新30号准则利润表失败')
|
||||
} finally {
|
||||
loadingNew30.value = false
|
||||
@@ -387,7 +451,7 @@ function formatMoney(val: number): string {
|
||||
|
||||
function switchNew30Format(fmt: string) {
|
||||
new30Format.value = fmt
|
||||
if (fmt === 'new') {
|
||||
if (fmt === 'new' || fmt === 'dual') {
|
||||
loadNew30()
|
||||
} else {
|
||||
// 切换到旧准则tab
|
||||
@@ -710,4 +774,23 @@ onMounted(() => {
|
||||
.restate-dot-red { background: #cf1322; }
|
||||
.restate-dot-green { background: #389e0d; }
|
||||
.restate-dot-orange { background: #d46b08; }
|
||||
|
||||
/* 双列对比样式 */
|
||||
.dual-comparison { margin-top: 12px; }
|
||||
.dual-desc { font-size: 13px; color: #888; margin-bottom: 12px; }
|
||||
.dual-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
|
||||
@media screen and (max-width: 1000px) { .dual-grid { grid-template-columns: 1fr; } }
|
||||
.dual-col { background: #fff; border-radius: 8px; border: 1px solid #ebeef5; overflow: hidden; }
|
||||
.dual-col-header { padding: 10px 14px; font-weight: 600; font-size: 14px; color: #fff; }
|
||||
.dual-col-header.old-col { background: #909399; }
|
||||
.dual-col-header.new-col { background: #409eff; }
|
||||
.dual-blocks { padding: 8px; }
|
||||
.dual-block { margin-bottom: 8px; border: 1px solid #ebeef5; border-radius: 4px; overflow: hidden; }
|
||||
.dual-block-header { display: flex; justify-content: space-between; padding: 6px 10px; background: #f9fafc; font-size: 13px; font-weight: 600; }
|
||||
.dual-block-subtotal { color: #1a1a2e; }
|
||||
.dual-block-item { display: flex; justify-content: space-between; padding: 4px 10px 4px 16px; font-size: 12px; color: #555; border-top: 1px dashed #f0f0f0; }
|
||||
.dual-item-name { flex: 1; }
|
||||
.dual-item-amount { font-weight: 500; }
|
||||
.dual-net-profit { padding: 10px 14px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #fff; border-radius: 4px; margin: 8px; display: flex; align-items: center; gap: 8px; font-size: 14px; }
|
||||
.dual-net-val { font-size: 18px; font-weight: 700; flex: 1; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user