# 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. **项目目录结构** — 前后端完整目录树