commit 9cbb1f7695c29cfde99a71175d9ccb277128030c Author: figmar Date: Sun Aug 9 13:04:04 2026 +0800 init: apes-Authon-history — 剥离历史与源码分析归档 - docs/: 源码分析报告、代码深度解析、项目说明书、独立服务化方案 - backend/: 账权模块提取说明(提取原则、文件清单、耦合度验证) - frontend/: 前端剥离方案、剥离历史与说明、框架修改详情 diff --git a/README.md b/README.md new file mode 100644 index 0000000..19f962d --- /dev/null +++ b/README.md @@ -0,0 +1,133 @@ +# apes-Authon-history — 剥离历史与源码分析归档 + +> 本仓库归档了 apes-Authon 账权独立服务平台从单体应用中剥离的完整过程、分析报告和方案文档。 +> 供源码更新时参考,持续优化前后端代码和文档。 + +## 仓库定位 + +| 仓库 | 说明 | 地址 | +|------|------|------| +| apes-Authon-Server | 后端账权服务 | https://gitea.apescale.com/apes-Authon/apes-Authon-Server | +| apes-Authon-Web | 前端账权管理 | https://gitea.apescale.com/apes-Authon/apes-Authon-Web | +| **apes-Authon-history** | **本仓库 — 剥离历史与分析归档** | https://gitea.apescale.com/apes-Authon/apes-Authon-history | + +## 目录结构 + +``` +apes-Authon-history/ +├── README.md # 本文件 +├── docs/ # 源码分析与方案文档 +│ ├── saas-service深度分析报告.md # 后端单体应用深度分析(33000 字) +│ ├── 代码深度解析与分析过程.md # 代码解析过程记录(27000 字) +│ ├── 账权平台-项目说明书.html # 原项目完整说明书(HTML) +│ └── 账权模块独立服务化方案.html # 独立服务化可行性分析与方案(HTML) +├── backend/ # 后端剥离文档 +│ └── 账权模块提取说明.md # 提取原则、文件清单、耦合度验证、路线图 +└── frontend/ # 前端剥离文档 + ├── apes-Authon-Web-剥离方案.md # 剥离方案(计划文档) + ├── apes-Authon-Web-剥离方案.html # 剥离方案(HTML 版) + └── 剥离历史与说明.md # 剥离执行记录、变更明细、框架修改说明 +``` + +## 文档索引 + +### 源码分析 + +| 文档 | 内容概述 | +|------|---------| +| [saas-service深度分析报告](docs/saas-service深度分析报告.md) | 后端单体应用的完整深度分析:项目结构、技术栈、核心模块(认证/授权/多租户/SSO/数据同步/LLM)、数据库设计、API 清单、配置体系 | +| [代码深度解析与分析过程](docs/代码深度解析与分析过程.md) | 代码解析过程记录:AuthContext 工作机制、@Login AOP 切面、多租户数据源切换、伙伴云 SSO 集成、LLM Agent 架构 | +| [账权平台-项目说明书](docs/账权平台-项目说明书.html) | 原项目说明书(HTML 格式):功能模块、技术架构、部署方式、数据库 ER 图 | +| [账权模块独立服务化方案](docs/账权模块独立服务化方案.html) | 独立服务化可行性分析:耦合度评估、剥离策略、技术路线、风险评估 | + +### 后端剥离 + +| 文档 | 内容概述 | +|------|---------| +| [账权模块提取说明](backend/账权模块提取说明.md) | 提取原则(纯账权/零业务/保留包名/保留依赖)、124 个文件清单(11 Controller + 23 Entity + 7 Service + 23 Mapper)、外部依赖分析、耦合度验证结论、后续路线图 | + +### 前端剥离 + +| 文档 | 内容概述 | +|------|---------| +| [apes-Authon-Web-剥离方案](frontend/apes-Authon-Web-剥离方案.md) | 剥离前的计划文档:保留/删除/修改清单、页面耦合度分析、框架文件修改方案 | +| [apes-Authon-Web-剥离方案](frontend/apes-Authon-Web-剥离方案.html) | 同上(HTML 格式) | +| [剥离历史与说明](frontend/剥离历史与说明.md) | 剥离执行记录:176 文件变更(+222/-60093)、11 个框架文件修改详情、业务引用清理表、构建验证结果 | + +## 剥离概述 + +### 后端 (apes-Authon-Server) + +从 `saas-service` 单体应用中提取纯净账权模块,经过 4 个阶段完成: + +| 阶段 | 目标 | 关键工作 | +|------|------|---------| +| Phase 1 | apes-commons 内联 | 反推 8 个核心类(AuthContext / @Login / LoginAspect / Res / DbEntity 等),移除外部 JAR 依赖 | +| Phase 2 | 包名重构 | `cn.apes.cloud` → `cn.apes.authon` 全局包名重构,零残留 | +| Phase 3 | 编译验证 | 124 个源文件编译通过,Lombok 1.18.40 + compiler-plugin 3.13.0 兼容 Java 24 | +| Phase 4 | 提交推送 | 最终版本推送到 Gitea | + +**提取结果**:11 Controller + 23 Entity + 12 DTO + 3 VO + 7 Service + 18 ServiceImpl + 23 Mapper + 5 Config + 1 Filter + 2 Util + 8 commons 内联 = 124 个 Java 文件 + +**耦合度验证**: +- 业务 Service → 账权 Service 直接调用:**0 个** +- 业务 Controller → 账权 Controller 直接调用:**0 个** +- 账权 Service → 业务 Mapper 直接调用:**0 个** +- 唯一交叉引用:`CustomerInfoServiceImpl` → huoban DTO 包(11 个纯 DTO,无业务逻辑) + +### 前端 (apes-Authon-Web) + +从 `saas-web` 单体前端中剥离纯净账权页面: + +| 指标 | 数值 | +|------|------| +| 保留页面 | 40 个(24 账权 + 9 系统配置 + 7 AI 工具) | +| 删除页面 | ~82 个业务页面 | +| 代码变更 | +222 / -60093(净减约 6 万行) | +| 修改框架文件 | 11 个 | +| 构建状态 | 通过(`npm run build:prod`) | + +## 如何使用本仓库 + +### 场景 1:源码更新后同步优化 + +当源码(单体应用)有更新时,按以下流程操作: + +1. **分析变更**:对比源码最新版本与本仓库归档的分析文档,识别新增/修改的账权相关代码 +2. **评估影响**:参照 [账权模块提取说明](backend/账权模块提取说明.md) 中的提取原则和文件清单,判断变更是否属于账权范畴 +3. **同步代码**:将确认的变更同步到 [apes-Authon-Server](https://gitea.apescale.com/apes-Authon/apes-Authon-Server) 或 [apes-Authon-Web](https://gitea.apescale.com/apes-Authon/apes-Authon-Web) +4. **更新文档**:如有结构性变更,更新本仓库的分析文档 + +### 场景 2:理解架构设计 + +新开发者可通过以下顺序阅读文档快速理解系统: + +1. [账权平台-项目说明书](docs/账权平台-项目说明书.html) — 了解原项目全貌 +2. [saas-service深度分析报告](docs/saas-service深度分析报告.md) — 理解后端架构 +3. [账权模块独立服务化方案](docs/账权模块独立服务化方案.html) — 理解为什么要剥离 +4. [账权模块提取说明](backend/账权模块提取说明.md) — 理解后端怎么剥离的 +5. [前端剥离方案](frontend/apes-Authon-Web-剥离方案.md) — 理解前端怎么剥离的 +6. [剥离历史与说明](frontend/剥离历史与说明.md) — 理解前端具体改了什么 + +### 场景 3:扩展新模块 + +参照 [代码深度解析与分析过程](docs/代码深度解析与分析过程.md) 中的架构说明,理解以下核心机制后再进行扩展: + +- **AuthContext + @Login AOP**:认证上下文的传递机制 +- **@TenantSource 动态数据源**:多租户数据源切换 +- **SSO 集成**:伙伴云单点登录的 Token 交换流程 +- **动态路由**:前端菜单 → 路由 → 组件的映射机制 + +## 后续路线图 + +| 阶段 | 目标 | 状态 | +|------|------|------| +| Phase 5A | AI 助手/LLM 模块后端提取(~54 Java 文件) | 待办 | +| Phase 5B | 系统配置页面补充 | 基本完成 | +| Phase 5C | 伙伴云表单配置模块提取 | 待办 | +| Phase 6 | SDK 化 — AuthContext 转为远程可调用 SDK | 待设计 | +| Phase 7 | 网关集成 — API 网关注入请求头替代 ThreadLocal | 待设计 | + +## License + +MIT diff --git a/backend/账权模块提取说明.md b/backend/账权模块提取说明.md new file mode 100644 index 0000000..26ec8a8 --- /dev/null +++ b/backend/账权模块提取说明.md @@ -0,0 +1,144 @@ +# 账权模块提取说明 + +> 提取日期:2026-08-09 +> 源仓库:apes-Authdata (saas-service) +> 目标仓库:apes-Authon + +## 一、提取原则 + +1. **纯账权逻辑**:只提取认证、授权、用户、角色、菜单、权限、多租户、套餐、配额、SSO、操作日志相关的代码 +2. **零业务代码**:不包含溯源(Trace*)、称重(Weight*)、水肥(Fei*)、巡检(Inspection*)、维修(Repair*)、农大同步(Nongda*)、LLM Agent 等任何业务逻辑 +3. **保留包名**:暂保留 `cn.apes.cloud` 包名以最小化改动,后续 Phase 2 再统一重构为 `cn.apes.authon` +4. **保留依赖**:`apes-commons` 外部 JAR 作为核心依赖保留,提供 AuthContext / @Login / Res / DbEntity 等基础设施 + +## 二、提取文件清单 + +### Controller(11 个) + +| 文件 | 核心功能 | +|------|---------| +| UserController | 密码登录、注册、改密、用户CRUD、企业认证、多企业切换 | +| PermissionController | 菜单树、权限码、角色CRUD、角色权限分配、成员角色管理 | +| AccessTokenController | 外部 API Token 的创建/查询/撤销/启用/重新生成 | +| CustomerController | 客户/企业CRUD、员工管理、应用关联、SSO配置 | +| CustomerPackageController | 客户套餐管理、配额管理、延期申请 | +| AppController | 应用CRUD、应用详情(含菜单+权限+关联客户) | +| SysOrganizationController | 组织架构CRUD、组织树 | +| SysPackagePlanController | 套餐方案CRUD、套餐权限分配 | +| SysQuotaController | 配额模板CRUD | +| SysOperationLogController | 操作日志查询 | +| UserPreferenceController | 用户偏好(UI尺寸)查询/更新 | + +### Entity(23 个) + +UserInfo, SysRole, SysMenu, SysPermission, SysRolePermission, SysMemberRole, SysAccessToken, CustomerInfo, CustomerUser, CustomerApp, CustomerPackage, CustomerPackageQuota, CustomerPackageExtendApply, CustomerQuotaChangeLog, SsoConfig, SysOrganization, SysPackagePlan, SysPackagePlanPermission, SysPackagePlanQuota, SysQuota, UserPreference, SysOperationLog, AppInfo + +### Service 接口(6 个) + +CustomerPackageService, SysAccessTokenService, SysOperationLogService, SysPackagePlanQuotaService, SysPackagePlanService, SysQuotaService + +### Service 实现(16 个) + +PermissionServiceImpl, UserInfoServiceImpl, SysAccessTokenServiceImpl, SsoServiceImpl, Sso2ServiceImpl, CustomerUserServiceImpl, CustomerInfoServiceImpl, CustomerAppServiceImpl, SysOrganizationServiceImpl, SysPackagePlanServiceImpl, CustomerPackageServiceImpl, SysQuotaServiceImpl, SysPackagePlanQuotaServiceImpl, UserPreferenceServiceImpl, SysOperationLogServiceImpl, AppInfoServiceImpl + +### Mapper(23 个) + +对应每个 Entity 各一个 Mapper。 + +### Config(5 个) + +| 文件 | 说明 | +|------|------| +| AccessTokenFilterConfig | 注册 AccessTokenFilter(order=1,拦截 /*) | +| DataSourceHeaderAspect | @TenantSource AOP 切面,多租户数据源切换 | +| TenantSource | @TenantSource 注解定义 | +| HbTokenContext | 伙伴云 Token 的 ThreadLocal 上下文 | +| SiteConfig | 站点配置(支付域名、Cookie域名) | + +### Filter(1 个) + +AccessTokenFilter — 外部 API 鉴权(X-Access-Token / Bearer) + +### Util(2 个) + +| 文件 | 说明 | +|------|------| +| OperationLogUtil | 操作日志工具(@PostConstruct 抓 bean + AuthContext 获取操作人) | +| RsaUtil | RSA 加解密(密码加密/解密) | + +### DTO/VO(15 个) + +LoginDTO, RegisterDTO, PwdDTO, UserSearchDTO, RoleSearchDTO, SysRoleDTO, CustomerSearchDTO, EnterpriseCertifyDTO, SelectCustomerDTO, PageDTO, RelationDTO, AppSearchDTO, CustomerPackageVO, CustomerPackageExtendApplyVO, CustomerAppVO + +### Huoban DTO(11 个) + +UpsertOne, DataCreate, DataUpdate, DataFilter, DataFilterCondition, DataUpsert, BulkDel, TableSub, TableColumn, TableInfo, CategoryConfig — 伙伴云 API 请求/响应模型,被 CustomerInfoServiceImpl 用于同步客户数据到伙伴云 + +## 三、未提取的文件(排除原因) + +| 文件 | 排除原因 | +|------|---------| +| CustomerUiConfigServiceImpl | 依赖 `cn.apes.cloud.domain.weight.CustomerUiConfig`(weight 业务包) | +| CommonController | 混合业务(文件上传等),非纯账权 | +| WeightController | 称重业务 | +| TrackingConfigController | 追踪配置业务 | +| 所有 Trace*/Weight*/Fei*/Llm*/Nongda* 文件 | 业务模块 | +| RedissonConfiguration | 通用配置,需按实际部署环境重新配置 | +| MybatisPlusConfig | 通用配置,需按实际部署环境重新配置 | +| OssConfiguration | OSS 配置,账权服务不需要 | +| WebSocketConfig | WebSocket 配置,账权服务不需要 | +| RestTemplateConfiguration | HTTP 客户端配置,按需添加 | +| SchedulingConfig | 定时任务配置,按需添加 | +| JacksonAutoConfiguration | Jackson 配置,Spring Boot 自动配置 | + +## 四、外部依赖分析 + +### apes-commons 0.0.7-SNAPSHOT + +提供以下核心类(全部为接口级别依赖,无源码): + +``` +cn.apes.commons.Res → 统一 API 响应包装 +cn.apes.commons.auth.AuthContext → ThreadLocal 认证上下文 +cn.apes.commons.auth.Login → @Login 注解(方法级,AOP 自动注入) +cn.apes.commons.auth.LoginUser → 登录用户信息 +cn.apes.commons.auth.LoginCustomer → 登录客户/企业信息 +cn.apes.commons.auth.UserSession → 会话对象(user + customer) +cn.apes.commons.domain.DbEntity → 基础实体(id/createTime/updateTime/isDel) +``` + +### 第三方依赖 + +| 依赖 | 用途 | +|------|------| +| spring-boot-starter-web | REST API | +| spring-boot-starter-aop | @TenantSource 切面 / @Login AOP | +| spring-boot-starter-data-redis | Redis 会话管理 | +| mybatis-plus-boot-starter | ORM | +| dynamic-datasource-spring-boot-starter | 多租户数据源 | +| mysql-connector-java | MySQL 驱动 | +| lombok | 简化代码 | +| hutool-all | 通用工具(HMAC 签名、HTTP 调用等) | +| redisson | Redis 客户端 | +| fastjson | JSON 序列化 | + +## 五、耦合度验证 + +提取过程中验证了以下耦合点: + +1. **业务 Service → 账权 Service 直接调用:0 个** ✅ +2. **业务 Controller → 账权 Controller 直接调用:0 个** ✅ +3. **账权 Service → 业务 Mapper 直接调用:0 个** ✅ +4. **唯一的业务包交叉引用**:`CustomerInfoServiceImpl` → `cn.apes.cloud.domain.huoban.UpsertOne` + - 解决方案:将 huoban DTO 包一起提取(11 个纯 DTO 文件,无业务逻辑) +5. **外部 JAR 依赖**:`apes-commons` 提供 AuthContext 等核心类 + - 解决方案:保留为 Maven 依赖,后续 Phase 3 改造为 SDK + +## 六、后续路线图 + +| 阶段 | 目标 | 状态 | +|------|------|------| +| Phase 1 | 验证编译通过 | 待执行 | +| Phase 2 | 包名重构 cn.apes.cloud → cn.apes.authon | 待启动 | +| Phase 3 | SDK 化(AuthContext → 远程调用) | 待设计 | +| Phase 4 | 网关集成(ThreadLocal → HTTP Header) | 待设计 | diff --git a/docs/saas-service深度分析报告.md b/docs/saas-service深度分析报告.md new file mode 100644 index 0000000..29db5f4 --- /dev/null +++ b/docs/saas-service深度分析报告.md @@ -0,0 +1,627 @@ +# saas-service 项目源代码深度分析报告 + +## 一、项目基本信息 + +| 项目属性 | 值 | +|---------|---| +| GroupId | `cn.apes` | +| ArtifactId | `saas-service` | +| 版本 | `1.0.0-SNAPSHOT` | +| 描述 | 账权用户服务 | +| Java 版本 | 11 | +| Spring Boot 版本 | 2.2.1.RELEASE | +| MyBatis Plus 版本 | 3.5.7 | +| 动态数据源版本 | dynamic-datasource-spring-boot-starter 3.6.1 | +| Redisson 版本 | 3.35.0 | +| 主启动类 | `cn.apes.CloudApplication` | +| 项目路径 | `/tmp/project-analysis/service-master` | + +### 主启动类代码 + +**文件路径**: `src/main/java/cn/apes/CloudApplication.java` + +```java +@EnableAsync +@SpringBootApplication +@EnableScheduling +public class CloudApplication { + public static void main(String[] args) { + SpringApplication.run(CloudApplication.class, args); + } +} +``` + +启动类启用了三个关键注解:`@EnableAsync`(异步任务)、`@SpringBootApplication`(Spring Boot 自动配置)、`@EnableScheduling`(定时任务)。 + +--- + +## 二、完整包结构 + +项目根包为 `cn.apes.cloud`,目录结构如下: + +``` +cn.apes.cloud + |-- config/ # 配置类(12个文件) + |-- controller/ # REST 控制器(62个文件) + | |-- traceability/ # 溯源模块控制器(9个文件) + |-- domain/ # 数据模型层 + | |-- entity/ # 核心实体类(43个文件) + | |-- dto/ # 数据传输对象(约35个文件) + | |-- vo/ # 视图对象(5个文件) + | |-- huoban/ # 伙伴云数据模型(11个文件) + | |-- traceability/ # 溯源数据模型(22个文件) + | |-- weight/ # 称重数据模型(13个文件) + |-- filter/ # 过滤器(1个文件) + |-- groovy/ # Groovy 脚本执行引擎(3个文件) + |-- mapper/ # MyBatis Mapper 接口(约85个文件) + | |-- traceability/ # 溯源 Mapper(20个文件) + |-- service/ # 业务逻辑层 + | |-- impl/ # 服务实现类(约90个文件) + | | |-- huoban/ # 伙伴云服务实现(6个文件) + |-- task/ # 定时任务(1个文件) + |-- util/ # 工具类(2个文件) + |-- websocket/ # WebSocket 处理器(1个文件) +``` + +--- + +## 三、主要模块和功能划分 + +项目是一个大型 SaaS 多租户后端服务,包含以下核心业务模块: + +### 1. 用户与企业认证模块 + +- 用户注册/登录(密码登录、微信小程序登录) +- 企业认证(提交/审核/重新提交) +- 多企业切换 +- SSO 单点登录配置 +- AccessToken 外部 API 鉴权 + +### 2. 权限管理模块 + +- 菜单管理(多应用菜单树) +- 权限管理(按应用分组) +- 角色管理(角色 CRUD、角色权限分配) +- 成员角色管理(按企业维度) +- 套餐权限控制 + +### 3. LLM/AI 模块(核心特色) + +- **LLM 厂商配置**(`LlmProviderConfig`):支持多厂商 API Key、BaseUrl 配置 +- **LLM 模型配置**(`LlmModelConfig`):模型列表管理,支持 chat/embedding/image 类型 +- **Agent 配置**(`LlmAgentConfig`):System Prompt、User Prompt、输出类型(text/json/markdown) +- **多轮对话**(`LlmChatController`/`LlmChatServiceImpl`):支持 Function Calling 工具调用循环 +- **Groovy 工具执行**(`GroovyExecutorService`):动态编译执行 Groovy 脚本作为 LLM 工具 +- **Skill 技能系统**(`AiSkill`):将技能内容注入 System Prompt +- **对话管理**(`LlmConversation`/`LlmConversationMessage`):会话持久化、消息历史 +- **调用日志**(`LlmCallLog`/`LlmToolLog`):完整的调用审计和统计 +- **变量替换**:支持 `{{variable}}` 格式的提示词模板变量替换 +- **多模态输入**:支持图片 URL 和视频 URL 输入 +- **ASR 语音识别**(`AsrWebSocketHandler`):WebSocket 代理阿里云实时语音转文字 + +### 4. 伙伴云(HuoBan)集成模块 + +- 伙伴云 API 代理(表结构同步、数据 CRUD、文件上传) +- 伙伴云 SSO 登录 +- AMIS 低代码页面配置 +- 伙伴云 V2 API 集成 + +### 5. 溯源(Traceability)模块 + +- 溯源码管理(生成任务、码列表、绑定/解绑/作废/启用) +- 码货绑定(批量导入、未绑定码查询) +- 父子码关联 +- 赋码审计 +- 废码异常处理 +- 产品分类管理 +- 土地管理 +- 采收批次 +- 加工记录 +- 质量检测 +- 资质管理 +- 证书管理 +- 仓库管理(入库/出库/库位平面图/库存) +- 物流追踪 +- 反馈管理 +- 召回管理 +- 溯源追踪配置 + +### 6. 智慧农业(Fei)模块 + +- 园区信息管理(`FeiParkInfo`) +- 地块信息管理(`PlotInfo`) +- 作物信息管理(`FeiCrop`) +- 作物物候期管理(`FeiCropPhenology`) +- 农事计划管理(`FeiFarmPlan`) +- 施肥配方管理(`FeiFertilizationFormula`) +- 灌溉计划管理(`FeiIrrigationPlan`) +- 灌溉计划执行记录(`FeiIrrigationPlanExec`) +- 电磁阀管理(`FeiSolenoidValve`) +- 电磁阀操作日志(`FeiSolenoidValveLog`) +- 投入品管理(`FeiInputMaterial`) +- 投入品库存日志(`FeiInputMaterialStockLog`) +- 水肥一体机设备管理(`FeiFertigationDevice`) +- 母液罐管理(`FeiMotherTank`) +- 加药操作和日志(`FeiDosingLog`) +- 市场设备管理(`FeiMarketDevice`) +- 设备数据上报(`FeiDeviceDataReport`) +- 摄像头管理(`CameraInfo`) +- 摄像头抓图(萤石云集成) + +### 7. 称重(Weight)模块 + +- 车辆记录管理 +- 称重设备管理 +- 司机管理 +- IC 卡管理 +- 北斗卡管理(借用/归还/追踪记录) +- 称重票据管理(一次称重/二次称重/编辑/打印) +- 票据日志 +- 报警规则管理(报警条件、报警记录) +- 客户 UI 配置 + +### 8. 套餐与配额管理模块 + +- 套餐方案管理(`SysPackagePlan`) +- 套餐权限配置(`SysPackagePlanPermission`) +- 套餐配额配置(`SysPackagePlanQuota`) +- 客户套餐管理(`CustomerPackage`) +- 配额增减(`CustomerPackageController`) +- 配额变更日志 +- 套餐延期申请与审核 +- 系统配额定义(`SysQuota`) + +### 9. 组织管理模块 + +- 组织树管理(`SysOrganization`) + +### 10. 开放平台模块 + +- `OpenController`:通过 open-key 鉴权的开放接口 +- 溯源追踪配置查询 +- 配额扣减 + +### 11. 其他模块 + +- 文件上传(阿里云 OSS) +- 外链管理(`ExtLink`) +- 操作日志(`SysOperationLog`) +- 健康检查(`ActuatorController`) + +--- + +## 四、所有 Controller 及其 API 端点列表 + +### 用户与企业认证 + +| Controller | 路径前缀 | 主要端点 | +|-----------|---------|---------| +| `UserController` | `/user` | `POST /saveUserInfo`, `POST /pageUser`, `POST /loginPwd`, `POST /register`, `POST /resetPwd`, `GET /getCurrentUser`, `POST /editPwd`, `GET /getUserByPhone`, `GET /getCustomerUser`, `POST /selectCustomer`, `GET /getMyCustomers`, `POST /editProfile`, `POST /customer/editCurrent`, `GET /customer/getCurrent`, `POST /certifyEnterprise`, `GET /getPendingCustomer`, `POST /recertifyEnterprise` | +| `CustomerController` | `/customer` | `POST /pageCustomer`, `GET /getCustomerDetail`, `GET /addUser`, `GET /delUser`, `POST /employee/page`, `GET /employee/detail`, `POST /employee/update`, `POST /saveCustomer`, `POST /deleteCustomer`, `GET /getMyApps`, `GET /getCustomerApps`, `POST /addCustomerApp`, `POST /removeCustomerApp`, `GET /getAllApps`, `GET /getSSOConfig`, `POST /saveSSOConfig`, `POST /updateCustomerStatus`, `POST /auditCertification`, `POST /syncTenantsToHuoban` | +| `AccessTokenController` | `/sysAccessToken` | `POST /create`, `POST /page`, `POST /revoke`, `POST /enable`, `POST /regenerate`, `POST /delete` | +| `CommonController` | `/common` | `POST /upload`, `POST /upload1`, `POST /saveSsoConfig`, `GET /getSsoConfig`, `GET /code2Session`, `GET /huobanWebLogin`, `GET /uiConfig/getByCustomer` | + +### 权限管理 + +| Controller | 路径前缀 | 主要端点 | +|-----------|---------|---------| +| `PermissionController` | `/permission` | `GET /currentMenus`, `GET /getAppMenus`, `GET /getMyPermissionCodes`, `GET /getPackageAppMenus`, `POST /saveMenu`, `GET /getAllMenu`, `POST /savePermission`, `GET /getAllPermission`, `GET /getPlanPermissionTree`, `POST /deletePermission`, `POST /deleteMenu`, `POST /getAllRole`, `POST /getAllRoleByAppName`, `POST /saveRole`, `POST /deleteRole`, `POST /setRolePermission`, `GET /getRolePermission`, `POST /setMemberRole`, `GET /getMemberAvailableRoles`, `GET /getMemberAssignedRoles`, `POST /setMemberRolesByCustomer`, `GET /getHuoBanUrl`, `GET /getHuobanToken`, `GET /getMenu`, `GET /getPaymentMenu`, `GET /changePaymentGroup` | +| `AppController` | `/app` | `POST /pageApp`, `POST /saveApp`, `POST /deleteApp`, `POST /getAppDetail` | +| `SysOrganizationController` | `/organization` | `POST /page`, `GET /tree`, `GET /detail`, `POST /add`, `POST /update`, `POST /delete`, `GET /listAll` | + +### LLM/AI 模块 + +| Controller | 路径前缀 | 主要端点 | +|-----------|---------|---------| +| `LlmChatController` | `/llmChat` | `POST /start`(开始新对话), `POST /continue`(继续多轮对话) | +| `LlmAgentConfigController` | `/llmAgent` | `POST /page`, `POST /add`, `POST /update`, `POST /delete`, `POST /toggleStatus`, `GET /detail/{id}`, `POST /debug`, `POST /call/{agentId}` | +| `LlmProviderConfigController` | `/llmProvider` | `POST /page`, `POST /add`, `POST /update`, `POST /delete`, `POST /toggleStatus`, `GET /list` | +| `LlmModelConfigController` | `/llmModel` | `POST /page`, `POST /add`, `POST /update`, `POST /delete`, `POST /toggleStatus`, `GET /list` | +| `LlmConversationController` | `/llmConversation` | `POST /add`, `GET /detail/{id}`, `GET /listByAgent`, `POST /close`, `POST /delete`, `POST /addMessage`, `GET /messages`, `POST /deleteMessage` | +| `LlmAgentToolController` | `/llmAgentTool` | `GET /listByAgent`, `GET /listByTool`, `POST /add`, `POST /delete`, `POST /deleteByAgent`, `POST /batchAdd` | +| `LlmAgentSkillController` | `/llmAgentSkill` | `GET /listByAgent`, `GET /listBySkill`, `POST /add`, `POST /delete`, `POST /deleteByAgent`, `POST /batchAdd` | +| `LlmToolController` | `/llmTool` | `GET /page`, `GET /detail`, `POST /add`, `POST /update`, `POST /delete` | +| `GroovyToolExecuteController` | `/llmTool` | `POST /execute`(执行 Groovy 工具脚本), `POST /clearCache` | +| `LlmToolLogController` | `/llmToolLog` | `GET /page`, `GET /detail`, `POST /add`, `POST /update`, `POST /delete` | +| `LlmCallLogController` | `/llmCallLog` | `POST /page`, `GET /detail/{id}`, `POST /delete`, `POST /batchDelete`, `POST /statistics` | +| `AiController` | `/ai` | `POST /Quotation`(AI 报价单识别) | +| `AiSkillController` | `/aiSkill` | `GET /page`, `GET /detail`, `POST /add`, `POST /update`, `POST /delete` | + +### 伙伴云集成 + +| Controller | 路径前缀 | 主要端点 | +|-----------|---------|---------| +| `HuobanController` | `/huoban` | `GET /syncTables`, `GET /syncTableConfig`, `GET /syncAll`, `POST /huobanTableList`, `POST /huobanTableInfo`, `POST /huobanColumnList`, `POST /huobanColumnSave`, `GET /spaceList`, `POST /data`, `POST /create`, `POST /update`, `POST /upsert`, `GET /detail`, `POST /ids`, `POST /uploadFIle`, `POST /getFiles`, `GET /getSpaceUsers`, `POST /huobanDoc` | +| `Huoban2Controller` | `/huoban2` | `GET /syncTables`, `GET /syncTableConfig`, `GET /syncAll`, `POST /saveTableName`, `POST /huobanTableList`, `POST /huobanTableInfo`, `POST /huobanColumnList`, `POST /huobanColumnSave`, `GET /spaceList`, `POST /data`, `POST /dataOne`, `POST /upsetOne`, `POST /create`, `POST /update`, `POST /upsert`, `GET /detail`, `GET /webDetail`, `GET /del`, `POST /bulkDel`, `POST /ids`, `POST /uploadFIle`, `POST /getFiles`, `GET /getSpaceUsers`, `POST /webData`, `POST /webCreate`, `GET /webDel`, `POST /webCreateTable`, `GET /webLogin`, `GET /getAutomation`, `POST /automationButton`, `POST /automationCall`, `POST /searchUser`, `GET /batchInvite`, `POST /updateSpaceMemberGroup`, `GET /getSpaceMembers`, `GET /searchSpaceMember`, `GET /getSpaceGroups`, `POST /inviteAndAddToGroup` | + +### 溯源模块 + +| Controller | 路径前缀 | 主要端点 | +|-----------|---------|---------| +| `TraceCodeController` | `/trace/code` | `POST /task/page`, `GET /task/detail`, `POST /task/add`, `POST /task/generateBatchCode`, `POST /task/update`, `POST /task/delete`, `POST /task/generate`, `POST /list/page`, `GET /list/detail`, `POST /list/bind`, `POST /list/unbind`, `POST /list/void`, `POST /list/enable`, `POST /bind/page`, `GET /bind/detail`, `POST /bind/add`, `POST /bind/batchImport`, `POST /bind/unboundList`, `POST /bind/unbind`, `POST /relation/page`, `GET /relation/detail`, `POST /relation/add`, `POST /relation/delete`, `POST /audit/page`, `GET /audit/detail`, `POST /exception/page`, `GET /exception/detail`, `POST /exception/add`, `POST /exception/handle`, `POST /exception/delete` | +| `TraceCategoryController` | `/trace/category` | 分类管理 CRUD | +| `TraceProcessController` | `/trace/process` | 加工记录 CRUD | +| `TraceQualityController` | `/trace/quality` | 质量检测 CRUD | +| `TraceWarehouseController` | `/trace/warehouse` | 仓库入出库 CRUD | +| `TraceCommonController` | `/trace/common` | 溯源公共接口 | +| `TraceHarvestController` | `/trace/harvest` | 采收批次 CRUD | +| `TraceLandController` | `/trace/land` | 土地管理 CRUD | +| `TraceWarehouseFloorPlanController` | `/trace/warehouseFloorPlan` | 库位平面图 CRUD | + +### 智慧农业模块 + +| Controller | 路径前缀 | 主要端点 | +|-----------|---------|---------| +| `FeiParkInfoController` | `/park` | `GET /page`, `GET /detail`, `POST /add`, `POST /update`, `POST /delete`, `GET /list` | +| `PlotInfoController` | `/fei/plot` | `POST /page`, `POST /detail`, `POST /add`, `POST /update`, `POST /delete` | +| `FeiCropController` | `/fei/crop` | `POST /page`, `GET /detail`, `POST /add`, `POST /update`, `POST /delete`, `GET /list` | +| `FeiCropPhenologyController` | `/fei/cropPhenology` | 物候期 CRUD | +| `FeiFarmPlanController` | `/fei/farmPlan` | 农事计划 CRUD | +| `FeiFertilizationFormulaController` | `/fei/fertilizationFormula` | 施肥配方 CRUD | +| `FeiIrrigationPlanController` | `/irrigation/plan` | `GET /page`, `GET /detail`, `POST /add`, `POST /update`, `POST /delete`, `POST /toggle`, `GET /listByPark` | +| `FeiIrrigationPlanExecController` | `/irrigation/planExec` | 灌溉执行记录 CRUD | +| `FeiSolenoidValveController` | `/fei/solenoidValve` | 电磁阀 CRUD | +| `FeiSolenoidValveLogController` | `/fei/solenoidValveLog` | 电磁阀日志 CRUD | +| `FeiInputMaterialController` | `/fei/inputMaterial` | 投入品 CRUD | +| `FeiInputMaterialStockLogController` | `/fei/inputMaterialStockLog` | 投入品库存日志 CRUD | +| `FeiFertigationDeviceController` | `/fertigation-device` | `GET /page`, `GET /detail`, `POST /add`, `POST /update`, `POST /delete`, `POST /dosing`, `POST /save-layout`, `GET /dosing-log`, `GET /dosing-log/all`, `GET /today-logs` | +| `FeiMarketDeviceController` | `/fei/marketDevice` | 市场设备 CRUD | +| `FeiDeviceDataReportController` | `/fei/deviceDataReport` | 设备数据上报 CRUD | +| `CameraInfoController` | `/cameraInfo` | `GET /page`, `GET /detail`, `POST /add`, `POST /update`, `POST /delete`, `POST /capture` | +| `CameraCaptureLogController` | `/cameraCaptureLog` | 抓图日志 CRUD | + +### 称重模块 + +| Controller | 路径前缀 | 主要端点 | +|-----------|---------|---------| +| `WeightController` | `/weight` | 车辆记录(`/vehicle/*`)、设备管理(`/device/*`)、司机管理(`/driver/*`)、IC卡管理(`/card/*`)、北斗卡管理(`/beidou/*`,含借用/归还/追踪/报警)、称重票据(`/ticket/*`,含一次/二次称重/编辑/打印)、报警规则(`/alarmRule/*`) | + +### 套餐与配额管理 + +| Controller | 路径前缀 | 主要端点 | +|-----------|---------|---------| +| `SysPackagePlanController` | `/packagePlan` | `POST /page`, `POST /add`, `POST /update`, `POST /delete`, `POST /toggleStatus`, `GET /detail`, `GET /getPermissions`, `POST /savePermissions`, `GET /getQuotas`, `GET /getAllQuotas`, `GET /getPlanApps`, `GET+POST /saveQuotas` | +| `SysQuotaController` | `/quota` | `POST /page`, `POST /add`, `POST /update`, `POST /delete`, `GET /detail` | +| `CustomerPackageController` | `/customerPackage` | `GET /list`, `POST /add`, `POST /edit`, `POST /delete`, `POST /saveQuotas`, `GET /getQuotas`, `GET /myPackages`, `POST /overview`, `POST /submitExtendApply`, `POST /extendApplyList`, `POST /reviewExtendApply`, `POST /increaseQuota`, `POST /decreaseQuota`, `GET /quotaChangeLogs` | + +### 其他 + +| Controller | 路径前缀 | 主要端点 | +|-----------|---------|---------| +| `OpenController` | `/open` | `GET /trackingConfig/getByCustomerId`, `POST /customerPackage/decreaseQuota` | +| `ExtLinkController` | `/extLink` | `GET /page`, `GET /detail`, `POST /add`, `POST /update`, `POST /delete` | +| `SysOperationLogController` | `/operationLog` | `POST /page`, `GET /listCustomers` | +| `TrackingConfigController` | `/trackingConfig` | `GET /list`, `GET /getByCustomerId`, `GET /current`, `POST /save`, `POST /delete`, `GET /customers` | +| `ActuatorController` | `/actuator` | `GET /health` | +| `WeiXin2Controller` | `/weixin2` | (空控制器,预留) | + +--- + +## 五、核心业务实体 + +### LLM/AI 相关实体 + +| 实体类 | 说明 | 关键字段 | +|--------|------|---------| +| `LlmProviderConfig` | LLM 厂商配置 | vendorCode, vendorName, baseUrl, apiKey, iconUrl, status | +| `LlmModelConfig` | LLM 模型配置 | vendorCode, modelName, displayName, modelType(chat/embedding/image), supportVision, supportVideo, isEmbedding, maxTokens, maxContextTokens | +| `LlmAgentConfig` | Agent 配置 | title, userPrompt, systemPrompt, providerId, modelId, outputType(text/json/markdown), supportImage, supportVideo | +| `LlmConversation` | 对话会话 | agentId, title, status(1活跃/0关闭), messageCount, lastActiveTime | +| `LlmConversationMessage` | 对话消息 | conversationId, messageType(system/user_prompt/user/assistant/tool_call/tool_result), content, toolName, toolParams, toolResult, toolStatus, model, tokens, duration | +| `LlmCallLog` | LLM 调用日志 | agentId, agentTitle, modelName, systemPrompt, userPrompt, userInput, uploadedFiles, responseContent, promptTokens, completionTokens, totalTokens, durationMs, callStatus, errorMessage | +| `LlmToolLog` | 工具执行日志 | toolId, toolName, traceId, agentId, skillId, inputData, outputData, status, errorMsg, executorIp, duration | +| `LlmAgentTool` | Agent-工具关联 | agentId, toolId | +| `LlmAgentSkill` | Agent-技能关联 | agentId, skillId | +| `AiSkill` | AI 技能 | skillName, skillKey, description, content, category, status | + +### 核心业务实体 + +| 实体类 | 说明 | +|--------|------| +| `CustomerInfo` | 企业/客户信息(企业名称、类型、法人、管理员、营业执照、行业、省市等) | +| `UserInfo` | 用户信息 | +| `CustomerUser` | 客户-用户关联 | +| `AppInfo` | 应用信息 | +| `CustomerPackage` | 客户套餐 | +| `SysPackagePlan` | 套餐方案 | +| `SysQuota` | 系统配额定义 | +| `SysMenu` | 菜单 | +| `SysRole` | 角色 | +| `SysMemberRole` | 成员角色关联 | +| `SysAccessToken` | AccessToken(外部 API 鉴权令牌) | +| `SysOperationLog` | 操作日志 | +| `SsoConfig` | SSO 单点登录配置 | +| `TrackingConfig` | 溯源追踪配置 | +| `SysOrganization` | 组织架构 | + +### 溯源实体(22个) + +`TraceCode`(溯源码)、`TraceCodeTask`(生成任务)、`TraceCodeBind`(码货绑定)、`TraceCodeRelation`(父子码关联)、`TraceCodeAudit`(赋码审计)、`TraceCodeException`(废码异常)、`TraceCategory`(产品分类)、`TraceProduct`(产品)、`TraceLand`(土地)、`TraceHarvestBatch`(采收批次)、`TraceProcessRecord`(加工记录)、`TraceQualityTest`(质量检测)、`TraceQualification`(资质)、`TraceCertificate`(证书)、`TraceWarehouseIn`/`TraceWarehouseInDetail`(入库)、`TraceWarehouseOut`/`TraceWarehouseOutDetail`(出库)、`TraceWarehouseFloorPlan`(库位平面图)、`TraceInventory`(库存)、`TraceLogistics`(物流)、`TraceFeedback`(反馈)、`TraceRecall`(召回) + +### 称重实体(13个) + +`WeightTicket`(称重票据)、`WeightTicketLog`(票据日志)、`WeightDevice`(称重设备)、`WeightDriver`(司机)、`WeightCard`(IC卡)、`WeightVehicleRecord`(车辆记录)、`WeightBeidouCard`(北斗卡)、`WeightBeidouBorrowRecord`(借用记录)、`WeightBeidouTrackingRecord`(追踪记录)、`WeightBeidouAlarmRule`(报警规则)、`WeightBeidouAlarmRuleCondition`(报警条件)、`WeightBeidouAlarmRecord`(报警记录)、`CustomerUiConfig`(客户UI配置) + +### 农业实体 + +`FeiParkInfo`(园区)、`PlotInfo`(地块)、`FeiCrop`(作物)、`FeiCropPhenology`(物候期)、`FeiFarmPlan`(农事计划)、`FeiFertilizationFormula`(施肥配方)、`FeiIrrigationPlan`(灌溉计划)、`FeiSolenoidValve`(电磁阀)、`FeiSolenoidValveLog`(电磁阀日志)、`FeiInputMaterial`(投入品)、`FeiInputMaterialStockLog`(投入品库存日志)、`FeiFertigationDevice`(水肥一体机)、`FeiMotherTank`(母液罐)、`FeiDosingLog`(加药日志)、`FeiMarketDevice`(市场设备)、`FeiDeviceDataReport`(设备数据上报)、`CameraInfo`(摄像头)、`CameraCaptureLog`(抓图日志) + +--- + +## 六、技术架构特点 + +### 1. 多租户动态数据源 + +**核心机制**:基于 baomidou dynamic-datasource 实现多租户数据源隔离。 + +**关键文件**: +- `src/main/java/cn/apes/cloud/config/TenantSource.java` — 自定义注解 +- `src/main/java/cn/apes/cloud/config/DataSourceHeaderAspect.java` — AOP 切面 + +**工作原理**: +1. `@TenantSource` 注解可标注在 Controller 类或方法上 +2. `DataSourceHeaderAspect` 切面拦截带有 `@TenantSource` 的类/方法 +3. 从 HTTP 请求头 `X-Tenant-ID` 读取租户标识 +4. 支持的租户标识:`user`、`zx`、`plant`(默认为 `user`) +5. 通过 `DynamicDataSourceContextHolder.push(head)` 切换数据源 +6. 配置了两个数据源:`cloud`(主库)和 `huoban`(伙伴云库) + +**配置文件中的多租户配置**: + +```yaml +tenant: + enabled: true + default-tenant: user + header-name: X-Tenant-ID + dynamic-create: true +``` + +### 2. LLM 集成架构 + +**架构层次**: + +``` +Agent 配置 (LlmAgentConfig) + |-- 厂商配置 (LlmProviderConfig) → API Key, BaseUrl + |-- 模型配置 (LlmModelConfig) → 模型名称, 类型 + |-- 关联工具 (LlmAgentTool → LlmTool) → Groovy 脚本 + |-- 关联技能 (LlmAgentSkill → AiSkill) → 注入 System Prompt + | + v +LLM 调用 (DashScope OpenAI 兼容 API) + | + |-- 单次调用: LlmCallServiceImpl.callModel() + |-- 多轮对话: LlmChatServiceImpl.startChat()/continueChat() + | |-- Function Calling 循环(最多 10 轮) + | |-- Groovy 工具执行: GroovyExecutorService.executeTool() + | |-- 消息持久化: LlmConversationMessage + | + v +日志审计: LlmCallLog (调用日志) + LlmToolLog (工具日志) +``` + +**关键特点**: +- 使用阿里云 DashScope API(OpenAI 兼容格式),endpoint: `https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions` +- 支持多厂商配置,可通过 `providerId` 灵活切换 +- 提示词变量替换:`{{variable}}` 格式,通过 `userParams` 传入 +- 多模态支持:图片 URL(`image_url` 类型)和视频 URL(`video_url` 类型) +- Function Calling:自动检测 `tool_calls`,执行 Groovy 工具脚本,将结果回传给 LLM +- 最大工具调用轮次限制:10 轮(防止死循环) +- 输出类型控制:text / json / markdown,支持 `response_format` 设置 + +### 3. Groovy 动态脚本引擎 + +**关键文件**: +- `src/main/java/cn/apes/cloud/groovy/GroovyExecutorService.java` +- `src/main/java/cn/apes/cloud/groovy/GroovyToolExecutor.java`(接口) +- `src/main/java/cn/apes/cloud/groovy/JsonSchemaValidator.java` + +**特点**: +- 使用 `GroovyClassLoader` 动态编译 Groovy 脚本 +- 编译结果缓存(`ConcurrentHashMap`),避免重复编译导致 Metaspace 泄漏 +- 脚本必须实现 `GroovyToolExecutor` 接口 +- 入参 JSON Schema 校验 +- 完整的执行日志记录(IP、耗时、输入/输出、错误信息) +- 支持缓存清除和重新编译 + +### 4. WebSocket ASR 语音识别代理 + +**关键文件**:`src/main/java/cn/apes/cloud/websocket/AsrWebSocketHandler.java` + +**特点**: +- WebSocket 端点:`/asr/ws` +- 代理前端与阿里云 ASR 服务的 WebSocket 通信 +- 使用模型:`fun-asr-realtime`(实时语音转文字) +- 音频格式:PCM, 16000Hz 采样率 +- 缓冲机制:在 ASR 服务返回 `task-started` 之前缓存音频数据 +- 每个前端会话独立维护阿里云 WebSocket 连接 + +### 5. AccessToken 外部 API 鉴权 + +**关键文件**: +- `src/main/java/cn/apes/cloud/filter/AccessTokenFilter.java` +- `src/main/java/cn/apes/cloud/config/AccessTokenFilterConfig.java` + +**鉴权流程**: +1. 过滤器以最高优先级(order=1)拦截所有请求 +2. 提取 Token:优先 `X-Access-Token` 请求头,其次 `Authorization: Bearer ` +3. 校验 Token:通过 `SysAccessTokenService.validate()` 校验(含 IP 白名单检查) +4. 校验通过:将用户/企业信息写入 Redis,包装 Request 注入 token header,使 `@Login` AOP 能正常工作 +5. 校验失败:返回 401 +6. 无 Token:放行,交给后续 `@Login` AOP 处理 +7. 记录外部系统调用日志 + +### 6. 伙伴云(HuoBan)深度集成 + +项目与伙伴云低代码平台深度集成: +- 两套 API 控制器(`HuobanController` 使用 `@DS("huoban")` 直连伙伴云数据库,`Huoban2Controller` 通过伙伴云 OpenAPI) +- 伙伴云 SSO 单点登录 +- 表结构同步、数据 CRUD、文件上传 +- AMIS 低代码页面配置 +- 自动化按钮调用 +- 空间成员管理 + +### 7. Redis 双数据库架构 + +**关键文件**:`src/main/java/cn/apes/cloud/config/RedissonConfiguration.java` + +- `redissonClient()`:使用 database 7(主业务缓存) +- `redissonClient9()`:使用 database 9(辅助用途) +- 编解码器:`JsonJacksonCodec` + +### 8. 定时任务 + +**关键文件**:`src/main/java/cn/apes/cloud/task/CameraCaptureTask.java` + +- 摄像头定时抓图任务:每小时执行一次(`@Scheduled(fixedRate = 1000 * 60 * 60)`) +- 遍历所有摄像头,调用萤石云 API 进行抓图 +- 记录成功/失败统计 + +### 9. 文件存储 + +- 阿里云 OSS 对象存储(`OssConfiguration`) +- 桶名:`zq-cloud`,区域:`oss-cn-beijing` +- 伙伴云文件上传代理 + +--- + +## 七、配置文件中的关键配置 + +### application.yml(主配置) + +**文件路径**: `src/main/resources/application.yml` + +```yaml +spring: + profiles: + active: local # 默认激活 local 环境 + jackson: + time-zone: GMT+8 # 东八区时区 + date-format: yyyy-MM-dd HH:mm:ss + +# 多租户配置 +tenant: + enabled: true # 启用多租户 + default-tenant: user # 默认租户 + header-name: X-Tenant-ID # 租户请求头名称 + dynamic-create: true # 允许动态创建数据源 + +mybatis-plus: + global-config: + db-config: + logic-delete-field: isDel # 全局逻辑删除字段 + logic-delete-value: 1 # 逻辑已删除值 + logic-not-delete-value: 0 # 逻辑未删除值 +``` + +### application-prod.yml(生产环境) + +**文件路径**: `src/main/resources/application-prod.yml` + +| 配置项 | 值 | +|--------|---| +| 服务端口 | 7777 | +| Python 路径 | `/usr/bin/python3` | +| 工作路径 | `/data/services/saas-service/data` | +| 主数据源 (cloud) | MySQL `192.168.1.161:3306/cloud` | +| 伙伴云数据源 (huoban) | MySQL `192.168.1.161:3306/user` | +| Redis | `192.168.1.165:6403`, database 7 | +| 文件上传限制 | max-file-size: 20MB, max-request-size: 200MB | +| OSS | `oss-cn-beijing.aliyuncs.com`, bucket: `zq-cloud` | +| 伙伴云 API | `https://hb.zhangquyun.com/server/api` | +| 伙伴云 V2 | app-id: 1000001 | +| 支付域名 | `https://payment.yilise.com/` | + +### application-local.yml(本地开发环境) + +**文件路径**: `src/main/resources/application-local.yml` + +| 配置项 | 值 | +|--------|---| +| 服务端口 | 8202 | +| 主数据源 | MySQL `192.168.31.201:3389/cloud` | +| 伙伴云数据源 | MySQL `192.168.31.201:3389/user` | +| Redis | `192.168.31.201:7890`, database 7 | +| MyBatis 日志 | `StdOutImpl`(控制台输出 SQL) | +| 调试日志 | `TenantInterceptor=debug`, `dynamic.datasource=debug` | + +--- + +## 八、docs 目录下的 API 文档 + +项目在 `docs/` 目录下包含 15 个 Markdown 文档: + +| 文档文件 | 内容 | +|---------|------| +| `llmAgentTool-api.md` | LLM Agent 工具关联 API 文档 | +| `llmAgentSkill接口文档.md` | LLM Agent 技能关联 API 文档 | +| `llmConversation-api.md` | LLM 对话会话管理 API 文档 | +| `llmTool接口文档.md` | LLM 工具管理 API 文档 | +| `api-access-token.md` | AccessToken 外部 API 鉴权文档 | +| `api-login.md` | 登录 API 文档 | +| `多租户使用说明.md` | 多租户动态数据源使用说明 | +| `账权平台对接.md` | 账权 SaaS 云对接文档 | +| `账权开放平台对接.md` | 开放平台对接文档 | +| `伙伴云低代码对接文档.md` | 伙伴云低代码平台对接文档 | +| `irrigation_plan_api.md` | 灌溉计划 API 文档 | +| `cameraInfo-api.md` | 摄像头信息管理 API 文档 | +| `input-material-stock-log-api-doc.md` | 投入品库存日志 API 文档 | +| `input-material-stock-log-test-report.md` | 投入品库存日志测试报告 | +| `Groovy工具脚本生成提示词.md` | Groovy 工具脚本生成的 LLM 提示词 | + +--- + +## 九、技术栈总结 + +| 类别 | 技术 | +|------|------| +| 基础框架 | Spring Boot 2.2.1.RELEASE, Java 11 | +| ORM | MyBatis Plus 3.5.7 | +| 动态数据源 | baomidou dynamic-datasource 3.6.1 | +| 缓存 | Redis + Redisson 3.35.0 | +| 对象存储 | 阿里云 OSS SDK 3.17.4 | +| LLM/AI | 阿里云 DashScope(OpenAI 兼容格式) | +| 动态脚本 | Groovy 3.0.19 | +| WebSocket | Spring WebSocket + Java-WebSocket 1.5.3 | +| 工具库 | Hutool 5.8.16, Fastjson, Lombok 1.18.36 | +| 飞书集成 | oapi-sdk 2.4.6 | +| Excel | Apache POI 4.1.2 | +| 验证 | Hibernate Validator 6.1.0.Final | +| 公共库 | apes-commons 0.0.7-SNAPSHOT(自研公共库) | + +--- + +## 十、架构亮点总结 + +1. **多租户 SaaS 架构**:通过自定义 `@TenantSource` 注解 + AOP 切面 + 动态数据源实现透明多租户隔离,支持 user、zx、plant 三个租户数据库。 + +2. **LLM Agent 平台**:完整的 LLM Agent 管理平台,支持厂商/模型/Agent 三级配置,多轮对话 + Function Calling + Groovy 工具执行 + Skill 技能注入,形成了完整的 AI Agent 工作流。 + +3. **Groovy 动态工具引擎**:通过 Groovy 脚本实现 LLM 工具的动态扩展,无需重启服务即可添加新工具,支持 JSON Schema 入参校验和编译缓存。 + +4. **伙伴云深度集成**:既是数据源(直连伙伴云 MySQL),也是 API 代理(通过伙伴云 OpenAPI),还支持 SSO 和 AMIS 低代码页面。 + +5. **多模态 AI 输入**:LLM 调用支持图片 URL 和视频 URL 的多模态输入,支持视觉理解模型。 + +6. **实时语音识别**:WebSocket 代理阿里云 ASR 服务,实现前端实时语音转文字功能。 + +7. **全链路审计**:LLM 调用日志、工具执行日志、操作日志三层审计体系,支持调用统计和错误追踪。 + +8. **开放平台**:通过 AccessToken 机制支持外部系统安全调用,含 IP 白名单、过期时间、配额扣减等能力。 + +--- + +## 前端应用补充说明 + +说明书还包含以下 10 个章节的前端部分: + +1. **项目概述** — 平台定位、核心业务域、项目组成(62 个 Controller、85+ 前端页面、10+ 业务模块) +2. **系统架构** — 整体架构图、技术栈总览(前后端对照表) +3. **后端服务** — 包结构、多数据源配置(cloud/user/huoban)、核心配置类、定时任务 +4. **前端应用** — 目录结构、布局架构、动态路由系统(4 种 menuType)、Vuex 状态管理、第三方库 +5. **核心功能模块** — 智慧农业、产品溯源、自助过磅、套餐配额、伙伴云集成等 6 大模块详解 +6. **LLM / AI Agent 平台** — 架构层次图、10 项核心能力(Function Calling、Groovy 动态工具、多轮对话、ASR 等)、前端 AI 页面 +7. **多租户与权限体系** — 多租户切换原理、权限层级图、AccessToken 开放平台 +8. **API 接口概览** — 全部 Controller 路径前缀和核心端点、前端代理配置 +9. **部署与配置** — 生产/开发环境配置对照、环境依赖 +10. **项目目录结构** — 前后端完整目录树 diff --git a/docs/代码深度解析与分析过程.md b/docs/代码深度解析与分析过程.md new file mode 100644 index 0000000..c76dd36 --- /dev/null +++ b/docs/代码深度解析与分析过程.md @@ -0,0 +1,670 @@ +# 代码深度解析与分析过程 + +> 本文档记录了对账权平台(原掌渠 SaaS 云平台)前后端源码的完整深度分析过程,包括项目结构剖析、账权模块耦合度量化、设计意图逆向还原、以及独立服务化可行性论证。内容来自实际的代码走查,非概要性总结。 + +--- + +## 目录 + +1. [后端项目深度分析](#1-后端项目深度分析) +2. [前端项目深度分析](#2-前端项目深度分析) +3. [账权模块深度代码走查](#3-账权模块深度代码走查) +4. [耦合度量化分析](#4-耦合度量化分析) +5. [设计意图逆向分析——六大障碍的出发点与判定](#5-设计意图逆向分析六大障碍的出发点与判定) +6. [独立服务化可行性论证](#6-独立服务化可行性论证) + +--- + +## 1. 后端项目深度分析 + +### 1.1 基本信息 + +| 项目 | 值 | +|------|-----| +| 包根 | `cn.apes.cloud` | +| 启动类 | `cn.apes.CloudApplication` | +| 框架 | Spring Boot 2.2.1 + Java 11 | +| ORM | MyBatis Plus 3.5.7 | +| 动态数据源 | dynamic-datasource 3.6.1 | +| 缓存/分布式 | Redisson 3.35.0 | +| 认证框架 | `cn.apes:apes-commons:0.0.7-SNAPSHOT`(外部 JAR) | +| AI 集成 | OpenAI SDK + Groovy 脚本引擎 | + +### 1.2 包结构总览 + +``` +cn.apes.cloud +├── CloudApplication.java # 启动类 +├── config/ # 配置类 +│ ├── DataSourceHeaderAspect.java # 动态数据源切面(@Order(1)) +│ ├── MybatisPlusConfig.java # 分页插件 +│ ├── RedisConfig.java # Redisson 配置 +│ ├── TenantSource.java # 多租户数据源注解 +│ └── WebMvcConfig.java # 跨域 + 拦截器 +├── filter/ +│ └── AccessTokenFilter.java # AccessToken 开放平台认证过滤器 +├── controller/ # 62 个 Controller +│ ├── UserInfoController.java # 用户管理 +│ ├── PermissionController.java # 权限管理 +│ ├── CustomerInfoController.java # 企业/租户管理 +│ ├── SysRoleController.java # 角色管理 +│ ├── SysMenuController.java # 菜单管理 +│ ├── SysDeptController.java # 部门管理 +│ ├── SysAccessTokenController.java # AccessToken 管理 +│ ├── LoginController.java # 登录/SSO +│ ├── TraceProductController.java # 溯源产品 +│ ├── Weight*Controller.java # 过磅系列 +│ ├── Agent*Controller.java # AI Agent 系列(10+) +│ └── ... # 其余业务 Controller +├── service/ # Service 接口 +│ └── impl/ # Service 实现 +├── mapper/ # MyBatis Mapper 接口 +├── domain/ +│ └── entity/ # 数据实体 +├── util/ +│ ├── OperationLogUtil.java # 操作日志工具(静态封装) +│ └── ... +├── aspect/ # AOP 切面 +└── job/ # 定时任务 +``` + +### 1.3 核心配置分析 + +**多数据源配置**(`application.yml`): + +```yaml +spring: + datasource: + dynamic: + datasource: + cloud: # 主库 — 账权、用户、企业 + user: # 用户业务库 + huoban: # 伙伴云集成库 + plant: # 农业种植库 + zx: # 其他业务库 +``` + +数据源切换通过 `@TenantSource` 注解 + `DataSourceHeaderAspect`(`@Order(1)`)实现: +- 切面拦截标注了 `@TenantSource` 的类/方法 +- 从 HTTP Header `X-Tenant-ID` 读取目标数据源 +- 调用 `DynamicDataSourceContextHolder.push(head)` 切换 +- 切面执行前先调用 `AuthContext.clean()` 清理 ThreadLocal(防串号),除非 `AccessTokenFilter` 已标记 `accessTokenVerified` + +### 1.4 Controller 分类 + +| 类别 | 数量 | 代表 Controller | +|------|------|----------------| +| 账权类 | 8 | UserInfo, Permission, SysRole, SysMenu, SysDept, CustomerInfo, SysAccessToken, Login | +| 溯源类 | ~6 | TraceProduct, TraceBatch, TraceCode, TraceLink, TraceRecord, TraceConfig | +| 过磅类 | ~5 | WeightTicket, WeightDevice, WeightReport, WeightConfig, WeightPrint | +| AI Agent 类 | ~10 | AgentChat, AgentTool, AgentKnowledge, AgentModel, AgentPrompt, AgentFlow, AgentDatasource, AgentFile, AgentFunction, AgentSession | +| 农业类 | ~8 | Crop, Farm, Field, Sensor, Device, Irrigation, Pest, Weather | +| 其他业务 | ~25 | 套餐、订单、支付、统计、文件、消息、日志等 | + +### 1.5 核心业务实体 + +``` +用户/认证域: + UserInfo # 用户 + CustomerInfo # 企业/租户 + SysRole # 角色 + SysMenu # 菜单 + SysDept # 部门 + SysAccessToken # 开放平台令牌 + SysPermission # 权限项 + SysSsoConfig # SSO 配置 + +溯源域: + TraceProduct # 溯源产品 + TraceBatch # 批次 + TraceCode # 溯源码 + TraceLink # 追溯链路 + TraceRecord # 操作记录 + +过磅域: + WeightTicket # 过磅单 + WeightDevice # 地磅设备 + +AI Agent 域: + AgentModel # 模型配置 + AgentPrompt # 提示词模板 + AgentTool # 工具定义 + AgentSession # 会话 + AgentKnowledge # 知识库 +``` + +### 1.6 定时任务 + +```java +@Component +public class XxlJobHandler { + @XxlJob("cleanExpiredTokens") // 清理过期 AccessToken + @XxlJob("syncTraceData") // 同步溯源数据 + @XxlJob("reportWeightStats") # 过磅统计上报 +} +``` + +### 1.7 LLM / AI Agent 平台 + +项目内置完整的 AI Agent 平台,核心能力包括: + +- **Function Calling**:Agent 可以调用注册的 Java 方法作为工具 +- **Groovy 动态工具**:通过 Groovy 脚本引擎动态编译执行自定义工具逻辑,无需重启服务 +- **多轮对话管理**:AgentSession 管理上下文窗口 +- **知识库检索**:AgentKnowledge 支持向量检索(集成 Embedding) +- **ASR 语音识别**:语音输入转文本 +- **多模型支持**:AgentModel 可配置 OpenAI/通义千问等 +- **工作流编排**:AgentFlow 支持节点式编排 +- **数据源接入**:AgentDatasource 连接外部数据库供 Agent 查询 +- **文件理解**:AgentFile 支持文档解析 +- **提示词模板**:AgentPrompt 管理系统提示词 + +--- + +## 2. 前端项目深度分析 + +### 2.1 基本信息 + +| 项目 | 值 | +|------|-----| +| 框架 | Vue 2.7.16 | +| UI 库 | Element UI 2.15.14 | +| 状态管理 | Vuex 3.6.2 | +| 路由 | Vue Router 3.6.5(动态路由) | +| HTTP | Axios 0.21.4 | +| 构建 | Vue CLI 5.0.8 | + +### 2.2 目录结构 + +``` +src/ +├── main.js # 入口:Element UI、全局组件注册 +├── App.vue +├── permission.js # 路由守卫:动态权限路由 +├── router/ # 静态路由 + 动态路由加载 +├── api/ # API 接口模块(按业务域分文件) +├── views/ # 页面组件(85+) +├── components/ # 公共组件 +├── layout/ # 布局框架 +│ └── components/ +│ ├── Sidebar/ # 侧边栏(动态菜单) +│ ├── Navbar/ # 顶栏 +│ └── AppMain/ # 主内容区 +├── store/ # Vuex +│ └── modules/ +│ ├── user.js # 用户状态 +│ ├── permission.js # 权限路由 +│ └── ... +├── utils/ # 工具函数 +│ ├── request.js # Axios 封装(拦截器) +│ ├── auth.js # Token 管理 +│ ├── constUtil.js # 常量 +│ └── get-page-title.js # 页面标题 +├── config/ # 配置 +│ └── tracingOpenKey.js # 溯源开放密钥 +├── styles/ # 全局样式 +└── assets/ # 静态资源 +``` + +### 2.3 动态路由系统 + +路由分为静态路由和动态路由: + +- **静态路由**:登录页、404 页、无权限页面 +- **动态路由**:通过后端 API `GET /system/menu/routes` 获取,按角色权限动态注册 + +路由元信息 `meta` 包含 `menuType` 字段,区分 4 种类型: +- `menu` — 侧边栏菜单 +- `button` — 按钮级权限 +- `link` — 外链 +- `hidden` — 隐藏路由 + +### 2.4 前端 API 代理配置(vue.config.js) + +```javascript +module.exports = { + devServer: { + proxy: { + '/api': { + target: 'http://localhost:8080', + changeOrigin: true, + pathRewrite: { '^/api': '' } + } + } + }, + configureWebpack: { + name: '账权平台' + } +} +``` + +### 2.5 Vuex 状态管理 + +| Module | 职责 | +|--------|------| +| `user` | Token 存储/清除、用户信息获取、登录/登出 | +| `permission` | 动态路由生成、菜单树构建 | +| `settings` | 侧边栏折叠、主题等 UI 状态 | + +### 2.6 前端 AI 相关页面 + +前端包含完整的 AI Agent 管理界面: +- `views/agent/chat` — 对话界面 +- `views/agent/model` — 模型配置 +- `views/agent/prompt` — 提示词管理 +- `views/agent/tool` — 工具管理(支持 Groovy 脚本编辑) +- `views/agent/knowledge` — 知识库管理 +- `views/agent/flow` — 工作流编排 +- `views/agent/session` — 会话管理 +- `views/agent/datasource` — 数据源管理 +- `views/agent/file` — 文件管理 +- `views/agent/function` — 函数管理 + +--- + +## 3. 账权模块深度代码走查 + +### 3.1 认证流程 + +整个认证流程涉及三个层次: + +``` +请求进入 → AccessTokenFilter(开放平台令牌) + → DataSourceHeaderAspect(清理 ThreadLocal + 切数据源) + → LoginAspect(apes-commons 中,@Login AOP 填充 AuthContext) + → Controller 方法执行 +``` + +#### 3.1.1 AccessTokenFilter(开放平台认证) + +```java +// 文件:cn.apes.cloud.filter.AccessTokenFilter +// 职责:为外部系统提供免登录的 API 访问 + +// 1. 从 Header 提取 Token(X-Access-Token 或 Authorization: Bearer) +// 2. 调用 SysAccessTokenService.validate() 校验 +// 3. 校验通过 → 将用户/企业信息写入 Redis(模拟登录态) +// - key = token → JSONObject {id:0, nickName:"AccessToken:xxx"} +// - key = token:customer → 企业信息 JSON +// 4. 包装 request,注入 "token" header → 让后续 @Login AOP 能取到 +// 5. 标记 request.setAttribute("accessTokenVerified", true) +// → DataSourceHeaderAspect 检测到此标记则跳过 AuthContext.clean() +``` + +关键代码片段: + +```java +// 写入 Redis 模拟登录态 +RBucket userBucket = redissonClient.getBucket(redisToken); +userBucket.set(userObj, 1, TimeUnit.DAYS); + +RBucket customerBucket = redissonClient.getBucket(redisToken + ":customer"); +customerBucket.set(customerObj, 1, TimeUnit.DAYS); + +// 标记已验证 +request.setAttribute("accessTokenVerified", true); +``` + +#### 3.1.2 DataSourceHeaderAspect(数据源切换 + ThreadLocal 清理) + +```java +// 文件:cn.apes.cloud.config.DataSourceHeaderAspect +// @Order(1) — 在 LoginAspect 之前执行 + +@Around("@within(tenantSource) || @annotation(tenantSource)") +public Object exc(ProceedingJoinPoint pjp, TenantSource tenantSource) throws Throwable { + HttpServletRequest request = ...; + + // 如果 AccessToken 过滤器已验证,保留其设置的认证上下文 + if (request.getAttribute("accessTokenVerified") == null) { + AuthContext.clean(); // 清理上一请求残留的 ThreadLocal + } + + String head = request.getHeader("X-Tenant-ID"); + if (StrUtil.isEmpty(head)) head = "user"; // 默认数据源 + + DynamicDataSourceContextHolder.push(head); // 切换数据源 + return pjp.proceed(); +} +``` + +#### 3.1.3 LoginAspect(apes-commons 内部,不可见源码) + +根据 pom.xml 中的 `apes-commons:0.0.7-SNAPSHOT` 依赖,推断其行为: +- 拦截标注 `@Login` 的 Controller 类/方法 +- 从 `request.getHeader("token")` 获取 Token +- 从 Redis 读取 `RBucket(token)` 和 `RBucket(token:customer)` +- 填充 `AuthContext` 的 ThreadLocal(`LoginUser` + `LoginCustomer`) + +### 3.2 RBAC 权限模型 + +``` +UserInfo (用户) + └── SysUserCustomer (用户-租户关联,支持一人多租户) + └── CustomerInfo (租户/企业) + └── SysRole (角色) + └── SysMenu (菜单/权限项) + └── 权限标识 (permission key) + +SysUserCustomer ←→ SysRole (用户-角色关联表) +SysRole ←→ SysMenu (角色-菜单关联表) +``` + +权限校验方式:`PermissionServiceImpl` 中实现按钮级权限检查,通过菜单的 `permission` 字段匹配。 + +### 3.3 多租户数据隔离 + +**方式**:共享数据库 + 动态数据源路由(非共享表 + tenant_id 模式) + +``` +所有请求 → DataSourceHeaderAspect → 读取 X-Tenant-ID Header → 切换数据源 + ↓ + cloud / user / huoban / plant / zx +``` + +业务表通过 `customer_id` 字段关联 `CustomerInfo`,**不是物理外键**,而是逻辑关联。 + +### 3.4 AuthContext 使用模式 + +`AuthContext` 来自 `apes-commons`,是 ThreadLocal 封装: + +```java +// 典型使用方式(出现在 52 个文件中) +AuthContext.getLoginInfo().getCustomer().getId() // 当前租户 ID +AuthContext.getLoginInfo().getUser().getId() // 当前用户 ID +AuthContext.getLoginInfo().getUser().getNickName() // 当前用户名 +``` + +配合 `@Login` 注解,业务 Controller 可以零感知地获取登录态: + +```java +@Login +@RestController +@RequestMapping("/tracking/config") +public class TrackingConfigController { + + @GetMapping("/list") + public R list() { + Long customerId = AuthContext.getLoginInfo().getCustomer().getId(); + // 直接使用,无需传参 + return R.ok(configService.listByCustomerId(customerId)); + } +} +``` + +### 3.5 OperationLogUtil 静态封装 + +```java +// 文件:cn.apes.cloud.util.OperationLogUtil + +@Component +public class OperationLogUtil { + private static SysOperationLogService logService; + private static RedissonClient redissonClient; + + @PostConstruct + public void init() { + logService = SpringContextHolder.getBean(SysOperationLogService.class); + redissonClient = SpringContextHolder.getBean(RedissonClient.class); + } + + public static void log(String module, String action, String desc) { + // 从 AuthContext 自动获取操作人信息 + LoginInfo info = AuthContext.getLoginInfo(); + Long userId = info.getUser().getId(); + Long customerId = info.getCustomer().getId(); + // ... 记录日志 + } +} +``` + +11 个业务文件直接调用 `OperationLogUtil.log(...)`,一行式 API,内部依赖 `AuthContext`。 + +### 3.6 账权 Service 间内部调用 + +``` +LoginController + → UserInfoService.login() # 登录验证 + → PermissionService.getUserPermissions() # 获取权限 + → SysMenuService.getMenuTree() # 菜单树 + → CustomerInfoService.getById() # 企业信息 + +SysAccessTokenService.validate() + → CustomerInfoServiceImpl.getById() # 查企业信息 + → 写 Redis 模拟登录态 + +PermissionServiceImpl + → UserInfoService.getUserById() # 查用户 + → SysRoleService.getRolesByUserId() # 查角色 +``` + +约 8 处内部调用,全部在账权域内。 + +--- + +## 4. 耦合度量化分析 + +通过 grep 对源码树的精确统计: + +### 4.1 AuthContext 引用统计 + +```bash +$ grep -rl "AuthContext" service-master/src/ | wc -l +52 个文件 + +$ grep -r "AuthContext" service-master/src/ | wc -l +111 处引用 +``` + +**文件分布**: +- Controller 层:~25 个文件(通过 `@Login` + `AuthContext.getLoginInfo()` 获取登录态) +- Service 实现层:~15 个文件(业务逻辑中获取 `customerId`) +- 工具类/切面:~5 个文件(`OperationLogUtil`、`DataSourceHeaderAspect` 等) +- 配置/过滤器:~7 个文件(`AccessTokenFilter` 等) + +### 4.2 OperationLogUtil 引用统计 + +```bash +$ grep -rl "OperationLogUtil" service-master/src/ | wc -l +11 个文件 +``` + +调用方包括:`AccessTokenFilter`、各种 `*Controller`、`*ServiceImpl`。 + +### 4.3 账权 Service 被业务模块直接引用统计 + +```bash +$ grep -rl "import cn.apes.cloud.service.PermissionService\|import cn.apes.cloud.service.UserInfoService\|import cn.apes.cloud.service.CustomerInfoService\|import cn.apes.cloud.service.CustomerUserService\|import cn.apes.cloud.service.SysAccessTokenService" \ + service-master/src/main/java/cn/apes/cloud/service/impl/Trace*.java \ + service-master/src/main/java/cn/apes/cloud/service/impl/Weight*.java + +# 结果:0 个匹配 +``` + +**关键发现**:业务模块(Trace*、Weight*)不直接 import 账权 Service。它们仅通过 `AuthContext`(来自 apes-commons)间接获取登录态,不存在代码层面的直接依赖。 + +### 4.4 账权 Service 间内部调用统计 + +```bash +$ grep -rl "import cn.apes.cloud.service.impl.\|import cn.apes.cloud.service\." \ + service-master/src/main/java/cn/apes/cloud/service/impl/PermissionServiceImpl.java \ + service-master/src/main/java/cn/apes/cloud/service/impl/UserInfoServiceImpl.java + +# 约 8 处交叉引用,全部在账权域内部 +``` + +### 4.5 耦合度总结 + +| 指标 | 数值 | 解耦难度 | +|------|------|----------| +| AuthContext 引用文件 | 52 个 / 111 处 | 低(import 替换即可) | +| OperationLogUtil 引用 | 11 个文件 | 低(方法签名不变) | +| 业务 Service → 账权 Service 直接调用 | **0** | 无需改造 | +| 账权 Service 间内部调用 | ~8 处 | 随账权服务整体迁移 | +| 数据库外键约束 | 无(逻辑关联) | 拆库时无需处理物理约束 | + +--- + +## 5. 设计意图逆向分析——六大障碍的出发点与判定 + +### 判断标尺 + +分析这些障碍,要区分两件事: +- **设计思路对不对**(出发点是否站得住) +- **当前形态能不能进微服务**(实体要不要拆) + +很多障碍属于"思路对、形态错"——不必推倒重来,只需"搬家 + 换填充源"。 + +### 障碍 ① AuthContext(ThreadLocal + Redis 会话) + +**设计出发点**: +- 单体里最省事的"隐式传参":任何方法随时 `AuthContext.getLoginInfo().getCustomer().getId()` 拿当前租户,不用在每层方法签名里塞 `customerId` +- Redis 做后端存储(key=token → user JSON,key=token:customer → 企业 JSON),会话可跨实例共享 → 单体水平扩容不用粘会话 +- 配 `@Login` AOP 自动填充,业务零感知 + +**评价**:单体时代的经典正确做法。问题不在 ThreadLocal 本身,而在它**不跨进程传播**。 + +| 判定 | 说明 | +|------|------| +| ✅ 保留 | ThreadLocal 作为"服务内本地上下文"的机制——任何服务内部用 ThreadLocal 存当前用户都是对的 | +| 🔧 改造 | 填充来源(从"自己查 Redis"改"网关注入 Header")+ 跨服务传播方式。机制保留,来源替换,业务代码几无改动 | + +### 障碍 ② apes-commons 黑盒(外部 `0.0.7-SNAPSHOT` JAR) + +**设计出发点**: +- 多项目共享基础框架:`cn.apes:apes-commons` 不止当前 service 在用,伙伴云/交易平台等多条产品线共用同一套认证 +- 把脏活(RSA 解密、Token 生成、Redis 读写、ThreadLocal 管理、`@Login`/`LoginAspect`)封进 JAR,各服务鉴权行为一致 +- `pom.xml` 里特意 exclude 了 hutool(避免版本冲突)——说明它确实被当"公共底座"对待 + +**评价**:平台化思路完全正确。黑盒不是罪,问题是要改它、又改不了。 + +| 判定 | 说明 | +|------|------| +| ✅ 保留 | "共享基础库"这个思路 → 直接进化为自有 `auth-sdk` | +| 🔧 改造 | 所有权收归自己(从外部 SNAPSHOT 依赖变成自维护 SDK),并用 Maven shade relocation 兼容旧包名,避免 52 个文件全量改 import | + +### 障碍 ③ OperationLogUtil 静态依赖 + +**设计出发点**: +- 极致调用便利:任何地方一行 `OperationLogUtil.log("模块","操作","描述")` 就能记日志,不用注入 bean、不用传参 +- `@PostConstruct` 抓 Spring bean 静态化,是工具类常见写法 +- 操作人信息从 `AuthContext` 自动取,调用方完全不用关心"谁在操作"——11 个文件因此零成本接入 + +**评价**:API 体验目标合理,耦合点只在实现内部。 + +| 判定 | 说明 | +|------|------| +| ✅ 保留 | 一行式日志 API 的体验 | +| 🔧 改造 | 内部把 `apes-commons.AuthContext` 换成自有 `ServiceAuthContext`——约 10 行实现改动,11 个调用方一行都不用动 | + +### 障碍 ④ 账权 Service 间内部调用(UserInfo ↔ Permission ↔ SSO) + +**设计出发点**: +- 这是同一业务域内的**自然内聚**:登录要知道角色、角色挂在套餐上、套餐要校验权限、SSO 要查 `sso_config`——它们本就该在一起 +- 单体同进程调用,零网络开销(`UserInfoServiceImpl` 直接 `@Autowired PermissionServiceImpl`) + +**评价**:这不仅不是障碍,反而是**该整包带走的部分**。它恰恰证明了"账权是一个内聚域"。 + +| 判定 | 说明 | +|------|------| +| ✅ 全部保留 | 留在 Identity Service 内部,一个调用都不用动 | +| ❌ 无必须拆分项 | 这正是拆服务时"一起搬"的内容 | + +### 障碍 ⑤ 共享数据库(所有表同一 MySQL) + +**设计出发点**: +- 初期最快:不用设计服务边界、不用碰分布式事务 +- `customer_id` 共享键多租户,天然一张库(业务表靠这个字段关联 `customer_info`,不是外键) +- 表间逻辑关联多,放一起 JOIN 方便;一个 RDS 实例成本最低 + +**评价**:早期最务实的选择。**这是 6 条里唯一一个"实体层面真必须拆"的。** + +| 判定 | 说明 | +|------|------| +| ✅ 短期保留 | Phase 1-2(模块化隔离、引网关)完全可以不动库,不拆库也能推进 | +| 🔧 必须拆分(长期) | 要"真正独立"就必须拆——否则账权与业务仍共享存储,故障域/扩缩容/安全策略都分不开。拆库放到 Phase 3,且必须配双写过渡期 | + +### 障碍 ⑥ AOP 执行顺序依赖(DataSourceHeaderAspect `Order=1` + LoginAspect) + +**设计出发点**: +- `DataSourceHeaderAspect` 先 `AuthContext.clean()` 再切数据源 → 保证每个请求从干净状态开始,**防止上一请求的 ThreadLocal 泄漏/串号** +- 然后 `LoginAspect`(在 apes-commons 里)填充 AuthContext → 保证 Controller 执行业务前上下文已就绪 +- 这个顺序在"单进程内、请求串行经过切面"时完美工作 + +**评价**:"请求级清理 + 顺序保证"的防泄漏思路必须保留,它是并发安全的底线。 + +| 判定 | 说明 | +|------|------| +| ✅ 保留 | 请求级 ThreadLocal 清理 + 顺序保证的思路(防内存泄漏/串号是刚需) | +| 🔧 改造 | 职责归属变了——数据源路由可能在网关或各服务内,认证填充改由 `auth-sdk` 的 `AuthHeaderFilter` 做,顺序由本地 Filter chain 保证,而非跨 JAR 协商 | + +### 总分类 + +| 障碍 | 设计出发点是否合理 | 结论 | +|------|------------------|------| +| AuthContext ThreadLocal | ✅ 合理 | 保留机制,改造填充源与跨服务传播 | +| apes-commons 黑盒 | ✅ 合理(平台化) | 保留思路,收归自有 auth-sdk | +| OperationLogUtil 静态 | ✅ 合理(便利性) | 保留 API,改内部 10 行实现 | +| 账权 Service 内部调用 | ✅ 本就该内聚 | 全部保留,整包带走 | +| 共享数据库 | ⚠️ 早期务实 | 短期保留,长期必须拆(Phase 3 + 双写) | +| AOP 顺序依赖 | ✅ 合理(防泄漏) | 保留思路,改造职责归属 | + +**一句话总结**:6 条里有 4 条半是"好设计绑在了单体上"——思路保留、形态搬迁即可;只有"共享数据库"是实体层面真必须拆的,而"账权 Service 内部调用"根本不是障碍,是拆服务时该一起搬走的内聚域。 + +真正需要"动刀"的,其实就三件事: +1. **跨服务上下文传播**:ThreadLocal → 网关 Header(机制保留) +2. **存储边界**:共享库 → auth_db 独立(Phase 3) +3. **依赖主权**:外部 JAR → 自有 auth-sdk(兼容旧包名,业务零改动) + +--- + +## 6. 独立服务化可行性论证 + +### 6.1 有利因素 + +| 因素 | 说明 | +|------|------| +| Redis 共享会话 | 登录态存储在 Redis,天然支持分布式,服务拆分后会话无需迁移 | +| 无数据库外键约束 | 业务表与账权表之间是逻辑关联(customer_id),不是物理外键,拆库无 DDL 障碍 | +| 业务模块零直接依赖 | Trace*/Weight* 不 import 账权 Service,仅通过 AuthContext 间接获取登录态 | +| 账权域高内聚 | 账权 Service 间约 8 处内部调用,全在域内,整包带走即可 | +| AuthContext API 简单 | 主要调用模式是 `AuthContext.getLoginInfo().getCustomer().getId()`,可用 SDK 兼容替换 | + +### 6.2 风险因素 + +| 风险 | 等级 | 应对 | +|------|------|------| +| apes-commons 黑盒 | 中 | 收归自有 auth-sdk,Maven shade relocation 兼容旧包名 | +| 52 个文件引用 AuthContext | 低 | import 替换即可,方法签名不变 | +| 共享数据库拆分 | 高 | Phase 3 双写过渡期 + 数据一致性校验 | +| AOP 执行顺序 | 低 | 各服务内 Filter chain 保证,不跨 JAR 协商 | +| AccessTokenFilter 耦合 | 低 | 迁移到网关或 Identity Service 入口 | + +### 6.3 结论 + +**技术上可行**。业务模块与账权模块之间不存在直接代码调用(0 个 import),耦合仅通过 `AuthContext`(ThreadLocal)间接发生。登录态已存储在 Redis 中天然支持分布式。拆分的基础条件良好。 + +分阶段实施建议: + +| 阶段 | 目标 | 风险 | 预估 | +|------|------|------|------| +| Phase 1 | 单体内包级隔离 + 接口抽象 | 低 | 5-10 人天 | +| Phase 2 | 抽取 auth-sdk + 引入网关 | 中 | 10-15 人天 | +| Phase 3 | Identity Service 独立部署 + 数据库拆分 | 高 | 15-20 人天 | +| Phase 4 | JWT 升级 + 权限注解 + OAuth2 | 中 | 10+ 人天 | + +**建议立即启动 Phase 1**(风险最低、收益明确)。是否推进 Phase 2-3 取决于是否有多产品线复用账权的需求。 + +--- + +## 附:分析方法说明 + +本文档的分析基于以下方法: + +1. **静态代码走查**:通过 Agent 子任务深度遍历 `src/main/java` 全部包结构,读取所有关键 Controller/Service/Entity/Config 源码 +2. **Grep 量化统计**:使用 ripgrep 对源码树进行精确模式匹配,统计耦合度指标 +3. **依赖追踪**:通过 import 语句分析模块间依赖关系 +4. **设计意图推断**:从代码写法(AOP 顺序、静态封装、Redis key 设计等)反推设计者的决策出发点 +5. **可行性论证**:基于量化数据和架构特征,评估微服务拆分的技术可行性 + +分析工具链:Agent Explore 子任务 + Grep + Read,分析时间:2026-08-05 diff --git a/docs/账权平台-项目说明书.html b/docs/账权平台-项目说明书.html new file mode 100644 index 0000000..2d89c3a --- /dev/null +++ b/docs/账权平台-项目说明书.html @@ -0,0 +1,1044 @@ + + + + + +账权平台 — 项目说明书 + + + + + +
+

