From 754dfd311677c7b2b8c1713b8fd8671f3c42e084 Mon Sep 17 00:00:00 2001 From: freedakgmail Date: Tue, 18 Aug 2026 07:52:52 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=91=98=E5=B7=A5=E7=AB=AF=E5=A7=93?= =?UTF-8?q?=E5=90=8D=E6=98=BE=E7=A4=BA=E5=A4=84=E5=8A=A0=E4=B8=8A=E8=BA=AB?= =?UTF-8?q?=E4=BB=BD=E8=AF=81=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后端: - portal.routes.ts: 密码登录/验证码登录/自动登录返回 idCardNumber - portal.routes.ts: home/overview 返回 employeeIdCardNumber - portal.routes.ts: 合同确认接口返回 employeeIdCardNumber 前端: - EmployeeHome.tsx: 首页欢迎卡片显示身份证号 - PortalLayout.tsx: 顶栏姓名后显示身份证号 - Payslip.tsx: 下载文件名加上身份证号 - ContractConfirm.tsx: 合同确认页显示身份证号 --- backend/src/routes/portal.routes.ts | 20 ++++++++++++------- .../src/components/layout/PortalLayout.tsx | 2 +- frontend/src/pages/portal/ContractConfirm.tsx | 2 +- frontend/src/pages/portal/EmployeeHome.tsx | 1 + frontend/src/pages/portal/Payslip.tsx | 2 +- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/backend/src/routes/portal.routes.ts b/backend/src/routes/portal.routes.ts index 23abe49..72cfcdb 100644 --- a/backend/src/routes/portal.routes.ts +++ b/backend/src/routes/portal.routes.ts @@ -40,7 +40,7 @@ router.post('/login', async (req, res, next) => { // 查找所有匹配手机号的在职员工(可能跨组织) const employees = await prisma.employee.findMany({ where: { phone: data.phone, status: 'ACTIVE' }, - select: { id: true, name: true, department: true, orgId: true, passwordHash: true, org: { select: { name: true } } }, + select: { id: true, name: true, department: true, orgId: true, passwordHash: true, idCardNumber: true, org: { select: { name: true } } }, }) if (employees.length === 0) { return res.status(400).json({ success: false, error: { code: 'AUTH_FAILED', message: '手机号或密码错误' } }) @@ -60,7 +60,7 @@ router.post('/login', async (req, res, next) => { return res.status(400).json({ success: false, error: { code: 'AUTH_FAILED', message: '手机号或密码错误' } }) } const token = signAccessToken({ id: matchedEmployee.id, orgId: matchedEmployee.orgId, role: 'EMPLOYEE' }) - res.json({ success: true, data: { token, employee: { id: matchedEmployee.id, name: matchedEmployee.name, department: matchedEmployee.department, orgName: (matchedEmployee as any).org?.name || '' } } }) + res.json({ success: true, data: { token, employee: { id: matchedEmployee.id, name: matchedEmployee.name, department: matchedEmployee.department, orgName: (matchedEmployee as any).org?.name || '', idCardNumber: (() => { try { return matchedEmployee.idCardNumber ? (matchedEmployee.idCardNumber.includes(':') ? decrypt(matchedEmployee.idCardNumber) : matchedEmployee.idCardNumber) : null } catch { return null } })() } } }) } catch (err) { next(err) } @@ -110,7 +110,7 @@ router.post('/verify-code', async (req, res, next) => { // 查找所有匹配手机号的在职员工(可能跨组织) const employees = await prisma.employee.findMany({ where: { phone: data.phone, status: 'ACTIVE' }, - select: { id: true, name: true, department: true, orgId: true, org: { select: { name: true } } }, + select: { id: true, name: true, department: true, orgId: true, idCardNumber: true, org: { select: { name: true } } }, }) if (employees.length === 0) { return res.status(400).json({ success: false, error: { code: 'NOT_FOUND', message: '员工不存在' } }) @@ -118,7 +118,7 @@ router.post('/verify-code', async (req, res, next) => { // 如果只有一个匹配,直接登录 const employee = employees[0] const token = signAccessToken({ id: employee.id, orgId: employee.orgId, role: 'EMPLOYEE' }) - res.json({ success: true, data: { token, employee: { id: employee.id, name: employee.name, department: employee.department, orgName: (employee as any).org?.name || '' } } }) + res.json({ success: true, data: { token, employee: { id: employee.id, name: employee.name, department: employee.department, orgName: (employee as any).org?.name || '', idCardNumber: (() => { try { return employee.idCardNumber ? (employee.idCardNumber.includes(':') ? decrypt(employee.idCardNumber) : employee.idCardNumber) : null } catch { return null } })() } } }) } catch (err) { next(err) } @@ -421,7 +421,7 @@ router.get('/contract-confirm/:token', async (req, res, next) => { include: { contract: { include: { - employee: { select: { name: true, org: { select: { name: true } } } }, + employee: { select: { name: true, idCardNumber: true, org: { select: { name: true } } } }, }, }, }, @@ -434,6 +434,7 @@ router.get('/contract-confirm/:token', async (req, res, next) => { data: { orgName: link.contract.employee.org.name, employeeName: link.contract.employee.name, + employeeIdCardNumber: (() => { try { const v = link.contract.employee.idCardNumber; return v ? (v.includes(':') ? decrypt(v) : v) : null } catch { return null } })(), contract: link.contract, }, }) @@ -694,13 +695,13 @@ router.get('/auto-login', async (req, res, next) => { } const employee = await prisma.employee.findFirst({ where: { id: payload.id, orgId: payload.orgId, status: 'ACTIVE' }, - select: { id: true, name: true, department: true, orgId: true, org: { select: { name: true } } }, + select: { id: true, name: true, department: true, orgId: true, idCardNumber: true, org: { select: { name: true } } }, }) if (!employee) { return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '员工不存在或已离职' } }) } const accessToken = signAccessToken({ id: employee.id, orgId: employee.orgId, role: 'EMPLOYEE' }) - res.json({ success: true, data: { token: accessToken, employee: { id: employee.id, name: employee.name, department: employee.department, orgName: (employee as any).org?.name || '' } } }) + res.json({ success: true, data: { token: accessToken, employee: { id: employee.id, name: employee.name, department: employee.department, orgName: (employee as any).org?.name || '', idCardNumber: (() => { try { return employee.idCardNumber ? (employee.idCardNumber.includes(':') ? decrypt(employee.idCardNumber) : employee.idCardNumber) : null } catch { return null } })() } } }) } catch (err) { next(err) } @@ -742,6 +743,9 @@ router.get('/home/overview', portalAuth, async (req: any, res, next) => { const employee = await prisma.employee.findFirst({ where: { id: employeeId, orgId } }) if (!employee) return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '员工不存在' } }) + let employeeIdCardNumber: string | null = null + try { if (employee.idCardNumber) employeeIdCardNumber = employee.idCardNumber.includes(':') ? decrypt(employee.idCardNumber) : employee.idCardNumber } catch {} + // 最新工资条 const latestPayslip = await prisma.payslip.findFirst({ where: { employeeId, orgId, publishStatus: 'PUBLISHED' }, @@ -808,6 +812,8 @@ router.get('/home/overview', portalAuth, async (req: any, res, next) => { res.json({ success: true, data: { + employeeName: employee.name, + employeeIdCardNumber, latestPayslip, contract: contract ? { typeLabel: typeLabels[contract.contractType] || contract.contractType, diff --git a/frontend/src/components/layout/PortalLayout.tsx b/frontend/src/components/layout/PortalLayout.tsx index fc5e20e..67087c9 100644 --- a/frontend/src/components/layout/PortalLayout.tsx +++ b/frontend/src/components/layout/PortalLayout.tsx @@ -38,7 +38,7 @@ export default function PortalLayout({ children }: { children: React.ReactNode }
{employee.name && ( - {employee.name} + {employee.name}{employee.idCardNumber ? `(${employee.idCardNumber})` : ''} )}