{"repo": "bkywksj/ruoyi-plus-uniapp-docs", "files": {"docs/backend/modules/business/base.md": {"4df4b869cb38268c2e1daeabe96d7979ad70203e": {"t": 1785746525.820662, "n": 27735, "h": "72144b0794344a02", "c": "# 基础服务模块 (base)\n\n基础服务模块提供了系统运行所需的核心基础服务,包括多平台配置管理、支付配置管理、广告配置、账号绑定等功能。\n\n## 模块结构\n\n```text\nbase/\n├── controller/ # 控制器层\n│ ├── AdController.java\n│ ├── BindController.java\n│ ├── PaymentController.java\n│ └── PlatformController.java\n├── service/ # 服务层\n│ ├── IAdService.java\n│ ├── IBindService.java\n│ ├── IPaymentService.java\n│ └── IPlatformService.java\n├── domain/ # 数据模型\n│ ├── entity/ # 实体类\n│ ├── vo/ # 视图对象\n│ └── bo/ # 业务对象\n├── mapper/ # 数据访问层\n└── authStrategy/ # 认证策略\n```\n\n## 核心功能\n\n### 平台配置管理\n\n支持多种平台的统一配置管理:\n\n- **微信小程序** (mp-weixin)\n- **微信公众号** (mp-official-account)\n- **支付宝小程序** (mp-alipay)\n- **QQ小程序** (mp-qq)\n- **其他平台** (mp-jd, mp-kuaishou, mp-lark, mp-baidu, mp-toutiao, mp-xhs)\n\n#### 平台配置实体\n```java\n@Data\n@TableName(\"b_platform\")\npublic class Platform extends TenantEntity {\n private Long id; // 平台配置ID\n private String type; // 平台类型\n private String name; // 平台名称\n private String appid; // 应用ID\n private String secret; // 应用密钥\n private String token; // 接口Token\n private String aeskey; // 加密密钥\n private String paymentIds; // 关联支付配置\n private String templateConfigs; // 模板配置\n private String status; // 状态\n}\n```\n\n#### 核心接口\n```java\npublic interface IPlatformService extends IBaseService {\n // 继承基础CRUD操作\n}\n\n// 全局平台服务\npublic interface PlatformService {\n List listPlatformsByType(String type, String tenantId);\n PlatformDTO getPlatformByAppidAndType(String appid, String type);\n PlatformDTO getPlatformByAppid(String appid, String tenantId);\n}\n```\n\n### 支付配置管理\n\n统一的支付配置管理,支持多种支付方式:\n\n#### 支付配置实体\n```java\n@Data\n@TableName(\"b_payment\") \npublic class Payment extends TenantEntity {\n private Long id; // 支付配置ID\n private String type; // 商户类型\n private String mchName; // 商户名称\n private String mchId; // 商户号\n private String mchKey; // 商户密钥\n private String apiV3Key; // APIv3密钥\n private String certPath; // 证书路径\n private String keyPath; // 密钥路径\n private String certSerialNo; // 证书序列号\n private String status; // 状态\n}\n```\n\n#### 核心服务\n```java\npublic interface PaymentService {\n List listPaymentByType(String type, String tenantId);\n PaymentDTO getByMchId(String mchId);\n PaymentDTO getById(Long paymentId);\n boolean existsValidMchId(String mchId);\n long countPayments();\n}\n```\n\n### 账号绑定管理\n\n管理用户在不同平台的账号绑定关系:\n\n#### 绑定实体\n```java\n@Data\n@TableName(\"b_bind\")\npublic class Bind extends TenantEntity {\n private Long id; // 绑定ID\n private Long userId; // 用户ID\n private String platformType; // 平台类型\n private String appid; // 应用ID\n private String unionid; // 统一标识\n private String openid; // 平台标识\n private String extraData; // 扩展数据\n}\n```\n\n#### 绑定服务\n```java\npublic interface IBindService extends IBaseService {\n /**\n * 根据平台用户信息获取或创建绑定信息\n */\n BindVo getOrCreateBind(PlatformUserInfoVo platformUserInfoVo);\n \n /**\n * 更新绑定信息的用户ID\n */\n void updateBindUserId(BindBo bindBo, Long userId);\n}\n```\n\n### 广告配置管理\n\n提供广告位和广告内容的统一管理:\n\n#### 广告实体\n```java\n@Data\n@TableName(\"b_ad\")\npublic class Ad extends TenantEntity {\n private Long id; // 广告ID\n private String appid; // 应用ID\n private String adUnitId; // 广告位ID\n private String adName; // 广告名称\n private String adType; // 广告类型\n private String position; // 投放位置\n private String img; // 广告图片\n private String description; // 描述\n private String jumpAppid; // 跳转应用ID\n private String jumpPath; // 跳转路径\n private String styleConfig; // 样式配置\n private Long sortOrder; // 排序值\n private String status; // 状态\n}\n```\n\n## 认证策略\n\n### 多平台认证架构\n\n基于策略模式实现多平台登录认证:\n\n#### 认证策略接口\n```java\npublic interface IAuthStrategy {\n String BASE_NAME = \"AuthStrategy\";\n AuthTokenVo login(String body);\n}\n```\n\n#### 小程序认证策略\n```java\n@Service(\"miniapp\" + IAuthStrategy.BASE_NAME)\npublic class MiniappAuthStrategy implements IAuthStrategy {\n \n @Override\n public AuthTokenVo login(String body) {\n // 1. 解析请求参数\n PlatformLoginBody loginBody = JsonUtils.parseObject(body, PlatformLoginBody.class);\n \n // 2. 获取平台用户信息\n PlatformUserInfoVo platformUserInfo = getMiniappUserIdentity(loginBody);\n \n // 3. 加载或创建用户\n SysUserVo user = loadOrCreateUser(platformUserInfo);\n \n // 4. 生成登录令牌\n LoginUser loginUser = loginService.createLoginUser(user);\n loginUser.setPlatform(platformUserInfo.getPlatform());\n loginUser.setAppid(platformUserInfo.getAppid());\n loginUser.setOpenid(platformUserInfo.getOpenid());\n loginUser.setUnionid(platformUserInfo.getUnionid());\n \n // 5. 完成登录\n LoginHelper.login(loginUser, loginParameter);\n \n // 6. 返回认证结果\n AuthTokenVo authTokenVo = new AuthTokenVo();\n authTokenVo.setAccessToken(StpUtil.getTokenValue());\n authTokenVo.setExpireIn(StpUtil.getTokenTimeout());\n return authTokenVo;\n }\n}\n```\n\n#### 公众号认证策略\n```java\n@Service(\"mp\" + IAuthStrategy.BASE_NAME)\npublic class MpAuthStrategy implements IAuthStrategy {\n // 公众号OAuth2.0认证流程实现\n // 支持网页授权登录场景\n}\n```\n\n### 认证流程\n\n1. **前端授权**:用户在前端完成平台授权,获取授权码\n2. **策略选择**:后端根据平台类型自动选择对应认证策略\n3. **信息获取**:通过授权码换取用户基本信息\n4. **账号绑定**:查找或创建用户账号绑定关系\n5. **令牌生成**:生成JWT访问令牌\n6. **登录完成**:返回令牌和用户信息\n\n## 手机号绑定\n\n### 微信小程序手机号获取\n```java\n@PostMapping(\"/bindPhone\")\npublic R bindPhone(@RequestBody PhoneBindBo bo) {\n LoginUser loginUser = LoginHelper.getLoginUser();\n wxMaService.switchover(loginUser.getAppid());\n \n try {\n WxMaPhoneNumberInfo phoneInfo = wxMaService.getUserService().getPhoneNumber(bo.getCode());\n String phone = phoneInfo.getPhoneNumber();\n \n // 更新用户手机号\n SysUser sysUser = userMapper.selectById(loginUser.getUserId());\n sysUser.setPhone(phone);\n userMapper.updateById(sysUser);\n \n return R.ok(\"绑定成功\", PhoneBindVo.of(phone));\n } catch (WxErrorException e) {\n return R.fail(\"获取手机号出错\");\n }\n}\n```\n\n## 数据字典服务\n\n### 支付方式字典\n```java\n@GetMapping(\"getPaymentDict\")\npublic R> getPaymentDict() {\n // 查询所有可用的支付方式\n List paymentVoList = paymentService.list(\n PlusLambdaQuery.of(Payment.class)\n .eq(Payment::getStatus, DictEnableStatus.ENABLE.getValue()));\n \n // 构建字典项列表\n List dictItems = StreamUtils.toList(paymentVoList, payment ->\n DictItemVo.of(payment.getMchName(), payment.getId().toString(), \"success\")\n );\n return R.ok(dictItems);\n}\n```\n\n## 配置管理\n\n### 平台配置热更新\n```java\nprivate void reloadPlatformConfig() {\n String tenantId = TenantHelper.getTenantId();\n \n // 重新初始化微信小程序配置\n SpringUtils.getBean(WxMaApplicationRunner.class).initByTenant(tenantId);\n \n // 重新初始化微信公众号配置 \n SpringUtils.getBean(WxMpApplicationRunner.class).initByTenant(tenantId);\n \n // 重新初始化支付配置\n SpringUtils.getBean(PayApplicationRunner.class).initByTenant(tenantId);\n}\n```\n\n### 支付配置热更新\n```java\nprivate void reloadPaymentConfig() {\n String tenantId = TenantHelper.getTenantId();\n SpringUtils.getBean(PayApplicationRunner.class).initByTenant(tenantId);\n}\n```\n\n## 使用示例\n\n### 配置微信小程序\n```java\n// 1. 创建平台配置\nPlatformBo platformBo = new PlatformBo();\nplatformBo.setType(\"mp-weixin\");\nplatformBo.setName(\"我的小程序\");\nplatformBo.setAppid(\"wx1234567890\");\nplatformBo.setSecret(\"your-secret\");\nplatformBo.setStatus(\"1\");\nplatformService.add(platformBo);\n\n// 2. 配置支付信息\nPaymentBo paymentBo = new PaymentBo();\npaymentBo.setType(\"wechat\");\npaymentBo.setMchName(\"我的商户\");\npaymentBo.setMchId(\"1234567890\");\npaymentBo.setMchKey(\"your-mch-key\");\npaymentBo.setStatus(\"1\");\npaymentService.add(paymentBo);\n```\n\n### 用户登录认证\n```java\n// 前端调用登录接口\nPOST /auth/login\n{\n \"platform\": \"miniapp\",\n \"body\": {\n \"platform\": \"mp-weixin\",\n \"appid\": \"wx1234567890\",\n \"platformCode\": \"授权码\"\n }\n}\n\n// 返回结果\n{\n \"code\": 200,\n \"msg\": \"登录成功\",\n \"data\": {\n \"accessToken\": \"eyJ0eXAiOiJKV1Q...\",\n \"expireIn\": 7200\n }\n}\n```\n\n## AI助手功能\n\n### 功能概述\n\n基础服务模块集成了强大的AI助手功能,基于 **LangChain4j** 框架实现,支持多种大语言模型(如 DeepSeek、通义千问、OpenAI、Claude等),为业务系统提供智能化能力。\n\n**核心特性:**\n- **多模型支持** - 灵活切换不同的AI模型提供商\n- **多场景应用** - 对话、优化、生成、审核、翻译等场景\n- **条件启用** - 通过配置开关控制功能启用\n- **权限控制** - 完善的权限校验机制\n- **上下文传递** - 支持业务上下文信息传递\n\n### AI服务接口\n\n#### AiController 控制器\n\n```java\n@RestController\n@RequestMapping(\"/base/ai\")\n@ConditionalOnProperty(\n prefix = \"langchain4j\",\n name = \"enabled\",\n havingValue = \"true\",\n matchIfMissing = true\n)\npublic class AiController {\n private final IAiService aiService;\n}\n```\n\n**条件启用说明:**\n- 需要在配置文件中设置 `langchain4j.enabled=true`\n- 如果配置项不存在,默认启用 (`matchIfMissing = true`)\n\n### 1. AI对话功能\n\n通用的AI对话接口,支持自由对话场景。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiChat\")\n@OpenApi(value = \"AI对话\")\npublic R aiChat(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiChat(bo));\n}\n```\n\n#### 请求示例\n\n```java\n// 创建对话请求\nAiChatBo chatBo = new AiChatBo();\nchatBo.setMessage(\"请帮我解释一下什么是微服务架构\");\nchatBo.setProvider(\"deepseek\");\nchatBo.setModelName(\"deepseek-chat\");\nchatBo.setTemperature(0.7);\nchatBo.setMaxTokens(2000);\n\n// 调用接口\nR result = aiController.aiChat(chatBo);\nAiChatVo response = result.getData();\nSystem.out.println(\"AI回复: \" + response.getMessage());\n```\n\n#### HTTP 调用示例\n\n```bash\nPOST /base/ai/aiChat\nContent-Type: application/json\n\n{\n \"message\": \"请帮我解释一下什么是微服务架构\",\n \"provider\": \"deepseek\",\n \"modelName\": \"deepseek-chat\",\n \"temperature\": 0.7,\n \"maxTokens\": 2000\n}\n```\n\n### 2. 文本优化功能\n\n对用户输入的文本进行优化,改善表达和文风。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiOptimize\")\n@OpenApi(value = \"AI文本优化\")\npublic R aiOptimize(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiOptimize(bo));\n}\n```\n\n#### 使用场景\n\n- 文章润色和改写\n- 产品描述优化\n- 邮件内容优化\n- 广告文案优化\n\n#### 请求示例\n\n```java\nAiChatBo optimizeBo = new AiChatBo();\noptimizeBo.setMessage(\"我们公司是做软件开发的,主要业务是给客户做系统\");\noptimizeBo.setAiFeature(\"optimize\");\noptimizeBo.setSystemPrompt(\"请将下列文本优化为更专业的企业简介\");\n\nR result = aiController.aiOptimize(optimizeBo);\n// 优化后: \"我们是一家专业的软件开发公司,致力于为企业客户提供定制化系统解决方案...\"\n```\n\n### 3. 数据生成功能\n\n根据用户需求生成结构化数据或内容。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiGenerate\")\n@OpenApi(value = \"AI数据生成\")\npublic R aiGenerate(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiGenerate(bo));\n}\n```\n\n#### 使用场景\n\n- 生成测试数据\n- 生成产品描述\n- 生成代码片段\n- 生成用户画像\n\n#### 请求示例\n\n```java\nAiChatBo generateBo = new AiChatBo();\ngenerateBo.setMessage(\"生成5个用户的测试数据,包含姓名、年龄、邮箱\");\ngenerateBo.setAiFeature(\"generate\");\n\n// 传递表单字段信息作为上下文\nMap context = new HashMap<>();\ncontext.put(\"fields\", Arrays.asList(\"name\", \"age\", \"email\"));\ncontext.put(\"count\", 5);\ngenerateBo.setContext(context);\n\nR result = aiController.aiGenerate(generateBo);\n```\n\n**生成结果示例:**\n```json\n[\n {\"name\": \"张三\", \"age\": 28, \"email\": \"zhangsan@example.com\"},\n {\"name\": \"李四\", \"age\": 32, \"email\": \"lisi@example.com\"},\n {\"name\": \"王五\", \"age\": 25, \"email\": \"wangwu@example.com\"},\n {\"name\": \"赵六\", \"age\": 30, \"email\": \"zhaoliu@example.com\"},\n {\"name\": \"钱七\", \"age\": 27, \"email\": \"qianqi@example.com\"}\n]\n```\n\n### 4. 内容审核功能\n\n对用户提交的内容进行智能审核,检测违规内容。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiReview\")\n@OpenApi(value = \"AI内容审核\")\npublic R aiReview(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiReview(bo));\n}\n```\n\n#### 使用场景\n\n- 评论内容审核\n- 文章内容审核\n- 用户昵称审核\n- 敏感词检测\n\n#### 请求示例\n\n```java\nAiChatBo reviewBo = new AiChatBo();\nreviewBo.setMessage(\"待审核的用户评论内容...\");\nreviewBo.setAiFeature(\"review\");\nreviewBo.setSystemPrompt(\"请审核以下内容是否包含违规、敏感、广告等不当信息\");\n\nR result = aiController.aiReview(reviewBo);\nAiChatVo response = result.getData();\n\n// 解析审核结果\nif (response.getMessage().contains(\"通过\")) {\n // 内容合规,允许发布\n} else {\n // 内容违规,拒绝发布\n}\n```\n\n### 5. 文本翻译功能\n\n提供多语言翻译服务。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiTranslate\")\n@OpenApi(value = \"AI文本翻译\")\npublic R aiTranslate(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiTranslate(bo));\n}\n```\n\n#### 使用场景\n\n- 多语言网站内容翻译\n- 用户评论翻译\n- 产品说明翻译\n- 客服消息翻译\n\n#### 请求示例\n\n```java\nAiChatBo translateBo = new AiChatBo();\ntranslateBo.setMessage(\"Hello, how are you today?\");\ntranslateBo.setAiFeature(\"translate\");\ntranslateBo.setSystemPrompt(\"请将以下英文翻译成中文\");\n\nR result = aiController.aiTranslate(translateBo);\n// 翻译结果: \"你好,你今天怎么样?\"\n```\n\n### AI配置说明\n\n#### LangChain4j 配置\n\n在 `application.yml` 中配置 LangChain4j:\n\n```yaml\nlangchain4j:\n enabled: true # 启用AI功能\n\n # DeepSeek 配置\n deepseek:\n api-key: ${DEEPSEEK_API_KEY}\n base-url: https://api.deepseek.com/v1\n model-name: deepseek-chat\n temperature: 0.7\n max-tokens: 2000\n timeout: 60s\n\n # 通义千问配置\n qianwen:\n api-key: ${QIANWEN_API_KEY}\n base-url: https://dashscope.aliyuncs.com/api/v1\n model-name: qwen-plus\n temperature: 0.7\n max-tokens: 2000\n\n # OpenAI 配置\n openai:\n api-key: ${OPENAI_API_KEY}\n base-url: https://api.openai.com/v1\n model-name: gpt-3.5-turbo\n temperature: 0.7\n max-tokens: 2000\n```\n\n#### 环境变量配置\n\n推荐使用环境变量管理敏感的API密钥:\n\n```bash\n# .env 文件\nDEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx\nQIANWEN_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx\nOPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx\n```\n\n#### 权限配置\n\n在菜单管理中配置AI功能权限:\n\n```sql\n-- AI对话权限\nINSERT INTO sys_menu (menu_name, parent_id, perms)\nVALUES ('AI对话', 1000, 'base:ai:chat');\n```\n\n### AI功能集成示例\n\n#### 示例1:智能客服回复\n\n```java\n@Service\npublic class CustomerServiceImpl implements ICustomerService {\n\n @Autowired\n private IAiService aiService;\n\n @Override\n public String handleCustomerQuestion(String question) {\n AiChatBo chatBo = new AiChatBo();\n chatBo.setMessage(question);\n chatBo.setProvider(\"deepseek\");\n chatBo.setSystemPrompt(\"你是一个友好的客服助手,请专业地回答客户问题\");\n\n AiChatVo response = aiService.aiChat(chatBo);\n return response.getMessage();\n }\n}\n```\n\n#### 示例2:文章内容审核\n\n```java\n@Service\npublic class ArticleServiceImpl extends ServiceImpl implements IArticleService {\n\n @Autowired\n private IAiService aiService;\n\n @Override\n public boolean publishArticle(Article article) {\n // 使用AI审核文章内容\n AiChatBo reviewBo = new AiChatBo();\n reviewBo.setMessage(article.getContent());\n reviewBo.setAiFeature(\"review\");\n reviewBo.setSystemPrompt(\"请审核文章内容是否合规,检查是否包含违规、敏感信息\");\n\n AiChatVo reviewResult = aiService.aiReview(reviewBo);\n\n // 判断审核结果\n if (reviewResult.getMessage().contains(\"违规\")) {\n throw new ServiceException(\"文章内容审核未通过: \" + reviewResult.getMessage());\n }\n\n // 审核通过,发布文章\n article.setStatus(\"published\");\n return this.updateById(article);\n }\n}\n```\n\n#### 示例3:数据智能生成\n\n```java\n@Service\npublic class DataGeneratorService {\n\n @Autowired\n private IAiService aiService;\n\n @Override\n public List generateTestUsers(int count) {\n AiChatBo generateBo = new AiChatBo();\n generateBo.setMessage(\n String.format(\"生成%d个用户测试数据,包含真实的中文姓名、邮箱、手机号\", count)\n );\n generateBo.setAiFeature(\"generate\");\n\n // 传递数据结构上下文\n Map context = new HashMap<>();\n context.put(\"format\", \"json\");\n context.put(\"fields\", Arrays.asList(\"name\", \"email\", \"phone\", \"age\", \"gender\"));\n generateBo.setContext(context);\n\n AiChatVo response = aiService.aiGenerate(generateBo);\n\n // 解析生成的JSON数据\n return JsonUtils.parseArray(response.getMessage(), User.class);\n }\n}\n```\n\n## 数据访问层架构\n\n### DAO模式说明\n\n基础服务模块采用 **DAO(Data Access Object)** 模式,将数据访问逻辑与业务逻辑分离,提供更清晰的架构层次。\n\n#### 架构层次\n\n```text\nController 层\n ↓\nService 层\n ↓\nDAO 层 (IBaseDao)\n ↓\nEntity 层 (数据库实体)\n```\n\n#### IBaseDao 接口\n\n所有 DAO 接口都继承自 `IBaseDao`,提供统一的 CRUD 操作:\n\n```java\npublic interface IBaseDao {\n // 插入\n boolean insert(T entity);\n boolean insertBatch(Collection entityList);\n\n // 更新\n boolean updateById(T entity);\n boolean updateBatchById(Collection entityList);\n\n // 删除\n boolean deleteById(Serializable id);\n boolean deleteBatchIds(Collection idList);\n\n // 查询\n T selectById(Serializable id);\n List selectBatchIds(Collection idList);\n List selectList(Wrapper queryWrapper);\n T selectOne(Wrapper queryWrapper);\n Long selectCount(Wrapper queryWrapper);\n\n // 分页查询\n Page selectPage(Page page, Wrapper queryWrapper);\n}\n```\n\n### 平台配置DAO (IPlatformDao)\n\n```java\npublic interface IPlatformDao extends IBaseDao {\n\n /**\n * 根据业务对象构建查询条件\n */\n PlusLambdaQuery buildQueryWrapper(PlatformBo bo);\n\n /**\n * 根据appid查询平台配置\n */\n Platform getByAppid(String appid);\n\n /**\n * 根据appid和平台类型查询平台配置\n */\n Platform getByAppidAndType(String appid, String type, String status);\n\n /**\n * 根据平台类型和状态查询配置列表\n */\n List listByTypeAndStatus(String type, String status);\n}\n```\n\n### 支付配置DAO (IPaymentDao)\n\n```java\npublic interface IPaymentDao extends IBaseDao {\n\n /**\n * 根据商户号查询支付配置\n */\n Payment getByMchId(String mchId, String status);\n\n /**\n * 根据支付类型和状态查询配置列表\n */\n List listByTypeAndStatus(String type, String status);\n\n /**\n * 根据状态统计配置数量\n */\n long countByStatus(String status);\n\n /**\n * 根据商户号查询是否存在(排除指定ID)\n */\n boolean existsByMchId(String mchId, Long excludeId);\n\n /**\n * 根据商户号和状态判断是否存在\n */\n boolean existsByMchIdAndStatus(String mchId, String status);\n\n /**\n * 根据状态查询配置列表\n */\n List listByStatus(String status);\n}\n```\n\n### DAO层使用示例\n\n```java\n@Service\npublic class PlatformServiceImpl implements IPlatformService {\n\n @Autowired\n private IPlatformDao platformDao;\n\n @Override\n public PlatformVo getWeixinPlatform(String appid) {\n // 使用DAO查询微信小程序配置\n Platform platform = platformDao.getByAppidAndType(\n appid,\n \"mp-weixin\",\n DictEnableStatus.ENABLE.getValue()\n );\n\n if (platform == null) {\n throw new ServiceException(\"未找到微信小程序配置\");\n }\n\n return BeanUtil.toBean(platform, PlatformVo.class);\n }\n\n @Override\n public List listActivePlatforms(String type) {\n // 使用DAO查询所有启用的平台配置\n List platforms = platformDao.listByTypeAndStatus(\n type,\n DictEnableStatus.ENABLE.getValue()\n );\n\n return BeanUtil.copyToList(platforms, PlatformVo.class);\n }\n}\n```\n\n## 高级功能\n\n### 多租户支持\n\n基础服务模块所有实体类都继承自 `TenantEntity`,自动支持多租户数据隔离。\n\n#### 租户实体基类\n\n```java\n@Data\npublic class TenantEntity extends BaseEntity {\n\n /**\n * 租户ID\n */\n @TableField(value = \"tenant_id\")\n private String tenantId;\n\n /**\n * 创建部门\n */\n @TableField(value = \"create_dept\")\n private Long createDept;\n}\n```\n\n#### 自动租户隔离\n\n```java\n// 查询时自动添加租户条件\nPlatform platform = platformDao.selectById(platformId);\n// SQL: SELECT * FROM b_platform WHERE id = ? AND tenant_id = '当前租户ID'\n\n// 新增时自动填充租户ID\nPlatform newPlatform = new Platform();\nnewPlatform.setType(\"mp-weixin\");\nplatformDao.insert(newPlatform);\n// SQL: INSERT INTO b_platform (..., tenant_id) VALUES (..., '当前租户ID')\n```\n\n### 数据缓存机制\n\n#### Redis缓存配置\n\n平台配置和支付配置支持Redis缓存,提升查询性能:\n\n```java\n@Service\npublic class PlatformCacheService {\n\n private static final String PLATFORM_CACHE_KEY = \"platform:config:\";\n private static final Duration CACHE_EXPIRE = Duration.ofHours(1);\n\n @Autowired\n private RedisTemplate redisTemplate;\n\n @Autowired\n private IPlatformDao platformDao;\n\n public Platform getPlatformWithCache(String appid) {\n String cacheKey = PLATFORM_CACHE_KEY + appid;\n\n // 尝试从缓存获取\n Platform platform = redisTemplate.opsForValue().get(cacheKey);\n if (platform != null) {\n return platform;\n }\n\n // 缓存未命中,查询数据库\n platform = platformDao.getByAppid(appid);\n if (platform != null) {\n // 写入缓存\n redisTemplate.opsForValue().set(cacheKey, platform, CACHE_EXPIRE);\n }\n\n return platform;\n }\n\n public void clearPlatformCache(String appid) {\n String cacheKey = PLATFORM_CACHE_KEY + appid;\n redisTemplate.delete(cacheKey);\n }\n}\n```\n\n### 事件监听机制\n\n#### 配置变更事件\n\n```java\n@Component\npublic class PlatformConfigEventListener {\n\n @Autowired\n private WxMaApplicationRunner wxMaRunner;\n\n @Autowired\n private WxMpApplicationRunner wxMpRunner;\n\n /**\n * 监听平台配置变更事件\n */\n @EventListener\n public void handlePlatformConfigChange(PlatformConfigChangeEvent event) {\n String tenantId = event.getTenantId();\n String platformType = event.getPlatformType();\n\n // 根据平台类型重新初始化配置\n if (\"mp-weixin\".equals(platformType)) {\n wxMaRunner.initByTenant(tenantId);\n } else if (\"mp-official-account\".equals(platformType)) {\n wxMpRunner.initByTenant(tenantId);\n }\n\n log.info(\"平台配置已更新: tenantId={}, platformType={}\", tenantId, platformType);\n }\n}\n```\n\n#### 自定义事件\n\n```java\n@Data\npublic class PlatformConfigChangeEvent extends ApplicationEvent {\n\n private String tenantId;\n private String platformType;\n private String action; // create, update, delete\n\n public PlatformConfigChangeEvent(Object source, String tenantId, String platformType, String action) {\n super(source);\n this.tenantId = tenantId;\n this.platformType = platformType;\n this.action = action;\n }\n}\n\n// 发布事件\n@Service\npublic class PlatformServiceImpl implements IPlatformService {\n\n @Autowired\n private ApplicationEventPublisher eventPublisher;\n\n @Override\n @Transactional\n public boolean updatePlatform(PlatformBo bo) {\n boolean result = platformDao.updateById(BeanUtil.toBean(bo, Platform.class));\n\n if (result) {\n // 发布配置变更事件\n eventPublisher.publishEvent(\n new PlatformConfigChangeEvent(this, TenantHelper.getTenantId(), bo.getType(), \"update\")\n );\n }\n\n return result;\n }\n}\n```\n\n## 常见问题\n\n### Q1: 平台配置不生效?\n\n**问题原因:**\n- 配置状态未启用\n- 租户ID不匹配\n- 缓存未更新\n- appid配置错误\n\n**解决方案:**\n\n```java\n// 1. 检查配置状态\nPlatform platform = platformDao.getByAppid(appid);\nif (!\"1\".equals(platform.getStatus())) {\n throw new ServiceException(\"平台配置未启用\");\n}\n\n// 2. 检查租户ID\nString currentTenantId = TenantHelper.getTenantId();\nif (!currentTenantId.equals(platform.getTenantId())) {\n throw new ServiceException(\"平台配置不属于当前租户\");\n}\n\n// 3. 清除缓存重新加载\nwxMaApplicationRunner.initByTenant(currentTenantId);\n```\n\n### Q2: 第三方登录失败?\n\n**问题原因:**\n- appid或secret配置错误\n- 授权码已过期\n- 平台配置未找到\n- 网络连接问题\n\n**解决方案:**\n\n```java\ntry {\n // 使用授权码登录\n AuthTokenVo authToken = authStrategy.login(loginBody);\n} catch (WxErrorException e) {\n // 微信接口调用失败\n log.error(\"微信登录失败: errCode={}, errMsg={}\", e.getError().getErrorCode(), e.getError().getErrorMsg());\n\n if (e.getError().getErrorCode() == 40029) {\n throw new ServiceException(\"授权码无效或已过期,请重新授权\");\n } else if (e.getError().getErrorCode() == 40013) {\n throw new ServiceException(\"appid配置错误\");\n } else {\n throw new ServiceException(\"登录失败: \" + e.getError().getErrorMsg());\n }\n}\n```\n\n### Q3: 支付配置重复?\n\n**问题原因:**\n- 同一商户号被多次配置\n- 未进行唯一性校验\n\n**解决方案:**\n\n```java\n@Service\npublic class PaymentServiceImpl implements IPaymentService {\n\n @Override\n public boolean addPayment(PaymentBo bo) {\n // 检查商户号是否已存在\n boolean exists = paymentDao.existsByMchIdAndStatus(\n bo.getMchId(),\n DictEnableStatus.ENABLE.getValue()\n );\n\n if (exists) {\n throw new ServiceException(\"该商户号已存在有效配置\");\n }\n\n Payment payment = BeanUtil.toBean(bo, Payment.class);\n return paymentDao.insert(payment);\n }\n\n @Override\n public boolean updatePayment(PaymentBo bo) {\n // 检查商户号是否与其他记录重复(排除当前记录)\n boolean exists = paymentDao.existsByMchId(bo.getMchId(), bo.getId());\n\n if (exists) {\n throw new ServiceException(\"该商户号已被其他配置使用\");\n }\n\n Payment payment = BeanUtil.toBean(bo, Payment.class);\n return paymentDao.updateById(payment);\n }\n}\n```\n\n### Q4: AI功能无法使用?\n\n**问题原因:**\n- LangChain4j未启用\n- API密钥配置错误\n- 网络连接问题\n- 权限未配置\n\n**解决方案:**\n\n```yaml\n# 1. 确保配置已启用\nlangchain4j:\n enabled: true # 必须为 true\n\n# 2. 检查API密钥\ndeepseek:\n api-key: ${DEEPSEEK_API_KEY} # 确保环境变量已设置\n\n# 3. 测试网络连接\ncurl -X POST https://api.deepseek.com/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\"model\":\"deepseek-chat\",\"messages\":[{\"role\":\"user\",\"content\":\"Hello\"}]}'\n\n# 4. 配置权限\nINSERT INTO sys_menu (menu_name, perms) VALUES ('AI对话', 'base:ai:chat');\n```\n\n## 故障排查\n\n### 日志配置\n\n#### 启用详细日志\n\n```yaml\nlogging:\n level:\n plus.ruoyi.business.base: DEBUG\n plus.ruoyi.business.base.controller: DEBUG\n plus.ruoyi.business.base.service: DEBUG\n plus.ruoyi.business.base.dao: DEBUG\n plus.ruoyi.business.base.authStrategy: DEBUG\n```\n\n### 常见错误及解决方案\n\n#### 错误1: 平台配置未找到\n\n```text\n错误信息: ServiceException: 未找到平台配置\n```\n\n**排查步骤:**\n1. 检查数据库中是否存在配置记录\n2. 检查appid是否正确\n3. 检查配置状态是否启用\n4. 检查租户ID是否匹配\n\n```java\n// 调试代码\nPlatform platform = platformDao.selectOne(\n new LambdaQueryWrapper()\n .eq(Platform::getAppid, appid)\n);\nSystem.out.println(\"查询到的平台配置: \" + JsonUtils.toJsonString(platform));\n```\n\n#### 错误2: 认证策略未找到\n\n```text\n错误信息: No bean named 'miniappAuthStrategy' available\n```\n\n**排查步骤:**\n1. 检查认证策略类是否标注 `@Service` 注解\n2. 检查策略名称是否正确\n3. 检查Spring扫描路径是否包含策略类\n\n```java\n// 正确的策略命名\n@Service(\"miniapp\" + IAuthStrategy.BASE_NAME) // miniappAuthStrategy\npublic class MiniappAuthStrategy implements IAuthStrategy {\n // ...\n}\n```\n\n#### 错误3: 多租户数据泄露\n\n```text\n错误信息: 查询到了其他租户的数据\n```\n\n**排查步骤:**\n1. 检查实体类是否继承 `TenantEntity`\n2. 检查租户拦截器是否生效\n3. 检查数据表是否包含 `tenant_id` 字段\n\n```java\n// 确保实体类正确继承\n@TableName(\"b_platform\")\npublic class Platform extends TenantEntity {\n // 自动支持租户隔离\n}\n```\n\n## API参考\n\n### Controller接口清单\n\n| 控制器 | 路径 | 功能说明 |\n|--------|------|----------|\n| PlatformController | `/base/platform/*` | 平台配置管理 |\n| PaymentController | `/base/payment/*` | 支付配置管理 |\n| BindController | `/base/bind/*` | 账号绑定管理 |\n| AdController | `/base/ad/*` | 广告配置管理 |\n| AiController | `/base/ai/*` | AI助手功能 |\n\n### 核心接口详情\n\n#### 平台配置接口\n\n```java\nGET /base/platform/list 查询平台配置列表\nGET /base/platform/{id} 查询平台配置详情\nPOST /base/platform 新增平台配置\nPUT /base/platform 更新平台配置\nDELETE /base/platform/{ids} 删除平台配置\nGET /base/platform/dict 获取平台字典\n```\n\n#### 支付配置接口\n\n```java\nGET /base/payment/list 查询支付配置列表\nGET /base/payment/{id} 查询支付配置详情\nPOST /base/payment 新增支付配置\nPUT /base/payment 更新支付配置\nDELETE /base/payment/{ids} 删除支付配置\nGET /base/payment/dict 获取支付方式字典\n```\n\n#### 账号绑定接口\n\n```java\nGET /base/bind/list 查询绑定列表\nPOST /base/bind/bindPhone 绑定手机号\nPOST /base/bind/unbind 解除绑定\n```\n\n#### AI助手接口\n\n```java\nPOST /base/ai/aiChat AI对话\nPOST /base/ai/aiOptimize 文本优化\nPOST /base/ai/aiGenerate 数据生成\nPOST /base/ai/aiReview 内容审核\nPOST /base/ai/aiTranslate 文本翻译\n```\n\n## 最佳实践\n\n### 配置管理\n- 敏感信息(如密钥)使用环境变量或加密存储\n- 支持配置热更新,通过事件机制通知相关服务\n- 按租户隔离配置,确保数据安全\n- 使用Redis缓存常用配置,提升性能\n\n### 安全考虑\n- 登录令牌设置合理的过期时间(建议2小时)\n- 敏感API添加 `@SaCheckPermission` 权限校验\n- 支付配置访问权限严格控制\n- AI接口调用添加频率限制,防止滥用\n- API密钥使用环境变量管理,不提交到代码仓库\n\n### 性能优化\n- 平台配置和支付配置使用Redis缓存,有效期1小时\n- 异步处理配置更新,使用Spring事件机制\n- 合理使用数据库索引(appid、mchId等字段)\n- AI接口调用使用连接池,复用HTTP连接\n- 批量查询使用 `selectBatchIds` 而不是循环查询\n\n### 扩展建议\n- 新增平台时,实现对应的 `IAuthStrategy` 认证策略\n- 支付方式扩展遵循统一的 DAO 接口规范\n- 配置项变更通过 `ApplicationEventPublisher` 发布事件\n- AI功能扩展可添加新的服务方法,保持接口一致性\n- 建议为每个租户配置独立的平台和支付配置\n"}, "d6768318945b2253c42088175a92e4d6a62be910": {"t": 1785765304.0229049, "n": 27735, "h": "72144b0794344a02", "c": "# 基础服务模块 (base)\n\n基础服务模块提供了系统运行所需的核心基础服务,包括多平台配置管理、支付配置管理、广告配置、账号绑定等功能。\n\n## 模块结构\n\n```text\nbase/\n├── controller/ # 控制器层\n│ ├── AdController.java\n│ ├── BindController.java\n│ ├── PaymentController.java\n│ └── PlatformController.java\n├── service/ # 服务层\n│ ├── IAdService.java\n│ ├── IBindService.java\n│ ├── IPaymentService.java\n│ └── IPlatformService.java\n├── domain/ # 数据模型\n│ ├── entity/ # 实体类\n│ ├── vo/ # 视图对象\n│ └── bo/ # 业务对象\n├── mapper/ # 数据访问层\n└── authStrategy/ # 认证策略\n```\n\n## 核心功能\n\n### 平台配置管理\n\n支持多种平台的统一配置管理:\n\n- **微信小程序** (mp-weixin)\n- **微信公众号** (mp-official-account)\n- **支付宝小程序** (mp-alipay)\n- **QQ小程序** (mp-qq)\n- **其他平台** (mp-jd, mp-kuaishou, mp-lark, mp-baidu, mp-toutiao, mp-xhs)\n\n#### 平台配置实体\n```java\n@Data\n@TableName(\"b_platform\")\npublic class Platform extends TenantEntity {\n private Long id; // 平台配置ID\n private String type; // 平台类型\n private String name; // 平台名称\n private String appid; // 应用ID\n private String secret; // 应用密钥\n private String token; // 接口Token\n private String aeskey; // 加密密钥\n private String paymentIds; // 关联支付配置\n private String templateConfigs; // 模板配置\n private String status; // 状态\n}\n```\n\n#### 核心接口\n```java\npublic interface IPlatformService extends IBaseService {\n // 继承基础CRUD操作\n}\n\n// 全局平台服务\npublic interface PlatformService {\n List listPlatformsByType(String type, String tenantId);\n PlatformDTO getPlatformByAppidAndType(String appid, String type);\n PlatformDTO getPlatformByAppid(String appid, String tenantId);\n}\n```\n\n### 支付配置管理\n\n统一的支付配置管理,支持多种支付方式:\n\n#### 支付配置实体\n```java\n@Data\n@TableName(\"b_payment\") \npublic class Payment extends TenantEntity {\n private Long id; // 支付配置ID\n private String type; // 商户类型\n private String mchName; // 商户名称\n private String mchId; // 商户号\n private String mchKey; // 商户密钥\n private String apiV3Key; // APIv3密钥\n private String certPath; // 证书路径\n private String keyPath; // 密钥路径\n private String certSerialNo; // 证书序列号\n private String status; // 状态\n}\n```\n\n#### 核心服务\n```java\npublic interface PaymentService {\n List listPaymentByType(String type, String tenantId);\n PaymentDTO getByMchId(String mchId);\n PaymentDTO getById(Long paymentId);\n boolean existsValidMchId(String mchId);\n long countPayments();\n}\n```\n\n### 账号绑定管理\n\n管理用户在不同平台的账号绑定关系:\n\n#### 绑定实体\n```java\n@Data\n@TableName(\"b_bind\")\npublic class Bind extends TenantEntity {\n private Long id; // 绑定ID\n private Long userId; // 用户ID\n private String platformType; // 平台类型\n private String appid; // 应用ID\n private String unionid; // 统一标识\n private String openid; // 平台标识\n private String extraData; // 扩展数据\n}\n```\n\n#### 绑定服务\n```java\npublic interface IBindService extends IBaseService {\n /**\n * 根据平台用户信息获取或创建绑定信息\n */\n BindVo getOrCreateBind(PlatformUserInfoVo platformUserInfoVo);\n \n /**\n * 更新绑定信息的用户ID\n */\n void updateBindUserId(BindBo bindBo, Long userId);\n}\n```\n\n### 广告配置管理\n\n提供广告位和广告内容的统一管理:\n\n#### 广告实体\n```java\n@Data\n@TableName(\"b_ad\")\npublic class Ad extends TenantEntity {\n private Long id; // 广告ID\n private String appid; // 应用ID\n private String adUnitId; // 广告位ID\n private String adName; // 广告名称\n private String adType; // 广告类型\n private String position; // 投放位置\n private String img; // 广告图片\n private String description; // 描述\n private String jumpAppid; // 跳转应用ID\n private String jumpPath; // 跳转路径\n private String styleConfig; // 样式配置\n private Long sortOrder; // 排序值\n private String status; // 状态\n}\n```\n\n## 认证策略\n\n### 多平台认证架构\n\n基于策略模式实现多平台登录认证:\n\n#### 认证策略接口\n```java\npublic interface IAuthStrategy {\n String BASE_NAME = \"AuthStrategy\";\n AuthTokenVo login(String body);\n}\n```\n\n#### 小程序认证策略\n```java\n@Service(\"miniapp\" + IAuthStrategy.BASE_NAME)\npublic class MiniappAuthStrategy implements IAuthStrategy {\n \n @Override\n public AuthTokenVo login(String body) {\n // 1. 解析请求参数\n PlatformLoginBody loginBody = JsonUtils.parseObject(body, PlatformLoginBody.class);\n \n // 2. 获取平台用户信息\n PlatformUserInfoVo platformUserInfo = getMiniappUserIdentity(loginBody);\n \n // 3. 加载或创建用户\n SysUserVo user = loadOrCreateUser(platformUserInfo);\n \n // 4. 生成登录令牌\n LoginUser loginUser = loginService.createLoginUser(user);\n loginUser.setPlatform(platformUserInfo.getPlatform());\n loginUser.setAppid(platformUserInfo.getAppid());\n loginUser.setOpenid(platformUserInfo.getOpenid());\n loginUser.setUnionid(platformUserInfo.getUnionid());\n \n // 5. 完成登录\n LoginHelper.login(loginUser, loginParameter);\n \n // 6. 返回认证结果\n AuthTokenVo authTokenVo = new AuthTokenVo();\n authTokenVo.setAccessToken(StpUtil.getTokenValue());\n authTokenVo.setExpireIn(StpUtil.getTokenTimeout());\n return authTokenVo;\n }\n}\n```\n\n#### 公众号认证策略\n```java\n@Service(\"mp\" + IAuthStrategy.BASE_NAME)\npublic class MpAuthStrategy implements IAuthStrategy {\n // 公众号OAuth2.0认证流程实现\n // 支持网页授权登录场景\n}\n```\n\n### 认证流程\n\n1. **前端授权**:用户在前端完成平台授权,获取授权码\n2. **策略选择**:后端根据平台类型自动选择对应认证策略\n3. **信息获取**:通过授权码换取用户基本信息\n4. **账号绑定**:查找或创建用户账号绑定关系\n5. **令牌生成**:生成JWT访问令牌\n6. **登录完成**:返回令牌和用户信息\n\n## 手机号绑定\n\n### 微信小程序手机号获取\n```java\n@PostMapping(\"/bindPhone\")\npublic R bindPhone(@RequestBody PhoneBindBo bo) {\n LoginUser loginUser = LoginHelper.getLoginUser();\n wxMaService.switchover(loginUser.getAppid());\n \n try {\n WxMaPhoneNumberInfo phoneInfo = wxMaService.getUserService().getPhoneNumber(bo.getCode());\n String phone = phoneInfo.getPhoneNumber();\n \n // 更新用户手机号\n SysUser sysUser = userMapper.selectById(loginUser.getUserId());\n sysUser.setPhone(phone);\n userMapper.updateById(sysUser);\n \n return R.ok(\"绑定成功\", PhoneBindVo.of(phone));\n } catch (WxErrorException e) {\n return R.fail(\"获取手机号出错\");\n }\n}\n```\n\n## 数据字典服务\n\n### 支付方式字典\n```java\n@GetMapping(\"getPaymentDict\")\npublic R> getPaymentDict() {\n // 查询所有可用的支付方式\n List paymentVoList = paymentService.list(\n PlusLambdaQuery.of(Payment.class)\n .eq(Payment::getStatus, DictEnableStatus.ENABLE.getValue()));\n \n // 构建字典项列表\n List dictItems = StreamUtils.toList(paymentVoList, payment ->\n DictItemVo.of(payment.getMchName(), payment.getId().toString(), \"success\")\n );\n return R.ok(dictItems);\n}\n```\n\n## 配置管理\n\n### 平台配置热更新\n```java\nprivate void reloadPlatformConfig() {\n String tenantId = TenantHelper.getTenantId();\n \n // 重新初始化微信小程序配置\n SpringUtils.getBean(WxMaApplicationRunner.class).initByTenant(tenantId);\n \n // 重新初始化微信公众号配置 \n SpringUtils.getBean(WxMpApplicationRunner.class).initByTenant(tenantId);\n \n // 重新初始化支付配置\n SpringUtils.getBean(PayApplicationRunner.class).initByTenant(tenantId);\n}\n```\n\n### 支付配置热更新\n```java\nprivate void reloadPaymentConfig() {\n String tenantId = TenantHelper.getTenantId();\n SpringUtils.getBean(PayApplicationRunner.class).initByTenant(tenantId);\n}\n```\n\n## 使用示例\n\n### 配置微信小程序\n```java\n// 1. 创建平台配置\nPlatformBo platformBo = new PlatformBo();\nplatformBo.setType(\"mp-weixin\");\nplatformBo.setName(\"我的小程序\");\nplatformBo.setAppid(\"wx1234567890\");\nplatformBo.setSecret(\"your-secret\");\nplatformBo.setStatus(\"1\");\nplatformService.add(platformBo);\n\n// 2. 配置支付信息\nPaymentBo paymentBo = new PaymentBo();\npaymentBo.setType(\"wechat\");\npaymentBo.setMchName(\"我的商户\");\npaymentBo.setMchId(\"1234567890\");\npaymentBo.setMchKey(\"your-mch-key\");\npaymentBo.setStatus(\"1\");\npaymentService.add(paymentBo);\n```\n\n### 用户登录认证\n```java\n// 前端调用登录接口\nPOST /auth/login\n{\n \"platform\": \"miniapp\",\n \"body\": {\n \"platform\": \"mp-weixin\",\n \"appid\": \"wx1234567890\",\n \"platformCode\": \"授权码\"\n }\n}\n\n// 返回结果\n{\n \"code\": 200,\n \"msg\": \"登录成功\",\n \"data\": {\n \"accessToken\": \"eyJ0eXAiOiJKV1Q...\",\n \"expireIn\": 7200\n }\n}\n```\n\n## AI助手功能\n\n### 功能概述\n\n基础服务模块集成了强大的AI助手功能,基于 **LangChain4j** 框架实现,支持多种大语言模型(如 DeepSeek、通义千问、OpenAI、Claude等),为业务系统提供智能化能力。\n\n**核心特性:**\n- **多模型支持** - 灵活切换不同的AI模型提供商\n- **多场景应用** - 对话、优化、生成、审核、翻译等场景\n- **条件启用** - 通过配置开关控制功能启用\n- **权限控制** - 完善的权限校验机制\n- **上下文传递** - 支持业务上下文信息传递\n\n### AI服务接口\n\n#### AiController 控制器\n\n```java\n@RestController\n@RequestMapping(\"/base/ai\")\n@ConditionalOnProperty(\n prefix = \"langchain4j\",\n name = \"enabled\",\n havingValue = \"true\",\n matchIfMissing = true\n)\npublic class AiController {\n private final IAiService aiService;\n}\n```\n\n**条件启用说明:**\n- 需要在配置文件中设置 `langchain4j.enabled=true`\n- 如果配置项不存在,默认启用 (`matchIfMissing = true`)\n\n### 1. AI对话功能\n\n通用的AI对话接口,支持自由对话场景。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiChat\")\n@OpenApi(value = \"AI对话\")\npublic R aiChat(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiChat(bo));\n}\n```\n\n#### 请求示例\n\n```java\n// 创建对话请求\nAiChatBo chatBo = new AiChatBo();\nchatBo.setMessage(\"请帮我解释一下什么是微服务架构\");\nchatBo.setProvider(\"deepseek\");\nchatBo.setModelName(\"deepseek-chat\");\nchatBo.setTemperature(0.7);\nchatBo.setMaxTokens(2000);\n\n// 调用接口\nR result = aiController.aiChat(chatBo);\nAiChatVo response = result.getData();\nSystem.out.println(\"AI回复: \" + response.getMessage());\n```\n\n#### HTTP 调用示例\n\n```bash\nPOST /base/ai/aiChat\nContent-Type: application/json\n\n{\n \"message\": \"请帮我解释一下什么是微服务架构\",\n \"provider\": \"deepseek\",\n \"modelName\": \"deepseek-chat\",\n \"temperature\": 0.7,\n \"maxTokens\": 2000\n}\n```\n\n### 2. 文本优化功能\n\n对用户输入的文本进行优化,改善表达和文风。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiOptimize\")\n@OpenApi(value = \"AI文本优化\")\npublic R aiOptimize(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiOptimize(bo));\n}\n```\n\n#### 使用场景\n\n- 文章润色和改写\n- 产品描述优化\n- 邮件内容优化\n- 广告文案优化\n\n#### 请求示例\n\n```java\nAiChatBo optimizeBo = new AiChatBo();\noptimizeBo.setMessage(\"我们公司是做软件开发的,主要业务是给客户做系统\");\noptimizeBo.setAiFeature(\"optimize\");\noptimizeBo.setSystemPrompt(\"请将下列文本优化为更专业的企业简介\");\n\nR result = aiController.aiOptimize(optimizeBo);\n// 优化后: \"我们是一家专业的软件开发公司,致力于为企业客户提供定制化系统解决方案...\"\n```\n\n### 3. 数据生成功能\n\n根据用户需求生成结构化数据或内容。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiGenerate\")\n@OpenApi(value = \"AI数据生成\")\npublic R aiGenerate(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiGenerate(bo));\n}\n```\n\n#### 使用场景\n\n- 生成测试数据\n- 生成产品描述\n- 生成代码片段\n- 生成用户画像\n\n#### 请求示例\n\n```java\nAiChatBo generateBo = new AiChatBo();\ngenerateBo.setMessage(\"生成5个用户的测试数据,包含姓名、年龄、邮箱\");\ngenerateBo.setAiFeature(\"generate\");\n\n// 传递表单字段信息作为上下文\nMap context = new HashMap<>();\ncontext.put(\"fields\", Arrays.asList(\"name\", \"age\", \"email\"));\ncontext.put(\"count\", 5);\ngenerateBo.setContext(context);\n\nR result = aiController.aiGenerate(generateBo);\n```\n\n**生成结果示例:**\n```json\n[\n {\"name\": \"张三\", \"age\": 28, \"email\": \"zhangsan@example.com\"},\n {\"name\": \"李四\", \"age\": 32, \"email\": \"lisi@example.com\"},\n {\"name\": \"王五\", \"age\": 25, \"email\": \"wangwu@example.com\"},\n {\"name\": \"赵六\", \"age\": 30, \"email\": \"zhaoliu@example.com\"},\n {\"name\": \"钱七\", \"age\": 27, \"email\": \"qianqi@example.com\"}\n]\n```\n\n### 4. 内容审核功能\n\n对用户提交的内容进行智能审核,检测违规内容。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiReview\")\n@OpenApi(value = \"AI内容审核\")\npublic R aiReview(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiReview(bo));\n}\n```\n\n#### 使用场景\n\n- 评论内容审核\n- 文章内容审核\n- 用户昵称审核\n- 敏感词检测\n\n#### 请求示例\n\n```java\nAiChatBo reviewBo = new AiChatBo();\nreviewBo.setMessage(\"待审核的用户评论内容...\");\nreviewBo.setAiFeature(\"review\");\nreviewBo.setSystemPrompt(\"请审核以下内容是否包含违规、敏感、广告等不当信息\");\n\nR result = aiController.aiReview(reviewBo);\nAiChatVo response = result.getData();\n\n// 解析审核结果\nif (response.getMessage().contains(\"通过\")) {\n // 内容合规,允许发布\n} else {\n // 内容违规,拒绝发布\n}\n```\n\n### 5. 文本翻译功能\n\n提供多语言翻译服务。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiTranslate\")\n@OpenApi(value = \"AI文本翻译\")\npublic R aiTranslate(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiTranslate(bo));\n}\n```\n\n#### 使用场景\n\n- 多语言网站内容翻译\n- 用户评论翻译\n- 产品说明翻译\n- 客服消息翻译\n\n#### 请求示例\n\n```java\nAiChatBo translateBo = new AiChatBo();\ntranslateBo.setMessage(\"Hello, how are you today?\");\ntranslateBo.setAiFeature(\"translate\");\ntranslateBo.setSystemPrompt(\"请将以下英文翻译成中文\");\n\nR result = aiController.aiTranslate(translateBo);\n// 翻译结果: \"你好,你今天怎么样?\"\n```\n\n### AI配置说明\n\n#### LangChain4j 配置\n\n在 `application.yml` 中配置 LangChain4j:\n\n```yaml\nlangchain4j:\n enabled: true # 启用AI功能\n\n # DeepSeek 配置\n deepseek:\n api-key: ${DEEPSEEK_API_KEY}\n base-url: https://api.deepseek.com/v1\n model-name: deepseek-chat\n temperature: 0.7\n max-tokens: 2000\n timeout: 60s\n\n # 通义千问配置\n qianwen:\n api-key: ${QIANWEN_API_KEY}\n base-url: https://dashscope.aliyuncs.com/api/v1\n model-name: qwen-plus\n temperature: 0.7\n max-tokens: 2000\n\n # OpenAI 配置\n openai:\n api-key: ${OPENAI_API_KEY}\n base-url: https://api.openai.com/v1\n model-name: gpt-3.5-turbo\n temperature: 0.7\n max-tokens: 2000\n```\n\n#### 环境变量配置\n\n推荐使用环境变量管理敏感的API密钥:\n\n```bash\n# .env 文件\nDEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx\nQIANWEN_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx\nOPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx\n```\n\n#### 权限配置\n\n在菜单管理中配置AI功能权限:\n\n```sql\n-- AI对话权限\nINSERT INTO sys_menu (menu_name, parent_id, perms)\nVALUES ('AI对话', 1000, 'base:ai:chat');\n```\n\n### AI功能集成示例\n\n#### 示例1:智能客服回复\n\n```java\n@Service\npublic class CustomerServiceImpl implements ICustomerService {\n\n @Autowired\n private IAiService aiService;\n\n @Override\n public String handleCustomerQuestion(String question) {\n AiChatBo chatBo = new AiChatBo();\n chatBo.setMessage(question);\n chatBo.setProvider(\"deepseek\");\n chatBo.setSystemPrompt(\"你是一个友好的客服助手,请专业地回答客户问题\");\n\n AiChatVo response = aiService.aiChat(chatBo);\n return response.getMessage();\n }\n}\n```\n\n#### 示例2:文章内容审核\n\n```java\n@Service\npublic class ArticleServiceImpl extends ServiceImpl implements IArticleService {\n\n @Autowired\n private IAiService aiService;\n\n @Override\n public boolean publishArticle(Article article) {\n // 使用AI审核文章内容\n AiChatBo reviewBo = new AiChatBo();\n reviewBo.setMessage(article.getContent());\n reviewBo.setAiFeature(\"review\");\n reviewBo.setSystemPrompt(\"请审核文章内容是否合规,检查是否包含违规、敏感信息\");\n\n AiChatVo reviewResult = aiService.aiReview(reviewBo);\n\n // 判断审核结果\n if (reviewResult.getMessage().contains(\"违规\")) {\n throw new ServiceException(\"文章内容审核未通过: \" + reviewResult.getMessage());\n }\n\n // 审核通过,发布文章\n article.setStatus(\"published\");\n return this.updateById(article);\n }\n}\n```\n\n#### 示例3:数据智能生成\n\n```java\n@Service\npublic class DataGeneratorService {\n\n @Autowired\n private IAiService aiService;\n\n @Override\n public List generateTestUsers(int count) {\n AiChatBo generateBo = new AiChatBo();\n generateBo.setMessage(\n String.format(\"生成%d个用户测试数据,包含真实的中文姓名、邮箱、手机号\", count)\n );\n generateBo.setAiFeature(\"generate\");\n\n // 传递数据结构上下文\n Map context = new HashMap<>();\n context.put(\"format\", \"json\");\n context.put(\"fields\", Arrays.asList(\"name\", \"email\", \"phone\", \"age\", \"gender\"));\n generateBo.setContext(context);\n\n AiChatVo response = aiService.aiGenerate(generateBo);\n\n // 解析生成的JSON数据\n return JsonUtils.parseArray(response.getMessage(), User.class);\n }\n}\n```\n\n## 数据访问层架构\n\n### DAO模式说明\n\n基础服务模块采用 **DAO(Data Access Object)** 模式,将数据访问逻辑与业务逻辑分离,提供更清晰的架构层次。\n\n#### 架构层次\n\n```text\nController 层\n ↓\nService 层\n ↓\nDAO 层 (IBaseDao)\n ↓\nEntity 层 (数据库实体)\n```\n\n#### IBaseDao 接口\n\n所有 DAO 接口都继承自 `IBaseDao`,提供统一的 CRUD 操作:\n\n```java\npublic interface IBaseDao {\n // 插入\n boolean insert(T entity);\n boolean insertBatch(Collection entityList);\n\n // 更新\n boolean updateById(T entity);\n boolean updateBatchById(Collection entityList);\n\n // 删除\n boolean deleteById(Serializable id);\n boolean deleteBatchIds(Collection idList);\n\n // 查询\n T selectById(Serializable id);\n List selectBatchIds(Collection idList);\n List selectList(Wrapper queryWrapper);\n T selectOne(Wrapper queryWrapper);\n Long selectCount(Wrapper queryWrapper);\n\n // 分页查询\n Page selectPage(Page page, Wrapper queryWrapper);\n}\n```\n\n### 平台配置DAO (IPlatformDao)\n\n```java\npublic interface IPlatformDao extends IBaseDao {\n\n /**\n * 根据业务对象构建查询条件\n */\n PlusLambdaQuery buildQueryWrapper(PlatformBo bo);\n\n /**\n * 根据appid查询平台配置\n */\n Platform getByAppid(String appid);\n\n /**\n * 根据appid和平台类型查询平台配置\n */\n Platform getByAppidAndType(String appid, String type, String status);\n\n /**\n * 根据平台类型和状态查询配置列表\n */\n List listByTypeAndStatus(String type, String status);\n}\n```\n\n### 支付配置DAO (IPaymentDao)\n\n```java\npublic interface IPaymentDao extends IBaseDao {\n\n /**\n * 根据商户号查询支付配置\n */\n Payment getByMchId(String mchId, String status);\n\n /**\n * 根据支付类型和状态查询配置列表\n */\n List listByTypeAndStatus(String type, String status);\n\n /**\n * 根据状态统计配置数量\n */\n long countByStatus(String status);\n\n /**\n * 根据商户号查询是否存在(排除指定ID)\n */\n boolean existsByMchId(String mchId, Long excludeId);\n\n /**\n * 根据商户号和状态判断是否存在\n */\n boolean existsByMchIdAndStatus(String mchId, String status);\n\n /**\n * 根据状态查询配置列表\n */\n List listByStatus(String status);\n}\n```\n\n### DAO层使用示例\n\n```java\n@Service\npublic class PlatformServiceImpl implements IPlatformService {\n\n @Autowired\n private IPlatformDao platformDao;\n\n @Override\n public PlatformVo getWeixinPlatform(String appid) {\n // 使用DAO查询微信小程序配置\n Platform platform = platformDao.getByAppidAndType(\n appid,\n \"mp-weixin\",\n DictEnableStatus.ENABLE.getValue()\n );\n\n if (platform == null) {\n throw new ServiceException(\"未找到微信小程序配置\");\n }\n\n return BeanUtil.toBean(platform, PlatformVo.class);\n }\n\n @Override\n public List listActivePlatforms(String type) {\n // 使用DAO查询所有启用的平台配置\n List platforms = platformDao.listByTypeAndStatus(\n type,\n DictEnableStatus.ENABLE.getValue()\n );\n\n return BeanUtil.copyToList(platforms, PlatformVo.class);\n }\n}\n```\n\n## 高级功能\n\n### 多租户支持\n\n基础服务模块所有实体类都继承自 `TenantEntity`,自动支持多租户数据隔离。\n\n#### 租户实体基类\n\n```java\n@Data\npublic class TenantEntity extends BaseEntity {\n\n /**\n * 租户ID\n */\n @TableField(value = \"tenant_id\")\n private String tenantId;\n\n /**\n * 创建部门\n */\n @TableField(value = \"create_dept\")\n private Long createDept;\n}\n```\n\n#### 自动租户隔离\n\n```java\n// 查询时自动添加租户条件\nPlatform platform = platformDao.selectById(platformId);\n// SQL: SELECT * FROM b_platform WHERE id = ? AND tenant_id = '当前租户ID'\n\n// 新增时自动填充租户ID\nPlatform newPlatform = new Platform();\nnewPlatform.setType(\"mp-weixin\");\nplatformDao.insert(newPlatform);\n// SQL: INSERT INTO b_platform (..., tenant_id) VALUES (..., '当前租户ID')\n```\n\n### 数据缓存机制\n\n#### Redis缓存配置\n\n平台配置和支付配置支持Redis缓存,提升查询性能:\n\n```java\n@Service\npublic class PlatformCacheService {\n\n private static final String PLATFORM_CACHE_KEY = \"platform:config:\";\n private static final Duration CACHE_EXPIRE = Duration.ofHours(1);\n\n @Autowired\n private RedisTemplate redisTemplate;\n\n @Autowired\n private IPlatformDao platformDao;\n\n public Platform getPlatformWithCache(String appid) {\n String cacheKey = PLATFORM_CACHE_KEY + appid;\n\n // 尝试从缓存获取\n Platform platform = redisTemplate.opsForValue().get(cacheKey);\n if (platform != null) {\n return platform;\n }\n\n // 缓存未命中,查询数据库\n platform = platformDao.getByAppid(appid);\n if (platform != null) {\n // 写入缓存\n redisTemplate.opsForValue().set(cacheKey, platform, CACHE_EXPIRE);\n }\n\n return platform;\n }\n\n public void clearPlatformCache(String appid) {\n String cacheKey = PLATFORM_CACHE_KEY + appid;\n redisTemplate.delete(cacheKey);\n }\n}\n```\n\n### 事件监听机制\n\n#### 配置变更事件\n\n```java\n@Component\npublic class PlatformConfigEventListener {\n\n @Autowired\n private WxMaApplicationRunner wxMaRunner;\n\n @Autowired\n private WxMpApplicationRunner wxMpRunner;\n\n /**\n * 监听平台配置变更事件\n */\n @EventListener\n public void handlePlatformConfigChange(PlatformConfigChangeEvent event) {\n String tenantId = event.getTenantId();\n String platformType = event.getPlatformType();\n\n // 根据平台类型重新初始化配置\n if (\"mp-weixin\".equals(platformType)) {\n wxMaRunner.initByTenant(tenantId);\n } else if (\"mp-official-account\".equals(platformType)) {\n wxMpRunner.initByTenant(tenantId);\n }\n\n log.info(\"平台配置已更新: tenantId={}, platformType={}\", tenantId, platformType);\n }\n}\n```\n\n#### 自定义事件\n\n```java\n@Data\npublic class PlatformConfigChangeEvent extends ApplicationEvent {\n\n private String tenantId;\n private String platformType;\n private String action; // create, update, delete\n\n public PlatformConfigChangeEvent(Object source, String tenantId, String platformType, String action) {\n super(source);\n this.tenantId = tenantId;\n this.platformType = platformType;\n this.action = action;\n }\n}\n\n// 发布事件\n@Service\npublic class PlatformServiceImpl implements IPlatformService {\n\n @Autowired\n private ApplicationEventPublisher eventPublisher;\n\n @Override\n @Transactional\n public boolean updatePlatform(PlatformBo bo) {\n boolean result = platformDao.updateById(BeanUtil.toBean(bo, Platform.class));\n\n if (result) {\n // 发布配置变更事件\n eventPublisher.publishEvent(\n new PlatformConfigChangeEvent(this, TenantHelper.getTenantId(), bo.getType(), \"update\")\n );\n }\n\n return result;\n }\n}\n```\n\n## 常见问题\n\n### Q1: 平台配置不生效?\n\n**问题原因:**\n- 配置状态未启用\n- 租户ID不匹配\n- 缓存未更新\n- appid配置错误\n\n**解决方案:**\n\n```java\n// 1. 检查配置状态\nPlatform platform = platformDao.getByAppid(appid);\nif (!\"1\".equals(platform.getStatus())) {\n throw new ServiceException(\"平台配置未启用\");\n}\n\n// 2. 检查租户ID\nString currentTenantId = TenantHelper.getTenantId();\nif (!currentTenantId.equals(platform.getTenantId())) {\n throw new ServiceException(\"平台配置不属于当前租户\");\n}\n\n// 3. 清除缓存重新加载\nwxMaApplicationRunner.initByTenant(currentTenantId);\n```\n\n### Q2: 第三方登录失败?\n\n**问题原因:**\n- appid或secret配置错误\n- 授权码已过期\n- 平台配置未找到\n- 网络连接问题\n\n**解决方案:**\n\n```java\ntry {\n // 使用授权码登录\n AuthTokenVo authToken = authStrategy.login(loginBody);\n} catch (WxErrorException e) {\n // 微信接口调用失败\n log.error(\"微信登录失败: errCode={}, errMsg={}\", e.getError().getErrorCode(), e.getError().getErrorMsg());\n\n if (e.getError().getErrorCode() == 40029) {\n throw new ServiceException(\"授权码无效或已过期,请重新授权\");\n } else if (e.getError().getErrorCode() == 40013) {\n throw new ServiceException(\"appid配置错误\");\n } else {\n throw new ServiceException(\"登录失败: \" + e.getError().getErrorMsg());\n }\n}\n```\n\n### Q3: 支付配置重复?\n\n**问题原因:**\n- 同一商户号被多次配置\n- 未进行唯一性校验\n\n**解决方案:**\n\n```java\n@Service\npublic class PaymentServiceImpl implements IPaymentService {\n\n @Override\n public boolean addPayment(PaymentBo bo) {\n // 检查商户号是否已存在\n boolean exists = paymentDao.existsByMchIdAndStatus(\n bo.getMchId(),\n DictEnableStatus.ENABLE.getValue()\n );\n\n if (exists) {\n throw new ServiceException(\"该商户号已存在有效配置\");\n }\n\n Payment payment = BeanUtil.toBean(bo, Payment.class);\n return paymentDao.insert(payment);\n }\n\n @Override\n public boolean updatePayment(PaymentBo bo) {\n // 检查商户号是否与其他记录重复(排除当前记录)\n boolean exists = paymentDao.existsByMchId(bo.getMchId(), bo.getId());\n\n if (exists) {\n throw new ServiceException(\"该商户号已被其他配置使用\");\n }\n\n Payment payment = BeanUtil.toBean(bo, Payment.class);\n return paymentDao.updateById(payment);\n }\n}\n```\n\n### Q4: AI功能无法使用?\n\n**问题原因:**\n- LangChain4j未启用\n- API密钥配置错误\n- 网络连接问题\n- 权限未配置\n\n**解决方案:**\n\n```yaml\n# 1. 确保配置已启用\nlangchain4j:\n enabled: true # 必须为 true\n\n# 2. 检查API密钥\ndeepseek:\n api-key: ${DEEPSEEK_API_KEY} # 确保环境变量已设置\n\n# 3. 测试网络连接\ncurl -X POST https://api.deepseek.com/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\"model\":\"deepseek-chat\",\"messages\":[{\"role\":\"user\",\"content\":\"Hello\"}]}'\n\n# 4. 配置权限\nINSERT INTO sys_menu (menu_name, perms) VALUES ('AI对话', 'base:ai:chat');\n```\n\n## 故障排查\n\n### 日志配置\n\n#### 启用详细日志\n\n```yaml\nlogging:\n level:\n plus.ruoyi.business.base: DEBUG\n plus.ruoyi.business.base.controller: DEBUG\n plus.ruoyi.business.base.service: DEBUG\n plus.ruoyi.business.base.dao: DEBUG\n plus.ruoyi.business.base.authStrategy: DEBUG\n```\n\n### 常见错误及解决方案\n\n#### 错误1: 平台配置未找到\n\n```text\n错误信息: ServiceException: 未找到平台配置\n```\n\n**排查步骤:**\n1. 检查数据库中是否存在配置记录\n2. 检查appid是否正确\n3. 检查配置状态是否启用\n4. 检查租户ID是否匹配\n\n```java\n// 调试代码\nPlatform platform = platformDao.selectOne(\n new LambdaQueryWrapper()\n .eq(Platform::getAppid, appid)\n);\nSystem.out.println(\"查询到的平台配置: \" + JsonUtils.toJsonString(platform));\n```\n\n#### 错误2: 认证策略未找到\n\n```text\n错误信息: No bean named 'miniappAuthStrategy' available\n```\n\n**排查步骤:**\n1. 检查认证策略类是否标注 `@Service` 注解\n2. 检查策略名称是否正确\n3. 检查Spring扫描路径是否包含策略类\n\n```java\n// 正确的策略命名\n@Service(\"miniapp\" + IAuthStrategy.BASE_NAME) // miniappAuthStrategy\npublic class MiniappAuthStrategy implements IAuthStrategy {\n // ...\n}\n```\n\n#### 错误3: 多租户数据泄露\n\n```text\n错误信息: 查询到了其他租户的数据\n```\n\n**排查步骤:**\n1. 检查实体类是否继承 `TenantEntity`\n2. 检查租户拦截器是否生效\n3. 检查数据表是否包含 `tenant_id` 字段\n\n```java\n// 确保实体类正确继承\n@TableName(\"b_platform\")\npublic class Platform extends TenantEntity {\n // 自动支持租户隔离\n}\n```\n\n## API参考\n\n### Controller接口清单\n\n| 控制器 | 路径 | 功能说明 |\n|--------|------|----------|\n| PlatformController | `/base/platform/*` | 平台配置管理 |\n| PaymentController | `/base/payment/*` | 支付配置管理 |\n| BindController | `/base/bind/*` | 账号绑定管理 |\n| AdController | `/base/ad/*` | 广告配置管理 |\n| AiController | `/base/ai/*` | AI助手功能 |\n\n### 核心接口详情\n\n#### 平台配置接口\n\n```java\nGET /base/platform/list 查询平台配置列表\nGET /base/platform/{id} 查询平台配置详情\nPOST /base/platform 新增平台配置\nPUT /base/platform 更新平台配置\nDELETE /base/platform/{ids} 删除平台配置\nGET /base/platform/dict 获取平台字典\n```\n\n#### 支付配置接口\n\n```java\nGET /base/payment/list 查询支付配置列表\nGET /base/payment/{id} 查询支付配置详情\nPOST /base/payment 新增支付配置\nPUT /base/payment 更新支付配置\nDELETE /base/payment/{ids} 删除支付配置\nGET /base/payment/dict 获取支付方式字典\n```\n\n#### 账号绑定接口\n\n```java\nGET /base/bind/list 查询绑定列表\nPOST /base/bind/bindPhone 绑定手机号\nPOST /base/bind/unbind 解除绑定\n```\n\n#### AI助手接口\n\n```java\nPOST /base/ai/aiChat AI对话\nPOST /base/ai/aiOptimize 文本优化\nPOST /base/ai/aiGenerate 数据生成\nPOST /base/ai/aiReview 内容审核\nPOST /base/ai/aiTranslate 文本翻译\n```\n\n## 最佳实践\n\n### 配置管理\n- 敏感信息(如密钥)使用环境变量或加密存储\n- 支持配置热更新,通过事件机制通知相关服务\n- 按租户隔离配置,确保数据安全\n- 使用Redis缓存常用配置,提升性能\n\n### 安全考虑\n- 登录令牌设置合理的过期时间(建议2小时)\n- 敏感API添加 `@SaCheckPermission` 权限校验\n- 支付配置访问权限严格控制\n- AI接口调用添加频率限制,防止滥用\n- API密钥使用环境变量管理,不提交到代码仓库\n\n### 性能优化\n- 平台配置和支付配置使用Redis缓存,有效期1小时\n- 异步处理配置更新,使用Spring事件机制\n- 合理使用数据库索引(appid、mchId等字段)\n- AI接口调用使用连接池,复用HTTP连接\n- 批量查询使用 `selectBatchIds` 而不是循环查询\n\n### 扩展建议\n- 新增平台时,实现对应的 `IAuthStrategy` 认证策略\n- 支付方式扩展遵循统一的 DAO 接口规范\n- 配置项变更通过 `ApplicationEventPublisher` 发布事件\n- AI功能扩展可添加新的服务方法,保持接口一致性\n- 建议为每个租户配置独立的平台和支付配置\n"}, "47c57979a68e81774de5550269109694ce6c5e78": {"t": 1785765309.0300627, "n": 27754, "h": "148f70df045e63ea", "c": "# 基础服务模块 (base)\n\n基础服务模块提供了系统运行所需的核心基础服务,包括多平台配置管理、支付配置管理、广告配置、账号绑定等功能。\n\n## 模块结构\n\n```text\nbase/\n├── controller/ # 控制器层\n│ ├── AdController.java\n│ ├── BindController.java\n│ ├── PaymentController.java\n│ └── PlatformController.java\n├── service/ # 服务层\n│ ├── IAdService.java\n│ ├── IBindService.java\n│ ├── IPaymentService.java\n│ └── IPlatformService.java\n├── domain/ # 数据模型\n│ ├── entity/ # 实体类\n│ ├── vo/ # 视图对象\n│ └── bo/ # 业务对象\n├── mapper/ # 数据访问层\n└── authStrategy/ # 认证策略\n```\n\n## 核心功能\n\n### 🏗️ 平台配置管理\n\n支持多种平台的统一配置管理:\n\n- **微信小程序** (mp-weixin)\n- **微信公众号** (mp-official-account)\n- **支付宝小程序** (mp-alipay)\n- **QQ小程序** (mp-qq)\n- **其他平台** (mp-jd, mp-kuaishou, mp-lark, mp-baidu, mp-toutiao, mp-xhs)\n\n#### 平台配置实体\n```java\n@Data\n@TableName(\"b_platform\")\npublic class Platform extends TenantEntity {\n private Long id; // 平台配置ID\n private String type; // 平台类型\n private String name; // 平台名称\n private String appid; // 应用ID\n private String secret; // 应用密钥\n private String token; // 接口Token\n private String aeskey; // 加密密钥\n private String paymentIds; // 关联支付配置\n private String templateConfigs; // 模板配置\n private String status; // 状态\n}\n```\n\n#### 核心接口\n```java\npublic interface IPlatformService extends IBaseService {\n // 继承基础CRUD操作\n}\n\n// 全局平台服务\npublic interface PlatformService {\n List listPlatformsByType(String type, String tenantId);\n PlatformDTO getPlatformByAppidAndType(String appid, String type);\n PlatformDTO getPlatformByAppid(String appid, String tenantId);\n}\n```\n\n### 💳 支付配置管理\n\n统一的支付配置管理,支持多种支付方式:\n\n#### 支付配置实体\n```java\n@Data\n@TableName(\"b_payment\") \npublic class Payment extends TenantEntity {\n private Long id; // 支付配置ID\n private String type; // 商户类型\n private String mchName; // 商户名称\n private String mchId; // 商户号\n private String mchKey; // 商户密钥\n private String apiV3Key; // APIv3密钥\n private String certPath; // 证书路径\n private String keyPath; // 密钥路径\n private String certSerialNo; // 证书序列号\n private String status; // 状态\n}\n```\n\n#### 核心服务\n```java\npublic interface PaymentService {\n List listPaymentByType(String type, String tenantId);\n PaymentDTO getByMchId(String mchId);\n PaymentDTO getById(Long paymentId);\n boolean existsValidMchId(String mchId);\n long countPayments();\n}\n```\n\n### 📱 账号绑定管理\n\n管理用户在不同平台的账号绑定关系:\n\n#### 绑定实体\n```java\n@Data\n@TableName(\"b_bind\")\npublic class Bind extends TenantEntity {\n private Long id; // 绑定ID\n private Long userId; // 用户ID\n private String platformType; // 平台类型\n private String appid; // 应用ID\n private String unionid; // 统一标识\n private String openid; // 平台标识\n private String extraData; // 扩展数据\n}\n```\n\n#### 绑定服务\n```java\npublic interface IBindService extends IBaseService {\n /**\n * 根据平台用户信息获取或创建绑定信息\n */\n BindVo getOrCreateBind(PlatformUserInfoVo platformUserInfoVo);\n \n /**\n * 更新绑定信息的用户ID\n */\n void updateBindUserId(BindBo bindBo, Long userId);\n}\n```\n\n### 📢 广告配置管理\n\n提供广告位和广告内容的统一管理:\n\n#### 广告实体\n```java\n@Data\n@TableName(\"b_ad\")\npublic class Ad extends TenantEntity {\n private Long id; // 广告ID\n private String appid; // 应用ID\n private String adUnitId; // 广告位ID\n private String adName; // 广告名称\n private String adType; // 广告类型\n private String position; // 投放位置\n private String img; // 广告图片\n private String description; // 描述\n private String jumpAppid; // 跳转应用ID\n private String jumpPath; // 跳转路径\n private String styleConfig; // 样式配置\n private Long sortOrder; // 排序值\n private String status; // 状态\n}\n```\n\n## 认证策略\n\n### 多平台认证架构\n\n基于策略模式实现多平台登录认证:\n\n#### 认证策略接口\n```java\npublic interface IAuthStrategy {\n String BASE_NAME = \"AuthStrategy\";\n AuthTokenVo login(String body);\n}\n```\n\n#### 小程序认证策略\n```java\n@Service(\"miniapp\" + IAuthStrategy.BASE_NAME)\npublic class MiniappAuthStrategy implements IAuthStrategy {\n \n @Override\n public AuthTokenVo login(String body) {\n // 1. 解析请求参数\n PlatformLoginBody loginBody = JsonUtils.parseObject(body, PlatformLoginBody.class);\n \n // 2. 获取平台用户信息\n PlatformUserInfoVo platformUserInfo = getMiniappUserIdentity(loginBody);\n \n // 3. 加载或创建用户\n SysUserVo user = loadOrCreateUser(platformUserInfo);\n \n // 4. 生成登录令牌\n LoginUser loginUser = loginService.createLoginUser(user);\n loginUser.setPlatform(platformUserInfo.getPlatform());\n loginUser.setAppid(platformUserInfo.getAppid());\n loginUser.setOpenid(platformUserInfo.getOpenid());\n loginUser.setUnionid(platformUserInfo.getUnionid());\n \n // 5. 完成登录\n LoginHelper.login(loginUser, loginParameter);\n \n // 6. 返回认证结果\n AuthTokenVo authTokenVo = new AuthTokenVo();\n authTokenVo.setAccessToken(StpUtil.getTokenValue());\n authTokenVo.setExpireIn(StpUtil.getTokenTimeout());\n return authTokenVo;\n }\n}\n```\n\n#### 公众号认证策略\n```java\n@Service(\"mp\" + IAuthStrategy.BASE_NAME)\npublic class MpAuthStrategy implements IAuthStrategy {\n // 公众号OAuth2.0认证流程实现\n // 支持网页授权登录场景\n}\n```\n\n### 认证流程\n\n1. **前端授权**:用户在前端完成平台授权,获取授权码\n2. **策略选择**:后端根据平台类型自动选择对应认证策略\n3. **信息获取**:通过授权码换取用户基本信息\n4. **账号绑定**:查找或创建用户账号绑定关系\n5. **令牌生成**:生成JWT访问令牌\n6. **登录完成**:返回令牌和用户信息\n\n## 手机号绑定\n\n### 微信小程序手机号获取\n```java\n@PostMapping(\"/bindPhone\")\npublic R bindPhone(@RequestBody PhoneBindBo bo) {\n LoginUser loginUser = LoginHelper.getLoginUser();\n wxMaService.switchover(loginUser.getAppid());\n \n try {\n WxMaPhoneNumberInfo phoneInfo = wxMaService.getUserService().getPhoneNumber(bo.getCode());\n String phone = phoneInfo.getPhoneNumber();\n \n // 更新用户手机号\n SysUser sysUser = userMapper.selectById(loginUser.getUserId());\n sysUser.setPhone(phone);\n userMapper.updateById(sysUser);\n \n return R.ok(\"绑定成功\", PhoneBindVo.of(phone));\n } catch (WxErrorException e) {\n return R.fail(\"获取手机号出错\");\n }\n}\n```\n\n## 数据字典服务\n\n### 支付方式字典\n```java\n@GetMapping(\"getPaymentDict\")\npublic R> getPaymentDict() {\n // 查询所有可用的支付方式\n List paymentVoList = paymentService.list(\n PlusLambdaQuery.of(Payment.class)\n .eq(Payment::getStatus, DictEnableStatus.ENABLE.getValue()));\n \n // 构建字典项列表\n List dictItems = StreamUtils.toList(paymentVoList, payment ->\n DictItemVo.of(payment.getMchName(), payment.getId().toString(), \"success\")\n );\n return R.ok(dictItems);\n}\n```\n\n## 配置管理\n\n### 平台配置热更新\n```java\nprivate void reloadPlatformConfig() {\n String tenantId = TenantHelper.getTenantId();\n \n // 重新初始化微信小程序配置\n SpringUtils.getBean(WxMaApplicationRunner.class).initByTenant(tenantId);\n \n // 重新初始化微信公众号配置 \n SpringUtils.getBean(WxMpApplicationRunner.class).initByTenant(tenantId);\n \n // 重新初始化支付配置\n SpringUtils.getBean(PayApplicationRunner.class).initByTenant(tenantId);\n}\n```\n\n### 支付配置热更新\n```java\nprivate void reloadPaymentConfig() {\n String tenantId = TenantHelper.getTenantId();\n SpringUtils.getBean(PayApplicationRunner.class).initByTenant(tenantId);\n}\n```\n\n## 使用示例\n\n### 配置微信小程序\n```java\n// 1. 创建平台配置\nPlatformBo platformBo = new PlatformBo();\nplatformBo.setType(\"mp-weixin\");\nplatformBo.setName(\"我的小程序\");\nplatformBo.setAppid(\"wx1234567890\");\nplatformBo.setSecret(\"your-secret\");\nplatformBo.setStatus(\"1\");\nplatformService.add(platformBo);\n\n// 2. 配置支付信息\nPaymentBo paymentBo = new PaymentBo();\npaymentBo.setType(\"wechat\");\npaymentBo.setMchName(\"我的商户\");\npaymentBo.setMchId(\"1234567890\");\npaymentBo.setMchKey(\"your-mch-key\");\npaymentBo.setStatus(\"1\");\npaymentService.add(paymentBo);\n```\n\n### 用户登录认证\n```java\n// 前端调用登录接口\nPOST /auth/login\n{\n \"platform\": \"miniapp\",\n \"body\": {\n \"platform\": \"mp-weixin\",\n \"appid\": \"wx1234567890\",\n \"platformCode\": \"授权码\"\n }\n}\n\n// 返回结果\n{\n \"code\": 200,\n \"msg\": \"登录成功\",\n \"data\": {\n \"accessToken\": \"eyJ0eXAiOiJKV1Q...\",\n \"expireIn\": 7200\n }\n}\n```\n\n## AI助手功能\n\n### 🤖 功能概述\n\n基础服务模块集成了强大的AI助手功能,基于 **LangChain4j** 框架实现,支持多种大语言模型(如 DeepSeek、通义千问、OpenAI、Claude等),为业务系统提供智能化能力。\n\n**核心特性:**\n- **多模型支持** - 灵活切换不同的AI模型提供商\n- **多场景应用** - 对话、优化、生成、审核、翻译等场景\n- **条件启用** - 通过配置开关控制功能启用\n- **权限控制** - 完善的权限校验机制\n- **上下文传递** - 支持业务上下文信息传递\n\n### AI服务接口\n\n#### AiController 控制器\n\n```java\n@RestController\n@RequestMapping(\"/base/ai\")\n@ConditionalOnProperty(\n prefix = \"langchain4j\",\n name = \"enabled\",\n havingValue = \"true\",\n matchIfMissing = true\n)\npublic class AiController {\n private final IAiService aiService;\n}\n```\n\n**条件启用说明:**\n- 需要在配置文件中设置 `langchain4j.enabled=true`\n- 如果配置项不存在,默认启用 (`matchIfMissing = true`)\n\n### 1. AI对话功能\n\n通用的AI对话接口,支持自由对话场景。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiChat\")\n@OpenApi(value = \"AI对话\")\npublic R aiChat(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiChat(bo));\n}\n```\n\n#### 请求示例\n\n```java\n// 创建对话请求\nAiChatBo chatBo = new AiChatBo();\nchatBo.setMessage(\"请帮我解释一下什么是微服务架构\");\nchatBo.setProvider(\"deepseek\");\nchatBo.setModelName(\"deepseek-chat\");\nchatBo.setTemperature(0.7);\nchatBo.setMaxTokens(2000);\n\n// 调用接口\nR result = aiController.aiChat(chatBo);\nAiChatVo response = result.getData();\nSystem.out.println(\"AI回复: \" + response.getMessage());\n```\n\n#### HTTP 调用示例\n\n```bash\nPOST /base/ai/aiChat\nContent-Type: application/json\n\n{\n \"message\": \"请帮我解释一下什么是微服务架构\",\n \"provider\": \"deepseek\",\n \"modelName\": \"deepseek-chat\",\n \"temperature\": 0.7,\n \"maxTokens\": 2000\n}\n```\n\n### 2. 文本优化功能\n\n对用户输入的文本进行优化,改善表达和文风。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiOptimize\")\n@OpenApi(value = \"AI文本优化\")\npublic R aiOptimize(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiOptimize(bo));\n}\n```\n\n#### 使用场景\n\n- 文章润色和改写\n- 产品描述优化\n- 邮件内容优化\n- 广告文案优化\n\n#### 请求示例\n\n```java\nAiChatBo optimizeBo = new AiChatBo();\noptimizeBo.setMessage(\"我们公司是做软件开发的,主要业务是给客户做系统\");\noptimizeBo.setAiFeature(\"optimize\");\noptimizeBo.setSystemPrompt(\"请将下列文本优化为更专业的企业简介\");\n\nR result = aiController.aiOptimize(optimizeBo);\n// 优化后: \"我们是一家专业的软件开发公司,致力于为企业客户提供定制化系统解决方案...\"\n```\n\n### 3. 数据生成功能\n\n根据用户需求生成结构化数据或内容。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiGenerate\")\n@OpenApi(value = \"AI数据生成\")\npublic R aiGenerate(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiGenerate(bo));\n}\n```\n\n#### 使用场景\n\n- 生成测试数据\n- 生成产品描述\n- 生成代码片段\n- 生成用户画像\n\n#### 请求示例\n\n```java\nAiChatBo generateBo = new AiChatBo();\ngenerateBo.setMessage(\"生成5个用户的测试数据,包含姓名、年龄、邮箱\");\ngenerateBo.setAiFeature(\"generate\");\n\n// 传递表单字段信息作为上下文\nMap context = new HashMap<>();\ncontext.put(\"fields\", Arrays.asList(\"name\", \"age\", \"email\"));\ncontext.put(\"count\", 5);\ngenerateBo.setContext(context);\n\nR result = aiController.aiGenerate(generateBo);\n```\n\n**生成结果示例:**\n```json\n[\n {\"name\": \"张三\", \"age\": 28, \"email\": \"zhangsan@example.com\"},\n {\"name\": \"李四\", \"age\": 32, \"email\": \"lisi@example.com\"},\n {\"name\": \"王五\", \"age\": 25, \"email\": \"wangwu@example.com\"},\n {\"name\": \"赵六\", \"age\": 30, \"email\": \"zhaoliu@example.com\"},\n {\"name\": \"钱七\", \"age\": 27, \"email\": \"qianqi@example.com\"}\n]\n```\n\n### 4. 内容审核功能\n\n对用户提交的内容进行智能审核,检测违规内容。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiReview\")\n@OpenApi(value = \"AI内容审核\")\npublic R aiReview(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiReview(bo));\n}\n```\n\n#### 使用场景\n\n- 评论内容审核\n- 文章内容审核\n- 用户昵称审核\n- 敏感词检测\n\n#### 请求示例\n\n```java\nAiChatBo reviewBo = new AiChatBo();\nreviewBo.setMessage(\"待审核的用户评论内容...\");\nreviewBo.setAiFeature(\"review\");\nreviewBo.setSystemPrompt(\"请审核以下内容是否包含违规、敏感、广告等不当信息\");\n\nR result = aiController.aiReview(reviewBo);\nAiChatVo response = result.getData();\n\n// 解析审核结果\nif (response.getMessage().contains(\"通过\")) {\n // 内容合规,允许发布\n} else {\n // 内容违规,拒绝发布\n}\n```\n\n### 5. 文本翻译功能\n\n提供多语言翻译服务。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiTranslate\")\n@OpenApi(value = \"AI文本翻译\")\npublic R aiTranslate(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiTranslate(bo));\n}\n```\n\n#### 使用场景\n\n- 多语言网站内容翻译\n- 用户评论翻译\n- 产品说明翻译\n- 客服消息翻译\n\n#### 请求示例\n\n```java\nAiChatBo translateBo = new AiChatBo();\ntranslateBo.setMessage(\"Hello, how are you today?\");\ntranslateBo.setAiFeature(\"translate\");\ntranslateBo.setSystemPrompt(\"请将以下英文翻译成中文\");\n\nR result = aiController.aiTranslate(translateBo);\n// 翻译结果: \"你好,你今天怎么样?\"\n```\n\n### AI配置说明\n\n#### LangChain4j 配置\n\n在 `application.yml` 中配置 LangChain4j:\n\n```yaml\nlangchain4j:\n enabled: true # 启用AI功能\n\n # DeepSeek 配置\n deepseek:\n api-key: ${DEEPSEEK_API_KEY}\n base-url: https://api.deepseek.com/v1\n model-name: deepseek-chat\n temperature: 0.7\n max-tokens: 2000\n timeout: 60s\n\n # 通义千问配置\n qianwen:\n api-key: ${QIANWEN_API_KEY}\n base-url: https://dashscope.aliyuncs.com/api/v1\n model-name: qwen-plus\n temperature: 0.7\n max-tokens: 2000\n\n # OpenAI 配置\n openai:\n api-key: ${OPENAI_API_KEY}\n base-url: https://api.openai.com/v1\n model-name: gpt-3.5-turbo\n temperature: 0.7\n max-tokens: 2000\n```\n\n#### 环境变量配置\n\n推荐使用环境变量管理敏感的API密钥:\n\n```bash\n# .env 文件\nDEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx\nQIANWEN_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx\nOPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx\n```\n\n#### 权限配置\n\n在菜单管理中配置AI功能权限:\n\n```sql\n-- AI对话权限\nINSERT INTO sys_menu (menu_name, parent_id, perms)\nVALUES ('AI对话', 1000, 'base:ai:chat');\n```\n\n### AI功能集成示例\n\n#### 示例1:智能客服回复\n\n```java\n@Service\npublic class CustomerServiceImpl implements ICustomerService {\n\n @Autowired\n private IAiService aiService;\n\n @Override\n public String handleCustomerQuestion(String question) {\n AiChatBo chatBo = new AiChatBo();\n chatBo.setMessage(question);\n chatBo.setProvider(\"deepseek\");\n chatBo.setSystemPrompt(\"你是一个友好的客服助手,请专业地回答客户问题\");\n\n AiChatVo response = aiService.aiChat(chatBo);\n return response.getMessage();\n }\n}\n```\n\n#### 示例2:文章内容审核\n\n```java\n@Service\npublic class ArticleServiceImpl extends ServiceImpl implements IArticleService {\n\n @Autowired\n private IAiService aiService;\n\n @Override\n public boolean publishArticle(Article article) {\n // 使用AI审核文章内容\n AiChatBo reviewBo = new AiChatBo();\n reviewBo.setMessage(article.getContent());\n reviewBo.setAiFeature(\"review\");\n reviewBo.setSystemPrompt(\"请审核文章内容是否合规,检查是否包含违规、敏感信息\");\n\n AiChatVo reviewResult = aiService.aiReview(reviewBo);\n\n // 判断审核结果\n if (reviewResult.getMessage().contains(\"违规\")) {\n throw new ServiceException(\"文章内容审核未通过: \" + reviewResult.getMessage());\n }\n\n // 审核通过,发布文章\n article.setStatus(\"published\");\n return this.updateById(article);\n }\n}\n```\n\n#### 示例3:数据智能生成\n\n```java\n@Service\npublic class DataGeneratorService {\n\n @Autowired\n private IAiService aiService;\n\n @Override\n public List generateTestUsers(int count) {\n AiChatBo generateBo = new AiChatBo();\n generateBo.setMessage(\n String.format(\"生成%d个用户测试数据,包含真实的中文姓名、邮箱、手机号\", count)\n );\n generateBo.setAiFeature(\"generate\");\n\n // 传递数据结构上下文\n Map context = new HashMap<>();\n context.put(\"format\", \"json\");\n context.put(\"fields\", Arrays.asList(\"name\", \"email\", \"phone\", \"age\", \"gender\"));\n generateBo.setContext(context);\n\n AiChatVo response = aiService.aiGenerate(generateBo);\n\n // 解析生成的JSON数据\n return JsonUtils.parseArray(response.getMessage(), User.class);\n }\n}\n```\n\n## 数据访问层架构\n\n### DAO模式说明\n\n基础服务模块采用 **DAO(Data Access Object)** 模式,将数据访问逻辑与业务逻辑分离,提供更清晰的架构层次。\n\n#### 架构层次\n\n```text\nController 层\n ↓\nService 层\n ↓\nDAO 层 (IBaseDao)\n ↓\nEntity 层 (数据库实体)\n```\n\n#### IBaseDao 接口\n\n所有 DAO 接口都继承自 `IBaseDao`,提供统一的 CRUD 操作:\n\n```java\npublic interface IBaseDao {\n // 插入\n boolean insert(T entity);\n boolean insertBatch(Collection entityList);\n\n // 更新\n boolean updateById(T entity);\n boolean updateBatchById(Collection entityList);\n\n // 删除\n boolean deleteById(Serializable id);\n boolean deleteBatchIds(Collection idList);\n\n // 查询\n T selectById(Serializable id);\n List selectBatchIds(Collection idList);\n List selectList(Wrapper queryWrapper);\n T selectOne(Wrapper queryWrapper);\n Long selectCount(Wrapper queryWrapper);\n\n // 分页查询\n Page selectPage(Page page, Wrapper queryWrapper);\n}\n```\n\n### 平台配置DAO (IPlatformDao)\n\n```java\npublic interface IPlatformDao extends IBaseDao {\n\n /**\n * 根据业务对象构建查询条件\n */\n PlusLambdaQuery buildQueryWrapper(PlatformBo bo);\n\n /**\n * 根据appid查询平台配置\n */\n Platform getByAppid(String appid);\n\n /**\n * 根据appid和平台类型查询平台配置\n */\n Platform getByAppidAndType(String appid, String type, String status);\n\n /**\n * 根据平台类型和状态查询配置列表\n */\n List listByTypeAndStatus(String type, String status);\n}\n```\n\n### 支付配置DAO (IPaymentDao)\n\n```java\npublic interface IPaymentDao extends IBaseDao {\n\n /**\n * 根据商户号查询支付配置\n */\n Payment getByMchId(String mchId, String status);\n\n /**\n * 根据支付类型和状态查询配置列表\n */\n List listByTypeAndStatus(String type, String status);\n\n /**\n * 根据状态统计配置数量\n */\n long countByStatus(String status);\n\n /**\n * 根据商户号查询是否存在(排除指定ID)\n */\n boolean existsByMchId(String mchId, Long excludeId);\n\n /**\n * 根据商户号和状态判断是否存在\n */\n boolean existsByMchIdAndStatus(String mchId, String status);\n\n /**\n * 根据状态查询配置列表\n */\n List listByStatus(String status);\n}\n```\n\n### DAO层使用示例\n\n```java\n@Service\npublic class PlatformServiceImpl implements IPlatformService {\n\n @Autowired\n private IPlatformDao platformDao;\n\n @Override\n public PlatformVo getWeixinPlatform(String appid) {\n // 使用DAO查询微信小程序配置\n Platform platform = platformDao.getByAppidAndType(\n appid,\n \"mp-weixin\",\n DictEnableStatus.ENABLE.getValue()\n );\n\n if (platform == null) {\n throw new ServiceException(\"未找到微信小程序配置\");\n }\n\n return BeanUtil.toBean(platform, PlatformVo.class);\n }\n\n @Override\n public List listActivePlatforms(String type) {\n // 使用DAO查询所有启用的平台配置\n List platforms = platformDao.listByTypeAndStatus(\n type,\n DictEnableStatus.ENABLE.getValue()\n );\n\n return BeanUtil.copyToList(platforms, PlatformVo.class);\n }\n}\n```\n\n## 高级功能\n\n### 多租户支持\n\n基础服务模块所有实体类都继承自 `TenantEntity`,自动支持多租户数据隔离。\n\n#### 租户实体基类\n\n```java\n@Data\npublic class TenantEntity extends BaseEntity {\n\n /**\n * 租户ID\n */\n @TableField(value = \"tenant_id\")\n private String tenantId;\n\n /**\n * 创建部门\n */\n @TableField(value = \"create_dept\")\n private Long createDept;\n}\n```\n\n#### 自动租户隔离\n\n```java\n// 查询时自动添加租户条件\nPlatform platform = platformDao.selectById(platformId);\n// SQL: SELECT * FROM b_platform WHERE id = ? AND tenant_id = '当前租户ID'\n\n// 新增时自动填充租户ID\nPlatform newPlatform = new Platform();\nnewPlatform.setType(\"mp-weixin\");\nplatformDao.insert(newPlatform);\n// SQL: INSERT INTO b_platform (..., tenant_id) VALUES (..., '当前租户ID')\n```\n\n### 数据缓存机制\n\n#### Redis缓存配置\n\n平台配置和支付配置支持Redis缓存,提升查询性能:\n\n```java\n@Service\npublic class PlatformCacheService {\n\n private static final String PLATFORM_CACHE_KEY = \"platform:config:\";\n private static final Duration CACHE_EXPIRE = Duration.ofHours(1);\n\n @Autowired\n private RedisTemplate redisTemplate;\n\n @Autowired\n private IPlatformDao platformDao;\n\n public Platform getPlatformWithCache(String appid) {\n String cacheKey = PLATFORM_CACHE_KEY + appid;\n\n // 尝试从缓存获取\n Platform platform = redisTemplate.opsForValue().get(cacheKey);\n if (platform != null) {\n return platform;\n }\n\n // 缓存未命中,查询数据库\n platform = platformDao.getByAppid(appid);\n if (platform != null) {\n // 写入缓存\n redisTemplate.opsForValue().set(cacheKey, platform, CACHE_EXPIRE);\n }\n\n return platform;\n }\n\n public void clearPlatformCache(String appid) {\n String cacheKey = PLATFORM_CACHE_KEY + appid;\n redisTemplate.delete(cacheKey);\n }\n}\n```\n\n### 事件监听机制\n\n#### 配置变更事件\n\n```java\n@Component\npublic class PlatformConfigEventListener {\n\n @Autowired\n private WxMaApplicationRunner wxMaRunner;\n\n @Autowired\n private WxMpApplicationRunner wxMpRunner;\n\n /**\n * 监听平台配置变更事件\n */\n @EventListener\n public void handlePlatformConfigChange(PlatformConfigChangeEvent event) {\n String tenantId = event.getTenantId();\n String platformType = event.getPlatformType();\n\n // 根据平台类型重新初始化配置\n if (\"mp-weixin\".equals(platformType)) {\n wxMaRunner.initByTenant(tenantId);\n } else if (\"mp-official-account\".equals(platformType)) {\n wxMpRunner.initByTenant(tenantId);\n }\n\n log.info(\"平台配置已更新: tenantId={}, platformType={}\", tenantId, platformType);\n }\n}\n```\n\n#### 自定义事件\n\n```java\n@Data\npublic class PlatformConfigChangeEvent extends ApplicationEvent {\n\n private String tenantId;\n private String platformType;\n private String action; // create, update, delete\n\n public PlatformConfigChangeEvent(Object source, String tenantId, String platformType, String action) {\n super(source);\n this.tenantId = tenantId;\n this.platformType = platformType;\n this.action = action;\n }\n}\n\n// 发布事件\n@Service\npublic class PlatformServiceImpl implements IPlatformService {\n\n @Autowired\n private ApplicationEventPublisher eventPublisher;\n\n @Override\n @Transactional\n public boolean updatePlatform(PlatformBo bo) {\n boolean result = platformDao.updateById(BeanUtil.toBean(bo, Platform.class));\n\n if (result) {\n // 发布配置变更事件\n eventPublisher.publishEvent(\n new PlatformConfigChangeEvent(this, TenantHelper.getTenantId(), bo.getType(), \"update\")\n );\n }\n\n return result;\n }\n}\n```\n\n## 常见问题\n\n### Q1: 平台配置不生效?\n\n**问题原因:**\n- 配置状态未启用\n- 租户ID不匹配\n- 缓存未更新\n- appid配置错误\n\n**解决方案:**\n\n```java\n// 1. 检查配置状态\nPlatform platform = platformDao.getByAppid(appid);\nif (!\"1\".equals(platform.getStatus())) {\n throw new ServiceException(\"平台配置未启用\");\n}\n\n// 2. 检查租户ID\nString currentTenantId = TenantHelper.getTenantId();\nif (!currentTenantId.equals(platform.getTenantId())) {\n throw new ServiceException(\"平台配置不属于当前租户\");\n}\n\n// 3. 清除缓存重新加载\nwxMaApplicationRunner.initByTenant(currentTenantId);\n```\n\n### Q2: 第三方登录失败?\n\n**问题原因:**\n- appid或secret配置错误\n- 授权码已过期\n- 平台配置未找到\n- 网络连接问题\n\n**解决方案:**\n\n```java\ntry {\n // 使用授权码登录\n AuthTokenVo authToken = authStrategy.login(loginBody);\n} catch (WxErrorException e) {\n // 微信接口调用失败\n log.error(\"微信登录失败: errCode={}, errMsg={}\", e.getError().getErrorCode(), e.getError().getErrorMsg());\n\n if (e.getError().getErrorCode() == 40029) {\n throw new ServiceException(\"授权码无效或已过期,请重新授权\");\n } else if (e.getError().getErrorCode() == 40013) {\n throw new ServiceException(\"appid配置错误\");\n } else {\n throw new ServiceException(\"登录失败: \" + e.getError().getErrorMsg());\n }\n}\n```\n\n### Q3: 支付配置重复?\n\n**问题原因:**\n- 同一商户号被多次配置\n- 未进行唯一性校验\n\n**解决方案:**\n\n```java\n@Service\npublic class PaymentServiceImpl implements IPaymentService {\n\n @Override\n public boolean addPayment(PaymentBo bo) {\n // 检查商户号是否已存在\n boolean exists = paymentDao.existsByMchIdAndStatus(\n bo.getMchId(),\n DictEnableStatus.ENABLE.getValue()\n );\n\n if (exists) {\n throw new ServiceException(\"该商户号已存在有效配置\");\n }\n\n Payment payment = BeanUtil.toBean(bo, Payment.class);\n return paymentDao.insert(payment);\n }\n\n @Override\n public boolean updatePayment(PaymentBo bo) {\n // 检查商户号是否与其他记录重复(排除当前记录)\n boolean exists = paymentDao.existsByMchId(bo.getMchId(), bo.getId());\n\n if (exists) {\n throw new ServiceException(\"该商户号已被其他配置使用\");\n }\n\n Payment payment = BeanUtil.toBean(bo, Payment.class);\n return paymentDao.updateById(payment);\n }\n}\n```\n\n### Q4: AI功能无法使用?\n\n**问题原因:**\n- LangChain4j未启用\n- API密钥配置错误\n- 网络连接问题\n- 权限未配置\n\n**解决方案:**\n\n```yaml\n# 1. 确保配置已启用\nlangchain4j:\n enabled: true # 必须为 true\n\n# 2. 检查API密钥\ndeepseek:\n api-key: ${DEEPSEEK_API_KEY} # 确保环境变量已设置\n\n# 3. 测试网络连接\ncurl -X POST https://api.deepseek.com/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\"model\":\"deepseek-chat\",\"messages\":[{\"role\":\"user\",\"content\":\"Hello\"}]}'\n\n# 4. 配置权限\nINSERT INTO sys_menu (menu_name, perms) VALUES ('AI对话', 'base:ai:chat');\n```\n\n## 故障排查\n\n### 日志配置\n\n#### 启用详细日志\n\n```yaml\nlogging:\n level:\n plus.ruoyi.business.base: DEBUG\n plus.ruoyi.business.base.controller: DEBUG\n plus.ruoyi.business.base.service: DEBUG\n plus.ruoyi.business.base.dao: DEBUG\n plus.ruoyi.business.base.authStrategy: DEBUG\n```\n\n### 常见错误及解决方案\n\n#### 错误1: 平台配置未找到\n\n```text\n错误信息: ServiceException: 未找到平台配置\n```\n\n**排查步骤:**\n1. 检查数据库中是否存在配置记录\n2. 检查appid是否正确\n3. 检查配置状态是否启用\n4. 检查租户ID是否匹配\n\n```java\n// 调试代码\nPlatform platform = platformDao.selectOne(\n new LambdaQueryWrapper()\n .eq(Platform::getAppid, appid)\n);\nSystem.out.println(\"查询到的平台配置: \" + JsonUtils.toJsonString(platform));\n```\n\n#### 错误2: 认证策略未找到\n\n```text\n错误信息: No bean named 'miniappAuthStrategy' available\n```\n\n**排查步骤:**\n1. 检查认证策略类是否标注 `@Service` 注解\n2. 检查策略名称是否正确\n3. 检查Spring扫描路径是否包含策略类\n\n```java\n// 正确的策略命名\n@Service(\"miniapp\" + IAuthStrategy.BASE_NAME) // miniappAuthStrategy\npublic class MiniappAuthStrategy implements IAuthStrategy {\n // ...\n}\n```\n\n#### 错误3: 多租户数据泄露\n\n```text\n错误信息: 查询到了其他租户的数据\n```\n\n**排查步骤:**\n1. 检查实体类是否继承 `TenantEntity`\n2. 检查租户拦截器是否生效\n3. 检查数据表是否包含 `tenant_id` 字段\n\n```java\n// 确保实体类正确继承\n@TableName(\"b_platform\")\npublic class Platform extends TenantEntity {\n // 自动支持租户隔离\n}\n```\n\n## API参考\n\n### Controller接口清单\n\n| 控制器 | 路径 | 功能说明 |\n|--------|------|----------|\n| PlatformController | `/base/platform/*` | 平台配置管理 |\n| PaymentController | `/base/payment/*` | 支付配置管理 |\n| BindController | `/base/bind/*` | 账号绑定管理 |\n| AdController | `/base/ad/*` | 广告配置管理 |\n| AiController | `/base/ai/*` | AI助手功能 |\n\n### 核心接口详情\n\n#### 平台配置接口\n\n```java\nGET /base/platform/list 查询平台配置列表\nGET /base/platform/{id} 查询平台配置详情\nPOST /base/platform 新增平台配置\nPUT /base/platform 更新平台配置\nDELETE /base/platform/{ids} 删除平台配置\nGET /base/platform/dict 获取平台字典\n```\n\n#### 支付配置接口\n\n```java\nGET /base/payment/list 查询支付配置列表\nGET /base/payment/{id} 查询支付配置详情\nPOST /base/payment 新增支付配置\nPUT /base/payment 更新支付配置\nDELETE /base/payment/{ids} 删除支付配置\nGET /base/payment/dict 获取支付方式字典\n```\n\n#### 账号绑定接口\n\n```java\nGET /base/bind/list 查询绑定列表\nPOST /base/bind/bindPhone 绑定手机号\nPOST /base/bind/unbind 解除绑定\n```\n\n#### AI助手接口\n\n```java\nPOST /base/ai/aiChat AI对话\nPOST /base/ai/aiOptimize 文本优化\nPOST /base/ai/aiGenerate 数据生成\nPOST /base/ai/aiReview 内容审核\nPOST /base/ai/aiTranslate 文本翻译\n```\n\n## 最佳实践\n\n### 📋 配置管理\n- 敏感信息(如密钥)使用环境变量或加密存储\n- 支持配置热更新,通过事件机制通知相关服务\n- 按租户隔离配置,确保数据安全\n- 使用Redis缓存常用配置,提升性能\n\n### 🔐 安全考虑\n- 登录令牌设置合理的过期时间(建议2小时)\n- 敏感API添加 `@SaCheckPermission` 权限校验\n- 支付配置访问权限严格控制\n- AI接口调用添加频率限制,防止滥用\n- API密钥使用环境变量管理,不提交到代码仓库\n\n### 🚀 性能优化\n- 平台配置和支付配置使用Redis缓存,有效期1小时\n- 异步处理配置更新,使用Spring事件机制\n- 合理使用数据库索引(appid、mchId等字段)\n- AI接口调用使用连接池,复用HTTP连接\n- 批量查询使用 `selectBatchIds` 而不是循环查询\n\n### 🔧 扩展建议\n- 新增平台时,实现对应的 `IAuthStrategy` 认证策略\n- 支付方式扩展遵循统一的 DAO 接口规范\n- 配置项变更通过 `ApplicationEventPublisher` 发布事件\n- AI功能扩展可添加新的服务方法,保持接口一致性\n- 建议为每个租户配置独立的平台和支付配置\n"}, "8cef6e1763c6cbc62e674a97d1c5afd41db7cf92": {"t": 1785765313.250317, "n": 27734, "h": "fd4edfde84b29047", "c": "# 基础服务模块 (base)\n\n基础服务模块提供了系统运行所需的核心基础服务,包括多平台配置管理、支付配置管理、广告配置、账号绑定等功能。\n\n## 模块结构\n\n```\nbase/\n├── controller/ # 控制器层\n│ ├── AdController.java\n│ ├── BindController.java\n│ ├── PaymentController.java\n│ └── PlatformController.java\n├── service/ # 服务层\n│ ├── IAdService.java\n│ ├── IBindService.java\n│ ├── IPaymentService.java\n│ └── IPlatformService.java\n├── domain/ # 数据模型\n│ ├── entity/ # 实体类\n│ ├── vo/ # 视图对象\n│ └── bo/ # 业务对象\n├── mapper/ # 数据访问层\n└── authStrategy/ # 认证策略\n```\n\n## 核心功能\n\n### 🏗️ 平台配置管理\n\n支持多种平台的统一配置管理:\n\n- **微信小程序** (mp-weixin)\n- **微信公众号** (mp-official-account)\n- **支付宝小程序** (mp-alipay)\n- **QQ小程序** (mp-qq)\n- **其他平台** (mp-jd, mp-kuaishou, mp-lark, mp-baidu, mp-toutiao, mp-xhs)\n\n#### 平台配置实体\n```java\n@Data\n@TableName(\"b_platform\")\npublic class Platform extends TenantEntity {\n private Long id; // 平台配置ID\n private String type; // 平台类型\n private String name; // 平台名称\n private String appid; // 应用ID\n private String secret; // 应用密钥\n private String token; // 接口Token\n private String aeskey; // 加密密钥\n private String paymentIds; // 关联支付配置\n private String templateConfigs; // 模板配置\n private String status; // 状态\n}\n```\n\n#### 核心接口\n```java\npublic interface IPlatformService extends IBaseService {\n // 继承基础CRUD操作\n}\n\n// 全局平台服务\npublic interface PlatformService {\n List listPlatformsByType(String type, String tenantId);\n PlatformDTO getPlatformByAppidAndType(String appid, String type);\n PlatformDTO getPlatformByAppid(String appid, String tenantId);\n}\n```\n\n### 💳 支付配置管理\n\n统一的支付配置管理,支持多种支付方式:\n\n#### 支付配置实体\n```java\n@Data\n@TableName(\"b_payment\") \npublic class Payment extends TenantEntity {\n private Long id; // 支付配置ID\n private String type; // 商户类型\n private String mchName; // 商户名称\n private String mchId; // 商户号\n private String mchKey; // 商户密钥\n private String apiV3Key; // APIv3密钥\n private String certPath; // 证书路径\n private String keyPath; // 密钥路径\n private String certSerialNo; // 证书序列号\n private String status; // 状态\n}\n```\n\n#### 核心服务\n```java\npublic interface PaymentService {\n List listPaymentByType(String type, String tenantId);\n PaymentDTO getByMchId(String mchId);\n PaymentDTO getById(Long paymentId);\n boolean existsValidMchId(String mchId);\n long countPayments();\n}\n```\n\n### 📱 账号绑定管理\n\n管理用户在不同平台的账号绑定关系:\n\n#### 绑定实体\n```java\n@Data\n@TableName(\"b_bind\")\npublic class Bind extends TenantEntity {\n private Long id; // 绑定ID\n private Long userId; // 用户ID\n private String platformType; // 平台类型\n private String appid; // 应用ID\n private String unionid; // 统一标识\n private String openid; // 平台标识\n private String extraData; // 扩展数据\n}\n```\n\n#### 绑定服务\n```java\npublic interface IBindService extends IBaseService {\n /**\n * 根据平台用户信息获取或创建绑定信息\n */\n BindVo getOrCreateBind(PlatformUserInfoVo platformUserInfoVo);\n \n /**\n * 更新绑定信息的用户ID\n */\n void updateBindUserId(BindBo bindBo, Long userId);\n}\n```\n\n### 📢 广告配置管理\n\n提供广告位和广告内容的统一管理:\n\n#### 广告实体\n```java\n@Data\n@TableName(\"b_ad\")\npublic class Ad extends TenantEntity {\n private Long id; // 广告ID\n private String appid; // 应用ID\n private String adUnitId; // 广告位ID\n private String adName; // 广告名称\n private String adType; // 广告类型\n private String position; // 投放位置\n private String img; // 广告图片\n private String description; // 描述\n private String jumpAppid; // 跳转应用ID\n private String jumpPath; // 跳转路径\n private String styleConfig; // 样式配置\n private Long sortOrder; // 排序值\n private String status; // 状态\n}\n```\n\n## 认证策略\n\n### 多平台认证架构\n\n基于策略模式实现多平台登录认证:\n\n#### 认证策略接口\n```java\npublic interface IAuthStrategy {\n String BASE_NAME = \"AuthStrategy\";\n AuthTokenVo login(String body);\n}\n```\n\n#### 小程序认证策略\n```java\n@Service(\"miniapp\" + IAuthStrategy.BASE_NAME)\npublic class MiniappAuthStrategy implements IAuthStrategy {\n \n @Override\n public AuthTokenVo login(String body) {\n // 1. 解析请求参数\n PlatformLoginBody loginBody = JsonUtils.parseObject(body, PlatformLoginBody.class);\n \n // 2. 获取平台用户信息\n PlatformUserInfoVo platformUserInfo = getMiniappUserIdentity(loginBody);\n \n // 3. 加载或创建用户\n SysUserVo user = loadOrCreateUser(platformUserInfo);\n \n // 4. 生成登录令牌\n LoginUser loginUser = loginService.createLoginUser(user);\n loginUser.setPlatform(platformUserInfo.getPlatform());\n loginUser.setAppid(platformUserInfo.getAppid());\n loginUser.setOpenid(platformUserInfo.getOpenid());\n loginUser.setUnionid(platformUserInfo.getUnionid());\n \n // 5. 完成登录\n LoginHelper.login(loginUser, loginParameter);\n \n // 6. 返回认证结果\n AuthTokenVo authTokenVo = new AuthTokenVo();\n authTokenVo.setAccessToken(StpUtil.getTokenValue());\n authTokenVo.setExpireIn(StpUtil.getTokenTimeout());\n return authTokenVo;\n }\n}\n```\n\n#### 公众号认证策略\n```java\n@Service(\"mp\" + IAuthStrategy.BASE_NAME)\npublic class MpAuthStrategy implements IAuthStrategy {\n // 公众号OAuth2.0认证流程实现\n // 支持网页授权登录场景\n}\n```\n\n### 认证流程\n\n1. **前端授权**:用户在前端完成平台授权,获取授权码\n2. **策略选择**:后端根据平台类型自动选择对应认证策略\n3. **信息获取**:通过授权码换取用户基本信息\n4. **账号绑定**:查找或创建用户账号绑定关系\n5. **令牌生成**:生成JWT访问令牌\n6. **登录完成**:返回令牌和用户信息\n\n## 手机号绑定\n\n### 微信小程序手机号获取\n```java\n@PostMapping(\"/bindPhone\")\npublic R bindPhone(@RequestBody PhoneBindBo bo) {\n LoginUser loginUser = LoginHelper.getLoginUser();\n wxMaService.switchover(loginUser.getAppid());\n \n try {\n WxMaPhoneNumberInfo phoneInfo = wxMaService.getUserService().getPhoneNumber(bo.getCode());\n String phone = phoneInfo.getPhoneNumber();\n \n // 更新用户手机号\n SysUser sysUser = userMapper.selectById(loginUser.getUserId());\n sysUser.setPhone(phone);\n userMapper.updateById(sysUser);\n \n return R.ok(\"绑定成功\", PhoneBindVo.of(phone));\n } catch (WxErrorException e) {\n return R.fail(\"获取手机号出错\");\n }\n}\n```\n\n## 数据字典服务\n\n### 支付方式字典\n```java\n@GetMapping(\"getPaymentDict\")\npublic R> getPaymentDict() {\n // 查询所有可用的支付方式\n List paymentVoList = paymentService.list(\n PlusLambdaQuery.of(Payment.class)\n .eq(Payment::getStatus, DictEnableStatus.ENABLE.getValue()));\n \n // 构建字典项列表\n List dictItems = StreamUtils.toList(paymentVoList, payment ->\n DictItemVo.of(payment.getMchName(), payment.getId().toString(), \"success\")\n );\n return R.ok(dictItems);\n}\n```\n\n## 配置管理\n\n### 平台配置热更新\n```java\nprivate void reloadPlatformConfig() {\n String tenantId = TenantHelper.getTenantId();\n \n // 重新初始化微信小程序配置\n SpringUtils.getBean(WxMaApplicationRunner.class).initByTenant(tenantId);\n \n // 重新初始化微信公众号配置 \n SpringUtils.getBean(WxMpApplicationRunner.class).initByTenant(tenantId);\n \n // 重新初始化支付配置\n SpringUtils.getBean(PayApplicationRunner.class).initByTenant(tenantId);\n}\n```\n\n### 支付配置热更新\n```java\nprivate void reloadPaymentConfig() {\n String tenantId = TenantHelper.getTenantId();\n SpringUtils.getBean(PayApplicationRunner.class).initByTenant(tenantId);\n}\n```\n\n## 使用示例\n\n### 配置微信小程序\n```java\n// 1. 创建平台配置\nPlatformBo platformBo = new PlatformBo();\nplatformBo.setType(\"mp-weixin\");\nplatformBo.setName(\"我的小程序\");\nplatformBo.setAppid(\"wx1234567890\");\nplatformBo.setSecret(\"your-secret\");\nplatformBo.setStatus(\"1\");\nplatformService.add(platformBo);\n\n// 2. 配置支付信息\nPaymentBo paymentBo = new PaymentBo();\npaymentBo.setType(\"wechat\");\npaymentBo.setMchName(\"我的商户\");\npaymentBo.setMchId(\"1234567890\");\npaymentBo.setMchKey(\"your-mch-key\");\npaymentBo.setStatus(\"1\");\npaymentService.add(paymentBo);\n```\n\n### 用户登录认证\n```java\n// 前端调用登录接口\nPOST /auth/login\n{\n \"platform\": \"miniapp\",\n \"body\": {\n \"platform\": \"mp-weixin\",\n \"appid\": \"wx1234567890\",\n \"platformCode\": \"授权码\"\n }\n}\n\n// 返回结果\n{\n \"code\": 200,\n \"msg\": \"登录成功\",\n \"data\": {\n \"accessToken\": \"eyJ0eXAiOiJKV1Q...\",\n \"expireIn\": 7200\n }\n}\n```\n\n## AI助手功能\n\n### 🤖 功能概述\n\n基础服务模块集成了强大的AI助手功能,基于 **LangChain4j** 框架实现,支持多种大语言模型(如 DeepSeek、通义千问、OpenAI、Claude等),为业务系统提供智能化能力。\n\n**核心特性:**\n- **多模型支持** - 灵活切换不同的AI模型提供商\n- **多场景应用** - 对话、优化、生成、审核、翻译等场景\n- **条件启用** - 通过配置开关控制功能启用\n- **权限控制** - 完善的权限校验机制\n- **上下文传递** - 支持业务上下文信息传递\n\n### AI服务接口\n\n#### AiController 控制器\n\n```java\n@RestController\n@RequestMapping(\"/base/ai\")\n@ConditionalOnProperty(\n prefix = \"langchain4j\",\n name = \"enabled\",\n havingValue = \"true\",\n matchIfMissing = true\n)\npublic class AiController {\n private final IAiService aiService;\n}\n```\n\n**条件启用说明:**\n- 需要在配置文件中设置 `langchain4j.enabled=true`\n- 如果配置项不存在,默认启用 (`matchIfMissing = true`)\n\n### 1. AI对话功能\n\n通用的AI对话接口,支持自由对话场景。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiChat\")\n@OpenApi(value = \"AI对话\")\npublic R aiChat(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiChat(bo));\n}\n```\n\n#### 请求示例\n\n```java\n// 创建对话请求\nAiChatBo chatBo = new AiChatBo();\nchatBo.setMessage(\"请帮我解释一下什么是微服务架构\");\nchatBo.setProvider(\"deepseek\");\nchatBo.setModelName(\"deepseek-chat\");\nchatBo.setTemperature(0.7);\nchatBo.setMaxTokens(2000);\n\n// 调用接口\nR result = aiController.aiChat(chatBo);\nAiChatVo response = result.getData();\nSystem.out.println(\"AI回复: \" + response.getMessage());\n```\n\n#### HTTP 调用示例\n\n```bash\nPOST /base/ai/aiChat\nContent-Type: application/json\n\n{\n \"message\": \"请帮我解释一下什么是微服务架构\",\n \"provider\": \"deepseek\",\n \"modelName\": \"deepseek-chat\",\n \"temperature\": 0.7,\n \"maxTokens\": 2000\n}\n```\n\n### 2. 文本优化功能\n\n对用户输入的文本进行优化,改善表达和文风。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiOptimize\")\n@OpenApi(value = \"AI文本优化\")\npublic R aiOptimize(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiOptimize(bo));\n}\n```\n\n#### 使用场景\n\n- 文章润色和改写\n- 产品描述优化\n- 邮件内容优化\n- 广告文案优化\n\n#### 请求示例\n\n```java\nAiChatBo optimizeBo = new AiChatBo();\noptimizeBo.setMessage(\"我们公司是做软件开发的,主要业务是给客户做系统\");\noptimizeBo.setAiFeature(\"optimize\");\noptimizeBo.setSystemPrompt(\"请将下列文本优化为更专业的企业简介\");\n\nR result = aiController.aiOptimize(optimizeBo);\n// 优化后: \"我们是一家专业的软件开发公司,致力于为企业客户提供定制化系统解决方案...\"\n```\n\n### 3. 数据生成功能\n\n根据用户需求生成结构化数据或内容。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiGenerate\")\n@OpenApi(value = \"AI数据生成\")\npublic R aiGenerate(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiGenerate(bo));\n}\n```\n\n#### 使用场景\n\n- 生成测试数据\n- 生成产品描述\n- 生成代码片段\n- 生成用户画像\n\n#### 请求示例\n\n```java\nAiChatBo generateBo = new AiChatBo();\ngenerateBo.setMessage(\"生成5个用户的测试数据,包含姓名、年龄、邮箱\");\ngenerateBo.setAiFeature(\"generate\");\n\n// 传递表单字段信息作为上下文\nMap context = new HashMap<>();\ncontext.put(\"fields\", Arrays.asList(\"name\", \"age\", \"email\"));\ncontext.put(\"count\", 5);\ngenerateBo.setContext(context);\n\nR result = aiController.aiGenerate(generateBo);\n```\n\n**生成结果示例:**\n```json\n[\n {\"name\": \"张三\", \"age\": 28, \"email\": \"zhangsan@example.com\"},\n {\"name\": \"李四\", \"age\": 32, \"email\": \"lisi@example.com\"},\n {\"name\": \"王五\", \"age\": 25, \"email\": \"wangwu@example.com\"},\n {\"name\": \"赵六\", \"age\": 30, \"email\": \"zhaoliu@example.com\"},\n {\"name\": \"钱七\", \"age\": 27, \"email\": \"qianqi@example.com\"}\n]\n```\n\n### 4. 内容审核功能\n\n对用户提交的内容进行智能审核,检测违规内容。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiReview\")\n@OpenApi(value = \"AI内容审核\")\npublic R aiReview(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiReview(bo));\n}\n```\n\n#### 使用场景\n\n- 评论内容审核\n- 文章内容审核\n- 用户昵称审核\n- 敏感词检测\n\n#### 请求示例\n\n```java\nAiChatBo reviewBo = new AiChatBo();\nreviewBo.setMessage(\"待审核的用户评论内容...\");\nreviewBo.setAiFeature(\"review\");\nreviewBo.setSystemPrompt(\"请审核以下内容是否包含违规、敏感、广告等不当信息\");\n\nR result = aiController.aiReview(reviewBo);\nAiChatVo response = result.getData();\n\n// 解析审核结果\nif (response.getMessage().contains(\"通过\")) {\n // 内容合规,允许发布\n} else {\n // 内容违规,拒绝发布\n}\n```\n\n### 5. 文本翻译功能\n\n提供多语言翻译服务。\n\n#### 接口定义\n\n```java\n@PostMapping(\"/aiTranslate\")\n@OpenApi(value = \"AI文本翻译\")\npublic R aiTranslate(@Valid @RequestBody AiChatBo bo) {\n return R.ok(aiService.aiTranslate(bo));\n}\n```\n\n#### 使用场景\n\n- 多语言网站内容翻译\n- 用户评论翻译\n- 产品说明翻译\n- 客服消息翻译\n\n#### 请求示例\n\n```java\nAiChatBo translateBo = new AiChatBo();\ntranslateBo.setMessage(\"Hello, how are you today?\");\ntranslateBo.setAiFeature(\"translate\");\ntranslateBo.setSystemPrompt(\"请将以下英文翻译成中文\");\n\nR result = aiController.aiTranslate(translateBo);\n// 翻译结果: \"你好,你今天怎么样?\"\n```\n\n### AI配置说明\n\n#### LangChain4j 配置\n\n在 `application.yml` 中配置 LangChain4j:\n\n```yaml\nlangchain4j:\n enabled: true # 启用AI功能\n\n # DeepSeek 配置\n deepseek:\n api-key: ${DEEPSEEK_API_KEY}\n base-url: https://api.deepseek.com/v1\n model-name: deepseek-chat\n temperature: 0.7\n max-tokens: 2000\n timeout: 60s\n\n # 通义千问配置\n qianwen:\n api-key: ${QIANWEN_API_KEY}\n base-url: https://dashscope.aliyuncs.com/api/v1\n model-name: qwen-plus\n temperature: 0.7\n max-tokens: 2000\n\n # OpenAI 配置\n openai:\n api-key: ${OPENAI_API_KEY}\n base-url: https://api.openai.com/v1\n model-name: gpt-3.5-turbo\n temperature: 0.7\n max-tokens: 2000\n```\n\n#### 环境变量配置\n\n推荐使用环境变量管理敏感的API密钥:\n\n```bash\n# .env 文件\nDEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx\nQIANWEN_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx\nOPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx\n```\n\n#### 权限配置\n\n在菜单管理中配置AI功能权限:\n\n```sql\n-- AI对话权限\nINSERT INTO sys_menu (menu_name, parent_id, perms)\nVALUES ('AI对话', 1000, 'base:ai:chat');\n```\n\n### AI功能集成示例\n\n#### 示例1:智能客服回复\n\n```java\n@Service\npublic class CustomerServiceImpl implements ICustomerService {\n\n @Autowired\n private IAiService aiService;\n\n @Override\n public String handleCustomerQuestion(String question) {\n AiChatBo chatBo = new AiChatBo();\n chatBo.setMessage(question);\n chatBo.setProvider(\"deepseek\");\n chatBo.setSystemPrompt(\"你是一个友好的客服助手,请专业地回答客户问题\");\n\n AiChatVo response = aiService.aiChat(chatBo);\n return response.getMessage();\n }\n}\n```\n\n#### 示例2:文章内容审核\n\n```java\n@Service\npublic class ArticleServiceImpl extends ServiceImpl implements IArticleService {\n\n @Autowired\n private IAiService aiService;\n\n @Override\n public boolean publishArticle(Article article) {\n // 使用AI审核文章内容\n AiChatBo reviewBo = new AiChatBo();\n reviewBo.setMessage(article.getContent());\n reviewBo.setAiFeature(\"review\");\n reviewBo.setSystemPrompt(\"请审核文章内容是否合规,检查是否包含违规、敏感信息\");\n\n AiChatVo reviewResult = aiService.aiReview(reviewBo);\n\n // 判断审核结果\n if (reviewResult.getMessage().contains(\"违规\")) {\n throw new ServiceException(\"文章内容审核未通过: \" + reviewResult.getMessage());\n }\n\n // 审核通过,发布文章\n article.setStatus(\"published\");\n return this.updateById(article);\n }\n}\n```\n\n#### 示例3:数据智能生成\n\n```java\n@Service\npublic class DataGeneratorService {\n\n @Autowired\n private IAiService aiService;\n\n @Override\n public List generateTestUsers(int count) {\n AiChatBo generateBo = new AiChatBo();\n generateBo.setMessage(\n String.format(\"生成%d个用户测试数据,包含真实的中文姓名、邮箱、手机号\", count)\n );\n generateBo.setAiFeature(\"generate\");\n\n // 传递数据结构上下文\n Map context = new HashMap<>();\n context.put(\"format\", \"json\");\n context.put(\"fields\", Arrays.asList(\"name\", \"email\", \"phone\", \"age\", \"gender\"));\n generateBo.setContext(context);\n\n AiChatVo response = aiService.aiGenerate(generateBo);\n\n // 解析生成的JSON数据\n return JsonUtils.parseArray(response.getMessage(), User.class);\n }\n}\n```\n\n## 数据访问层架构\n\n### DAO模式说明\n\n基础服务模块采用 **DAO(Data Access Object)** 模式,将数据访问逻辑与业务逻辑分离,提供更清晰的架构层次。\n\n#### 架构层次\n\n```\nController 层\n ↓\nService 层\n ↓\nDAO 层 (IBaseDao)\n ↓\nEntity 层 (数据库实体)\n```\n\n#### IBaseDao 接口\n\n所有 DAO 接口都继承自 `IBaseDao`,提供统一的 CRUD 操作:\n\n```java\npublic interface IBaseDao {\n // 插入\n boolean insert(T entity);\n boolean insertBatch(Collection entityList);\n\n // 更新\n boolean updateById(T entity);\n boolean updateBatchById(Collection entityList);\n\n // 删除\n boolean deleteById(Serializable id);\n boolean deleteBatchIds(Collection idList);\n\n // 查询\n T selectById(Serializable id);\n List selectBatchIds(Collection idList);\n List selectList(Wrapper queryWrapper);\n T selectOne(Wrapper queryWrapper);\n Long selectCount(Wrapper queryWrapper);\n\n // 分页查询\n Page selectPage(Page page, Wrapper queryWrapper);\n}\n```\n\n### 平台配置DAO (IPlatformDao)\n\n```java\npublic interface IPlatformDao extends IBaseDao {\n\n /**\n * 根据业务对象构建查询条件\n */\n PlusLambdaQuery buildQueryWrapper(PlatformBo bo);\n\n /**\n * 根据appid查询平台配置\n */\n Platform getByAppid(String appid);\n\n /**\n * 根据appid和平台类型查询平台配置\n */\n Platform getByAppidAndType(String appid, String type, String status);\n\n /**\n * 根据平台类型和状态查询配置列表\n */\n List listByTypeAndStatus(String type, String status);\n}\n```\n\n### 支付配置DAO (IPaymentDao)\n\n```java\npublic interface IPaymentDao extends IBaseDao {\n\n /**\n * 根据商户号查询支付配置\n */\n Payment getByMchId(String mchId, String status);\n\n /**\n * 根据支付类型和状态查询配置列表\n */\n List listByTypeAndStatus(String type, String status);\n\n /**\n * 根据状态统计配置数量\n */\n long countByStatus(String status);\n\n /**\n * 根据商户号查询是否存在(排除指定ID)\n */\n boolean existsByMchId(String mchId, Long excludeId);\n\n /**\n * 根据商户号和状态判断是否存在\n */\n boolean existsByMchIdAndStatus(String mchId, String status);\n\n /**\n * 根据状态查询配置列表\n */\n List listByStatus(String status);\n}\n```\n\n### DAO层使用示例\n\n```java\n@Service\npublic class PlatformServiceImpl implements IPlatformService {\n\n @Autowired\n private IPlatformDao platformDao;\n\n @Override\n public PlatformVo getWeixinPlatform(String appid) {\n // 使用DAO查询微信小程序配置\n Platform platform = platformDao.getByAppidAndType(\n appid,\n \"mp-weixin\",\n DictEnableStatus.ENABLE.getValue()\n );\n\n if (platform == null) {\n throw new ServiceException(\"未找到微信小程序配置\");\n }\n\n return BeanUtil.toBean(platform, PlatformVo.class);\n }\n\n @Override\n public List listActivePlatforms(String type) {\n // 使用DAO查询所有启用的平台配置\n List platforms = platformDao.listByTypeAndStatus(\n type,\n DictEnableStatus.ENABLE.getValue()\n );\n\n return BeanUtil.copyToList(platforms, PlatformVo.class);\n }\n}\n```\n\n## 高级功能\n\n### 多租户支持\n\n基础服务模块所有实体类都继承自 `TenantEntity`,自动支持多租户数据隔离。\n\n#### 租户实体基类\n\n```java\n@Data\npublic class TenantEntity extends BaseEntity {\n\n /**\n * 租户ID\n */\n @TableField(value = \"tenant_id\")\n private String tenantId;\n\n /**\n * 创建部门\n */\n @TableField(value = \"create_dept\")\n private Long createDept;\n}\n```\n\n#### 自动租户隔离\n\n```java\n// 查询时自动添加租户条件\nPlatform platform = platformDao.selectById(platformId);\n// SQL: SELECT * FROM b_platform WHERE id = ? AND tenant_id = '当前租户ID'\n\n// 新增时自动填充租户ID\nPlatform newPlatform = new Platform();\nnewPlatform.setType(\"mp-weixin\");\nplatformDao.insert(newPlatform);\n// SQL: INSERT INTO b_platform (..., tenant_id) VALUES (..., '当前租户ID')\n```\n\n### 数据缓存机制\n\n#### Redis缓存配置\n\n平台配置和支付配置支持Redis缓存,提升查询性能:\n\n```java\n@Service\npublic class PlatformCacheService {\n\n private static final String PLATFORM_CACHE_KEY = \"platform:config:\";\n private static final Duration CACHE_EXPIRE = Duration.ofHours(1);\n\n @Autowired\n private RedisTemplate redisTemplate;\n\n @Autowired\n private IPlatformDao platformDao;\n\n public Platform getPlatformWithCache(String appid) {\n String cacheKey = PLATFORM_CACHE_KEY + appid;\n\n // 尝试从缓存获取\n Platform platform = redisTemplate.opsForValue().get(cacheKey);\n if (platform != null) {\n return platform;\n }\n\n // 缓存未命中,查询数据库\n platform = platformDao.getByAppid(appid);\n if (platform != null) {\n // 写入缓存\n redisTemplate.opsForValue().set(cacheKey, platform, CACHE_EXPIRE);\n }\n\n return platform;\n }\n\n public void clearPlatformCache(String appid) {\n String cacheKey = PLATFORM_CACHE_KEY + appid;\n redisTemplate.delete(cacheKey);\n }\n}\n```\n\n### 事件监听机制\n\n#### 配置变更事件\n\n```java\n@Component\npublic class PlatformConfigEventListener {\n\n @Autowired\n private WxMaApplicationRunner wxMaRunner;\n\n @Autowired\n private WxMpApplicationRunner wxMpRunner;\n\n /**\n * 监听平台配置变更事件\n */\n @EventListener\n public void handlePlatformConfigChange(PlatformConfigChangeEvent event) {\n String tenantId = event.getTenantId();\n String platformType = event.getPlatformType();\n\n // 根据平台类型重新初始化配置\n if (\"mp-weixin\".equals(platformType)) {\n wxMaRunner.initByTenant(tenantId);\n } else if (\"mp-official-account\".equals(platformType)) {\n wxMpRunner.initByTenant(tenantId);\n }\n\n log.info(\"平台配置已更新: tenantId={}, platformType={}\", tenantId, platformType);\n }\n}\n```\n\n#### 自定义事件\n\n```java\n@Data\npublic class PlatformConfigChangeEvent extends ApplicationEvent {\n\n private String tenantId;\n private String platformType;\n private String action; // create, update, delete\n\n public PlatformConfigChangeEvent(Object source, String tenantId, String platformType, String action) {\n super(source);\n this.tenantId = tenantId;\n this.platformType = platformType;\n this.action = action;\n }\n}\n\n// 发布事件\n@Service\npublic class PlatformServiceImpl implements IPlatformService {\n\n @Autowired\n private ApplicationEventPublisher eventPublisher;\n\n @Override\n @Transactional\n public boolean updatePlatform(PlatformBo bo) {\n boolean result = platformDao.updateById(BeanUtil.toBean(bo, Platform.class));\n\n if (result) {\n // 发布配置变更事件\n eventPublisher.publishEvent(\n new PlatformConfigChangeEvent(this, TenantHelper.getTenantId(), bo.getType(), \"update\")\n );\n }\n\n return result;\n }\n}\n```\n\n## 常见问题\n\n### Q1: 平台配置不生效?\n\n**问题原因:**\n- 配置状态未启用\n- 租户ID不匹配\n- 缓存未更新\n- appid配置错误\n\n**解决方案:**\n\n```java\n// 1. 检查配置状态\nPlatform platform = platformDao.getByAppid(appid);\nif (!\"1\".equals(platform.getStatus())) {\n throw new ServiceException(\"平台配置未启用\");\n}\n\n// 2. 检查租户ID\nString currentTenantId = TenantHelper.getTenantId();\nif (!currentTenantId.equals(platform.getTenantId())) {\n throw new ServiceException(\"平台配置不属于当前租户\");\n}\n\n// 3. 清除缓存重新加载\nwxMaApplicationRunner.initByTenant(currentTenantId);\n```\n\n### Q2: 第三方登录失败?\n\n**问题原因:**\n- appid或secret配置错误\n- 授权码已过期\n- 平台配置未找到\n- 网络连接问题\n\n**解决方案:**\n\n```java\ntry {\n // 使用授权码登录\n AuthTokenVo authToken = authStrategy.login(loginBody);\n} catch (WxErrorException e) {\n // 微信接口调用失败\n log.error(\"微信登录失败: errCode={}, errMsg={}\", e.getError().getErrorCode(), e.getError().getErrorMsg());\n\n if (e.getError().getErrorCode() == 40029) {\n throw new ServiceException(\"授权码无效或已过期,请重新授权\");\n } else if (e.getError().getErrorCode() == 40013) {\n throw new ServiceException(\"appid配置错误\");\n } else {\n throw new ServiceException(\"登录失败: \" + e.getError().getErrorMsg());\n }\n}\n```\n\n### Q3: 支付配置重复?\n\n**问题原因:**\n- 同一商户号被多次配置\n- 未进行唯一性校验\n\n**解决方案:**\n\n```java\n@Service\npublic class PaymentServiceImpl implements IPaymentService {\n\n @Override\n public boolean addPayment(PaymentBo bo) {\n // 检查商户号是否已存在\n boolean exists = paymentDao.existsByMchIdAndStatus(\n bo.getMchId(),\n DictEnableStatus.ENABLE.getValue()\n );\n\n if (exists) {\n throw new ServiceException(\"该商户号已存在有效配置\");\n }\n\n Payment payment = BeanUtil.toBean(bo, Payment.class);\n return paymentDao.insert(payment);\n }\n\n @Override\n public boolean updatePayment(PaymentBo bo) {\n // 检查商户号是否与其他记录重复(排除当前记录)\n boolean exists = paymentDao.existsByMchId(bo.getMchId(), bo.getId());\n\n if (exists) {\n throw new ServiceException(\"该商户号已被其他配置使用\");\n }\n\n Payment payment = BeanUtil.toBean(bo, Payment.class);\n return paymentDao.updateById(payment);\n }\n}\n```\n\n### Q4: AI功能无法使用?\n\n**问题原因:**\n- LangChain4j未启用\n- API密钥配置错误\n- 网络连接问题\n- 权限未配置\n\n**解决方案:**\n\n```yaml\n# 1. 确保配置已启用\nlangchain4j:\n enabled: true # 必须为 true\n\n# 2. 检查API密钥\ndeepseek:\n api-key: ${DEEPSEEK_API_KEY} # 确保环境变量已设置\n\n# 3. 测试网络连接\ncurl -X POST https://api.deepseek.com/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\"model\":\"deepseek-chat\",\"messages\":[{\"role\":\"user\",\"content\":\"Hello\"}]}'\n\n# 4. 配置权限\nINSERT INTO sys_menu (menu_name, perms) VALUES ('AI对话', 'base:ai:chat');\n```\n\n## 故障排查\n\n### 日志配置\n\n#### 启用详细日志\n\n```yaml\nlogging:\n level:\n plus.ruoyi.business.base: DEBUG\n plus.ruoyi.business.base.controller: DEBUG\n plus.ruoyi.business.base.service: DEBUG\n plus.ruoyi.business.base.dao: DEBUG\n plus.ruoyi.business.base.authStrategy: DEBUG\n```\n\n### 常见错误及解决方案\n\n#### 错误1: 平台配置未找到\n\n```\n错误信息: ServiceException: 未找到平台配置\n```\n\n**排查步骤:**\n1. 检查数据库中是否存在配置记录\n2. 检查appid是否正确\n3. 检查配置状态是否启用\n4. 检查租户ID是否匹配\n\n```java\n// 调试代码\nPlatform platform = platformDao.selectOne(\n new LambdaQueryWrapper()\n .eq(Platform::getAppid, appid)\n);\nSystem.out.println(\"查询到的平台配置: \" + JsonUtils.toJsonString(platform));\n```\n\n#### 错误2: 认证策略未找到\n\n```\n错误信息: No bean named 'miniappAuthStrategy' available\n```\n\n**排查步骤:**\n1. 检查认证策略类是否标注 `@Service` 注解\n2. 检查策略名称是否正确\n3. 检查Spring扫描路径是否包含策略类\n\n```java\n// 正确的策略命名\n@Service(\"miniapp\" + IAuthStrategy.BASE_NAME) // miniappAuthStrategy\npublic class MiniappAuthStrategy implements IAuthStrategy {\n // ...\n}\n```\n\n#### 错误3: 多租户数据泄露\n\n```\n错误信息: 查询到了其他租户的数据\n```\n\n**排查步骤:**\n1. 检查实体类是否继承 `TenantEntity`\n2. 检查租户拦截器是否生效\n3. 检查数据表是否包含 `tenant_id` 字段\n\n```java\n// 确保实体类正确继承\n@TableName(\"b_platform\")\npublic class Platform extends TenantEntity {\n // 自动支持租户隔离\n}\n```\n\n## API参考\n\n### Controller接口清单\n\n| 控制器 | 路径 | 功能说明 |\n|--------|------|----------|\n| PlatformController | `/base/platform/*` | 平台配置管理 |\n| PaymentController | `/base/payment/*` | 支付配置管理 |\n| BindController | `/base/bind/*` | 账号绑定管理 |\n| AdController | `/base/ad/*` | 广告配置管理 |\n| AiController | `/base/ai/*` | AI助手功能 |\n\n### 核心接口详情\n\n#### 平台配置接口\n\n```java\nGET /base/platform/list 查询平台配置列表\nGET /base/platform/{id} 查询平台配置详情\nPOST /base/platform 新增平台配置\nPUT /base/platform 更新平台配置\nDELETE /base/platform/{ids} 删除平台配置\nGET /base/platform/dict 获取平台字典\n```\n\n#### 支付配置接口\n\n```java\nGET /base/payment/list 查询支付配置列表\nGET /base/payment/{id} 查询支付配置详情\nPOST /base/payment 新增支付配置\nPUT /base/payment 更新支付配置\nDELETE /base/payment/{ids} 删除支付配置\nGET /base/payment/dict 获取支付方式字典\n```\n\n#### 账号绑定接口\n\n```java\nGET /base/bind/list 查询绑定列表\nPOST /base/bind/bindPhone 绑定手机号\nPOST /base/bind/unbind 解除绑定\n```\n\n#### AI助手接口\n\n```java\nPOST /base/ai/aiChat AI对话\nPOST /base/ai/aiOptimize 文本优化\nPOST /base/ai/aiGenerate 数据生成\nPOST /base/ai/aiReview 内容审核\nPOST /base/ai/aiTranslate 文本翻译\n```\n\n## 最佳实践\n\n### 📋 配置管理\n- 敏感信息(如密钥)使用环境变量或加密存储\n- 支持配置热更新,通过事件机制通知相关服务\n- 按租户隔离配置,确保数据安全\n- 使用Redis缓存常用配置,提升性能\n\n### 🔐 安全考虑\n- 登录令牌设置合理的过期时间(建议2小时)\n- 敏感API添加 `@SaCheckPermission` 权限校验\n- 支付配置访问权限严格控制\n- AI接口调用添加频率限制,防止滥用\n- API密钥使用环境变量管理,不提交到代码仓库\n\n### 🚀 性能优化\n- 平台配置和支付配置使用Redis缓存,有效期1小时\n- 异步处理配置更新,使用Spring事件机制\n- 合理使用数据库索引(appid、mchId等字段)\n- AI接口调用使用连接池,复用HTTP连接\n- 批量查询使用 `selectBatchIds` 而不是循环查询\n\n### 🔧 扩展建议\n- 新增平台时,实现对应的 `IAuthStrategy` 认证策略\n- 支付方式扩展遵循统一的 DAO 接口规范\n- 配置项变更通过 `ApplicationEventPublisher` 发布事件\n- AI功能扩展可添加新的服务方法,保持接口一致性\n- 建议为每个租户配置独立的平台和支付配置\n"}, "3a08cad78b6d3370115044894b57554304e28199": {"t": 1785765316.668726, "n": 8440, "h": "1b41b9353a9f5514", "c": "# 基础服务模块 (base)\n\n基础服务模块提供了系统运行所需的核心基础服务,包括多平台配置管理、支付配置管理、广告配置、账号绑定等功能。\n\n## 模块结构\n\n```\nbase/\n├── controller/ # 控制器层\n│ ├── AdController.java\n│ ├── BindController.java\n│ ├── PaymentController.java\n│ └── PlatformController.java\n├── service/ # 服务层\n│ ├── IAdService.java\n│ ├── IBindService.java\n│ ├── IPaymentService.java\n│ └── IPlatformService.java\n├── domain/ # 数据模型\n│ ├── entity/ # 实体类\n│ ├── vo/ # 视图对象\n│ └── bo/ # 业务对象\n├── mapper/ # 数据访问层\n└── authStrategy/ # 认证策略\n```\n\n## 核心功能\n\n### 🏗️ 平台配置管理\n\n支持多种平台的统一配置管理:\n\n- **微信小程序** (mp-weixin)\n- **微信公众号** (mp-official-account)\n- **支付宝小程序** (mp-alipay)\n- **QQ小程序** (mp-qq)\n- **其他平台** (mp-jd, mp-kuaishou, mp-lark, mp-baidu, mp-toutiao, mp-xhs)\n\n#### 平台配置实体\n```java\n@Data\n@TableName(\"b_platform\")\npublic class Platform extends TenantEntity {\n private Long id; // 平台配置ID\n private String type; // 平台类型\n private String name; // 平台名称\n private String appid; // 应用ID\n private String secret; // 应用密钥\n private String token; // 接口Token\n private String aeskey; // 加密密钥\n private String paymentIds; // 关联支付配置\n private String templateConfigs; // 模板配置\n private String status; // 状态\n}\n```\n\n#### 核心接口\n```java\npublic interface IPlatformService extends IBaseService {\n // 继承基础CRUD操作\n}\n\n// 全局平台服务\npublic interface PlatformService {\n List listPlatformsByType(String type, String tenantId);\n PlatformDTO getPlatformByAppidAndType(String appid, String type);\n PlatformDTO getPlatformByAppid(String appid, String tenantId);\n}\n```\n\n### 💳 支付配置管理\n\n统一的支付配置管理,支持多种支付方式:\n\n#### 支付配置实体\n```java\n@Data\n@TableName(\"b_payment\") \npublic class Payment extends TenantEntity {\n private Long id; // 支付配置ID\n private String type; // 商户类型\n private String mchName; // 商户名称\n private String mchId; // 商户号\n private String mchKey; // 商户密钥\n private String apiV3Key; // APIv3密钥\n private String certPath; // 证书路径\n private String keyPath; // 密钥路径\n private String certSerialNo; // 证书序列号\n private String status; // 状态\n}\n```\n\n#### 核心服务\n```java\npublic interface PaymentService {\n List listPaymentByType(String type, String tenantId);\n PaymentDTO getByMchId(String mchId);\n PaymentDTO getById(Long paymentId);\n boolean existsValidMchId(String mchId);\n long countPayments();\n}\n```\n\n### 📱 账号绑定管理\n\n管理用户在不同平台的账号绑定关系:\n\n#### 绑定实体\n```java\n@Data\n@TableName(\"b_bind\")\npublic class Bind extends TenantEntity {\n private Long id; // 绑定ID\n private Long userId; // 用户ID\n private String platformType; // 平台类型\n private String appid; // 应用ID\n private String unionid; // 统一标识\n private String openid; // 平台标识\n private String extraData; // 扩展数据\n}\n```\n\n#### 绑定服务\n```java\npublic interface IBindService extends IBaseService {\n /**\n * 根据平台用户信息获取或创建绑定信息\n */\n BindVo getOrCreateBind(PlatformUserInfoVo platformUserInfoVo);\n \n /**\n * 更新绑定信息的用户ID\n */\n void updateBindUserId(BindBo bindBo, Long userId);\n}\n```\n\n### 📢 广告配置管理\n\n提供广告位和广告内容的统一管理:\n\n#### 广告实体\n```java\n@Data\n@TableName(\"b_ad\")\npublic class Ad extends TenantEntity {\n private Long id; // 广告ID\n private String appid; // 应用ID\n private String adUnitId; // 广告位ID\n private String adName; // 广告名称\n private String adType; // 广告类型\n private String position; // 投放位置\n private String img; // 广告图片\n private String description; // 描述\n private String jumpAppid; // 跳转应用ID\n private String jumpPath; // 跳转路径\n private String styleConfig; // 样式配置\n private Long sortOrder; // 排序值\n private String status; // 状态\n}\n```\n\n## 认证策略\n\n### 多平台认证架构\n\n基于策略模式实现多平台登录认证:\n\n#### 认证策略接口\n```java\npublic interface IAuthStrategy {\n String BASE_NAME = \"AuthStrategy\";\n AuthTokenVo login(String body);\n}\n```\n\n#### 小程序认证策略\n```java\n@Service(\"miniapp\" + IAuthStrategy.BASE_NAME)\npublic class MiniappAuthStrategy implements IAuthStrategy {\n \n @Override\n public AuthTokenVo login(String body) {\n // 1. 解析请求参数\n PlatformLoginBody loginBody = JsonUtils.parseObject(body, PlatformLoginBody.class);\n \n // 2. 获取平台用户信息\n PlatformUserInfoVo platformUserInfo = getMiniappUserIdentity(loginBody);\n \n // 3. 加载或创建用户\n SysUserVo user = loadOrCreateUser(platformUserInfo);\n \n // 4. 生成登录令牌\n LoginUser loginUser = loginService.createLoginUser(user);\n loginUser.setPlatform(platformUserInfo.getPlatform());\n loginUser.setAppid(platformUserInfo.getAppid());\n loginUser.setOpenid(platformUserInfo.getOpenid());\n loginUser.setUnionid(platformUserInfo.getUnionid());\n \n // 5. 完成登录\n LoginHelper.login(loginUser, loginParameter);\n \n // 6. 返回认证结果\n AuthTokenVo authTokenVo = new AuthTokenVo();\n authTokenVo.setAccessToken(StpUtil.getTokenValue());\n authTokenVo.setExpireIn(StpUtil.getTokenTimeout());\n return authTokenVo;\n }\n}\n```\n\n#### 公众号认证策略\n```java\n@Service(\"mp\" + IAuthStrategy.BASE_NAME)\npublic class MpAuthStrategy implements IAuthStrategy {\n // 公众号OAuth2.0认证流程实现\n // 支持网页授权登录场景\n}\n```\n\n### 认证流程\n\n1. **前端授权**:用户在前端完成平台授权,获取授权码\n2. **策略选择**:后端根据平台类型自动选择对应认证策略\n3. **信息获取**:通过授权码换取用户基本信息\n4. **账号绑定**:查找或创建用户账号绑定关系\n5. **令牌生成**:生成JWT访问令牌\n6. **登录完成**:返回令牌和用户信息\n\n## 手机号绑定\n\n### 微信小程序手机号获取\n```java\n@PostMapping(\"/bindPhone\")\npublic R bindPhone(@RequestBody PhoneBindBo bo) {\n LoginUser loginUser = LoginHelper.getLoginUser();\n wxMaService.switchover(loginUser.getAppid());\n \n try {\n WxMaPhoneNumberInfo phoneInfo = wxMaService.getUserService().getPhoneNumber(bo.getCode());\n String phone = phoneInfo.getPhoneNumber();\n \n // 更新用户手机号\n SysUser sysUser = userMapper.selectById(loginUser.getUserId());\n sysUser.setPhone(phone);\n userMapper.updateById(sysUser);\n \n return R.ok(\"绑定成功\", PhoneBindVo.of(phone));\n } catch (WxErrorException e) {\n return R.fail(\"获取手机号出错\");\n }\n}\n```\n\n## 数据字典服务\n\n### 支付方式字典\n```java\n@GetMapping(\"getPaymentDict\")\npublic R> getPaymentDict() {\n // 查询所有可用的支付方式\n List paymentVoList = paymentService.list(\n PlusLambdaQuery.of(Payment.class)\n .eq(Payment::getStatus, DictEnableStatus.ENABLE.getValue()));\n \n // 构建字典项列表\n List dictItems = StreamUtils.toList(paymentVoList, payment ->\n DictItemVo.of(payment.getMchName(), payment.getId().toString(), \"success\")\n );\n return R.ok(dictItems);\n}\n```\n\n## 配置管理\n\n### 平台配置热更新\n```java\nprivate void reloadPlatformConfig() {\n String tenantId = TenantHelper.getTenantId();\n \n // 重新初始化微信小程序配置\n SpringUtils.getBean(WxMaApplicationRunner.class).initByTenant(tenantId);\n \n // 重新初始化微信公众号配置 \n SpringUtils.getBean(WxMpApplicationRunner.class).initByTenant(tenantId);\n \n // 重新初始化支付配置\n SpringUtils.getBean(PayApplicationRunner.class).initByTenant(tenantId);\n}\n```\n\n### 支付配置热更新\n```java\nprivate void reloadPaymentConfig() {\n String tenantId = TenantHelper.getTenantId();\n SpringUtils.getBean(PayApplicationRunner.class).initByTenant(tenantId);\n}\n```\n\n## 使用示例\n\n### 配置微信小程序\n```java\n// 1. 创建平台配置\nPlatformBo platformBo = new PlatformBo();\nplatformBo.setType(\"mp-weixin\");\nplatformBo.setName(\"我的小程序\");\nplatformBo.setAppid(\"wx1234567890\");\nplatformBo.setSecret(\"your-secret\");\nplatformBo.setStatus(\"1\");\nplatformService.add(platformBo);\n\n// 2. 配置支付信息\nPaymentBo paymentBo = new PaymentBo();\npaymentBo.setType(\"wechat\");\npaymentBo.setMchName(\"我的商户\");\npaymentBo.setMchId(\"1234567890\");\npaymentBo.setMchKey(\"your-mch-key\");\npaymentBo.setStatus(\"1\");\npaymentService.add(paymentBo);\n```\n\n### 用户登录认证\n```java\n// 前端调用登录接口\nPOST /auth/login\n{\n \"platform\": \"miniapp\",\n \"body\": {\n \"platform\": \"mp-weixin\",\n \"appid\": \"wx1234567890\",\n \"platformCode\": \"授权码\"\n }\n}\n\n// 返回结果\n{\n \"code\": 200,\n \"msg\": \"登录成功\",\n \"data\": {\n \"accessToken\": \"eyJ0eXAiOiJKV1Q...\",\n \"expireIn\": 7200\n }\n}\n```\n\n## 最佳实践\n\n### 📋 配置管理\n- 敏感信息(如密钥)加密存储\n- 支持配置热更新,无需重启服务\n- 按租户隔离配置,避免数据混淆\n\n### 🔐 安全考虑\n- 登录令牌设置合理的过期时间\n- 敏感API添加权限校验\n- 支付配置访问权限严格控制\n\n### 🚀 性能优化\n- 平台配置缓存,减少数据库查询\n- 异步处理配置更新,提升响应速度\n- 合理使用数据库索引\n\n### 🔧 扩展建议\n- 新增平台时,实现对应的认证策略\n- 支付方式扩展遵循统一接口规范\n- 配置项变更通过事件机制通知相关服务\n"}}}}