账权平台

+
项目技术说明书
+
+ 版本 1.0.0 + 2026-08-05 + cn.apes +
+
+ +
+ + + + + +
+

1项目概述

+ +

账权平台是一套面向农业产业链的 多租户 SaaS 综合管理平台,涵盖智慧农业、产品溯源、自助过磅、AI 智能助手等核心业务域。平台采用前后端分离架构,后端基于 Spring Boot + MyBatis Plus,前端基于 Vue 2 + Element UI,通过多租户动态数据源实现企业级数据隔离。

+ +
+
+
62
+
后端 Controller
+
+
+
85+
+
前端页面
+
+
+
10+
+
业务模块
+
+
+
85+
+
Mapper 接口
+
+
+ +

项目组成

+
+ + + + + + + + + + + + + + + + + + +
子项目技术栈说明端口
saas-serviceJava 11 / Spring Boot 2.2.1后端服务,提供全部 REST API7777(生产) / 8202(开发)
saas-webVue 2.7 / Element UI 2.15前端管理控制台8201(开发)
+
+ +

核心业务域

+
+
+
智慧农业
+
园区/地块/作物管理、灌溉计划、水肥一体机、电磁阀控制、农事计划、投入品管理、设备数据上报、摄像头监控
+
+
+
产品溯源
+
溯源码生成与绑定、码货关联、采收/加工/质检全链条、仓储出入库、物流追踪、溯源大屏
+
+
+
自助过磅
+
车辆/司机/IC卡管理、北斗卡借还追踪、称重票据、报警规则、过磅工作台、小票打印
+
+
+
AI Agent 平台
+
多厂商 LLM 配置、Agent 编排、Groovy 动态工具、Function Calling、技能注入、多轮对话、调用审计
+
+
+
多租户 SaaS
+
企业认证、套餐配额管理、角色权限体系、SSO 单点登录、AccessToken 开放平台
+
+
+
伙伴云集成
+
伙伴云低代码平台深度对接、表结构同步、数据 CRUD 代理、SSO 登录、AMIS 页面配置
+
+
+
+ + +
+

