freedakgmail
442063fb14
fix: 后端统一非劳动合同类型不缴社保公积金
...
- payroll.service.ts: isNoSocialContract 补充 PARTTIME/OUTSOURCING/UNSIGNED
- payroll.routes.ts tax-preview: 增加 contract 类型判断,非劳动合同 socialBase/housingBase 强制 0
- roster.routes.ts: 之前已修复
2026-08-17 20:25:11 +08:00
freedakgmail
0c2b9ec5e8
fix: 劳务协议等非劳动合同类型不计算社保公积金
...
合同类型为 LABOR/INTERNSHIP/PARTTIME/OUTSOURCING/UNSIGNED 时
socialInsCalc 和 housingFundCalc 返回 null
2026-08-17 20:21:30 +08:00
freedakgmail
007109e425
feat: 附件管理拆为独立tab + 员工端附件上传
...
管理端:
- 花名册详情新增「附件资料」独立tab(人事信息分组下)
- 从 BasicInfo 移除附件管理代码到独立 AttachmentsTab 组件
- shared.ts 添加 attachments tab 类型和计数映射
员工端:
- 后端新增 GET/POST/DELETE /portal/attachments 接口
- 前端 api-services 添加 portalDelete + 附件 API 方法
- MyProfile 新增附件资料卡片,支持上传/查看/删除附件
- 附件类型:身份证/银行卡/学历证书/职业资格证书/合同/照片/其他
2026-08-17 19:27:45 +08:00
freedakgmail
7b2f722984
fix: 员工端Header标题显示企业名称而非安职通Logo
...
- 后端3处登录接口(密码/验证码/auto-login)返回 orgName
- 前端 PortalLayout Header 改为显示 employee.orgName
- 移除 Logo 组件引用
2026-08-17 19:20:38 +08:00
freedakgmail
76a49985f1
fix: 专项附加扣除改为5项明细分类(子女教育、赡养老人、住房、继续教育、婴幼儿照护)
...
- 后端 GET /profile 返回最新月份的专项附加扣除明细记录
- 后端 PUT /profile 保存明细到 SpecialDeductionRecord 表(当前月份 upsert)
- 前端5项明细输入框 + 合计实时计算 + 备注字段
- 与管理端社保>专项附加扣除 Tab 数据结构一致
2026-08-17 19:16:26 +08:00
freedakgmail
88b0fcdc7d
feat: 个人资料补充工号、女性岗位类型、专项附加扣除字段
...
- 后端 GET /profile 返回 employeeNo/femaleWorkerType/specialDeduction
- 后端 PUT /profile 支持更新 specialDeduction(员工自行填报)
- 前端只读区补充:工号、女性岗位类型(仅女性显示)
- 前端可编辑区补充:专项附加扣除(元/月)
2026-08-17 19:09:28 +08:00
freedakgmail
4eb882b1e2
fix: 创建员工时从身份证解析性别和出生日期
...
- contract.service.ts createEmployee: gender 为空时从身份证第17位解析,birthDate 从第7-14位提取
- portal.routes.ts GET /profile: gender/birthDate 为空时从身份证 fallback 解析
- gender 统一使用中文 男/女(与数据库和其他服务一致)
- 前端 MyProfile.tsx 性别显示适配中文
2026-08-17 19:04:22 +08:00
freedakgmail
c4a929fc8e
feat: 员工端新增个人资料页面,数据同步到花名册
...
- 后端新增 GET/PUT /portal/profile 接口,员工可查看和编辑个人资料
- 员工可编辑:紧急联系人、住址、银行卡、学历、参保城市
- 只读字段:姓名、性别、手机号、证件号码、部门、岗位、入职日期
- 数据直接写入 Employee 表(花名册),HR 管理端可见
- 更新操作记录证据链(PROFILE_UPDATE)
- 前端新增 MyProfile.tsx 页面,PortalNav 添加导航入口
2026-08-17 18:56:42 +08:00
freedakgmail
cdbfeb4f99
fix: AI风险预测员工下拉框显示完整身份证号区分同名员工
...
- 后端 /employees/list 接口返回解密后的完整身份证号
- 前端 AI风险预测通用模式和结构化模式员工下拉框显示 姓名(身份证号)
2026-08-17 18:47:37 +08:00
freedakgmail
f2a8f9a97c
fix: AI身份证不脱敏+优化员工端登录页UI
...
- AI读取身份证改为解密明文,不再脱敏,确保生日等信息正确
- 员工端登录页优化:渐变背景、图标输入框、圆角Tab、loading动画、回车登录
2026-08-17 18:40:27 +08:00
selfrelease
aea88fd385
feat: 工作台合规评分优化、面包屑补全、花名册斑马纹
...
- 合规评分维度拆分:薪酬社保拆为薪酬工资+社保公积金两个独立维度
- 合同管理评分纳入待签署合同(signDate为null)扣分
- 维度评分hover显示得分依据findings和建议recommendations
- 概览统计卡片支持点击跳转(在管员工/高风险/待办/工资条)
- 面包屑补全10个缺失路由,统一分组名与侧边栏一致
- 移除子Tab中重复的PageGuide组件
- 花名册列表添加斑马纹隔行变色
- 薪酬结构模版表格列宽优化,计算公式列截断+title显示
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-17 17:33:48 +08:00
selfrelease
5196d7c80a
fix: portal端token过期后自动跳转登录页,避免显示空数据
...
- portalAxios 401 响应拦截器:清除 token 并跳转 /portal/login
- PortalLayoutWrapper:检查 token 是否存在,不存在则跳转登录页
- 排除 /portal/login 和 /portal/auto-login 页面避免重复跳转
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-17 15:06:46 +08:00
selfrelease
c66ea290eb
fix: 签署日期不能晚于当前日期
...
后端 /sign-date 和 /paper-sign 均增加校验,签署日期晚于今天则报错。
前端日期选择器增加 max 属性限制为今天。
2026-08-17 12:48:07 +08:00
selfrelease
e824cd1629
fix: 线下签署登记完成时间改为实际签署日期
...
/sign-date 路径 completedAt 原来用 new Date()(HR登记时间),
导致发起时间和完成时间完全一样。改为用 parsedDate(HR选择的签署日期)。
2026-08-17 12:44:39 +08:00
selfrelease
d3a9ea041f
feat: AI风险检查以身份证号为员工唯一标识
...
- buildOrgContext 员工列表加入脱敏身份证号(前6后4,中间*)
- 单员工/部门预测上下文加入脱敏身份证号
- AI prompt 更新:要求用身份证号标识员工,姓名仅辅助参考
- 同名员工以身份证号区分
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-17 11:48:42 +08:00
selfrelease
6919f997c6
fix: 员工端首页应发合计显示为0
...
后端返回字段是 totalPay,前端误用 grossPay(不存在的字段),
导致应发合计始终显示 0。
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-17 10:37:20 +08:00
selfrelease
16f38f3c36
feat: 补充公积金支持(员工级别可选)
...
上海等城市存在补充公积金账户,同一企业内高管可能有但普通员工
没有。新增员工级别补充公积金账户关联:
- Employee 表加 supplementaryHousingAccountId 字段
- BatchEntry 表加 supplementaryHousingEmp/Org 字段
- 薪资计算 calcBatchEntry 支持补充公积金(额外算一笔,纳入
个税扣除、最低工资保护递延逻辑)
- 新增员工弹窗加补充公积金账户选择器(可选,仅显示
accountType=SUPPLEMENTARY 的公积金账户)
- 员工档案编辑支持补充公积金账户
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-17 10:20:59 +08:00
selfrelease
def0fe3a1f
refactor: 删除 PRE_ONBOARD 显式状态,统一按入职日期判定预入职
...
预入职不再需要显式设置 PRE_ONBOARD 状态,统一按入职日期自动
判定:入职日期在未来 = 预入职(不进入薪资),入职日期 <= 今天
= 正式在职。
删除内容:
- schema: EmployeeStatus 枚举移除 PRE_ONBOARD
- roster.routes.ts: 移除 PRE_ONBOARD 筛选和 /activate API
- payroll2.routes.ts: 移除 NOT PRE_ONBOARD 排除条件
- modals.tsx: 移除入职状态选择器
保留:按 hireDate > 今天 自动判定预入职的逻辑
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-17 09:59:21 +08:00
selfrelease
1d9890e607
fix: 创建年度标准时同effectiveFrom已存在则更新而非报错
...
问题:创建年度标准时如果该账户已有同 effectiveFrom 的标准,
会触发 P2002 唯一约束冲突,返回400"数据已存在"。
修复:先查是否已存在同 effectiveFrom 的标准,存在则更新,
不存在才创建新标准。
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 15:48:21 +08:00
selfrelease
b5aa5552ff
chore: 添加社保公积金账户数据修复脚本
...
- fix-missing-standards.ts: 补齐无年度标准的账户
- fix-housing-base-limits.ts: 更新各城市公积金基数上下限
- check-test-accounts.ts: 删除不完整的测试账户
- assign-accounts.ts: 为全部员工按城市匹配社保公积金账户
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 15:42:37 +08:00
selfrelease
38075420f4
feat: 社保年度标准完善 — 医疗附加 + 继承旧配置 + 公积金独立上下限
...
1. 医疗附加金额:SocialYearStandard 和 SocialInsuranceConfig 新增
medicalOrgExtra/medicalEmpExtra 字段(如北京3元大病医疗)
- calcSocialInsurance 计算时加上医疗附加
- 前端年度标准表单加医疗企业/个人附加输入
2. 新建年度标准继承:新增 /inherit-config API
- 优先用当前年度标准
- 回退到旧 SocialInsuranceConfig/HousingFundConfig
- 前端点击"新建年度标准"时自动继承填充
3. 公积金独立上下限:SocialYearStandard 新增 housingBaseMin/housingBaseMax
- calcHousingFund 优先用公积金专用上下限,为0时回退到社保
- 前端公积金年度标准表单加公积金基数上下限输入
4. blank_employees/blank_all 模式跳过试用期工资覆盖
5. 劳务协议/实习协议人员 calcBatchEntry 强制社保公积金为0
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 15:31:56 +08:00
selfrelease
3ac333891c
fix: 劳务协议/实习协议人员薪资计算强制社保公积金为0
...
calcBatchEntry 查询员工时 include contracts,判断合同类型:
- LABOR(劳务协议)/ INTERNSHIP(实习协议)→ 社保公积金基数强制0,跳过社保计算
- 其他合同类型 → 正常计算
无论哪种批次创建模式(copy_last/blank_employees/custom等),
劳务协议人员的社保公积金都为0。
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 15:24:49 +08:00
selfrelease
c3ca2c9f50
fix: 公积金基数上下限独立于社保
...
问题:SocialYearStandard 只有一套 baseMin/baseMax,社保和公积金
共用,但公积金下限通常是最低工资标准(如北京2420),远低于社保
下限(如北京6326)。
修复:
- SocialYearStandard 新增 housingBaseMin/housingBaseMax 字段
- clampHousingFundBase 优先用公积金专用上下限,为0时回退到社保
- calcHousingFund 同样优先用公积金专用上下限
- 前端公积金年度标准表单加公积金基数上下限输入
- 前端公积金当前标准展示用公积金专用上下限
同时修复 blank_employees/blank_all 模式跳过试用期工资覆盖
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 15:23:08 +08:00
selfrelease
94959522df
fix: blank_employees/blank_all 模式跳过试用期工资覆盖
...
blank_employees 和 blank_all 模式下所有金额应为 0,但统一试用期
判定逻辑会把 probationSalary 覆盖到 baseSalary,导致有试用期合同
的员工基本工资不为 0。
修复:试用期判定仅对 copy_last / copy_batch / custom 模式执行,
blank_employees / blank_all 模式跳过。
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 15:20:05 +08:00
selfrelease
2f1e339413
fix: 劳务协议人员社保基数为0时仍按基本工资计算的bug
...
根因:socialInsBase || baseSalary 中 0 是 falsy,导致基数为0
的劳务协议/实习人员回退到基本工资计算社保。
修复:改为 nullish check(!= null),区分"明确设置为0"
和"未设置(null)":
- socialInsBase = 0 → 用 0(劳务协议不交社保)
- socialInsBase = null → 用 baseSalary(回退)
- socialInsBase = 5000 → 用 5000(核定基数)
涉及文件:
- payroll.service.ts calcBatchEntry + prePayrollCheck
- payroll.routes.ts 旧版薪资计算
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 15:12:07 +08:00
selfrelease
8391c123fc
refactor: 社保公积金Tab重构为账户卡片列表+展开年度标准管理
...
1. 社保/公积金Tab从"选账户→展示配置"改为"账户卡片列表+展开管理"
2. 每个账户卡片可展开显示:当前标准/最低工资编辑/新建年度标准/版本历史/调基/试算
3. 账户新建/编辑/删除/设默认从设置页面迁移到社保公积金菜单
4. 设置页面去掉"社保公积金账户"Tab
5. "新建版本"改名为"新建年度标准"
6. 新增AccountCard组件独立管理每个账户的展开状态和数据查询
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 15:05:06 +08:00
selfrelease
a5911d1874
fix: blank_employees 模式不再自动带出基本工资
...
本月空白模式应所有金额默认 0,去掉从 emp.monthlySalary 自动填充
基本工资的逻辑,保持与"空白"语义一致。
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 14:57:10 +08:00
selfrelease
2875965113
fix: 修复薪资编辑保存失败 + 应发计算丢失细化字段
...
两个问题:
1. 编辑保存 422 错误:updateEntrySchema 要求 min(0),但 bonus
可能为负数(如扣款),导致 Zod 验证失败。放宽为 z.number().optional()
2. 应发不随编辑变化:编辑条目时 inputs 只合并 5 个基本字段,
丢失了 positionSalary/performanceSalary 等细化字段,
导致 calcBatchEntry 计算的 totalPay 不包含细化薪资项。
修复:从 entry 中补全所有细化字段
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 14:19:43 +08:00
selfrelease
ea2dfe3b4b
feat: 最低工资保护 + 社保/最低工资递延补扣机制
...
新增功能:
1. SocialYearStandard / SocialInsuranceConfig 增加 minWage 字段
2. BatchEntry 增加递延扣款字段(deferredSocialEmp/HousingEmp/MinWage)
3. calcBatchEntry 增加最低工资保护逻辑:
- 实发 < 最低工资时,优先递延社保 → 递延公积金 → 递延最低工资补齐
- 递延金额记录到 BatchEntry,次月创建批次时自动补扣
4. prePayrollCheck 增加最低工资检查(第 11/12 项)
5. 前端社保配置增加最低工资输入框
6. 前端 BatchTab 质量门禁增加最低工资/递延扣款提示
处理场景:
- 入职当月工资不足扣社保个人部分 → 递延到次月补扣
- 实发低于最低工资 → 补齐到最低工资,差额递延次月扣
- 次月创建批次时自动读取上月递延金额并补扣
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 14:15:39 +08:00
selfrelease
fe427ef13f
refactor: 新增员工去掉参保城市选择器,城市从社保账户继承
...
- 前端:参保城市改为只读显示,从选中的社保账户自动继承
- 前端:去掉参保城市下拉选择器和 cities 查询
- 后端:clampSocialInsBase/clampHousingFundBase 改为优先按 accountId
查年度标准裁剪基数,回退旧配置表
- 后端:createEmployee 传入 socialAccountId/housingAccountId 给 clamp 函数
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 14:08:11 +08:00
selfrelease
014c94e482
feat: 账户关联根部门 + 员工新增自动带出账户
...
1. 账户管理:新建/编辑时可勾选关联 level=0 根部门(公司/分公司/子公司)
2. 后端新增 API:
- PUT /social/accounts/:id/departments 批量关联根部门
- GET /social/accounts/:id/departments 查询已关联部门
- GET /social/department-account/:departmentId 按部门带出适用账户+标准
3. 部门更新 API 支持 socialAccountId/housingAccountId 字段
4. 员工新增表单:选定部门后自动带出社保公积金账户,可手动调整
5. 参保记录创建时写入 accountId
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 13:59:06 +08:00
selfrelease
63b6c9dcc7
feat: 社保公积金账户化重构
...
新增 SocialAccount(账户)+ SocialYearStandard(年度标准)两层实体,
替代原 SocialInsuranceConfig/HousingFundConfig 按城市管理的方式。
- DB: 新增 SocialAccount、SocialYearStandard 表,Department 加账户关联
- 迁移: 旧 Config 表数据迁移到 Account + YearStandard
- 后端: 新增账户 CRUD + 年度标准 API,薪资计算适配 accountId
- 前端: 设置页新增账户管理 Tab,组织架构提示 level=0 可关联账户
- 前端: SocialInsurance.tsx 城市选择器改为账户选择器
- 兼容: 旧 Config 表保留,薪资计算回退旧表
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 13:50:15 +08:00
selfrelease
454b3d4b05
fix: 个税累计预扣中专项附加扣除改为按月读取实际填报金额
...
原逻辑用 employee.specialDeduction(便捷字段)× 月数计算累计
专项附加扣除,未按月读取 SpecialDeductionRecord 实际金额。
若员工某月填报/取消专项附加扣除,累计值会不准。
修复:
- 优先按月查询 SpecialDeductionRecord(当年至当月)累加实际金额
- 无按月记录时回退到便捷字段 × 月数(兼容旧数据)
- taxBreakdown 增加 specialDeductionSource 字段标识数据来源
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 13:36:02 +08:00
selfrelease
ce1670d171
fix: 所有批次模式统一试用期工资判定
...
之前只有copy_last模式有试用期判定,copy_batch和blank_employees模式
未判定试用期,试用期员工baseSalary错误填为转正工资。
修复: 在所有模式赋值后统一加试用期覆盖逻辑(SEVERANCE/TERMINATION除外),
试用期且probationSalary>0时强制覆盖baseSalary为试用期工资。
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 13:20:50 +08:00
selfrelease
37649419c4
fix: copy_last模式试用期工资被上月工资条覆盖
...
bug: copy_last模式下试用期判定后被prevPayslip.baseSalary无条件覆盖,
导致试用期员工复制上月批次时仍用转正工资而非probationSalary。
修复: 试用期判定优先,仅非试用期时才用上月工资条baseSalary。
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 13:16:42 +08:00
selfrelease
5ef18cb05b
fix: 风险检测同步更新actionUrl+MONTHLY类型actionUrl修正
...
- runRiskDetection 更新逻辑增加 actionUrl 变化检测(非月度风险)
- 新增 MONTHLY 类型 PENDING 记录的 actionUrl 同步更新逻辑
- existingRisks 查询补充 actionUrl 字段
- 修复存量月度待办跳转目标不更新问题
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 13:00:33 +08:00
selfrelease
851557729f
fix: 月度待办跳转精准化+优化清单状态同步
...
- 社保/公积金待办 actionUrl 从 /money 改为 /social?tab=monthly(跳到社保公积金月度办理 Tab)
- 工资/个税待办 actionUrl 从 /money 改为 /money?tab=batch(跳到薪税管理发薪批次 Tab)
- SocialInsurance.tsx 支持 ?tab= 参数初始化 Tab
- Money.tsx 支持 ?tab= 参数初始化 Tab
- 已更新存量 PENDING 记录的 actionUrl
- 优化清单全部 10 项标注 ✅ 已完成
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 12:55:05 +08:00
selfrelease
327a41d619
fix: 线下签署登记完成时间改为记录创建时间
...
completedAt 之前用签署日期(12:00:00),早于发起时间(12:23:52),
逻辑不合理。改为 completedAt = 当前时间(HR 登记时间),
signedAt = 签署日期(HR 选择的日子)。
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 12:33:30 +08:00
selfrelease
5a9d440339
fix: 线下签署登记标题英文转中文+完成时间时区+签署记录角标
...
1. documentTitle 中 contractType 枚举值转中文
(LABOR→劳务协议、FIXED→固定期限劳动合同等)
2. 签署日期解析改为本地时区构造(new Date(y,m-1,d,12)),
避免 new Date('2026-08-16') 被解析为 UTC 00:00 导致
本地 +8 显示为 08:00:00
3. 签署记录 Tab 增加数字角标显示总记录数
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 12:26:13 +08:00
selfrelease
72a6eab3bd
fix: risk.service.ts priorityOrder 重复声明导致后端启动失败
...
用户手动修改 risk.service.ts 时在第 966 行重复声明了
priorityOrder(第 955 行已声明),导致 esbuild 报错
"The symbol priorityOrder has already been declared",
后端 502 Bad Gateway。删除重复声明。
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 12:22:00 +08:00
selfrelease
ef6d4591be
fix: 登记线下签署日期时同步创建 EsignRecord
...
登记签署日期后,签署记录 Tab 中也能看到这条记录。
创建一条 status=COMPLETED 的线下手签 EsignRecord,
避免已签合同在签署记录中无痕可查。
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 12:17:39 +08:00
selfrelease
040c5a3ab9
feat: 待签合同支持登记线下签署日期
...
- 线下手签合同:展开后可点击「登记签署日期」选择日期并保存
保存后合同从待签列表移除(signDate 已填写)
- 电子签合同:签署日期由电签系统自动回写,不可手动修改
- 后端新增 POST /esign/sign-date 接口
电子签合同拒绝手动修改签署日期
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 12:13:07 +08:00
selfrelease
79145b47b9
fix: 待签合同列表中合同类型英文改为中文
...
LaborContract.contractType 枚举值(FIXED/UNFIXED/LABOR等)
转为中文显示(固定期限劳动合同/劳务协议等)。
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 12:08:06 +08:00
selfrelease
71f0619d18
feat: 电子签署改为「待签合同」,按员工聚合+催办功能
...
1. 菜单「电子签署」改名为「待签合同」
2. 页面重构为两个 Tab:
- 待签合同:按员工聚合展示所有未签文件(EsignRecord
PENDING/SIGNING + LaborContract signDate 为空),展开可
查看该员工名下所有待签文件详情
- 签署记录:原有全部签署记录列表(保留筛选功能)
3. 催办功能:点击催办生成一次性自动登录链接(24h有效),
指向员工端签署页,弹窗展示二维码+可复制链接,HR 发给
员工扫码直接进入签署
4. 后端新增接口:
- GET /esign/pending 待签合同按员工聚合列表
- POST /esign/remind 催办生成自动登录链接
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 11:57:43 +08:00
selfrelease
ebd47e4500
fix: Excel 批量导入员工时自动设置默认密码(手机号后6位)
...
与 createEmployee 保持一致,导入时自动生成 passwordHash,
无需管理员再手动重置。
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 11:34:58 +08:00
selfrelease
d7fdec49fa
feat: 员工端密码登录完整支持
...
1. createEmployee 创建员工时自动设置默认密码(手机号后6位)
2. 管理员重置密码接口 POST /employees/:id/reset-password
(重置为手机号后6位)
3. 员工自己修改密码接口 POST /portal/change-password
(需验证旧密码,新密码至少6位)
4. 花名册详情添加"重置密码"按钮,显示默认密码提示
5. 员工端导航栏添加"修改密码"入口,弹窗修改密码
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 11:28:56 +08:00
selfrelease
94b85d5c36
fix: 同企业内员工身份证和手机号唯一性完整校验
...
补充以下场景的查重:
1. updateEmployee:编辑员工信息时手机号/身份证查重
(排除自身,同组织内不可与其他员工重复)
2. import.routes.ts:Excel 批量导入时身份证和手机号查重
(重复则跳过并记录错误日志)
至此同企业内身份证和手机号唯一性校验覆盖全部入口:
- createEmployee(新增员工)
- updateEmployee(编辑员工)
- Excel 导入(批量导入)
- work-process(走 createEmployee)
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 10:59:38 +08:00
selfrelease
6b3e1f9d46
fix: 手机号查重硬校验 + portal 登录跨组织安全
...
问题:
1. 后端 createEmployee 只有身份证查重,没有手机号查重,
同组织内可重复录入相同手机号,导致员工端登录混乱
2. portal 登录用 findFirst 按 phone 查,未考虑跨组织重复,
多组织同手机号时会登录到错误员工
3. Contracts.tsx 的 AddEmployeeModal 完全没有手机号查重
修复:
1. contract.service.ts createEmployee 添加手机号查重硬校验
(同组织内 phone 唯一,抛 DUPLICATE_PHONE 错误)
2. portal.routes.ts 密码登录改为 findMany 遍历校验密码,
验证码登录改为 findMany 取第一个匹配
3. Contracts.tsx AddEmployeeModal 添加手机号查重和警告提示
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 10:57:06 +08:00
selfrelease
13f485a049
fix: contractType zod 枚举与 Prisma/前端对齐
...
zod schema 只允许 FIXED|UNFIXED|UNSIGNED 三种,但 Prisma 枚举和
前端 /contract-types 接口返回 8 种(含 LABOR/INTERNSHIP/DISPATCH/
OUTSOURCING/PARTTIME),导致选择劳务协议等类型时校验失败。
扩展 createEmployeeSchema 和 addContractSchema 的 contractType
枚举为全部 8 种,与 Prisma ContractType 枚举一致。
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 09:28:58 +08:00
selfrelease
9a826c16b0
fix: 组织架构根部门自动创建为公司名
...
1. 注册时自动创建根部门(公司名,level=0),作为组织架构顶层节点
2. 部门列表查询时兼容历史组织:若无任何部门,自动补建根部门
3. 创建部门时若未指定父部门,默认挂到根部门下
4. 前端 OrgChart:
- 根部门显示"公司"标签,不可编辑/删除
- 新增部门时默认父部门为根部门
- 上级部门下拉移除"无(根部门)"选项,改为列出所有可选部门
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 09:16:31 +08:00