/** * 审批流服务 - 与后端审批API交互 */ import { authFetch, baseUrl } from './authHelper' import type { AdminRole } from '../auth/roles' export interface ApprovalFlow { id: number flowCode: string flowName: string moduleCode: string description?: string status: number createdAt: string updatedAt?: string } export interface ApprovalRecord { id: number flowId: number bizType: string bizId: string title: string applicantId: number applicantName: string currentStatus: string currentNodeId: number currentNodeName: string applyReason?: string applyAttachments?: string createdAt: string updatedAt?: string } export interface ApprovalNode { id: number flowId: number nodeName: string nodeType: 'start' | 'approver' | 'condition' | 'cc' | 'end' approverType: 'user' | 'role' | 'department_leader' approverIds?: string approverRoles?: string condition?: string timeout: number action: string sortOrder: number } export interface ApprovalHistory { id: number recordId: number nodeId: number nodeName: string action: 'submit' | 'approve' | 'reject' | 'transfer' | 'callback' operatorId: number operatorName: string comment?: string attachments?: string createdAt: string } export interface CreateFlowRequest { flowCode: string flowName: string moduleCode: string description?: string } export interface UpdateFlowRequest extends Partial { id: number status?: number } export interface ApiResponse { code: number data: T message?: string } /** * 审批流服务类 */ class ApprovalService { private baseUrl = baseUrl || '/api/v1' /** * 获取所有审批流 */ async getFlows(): Promise { const response = await authFetch(`${this.baseUrl}/approval/flows`, { credentials: undefined }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '获取审批流失败') } return result.data } /** * 获取审批流详情 */ async getFlowById(id: number): Promise { const response = await authFetch(`${this.baseUrl}/approval/flows/${id}`, { credentials: undefined }) const result = await response.json() as ApiResponse if (result.code !== 200) { return null } return result.data } /** * 创建审批流 */ async createFlow(data: CreateFlowRequest): Promise { const response = await authFetch(`${this.baseUrl}/approval/flows`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: undefined, body: JSON.stringify(data) }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '创建审批流失败') } return result.data } /** * 更新审批流 */ async updateFlow(data: UpdateFlowRequest): Promise { const response = await authFetch(`${this.baseUrl}/approval/flows/${data.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, credentials: undefined, body: JSON.stringify(data) }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '更新审批流失败') } } /** * 删除审批流 */ async deleteFlow(id: number): Promise { const response = await authFetch(`${this.baseUrl}/approval/flows/${id}`, { method: 'DELETE', credentials: undefined }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '删除审批流失败') } } /** * 获取待审批列表 */ async getPendingApprovals(): Promise { const response = await authFetch(`${this.baseUrl}/approval/pending`, { credentials: undefined }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '获取待审批列表失败') } return result.data } /** * 获取已审批列表 */ async getApprovedList(): Promise { const response = await authFetch(`${this.baseUrl}/approval/processed`, { credentials: undefined }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '获取已审批列表失败') } return result.data } /** * 获取我发起的审批 */ async getMyApplications(): Promise { const response = await authFetch(`${this.baseUrl}/approval/my`, { credentials: undefined }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '获取我发起的审批失败') } return result.data } /** * 审批操作(统一入口) * @deprecated 请使用 approveRecord, rejectRecord, transferRecord 三个独立方法 */ async approve(data: { recordId: number action: 'APPROVE' | 'REJECT' | 'TRANSFER' operatorId: number comment?: string transferTo?: number // TRANSFER时必填 }): Promise { // 根据action调用对应的独立接口 switch (data.action) { case 'APPROVE': return this.approveRecord({ recordId: data.recordId, comment: data.comment }) case 'REJECT': return this.rejectRecord({ recordId: data.recordId, comment: data.comment }) case 'TRANSFER': if (data.transferTo == null) { throw new Error('TRANSFER操作需要提供transferTo参数') } return this.transferRecord({ recordId: data.recordId, transferTo: data.transferTo, comment: data.comment }) default: throw new Error(`Unknown action: ${data.action}`) } } /** * 审批通过 */ async approveRecord(data: { recordId: number comment?: string }): Promise { const response = await authFetch(`${this.baseUrl}/approval/approve`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: undefined, body: JSON.stringify({ recordId: data.recordId, comment: data.comment || '' }) }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '审批通过失败') } } /** * 审批拒绝 */ async rejectRecord(data: { recordId: number comment?: string }): Promise { const response = await authFetch(`${this.baseUrl}/approval/reject`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: undefined, body: JSON.stringify({ recordId: data.recordId, comment: data.comment || '' }) }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '审批拒绝失败') } } /** * 审批转交 */ async transferRecord(data: { recordId: number transferTo: number comment?: string }): Promise { const response = await authFetch(`${this.baseUrl}/approval/transfer`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: undefined, body: JSON.stringify({ recordId: data.recordId, transferTo: data.transferTo, comment: data.comment || '' }) }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '审批转交失败') } } /** * 审批委托 */ async delegateRecord(data: { recordId: number delegateTo: number reason?: string }): Promise { const response = await authFetch(`${this.baseUrl}/approval/delegate`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: undefined, body: JSON.stringify({ recordId: data.recordId, delegateTo: data.delegateTo, reason: data.reason || '' }) }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '审批委托失败') } } /** * 批量审批操作 * 使用新批量接口 POST /api/v1/approval/batch (approval.index.batch.ALL) * 注意:批量转交使用 POST /api/v1/approval/batch-transfer (approval.index.batch.transfer.ALL) */ async batchApprove(data: { recordIds: number[] action: 'APPROVE' | 'REJECT' | 'TRANSFER' comment?: string }): Promise<{ total: number successCount: number failCount: number results: Array<{ recordId: number; success: boolean; status: string; message: string }> }> { // 根据操作类型选择接口:TRANSFER使用批量转交接口,其他使用批量审批接口 const endpoint = data.action === 'TRANSFER' ? `${this.baseUrl}/api/v1/approval/batch-transfer` : `${this.baseUrl}/api/v1/approval/batch`; const response = await authFetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: undefined, body: JSON.stringify(data) }) const result = await response.json() as ApiResponse<{ total: number successCount: number failCount: number results: Array<{ recordId: number; success: boolean; status: string; message: string }> }> if (result.code !== 200) { throw new Error(result.message || '批量审批操作失败') } return result.data } /** * 提交审批申请 */ async submitApproval(data: { flowId: number bizType: string bizId: number title: string applicantId: number applyReason: string }): Promise { const response = await authFetch(`${this.baseUrl}/approval/submit`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: undefined, body: JSON.stringify(data) }) const result = await response.json() as ApiResponse<{ recordId: number }> if (result.code !== 200) { throw new Error(result.message || '提交审批失败') } return result.data.recordId } /** * 取消审批 */ async cancelApproval(recordId: number, operatorId: number): Promise { const response = await authFetch(`${this.baseUrl}/approval/cancel`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: undefined, body: JSON.stringify({ recordId, operatorId }) }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '取消审批失败') } } /** * 获取审批记录详情 */ async getRecordById(id: number): Promise { const response = await authFetch(`${this.baseUrl}/approval/records/${id}`, { credentials: undefined }) const result = await response.json() as ApiResponse if (result.code !== 200) { return null } return result.data } /** * 获取审批历史 */ async getApprovalHistory(recordId: number): Promise { const response = await authFetch(`${this.baseUrl}/approval/records/${recordId}/history`, { credentials: undefined }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '获取审批历史失败') } return result.data } /** * 添加审批意见(不改变审批状态) */ async addComment(recordId: number, comment: string): Promise { const response = await authFetch(`${this.baseUrl}/approval/records/${recordId}/comment`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: undefined, body: JSON.stringify({ comment }) }) const result = await response.json() as ApiResponse if (result.code !== 200) { throw new Error(result.message || '添加审批意见失败') } } } export const approvalService = new ApprovalService() export default approvalService