Переглянути джерело

feat(system): 添加员工信息与用户关联功能

- 在ComStaff实体类中新增userId字段用于关联系统用户
- 在ComStaffBo和ComStaffVo中同步添加userId字段支持
- 在ComStaffServiceImpl中实现员工新增时自动创建对应系统用户
- 优化微信登录流程,区分已注册用户与新用户处理逻辑
- 添加小程序页面设置相关数据模型和接口定义
- 扩展CustomerRegisterBo支持注册来源和OpenId信息
- 更新数据权限拦截器配置以支持新表权限控制
hurx 3 тижнів тому
батько
коміт
8b3c9725e7
31 змінених файлів з 1042 додано та 137 видалено
  1. 4 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/domain/bo/RemoteUserBo.java
  2. 203 28
      ruoyi-auth/src/main/java/org/dromara/auth/controller/MiniTokenController.java
  3. 2 0
      ruoyi-auth/src/main/java/org/dromara/auth/domain/vo/SysUserWechatVo.java
  4. 80 85
      ruoyi-auth/src/main/java/org/dromara/auth/service/impl/MiniAuthServiceImpl.java
  5. 3 1
      ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlatformDataScopeInterceptor.java
  6. 8 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerRegisterBo.java
  7. 24 15
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInfoServiceImpl.java
  8. 106 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/controller/MiniPageSetController.java
  9. 32 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/controller/mini/MiniPageSetMiniController.java
  10. 82 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/MiniPageSet.java
  11. 4 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/PageCategory.java
  12. 4 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/PageLink.java
  13. 74 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/bo/MiniPageSetBo.java
  14. 4 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/bo/PageCategoryBo.java
  15. 4 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/bo/PageLinkBo.java
  16. 93 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/vo/MiniPageSetVo.java
  17. 4 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/vo/PageCategoryVo.java
  18. 4 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/vo/PageLinkVo.java
  19. 15 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/mapper/MiniPageSetMapper.java
  20. 77 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/IMiniPageSetService.java
  21. 153 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/impl/MiniPageSetServiceImpl.java
  22. 1 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/impl/PageCategoryServiceImpl.java
  23. 1 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/impl/PageLinkServiceImpl.java
  24. 7 0
      ruoyi-modules/ruoyi-mall/src/main/resources/mapper/mall/MiniPageSetMapper.xml
  25. 3 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/ComStaff.java
  26. 4 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java
  27. 3 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/ComStaffBo.java
  28. 7 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java
  29. 3 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ComStaffVo.java
  30. 4 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java
  31. 29 8
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/ComStaffServiceImpl.java

+ 4 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/domain/bo/RemoteUserBo.java

