fix: allow reviewing legacy draft signatures

This commit is contained in:
hectorzhao
2026-07-13 17:44:44 +08:00
parent 6eaa4157e8
commit ff3e56070a
2 changed files with 6 additions and 1 deletions
+1
View File
@@ -1678,3 +1678,4 @@ git diff --check
- 短信发送选路和最终通道二次校验明确增加 `reportType=signature`,引流通过任务不会误放行未报备签名。Prisma migrations`20260713153000_add_drainage_report_tasks``20260713154000_backfill_drainage_report_tasks``20260713155000_unique_report_task_scope`;后两者分别回填已有引流材料的 pending 任务/记录,并保证同一报备对象和通道仅一个任务。 - 短信发送选路和最终通道二次校验明确增加 `reportType=signature`,引流通过任务不会误放行未报备签名。Prisma migrations`20260713153000_add_drainage_report_tasks``20260713154000_backfill_drainage_report_tasks``20260713155000_unique_report_task_scope`;后两者分别回填已有引流材料的 pending 任务/记录,并保证同一报备对象和通道仅一个任务。
- 本地真实 PostgreSQL 已成功应用 3 条新 migrationAPI 全量 13 suites、139 项通过,Gateway 全量 Go 测试、Prisma validate、API build、前端 build 和 `git diff --check` 通过,前端仅有既有 chunk size warning。应用内浏览器确认本地运营端登录路由标题正确、DOM 非空、无框架错误覆盖且 console 无 error/warn;真实图形验证码阻止进入受保护页,未代解验证码、未绕过认证、未注入 mock。 - 本地真实 PostgreSQL 已成功应用 3 条新 migrationAPI 全量 13 suites、139 项通过,Gateway 全量 Go 测试、Prisma validate、API build、前端 build 和 `git diff --check` 通过,前端仅有既有 chunk size warning。应用内浏览器确认本地运营端登录路由标题正确、DOM 非空、无框架错误覆盖且 console 无 error/warn;真实图形验证码阻止进入受保护页,未代解验证码、未绕过认证、未注入 mock。
- 功能提交 `551b99cb` 已 push 并部署生产。部署前 PostgreSQL 备份为 `/opt/cmpp-platform/backups/cmpp-20260713-174148.sql`,运行源码备份为 `/opt/cmpp-platform/deploy-backups/full-19d47b45-20260713-174148`;三条 migration 成功应用。生产 `.deployed-commit=551b99cb`,四项服务 active`12026/17890/8090/3000` 监听,API/Gateway health 和外部 HTTP 200;前端产物已包含“短信签名审核”“按通道修改引流信息报备状态”“签名与引流信息报备任务”。生产现有 4 条任务均已回填为 `reportType=signature``DrainageReportMaterial=0`,因此没有伪造引流任务,待真实引流字段资料保存时自动生成。 - 功能提交 `551b99cb` 已 push 并部署生产。部署前 PostgreSQL 备份为 `/opt/cmpp-platform/backups/cmpp-20260713-174148.sql`,运行源码备份为 `/opt/cmpp-platform/deploy-backups/full-19d47b45-20260713-174148`;三条 migration 成功应用。生产 `.deployed-commit=551b99cb`,四项服务 active`12026/17890/8090/3000` 监听,API/Gateway health 和外部 HTTP 200;前端产物已包含“短信签名审核”“按通道修改引流信息报备状态”“签名与引流信息报备任务”。生产现有 4 条任务均已回填为 `reportType=signature``DrainageReportMaterial=0`,因此没有伪造引流任务,待真实引流字段资料保存时自动生成。
- 部署后交付复核发现历史运营端新建的 draft 签名虽可在审核页筛选,但操作按钮只对 pending 开放。已改为 draft/pending 都可由运营直接通过或驳回,用于处理【安徽航天信息】等存量草稿;新增签名仍按新规则自动通过。
+5 -1
View File
@@ -24,6 +24,10 @@ function fileRef(value: unknown): FileRef | null {
} : null; } : null;
} }
function canReviewSignature(item: ClientSmsSignature) {
return ['draft', 'pending'].includes(item.auditStatus);
}
function SignatureDetail({ item, onClose }: { item: ClientSmsSignature; onClose: () => void }) { function SignatureDetail({ item, onClose }: { item: ClientSmsSignature; onClose: () => void }) {
const payload = asRecord(item.drainageInfo); const payload = asRecord(item.drainageInfo);
const profile = asRecord(payload.signatureProfile); const profile = asRecord(payload.signatureProfile);
@@ -95,7 +99,7 @@ export function AdminSignatureAuditPage() {
{ key: 'application', title: '应用', render: (record) => record.application?.name ?? '-' }, { key: 'application', title: '应用', render: (record) => record.application?.name ?? '-' },
{ key: 'submittedAt', title: '提交时间', render: (record) => formatDateTime(record.updatedAt) }, { key: 'submittedAt', title: '提交时间', render: (record) => formatDateTime(record.updatedAt) },
{ key: 'status', title: '状态', render: (record) => <Tag tone={(statusMeta[record.auditStatus] ?? statusMeta.draft).tone}>{(statusMeta[record.auditStatus] ?? statusMeta.draft).label}</Tag> }, { key: 'status', title: '状态', render: (record) => <Tag tone={(statusMeta[record.auditStatus] ?? statusMeta.draft).tone}>{(statusMeta[record.auditStatus] ?? statusMeta.draft).label}</Tag> },
{ key: 'actions', title: '操作', align: 'right', render: (record) => <div className="table-actions"><Button icon={<Eye size={15} />} onClick={() => setDetail(record)} size="sm" variant="ghost"></Button><Button disabled={record.auditStatus !== 'pending'} icon={<Check size={15} />} onClick={() => void approve(record)} size="sm" variant="success"></Button><Button disabled={record.auditStatus !== 'pending'} icon={<X size={15} />} onClick={() => setRejectTarget(record)} size="sm" variant="danger"></Button></div> }, { key: 'actions', title: '操作', align: 'right', render: (record) => <div className="table-actions"><Button icon={<Eye size={15} />} onClick={() => setDetail(record)} size="sm" variant="ghost"></Button><Button disabled={!canReviewSignature(record)} icon={<Check size={15} />} onClick={() => void approve(record)} size="sm" variant="success"></Button><Button disabled={!canReviewSignature(record)} icon={<X size={15} />} onClick={() => setRejectTarget(record)} size="sm" variant="danger"></Button></div> },
], []); ], []);
return <section className="page-stack admin-template-audit-page"> return <section className="page-stack admin-template-audit-page">