refactor: 全量迁移前端 API 调用到统一 api-services 服务层

- 新建 api-services-raw.ts 导出原始 axios 方法供特殊端点使用
- 完成 api-services.ts 全领域覆盖(auth/employee/roster/dashboard/attendance/payroll/socialInsurance/commercialInsurance/termination/policies/evidence/audit/calendar/companyFiles/notifications/settings/ai/platform/portal/survey/search)
- 迁移所有 47+ 页面文件:pages/、pages/roster/、pages/portal/、pages/platform/、pages/auth/、pages/dashboard/、pages/compliance/
- 移除所有直接 import api from '../../lib/api' 引用
- 修复 Termination.tsx / WorkProcess.tsx 中 string|null 类型错误
- 修复 SocialInsurance.tsx 中 api-services-raw delete 导入名
- 修复 PlatformLogin.tsx 变量遮蔽问题
- tsc --noEmit 零错误,vite build 成功
This commit is contained in:
selfrelease
2026-08-01 16:13:19 +08:00
parent fb924dea98
commit 16f22e6622
64 changed files with 1197 additions and 597 deletions
+34 -41
View File
@@ -7,8 +7,8 @@ import remarkGfm from 'remark-gfm'
import rehypeRaw from 'rehype-raw'
import { Document, Packer, Paragraph, HeadingLevel, TextRun, Table, TableRow, TableCell, WidthType, BorderStyle, AlignmentType } from 'docx'
import { saveAs } from 'file-saver'
import api from '../lib/api'
import { employeeApi } from '../lib/api-services'
import { aiApi, rosterApi, employeeApi } from '../lib/api-services'
import { post as apiPost } from '../lib/api-services-raw'
import { useAuthStore } from '../store/authStore'
import Card from '../components/ui/Card'
import Button from '../components/ui/Button'
@@ -107,30 +107,28 @@ function useAIHistory(type: 'predict' | 'review' | 'case') {
const { data: history } = useQuery<any[]>({
queryKey,
queryFn: async () => {
const res = await api.get(`/ai/conversations?type=${type}`) as any
return res.data
return await aiApi.conversations(type)
},
})
const saveMutation = useMutation({
mutationFn: async ({ title, input, result }: { title: string; input: string; result: string }) => {
const res = await api.post('/ai/conversations', {
const res = await aiApi.createConversation({
title: `${type}:${title}`,
messages: [{ role: 'user', content: input }, { role: 'assistant', content: result }],
}) as any
return res.data
return res
},
onSuccess: () => queryClient.invalidateQueries({ queryKey }),
})
const deleteMutation = useMutation({
mutationFn: (id: string) => api.delete(`/ai/conversations/${id}`),
mutationFn: (id: string) => aiApi.removeConversation(id),
onSuccess: () => queryClient.invalidateQueries({ queryKey }),
})
const loadHistory = useCallback(async (id: string) => {
const res = await api.get(`/ai/conversations/${id}`) as any
return res.data
return await aiApi.conversation(id)
}, [])
return { history, saveMutation, deleteMutation, loadHistory }
@@ -238,20 +236,18 @@ function ChatTab() {
const { data: conversations } = useQuery<any[]>({
queryKey: ['ai-conversations'],
queryFn: async () => {
const res = await api.get('/ai/conversations?type=chat') as any
return res.data
return await aiApi.conversations('chat')
},
})
const deleteConvMutation = useMutation({
mutationFn: (id: string) => api.delete(`/ai/conversations/${id}`),
mutationFn: (id: string) => aiApi.removeConversation(id),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['ai-conversations'] }),
})
const consultMutation = useMutation({
mutationFn: async (data: typeof consultForm) => {
const res = await api.post('/ai/consultation', data) as any
return res.data
return await aiApi.consult(data)
},
onSuccess: () => {
toast.success('已提交咨询请求,专业律师将尽快与您联系')
@@ -274,11 +270,11 @@ function ChatTab() {
saveTimerRef.current = setTimeout(async () => {
const title = `chat:${messages.find(m => m.role === 'user')?.content.slice(0, 30) || '新对话'}`
if (currentConvId) {
await api.put(`/ai/conversations/${currentConvId}`, { messages }).catch(() => {})
await aiApi.updateConversation(currentConvId, { messages }).catch(() => {})
} else {
const res = await api.post('/ai/conversations', { title, messages }) as any
if (res.data?.id) {
setCurrentConvId(res.data.id)
const res = await aiApi.createConversation({ title, messages }) as any
if (res?.id) {
setCurrentConvId(res.id)
queryClient.invalidateQueries({ queryKey: ['ai-conversations'] })
}
}
@@ -288,9 +284,9 @@ function ChatTab() {
const loadConversation = async (id: string) => {
try {
const res = await api.get(`/ai/conversations/${id}`) as any
if (res.data?.messages) {
setMessages(res.data.messages)
const res = await aiApi.conversation(id) as any
if (res?.messages) {
setMessages(res.messages)
setCurrentConvId(id)
setShowHistory(false)
}
@@ -679,8 +675,8 @@ function PredictTab() {
// 4. 获取违纪记录(列表接口未含明细,需调用专用接口)
try {
const res = await api.get(`/roster/${emp.id}/disciplinary`) as any
const records = res?.data || res || []
const res = await rosterApi.disciplinary(emp.id) as any
const records = res || []
if (Array.isArray(records) && records.length > 0) {
const typeMap: Record<string, string> = { LATE: '迟到', ABSENT: '旷工', INSUBORDINATION: '不服从管理', MISCONDUCT: '违纪', VIOLATE_POLICY: '违反制度', OTHER: '其他' }
const actionMap: Record<string, string> = { ORAL_WARNING: '口头警告', WRITTEN_WARNING: '书面警告', DEDUCTION: '扣款', DEMOTION: '降职', TERMINATION: '辞退' }
@@ -1365,10 +1361,8 @@ function ReviewTab() {
try {
const formData = new FormData()
formData.append('file', file)
const res = await api.post('/ai/review/upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' },
}) as any
if (res.data?.text) {
const res = await aiApi.reviewUpload(formData) as any
if (res?.text) {
setContractText(res.data.text)
setFileName(file.name)
toast.success(`已提取文件内容(${res.data.text.length} 字)`)
@@ -1391,10 +1385,10 @@ function ReviewTab() {
setLoading(true)
setResult(null)
try {
const res = await api.post('/ai/review', { contractText }) as any
setResult(res.data)
const res = await aiApi.review(contractText) as any
setResult(res)
// 自动保存到历史
if (res.data && !res.data.error) {
if (res && !res.error) {
const title = contractText.slice(0, 30).replace(/\n/g, ' ')
saveMutation.mutate({ title, input: contractText, result: res.data.text || JSON.stringify(res.data) })
}
@@ -1421,7 +1415,7 @@ function ReviewTab() {
const handleSave = async () => {
if (!saveEmployeeId || !result) return
try {
await api.post('/ai/review/save', { employeeId: saveEmployeeId, type: 'REVIEW', input: contractText, result: result.text || JSON.stringify(result) })
await aiApi.reviewSave({ employeeId: saveEmployeeId, type: 'REVIEW', input: contractText, result: result.text || JSON.stringify(result) })
setShowSaveModal(false)
setSaveEmployeeId('')
toast.success('已保存到员工档案')
@@ -1584,10 +1578,10 @@ function CaseTab() {
setLoading(true)
setResult('')
try {
const res = await api.post('/ai/match-case', { scenario }) as any
setResult(res.data.result)
const res = await aiApi.matchCase(scenario) as any
setResult(res.result)
// 自动保存到历史
if (res.data?.result && !res.data.result.startsWith('出错了')) {
if (res?.result && !res.result.startsWith('出错了')) {
const title = scenario.slice(0, 30).replace(/\n/g, ' ')
saveMutation.mutate({ title, input: scenario, result: res.data.result })
}
@@ -1612,7 +1606,7 @@ function CaseTab() {
const handleSave = async () => {
if (!saveEmployeeId || !result) return
try {
await api.post('/ai/review/save', { employeeId: saveEmployeeId, type: 'CASE', input: scenario, result })
await aiApi.reviewSave({ employeeId: saveEmployeeId, type: 'CASE', input: scenario, result })
setShowSaveModal(false)
setSaveEmployeeId('')
toast.success('已保存到员工档案')
@@ -1625,7 +1619,7 @@ function CaseTab() {
if (!todoEmployeeId || !todoTitle) return
setCreatingTodo(true)
try {
await api.post('/ai/case-to-todo', {
await aiApi.caseToTodo({
employeeId: todoEmployeeId,
title: todoTitle,
description: result.slice(0, 500),
@@ -1761,14 +1755,13 @@ function KnowledgeTab() {
const { data: knowledgeList, isLoading } = useQuery<any[]>({
queryKey: ['rag-knowledge'],
queryFn: async () => {
const res = await api.get('/ai/rag/list') as any
return res.data
return await aiApi.ragList()
},
})
const addMutation = useMutation({
mutationFn: async (data: typeof newItem) => {
return await api.post('/ai/rag/add', data)
return await aiApi.ragAdd(data)
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['rag-knowledge'] })
@@ -1778,12 +1771,12 @@ function KnowledgeTab() {
})
const deleteMutation = useMutation({
mutationFn: (id: string) => api.delete(`/ai/rag/${id}`),
mutationFn: (id: string) => aiApi.ragRemove(id),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['rag-knowledge'] }),
})
const seedMutation = useMutation({
mutationFn: () => api.post('/ai/rag/seed'),
mutationFn: () => aiApi.ragSeed(),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['rag-knowledge'] }),
})