Files
selfrelease d79e3baa34 feat: 系统优化Phase2 - 面包屑导航/侧边栏间距/制度公示阅读签收/模板变量中文化/通知类型补全
- 面包屑导航组件,集成至TopNav header
- 侧边栏菜单分组间距增大,分组间分隔线
- 制度公示员工阅读签收:PolicyReadRecord模型、portal路由、管理端阅读统计
- 修复Policies.tsx民主程序推进bug(字段名/API路径/参数)
- 用工文本模板变量名英文转中文显示
- 通知类型TYPE_LABELS补全(RISK_ALERT/SOCIAL_INS/OVERTIME_ALERT/PAYSLIP_READY)
- 通知示例数据补充
- h2标题统一为text-sm font-medium
- 新增run.md
2026-07-26 20:32:38 +08:00

90 lines
4.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 批量补齐现有示例数据的证据链
* 运行: npx tsx scripts/seed-evidence.ts
*/
import prisma from '../src/lib/prisma'
import { sha256 } from '../src/lib/crypto'
async function main() {
const orgId = 'cmry97x7l0000trrp5f9jgng5'
const systemUserId = 'system-seed'
let count = 0
// 清除旧的 seed 数据
await prisma.evidenceChain.deleteMany({ where: { createdBy: systemUserId } })
console.log('Cleared old seed evidence chains')
// 1. 员工入职证据链
const employees = await prisma.employee.findMany({ select: { id: true, name: true, hireDate: true, createdAt: true } })
for (const emp of employees) {
const events = [{ action: '员工入职登记', timestamp: emp.createdAt.toISOString(), ip: '127.0.0.1', userAgent: 'system-seed' }]
const hash = sha256(JSON.stringify(events) + orgId + 'ONBOARD' + emp.id)
await prisma.evidenceChain.create({
data: { orgId, category: 'ONBOARD', refId: emp.id, employeeId: emp.id, events: events as any, hash, createdBy: systemUserId, createdAt: emp.createdAt },
}).catch(() => {})
count++
}
console.log('ONBOARD:', employees.length)
// 2. 合同签订证据链
const contracts = await prisma.laborContract.findMany({ select: { id: true, employeeId: true, createdAt: true } })
for (const c of contracts) {
const events = [{ action: '合同签订', timestamp: c.createdAt.toISOString(), ip: '127.0.0.1', userAgent: 'system-seed' }]
const hash = sha256(JSON.stringify(events) + orgId + 'CONTRACT_SIGN' + c.id)
await prisma.evidenceChain.create({
data: { orgId, category: 'CONTRACT_SIGN', refId: c.id, employeeId: c.employeeId, events: events as any, hash, createdBy: systemUserId, createdAt: c.createdAt },
}).catch(() => {})
count++
}
console.log('CONTRACT_SIGN:', contracts.length)
// 3. 工资条确认证据链
const payslips = await prisma.payslip.findMany({ where: { confirmedAt: { not: null } }, select: { id: true, employeeId: true, confirmedAt: true } })
for (const p of payslips) {
const events = [{ action: '工资条确认', timestamp: p.confirmedAt!.toISOString(), ip: '127.0.0.1', userAgent: 'employee-portal' }]
const hash = sha256(JSON.stringify(events) + orgId + 'PAYSLIP_CONFIRM' + p.id)
await prisma.evidenceChain.create({
data: { orgId, category: 'PAYSLIP_CONFIRM', refId: p.id, employeeId: p.employeeId, events: events as any, hash, createdBy: p.employeeId, createdAt: p.confirmedAt! },
}).catch(() => {})
count++
}
console.log('PAYSLIP_CONFIRM:', payslips.length)
// 4. 违纪记录证据链
const disciplinaries = await prisma.disciplinaryRecord.findMany({ select: { id: true, employeeId: true, createdAt: true, violationType: true, severity: true } })
const violationMap: Record<string, string> = { LATE: '迟到', ABSENT: '旷工', INSUBORDINATION: '不服从管理', OTHER: '其他违规' }
for (const d of disciplinaries) {
const desc = violationMap[d.violationType] || d.violationType
const events = [{ action: `违纪记录创建(${desc}`, timestamp: d.createdAt.toISOString(), ip: '127.0.0.1', userAgent: 'system-seed' }]
const hash = sha256(JSON.stringify(events) + orgId + 'DISCIPLINARY' + d.id)
await prisma.evidenceChain.create({
data: { orgId, category: 'DISCIPLINARY', refId: d.id, employeeId: d.employeeId, events: events as any, hash, createdBy: systemUserId, createdAt: d.createdAt },
}).catch(() => {})
count++
}
console.log('DISCIPLINARY:', disciplinaries.length)
// 5. 解聘证据链
const terminations = await prisma.terminationRecord.findMany({ select: { id: true, employeeId: true, createdAt: true, reason: true, status: true } })
const reasonMap: Record<string, string> = { NEGOTIATED: '协商解除', UNILATERAL: '单方解除', EXPIRY: '合同到期', RESIGNATION: '员工辞职', OTHER: '其他' }
const statusMap: Record<string, string> = { DRAFT: '草稿', PENDING_APPROVAL: '待审批', APPROVED: '已审批', EXECUTED: '已执行', CANCELLED: '已撤销' }
for (const t of terminations) {
const reasonText = reasonMap[t.reason] || t.reason
const statusText = statusMap[t.status] || t.status
const events = [{ action: `解聘流程(${reasonText}·${statusText}`, timestamp: t.createdAt.toISOString(), ip: '127.0.0.1', userAgent: 'system-seed' }]
const hash = sha256(JSON.stringify(events) + orgId + 'TERMINATION' + t.id)
await prisma.evidenceChain.create({
data: { orgId, category: 'TERMINATION', refId: t.id, employeeId: t.employeeId, events: events as any, hash, createdBy: systemUserId, createdAt: t.createdAt },
}).catch(() => {})
count++
}
console.log('TERMINATION:', terminations.length)
const total = await prisma.evidenceChain.count()
console.log(`\n总计插入 ${count} 条,数据库现有 ${total} 条证据链`)
await prisma.$disconnect()
}
main().catch(console.error)