# 系统架构与业务流程图 > 基于项目源码自动生成,所有图表均使用 Mermaid 语法,可在支持 Mermaid 的 Markdown 编辑器中渲染。 --- ## 一、系统整体架构 ### 1.1 分层架构总览 ```mermaid graph TB subgraph 用户层 Browser["浏览器
(Chrome / Edge)"] end subgraph 前端["前端 · Vue 3 + Vite"] Router["Vue Router
路由守卫 / 权限控制"] Views["页面组件
Dashboard / Resource / Project ..."] Store["Pinia Store
用户状态 / Token"] API["Axios API 层
request.js 统一拦截"] end subgraph 反向代理["Nginx 反向代理"] Static["静态资源托管
dist/"] Proxy["/api/ → :8080
API 反代"] end subgraph 后端["后端 · Spring Boot 3"] Controller["Controller 层
REST 接口"] Security["Spring Security
JWT 认证 + 权限"] Service["Service 层
核心业务逻辑"] Mapper["Mapper 层
MyBatis-Plus"] Task["定时任务
ResourceExpireTask"] Mail["邮件服务
EmailService"] end subgraph 数据层 MySQL["MySQL 8.0+
resource_platform"] SMTP["SMTP 邮件服务器"] end Browser -->|HTTP| 反向代理 反向代理 -->|静态文件| Static 反向代理 -->|/api/*| Controller Router --> Views Views --> Store Views --> API API -->|Bearer Token| Controller Controller --> Security Security --> Service Service --> Mapper Mapper --> MySQL Task --> Service Service --> Mail Mail --> SMTP ``` ### 1.2 后端内部分层 ```mermaid graph LR subgraph 接入层 A["AuthController"] RC["ResourceController"] PC["ProjectController"] DC["DashboardController"] UC["UserController"] RTC["ResourceTypeController"] PRC["ProviderController"] LC["OperationLogController"] end subgraph 安全层 JWT["JwtAuthenticationFilter"] SC["SecurityConfig
CORS / 权限规则"] SU["SecurityUtils"] end subgraph 业务层 RS["ResourceServiceImpl"] PS["ProjectServiceImpl"] US["SysUserServiceImpl"] RRS["ResourceRenewalServiceImpl"] DS["DashboardServiceImpl"] OLS["OperationLogServiceImpl"] ES["EmailServiceImpl"] end subgraph 数据层 RM["ResourceMapper"] PM["ProjectMapper"] UM["SysUserMapper"] RRM["ResourceRenewalMapper"] PRM["ProjectResourceMapper"] OLM["OperationLogMapper"] ENLM["ExpireNotifyLogMapper"] end A --> US RC --> RS RC --> RRS PC --> PS DC --> DS UC --> US RTC --> RS PRC --> RS LC --> OLS RS --> RM RS --> PRM PS --> PM PS --> PRM US --> UM RRS --> RRM RRS --> RM DS --> RM DS --> PM OLS --> OLM RS --> OLS ES --> SMTP["SMTP"] JWT --> SC ``` --- ## 二、数据模型关系图 ### 2.1 ER 图 ```mermaid erDiagram sys_user ||--o{ resource : "负责" sys_user ||--o{ project : "负责" sys_user ||--o{ operation_log : "操作" project ||--o{ project : "父子(两层)" project ||--o{ project_resource : "关联" resource ||--o{ project_resource : "关联" resource ||--o{ resource_renewal : "续费" resource ||--o{ expire_notify_log : "提醒" resource }o--|| resource_type : "类型" resource }o--|| provider : "服务商" sys_user { int id PK varchar username varchar password varchar real_name varchar email int role "1=管理员 2=普通" int status "0=禁用 1=启用" } resource { int id PK varchar name int type_id FK int provider_id FK int owner_id FK date start_date date expire_date decimal cost int cost_cycle "1=月 2=年 3=一次性" int status "0停用 1使用中 2即将到期 3已过期" int purchase_duration varchar account_info varchar remark } project { int id PK varchar name int parent_id FK "NULL=顶层" int owner_id FK int status "0=下线 1=进行中" varchar remark } project_resource { int id PK int project_id FK int resource_id FK decimal allocation_percent "分摊占比" } resource_type { int id PK varchar name int sort varchar remark } provider { int id PK varchar name varchar remark } resource_renewal { int id PK int resource_id FK date old_expire_date date new_expire_date int duration_code decimal cost varchar remark int operator_id FK } expire_notify_log { int id PK int resource_id FK varchar stage "far/near/expired" date notify_date varchar send_to } operation_log { int id PK int user_id FK varchar module varchar operation varchar detail } ``` ### 2.2 核心关联关系说明 | 关系 | 类型 | 说明 | |------|------|------| | resource ↔ resource_type | 多对一 | 每个资源属于一个类型 | | resource ↔ provider | 多对一 | 每个资源属于一个服务商 | | resource ↔ sys_user (owner) | 多对一 | 每个资源有一个负责人 | | resource ↔ project | 多对多 | 通过 project_resource 关联,支持费用分摊 | | project_resource.allocation_percent | 分摊占比 | 同一资源在不同项目间按比例分摊费用 | | project ↔ project (parent) | 自关联 | 两层结构:顶层项目 + 子项目 | | resource ↔ resource_renewal | 一对多 | 一个资源可有多条续费记录 | | resource ↔ expire_notify_log | 一对多 | 三阶段提醒记录(far/near/expired) | --- ## 三、核心业务流程图 ### 3.1 用户认证流程 ```mermaid sequenceDiagram participant U as 浏览器 participant F as 前端 (Vue) participant S as 后端 (Spring Boot) participant DB as MySQL U->>F: 输入用户名/密码 F->>S: POST /auth/login {username, password} S->>DB: 查询用户信息 DB-->>S: sys_user 记录 alt 账号不存在 / 已禁用 S-->>F: {code: 401, message: "账号不存在或已禁用"} end alt 连续失败 ≥ 5 次(15 分钟内) S-->>F: {code: 401, message: "账号已锁定,请 15 分钟后重试"} end alt 密码错误 S->>DB: 记录失败次数 S-->>F: {code: 401, message: "密码错误"} end alt 认证成功 S->>S: 生成 JWT Token (HS256, 24h) S->>DB: 清除失败计数 S-->>F: {code: 200, data: {token, userId, username, role}} F->>F: 存储 token 到 localStorage F->>F: Pinia store 更新用户状态 F-->>U: 跳转至 Dashboard end Note over U,DB: 后续请求 U->>F: 操作页面 F->>S: 请求头 Authorization: Bearer S->>S: JwtAuthenticationFilter 校验 Token alt Token 有效 S->>S: 设置 SecurityContext S-->>F: 返回业务数据 else Token 过期/无效 S-->>F: 401 Unauthorized F->>F: 清除 token,跳转登录页 end ``` ### 3.2 权限控制模型 ```mermaid graph TD Login["用户登录"] --> JWT["获取 JWT Token"] JWT --> Filter["JwtAuthenticationFilter"] Filter -->|每次请求| Check{"Token 有效?"} Check -->|否| Reject["401 → 跳转登录"] Check -->|是| Load["加载 LoginUser
(role, status)"] Load --> SecConfig["SecurityConfig 规则匹配"] SecConfig --> R1["/auth/login → 公开"] SecConfig --> R2["/user/enabled-list → 登录即可"] SecConfig --> R3["/user/** → ROLE_ADMIN"] SecConfig --> R4["POST/DELETE /resource-type/** → ROLE_ADMIN"] SecConfig --> R5["POST/DELETE /provider/** → ROLE_ADMIN"] SecConfig --> R6["其他接口 → 登录即可"] R1 --> Pass["放行"] R2 --> Pass R3 --> Admin{"isAdmin?"} R4 --> Admin R5 --> Admin R6 --> Pass Admin -->|是| Pass Admin -->|否| Deny["403 Forbidden"] ``` ### 3.3 资源生命周期 ```mermaid stateDiagram-v2 [*] --> 使用中: 创建资源
(expire_date > 今天) [*] --> 已过期: 创建资源
(expire_date ≤ 今天) 使用中 --> 即将到期: 定时任务扫描
(距到期 ≤ 30 天) 即将到期 --> 即将到期: 定时任务扫描
(距到期 ≤ 7 天) 即将到期 --> 已过期: 超过到期日 使用中 --> 已过期: 超过到期日 已过期 --> 使用中: 续费
(新到期日 > 今天) 已过期 --> 即将到期: 续费
(新到期日在 30 天内) 使用中 --> 已停用: 手动停用 即将到期 --> 已停用: 手动停用 已停用 --> 使用中: 重新启用
(更新到期日) 使用中 --> [*]: 删除资源 即将到期 --> [*]: 删除资源 已过期 --> [*]: 删除资源 已停用 --> [*]: 删除资源 ``` ### 3.4 资源续费流程 ```mermaid sequenceDiagram participant U as 用户 participant F as 前端 participant C as ResourceController participant RRS as ResourceRenewalService participant RS as ResourceService participant DB as MySQL U->>F: 点击"续费",填写续费表单 Note over U,F: 续费日期、新到期日、时长、金额、备注 F->>C: POST /resource/{id}/renew C->>RRS: renewResource(id, dto) RRS->>DB: 查询当前资源信息 DB-->>RRS: Resource 记录 RRS->>RRS: 校验:新到期日 > 当前到期日 alt 校验失败 RRS-->>C: 抛出 BusinessException C-->>F: {code: 400, message: "新到期日必须晚于当前到期日"} end RRS->>DB: INSERT resource_renewal RRS->>DB: UPDATE resource.expire_date = 新到期日 RRS->>RS: 刷新资源状态 RS->>DB: 根据新到期日计算 status Note over RS,DB: 使用中 / 即将到期 RRS-->>C: 续费成功 C->>C: 记录操作日志 C-->>F: {code: 200} F->>F: 刷新详情页 + 续费历史列表 ``` ### 3.5 到期提醒定时任务 ```mermaid flowchart TD Start["定时触发
每天 08:00
cron: 0 0 8 * * ?"] --> Refresh["刷新所有资源状态
refreshExpireStatus()"] Refresh --> Scan["扫描需要提醒的资源"] Scan --> Check30{"距到期 ≤ 30 天
且 > 7 天?"} Scan --> Check7{"距到期 ≤ 7 天
且 > 0 天?"} Scan --> CheckExpired{"已过期
expire_date < 今天?"} Check30 -->|是| Log30{"已发过 far 提醒?"} Check30 -->|否| Skip1["跳过"] Check7 -->|是| Log7{"已发过 near 提醒?"} Check7 -->|否| Skip2["跳过"] CheckExpired -->|是| LogExp{"已发过 expired 提醒?"} CheckExpired -->|否| Skip3["跳过"] Log30 -->|未发| Send30["发送邮件
stage=far
普通提醒"] Log30 -->|已发| Skip1 Log7 -->|未发| Send7["发送邮件
stage=near
紧急提醒"] Log7 -->|已发| Skip2 LogExp -->|未发| SendExp["发送邮件
stage=expired
过期通知"] LogExp -->|已发| Skip3 Send30 --> Record30["INSERT expire_notify_log
stage=far"] Send7 --> Record7["INSERT expire_notify_log
stage=near"] SendExp --> RecordExp["INSERT expire_notify_log
stage=expired"] Record30 --> End["完成"] Record7 --> End RecordExp --> End Skip1 --> End Skip2 --> End Skip3 --> End ``` ### 3.6 费用分摊计算流程 ```mermaid flowchart TD Start["资源关联多个项目"] --> Input["用户选择关联项目"] Input --> Mode{"分摊模式"} Mode -->|均分| Calc1["每个项目 = 100% / N
尾差加到最后一个"] Mode -->|自定义| Calc2["用户手动输入各占比
合计必须 = 100%"] Calc1 --> Save["保存到 project_resource
allocation_percent"] Calc2 --> Validate{"合计 = 100%?"} Validate -->|否| Error["提示:分摊占比合计必须为 100%"] Validate -->|是| Save Save --> Stat["费用统计时"] Stat --> Formula["分摊费用 = 资源总费用 ×
allocation_percent / 100"] Formula --> Report["生成费用报表
按项目 / 按类型"] ``` --- ## 四、项目管理流程 ### 4.1 项目树形结构 ```mermaid graph TD subgraph 两层项目模型 P1["顶层项目 A"] P1 --> C1["子项目 A-1"] P1 --> C2["子项目 A-2"] P2["顶层项目 B"] P2 --> C3["子项目 B-1"] P3["顶层项目 C
(无子项目)"] end C1 --> R1["资源 1"] C1 --> R2["资源 2"] C2 --> R3["资源 3"] C3 --> R4["资源 4"] P3 --> R5["资源 5"] style P1 fill:#409eff,color:#fff style P2 fill:#409eff,color:#fff style P3 fill:#409eff,color:#fff style C1 fill:#67c23a,color:#fff style C2 fill:#67c23a,color:#fff style C3 fill:#67c23a,color:#fff ``` > **规则**:资源只挂在叶子节点(子项目或无子项目的顶层项目)。父项目的资源统计 = 所有子项目资源的聚合。 ### 4.2 项目新增/编辑流程 ```mermaid flowchart TD Start["用户点击新增/编辑"] --> Form["弹窗表单"] Form --> Fields["名称 / 父项目 / 负责人 / 状态 / 备注"] Fields --> Submit["提交"] Submit --> Check{"有父项目?"} Check -->|是| Leaf["标记为子项目
parent_id = 选中值"] Check -->|否| Root["标记为顶层项目
parent_id = NULL"] Leaf --> Save["保存到 project 表"] Root --> Save Save --> Edit{"编辑模式?"} Edit -->|是| Update["UPDATE + 保留子项目关系"] Edit -->|否| Insert["INSERT"] Update --> Done["刷新列表"] Insert --> Done ``` --- ## 五、前端页面结构 ### 5.1 页面导航树 ```mermaid graph TD App["App.vue"] --> Login["/login
Login.vue"] App --> Layout["Layout.vue
侧边栏 + 顶栏"] Layout --> Dashboard["/dashboard
工作台"] Layout --> Resource["/resource
资源台账"] Layout --> ResourceDetail["/resource/:id
资源详情"] Layout --> Project["/project
项目管理"] Layout --> ProjectDetail["/project/:id
项目详情"] Layout --> CostStat["/cost-stat
费用统计"] Layout --> ProcurementCost["/procurement-cost
采购费用"] Layout --> Dict["/dict
字典管理"] Layout --> User["/user
用户管理 🔒"] Layout --> Log["/log
操作日志"] Dashboard --> KPI["6 个 KPI 卡片"] Dashboard --> Chart1["项目状态环形图"] Dashboard --> Chart2["资源类型分布条形图"] Dashboard --> Table["风险清单表格"] CostStat --> Chart3["资源类型费用环形图"] CostStat --> Chart4["项目预算消耗排行"] CostStat --> Chart5["各类型费用条形图"] CostStat --> Chart6["项目资源数对比"] Dict --> Tab1["资源类型 Tab"] Dict --> Tab2["服务商 Tab"] style User fill:#e6a23c,color:#fff ``` ### 5.2 前端组件依赖 ```mermaid graph LR subgraph 页面组件 RL["ResourceList"] RF["ResourceForm"] RD["ResourceDetail"] PL["ProjectList"] PD["ProjectDetail"] DSH["Dashboard"] CS["CostStat"] PC["ProcurementCost"] end subgraph 组合式函数 UC["useChart()
ECharts 封装"] USR["useScrollRestore()
滚动恢复"] end subgraph 工具 CSV["exportCsv()"] CC["getChartColors()"] SC["statusClass()"] end subgraph API RA["api/resource"] PA["api/project"] DA["api/dashboard"] end subgraph Store ST["store/user"] end RL --> RF RL --> RA RL --> SC RD --> RA PL --> PA PD --> PA DSH --> DA DSH --> UC DSH --> CSV CS --> RA CS --> UC CS --> CSV PC --> RA PC --> CSV UC --> CC RL --> USR ``` --- ## 六、部署架构 ### 6.1 生产部署拓扑 ```mermaid graph TB subgraph 客户端 Browser2["浏览器"] end subgraph Nginx["Nginx (resource.mizentech.com:80)"] Frontend["前端静态资源
/opt/resource-platform/frontend/dist/"] APIProxy["/api/ 反代
→ 127.0.0.1:8080"] end subgraph Backend["Spring Boot (127.0.0.1:8080)"] App["resource-platform.jar
--spring.profiles.active=prod"] end subgraph Data["数据层"] RDS["MySQL 8.0+
resource_platform"] Mail2["SMTP 邮件服务器
smtp.qiye.aliyun.com:465"] end subgraph 配置 Env[".env (chmod 600)
DB_URL / JWT_SECRET
MAIL_* / CORS_ORIGINS"] Systemd["systemd 服务
自动重启 / 开机自启"] end Browser2 -->|HTTP| Nginx Nginx -->|/| Frontend Nginx -->|/api/*| APIProxy APIProxy --> App App --> RDS App --> Mail2 Env --> App Systemd --> App ``` ### 6.2 环境配置对比 ```mermaid graph LR subgraph 开发环境 Dev["application-dev.yml"] DevDB["阿里云 RDS
明文密码"] DevMail["smtp.example.com
占位配置"] DevLog["日志级别: DEBUG"] DevCORS["CORS: localhost:5173"] end subgraph 生产环境 Prod["application-prod.yml"] ProdDB["环境变量注入
DB_URL / DB_PASSWORD"] ProdMail["smtp.qiye.aliyun.com
企业邮箱"] ProdLog["日志级别: INFO"] ProdCORS["CORS: resource.mizentech.com"] end Dev --> DevDB Dev --> DevMail Dev --> DevLog Dev --> DevCORS Prod --> ProdDB Prod --> ProdMail Prod --> ProdLog Prod --> ProdCORS ``` --- ## 七、API 接口全景 ### 7.1 接口分组总览 ```mermaid graph TD subgraph 认证模块 A1["POST /auth/login"] A2["GET /auth/me"] A3["PUT /auth/password"] end subgraph 资源管理 R1["GET /resource/page"] R2["GET /resource/{id}"] R3["POST /resource"] R4["DELETE /resource/{id}"] R5["POST /resource/relate"] R6["DELETE /resource/unrelate"] R7["POST /resource/{id}/renew"] R8["GET /resource/{id}/renewals"] R9["DELETE /resource/{id}/renewals/{rid}"] R10["GET /resource/export"] end subgraph 费用统计 C1["GET /resource/cost-stat/project"] C2["GET /resource/cost-stat/type"] C3["GET /resource/procurement-cost"] C4["GET /resource/procurement-cost/export"] end subgraph 项目管理 P1["GET /project/page"] P2["GET /project/tree"] P3["GET /project/{id}"] P4["POST /project"] P5["DELETE /project/{id}"] P6["GET /project/active-list"] P7["GET /project/parent-options"] end subgraph 工作台 D1["GET /dashboard"] end subgraph 系统管理 🔒 U1["GET /user/list"] U2["GET /user/enabled-list"] U3["POST /user"] U4["DELETE /user/{id}"] T1["GET /resource-type/list"] T2["POST /resource-type"] T3["DELETE /resource-type/{id}"] V1["GET /provider/list"] V2["POST /provider"] V3["DELETE /provider/{id}"] L1["GET /operation-log/page"] end ``` --- ## 八、技术栈依赖关系 ```mermaid graph TD subgraph 前端依赖 Vue["Vue 3.4"] --> VRouter["Vue Router 4.3"] Vue --> Pinia["Pinia 2.1"] Vue --> EP["Element Plus 2.6"] Vue --> ECharts["ECharts 6.1"] Vue --> Axios["Axios 1.6"] Vue --> DayJS["Day.js 1.11"] end subgraph 后端依赖 SB["Spring Boot 3.2.5"] --> SS["Spring Security 6.2"] SB --> MBP["MyBatis-Plus 3.5.5"] SB --> SM["Spring Mail"] SB --> SV["Spring Validation"] SS --> JWT["JJWT 0.11.5"] MBP --> MySQL["MySQL Connector 8.3"] SB --> EE["EasyExcel 3.3.2"] SB --> Lombok["Lombok 1.18.32"] end subgraph 构建工具 Vite["Vite 5.1"] Maven["Maven"] Vitest["Vitest 4.1"] JUnit["JUnit 5 + Mockito"] end ```