feat: 社保AI建议、合同附件多文件上传预览、删除合同、扩展上传格式
This commit is contained in:
@@ -92,6 +92,8 @@ export async function getEvidenceDetail(orgId: string, id: string) {
|
||||
|
||||
/**
|
||||
* 验证证据链完整性(重新计算哈希对比)
|
||||
* 注意:PostgreSQL 的 json 类型会按 key 字母序重排属性,导致 JSON.stringify 结果与原始不一致。
|
||||
* 因此验证时需要尝试两种方式:原始序列化和排序后序列化。
|
||||
*/
|
||||
export async function verifyEvidence(orgId: string, id: string): Promise<{ valid: boolean; expectedHash: string; actualHash: string }> {
|
||||
const evidence = await prisma.evidenceChain.findFirst({ where: { id, orgId } })
|
||||
@@ -99,11 +101,28 @@ export async function verifyEvidence(orgId: string, id: string): Promise<{ valid
|
||||
throw { code: 'NOT_FOUND', message: '证据链不存在' }
|
||||
}
|
||||
|
||||
const eventsJson = JSON.stringify(evidence.events)
|
||||
const events = evidence.events as any[]
|
||||
const eventsJson = JSON.stringify(events)
|
||||
const expectedHash = sha256(eventsJson + orgId + evidence.category + (evidence.refId || ''))
|
||||
|
||||
// 如果标准序列化不匹配,尝试按 key 排序后序列化(兼容 PostgreSQL json 类型重排)
|
||||
if (expectedHash !== evidence.hash) {
|
||||
const sortedEvents = events.map(e => {
|
||||
const sorted: any = {}
|
||||
Object.keys(e).sort().forEach(k => sorted[k] = e[k])
|
||||
return sorted
|
||||
})
|
||||
const sortedJson = JSON.stringify(sortedEvents)
|
||||
const sortedHash = sha256(sortedJson + orgId + evidence.category + (evidence.refId || ''))
|
||||
return {
|
||||
valid: sortedHash === evidence.hash,
|
||||
expectedHash: sortedHash,
|
||||
actualHash: evidence.hash,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
valid: expectedHash === evidence.hash,
|
||||
valid: true,
|
||||
expectedHash,
|
||||
actualHash: evidence.hash,
|
||||
}
|
||||
@@ -165,9 +184,19 @@ export async function verifyAllEvidence(orgId: string) {
|
||||
let valid = 0
|
||||
let invalid = 0
|
||||
for (const r of records) {
|
||||
const eventsJson = JSON.stringify(r.events)
|
||||
const events = r.events as any[]
|
||||
const eventsJson = JSON.stringify(events)
|
||||
const expectedHash = sha256(eventsJson + orgId + r.category + (r.refId || ''))
|
||||
if (expectedHash === r.hash) valid++
|
||||
if (expectedHash === r.hash) { valid++; continue }
|
||||
// 尝试按 key 排序后序列化(兼容 PostgreSQL json 类型重排)
|
||||
const sortedEvents = events.map(e => {
|
||||
const sorted: any = {}
|
||||
Object.keys(e).sort().forEach(k => sorted[k] = e[k])
|
||||
return sorted
|
||||
})
|
||||
const sortedJson = JSON.stringify(sortedEvents)
|
||||
const sortedHash = sha256(sortedJson + orgId + r.category + (r.refId || ''))
|
||||
if (sortedHash === r.hash) valid++
|
||||
else invalid++
|
||||
}
|
||||
return { total: records.length, valid, invalid }
|
||||
|
||||
Reference in New Issue
Block a user