# 2026-06-17

## WxLoginController 配置读取改造（app_config 跨表查询）

### 需求
- `WxLoginController.loginByMpWxPhone` 等微信小程序相关接口读取配置时，优先从 `gxwebsoft_core.app_config`（db_websopy 库）读取，命中失败时回退到 `gxwebsoft_core.sys_setting.mp-weixin`。
- app_config 是 KV 行式存储：`id, tenant_id, config_key, config_value, category`（如 `category=wechat`，`config_key=wechat.appId`）。

### 方案（无需新建数据源）
- 直接 MyBatis XML 跨表：`FROM gxwebsoft_core.app_config`
- 走主数据源，依赖 gxwebsoft_core 库账号对 app_config 有 SELECT 权限

### 新增文件
- `src/main/java/com/gxwebsoft/websopy/entity/AppConfig.java` —— 实体
- `src/main/java/com/gxwebsoft/websopy/mapper/AppConfigMapper.java` —— Mapper（声明 selectByCategory）
- `src/main/java/com/gxwebsoft/websopy/mapper/AppConfigMapper.xml` —— XML 跨表查询（**XML 与 Mapper 同包**）
- `src/main/java/com/gxwebsoft/websopy/service/AppConfigService.java` —— 带 Redis 缓存

### 改造 WxLoginController
- 注入 `AppConfigService appConfigService`
- 新增私有方法 `getMpWxSetting(Integer tenantId)`：先读 app_config category=wechat，失败回退 `settingService.getBySettingKey("mp-weixin")`
- 替换 5 处调用：
  - `getOpenIdByCode`（约 521 行）
  - `getAccessToken(Integer)`（约 716 行）
  - `getWxOpenId`（约 834 行）
  - `getWxOpenIdOnly`（约 861 行）
  - `loginByOpenId`（约 959 行，写回 AppId/AppSecret Redis 缓存保持一致）

### 关键细节
- 缓存 Key 前缀 `appConfig:{tenantId}:{category}`（与 setting:* 隔离）
- 缓存 TTL 2 小时
- 配置文件组装：去掉 `config_key` 中的 `wechat.` 前缀，直接得到 `appId`/`appSecret`
- 编译错误原因及修复：Mapper interface 必须显式声明 selectByCategory 方法（编译期不查 XML）

### 编译验证
- `./mvnw clean compile -DskipTests` 通过 ✅

### 运行期 BeanCreationException 修复（2026-06-18 补记）
- 报错：`Bean named 'redisTemplate' expected StringRedisTemplate but was actually RedisTemplate`
- 原因：`@Resource` 按字段名（bean name）注入，容器中 `redisTemplate` 是 `RedisTemplate<Object,Object>`，而 `StringRedisTemplate` bean 叫 `stringRedisTemplate`
- 修复：`AppConfigService` 字段名从 `redisTemplate` 改为 `stringRedisTemplate`，4 处引用同步修改
- **项目规律：统一用字段名 `stringRedisTemplate`，禁止用 `redisTemplate` 注入 StringRedisTemplate**

### 运行期 SQLSyntaxErrorException 修复（2026-06-18 补记）
- 报错：`Table 'gxwebsoft_core.app_config' doesn't exist` + TenantLineInnerInterceptor 自动追加 `AND tenant_id = 10611`
- 原因 1：app_config 表实际在 `db_websopy` 库中，不在 gxwebsoft_core
- 原因 2：`TenantLineInnerInterceptor` 对所有 SQL 自动追加 tenant_id 条件，导致参数重复
- 实际表结构（从用户截图确认）：
  - 主键 `config_id`（不是 id）
  - 分类字段 `config_type`（不是 category）
  - 有 `deleted` 逻辑删除字段
  - tenant_id 示例值 105885
- 修复：
  1. XML 表名改为 `db_websopy.app_config`
  2. Mapper 方法加 `@InterceptorIgnore(tenantLine = "true")`（与项目其他跨库 Mapper 一致）
  3. 实体类字段对齐实际表结构（configId/configType/deleted）
  4. Service 参数名 category → configType 全部对齐
- **关键教训：跨库查询必须加 @InterceptorIgnore(tenantLine="true")，且表名必须带正确库名前缀**
