修复财务结算周期与主体展示

This commit is contained in:
czl231
2026-08-17 00:59:25 +08:00
parent 74efb323f0
commit a6560f99b6
5 changed files with 84 additions and 2 deletions

View File

@@ -0,0 +1,48 @@
# 财务结算周期时间展示修复操作日志
操作时间2026-08-17
操作类型:修改
影响模块:平台总后台、财务管理、财务结算
## 操作前状态
- 结算开始时间和结束时间虽已声明为日期时间字段,但通用展示逻辑只格式化名称以 `_at` 结尾的字段。
- `period_start``period_end` 因字段名不匹配而直接显示 RFC3339 原文,并在列表中出现 `T` 和省略号。
## 具体操作
1. 通用字段展示增加基于 `field.type === 'datetime'` 的日期时间格式化。
2. 结算周期统一显示为 `YYYY-MM-DD HH:mm:ss`,不修改后端时间值和时区处理规则。
3. 增加静态展示契约,防止非 `_at` 日期时间字段再次回显原始字符串。
4. 结算主体类型改为气站、配送点、工作人员三类中文枚举,并联动相应主体下拉。
5. 切换主体类型时清空原主体,防止跨类型标识误提交。
## 行为变化
- 修改前:`2026-06-01T09:00:00...`
- 修改后:`2026-06-01 09:00:00`
- 仅改变展示格式,不改变结算周期、接口字段、保存值或结算流程。
- 新建和编辑结算单不再要求手工输入主体类型编码。
## 代码变更
- `frontend/platform_admin/src/api/resource-display.ts`:日期时间改为按字段类型统一格式化。
- `frontend/platform_admin/src/api/resources.ts`:补齐结算主体类型枚举和三类动态关系。
- `frontend/platform_admin/scripts/check-resource-display-contracts.mjs`:增加日期时间类型格式化契约。
- `docs/项目文档_平台资源中文展示统一_v1.0.md`:记录 v1.14 变更。
## 验证结果
- `pnpm resource-display-contracts:check`:通过。
- `pnpm contract:check`通过48 个资源契约一致。
- 修改文件定向 Biome lint无错误保留 `resource-display.ts` 既有的 `hasOwnProperty` 建议性警告。
- `pnpm type:check`:通过。
- `pnpm build`通过TypeScript 类型检查及 Vite 生产构建完成,共转换 2621 个模块。
- 补齐结算主体联动后再次执行资源契约、48 资源契约、定向 lint、类型检查和生产构建全部通过仍仅有既有建议性警告。
## 风险评估
- 影响所有已声明为 `datetime` 的字段,输出格式与现有 `_at` 日期时间字段保持一致。
- 不新增文档未规定的自然月、固定周期或时区转换规则。

View File

@@ -76,3 +76,5 @@ frontend/platform_admin/
- v1.11:退款审核新增“退款商品”,商城退款读取成交快照,气体配送退款通过原订单项读取产品名称,并汇总退款数量。
- v1.12退款审核补齐空值业务文案、审核人名称、支付单号和钱包归属摘要UUID 统一降级为复制信息。
- v1.13:修正固定 Mock 退款误把气站账号写为平台审核人的数据错误,并在重复初始化时幂等修复历史记录;退款审核人由接口稳定返回平台账号名称。
- v1.14:日期时间统一按字段类型格式化,财务结算周期完整显示为 `YYYY-MM-DD HH:mm:ss`,不再回显带 `T` 的截断 RFC3339 文本。
- v1.15:财务结算主体类型改为气站、配送点、工作人员中文枚举,并按类型联动对应主体资源,切换类型时清空旧主体。

View File

@@ -316,6 +316,23 @@ assertIncludes(
'hasResourceFieldLabel',
'详情必须提供未知字段中文契约检查',
);
assertIncludes(
display,
"field.type === 'datetime'",
'日期时间必须按字段类型统一格式化,不能依赖 `_at` 字段名后缀',
);
for (const settlementContract of [
"{ label: '气站', value: 'gas' }",
"{ label: '配送点', value: 'delivery' }",
"{ label: '工作人员', value: 'staff' }",
"resources: { gas: '/gas_basic', delivery: '/delivery_basic', staff: '/staff_account' }",
]) {
assertIncludes(
resources,
settlementContract,
`财务结算缺少主体类型联动契约:${settlementContract}`,
);
}
assertIncludes(
detailPage,
'!hasResourceFieldLabel(props.definition, actualKey)',

View File

@@ -513,6 +513,11 @@ export function displayResourceField(
? numericValue.toFixed(field.displayPrecision)
: String(value);
}
// 日期时间应以字段类型为准,避免 period_start 等非 `_at` 字段回显原始 RFC3339 文本。
if (field.type === 'datetime') {
const date = dayjs(String(value));
return date.isValid() ? date.format('YYYY-MM-DD HH:mm:ss') : String(value);
}
if (field.type === 'identity' && typeof value === 'string') {
return relationLabel(field, value, relationOptions, row);
}

View File

@@ -850,12 +850,22 @@ export const resources: ResourceUiDefinition[] = [
}),
f('amount'), f('paid_at'),
]),
define('fin_settlement', '财务结算', 'writable', [f('settlement_no', { required: true }), f('subject_type', { required: true }), f('subject_identity', {
define('fin_settlement', '财务结算', 'writable', [f('settlement_no', { required: true }), f('subject_type', {
required: true,
type: 'select',
options: [
{ label: '气站', value: 'gas' },
{ label: '配送点', value: 'delivery' },
{ label: '工作人员', value: 'staff' },
],
unknownValueLabel: '未知结算主体类型',
}), f('subject_identity', {
required: true, type: 'identity', label: '结算主体', listRelationNameOnly: true,
displayRelationLabel: true, showIdentityCopy: true,
dynamicRelation: {
parentKey: 'subject_type', parentLabel: '结算主体类型',
resources: { gas: '/gas_basic', delivery: '/delivery_basic' },
resources: { gas: '/gas_basic', delivery: '/delivery_basic', staff: '/staff_account' },
parentChangeMessage: '结算主体类型已变更,请重新选择结算主体',
},
}), f('period_start', { required: true }), f('period_end', { required: true })]),
define('fin_reconciliation', '财务对账', 'readonly', [