feat: 调部门改为调动,使用组织架构部门和职务下拉选择

- 后端:EmployeeDepartmentRecord 增加 oldPosition/newPosition 字段
- 后端:department-change 接口支持 departmentId 关联 + position 职务变动
- 后端:同步更新 Employee.departmentId 和 Employee.position
- 前端:DeptChangeModal 改为从组织架构下拉选择目标部门(树形)和职务
- 前端:选择部门后自动过滤该部门下的职务
- 前端:按钮文案从"调部门"改为"调动"

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
selfrelease
2026-08-15 15:00:38 +08:00
parent e8470e7bb4
commit e3d46d9142
4 changed files with 91 additions and 25 deletions
+24 -7
View File
@@ -1442,10 +1442,10 @@ router.get('/:id/salary-records', authMiddleware, async (req: AuthRequest, res,
} catch (err) { next(err) }
})
// 调部门
// 调动(部门+职务变动)
router.post('/:id/department-change', authMiddleware, async (req: AuthRequest, res, next) => {
try {
const { newDepartment, effectiveMonth, reason } = req.body
const { newDepartment, newPosition, departmentId, effectiveMonth, reason } = req.body
const employee = await prisma.employee.findFirst({
where: { id: req.params.id, orgId: req.user!.orgId },
})
@@ -1454,22 +1454,35 @@ router.post('/:id/department-change', authMiddleware, async (req: AuthRequest, r
}
const oldDepartment = employee.department
const oldPosition = employee.position || null
const effMonth = effectiveMonth || dateToMonth(new Date())
const prevEffMonth = prevMonth(effMonth)
// 校验 departmentId 是否属于当前组织
let deptName = newDepartment
if (departmentId) {
const dept = await prisma.department.findFirst({ where: { id: departmentId, orgId: req.user!.orgId } })
if (!dept) {
return res.status(400).json({ success: false, error: { code: 'VALIDATION_ERROR', message: '目标部门不存在' } })
}
deptName = dept.name
}
// 关闭之前有效记录
await prisma.employeeDepartmentRecord.updateMany({
where: { employeeId: req.params.id, endMonth: null },
data: { endMonth: prevEffMonth },
})
// 创建新部门记录
// 创建新调动记录
const record = await prisma.employeeDepartmentRecord.create({
data: {
orgId: req.user!.orgId,
employeeId: req.params.id,
oldDepartment,
newDepartment,
newDepartment: deptName,
oldPosition,
newPosition: newPosition || null,
effectiveMonth: effMonth,
endMonth: null,
changeType: 'TRANSFER',
@@ -1478,13 +1491,17 @@ router.post('/:id/department-change', authMiddleware, async (req: AuthRequest, r
},
})
// 同步 Employee 便捷字段
// 同步 Employee 字段department 文本 + departmentId 关联 + position 职务)
await prisma.employee.update({
where: { id: req.params.id },
data: { department: newDepartment },
data: {
department: deptName,
departmentId: departmentId || null,
position: newPosition || employee.position,
},
})
await auditLog(req, 'CREATE', 'DEPARTMENT_CHANGE', record.id, { employeeId: req.params.id, oldDepartment, newDepartment })
await auditLog(req, 'CREATE', 'DEPARTMENT_CHANGE', record.id, { employeeId: req.params.id, oldDepartment, newDepartment: deptName, oldPosition, newPosition })
res.json({ success: true, data: record })
} catch (err) { next(err) }
})