import axios from 'axios' // ==================== Axios 实例 ==================== const api = axios.create({ baseURL: '/api/v1', timeout: 30000, headers: { 'Content-Type': 'application/json' } }) // 请求拦截器 - 自动附加 Token api.interceptors.request.use( config => { const token = localStorage.getItem('accessToken') if (token) { config.headers.Authorization = `Bearer ${token}` } return config }, error => Promise.reject(error) ) // 响应拦截器 api.interceptors.response.use( response => { const { data } = response if (data.code === 200) { return data.data } return Promise.reject(new Error(data.message || '请求失败')) }, error => { if (error.response?.status === 401 || error.response?.status === 403) { localStorage.removeItem('accessToken') localStorage.removeItem('refreshToken') localStorage.removeItem('username') if (!window.location.pathname.includes('/login')) { window.location.href = '/login' } } const msg = error.response?.data?.message || error.message || '网络错误' return Promise.reject(new Error(msg)) } ) // ==================== 认证 API ==================== export const authApi = { login(data) { return api.post('/auth/login', { username: data.usernameOrEmail || data.username, password: data.password }) }, logout() { return api.post('/auth/logout') }, refreshToken(refreshToken) { return api.post('/auth/refresh', { refreshToken }) }, getCurrentUser() { return api.get('/auth/me') }, getPermissions() { return api.get('/auth/permissions') }, changePassword(data) { return api.put('/auth/password', data) } } // ==================== 项目 API ==================== export const projectApi = { list(params = {}) { return api.get('/projects', { params }) }, getById(id) { return api.get(`/projects/${id}`) }, create(data) { return api.post('/projects', data) }, update(id, data) { return api.put(`/projects/${id}`, data) }, delete(id) { return api.delete(`/projects/${id}`) }, copy(id) { return api.post(`/projects/${id}/copy`) }, archive(id) { return api.post(`/projects/${id}/archive`) }, export(id) { return api.get(`/projects/${id}/export`, { responseType: 'blob' }) }, getDocContent(id) { return api.get(`/projects/${id}/doc-content`) } } // ==================== 要素 API ==================== export const elementApi = { list(projectId) { return api.get(`/projects/${projectId}/elements`) }, add(projectId, data) { return api.post(`/projects/${projectId}/elements`, data) }, update(projectId, elementId, data) { return api.put(`/projects/${projectId}/elements/${elementId}`, data) }, delete(projectId, elementId) { return api.delete(`/projects/${projectId}/elements/${elementId}`) } } // ==================== 要素值 API ==================== export const valueApi = { list(projectId) { return api.get(`/projects/${projectId}/values`) }, getByKey(projectId, elementKey) { return api.get(`/projects/${projectId}/values/${elementKey}`) }, update(projectId, elementKey, data) { return api.put(`/projects/${projectId}/values/${encodeURIComponent(elementKey)}`, data) }, batchUpdate(projectId, values) { return api.put(`/projects/${projectId}/values`, values) } } // ==================== 附件 API ==================== export const attachmentApi = { list(projectId) { return api.get(`/projects/${projectId}/attachments`) }, getById(attachmentId) { return api.get(`/attachments/${attachmentId}`) }, upload(projectId, file, displayName = null) { const formData = new FormData() formData.append('file', file) if (displayName) { formData.append('displayName', displayName) } return api.post(`/projects/${projectId}/attachments/upload`, formData, { headers: { 'Content-Type': 'multipart/form-data' } }) }, delete(attachmentId) { return api.delete(`/attachments/${attachmentId}`) }, parse(attachmentId) { return api.post(`/attachments/${attachmentId}/parse`) }, saveParsedContent(attachmentId, parsedText) { return api.put(`/attachments/${attachmentId}/parsed-content`, { parsedText }) }, getParsedText(attachmentId) { return api.get(`/attachments/${attachmentId}/parsed-text`) }, parseDocx(file) { const formData = new FormData() formData.append('file', file) return api.post('/tools/parse-docx', formData, { headers: { 'Content-Type': 'multipart/form-data' }, timeout: 120000 }) }, sort(projectId, orderedIds) { return api.put(`/projects/${projectId}/attachments/sort`, orderedIds) }, getDocContent(attachmentId) { return api.get(`/attachments/${attachmentId}/doc-content`) } } // ==================== 规则 API ==================== export const ruleApi = { list(projectId) { return api.get(`/projects/${projectId}/rules`) }, getById(ruleId) { return api.get(`/rules/${ruleId}`) }, create(projectId, data) { return api.post(`/projects/${projectId}/rules`, data) }, update(ruleId, data) { return api.put(`/rules/${ruleId}`, data) }, delete(ruleId) { return api.delete(`/rules/${ruleId}`) }, execute(ruleId) { return api.post(`/rules/${ruleId}/execute`) }, batchExecute(projectId) { return api.post(`/projects/${projectId}/rules/execute`) } } // ==================== 文件 API ==================== export const fileApi = { upload(file) { const formData = new FormData() formData.append('file', file) return api.post('/files/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' } }) }, getDownloadUrl(fileKey) { return `/api/v1/files/${fileKey}` }, getPreviewUrl(fileKey) { return `/api/v1/files/${fileKey}/preview` }, delete(fileKey) { return api.delete(`/files/${fileKey}`) } } // ==================== 任务 API ==================== export const taskApi = { list(params = {}) { return api.get('/tasks', { params }) }, getById(taskId) { return api.get(`/tasks/${taskId}`) }, cancel(taskId) { return api.post(`/tasks/${taskId}/cancel`) } } // ==================== 用户管理 API ==================== export const userApi = { list(params = {}) { return api.get('/users', { params }) }, getById(id) { return api.get(`/users/${id}`) }, create(data) { return api.post('/users', data) }, update(id, data) { return api.put(`/users/${id}`, data) }, delete(id) { return api.delete(`/users/${id}`) } } // ==================== AI API ==================== export const aiApi = { extractEntities(data) { return api.post('/ai/ner', data) }, chat(data) { return api.post('/ai/chat', data) }, suggest(data) { return api.post('/ai/suggest', data) }, optimize(data) { return api.post('/ai/optimize', data) } } // ==================== PDF 解析 API (外部服务) ==================== const parseService = axios.create({ baseURL: 'http://47.108.80.98:4214', timeout: 120000 }) export const parseApi = { // 提交 PDF/图片解析任务 submit(file, options = {}) { const formData = new FormData() formData.append('file', file) if (options.backend) formData.append('backend', options.backend) if (options.remove_watermark) formData.append('remove_watermark', 'true') if (options.crop_header_footer) formData.append('crop_header_footer', 'true') if (options.return_images) formData.append('return_images', 'true') return parseService.post('/pdf_to_markdown', formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(r => r.data) }, // 查询任务状态 getStatus(taskId) { return parseService.get(`/task/${taskId}`).then(r => r.data) }, // 获取解析结果 JSON { markdown, filename } getResult(taskId) { return parseService.get(`/task/${taskId}/json`).then(r => r.data) }, // 下载 markdown 文件 downloadMarkdown(taskId) { return parseService.get(`/download/${taskId}/markdown`, { responseType: 'blob' }).then(r => r.data) }, // 下载 zip 包(markdown + 图片) downloadZip(taskId) { return parseService.get(`/download/${taskId}/zip`, { responseType: 'blob' }).then(r => r.data) }, // 获取解析任务的图片 URL 基础路径 getImageBaseUrl(taskId) { return `http://47.108.80.98:4214/download/${taskId}/images` } } export default api