@@ -132,6 +132,10 @@ public class RemoteUserBo implements Serializable {
 
 
     private String delFlag;
     private String delFlag;
 
 
+    private String source;
+
+    private String openId;
+
     public RemoteUserBo(Long userId) {
     public RemoteUserBo(Long userId) {
         this.userId = userId;
         this.userId = userId;
     }
     }

+ 203 - 28
ruoyi-auth/src/main/java/org/dromara/auth/controller/MiniTokenController.java

@@ -5,7 +5,9 @@ import cn.dev33.satoken.stp.StpUtil;
 import cn.dev33.satoken.stp.parameter.SaLoginParameter;
 import cn.dev33.satoken.stp.parameter.SaLoginParameter;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson2.JSONObject;
 import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.NotNull;
@@ -16,14 +18,19 @@ import org.apache.seata.spring.annotation.GlobalTransactional;
 import org.dromara.auth.domain.SysUserWechat;
 import org.dromara.auth.domain.SysUserWechat;
 import org.dromara.auth.domain.bo.SysUserWechatBo;
 import org.dromara.auth.domain.bo.SysUserWechatBo;
 import org.dromara.auth.domain.vo.SysUserWechatVo;
 import org.dromara.auth.domain.vo.SysUserWechatVo;
+import org.dromara.auth.mapper.SysUserWechatMapper;
 import org.dromara.auth.service.MiniAuthService;
 import org.dromara.auth.service.MiniAuthService;
+import org.dromara.auth.util.HttpClientUtil;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.core.utils.ServletUtils;
 import org.dromara.common.core.utils.ServletUtils;
+import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.common.tenant.helper.TenantHelper;
 import org.dromara.common.tenant.helper.TenantHelper;
 import org.dromara.resource.api.RemoteFileService;
 import org.dromara.resource.api.RemoteFileService;
 import org.dromara.resource.api.domain.RemoteFile;
 import org.dromara.resource.api.domain.RemoteFile;
+import org.dromara.system.api.RemoteUserService;
 import org.dromara.system.api.model.LoginUser;
 import org.dromara.system.api.model.LoginUser;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpHeaders;
@@ -33,6 +40,7 @@ import org.springframework.web.bind.annotation.*;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.MultipartFile;
 
 
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Objects;
 
 
@@ -47,11 +55,18 @@ import java.util.Objects;
 @RestController
 @RestController
 @RequestMapping("/wx")
 @RequestMapping("/wx")
 public class MiniTokenController {
 public class MiniTokenController {
+    public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";
 
 
     private final MiniAuthService miniAuthService;
     private final MiniAuthService miniAuthService;
+
+    @Autowired
+    private SysUserWechatMapper wechatMapper;
     @DubboReference
     @DubboReference
     private RemoteFileService remoteFileService;
     private RemoteFileService remoteFileService;
 
 
+    @DubboReference
+    private RemoteUserService remoteUserService;
+
     @Value("${tr.wechat.secret}")
     @Value("${tr.wechat.secret}")
     private String appSecret;
     private String appSecret;
 
 
@@ -72,34 +87,150 @@ public class MiniTokenController {
 
 
         // 在动态租户上下文中执行登录逻辑
         // 在动态租户上下文中执行登录逻辑
         return TenantHelper.dynamic(tenantId, () -> {
         return TenantHelper.dynamic(tenantId, () -> {
-            SysUserWechat wechat = miniAuthService.wxLogin(wechatBo);
-            LoginUser loginUser = new LoginUser();
-            loginUser.setUserId(wechat.getUserId());
-            loginUser.setNickname(wechat.getNickname());
-            loginUser.setUserType("app_user");
-            loginUser.setOpenid(wechat.getOpenId());
-            loginUser.setTenantId(tenantId); // 设置租户ID到登录用户
-
-            // 配置登录参数
-            SaLoginParameter model = new SaLoginParameter();
-            model.setDeviceType("xcx"); // 小程序设备类型
-            model.setTimeout(30 * 24 * 60 * 60); // 30天过期时间
-            model.setActiveTimeout(7 * 24 * 60 * 60); // 7天活跃超时
-            model.setExtra(LoginHelper.CLIENT_KEY, "miniprogram_client_id_2025"); // 使用系统认可的APP端客户端ID
-
-            //生成token
-            LoginHelper.login(loginUser, model);
-            // 获取token信息
-            String accessToken = StpUtil.getTokenValue();
-            Long expireIn = StpUtil.getTokenTimeout();
-            SysUserWechatVo wechatVo = BeanUtil.copyProperties(wechat, SysUserWechatVo.class);
-            wechatVo.setOpenId(wechat.getOpenId());
-            wechatVo.setAccessToken(accessToken);
-            wechatVo.setExpireIn(expireIn);
-            return R.ok(wechatVo);
+            try {
+                // 1. 调用 Service 层逻辑
+                // 注意:这里需要修改 Service,如果用户不存在,让它抛出特定异常
+                SysUserWechat wechat = miniAuthService.wxLogin(wechatBo);
+
+                // --- 登录成功逻辑 (用户已存在) ---
+                LoginUser loginUser = new LoginUser();
+                loginUser.setUserId(wechat.getUserId());
+                loginUser.setNickname(wechat.getNickname());
+                loginUser.setUserType("app_user");
+                loginUser.setOpenid(wechat.getOpenId());
+                loginUser.setTenantId(tenantId);
+
+                SaLoginParameter model = new SaLoginParameter();
+                model.setDeviceType("xcx");
+                model.setTimeout(30 * 24 * 60 * 60);
+                model.setActiveTimeout(7 * 24 * 60 * 60);
+                model.setExtra(LoginHelper.CLIENT_KEY, "miniprogram_client_id_2025");
+
+                LoginHelper.login(loginUser, model);
+                String accessToken = StpUtil.getTokenValue();
+                Long expireIn = StpUtil.getTokenTimeout();
+
+                SysUserWechatVo wechatVo = BeanUtil.copyProperties(wechat, SysUserWechatVo.class);
+                wechatVo.setOpenId(wechat.getOpenId());
+                wechatVo.setAccessToken(accessToken);
+                wechatVo.setExpireIn(expireIn);
+
+                return R.ok(wechatVo);
+
+            } catch (Exception e) {
+                // --- 异常处理逻辑 ---
+                // 判断是否是“用户未注册”的特定异常
+                // 这里假设你在 Service 层抛出的异常信息包含 "USER_NOT_REGISTERED"
+                if (e.getMessage() != null && e.getMessage().contains("USER_NOT_REGISTERED")) {
+                    log.info("检测到新用户,返回 AppID 引导注册");
+                    SysUserWechatVo wechatVo = new SysUserWechatVo();
+                    wechatVo.setOpenId(wechatBo.getCode());
+                    wechatVo.setAppId(appId);
+                    // 返回特定状态码 (例如 201) 和 AppID
+                    return R.warn("用户未注册,请前往注册", wechatVo);
+                }
+
+                // 其他异常正常抛出
+                log.error("登录异常", e);
+                return R.fail("登录失败: " + e.getMessage());
+            }
         });
         });
     }
     }
 
 
+    /*
+     * 小程序登录手机号
+     * */
+    @SaIgnore
+    @PostMapping("/loginByPhone")
+    public R<SysUserWechatVo> loginByPhone(@RequestBody Map<String, String> data) {
+        try {
+            String code = data.get("code");
+            String openId = data.get("openId");
+            log.info("手机号快捷登录,获取临时code: {}", code);
+
+            // 获取 tenantId
+            String tenantId = ServletUtils.getHeader(Objects.requireNonNull(ServletUtils.getRequest()), "tenantId");
+
+            return TenantHelper.dynamic(tenantId, () -> {
+                // 1. 通过 code 换取手机号
+                String phoneNumber = getPhoneNumberByCode(code);
+                if (phoneNumber == null) {
+                    return R.fail("获取手机号失败");
+                }
+                log.info("获取到手机号: {}", phoneNumber);
+                SysUserWechat user = null;
+                LoginUser userInfoByPhonenumber = remoteUserService.getUserInfoByPhonenumber(phoneNumber, "000000");
+                if (ObjectUtil.isNotEmpty(userInfoByPhonenumber)) {
+                    SysUserWechat sysUserWechat = miniAuthService.queryByPhoneNumber(phoneNumber);
+                    if (ObjectUtil.isEmpty(sysUserWechat)) {
+                        SysUserWechat userWechat = new SysUserWechat();
+                        userWechat.setOpenId(openId);
+                        userWechat.setStatus("0");
+                        // 设置租户ID
+                        userWechat.setTenantId(tenantId);
+
+                        // --- 核心修复:处理昵称 ---
+                        // 静默登录没传昵称,生成默认昵称
+                        String nickName = "用户_" + openId.substring(openId.length() - 8);
+                        userWechat.setUserId(userInfoByPhonenumber.getUserId());
+                        userWechat.setPhoneNumber(phoneNumber);
+                        // 保存微信关联表
+                        userWechat.setNickname(nickName); // 保存默认昵称
+                        // --- 处理头像 ---
+                        userWechat.setAvatarUrl("/default/avatar.png"); // 默认头像
+                        int insert = wechatMapper.insert(userWechat);
+                        if (insert > 0) {
+                            user = userWechat;
+                        }else{
+                            return R.fail("保存微信关联失败");
+                        }
+                    } else {
+                        user = sysUserWechat;
+                    }
+                }
+
+                // 2. 根据手机号查询用户
+                //  user = miniAuthService.queryByPhoneNumber(phoneNumber);
+
+                // 如果业务逻辑是“查不到就注册”,请取消下面的注释
+                // if (user == null) {
+                //     user = miniAuthService.registerByPhoneNumber(phoneNumber);
+                // }
+
+                if (user == null) {
+                    return R.fail("该手机号未注册,请先注册");
+                }
+
+                // 3. 登录逻辑(与 /login 接口保持一致)
+                LoginUser loginUser = new LoginUser();
+                loginUser.setUserId(user.getUserId());
+                loginUser.setNickname(user.getNickname());
+                loginUser.setUserType("app_user");
+                loginUser.setOpenid(user.getOpenId());
+                loginUser.setTenantId(tenantId);
+
+                SaLoginParameter model = new SaLoginParameter();
+                model.setDeviceType("xcx");
+                model.setTimeout(30 * 24 * 60 * 60);
+                model.setActiveTimeout(7 * 24 * 60 * 60);
+                model.setExtra(LoginHelper.CLIENT_KEY, "miniprogram_client_id_2025");
+
+                LoginHelper.login(loginUser, model);
+                String accessToken = StpUtil.getTokenValue();
+                Long expireIn = StpUtil.getTokenTimeout();
+
+                SysUserWechatVo userVo = BeanUtil.copyProperties(user, SysUserWechatVo.class);
+                userVo.setAccessToken(accessToken);
+                userVo.setExpireIn(expireIn);
+
+                return R.ok(userVo);
+            });
+        } catch (Exception e) {
+            log.error("手机号登录失败", e);
+            return R.fail("登录失败");
+        }
+    }
+
 
 
     @SaIgnore
     @SaIgnore
     @PostMapping("/bindPhone")
     @PostMapping("/bindPhone")
@@ -187,9 +318,53 @@ public class MiniTokenController {
     /*
     /*
      * 获取手机号
      * 获取手机号
      * */
      * */
-    @PostMapping("/getPhoneNumber")
-    public Object getPhoneNumber(@RequestBody Map<String, String> data) {
-        return R.ok(getPhoneNumberByCode(data.get("code")));
+    @PostMapping("/getOpenId")
+    public Object getOpenId(@RequestBody Map<String, String> data) {
+        return R.ok(getOpenid(data.get("code")));
+    }
+
+    private String getOpenid(String code) {
+        // 1. 获取配置(注意:这里获取的是后端配置的 AppID,必须与前端小程序的 AppID 一致)
+
+        // 2. 构建参数
+        Map<String, String> map = new HashMap<>();
+        map.put("appid", appId);
+        map.put("secret", appSecret);
+        map.put("js_code", code);
+        map.put("grant_type", "authorization_code");
+
+        try {
+            // 3. 调用微信接口
+            String json = HttpClientUtil.doGet(WX_LOGIN, map);
+            log.info("微信接口返回: {}", json);
+
+            // 4. 解析结果
+            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(json);
+
+            // 5. 【关键】先检查有没有错误码
+            if (jsonObject.containsKey("errcode")) {
+                int errCode = jsonObject.getIntValue("errcode");
+                String errMsg = jsonObject.getString("errmsg");
+                log.error("微信登录失败: code={}, error={}", errCode, errMsg);
+                // 抛出异常或返回 null,让上层知道登录失败
+                throw new RuntimeException("微信登录失败: " + errMsg);
+            }
+
+            // 6. 获取 OpenID
+            String openid = jsonObject.getString("openid");
+            if (StringUtils.isEmpty(openid)) {
+                throw new RuntimeException("微信返回openid为空");
+            }
+
+            // 7. (可选) 获取 UnionID - 如果你需要打通公众号/App 账号体系
+            String unionId = jsonObject.getString("unionid");
+
+            return openid;
+
+        } catch (Exception e) {
+            log.error("调用微信接口异常", e);
+            throw new RuntimeException("网络连接微信服务失败", e);
+        }
     }
     }
 
 
     private String getPhoneNumberByCode(String code) {
     private String getPhoneNumberByCode(String code) {

+ 2 - 0
ruoyi-auth/src/main/java/org/dromara/auth/domain/vo/SysUserWechatVo.java

@@ -110,4 +110,6 @@ public class SysUserWechatVo implements Serializable {
     @ExcelProperty(value = "电话号码")
     @ExcelProperty(value = "电话号码")
     private String phoneNumber;
     private String phoneNumber;
 
 
+    private String appId;
+
 }
 }

+ 80 - 85
ruoyi-auth/src/main/java/org/dromara/auth/service/impl/MiniAuthServiceImpl.java

@@ -58,115 +58,110 @@ public class MiniAuthServiceImpl implements MiniAuthService {
     @Transactional(rollbackFor = Exception.class)
     @Transactional(rollbackFor = Exception.class)
     public SysUserWechat wxLogin(SysUserWechatBo wechatBo) {
     public SysUserWechat wxLogin(SysUserWechatBo wechatBo) {
 
 
-        String openid = getOpenid(wechatBo.getCode());
+        String openid = getOpenid(wechatBo.getCode()); //
 
 
-        // 判断openid是否为空,如果为空表示登录失败,抛出异常
         if (openid == null) {
         if (openid == null) {
-            throw new RuntimeException("登录code为空,登录失败");
+            throw new RuntimeException("登录code无效,登录失败");
         }
         }
 
 
         LambdaQueryWrapper<SysUserWechat> lqw =
         LambdaQueryWrapper<SysUserWechat> lqw =
             new LambdaQueryWrapper<SysUserWechat>().eq(SysUserWechat::getOpenId, openid);
             new LambdaQueryWrapper<SysUserWechat>().eq(SysUserWechat::getOpenId, openid);
+
         // 判断当前用户是否为新用户
         // 判断当前用户是否为新用户
         SysUserWechat user = wechatMapper.selectOne(lqw);
         SysUserWechat user = wechatMapper.selectOne(lqw);
-        // 如果是新用户,自动完成注册(写入昵称与头像)
+
+        // 如果是新用户,抛出特定异常,不再自动注册
         if (user == null) {
         if (user == null) {
-            user = new SysUserWechat();
-            user.setOpenId(openid);
-            user.setStatus("0");
-
-            // 从当前租户上下文中获取 tenantId 并设置
-            String tenantId = TenantHelper.getTenantId();
-            if (StringUtils.isNotBlank(tenantId)) {
-                user.setTenantId(tenantId);
-                log.info("注册新用户,设置 tenantId: {}", tenantId);
-            } else {
-                log.warn("注册新用户时未获取到 tenantId");
-            }
+            log.info("检测到新用户 (OpenID: {}), 引导注册", openid);
+            // 抛出一个包含特定标记的异常,供 Controller 捕获
+            throw new RuntimeException("USER_NOT_REGISTERED: 用户未注册");
+        }
 
 
-            if (StringUtils.isNotBlank(wechatBo.getNickname())) {
-                user.setNickname(wechatBo.getNickname());
-            }
-            if (StringUtils.isNotBlank(wechatBo.getAvatarUrl())) {
-                String ossUrl = transferImageToOss(wechatBo.getAvatarUrl());
-                if (StringUtils.isNotBlank(ossUrl)) {
-                    if (ossUrl.length() > 200) {
-                        ossUrl = ossUrl.substring(0, 200);
-                    }
-                    user.setAvatarUrl(ossUrl);
-                }
-            }
-            // 创建系统用户
-            RemoteUserBo remoteUserBo = new RemoteUserBo();
-            remoteUserBo.setDeptId(null);
-            remoteUserBo.setUserName(wechatBo.getNickname());
-            remoteUserBo.setNickName(wechatBo.getNickname());
-            remoteUserBo.setPhonenumber(wechatBo.getPhoneNumber());
-            // remoteUserBo.setRoleId(1996816313015631873L);
-            remoteUserBo.setPassword(BCrypt.hashpw("123456"));
-            remoteUserBo.setUserSonType("4"); // 小程序用户
-            remoteUserBo.setTenantId(LoginHelper.getTenantId());
-            remoteUserBo.setStatus("0"); // 正常状态
-            Long userId = remoteUserService.addUser(remoteUserBo);
-            user.setUserId(userId);
-            if (wechatMapper.insert(user) > 0) {
-                log.info("用户注册成功");
-            } else {
-                log.error("用户注册失败");
-            }
-        } else {
-            // 老用户:如本次登录携带了新的昵称或头像,与库中不同则更新
-            boolean needUpdate = false;
-            if (StringUtils.isNotBlank(wechatBo.getNickname()) && !wechatBo.getNickname().equals(user.getNickname())) {
-                user.setNickname(wechatBo.getNickname());
-                log.info("设置昵称完成");
+        // --- 老用户逻辑保持不变 ---
+        boolean needUpdate = false;
+        if (StringUtils.isNotBlank(wechatBo.getNickname()) && !wechatBo.getNickname().equals(user.getNickname())) {
+            user.setNickname(wechatBo.getNickname());
+            needUpdate = true;
+        }
+        if (StringUtils.isNotBlank(wechatBo.getAvatarUrl()) && !wechatBo.getAvatarUrl().equals(user.getAvatarUrl())) {
+            String ossUrl = transferImageToOss(wechatBo.getAvatarUrl());
+            if (StringUtils.isNotBlank(ossUrl)) {
+                user.setAvatarUrl(ossUrl.length() > 200 ? ossUrl.substring(0, 200) : ossUrl);
                 needUpdate = true;
                 needUpdate = true;
             }
             }
-            if (StringUtils.isNotBlank(wechatBo.getAvatarUrl()) && !wechatBo.getAvatarUrl().equals(user.getAvatarUrl())) {
-                String ossUrl = transferImageToOss(wechatBo.getAvatarUrl());
-                if (StringUtils.isNotBlank(ossUrl)) {
-                    if (ossUrl.length() > 200) {
-                        ossUrl = ossUrl.substring(0, 200);
-                    }
-                    user.setAvatarUrl(ossUrl);
-                    needUpdate = true;
-                }
-            }
-            if (needUpdate) {
-                log.info("设置昵称完成  : {}", user.getNickname());
-                int flag = wechatMapper.updateById(user);
-                if (flag > 0) {
-                    log.info("更新用户信息成功");
-                } else {
-                    log.error("更新用户信息失败");
-                }
-            }
+        }
+        if (needUpdate) {
+            wechatMapper.updateById(user);
+            log.info("用户信息更新成功: {}", user.getNickname());
         }
         }
 
 
-        // 返回这个用户对象
         return user;
         return user;
     }
     }
 
 
 
 
+    //    private String getOpenid(String code) {
+//        log.info("微信接口服务,获得当前微信用户的openid{}", code);
+//        // 调用微信接口服务,获得当前微信用户的openid
+//        log.info("微信接口服务,获得当前微信用户的Appid{}", weChatProperties.getAppid());
+//        log.info("微信接口服务,获得当前微信用户的Secret{}", weChatProperties.getSecret());
+//
+//        Map<String, String> map = new HashMap<>();
+//        map.put("appid", weChatProperties.getAppid());
+//        map.put("secret", weChatProperties.getSecret());
+//        map.put("js_code", code);
+//        map.put("grant_type", "authorization_code");
+//        String json = HttpClientUtil.doGet(WX_LOGIN, map);
+//        log.info("微信接口服务,获得当前微信用户的json{}", json);
+//        JSONObject jsonObject = JSON.parseObject(json);
+//        String openid = jsonObject.getString("openid");
+//        log.info("微信接口服务,获得当前微信用户的openid{}", openid);
+//        return openid;
+//    }
     private String getOpenid(String code) {
     private String getOpenid(String code) {
-        log.info("微信接口服务,获得当前微信用户的openid{}", code);
-        // 调用微信接口服务,获得当前微信用户的openid
-        log.info("微信接口服务,获得当前微信用户的Appid{}", weChatProperties.getAppid());
-        log.info("微信接口服务,获得当前微信用户的Secret{}", weChatProperties.getSecret());
+        // 1. 获取配置(注意:这里获取的是后端配置的 AppID,必须与前端小程序的 AppID 一致)
+        String appId = weChatProperties.getAppid();
+        String secret = weChatProperties.getSecret();
 
 
+        // 2. 构建参数
         Map<String, String> map = new HashMap<>();
         Map<String, String> map = new HashMap<>();
-        map.put("appid", weChatProperties.getAppid());
-        map.put("secret", weChatProperties.getSecret());
+        map.put("appid", appId);
+        map.put("secret", secret);
         map.put("js_code", code);
         map.put("js_code", code);
         map.put("grant_type", "authorization_code");
         map.put("grant_type", "authorization_code");
-        String json = HttpClientUtil.doGet(WX_LOGIN, map);
-        log.info("微信接口服务,获得当前微信用户的json{}", json);
-        JSONObject jsonObject = JSON.parseObject(json);
-        String openid = jsonObject.getString("openid");
-        log.info("微信接口服务,获得当前微信用户的openid{}", openid);
-        return openid;
-    }
 
 
+        try {
+            // 3. 调用微信接口
+            String json = HttpClientUtil.doGet(WX_LOGIN, map);
+            log.info("微信接口返回: {}", json);
+
+            // 4. 解析结果
+            JSONObject jsonObject = JSON.parseObject(json);
+
+            // 5. 【关键】先检查有没有错误码
+            if (jsonObject.containsKey("errcode")) {
+                int errCode = jsonObject.getIntValue("errcode");
+                String errMsg = jsonObject.getString("errmsg");
+                log.error("微信登录失败: code={}, error={}", errCode, errMsg);
+                // 抛出异常或返回 null,让上层知道登录失败
+                throw new RuntimeException("微信登录失败: " + errMsg);
+            }
+
+            // 6. 获取 OpenID
+            String openid = jsonObject.getString("openid");
+            if (StringUtils.isEmpty(openid)) {
+                throw new RuntimeException("微信返回openid为空");
+            }
+
+            // 7. (可选) 获取 UnionID - 如果你需要打通公众号/App 账号体系
+            String unionId = jsonObject.getString("unionid");
+
+            return openid;
+
+        } catch (Exception e) {
+            log.error("调用微信接口异常", e);
+            throw new RuntimeException("网络连接微信服务失败", e);
+        }
+    }
 
 
     /**
     /**
      * 将传入的头像地址转存到OSS并返回最终URL
      * 将传入的头像地址转存到OSS并返回最终URL

+ 3 - 1
ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlatformDataScopeInterceptor.java

@@ -120,7 +120,9 @@ public class PlatformDataScopeInterceptor implements Interceptor {
         "statement_order",
         "statement_order",
         "statement_detail",
         "statement_detail",
         "statement_product",
         "statement_product",
-        "invoice_info"
+        "invoice_info",
+        "sys_user_wechat",
+        "mini_page_set"
         // 注意:前缀匹配需特殊处理(如 qrtz_),见 isIgnoreTable 方法
         // 注意:前缀匹配需特殊处理(如 qrtz_),见 isIgnoreTable 方法
     ));
     ));
 
 

+ 8 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerRegisterBo.java

@@ -32,4 +32,12 @@ public class CustomerRegisterBo {
     * 确认密码
     * 确认密码
     * */
     * */
     private String confirmPassword;
     private String confirmPassword;
+
+    /**
+    * 注册来源 1 平台pc  2小程序
+    * */
+    private String RegisterSource;
+
+    private String openId;
+
 }
 }

+ 24 - 15
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInfoServiceImpl.java

@@ -209,8 +209,10 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         if (businessInfo != null) {
         if (businessInfo != null) {
             vo.setCustomerBusinessInfoVo(MapstructUtils.convert(businessInfo, CustomerBusinessInfoVo.class));
             vo.setCustomerBusinessInfoVo(MapstructUtils.convert(businessInfo, CustomerBusinessInfoVo.class));
             // 补充主表缺失字段
             // 补充主表缺失字段
-            if (StringUtils.isBlank(vo.getSocialCreditCode())) vo.setSocialCreditCode(businessInfo.getSocialCreditCode());
-            if (StringUtils.isBlank(vo.getBusinessCustomerName())) vo.setBusinessCustomerName(businessInfo.getBusinessCustomerName());
+            if (StringUtils.isBlank(vo.getSocialCreditCode()))
+                vo.setSocialCreditCode(businessInfo.getSocialCreditCode());
+            if (StringUtils.isBlank(vo.getBusinessCustomerName()))
+                vo.setBusinessCustomerName(businessInfo.getBusinessCustomerName());
         }
         }
 
 
         // 销售信息
         // 销售信息
@@ -776,11 +778,11 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         if ("true".equals(isHighSeasStr)) {
         if ("true".equals(isHighSeasStr)) {
             // 公海客户:负责人和客服均为空(或为0)
             // 公海客户:负责人和客服均为空(或为0)
             lqw.and(w -> w.and(a -> a.isNull(CustomerInfo::getSalesPersonId).or().eq(CustomerInfo::getSalesPersonId, 0))
             lqw.and(w -> w.and(a -> a.isNull(CustomerInfo::getSalesPersonId).or().eq(CustomerInfo::getSalesPersonId, 0))
-                         .and(b -> b.isNull(CustomerInfo::getServiceStaffId).or().eq(CustomerInfo::getServiceStaffId, 0)));
+                .and(b -> b.isNull(CustomerInfo::getServiceStaffId).or().eq(CustomerInfo::getServiceStaffId, 0)));
         } else if ("false".equals(isHighSeasStr)) {
         } else if ("false".equals(isHighSeasStr)) {
             // 有效客户:负责人不为空(且不为0) OR 客服不为空(且不为0)
             // 有效客户:负责人不为空(且不为0) OR 客服不为空(且不为0)
             lqw.and(w -> w.and(a -> a.isNotNull(CustomerInfo::getSalesPersonId).ne(CustomerInfo::getSalesPersonId, 0))
             lqw.and(w -> w.and(a -> a.isNotNull(CustomerInfo::getSalesPersonId).ne(CustomerInfo::getSalesPersonId, 0))
-                         .or(b -> b.isNotNull(CustomerInfo::getServiceStaffId).ne(CustomerInfo::getServiceStaffId, 0)));
+                .or(b -> b.isNotNull(CustomerInfo::getServiceStaffId).ne(CustomerInfo::getServiceStaffId, 0)));
         }
         }
         return lqw;
         return lqw;
     }
     }
@@ -1200,14 +1202,14 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
     @Transactional(rollbackFor = Exception.class)
     @Transactional(rollbackFor = Exception.class)
     public Boolean register(CustomerRegisterBo bo) {
     public Boolean register(CustomerRegisterBo bo) {
         //先校验验证码是否正确
         //先校验验证码是否正确
-        String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + bo.getPurchasePhone());
-        if (code == null) {
-            throw new ServiceException("验证码已过期");
-        }
-
-        if (!code.equals(bo.getCode())) {
-            throw new ServiceException("验证码错误");
-        }
+//        String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + bo.getPurchasePhone());
+//        if (code == null) {
+//            throw new ServiceException("验证码已过期");
+//        }
+//
+//        if (!code.equals(bo.getCode())) {
+//            throw new ServiceException("验证码错误");
+//        }
 
 
         //校验密码与确认密码是否一致
         //校验密码与确认密码是否一致
         if (!bo.getPassword().equals(bo.getConfirmPassword())) {
         if (!bo.getPassword().equals(bo.getConfirmPassword())) {
@@ -1358,9 +1360,16 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         remoteUserBo.setUserSonType("3"); // 商城用户
         remoteUserBo.setUserSonType("3"); // 商城用户
         remoteUserBo.setTenantId(LoginHelper.getTenantId());
         remoteUserBo.setTenantId(LoginHelper.getTenantId());
         remoteUserBo.setStatus("0"); // 正常状态
         remoteUserBo.setStatus("0"); // 正常状态
+        remoteUserBo.setSource(bo.getRegisterSource());
+        if (null!=bo.getOpenId()){
+            remoteUserBo.setOpenId(bo.getOpenId());
+        }
         Long userId = remoteUserService.addUser(remoteUserBo);
         Long userId = remoteUserService.addUser(remoteUserBo);
+        if ("2".equals(bo.getRegisterSource())) {//微信小程序注册
 
 
 
 
+        }
+
         remoteUserBo.setUserId(userId);
         remoteUserBo.setUserId(userId);
         remoteUserService.addUserRole(remoteUserBo);
         remoteUserService.addUserRole(remoteUserBo);
         // 添加客户联系人信息
         // 添加客户联系人信息
@@ -1389,9 +1398,9 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
 
 
         log.info("客户注册成功,客户ID:{},客户名称:{}", customerId, bo.getCustomerName());
         log.info("客户注册成功,客户ID:{},客户名称:{}", customerId, bo.getCustomerName());
 
 
-        if (null != code) {
-            RedisUtils.deleteObject(GlobalConstants.CAPTCHA_CODE_KEY + bo.getPurchasePhone());
-        }
+//        if (null != code) {
+//            RedisUtils.deleteObject(GlobalConstants.CAPTCHA_CODE_KEY + bo.getPurchasePhone());
+//        }
         return true;
         return true;
     }
     }
 
 

+ 106 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/controller/MiniPageSetController.java

@@ -0,0 +1,106 @@
+package org.dromara.mall.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.mall.domain.vo.MiniPageSetVo;
+import org.dromara.mall.domain.bo.MiniPageSetBo;
+import org.dromara.mall.service.IMiniPageSetService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 小程序页面设置
+ * 前端访问路由地址为:/mall/miniPageSet
+ *
+ * @author LionLi
+ * @date 2026-05-09
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/miniPageSet")
+public class MiniPageSetController extends BaseController {
+
+    private final IMiniPageSetService miniPageSetService;
+
+    /**
+     * 查询小程序页面设置列表
+     */
+    //@SaCheckPermission("mall:miniPageSet:list")
+    @GetMapping("/list")
+    public TableDataInfo<MiniPageSetVo> list(MiniPageSetBo bo, PageQuery pageQuery) {
+        return miniPageSetService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出小程序页面设置列表
+     */
+    //@SaCheckPermission("mall:miniPageSet:export")
+    @Log(title = "小程序页面设置", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(MiniPageSetBo bo, HttpServletResponse response) {
+        List<MiniPageSetVo> list = miniPageSetService.queryList(bo);
+        ExcelUtil.exportExcel(list, "小程序页面设置", MiniPageSetVo.class, response);
+    }
+
+    /**
+     * 获取小程序页面设置详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("mall:miniPageSet:query")
+    @GetMapping("/{id}")
+    public R<MiniPageSetVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(miniPageSetService.queryById(id));
+    }
+
+    /**
+     * 新增小程序页面设置
+     */
+    //@SaCheckPermission("mall:miniPageSet:add")
+    @Log(title = "小程序页面设置", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody MiniPageSetBo bo) {
+        return toAjax(miniPageSetService.insertByBo(bo));
+    }
+
+    /**
+     * 修改小程序页面设置
+     */
+    //@SaCheckPermission("mall:miniPageSet:edit")
+    @Log(title = "小程序页面设置", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody MiniPageSetBo bo) {
+        return toAjax(miniPageSetService.updateByBo(bo));
+    }
+
+    /**
+     * 删除小程序页面设置
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("mall:miniPageSet:remove")
+    @Log(title = "小程序页面设置", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(miniPageSetService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 32 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/controller/mini/MiniPageSetMiniController.java

@@ -0,0 +1,32 @@
+package org.dromara.mall.controller.mini;
+
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.mall.domain.vo.MNavigationConfigVo;
+import org.dromara.mall.domain.vo.MiniPageSetVo;
+import org.dromara.mall.service.IMiniPageSetService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * 小程序页面配置
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/miniPageSetMini")
+public class MiniPageSetMiniController {
+
+    private final IMiniPageSetService miniPageSetService;
+
+    /**
+     * 获取当前页面设置
+     */
+    @GetMapping("/current")
+    public R<MiniPageSetVo> getCurrent() {
+        return R.ok(miniPageSetService.getCurrentPageSet());
+    }
+}

+ 82 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/MiniPageSet.java

@@ -0,0 +1,82 @@
+package org.dromara.mall.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 小程序页面设置对象 mini_page_set
+ *
+ * @author LionLi
+ * @date 2026-05-09
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("mini_page_set")
+public class MiniPageSet extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 分类类型
+     */
+    private String level;
+
+    /**
+     * 分类模板
+     */
+    private String template;
+
+    /**
+     * 页面名称
+     */
+    private String pageTitle;
+
+    /**
+     * 搜索栏开关
+     */
+    private String searchControl;
+
+    /**
+     * 搜索栏文字
+     */
+    private String searchTitle;
+
+    /**
+     * 
+     */
+    private String goodsStyle;
+
+    /**
+     * 排序
+     */
+    private String sort;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 4 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/PageCategory.java

@@ -74,5 +74,9 @@ public class PageCategory extends BaseEntity {
      */
      */
     private Integer isMer;
     private Integer isMer;
 
 
+    /*
+    * 页面类型: 1 pc 2小程序*/
+    private String pageType;
+
 }
 }
 
 

+ 4 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/PageLink.java

@@ -76,5 +76,9 @@ public class PageLink extends BaseEntity {
      */
      */
     private Integer isMer;
     private Integer isMer;
 
 
+    /*
+     * 页面类型: 1 pc 2小程序*/
+    private String pageType;
+
 }
 }
 
 

+ 74 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/bo/MiniPageSetBo.java

@@ -0,0 +1,74 @@
+package org.dromara.mall.domain.bo;
+
+import org.dromara.mall.domain.MiniPageSet;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 小程序页面设置业务对象 mini_page_set
+ *
+ * @author LionLi
+ * @date 2026-05-09
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = MiniPageSet.class, reverseConvertGenerate = false)
+public class MiniPageSetBo extends BaseEntity {
+
+    /**
+     * 
+     */
+    private Long id;
+
+    /**
+     * 分类类型
+     */
+    private String level;
+
+    /**
+     * 分类模板
+     */
+    private String template;
+
+    /**
+     * 页面名称
+     */
+    private String pageTitle;
+
+    /**
+     * 搜索栏开关
+     */
+    private String searchControl;
+
+    /**
+     * 搜索栏文字
+     */
+    private String searchTitle;
+
+    /**
+     * 
+     */
+    private String goodsStyle;
+
+    /**
+     * 排序
+     */
+    private String sort;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 4 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/bo/PageCategoryBo.java

@@ -76,5 +76,9 @@ public class PageCategoryBo extends BaseEntity {
      * 是否商户 0平台,1商户
      * 是否商户 0平台,1商户
      */
      */
     private Integer isMer;
     private Integer isMer;
+
+    /*
+     * 页面类型: 1 pc 2小程序*/
+    private String pageType;
 }
 }
 
 

+ 4 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/bo/PageLinkBo.java

@@ -77,6 +77,10 @@ public class PageLinkBo extends BaseEntity {
      * 是否商户 0平台,1商户
      * 是否商户 0平台,1商户
      */
      */
     private Integer isMer;
     private Integer isMer;
+
+    /*
+     * 页面类型: 1 pc 2小程序*/
+    private String pageType;
 }
 }
 
 
 
 

