fix(wxlogin): 修复scene参数解析与多租户用户查询异常问题

- 修改UserMapper接口,selectByIdIgnoreTenant由返回单用户改为返回用户列表,避免多结果异常
- UserService新增listByIdIgnoreTenant方法,兼容多条用户记录查询
- WxLoginController优先从scene参数直接解析tenantId,兼容旧格式时使用list接口查询用户
- 调整website.getRunning判空,避免空指针异常
- 多处调用处修改获取用户信息的逻辑,防止因多租户导致的查询失败
- 前端三处vue组件调整scene格式为uid_userId_tenantId,确保tenantId正确传递
This commit is contained in:
2026-04-21 12:44:25 +08:00
parent d9e4371735
commit 47ae81ca9f
7 changed files with 72 additions and 17 deletions

View File

@@ -0,0 +1,18 @@
# 2026-04-21 日志
## WxLoginController.getOrderQRCodeUnlimited 修复(完整)
### 根因
1. `extractTenantIdFromScene` 通过 `selectByIdIgnoreTenant` 反查用户获取 tenantIduserId=35280 在多租户下有2条记录 → `TooManyResultsException`
2. 异常被 catch 后 fallback 到默认租户 10550Redis 中无 `mp-weixin:10550` 缓存 → 最终失败
3. 第 452 行 `website.getRunning().equals(2)` 存在 NPE 风险
### 修复内容
- **后端 WxLoginController**: scene 格式改为 `uid_userId_tenantId`,优先从 scene 直接解析 tenantId兼容旧 `uid_userId` 格式时改用 `selectList` 避免多条记录异常
- **后端 UserMapper/UserService**: `selectByIdIgnoreTenant` 返回类型从 `User` 改为 `List<User>`;新增 `listByIdIgnoreTenant` 方法
- **后端 NPE 修复**: `website.getRunning().equals(2)``website != null && Integer.valueOf(2).equals(website.getRunning())`
- **前端 3 个 vue**: scene 从 `uid_${userId}` 改为 `uid_${userId}_${tenantId}`(从 tenantStore.company.tenantId 获取)
- shopDealerUser/index.vue
- shopDealerUserShop/index.vue
- shopDealerUserDelivery/index.vue

View File

