feat(ui): 面向客户的文案中文化

系统由财务与营销人员日常使用,不是给开发者看的。本批把会渲染到页面上的
文本统一改成业务语言:
- param_registry 的 22 条参数说明重写为「管什么、钱怎么变、何时该调它」,
  去掉英文枚举名、需求编号、内部阶段号与精度约束
- 前端补 formatByCode:变更记录、版本历史、快照对比只给裸 value_text,
  需回目录按编码补 value_type 与 unit 才能翻译枚举,否则这些位置仍显示
  INCLUDE/FULL/1;编辑弹窗 BOOL 改为开启/关闭下拉
- 后端错误文案:模板报错用中文模板名并给出下一步,产品类别不再甩
  municipal_water / rail_transit
- 台账与预览落库的计提说明口语化(rate_note / strategy_note / 聚合行 note),
  去掉「基数开关=1」「#12 参数化」「9.8 方案公式」

分数原文 11/1125 与「聚合:20%+5%」不动——那是金额口径的可复核原文,
不是说明文案。init-dev.sql 种子 description 与 registry 同源。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
liuwenxinandClaude Code committed 2026-10-23 16:20:05 +08:00
1 parent 111ac5425a
commit 61965e0b60
9 files changed
+164 -104

No files matched your search

@@ -171,7 +171,7 @@ const allocationHint = computed(() => {
const total = Number(allocationTotal.value.toFixed(2))
if (total === 100) return `二次分配合计 ${total.toFixed(2)}%`
const rest = Number((100 - total).toFixed(2))
return `二次分配合计 ${total.toFixed(2)}%,余额 ${rest.toFixed(2)}%(归属待业务确认)`
return `二次分配合计 ${total.toFixed(2)}%,余额 ${rest.toFixed(2)}%(归负责人)`
})
function addAllocationRow(): void {
@@ -880,7 +880,7 @@ onMounted(() => {
<div class="items-head">
<span class="items-title">
二次分配方案
<span class="alloc-note">(可选;比例不要求合计 100%,分摊计算待业务确认后另批)</span>
<span class="alloc-note">(可选;各参与人比例不要求合计 100%,余额归负责人)</span>
</span>
<el-button size="small" @click="addAllocationRow">添加参与人</el-button>
</div>
@@ -479,7 +479,7 @@ onMounted(() => {
v-model="form.receipt_date"
type="date"
value-format="YYYY-MM-DD"
placeholder="M3 核算按此日匹配参数版本"
placeholder="选到账当天;计提比例按这一天的参数计算"
style="width: 100%"
/>
</el-form-item>
+71 -21
View File
@@ -99,9 +99,24 @@ function valueLabel(value: string | null | undefined): string {
return ENUM_VALUE_LABELS[value] ?? value
}
/** 带单位的值展示 */
/** 带单位的值展示:枚举与开关先翻成中文,其余原样加单位 */
function formatValue(item: ParamCatalogItem, value: string): string {
return item.unit ? `${value} ${item.unit}` : value
// 枚举/开关的原始值是 INCLUDE、FULL、1、0 —— 直接摆给业务人员看不懂,
// 数字型(比例、天数、金额)保持原样,只补单位
const shown =
item.value_type === 'ENUM' || item.value_type === 'BOOL' ? valueLabel(value) : value
return item.unit ? `${shown} ${item.unit}` : shown
}
/**
* 按参数编码格式化取值:变更记录 / 版本历史 / 快照对比拿到的都是裸 value_text,
* 没有 value_type 与 unit,只能回目录里按编码查定义再格式化。
* 目录还没加载完或编码已下线时原样返回,宁可显示原文也不显示空白。
*/
function formatByCode(code: string, value: string | null | undefined): string {
if (value === null || value === undefined || value === '') return '—'
const item = catalog.value.find((entry) => entry.param_code === code)
return item ? formatValue(item, value) : value
}
// ==================== 修改(待提交) ====================
@@ -436,7 +451,7 @@ onMounted(() => {
<div class="page-head">
<h1 class="page-title">计提参数</h1>
<p class="page-desc">
计提比例、系数、阈值、分成与起付比例在此统一维护;变更逐项留痕并支持按日期生效。
计提比例、系数、阈值、分成与起付比例都在这里统一维护;每次改动留下旧值,可以指定从哪天起生效。
</p>
<div class="waterline"></div>
</div>
@@ -484,7 +499,7 @@ onMounted(() => {
type="warning"
disable-transitions
>
待改为 {{ pendingOf(item, v.dimension_value)!.new_value }}
待改为 {{ formatValue(item, pendingOf(item, v.dimension_value)!.new_value) }}
</el-tag>
<el-button
v-if="isAdmin"
@@ -498,7 +513,7 @@ onMounted(() => {
</div>
</template>
<span v-else class="no-value">
未设置(默认 {{ item.default_value ?? '—' }})
未设置(默认 {{ formatByCode(item.param_code, item.default_value) }})
</span>
</td>
<td>
@@ -537,10 +552,14 @@ onMounted(() => {
<template #default="{ row }">{{ dimensionLabel(row.dimension_value) }}</template>
</el-table-column>
<el-table-column label="旧值" min-width="110">
<template #default="{ row }">{{ row.old_value || '—' }}</template>
<template #default="{ row }">
{{ row.old_value ? formatByCode(row.item.param_code, row.old_value) : '—' }}
</template>
</el-table-column>
<el-table-column label="新值" min-width="110">
<template #default="{ row }"><b class="num">{{ row.new_value }}</b></template>
<template #default="{ row }">
<b class="num">{{ formatByCode(row.item.param_code, row.new_value) }}</b>
</template>
</el-table-column>
<el-table-column label="操作" width="80">
<template #default="{ row }">
@@ -590,24 +609,50 @@ onMounted(() => {
</el-select>
</el-form-item>
<el-form-item label="当前值">
<span class="num">{{ currentValue(editTarget.item, editTarget.dimension) ?? editTarget.item.default_value ?? '—' }}</span>
<span v-if="editTarget.item.unit" style="color: var(--ys-ink-3)"> {{ editTarget.item.unit }}</span>
<!-- 当前值同目录卡口径:枚举翻中文、数字补单位;编辑框里存的仍是原始值 -->
<span class="num">
{{ formatByCode(editTarget.item.param_code, currentValue(editTarget.item, editTarget.dimension) ?? editTarget.item.default_value) }}
</span>
</el-form-item>
<el-form-item label="新值">
<!--
枚举与开关都给下拉:让业务人员在「含基本工资」「开」里选,
而不是自己敲 INCLUDE / 1 —— 提交给后端的仍是原始值(v-model 绑的是 value)
-->
<el-select
v-if="editTarget.item.value_type === 'ENUM'"
v-model="editValue"
style="width: 100%"
>
<el-option v-for="opt in editTarget.item.options" :key="opt" :label="opt" :value="opt" />
<!-- label 走 valueLabel:下拉里给的是「含基本工资」这类中文,提交值仍是 INCLUDE 原值 -->
<el-option
v-for="opt in editTarget.item.options"
:key="opt"
:label="valueLabel(opt)"
:value="opt"
/>
</el-select>
<el-select
v-else-if="editTarget.item.value_type === 'BOOL'"
v-model="editValue"
style="width: 100%"
>
<el-option label="开启" value="1" />
<el-option label="关闭" value="0" />
</el-select>
<el-input v-else v-model="editValue" placeholder="输入新值(分数式如 4/360 原样保留)" />
</el-form-item>
</el-form>
<div class="edit-tip">
取值范围:{{ editTarget.item.value_min ?? '−' }} ~ {{ editTarget.item.value_max ?? '不限' }};
精确分数(如 4/360)原样存储、不做小数截断。
<!--
取值提示只对数字型参数有意义:枚举与开关是选出来的,摆「取值范围」只会添乱。
分数式(4/360)保留原文是因为截成小数会算出不一样的绩效,这条得讲给业务听。
-->
<div v-if="editTarget.item.value_type !== 'ENUM' && editTarget.item.value_type !== 'BOOL'" class="edit-tip">
取值范围:{{ editTarget.item.value_min ?? '不限' }} ~ {{ editTarget.item.value_max ?? '不限' }}
<template v-if="editTarget.item.unit">(单位:{{ editTarget.item.unit }})</template>
;比例可写成 4/360 这样的分数,系统按精确值计算,不四舍五入。
</div>
<div v-else class="edit-tip">改动提交后按你选择的生效日期起作用,旧值会保留在变更记录里。</div>
</template>
<template #footer>
<el-button @click="editVisible = false">取消</el-button>
@@ -615,7 +660,7 @@ onMounted(() => {
</template>
</el-dialog>
<!-- 版本管理抽屉 -->
<!-- 版本管理抽屉:对比两个日期各自的生效值 + 变更记录 -->
<el-drawer v-model="versionVisible" title="版本管理" size="760px">
<div class="drawer-block">
<div class="drawer-row">
@@ -637,18 +682,18 @@ onMounted(() => {
<el-button :loading="exporting" @click="doExport">导出记录</el-button>
</div>
<template v-if="diffSearched">
<div class="drawer-title">快照对比({{ compareFrom }} → {{ compareTo }})</div>
<div class="drawer-title">两个日期的参数对比({{ compareFrom }} → {{ compareTo }})</div>
<el-table :data="diffResult" size="small" max-height="260">
<el-table-column prop="param_name" label="参数" min-width="130" />
<el-table-column label="维度" width="90">
<template #default="{ row }">{{ dimensionLabel(row.dimension_value) }}</template>
</el-table-column>
<el-table-column label="旧值" min-width="90">
<template #default="{ row }">{{ row.old_value ?? '—' }}</template>
<template #default="{ row }">{{ formatByCode(row.param_code, row.old_value) }}</template>
</el-table-column>
<el-table-column label="新值" min-width="90">
<template #default="{ row }">
<span :class="{ changed: row.changed }">{{ row.new_value ?? '—' }}</span>
<span :class="{ changed: row.changed }">{{ formatByCode(row.param_code, row.new_value) }}</span>
</template>
</el-table-column>
<el-table-column label="变化" width="70" align="center">
@@ -670,7 +715,7 @@ onMounted(() => {
<div v-for="item in detailCache[row.id].items" :key="item.param_code + item.dimension_value" class="batch-item">
<span class="param-name">{{ item.param_name }}</span>
<span class="dim-label">{{ dimensionLabel(item.dimension_value) }}</span>
<span class="num">{{ item.old_value_text ?? '—' }} → <b>{{ item.value_text }}</b></span>
<span class="num">{{ formatByCode(item.param_code, item.old_value_text) }} → <b>{{ formatByCode(item.param_code, item.value_text) }}</b></span>
</div>
</template>
<el-button v-else link size="small" @click="detailOf(row).catch(() => {})">
@@ -719,7 +764,11 @@ onMounted(() => {
</el-table-column>
<el-table-column label="旧值 → 新值" min-width="130">
<template #default="{ row }">
<span class="num">{{ row.old_value_text ?? '—' }} → {{ row.value_text }}</span>
<!-- 历史行没有 value_type,按当前参数定义格式化(枚举翻中文、数字补单位) -->
<span class="num">
{{ formatByCode(historyItem?.param_code ?? '', row.old_value_text) }} →
{{ formatByCode(historyItem?.param_code ?? '', row.value_text) }}
</span>
</template>
</el-table-column>
<el-table-column prop="version_no" label="版本" width="115" />
@@ -809,9 +858,10 @@ onMounted(() => {
<div v-if="previewResult.probation_note" class="pr-note">{{ previewResult.probation_note }}</div>
</div>
<div class="pr-used">
<div class="drawer-title">所用参数(按回款到账日取值)</div>
<div class="drawer-title">本次用到的参数(按回款到账日取当天生效值)</div>
<!-- 只显示中文参数名与格式化后的值:参数编码是内部标识,业务人员对不上 -->
<div v-for="u in previewResult.params_used" :key="u.param_code" class="pr-used-row">
{{ paramNameByCode(u.param_code) }}({{ u.param_code }})= {{ valueLabel(u.value_text) || u.value_text }}
{{ paramNameByCode(u.param_code) }} = {{ formatByCode(u.param_code, u.value_text) }}
<span v-if="u.effective_date" class="eff">({{ u.effective_date }} 起)</span>
</div>
</div>