+ 93 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/vo/MiniPageSetVo.java

@@ -0,0 +1,93 @@
+package org.dromara.mall.domain.vo;
+
+import org.dromara.mall.domain.MiniPageSet;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 小程序页面设置视图对象 mini_page_set
+ *
+ * @author LionLi
+ * @date 2026-05-09
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = MiniPageSet.class)
+public class MiniPageSetVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 
+     */
+    @ExcelProperty(value = "")
+    private Long id;
+
+    /**
+     * 分类类型
+     */
+    @ExcelProperty(value = "分类类型")
+    private String level;
+
+    /**
+     * 分类模板
+     */
+    @ExcelProperty(value = "分类模板")
+    private String template;
+
+    /**
+     * 页面名称
+     */
+    @ExcelProperty(value = "页面名称")
+    private String pageTitle;
+
+    /**
+     * 搜索栏开关
+     */
+    @ExcelProperty(value = "搜索栏开关")
+    private String searchControl;
+
+    /**
+     * 搜索栏文字
+     */
+    @ExcelProperty(value = "搜索栏文字")
+    private String searchTitle;
+
+    /**
+     * 
+     */
+    @ExcelProperty(value = "")
+    private String goodsStyle;
+
+    /**
+     * 排序
+     */
+    @ExcelProperty(value = "排序")
+    private String sort;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}

