From 061328ebb114af9112f405482e7278cbc1ac5bad Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 5 Mar 2026 09:34:44 +0800 Subject: [PATCH] =?UTF-8?q?feat(approval):=20=E6=B7=BB=E5=8A=A0=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E6=B5=81=E5=89=8D=E7=AB=AF=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建 approval.ts 审批流API服务 - 包含审批流CRUD、待审批列表、审批操作等功能 --- .ralph/state.md | 25 ++- frontend/admin/src/services/approval.ts | 253 ++++++++++++++++++++++++ 2 files changed, 268 insertions(+), 10 deletions(-) create mode 100644 frontend/admin/src/services/approval.ts diff --git a/.ralph/state.md b/.ralph/state.md index d9ab328..4e9f501 100644 --- a/.ralph/state.md +++ b/.ralph/state.md @@ -6,9 +6,9 @@ - **Max Iterations**: 100 ## Current State -- **Iteration**: 6 +- **Iteration**: 7 - **Status**: In Progress -- **Current Phase**: Phase 2 - 前端权限组件开发 +- **Current Phase**: Phase 2 完成, Phase 3 审批流前端进行中 ## Progress - Phase 2 - [x] Phase 1: 数据库表创建(10张表)✅ @@ -22,21 +22,26 @@ - [x] Phase 2: 前端权限组件 - [x] 扩展 auth/roles.ts - 添加13个新角色和40+权限 - [x] 创建 services/permission.ts - 权限API服务 + - [x] 创建 services/role.ts - 角色管理服务 + - [x] 创建 services/approval.ts - 审批流服务 - [x] 创建 composables/usePermission.ts - 权限组合函数 - [x] 创建 router/permissionGuard.ts - 路由权限守卫 + - [x] 创建 components/PermissionButton.vue - 权限按钮组件 + - [x] 创建 components/PermissionDialog.vue - 权限对话框组件 + - [x] 创建 views/RoleManagementView.vue - 角色管理页面 - [x] 更新路由配置 - 使用新角色系统 - - [x] 更新 App.vue, LoginView, UsersView 等使用新角色 + - [x] 前端编译验证通过 - [ ] Phase 3: 审批流引擎 ## Completion Criteria - [x] Phase 1: 数据库表创建 - 100% - [x] Phase 2: 后端核心模块 - 100% -- [x] Phase 2: 前端权限组件 - 90% -- [ ] Phase 3: 审批流引擎 - 0% +- [x] Phase 2: 前端权限组件 - 100% +- [ ] Phase 3: 审批流引擎 - 10% - [ ] Phase 4: 业务模块开发 - 0% -## Recent Changes (Iteration 6) -- 扩展前端角色权限类型定义 -- 创建权限服务和路由守卫 -- 更新前端视图使用新角色系统 -- 前端编译成功 +## Recent Changes (Iteration 7) +- 添加 approval.ts 审批流服务 +- 创建 RoleManagementView.vue 角色管理页面 +- 权限菜单添加角色管理入口 +- 前端编译验证通过 diff --git a/frontend/admin/src/services/approval.ts b/frontend/admin/src/services/approval.ts new file mode 100644 index 0000000..4b0ee30 --- /dev/null +++ b/frontend/admin/src/services/approval.ts @@ -0,0 +1,253 @@ +/** + * 审批流服务 - 与后端审批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 { + id: number + status?: number +} + +export interface ApiResponse { + code: number + data: T + message?: string +} + +/** + * 审批流服务类 + */ +class ApprovalService { + private baseUrl = '/api' + + /** + * 获取所有审批流 + */ + async getFlows(): Promise { + const response = await fetch(`${this.baseUrl}/approval/flows`, { + credentials: 'include' + }) + 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 fetch(`${this.baseUrl}/approval/flows/${id}`, { + credentials: 'include' + }) + const result = await response.json() as ApiResponse + if (result.code !== 200) { + return null + } + return result.data + } + + /** + * 创建审批流 + */ + async createFlow(data: CreateFlowRequest): Promise { + 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 + if (result.code !== 200) { + throw new Error(result.message || '创建审批流失败') + } + return result.data + } + + /** + * 更新审批流 + */ + async updateFlow(data: UpdateFlowRequest): Promise { + 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 + if (result.code !== 200) { + throw new Error(result.message || '更新审批流失败') + } + } + + /** + * 删除审批流 + */ + async deleteFlow(id: number): Promise { + const response = await fetch(`${this.baseUrl}/approval/flows/${id}`, { + method: 'DELETE', + credentials: 'include' + }) + const result = await response.json() as ApiResponse + if (result.code !== 200) { + throw new Error(result.message || '删除审批流失败') + } + } + + /** + * 获取待审批列表 + */ + async getPendingApprovals(): Promise { + const response = await fetch(`${this.baseUrl}/approval/pending`, { + credentials: 'include' + }) + 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 fetch(`${this.baseUrl}/approval/approved`, { + credentials: 'include' + }) + 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 fetch(`${this.baseUrl}/approval/my`, { + credentials: 'include' + }) + const result = await response.json() as ApiResponse + if (result.code !== 200) { + throw new Error(result.message || '获取我发起的审批失败') + } + return result.data + } + + /** + * 审批操作 + */ + async approve(data: { + recordId: number + action: 'approve' | 'reject' | 'transfer' + comment?: string + }): Promise { + 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 + if (result.code !== 200) { + throw new Error(result.message || '审批操作失败') + } + } + + /** + * 获取审批记录详情 + */ + async getRecordById(id: number): Promise { + const response = await fetch(`${this.baseUrl}/approval/records/${id}`, { + credentials: 'include' + }) + const result = await response.json() as ApiResponse + if (result.code !== 200) { + return null + } + return result.data + } + + /** + * 获取审批历史 + */ + async getApprovalHistory(recordId: number): Promise { + const response = await fetch(`${this.baseUrl}/approval/records/${recordId}/history`, { + credentials: 'include' + }) + const result = await response.json() as ApiResponse + if (result.code !== 200) { + throw new Error(result.message || '获取审批历史失败') + } + return result.data + } +} + +export const approvalService = new ApprovalService() +export default approvalService