2026-03-05 09:34:44 +08:00
|
|
|
/**
|
|
|
|
|
* 审批流服务 - 与后端审批API交互
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
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<CreateFlowRequest> {
|
|
|
|
|
id: number
|
|
|
|
|
status?: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ApiResponse<T> {
|
|
|
|
|
code: number
|
|
|
|
|
data: T
|
|
|
|
|
message?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 审批流服务类
|
|
|
|
|
*/
|
|
|
|
|
class ApprovalService {
|
|
|
|
|
private baseUrl = '/api'
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取所有审批流
|
|
|
|
|
*/
|
|
|
|
|
async getFlows(): Promise<ApprovalFlow[]> {
|
|
|
|
|
const response = await fetch(`${this.baseUrl}/approval/flows`, {
|
|
|
|
|
credentials: 'include'
|
|
|
|
|
})
|
|
|
|
|
const result = await response.json() as ApiResponse<ApprovalFlow[]>
|
|
|
|
|
if (result.code !== 200) {
|
|
|
|
|
throw new Error(result.message || '获取审批流失败')
|
|
|
|
|
}
|
|
|
|
|
return result.data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取审批流详情
|
|
|
|
|
*/
|
|
|
|
|
async getFlowById(id: number): Promise<ApprovalFlow | null> {
|
|
|
|
|
const response = await fetch(`${this.baseUrl}/approval/flows/${id}`, {
|
|
|
|
|
credentials: 'include'
|
|
|
|
|
})
|
|
|
|
|
const result = await response.json() as ApiResponse<ApprovalFlow>
|
|
|
|
|
if (result.code !== 200) {
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
return result.data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建审批流
|
|
|
|
|
*/
|
|
|
|
|
async createFlow(data: CreateFlowRequest): Promise<number> {
|
|
|
|
|
const response = await fetch(`${this.baseUrl}/approval/flows`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
credentials: 'include',
|
|
|
|
|
body: JSON.stringify(data)
|
|
|
|
|
})
|
|
|
|
|
const result = await response.json() as ApiResponse<number>
|
|
|
|
|
if (result.code !== 200) {
|
|
|
|
|
throw new Error(result.message || '创建审批流失败')
|
|
|
|
|
}
|
|
|
|
|
return result.data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 更新审批流
|
|
|
|
|
*/
|
|
|
|
|
async updateFlow(data: UpdateFlowRequest): Promise<void> {
|
|
|
|
|
const response = await fetch(`${this.baseUrl}/approval/flows/${data.id}`, {
|
|
|
|
|
method: 'PUT',
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
credentials: 'include',
|
|
|
|
|
body: JSON.stringify(data)
|
|
|
|
|
})
|
|
|
|
|
const result = await response.json() as ApiResponse<void>
|
|
|
|
|
if (result.code !== 200) {
|
|
|
|
|
throw new Error(result.message || '更新审批流失败')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 删除审批流
|
|
|
|
|
*/
|
|
|
|
|
async deleteFlow(id: number): Promise<void> {
|
|
|
|
|
const response = await fetch(`${this.baseUrl}/approval/flows/${id}`, {
|
|
|
|
|
method: 'DELETE',
|
|
|
|
|
credentials: 'include'
|
|
|
|
|
})
|
|
|
|
|
const result = await response.json() as ApiResponse<void>
|
|
|
|
|
if (result.code !== 200) {
|
|
|
|
|
throw new Error(result.message || '删除审批流失败')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取待审批列表
|
|
|
|
|
*/
|
2026-03-05 10:37:09 +08:00
|
|
|
async getPendingApprovals(userId: number): Promise<ApprovalRecord[]> {
|
|
|
|
|
const response = await fetch(`${this.baseUrl}/approval/pending?userId=${userId}`, {
|
2026-03-05 09:34:44 +08:00
|
|
|
credentials: 'include'
|
|
|
|
|
})
|
|
|
|
|
const result = await response.json() as ApiResponse<ApprovalRecord[]>
|
|
|
|
|
if (result.code !== 200) {
|
|
|
|
|
throw new Error(result.message || '获取待审批列表失败')
|
|
|
|
|
}
|
|
|
|
|
return result.data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取已审批列表
|
|
|
|
|
*/
|
2026-03-05 10:37:09 +08:00
|
|
|
async getApprovedList(userId: number): Promise<ApprovalRecord[]> {
|
|
|
|
|
const response = await fetch(`${this.baseUrl}/approval/processed?userId=${userId}`, {
|
2026-03-05 09:34:44 +08:00
|
|
|
credentials: 'include'
|
|
|
|
|
})
|
|
|
|
|
const result = await response.json() as ApiResponse<ApprovalRecord[]>
|
|
|
|
|
if (result.code !== 200) {
|
|
|
|
|
throw new Error(result.message || '获取已审批列表失败')
|
|
|
|
|
}
|
|
|
|
|
return result.data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取我发起的审批
|
|
|
|
|
*/
|
2026-03-05 10:37:09 +08:00
|
|
|
async getMyApplications(userId: number): Promise<ApprovalRecord[]> {
|
|
|
|
|
const response = await fetch(`${this.baseUrl}/approval/my?userId=${userId}`, {
|
2026-03-05 09:34:44 +08:00
|
|
|
credentials: 'include'
|
|
|
|
|
})
|
|
|
|
|
const result = await response.json() as ApiResponse<ApprovalRecord[]>
|
|
|
|
|
if (result.code !== 200) {
|
|
|
|
|
throw new Error(result.message || '获取我发起的审批失败')
|
|
|
|
|
}
|
|
|
|
|
return result.data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 审批操作
|
|
|
|
|
*/
|
|
|
|
|
async approve(data: {
|
|
|
|
|
recordId: number
|
2026-03-05 10:37:09 +08:00
|
|
|
action: 'APPROVE' | 'REJECT' | 'TRANSFER'
|
|
|
|
|
operatorId: number
|
2026-03-05 09:34:44 +08:00
|
|
|
comment?: string
|
|
|
|
|
}): Promise<void> {
|
|
|
|
|
const response = await fetch(`${this.baseUrl}/approval/handle`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
credentials: 'include',
|
|
|
|
|
body: JSON.stringify(data)
|
|
|
|
|
})
|
|
|
|
|
const result = await response.json() as ApiResponse<void>
|
|
|
|
|
if (result.code !== 200) {
|
|
|
|
|
throw new Error(result.message || '审批操作失败')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-05 10:37:09 +08:00
|
|
|
/**
|
|
|
|
|
* 提交审批申请
|
|
|
|
|
*/
|
|
|
|
|
async submitApproval(data: {
|
|
|
|
|
flowId: number
|
|
|
|
|
bizType: string
|
|
|
|
|
bizId: number
|
|
|
|
|
title: string
|
|
|
|
|
applicantId: number
|
|
|
|
|
applyReason: string
|
|
|
|
|
}): Promise<number> {
|
|
|
|
|
const response = await fetch(`${this.baseUrl}/approval/submit`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
credentials: 'include',
|
|
|
|
|
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<void> {
|
|
|
|
|
const response = await fetch(`${this.baseUrl}/approval/cancel`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
credentials: 'include',
|
|
|
|
|
body: JSON.stringify({ recordId, operatorId })
|
|
|
|
|
})
|
|
|
|
|
const result = await response.json() as ApiResponse<void>
|
|
|
|
|
if (result.code !== 200) {
|
|
|
|
|
throw new Error(result.message || '取消审批失败')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-05 09:34:44 +08:00
|
|
|
/**
|
|
|
|
|
* 获取审批记录详情
|
|
|
|
|
*/
|
|
|
|
|
async getRecordById(id: number): Promise<ApprovalRecord | null> {
|
|
|
|
|
const response = await fetch(`${this.baseUrl}/approval/records/${id}`, {
|
|
|
|
|
credentials: 'include'
|
|
|
|
|
})
|
|
|
|
|
const result = await response.json() as ApiResponse<ApprovalRecord>
|
|
|
|
|
if (result.code !== 200) {
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
return result.data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取审批历史
|
|
|
|
|
*/
|
|
|
|
|
async getApprovalHistory(recordId: number): Promise<ApprovalHistory[]> {
|
|
|
|
|
const response = await fetch(`${this.baseUrl}/approval/records/${recordId}/history`, {
|
|
|
|
|
credentials: 'include'
|
|
|
|
|
})
|
|
|
|
|
const result = await response.json() as ApiResponse<ApprovalHistory[]>
|
|
|
|
|
if (result.code !== 200) {
|
|
|
|
|
throw new Error(result.message || '获取审批历史失败')
|
|
|
|
|
}
|
|
|
|
|
return result.data
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const approvalService = new ApprovalService()
|
|
|
|
|
export default approvalService
|