【薪资】计薪设置、薪资档案
计薪设置与薪资档案模块,由 yudao-module-hrm 后端模块的 salary.config、salary.employeeinfo 包实现,前端实现在 @/views/hrm/salary/config、@/views/hrm/salary/employee-info 目录。
薪资是 HRM 中表最多、链路最长的模块,共 13 张表,按「计薪设置 → 薪资档案 → 月度工资 → 工资条」四段组织。本文解决的是前两段,也就是「按什么规则算、每个人算多少」:
- 计薪设置:计薪周期、计税规则、薪资组、工资项和调薪模板,配置一次后长期沿用。
- 薪资档案与调薪:员工当前薪资 + 定薪调薪记录,支持立即或未来生效。
五类计薪设置的职责与约束如下,下文按此顺序逐个展开:
| 小节 | 表 | 职责 | 关键约束 |
|---|---|---|---|
| §1 计薪周期 | hrm_salary_config | 每月算哪一段时间的工资 | 每租户仅一套,初始化后周期只读 |
| §2 计税规则 | hrm_salary_tax_rule | 个税按什么口径算 | 被薪资组引用时不可删除 |
| §3 薪资组 | hrm_salary_group | 谁参与核算、用哪套计税规则 | 未命中薪资组的员工不参与核算 |
| §4 工资项 | hrm_salary_option_template、hrm_salary_option | 工资由哪些项目构成 | 标准目录平台维护,租户项 code 唯一 |
| §5 调薪模板 | hrm_salary_change_template | 定薪、调薪时允许改哪些项 | 默认模板不可删除 |
配置就绪后的月度核算与工资条发放,详见 《【薪资】月度工资、工资条》。
本文涉及表如下图所示:
# 1. 计薪周期
计薪周期,由 HrmSalaryConfigController 提供接口(/hrm/salary/config),对应 hrm_salary_config 表。
首次初始化计薪周期时,系统会同时创建第一张「未核算」的月度工资表,因此计薪周期是薪资模块的启动开关。
# 1.1 表结构
省略 creator/create_time/updater/update_time/deleted/tenant_id 等通用字段,下同;需要说明唯一约束时保留
tenant_id,JSON 字段由 TypeHandler 完成对象转换
CREATE TABLE `hrm_salary_config` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`cycle_start_day` int DEFAULT NULL COMMENT '计薪周期开始日',
`cycle_end_day` int DEFAULT NULL COMMENT '计薪周期结束日',
`start_year` int DEFAULT NULL COMMENT '起始年份',
`start_month` int DEFAULT NULL COMMENT '起始月份',
`social_security_month_type` tinyint DEFAULT NULL COMMENT '社保对应月份',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hrm_salary_config_tenant_id` (`tenant_id`)
) ENGINE=InnoDB COMMENT='HRM 薪资配置';
① tenant_id 唯一,因此每个租户只能初始化一套计薪周期。
② cycle_start_day 为 1 时,cycle_end_day 保存为 31;否则结束日为「开始日减 1」,即自然月跨月计薪。初始化后开始日、结束日和起始年月只读,只允许调整社保对应月份。
③ 枚举 social_security_month_type 社保对应月份(HrmSalarySocialSecurityMonthTypeEnum):0 上月、1 当月、2 次月。核算时按该配置读取对应月份的社保记录。
# 1.2 管理后台
对应 [HRM 人力资源 -> 薪资管理 -> 计薪设置] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/hrm/salary/config 目录。
# 初始化计薪周期
首次进入 config/index.vue 时填写计薪周期开始日、工资起始年月和社保对应月份。保存后,系统同时创建首张月度工资表。

# 修改计薪周期
初始化后,开始日、结束日和起始年月只读,只允许修改社保对应月份。
# 2. 计税规则
计税规则,由 HrmSalaryTaxRuleController 提供接口(/hrm/salary/tax-rule),对应 hrm_salary_tax_rule 表。薪资组通过它决定员工按哪套口径计算个税。
# 2.1 表结构
CREATE TABLE `hrm_salary_tax_rule` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(64) NOT NULL COMMENT '计税规则名称',
`type` tinyint DEFAULT NULL COMMENT '计税类型',
`tax_enabled` bit DEFAULT NULL COMMENT '是否计税',
`threshold` decimal(12,2) DEFAULT NULL COMMENT '起征阈值',
`decimal_scale` int DEFAULT NULL COMMENT '保留小数位数',
`cycle_type` tinyint DEFAULT NULL COMMENT '计税周期类型',
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='HRM 计税规则';
① 枚举 type 计税类型(HrmSalaryTaxTypeEnum,字典 hrm_salary_tax_type):1 工资薪金所得税、2 劳务报酬所得税、3 不计税。税率档位由 HrmSalaryTaxRateEnum 内置(工资薪金 7 级、劳务报酬 3 级),不需要在页面维护。
② tax_enabled = 0 时不计算个税;启用后由 threshold 起征阈值、decimal_scale 保留小数位数和 cycle_type 计税周期共同决定计税口径。
③ 枚举 cycle_type 计税周期(HrmSalaryTaxCycleTypeEnum):1 上年 12 月至本年 11 月、2 本年 1 月至 12 月。
④ 薪资组通过 tax_rule_id 选用规则。
# 2.2 管理后台
对应 [HRM 人力资源 -> 薪资管理 -> 计薪设置 -> 计税规则] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/hrm/salary/config/tax-rule 目录。
# 列表
tax-rule/index.vue 展示规则名称、个税类型、起征点和被薪资组使用的数量,最后一列用于判断能否删除。

# 新增 / 修改
通过弹窗 SalaryTaxRuleForm.vue 完成,填写方案名称、个税类型、是否计税、起征点、小数位和计税周期。关闭「是否计税」后,起征点和计税周期不再生效,核算时该薪资组的员工个税按 0 处理。

# 删除
已被薪资组引用的规则不能删除,需要先把引用它的薪资组改绑到其它规则。
# 3. 薪资组
薪资组,由 HrmSalaryGroupController 提供接口(/hrm/salary/group),对应 hrm_salary_group 表。它把员工和计税规则绑在一起,是员工能否参与月度核算的前提。
# 3.1 表结构
CREATE TABLE `hrm_salary_group` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(64) NOT NULL COMMENT '薪资组名称',
`salary_standard` decimal(12,2) DEFAULT NULL COMMENT '月计薪标准天数',
`change_rule` varchar(255) DEFAULT NULL COMMENT '转正、调薪月计算规则',
`dept_ids` varchar(20000) DEFAULT NULL COMMENT '适用部门编号 JSON',
`employee_ids` varchar(20000) DEFAULT NULL COMMENT '适用员工编号 JSON',
`tax_rule_id` bigint DEFAULT NULL COMMENT '计税规则编号',
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='HRM 薪资组';
① dept_ids 关联 system_dept 表,employee_ids 关联 hrm_employee 表,tax_rule_id 关联 hrm_salary_tax_rule 表。
② 员工先按 employee_ids 精确匹配,再按所在部门及父部门匹配。未命中任何薪资组的员工不能参与月度核算,核算前的准备检查会把这些员工列出来。
③ salary_standard 月计薪标准天数用于按天折算,当前由后端固定写入 21.75;change_rule 同样由后端写入固定说明,不作为用户可配置的分支规则。转正月、调薪月会按周期内每天生效的薪资档案自动混合计算。
# 3.2 管理后台
对应 [HRM 人力资源 -> 薪资管理 -> 计薪设置 -> 薪资组] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/hrm/salary/config/group 目录。
# 列表
group/index.vue 展示薪资组名称、所用计税规则和适用范围。

# 新增 / 修改
通过弹窗 SalaryGroupForm.vue 完成,填写薪资组名称、计税规则、部门范围和员工范围;「计薪标准」和「调薪规则」两项只读展示,分别是固定的 21.75 天 / 月,以及转正、调薪生效日前后工资混合计算的说明。
保存适用范围时,后端会从其它薪资组移除重复的部门和员工,保证一名员工只命中一个薪资组。

# 4. 工资项
工资项,由 HrmSalaryOptionController 提供接口(/hrm/salary/option),用两张表保存:hrm_salary_option_template 是平台统一维护的标准目录,hrm_salary_option 是各租户实际启用的工资项。租户通过「同步标准项」把标准目录复制或补齐到自己的工资项中。
# 4.1 标准目录表结构
CREATE TABLE `hrm_salary_option_template` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`code` int NOT NULL COMMENT '标准工资项编码',
`parent_code` int NOT NULL DEFAULT 0 COMMENT '父工资项编码',
`name` varchar(64) NOT NULL COMMENT '工资项名称',
`type` tinyint NOT NULL DEFAULT 1 COMMENT '工资项类型',
`system_flag` bit NOT NULL DEFAULT 0 COMMENT '是否系统默认项',
`tax_enabled` bit NOT NULL DEFAULT 1 COMMENT '是否计税',
`visible` bit NOT NULL DEFAULT 1 COMMENT '是否显示',
`calculate_enabled` bit NOT NULL DEFAULT 1 COMMENT '是否参与计��',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hrm_salary_option_template_code` (`code`)
) ENGINE=InnoDB COMMENT='HRM 标准工资项目录';
标准目录不带 tenant_id,由平台统一维护。code 全局唯一,parent_code 指向同表 code,用于组织工资项树;标准编码见 HrmSalaryOptionCodeEnum,其中应发工资、应税工资、个人所得税、实发工资和各项累计值属于系统计算项(COMPUTED_CODES),不允许手工填写。
# 4.2 租户工资项表结构
CREATE TABLE `hrm_salary_option` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`code` int NOT NULL COMMENT '工资项编码',
`parent_code` int NOT NULL DEFAULT 0 COMMENT '父工资项编码',
`name` varchar(64) NOT NULL COMMENT '工资项名称',
`template_id` bigint DEFAULT NULL COMMENT '标准工资项目录编号',
`type` tinyint NOT NULL DEFAULT 1 COMMENT '工资项类型',
`system_flag` bit NOT NULL DEFAULT 0 COMMENT '是否系统默认项',
`tax_enabled` bit NOT NULL DEFAULT 1 COMMENT '是否计税',
`visible` bit NOT NULL DEFAULT 1 COMMENT '是否显示',
`calculate_enabled` bit NOT NULL DEFAULT 1 COMMENT '是否参与计算',
`enabled` bit NOT NULL DEFAULT 1 COMMENT '是否启用',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hrm_salary_option_tenant_code` (`tenant_id`, `code`)
) ENGINE=InnoDB COMMENT='HRM 租户工资项';
① template_id 关联 hrm_salary_option_template 表的 id 字段;tenant_id + code 唯一,parent_code 指向同租户的父项编码。
② 枚举 type 工资项类型(HrmSalaryOptionTypeEnum,字典 hrm_salary_option_type):0 减项、1 加项、2 计算项。
③ 三个开关的职责不同:enabled 控制企业是否使用该项,visible 控制工资表和工资条是否展示,calculate_enabled 控制是否参与汇总计算。
# 4.3 管理后台
对应 [HRM 人力资源 -> 薪资管理 -> 计薪设置 -> 工资项] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/hrm/salary/config/option 目录。
# 列表
option/index.vue 按「企业工资项」和「系统工资项」两个页签展示工资项树:
- 企业工资项:租户自己维护的工资项,可新增、停用和删除。
- 系统工资项:平台预置的计算项,只能控制是否展示,不能新增或删除。
列表里的「是否启用」「是否显示」两个开关直接在行内切换,不需要打开表单。

# 同步标准项
点击【同步标准薪资项】,把平台的标准工资项目录补齐到本租户。已存在的 code 不会被覆盖,因此可以反复同步。
# 新增
在某个分类下点击新增,打开 SalaryOptionForm.vue,只需填写工资项名称和备注——工资项分类由入口带入且不可修改,所以该表单只支持新增,不支持改分类。计税、参与计算等属性沿用分类的默认值。

# 删除与停用
同一个【删除】按钮对两类工资项行为不同:标准项的删除等同于停用(保留记录,enabled 置否),只有租户自定义项才会真正逻辑删除。
# 5. 调薪模板
调薪模板,由 HrmSalaryChangeTemplateController 提供接口(/hrm/salary/change-template),对应 hrm_salary_change_template 表。它决定定薪、调薪表单上允许调整哪些工资项。
# 5.1 表结构
CREATE TABLE `hrm_salary_change_template` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(64) NOT NULL COMMENT '调薪模板名称',
`default_status` bit NOT NULL DEFAULT 0 COMMENT '是否默认模板',
`options` varchar(4000) DEFAULT NULL COMMENT '可调整工资项 JSON',
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='HRM 调薪模板';
options 保存工资项的 code 与名称快照,用于限定定薪、调薪表单可编辑的项目。同一租户只有一条默认模板:默认模板可以修改,也可以把其它模板设为默认,但当前默认模板不能删除。
# 5.2 管理后台
对应 [HRM 人力资源 -> 薪资管理 -> 计薪设��� -> 调薪模板] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/hrm/salary/config/change-template 目录。
# 列表
change-template/index.vue 展示模板名称、是否默认模板和包含的调薪项。

# 新增 / 修改
通过弹窗 SalaryChangeTemplateForm.vue 完成,填写模板名称、是否设为默认模板,并勾选允许调整的调薪项。把某个模板设为默认后,原默认模板自动取消默认。

# 删除
当前默认模板不能删除,需要先把其它模板设为默认。
# 6. 薪资档案与调薪
员工当前薪资,由 HrmSalaryEmployeeInfoController 提供接口(/hrm/salary/employee-info);定薪、调薪和未来变更记录,由 HrmSalaryChangeRecordController 提供查询、取消和删除接口(/hrm/salary/change-record)。
两张表的 employee_id 都关联 hrm_employee 表,不直接关联后台账号。
# 6.1 主表表结构
CREATE TABLE `hrm_salary_employee_info` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`employee_id` bigint NOT NULL COMMENT '员工编号',
`change_type` tinyint DEFAULT NULL COMMENT '变更类型',
`change_reason` tinyint DEFAULT NULL COMMENT '变更原因',
`effect_time` datetime DEFAULT NULL COMMENT '生效时间',
`regular_salary` decimal(12,2) DEFAULT NULL COMMENT '正式工资',
`probation_salary` decimal(12,2) DEFAULT NULL COMMENT '试用期工资',
`salary_options` varchar(20000) DEFAULT NULL COMMENT '正式工资项快照 JSON',
`probation_salary_options` varchar(20000) DEFAULT NULL COMMENT '试用期工资项快照 JSON',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hrm_salary_employee_info_employee_id` (`employee_id`)
) ENGINE=InnoDB COMMENT='HRM 员工薪资档案';
① employee_id 唯一,每名员工只有一份当前有效薪资档案;历史和未来薪资保存在 hrm_salary_change_record 中。
② 枚举 change_type 变更类型(HrmSalaryEmployeeInfoChangeTypeEnum,字典 hrm_salary_change_type):0 未定薪、1 已定薪、2 已调薪。列表据此把操作按钮显示为【定薪】或【调薪】。
③ 枚举 change_reason 变更原因(HrmSalaryChangeReasonEnum,字典 hrm_salary_change_reason):0 入职定薪、1 入职核定、2 转正、3 晋升、4 调动、5 年中调薪、6 年度调薪、7 特别调薪、8 其他。
④ salary_options、probation_salary_options 是工资项 JSON 快照。后续修改工资项配置不会回写已生效的薪资记录。
salary_options JSON 字段结构
正式工资项与试用期工资项结构相同,分别保存在 salary_options 和 probation_salary_options 列中:
[
{ "code": 1001, "name": "基本工资", "value": 8000.00 },
{ "code": 1002, "name": "岗位工资", "value": 2000.00 },
{ "code": 1003, "name": "绩效工资", "value": 3000.00 }
]
① code 对应租户工资项 hrm_salary_option.code,name 是提交当时的名称快照,因此工资项改名不会影响历史记录。
② 数组只包含调薪模板允许调整的项目,系统计算项(应发、应税、个税、实发)不在其中,由月度核算实时算出。
③ 主表的 regular_salary、probation_salary 是这些 value 的汇总值,用于列表直接展示。
该表包含一张记录表:
hrm_salary_change_record(定薪调薪记录):保存每一次定薪、调薪的前后金额与工资项快照,同一员工同时只允许一条待生效记录。
# 6.2 记录表结构
CREATE TABLE `hrm_salary_change_record` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`employee_id` bigint NOT NULL COMMENT '员工编号',
`type` tinyint DEFAULT NULL COMMENT '记录类型',
`reason` tinyint DEFAULT NULL COMMENT '调整原因',
`status` tinyint DEFAULT NULL COMMENT '状态',
`effect_time` datetime DEFAULT NULL COMMENT '生效时间',
`before_total` decimal(12,2) DEFAULT NULL COMMENT '调整前正式薪资',
`after_total` decimal(12,2) DEFAULT NULL COMMENT '调整后正式薪资',
`probation_before_total` decimal(12,2) DEFAULT NULL COMMENT '调整前试用期薪资',
`probation_after_total` decimal(12,2) DEFAULT NULL COMMENT '调整后试用期薪资',
`salary_options` varchar(4000) DEFAULT NULL COMMENT '正式工资项后态快照 JSON',
`probation_salary_options` varchar(4000) DEFAULT NULL COMMENT '试用期工资项后态快照 JSON',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='HRM 定薪调薪记录';
① 枚举 type 记录类型(HrmSalaryChangeRecordTypeEnum):1 定薪、2 调薪。
② 枚举 status 记录状态(HrmSalaryChangeRecordStatusEnum,字典 hrm_salary_change_record_status:0 = 待生效,1 = 已生效,2 = 已取消)。详见 §6.3 状态流转。
③ before_total / after_total 便于列表展示变动幅度,两个工资项字段保存变更后的明细。
# 6.3 状态流转
定薪、调薪记录的生命周期由 HrmSalaryEmployeeInfoServiceImpl 与 HrmSalaryChangeRecordServiceImpl 控制。状态枚举 HrmSalaryChangeRecordStatusEnum:
| 状态值 | 枚举 | 说明 | 可执行操作 |
|---|---|---|---|
| 0 | PENDING | 待生效 | 取消、删除 |
| 1 | EFFECTIVE | 已生效 | — |
| 2 | CANCELLED | 已取消 | 删除 |
状态流转说明
立即生效:创建 ──→ 已生效(1)(同步更新 hrm_salary_employee_info)
未来生效:创建 ──→ 待生效(0) ──HrmSalaryChangeJob──→ 已生效(1)
│
└──取消──→ 已取消(2)
- 定薪 / 调薪(
updateSalaryEmployeeInfo):生效时间为今天或过去时,立即更新当前薪资档案;未来日期只创建待生效记录。最早允许的生效日期由后端按当前月度工资表计算。 - 到期生效(HrmSalaryChangeJob):把到期的待生效记录写入
hrm_salary_employee_info,并置为已生效。 - 取消(
cancelSalaryChangeRecord):仅待生效可取消。 - 删除(
deleteSalaryChangeRecord):仅待生效或已取消可删除,已生效记录不可删除,避免破坏调薪历史。
同一员工同时只允许存在一条待生效记录。
# 6.4 管理后台
对应 [HRM 人力资源 -> 薪资管理 -> 薪资档案] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/hrm/salary/employee-info 目录。
# 列表
支持按姓名、工号、部门、岗位和在职状态筛选,顶部按定薪状态展示页签及数量。未建立档案的员工显示【定薪】,已有档案的员工显示【调薪】。