+ 4 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/vo/PageCategoryVo.java

@@ -81,6 +81,10 @@ public class PageCategoryVo implements Serializable {
      */
      */
     private Integer isMer;
     private Integer isMer;
 
 
+    /*
+     * 页面类型: 1 pc 2小程序*/
+    private String pageType;
+
     /**
     /**
      * 子分类列表
      * 子分类列表
      */
      */

+ 4 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/vo/PageLinkVo.java

@@ -75,5 +75,9 @@ public class PageLinkVo implements Serializable {
      */
      */
     private Integer isMer;
     private Integer isMer;
 
 
+    /*
+     * 页面类型: 1 pc 2小程序*/
+    private String pageType;
+
 }
 }
 
 

+ 15 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/mapper/MiniPageSetMapper.java

@@ -0,0 +1,15 @@
+package org.dromara.mall.mapper;
+
+import org.dromara.mall.domain.MiniPageSet;
+import org.dromara.mall.domain.vo.MiniPageSetVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 小程序页面设置Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-05-09
+ */
+public interface MiniPageSetMapper extends BaseMapperPlus<MiniPageSet, MiniPageSetVo> {
+
+}

+ 77 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/IMiniPageSetService.java

@@ -0,0 +1,77 @@
+package org.dromara.mall.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.mall.domain.MiniPageSet;
+import org.dromara.mall.domain.vo.MNavigationConfigVo;
+import org.dromara.mall.domain.vo.MiniPageSetVo;
+import org.dromara.mall.domain.bo.MiniPageSetBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 小程序页面设置Service接口
+ *
+ * @author LionLi
+ * @date 2026-05-09
+ */
+public interface IMiniPageSetService extends IService<MiniPageSet>{
+
+    /**
+     * 查询小程序页面设置
+     *
+     * @param id 主键
+     * @return 小程序页面设置
+     */
+    MiniPageSetVo queryById(Long id);
+
+    /**
+     * 分页查询小程序页面设置列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 小程序页面设置分页列表
+     */
+    TableDataInfo<MiniPageSetVo> queryPageList(MiniPageSetBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的小程序页面设置列表
+     *
+     * @param bo 查询条件
+     * @return 小程序页面设置列表
+     */
+    List<MiniPageSetVo> queryList(MiniPageSetBo bo);
+
+    /**
+     * 新增小程序页面设置
+     *
+     * @param bo 小程序页面设置
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(MiniPageSetBo bo);
+
+    /**
+     * 修改小程序页面设置
+     *
+     * @param bo 小程序页面设置
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(MiniPageSetBo bo);
+
+    /**
+     * 校验并批量删除小程序页面设置信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    /**
+     * 获取当前页面设置
+     *
+     */
+    MiniPageSetVo getCurrentPageSet();
+}

+ 153 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/impl/MiniPageSetServiceImpl.java

@@ -0,0 +1,153 @@
+package org.dromara.mall.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.mall.domain.MNavigationConfig;
+import org.dromara.mall.domain.vo.MNavigationConfigVo;
+import org.springframework.stereotype.Service;
+import org.dromara.mall.domain.bo.MiniPageSetBo;
+import org.dromara.mall.domain.vo.MiniPageSetVo;
+import org.dromara.mall.domain.MiniPageSet;
+import org.dromara.mall.mapper.MiniPageSetMapper;
+import org.dromara.mall.service.IMiniPageSetService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 小程序页面设置Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-05-09
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class MiniPageSetServiceImpl  extends ServiceImpl<MiniPageSetMapper, MiniPageSet> implements IMiniPageSetService {
+
+    private final MiniPageSetMapper baseMapper;
+
+    /**
+     * 查询小程序页面设置
+     *
+     * @param id 主键
+     * @return 小程序页面设置
+     */
+    @Override
+    public MiniPageSetVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询小程序页面设置列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 小程序页面设置分页列表
+     */
+    @Override
+    public TableDataInfo<MiniPageSetVo> queryPageList(MiniPageSetBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<MiniPageSet> lqw = buildQueryWrapper(bo);
+        Page<MiniPageSetVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的小程序页面设置列表
+     *
+     * @param bo 查询条件
+     * @return 小程序页面设置列表
+     */
+    @Override
+    public List<MiniPageSetVo> queryList(MiniPageSetBo bo) {
+        LambdaQueryWrapper<MiniPageSet> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<MiniPageSet> buildQueryWrapper(MiniPageSetBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<MiniPageSet> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(MiniPageSet::getId);
+        lqw.eq(StringUtils.isNotBlank(bo.getLevel()), MiniPageSet::getLevel, bo.getLevel());
+        lqw.eq(StringUtils.isNotBlank(bo.getTemplate()), MiniPageSet::getTemplate, bo.getTemplate());
+        lqw.eq(StringUtils.isNotBlank(bo.getPageTitle()), MiniPageSet::getPageTitle, bo.getPageTitle());
+        lqw.eq(StringUtils.isNotBlank(bo.getSearchControl()), MiniPageSet::getSearchControl, bo.getSearchControl());
+        lqw.eq(StringUtils.isNotBlank(bo.getSearchTitle()), MiniPageSet::getSearchTitle, bo.getSearchTitle());
+        lqw.eq(StringUtils.isNotBlank(bo.getGoodsStyle()), MiniPageSet::getGoodsStyle, bo.getGoodsStyle());
+        lqw.eq(StringUtils.isNotBlank(bo.getSort()), MiniPageSet::getSort, bo.getSort());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), MiniPageSet::getStatus, bo.getStatus());
+        lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), MiniPageSet::getPlatformCode, bo.getPlatformCode());
+        return lqw;
+    }
+
+    /**
+     * 新增小程序页面设置
+     *
+     * @param bo 小程序页面设置
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(MiniPageSetBo bo) {
+        MiniPageSet add = MapstructUtils.convert(bo, MiniPageSet.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改小程序页面设置
+     *
+     * @param bo 小程序页面设置
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(MiniPageSetBo bo) {
+        MiniPageSet update = MapstructUtils.convert(bo, MiniPageSet.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(MiniPageSet entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除小程序页面设置信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+
+    @Override
+    public MiniPageSetVo getCurrentPageSet() {
+        // 查询是否有配置
+        LambdaQueryWrapper<MiniPageSet> lqw = Wrappers.lambdaQuery();
+        lqw.last("LIMIT 1");
+        MiniPageSet config = baseMapper.selectOne(lqw);
+        MiniPageSetVo vo = baseMapper.selectVoById(config.getId());
+        return vo;
+    }
+}

+ 1 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/impl/PageCategoryServiceImpl.java

@@ -60,6 +60,7 @@ public class PageCategoryServiceImpl extends ServiceImpl<PageCategoryMapper, Pag
             .eq(bo.getStatus() != null, PageCategory::getStatus, bo.getStatus())
             .eq(bo.getStatus() != null, PageCategory::getStatus, bo.getStatus())
             .eq(bo.getType() != null, PageCategory::getType, bo.getType())
             .eq(bo.getType() != null, PageCategory::getType, bo.getType())
             .eq(bo.getIsMer() != null, PageCategory::getIsMer, bo.getIsMer())
             .eq(bo.getIsMer() != null, PageCategory::getIsMer, bo.getIsMer())
+            .eq(bo.getPageType() != null, PageCategory::getPageType, bo.getPageType())
             .like(StringUtils.isNotBlank(bo.getName()), PageCategory::getName, bo.getName())
             .like(StringUtils.isNotBlank(bo.getName()), PageCategory::getName, bo.getName())
             .orderByAsc(PageCategory::getSort);
             .orderByAsc(PageCategory::getSort);
     }
     }

+ 1 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/impl/PageLinkServiceImpl.java

@@ -67,6 +67,7 @@ public class PageLinkServiceImpl extends ServiceImpl<PageLinkMapper, PageLink> i
         lqw.eq(bo.getSort() != null, PageLink::getSort, bo.getSort());
         lqw.eq(bo.getSort() != null, PageLink::getSort, bo.getSort());
         lqw.eq(bo.getCreateTime() != null, PageLink::getCreateTime, bo.getCreateTime());
         lqw.eq(bo.getCreateTime() != null, PageLink::getCreateTime, bo.getCreateTime());
         lqw.eq(bo.getIsMer() != null, PageLink::getIsMer, bo.getIsMer());
         lqw.eq(bo.getIsMer() != null, PageLink::getIsMer, bo.getIsMer());
+        lqw.eq(bo.getPageType() != null, PageLink::getPageType, bo.getPageType());
         return lqw;
         return lqw;
     }
     }
 
 

+ 7 - 0
ruoyi-modules/ruoyi-mall/src/main/resources/mapper/mall/MiniPageSetMapper.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.dromara.mall.mapper.MiniPageSetMapper">
+
+</mapper>

+ 3 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/ComStaff.java

@@ -100,5 +100,8 @@ public class ComStaff extends TenantEntity {
      */
      */
     private String remark;
     private String remark;
 
 
