fix: 培训/绩效/违纪列表页CRUD改用api实例(修复401鉴权失败)
This commit is contained in:
@@ -399,6 +399,112 @@ async function createOrg(orgConfig: OrgConfig) {
|
||||
}
|
||||
}
|
||||
console.log(` ✅ 历史工资条已生成`)
|
||||
|
||||
// 10. 生成培训记录
|
||||
console.log(` 📝 生成培训记录...`)
|
||||
const trainingTopics = [
|
||||
{ topic: '新员工入职培训', content: '公司文化、规章制度、安全规范', trainer: '张经理', duration: 4 },
|
||||
{ topic: '岗位技能培训', content: '岗位操作规范与流程', trainer: '李主管', duration: 6 },
|
||||
{ topic: '安全生产培训', content: '安全生产法规与操作规程', trainer: '王安全', duration: 3 },
|
||||
{ topic: '团队协作培训', content: '沟通技巧与团队建设', trainer: '刘讲师', duration: 2 },
|
||||
]
|
||||
for (let i = 0; i < allEmployees.length; i++) {
|
||||
const emp = allEmployees[i]
|
||||
const t = trainingTopics[i % trainingTopics.length]
|
||||
const trainDate = new Date(2026, (i % 6), 15)
|
||||
const ackStatus = i % 3 === 0 ? 'PENDING' : i % 3 === 1 ? 'SIGNED' : 'REFUSED'
|
||||
await prisma.trainingRecord.create({
|
||||
data: {
|
||||
orgId: org.id,
|
||||
employeeId: emp.id,
|
||||
trainingDate: trainDate,
|
||||
topic: t.topic,
|
||||
content: t.content,
|
||||
trainer: t.trainer,
|
||||
duration: t.duration,
|
||||
ackStatus: ackStatus as any,
|
||||
ackDate: ackStatus === 'SIGNED' ? new Date(trainDate.getTime() + 86400000) : null,
|
||||
createdBy: admin.id,
|
||||
},
|
||||
})
|
||||
}
|
||||
console.log(` ✅ 培训记录已生成 (${allEmployees.length}条)`)
|
||||
|
||||
// 11. 生成绩效记录
|
||||
console.log(` 📊 生成绩效记录...`)
|
||||
const perfResults = ['EXCELLENT', 'QUALIFIED', 'QUALIFIED', 'NEED_IMPROVE', 'UNQUALIFIED'] as const
|
||||
const perfGrades = ['A', 'B', 'B', 'C', 'D']
|
||||
for (let i = 0; i < allEmployees.length; i++) {
|
||||
const emp = allEmployees[i]
|
||||
const idx = i % perfResults.length
|
||||
const score = 95 - idx * 12
|
||||
await prisma.performanceRecord.create({
|
||||
data: {
|
||||
orgId: org.id,
|
||||
employeeId: emp.id,
|
||||
period: '2026-Q1',
|
||||
score,
|
||||
grade: perfGrades[idx],
|
||||
result: perfResults[idx] as any,
|
||||
summary: idx < 2 ? '工作表现优秀,完成任务质量高' : idx < 4 ? '基本完成工作目标,有待提升' : '未达到岗位要求,需制定改进计划',
|
||||
improvementPlan: idx >= 3 ? '加强技能培训,设定阶段性目标' : null,
|
||||
reviewer: admin.name,
|
||||
employeeAck: i % 2 === 0,
|
||||
createdBy: admin.id,
|
||||
},
|
||||
})
|
||||
// 部分员工有Q2绩效
|
||||
if (i % 2 === 0) {
|
||||
await prisma.performanceRecord.create({
|
||||
data: {
|
||||
orgId: org.id,
|
||||
employeeId: emp.id,
|
||||
period: '2026-Q2',
|
||||
score: score - 5,
|
||||
grade: perfGrades[Math.min(idx + 1, 4)],
|
||||
result: perfResults[Math.min(idx + 1, 4)] as any,
|
||||
summary: '二季度绩效评估',
|
||||
reviewer: admin.name,
|
||||
employeeAck: false,
|
||||
createdBy: admin.id,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
console.log(` ✅ 绩效记录已生成 (${allEmployees.length}条)`)
|
||||
|
||||
// 12. 生成违纪记录(部分员工)
|
||||
console.log(` ⚠️ 生成违纪记录...`)
|
||||
const discTypes = ['LATE', 'ABSENT', 'INSUBORDINATION', 'MISCONDUCT'] as const
|
||||
const discDescriptions = [
|
||||
'月内累计迟到3次,超过公司允许范围',
|
||||
'未经请假擅自缺勤1天',
|
||||
'不服从主管工作安排,拒绝执行合理指令',
|
||||
'违反公司安全操作规程,未佩戴防护设备',
|
||||
]
|
||||
const discActions = ['ORAL_WARNING', 'WRITTEN_WARNING', 'DEDUCTION', 'WRITTEN_WARNING'] as const
|
||||
for (let i = 0; i < Math.min(allEmployees.length, 4); i++) {
|
||||
const emp = allEmployees[i]
|
||||
const violationDate = new Date(2026, i % 6, 10)
|
||||
await prisma.disciplinaryRecord.create({
|
||||
data: {
|
||||
orgId: org.id,
|
||||
employeeId: emp.id,
|
||||
violationDate,
|
||||
violationType: discTypes[i],
|
||||
description: discDescriptions[i],
|
||||
severity: i < 2 ? 'WARNING' : 'SERIOUS',
|
||||
action: discActions[i],
|
||||
actionDetail: i === 2 ? '扣除当日工资' : '',
|
||||
employeeAck: i % 2 === 0,
|
||||
ackDate: i % 2 === 0 ? new Date(violationDate.getTime() + 86400000) : null,
|
||||
ackMethod: i % 2 === 0 ? 'SIGN' : null,
|
||||
witness: i >= 2 ? '部门主管' : null,
|
||||
createdBy: admin.id,
|
||||
},
|
||||
})
|
||||
}
|
||||
console.log(` ✅ 违纪记录已生成 (${Math.min(allEmployees.length, 4)}条)`)
|
||||
}
|
||||
|
||||
// ========== 主函数 ==========
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Link } from 'react-router-dom'
|
||||
import { Search, Plus, Edit2, Trash2, X } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { rosterApi, employeeApi } from '../../lib/api-services'
|
||||
import api from '../../lib/api'
|
||||
import { usePageSize } from '../../hooks/usePageSize'
|
||||
import { Input, Label, Select } from '../../components/ui/Input'
|
||||
import Button from '../../components/ui/Button'
|
||||
@@ -43,14 +44,10 @@ export default function DisciplinaryRecords() {
|
||||
const isEdit = !!data.recordId
|
||||
const recordId = data.recordId
|
||||
delete data.recordId
|
||||
const url = isEdit
|
||||
? `/api/v1/roster/${empId}/disciplinary/${recordId}`
|
||||
: `/api/v1/roster/${empId}/disciplinary`
|
||||
return fetch(url, {
|
||||
method: isEdit ? 'PUT' : 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` },
|
||||
body: JSON.stringify(data),
|
||||
}).then(r => r.json())
|
||||
if (isEdit) {
|
||||
return api.put(`/roster/${empId}/disciplinary/${recordId}`, data)
|
||||
}
|
||||
return api.post(`/roster/${empId}/disciplinary`, data)
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success('违纪记录已保存')
|
||||
@@ -63,10 +60,7 @@ export default function DisciplinaryRecords() {
|
||||
|
||||
const deleteMut = useMutation({
|
||||
mutationFn: ({ employeeId, recordId }: { employeeId: string; recordId: string }) =>
|
||||
fetch(`/api/v1/roster/${employeeId}/disciplinary/${recordId}`, {
|
||||
method: 'DELETE',
|
||||
headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` },
|
||||
}).then(r => r.json()),
|
||||
api.delete(`/roster/${employeeId}/disciplinary/${recordId}`),
|
||||
onSuccess: () => {
|
||||
toast.success('记录已删除')
|
||||
queryClient.invalidateQueries({ queryKey: ['disciplinary-list'] })
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Link } from 'react-router-dom'
|
||||
import { Search, Plus, Edit2, Trash2, X } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { rosterApi, employeeApi } from '../../lib/api-services'
|
||||
import api from '../../lib/api'
|
||||
import { usePageSize } from '../../hooks/usePageSize'
|
||||
import { Input, Label, Select } from '../../components/ui/Input'
|
||||
import Button from '../../components/ui/Button'
|
||||
@@ -36,14 +37,10 @@ export default function PerformanceRecords() {
|
||||
const isEdit = !!data.recordId
|
||||
const recordId = data.recordId
|
||||
delete data.recordId
|
||||
const url = isEdit
|
||||
? `/api/v1/roster/${empId}/performance/${recordId}`
|
||||
: `/api/v1/roster/${empId}/performance`
|
||||
return fetch(url, {
|
||||
method: isEdit ? 'PUT' : 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` },
|
||||
body: JSON.stringify(data),
|
||||
}).then(r => r.json())
|
||||
if (isEdit) {
|
||||
return api.put(`/roster/${empId}/performance/${recordId}`, data)
|
||||
}
|
||||
return api.post(`/roster/${empId}/performance`, data)
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success('绩效记录已保存')
|
||||
@@ -56,10 +53,7 @@ export default function PerformanceRecords() {
|
||||
|
||||
const deleteMut = useMutation({
|
||||
mutationFn: ({ employeeId, recordId }: { employeeId: string; recordId: string }) =>
|
||||
fetch(`/api/v1/roster/${employeeId}/performance/${recordId}`, {
|
||||
method: 'DELETE',
|
||||
headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` },
|
||||
}).then(r => r.json()),
|
||||
api.delete(`/roster/${employeeId}/performance/${recordId}`),
|
||||
onSuccess: () => {
|
||||
toast.success('记录已删除')
|
||||
queryClient.invalidateQueries({ queryKey: ['performance-list'] })
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Link } from 'react-router-dom'
|
||||
import { Search, Plus, Edit2, Trash2, X } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { rosterApi, employeeApi } from '../../lib/api-services'
|
||||
import api from '../../lib/api'
|
||||
import { usePageSize } from '../../hooks/usePageSize'
|
||||
import { Input, Label, Select } from '../../components/ui/Input'
|
||||
import Button from '../../components/ui/Button'
|
||||
@@ -38,11 +39,7 @@ export default function TrainingRecords() {
|
||||
mutationFn: (data: any) => {
|
||||
const empId = data.employeeId
|
||||
delete data.employeeId
|
||||
return fetch(`/api/v1/roster/${empId}/training`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` },
|
||||
body: JSON.stringify(data),
|
||||
}).then(r => r.json())
|
||||
return api.post(`/roster/${empId}/training`, data)
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success('培训记录已添加')
|
||||
@@ -58,11 +55,7 @@ export default function TrainingRecords() {
|
||||
const recordId = data.recordId
|
||||
delete data.employeeId
|
||||
delete data.recordId
|
||||
return fetch(`/api/v1/roster/${empId}/training/${recordId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` },
|
||||
body: JSON.stringify(data),
|
||||
}).then(r => r.json())
|
||||
return api.put(`/roster/${empId}/training/${recordId}`, data)
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success('培训记录已更新')
|
||||
@@ -74,10 +67,7 @@ export default function TrainingRecords() {
|
||||
|
||||
const deleteMut = useMutation({
|
||||
mutationFn: ({ employeeId, recordId }: { employeeId: string; recordId: string }) =>
|
||||
fetch(`/api/v1/roster/${employeeId}/training/${recordId}`, {
|
||||
method: 'DELETE',
|
||||
headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` },
|
||||
}).then(r => r.json()),
|
||||
api.delete(`/roster/${employeeId}/training/${recordId}`),
|
||||
onSuccess: () => {
|
||||
toast.success('记录已删除')
|
||||
queryClient.invalidateQueries({ queryKey: ['training-list'] })
|
||||
|
||||
Reference in New Issue
Block a user