# 定薪与调薪
通过弹窗 SalaryEmployeeInfoForm.vue 完成,依次填写员工、记录类型、调薪模板、生效日期、调整原因和备注。选定调薪模板后,表单只展示该模板允许调整的工资项,并分正式、试用期两组填写;调薪时左侧同步显示调整前的金额,方便对照。
生效日期晚于今天时,表单会提示该调整在生效前保持待生效,当前薪资档案不会提前变化。

# 批量调薪
选择多名员工后打开 SalaryEmployeeInfoBatchForm.vue,先用部门范围和指定员工圈定人群,再统一设置调整原因、生效日期、调薪方式(按比例 / 按金额,HrmSalaryBatchAdjustTypeEnum)和调薪项。批量处理中,立即生效的记录同步更新当前档案,未来记录保持待生效,接口返回每名员工的成功或失败原因。

# Excel 导入
SalaryEmployeeInfoImportForm.vue 支持「固定���资导入」和「调薪导入」两种模板,上传后展示成功数和逐行失败原因。导入时会排除系统计算类的父级工资项目录(EMPLOYEE_INFO_IMPORT_EXCLUDED_PARENT_CODES)。

# 薪资详情与变更记录
点击员工姓名进入 employee-info/detail/index.vue。SalaryEmployeeInfoDetails.vue 展示当前正式、试用期工资和工资项;SalaryChangeRecordList.vue 展示全部定薪、调薪记录,并提供取消、删除操作。

# 7. 与其它模块的衔接
- 员工:定薪、调薪都以
hrm_employee.id为业务关联,员工入职后即可定薪,不要求绑定后台账号。 - 月度工资:核算时读取计薪周期内生效的薪资档案,因此调薪的生效日期决定了它从哪个月开始计入工资,详见 《【薪资】月度工资、工资条》。