@@ -40,6 +40,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.time.Instant; import java.time.Instant;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -449,7 +450,7 @@ public class WxLoginController extends BaseController {
// 判断应用运行状态 // 判断应用运行状态
final CmsWebsite website = cmsWebsiteService.getByTenantId(tenantId); final CmsWebsite website = cmsWebsiteService.getByTenantId(tenantId);
if(website.getRunning().equals(2)){ if(website != null && Integer.valueOf(2).equals(website.getRunning())){
map.put("check_path",false); map.put("check_path",false);
map.put("env_version","trial"); map.put("env_version","trial");
} }
@@ -725,27 +726,44 @@ public class WxLoginController extends BaseController {
/** /**
* 从scene参数中提取租户ID * 从scene参数中提取租户ID
* scene格式可能是: uid_33103 或其他包含用户ID的格式 * scene格式: uid_userId_tenantId优先或 uid_userId兼容旧格式
*/ */
private Integer extractTenantIdFromScene(String scene) { private Integer extractTenantIdFromScene(String scene) {
try { try {
System.out.println("解析scene参数: " + scene); System.out.println("解析scene参数: " + scene);
// 如果scene包含uid_前缀提取用户ID
if (scene != null && scene.startsWith("uid_")) { if (scene != null && scene.startsWith("uid_")) {
String userIdStr = scene.substring(4); // 去掉"uid_"前缀 String content = scene.substring(4); // 去掉"uid_"前缀
Integer userId = Integer.parseInt(userIdStr);
System.out.println("userId = " + userId);
// 根据用户ID查询用户信息获取租户ID // 优先解析 uid_userId_tenantId 格式
User user = userService.getByIdIgnoreTenant(userId); String[] parts = content.split("_");
System.out.println("user = " + user); if (parts.length >= 2) {
if (user != null) { try {
System.out.println("从用户ID " + userId + " 获取到租户ID: " + user.getTenantId()); Integer tenantId = Integer.parseInt(parts[1]);
return user.getTenantId(); System.out.println("从scene直接解析到tenantId = " + tenantId);
return tenantId;
} catch (NumberFormatException e) {
System.err.println("scene中tenantId格式异常: " + parts[1]);
}
}
// 兼容旧格式 uid_userId根据用户ID查询租户ID
if (parts.length == 1) {
Integer userId = Integer.parseInt(parts[0]);
System.out.println("userId = " + userId);
try {
List<User> users = userService.listByIdIgnoreTenant(userId);
System.out.println("查询到用户数量 = " + (users != null ? users.size() : 0));
if (users != null && !users.isEmpty()) {
System.out.println("从用户ID " + userId + " 获取到租户ID: " + users.get(0).getTenantId());
return users.get(0).getTenantId();
} else { } else {
System.err.println("未找到用户ID: " + userId); System.err.println("未找到用户ID: " + userId);
} }
} catch (Exception ex) {
System.err.println("查询用户异常: " + ex.getMessage());
}
}
} }
// 如果无法解析默认使用租户10550 // 如果无法解析默认使用租户10550

View File

@@ -60,7 +60,7 @@ public interface UserMapper extends BaseMapper<User> {
* @return User * @return User
*/ */
@InterceptorIgnore(tenantLine = "true") @InterceptorIgnore(tenantLine = "true")
User selectByIdIgnoreTenant(@Param("userId") Integer userId); List<User> selectByIdIgnoreTenant(@Param("userId") Integer userId);
@InterceptorIgnore(tenantLine = "true") @InterceptorIgnore(tenantLine = "true")
List<User> pageAdminByPhone(@Param("param") UserParam param); List<User> pageAdminByPhone(@Param("param") UserParam param);

View File

@@ -117,6 +117,11 @@ public interface UserService extends IService<User>, UserDetailsService {
*/ */
User getByIdIgnoreTenant(Integer userId); User getByIdIgnoreTenant(Integer userId);
/**
* 根据用户ID查询用户列表忽略租户隔离
*/
List<User> listByIdIgnoreTenant(Integer userId);
List<User> pageAdminByPhone(UserParam param); List<User> pageAdminByPhone(UserParam param);
List<User> listByAlert(); List<User> listByAlert();

View File

@@ -2,6 +2,9 @@ package com.gxwebsoft.common.system.service.impl;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import java.util.Collections;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -224,6 +227,15 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
if (userId == null) { if (userId == null) {
return null; return null;
} }
List<User> users = baseMapper.selectByIdIgnoreTenant(userId);
return users != null && !users.isEmpty() ? users.get(0) : null;
}
@Override
public List<User> listByIdIgnoreTenant(Integer userId) {
if (userId == null) {
return Collections.emptyList();
}
return baseMapper.selectByIdIgnoreTenant(userId); return baseMapper.selectByIdIgnoreTenant(userId);
} }

View File

@@ -878,7 +878,8 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
newDealerUser.setFreezeMoney(BigDecimal.ZERO); newDealerUser.setFreezeMoney(BigDecimal.ZERO);
newDealerUser.setTotalMoney(BigDecimal.ZERO); newDealerUser.setTotalMoney(BigDecimal.ZERO);
try { try {
User sysUser = userMapper.selectByIdIgnoreTenant(riderId); List<User> sysUsers = userMapper.selectByIdIgnoreTenant(riderId);
User sysUser = (sysUsers != null && !sysUsers.isEmpty()) ? sysUsers.get(0) : null;
if (sysUser != null) { if (sysUser != null) {
newDealerUser.setRealName(sysUser.getRealName() != null ? sysUser.getRealName() : sysUser.getNickname()); newDealerUser.setRealName(sysUser.getRealName() != null ? sysUser.getRealName() : sysUser.getNickname());
newDealerUser.setMobile(sysUser.getPhone()); newDealerUser.setMobile(sysUser.getPhone());

View File

@@ -620,7 +620,8 @@ public class DealerOrderSettlement10584Task {
newDealerUser.setTotalMoney(BigDecimal.ZERO); newDealerUser.setTotalMoney(BigDecimal.ZERO);
// 尽量补齐基础信息,避免表字段 NOT NULL 导致插入失败(插入失败会让门店分佣“找到了人但入不了账”)。 // 尽量补齐基础信息,避免表字段 NOT NULL 导致插入失败(插入失败会让门店分佣“找到了人但入不了账”)。
try { try {
User sysUser = userMapper.selectByIdIgnoreTenant(dealerUserId); List<User> sysUsers = userMapper.selectByIdIgnoreTenant(dealerUserId);
User sysUser = (sysUsers != null && !sysUsers.isEmpty()) ? sysUsers.get(0) : null;
if (sysUser != null) { if (sysUser != null) {
newDealerUser.setRealName(sysUser.getRealName() != null ? sysUser.getRealName() : sysUser.getNickname()); newDealerUser.setRealName(sysUser.getRealName() != null ? sysUser.getRealName() : sysUser.getNickname());
newDealerUser.setMobile(sysUser.getPhone()); newDealerUser.setMobile(sysUser.getPhone());