+    /*系统用户Id*/
+    private Long userId;
+
 
 
 }
 }

+ 4 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java

@@ -108,6 +108,10 @@ public class SysUser extends TenantEntity {
      * */
      * */
     private String userSonType;
     private String userSonType;
 
 
+    private String source;
+
+    private String openId;
+
     /**
     /**
      * 插入时自动填充 platformCode
      * 插入时自动填充 platformCode
      */
      */

+ 3 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/ComStaffBo.java

@@ -94,4 +94,7 @@ public class ComStaffBo extends BaseEntity {
     private String remark;
     private String remark;
 
 
 
 
+    /*系统用户Id*/
+    private Long userId;
+
 }
 }

+ 7 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java

@@ -121,6 +121,13 @@ public class SysUserBo extends BaseEntity {
      */
      */
     private String userIds;
     private String userIds;
 
 
+    /**
+     * 来源 1平台 2微信小程序
+     */
+    private String source;
+
+    private String openId;
+
     /**
     /**
      * 排除不查询的用户(工作流用)
      * 排除不查询的用户(工作流用)
      */
      */

+ 3 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ComStaffVo.java

@@ -121,6 +121,9 @@ public class ComStaffVo implements Serializable {
     @ExcelProperty(value = "备注")
     @ExcelProperty(value = "备注")
     private String remark;
     private String remark;
 
 
+    /*系统用户Id*/
+    private Long userId;
+
     private String deptName;
     private String deptName;
 
 
     private String deptCode;
     private String deptCode;

+ 4 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java

@@ -147,4 +147,8 @@ public class SysUserVo implements Serializable {
     /*平台标识*/
     /*平台标识*/
     private String platformCode;
     private String platformCode;
 
 
+    private String source;
+
+    private String openId;
+
 }
 }

+ 29 - 8
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/ComStaffServiceImpl.java

@@ -1,6 +1,7 @@
 package org.dromara.system.service.impl;
 package org.dromara.system.service.impl;
 
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.crypto.digest.BCrypt;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -8,21 +9,19 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.ObjectUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
-import org.dromara.system.domain.ComStaff;
-import org.dromara.system.domain.SysDept;
-import org.dromara.system.domain.SysPost;
-import org.dromara.system.domain.SysRole;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.system.domain.*;
 import org.dromara.system.domain.bo.ComStaffBo;
 import org.dromara.system.domain.bo.ComStaffBo;
+import org.dromara.system.domain.bo.SysUserBo;
 import org.dromara.system.domain.vo.ComStaffVo;
 import org.dromara.system.domain.vo.ComStaffVo;
-import org.dromara.system.mapper.ComStaffMapper;
-import org.dromara.system.mapper.SysDeptMapper;
-import org.dromara.system.mapper.SysPostMapper;
-import org.dromara.system.mapper.SysRoleMapper;
+import org.dromara.system.mapper.*;
 import org.dromara.system.service.IComStaffService;
 import org.dromara.system.service.IComStaffService;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 
 import java.util.*;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
@@ -46,6 +45,8 @@ public class ComStaffServiceImpl extends ServiceImpl<ComStaffMapper, ComStaff> i
 
 
     private final SysRoleMapper sysRoleMapper;
     private final SysRoleMapper sysRoleMapper;
 
 
+    private final SysUserMapper sysUserMapper;
+
     /**
     /**
      * 查询人员信息
      * 查询人员信息
      *
      *
@@ -214,8 +215,28 @@ public class ComStaffServiceImpl extends ServiceImpl<ComStaffMapper, ComStaff> i
      * @return 是否新增成功
      * @return 是否新增成功
      */
      */
     @Override
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public Boolean insertByBo(ComStaffBo bo) {
     public Boolean insertByBo(ComStaffBo bo) {
+        Long userId=null;
+        if (ObjectUtils.isNotEmpty( bo.getPhone())){
+            SysUserBo user = new SysUserBo();
+            user.setUserName(bo.getPhone());
+            user.setNickName(bo.getStaffName());
+            user.setDeptId(bo.getDeptId());
+            user.setUserName(bo.getPhone());// 用手机号做账号
+            user.setPhonenumber(bo.getPhone());
+            String defaultPassword = "123456";
+            user.setPassword(BCrypt.hashpw(defaultPassword));
+            user.setUserSonType("3");
+            user.setRoleIds(new Long[]{bo.getRoleId()});
+            SysUser sysUser = MapstructUtils.convert(user, SysUser.class);
+            int insert = sysUserMapper.insert(sysUser);
+            if (insert>0){
+                userId = sysUser.getUserId();
+            }
+        }
         ComStaff add = MapstructUtils.convert(bo, ComStaff.class);
         ComStaff add = MapstructUtils.convert(bo, ComStaff.class);
+        add.setUserId(userId);
         validEntityBeforeSave(add);
         validEntityBeforeSave(add);
         boolean flag = baseMapper.insert(add) > 0;
         boolean flag = baseMapper.insert(add) > 0;
         if (flag) {
         if (flag) {