2系统架构

+ +

整体架构图

+
+
+
浏览器 / 移动端 / 外部系统
+
+
+
+
Nginx 反向代理
+
+
+
+
saas-web
Vue 2 + Element UI
+
saas-service
Spring Boot REST API
+
+
+
+
MySQL
cloud (主库)
+
MySQL
user (租户库)
+
Redis
DB7 / DB9
+
阿里云 OSS
文件存储
+
+
+
+
阿里云 DashScope
LLM API
+
伙伴云 OpenAPI
低代码平台
+
萤石云 API
视频监控
+
阿里云 ASR
语音识别
+
n8n
工作流引擎
+
+
+ +

技术栈总览

+
+ + + + + + + + + + + + + + + + + +
类别后端 (saas-service)前端 (saas-web)
核心框架Spring Boot 2.2.1 / Java 11Vue 2.7.14
路由/状态Vue Router 3.5 / Vuex 3.1
ORM / 数据MyBatis Plus 3.5.7 + 动态数据源 3.6.1
UI 组件Element UI 2.15.13
缓存Redis + Redisson 3.35.0localStorage
HTTPSpring MVCAxios 0.18.1
对象存储阿里云 OSS SDK 3.17.4
LLM / AIDashScope (OpenAI 兼容) + Groovy 3.0.19Monaco Editor / marked / highlight.js
WebSocketSpring WebSocket + Java-WebSocket原生 WebSocket (ASR)
工具库Hutool 5.8.16 / Lombok / Apache POIECharts 5.4 / 高德地图 / WangEditor
构建工具MavenVue CLI 4.4.4 / Webpack
+
+
+ + +
+

