ux: 花名册操作图标按钮分两行显示

第一行:调薪、转正、调部门
第二行:开具证明、续签合同、离职

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 14:47:48 +08:00
parent 4486adc957
commit 55f89d384b
+90 -86
View File
@@ -841,100 +841,104 @@ export default function Roster() {
</td>} </td>}
<td className="px-4 py-3 text-center"> <td className="px-4 py-3 text-center">
{e.status === 'ACTIVE' && (!e.hasTermination || e.latestTerminationStatus === 'CANCELLED' || e.latestTerminationStatus === 'COMPLETED') && ( {e.status === 'ACTIVE' && (!e.hasTermination || e.latestTerminationStatus === 'CANCELLED' || e.latestTerminationStatus === 'COMPLETED') && (
<div className="flex items-center justify-center gap-2"> <div className="flex flex-col items-center gap-1">
<button <div className="flex items-center justify-center gap-1">
type="button"
title="调薪"
aria-label={`${e.name}调薪`}
className="rounded-md p-1.5 text-gray-500 transition hover:bg-primary/10 hover:text-primary"
onClick={(ev) => {
ev.stopPropagation()
setSalaryEmployee(e)
setShowSalaryModal(true)
}}
>
<DollarSign className="h-4 w-4" />
</button>
{/* 试用期员工显示转正按钮 */}
{e.probationInfo?.isProbation && (
<button <button
type="button" type="button"
title="转正" title="调薪"
aria-label={`${e.name}办理转正`} aria-label={`${e.name}调薪`}
className="rounded-md p-1.5 text-gray-500 transition hover:bg-primary/10 hover:text-primary" className="rounded-md p-1.5 text-gray-500 transition hover:bg-primary/10 hover:text-primary"
onClick={(ev) => { onClick={(ev) => {
ev.stopPropagation() ev.stopPropagation()
setConfirmEmployee(e) setSalaryEmployee(e)
setShowConfirmModal(true) setShowSalaryModal(true)
}} }}
> >
<CheckCircle className="h-4 w-4" /> <DollarSign className="h-4 w-4" />
</button> </button>
)} {/* 试用期员工显示转正按钮 */}
<button {e.probationInfo?.isProbation && (
type="button" <button
title="调部门" type="button"
aria-label={`${e.name}调整部门`} title="转正"
className="rounded-md p-1.5 text-gray-500 transition hover:bg-primary/10 hover:text-primary" aria-label={`${e.name}办理转正`}
onClick={(ev) => { className="rounded-md p-1.5 text-gray-500 transition hover:bg-primary/10 hover:text-primary"
ev.stopPropagation() onClick={(ev) => {
setDeptEmployee(e) ev.stopPropagation()
setShowDeptModal(true) setConfirmEmployee(e)
}} setShowConfirmModal(true)
> }}
<Building2 className="h-4 w-4" /> >
</button> <CheckCircle className="h-4 w-4" />
<button </button>
type="button" )}
title="开具证明" <button
aria-label={`${e.name}开具证明`} type="button"
className="rounded-md p-1.5 text-gray-500 transition hover:bg-primary/10 hover:text-primary" title="调部门"
onClick={(ev) => { aria-label={`${e.name}调整部门`}
ev.stopPropagation() className="rounded-md p-1.5 text-gray-500 transition hover:bg-primary/10 hover:text-primary"
setCertEmployee(e) onClick={(ev) => {
setCertPurpose('') ev.stopPropagation()
setShowCertModal(true) setDeptEmployee(e)
}} setShowDeptModal(true)
> }}
<FileText className="h-4 w-4" /> >
</button> <Building2 className="h-4 w-4" />
<button </button>
type="button" </div>
title="续签合同" <div className="flex items-center justify-center gap-1">
aria-label={`${e.name}续签合同`} <button
className="rounded-md p-1.5 text-gray-500 transition hover:bg-primary/10 hover:text-primary" type="button"
onClick={(ev) => { title="开具证明"
ev.stopPropagation() aria-label={`${e.name}开具证明`}
// 自动推导新合同开始日期:原合同结束日 + 1天 className="rounded-md p-1.5 text-gray-500 transition hover:bg-primary/10 hover:text-primary"
const oldEndDate = e.latestContract?.endDate onClick={(ev) => {
let newStart = new Date().toISOString().slice(0, 10) ev.stopPropagation()
if (oldEndDate) { setCertEmployee(e)
const d = new Date(oldEndDate) setCertPurpose('')
d.setDate(d.getDate() + 1) setShowCertModal(true)
newStart = d.toISOString().slice(0, 10) }}
} >
setRenewEmployee(e) <FileText className="h-4 w-4" />
setRenewNewStartDate(newStart) </button>
setRenewNewEndDate('') <button
setRenewNewSalary(e.monthlySalary ? String(e.monthlySalary) : '') type="button"
setShowRenewModal(true) title="续签合同"
}} aria-label={`${e.name}续签合同`}
> className="rounded-md p-1.5 text-gray-500 transition hover:bg-primary/10 hover:text-primary"
<RotateCcw className="h-4 w-4" /> onClick={(ev) => {
</button> ev.stopPropagation()
<button // 自动推导新合同开始日期:原合同结束日 + 1天
type="button" const oldEndDate = e.latestContract?.endDate
title="离职" let newStart = new Date().toISOString().slice(0, 10)
aria-label={`${e.name}办理离职`} if (oldEndDate) {
className="rounded-md p-1.5 text-gray-500 transition hover:bg-danger/10 hover:text-danger" const d = new Date(oldEndDate)
onClick={(ev) => { d.setDate(d.getDate() + 1)
ev.stopPropagation() newStart = d.toISOString().slice(0, 10)
setResignEmployee(e) }
setShowResignModal(true) setRenewEmployee(e)
}} setRenewNewStartDate(newStart)
> setRenewNewEndDate('')
<UserX className="h-4 w-4" /> setRenewNewSalary(e.monthlySalary ? String(e.monthlySalary) : '')
</button> setShowRenewModal(true)
}}
>
<RotateCcw className="h-4 w-4" />
</button>
<button
type="button"
title="离职"
aria-label={`${e.name}办理离职`}
className="rounded-md p-1.5 text-gray-500 transition hover:bg-danger/10 hover:text-danger"
onClick={(ev) => {
ev.stopPropagation()
setResignEmployee(e)
setShowResignModal(true)
}}
>
<UserX className="h-4 w-4" />
</button>
</div>
</div> </div>
)} )}
{e.hasTermination && e.status === 'ACTIVE' && e.latestTerminationStatus !== 'CANCELLED' && e.latestTerminationStatus !== 'COMPLETED' && ( {e.hasTermination && e.status === 'ACTIVE' && e.latestTerminationStatus !== 'CANCELLED' && e.latestTerminationStatus !== 'COMPLETED' && (