diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 4eb7bdb..b441d9c 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -22,7 +22,9 @@
"Bash(npm run build 2>&1 | head -40)",
"Bash(npm run build 2>&1 | head -50)",
"Bash(cd /home/long/project/蚊子/frontend/admin && npm run build 2>&1 | tail -20)",
- "Bash(npm run build 2>&1 | tail -15)"
+ "Bash(npm run build 2>&1 | tail -15)",
+ "Bash(cd /home/long/project/蚊子/frontend/admin && npm run build 2>&1 | tail -15)",
+ "Bash(npm run build 2>&1 | tail -10)"
],
"deny": []
},
diff --git a/.ralph/state.md b/.ralph/state.md
index 4e9f501..f242cec 100644
--- a/.ralph/state.md
+++ b/.ralph/state.md
@@ -6,42 +6,36 @@
- **Max Iterations**: 100
## Current State
-- **Iteration**: 7
+- **Iteration**: 8
- **Status**: In Progress
-- **Current Phase**: Phase 2 完成, Phase 3 审批流前端进行中
+- **Current Phase**: Phase 2 & 3 进行中
-## Progress - Phase 2
-- [x] Phase 1: 数据库表创建(10张表)✅
-- [x] Phase 2: 权限核心模块后端
- - [x] 角色管理 (SysRole + RoleRepository/Service/Controller)
- - [x] 权限管理 (SysPermission + PermissionRepository/Service)
- - [x] 部门管理 (SysDepartment + DepartmentRepository/Service/Controller)
- - [x] 权限判断服务 (PermissionCheckService) - 已完善
- - [x] 用户角色关联 (SysUserRole + UserRoleRepository)
- - [x] 角色权限关联 (SysRolePermission + RolePermissionRepository)
-- [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] 前端编译验证通过
-- [ ] Phase 3: 审批流引擎
+## Progress Summary
+- [x] Phase 1: 数据库表创建(10张表)100%
+- [x] Phase 2: 后端权限核心模块 100%
+ - 实体: SysRole, SysPermission, SysDepartment, SysUserRole, SysRolePermission
+ - Repositories: 完整的JPA查询
+ - Services: RoleService, PermissionService, DepartmentService, PermissionCheckService
+ - Controllers: RoleController, PermissionController, ApprovalController, UserController
+- [x] Phase 2: 前端权限组件 100%
+ - 角色权限类型定义 (13角色, 40+权限)
+ - 权限服务 (permission.ts, role.ts, approval.ts)
+ - 权限组件 (PermissionButton, PermissionDialog)
+ - 权限 composable (usePermission)
+ - 路由守卫 (permissionGuard)
+ - 角色管理页面
+- [ ] Phase 3: 审批流引擎 30%
+- [ ] Phase 4: 业务模块开发 0%
-## Completion Criteria
-- [x] Phase 1: 数据库表创建 - 100%
-- [x] Phase 2: 后端核心模块 - 100%
-- [x] Phase 2: 前端权限组件 - 100%
-- [ ] Phase 3: 审批流引擎 - 10%
-- [ ] Phase 4: 业务模块开发 - 0%
+## Recent Commits
+- ddae043: 修复 JPA 查询兼容性问题
+- 64bae7c: 前端权限系统完善
+- 62b1eef: 权限核心模块后端
+- c621af0: 角色管理功能
+- 061328e: 审批流服务
+- e08192b: 权限和审批控制器
-## Recent Changes (Iteration 7)
-- 添加 approval.ts 审批流服务
-- 创建 RoleManagementView.vue 角色管理页面
-- 权限菜单添加角色管理入口
-- 前端编译验证通过
+## Next Steps
+1. 完成审批流后端 Service 实现
+2. 创建审批流前端页面
+3. 继续 Phase 4 业务模块
diff --git a/frontend/admin/src/App.vue b/frontend/admin/src/App.vue
index a5fbf06..a02488c 100644
--- a/frontend/admin/src/App.vue
+++ b/frontend/admin/src/App.vue
@@ -90,6 +90,14 @@
>
通知
+
+ 系统
+
演示模式
diff --git a/frontend/admin/src/router/index.ts b/frontend/admin/src/router/index.ts
index ea0b78f..3254eed 100644
--- a/frontend/admin/src/router/index.ts
+++ b/frontend/admin/src/router/index.ts
@@ -17,9 +17,11 @@ import ApprovalCenterView from '../views/ApprovalCenterView.vue'
import UserDetailView from '../views/UserDetailView.vue'
import PermissionsView from '../views/PermissionsView.vue'
import RoleManagementView from '../views/RoleManagementView.vue'
+import DepartmentManagementView from '../views/DepartmentManagementView.vue'
+import SystemConfigView from '../views/SystemConfigView.vue'
import type { AdminRole } from '../auth/roles'
-// 路由权限配置 - 使用新的角色系统
+// 路由权限配置
const routeRoles: Record
= {
'dashboard': ['super_admin', 'system_admin', 'operation_manager', 'operation_member', 'marketing_manager', 'marketing_member', 'finance_manager', 'finance_member', 'risk_manager', 'risk_member', 'customer_service', 'auditor', 'viewer'],
'activities': ['super_admin', 'system_admin', 'operation_manager', 'operation_member', 'marketing_manager', 'marketing_member', 'customer_service', 'auditor', 'viewer'],
@@ -35,119 +37,33 @@ const routeRoles: Record = {
'approvals': ['super_admin', 'system_admin', 'operation_manager', 'marketing_manager', 'finance_manager', 'risk_manager'],
'permissions': ['super_admin', 'system_admin'],
'role-management': ['super_admin', 'system_admin'],
- 'notifications': ['super_admin', 'system_admin', 'operation_manager', 'operation_member', 'marketing_manager', 'marketing_member', 'finance_manager', 'finance_member', 'risk_manager', 'risk_member', 'customer_service', 'auditor', 'viewer'],
- 'system': ['super_admin', 'system_admin', 'auditor']
+ 'department-management': ['super_admin', 'system_admin'],
+ 'system-config': ['super_admin', 'system_admin', 'auditor'],
+ 'notifications': ['super_admin', 'system_admin', 'operation_manager', 'operation_member', 'marketing_manager', 'marketing_member', 'finance_manager', 'finance_member', 'risk_manager', 'risk_member', 'customer_service', 'auditor', 'viewer']
}
const router = createRouter({
history: createWebHistory(),
routes: [
- {
- path: '/login',
- name: 'login',
- component: LoginView
- },
- {
- path: '/',
- name: 'dashboard',
- component: DashboardView,
- meta: { roles: routeRoles.dashboard }
- },
- {
- path: '/activities',
- name: 'activities',
- component: ActivityListView,
- meta: { roles: routeRoles.activities }
- },
- {
- path: '/activities/new',
- name: 'activity-create',
- component: ActivityCreateView,
- meta: { roles: routeRoles['activity-create'] }
- },
- {
- path: '/activities/:id',
- name: 'activity-detail',
- component: ActivityDetailView,
- meta: { roles: routeRoles['activity-detail'] }
- },
- {
- path: '/activities/config',
- name: 'activity-config',
- component: ActivityConfigWizardView,
- meta: { roles: routeRoles['activity-config'] }
- },
- {
- path: '/activities/:id',
- name: 'activity-detail',
- component: ActivityDetailView,
- meta: { roles: routeRoles['activity-detail'] }
- },
- {
- path: '/users',
- name: 'users',
- component: UsersView,
- meta: { roles: routeRoles.users }
- },
- {
- path: '/users/:id',
- name: 'user-detail',
- component: UserDetailView,
- meta: { roles: routeRoles['user-detail'] }
- },
- {
- path: '/users/invite',
- name: 'user-invite',
- component: InviteUserView,
- meta: { roles: routeRoles['user-invite'] }
- },
- {
- path: '/rewards',
- name: 'rewards',
- component: RewardsView,
- meta: { roles: routeRoles.rewards }
- },
- {
- path: '/risk',
- name: 'risk',
- component: RiskView,
- meta: { roles: routeRoles.risk }
- },
- {
- path: '/audit',
- name: 'audit',
- component: AuditLogView,
- meta: { roles: routeRoles.audit }
- },
- {
- path: '/approvals',
- name: 'approvals',
- component: ApprovalCenterView,
- meta: { roles: routeRoles.approvals }
- },
- {
- path: '/permissions',
- name: 'permissions',
- component: PermissionsView,
- meta: { roles: routeRoles.permissions }
- },
- {
- path: '/roles',
- name: 'role-management',
- component: RoleManagementView,
- meta: { roles: routeRoles['role-management'] }
- },
- {
- path: '/notifications',
- name: 'notifications',
- component: NotificationsView,
- meta: { roles: routeRoles.notifications }
- },
- {
- path: '/403',
- name: 'forbidden',
- component: ForbiddenView
- }
+ { path: '/login', name: 'login', component: LoginView },
+ { path: '/', name: 'dashboard', component: DashboardView, meta: { roles: routeRoles.dashboard } },
+ { path: '/activities', name: 'activities', component: ActivityListView, meta: { roles: routeRoles.activities } },
+ { path: '/activities/new', name: 'activity-create', component: ActivityCreateView, meta: { roles: routeRoles['activity-create'] } },
+ { path: '/activities/:id', name: 'activity-detail', component: ActivityDetailView, meta: { roles: routeRoles['activity-detail'] } },
+ { path: '/activities/config', name: 'activity-config', component: ActivityConfigWizardView, meta: { roles: routeRoles['activity-config'] } },
+ { path: '/users', name: 'users', component: UsersView, meta: { roles: routeRoles.users } },
+ { path: '/users/:id', name: 'user-detail', component: UserDetailView, meta: { roles: routeRoles['user-detail'] } },
+ { path: '/users/invite', name: 'user-invite', component: InviteUserView, meta: { roles: routeRoles['user-invite'] } },
+ { path: '/rewards', name: 'rewards', component: RewardsView, meta: { roles: routeRoles.rewards } },
+ { path: '/risk', name: 'risk', component: RiskView, meta: { roles: routeRoles.risk } },
+ { path: '/audit', name: 'audit', component: AuditLogView, meta: { roles: routeRoles.audit } },
+ { path: '/approvals', name: 'approvals', component: ApprovalCenterView, meta: { roles: routeRoles.approvals } },
+ { path: '/permissions', name: 'permissions', component: PermissionsView, meta: { roles: routeRoles.permissions } },
+ { path: '/roles', name: 'role-management', component: RoleManagementView, meta: { roles: routeRoles['role-management'] } },
+ { path: '/departments', name: 'department-management', component: DepartmentManagementView, meta: { roles: routeRoles['department-management'] } },
+ { path: '/system', name: 'system-config', component: SystemConfigView, meta: { roles: routeRoles['system-config'] } },
+ { path: '/notifications', name: 'notifications', component: NotificationsView, meta: { roles: routeRoles.notifications } },
+ { path: '/403', name: 'forbidden', component: ForbiddenView }
]
})
diff --git a/frontend/admin/src/services/department.ts b/frontend/admin/src/services/department.ts
new file mode 100644
index 0000000..cae157c
--- /dev/null
+++ b/frontend/admin/src/services/department.ts
@@ -0,0 +1,87 @@
+/**
+ * 部门管理服务
+ */
+
+export interface Department {
+ id?: number
+ deptName: string
+ parentId?: number
+ deptCode?: string
+ leaderId?: number
+ sortOrder?: number
+ status: number
+ createdAt?: string
+}
+
+export interface ApiResponse {
+ code: number
+ data: T
+ message?: string
+}
+
+class DepartmentService {
+ private baseUrl = '/api'
+
+ async getDepartments(): Promise {
+ const response = await fetch(`${this.baseUrl}/departments`, {
+ credentials: 'include'
+ })
+ const result = await response.json() as ApiResponse
+ if (result.code !== 200) {
+ throw new Error(result.message || '获取部门列表失败')
+ }
+ return result.data
+ }
+
+ async getDepartmentById(id: number): Promise {
+ const response = await fetch(`${this.baseUrl}/departments/${id}`, {
+ credentials: 'include'
+ })
+ const result = await response.json() as ApiResponse
+ if (result.code !== 200) {
+ return null
+ }
+ return result.data
+ }
+
+ async createDepartment(data: Department): Promise {
+ const response = await fetch(`${this.baseUrl}/departments`, {
+ 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 updateDepartment(id: number, data: Department): Promise {
+ const response = await fetch(`${this.baseUrl}/departments/${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 deleteDepartment(id: number): Promise {
+ const response = await fetch(`${this.baseUrl}/departments/${id}`, {
+ method: 'DELETE',
+ credentials: 'include'
+ })
+ const result = await response.json() as ApiResponse
+ if (result.code !== 200) {
+ throw new Error(result.message || '删除部门失败')
+ }
+ }
+}
+
+export const departmentService = new DepartmentService()
+export default departmentService
diff --git a/frontend/admin/src/views/DepartmentManagementView.vue b/frontend/admin/src/views/DepartmentManagementView.vue
new file mode 100644
index 0000000..d9bc6d2
--- /dev/null
+++ b/frontend/admin/src/views/DepartmentManagementView.vue
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+ 加载中...
+
+
+ 暂无部门数据
+
+
+
+
+
+
+ {{ dept.deptName }}
+ {{ dept.deptCode }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ child.deptName }}
+ {{ child.deptCode }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ isEdit ? '编辑部门' : '新建部门' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/admin/src/views/SystemConfigView.vue b/frontend/admin/src/views/SystemConfigView.vue
new file mode 100644
index 0000000..8a1a891
--- /dev/null
+++ b/frontend/admin/src/views/SystemConfigView.vue
@@ -0,0 +1,197 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ config.label }}
+
{{ config.description }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | 名称 |
+ 密钥 |
+ 状态 |
+ 创建时间 |
+ 操作 |
+
+
+
+
+ | {{ key.name }} |
+ {{ showKeyId === key.id ? key.key : '••••••••••••••••' }} |
+
+
+ {{ key.status === 1 ? '启用' : '禁用' }}
+
+ |
+ {{ key.createdAt }} |
+
+
+
+ |
+
+
+
+
+ 暂无API密钥
+
+
+
+
+
+
diff --git a/src/main/java/com/mosquito/project/permission/ApprovalFlowService.java b/src/main/java/com/mosquito/project/permission/ApprovalFlowService.java
new file mode 100644
index 0000000..764948f
--- /dev/null
+++ b/src/main/java/com/mosquito/project/permission/ApprovalFlowService.java
@@ -0,0 +1,83 @@
+package com.mosquito.project.permission;
+
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 审批流服务
+ */
+@Service
+public class ApprovalFlowService {
+
+ // 审批状态常量
+ public static final String STATUS_PENDING = "pending";
+ public static final String STATUS_APPROVED = "approved";
+ public static final String STATUS_REJECTED = "rejected";
+ public static final String STATUS_PROCESSING = "processing";
+
+ // 审批动作
+ public static final String ACTION_SUBMIT = "submit";
+ public static final String ACTION_APPROVE = "approve";
+ public static final String ACTION_REJECT = "reject";
+ public static final String ACTION_TRANSFER = "transfer";
+
+ /**
+ * 提交审批申请
+ */
+ @Transactional
+ public Long submitApproval(Long flowId, String bizType, String bizId, String title,
+ Long applicantId, String applicantName, String applyReason) {
+ // 创建审批记录
+ Long recordId = recordId++; // TODO: 实际创建记录
+ return recordId;
+ }
+
+ /**
+ * 处理审批
+ */
+ @Transactional
+ public boolean handleApproval(Long recordId, String action, Long operatorId,
+ String operatorName, String comment) {
+ // 处理审批逻辑
+ return true;
+ }
+
+ /**
+ * 获取待审批列表
+ */
+ public List