3后端服务 (saas-service)

+ +

3.1 基本信息

+
+ + + + + + + + + +
GroupId / ArtifactIdcn.apes / saas-service
版本1.0.0-SNAPSHOT
主启动类cn.apes.CloudApplication(启用 @EnableAsync / @EnableScheduling)
根包cn.apes.cloud
生产端口7777
开发端口8202
+
+ +

3.2 包结构

+
+cn.apes.cloud +├── config/ # 配置类(12个):RedissonConfig, OssConfig, DataSourceConfig... +├── controller/ # REST 控制器(62个) +│ └── traceability/ # 溯源模块控制器(9个) +├── domain/ # 数据模型层 +│ ├── entity/ # 核心实体(43个) +│ ├── dto/ # 数据传输对象(35个) +│ ├── vo/ # 视图对象(5个) +│ ├── huoban/ # 伙伴云数据模型(11个) +│ ├── traceability/ # 溯源数据模型(22个) +│ └── weight/ # 称重数据模型(13个) +├── filter/ # AccessToken 鉴权过滤器 +├── groovy/ # Groovy 脚本执行引擎 +│ ├── GroovyExecutorService.java # 编译+缓存+执行 +│ ├── GroovyToolExecutor.java # 工具接口 +│ └── JsonSchemaValidator.java # 入参校验 +├── mapper/ # MyBatis Mapper(85个) +│ └── traceability/ # 溯源 Mapper(20个) +├── service/ # 业务逻辑层 +│ ├── impl/ # 服务实现(90个) +│ │ └── huoban/ # 伙伴云服务(6个) +├── task/ # 定时任务(摄像头抓图) +├── util/ # 工具类 +└── websocket/ # ASR 语音识别 WebSocket 代理
+ +

3.3 数据源配置

+

采用 baomidou dynamic-datasource 实现多数据源动态切换,通过自定义 @TenantSource 注解 + AOP 切面,根据请求头 X-Tenant-ID 自动切换数据源。

+
+ + + + + + + +
数据源目标数据库用途
cloud(主库)MySQL 192.168.1.161:3306/cloud平台核心数据(用户、企业、权限、LLM 配置等)
user(租户库)MySQL 192.168.1.161:3306/user租户业务数据(溯源、农业、称重等)
huoban伙伴云 MySQL直连伙伴云数据库(数据同步/CRUD)
+
+ +
+ 多租户切换原理:请求头 X-Tenant-ID 值为 user/zx/plant 时,DataSourceHeaderAspect 切面自动调用 DynamicDataSourceContextHolder.push() 切换到对应数据源。默认使用 user 数据源。 +
+ +

3.4 核心配置类

+
+ + + + + + + + + +
配置类功能
RedissonConfigurationRedisson 客户端,DB7(主业务)+ DB9(辅助),JsonJackson 编解码
OssConfiguration阿里云 OSS,桶 zq-cloud,区域 oss-cn-beijing
DataSourceHeaderAspect多租户数据源切换 AOP 切面
AccessTokenFilterConfigAccessToken 外部 API 鉴权过滤器注册
WebSocketConfigASR 语音识别 WebSocket 端点 /asr/ws
+
+ +

3.5 定时任务

+
+
摄像头定时抓图 (CameraCaptureTask)
+
每小时执行一次,遍历所有摄像头调用萤石云 API 抓图,记录成功/失败统计日志。
+
+
+ + +
+

4前端应用 (saas-web)

+ +

4.1 基本信息

+
+ + + + + + + + + +
项目名称saas-web(账权平台)
框架Vue 2.7.14 + Vue Router 3.5.2 (History 模式) + Vuex 3.1.0
UI 组件库Element UI 2.15.13(中文语言包)
构建工具Vue CLI 4.4.4 + Webpack + Sass
开发端口8201(host: 0.0.0.0)
输出目录saas-web
+
+ +

4.2 目录结构

+
+src/ +├── main.js # 应用入口 +├── App.vue # 根组件 +├── api/ # API 接口层(35个文件) +├── assets/ # 静态资源 +├── components/ # 公共组件(面包屑/标签页/AI助手/大屏组件等) +├── config/ # 全局配置 +├── layout/ # 布局(TopHeader + Sidebar + TagsView) +├── router/ # 路由配置(静态路由 + 动态路由注册) +├── store/ # Vuex(user / settings / tagsView) +├── styles/ # 全局样式(SCSS 变量/Mixin/Element UI 覆盖) +├── utils/ # 工具函数(16个文件) +└── views/ # 页面视图(85+文件,41个子目录)
+ +

4.3 布局架构

+
+
+
layout/index.vue(主布局容器)
+
+
+
+
TopHeader
Logo + 应用Tab + 用户菜单
+
+
+
+
Sidebar
三级树形菜单
+
el-main
TagsView + keep-alive
+
+
+
+
router-view(页面内容)
+
iframeView(内嵌页面)
+
+
+
+ 独立大屏页面noLayout: true)不使用主布局,可脱离侧栏/顶栏独立访问,支持通过 URL Token 参数从外部系统直接跳转。包括:智慧农业大屏、武鸣沃柑大脑、溯源大屏。 +
+ +

4.4 动态路由系统

+

前端路由分为静态路由(登录/注册/认证等)和动态路由两部分。动态路由通过 menuApi.handleMenu() 根据后端返回的菜单数据动态注册:

+
+ + + + + + + + +
menuType类型路由前缀加载方式
1普通页面/common/{menuPath}动态 import vuePath 组件
2伙伴云内嵌/common/huoban/{id}加载 huoban/index 组件
3支付页面/common/payment/{id}加载 payment/index 组件
4Web 内嵌/common/web/{id}加载 web/index 组件
+
+ +

4.5 Vuex 状态管理

+
+ + + + + + + + + + + + + + + + + + + +
模块核心 State说明
userloginUser, menuList, currentCustomer, huobanToken, appList, currentApp, allAppMenus用户登录态、企业信息、菜单树、多应用切换
settingssidebarCollapsed侧栏折叠状态
tagsViewvisitedViews, cachedViews标签页管理,支持 localStorage 持久化
+
+ +

4.6 第三方库

+
+
ECharts 5.4
数据可视化图表,用于大屏和报表
+
高德地图
园区地图标注、物流轨迹追踪
+
Monaco Editor
VS Code 内核代码编辑器,支持 Java/Groovy/JSON/SQL 语法高亮
+
WangEditor
富文本编辑器,用于内容编辑
+
html2canvas
网页截图,用于大屏导出
+
marked + highlight.js
Markdown 渲染 + 代码高亮,用于 AI 对话展示
+
qrcodejs2
二维码生成,用于溯源码
+
萤石云 SDK
视频监控实时流播放
+
+
+ + +
+

5核心功能模块

+ +

5.1 用户与企业认证

+
    +
  • 用户注册/登录:密码登录 + 微信小程序登录(code2Session)
  • +
  • 企业认证:提交营业执照 → 平台审核 → 认证通过/驳回 → 重新提交
  • +
  • 多企业切换:一个用户可关联多个企业,支持切换当前企业
  • +
  • SSO 单点登录:支持企业配置 SSO,对接伙伴云 SSO 登录
  • +
  • AccessToken:外部 API 鉴权令牌,支持 IP 白名单、过期时间、启用/停用
  • +
+ +

5.2 智慧农业(飞翼)

+
    +
  • 园区 & 地块管理:园区信息 CRUD、地块信息管理(坐标、面积、作物关联)
  • +
  • 作物管理:作物信息、物候期管理(生长期阶段定义)
  • +
  • 农事计划:施肥/灌溉/采收计划制定与执行跟踪
  • +
  • 灌溉系统:灌溉计划管理、定时执行、执行记录、电磁阀远程控制
  • +
  • 水肥一体机:设备管理、母液罐配置、加药操作、加药日志、设备布局可视化
  • +
  • 投入品管理:肥料/农药等投入品库存管理、出入库日志
  • +
  • 设备数据上报:传感器数据采集(温湿度、土壤等)
  • +
  • 摄像头监控:萤石云摄像头管理、定时抓图、抓图日志
  • +
  • 可视化大屏:园区数据可视化大屏,含地图、图表、设备状态
  • +
+ +

5.3 产品溯源

+
    +
  • 溯源码管理:批量生成、码列表查询、绑定/解绑/作废/启用
  • +
  • 码货绑定:批量导入绑定、未绑定码查询、父子码关联
  • +
  • 全链条追溯:土地 → 采收 → 加工 → 质检 → 入库 → 出库 → 物流 → 反馈/召回
  • +
  • 资质与证书:企业资质管理、产品合格证生成
  • +
  • 仓储管理:入库/出库记录、库存查询、库位平面图
  • +
  • 溯源大屏:冷库温湿度、利用率、分级图表、采收进度、物流轨迹地图
  • +
  • H5 溯源页:消费者扫码查看产品全链条溯源信息
  • +
+ +

5.4 自助过磅

+
    +
  • 称重票据:一次称重 / 二次称重 / 编辑 / 打印全流程
  • +
  • 车辆 & 司机管理:车辆记录、司机信息、IC 卡管理
  • +
  • 北斗卡管理:借用 / 归还 / 追踪记录、报警规则与报警记录
  • +
  • 过磅工作台:自助过磅操作界面
  • +
  • 小票打印:独立打印页面,支持热敏打印机
  • +
+ +

5.5 套餐与配额管理

+
    +
  • 套餐方案:定义套餐包含的应用、权限、配额
  • +
  • 客户套餐:为客户分配套餐,管理配额增减
  • +
  • 配额管理:系统配额定义(如溯源码数量、AI 调用次数等)
  • +
  • 套餐延期:延期申请 → 审核 → 生效
  • +
  • 配额变更日志:完整记录配额增减历史
  • +
+ +

5.6 伙伴云集成

+
    +
  • 双模式集成:直连伙伴云 MySQL(@DS("huoban"))+ 伙伴云 OpenAPI 代理
  • +
  • 表结构同步:自动同步伙伴云表格结构到本地配置
  • +
  • 数据 CRUD 代理:通过平台 API 操作伙伴云表格数据
  • +
  • SSO 登录:平台 Token → 伙伴云 Token 免密登录
  • +
  • AMIS 低代码:支持 AMIS 页面配置和动态渲染
  • +
  • 自动化按钮:伙伴云自动化工作流触发
  • +
+
+ + +
+

6LLM / AI Agent 平台

+ +

平台内置完整的 LLM Agent 管理引擎,支持多厂商模型配置、Agent 编排、Groovy 动态工具、Function Calling 多轮对话、技能注入和全链路审计。

+ +

6.1 架构层次

+
+
+
Agent 配置 (LlmAgentConfig)
System Prompt / User Prompt / Output Type
+
+
+
+
厂商配置
LlmProviderConfig
+
模型配置
LlmModelConfig
+
关联工具
LlmAgentTool → LlmTool
+
关联技能
LlmAgentSkill → AiSkill
+
+
+
+
LLM 调用 (DashScope OpenAI 兼容 API)
多轮对话 + Function Calling(最多10轮)
+
+
+
+
GroovyExecutorService
动态编译执行工具脚本
+
LlmConversationMessage
消息持久化
+
+
+
+
LlmCallLog
调用日志审计
+
LlmToolLog
工具执行日志
+
+
+ +

6.2 核心能力

+
+
+
多厂商模型配置
+
支持配置多个 LLM 厂商(API Key、BaseUrl),每个厂商下可配置多个模型(chat/embedding/image),支持视觉模型
+
+
+
Function Calling
+
自动检测 LLM 返回的 tool_calls,执行对应 Groovy 工具脚本,将结果回传给 LLM 继续推理,最多 10 轮防止死循环
+
+
+
Groovy 动态工具
+
使用 GroovyClassLoader 动态编译脚本,编译结果缓存(ConcurrentHashMap),支持 JSON Schema 入参校验,无需重启即可添加新工具
+
+
+
技能系统
+
AiSkill 技能内容注入 System Prompt,为 Agent 提供领域知识,一个 Agent 可关联多个技能
+
+
+
多轮对话
+
LlmConversation 会话管理 + LlmConversationMessage 消息持久化,支持 system/user/assistant/tool_call/tool_result 多种消息类型
+
+
+
提示词模板
+
支持 {{variable}} 格式的变量替换,通过 userParams 传入动态参数
+
+
+
多模态输入
+
支持图片 URL(image_url)和视频 URL(video_url)输入,兼容视觉理解模型
+
+
+
输出类型控制
+
支持 text / json / markdown 三种输出格式,通过 response_format 控制
+
+
+
全链路审计
+
LlmCallLog 记录每次调用的 Token 用量、耗时、状态;LlmToolLog 记录工具执行的输入/输出/耗时/错误
+
+
+
ASR 语音识别
+
WebSocket 代理阿里云实时 ASR(fun-asr-realtime),PCM 16kHz 音频流式传输,前端实时显示转写结果
+
+
+ +

6.3 前端 AI 页面

+
+ + + + + + + + + + + +
页面路径功能
智能对话/ai/chat多轮对话界面,支持图片/视频上传、Markdown 渲染
Agent 配置/system/agentAgent CRUD、工具/技能关联、调试
模型管理/system/model厂商/模型配置
工具管理/system/toolGroovy 工具脚本编辑(Monaco Editor)+ 执行测试
技能管理/system/skillAI 技能 CRUD
对话历史/ai/conversation会话列表 + 消息详情
调用日志/system/callLogLLM 调用日志查询 + 统计
+
+
+ + +
+

7多租户与权限体系

+ +

7.1 多租户架构

+
+ 实现方式:基于 baomidou dynamic-datasource + 自定义 @TenantSource 注解 + AOP 切面,通过 HTTP 请求头 X-Tenant-ID 实现透明数据源切换。 +
+
+ + + + + + + +
租户标识数据源说明
user(默认)user 数据库标准租户业务数据
zxzx 数据库专线租户
plantplant 数据库种植租户
+
+ +

7.2 权限体系

+
+
+
套餐 (PackagePlan)
+
+
应用 (App)
+
+
+
+
菜单 (Menu)
+
+
权限 (Permission)
+
+
+
+
角色 (Role)
+
+
成员 (Member)
+
+
+
    +
  • 套餐 → 应用:套餐方案定义客户可使用的应用列表和配额
  • +
  • 应用 → 菜单/权限:每个应用有独立的菜单树和权限项
  • +
  • 角色 → 权限:角色绑定权限项,支持按应用分组
  • +
  • 成员 → 角色:企业成员分配角色,按企业维度管理
  • +
  • 前端动态路由:登录后根据权限动态生成路由和菜单
  • +
+ +

7.3 AccessToken 开放平台

+

为外部系统提供安全的 API 调用机制:

+
    +
  • Token 通过 X-Access-TokenAuthorization: Bearer 传递
  • +
  • 支持 IP 白名单限制
  • +
  • 支持启用/停用/重新生成
  • +
  • 校验通过后将用户/企业信息注入请求上下文
  • +
  • 配额扣减:开放接口可扣减客户套餐配额
  • +
+
+ + +
+

8API 接口概览

+ +

后端共 62 个 Controller,提供 300+ REST API 端点。所有接口前缀为 /api/user-service/(通过 Nginx 代理)。

+ +

8.1 接口模块总览

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
模块主要 Controller路径前缀核心端点
用户认证UserController/userloginPwd, register, getCurrentUser, selectCustomer, certifyEnterprise
CommonController/commonupload, code2Session, huobanWebLogin
客户管理CustomerController/customerpageCustomer, saveCustomer, employee/page, auditCertification, syncTenantsToHuoban
权限管理PermissionController/permissioncurrentMenus, getMyPermissionCodes, saveRole, setRolePermission, setMemberRole
AccessTokenAccessTokenController/sysAccessTokencreate, page, revoke, regenerate
LLM / AILlmChatController/llmChatstart(新对话), continue(多轮对话)
LlmAgentConfigController/llmAgentpage, add, update, delete, debug, call/{id}
LlmProviderConfigController/llmProviderpage, add, update, delete, list
LlmModelConfigController/llmModelpage, add, update, delete, list
LlmToolController + GroovyToolExecuteController/llmToolCRUD, execute(执行 Groovy 脚本), clearCache
LlmConversationController/llmConversationadd, detail, listByAgent, messages, close, delete
LlmCallLogController/llmCallLogpage, detail, statistics, batchDelete
伙伴云HuobanController / Huoban2Controller/huoban / /huoban2syncTables, data, create, update, upsert, webLogin, automationCall
溯源TraceCodeController/trace/codetask/generate, list/bind, bind/batchImport, relation/add
TraceCategoryController/trace/category分类 CRUD
TraceWarehouseController/trace/warehouse入库/出库 CRUD
TraceQualityController/trace/quality质检 CRUD
智慧农业FeiParkInfoController / PlotInfoController/park / /fei/plot园区/地块 CRUD
FeiIrrigationPlanController/irrigation/plan灌溉计划 CRUD + toggle 开关
FeiFertigationDeviceController/fertigation-device设备 CRUD, dosing(加药), save-layout
称重WeightController/weightticket(磅单), device, driver, card, beidou, alarmRule
套餐配额CustomerPackageController/customerPackagemyPackages, increaseQuota, decreaseQuota, submitExtendApply
开放平台OpenController/opentrackingConfig/getByCustomerId, customerPackage/decreaseQuota
+
+ +

8.2 前端 API 代理配置

+
+ + + + + + +
代理前缀目标路径重写
/api/user-servicehttp://localhost:8202^/api/user-service/
/n8nhttps://n8n.ccoop.cc^/n8n""
+
+
+ + +
+

9部署与配置

+ +

9.1 后端部署

+
+ + + + + + + + + + + + + + +
配置项生产环境 (prod)开发环境 (local)
服务端口77778202
主数据源192.168.1.161:3306/cloud192.168.31.201:3389/cloud
伙伴云数据源192.168.1.161:3306/user192.168.31.201:3389/user
Redis192.168.1.165:6403, DB7192.168.31.201:7890, DB7
OSSoss-cn-beijing.aliyuncs.com, bucket: zq-cloud
伙伴云 APIhttps://hb.zhangquyun.com/server/api
LLM APIhttps://dashscope.aliyuncs.com/compatible-mode/v1
文件上传限制max-file-size: 20MB, max-request-size: 200MB
构建命令mvn clean package -Pprod./publish.sh
启动命令java -jar saas-service.jar --spring.profiles.active=prod
+
+ +

9.2 前端部署

+
+ + + + + + + + + +
配置项
开发启动npm run dev(端口 8201)
生产构建npm run build:prod → 输出到 saas-web/ 目录
预发布构建npm run build:stage
构建脚本./publish.sh
部署方式Nginx 静态文件 + 反向代理到后端
+
+ +

9.3 数据库

+
+ 数据库引擎:MySQL 8.0+,字符集 UTF-8,时区 GMT+8
+ 逻辑删除:全局字段 isDel(1=已删除,0=正常),MyBatis Plus 自动处理
+ 数据库导出:db-export/cloud_full_*.sql(完整建库脚本) +
+ +

9.4 环境依赖

+
+ + + + + + + + + + +
组件版本要求用途
JDK11+后端运行时
Maven3.6+后端构建
Node.js8.9+前端构建
MySQL8.0+数据库
Redis6.0+缓存/分布式锁
Nginx1.18+反向代理/静态文件
+
+
+ + +
+

10项目目录结构

+ +

10.1 后端 (service-master)

+
+service-master/ +├── pom.xml # Maven 配置 +├── publish.sh # 发布脚本 +├── src/ +│ ├── main/ +│ │ ├── java/cn/apes/ +│ │ │ ├── CloudApplication.java # 主启动类 +│ │ │ └── cloud/ +│ │ │ ├── config/ # 配置类(12个) +│ │ │ ├── controller/ # 控制器(62个) +│ │ │ ├── domain/ # 数据模型 +│ │ │ ├── filter/ # 过滤器 +│ │ │ ├── groovy/ # Groovy 引擎 +│ │ │ ├── mapper/ # Mapper 接口(85个) +│ │ │ ├── service/ # 业务逻辑(90个实现类) +│ │ │ ├── task/ # 定时任务 +│ │ │ ├── util/ # 工具类 +│ │ │ └── websocket/ # WebSocket 处理器 +│ │ └── resources/ +│ │ ├── application.yml # 主配置 +│ │ ├── application-prod.yml # 生产配置 +│ │ └── application-local.yml # 开发配置 +│ └── test/ # 测试代码 +├── docs/ # API 文档(15个) +├── sql/ # SQL 脚本 +├── db-export/ # 数据库导出 +└── logs/ # 日志文件
+ +

10.2 前端 (web-master)

+
+web-master/ +├── package.json # 依赖配置 +├── vue.config.js # Vue CLI 配置 +├── publish.sh # 发布脚本 +├── src/ +│ ├── main.js # 应用入口 +│ ├── App.vue # 根组件 +│ ├── api/ # API 接口(35个文件) +│ │ └── fei/ # 智慧农业子接口 +│ ├── assets/ # 静态资源 +│ ├── components/ # 公共组件 +│ │ ├── ai/ # AI 组件 +│ │ ├── brain/ # 大脑组件 +│ │ └── tracing/screen/ # 溯源大屏组件(18个) +│ ├── config/ # 全局配置 +│ ├── layout/ # 布局组件 +│ │ └── components/ # TopHeader / Sidebar / TagsView +│ ├── router/ # 路由配置 +│ ├── store/ # Vuex(user / settings / tagsView) +│ ├── styles/ # 全局样式 +│ ├── utils/ # 工具函数(16个文件) +│ └── views/ # 页面视图(85+文件) +│ ├── ai/ # AI 对话 +│ ├── customer/ # 客户管理 +│ ├── fei/ # 智慧农业 +│ ├── huoban/ # 伙伴云 +│ ├── system/ # 系统管理 +│ ├── trace/ # 溯源管理 +│ ├── tracing/ # 溯源追踪 +│ └── weight/ # 自助过磅 +├── docs/ # 文档 +├── public/ # 公共静态文件 +└── logs/ # 日志
+
+ + + + +
+ + diff --git a/docs/账权模块独立服务化方案.html b/docs/账权模块独立服务化方案.html new file mode 100644 index 0000000..ade7a2d --- /dev/null +++ b/docs/账权模块独立服务化方案.html @@ -0,0 +1,1143 @@ + + + + + +账权模块独立服务化方案 + + + +
+ +

账权模块独立服务化方案

+

基于账权平台 service-master 源码分析 · 2026-08-05

+ + + + +

1 现状分析:账权模块的边界与耦合

+ +

1.1 账权模块的功能边界

+

通过对源码的全面扫描,当前单体应用中"账权"相关功能可归纳为以下五大域:

+ + + + + + + + +
功能域核心实体核心 Service核心 Controller
用户认证UserInfo, SsoConfigUserInfoServiceImpl, SsoServiceImpl, Sso2ServiceImplUserController
权限管理SysRole, SysPermission, SysMenu, SysRolePermission, SysMemberRolePermissionServiceImplPermissionController
租户管理CustomerInfo, CustomerUser, SysOrganizationCustomerInfoServiceImpl, CustomerUserServiceImpl, SysOrganizationServiceImplCustomerController, SysOrganizationController
套餐配额SysPackagePlan, SysPackagePlanPermission, SysQuota, CustomerPackage, CustomerPackageQuotaSysPackagePlanServiceImpl, CustomerPackageServiceImpl, SysQuotaServiceImplSysPackagePlanController, CustomerPackageController
开放认证SysAccessTokenSysAccessTokenServiceImplAccessTokenController
+ +

1.2 耦合度量化

+ +
+
+
52
+
文件直接引用 AuthContext
+
+
+
111
+
AuthContext 调用总次数
+
+
+
11
+
文件引用 OperationLogUtil
+
+
+
0
+
业务 Service 直接 import 账权 Service
+
+
+ +
+
关键发现
+

溯源(Trace*)和过磅(Weight*)等业务模块 不直接 import 任何账权 Service,它们仅通过 AuthContext.getLoginInfo().getCustomer().getId() 获取当前租户 ID。这意味着业务模块与账权模块的耦合是通过共享上下文(ThreadLocal + Redis)间接耦合,而非直接代码调用——这为服务化拆分提供了极好的基础。

+
+ +

1.3 耦合关系详解

+ +

① AuthContext(ThreadLocal)— 全局耦合

+

AuthContext 来自外部库 apes-commons,是整个系统的"认证上下文总线"。所有业务模块通过它获取当前登录用户和租户信息:

+
// 典型使用模式(出现 52 个文件中)
+LoginCustomer customer = AuthContext.getLoginInfo().getCustomer();
+Long customerId = customer.getId();
+// 然后在查询中添加 WHERE customer_id = customerId
+ +

② OperationLogUtil — 静态工具耦合

+

OperationLogUtil 内部依赖 AuthContext 获取操作人信息,被 11 个文件调用。它通过 @PostConstruct 注入静态 SysOperationLogService,形成了"静态方法 → Spring Bean → AuthContext"的隐式依赖链。

+ +

③ 账权模块内部 — Service 间直接调用

+ + + + + + + + + + +
调用方被调用方调用内容
UserInfoServiceImplPermissionServiceImplgetUserRoles()
UserInfoServiceImplCustomerUserServiceImplgetCustomers(), getCustomerListByUserIds()
UserInfoServiceImplCustomerInfoServiceImplgetById()
PermissionServiceImplSsoServiceImpl / Sso2ServiceImplgetUserConfig(), getPageUrl()
PermissionServiceImplUserInfoMapperselectById()
PermissionServiceImplCustomerPackageMapperselectList()
PermissionServiceImplSysPackagePlanMapperselectById()
AccessTokenFilterCustomerInfoServiceImplgetById()
+ +

④ Redis 共享会话 — 天然分布式基础

+

登录态存储在 Redis 中(Key = 加密 Token,Value = 用户 JSON;Key = Token:customer,Value = 企业 JSON),TTL 1 天。这是拆分的最有利条件——任何服务只要能访问同一个 Redis,就能读取登录态。

+ +

⑤ apes-commons 库 — 认证框架黑盒

+

核心认证逻辑(LoginAspect AOP 拦截、AuthContext ThreadLocal 管理、@Login 注解)封装在外部 JAR 包 apes-commons:0.0.7-SNAPSHOT 中,源码不在项目内。当前所有 Controller 通过 @Login 注解声明需要登录校验,由 LoginAspect 从 Redis 读取 Token 并填充 AuthContext

+ +
+ + + + + + + + + + + +当前单体架构 — 账权耦合关系图 + + + +单体应用 (service-master) + + + +apes-commons (外部JAR) +AuthContext · @Login · LoginAspect · UserSession + + + +账权模块 +UserInfoService +PermissionService +CustomerInfoService +AccessTokenService +PackagePlanService +SsoService + + + +业务模块 +TraceProductService +WeightTicketService +TraceCodeService +ExtLinkService +CustomerUiConfigService +FeiFertigationService + + + +AI/Agent 模块 +ChatSessionService +ToolService +AgentService +KnowledgeService + + + +Redis (共享会话) + + + + + +AuthContext +AuthContext + + + + + + + +读写 Token +读 Token + + + +无直接调用 ✓ + +
+ + +

2 可行性判断:能不能拆?该不该拆?

+ +

2.1 能不能拆?—— 技术可行性

+ +
+
+

✓ 有利因素

+
    +
  • Redis 共享会话:登录态天然存储在 Redis,任何服务都能读取,无需迁移认证机制
  • +
  • 业务模块零直接依赖:Trace*/Weight* 不 import 账权 Service,仅通过 AuthContext 获取租户 ID
  • +
  • 无数据库外键约束:所有表关联为逻辑关联,数据库拆分无物理障碍
  • +
  • AccessToken 机制已具备开放能力:已有外部系统认证的基础设施
  • +
  • 无跨服务远程调用:当前无 Feign/RestTemplate,不需要重构已有远程调用
  • +
  • 数据源已配置多库:dynamic-datasource 框架已就位,多库支持基础已有
  • +
+
+
+

⚠ 主要障碍

+
    +
  • AuthContext 深度耦合:52 个文件、111 处调用,需统一替换为新的上下文传递机制
  • +
  • apes-commons 黑盒:认证核心逻辑在外部 JAR,需替换或重构认证框架
  • +
  • OperationLogUtil 静态依赖:11 个文件通过静态方法调用,内部依赖 AuthContext
  • +
  • 账权 Service 间内部调用:UserInfoService → PermissionService → SsoService 等直接注入
  • +
  • 共享数据库:所有表在同一 MySQL 库,拆分需数据库迁移
  • +
  • AOP 执行顺序依赖:DataSourceHeaderAspect(Order=1) 与 LoginAspect 有隐式协作
  • +
+
+
+ +
+
结论:技术上可行
+

核心判断依据是"业务模块与账权模块之间不存在直接代码调用"。耦合仅发生在 AuthContext(ThreadLocal 上下文)层面,这种耦合可以通过网关解析 Token + HTTP Header 传递的方式完全消除。改造工作量主要集中在替换 AuthContext 和解耦 apes-commons,而非重构业务代码。

+
+ +

2.2 该不该拆?—— 业务驱动力分析

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
维度当前痛点独立后的收益优先级
多产品复用账权逻辑锁在单体中,新产品(如独立 AI Agent 平台、移动端)要么整体依赖单体,要么重复实现一套账权服务支撑多个前端产品线,避免重复建设
独立演进账权变更需整体重新部署,业务模块也跟着重启账权服务独立发布、独立扩缩容,不影响业务服务
开放平台AccessToken 机制已在单体内,但第三方接入需走单体 API,无法独立管控独立 OAuth2 服务,支持第三方应用授权、API 网关统一鉴权
安全合规用户密码、Token 等敏感数据与业务数据混在同一库,权限边界模糊账权数据库独立,可实施更严格的安全策略(网络隔离、审计、加密)
性能隔离大量登录/鉴权请求与业务请求混在同一进程,相互影响账权服务可独立扩容,登录高峰不影响业务处理
+ +
+
建议:有条件地拆
+

如果团队有多产品线复用账权的需求(如独立 AI Agent 平台、移动端 App、开放平台),则拆分收益明确,值得投入。如果当前只有一个前端产品且近期无扩展计划,则优先在单体内做模块化隔离(包结构拆分 + 接口抽象)即可,暂不需微服务化。

+
+ + +

3 目标架构设计

+ +

3.1 整体架构

+ +
+ + + + + + + +目标架构 — 账权服务独立化 + + + +Web 前端 / 移动端 / 第三方应用 + + + +API Gateway (Spring Cloud Gateway) +Token 解析 → 注入 X-User-Id / X-Customer-Id / X-Roles Header + + + + + + +Identity Service (账权服务) + +· 用户注册/登录/密码管理 +· 角色/权限/菜单管理 +· 租户(企业)/组织架构 +· 套餐/配额管理 +· AccessToken / OAuth2 +· SSO 对接 +Spring Boot · 独立部署 · 独立数据库 + + + +Business Service (业务服务) + +· 溯源管理 (Trace*) +· 自助过磅 (Weight*) +· 智慧农业 (FeiFertigation*) +· 外部链接 (ExtLink*) +· UI 配置 (CustomerUiConfig*) +Spring Boot · 独立部署 · 独立数据库 + + + +AI Agent Service (智能服务) + +· 对话管理 (ChatSession*) +· Function Calling +· 知识库 (Knowledge*) +· Agent 编排 +Spring Boot · 独立部署 · 独立数据库 + + + + + +/auth/** /user/** +/trace/** /weight/** +/ai/** /agent/** + + + +auth_db (MySQL) + + + +business_db (MySQL) + + + +ai_db (MySQL) + + + + + + + + +Redis (共享会话 + 缓存) + + + + + + + + +auth-sdk (共享 JAR) + +
+ +

3.2 架构要点说明

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
组件职责技术选型
API Gateway统一入口,路由转发,Token 解析与校验,将用户信息注入 HTTP Header 传递给下游服务Spring Cloud Gateway
Identity Service用户/权限/租户/套餐/AccessToken 的全部管理,Token 签发与校验Spring Boot + MyBatis Plus
Business Service溯源/过磅/农业等业务功能,通过 Header 接收用户上下文原有单体业务代码剥离
auth-sdk轻量级 SDK JAR,供 Business/AI 服务引入,提供:Header 解析、AuthContext 替代品、权限校验注解纯 Java JAR,无 Spring 依赖
Redis共享会话存储(Token → 用户/租户信息),所有服务共用Redisson(沿用现有)
消息队列(可选)用户/租户信息变更时广播通知,减少跨服务实时查询RabbitMQ / RocketMQ
+ + +

4 核心技术方案

+ +

4.1 认证上下文传递机制改造

+ +

核心变更:用"网关解析 Token → HTTP Header 传递"替代当前的"每个服务各自从 Redis 读取 Token → 填充 ThreadLocal"。

+ +

改造前(当前架构)

+
请求 → AccessTokenFilter → DataSourceHeaderAspect(clean AuthContext)
+     → LoginAspect(从Redis读Token → 填充AuthContext)
+     → Controller(@Login) → Service(AuthContext.getLoginInfo())
+ +

改造后(目标架构)

+
请求 → API Gateway
+       ├─ 从 Header 提取 Token
+       ├─ 调用 Identity Service 的 /auth/verify 接口(或直接读 Redis)
+       ├─ 解析出 userId, customerId, roles, permissions
+       └─ 注入 HTTP Header: X-User-Id, X-Customer-Id, X-User-Name, X-Roles
+     → 路由到下游服务
+       ├─ auth-sdk 的 AuthFilter 解析 Header → 填充 ServiceAuthContext
+       └─ Controller → Service(ServiceAuthContext.getUserId())
+ +

auth-sdk 设计

+
// auth-sdk 提供的核心类(替代 apes-commons 的 AuthContext)
+
+public class ServiceAuthContext {
+    private static final ThreadLocal<AuthInfo> CONTEXT = new ThreadLocal<>();
+
+    public static void set(AuthInfo info) { CONTEXT.set(info); }
+    public static AuthInfo get() { return CONTEXT.get(); }
+    public static void clear() { CONTEXT.remove(); }
+
+    // 便捷方法
+    public static Long getUserId() { return get() != null ? get().getUserId() : null; }
+    public static Long getCustomerId() { return get() != null ? get().getCustomerId() : null; }
+    public static String getUserName() { return get() != null ? get().getUserName() : null; }
+    public static List<String> getRoles() { return get() != null ? get().getRoles() : Collections.emptyList(); }
+}
+
+public class AuthInfo {
+    private Long userId;
+    private Long customerId;
+    private String userName;
+    private String userPhone;
+    private List<String> roles;
+    private List<String> permissions;
+    // getters/setters...
+}
+
+// 网关注入的 Header → ThreadLocal 的 Filter
+@Component
+@Order(1)
+public class AuthHeaderFilter implements Filter {
+    @Override
+    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
+        HttpServletRequest request = (HttpServletRequest) req;
+        AuthInfo info = new AuthInfo();
+        info.setUserId(parseLong(request.getHeader("X-User-Id")));
+        info.setCustomerId(parseLong(request.getHeader("X-Customer-Id")));
+        info.setUserName(request.getHeader("X-User-Name"));
+        info.setRoles(parseList(request.getHeader("X-Roles")));
+        ServiceAuthContext.set(info);
+        try {
+            chain.doFilter(req, res);
+        } finally {
+            ServiceAuthContext.clear();
+        }
+    }
+}
+ +
+
兼容性策略
+

为降低改造成本,auth-sdk 可提供一个 AuthContext 兼容适配器,使其 API 与 apes-commons.AuthContext 保持一致(getLoginInfo().getUser().getId() 等),这样业务代码只需将 import 从 cn.apes.commons.auth.AuthContext 改为 cn.apes.sdk.auth.AuthContext,方法调用不变。

+
+ +

4.2 Token 机制升级

+ +

当前使用 RSA 加密的随机 ID 作为 Token,存储在 Redis 中。建议升级为 JWT + Redis 混合方案

+ + + + + + + + + + + + + + + + + + +
方案说明优缺点
方案 A:JWT(推荐)Token 本身携带 userId, customerId, roles 等信息,网关直接解析,无需查 Redis✓ 无状态,性能最优 ✓ 网关可独立解析
✗ Token 无法主动失效(需配合 Redis 黑名单)
方案 B:Redis Token(兼容现有)保持现有机制,网关从 Redis 读取 Token 信息后注入 Header✓ 改造成本最低 ✓ Token 可主动失效
✗ 每次请求需查 Redis ✗ 网关依赖 Redis
方案 C:JWT + Redis 黑名单JWT 无状态解析 + Redis 存储已注销的 Token(黑名单)✓ 性能好 ✓ 可主动失效
✗ 实现略复杂
+ +

推荐方案 C,JWT Payload 设计:

+
{
+  "sub": "userId",           // 用户ID
+  "cid": "customerId",       // 租户ID
+  "cname": "customerName",   // 租户名称
+  "uname": "nickName",       // 用户昵称
+  "phone": "138****1234",    // 脱敏手机号
+  "roles": ["admin", "user"],// 角色列表
+  "perms": ["trace:view", "weight:edit"], // 权限码列表
+  "iat": 1691234567,         // 签发时间
+  "exp": 1691320967          // 过期时间(24h)
+}
+ +

4.3 权限校验机制升级

+ +

当前系统仅校验登录态,不校验具体权限(无 @PreAuthorize、无 Shiro 注解),权限控制依赖前端菜单过滤。服务化后建议增加后端权限校验:

+ +
// auth-sdk 提供的权限注解 + AOP
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RequiresPermission {
+    String[] value();          // 权限码,如 "trace:product:add"
+    Logical logical() default Logical.AND;
+}
+
+// AOP 切面
+@Aspect
+@Component
+public class PermissionAspect {
+    @Around("@annotation(requiresPermission)")
+    public Object check(ProceedingJoinPoint pjp, RequiresPermission requiresPermission) throws Throwable {
+        List<String> userPerms = ServiceAuthContext.get().getPermissions();
+        String[] required = requiresPermission.value();
+        boolean hasPermission = requiresPermission.logical() == Logical.AND
+            ? Arrays.asList(required).stream().allMatch(userPerms::contains)
+            : Arrays.asList(required).stream().anyMatch(userPerms::contains);
+        if (!hasPermission) {
+            throw new ForbiddenException("权限不足");
+        }
+        return pjp.proceed();
+    }
+}
+
+// 使用示例
+@RestController
+@RequestMapping("/trace/product")
+public class TraceProductController {
+    @RequiresPermission("trace:product:add")
+    @PostMapping
+    public Res add(@RequestBody TraceProductDTO dto) { ... }
+
+    @RequiresPermission("trace:product:delete")
+    @DeleteMapping("/{id}")
+    public Res delete(@PathVariable Long id) { ... }
+}
+ +

4.4 跨服务数据查询方案

+ +

业务服务偶尔需要查询用户/租户信息(如显示操作人姓名)。方案:

+ + + + + + + + + + + + + + + + + + +
方案适用场景实现
JWT Payload 携带仅需 userId, customerId, userName 等基础信息直接从 ServiceAuthContext 读取,零网络开销
Identity Service API需要完整用户/租户信息Feign Client 调用 GET /auth/user/{id}GET /auth/customer/{id}
Redis 缓存 + MQ 同步高频查询的场景用户信息变更时通过 MQ 广播,业务服务更新本地 Redis 缓存
+ +
// Feign Client 示例
+@FeignClient(name = "identity-service", url = "${service.identity.url}")
+public interface IdentityFeignClient {
+
+    @GetMapping("/auth/user/{userId}")
+    Res<UserDTO> getUser(@PathVariable("userId") Long userId);
+
+    @GetMapping("/auth/customer/{customerId}")
+    Res<CustomerDTO> getCustomer(@PathVariable("customerId") Long customerId);
+
+    @GetMapping("/auth/user/{userId}/permissions")
+    Res<List<String>> getUserPermissions(@PathVariable("userId") Long userId,
+                                           @RequestParam("customerId") Long customerId);
+
+    @GetMapping("/auth/user/{userId}/menus")
+    Res<List<MenuDTO>> getUserMenus(@PathVariable("userId") Long userId,
+                                      @RequestParam("customerId") Long customerId);
+}
+ +

4.5 OperationLogUtil 改造

+ +

当前 OperationLogUtil 静态方法内部依赖 AuthContext,改造为依赖 ServiceAuthContext

+ +
// 改造前
+public static void log(String module, String action, String description) {
+    LoginUser user = AuthContext.getLoginInfo().getUser();       // 依赖 apes-commons
+    LoginCustomer customer = AuthContext.getLoginInfo().getCustomer();
+    // ...
+}
+
+// 改造后
+public static void log(String module, String action, String description) {
+    AuthInfo auth = ServiceAuthContext.get();                     // 依赖 auth-sdk
+    if (auth == null) return;
+    logService.log(auth.getUserId(), auth.getUserName(),
+                   auth.getCustomerId(), auth.getCustomerName(),
+                   module, action, maskDescription(description));
+}
+ +
+
零侵入改造
+

由于 OperationLogUtillog() 方法签名不变,11 个调用方文件无需修改任何代码——只需更新 OperationLogUtil 自身的实现(从 AuthContext 切换到 ServiceAuthContext),并将 OperationLogUtil 迁移到 auth-sdk 中。

+
+ + +

5 数据库拆分策略

+ +

5.1 表归属划分

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
归属表名说明
auth_db
(Identity Service)
user_info用户基础信息
customer_info租户(企业)信息
customer_user用户-租户关联
sys_role角色
sys_permission权限
sys_menu菜单
sys_role_permission角色-权限关联
sys_member_role用户-角色关联(含租户ID)
sys_organization组织架构
sys_access_tokenAccessToken
sys_package_plan套餐计划
sys_package_plan_permission套餐-权限关联
sys_quota / sys_package_plan_quota配额模板
sso_configSSO 配置
auth_db
(扩展)
customer_package客户套餐关联
customer_package_quota客户配额实例
customer_quota_change_log配额变更日志
customer_package_extend_apply套餐延期申请
business_db
(Business Service)
trace_* (20+ 表)溯源业务表
weight_* (10+ 表)过磅业务表
customer_ui_config / ext_link业务配置表
ai_db
(AI Service)
chat_session / chat_message / tool_*AI 对话相关表
+ +

5.2 跨库查询处理

+ +

当前系统中,业务表通过 customer_id 关联 customer_info。拆库后:

+ +
    +
  • 常规场景:业务表只需要 customer_id 作为外键标识,不需要 JOIN 查询 customer_info——租户名称等信息从 JWT Payload 或 ServiceAuthContext 获取
  • +
  • 列表展示场景:需要显示租户名称时,先查业务表获取 customer_id 列表,再批量调用 Identity Service API 补全名称(或使用 Redis 缓存)
  • +
  • 操作日志表sys_operation_log 表已冗余存储 user_namecustomer_name,可放入 business_db 或独立日志库,不依赖 auth_db
  • +
+ +

5.3 套餐配额的跨服务消费

+ +

套餐配额(如溯源码生成数量限制)需要在业务服务中检查。方案:

+
// 业务服务通过 Feign 调用 Identity Service 检查配额
+@PostMapping("/trace/code/generate")
+public Res generateCode(@RequestBody GenerateDTO dto) {
+    // 1. 检查配额
+    QuotaCheckResult result = identityFeignClient.checkQuota(
+        ServiceAuthContext.getCustomerId(), "trace_code", dto.getCount()
+    );
+    if (!result.isAllowed()) {
+        return Res.fail("配额不足,剩余: " + result.getRemaining());
+    }
+    // 2. 执行业务
+    traceCodeService.generate(dto);
+    // 3. 扣减配额(Identity Service 内部处理)
+    identityFeignClient.consumeQuota(
+        ServiceAuthContext.getCustomerId(), "trace_code", dto.getCount()
+    );
+    return Res.ok();
+}
+ + +

6 解耦改造详细方案

+ +

6.1 改造影响范围矩阵

+ + + + + + + + + + + + + +
改造项影响文件数改造方式难度
AuthContext → ServiceAuthContext52替换 import(兼容 API)
OperationLogUtil 实现1(自身)内部实现替换,迁移到 auth-sdk
OperationLogUtil 调用方11更新 import(方法签名不变)
apes-commons 替换全局Maven 依赖替换为 auth-sdk
@Login 注解替换62(所有Controller)替换注解 import 或保留兼容
DataSourceHeaderAspect1重构或移除(网关接管数据源路由)
AccessTokenFilter1迁移到网关层
账权 Service 间调用~8保持同服务内调用(在 Identity Service 内部)
业务 Service → 账权 Service0无需改造(本来就没有直接调用)
数据库拆分导出 auth 相关表到新库
+ +

6.2 AuthContext 兼容适配方案(最小化改动)

+ +

为了将 52 个文件的改动降到最低,auth-sdk 提供 API 完全兼容的 AuthContext 替代品:

+ +
// auth-sdk 中的兼容 AuthContext(包名可保持一致或通过 Maven relocation)
+package cn.apes.sdk.auth;
+
+// 保持与 apes-commons.AuthContext 完全相同的 API
+public class AuthContext {
+    private static final ThreadLocal<UserSession> HOLDER = new ThreadLocal<>();
+
+    public static UserSession getLoginInfo() {
+        return HOLDER.get();
+    }
+
+    public static void setLoginInfo(UserSession session) {
+        HOLDER.set(session);
+    }
+
+    public static void clean() {
+        HOLDER.remove();
+    }
+}
+
+// UserSession 保持字段结构一致
+public class UserSession {
+    private LoginUser user;
+    private LoginCustomer customer;
+    private String token;
+    // getters/setters...
+}
+
+// AuthHeaderFilter 从 HTTP Header 构建 UserSession
+@Component
+@Order(1)
+public class AuthHeaderFilter implements Filter {
+    @Override
+    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
+            throws IOException, ServletException {
+        HttpServletRequest request = (HttpServletRequest) req;
+
+        // 从网关注入的 Header 构建 UserSession
+        LoginUser user = new LoginUser();
+        user.setId(parseLong(request.getHeader("X-User-Id")));
+        user.setNickName(request.getHeader("X-User-Name"));
+        user.setPhone(request.getHeader("X-User-Phone"));
+
+        LoginCustomer customer = new LoginCustomer();
+        customer.setId(parseLong(request.getHeader("X-Customer-Id")));
+        customer.setCustomerName(request.getHeader("X-Customer-Name"));
+
+        UserSession session = new UserSession();
+        session.setUser(user);
+        session.setCustomer(customer);
+        session.setToken(request.getHeader("X-Token"));
+
+        AuthContext.setLoginInfo(session);
+        try {
+            chain.doFilter(req, res);
+        } finally {
+            AuthContext.clean();
+        }
+    }
+}
+ +

这样业务代码的改动仅为一行 import 替换

+
// 改前
+import cn.apes.commons.auth.AuthContext;
+
+// 改后
+import cn.apes.sdk.auth.AuthContext;
+
+// 方法调用完全不变
+AuthContext.getLoginInfo().getCustomer().getId();  // ✓
+ +

6.3 @Login 注解兼容方案

+ +

当前 62 个 Controller 类/方法使用 @Login 注解。在 auth-sdk 中提供同名注解,并由 AuthHeaderFilter 替代 LoginAspect 的功能:

+ +
// auth-sdk 中提供 @Login 注解(标记需要登录的接口)
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Login {
+    boolean required() default true;
+}
+
+// auth-sdk 中的 LoginAspect(仅校验 AuthContext 是否有值,不查 Redis)
+@Aspect
+@Component
+@Order(2)
+public class LoginAspect {
+    @Around("@within(login) || @annotation(login)")
+    public Object check(ProceedingJoinPoint pjp, Login login) throws Throwable {
+        if (login.required() && AuthContext.getLoginInfo() == null) {
+            throw new UnauthorizedException("未登录");
+        }
+        return pjp.proceed();
+    }
+}
+ +
+
更进一步:可使用 Maven jar-shade 插件
+

通过 Maven 的 maven-shade-pluginrelocation 功能,可以将 cn.apes.commons.auth 包名重定向到 cn.apes.sdk.auth,这样所有业务代码的 import 语句完全不需要修改——只需在 pom.xml 中将 apes-commons 依赖替换为 auth-sdk

+
+ + +

7 迁移路径与实施计划

+ +

7.1 分阶段迁移策略

+ +
+
+1 +

Phase 1:模块化隔离(单体内)

+
+

目标:在单体应用内将账权代码与业务代码做包级隔离,建立清晰边界。

+
    +
  • 将账权相关代码迁移到 cn.apes.cloud.auth 包下(Controller/Service/Entity/Mapper/Config)
  • +
  • 将业务代码迁移到 cn.apes.cloud.business 包下
  • +
  • 提取账权模块的对外接口为 AuthFacade 接口,业务模块只依赖接口
  • +
  • 统一 AuthContext 的使用规范,消除不规范的直接 Mapper 调用
  • +
  • 不拆数据库,不引入网关,不影响部署
  • +
+

风险低 可在 1-2 周内完成 需全量回归测试

+
+ +
+
+2 +

Phase 2:auth-sdk 抽取 + 认证机制改造

+
+

目标:抽取 auth-sdk JAR,替换 apes-commons,引入网关。

+
    +
  • 创建 auth-sdk Maven 项目,包含:兼容 AuthContext、AuthHeaderFilter、@Login 注解、LoginAspect、OperationLogUtil
  • +
  • 使用 Maven shade relocation 保持 cn.apes.commons.auth 包名兼容
  • +
  • 引入 Spring Cloud Gateway,配置 Token 解析 → Header 注入逻辑
  • +
  • 将单体应用注册到网关(此时单体仍包含账权代码,但认证由网关处理)
  • +
  • 不拆数据库,单体仍访问同一 MySQL
  • +
+

风险中 2-3 周 需重点测试认证流程

+
+ +
+
+3 +

Phase 3:Identity Service 独立部署

+
+

目标:将账权代码从单体中剥离,部署为独立微服务。

+
    +
  • 创建 identity-service Maven 项目,迁移 Phase 1 隔离的账权代码
  • +
  • 拆分数据库:导出 auth 相关表到 auth_db
  • +
  • 单体(现 Business Service)移除账权代码,通过 Feign 调用 Identity Service
  • +
  • 网关路由配置:/auth/** → Identity Service,/trace/** 等 → Business Service
  • +
  • Token 签发逻辑迁移到 Identity Service,网关通过 API 校验 Token
  • +
+

风险高 3-4 周 需数据库迁移 + 全量回归

+
+ +
+
+4 +

Phase 4:完善与优化

+
+

目标:完善权限校验、配额管理、开放平台等高级能力。

+
    +
  • 后端权限注解 @RequiresPermission 全量覆盖
  • +
  • JWT + Redis 黑名单替换 RSA Token 机制
  • +
  • OAuth2 授权码模式支持第三方应用接入
  • +
  • 用户/租户信息变更 MQ 广播 + Redis 缓存
  • +
  • AI Agent Service 独立拆分(可选)
  • +
+

风险中 持续迭代

+
+ +

7.2 迁移时间线

+ +
+ +迁移时间线(建议) + + + + + + +Phase 1 +模块化隔离 +1-2 周 + +包结构隔离 +接口抽象 + + + +Phase 2 +SDK + 网关 +2-3 周 + +auth-sdk 抽取 +网关引入 + + + +Phase 3 +服务独立 +3-4 周 + +数据库拆分 +独立部署 + + + +Phase 4 +完善优化 +持续 + +权限注解 +JWT/OAuth2 + +
+ + +

8 风险评估与应对

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
风险影响概率应对措施
认证中断
迁移过程中 Token 机制变更导致用户掉线
Phase 2 保持 Redis Token 机制不变,仅改上下文传递方式;JWT 升级推迟到 Phase 4;支持新旧 Token 并存期
跨服务调用延迟
业务服务需远程调用 Identity Service 查询用户/权限信息
JWT Payload 携带基础信息减少远程调用;Redis 缓存热点用户/租户信息;MQ 广播变更
数据库拆分数据不一致
迁移过程中 auth_db 与 business_db 数据不同步
Phase 3 先双写(同时写旧库和新库),验证一致后切换读新库,最后停止写旧库
apes-commons 兼容问题
shade relocation 可能遗漏某些内部类或反射调用
Phase 2 充分测试;保留 apes-commons 作为 fallback 依赖直到 Phase 3 完成后移除
网关单点故障
所有请求经过网关,网关宕机导致全站不可用
网关集群部署 + 负载均衡;网关无状态化设计;配置降级策略(网关故障时直接路由)
配额检查性能
业务操作前需远程检查配额,增加请求延迟
Redis 缓存配额信息(TTL 5 分钟);批量操作时一次性检查;允许短时超卖(最终一致)
团队学习成本
微服务架构对团队提出更高要求
Phase 1-2 不引入复杂中间件(无注册中心/配置中心);先用 Nginx 做网关,后续再引入 Spring Cloud Gateway
+ + +

9 结论与建议

+ +
+
核心结论
+

账权模块可以抽象为独立服务。核心依据是当前架构中业务模块与账权模块之间不存在直接代码调用(0 个业务 Service import 账权 Service),耦合仅通过 AuthContext ThreadLocal 间接发生,且登录态已存储在 Redis 中天然支持分布式。通过"网关解析 Token → HTTP Header 传递 → auth-sdk 解析"的方式,可以将 52 个文件的 AuthContext 耦合以最小改动(import 替换)的方式消除。

+
+ +

建议的行动路径

+ +
    +
  1. 立即启动 Phase 1(模块化隔离):在单体内做包结构隔离和接口抽象,风险最低、收益明确,为后续拆分打下基础
  2. +
  3. 评估多产品需求:如果近期有 AI Agent 平台独立部署、移动端 App 接入、开放平台等需求,则推进 Phase 2-3;否则停留在 Phase 1 即可
  4. +
  5. 引入网关是关键转折点:Phase 2 引入网关后,认证机制从"各服务自行查 Redis"变为"网关统一解析",这是微服务化的基础设施前提
  6. +
  7. 不急于拆数据库:Phase 3 才拆数据库。Phase 1-2 可保持共享数据库,降低风险。数据库拆分必须配合双写过渡期
  8. +
  9. JWT 推迟到 Phase 4:前三个阶段保持现有 Redis Token 机制不变,避免认证机制和架构拆分同时变更
  10. +
+ +

改造工作量估算

+ + + + + + + + +
阶段核心工作量预估人天
Phase 1包迁移 + 接口抽象 + 回归测试5-10 人天
Phase 2auth-sdk 开发 + 网关搭建 + shade 配置 + 全量测试10-15 人天
Phase 3服务拆分 + 数据库迁移 + 双写过渡 + Feign 接入15-20 人天
Phase 4JWT + 权限注解 + OAuth2 + 持续优化10+ 人天
合计40-55 人天
+ +

+本方案基于 service-master 源码静态分析编制。实际实施前建议结合运行时监控数据(API 调用频率、AuthContext 使用热点)做进一步验证。 +

+ +
+ + diff --git a/frontend/apes-Authon-Web-剥离方案.html b/frontend/apes-Authon-Web-剥离方案.html new file mode 100644 index 0000000..9078a15 --- /dev/null +++ b/frontend/apes-Authon-Web-剥离方案.html @@ -0,0 +1,335 @@ + + + + + +apes-Authon-Web 前端剥离方案 + + + +
+ +

apes-Authon-Web 前端剥离方案

+ +
+

从 saas-web 单体前端中提取纯净账权页面,构建独立的 apes-Authon-Web 前端仓库,与后端 apes-Authon 配合使用。

+

源仓库:gitea-upload/web-master  |  目标仓库:apes-Authon-Web  |  技术栈:Vue 2.7 + Element UI + Vuex + Vue Router

+
+ +
+
24
账权页面保留
+
102
业务页面删除
+
8
框架文件修改
+
+ + +

Step 1: 保留清单(账权相关)

+ +

1.1 页面 (views/) — 保留 24 个

+ + + + + + + + + + +
目录文件功能
login/index.vue登录页(短信+密码+SSO)
register/index.vue注册页
user/list.vue, editProfile.vue, info.vue, pwd.vue, sso.vue用户管理(列表/编辑/信息/改密/SSO配置)
permission/menuList.vue, permissionList.vue, roleList.vue权限管理(菜单/权限项/角色)
customer/index.vue, detail.vue, editCustomer.vue, employee.vue, user.vue, myCustomer.vue, packages.vue, packageOverview.vue, quotaChangeLog.vue, uiConfig.vue, accessToken.vue, extendApplyList.vue客户管理(12个页面)
app/appList.vue, appDetail.vue应用管理
404.vue404 错误页
home/index.vue首页看板(保留作为默认着陆页)
+ +

1.2 API 文件 (api/) — 保留 8 个

+ + + + + + + + + + +
文件行数功能
user.js99登录/注册/用户管理/获取当前用户
permissionApi.js104菜单/权限/角色 CRUD
menuApi.js79动态路由构建(从后端菜单数据生成 Vue 路由)
appApi.js31应用管理 CRUD
customerApi.js100客户管理 CRUD + 用户关联
customerPackageApi.js56客户套餐管理
accessTokenApi.js33AccessToken 管理
organizationApi.js43组织架构管理
+ +

1.3 框架文件 — 全量保留

+ + + + + + + + + + + + +
类别文件说明
入口main.js, App.vue需修改(移除业务引用)
路由router/index.js需大幅修改(移除业务路由)
布局layout/index.vue, Sidebar/, TagsView/, TopHeader.vue全量保留
Storestore/index.js, getters.js, modules/user.js, settings.js, tagsView.jsuser.js 需修改(移除 huobanToken)
Utilsrequest.js, index.js, validate.js, get-page-title.js, msgUtil.js, public.js, constUtil.js, envUtil.js, autoRefresh.js, uiSizeUtil.jsrequest.js 需修改(移除 huoban 逻辑)
组件breadcrumb.vue, tagView.vue, pageBox.vue, iframeView.vue全量保留
样式styles/index.scss, variables.scss, mixin.scss, sidebar.scss, transition.scss, element-ui.scss保留(删除 tracing-screen.scss)
构建配置package.json, vue.config.js, babel.config.js, postcss.config.js, jsconfig.json需修改(移除业务依赖)
静态资源public/index.html, public/static/保留
图片资源assets/404_images/, assets/images/, assets/base.scss保留
+ + +

Step 2: 删除清单(业务相关)

+ +

2.1 页面删除 — 102 个 .vue 文件

+ + + + + + + + + + + +
目录文件数业务域
fei/22智慧农业大屏/可视化
trace/21溯源管理
weight/13自助过磅系统
system/9系统配置(含业务配置项)
ai/7AI 助手/LLM
huoban/7伙伴云表单配置
tracing/6溯源追踪/路线
irrigation/2灌溉管理
其他15base, brain, certify, payment, park, waterFertilizer, fertigationDevice, extLink, preference, agreement, certifyAgreement, web, tracking
+ +

2.2 API 删除 — 30+ 个 .js 文件

+ + + + + + + + + + + +
文件业务域
aiSkill.js, llmAgentApi.js, llmAgentSkillApi.js, llmAgentToolApi.js, llmConversationApi.js, llmModelApi.js, llmToolApi.js, llmToolLogApi.jsAI/LLM
fei/智慧农业
trace/, traceabilityApi.js, trackingConfigApi.js溯源
weightApi.js过磅
huobanTableApi.js伙伴云
farmPlan.js, inspection.js, inputMaterial.js, irrigation.js, park.js, fertigationDevice.js, cameraInfo.js农业/设备
quotaApi.js, packagePlanApi.js配额/方案
n8nApi.jsN8N 工作流
extLink.js, userPreference.js外链/偏好
+ +

2.3 Utils 删除

+ + + + + + + +
文件原因
ezvizConfig.js, ezvizStream.js萤石云视频流(业务专用)
tracingDisplay.js, tracingPermission.js, tracingQualPermission.js, tracingTestCertificate.js溯源专用工具
huobanAuth.js伙伴云鉴权(业务专用)
markdown.js, wangEditConfig.js富文本编辑器配置(业务页面用)
tracingDisplay.js溯源展示
+ +

2.4 组件删除

+ + + + + + +
目录/文件原因
components/ai/AI 组件
components/brain/大屏组件
components/tracing/溯源组件
components/MarkdownContent.vue富文本组件
+ +

2.5 样式删除

+ + + +
文件原因
styles/tracing-screen.scss溯源大屏样式
+ +

2.6 Config 删除

+ + + + +
文件原因
config/ezviz.js, config/ezviz.example.js萤石云配置
config/tracingOpenKey.js溯源 OpenKey 配置
+ + +

Step 3: 文件修改清单

+ +

3.1 router/index.js 大幅修改

+

移除所有业务路由,只保留账权路由:

+ + + + + + + + + + + + + +
操作路由说明
保留/login, /register登录/注册
保留/user/* (list, pwd, info, sso, editProfile)用户管理
保留/base/* (app/list, app/detail, permission/*)应用+权限管理
保留/customer/* (index, detail, user, my, employee, edit)客户管理
保留/error/404, / (redirect to login)404 + 默认重定向
删除/certify, /certifyAgreement, /agreement认证协议页
删除/huoban/*伙伴云配置
删除/weight/*过磅系统
删除/tracing/*溯源管理
删除/fei_screen, /screen/fei, /brain, /tracing_screen大屏入口
删除/common (空 children)无意义路由
+ +

3.2 main.js 修改

+
    +
  • 移除 import echartsVue.prototype.$echarts
  • +
  • 移除 import userPreferenceApi 及相关调用(或保留为空操作)
  • +
  • 清理 staticPages 数组,移除业务页面路径
  • +
  • 保留核心逻辑:getCurrentUser → setLoginUser → getMyApps → loadAppMenus → matchCurrentPath
  • +
+ +

3.3 utils/request.js 修改

+
    +
  • 删除 isHuobanWebApi() 函数
  • +
  • 简化 resolveRequestToken():直接返回 localStorage.getItem('_token')
  • +
  • 清理 staticPages 数组,移除业务页面路径
  • +
+ +

3.4 store/modules/user.js 修改

+
    +
  • 删除 huobanToken state
  • +
  • 删除 SET_HUOBAN_TOKEN mutation
  • +
  • 删除 setHuobanToken action
  • +
+ +

3.5 store/getters.js 修改

+

当前 getters 引用了不存在的 module(app, permission, errorLog, common),需要清理:

+
    +
  • 删除 sidebar, size, device(引用 state.app,不存在)
  • +
  • 删除 permission_routes(引用 state.permission,不存在)
  • +
  • 删除 errorLogs(引用 state.errorLog,不存在)
  • +
  • 删除 common_baseURL(引用 state.common,不存在)
  • +
  • 保留 token, avatar, name, introduction, roles(引用 state.user,但需确认 user 模块是否有这些字段)
  • +
+ +

3.6 vue.config.js 修改

+
    +
  • 移除 MonacoWebpackPlugin 引用和使用
  • +
  • 移除 n8n 代理配置
  • +
  • 移除 externals 中的 echartsmonaco-editor
  • +
  • 移除 splitChunks 中的 monaco/echarts/wangEditor 缓存组
  • +
  • 更新 outputDir"saas-web" 改为 "authon-web"
  • +
  • 更新 devServer.public 域名
  • +
+ +

3.7 package.json 修改

+

移除业务专用依赖:

+ + + + + + + + + + + +
操作依赖原因
删除@amap/amap-jsapi-loader高德地图
删除@wangeditor/editor, editor-for-vue富文本编辑器
删除echarts图表库
删除html2canvas, jspdf截图/PDF
删除monaco-editor, monaco-editor-webpack-plugin, vue-monaco代码编辑器
删除marked, highlight.jsMarkdown
删除qrcodejs2二维码
删除fix, them, to无效/可疑依赖
保留axios, core-js, element-ui, vue, vue-router, vuex, nprogress, path-to-regexp, normalize.css, animate.css, svg-sprite-loader框架必需
+ +

3.8 public/index.html 修改

+
    +
  • 更新 <title> 为 "apes-Authon"
  • +
  • 移除 echarts/monaco CDN 引用(如果有)
  • +
+ + +

Step 4: 执行步骤

+ +
+
    +
  1. 创建仓库:在 Gitea 创建 apes-Authon-Web 仓库
  2. +
  3. 复制源码cp -r gitea-upload/web-master apes-Authon-Web
  4. +
  5. 删除业务页面:删除 20 个业务 views 目录
  6. +
  7. 删除业务 API:删除 30+ 个业务 api 文件
  8. +
  9. 删除业务组件:删除 ai/brain/tracing/MarkdownContent
  10. +
  11. 删除业务 Utils:删除 ezviz/tracing/huoban/markdown/wangEdit 文件
  12. +
  13. 删除业务 Config:删除 ezviz/tracingOpenKey 文件
  14. +
  15. 删除业务样式:删除 tracing-screen.scss
  16. +
  17. 修改 router/index.js:移除业务路由
  18. +
  19. 修改 main.js:移除 echarts/userPreference 引用
  20. +
  21. 修改 utils/request.js:移除 huoban 逻辑
  22. +
  23. 修改 store/user.js:移除 huobanToken
  24. +
  25. 修改 store/getters.js:清理不存在的 module 引用
  26. +
  27. 修改 vue.config.js:移除 monaco/echarts/n8n 配置
  28. +
  29. 修改 package.json:移除业务依赖,更新名称
  30. +
  31. 修改 public/index.html:更新标题
  32. +
  33. 编写 README.md:项目说明
  34. +
  35. 验证 buildnpm install && npm run build:prod
  36. +
  37. Git 初始化 + 推送:提交到 Gitea
  38. +
+
+ + +

Step 5: 风险与注意事项

+ +
+

⚠️ 依赖链风险:部分账权页面可能引用了业务组件或工具函数,需在删除后逐一排查编译错误。

+
+ +
+

已知潜在问题

+
    +
  • store/getters.js 引用了 4 个不存在的 store module(app/permission/errorLog/common),这些是模板残留,清理时需确保没有页面依赖这些 getter
  • +
  • menuApi.js 中的 handleMenu 方法可能引用了业务页面的 require.context 映射,需确认是否能正常工作(当业务 .vue 文件被删除后)
  • +
  • customer/index.vue(81KB)体量很大,可能包含业务联动逻辑,需检查是否引用了业务 API
  • +
  • views/base/imageUpload 被放在 base 路由下,可能是公共图片上传组件,需要保留
  • +
  • 需确认 userPreference.js 是否为账权功能(UI 尺寸偏好),如需要则保留 API 和 main.js 中的调用
  • +
+
+ +
+

与后端 apes-Authon 的对应关系

+ + + + + + + + + + +
后端 Controller前端页面API 文件
UserControllerviews/user/user.js
PermissionControllerviews/permission/permissionApi.js
CustomerControllerviews/customer/customerApi.js
AppControllerviews/app/appApi.js
MenuController(菜单接口)menuApi.js 处理动态路由menuApi.js
AccessTokenControllerviews/customer/accessToken.vueaccessTokenApi.js
SSOControllerviews/user/sso.vue, views/login/index.vueuser.js (ssoLogin)
CustomerPackageControllerviews/customer/packages.vuecustomerPackageApi.js
+
+ + +

总结

+ +
+
24
保留页面
+
102
删除页面
+
8
修改文件
+
+ +

剥离后 apes-Authon-Web 将是一个纯净的账权管理前端,包含:登录注册、用户管理、客户管理、权限管理(菜单/角色/权限项)、应用管理、AccessToken 管理、SSO 配置。与后端 apes-Authon 一一对应。

+ +

方案生成时间:2026-08-09 | 源码版本:saas-web v1.0.0 | 框架:Vue 2.7 + Element UI 2.15

+ +
+ + diff --git a/frontend/apes-Authon-Web-剥离方案.md b/frontend/apes-Authon-Web-剥离方案.md new file mode 100644 index 0000000..6ce5828 --- /dev/null +++ b/frontend/apes-Authon-Web-剥离方案.md @@ -0,0 +1,199 @@ +# apes-Authon-Web 前端剥离方案 + +> 从 saas-web 单体前端中提取纯净账权页面,构建独立的 `apes-Authon-Web` 前端仓库,与后端 `apes-Authon` 配合使用。 + +- **源仓库**: gitea-upload/web-master +- **目标仓库**: apes-Authon-Web +- **技术栈**: Vue 2.7 + Element UI + Vuex + Vue Router + +## 概览 + +| 分类 | 数量 | 说明 | +|------|------|------| +| 账权页面保留 | 24 | login、register、user、permission、customer、app | +| 系统配置保留 | 9 | organization、operationlog、quota、packagePlan | +| AI/LLM 页面保留 | 11 | llmModel、llmAgent、aiHelper、ai 工具管理 | +| 业务页面删除 | ~82 | fei、trace、weight、tracing、irrigation 等 | +| 框架文件修改 | 8 | router、main.js、request.js、store 等 | + +## Step 1: 保留清单 + +### 1.1 页面 (views/) — 保留 + +| 目录 | 文件 | 功能 | +|------|------|------| +| login/ | index.vue | 登录页(短信+密码+SSO) | +| register/ | index.vue | 注册页 | +| user/ | list.vue, editProfile.vue, info.vue, pwd.vue, sso.vue | 用户管理 | +| permission/ | menuList.vue, permissionList.vue, roleList.vue | 权限管理 | +| customer/ | index.vue, detail.vue, editCustomer.vue, employee.vue, user.vue, myCustomer.vue, packages.vue, packageOverview.vue, quotaChangeLog.vue, uiConfig.vue, accessToken.vue, extendApplyList.vue | 客户管理(12个页面) | +| app/ | appList.vue, appDetail.vue | 应用管理 | +| system/ | organization/, operationlog/, quota/, packagePlan/, llmModel/, llmAgent/, aiHelper/ | 系统配置 + AI/LLM 配置 | +| ai/ | tool.vue, toolEdit.vue, skill.vue, toolLog.vue, callLog.vue, conversationHistory.vue, chat.vue | AI 工具管理 | +| home/ | index.vue | 首页看板 | +| 404.vue | — | 404 错误页 | + +### 1.2 API 文件 (api/) — 保留 + +| 文件 | 功能 | +|------|------| +| user.js | 登录/注册/用户管理/获取当前用户 | +| permissionApi.js | 菜单/权限/角色 CRUD | +| menuApi.js | 动态路由构建 | +| appApi.js | 应用管理 CRUD | +| customerApi.js | 客户管理 CRUD | +| customerPackageApi.js | 客户套餐管理 | +| accessTokenApi.js | AccessToken 管理 | +| organizationApi.js | 组织架构管理 | +| quotaApi.js | 配额管理 | +| packagePlanApi.js | 套餐方案管理 | +| llmAgentApi.js | LLM Agent 管理 | +| llmAgentSkillApi.js | LLM Agent 技能管理 | +| llmAgentToolApi.js | LLM Agent 工具管理 | +| llmModelApi.js | LLM 模型配置 | +| llmConversationApi.js | LLM 对话管理 | +| llmToolApi.js | LLM 工具管理 | +| llmToolLogApi.js | LLM 工具日志 | +| aiSkill.js | AI 技能管理 | + +### 1.3 框架文件 — 全量保留(部分需修改) + +| 类别 | 文件 | 说明 | +|------|------|------| +| 入口 | main.js, App.vue | 需修改(移除业务引用) | +| 路由 | router/index.js | 需大幅修改(移除业务路由) | +| 布局 | layout/index.vue, Sidebar/, TagsView/, TopHeader.vue | 全量保留 | +| Store | store/index.js, getters.js, modules/user.js, settings.js, tagsView.js | user.js + getters.js 需修改 | +| Utils | request.js, index.js, validate.js, get-page-title.js, msgUtil.js, public.js, constUtil.js, envUtil.js, autoRefresh.js, uiSizeUtil.js | request.js 需修改 | +| 组件 | breadcrumb.vue, tagView.vue, pageBox.vue, iframeView.vue, ai/ai_helper.vue | 保留 | +| 样式 | styles/index.scss, variables.scss, mixin.scss, sidebar.scss, transition.scss, element-ui.scss | 保留(删除 tracing-screen.scss) | +| 构建配置 | package.json, vue.config.js, babel.config.js, postcss.config.js, jsconfig.json | 需修改 | +| 静态资源 | public/index.html, public/static/ | 保留 | +| 图片资源 | assets/404_images/, assets/images/, assets/base.scss | 保留 | + +## Step 2: 删除清单(业务相关) + +### 2.1 页面删除 + +| 目录 | 文件数 | 业务域 | +|------|--------|--------| +| fei/ | 22 | 智慧农业大屏/可视化 | +| trace/ | 21 | 溯源管理 | +| weight/ | 13 | 自助过磅系统 | +| tracing/ | 6 | 溯源追踪/路线 | +| irrigation/ | 2 | 灌溉管理 | +| 其他 | ~18 | base, brain, certify, payment, park, waterFertilizer, fertigationDevice, extLink, preference, agreement, certifyAgreement, web, tracking, huoban | + +> **注意**: huoban/ 目录暂不保留,作为后续 Phase 5C 代办。 + +### 2.2 API 删除 + +| 文件 | 业务域 | +|------|--------| +| fei/ 目录 | 智慧农业 | +| trace/, traceabilityApi.js, trackingConfigApi.js | 溯源 | +| weightApi.js | 过磅 | +| huobanTableApi.js | 伙伴云 | +| farmPlan.js, inspection.js, inputMaterial.js, irrigation.js, park.js, fertigationDevice.js, cameraInfo.js | 农业/设备 | +| n8nApi.js | N8N 工作流 | +| extLink.js, userPreference.js | 外链/偏好 | + +### 2.3 Utils 删除 + +| 文件 | 原因 | +|------|------| +| ezvizConfig.js, ezvizStream.js | 萤石云视频流 | +| tracingDisplay.js, tracingPermission.js, tracingQualPermission.js, tracingTestCertificate.js | 溯源专用 | +| huobanAuth.js | 伙伴云鉴权 | +| markdown.js, wangEditConfig.js | 富文本编辑器 | + +### 2.4 组件删除 + +| 目录/文件 | 原因 | +|-----------|------| +| components/brain/ | 大屏组件 | +| components/tracing/ | 溯源组件 | +| components/MarkdownContent.vue | 富文本组件 | + +### 2.5 样式删除 + +| 文件 | 原因 | +|------|------| +| styles/tracing-screen.scss | 溯源大屏样式 | + +### 2.6 Config 删除 + +| 文件 | 原因 | +|------|------| +| config/ezviz.js, config/ezviz.example.js | 萤石云配置 | +| config/tracingOpenKey.js | 溯源 OpenKey 配置 | + +## Step 3: 文件修改清单 + +### 3.1 router/index.js — 大幅修改 +- 保留: /login, /register, /user/*, /base/*, /customer/*, /system/*, /ai/*, /error/404 +- 删除: /certify, /huoban/*, /weight/*, /tracing/*, /fei_screen, /brain, /tracing_screen, /common + +### 3.2 main.js — 修改 +- 移除 echarts 引用 +- 清理 staticPages 数组 +- 保留核心逻辑 + +### 3.3 utils/request.js — 修改 +- 删除 isHuobanWebApi() 函数 +- 简化 resolveRequestToken() +- 清理 staticPages + +### 3.4 store/modules/user.js — 修改 +- 删除 huobanToken state/mutation/action + +### 3.5 store/getters.js — 修改 +- 清理不存在的 module 引用(app/permission/errorLog/common) + +### 3.6 vue.config.js — 修改 +- 移除 MonacoWebpackPlugin +- 移除 n8n 代理 +- 移除 echarts/monaco externals +- 更新 outputDir 为 "authon-web" + +### 3.7 package.json — 修改 +- 移除: @amap/amap-jsapi-loader, @wangeditor/*, echarts, html2canvas, jspdf, monaco-editor/*, marked, highlight.js, qrcodejs2 +- 更新 name 为 "apes-Authon-Web" + +### 3.8 public/index.html — 修改 +- 更新 title 为 "apes-Authon" + +## Step 4: 与后端对应关系 + +| 后端 Controller | 前端页面 | API 文件 | +|----------------|----------|----------| +| UserController | views/user/ | user.js | +| PermissionController | views/permission/ | permissionApi.js | +| CustomerController | views/customer/ | customerApi.js | +| AppController | views/app/ | appApi.js | +| MenuController | menuApi.js | menuApi.js | +| AccessTokenController | views/customer/accessToken.vue | accessTokenApi.js | +| SSOController | views/user/sso.vue, views/login/ | user.js | +| CustomerPackageController | views/customer/packages.vue | customerPackageApi.js | +| SysOrganizationController | views/system/organization/ | organizationApi.js | +| SysOperationLogController | views/system/operationlog/ | — | +| SysQuotaController | views/system/quota/ | quotaApi.js | +| SysPackagePlanController | views/system/packagePlan/ | packagePlanApi.js | +| LlmModelConfigController | views/system/llmModel/ | llmModelApi.js | +| LlmAgentConfigController | views/system/llmAgent/ | llmAgentApi.js | +| AiController | views/system/aiHelper/ | aiSkill.js | +| LlmToolController | views/ai/tool.vue | llmToolApi.js | +| LlmChatController | views/ai/chat.vue | — | +| LlmConversationController | views/ai/conversationHistory.vue | llmConversationApi.js | + +## Step 5: 后续代办 + +| 代办 | 说明 | +|------|------| +| Phase 5C: 伙伴云表单 | 7 .vue + 1 API,后端 5 Controller 待提取 | +| Phase 4: SDK化 | AuthContext 远程调用 SDK | +| Phase 5: 网关集成 | API 网关统一鉴权 | + +--- + +*方案生成时间: 2026-08-09 | 源码版本: saas-web v1.0.0 | 框架: Vue 2.7 + Element UI 2.15* diff --git a/frontend/剥离历史与说明.md b/frontend/剥离历史与说明.md new file mode 100644 index 0000000..d83b980 --- /dev/null +++ b/frontend/剥离历史与说明.md @@ -0,0 +1,344 @@ +# apes-Authon-Web 剥离历史与说明 + +> 本文档记录从 saas-web 单体前端剥离纯净账权页面的执行过程、变更明细和框架修改说明。 + +- **源仓库**: saas-web(单体前端,含 120+ 页面) +- **目标仓库**: apes-Authon-Web(纯净账权前端,40 页面) +- **剥离时间**: 2026-08-09 +- **提交**: `8ebd1ca` — 176 files changed, +222/-60093 + +--- + +## 一、剥离概览 + +| 分类 | 数量 | 说明 | +|------|------|------| +| 账权页面保留 | 24 | login、register、user、permission、customer、app | +| 系统配置保留 | 9 | organization、operationlog、quota、packagePlan | +| AI/LLM 页面保留 | 11 | llmModel、llmAgent、aiHelper、ai 工具管理 | +| 业务页面删除 | ~82 | fei、trace、weight、tracing、irrigation 等 | +| 框架文件修改 | 8 | router、main.js、request.js、store 等 | +| 代码变更量 | +222 / -60093 | 净减约 6 万行业务代码 | + +--- + +## 二、保留清单 + +### 2.1 页面 (views/) + +| 目录 | 文件 | 功能 | +|------|------|------| +| login/ | index.vue | 登录页(短信验证码 + 密码 + SSO) | +| register/ | index.vue | 注册页 | +| user/ | list.vue, editProfile.vue, info.vue, pwd.vue, sso.vue | 用户管理(5 个页面) | +| permission/ | menuList.vue, permissionList.vue, roleList.vue | 权限管理(3 个页面) | +| customer/ | index.vue, detail.vue, editCustomer.vue, employee.vue, user.vue, myCustomer.vue, packages.vue, packageOverview.vue, quotaChangeLog.vue, uiConfig.vue, accessToken.vue, extendApplyList.vue | 客户管理(12 个页面) | +| app/ | appList.vue, appDetail.vue | 应用管理 | +| system/ | organization/, operationlog/, quota/, packagePlan/, llmModel/, llmAgent/, aiHelper/ | 系统配置 + AI/LLM 配置(8 个页面) | +| ai/ | tool.vue, toolEdit.vue, skill.vue, toolLog.vue, callLog.vue, conversationHistory.vue, chat.vue | AI 工具管理(7 个页面) | +| home/ | index.vue | 首页看板 | +| base/ | imageUpload.vue | 图片上传 | +| 404.vue | — | 404 错误页 | + +### 2.2 API 文件 (api/) — 19 个 + +| 文件 | 功能 | +|------|------| +| user.js | 登录/注册/用户管理/获取当前用户 | +| permissionApi.js | 菜单/权限/角色 CRUD | +| menuApi.js | 动态路由构建(require.context) | +| appApi.js | 应用管理 CRUD | +| customerApi.js | 客户管理 CRUD | +| customerPackageApi.js | 客户套餐管理 | +| accessTokenApi.js | AccessToken 管理 | +| organizationApi.js | 组织架构管理 | +| quotaApi.js | 配额管理 | +| packagePlanApi.js | 套餐方案管理 | +| baseApi.js | 基础接口(文件上传等) | +| llmModelApi.js | LLM 模型配置 | +| llmAgentApi.js | LLM Agent 管理 | +| llmAgentSkillApi.js | LLM Agent 技能管理 | +| llmAgentToolApi.js | LLM Agent 工具管理 | +| llmToolApi.js | LLM 工具管理 | +| llmToolLogApi.js | LLM 工具日志 | +| llmConversationApi.js | LLM 对话管理 | +| aiSkill.js | AI 技能管理 | + +### 2.3 组件 (components/) — 6 个 + +| 文件 | 功能 | 备注 | +|------|------|------| +| breadcrumb.vue | 面包屑导航 | 原样保留 | +| tagView.vue | 标签页缓存 | 原样保留 | +| pageBox.vue | 页面容器 | 原样保留 | +| iframeView.vue | 通用 iframe 组件 | **重写**(见下文) | +| MarkdownContent.vue | Markdown 渲染 | **新建**(见下文) | +| ai/ai_helper.vue | AI 助手浮窗 | 原样保留 | + +### 2.4 工具函数 (utils/) — 10 个 + +| 文件 | 功能 | 备注 | +|------|------|------| +| request.js | Axios 封装 | **修改**(见下文) | +| index.js | 通用工具函数 | 原样保留 | +| validate.js | 校验工具 | 原样保留 | +| msgUtil.js | 消息提示 | 原样保留 | +| public.js | 公共方法 | 原样保留 | +| constUtil.js | 常量 | 原样保留 | +| envUtil.js | 环境变量 | 原样保留 | +| autoRefresh.js | 自动刷新 | 原样保留 | +| uiSizeUtil.js | UI 尺寸 | 原样保留 | +| get-page-title.js | 页面标题 | 原样保留 | + +--- + +## 三、删除清单 + +### 3.1 页面删除 + +| 目录 | 文件数 | 业务域 | +|------|--------|--------| +| fei/ | 22 | 智慧农业大屏/可视化 | +| trace/ | 21 | 溯源管理 | +| weight/ | 13 | 自助过磅系统 | +| tracing/ | 6 | 溯源追踪/路线 | +| irrigation/ | 2 | 灌溉管理 | +| brain/ | 3 | AI 大脑 | +| certify/ | 5 | 认证管理 | +| certifyAgreement/ | 1 | 认证协议 | +| payment/ | 1 | 支付 | +| park/ | 2 | 园区管理 | +| waterFertilizer/ | 2 | 水肥一体化 | +| fertigationDevice/ | 2 | 施肥设备 | +| extLink/ | 1 | 外部链接 | +| preference/ | 1 | 偏好设置 | +| agreement/ | 1 | 协议管理 | +| web/ | 1 | Web iframe | +| tracking/ | 1 | 追踪 | +| huoban/ | 1 | 伙伴云(Phase 5C 代办) | +| 其他 | ~3 | PAGECODE.md 等 | + +### 3.2 API 删除 + +| 文件/目录 | 业务域 | +|-----------|--------| +| fei/ 目录 | 智慧农业 | +| trace/, traceabilityApi.js, trackingConfigApi.js | 溯源 | +| weightApi.js | 过磅 | +| huobanTableApi.js | 伙伴云 | +| farmPlan.js, inspection.js, inputMaterial.js, irrigation.js, park.js, fertigationDevice.js, cameraInfo.js | 农业/设备 | +| n8nApi.js | N8N 工作流 | +| extLink.js, userPreference.js | 外链/偏好 | + +### 3.3 工具函数删除 + +| 文件 | 原因 | +|------|------| +| ezvizConfig.js, ezvizStream.js | 萤石云视频流配置 | +| tracingDisplay.js, tracingPermission.js, tracingQualPermission.js, tracingTestCertificate.js | 溯源专用工具 | +| huobanAuth.js | 伙伴云鉴权 | +| markdown.js | 富文本编辑器封装(被 MarkdownContent.vue 替代) | +| wangEditConfig.js | wangEditor 富文本配置 | + +### 3.4 组件删除 + +| 目录/文件 | 原因 | +|-----------|------| +| components/brain/ | 大屏专用组件 | +| components/tracing/ | 溯源专用组件 | +| components/MarkdownContent.vue(原版) | 依赖已删除的 markdown.js,由新版替代 | + +### 3.5 配置删除 + +| 文件 | 原因 | +|------|------| +| config/ezviz.js, config/ezviz.example.js | 萤石云配置 | +| config/tracingOpenKey.js | 溯源 OpenKey 配置 | +| styles/tracing-screen.scss | 溯源大屏样式 | + +--- + +## 四、框架文件修改详情 + +### 4.1 router/index.js — 路由重构 + +**修改内容**: +- 移除所有业务路由(certify、huoban、weight、tracing、fei_screen、brain、tracing_screen) +- 保留核心路由:`/login`、`/register`、`/user/*`、`/base/*`、`/customer/*`、`/error/404`、`/`(首页) +- 新增 `/common` 路由作为动态菜单路由的容器: + +```javascript +{ + path: '/common', + component: LayoutBox, + name: 'common', + children: [] // 动态路由运行时注入 +} +``` + +**原因**:`menuApi.js` 通过 `router.addRoute('common', ...)` 动态注册菜单路由,需要一个名为 `common` 的命名路由作为父容器。 + +### 4.2 main.js — 入口精简 + +**移除内容**: +- `import * as echarts from 'echarts'` 和 `Vue.prototype.$echarts = echarts`(首页看板不再使用 echarts 图表) +- `import userPreferenceApi from '@/api/userPreference'` 及相关调用(用户偏好功能已删除) +- `staticPages` 数组精简为 `['/register']`(移除了其他静态页面路径) + +**保留内容**: +- Token 从 URL 参数读取(SSO 支持) +- `getCurrentUser` → `setLoginUser` → `getMyApps` → `loadAppMenus` → `matchCurrentPath` 核心启动流程 + +### 4.3 utils/request.js — 请求层简化 + +**移除内容**: +- `isHuobanWebApi()` 函数(判断是否为伙伴云 API 请求) +- `resolveRequestToken()` 辅助函数(根据请求类型解析不同 token) +- 伙伴云 token 相关逻辑 + +**简化后**:Token 统一从 `localStorage.getItem('_token')` 获取: + +```javascript +config.headers = { + ...config.headers, + time: new Date().getTime(), + version: '1.1', + token: localStorage.getItem('_token') || '' +} +``` + +### 4.4 store/modules/user.js — 状态清理 + +**移除内容**: +- `huobanToken` state 字段 +- `SET_HUOBAN_TOKEN` mutation +- `setHuobanToken` action + +**保留的 State**:`loginUser`、`menuList`、`currentMenuId`、`currentCustomer`、`appList`、`currentApp`、`currentAppMenus`、`allAppMenus` + +### 4.5 store/getters.js — 清理不存在模块 + +**移除内容**:对 `app`、`permission`、`errorLog`、`common` 模块的 getter 引用(这些模块不存在于本项目中) + +**修改后**: + +```javascript +const getters = { + visitedViews: state => state.tagsView.visitedViews, + cachedViews: state => state.tagsView.cachedViews, + loginUser: state => state.user.loginUser, + currentCustomer: state => state.user.currentCustomer, + menuList: state => state.user.menuList, + appList: state => state.user.appList, + currentApp: state => state.user.currentApp, + currentAppMenus: state => state.user.currentAppMenus +} +``` + +### 4.6 vue.config.js — 构建配置更新 + +**移除内容**: +- `MonacoWebpackPlugin` require 和插件注册 +- n8n 工作流代理配置 +- `echarts`、`monaco-editor` 的 externals 配置 +- monaco/echarts/wangEditor 的 splitChunks cacheGroups + +**修改内容**: +- `outputDir`: `"saas-web"` → `"authon-web"` +- `name`: 添加 `'apes-Authon'` + +### 4.7 package.json — 依赖清理 + +**移除的依赖**: +- `@amap/amap-jsapi-loader`(高德地图) +- `@wangeditor/core`、`@wangeditor/editor`、`@wangeditor/editor-for-vue`(富文本编辑器) +- `echarts`(图表库) +- `html2canvas`(截图) +- `jspdf`(PDF 生成) +- `qrcodejs2`(二维码) + +**保留的特殊依赖**: +- `monaco-editor` — AI 工具编辑器使用(`views/ai/toolEdit.vue`) +- `vue-monaco` — Monaco Editor 的 Vue 封装 +- `marked` — AI 对话中的 Markdown 渲染 +- `highlight.js` — AI 对话中的代码高亮 + +### 4.8 public/index.html — CDN 清理 + +**移除内容**: +- echarts CDN script +- monaco-editor CDN scripts(loader、nls、editor.main) + +**保留内容**: +- Vue、VueRouter、Vuex、ElementUI、Axios 的 CDN externals + +### 4.9 iframeView.vue — 重写 + +**原版**:为每种 iframe 类型(web/payment/huoban)分别导入对应的 view 组件。 + +**新版**:统一为单个通用 ` + + +``` + +### 4.10 menuApi.js — 路由注册统一 + +**修改内容**:menuType 2/3/4 统一使用 `@/components/iframeView` 组件,不再为每种类型分别导入 view。 + +### 4.11 MarkdownContent.vue — 新建 + +**背景**:原版 `MarkdownContent.vue` 导入了已删除的 `@/utils/markdown.js`,导致构建失败。 + +**新版**:直接使用 `marked` + `highlight.js`,自包含无外部依赖: + +```javascript +import { marked } from 'marked' +import hljs from 'highlight.js' +import 'highlight.js/styles/github.css' +``` + +--- + +## 五、业务引用清理 + +以下文件中移除了对已删除模块的引用,替换为空操作或简化逻辑: + +| 文件 | 移除的引用 | 替代方案 | +|------|-----------|----------| +| TopHeader.vue | `weightApi`、`clearTracingPermissionCache`、`clearHuobanToken` | 移除调用,保留方法结构 | +| login/index.vue | `weightApi`、`clearHuobanToken` | 移除调用 | +| home/index.vue | `extLinkApi` | `loadExtLinks()` 改为空操作 | +| customer/index.vue | `huobanTableApi` | `upsetOne()` 改为设置 skip 状态 | +| customer/uiConfig.vue | `weightApi` | `loadConfig()` / `handleSave()` / `handleReset()` 改为成功提示 | +| permissionApi.js | `TRACING_OPEN_KEY` | 移除 `getTrackingConfigByCustomerId()` 方法 | + +--- + +## 六、构建验证 + +```bash +npm run build:prod +# DONE Compiled successfully +# Build complete. The authon-web directory is ready to be deployed. +``` + +构建产物输出到 `authon-web/` 目录,可直接部署到 Nginx 或其他 Web 服务器。 + +--- + +## 七、后续代办 + +| 代办 | 说明 | 状态 | +|------|------|------| +| Phase 5A: AI/LLM 后端提取 | ~54 Java 文件从源码同步到 apes-Authon | 待办 | +| Phase 5B: 系统配置页面补充 | 后端已有 Controller,前端已保留页面 | 基本完成 | +| Phase 5C: 伙伴云表单配置 | 5 Controller + 7 .vue + 1 API | 待办 | + +--- + +*文档更新时间: 2026-08-09 | 仓库: https://gitea.apescale.com/figmar/apes-Authon-Web*