yangdamao 2 лет назад
Родитель
Сommit
c7af6bd299
88 измененных файлов с 6482 добавлено и 37 удалено
  1. 32 0
      run-prod.sh
  2. 1 1
      zhongzheng-admin-saas/src/main/resources/application.yml
  3. 18 0
      zhongzheng-admin-store/src/main/java/com/zhongzheng/ZhongZhengStoreApplication.java
  4. 18 0
      zhongzheng-admin-store/src/main/java/com/zhongzheng/ZhongZhengStoreServletInitializer.java
  5. 77 0
      zhongzheng-admin-store/src/main/java/com/zhongzheng/controller/category/GoodsCategoryController.java
  6. 47 0
      zhongzheng-admin-store/src/main/java/com/zhongzheng/controller/system/LoginController.java
  7. 165 0
      zhongzheng-admin-store/src/main/java/com/zhongzheng/controller/system/StoreMenuController.java
  8. 165 0
      zhongzheng-admin-store/src/main/java/com/zhongzheng/controller/system/StoreRoleController.java
  9. 191 0
      zhongzheng-admin-store/src/main/java/com/zhongzheng/controller/system/StoreUserController.java
  10. 137 0
      zhongzheng-admin-store/src/main/java/com/zhongzheng/core/config/SwaggerConfig.java
  11. 1 0
      zhongzheng-admin-store/src/main/resources/META-INF/spring-devtools.properties
  12. 168 0
      zhongzheng-admin-store/src/main/resources/application-dev.yml
  13. 154 0
      zhongzheng-admin-store/src/main/resources/application-pre.yml
  14. 157 0
      zhongzheng-admin-store/src/main/resources/application-prod.yml
  15. 308 0
      zhongzheng-admin-store/src/main/resources/application.yml
  16. 2 0
      zhongzheng-admin-store/src/main/resources/banner.txt
  17. 36 0
      zhongzheng-admin-store/src/main/resources/i18n/messages.properties
  18. 108 0
      zhongzheng-admin-store/src/main/resources/logback.xml
  19. 0 0
      zhongzheng-admin-store/src/main/resources/mybatis/mybatis-config.xml
  20. 1 1
      zhongzheng-admin/src/main/resources/application.yml
  21. 1 1
      zhongzheng-api/src/main/resources/application.yml
  22. 12 0
      zhongzheng-common/src/main/java/com/zhongzheng/common/constant/Constants.java
  23. 81 0
      zhongzheng-common/src/main/java/com/zhongzheng/common/core/domain/entity/store/StoreMenu.java
  24. 110 0
      zhongzheng-common/src/main/java/com/zhongzheng/common/core/domain/entity/store/StoreRole.java
  25. 32 0
      zhongzheng-common/src/main/java/com/zhongzheng/common/core/domain/entity/store/StoreRoleMenu.java
  26. 87 0
      zhongzheng-common/src/main/java/com/zhongzheng/common/core/domain/entity/store/StoreUser.java
  27. 34 0
      zhongzheng-common/src/main/java/com/zhongzheng/common/core/domain/entity/store/StoreUserRole.java
  28. 143 0
      zhongzheng-common/src/main/java/com/zhongzheng/common/core/domain/model/StoreLoginUser.java
  29. 3 3
      zhongzheng-common/src/main/java/com/zhongzheng/common/utils/SecurityUtils.java
  30. 14 5
      zhongzheng-framework/src/main/java/com/zhongzheng/framework/aspectj/LogAspect.java
  31. 13 5
      zhongzheng-framework/src/main/java/com/zhongzheng/framework/config/SecurityConfig.java
  32. 4 4
      zhongzheng-framework/src/main/java/com/zhongzheng/framework/mybatisplus/CreateAndUpdateMetaObjectHandler.java
  33. 4 4
      zhongzheng-framework/src/main/java/com/zhongzheng/framework/mybatisplus/CustomTenantLineHandler.java
  34. 22 10
      zhongzheng-framework/src/main/java/com/zhongzheng/framework/security/filter/JwtAuthenticationTokenFilter.java
  35. 2 3
      zhongzheng-framework/src/main/java/com/zhongzheng/framework/web/service/PermissionService.java
  36. 67 0
      zhongzheng-framework/src/main/java/com/zhongzheng/framework/web/service/StorePermissionService.java
  37. 243 0
      zhongzheng-framework/src/main/java/com/zhongzheng/framework/web/service/StoreTokenService.java
  38. 64 0
      zhongzheng-framework/src/main/java/com/zhongzheng/framework/web/service/StoreUserDetailsServiceImpl.java
  39. 265 0
      zhongzheng-framework/src/main/java/com/zhongzheng/framework/web/service/StoreUserServiceImpl.java
  40. 43 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/bo/GoodsCategoryBo.java
  41. 41 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/bo/GoodsCategoryQueryBo.java
  42. 44 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/domain/GoodsCategory.java
  43. 13 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/mapper/GoodsCategoryMapper.java
  44. 23 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/service/IGoodsCategoryService.java
  45. 114 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/service/impl/GoodsCategoryServiceImpl.java
  46. 47 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/vo/GoodsCategoryVo.java
  47. 80 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreMenuAddBo.java
  48. 94 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreMenuEditBo.java
  49. 81 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreMenuQueryBo.java
  50. 68 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreRoleAddBo.java
  51. 74 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreRoleEditBo.java
  52. 27 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreRoleMenuAddBo.java
  53. 37 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreRoleMenuEditBo.java
  54. 45 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreRoleMenuQueryBo.java
  55. 66 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreRoleQueryBo.java
  56. 63 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreUserAddBo.java
  57. 77 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreUserEditBo.java
  58. 75 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreUserQueryBo.java
  59. 27 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreUserRoleAddBo.java
  60. 37 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreUserRoleEditBo.java
  61. 45 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreUserRoleQueryBo.java
  62. 53 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/mapper/StoreMenuMapper.java
  63. 26 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/mapper/StoreRoleMapper.java
  64. 16 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/mapper/StoreRoleMenuMapper.java
  65. 31 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/mapper/StoreUserMapper.java
  66. 15 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/mapper/StoreUserRoleMapper.java
  67. 141 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/IStoreMenuService.java
  68. 53 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/IStoreRoleMenuService.java
  69. 127 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/IStoreRoleService.java
  70. 53 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/IStoreUserRoleService.java
  71. 85 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/IStoreUserService.java
  72. 425 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/impl/StoreMenuServiceImpl.java
  73. 94 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/impl/StoreRoleMenuServiceImpl.java
  74. 276 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/impl/StoreRoleServiceImpl.java
  75. 94 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/impl/StoreUserRoleServiceImpl.java
  76. 85 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/vo/StoreMenuVo.java
  77. 35 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/vo/StoreRoleMenuVo.java
  78. 67 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/vo/StoreRoleVo.java
  79. 35 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/vo/StoreUserRoleVo.java
  80. 75 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/store/vo/StoreUserVo.java
  81. 44 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/top/util/TreeSelectStore.java
  82. 146 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/user/entity/ClientLoginStoreUser.java
  83. 23 0
      zhongzheng-system/src/main/resources/mapper/modules/goods/GoodsCategoryMapper.xml
  84. 120 0
      zhongzheng-system/src/main/resources/mapper/modules/store/StoreMenuMapper.xml
  85. 56 0
      zhongzheng-system/src/main/resources/mapper/modules/store/StoreRoleMapper.xml
  86. 15 0
      zhongzheng-system/src/main/resources/mapper/modules/store/StoreRoleMenuMapper.xml
  87. 69 0
      zhongzheng-system/src/main/resources/mapper/modules/store/StoreUserMapper.xml
  88. 15 0
      zhongzheng-system/src/main/resources/mapper/modules/store/StoreUserRoleMapper.xml

+ 32 - 0
run-prod.sh

@@ -106,5 +106,37 @@ docker run \
 -d ${group_admin_name}/${app_admin_name}:${app_admin_version}
 echo '----start container admin top----'
 
+#!/usr/bin/env bash
+# 定义应用组名
+group_admin_name='zhongzheng'
+# 定义应用名称
+app_admin_name='zhongzheng-saas-admin-top'
+# 定义应用版本
+app_admin_version='1.0-SNAPSHOT'
+# 定义应用环境
+profile_active='prod'
+echo '----copy jar admin top----'
+docker stop ${app_admin_name}
+echo '----stop container admin top----'
+docker rm ${app_admin_name}
+echo '----rm container admin top----'
+docker rmi ${group_admin_name}/${app_admin_name}:${app_admin_version}
+echo '----rm image admin top----'
+# 打包编译docker镜像
+docker build -f /mydata/maven/build/Dockerfile-saas -t ${group_admin_name}/${app_admin_name}:${app_admin_version} .
+echo '----build image admin top----'
+docker run \
+-p 7077:7077 \
+--name ${app_admin_name} \
+--restart=always \
+-e 'spring.profiles.active'=${profile_active} \
+-e TZ="Asia/Shanghai" \
+-v /etc/localtime:/etc/localtime \
+-v /usr/share/fonts:/usr/share/fonts \
+-v /data/logs/prod_admin:/logs \
+-v /mydata/app/${app_admin_name}/logs:/var/logs \
+-v /data/nginx/conf.d:/data/nginx/conf.d \
+-d ${group_admin_name}/${app_admin_name}:${app_admin_version}
+echo '----start container admin top----'
 
 

+ 1 - 1
zhongzheng-admin-saas/src/main/resources/application.yml

@@ -209,7 +209,7 @@ mybatis-plus:
       selectStrategy: NOT_EMPTY
   # 开启多租户
   tenant:
-    enabled-tenant: false
+    enabled-tenant: 2
 # PageHelper分页插件
 pagehelper:
   helperDialect: mysql

+ 18 - 0
zhongzheng-admin-store/src/main/java/com/zhongzheng/ZhongZhengStoreApplication.java

@@ -0,0 +1,18 @@
+package com.zhongzheng;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
+@EnableScheduling
+public class ZhongZhengStoreApplication {
+
+    public static void main(String[] args) {
+        System.setProperty("spring.devtools.restart.enabled", "false");
+        SpringApplication.run(ZhongZhengStoreApplication.class, args);
+        System.out.println("(♥◠‿◠)ノ゙  AdminStore启动成功   ლ(´ڡ`ლ)゙"+"AdminStore");
+    }
+
+}

+ 18 - 0
zhongzheng-admin-store/src/main/java/com/zhongzheng/ZhongZhengStoreServletInitializer.java

@@ -0,0 +1,18 @@
+package com.zhongzheng;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+/**
+ * web容器中进行部署
+ *
+ * @author zhongzheng
+ */
+public class ZhongZhengStoreServletInitializer extends SpringBootServletInitializer
+{
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
+    {
+        return application.sources(ZhongZhengStoreApplication.class);
+    }
+}

+ 77 - 0
zhongzheng-admin-store/src/main/java/com/zhongzheng/controller/category/GoodsCategoryController.java

@@ -0,0 +1,77 @@
+package com.zhongzheng.controller.category;
+
+import com.zhongzheng.common.core.controller.BaseController;
+import com.zhongzheng.common.core.domain.AjaxResult;
+import com.zhongzheng.common.core.page.TableDataInfo;
+import com.zhongzheng.modules.goods.bo.GoodsCategoryBo;
+import com.zhongzheng.modules.goods.bo.GoodsCategoryQueryBo;
+import com.zhongzheng.modules.goods.service.IGoodsCategoryService;
+import com.zhongzheng.modules.goods.vo.GoodsCategoryVo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 商品类目Controller
+ *
+ * @date
+ */
+@Api(value = "商品类目控制器", tags = {"商品类目管理"})
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+@RestController
+@RequestMapping("/goods/category")
+public class GoodsCategoryController extends BaseController {
+
+    private final IGoodsCategoryService iGoodsCategoryService;
+
+    /**
+     * 查询类目列表
+     */
+    @ApiOperation("查询类目列表")
+    @GetMapping("/list")
+    public TableDataInfo<GoodsCategoryVo> list(GoodsCategoryQueryBo bo) {
+        startPage();
+        List<GoodsCategoryVo> list = iGoodsCategoryService.queryList(bo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 新增
+     */
+    @ApiOperation("新增类目")
+    @PostMapping("/save")
+    public AjaxResult<Void> saveCategory(@RequestBody GoodsCategoryBo bo) {
+        return toAjax(iGoodsCategoryService.saveCategory(bo) ? 1 : 0);
+    }
+
+    /**
+     * 修改
+     */
+    @ApiOperation("修改类目")
+    @PostMapping("/update")
+    public AjaxResult<Void> updateCategory(@RequestBody GoodsCategoryBo bo) {
+        return toAjax(iGoodsCategoryService.updateCategory(bo) ? 1 : 0);
+    }
+
+    /**
+     * 批量删除
+     */
+    @ApiOperation("批量删除类目")
+    @PostMapping("/batch/del")
+    public AjaxResult<Void> batchDelCategory(@RequestBody List<Long> ids) {
+        return toAjax(iGoodsCategoryService.batchDelCategory(ids) ? 1 : 0);
+    }
+
+    /**
+     * 类目树
+     */
+    @ApiOperation("类目树")
+    @GetMapping("/tree")
+    public AjaxResult<List<GoodsCategoryVo>> categoryTree() {
+        return AjaxResult.success(iGoodsCategoryService.categoryTree());
+    }
+}

+ 47 - 0
zhongzheng-admin-store/src/main/java/com/zhongzheng/controller/system/LoginController.java

@@ -0,0 +1,47 @@
+package com.zhongzheng.controller.system;
+
+import com.zhongzheng.common.core.controller.BaseController;
+import com.zhongzheng.common.core.domain.AjaxResult;
+import com.zhongzheng.modules.store.service.IStoreUserService;
+import com.zhongzheng.modules.user.bo.UserAppAccountLoginBo;
+import com.zhongzheng.modules.user.bo.UserAppSmsLoginBo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+/**
+ * 客户端用户Controller
+ *
+ * @author hjl
+ * @date 2021-06-08
+ */
+@Api(value = "短信控制器", tags = {"登录控制器"})
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+@RestController
+@RequestMapping("/app/store/common")
+public class LoginController extends BaseController {
+
+    private final IStoreUserService iUserService;
+
+
+    @ApiOperation("短信登录")
+    @PostMapping("/sms_login")
+    public AjaxResult sms_login(@RequestBody UserAppSmsLoginBo bo) {
+        Map<String,Object> map = iUserService.smsLogin(bo);
+        return AjaxResult.success(map);
+    }
+
+    @ApiOperation("账号登录")
+    @PostMapping("/account_login")
+    public AjaxResult account_login(@RequestBody UserAppAccountLoginBo bo) {
+        Map<String,Object> map = iUserService.accountLogin(bo);
+        return AjaxResult.success(map);
+    }
+}

+ 165 - 0
zhongzheng-admin-store/src/main/java/com/zhongzheng/controller/system/StoreMenuController.java

@@ -0,0 +1,165 @@
+package com.zhongzheng.controller.system;
+
+import cn.hutool.core.util.StrUtil;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.zhongzheng.common.annotation.Log;
+import com.zhongzheng.common.constant.Constants;
+import com.zhongzheng.common.constant.UserConstants;
+import com.zhongzheng.common.core.controller.BaseController;
+import com.zhongzheng.common.core.domain.AjaxResult;
+import com.zhongzheng.common.core.domain.entity.store.StoreMenu;
+import com.zhongzheng.common.enums.BusinessType;
+import com.zhongzheng.common.utils.SecurityUtils;
+import com.zhongzheng.common.utils.ServletUtils;
+import com.zhongzheng.framework.web.service.StoreTokenService;
+import com.zhongzheng.modules.store.service.IStoreMenuService;
+import com.zhongzheng.modules.user.entity.ClientLoginStoreUser;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Controller
+ * 
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Api(value = "【请填写功能名称】控制器", tags = {"【请填写功能名称】管理"})
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+@RestController
+@RequestMapping("/store/system/menu")
+public class StoreMenuController extends BaseController {
+    
+    private final IStoreMenuService storeMenuService; 
+    private final StoreTokenService tokenService;
+
+    /**
+     * 获取菜单列表
+     */
+    @ApiOperation("获取菜单列表")
+    @GetMapping("/list")
+    public AjaxResult list(StoreMenu menu)
+    {
+        ClientLoginStoreUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        List<StoreMenu> menus = storeMenuService.selectMenuList(menu, userId);
+        return AjaxResult.success(menus);
+    }
+
+    /**
+     * 根据菜单编号获取详细信息
+     */
+    @ApiOperation("根据菜单编号获取详细信息")
+    @GetMapping(value = "/{menuId}")
+    public AjaxResult getInfo(@PathVariable Long menuId)
+    {
+        return AjaxResult.success(storeMenuService.selectMenuById(menuId));
+    }
+
+    /**
+     * 获取菜单下拉树列表
+     */
+    @ApiOperation("获取菜单下拉树列表")
+    @ApiOperationSupport(includeParameters = {})
+    @GetMapping("/treeselect")
+    public AjaxResult treeselect(StoreMenu menu)
+    {
+        ClientLoginStoreUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        List<StoreMenu> menus = storeMenuService.selectMenuList(menu, userId);
+        return AjaxResult.success(storeMenuService.buildMenuTreeSelect(menus));
+    }
+
+    /**
+     * 加载对应角色菜单列表树
+     */
+    @ApiOperation("加载对应角色菜单列表树")
+    @GetMapping(value = "/roleMenuTreeselect/{roleId}")
+    public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
+    {
+        ClientLoginStoreUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        List<StoreMenu> menus = storeMenuService.selectMenuList(loginUser.getUser().getUserId());
+        AjaxResult ajax = AjaxResult.success();
+        ajax.put("checkedKeys", storeMenuService.selectMenuListByRoleId(roleId));
+        ajax.put("menus", storeMenuService.buildMenuTreeSelect(menus));
+        return ajax;
+    }
+
+    /**
+     * 新增菜单
+     */
+    @ApiOperation("新增菜单")
+    @ApiOperationSupport(ignoreParameters = {"children","createBy","createTime","menuId","params"
+            ,"parentName","remark","updateBy","updateTime"})
+    @PreAuthorize("@ss.hasPermi('system:menu:add')")
+    @Log(title = "菜单管理", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@Validated @RequestBody StoreMenu menu)
+    {
+        if (UserConstants.NOT_UNIQUE.equals(storeMenuService.checkMenuNameUnique(menu)))
+        {
+            return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
+        }
+        else if (UserConstants.YES_FRAME.equals(menu.getIsFrame())
+                && !StrUtil.startWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS))
+        {
+            return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
+        }
+        menu.setCreateBy(SecurityUtils.getUsername());
+        return toAjax(storeMenuService.insertMenu(menu));
+    }
+
+    /**
+     * 修改菜单
+     */
+    @ApiOperation("修改菜单")
+    @ApiOperationSupport(ignoreParameters = {"children","createBy","createTime","params"
+            ,"parentName","remark","updateBy","updateTime"})
+    @PreAuthorize("@ss.hasPermi('system:menu:edit')")
+    @Log(title = "菜单管理", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    public AjaxResult edit(@Validated @RequestBody StoreMenu menu)
+    {
+        if (UserConstants.NOT_UNIQUE.equals(storeMenuService.checkMenuNameUnique(menu)))
+        {
+            return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
+        }
+        else if (UserConstants.YES_FRAME.equals(menu.getIsFrame())
+                && !StrUtil.startWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS))
+        {
+            return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
+        }
+        else if (menu.getMenuId().equals(menu.getParentId()))
+        {
+            return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
+        }
+        menu.setUpdateBy(SecurityUtils.getUsername());
+        return toAjax(storeMenuService.updateMenu(menu));
+    }
+
+    /**
+     * 删除菜单
+     */
+    @ApiOperation("删除菜单")
+    @PreAuthorize("@ss.hasPermi('system:menu:remove')")
+    @Log(title = "菜单管理", businessType = BusinessType.DELETE)
+    @PostMapping("/delete/{menuId}")
+    public AjaxResult remove(@PathVariable Long menuId)
+    {
+        if (storeMenuService.hasChildByMenuId(menuId))
+        {
+            return AjaxResult.error("存在子菜单,不允许删除");
+        }
+        if (storeMenuService.checkMenuExistRole(menuId))
+        {
+            return AjaxResult.error("菜单已分配,不允许删除");
+        }
+        return toAjax(storeMenuService.deleteMenuById(menuId));
+    }
+}

+ 165 - 0
zhongzheng-admin-store/src/main/java/com/zhongzheng/controller/system/StoreRoleController.java

@@ -0,0 +1,165 @@
+package com.zhongzheng.controller.system;
+
+import cn.hutool.core.lang.Validator;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.zhongzheng.common.annotation.Log;
+import com.zhongzheng.common.constant.UserConstants;
+import com.zhongzheng.common.core.controller.BaseController;
+import com.zhongzheng.common.core.domain.AjaxResult;
+import com.zhongzheng.common.core.domain.entity.store.StoreRole;
+import com.zhongzheng.common.core.page.TableDataInfo;
+import com.zhongzheng.common.enums.BusinessType;
+import com.zhongzheng.common.utils.SecurityUtils;
+import com.zhongzheng.common.utils.ServletUtils;
+import com.zhongzheng.framework.web.service.StorePermissionService;
+import com.zhongzheng.framework.web.service.StoreTokenService;
+import com.zhongzheng.modules.store.service.IStoreRoleService;
+import com.zhongzheng.modules.store.service.IStoreUserService;
+import com.zhongzheng.modules.user.entity.ClientLoginStoreUser;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Controller
+ * 
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Api(value = "【请填写功能名称】控制器", tags = {"【请填写功能名称】管理"})
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+@RestController
+@RequestMapping("/store/system/role")
+public class StoreRoleController extends BaseController {
+    
+    private final IStoreRoleService storeRoleService;
+    private final StoreTokenService storeTokenService;
+    private final StorePermissionService storePermissionService;
+    private final IStoreUserService storeUserService;
+
+    @ApiOperation("角色列表")
+    @GetMapping("/list")
+    public TableDataInfo list(StoreRole role)
+    {
+        startPage();
+        List<StoreRole> list = storeRoleService.selectRoleList(role);
+        return getDataTable(list);
+    }
+
+
+    /**
+     * 根据角色编号获取详细信息
+     */
+    @ApiOperation("根据角色编号获取详细信息")
+    @GetMapping(value = "/{roleId}")
+    public AjaxResult getInfo(@PathVariable Long roleId)
+    {
+        return AjaxResult.success(storeRoleService.selectRoleById(roleId));
+    }
+
+    /**
+     * 新增角色
+     */
+    @ApiOperation("新增角色")
+    @ApiOperationSupport(ignoreParameters = {"createBy","createTime","dataScope","delFlag","updateTime"
+            ,"flag","params","roleId","updateBy","deptIds","deptCheckStrictly","menuCheckStrictly"})
+    @PostMapping
+    public AjaxResult add(@Validated @RequestBody StoreRole role)
+    {
+        if (UserConstants.NOT_UNIQUE.equals(storeRoleService.checkRoleNameUnique(role)))
+        {
+            return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
+        }
+        else if (UserConstants.NOT_UNIQUE.equals(storeRoleService.checkRoleKeyUnique(role)))
+        {
+            return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
+        }
+        role.setCreateBy(SecurityUtils.getUsername());
+        return toAjax(storeRoleService.insertRole(role));
+
+    }
+
+    /**
+     * 修改保存角色
+     */
+    @ApiOperation("修改保存角色")
+    @PreAuthorize("@ss.hasPermi('system:role:edit')")
+    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    public AjaxResult edit(@Validated @RequestBody StoreRole role)
+    {
+        storeRoleService.checkRoleAllowed(role);
+        if (UserConstants.NOT_UNIQUE.equals(storeRoleService.checkRoleNameUnique(role)))
+        {
+            return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
+        }
+        else if (UserConstants.NOT_UNIQUE.equals(storeRoleService.checkRoleKeyUnique(role)))
+        {
+            return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
+        }
+        role.setUpdateBy(SecurityUtils.getUsername());
+
+        if (storeRoleService.updateRole(role) > 0)
+        {
+            // 更新缓存用户权限
+            ClientLoginStoreUser loginUser = storeTokenService.getLoginUser(ServletUtils.getRequest());
+            if (Validator.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
+            {
+                loginUser.setPermissions(storePermissionService.getMenuPermission(loginUser.getUser()));
+                loginUser.setUser(storeUserService.selectUserByUserName(loginUser.getUser().getUserAccount()));
+                storeTokenService.setLoginUser(loginUser);
+            }
+            return AjaxResult.success();
+        }
+        return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
+    }
+
+    /**
+     * 修改保存数据权限
+     */
+    @ApiOperation("修改保存数据权限")
+    @PostMapping("/dataScope")
+    public AjaxResult dataScope(@RequestBody StoreRole role)
+    {
+        storeRoleService.checkRoleAllowed(role);
+        return toAjax(storeRoleService.authDataScope(role));
+    }
+
+    /**
+     * 状态修改
+     */
+    @ApiOperation("状态修改")
+    @PostMapping("/changeStatus")
+    public AjaxResult changeStatus(@RequestBody StoreRole role)
+    {
+        storeRoleService.checkRoleAllowed(role);
+        role.setUpdateBy(SecurityUtils.getUsername());
+        return toAjax(storeRoleService.updateRoleStatus(role));
+    }
+
+    /**
+     * 删除角色
+     */
+    @ApiOperation("删除角色")
+    @PostMapping("/delete/{roleIds}")
+    public AjaxResult remove(@PathVariable Long[] roleIds)
+    {
+        return toAjax(storeRoleService.deleteRoleByIds(roleIds));
+    }
+
+    /**
+     * 获取角色选择框列表
+     */
+    @ApiOperation("获取角色选择框列表")
+    @GetMapping("/optionselect")
+    public AjaxResult optionselect()
+    {
+        return AjaxResult.success(storeRoleService.selectRoleAll());
+    }
+}

+ 191 - 0
zhongzheng-admin-store/src/main/java/com/zhongzheng/controller/system/StoreUserController.java

@@ -0,0 +1,191 @@
+package com.zhongzheng.controller.system;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.lang.Validator;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.zhongzheng.common.annotation.Log;
+import com.zhongzheng.common.constant.UserConstants;
+import com.zhongzheng.common.core.bo.SysUserEditBo;
+import com.zhongzheng.common.core.controller.BaseController;
+import com.zhongzheng.common.core.domain.AjaxResult;
+import com.zhongzheng.common.core.domain.entity.store.StoreRole;
+import com.zhongzheng.common.core.domain.entity.store.StoreUser;
+import com.zhongzheng.common.core.page.TableDataInfo;
+import com.zhongzheng.common.enums.BusinessType;
+import com.zhongzheng.common.exception.CustomException;
+import com.zhongzheng.common.utils.SecurityUtils;
+import com.zhongzheng.common.utils.ServletUtils;
+import com.zhongzheng.common.utils.ToolsUtils;
+import com.zhongzheng.framework.web.service.StoreTokenService;
+import com.zhongzheng.modules.store.service.IStoreRoleService;
+import com.zhongzheng.modules.store.service.IStoreUserService;
+import com.zhongzheng.modules.user.entity.ClientLoginStoreUser;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 【请填写功能名称】Controller
+ * 
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Api(value = "【请填写功能名称】控制器", tags = {"【请填写功能名称】管理"})
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+@RestController
+@RequestMapping("/store/system/user")
+public class StoreUserController extends BaseController {
+
+    @Autowired
+    private IStoreUserService storeUserService;
+
+    @Autowired
+    private IStoreRoleService storeRoleService;
+
+    @Autowired
+    private StoreTokenService tokenService;
+
+    @Resource
+    private AuthenticationManager authenticationManager;
+
+    /**
+     * 获取用户列表
+     */
+    @ApiOperation("获取用户列表")
+    @GetMapping("/list")
+    public TableDataInfo list(StoreUser user)
+    {
+        startPage();
+        List<StoreUser> list = storeUserService.selectUserList(user);
+        return getDataTable(list);
+    }
+
+    /**
+     * 根据用户编号获取详细信息
+     */
+    @ApiOperation("获取用户详细")
+    @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path")
+    @GetMapping(value = {  "/{userId}" })
+    public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
+    {
+        AjaxResult ajax = AjaxResult.success();
+        List<StoreRole> roles = storeRoleService.selectRoleAll();
+        StoreUser sysUser = storeUserService.selectUserById(userId);
+        ajax.put("roles", sysUser.isAdmin() ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
+        if (Validator.isNotNull(userId))
+        {
+            ajax.put(AjaxResult.DATA_TAG, storeUserService.selectUserById(userId));
+            ajax.put("roleIds", storeRoleService.selectRoleListByUserId(userId));
+        }
+        return ajax;
+    }
+
+    /**
+     * 新增用户
+     */
+    @ApiOperation("新增用户")
+    @ApiOperationSupport(ignoreParameters = {"id","orderDate.id"})
+    @PostMapping
+    public AjaxResult add(@Validated @RequestBody StoreUser user)
+    {
+        if (UserConstants.NOT_UNIQUE.equals(storeUserService.checkUserNameUnique(user.getUserAccount())))
+        {
+            return AjaxResult.error("新增用户'" + user.getUserAccount() + "'失败,登录账号已存在");
+        }
+        else if (Validator.isNotEmpty(user.getTelphone())
+                && UserConstants.NOT_UNIQUE.equals(storeUserService.checkPhoneUnique(user)))
+        {
+            return AjaxResult.error("新增用户'" + user.getUserAccount() + "'失败,手机号码已存在");
+        }
+        if(!ToolsUtils.verifPwd(user.getPassword())){
+            throw new CustomException("密码应由8-16位数字、大小写字母、符号组成");
+        }
+        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
+        return toAjax(storeUserService.insertUser(user));
+    }
+
+    /**
+     * 修改用户
+     */
+    @ApiOperation("更新用户")
+    @PreAuthorize("@ss.hasPermi('system:user:edit')")
+    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    public AjaxResult edit(@Validated @RequestBody SysUserEditBo bo)
+    {
+        if (Validator.isNotEmpty(bo.getStatus())&&bo.getStatus().equals(-1)){
+            StoreUser user = BeanUtil.toBean(bo, StoreUser.class);
+            int result = storeUserService.updateUser(user);
+            return toAjax(result);
+        }
+        StoreUser user = BeanUtil.toBean(bo, StoreUser.class);
+        storeUserService.checkUserAllowed(user);
+        ClientLoginStoreUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if(!loginUser.getUser().isAdmin()&& !loginUser.getUser().getUserId().equals(user.getUserId())){
+            return AjaxResult.error("您无权限修改本信息");
+        }
+
+        if (Validator.isNotEmpty(user.getTelphone())
+                && UserConstants.NOT_UNIQUE.equals(storeUserService.checkPhoneUnique(user)))
+        {
+            return AjaxResult.error("修改用户'" + user.getUserAccount() + "'失败,手机号码已存在");
+        }
+        if(Validator.isNotEmpty(user.getPassword())){
+            //重置密码
+            if(!loginUser.getUser().isAdmin()){
+                //普通用户需传入旧密码修改
+                // 旧密码用户验证
+                Authentication authentication = null;
+                try
+                {
+                    // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
+                    authentication = authenticationManager
+                            .authenticate(new UsernamePasswordAuthenticationToken(loginUser.getUser().getUserAccount(), bo.getOldPassword()));
+                }
+                catch (Exception e)
+                {
+                    return AjaxResult.error("旧密码错误");
+                }
+
+            }
+            if(!ToolsUtils.verifPwd(user.getPassword())){
+                throw new CustomException("密码应由8-16位数字、大小写字母、符号组成");
+            }
+            user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
+        }
+        int result = storeUserService.updateUser(user);
+        if(result>0){
+            StoreUser newUser = storeUserService.selectUserByUserName(loginUser.getUser().getUserAccount());
+            //同个用户ID则更新用户信息,admin操作其他用户则不更新
+            if(newUser.getUserId().equals(loginUser.getUser().getUserId())){
+                // 更新缓存用户
+                loginUser.setUser(newUser);
+            }
+            tokenService.setLoginUser(loginUser);
+        }
+        return toAjax(result);
+    }
+
+    /**
+     * 状态修改
+     */
+    @PutMapping("/changeStatus")
+    public AjaxResult changeStatus(@RequestBody StoreUser user)
+    {
+        storeUserService.checkUserAllowed(user);
+        return toAjax(storeUserService.updateUserStatus(user));
+    }
+    
+}

+ 137 - 0
zhongzheng-admin-store/src/main/java/com/zhongzheng/core/config/SwaggerConfig.java

@@ -0,0 +1,137 @@
+package com.zhongzheng.core.config;
+
+import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
+import com.zhongzheng.common.config.RuoYiConfig;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.ParameterBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.schema.ModelRef;
+import springfox.documentation.service.*;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.contexts.SecurityContext;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Swagger2的接口配置
+ *
+ * @author zhongzheng
+ */
+@Configuration
+@EnableSwagger2WebMvc
+@EnableKnife4j
+public class SwaggerConfig
+{
+    /** 系统基础配置 */
+    @Autowired
+    private RuoYiConfig ruoyiConfig;
+
+    /** 是否开启swagger */
+    @Value("${swagger.enabled}")
+    private boolean enabled;
+
+    /** 设置请求的统一前缀 */
+    @Value("${swagger.pathMapping}")
+    private String pathMapping;
+
+    /**
+     * 创建API
+     */
+    @Bean
+    public Docket createRestApi()
+    {
+        return new Docket(DocumentationType.SWAGGER_2)
+                // 是否启用Swagger
+                .enable(enabled)
+                // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
+                .apiInfo(apiInfo())
+                // 设置哪些接口暴露给Swagger展示
+                .select()
+                // 扫描所有有注解的api,用这种方式更灵活
+                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
+                // 扫描指定包中的swagger注解
+                // .apis(RequestHandlerSelectors.basePackage("com.zhongzheng.project.tool.swagger"))
+                // 扫描所有 .apis(RequestHandlerSelectors.any())
+                .paths(PathSelectors.any())
+                .build()
+                /* 设置安全模式,swagger可以设置访问token */
+                //    .securitySchemes(securitySchemes())
+                .securityContexts(securityContexts())
+                .pathMapping(pathMapping)
+                .globalOperationParameters(getGlobalOperationParameters());
+    }
+
+    /**
+     * 安全模式,这里指定token通过AuthorizationToken头请求头传递
+     */
+    private List<ApiKey> securitySchemes()
+    {
+        List<ApiKey> apiKeyList = new ArrayList<ApiKey>();
+        apiKeyList.add(new ApiKey("AuthorizationToken", "AuthorizationToken", "header"));
+        return apiKeyList;
+    }
+
+    /**
+     * 安全上下文
+     */
+    private List<SecurityContext> securityContexts()
+    {
+        List<SecurityContext> securityContexts = new ArrayList<>();
+        securityContexts.add(
+                SecurityContext.builder()
+                        .securityReferences(defaultAuth())
+                        .forPaths(PathSelectors.regex("^(?!auth).*$"))
+                        .build());
+        return securityContexts;
+    }
+
+    /**
+     * 默认的安全上引用
+     */
+    private List<SecurityReference> defaultAuth()
+    {
+        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
+        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
+        authorizationScopes[0] = authorizationScope;
+        List<SecurityReference> securityReferences = new ArrayList<>();
+        securityReferences.add(new SecurityReference("AuthorizationToken", authorizationScopes));
+        return securityReferences;
+    }
+
+    /**
+     * 添加摘要信息
+     */
+    private ApiInfo apiInfo()
+    {
+        // 用ApiInfoBuilder进行定制
+        return new ApiInfoBuilder()
+                // 设置标题
+                .title("标题:中正SAAS管理系统接口文档")
+                // 描述
+                .description("描述:用于中正SAAS管理系统接口文档")
+                // 作者信息
+                .contact(new Contact(ruoyiConfig.getName(), null, null))
+                // 版本
+                .version("版本号:" + ruoyiConfig.getVersion())
+                .build();
+    }
+
+    private List<Parameter> getGlobalOperationParameters() {
+        List<Parameter> pars = new ArrayList<>();
+        // header query cookie
+        // header query cookie
+        ParameterBuilder parameterBuilder = new ParameterBuilder();
+        parameterBuilder.name("X-Auth-Token").description("token").modelRef(new ModelRef("string")).parameterType("header").defaultValue("test").required(false);
+        pars.add(parameterBuilder.build());
+        return pars;
+    }
+}

+ 1 - 0
zhongzheng-admin-store/src/main/resources/META-INF/spring-devtools.properties

@@ -0,0 +1 @@
+restart.include.json=/com.alibaba.fastjson.*.jar

+ 168 - 0
zhongzheng-admin-store/src/main/resources/application-dev.yml

@@ -0,0 +1,168 @@
+# 数据源配置
+spring:
+    datasource:
+        type: com.alibaba.druid.pool.DruidDataSource
+        driverClassName: com.mysql.cj.jdbc.Driver
+        druid:
+            url: jdbc:mysql://192.168.1.222:3306/zz_edu_saas?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
+            username: root
+            password: zhongzheng2021
+            # 初始连接数
+            initialSize: 5
+            # 最小连接池数量
+            minIdle: 10
+            # 最大连接池数量
+            maxActive: 20
+            # 配置获取连接等待超时的时间
+            maxWait: 60000
+            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+            timeBetweenEvictionRunsMillis: 60000
+            # 配置一个连接在池中最小生存的时间,单位是毫秒
+            minEvictableIdleTimeMillis: 300000
+            # 配置一个连接在池中最大生存的时间,单位是毫秒
+            maxEvictableIdleTimeMillis: 900000
+            # 配置检测连接是否有效
+            validationQuery: SELECT 1 FROM DUAL
+            testWhileIdle: true
+            testOnBorrow: false
+            testOnReturn: false
+            webStatFilter:
+                enabled: true
+            statViewServlet:
+                enabled: true
+                # 设置白名单,不填则允许所有访问
+                allow:
+                url-pattern: /druid/*
+                # 控制台管理用户名和密码
+                login-username: ruoyi
+                login-password: 123456
+            filter:
+                stat:
+                    enabled: true
+                    # 慢SQL记录
+                    log-slow-sql: true
+                    slow-sql-millis: 1000
+                    merge-sql: true
+                wall:
+                    config:
+                        multi-statement-allow: true
+    # redis 配置
+    redis:
+        # 地址
+        host: 192.168.1.222
+        # 端口,默认为6379
+        port: 6379
+        # 数据库索引
+        database: 0
+        # 密码
+        password: zhongzheng2021_redis
+        # 连接超时时间
+        timeout: 10s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 8
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                max-wait: -1ms
+aliyun:
+    oss:
+        endpoint: https://file-dev.xyyxt.net # oss对外服务的访问域名
+        accessKeyId: LTAIgC8O2WUXvXuR  # 访问身份验证中用到用户标识
+        accessKeySecret: 1yyCazuT1M6MruBXzgFjP0p9gdMlwX # 用户用于加密签名字符串和oss用来验证签名字符串的密钥
+        bucketName: zhongzheng-test # oss的存储空间
+        policy:
+            expire: 30 # 签名有效期(S)
+        maxSize: 100 # 上传文件大小(M)
+        callback: http://120.79.166.78:19004/aliyun/oss/callback # 文件上传成功后的回调地址
+        dir:
+            prefix: oss/images/ # 上传文件夹路径前缀 `
+
+poliv:
+    token:
+        userid: d5f6d309fe
+        writetoken: 8f14a371-9d02-4ec1-922d-54d7b4f79dca
+        readtoken: f2c397b4-e2a3-46dc-9266-e6a43ac26a35
+        secretkey: xpPrYdcbA1
+
+wx:
+    small:
+        appid: wxd3c8ae80cf43a305
+        appsecret: 193a001ebfd46f227008a21e9d13e750
+    gzh:
+        appid: wx6f48f721d18244eb
+        appsecret: 2f8b2b4ff66e2f6adfb9f08ae22d7474
+        studyNoteTpId: DndIixcAp15Sqgb4KOGTMf73VLF09NlCUifPSel5Y_s
+        qdyTpId: s981yq3SyIODNUEXFzVSWn0OYj90E72aKdtKtSp05_E
+        qdySubTpId: gzE6zddD7OzDLUtOO4GfU-KPCxpMqWFhCj86uXExqB8
+        qdySubStatusTpId: 7oKaAHmc4P7jqfonuiM1wnjfNLh9T662Ywm1OAFaUFA
+        qdyExamTpId: 66LitnYp0AIWFclo0rLdyLQP4-_vVc4pM95fyFs6l-c
+        qdyExamStatusTpId: J7nNogGhD38OD20gI-3CzwawfEMu7lOjR8fsi4LgJ5g
+        signatureTpId: 66LitnYp0AIWFclo0rLdyLQP4-_vVc4pM95fyFs6l-c
+    wepay:
+        mchid: 1342013901
+        key: GdXyPxYjZx1234123yJzXgDxYpXyjpx9
+        appsecret: GdXyPxYjZx1234123yJzXgDxYpXyjpx9
+        notifyUrl: http://120.79.166.78:19012/wx/pay/callback
+    scanLogin:
+        host: https://testm.xyyxt.net/
+
+wisdomExamRoom:
+    mchid: 10001
+    appid: ZZ-YXT-GZ-20220820-0001
+    app_secret: mt70O1s/Xd5LwuH7yHLpj9R+tKUn5j9vTnCvmgBnbJDA11Hpl7+q4lEZliqPAjN+YHPn9bGmHkAbw5XwhhMiYg==
+    host:  http://bg.sam457.site:9020
+
+certificate:
+    host: http://192.168.1.38:8000/
+
+liveGotoURL: http://120.79.166.78:19014/
+
+enCodeVersion: develop
+
+oldStudySys:
+    syncPath: http://gdxypx.xy.com/System/BussinessApi/PostUserStudyRecords
+    sharePath: http://192.168.1.210:8086/witsystem/dataapi/SaleOrder
+    shareCanclePath: http://192.168.1.210:8086/witsystem/dataapi/ordercance
+    searchGradeCount: http://gdxypx.xy.com/System/BussinessApi/OfficialGradeCount
+    pushGradeCount: http://gdxypx.xy.com/System/BussinessApi/OfficialGradeCountAuto
+    educationalInspector: http://192.168.1.210/EduSystem/BusinessApi/NewYxtUserPrompt
+    classUserListPath: http://gdxypx.xy.com/System/BussinessApi/UserCourseCategoryListcno
+    classOpenPath: http://gdxypx.xy.com/System/BussinessApi/OpenClass
+    salePassword: http://gdxypx.xy.com/WitSystem/BussinessApi/GetSaleInfo
+    updateInvoicePath: http://gdxypx.xy.com/system/BussinessApi/UpdateInvoiceData
+
+officialPush:
+    infoPath: http://jypt-dev.gdcic.net/organjxjy/ShangBaoMingdan
+    periodPath: http://jypt-dev.gdcic.net/organjxjy/XueshiShenqing
+    infoAccount: peixunjigou
+    token: 0ca175b9c0f726a831d895e26933246
+
+distributionOldPay:
+    host: http://gdxypx.xy.com/System/BussinessApi/AddRedPackData
+
+handouts:
+    savePath: http://192.168.1.7:9090/course/handouts/save
+    updatePath: http://192.168.1.7:9090/course/handouts/edit
+
+Nuonuo:
+    host: https://sdk.nuonuo.com/open/v1/services
+    APPkey: SD39149760
+    APPSecret: 07168A248B2844E0
+
+oldOrder:
+    studyRecord: http://gdxypx.xy.com/WitSystem/BussinessApi/GetStudyRecord
+    orderCheck: http://gdxypx.xy.com/WitSystem/BussinessApi/AuditUnderOrder
+    finishOrder: http://gdxypx.xy.com/WitSystem/BussinessApi/CompleteOrder
+    refuseCheck: http://gdxypx.xy.com/WitSystem/BussinessApi/ReFundAuditResult
+    inputOrderSn: http://gdxypx.xy.com/WitSystem/BussinessApi/GetNewYxtinputOrderSn
+    checkOrderStudent: http://gdxypx.xy.com/WitSystem/BussinessApi/ReAuditUnderOrder
+    checkOrderBrokerage: http://gdxypx.xy.com/WitSystem/BussinessApi/CommissionRate
+    refundPay: http://192.168.1.222:5030/common/platform/pay
+    refundPayHandle: http://192.168.1.222:5030/common/platform/pay/handle
+
+oldSys:
+    host: http://gdxypx.xy.com

+ 154 - 0
zhongzheng-admin-store/src/main/resources/application-pre.yml

@@ -0,0 +1,154 @@
+# 数据源配置
+spring:
+    datasource:
+        type: com.alibaba.druid.pool.DruidDataSource
+        driverClassName: com.mysql.cj.jdbc.Driver
+        druid:
+            url: jdbc:mysql://rm-wz950fu2v70864v85.mysql.rds.aliyuncs.com/zz_edu_saas?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
+            username: root
+            password: gdxy2021!@#zzjykj
+            # 初始连接数
+            initialSize: 5
+            # 最小连接池数量
+            minIdle: 10
+            # 最大连接池数量
+            maxActive: 20
+            # 配置获取连接等待超时的时间
+            maxWait: 60000
+            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+            timeBetweenEvictionRunsMillis: 60000
+            # 配置一个连接在池中最小生存的时间,单位是毫秒
+            minEvictableIdleTimeMillis: 300000
+            # 配置一个连接在池中最大生存的时间,单位是毫秒
+            maxEvictableIdleTimeMillis: 900000
+            # 配置检测连接是否有效
+            validationQuery: SELECT 1 FROM DUAL
+            testWhileIdle: true
+            testOnBorrow: false
+            testOnReturn: false
+            webStatFilter:
+                enabled: true
+            statViewServlet:
+                enabled: true
+                # 设置白名单,不填则允许所有访问
+                allow:
+                url-pattern: /druid/*
+                # 控制台管理用户名和密码
+                login-username: ruoyi
+                login-password: 123456
+            filter:
+                stat:
+                    enabled: true
+                    # 慢SQL记录
+                    log-slow-sql: true
+                    slow-sql-millis: 1000
+                    merge-sql: true
+                wall:
+                    config:
+                        multi-statement-allow: true
+    # redis 配置
+    redis:
+        # 地址
+        host: 172.18.19.227
+        # 端口,默认为6379
+        port: 6379
+        # 数据库索引
+        database: 0
+        # 密码
+        password: zhongzheng2021_redis
+        # 连接超时时间
+        timeout: 10s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 8
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                max-wait: -1ms
+aliyun:
+    oss:
+        endpoint: https://file.xyyxt.net # oss对外服务的访问域名
+        accessKeyId: LTAIgC8O2WUXvXuR  # 访问身份验证中用到用户标识
+        accessKeySecret: 1yyCazuT1M6MruBXzgFjP0p9gdMlwX # 用户用于加密签名字符串和oss用来验证签名字符串的密钥
+        bucketName: zhongzheng-prod # oss的存储空间
+        policy:
+            expire: 30 # 签名有效期(S)
+        maxSize: 100 # 上传文件大小(M)
+        callback: https://cloud.xyyxt.net/aliyun/oss/callback # 文件上传成功后的回调地址
+        dir:
+            prefix: oss/images/ # 上传文件夹路径前缀 `
+
+poliv:
+    token:
+        userid: d5f6d309fe
+        writetoken: 8f14a371-9d02-4ec1-922d-54d7b4f79dca
+        readtoken: f2c397b4-e2a3-46dc-9266-e6a43ac26a35
+        secretkey: xpPrYdcbA1
+
+wx:
+    small:
+        appid: wxd3c8ae80cf43a305
+        appsecret: 193a001ebfd46f227008a21e9d13e750
+    gzh:
+        appid: wx6f48f721d18244eb
+        appsecret: 2f8b2b4ff66e2f6adfb9f08ae22d7474
+        studyNoteTpId: DndIixcAp15Sqgb4KOGTMf73VLF09NlCUifPSel5Y_s
+        qdyTpId: s981yq3SyIODNUEXFzVSWn0OYj90E72aKdtKtSp05_E
+        qdySubTpId: gzE6zddD7OzDLUtOO4GfU-KPCxpMqWFhCj86uXExqB8
+        qdySubStatusTpId: 7oKaAHmc4P7jqfonuiM1wnjfNLh9T662Ywm1OAFaUFA
+        qdyExamTpId: 66LitnYp0AIWFclo0rLdyLQP4-_vVc4pM95fyFs6l-c
+        qdyExamStatusTpId: J7nNogGhD38OD20gI-3CzwawfEMu7lOjR8fsi4LgJ5g
+        signatureTpId: 66LitnYp0AIWFclo0rLdyLQP4-_vVc4pM95fyFs6l-c
+    wepay:
+        mchid: 1342013901
+        key: GdXyPxYjZx1234123yJzXgDxYpXyjpx9
+        appsecret: GdXyPxYjZx1234123yJzXgDxYpXyjpx9
+        notifyUrl: https://api.xyyxt.net/wx/pay/callback
+    scanLogin:
+        host: https://m.xyyxt.net/
+
+wisdomExamRoom:
+    mchid: 10001
+    appid: ZZ-YXT-GZ-20220820-0001
+    app_secret: mt70O1s/Xd5LwuH7yHLpj9R+tKUn5j9vTnCvmgBnbJDA11Hpl7+q4lEZliqPAjN+YHPn9bGmHkAbw5XwhhMiYg==
+    host: http://bg.sam457.site:9020
+
+certificate:
+    host: https://m.xyyxt.net/
+
+liveGotoURL: https://
+
+enCodeVersion: release
+
+oldStudySys:
+    syncPath: https://www.xyyxt.net/System/BussinessApi/PostUserStudyRecords
+    sharePath: https://www.xyyxt.net/witsystem/dataapi/SaleOrder
+    shareCanclePath: https://www.xyyxt.net/witsystem/dataapi/ordercance
+    searchGradeCount: https://www.xyyxt.net/System/BussinessApi/OfficialGradeCount
+    pushGradeCount: https://www.xyyxt.net/System/BussinessApi/OfficialGradeCountAuto
+    educationalInspector: https://zs.gdzzkj.net/EduSystem/BusinessApi/NewYxtUserPrompt
+    classUserListPath: https://www.xyyxt.net/System/BussinessApi/UserCourseCategoryListcno
+    classOpenPath: https://www.xyyxt.net/System/BussinessApi/OpenClass
+    salePassword: http://www.xyyxt.net/WitSystem/BussinessApi/GetSaleInfo
+    updateInvoicePath: http://gdxypx.xy.com/system/BussinessApi/UpdateInvoiceData
+
+officialPush:
+    infoPath: https://jypt.gdcic.net/organjxjy/ShangBaoMingdan
+    periodPath: https://jypt.gdcic.net/organjxjy/XueshiShenqing
+    infoAccount: GDSXY
+    token: 01b5d9833987efdff54483cdc9720da6
+
+distributionOldPay:
+    host: https://www.xyyxt.net/System/BussinessApi/AddRedPackData
+
+handouts:
+    savePath: https://attach.xyyxt.net/course/handouts/save
+    updatePath: https://attach.xyyxt.net/course/handouts/edit
+
+Nuonuo:
+    host: https://sdk.nuonuo.com/open/v1/services
+    APPkey: 39149760
+    APPSecret: 07168A248B2844E0

+ 157 - 0
zhongzheng-admin-store/src/main/resources/application-prod.yml

@@ -0,0 +1,157 @@
+# 数据源配置
+spring:
+    datasource:
+        type: com.alibaba.druid.pool.DruidDataSource
+        driverClassName: com.mysql.cj.jdbc.Driver
+        druid:
+            url: jdbc:mysql://rm-wz950fu2v70864v85.mysql.rds.aliyuncs.com/zz_edu_saas?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
+            username: root
+            password: gdxy2021!@#zzjykj
+            # 初始连接数
+            initialSize: 5
+            # 最小连接池数量
+            minIdle: 10
+            # 最大连接池数量
+            maxActive: 20
+            # 配置获取连接等待超时的时间
+            maxWait: 60000
+            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+            timeBetweenEvictionRunsMillis: 60000
+            # 配置一个连接在池中最小生存的时间,单位是毫秒
+            minEvictableIdleTimeMillis: 300000
+            # 配置一个连接在池中最大生存的时间,单位是毫秒
+            maxEvictableIdleTimeMillis: 900000
+            # 配置检测连接是否有效
+            validationQuery: SELECT 1 FROM DUAL
+            testWhileIdle: true
+            testOnBorrow: false
+            testOnReturn: false
+            webStatFilter:
+                enabled: true
+            statViewServlet:
+                enabled: true
+                # 设置白名单,不填则允许所有访问
+                allow:
+                url-pattern: /druid/*
+                # 控制台管理用户名和密码
+                login-username: ruoyi
+                login-password: 123456
+            filter:
+                stat:
+                    enabled: true
+                    # 慢SQL记录
+                    log-slow-sql: true
+                    slow-sql-millis: 1000
+                    merge-sql: true
+                wall:
+                    config:
+                        multi-statement-allow: true
+    # redis 配置
+    redis:
+        # 地址
+        host: 172.18.19.227
+        # 端口,默认为6379
+        port: 6379
+        # 数据库索引
+        database: 0
+        # 密码
+        password: zhongzheng2021_redis
+        # 连接超时时间
+        timeout: 10s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 8
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                max-wait: -1ms
+aliyun:
+    oss:
+        endpoint: https://file.xyyxt.net # oss对外服务的访问域名
+        accessKeyId: LTAIgC8O2WUXvXuR  # 访问身份验证中用到用户标识
+        accessKeySecret: 1yyCazuT1M6MruBXzgFjP0p9gdMlwX # 用户用于加密签名字符串和oss用来验证签名字符串的密钥
+        bucketName: zhongzheng-prod # oss的存储空间
+        policy:
+            expire: 30 # 签名有效期(S)
+        maxSize: 100 # 上传文件大小(M)
+        callback: https://cloud.xyyxt.net/aliyun/oss/callback # 文件上传成功后的回调地址
+        dir:
+            prefix: oss/images/ # 上传文件夹路径前缀 `
+
+poliv:
+    token:
+        userid: d5f6d309fe
+        writetoken: 8f14a371-9d02-4ec1-922d-54d7b4f79dca
+        readtoken: f2c397b4-e2a3-46dc-9266-e6a43ac26a35
+        secretkey: xpPrYdcbA1
+
+wx:
+    small:
+        appid: wxd3c8ae80cf43a305
+        appsecret: 193a001ebfd46f227008a21e9d13e750
+    gzh:
+        appid: wx6f48f721d18244eb
+        appsecret: 2f8b2b4ff66e2f6adfb9f08ae22d7474
+        studyNoteTpId: DndIixcAp15Sqgb4KOGTMf73VLF09NlCUifPSel5Y_s
+        qdyTpId: s981yq3SyIODNUEXFzVSWn0OYj90E72aKdtKtSp05_E
+        qdySubTpId: gzE6zddD7OzDLUtOO4GfU-KPCxpMqWFhCj86uXExqB8
+        qdySubStatusTpId: 7oKaAHmc4P7jqfonuiM1wnjfNLh9T662Ywm1OAFaUFA
+        qdyExamTpId: 66LitnYp0AIWFclo0rLdyLQP4-_vVc4pM95fyFs6l-c
+        qdyExamStatusTpId: J7nNogGhD38OD20gI-3CzwawfEMu7lOjR8fsi4LgJ5g
+        signatureTpId: 66LitnYp0AIWFclo0rLdyLQP4-_vVc4pM95fyFs6l-c
+    wepay:
+        mchid: 1342013901
+        key: GdXyPxYjZx1234123yJzXgDxYpXyjpx9
+        appsecret: GdXyPxYjZx1234123yJzXgDxYpXyjpx9
+        notifyUrl: https://api.xyyxt.net/wx/pay/callback
+    scanLogin:
+        host: https://m.xyyxt.net/
+
+wisdomExamRoom:
+    mchid: 10001
+    appid: ZZ-YXT-GZ-20220820-0001
+    app_secret: mt70O1s/Xd5LwuH7yHLpj9R+tKUn5j9vTnCvmgBnbJDA11Hpl7+q4lEZliqPAjN+YHPn9bGmHkAbw5XwhhMiYg==
+    host: http://bg.sam457.site:9020
+
+certificate:
+    host: https://m.xyyxt.net/
+
+liveGotoURL: https://
+
+enCodeVersion: release
+
+oldStudySys:
+    syncPath: https://www.xyyxt.net/System/BussinessApi/PostUserStudyRecords
+    sharePath: https://www.xyyxt.net/witsystem/dataapi/SaleOrder
+    shareCanclePath: https://www.xyyxt.net/witsystem/dataapi/ordercance
+    searchGradeCount: https://www.xyyxt.net/System/BussinessApi/OfficialGradeCount
+    pushGradeCount: https://www.xyyxt.net/System/BussinessApi/OfficialGradeCountAuto
+    educationalInspector: https://zs.gdzzkj.net/EduSystem/BusinessApi/NewYxtUserPrompt
+    classUserListPath: https://www.xyyxt.net/System/BussinessApi/UserCourseCategoryListcno
+    classOpenPath: https://www.xyyxt.net/System/BussinessApi/OpenClass
+    salePassword: http://www.xyyxt.net/WitSystem/BussinessApi/GetSaleInfo
+    updateInvoicePath: http://www.xyyxt.net/system/BussinessApi/UpdateInvoiceData
+
+officialPush:
+    infoPath: https://jypt.gdcic.net/organjxjy/ShangBaoMingdan
+    periodPath: https://jypt.gdcic.net/organjxjy/XueshiShenqing
+    infoAccount: GDSXY
+    token: 01b5d9833987efdff54483cdc9720da6
+
+distributionOldPay:
+    host: https://www.xyyxt.net/System/BussinessApi/AddRedPackData
+
+handouts:
+    savePath: https://attach.xyyxt.net/course/handouts/save
+    updatePath: https://attach.xyyxt.net/course/handouts/edit
+
+Nuonuo:
+    host: https://sdk.nuonuo.com/open/v1/services
+    APPkey: 39149760
+    APPSecret: 07168A248B2844E0
+
+oldSys:
+    host: https://www.xyyxt.net

+ 308 - 0
zhongzheng-admin-store/src/main/resources/application.yml

@@ -0,0 +1,308 @@
+# 项目相关配置
+zhongzheng:
+  # 名称
+  name: zhongzheng_store
+  # 版本
+  version: 3.4.0
+  # 版权年份
+  copyrightYear: 2021
+  # 实例演示开关
+  demoEnabled: true
+  # 文件路径,使用jvm系统变量,兼容windows和linux;
+  profile: ${user.dir}/zhongzheng/uploadPath
+  # 获取ip地址开关
+  addressEnabled: false
+
+captcha:
+  # 验证码类型 math 数组计算 char 字符验证
+  captchaType: math
+  # line 线段干扰 circle 圆圈干扰 shear 扭曲干扰
+  captchaCategory: circle
+  # 数字验证码位数
+  captchaNumberLength: 1
+  # 字符验证码长度
+  captchaCharLength: 4
+
+# 开发环境配置
+server:
+  # 服务器的HTTP端口,默认为8080
+  port: 7088
+  servlet:
+    # 应用的访问路径
+    context-path: /
+  # undertow 配置
+  undertow:
+    # HTTP post内容的最大大小。当值为-1时,默认值为大小是无限的
+    max-http-post-size: -1
+    # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
+    # 每块buffer的空间大小,越小的空间被利用越充分
+    buffer-size: 512
+    # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
+    io-threads: 8
+    # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
+    worker-threads: 256
+    # 是否分配的直接内存
+    direct-buffers: true
+#  # tomcat 配置
+#  tomcat:
+#    # tomcat的URI编码
+#    uri-encoding: UTF-8
+#    # tomcat最大线程数,默认为200
+#    max-threads: 500
+#    # Tomcat启动初始化的线程数,默认值25
+#    min-spare-threads: 30
+
+# 日志配置
+logging:
+  level:
+    com.zhongzheng: @logging.level@
+    org.springframework: warn
+  config: classpath:logback.xml
+
+# Spring配置
+spring:
+  mvc:
+    async:
+      request-timeout: 30000
+  main:
+    allow-bean-definition-overriding: true
+  # 资源信息
+  messages:
+    # 国际化资源文件路径
+    basename: i18n/messages
+  profiles:
+    active: @profiles.active@
+  # 文件上传
+  servlet:
+    multipart:
+      # 单个文件大小
+      max-file-size:  10MB
+      # 设置总上传的文件大小
+      max-request-size:  20MB
+  # 服务模块
+  devtools:
+    restart:
+      # 热部署开关
+      enabled: true
+  application:
+    name: zz_edu
+  boot:
+    admin:
+      # Spring Boot Admin Client 客户端的相关配置
+      client:
+        # 设置 Spring Boot Admin Server 地址
+        url: http://localhost:${server.port}${spring.boot.admin.context-path}
+        instance:
+          prefer-ip: true # 注册实例时,优先使用 IP
+      # Spring Boot Admin Server 服务端的相关配置
+      context-path: /admin # 配置 Spring
+
+# Actuator 监控端点的配置项
+management:
+  endpoints:
+    web:
+      # Actuator 提供的 API 接口的根目录。默认为 /actuator
+      base-path: /actuator
+      exposure:
+        # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
+        include: '*'
+  endpoint:
+    logfile:
+      external-file: ./logs/sys-console.log
+
+# token配置
+token:
+  # 令牌自定义标识
+  header: AuthorizationToken
+  # 令牌密钥
+  secret: abcdefghijklmnopqrstuvwxyz
+  # 令牌有效期(默认30分钟)
+  expireTime: 360
+
+# MyBatis配置
+# https://baomidou.com/config/
+mybatis-plus:
+  # 对应的 XML 文件位置
+  mapperLocations: classpath*:mapper/**/*Mapper.xml
+  # 实体扫描,多个package用逗号或者分号分隔
+  typeAliasesPackage: com.zhongzheng.**.domain
+  # 针对 typeAliasesPackage,如果配置了该属性,则仅仅会扫描路径下以该类作为父类的域对象
+  #typeAliasesSuperType: Class<?>
+  # 如果配置了该属性,SqlSessionFactoryBean 会把该包下面的类注册为对应的 TypeHandler
+  #typeHandlersPackage: null
+  # 如果配置了该属性,会将路径下的枚举类进行注入,让实体类字段能够简单快捷的使用枚举属性
+  #typeEnumsPackage: null
+  # 启动时是否检查 MyBatis XML 文件的存在,默认不检查
+  checkConfigLocation: false
+  # 通过该属性可指定 MyBatis 的执行器,MyBatis 的执行器总共有三种:
+  # SIMPLE:该执行器类型不做特殊的事情,为每个语句的执行创建一个新的预处理语句(PreparedStatement)
+  # REUSE:该执行器类型会复用预处理语句(PreparedStatement)
+  # BATCH:该执行器类型会批量执行所有的更新语句
+  executorType: SIMPLE
+  # 指定外部化 MyBatis Properties 配置,通过该配置可以抽离配置,实现不同环境的配置部署
+  configurationProperties: null
+  typeHandlersPackage: com.zhongzheng.common.type
+  configuration:
+    # 自动驼峰命名规则(camel case)映射
+    # 如果您的数据库命名符合规则无需使用 @TableField 注解指定数据库字段名
+    mapUnderscoreToCamelCase: true
+    # 默认枚举处理类,如果配置了该属性,枚举将统一使用指定处理器进行处理
+    # org.apache.ibatis.type.EnumTypeHandler : 存储枚举的名称
+    # org.apache.ibatis.type.EnumOrdinalTypeHandler : 存储枚举的索引
+    # com.baomidou.mybatisplus.extension.handlers.MybatisEnumTypeHandler : 枚举类需要实现IEnum接口或字段标记@EnumValue注解.
+    defaultEnumTypeHandler: org.apache.ibatis.type.EnumTypeHandler
+    # 当设置为 true 的时候,懒加载的对象可能被任何懒属性全部加载,否则,每个属性都按需加载。需要和 lazyLoadingEnabled 一起使用。
+    aggressiveLazyLoading: true
+    # MyBatis 自动映射策略
+    # NONE:不启用自动映射
+    # PARTIAL:只对非嵌套的 resultMap 进行自动映射
+    # FULL:对所有的 resultMap 都进行自动映射
+    autoMappingBehavior: PARTIAL
+    # MyBatis 自动映射时未知列或未知属性处理策
+    # NONE:不做任何处理 (默认值)
+    # WARNING:以日志的形式打印相关警告信息
+    # FAILING:当作映射失败处理,并抛出异常和详细信息
+    autoMappingUnknownColumnBehavior: NONE
+    # Mybatis一级缓存,默认为 SESSION
+    # SESSION session级别缓存,同一个session相同查询语句不会再次查询数据库
+    # STATEMENT 关闭一级缓存
+    localCacheScope: SESSION
+    # 开启Mybatis二级缓存,默认为 true
+    cacheEnabled: true
+  global-config:
+    # 是否打印 Logo banner
+    banner: true
+    # 是否初始化 SqlRunner
+    enableSqlRunner: false
+    dbConfig:
+      # 主键类型
+      # AUTO 数据库ID自增
+      # NONE 空
+      # INPUT 用户输入ID
+      # ASSIGN_ID 全局唯一ID
+      # ASSIGN_UUID 全局唯一ID UUID
+      idType: AUTO
+      # 表名前缀
+      tablePrefix: null
+      # 字段 format,例: %s,(对主键无效)
+      columnFormat: null
+      # 表名是否使用驼峰转下划线命名,只对表名生效
+      tableUnderline: true
+      # 大写命名,对表名和字段名均生效
+      capitalMode: false
+      # 全局的entity的逻辑删除字段属性名
+      logicDeleteField: null
+      # 逻辑已删除值
+      logicDeleteValue: 2
+      # 逻辑未删除值
+      logicNotDeleteValue: 0
+      # 字段验证策略之 insert,在 insert 的时候的字段验证策略
+      # IGNORED 忽略判断
+      # NOT_NULL 非NULL判断
+      # NOT_EMPTY 非空判断(只对字符串类型字段,其他类型字段依然为非NULL判断)
+      # DEFAULT 默认的,一般只用于注解里
+      # NEVER 不加入 SQL
+      insertStrategy: NOT_EMPTY
+      # 字段验证策略之 update,在 update 的时候的字段验证策略
+      updateStrategy: NOT_EMPTY
+      # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
+      selectStrategy: NOT_EMPTY
+  # 开启多租户
+  tenant:
+    enabled-tenant: 3
+# PageHelper分页插件
+pagehelper:
+  helperDialect: mysql
+  reasonable: true
+  supportMethodsArguments: true
+  params: count=countSql
+# Swagger配置
+swagger:
+  # 是否开启swagger
+  enabled: true
+  # 请求前缀
+  pathMapping:
+knife4j:
+  enable: true
+  setting:
+    enableFooter: false
+
+# 防止XSS攻击
+xss:
+  # 过滤开关
+  enabled: true
+  # 排除链接(多个用逗号分隔)
+  excludes: /system/notice/*
+  # 匹配链接
+  urlPatterns: /system/*,/monitor/*,/tool/*
+
+feign:
+  # 开启压缩
+  compression:
+    request:
+      enabled: true
+    response:
+      enabled: true
+  okhttp:
+    enabled: true
+  hystrix:
+    enabled: true
+
+poliv:
+  sdk:
+    userid: egsxlptzdq
+    appId: ezl5uy4zei
+    appSecret: 2bf5bb3c31d34531943df10284edd50b
+
+tencent:
+  cloud:
+    SecretId: AKIDd6XkjTw9D1atwkJceS2NSIuHPK1ThfOr
+    SecretKey: GG2ZqrdCWcS6Yx72h6F7k7E4ey2qPnwq
+
+aliyun:
+  sms:
+    signName: 祥粤学校
+    registerTemplateCode: SMS_228670004
+    loginTemplateCode: SMS_228670005
+    forgetTemplateCode: SMS_228685033
+    pwdTemplateCode: SMS_230220381
+    bindNewTelCode: SMS_232178371
+    accessKeyId: LTAIgC8O2WUXvXuR
+    accessKeySecret: 1yyCazuT1M6MruBXzgFjP0p9gdMlwX
+    OpenTheGoodsCode: SMS_230970155     #商品开通提醒
+    informationNotificationCode: SMS_230965149  #完善报名资料通知
+    materialReviewCode: SMS_230980165         #报名资料审核通过通知
+    NotificationOfFailureCode: SMS_230980172  #报名资料审核不通过通知
+    remainingDaysValidityCode: SMS_236566823  #开通班级有效期还剩天数
+    completionReminderCode: SMS_230965157   #学时学习完成提醒
+    schoolHoursCode: SMS_230970166    #学时机构审核通过提醒
+    auditFailedCode: SMS_230970167  #学时机构审核不通过提醒
+    ReminderApproval: SMS_231200314 #学时机构审核通过提醒
+    passTheReminder: SMS_230980180  #学时机构审核不通过提醒
+    bookingReminder: SMS_230980181  #考试预约提醒
+    cancellationReminder: SMS_230980183 #考试预约取消提醒
+    reservationSuccess: SMS_230980186 #考试预约成功提醒
+    examinationRemind: SMS_230960195  #考试提醒
+    newExamPass: SMS_230970179  #七大员新考考试通过提醒
+    newExamFail: SMS_235491082  #七大员新考考试不通过提醒
+    openingReminder: SMS_230970209  #七大员题库开通提醒(12-22
+    classRemind: SMS_230965224  #二建继教开班提醒
+    OverdueReminder: SMS_230980259  #班级过期提醒
+    OverdueReminderHave: SMS_230965228  #班级过期提醒有学习次数
+    planReminder: SMS_230970248     #学习计划提醒
+    commitmentCode: SMS_231190546     #承诺书审核通过通知
+    commitmentFailsCode: SMS_231215516     #承诺书审核不通过通知
+    mockBookingReminder: SMS_243430276     #模考预约提醒
+    mockRemind: SMS_243355276      #模考开始提醒
+    liveStartRemind: SMS_243345514      #直播开课提醒
+    buyNotStudyStudentRemind : SMS_247745294  #学生购买未学习
+    buyNotStudyTeacherRemind : SMS_247935257  #学生购买未学习老师
+    longNotStudyStudentRemind: SMS_247910221  #学生长时间未学习
+    longNotStudyTeacherRemind: SMS_247765294  #学生长时间未学习老师
+    signCommitmentRemind: SMS_250390195  #签署承诺书提醒
+    todayExamNotRecordWarn: SMS_257713140  #学员打卡提醒(每日一练)
+    todayExamNotRecordTeachWarn: SMS_257702971  #学员打卡教务提醒(每日一练)
+    noFinishExamNoteCode: SMS_262460267  #未做完试卷通知
+
+distributionOldPay:
+      host: http://test.jqbao.net/System/BussinessApi/AddRedPackData

+ 2 - 0
zhongzheng-admin-store/src/main/resources/banner.txt

@@ -0,0 +1,2 @@
+Application Version: ${zhongzheng.version}
+Spring Boot Version: ${spring-boot.version}

+ 36 - 0
zhongzheng-admin-store/src/main/resources/i18n/messages.properties

@@ -0,0 +1,36 @@
+#错误消息
+not.null=* 必须填写
+user.jcaptcha.error=验证码错误
+user.jcaptcha.expire=验证码已失效
+user.not.exists=用户不存在/密码错误
+user.password.not.match=用户不存在/密码错误
+user.password.retry.limit.count=密码输入错误{0}次
+user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定10分钟
+user.password.delete=对不起,您的账号已被删除
+user.blocked=用户已封禁,请联系管理员
+role.blocked=角色已封禁,请联系管理员
+user.logout.success=退出成功
+
+length.not.valid=长度必须在{min}到{max}个字符之间
+
+user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
+user.password.not.valid=* 5-50个字符
+ 
+user.email.not.valid=邮箱格式错误
+user.mobile.phone.number.not.valid=手机号格式错误
+user.login.success=登录成功
+user.notfound=请重新登录
+user.forcelogout=管理员强制退出,请重新登录
+user.unknown.error=未知错误,请重新登录
+
+##文件上传消息
+upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB!
+upload.filename.exceed.length=上传的文件名最长{0}个字符
+
+##权限
+no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
+no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
+no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
+no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
+no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
+no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]

+ 108 - 0
zhongzheng-admin-store/src/main/resources/logback.xml

@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <property name="log.path" value="./logs"/>
+    <property name="console.log.pattern"
+              value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
+    <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
+
+    <!-- 控制台输出 -->
+    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>${console.log.pattern}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+    </appender>
+
+    <!-- 控制台输出 -->
+    <appender name="file_console" class="ch.qos.logback.core.FileAppender">
+        <file>${log.path}/sys-console.log</file>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <!-- 过滤的级别 -->
+            <level>INFO</level>
+        </filter>
+    </appender>
+
+    <!-- 系统日志输出 -->
+    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${log.path}/sys-info.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>INFO</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${log.path}/sys-error.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>ERROR</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!-- 用户访问日志输出  -->
+    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${log.path}/sys-user.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+    </appender>
+
+    <!-- 系统模块日志级别控制  -->
+    <logger name="com.zhongzheng" level="info" />
+    <!-- Spring日志级别控制  -->
+    <logger name="org.springframework" level="warn" />
+
+    <root level="info">
+        <appender-ref ref="console" />
+    </root>
+
+    <!--系统操作日志-->
+    <root level="info">
+        <appender-ref ref="file_info" />
+        <appender-ref ref="file_error" />
+        <appender-ref ref="file_console" />
+    </root>
+
+    <!--系统用户操作日志-->
+    <logger name="sys-user" level="info">
+        <appender-ref ref="sys-user"/>
+    </logger>
+</configuration>

+ 0 - 0
zhongzheng-admin-store/src/main/resources/mybatis/mybatis-config.xml


+ 1 - 1
zhongzheng-admin/src/main/resources/application.yml

@@ -209,7 +209,7 @@ mybatis-plus:
       selectStrategy: NOT_EMPTY
   # 开启多租户
   tenant:
-    enabled-tenant: true
+    enabled-tenant: 1
 # PageHelper分页插件
 pagehelper:
   helperDialect: mysql

+ 1 - 1
zhongzheng-api/src/main/resources/application.yml

@@ -206,7 +206,7 @@ mybatis-plus:
       selectStrategy: NOT_EMPTY
   # 开启多租户
   tenant:
-    enabled-tenant: true
+    enabled-tenant: 1
 # PageHelper分页插件
 pagehelper:
   helperDialect: mysql

+ 12 - 0
zhongzheng-common/src/main/java/com/zhongzheng/common/constant/Constants.java

@@ -64,6 +64,11 @@ public class Constants
 
     public static final String WX_LOGIN_TOKEN_KEY = "wx_login_tokens:";
 
+    /**
+     * 核销系统登录用户 redis key
+     */
+    public static final String STORE_LOGIN_TOKEN_KEY = "store_login_tokens:";
+
 
     /**
      * 防重提交 redis key
@@ -97,6 +102,11 @@ public class Constants
      */
     public static final String WX_TOKEN_PREFIX = "WX ";
 
+    /**
+     * 核销系统令牌前缀
+     */
+    public static final String STORE_TOKEN_PREFIX = "Store ";
+
 
     public static final String REGISTER_SMS = "REGISTER-";
     public static final String FORGET_SMS = "FORGET-";
@@ -112,6 +122,8 @@ public class Constants
 
     public static final String WX_LOGIN_USER_KEY = "wx_login_user_key";
 
+    public static final String STORE_LOGIN_USER_KEY = "store_login_user_key";
+
 
 
 

+ 81 - 0
zhongzheng-common/src/main/java/com/zhongzheng/common/core/domain/entity/store/StoreMenu.java

@@ -0,0 +1,81 @@
+package com.zhongzheng.common.core.domain.entity.store;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * 【请填写功能名称】对象 store_menu
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("store_menu")
+public class StoreMenu implements Serializable {
+
+private static final long serialVersionUID=1L;
+
+    /** 菜单ID */
+    @TableId(value = "menu_id")
+    private Long menuId;
+    /** 菜单名称 */
+    private String menuName;
+    /** 父菜单ID */
+    private Long parentId;
+    /** 显示顺序 */
+    private Long orderNum;
+    /** 路由地址 */
+    private String path;
+    /** 组件路径 */
+    private String component;
+    /** 是否为外链(0是 1否) */
+    private Long isFrame;
+    /** 是否缓存(0缓存 1不缓存) */
+    private Long isCache;
+    /** 菜单类型(M目录 C菜单 F按钮) */
+    private String menuType;
+    /** 菜单状态(1显示 0隐藏) */
+    private String visible;
+    /** 菜单状态(1正常 0停用) */
+    private String status;
+    /** 权限标识 */
+    private String perms;
+    /** 菜单图标 */
+    private String icon;
+    /** 创建者 */
+    @TableField(fill = FieldFill.INSERT)
+    private String createBy;
+    /** 创建时间 */
+    @TableField(fill = FieldFill.INSERT)
+    private Date createTime;
+    /** 更新者 */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private String updateBy;
+    /** 更新时间 */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Date updateTime;
+    /** 备注 */
+    private String remark;
+    /** 店铺ID */
+    private Long storeId;
+    /** 商户ID */
+    private Long companyId;
+
+    /** 请求参数 */
+    @TableField(exist = false)
+    private Map<String, Object> params = new HashMap<>();
+
+    /** 子菜单 */
+    @TableField(exist = false)
+    private List<StoreMenu> children = new ArrayList<StoreMenu>();
+}

+ 110 - 0
zhongzheng-common/src/main/java/com/zhongzheng/common/core/domain/entity/store/StoreRole.java

@@ -0,0 +1,110 @@
+package com.zhongzheng.common.core.domain.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import org.springframework.beans.factory.annotation.Value;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 【请填写功能名称】对象 store_role
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("store_role")
+public class StoreRole implements Serializable {
+
+private static final long serialVersionUID=1L;
+
+    /** 角色ID */
+    @TableId(value = "role_id")
+    private Long roleId;
+    /** 角色名称 */
+    private String roleName;
+    /** 角色权限字符串 */
+    private String roleKey;
+    /** 显示顺序 */
+    private Long roleSort;
+    /** 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:本人数据权限 6业务层次数据权限) */
+    private String dataScope;
+    /** 部门树选择项是否关联显示 */
+    private Integer deptCheckStrictly;
+    /** 角色状态(1正常 0停用) */
+    private String status;
+    /** 删除标志(0代表存在 2代表删除) */
+    @TableLogic
+    private String delFlag;
+    /** 创建者 */
+    @TableField(fill = FieldFill.INSERT)
+    private String createBy;
+    /** 创建时间 */
+    @TableField(fill = FieldFill.INSERT)
+    private Date createTime;
+    /** 更新者 */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private String updateBy;
+    /** 更新时间 */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Date updateTime;
+    /** 备注 */
+    private String remark;
+    /** 店铺ID */
+    private Long storeId;
+    /** 商户ID */
+    private Long companyId;
+
+    @Value("true")
+    /** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */
+    private boolean menuCheckStrictly;
+
+    /**
+     * 请求参数
+     */
+    @TableField(exist = false)
+    private Map<String, Object> params = new HashMap<>();
+
+    /** 用户是否存在此角色标识 默认不存在 */
+    @TableField(exist = false)
+    private boolean flag = false;
+
+    /** 菜单组 */
+    @ApiModelProperty(value ="菜单数组")
+    @TableField(exist = false)
+    private Long[] menuIds;
+
+
+
+    /** 部门组(数据权限) */
+    @TableField(exist = false)
+    private Long[] deptIds;
+
+    @TableField(exist = false)
+    private List<String> statusArray;
+
+
+    public StoreRole(Long roleId)
+    {
+        this.roleId = roleId;
+    }
+
+    public boolean isAdmin()
+    {
+        return isAdmin(this.roleId);
+    }
+
+    public static boolean isAdmin(Long roleId)
+    {
+        return roleId != null && 1L == roleId;
+    }
+}

+ 32 - 0
zhongzheng-common/src/main/java/com/zhongzheng/common/core/domain/entity/store/StoreRoleMenu.java

@@ -0,0 +1,32 @@
+package com.zhongzheng.common.core.domain.entity.store;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * 【请填写功能名称】对象 store_role_menu
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("store_role_menu")
+public class StoreRoleMenu implements Serializable {
+
+private static final long serialVersionUID=1L;
+
+    /** 角色ID */
+    private Long roleId;
+    /** 菜单ID */
+    private Long menuId;
+    /** 店铺ID */
+    private Long storeId;
+    /** 商户ID */
+    private Long companyId;
+}

+ 87 - 0
zhongzheng-common/src/main/java/com/zhongzheng/common/core/domain/entity/store/StoreUser.java

@@ -0,0 +1,87 @@
+package com.zhongzheng.common.core.domain.entity.store;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 【请填写功能名称】对象 store_user
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("store_user")
+public class StoreUser implements Serializable {
+
+private static final long serialVersionUID=1L;
+
+    /** $column.columnComment */
+    @TableId(value = "user_id")
+    private Long userId;
+    /** 账号 */
+    private String userAccount;
+    /** 昵称 */
+    private String nickname;
+    /** 真实姓名 */
+    private String realname;
+    /** 性别 1男 2女 */
+    private Integer sex;
+    /** 身份证号 */
+    private String idCard;
+    /** 手机号码 */
+    private String telphone;
+    /** 微信openid */
+    private String openId;
+    /** 微信unionId */
+    private String unionId;
+    /** 公众号openid */
+    private String gzhOpenId;
+    /** 密码 */
+    private String password;
+    /** 添加时间 */
+    @TableField(fill = FieldFill.INSERT)
+    private Long createTime;
+    /** 修改时间 */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateTime;
+    /** 状态 1正常 0关闭 */
+    private Integer status;
+    /** 店铺ID */
+    private Long storeId;
+    /** 商户ID */
+    private Long companyId;
+
+    private Integer administrator;
+
+    private String delFlag;
+
+    /** 角色组 */
+    @TableField(exist = false)
+    private List<Long> roleIds;
+
+    /** 角色对象 */
+    @TableField(exist = false)
+    private List<StoreRole> roles;
+
+    public StoreUser(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public boolean isAdmin()
+    {
+        return this.administrator != 0;
+    }
+
+
+}

+ 34 - 0
zhongzheng-common/src/main/java/com/zhongzheng/common/core/domain/entity/store/StoreUserRole.java

@@ -0,0 +1,34 @@
+package com.zhongzheng.common.core.domain.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import java.io.Serializable;
+import java.util.Date;
+import java.math.BigDecimal;
+import com.zhongzheng.common.annotation.Excel;
+
+/**
+ * 【请填写功能名称】对象 store_user_role
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("store_user_role")
+public class StoreUserRole implements Serializable {
+
+private static final long serialVersionUID=1L;
+
+    /** 用户ID */
+    private Long userId;
+    /** 角色ID */
+    private Long roleId;
+    /** 店铺ID */
+    private Long storeId;
+    /** 商户ID */
+    private Long companyId;
+}

+ 143 - 0
zhongzheng-common/src/main/java/com/zhongzheng/common/core/domain/model/StoreLoginUser.java

@@ -0,0 +1,143 @@
+package com.zhongzheng.common.core.domain.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.zhongzheng.common.core.domain.entity.store.StoreUser;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * 登录用户身份权限
+ *
+ * @author zhongzheng
+ */
+
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+public class StoreLoginUser implements UserDetails
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 用户唯一标识
+     */
+    private String token;
+
+    /**
+     * 登录时间
+     */
+    private Long loginTime;
+
+    /**
+     * 过期时间
+     */
+    private Long expireTime;
+
+    /**
+     * 登录IP地址
+     */
+    private String ipaddr;
+
+    /**
+     * 登录地点
+     */
+    private String loginLocation;
+
+    /**
+     * 浏览器类型
+     */
+    private String browser;
+
+    /**
+     * 操作系统
+     */
+    private String os;
+
+    /**
+     * 权限列表
+     */
+    private Set<String> permissions;
+
+    /**
+     * 用户信息
+     */
+    private StoreUser user;
+
+
+    public StoreLoginUser(StoreUser user, Set<String> permissions)
+    {
+        this.user = user;
+        this.permissions = permissions;
+    }
+
+    @JsonIgnore
+    @Override
+    public String getPassword()
+    {
+        return user.getPassword();
+    }
+
+    @Override
+    public String getUsername()
+    {
+        return user.getUserAccount();
+    }
+
+    /**
+     * 账户是否未过期,过期无法验证
+     */
+    @JsonIgnore
+    @Override
+    public boolean isAccountNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 指定用户是否解锁,锁定的用户无法进行身份验证
+     *
+     * @return
+     */
+    @JsonIgnore
+    @Override
+    public boolean isAccountNonLocked()
+    {
+        return true;
+    }
+
+    /**
+     * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
+     *
+     * @return
+     */
+    @JsonIgnore
+    @Override
+    public boolean isCredentialsNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 是否可用 ,禁用的用户不能身份验证
+     *
+     * @return
+     */
+    @JsonIgnore
+    @Override
+    public boolean isEnabled()
+    {
+        return true;
+    }
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities()
+    {
+        return null;
+    }
+}

+ 3 - 3
zhongzheng-common/src/main/java/com/zhongzheng/common/utils/SecurityUtils.java

@@ -24,12 +24,12 @@ public class SecurityUtils
    // @Value("${mybatis-plus.tenant.enabled-tenant:true}")
     public static boolean EnabledTenant;
 
-    @Value("${mybatis-plus.tenant.enabled-tenant:true}")
-    private boolean enabledTenant;
+    @Value("${mybatis-plus.tenant.enabled-tenant}")
+    private Integer enabledTenant;
 
     @PostConstruct
     public void getEnvironment(){
-        EnabledTenant = this.enabledTenant;
+        EnabledTenant = this.enabledTenant == 1 || this.enabledTenant == 3;
     }
     /**
      * 获取用户账户

+ 14 - 5
zhongzheng-framework/src/main/java/com/zhongzheng/framework/aspectj/LogAspect.java

@@ -11,17 +11,17 @@ import com.zhongzheng.common.core.domain.model.LoginUser;
 import com.zhongzheng.common.core.domain.model.TopLoginUser;
 import com.zhongzheng.common.enums.BusinessStatus;
 import com.zhongzheng.common.enums.HttpMethod;
-import com.zhongzheng.common.filter.XssHttpServletRequestWrapper;
 import com.zhongzheng.common.utils.ServletUtils;
-import com.zhongzheng.common.utils.http.HttpHelper;
 import com.zhongzheng.common.utils.ip.IpUtils;
 import com.zhongzheng.common.utils.spring.SpringUtils;
 import com.zhongzheng.framework.manager.AsyncManager;
 import com.zhongzheng.framework.manager.factory.AsyncFactory;
+import com.zhongzheng.framework.web.service.StoreTokenService;
 import com.zhongzheng.framework.web.service.TokenService;
 import com.zhongzheng.framework.web.service.TopTokenService;
 import com.zhongzheng.framework.web.service.WxTokenService;
 import com.zhongzheng.modules.system.domain.SysOperLog;
+import com.zhongzheng.modules.user.entity.ClientLoginStoreUser;
 import com.zhongzheng.modules.user.entity.ClientLoginUser;
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.Signature;
@@ -56,8 +56,8 @@ public class LogAspect
 {
     private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
 
-    @Value("${mybatis-plus.tenant.enabled-tenant:true}")
-    private boolean enabledTenant;
+    @Value("${mybatis-plus.tenant.enabled-tenant}")
+    private Integer enabledTenant;
 
     @Value("${zhongzheng.name}")
     private String applicationName;
@@ -102,7 +102,7 @@ public class LogAspect
                 return;
             }
             String username = null;
-            if(enabledTenant){
+            if(enabledTenant == 1 || enabledTenant == 3){
                 // 获取当前的用户
                 //后台
                 if(applicationName.equals("zhongzheng")){
@@ -121,6 +121,15 @@ public class LogAspect
                     }
                     return ;
                 }
+                //客户端
+                if(applicationName.equals("zhongzheng_store")){
+                    ClientLoginStoreUser  loginUser = SpringUtils.getBean(StoreTokenService.class).getLoginUser(ServletUtils.getRequest());
+                    if (loginUser != null)
+                    {
+                        username = loginUser.getUser().getUserAccount();
+                    }
+                    return ;
+                }
             }else{
                 TopLoginUser topLoginUser = SpringUtils.getBean(TopTokenService.class).getLoginUser(ServletUtils.getRequest());
                 if (topLoginUser != null)

+ 13 - 5
zhongzheng-framework/src/main/java/com/zhongzheng/framework/config/SecurityConfig.java

@@ -4,6 +4,7 @@ import com.zhongzheng.framework.security.filter.JwtAuthenticationTokenFilter;
 import com.zhongzheng.framework.security.handle.AuthenticationEntryPointImpl;
 import com.zhongzheng.framework.security.handle.LogoutSuccessHandlerImpl;
 import com.zhongzheng.framework.security.handle.TopLogoutSuccessHandlerImpl;
+import com.zhongzheng.framework.web.service.StoreUserDetailsServiceImpl;
 import com.zhongzheng.framework.web.service.TopUserDetailsServiceImpl;
 import com.zhongzheng.framework.web.service.UserDetailsServiceImpl;
 import de.codecentric.boot.admin.server.config.AdminServerProperties;
@@ -40,8 +41,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
     @Autowired
     private TopUserDetailsServiceImpl topUserDetailsService;
 
-    @Value("${mybatis-plus.tenant.enabled-tenant:false}")
-    private boolean enabledTenant;
+    @Autowired
+    private StoreUserDetailsServiceImpl storeUserDetailsServiceImpl;
+
+    @Value("${mybatis-plus.tenant.enabled-tenant}")
+    private Integer enabledTenant;
 
     /**
      * 认证失败处理类
@@ -129,6 +133,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                         "/**/*.js"
                 ).permitAll()
                 .antMatchers("/app/common/**").anonymous() //小程序非验证接口
+                .antMatchers("/app/store/common/**").anonymous() //核销系统非验证接口
                 .antMatchers("/sys/common/**").anonymous()
                 .antMatchers("/refreshToken/**").anonymous()
                 .antMatchers("/v1/test/**").anonymous()
@@ -164,7 +169,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                 .anyRequest().authenticated()
                 .and()
                 .headers().frameOptions().disable();
-        if(enabledTenant){
+        if(enabledTenant == 1 || enabledTenant == 3){
             //开启多租户
             httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
         }else{
@@ -194,10 +199,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception
     {
-        if(enabledTenant){
+        if(enabledTenant == 1){
             //开启多租户
             auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
-        }else{
+        }else if (enabledTenant == 3){
+            //开启多租户
+            auth.userDetailsService(storeUserDetailsServiceImpl).passwordEncoder(bCryptPasswordEncoder());
+        }else {
             auth.userDetailsService(topUserDetailsService).passwordEncoder(bCryptPasswordEncoder());
         }
 

+ 4 - 4
zhongzheng-framework/src/main/java/com/zhongzheng/framework/mybatisplus/CreateAndUpdateMetaObjectHandler.java

@@ -13,14 +13,14 @@ import org.springframework.beans.factory.annotation.Value;
  */
 public class CreateAndUpdateMetaObjectHandler implements MetaObjectHandler {
 
-	@Value("${mybatis-plus.tenant.enabled-tenant:true}")
-	private boolean enabledTenant;
+	@Value("${mybatis-plus.tenant.enabled-tenant}")
+	private Integer enabledTenant;
 
 	@Override
 	public void insertFill(MetaObject metaObject) {
 		//根据属性名字设置要填充的值
 		if (metaObject.hasGetter("createTime")) {
-			if (metaObject.getValue("createTime") == null && enabledTenant) {
+			if (metaObject.getValue("createTime") == null && enabledTenant == 1) {
 				this.setFieldValByName("createTime", DateUtils.getNowDate(), metaObject);
 			}
 		}
@@ -39,7 +39,7 @@ public class CreateAndUpdateMetaObjectHandler implements MetaObjectHandler {
 			}
 		}
 		if (metaObject.hasGetter("updateTime")) {
-			if (metaObject.getValue("updateTime") == null && enabledTenant) {
+			if (metaObject.getValue("updateTime") == null && enabledTenant == 1) {
 				this.setFieldValByName("updateTime", DateUtils.getNowDate(), metaObject);
 			}
 		}

+ 4 - 4
zhongzheng-framework/src/main/java/com/zhongzheng/framework/mybatisplus/CustomTenantLineHandler.java

@@ -31,8 +31,8 @@ public class CustomTenantLineHandler implements TenantLineHandler {
 
   //  public static  String TENANT_ID = null;
 
-    @Value("${mybatis-plus.tenant.enabled-tenant:true}")
-    private boolean enabledTenant;
+    @Value("${mybatis-plus.tenant.enabled-tenant}")
+    private Integer enabledTenant;
 
     /**
      * 忽略添加租户ID的表
@@ -57,7 +57,7 @@ public class CustomTenantLineHandler implements TenantLineHandler {
         String TenantId = ServletUtils.getRequest().getHeader("TenantId");
         if(Validator.isEmpty(TenantId)){
             TenantId = ServletUtils.getResponse().getHeader("TenantId");
-            if(enabledTenant){
+            if(enabledTenant == 1 || enabledTenant == 3){
                 if(Validator.isEmpty(TenantId)){
                     int code = HttpStatus.HTTP_UNAVAILABLE;
                     String msg = "企业非法访问";
@@ -88,7 +88,7 @@ public class CustomTenantLineHandler implements TenantLineHandler {
      */
     @Override
     public boolean ignoreTable(String tableName) {
-        if (!enabledTenant || tableName.contains("top_")){
+        if (enabledTenant == 2 || tableName.contains("top_")){
             //总平台忽略tenantId
             return true;
         }

+ 22 - 10
zhongzheng-framework/src/main/java/com/zhongzheng/framework/security/filter/JwtAuthenticationTokenFilter.java

@@ -1,16 +1,15 @@
 package com.zhongzheng.framework.security.filter;
 
 import cn.hutool.core.lang.Validator;
-import cn.hutool.http.HttpStatus;
-import com.zhongzheng.common.core.domain.AjaxResult;
-import com.zhongzheng.common.core.domain.model.TopLoginUser;
-import com.zhongzheng.framework.web.service.TopTokenService;
-import com.zhongzheng.modules.user.entity.ClientLoginSeller;
-import com.zhongzheng.modules.user.entity.ClientLoginUser;
 import com.zhongzheng.common.core.domain.model.LoginUser;
+import com.zhongzheng.common.core.domain.model.TopLoginUser;
 import com.zhongzheng.common.utils.SecurityUtils;
+import com.zhongzheng.framework.web.service.StoreTokenService;
 import com.zhongzheng.framework.web.service.TokenService;
+import com.zhongzheng.framework.web.service.TopTokenService;
 import com.zhongzheng.framework.web.service.WxTokenService;
+import com.zhongzheng.modules.user.entity.ClientLoginStoreUser;
+import com.zhongzheng.modules.user.entity.ClientLoginUser;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -40,11 +39,14 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
     @Autowired
     private WxTokenService wxTokenService;
 
+    @Autowired
+    private StoreTokenService storeTokenService;
+
     @Autowired
     private TopTokenService topTokenService;
 
-    @Value("${mybatis-plus.tenant.enabled-tenant:true}")
-    private boolean enabledTenant;
+    @Value("${mybatis-plus.tenant.enabled-tenant}")
+    private Integer enabledTenant;
 
     @Override
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
@@ -52,6 +54,7 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
     {
         try{
             String wxToken = wxTokenService.getToken(request);
+            String storeToken = storeTokenService.getToken(request);
             if(StringUtils.isNoneEmpty(wxToken)){
                 ClientLoginUser clientLoginUser = wxTokenService.getLoginUser(request);
                 if(clientLoginUser!=null){
@@ -60,8 +63,17 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
                     authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                     SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                 }
-            }else{
-                if(!enabledTenant){
+            }else if (StringUtils.isNoneEmpty(storeToken)){
+                ClientLoginStoreUser clientLoginUser = storeTokenService.getLoginUser(request);
+                if(clientLoginUser!=null){
+                    storeTokenService.verifyToken(clientLoginUser);
+                    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(clientLoginUser, null,null);
+                    authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+                }
+
+            }else {
+                if(enabledTenant == 2){
                     //SAAS管理员
                     TopLoginUser top_loginUser = topTokenService.getLoginUser(request);
                     if (Validator.isNotNull(top_loginUser) && Validator.isNull(SecurityUtils.getAuthentication()))

+ 2 - 3
zhongzheng-framework/src/main/java/com/zhongzheng/framework/web/service/PermissionService.java

@@ -4,7 +4,6 @@ import cn.hutool.core.lang.Validator;
 import cn.hutool.core.util.StrUtil;
 import com.zhongzheng.common.core.domain.entity.SysRole;
 import com.zhongzheng.common.core.domain.model.LoginUser;
-import com.zhongzheng.common.core.domain.model.TopLoginUser;
 import com.zhongzheng.common.utils.ServletUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -36,8 +35,8 @@ public class PermissionService
     @Autowired
     private TopTokenService topTokenService;
 
-    @Value("${mybatis-plus.tenant.enabled-tenant:true}")
-    private boolean enabledTenant;
+    @Value("${mybatis-plus.tenant.enabled-tenant}")
+    private Integer enabledTenant;
 
     /**
      * 验证用户是否具备某权限

+ 67 - 0
zhongzheng-framework/src/main/java/com/zhongzheng/framework/web/service/StorePermissionService.java

@@ -0,0 +1,67 @@
+package com.zhongzheng.framework.web.service;
+
+import com.zhongzheng.common.core.domain.entity.store.StoreUser;
+import com.zhongzheng.modules.store.service.IStoreMenuService;
+import com.zhongzheng.modules.store.service.IStoreRoleService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * 用户权限处理
+ *
+ * @author zhongzheng
+ */
+@Component
+public class StorePermissionService
+{
+    @Autowired
+    private IStoreRoleService roleService;
+
+    @Autowired
+    private IStoreMenuService menuService;
+
+    /**
+     * 获取角色数据权限
+     *
+     * @param user 用户信息
+     * @return 角色权限信息
+     */
+    public Set<String> getRolePermission(StoreUser user)
+    {
+        Set<String> roles = new HashSet<String>();
+        // 管理员拥有所有权限
+        if (user.isAdmin())
+        {
+            roles.add("admin");
+        }
+        else
+        {
+            roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId()));
+        }
+        return roles;
+    }
+
+    /**
+     * 获取菜单数据权限
+     *
+     * @param user 用户信息
+     * @return 菜单权限信息
+     */
+    public Set<String> getMenuPermission(StoreUser user)
+    {
+        Set<String> perms = new HashSet<String>();
+        // 管理员拥有所有权限
+        if (user.isAdmin())
+        {
+            perms.add("*:*:*");
+        }
+        else
+        {
+            perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
+        }
+        return perms;
+    }
+}

+ 243 - 0
zhongzheng-framework/src/main/java/com/zhongzheng/framework/web/service/StoreTokenService.java

@@ -0,0 +1,243 @@
+package com.zhongzheng.framework.web.service;
+
+import cn.hutool.core.lang.Validator;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.http.useragent.UserAgent;
+import cn.hutool.http.useragent.UserAgentUtil;
+import com.zhongzheng.common.constant.Constants;
+import com.zhongzheng.common.core.domain.entity.store.StoreUser;
+import com.zhongzheng.common.core.redis.RedisCache;
+import com.zhongzheng.common.utils.ServletUtils;
+import com.zhongzheng.common.utils.ip.AddressUtils;
+import com.zhongzheng.common.utils.ip.IpUtils;
+import com.zhongzheng.modules.store.service.IStoreUserService;
+import com.zhongzheng.modules.user.entity.ClientLoginStoreUser;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * token验证处理
+ *
+ * @author zhongzheng
+ */
+@Component
+public class StoreTokenService
+{
+    // 令牌自定义标识
+    @Value("${token.header}")
+    private String header;
+
+    // 令牌秘钥
+    @Value("${token.secret}")
+    private String secret;
+
+    // 令牌有效期(默认30分钟)
+    @Value("${token.expireTime}")
+    private int expireTime;
+
+    protected static final long MILLIS_SECOND = 1000;
+
+    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
+
+    private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    @Autowired
+    private IStoreUserService iUserService;
+
+
+    /**
+     * 获取用户身份信息
+     *
+     * @return 用户信息
+     */
+    public ClientLoginStoreUser getLoginUser(HttpServletRequest request)
+    {
+        //测试用户
+        String test_token = request.getHeader("X-Auth-Token");
+        if("test".equals(test_token)){
+            return getTestUser();
+        }
+        // 获取请求携带的令牌
+        String token = getToken(request);
+        if (Validator.isNotEmpty(token))
+        {
+            Claims claims = parseToken(token);
+            // 解析对应的权限以及用户信息
+            String uuid = (String) claims.get(Constants.STORE_LOGIN_USER_KEY);
+            String userKey = getTokenKey(uuid);
+            ClientLoginStoreUser user = redisCache.getCacheObject(userKey);
+            return user;
+        }
+        return null;
+    }
+
+    private ClientLoginStoreUser getTestUser(){
+        String unionId = "oQ2yp56PgQ-PfwN4vxTZhR5eTpzk";
+        StoreUser user = iUserService.queryByUnionId(unionId);
+        ClientLoginStoreUser loginUser = new ClientLoginStoreUser();
+        loginUser.setUser(user);
+        loginUser.setExpireTime(System.currentTimeMillis()+200);
+        return loginUser;
+    }
+
+    /**
+     * 设置用户身份信息
+     */
+    public void setLoginUser(ClientLoginStoreUser loginUser)
+    {
+        if (Validator.isNotNull(loginUser) && Validator.isNotEmpty(loginUser.getToken()))
+        {
+            refreshToken(loginUser);
+        }
+    }
+
+    /**
+     * 删除用户身份信息
+     */
+    public void delLoginUser(String token)
+    {
+        if (Validator.isNotEmpty(token))
+        {
+            String userKey = getTokenKey(token);
+            redisCache.deleteObject(userKey);
+        }
+    }
+
+    /**
+     * 创建令牌
+     *
+     * @param loginUser 用户信息
+     * @return 令牌
+     */
+    public String createToken(ClientLoginStoreUser loginUser)
+    {
+        String token = IdUtil.simpleUUID()+loginUser.getUser().getUserAccount();
+        loginUser.setToken(token);
+        setUserAgent(loginUser);
+        refreshToken(loginUser);
+        Map<String, Object> claims = new HashMap<>();
+        claims.put(Constants.STORE_LOGIN_USER_KEY, token);
+        return createToken(claims);
+    }
+
+    /**
+     * 验证令牌有效期,相差不足20分钟,自动刷新缓存
+     *
+     * @param loginUser
+     * @return 令牌
+     */
+    public void verifyToken(ClientLoginStoreUser loginUser)
+    {
+        long expireTime = loginUser.getExpireTime();
+        long currentTime = System.currentTimeMillis();
+        if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
+        {
+            refreshToken(loginUser);
+        }
+    }
+
+    /**
+     * 刷新令牌有效期
+     *
+     * @param loginUser 登录信息
+     */
+    public void refreshToken(ClientLoginStoreUser loginUser)
+    {
+        loginUser.setLoginTime(System.currentTimeMillis());
+        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
+        // 根据uuid将loginUser缓存
+        String userKey = getTokenKey(loginUser.getToken());
+        redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
+    }
+
+    /**
+     * 设置用户代理信息
+     *
+     * @param loginUser 登录信息
+     */
+    public void setUserAgent(ClientLoginStoreUser loginUser)
+    {
+        UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
+        String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
+        loginUser.setIpaddr(ip);
+        loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
+        loginUser.setBrowser(userAgent.getBrowser().getName());
+        loginUser.setOs(userAgent.getOs().getName());
+    }
+
+    /**
+     * 从数据声明生成令牌
+     *
+     * @param claims 数据声明
+     * @return 令牌
+     */
+    private String createToken(Map<String, Object> claims)
+    {
+        String token = Jwts.builder()
+                .setClaims(claims)
+                .signWith(SignatureAlgorithm.HS512, secret).compact();
+        return token;
+    }
+
+    /**
+     * 从令牌中获取数据声明
+     *
+     * @param token 令牌
+     * @return 数据声明
+     */
+    private Claims parseToken(String token)
+    {
+        return Jwts.parser()
+                .setSigningKey(secret)
+                .parseClaimsJws(token)
+                .getBody();
+    }
+
+    /**
+     * 从令牌中获取用户名
+     *
+     * @param token 令牌
+     * @return 用户名
+     */
+    public String getUsernameFromToken(String token)
+    {
+        Claims claims = parseToken(token);
+        return claims.getSubject();
+    }
+
+    /**
+     * 获取请求token
+     *
+     * @param request
+     * @return token
+     */
+    public String getToken(HttpServletRequest request)
+    {
+        String token = request.getHeader(header);
+        if (Validator.isNotEmpty(token) && token.startsWith(Constants.STORE_TOKEN_PREFIX))
+        {
+            token = token.replace(Constants.STORE_TOKEN_PREFIX, "");
+            return token;
+        }else{
+            return null;
+        }
+
+    }
+
+    private String getTokenKey(String uuid)
+    {
+        return Constants.STORE_LOGIN_TOKEN_KEY + uuid;
+    }
+}

+ 64 - 0
zhongzheng-framework/src/main/java/com/zhongzheng/framework/web/service/StoreUserDetailsServiceImpl.java

@@ -0,0 +1,64 @@
+package com.zhongzheng.framework.web.service;
+
+import cn.hutool.core.lang.Validator;
+import com.zhongzheng.common.core.domain.entity.store.StoreUser;
+import com.zhongzheng.common.enums.UserStatus;
+import com.zhongzheng.common.exception.BaseException;
+import com.zhongzheng.modules.store.service.IStoreUserService;
+import com.zhongzheng.modules.user.entity.ClientLoginStoreUser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+/**
+ * 用户验证处理
+ *
+ * @author zhongzheng
+ */
+@Service
+public class StoreUserDetailsServiceImpl implements UserDetailsService
+{
+    private static final Logger log = LoggerFactory.getLogger(StoreUserDetailsServiceImpl.class);
+
+    @Autowired
+    private IStoreUserService userService;
+
+    @Autowired
+    private StorePermissionService permissionService;
+
+
+    @Override
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
+    {
+        //普通系统用户
+        StoreUser user = userService.selectUserByUserName(username);
+        if (Validator.isNull(user))
+        {
+            log.info("登录用户:{} 不存在.", username);
+            throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
+        }
+        else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
+        {
+            log.info("登录用户:{} 已被删除.", username);
+            throw new BaseException("对不起,您的账号:" + username + " 已被删除");
+        }
+        else if (user.getStatus().longValue()==0L)
+        {
+            log.info("登录用户:{} 已被停用.", username);
+            throw new BaseException("对不起,您的账号:" + username + " 已停用");
+        }
+
+        return createLoginUser(user);
+    }
+
+    public UserDetails createLoginUser(StoreUser user)
+    {
+        return new ClientLoginStoreUser(user, permissionService.getMenuPermission(user));
+    }
+
+
+}

+ 265 - 0
zhongzheng-framework/src/main/java/com/zhongzheng/framework/web/service/StoreUserServiceImpl.java

@@ -0,0 +1,265 @@
+package com.zhongzheng.framework.web.service;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.lang.Validator;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhongzheng.common.constant.Constants;
+import com.zhongzheng.common.constant.UserConstants;
+import com.zhongzheng.common.core.domain.entity.store.StoreRole;
+import com.zhongzheng.common.core.domain.entity.store.StoreUser;
+import com.zhongzheng.common.core.domain.entity.store.StoreUserRole;
+import com.zhongzheng.common.core.redis.RedisCache;
+import com.zhongzheng.common.enums.UserStatus;
+import com.zhongzheng.common.exception.BaseException;
+import com.zhongzheng.common.exception.CustomException;
+import com.zhongzheng.common.type.EncryptHandler;
+import com.zhongzheng.common.utils.AES;
+import com.zhongzheng.common.utils.SecurityUtils;
+import com.zhongzheng.modules.store.mapper.StoreUserMapper;
+import com.zhongzheng.modules.store.mapper.StoreUserRoleMapper;
+import com.zhongzheng.modules.store.service.IStoreRoleService;
+import com.zhongzheng.modules.store.service.IStoreUserService;
+import com.zhongzheng.modules.user.bo.UserAppAccountLoginBo;
+import com.zhongzheng.modules.user.bo.UserAppSmsLoginBo;
+import com.zhongzheng.modules.user.entity.ClientLoginStoreUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Service
+public class StoreUserServiceImpl extends ServiceImpl<StoreUserMapper, StoreUser> implements IStoreUserService {
+
+    @Autowired
+    private RedisCache redisCache;
+
+    @Autowired
+    private StoreTokenService storeTokenService;
+
+    @Autowired
+    private StoreUserRoleMapper StoreUserRoleMapper;
+
+    @Autowired
+    private IStoreRoleService iStoreRoleService;
+    
+    
+    @Override
+    public List<StoreUser> selectUserList(StoreUser user) {
+        List<StoreUser> sysUsers = baseMapper.selectUserList(user);
+        for (StoreUser sysUser : sysUsers) {
+
+            List<StoreUserRole> StoreUserRoles = StoreUserRoleMapper.selectList(new LambdaQueryWrapper<StoreUserRole>().eq(StoreUserRole::getUserId, sysUser.getUserId()));
+            if (CollectionUtils.isNotEmpty(StoreUserRoles)){
+                List<Long> collect = StoreUserRoles.stream().map(StoreUserRole::getRoleId).collect(Collectors.toList());
+                sysUser.setRoleIds(collect);
+                List<StoreRole> sysRoles = iStoreRoleService.listByIds(collect);
+                if (CollectionUtils.isNotEmpty(sysRoles)){
+                    List<StoreRole> collect1 = sysRoles.stream().map(x -> BeanUtil.toBean(x, StoreRole.class)).collect(Collectors.toList());
+                    sysUser.setRoles(collect1);
+                }
+            }else {
+                sysUser.setRoleIds(new ArrayList<>());
+                sysUser.setRoles(new ArrayList<>());
+            }
+
+        }
+        return sysUsers;
+    }
+
+    @Override
+    public String checkUserNameUnique(String userName) {
+        int count = count(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getUserAccount, userName).ne(StoreUser::getStatus, -1).last("limit 1"));
+        if (count > 0) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    @Override
+    public String checkPhoneUnique(StoreUser user) {
+        Long userId = Validator.isNull(user.getUserId()) ? -1L : user.getUserId();
+        StoreUser info = getOne(new LambdaQueryWrapper<StoreUser>()
+                .select(StoreUser::getUserId, StoreUser::getTelphone)
+                .eq(StoreUser::getTelphone, user.getTelphone()).last("limit 1"));
+        if (Validator.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    @Override
+    public void checkUserAllowed(StoreUser user) {
+        if (Validator.isNotNull(user.getUserId()) && user.isAdmin()) {
+            throw new CustomException("不允许操作超级管理员用户");
+        }
+    }
+
+    @Override
+    public int insertUser(StoreUser user) {
+        validEntityBeforeSave(user);
+        int rows = baseMapper.insert(user);
+        // 新增用户与角色管理
+        insertUserRole(user);
+        return rows;
+    }
+
+    @Override
+    public int updateUser(StoreUser user) {
+        validEntityBeforeSave(user);
+        // 新增用户与角色管理
+        if (!user.getStatus().equals(-1)) {
+            insertUserRole(user);
+        }
+        return baseMapper.updateById(user);
+    }
+
+    /**
+     * 保存前的数据校验
+     *
+     * @param entity 实体类数据
+     */
+    private void validEntityBeforeSave(StoreUser entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+    
+    /**
+     * 新增用户角色信息
+     *
+     * @param user 用户对象
+     */
+    public void insertUserRole(StoreUser user) {
+        List<Long> roles = user.getRoleIds();
+        if (Validator.isNotNull(roles)) {
+            // 删除用户与角色关联
+            StoreUserRoleMapper.delete(new LambdaQueryWrapper<StoreUserRole>().eq(StoreUserRole::getUserId,user.getUserId()));
+            // 新增用户与角色管理
+            List<StoreUserRole> list = new ArrayList<StoreUserRole>();
+            for (Long roleId : roles) {
+                StoreUserRole ur = new StoreUserRole();
+                ur.setUserId(user.getUserId());
+                ur.setRoleId(roleId);
+                list.add(ur);
+            }
+            if (list.size() > 0) {
+                for (StoreUserRole sysUserRole : list) {
+                    StoreUserRoleMapper.insert(sysUserRole);
+                }
+            }
+        }
+    }
+
+    @Override
+    public int updateUserStatus(StoreUser user) {
+        return baseMapper.updateById(user);
+    }
+
+    @Override
+    public StoreUser queryByUnionId(String unionId) {
+        StoreUser user = getOne(new LambdaQueryWrapper<StoreUser>()
+                .eq(StoreUser::getUnionId, unionId)
+                .last("limit 1"));
+        if (Validator.isNotNull(user)) {
+            return user;
+        }
+        return null;
+    }
+
+    @Override
+    public StoreUser selectUserByUserName(String username) {
+        return baseMapper.selectUserByUserName(username);
+    }
+
+    @Override
+    public Map<String, Object> smsLogin(UserAppSmsLoginBo bo) {
+        if(bo.getTel()==null){
+            throw new CustomException("手机号不能为空");
+        }
+        String key = Constants.LOGIN_SMS + bo.getTel();
+        String code =  redisCache.getCacheObject(key);
+        if(code==null){
+            throw new CustomException("验证码错误");
+        }
+        if(!code.equals(bo.getCode())){
+            throw new CustomException("验证码错误");
+        }
+        redisCache.deleteObject(key);
+        StoreUser user = getOne(new LambdaQueryWrapper<StoreUser>()
+                .eq(StoreUser::getTelphone, EncryptHandler.encrypt(bo.getTel())).last("limit 1"));
+        if(Validator.isEmpty(user)){
+            throw new CustomException("该手机号未注册");
+        }
+        ClientLoginStoreUser loginUser = new ClientLoginStoreUser();
+        loginUser.setUser(user);
+        Map<String,Object> map = new HashMap<>();
+        map.put(Constants.TOKEN,storeTokenService.createToken(loginUser));
+        map.put("user_account",user.getUserAccount());
+        map.put("full_info",Validator.isEmpty(user.getIdCard())?false:true); //是否完善身份信息
+        return map;
+    }
+
+    @Override
+    public Map<String, Object> accountLogin(UserAppAccountLoginBo bo) {
+        if(Validator.isEmpty(bo.getAccount())){
+            throw new CustomException("账号不能为空");
+        }
+        LambdaQueryWrapper<StoreUser> queryWrapper =new LambdaQueryWrapper<StoreUser>();
+        queryWrapper.and(wq -> wq
+                .eq(StoreUser::getTelphone,EncryptHandler.encrypt(bo.getAccount()))
+                .or()
+                .eq(StoreUser::getIdCard,EncryptHandler.encrypt(bo.getAccount()))
+                .or()
+                .eq(StoreUser::getUserAccount,bo.getAccount()));
+        StoreUser user = getOne(queryWrapper);
+        if(Validator.isEmpty(user)){
+            throw new CustomException("登录信息错误");
+        }
+        else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
+        {
+            throw new BaseException("对不起,您的账号:已停用");
+        }
+        String password = null;
+        if(bo.getPwd().length()>20){
+            String rsaPrivate = null;
+            try {
+                InputStream certStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("config/pri.key");
+                rsaPrivate = AES.getStringByInputStream_1(certStream);
+                certStream.close();
+                password = AES.decrypt(bo.getPwd(),rsaPrivate);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }else{
+            password = bo.getPwd();
+        }
+        if (!SecurityUtils.matchesPassword(password,user.getPassword()))
+        {
+            throw new BaseException("登录信息错误");
+        }
+        ClientLoginStoreUser loginUser = new ClientLoginStoreUser();
+        loginUser.setUser(user);
+        Map<String,Object> map = new HashMap<>();
+        map.put(Constants.TOKEN,storeTokenService.createToken(loginUser));
+        map.put("user_account",user.getUserAccount());
+        map.put("full_info",Validator.isEmpty(user.getIdCard())?false:true); //是否完善身份信息
+        return map;
+    }
+
+    @Override
+    public StoreUser selectUserById(Long userId) {
+        return baseMapper.selectById(userId);
+    }
+
+}

+ 43 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/bo/GoodsCategoryBo.java

@@ -0,0 +1,43 @@
+package com.zhongzheng.modules.goods.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 【请填写功能名称】对象 goods_spec
+ *
+ * @author ruoyi
+ * @date 2022-09-29
+ */
+@Data
+@ApiModel("请求对象")
+public class GoodsCategoryBo implements Serializable {
+
+private static final long serialVersionUID=1L;
+
+    /** 主键 */
+    @ApiModelProperty("类目ID")
+    private Long categoryId;
+    /** 类目名称 */
+    @ApiModelProperty("类目名称")
+    private String categoryName;
+    /** 父ID */
+    @ApiModelProperty("父ID")
+    private Integer parentId;
+    /** 状态:1启用 0禁用 -1删除 */
+    @ApiModelProperty("状态:1启用 0禁用 -1删除")
+    private Integer status;
+    /** 创建时间 */
+    @ApiModelProperty("创建时间")
+    private Long createTime;
+    /** 更新时间 */
+    @ApiModelProperty("更新时间")
+    private Long updateTime;
+    @ApiModelProperty("")
+    private Long tenantId;
+    @ApiModelProperty("店铺ID")
+    private Long storeId;
+}

+ 41 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/bo/GoodsCategoryQueryBo.java

@@ -0,0 +1,41 @@
+package com.zhongzheng.modules.goods.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 【请填写功能名称】对象 goods_spec
+ *
+ * @author ruoyi
+ * @date 2022-09-29
+ */
+@Data
+@ApiModel("请求对象")
+public class GoodsCategoryQueryBo implements Serializable {
+
+    /** 分页大小 */
+    @ApiModelProperty("分页大小")
+    private Integer pageSize;
+    /** 当前页数 */
+    @ApiModelProperty("当前页数")
+    private Integer pageNum;
+    /** 排序列 */
+    @ApiModelProperty("排序列")
+    private String orderByColumn;
+    /** 排序的方向desc或者asc */
+    @ApiModelProperty(value = "排序的方向", example = "asc,desc")
+    private String isAsc;
+
+    /** 类目名称 */
+    @ApiModelProperty("类目名称")
+    private String categoryName;
+
+    private List<Integer> statusList;
+
+    private Integer parentId;
+
+}

+ 44 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/domain/GoodsCategory.java

@@ -0,0 +1,44 @@
+package com.zhongzheng.modules.goods.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * 【请填写功能名称】对象 goods_spec
+ *
+ * @author ruoyi
+ * @date 2022-09-29
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("goods_category")
+public class GoodsCategory implements Serializable {
+
+private static final long serialVersionUID=1L;
+
+    /** 主键 */
+    @TableId(value = "category_id")
+    private Long categoryId;
+    /** 类目名称 */
+    private String categoryName;
+    /** 父ID */
+    private Integer parentId;
+    /** 状态:1启用 0禁用 -1删除 */
+    private Integer status;
+    /** 创建时间 */
+    private Long createTime;
+    /** 更新时间 */
+    private Long updateTime;
+
+    private Long tenantId;
+
+    private Long storeId;
+
+    private Long companyId;
+}

+ 13 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/mapper/GoodsCategoryMapper.java

@@ -0,0 +1,13 @@
+package com.zhongzheng.modules.goods.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhongzheng.modules.goods.bo.GoodsCategoryQueryBo;
+import com.zhongzheng.modules.goods.domain.GoodsCategory;
+import com.zhongzheng.modules.goods.vo.GoodsCategoryVo;
+
+import java.util.List;
+
+public interface GoodsCategoryMapper extends BaseMapper<GoodsCategory> {
+
+    List<GoodsCategoryVo> queryList(GoodsCategoryQueryBo bo);
+}

+ 23 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/service/IGoodsCategoryService.java

@@ -0,0 +1,23 @@
+package com.zhongzheng.modules.goods.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhongzheng.modules.goods.bo.GoodsCategoryBo;
+import com.zhongzheng.modules.goods.bo.GoodsCategoryQueryBo;
+import com.zhongzheng.modules.goods.domain.GoodsCategory;
+import com.zhongzheng.modules.goods.vo.GoodsCategoryVo;
+
+import java.util.List;
+
+public interface IGoodsCategoryService extends IService<GoodsCategory> {
+
+    List<GoodsCategoryVo> queryList(GoodsCategoryQueryBo bo);
+
+    boolean saveCategory(GoodsCategoryBo bo);
+
+    boolean updateCategory(GoodsCategoryBo bo);
+
+    boolean batchDelCategory(List<Long> ids);
+
+    List<GoodsCategoryVo> categoryTree();
+
+}

+ 114 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/service/impl/GoodsCategoryServiceImpl.java

@@ -0,0 +1,114 @@
+package com.zhongzheng.modules.goods.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhongzheng.common.exception.CustomException;
+import com.zhongzheng.common.utils.DateUtils;
+import com.zhongzheng.modules.goods.bo.GoodsCategoryBo;
+import com.zhongzheng.modules.goods.bo.GoodsCategoryQueryBo;
+import com.zhongzheng.modules.goods.domain.GoodsCategory;
+import com.zhongzheng.modules.goods.mapper.GoodsCategoryMapper;
+import com.zhongzheng.modules.goods.service.IGoodsCategoryService;
+import com.zhongzheng.modules.goods.vo.GoodsCategoryVo;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author yangdamao
+ * @date 2023年05月24日 16:37
+ */
+@Service
+public class GoodsCategoryServiceImpl extends ServiceImpl<GoodsCategoryMapper, GoodsCategory> implements IGoodsCategoryService {
+
+    @Override
+    public List<GoodsCategoryVo> queryList(GoodsCategoryQueryBo bo) {
+        bo.setStatusList(Arrays.asList(0,1));
+        bo.setParentId(0);//父ID
+        List<GoodsCategoryVo> categoryVos = baseMapper.queryList(bo);
+        if (CollectionUtils.isEmpty(categoryVos)){
+            return new ArrayList<>();
+        }
+        categoryVos.forEach(item -> {
+            //获取子集
+            categoryChildren(item);
+        });
+        return categoryVos;
+    }
+
+
+    private void categoryChildren(GoodsCategoryVo item) {
+        List<GoodsCategory> list = list(new LambdaQueryWrapper<GoodsCategory>().eq(GoodsCategory::getParentId, item.getCategoryId()));
+        if (CollectionUtils.isEmpty(list)){
+            return;
+        }
+        item.setChildren(list.stream().map(x -> BeanUtil.toBean(x,GoodsCategoryVo.class)).collect(Collectors.toList()));
+        item.getChildren().forEach(categoryVo -> {
+            categoryChildren(categoryVo);
+        });
+    }
+
+    @Override
+    public boolean saveCategory(GoodsCategoryBo bo) {
+        validEntity(bo);
+        GoodsCategory goodsCategory = BeanUtil.toBean(bo, GoodsCategory.class);
+        goodsCategory.setCreateTime(DateUtils.getNowTime());
+        goodsCategory.setUpdateTime(DateUtils.getNowTime());
+        return save(goodsCategory);
+    }
+
+    @Override
+    public boolean updateCategory(GoodsCategoryBo bo) {
+        validEntity(bo);
+        GoodsCategory categoryCategory = getById(bo.getCategoryId());
+        if (ObjectUtil.isNull(categoryCategory)){
+            throw new CustomException("类目信息获取失败");
+        }
+        categoryCategory.setCategoryName(bo.getCategoryName());
+        categoryCategory.setParentId(bo.getParentId());
+        categoryCategory.setUpdateTime(DateUtils.getNowTime());
+        if (ObjectUtil.isNotNull(bo.getStatus())){
+            categoryCategory.setStatus(bo.getStatus());
+        }
+        return updateById(categoryCategory);
+    }
+
+    @Override
+    public boolean batchDelCategory(List<Long> ids) {
+        //todo 删除校验
+        List<GoodsCategory> categoryList = listByIds(ids);
+        categoryList.forEach(x -> x.setStatus(-1));
+        return updateBatchById(categoryList);
+    }
+
+    @Override
+    public List<GoodsCategoryVo> categoryTree() {
+        GoodsCategoryQueryBo bo = new GoodsCategoryQueryBo();
+        bo.setParentId(0);//父ID
+        bo.setStatusList(Arrays.asList(1));
+        List<GoodsCategoryVo> categoryVos = baseMapper.queryList(bo);
+        if (CollectionUtils.isEmpty(categoryVos)){
+            return new ArrayList<>();
+        }
+        categoryVos.forEach(item -> {
+            //获取子集
+            categoryChildren(item);
+        });
+        return categoryVos;
+    }
+
+    //校验
+    private void validEntity(GoodsCategoryBo bo){
+        int count = count(new LambdaQueryWrapper<GoodsCategory>()
+                .eq(GoodsCategory::getCategoryName, bo.getCategoryName()));
+        if (count > 0){
+            throw new CustomException("类目名称已存在!");
+        }
+    }
+}

+ 47 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/goods/vo/GoodsCategoryVo.java

@@ -0,0 +1,47 @@
+package com.zhongzheng.modules.goods.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 【请填写功能名称】对象 goods_spec
+ *
+ * @author ruoyi
+ * @date 2022-09-29
+ */
+@Data
+@ApiModel("请求对象")
+public class GoodsCategoryVo implements Serializable {
+
+private static final long serialVersionUID=1L;
+
+    /** 主键 */
+    @ApiModelProperty("类目ID")
+    private Long categoryId;
+    /** 类目名称 */
+    @ApiModelProperty("类目名称")
+    private String categoryName;
+    /** 父ID */
+    @ApiModelProperty("父ID")
+    private Integer parentId;
+    /** 状态:1启用 0禁用 -1删除 */
+    @ApiModelProperty("状态:1启用 0禁用 -1删除")
+    private Integer status;
+    /** 创建时间 */
+    @ApiModelProperty("创建时间")
+    private Long createTime;
+    /** 更新时间 */
+    @ApiModelProperty("更新时间")
+    private Long updateTime;
+    @ApiModelProperty("")
+    private Long tenantId;
+    @ApiModelProperty("店铺ID")
+    private Long storeId;
+
+    @ApiModelProperty("子类目")
+    private List<GoodsCategoryVo> children;
+}

+ 80 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreMenuAddBo.java

@@ -0,0 +1,80 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.util.Date;
+
+
+
+/**
+ * 【请填写功能名称】添加对象 store_menu
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】添加对象")
+public class StoreMenuAddBo {
+
+    /** 菜单名称 */
+    @ApiModelProperty("菜单名称")
+    private String menuName;
+    /** 父菜单ID */
+    @ApiModelProperty("父菜单ID")
+    private Long parentId;
+    /** 显示顺序 */
+    @ApiModelProperty("显示顺序")
+    private Long orderNum;
+    /** 路由地址 */
+    @ApiModelProperty("路由地址")
+    private String path;
+    /** 组件路径 */
+    @ApiModelProperty("组件路径")
+    private String component;
+    /** 是否为外链(0是 1否) */
+    @ApiModelProperty("是否为外链(0是 1否)")
+    private Long isFrame;
+    /** 是否缓存(0缓存 1不缓存) */
+    @ApiModelProperty("是否缓存(0缓存 1不缓存)")
+    private Long isCache;
+    /** 菜单类型(M目录 C菜单 F按钮) */
+    @ApiModelProperty("菜单类型(M目录 C菜单 F按钮)")
+    private String menuType;
+    /** 菜单状态(1显示 0隐藏) */
+    @ApiModelProperty("菜单状态(1显示 0隐藏)")
+    private String visible;
+    /** 菜单状态(1正常 0停用) */
+    @ApiModelProperty("菜单状态(1正常 0停用)")
+    private String status;
+    /** 权限标识 */
+    @ApiModelProperty("权限标识")
+    private String perms;
+    /** 菜单图标 */
+    @ApiModelProperty("菜单图标")
+    private String icon;
+    /** 创建者 */
+    @ApiModelProperty("创建者")
+    private String createBy;
+    /** 创建时间 */
+    @ApiModelProperty("创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+    /** 更新者 */
+    @ApiModelProperty("更新者")
+    private String updateBy;
+    /** 更新时间 */
+    @ApiModelProperty("更新时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+    /** 备注 */
+    @ApiModelProperty("备注")
+    private String remark;
+    /** 店铺ID */
+    @ApiModelProperty("店铺ID")
+    private Long storeId;
+    /** 商户ID */
+    @ApiModelProperty("商户ID")
+    private Long companyId;
+}

+ 94 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreMenuEditBo.java

@@ -0,0 +1,94 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.util.Date;
+
+
+/**
+ * 【请填写功能名称】编辑对象 store_menu
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】编辑对象")
+public class StoreMenuEditBo {
+
+    /** 菜单ID */
+    @ApiModelProperty("菜单ID")
+    private Long menuId;
+
+    /** 菜单名称 */
+    @ApiModelProperty("菜单名称")
+    private String menuName;
+
+    /** 父菜单ID */
+    @ApiModelProperty("父菜单ID")
+    private Long parentId;
+
+    /** 显示顺序 */
+    @ApiModelProperty("显示顺序")
+    private Long orderNum;
+
+    /** 路由地址 */
+    @ApiModelProperty("路由地址")
+    private String path;
+
+    /** 组件路径 */
+    @ApiModelProperty("组件路径")
+    private String component;
+
+    /** 是否为外链(0是 1否) */
+    @ApiModelProperty("是否为外链(0是 1否)")
+    private Long isFrame;
+
+    /** 是否缓存(0缓存 1不缓存) */
+    @ApiModelProperty("是否缓存(0缓存 1不缓存)")
+    private Long isCache;
+
+    /** 菜单类型(M目录 C菜单 F按钮) */
+    @ApiModelProperty("菜单类型(M目录 C菜单 F按钮)")
+    private String menuType;
+
+    /** 菜单状态(1显示 0隐藏) */
+    @ApiModelProperty("菜单状态(1显示 0隐藏)")
+    private String visible;
+
+    /** 菜单状态(1正常 0停用) */
+    @ApiModelProperty("菜单状态(1正常 0停用)")
+    private String status;
+
+    /** 权限标识 */
+    @ApiModelProperty("权限标识")
+    private String perms;
+
+    /** 菜单图标 */
+    @ApiModelProperty("菜单图标")
+    private String icon;
+
+    /** 更新者 */
+    @ApiModelProperty("更新者")
+    private String updateBy;
+
+    /** 更新时间 */
+    @ApiModelProperty("更新时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /** 备注 */
+    @ApiModelProperty("备注")
+    private String remark;
+
+    /** 店铺ID */
+    @ApiModelProperty("店铺ID")
+    private Long storeId;
+
+
+    /** 商户ID */
+    @ApiModelProperty("商户ID")
+    private Long companyId;
+
+}

+ 81 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreMenuQueryBo.java

@@ -0,0 +1,81 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.HashMap;
+
+import com.zhongzheng.common.core.domain.BaseEntity;
+
+/**
+ * 【请填写功能名称】分页查询对象 store_menu
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel("【请填写功能名称】分页查询对象")
+public class StoreMenuQueryBo extends BaseEntity {
+
+	/** 分页大小 */
+	@ApiModelProperty("分页大小")
+	private Integer pageSize;
+	/** 当前页数 */
+	@ApiModelProperty("当前页数")
+	private Integer pageNum;
+	/** 排序列 */
+	@ApiModelProperty("排序列")
+	private String orderByColumn;
+	/** 排序的方向desc或者asc */
+	@ApiModelProperty(value = "排序的方向", example = "asc,desc")
+	private String isAsc;
+
+
+	/** 菜单名称 */
+	@ApiModelProperty("菜单名称")
+	private String menuName;
+	/** 父菜单ID */
+	@ApiModelProperty("父菜单ID")
+	private Long parentId;
+	/** 显示顺序 */
+	@ApiModelProperty("显示顺序")
+	private Long orderNum;
+	/** 路由地址 */
+	@ApiModelProperty("路由地址")
+	private String path;
+	/** 组件路径 */
+	@ApiModelProperty("组件路径")
+	private String component;
+	/** 是否为外链(0是 1否) */
+	@ApiModelProperty("是否为外链(0是 1否)")
+	private Long isFrame;
+	/** 是否缓存(0缓存 1不缓存) */
+	@ApiModelProperty("是否缓存(0缓存 1不缓存)")
+	private Long isCache;
+	/** 菜单类型(M目录 C菜单 F按钮) */
+	@ApiModelProperty("菜单类型(M目录 C菜单 F按钮)")
+	private String menuType;
+	/** 菜单状态(1显示 0隐藏) */
+	@ApiModelProperty("菜单状态(1显示 0隐藏)")
+	private String visible;
+	/** 菜单状态(1正常 0停用) */
+	@ApiModelProperty("菜单状态(1正常 0停用)")
+	private String status;
+	/** 权限标识 */
+	@ApiModelProperty("权限标识")
+	private String perms;
+	/** 菜单图标 */
+	@ApiModelProperty("菜单图标")
+	private String icon;
+	/** 店铺ID */
+	@ApiModelProperty("店铺ID")
+	private Long storeId;
+	/** 商户ID */
+	@ApiModelProperty("商户ID")
+	private Long companyId;
+}

+ 68 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreRoleAddBo.java

@@ -0,0 +1,68 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.util.Date;
+
+
+
+/**
+ * 【请填写功能名称】添加对象 store_role
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】添加对象")
+public class StoreRoleAddBo {
+
+    /** 角色名称 */
+    @ApiModelProperty("角色名称")
+    private String roleName;
+    /** 角色权限字符串 */
+    @ApiModelProperty("角色权限字符串")
+    private String roleKey;
+    /** 显示顺序 */
+    @ApiModelProperty("显示顺序")
+    private Long roleSort;
+    /** 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:本人数据权限 6业务层次数据权限) */
+    @ApiModelProperty("数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:本人数据权限 6业务层次数据权限)")
+    private String dataScope;
+    /** 菜单树选择项是否关联显示 */
+    @ApiModelProperty("菜单树选择项是否关联显示")
+    private Integer menuCheckStrictly;
+    /** 部门树选择项是否关联显示 */
+    @ApiModelProperty("部门树选择项是否关联显示")
+    private Integer deptCheckStrictly;
+    /** 角色状态(1正常 0停用) */
+    @ApiModelProperty("角色状态(1正常 0停用)")
+    private String status;
+    /** 删除标志(0代表存在 2代表删除) */
+    @ApiModelProperty("删除标志(0代表存在 2代表删除)")
+    private String delFlag;
+    /** 创建者 */
+    @ApiModelProperty("创建者")
+    private String createBy;
+    /** 创建时间 */
+    @ApiModelProperty("创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+    /** 更新者 */
+    @ApiModelProperty("更新者")
+    private String updateBy;
+    /** 更新时间 */
+    @ApiModelProperty("更新时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+    /** 备注 */
+    @ApiModelProperty("备注")
+    private String remark;
+    /** 店铺ID */
+    @ApiModelProperty("店铺ID")
+    private Long storeId;
+    /** 商户ID */
+    @ApiModelProperty("商户ID")
+    private Long companyId;
+}

+ 74 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreRoleEditBo.java

@@ -0,0 +1,74 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.util.Date;
+
+
+/**
+ * 【请填写功能名称】编辑对象 store_role
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】编辑对象")
+public class StoreRoleEditBo {
+
+    /** 角色ID */
+    @ApiModelProperty("角色ID")
+    private Long roleId;
+
+    /** 角色名称 */
+    @ApiModelProperty("角色名称")
+    private String roleName;
+
+    /** 角色权限字符串 */
+    @ApiModelProperty("角色权限字符串")
+    private String roleKey;
+
+    /** 显示顺序 */
+    @ApiModelProperty("显示顺序")
+    private Long roleSort;
+
+    /** 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:本人数据权限 6业务层次数据权限) */
+    @ApiModelProperty("数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:本人数据权限 6业务层次数据权限)")
+    private String dataScope;
+
+    /** 菜单树选择项是否关联显示 */
+    @ApiModelProperty("菜单树选择项是否关联显示")
+    private Integer menuCheckStrictly;
+
+    /** 部门树选择项是否关联显示 */
+    @ApiModelProperty("部门树选择项是否关联显示")
+    private Integer deptCheckStrictly;
+
+    /** 角色状态(1正常 0停用) */
+    @ApiModelProperty("角色状态(1正常 0停用)")
+    private String status;
+
+    /** 更新者 */
+    @ApiModelProperty("更新者")
+    private String updateBy;
+
+    /** 更新时间 */
+    @ApiModelProperty("更新时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /** 备注 */
+    @ApiModelProperty("备注")
+    private String remark;
+
+    /** 店铺ID */
+    @ApiModelProperty("店铺ID")
+    private Long storeId;
+
+
+    /** 商户ID */
+    @ApiModelProperty("商户ID")
+    private Long companyId;
+
+}

+ 27 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreRoleMenuAddBo.java

@@ -0,0 +1,27 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.util.Date;
+
+
+
+/**
+ * 【请填写功能名称】添加对象 store_role_menu
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】添加对象")
+public class StoreRoleMenuAddBo {
+
+    /** 店铺ID */
+    @ApiModelProperty("店铺ID")
+    private Long storeId;
+    /** 商户ID */
+    @ApiModelProperty("商户ID")
+    private Long companyId;
+}

+ 37 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreRoleMenuEditBo.java

@@ -0,0 +1,37 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.util.Date;
+
+
+/**
+ * 【请填写功能名称】编辑对象 store_role_menu
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】编辑对象")
+public class StoreRoleMenuEditBo {
+
+    /** 角色ID */
+    @ApiModelProperty("角色ID")
+    private Long roleId;
+
+    /** 菜单ID */
+    @ApiModelProperty("菜单ID")
+    private Long menuId;
+
+    /** 店铺ID */
+    @ApiModelProperty("店铺ID")
+    private Long storeId;
+
+
+    /** 商户ID */
+    @ApiModelProperty("商户ID")
+    private Long companyId;
+
+}

+ 45 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreRoleMenuQueryBo.java

@@ -0,0 +1,45 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.HashMap;
+
+import com.zhongzheng.common.core.domain.BaseEntity;
+
+/**
+ * 【请填写功能名称】分页查询对象 store_role_menu
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel("【请填写功能名称】分页查询对象")
+public class StoreRoleMenuQueryBo extends BaseEntity {
+
+	/** 分页大小 */
+	@ApiModelProperty("分页大小")
+	private Integer pageSize;
+	/** 当前页数 */
+	@ApiModelProperty("当前页数")
+	private Integer pageNum;
+	/** 排序列 */
+	@ApiModelProperty("排序列")
+	private String orderByColumn;
+	/** 排序的方向desc或者asc */
+	@ApiModelProperty(value = "排序的方向", example = "asc,desc")
+	private String isAsc;
+
+
+	/** 店铺ID */
+	@ApiModelProperty("店铺ID")
+	private Long storeId;
+	/** 商户ID */
+	@ApiModelProperty("商户ID")
+	private Long companyId;
+}

+ 66 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreRoleQueryBo.java

@@ -0,0 +1,66 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.HashMap;
+
+import com.zhongzheng.common.core.domain.BaseEntity;
+
+/**
+ * 【请填写功能名称】分页查询对象 store_role
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel("【请填写功能名称】分页查询对象")
+public class StoreRoleQueryBo extends BaseEntity {
+
+	/** 分页大小 */
+	@ApiModelProperty("分页大小")
+	private Integer pageSize;
+	/** 当前页数 */
+	@ApiModelProperty("当前页数")
+	private Integer pageNum;
+	/** 排序列 */
+	@ApiModelProperty("排序列")
+	private String orderByColumn;
+	/** 排序的方向desc或者asc */
+	@ApiModelProperty(value = "排序的方向", example = "asc,desc")
+	private String isAsc;
+
+
+	/** 角色名称 */
+	@ApiModelProperty("角色名称")
+	private String roleName;
+	/** 角色权限字符串 */
+	@ApiModelProperty("角色权限字符串")
+	private String roleKey;
+	/** 显示顺序 */
+	@ApiModelProperty("显示顺序")
+	private Long roleSort;
+	/** 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:本人数据权限 6业务层次数据权限) */
+	@ApiModelProperty("数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:本人数据权限 6业务层次数据权限)")
+	private String dataScope;
+	/** 菜单树选择项是否关联显示 */
+	@ApiModelProperty("菜单树选择项是否关联显示")
+	private Integer menuCheckStrictly;
+	/** 部门树选择项是否关联显示 */
+	@ApiModelProperty("部门树选择项是否关联显示")
+	private Integer deptCheckStrictly;
+	/** 角色状态(1正常 0停用) */
+	@ApiModelProperty("角色状态(1正常 0停用)")
+	private String status;
+	/** 店铺ID */
+	@ApiModelProperty("店铺ID")
+	private Long storeId;
+	/** 商户ID */
+	@ApiModelProperty("商户ID")
+	private Long companyId;
+}

+ 63 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreUserAddBo.java

@@ -0,0 +1,63 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.util.Date;
+
+
+
+/**
+ * 【请填写功能名称】添加对象 store_user
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】添加对象")
+public class StoreUserAddBo {
+
+    /** 账号 */
+    @ApiModelProperty("账号")
+    private String userAccount;
+    /** 昵称 */
+    @ApiModelProperty("昵称")
+    private String nickname;
+    /** 真实姓名 */
+    @ApiModelProperty("真实姓名")
+    private String realname;
+    /** 性别 1男 2女 */
+    @ApiModelProperty("性别 1男 2女")
+    private Integer sex;
+    /** 身份证号 */
+    @ApiModelProperty("身份证号")
+    private String idCard;
+    /** 手机号码 */
+    @ApiModelProperty("手机号码")
+    private String telphone;
+    /** 微信openid */
+    @ApiModelProperty("微信openid")
+    private String openId;
+    /** 微信unionId */
+    @ApiModelProperty("微信unionId")
+    private String unionId;
+    /** 公众号openid */
+    @ApiModelProperty("公众号openid")
+    private String gzhOpenId;
+    /** 添加时间 */
+    @ApiModelProperty("添加时间")
+    private Long createTime;
+    /** 修改时间 */
+    @ApiModelProperty("修改时间")
+    private Long updateTime;
+    /** 状态 1正常 0关闭 */
+    @ApiModelProperty("状态 1正常 0关闭")
+    private Integer status;
+    /** 店铺ID */
+    @ApiModelProperty("店铺ID")
+    private Long storeId;
+    /** 商户ID */
+    @ApiModelProperty("商户ID")
+    private Long companyId;
+}

+ 77 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreUserEditBo.java

@@ -0,0 +1,77 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.util.Date;
+
+
+/**
+ * 【请填写功能名称】编辑对象 store_user
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】编辑对象")
+public class StoreUserEditBo {
+
+    /** $column.columnComment */
+    @ApiModelProperty("$column.columnComment")
+    private Long userId;
+
+    /** 账号 */
+    @ApiModelProperty("账号")
+    private String userAccount;
+
+    /** 昵称 */
+    @ApiModelProperty("昵称")
+    private String nickname;
+
+    /** 真实姓名 */
+    @ApiModelProperty("真实姓名")
+    private String realname;
+
+    /** 性别 1男 2女 */
+    @ApiModelProperty("性别 1男 2女")
+    private Integer sex;
+
+    /** 身份证号 */
+    @ApiModelProperty("身份证号")
+    private String idCard;
+
+    /** 手机号码 */
+    @ApiModelProperty("手机号码")
+    private String telphone;
+
+    /** 微信openid */
+    @ApiModelProperty("微信openid")
+    private String openId;
+
+    /** 微信unionId */
+    @ApiModelProperty("微信unionId")
+    private String unionId;
+
+    /** 公众号openid */
+    @ApiModelProperty("公众号openid")
+    private String gzhOpenId;
+
+    /** 修改时间 */
+    @ApiModelProperty("修改时间")
+    private Long updateTime;
+
+    /** 状态 1正常 0关闭 */
+    @ApiModelProperty("状态 1正常 0关闭")
+    private Integer status;
+
+    /** 店铺ID */
+    @ApiModelProperty("店铺ID")
+    private Long storeId;
+
+
+    /** 商户ID */
+    @ApiModelProperty("商户ID")
+    private Long companyId;
+
+}

+ 75 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreUserQueryBo.java

@@ -0,0 +1,75 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.HashMap;
+
+import com.zhongzheng.common.core.domain.BaseEntity;
+
+/**
+ * 【请填写功能名称】分页查询对象 store_user
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel("【请填写功能名称】分页查询对象")
+public class StoreUserQueryBo extends BaseEntity {
+
+	/** 分页大小 */
+	@ApiModelProperty("分页大小")
+	private Integer pageSize;
+	/** 当前页数 */
+	@ApiModelProperty("当前页数")
+	private Integer pageNum;
+	/** 排序列 */
+	@ApiModelProperty("排序列")
+	private String orderByColumn;
+	/** 排序的方向desc或者asc */
+	@ApiModelProperty(value = "排序的方向", example = "asc,desc")
+	private String isAsc;
+
+
+	/** 账号 */
+	@ApiModelProperty("账号")
+	private String userAccount;
+	/** 昵称 */
+	@ApiModelProperty("昵称")
+	private String nickname;
+	/** 真实姓名 */
+	@ApiModelProperty("真实姓名")
+	private String realname;
+	/** 性别 1男 2女 */
+	@ApiModelProperty("性别 1男 2女")
+	private Integer sex;
+	/** 身份证号 */
+	@ApiModelProperty("身份证号")
+	private String idCard;
+	/** 手机号码 */
+	@ApiModelProperty("手机号码")
+	private String telphone;
+	/** 微信openid */
+	@ApiModelProperty("微信openid")
+	private String openId;
+	/** 微信unionId */
+	@ApiModelProperty("微信unionId")
+	private String unionId;
+	/** 公众号openid */
+	@ApiModelProperty("公众号openid")
+	private String gzhOpenId;
+	/** 状态 1正常 0关闭 */
+	@ApiModelProperty("状态 1正常 0关闭")
+	private Integer status;
+	/** 店铺ID */
+	@ApiModelProperty("店铺ID")
+	private Long storeId;
+	/** 商户ID */
+	@ApiModelProperty("商户ID")
+	private Long companyId;
+}

+ 27 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreUserRoleAddBo.java

@@ -0,0 +1,27 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.util.Date;
+
+
+
+/**
+ * 【请填写功能名称】添加对象 store_user_role
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】添加对象")
+public class StoreUserRoleAddBo {
+
+    /** 店铺ID */
+    @ApiModelProperty("店铺ID")
+    private Long storeId;
+    /** 商户ID */
+    @ApiModelProperty("商户ID")
+    private Long companyId;
+}

+ 37 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreUserRoleEditBo.java

@@ -0,0 +1,37 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.util.Date;
+
+
+/**
+ * 【请填写功能名称】编辑对象 store_user_role
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】编辑对象")
+public class StoreUserRoleEditBo {
+
+    /** 用户ID */
+    @ApiModelProperty("用户ID")
+    private Long userId;
+
+    /** 角色ID */
+    @ApiModelProperty("角色ID")
+    private Long roleId;
+
+    /** 店铺ID */
+    @ApiModelProperty("店铺ID")
+    private Long storeId;
+
+    /** 商户ID */
+    @ApiModelProperty("商户ID")
+    private Long companyId;
+
+
+}

+ 45 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/bo/StoreUserRoleQueryBo.java

@@ -0,0 +1,45 @@
+package com.zhongzheng.modules.store.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.HashMap;
+
+import com.zhongzheng.common.core.domain.BaseEntity;
+
+/**
+ * 【请填写功能名称】分页查询对象 store_user_role
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel("【请填写功能名称】分页查询对象")
+public class StoreUserRoleQueryBo extends BaseEntity {
+
+	/** 分页大小 */
+	@ApiModelProperty("分页大小")
+	private Integer pageSize;
+	/** 当前页数 */
+	@ApiModelProperty("当前页数")
+	private Integer pageNum;
+	/** 排序列 */
+	@ApiModelProperty("排序列")
+	private String orderByColumn;
+	/** 排序的方向desc或者asc */
+	@ApiModelProperty(value = "排序的方向", example = "asc,desc")
+	private String isAsc;
+
+
+	/** 店铺ID */
+	@ApiModelProperty("店铺ID")
+	private Long storeId;
+	/** 商户ID */
+	@ApiModelProperty("商户ID")
+	private Long companyId;
+}

+ 53 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/mapper/StoreMenuMapper.java

@@ -0,0 +1,53 @@
+package com.zhongzheng.modules.store.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhongzheng.common.core.domain.entity.store.StoreMenu;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+public interface StoreMenuMapper extends BaseMapper<StoreMenu> {
+
+    List<StoreMenu> selectMenuListByUserId(StoreMenu menu);
+    
+
+    /**
+     * 根据用户ID查询权限
+     *
+     * @param userId 用户ID
+     * @return 权限列表
+     */
+    List<String> selectMenuPermsByUserId(Long userId);
+
+    /**
+     * 根据用户ID查询菜单
+     *
+     * @return 菜单列表
+     */
+    List<StoreMenu> selectMenuTreeAll();
+
+    /**
+     * 根据用户ID查询菜单
+     *
+     * @param userId 用户ID
+     * @return 菜单列表
+     */
+    List<StoreMenu> selectMenuTreeByUserId(Long userId);
+
+    /**
+     * 根据角色ID查询菜单树信息
+     *
+     * @param roleId            角色ID
+     * @param menuCheckStrictly 菜单树选择项是否关联显示
+     * @return 选中菜单列表
+     */
+    List<Integer> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
+
+}

+ 26 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/mapper/StoreRoleMapper.java

@@ -0,0 +1,26 @@
+package com.zhongzheng.modules.store.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhongzheng.common.core.domain.entity.store.StoreRole;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+public interface StoreRoleMapper extends BaseMapper<StoreRole> {
+
+    /**
+     * 根据用户ID查询角色
+     *
+     * @param userId 用户ID
+     * @return 角色列表
+     */
+    List<StoreRole> selectRolePermissionByUserId(Long userId);
+
+    List<Integer> selectRoleListByUserId(Long userId);
+}

+ 16 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/mapper/StoreRoleMenuMapper.java

@@ -0,0 +1,16 @@
+package com.zhongzheng.modules.store.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhongzheng.common.core.domain.entity.store.StoreRoleMenu;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+public interface StoreRoleMenuMapper extends BaseMapper<StoreRoleMenu> {
+
+}

+ 31 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/mapper/StoreUserMapper.java

@@ -0,0 +1,31 @@
+package com.zhongzheng.modules.store.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhongzheng.common.core.domain.entity.TopSysUser;
+import com.zhongzheng.common.core.domain.entity.store.StoreUser;
+import com.zhongzheng.modules.course.bo.CourseBusinessQueryBo;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+public interface StoreUserMapper extends BaseMapper<StoreUser> {
+
+    StoreUser selectUserByUserName(String username);
+
+
+    /**
+     * 根据条件分页查询用户列表
+     *
+     * @param sysUser 用户信息
+     * @return 用户信息集合信息
+     */
+    List<StoreUser> selectUserList(StoreUser sysUser);
+
+}

+ 15 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/mapper/StoreUserRoleMapper.java

@@ -0,0 +1,15 @@
+package com.zhongzheng.modules.store.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhongzheng.common.core.domain.entity.store.StoreUserRole;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+public interface StoreUserRoleMapper extends BaseMapper<StoreUserRole> {
+
+}

+ 141 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/IStoreMenuService.java

@@ -0,0 +1,141 @@
+package com.zhongzheng.modules.store.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhongzheng.common.core.domain.entity.store.StoreMenu;
+import com.zhongzheng.modules.system.domain.vo.RouterVo;
+import com.zhongzheng.modules.top.util.TreeSelectStore;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 【请填写功能名称】Service接口
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+public interface IStoreMenuService extends IService<StoreMenu> {
+	/**
+	 * 根据用户查询系统菜单列表
+	 *
+	 * @param userId 用户ID
+	 * @return 菜单列表
+	 */
+	List<StoreMenu> selectMenuList(Long userId);
+
+	/**
+	 * 根据用户查询系统菜单列表
+	 *
+	 * @param menu   菜单信息
+	 * @param userId 用户ID
+	 * @return 菜单列表
+	 */
+	List<StoreMenu> selectMenuList(StoreMenu menu, Long userId);
+
+	/**
+	 * 根据用户ID查询权限
+	 *
+	 * @param userId 用户ID
+	 * @return 权限列表
+	 */
+	Set<String> selectMenuPermsByUserId(Long userId);
+
+	/**
+	 * 根据用户ID查询菜单树信息
+	 *
+	 * @param userId 用户ID
+	 * @return 菜单列表
+	 */
+	List<StoreMenu> selectMenuTreeByUserId(Long userId);
+
+	/**
+	 * 根据角色ID查询菜单树信息
+	 *
+	 * @param roleId 角色ID
+	 * @return 选中菜单列表
+	 */
+	List<Integer> selectMenuListByRoleId(Long roleId);
+
+	/**
+	 * 构建前端路由所需要的菜单
+	 *
+	 * @param menus 菜单列表
+	 * @return 路由列表
+	 */
+	List<RouterVo> buildMenus(List<StoreMenu> menus);
+
+	/**
+	 * 构建前端所需要树结构
+	 *
+	 * @param menus 菜单列表
+	 * @return 树结构列表
+	 */
+	List<StoreMenu> buildMenuTree(List<StoreMenu> menus);
+
+	/**
+	 * 构建前端所需要下拉树结构
+	 *
+	 * @param menus 菜单列表
+	 * @return 下拉树结构列表
+	 */
+	List<TreeSelectStore> buildMenuTreeSelect(List<StoreMenu> menus);
+
+	/**
+	 * 根据菜单ID查询信息
+	 *
+	 * @param menuId 菜单ID
+	 * @return 菜单信息
+	 */
+	StoreMenu selectMenuById(Long menuId);
+
+	/**
+	 * 是否存在菜单子节点
+	 *
+	 * @param menuId 菜单ID
+	 * @return 结果 true 存在 false 不存在
+	 */
+	boolean hasChildByMenuId(Long menuId);
+
+	/**
+	 * 查询菜单是否存在角色
+	 *
+	 * @param menuId 菜单ID
+	 * @return 结果 true 存在 false 不存在
+	 */
+	boolean checkMenuExistRole(Long menuId);
+
+	/**
+	 * 新增保存菜单信息
+	 *
+	 * @param menu 菜单信息
+	 * @return 结果
+	 */
+	int insertMenu(StoreMenu menu);
+
+	/**
+	 * 修改保存菜单信息
+	 *
+	 * @param menu 菜单信息
+	 * @return 结果
+	 */
+	int updateMenu(StoreMenu menu);
+
+	/**
+	 * 删除菜单管理信息
+	 *
+	 * @param menuId 菜单ID
+	 * @return 结果
+	 */
+	int deleteMenuById(Long menuId);
+
+	/**
+	 * 校验菜单名称是否唯一
+	 *
+	 * @param menu 菜单信息
+	 * @return 结果
+	 */
+	String checkMenuNameUnique(StoreMenu menu);
+
+	
+}

+ 53 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/IStoreRoleMenuService.java

@@ -0,0 +1,53 @@
+package com.zhongzheng.modules.store.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhongzheng.modules.store.bo.StoreRoleMenuAddBo;
+import com.zhongzheng.modules.store.bo.StoreRoleMenuEditBo;
+import com.zhongzheng.modules.store.bo.StoreRoleMenuQueryBo;
+import com.zhongzheng.common.core.domain.entity.store.StoreRoleMenu;
+import com.zhongzheng.modules.store.vo.StoreRoleMenuVo;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Service接口
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+public interface IStoreRoleMenuService extends IService<StoreRoleMenu> {
+	/**
+	 * 查询单个
+	 * @return
+	 */
+	StoreRoleMenuVo queryById(Long roleId);
+
+	/**
+	 * 查询列表
+	 */
+	List<StoreRoleMenuVo> queryList(StoreRoleMenuQueryBo bo);
+
+	/**
+	 * 根据新增业务对象插入【请填写功能名称】
+	 * @param bo 【请填写功能名称】新增业务对象
+	 * @return
+	 */
+	Boolean insertByAddBo(StoreRoleMenuAddBo bo);
+
+	/**
+	 * 根据编辑业务对象修改【请填写功能名称】
+	 * @param bo 【请填写功能名称】编辑业务对象
+	 * @return
+	 */
+	Boolean updateByEditBo(StoreRoleMenuEditBo bo);
+
+	/**
+	 * 校验并删除数据
+	 * @param ids 主键集合
+	 * @param isValid 是否校验,true-删除前校验,false-不校验
+	 * @return
+	 */
+	Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 127 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/IStoreRoleService.java

@@ -0,0 +1,127 @@
+package com.zhongzheng.modules.store.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhongzheng.common.core.domain.entity.store.StoreRole;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 【请填写功能名称】Service接口
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+public interface IStoreRoleService extends IService<StoreRole> {
+	/**
+	 * 根据条件分页查询角色数据
+	 *
+	 * @param role 角色信息
+	 * @return 角色数据集合信息
+	 */
+	List<StoreRole> selectRoleList(StoreRole role);
+
+	/**
+	 * 根据用户ID查询角色
+	 *
+	 * @param userId 用户ID
+	 * @return 权限列表
+	 */
+	Set<String> selectRolePermissionByUserId(Long userId);
+
+	/**
+	 * 查询所有角色
+	 *
+	 * @return 角色列表
+	 */
+	List<StoreRole> selectRoleAll();
+
+	/**
+	 * 根据用户ID获取角色选择框列表
+	 *
+	 * @param userId 用户ID
+	 * @return 选中角色ID列表
+	 */
+	List<Integer> selectRoleListByUserId(Long userId);
+
+	/**
+	 * 通过角色ID查询角色
+	 *
+	 * @param roleId 角色ID
+	 * @return 角色对象信息
+	 */
+	StoreRole selectRoleById(Long roleId);
+
+	/**
+	 * 校验角色名称是否唯一
+	 *
+	 * @param role 角色信息
+	 * @return 结果
+	 */
+	String checkRoleNameUnique(StoreRole role);
+
+	/**
+	 * 校验角色权限是否唯一
+	 *
+	 * @param role 角色信息
+	 * @return 结果
+	 */
+	String checkRoleKeyUnique(StoreRole role);
+
+	/**
+	 * 校验角色是否允许操作
+	 *
+	 * @param role 角色信息
+	 */
+	void checkRoleAllowed(StoreRole role);
+
+	/**
+	 * 通过角色ID查询角色使用数量
+	 *
+	 * @param roleId 角色ID
+	 * @return 结果
+	 */
+	int countUserRoleByRoleId(Long roleId);
+
+	/**
+	 * 新增保存角色信息
+	 *
+	 * @param role 角色信息
+	 * @return 结果
+	 */
+	int insertRole(StoreRole role);
+
+	/**
+	 * 修改保存角色信息
+	 *
+	 * @param role 角色信息
+	 * @return 结果
+	 */
+	int updateRole(StoreRole role);
+
+	/**
+	 * 修改角色状态
+	 *
+	 * @param role 角色信息
+	 * @return 结果
+	 */
+	int updateRoleStatus(StoreRole role);
+
+	/**
+	 * 修改数据权限信息
+	 *
+	 * @param role 角色信息
+	 * @return 结果
+	 */
+	int authDataScope(StoreRole role);
+
+
+	/**
+	 * 批量删除角色信息
+	 *
+	 * @param roleIds 需要删除的角色ID
+	 * @return 结果
+	 */
+	int deleteRoleByIds(Long[] roleIds);
+}

+ 53 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/IStoreUserRoleService.java

@@ -0,0 +1,53 @@
+package com.zhongzheng.modules.store.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhongzheng.modules.store.bo.StoreUserRoleAddBo;
+import com.zhongzheng.modules.store.bo.StoreUserRoleEditBo;
+import com.zhongzheng.modules.store.bo.StoreUserRoleQueryBo;
+import com.zhongzheng.common.core.domain.entity.store.StoreUserRole;
+import com.zhongzheng.modules.store.vo.StoreUserRoleVo;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Service接口
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+public interface IStoreUserRoleService extends IService<StoreUserRole> {
+	/**
+	 * 查询单个
+	 * @return
+	 */
+	StoreUserRoleVo queryById(Long userId);
+
+	/**
+	 * 查询列表
+	 */
+	List<StoreUserRoleVo> queryList(StoreUserRoleQueryBo bo);
+
+	/**
+	 * 根据新增业务对象插入【请填写功能名称】
+	 * @param bo 【请填写功能名称】新增业务对象
+	 * @return
+	 */
+	Boolean insertByAddBo(StoreUserRoleAddBo bo);
+
+	/**
+	 * 根据编辑业务对象修改【请填写功能名称】
+	 * @param bo 【请填写功能名称】编辑业务对象
+	 * @return
+	 */
+	Boolean updateByEditBo(StoreUserRoleEditBo bo);
+
+	/**
+	 * 校验并删除数据
+	 * @param ids 主键集合
+	 * @param isValid 是否校验,true-删除前校验,false-不校验
+	 * @return
+	 */
+	Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 85 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/IStoreUserService.java

@@ -0,0 +1,85 @@
+package com.zhongzheng.modules.store.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhongzheng.common.core.domain.entity.store.StoreUser;
+import com.zhongzheng.modules.user.bo.UserAppAccountLoginBo;
+import com.zhongzheng.modules.user.bo.UserAppSmsLoginBo;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 【请填写功能名称】Service接口
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+public interface IStoreUserService extends IService<StoreUser> {
+
+	StoreUser queryByUnionId(String unionId);
+
+    StoreUser selectUserByUserName(String username);
+
+    Map<String, Object> smsLogin(UserAppSmsLoginBo bo);
+
+	Map<String, Object> accountLogin(UserAppAccountLoginBo bo);
+
+    StoreUser selectUserById(Long userId);
+
+    /**
+     * 根据条件分页查询用户列表
+     *
+     * @param user 用户信息
+     * @return 用户信息集合信息
+     */
+    List<StoreUser> selectUserList(StoreUser user);
+
+
+    /**
+     * 校验用户名称是否唯一
+     *
+     * @param userName 用户名称
+     * @return 结果
+     */
+    String checkUserNameUnique(String userName);
+
+    /**
+     * 校验手机号码是否唯一
+     *
+     * @param user 用户信息
+     * @return 结果
+     */
+    String checkPhoneUnique(StoreUser user);
+
+    /**
+     * 校验用户是否允许操作
+     *
+     * @param user 用户信息
+     */
+    void checkUserAllowed(StoreUser user);
+
+    /**
+     * 新增用户信息
+     *
+     * @param user 用户信息
+     * @return 结果
+     */
+    int insertUser(StoreUser user);
+
+    /**
+     * 修改用户信息
+     *
+     * @param user 用户信息
+     * @return 结果
+     */
+    int updateUser(StoreUser user);
+
+    /**
+     * 修改用户状态
+     *
+     * @param user 用户信息
+     * @return 结果
+     */
+    int updateUserStatus(StoreUser user);
+}

+ 425 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/impl/StoreMenuServiceImpl.java

@@ -0,0 +1,425 @@
+package com.zhongzheng.modules.store.service.impl;
+
+import cn.hutool.core.lang.Validator;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhongzheng.common.constant.UserConstants;
+import com.zhongzheng.common.core.domain.entity.store.StoreMenu;
+import com.zhongzheng.common.core.domain.entity.store.StoreRole;
+import com.zhongzheng.common.core.domain.entity.store.StoreRoleMenu;
+import com.zhongzheng.common.core.domain.entity.store.StoreUser;
+import com.zhongzheng.common.utils.SecurityUtils;
+import com.zhongzheng.modules.store.mapper.StoreMenuMapper;
+import com.zhongzheng.modules.store.mapper.StoreRoleMapper;
+import com.zhongzheng.modules.store.mapper.StoreRoleMenuMapper;
+import com.zhongzheng.modules.store.service.IStoreMenuService;
+import com.zhongzheng.modules.store.service.IStoreUserService;
+import com.zhongzheng.modules.system.domain.vo.MetaVo;
+import com.zhongzheng.modules.system.domain.vo.RouterVo;
+import com.zhongzheng.modules.top.util.TreeSelectStore;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Service
+public class StoreMenuServiceImpl extends ServiceImpl<StoreMenuMapper, StoreMenu> implements IStoreMenuService {
+
+    public static final String PREMISSION_STRING = "perms[\"{0}\"]";
+
+    @Autowired
+    private StoreRoleMapper storeRoleMapper;
+
+    @Autowired
+    private StoreRoleMenuMapper storeRoleMenuMapper;
+
+    @Autowired
+    private IStoreUserService storeUserService;
+
+    /**
+     * 根据用户查询系统菜单列表
+     *
+     * @param userId 用户ID
+     * @return 菜单列表
+     */
+    @Override
+    public List<StoreMenu> selectMenuList(Long userId) {
+        return selectMenuList(new StoreMenu(), userId);
+    }
+
+    /**
+     * 查询系统菜单列表
+     *
+     * @param menu 菜单信息
+     * @return 菜单列表
+     */
+    @Override
+    public List<StoreMenu> selectMenuList(StoreMenu menu, Long userId) {
+        List<StoreMenu> menuList = null;
+        StoreUser sysUser = storeUserService.selectUserById(userId);
+        // 管理员显示所有菜单信息
+        if (sysUser.isAdmin()) {
+            menuList = list(new LambdaQueryWrapper<StoreMenu>()
+                    .like(StrUtil.isNotBlank(menu.getMenuName()),StoreMenu::getMenuName,menu.getMenuName())
+                    .eq(StrUtil.isNotBlank(menu.getVisible()),StoreMenu::getVisible,menu.getVisible())
+                    .eq(StrUtil.isNotBlank(menu.getStatus()),StoreMenu::getStatus,menu.getStatus())
+                    .orderByAsc(StoreMenu::getParentId)
+                    .orderByAsc(StoreMenu::getOrderNum));
+        } else {
+            menu.getParams().put("userId", userId);
+            menuList = baseMapper.selectMenuListByUserId(menu);
+        }
+        return menuList;
+    }
+
+    /**
+     * 根据用户ID查询权限
+     *
+     * @param userId 用户ID
+     * @return 权限列表
+     */
+    @Override
+    public Set<String> selectMenuPermsByUserId(Long userId) {
+        List<String> perms = baseMapper.selectMenuPermsByUserId(userId);
+        Set<String> permsSet = new HashSet<>();
+        for (String perm : perms) {
+            if (Validator.isNotEmpty(perm)) {
+                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
+            }
+        }
+        return permsSet;
+    }
+
+    /**
+     * 根据用户ID查询菜单
+     *
+     * @param userId 用户名称
+     * @return 菜单列表
+     */
+    @Override
+    public List<StoreMenu> selectMenuTreeByUserId(Long userId) {
+        List<StoreMenu> menus = null;
+        if (SecurityUtils.isTopAdmin(userId)) {
+            menus = baseMapper.selectMenuTreeAll();
+        } else {
+            menus = baseMapper.selectMenuTreeByUserId(userId);
+        }
+        return getChildPerms(menus, 0);
+    }
+
+    /**
+     * 根据角色ID查询菜单树信息
+     *
+     * @param roleId 角色ID
+     * @return 选中菜单列表
+     */
+    @Override
+    public List<Integer> selectMenuListByRoleId(Long roleId) {
+        StoreRole role = storeRoleMapper.selectById(roleId);
+        return baseMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly());
+    }
+
+    /**
+     * 构建前端路由所需要的菜单
+     *
+     * @param menus 菜单列表
+     * @return 路由列表
+     */
+    @Override
+    public List<RouterVo> buildMenus(List<StoreMenu> menus) {
+        List<RouterVo> routers = new LinkedList<RouterVo>();
+        for (StoreMenu menu : menus) {
+            RouterVo router = new RouterVo();
+            router.setMenuId(menu.getMenuId());
+            router.setHidden("1".equals(menu.getVisible()));
+            router.setName(getRouteName(menu));
+            router.setPath(getRouterPath(menu));
+            router.setComponent(getComponent(menu));
+            router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StrUtil.equals("1", menu.getIsCache().toString())));
+            List<StoreMenu> cMenus = menu.getChildren();
+            if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType())) {
+                router.setAlwaysShow(true);
+                router.setRedirect("noRedirect");
+                router.setChildren(buildMenus(cMenus));
+            } else if (isMenuFrame(menu)) {
+                router.setMeta(null);
+                List<RouterVo> childrenList = new ArrayList<RouterVo>();
+                RouterVo children = new RouterVo();
+                children.setPath(menu.getPath());
+                children.setComponent(menu.getComponent());
+                children.setName(StrUtil.upperFirst(menu.getPath()));
+                children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StrUtil.equals("1", menu.getIsCache().toString())));
+                childrenList.add(children);
+                router.setChildren(childrenList);
+            }
+            routers.add(router);
+        }
+        return routers;
+    }
+
+    /**
+     * 构建前端所需要树结构
+     *
+     * @param menus 菜单列表
+     * @return 树结构列表
+     */
+    @Override
+    public List<StoreMenu> buildMenuTree(List<StoreMenu> menus) {
+        List<StoreMenu> returnList = new ArrayList<StoreMenu>();
+        List<Long> tempList = new ArrayList<Long>();
+        for (StoreMenu dept : menus) {
+            tempList.add(dept.getMenuId());
+        }
+        for (Iterator<StoreMenu> iterator = menus.iterator(); iterator.hasNext(); ) {
+            StoreMenu menu = (StoreMenu) iterator.next();
+            // 如果是顶级节点, 遍历该父节点的所有子节点
+            if (!tempList.contains(menu.getParentId())) {
+                recursionFn(menus, menu);
+                returnList.add(menu);
+            }
+        }
+        if (returnList.isEmpty()) {
+            returnList = menus;
+        }
+        return returnList;
+    }
+
+    /**
+     * 构建前端所需要下拉树结构
+     *
+     * @param menus 菜单列表
+     * @return 下拉树结构列表
+     */
+    @Override
+    public List<TreeSelectStore> buildMenuTreeSelect(List<StoreMenu> menus) {
+        List<StoreMenu> menuTrees = buildMenuTree(menus);
+        return menuTrees.stream().map(TreeSelectStore::new).collect(Collectors.toList());
+    }
+
+    /**
+     * 根据菜单ID查询信息
+     *
+     * @param menuId 菜单ID
+     * @return 菜单信息
+     */
+    @Override
+    public StoreMenu selectMenuById(Long menuId) {
+        return getById(menuId);
+    }
+
+    /**
+     * 是否存在菜单子节点
+     *
+     * @param menuId 菜单ID
+     * @return 结果
+     */
+    @Override
+    public boolean hasChildByMenuId(Long menuId) {
+        int result = count(new LambdaQueryWrapper<StoreMenu>().eq(StoreMenu::getParentId,menuId));
+        return result > 0 ? true : false;
+    }
+
+    /**
+     * 查询菜单使用数量
+     *
+     * @param menuId 菜单ID
+     * @return 结果
+     */
+    @Override
+    public boolean checkMenuExistRole(Long menuId) {
+        int result = storeRoleMenuMapper.selectCount(new LambdaQueryWrapper<StoreRoleMenu>().eq(StoreRoleMenu::getMenuId,menuId));
+        return result > 0 ? true : false;
+    }
+
+    /**
+     * 新增保存菜单信息
+     *
+     * @param menu 菜单信息
+     * @return 结果
+     */
+    @Override
+    public int insertMenu(StoreMenu menu) {
+        return baseMapper.insert(menu);
+    }
+
+    /**
+     * 修改保存菜单信息
+     *
+     * @param menu 菜单信息
+     * @return 结果
+     */
+    @Override
+    public int updateMenu(StoreMenu menu) {
+        return baseMapper.updateById(menu);
+    }
+
+    /**
+     * 删除菜单管理信息
+     *
+     * @param menuId 菜单ID
+     * @return 结果
+     */
+    @Override
+    public int deleteMenuById(Long menuId) {
+        return baseMapper.deleteById(menuId);
+    }
+
+    /**
+     * 校验菜单名称是否唯一
+     *
+     * @param menu 菜单信息
+     * @return 结果
+     */
+    @Override
+    public String checkMenuNameUnique(StoreMenu menu) {
+        Long menuId = Validator.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
+        StoreMenu info = getOne(new LambdaQueryWrapper<StoreMenu>()
+                .eq(StoreMenu::getMenuName,menu.getMenuName())
+                .eq(StoreMenu::getParentId,menu.getParentId())
+                .last("limit 1"));
+        if (Validator.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue()) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+
+    /**
+     * 获取路由名称
+     *
+     * @param menu 菜单信息
+     * @return 路由名称
+     */
+    public String getRouteName(StoreMenu menu) {
+        String routerName = StrUtil.upperFirst(menu.getPath());
+        // 非外链并且是一级目录(类型为目录)
+        if (isMenuFrame(menu)) {
+            routerName = StrUtil.EMPTY;
+        }
+        return routerName;
+    }
+
+    /**
+     * 获取路由地址
+     *
+     * @param menu 菜单信息
+     * @return 路由地址
+     */
+    public String getRouterPath(StoreMenu menu) {
+        String routerPath = menu.getPath();
+        // 非外链并且是一级目录(类型为目录)
+        if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
+                && UserConstants.NO_FRAME.equals(menu.getIsFrame())) {
+            routerPath = "/" + menu.getPath();
+        }
+        // 非外链并且是一级目录(类型为菜单)
+        else if (isMenuFrame(menu)) {
+            routerPath = "/";
+        }
+        return routerPath;
+    }
+
+    /**
+     * 获取组件信息
+     *
+     * @param menu 菜单信息
+     * @return 组件信息
+     */
+    public String getComponent(StoreMenu menu) {
+        String component = UserConstants.LAYOUT;
+        if (StrUtil.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) {
+            component = menu.getComponent();
+        } else if (StrUtil.isEmpty(menu.getComponent()) && isParentView(menu)) {
+            component = UserConstants.PARENT_VIEW;
+        }
+        return component;
+    }
+
+    /**
+     * 是否为菜单内部跳转
+     *
+     * @param menu 菜单信息
+     * @return 结果
+     */
+    public boolean isMenuFrame(StoreMenu menu) {
+        return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType())
+                && menu.getIsFrame().equals(UserConstants.NO_FRAME);
+    }
+
+    /**
+     * 是否为parent_view组件
+     *
+     * @param menu 菜单信息
+     * @return 结果
+     */
+    public boolean isParentView(StoreMenu menu) {
+        return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType());
+    }
+
+    /**
+     * 根据父节点的ID获取所有子节点
+     *
+     * @param list     分类表
+     * @param parentId 传入的父节点ID
+     * @return String
+     */
+    public List<StoreMenu> getChildPerms(List<StoreMenu> list, int parentId) {
+        List<StoreMenu> returnList = new ArrayList<StoreMenu>();
+        for (Iterator<StoreMenu> iterator = list.iterator(); iterator.hasNext(); ) {
+            StoreMenu t = (StoreMenu) iterator.next();
+            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
+            if (t.getParentId() == parentId) {
+                recursionFn(list, t);
+                returnList.add(t);
+            }
+        }
+        return returnList;
+    }
+
+    /**
+     * 递归列表
+     *
+     * @param list
+     * @param t
+     */
+    private void recursionFn(List<StoreMenu> list, StoreMenu t) {
+        // 得到子节点列表
+        List<StoreMenu> childList = getChildList(list, t);
+        t.setChildren(childList);
+        for (StoreMenu tChild : childList) {
+            if (hasChild(list, tChild)) {
+                recursionFn(list, tChild);
+            }
+        }
+    }
+
+    /**
+     * 得到子节点列表
+     */
+    private List<StoreMenu> getChildList(List<StoreMenu> list, StoreMenu t) {
+        List<StoreMenu> tlist = new ArrayList<StoreMenu>();
+        Iterator<StoreMenu> it = list.iterator();
+        while (it.hasNext()) {
+            StoreMenu n = (StoreMenu) it.next();
+            if (n.getParentId().longValue() == t.getMenuId().longValue()) {
+                tlist.add(n);
+            }
+        }
+        return tlist;
+    }
+
+    /**
+     * 判断是否有子节点
+     */
+    private boolean hasChild(List<StoreMenu> list, StoreMenu t) {
+        return getChildList(list, t).size() > 0 ? true : false;
+    }
+}

+ 94 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/impl/StoreRoleMenuServiceImpl.java

@@ -0,0 +1,94 @@
+package com.zhongzheng.modules.store.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.pagehelper.Page;
+import com.zhongzheng.common.core.domain.entity.store.StoreRoleMenu;
+import com.zhongzheng.modules.store.bo.StoreRoleMenuAddBo;
+import com.zhongzheng.modules.store.bo.StoreRoleMenuEditBo;
+import com.zhongzheng.modules.store.bo.StoreRoleMenuQueryBo;
+import com.zhongzheng.modules.store.mapper.StoreRoleMenuMapper;
+import com.zhongzheng.modules.store.service.IStoreRoleMenuService;
+import com.zhongzheng.modules.store.vo.StoreRoleMenuVo;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Service
+public class StoreRoleMenuServiceImpl extends ServiceImpl<StoreRoleMenuMapper, StoreRoleMenu> implements IStoreRoleMenuService {
+
+    @Override
+    public StoreRoleMenuVo queryById(Long roleId){
+        StoreRoleMenu db = this.baseMapper.selectById(roleId);
+        return BeanUtil.toBean(db, StoreRoleMenuVo.class);
+    }
+
+    @Override
+    public List<StoreRoleMenuVo> queryList(StoreRoleMenuQueryBo bo) {
+        LambdaQueryWrapper<StoreRoleMenu> lqw = Wrappers.lambdaQuery();
+        lqw.eq(bo.getStoreId() != null, StoreRoleMenu::getStoreId, bo.getStoreId());
+        lqw.eq(bo.getCompanyId() != null, StoreRoleMenu::getCompanyId, bo.getCompanyId());
+        return entity2Vo(this.list(lqw));
+    }
+
+    /**
+    * 实体类转化成视图对象
+    *
+    * @param collection 实体类集合
+    * @return
+    */
+    private List<StoreRoleMenuVo> entity2Vo(Collection<StoreRoleMenu> collection) {
+        List<StoreRoleMenuVo> voList = collection.stream()
+                .map(any -> BeanUtil.toBean(any, StoreRoleMenuVo.class))
+                .collect(Collectors.toList());
+        if (collection instanceof Page) {
+            Page<StoreRoleMenu> page = (Page<StoreRoleMenu>)collection;
+            Page<StoreRoleMenuVo> pageVo = new Page<>();
+            BeanUtil.copyProperties(page,pageVo);
+            pageVo.addAll(voList);
+            voList = pageVo;
+        }
+        return voList;
+    }
+
+    @Override
+    public Boolean insertByAddBo(StoreRoleMenuAddBo bo) {
+        StoreRoleMenu add = BeanUtil.toBean(bo, StoreRoleMenu.class);
+        validEntityBeforeSave(add);
+        return this.save(add);
+    }
+
+    @Override
+    public Boolean updateByEditBo(StoreRoleMenuEditBo bo) {
+        StoreRoleMenu update = BeanUtil.toBean(bo, StoreRoleMenu.class);
+        validEntityBeforeSave(update);
+        return this.updateById(update);
+    }
+
+    /**
+     * 保存前的数据校验
+     *
+     * @param entity 实体类数据
+     */
+    private void validEntityBeforeSave(StoreRoleMenu entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return this.removeByIds(ids);
+    }
+}

+ 276 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/impl/StoreRoleServiceImpl.java

@@ -0,0 +1,276 @@
+package com.zhongzheng.modules.store.service.impl;
+
+import cn.hutool.core.lang.Validator;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhongzheng.common.annotation.DataScope;
+import com.zhongzheng.common.constant.UserConstants;
+import com.zhongzheng.common.core.domain.entity.store.StoreRole;
+import com.zhongzheng.common.core.domain.entity.store.StoreRoleMenu;
+import com.zhongzheng.common.core.domain.entity.store.StoreUserRole;
+import com.zhongzheng.common.exception.CustomException;
+import com.zhongzheng.common.utils.spring.SpringUtils;
+import com.zhongzheng.modules.store.mapper.StoreRoleMapper;
+import com.zhongzheng.modules.store.mapper.StoreRoleMenuMapper;
+import com.zhongzheng.modules.store.mapper.StoreUserRoleMapper;
+import com.zhongzheng.modules.store.service.IStoreRoleService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Service
+public class StoreRoleServiceImpl extends ServiceImpl<StoreRoleMapper, StoreRole> implements IStoreRoleService {
+
+    @Autowired
+    private StoreRoleMenuMapper storeRoleMenuMapper;
+
+    @Autowired
+    private StoreUserRoleMapper storeUserRoleMapper;
+    
+
+
+    /**
+     * 根据条件分页查询角色数据
+     *
+     * @param role 角色信息
+     * @return 角色数据集合信息
+     */
+    @Override
+    @DataScope(deptAlias = "d")
+    public List<StoreRole> selectRoleList(StoreRole role) {
+        Map<String, Object> params = role.getParams();
+        Object dataScope = params.get("dataScope");
+        return list(new LambdaQueryWrapper<StoreRole>()
+                .like(StrUtil.isNotBlank(role.getRoleName()), StoreRole::getRoleName, role.getRoleName())
+                .eq(StrUtil.isNotBlank(role.getStatus()), StoreRole::getStatus, role.getStatus())
+                .in(role.getStatusArray()!=null, StoreRole::getStatus, role.getStatusArray())
+                .like(StrUtil.isNotBlank(role.getRoleKey()), StoreRole::getRoleKey, role.getRoleKey())
+                .apply(Validator.isNotEmpty(params.get("beginTime")),
+                        "date_format(create_time,'%y%m%d') >= date_format({0},'%y%m%d')",
+                        params.get("beginTime"))
+                .apply(Validator.isNotEmpty(params.get("endTime")),
+                        "date_format(create_time,'%y%m%d') <= date_format({0},'%y%m%d')",
+                        params.get("endTime"))
+                .apply(dataScope != null, dataScope != null ? dataScope.toString() : null)
+                .orderByAsc(StoreRole::getRoleSort));
+    }
+
+    /**
+     * 根据用户ID查询权限
+     *
+     * @param userId 用户ID
+     * @return 权限列表
+     */
+    @Override
+    public Set<String> selectRolePermissionByUserId(Long userId) {
+        List<StoreRole> perms = baseMapper.selectRolePermissionByUserId(userId);
+        Set<String> permsSet = new HashSet<>();
+        for (StoreRole perm : perms) {
+            if (Validator.isNotNull(perm)) {
+                permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
+            }
+        }
+        return permsSet;
+    }
+
+    /**
+     * 查询所有角色
+     *
+     * @return 角色列表
+     */
+    @Override
+    public List<StoreRole> selectRoleAll() {
+        return SpringUtils.getAopProxy(this).selectRoleList(new StoreRole());
+    }
+
+    /**
+     * 根据用户ID获取角色选择框列表
+     *
+     * @param userId 用户ID
+     * @return 选中角色ID列表
+     */
+    @Override
+    public List<Integer> selectRoleListByUserId(Long userId) {
+        return baseMapper.selectRoleListByUserId(userId);
+    }
+
+    /**
+     * 通过角色ID查询角色
+     *
+     * @param roleId 角色ID
+     * @return 角色对象信息
+     */
+    @Override
+    public StoreRole selectRoleById(Long roleId) {
+        StoreRole sysRole = getById(roleId);
+        return sysRole;
+    }
+
+    /**
+     * 校验角色名称是否唯一
+     *
+     * @param role 角色信息
+     * @return 结果
+     */
+    @Override
+    public String checkRoleNameUnique(StoreRole role) {
+        Long roleId = Validator.isNull(role.getRoleId()) ? -1L : role.getRoleId();
+        StoreRole info = getOne(new LambdaQueryWrapper<StoreRole>()
+                .eq(StoreRole::getRoleName, role.getRoleName()).last("limit 1"));
+        if (Validator.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 校验角色权限是否唯一
+     *
+     * @param role 角色信息
+     * @return 结果
+     */
+    @Override
+    public String checkRoleKeyUnique(StoreRole role) {
+        Long roleId = Validator.isNull(role.getRoleId()) ? -1L : role.getRoleId();
+        StoreRole info = getOne(new LambdaQueryWrapper<StoreRole>()
+                .eq(StoreRole::getRoleKey, role.getRoleKey()).last("limit 1"));
+        if (Validator.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 校验角色是否允许操作
+     *
+     * @param role 角色信息
+     */
+    @Override
+    public void checkRoleAllowed(StoreRole role) {
+        if (Validator.isNotNull(role.getRoleId()) && role.isAdmin()) {
+            throw new CustomException("不允许操作超级管理员角色");
+        }
+    }
+
+    /**
+     * 通过角色ID查询角色使用数量
+     *
+     * @param roleId 角色ID
+     * @return 结果
+     */
+    @Override
+    public int countUserRoleByRoleId(Long roleId) {
+        return storeUserRoleMapper.selectCount(new LambdaQueryWrapper<StoreUserRole>().eq(StoreUserRole::getRoleId, roleId));
+    }
+
+    /**
+     * 新增保存角色信息
+     *
+     * @param role 角色信息
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int insertRole(StoreRole role) {
+        // 新增角色信息
+        baseMapper.insert(role);
+        return insertRoleMenu(role);
+    }
+
+    /**
+     * 修改保存角色信息
+     *
+     * @param role 角色信息
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int updateRole(StoreRole role) {
+        // 修改角色信息
+        baseMapper.updateById(role);
+        // 删除角色与菜单关联
+        storeRoleMenuMapper.delete(new LambdaQueryWrapper<StoreRoleMenu>().eq(StoreRoleMenu::getRoleId, role.getRoleId()));
+        return insertRoleMenu(role);
+    }
+
+    /**
+     * 修改角色状态
+     *
+     * @param role 角色信息
+     * @return 结果
+     */
+    @Override
+    public int updateRoleStatus(StoreRole role) {
+        return baseMapper.updateById(role);
+    }
+
+    /**
+     * 修改数据权限信息
+     *
+     * @param role 角色信息
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int authDataScope(StoreRole role) {
+        // 修改角色信息
+        baseMapper.updateById(role);
+        
+        return 1;
+    }
+
+    /**
+     * 新增角色菜单信息
+     *
+     * @param role 角色对象
+     */
+    public int insertRoleMenu(StoreRole role) {
+        int rows = 1;
+        // 新增用户与角色管理
+        List<StoreRoleMenu> list = new ArrayList<StoreRoleMenu>();
+        for (Long menuId : role.getMenuIds()) {
+            StoreRoleMenu rm = new StoreRoleMenu();
+            rm.setRoleId(role.getRoleId());
+            rm.setMenuId(menuId);
+            list.add(rm);
+        }
+        if (list.size() > 0) {
+            for (StoreRoleMenu sysRoleMenu : list) {
+                rows += storeRoleMenuMapper.insert(sysRoleMenu);
+            }
+        }
+        return rows;
+    }
+
+
+    /**
+     * 批量删除角色信息
+     *
+     * @param roleIds 需要删除的角色ID
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int deleteRoleByIds(Long[] roleIds) {
+        for (Long roleId : roleIds) {
+            checkRoleAllowed(new StoreRole(roleId));
+            StoreRole role = selectRoleById(roleId);
+            if (countUserRoleByRoleId(roleId) > 0) {
+                throw new CustomException(String.format("%1$s已分配,不能删除", role.getRoleName()));
+            }
+        }
+        List<Long> ids = Arrays.asList(roleIds);
+        // 删除角色与菜单关联
+        storeRoleMenuMapper.delete(new LambdaQueryWrapper<StoreRoleMenu>().in(StoreRoleMenu::getRoleId, ids));
+        return baseMapper.deleteBatchIds(ids);
+    }
+}

+ 94 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/service/impl/StoreUserRoleServiceImpl.java

@@ -0,0 +1,94 @@
+package com.zhongzheng.modules.store.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.pagehelper.Page;
+import com.zhongzheng.common.core.domain.entity.store.StoreUserRole;
+import com.zhongzheng.modules.store.bo.StoreUserRoleAddBo;
+import com.zhongzheng.modules.store.bo.StoreUserRoleEditBo;
+import com.zhongzheng.modules.store.bo.StoreUserRoleQueryBo;
+import com.zhongzheng.modules.store.mapper.StoreUserRoleMapper;
+import com.zhongzheng.modules.store.service.IStoreUserRoleService;
+import com.zhongzheng.modules.store.vo.StoreUserRoleVo;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Service
+public class StoreUserRoleServiceImpl extends ServiceImpl<StoreUserRoleMapper, StoreUserRole> implements IStoreUserRoleService {
+
+    @Override
+    public StoreUserRoleVo queryById(Long userId){
+        StoreUserRole db = this.baseMapper.selectById(userId);
+        return BeanUtil.toBean(db, StoreUserRoleVo.class);
+    }
+
+    @Override
+    public List<StoreUserRoleVo> queryList(StoreUserRoleQueryBo bo) {
+        LambdaQueryWrapper<StoreUserRole> lqw = Wrappers.lambdaQuery();
+        lqw.eq(bo.getStoreId() != null, StoreUserRole::getStoreId, bo.getStoreId());
+        lqw.eq(bo.getCompanyId() != null, StoreUserRole::getCompanyId, bo.getCompanyId());
+        return entity2Vo(this.list(lqw));
+    }
+
+    /**
+    * 实体类转化成视图对象
+    *
+    * @param collection 实体类集合
+    * @return
+    */
+    private List<StoreUserRoleVo> entity2Vo(Collection<StoreUserRole> collection) {
+        List<StoreUserRoleVo> voList = collection.stream()
+                .map(any -> BeanUtil.toBean(any, StoreUserRoleVo.class))
+                .collect(Collectors.toList());
+        if (collection instanceof Page) {
+            Page<StoreUserRole> page = (Page<StoreUserRole>)collection;
+            Page<StoreUserRoleVo> pageVo = new Page<>();
+            BeanUtil.copyProperties(page,pageVo);
+            pageVo.addAll(voList);
+            voList = pageVo;
+        }
+        return voList;
+    }
+
+    @Override
+    public Boolean insertByAddBo(StoreUserRoleAddBo bo) {
+        StoreUserRole add = BeanUtil.toBean(bo, StoreUserRole.class);
+        validEntityBeforeSave(add);
+        return this.save(add);
+    }
+
+    @Override
+    public Boolean updateByEditBo(StoreUserRoleEditBo bo) {
+        StoreUserRole update = BeanUtil.toBean(bo, StoreUserRole.class);
+        validEntityBeforeSave(update);
+        return this.updateById(update);
+    }
+
+    /**
+     * 保存前的数据校验
+     *
+     * @param entity 实体类数据
+     */
+    private void validEntityBeforeSave(StoreUserRole entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return this.removeByIds(ids);
+    }
+}

+ 85 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/vo/StoreMenuVo.java

@@ -0,0 +1,85 @@
+package com.zhongzheng.modules.store.vo;
+
+import com.zhongzheng.common.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+
+
+/**
+ * 【请填写功能名称】视图对象 mall_package
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】视图对象")
+public class StoreMenuVo {
+	private static final long serialVersionUID = 1L;
+
+	/** 菜单ID */
+	@ApiModelProperty("菜单ID")
+	private Long menuId;
+
+	/** 菜单名称 */
+	@Excel(name = "菜单名称")
+	@ApiModelProperty("菜单名称")
+	private String menuName;
+	/** 父菜单ID */
+	@Excel(name = "父菜单ID")
+	@ApiModelProperty("父菜单ID")
+	private Long parentId;
+	/** 显示顺序 */
+	@Excel(name = "显示顺序")
+	@ApiModelProperty("显示顺序")
+	private Long orderNum;
+	/** 路由地址 */
+	@Excel(name = "路由地址")
+	@ApiModelProperty("路由地址")
+	private String path;
+	/** 组件路径 */
+	@Excel(name = "组件路径")
+	@ApiModelProperty("组件路径")
+	private String component;
+	/** 是否为外链(0是 1否) */
+	@Excel(name = "是否为外链" , readConverterExp = "0=是,1=否")
+	@ApiModelProperty("是否为外链(0是 1否)")
+	private Long isFrame;
+	/** 是否缓存(0缓存 1不缓存) */
+	@Excel(name = "是否缓存" , readConverterExp = "0=缓存,1=不缓存")
+	@ApiModelProperty("是否缓存(0缓存 1不缓存)")
+	private Long isCache;
+	/** 菜单类型(M目录 C菜单 F按钮) */
+	@Excel(name = "菜单类型" , readConverterExp = "M=目录,C=菜单,F=按钮")
+	@ApiModelProperty("菜单类型(M目录 C菜单 F按钮)")
+	private String menuType;
+	/** 菜单状态(1显示 0隐藏) */
+	@Excel(name = "菜单状态" , readConverterExp = "1=显示,0=隐藏")
+	@ApiModelProperty("菜单状态(1显示 0隐藏)")
+	private String visible;
+	/** 菜单状态(1正常 0停用) */
+	@Excel(name = "菜单状态" , readConverterExp = "1=正常,0=停用")
+	@ApiModelProperty("菜单状态(1正常 0停用)")
+	private String status;
+	/** 权限标识 */
+	@Excel(name = "权限标识")
+	@ApiModelProperty("权限标识")
+	private String perms;
+	/** 菜单图标 */
+	@Excel(name = "菜单图标")
+	@ApiModelProperty("菜单图标")
+	private String icon;
+	/** 备注 */
+	@Excel(name = "备注")
+	@ApiModelProperty("备注")
+	private String remark;
+	/** 店铺ID */
+	@Excel(name = "店铺ID")
+	@ApiModelProperty("店铺ID")
+	private Long storeId;
+	/** 商户ID */
+	@Excel(name = "商户ID")
+	@ApiModelProperty("商户ID")
+	private Long companyId;
+}

+ 35 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/vo/StoreRoleMenuVo.java

@@ -0,0 +1,35 @@
+package com.zhongzheng.modules.store.vo;
+
+import com.zhongzheng.common.annotation.Excel;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.util.Date;
+
+
+
+/**
+ * 【请填写功能名称】视图对象 mall_package
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】视图对象")
+public class StoreRoleMenuVo {
+	private static final long serialVersionUID = 1L;
+
+	/** 角色ID */
+	@ApiModelProperty("角色ID")
+	private Long roleId;
+
+	/** 店铺ID */
+	@Excel(name = "店铺ID")
+	@ApiModelProperty("店铺ID")
+	private Long storeId;
+	/** 商户ID */
+	@Excel(name = "商户ID")
+	@ApiModelProperty("商户ID")
+	private Long companyId;
+}

+ 67 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/vo/StoreRoleVo.java

@@ -0,0 +1,67 @@
+package com.zhongzheng.modules.store.vo;
+
+import com.zhongzheng.common.annotation.Excel;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.util.Date;
+
+
+
+/**
+ * 【请填写功能名称】视图对象 mall_package
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】视图对象")
+public class StoreRoleVo {
+	private static final long serialVersionUID = 1L;
+
+	/** 角色ID */
+	@ApiModelProperty("角色ID")
+	private Long roleId;
+
+	/** 角色名称 */
+	@Excel(name = "角色名称")
+	@ApiModelProperty("角色名称")
+	private String roleName;
+	/** 角色权限字符串 */
+	@Excel(name = "角色权限字符串")
+	@ApiModelProperty("角色权限字符串")
+	private String roleKey;
+	/** 显示顺序 */
+	@Excel(name = "显示顺序")
+	@ApiModelProperty("显示顺序")
+	private Long roleSort;
+	/** 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:本人数据权限 6业务层次数据权限) */
+	@Excel(name = "数据范围" , readConverterExp = "1=:全部数据权限,2=:自定数据权限,3=:本部门数据权限,4=:本部门及以下数据权限,5=:本人数据权限,6=业务层次数据权限")
+	@ApiModelProperty("数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:本人数据权限 6业务层次数据权限)")
+	private String dataScope;
+	/** 菜单树选择项是否关联显示 */
+	@Excel(name = "菜单树选择项是否关联显示")
+	@ApiModelProperty("菜单树选择项是否关联显示")
+	private Integer menuCheckStrictly;
+	/** 部门树选择项是否关联显示 */
+	@Excel(name = "部门树选择项是否关联显示")
+	@ApiModelProperty("部门树选择项是否关联显示")
+	private Integer deptCheckStrictly;
+	/** 角色状态(1正常 0停用) */
+	@Excel(name = "角色状态" , readConverterExp = "1=正常,0=停用")
+	@ApiModelProperty("角色状态(1正常 0停用)")
+	private String status;
+	/** 备注 */
+	@Excel(name = "备注")
+	@ApiModelProperty("备注")
+	private String remark;
+	/** 店铺ID */
+	@Excel(name = "店铺ID")
+	@ApiModelProperty("店铺ID")
+	private Long storeId;
+	/** 商户ID */
+	@Excel(name = "商户ID")
+	@ApiModelProperty("商户ID")
+	private Long companyId;
+}

+ 35 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/vo/StoreUserRoleVo.java

@@ -0,0 +1,35 @@
+package com.zhongzheng.modules.store.vo;
+
+import com.zhongzheng.common.annotation.Excel;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.util.Date;
+
+
+
+/**
+ * 【请填写功能名称】视图对象 mall_package
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】视图对象")
+public class StoreUserRoleVo {
+	private static final long serialVersionUID = 1L;
+
+	/** 用户ID */
+	@ApiModelProperty("用户ID")
+	private Long userId;
+
+	/** 店铺ID */
+	@Excel(name = "店铺ID")
+	@ApiModelProperty("店铺ID")
+	private Long storeId;
+	/** 商户ID */
+	@Excel(name = "商户ID")
+	@ApiModelProperty("商户ID")
+	private Long companyId;
+}

+ 75 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/store/vo/StoreUserVo.java

@@ -0,0 +1,75 @@
+package com.zhongzheng.modules.store.vo;
+
+import com.zhongzheng.common.annotation.Excel;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.util.Date;
+
+
+
+/**
+ * 【请填写功能名称】视图对象 mall_package
+ *
+ * @author ruoyi
+ * @date 2023-05-25
+ */
+@Data
+@ApiModel("【请填写功能名称】视图对象")
+public class StoreUserVo {
+	private static final long serialVersionUID = 1L;
+
+	/** $pkColumn.columnComment */
+	@ApiModelProperty("$pkColumn.columnComment")
+	private Long userId;
+
+	/** 账号 */
+	@Excel(name = "账号")
+	@ApiModelProperty("账号")
+	private String userAccount;
+	/** 昵称 */
+	@Excel(name = "昵称")
+	@ApiModelProperty("昵称")
+	private String nickname;
+	/** 真实姓名 */
+	@Excel(name = "真实姓名")
+	@ApiModelProperty("真实姓名")
+	private String realname;
+	/** 性别 1男 2女 */
+	@Excel(name = "性别 1男 2女")
+	@ApiModelProperty("性别 1男 2女")
+	private Integer sex;
+	/** 身份证号 */
+	@Excel(name = "身份证号")
+	@ApiModelProperty("身份证号")
+	private String idCard;
+	/** 手机号码 */
+	@Excel(name = "手机号码")
+	@ApiModelProperty("手机号码")
+	private String telphone;
+	/** 微信openid */
+	@Excel(name = "微信openid")
+	@ApiModelProperty("微信openid")
+	private String openId;
+	/** 微信unionId */
+	@Excel(name = "微信unionId")
+	@ApiModelProperty("微信unionId")
+	private String unionId;
+	/** 公众号openid */
+	@Excel(name = "公众号openid")
+	@ApiModelProperty("公众号openid")
+	private String gzhOpenId;
+	/** 状态 1正常 0关闭 */
+	@Excel(name = "状态 1正常 0关闭")
+	@ApiModelProperty("状态 1正常 0关闭")
+	private Integer status;
+	/** 店铺ID */
+	@Excel(name = "店铺ID")
+	@ApiModelProperty("店铺ID")
+	private Long storeId;
+	/** 商户ID */
+	@Excel(name = "商户ID")
+	@ApiModelProperty("商户ID")
+	private Long companyId;
+}

+ 44 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/top/util/TreeSelectStore.java

@@ -0,0 +1,44 @@
+package com.zhongzheng.modules.top.util;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.zhongzheng.common.core.domain.entity.store.StoreMenu;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Treeselect树结构实体类
+ * 
+ * @author zhongzheng
+ */
+
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+public class TreeSelectStore implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 节点ID */
+    private Long id;
+
+    /** 节点名称 */
+    private String label;
+
+    /** 子节点 */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    private List<TreeSelectStore> children;
+
+
+    public TreeSelectStore(StoreMenu menu)
+    {
+        this.id = menu.getMenuId();
+        this.label = menu.getMenuName();
+        this.children = menu.getChildren().stream().map(TreeSelectStore::new).collect(Collectors.toList());
+    }
+
+}

+ 146 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/user/entity/ClientLoginStoreUser.java

@@ -0,0 +1,146 @@
+package com.zhongzheng.modules.user.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.zhongzheng.common.core.domain.entity.store.StoreUser;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * 登录用户身份权限
+ *
+ * @author zhongzheng
+ */
+
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+public class ClientLoginStoreUser implements UserDetails
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 用户唯一标识
+     */
+    private String token;
+
+    /**
+     * 登录时间
+     */
+    private Long loginTime;
+
+    /**
+     * 过期时间
+     */
+    private Long expireTime;
+
+    /**
+     * 登录IP地址
+     */
+    private String ipaddr;
+
+    /**
+     * 登录地点
+     */
+    private String loginLocation;
+
+    /**
+     * 浏览器类型
+     */
+    private String browser;
+
+    /**
+     * 操作系统
+     */
+    private String os;
+
+    /**
+     * 权限列表
+     */
+    private Set<String> permissions;
+
+
+    /**
+     * 用户信息
+     */
+    private StoreUser user;
+
+
+
+    public ClientLoginStoreUser(StoreUser user, Set<String> permissions)
+    {
+        this.user = user;
+        this.permissions = permissions;
+    }
+
+    @JsonIgnore
+    @Override
+    public String getPassword()
+    {
+        return user.getPassword();
+    }
+
+    @Override
+    public String getUsername()
+    {
+        return user.getUserAccount();
+    }
+
+    /**
+     * 账户是否未过期,过期无法验证
+     */
+    @JsonIgnore
+    @Override
+    public boolean isAccountNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 指定用户是否解锁,锁定的用户无法进行身份验证
+     *
+     * @return
+     */
+    @JsonIgnore
+    @Override
+    public boolean isAccountNonLocked()
+    {
+        return true;
+    }
+
+    /**
+     * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
+     *
+     * @return
+     */
+    @JsonIgnore
+    @Override
+    public boolean isCredentialsNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 是否可用 ,禁用的用户不能身份验证
+     *
+     * @return
+     */
+    @JsonIgnore
+    @Override
+    public boolean isEnabled()
+    {
+        return true;
+    }
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities()
+    {
+        return null;
+    }
+
+}

+ 23 - 0
zhongzheng-system/src/main/resources/mapper/modules/goods/GoodsCategoryMapper.xml

@@ -0,0 +1,23 @@
+<?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="com.zhongzheng.modules.goods.mapper.GoodsCategoryMapper">
+
+    <select id="queryList" parameterType="com.zhongzheng.modules.goods.bo.GoodsCategoryQueryBo" resultType="com.zhongzheng.modules.goods.vo.GoodsCategoryVo">
+        select * from goods_category where 1=1
+        <if test="parentId != null and parentId != ''">
+            AND parent_id = #{parentId}
+        </if>
+        <if test="categoryName != null and categoryName != ''">
+            AND category_name like concat('%', #{categoryName}, '%')
+        </if>
+        <if test="statusList != null and statusList.size()!=0 ">
+            AND status in
+            <foreach collection="statusList" item="item" index="index" open="(" close=")" separator=",">
+                #{item}
+            </foreach>
+        </if>
+    </select>
+
+</mapper>

+ 120 - 0
zhongzheng-system/src/main/resources/mapper/modules/store/StoreMenuMapper.xml

@@ -0,0 +1,120 @@
+<?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="com.zhongzheng.modules.store.mapper.StoreMenuMapper">
+
+    <resultMap type="com.zhongzheng.common.core.domain.entity.store.StoreMenu" id="StoreMenuResult">
+        <result property="menuId" column="menu_id"/>
+        <result property="menuName" column="menu_name"/>
+        <result property="parentId" column="parent_id"/>
+        <result property="orderNum" column="order_num"/>
+        <result property="path" column="path"/>
+        <result property="component" column="component"/>
+        <result property="isFrame" column="is_frame"/>
+        <result property="isCache" column="is_cache"/>
+        <result property="menuType" column="menu_type"/>
+        <result property="visible" column="visible"/>
+        <result property="status" column="status"/>
+        <result property="perms" column="perms"/>
+        <result property="icon" column="icon"/>
+        <result property="createBy" column="create_by"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateBy" column="update_by"/>
+        <result property="updateTime" column="update_time"/>
+        <result property="remark" column="remark"/>
+        <result property="storeId" column="store_id"/>
+        <result property="companyId" column="company_id"/>
+    </resultMap>
+
+    <select id="selectMenuListByUserId" parameterType="com.zhongzheng.common.core.domain.entity.store.StoreMenu" resultMap="StoreMenuResult">
+        select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status,
+        ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
+        from store_menu m
+        left join store_role_menu rm on m.menu_id = rm.menu_id
+        left join store_user_role ur on rm.role_id = ur.role_id
+        left join store_role ro on ur.role_id = ro.role_id
+        where ur.user_id = #{params.userId}
+        <if test="menuName != null and menuName != ''">
+            AND menu_name like concat('%', #{menuName}, '%')
+        </if>
+        <if test="visible != null and visible != ''">
+            AND visible = #{visible}
+        </if>
+        <if test="status != null and status != ''">
+            AND m.status = #{status}
+        </if>
+        order by m.parent_id, m.order_num
+    </select>
+
+    <select id="selectMenuPermsByUserId" parameterType="Long" resultType="String">
+        select distinct m.perms
+        from store_menu m
+                 left join store_role_menu rm on m.menu_id = rm.menu_id
+                 left join store_user_role ur on rm.role_id = ur.role_id
+                 left join store_role r on r.role_id = ur.role_id
+        where m.status = '1'
+          and r.status = '1'
+          and ur.user_id = #{userId}
+    </select>
+
+    <select id="selectMenuTreeAll" resultMap="StoreMenuResult">
+        select distinct m.menu_id,
+                        m.parent_id,
+                        m.menu_name,
+                        m.path,
+                        m.component,
+                        m.visible,
+                        m.status,
+                        ifnull(m.perms, '') as perms,
+                        m.is_frame,
+                        m.is_cache,
+                        m.menu_type,
+                        m.icon,
+                        m.order_num,
+                        m.create_time
+        from store_menu m
+        where m.menu_type in ('M', 'C')
+          and m.status = '1'
+        order by m.parent_id, m.order_num
+    </select>
+
+    <select id="selectMenuTreeByUserId" parameterType="Long" resultMap="StoreMenuResult">
+        select distinct m.menu_id,
+                        m.parent_id,
+                        m.menu_name,
+                        m.path,
+                        m.component,
+                        m.visible,
+                        m.status,
+                        ifnull(m.perms, '') as perms,
+                        m.is_frame,
+                        m.is_cache,
+                        m.menu_type,
+                        m.icon,
+                        m.order_num,
+                        m.create_time
+        from store_menu m
+                 left join store_role_menu rm on m.menu_id = rm.menu_id
+                 left join store_user_role ur on rm.role_id = ur.role_id
+                 left join store_role ro on ur.role_id = ro.role_id
+                 left join store_user u on ur.user_id = u.user_id
+        where u.user_id = #{userId}
+          and m.menu_type in ('M', 'C')
+          and m.status = 1
+          AND ro.status = 1
+        order by m.parent_id, m.order_num
+    </select>
+
+    <select id="selectMenuListByRoleId" resultType="Integer">
+        select m.menu_id
+        from store_menu m
+        left join store_role_menu rm on m.menu_id = rm.menu_id
+        where rm.role_id = #{roleId}
+        <if test="menuCheckStrictly">
+            and m.menu_id not in (select m.parent_id from store_menu m inner join store_role_menu rm on m.menu_id =
+            rm.menu_id and rm.role_id = #{roleId})
+        </if>
+        order by m.parent_id, m.order_num
+    </select>
+</mapper>

+ 56 - 0
zhongzheng-system/src/main/resources/mapper/modules/store/StoreRoleMapper.xml

@@ -0,0 +1,56 @@
+<?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="com.zhongzheng.modules.store.mapper.StoreRoleMapper">
+
+    <resultMap type="com.zhongzheng.common.core.domain.entity.store.StoreRole" id="StoreRoleResult">
+        <result property="roleId" column="role_id"/>
+        <result property="roleName" column="role_name"/>
+        <result property="roleKey" column="role_key"/>
+        <result property="roleSort" column="role_sort"/>
+        <result property="dataScope" column="data_scope"/>
+        <result property="menuCheckStrictly" column="menu_check_strictly"/>
+        <result property="deptCheckStrictly" column="dept_check_strictly"/>
+        <result property="status" column="status"/>
+        <result property="delFlag" column="del_flag"/>
+        <result property="createBy" column="create_by"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateBy" column="update_by"/>
+        <result property="updateTime" column="update_time"/>
+        <result property="remark" column="remark"/>
+        <result property="storeId" column="store_id"/>
+        <result property="companyId" column="company_id"/>
+    </resultMap>
+
+    <sql id="selectRoleVo">
+        select distinct r.role_id,
+                        r.role_name,
+                        r.role_key,
+                        r.role_sort,
+                        r.data_scope,
+                        r.menu_check_strictly,
+                        r.dept_check_strictly,
+                        r.status,
+                        r.del_flag,
+                        r.create_time,
+                        r.remark
+        from store_role r
+                 left join store_user_role ur on ur.role_id = r.role_id
+                 left join store_user u on u.user_id = ur.user_id
+    </sql>
+
+    <select id="selectRolePermissionByUserId" parameterType="Long" resultMap="StoreRoleResult">
+        <include refid="selectRoleVo"/>
+        WHERE r.del_flag = '0' and ur.user_id = #{userId}
+    </select>
+
+    <select id="selectRoleListByUserId" parameterType="Long" resultType="Integer">
+        select r.role_id
+        from store_role r
+                 left join store_user_role ur on ur.role_id = r.role_id
+                 left join store_user u on u.user_id = ur.user_id
+        where u.user_id = #{userId}
+    </select>
+
+</mapper>

+ 15 - 0
zhongzheng-system/src/main/resources/mapper/modules/store/StoreRoleMenuMapper.xml

@@ -0,0 +1,15 @@
+<?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="com.zhongzheng.modules.store.mapper.StoreRoleMenuMapper">
+
+    <resultMap type="com.zhongzheng.common.core.domain.entity.store.StoreRoleMenu" id="StoreRoleMenuResult">
+        <result property="roleId" column="role_id"/>
+        <result property="menuId" column="menu_id"/>
+        <result property="storeId" column="store_id"/>
+        <result property="companyId" column="company_id"/>
+    </resultMap>
+
+
+</mapper>

+ 69 - 0
zhongzheng-system/src/main/resources/mapper/modules/store/StoreUserMapper.xml

@@ -0,0 +1,69 @@
+<?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="com.zhongzheng.modules.store.mapper.StoreUserMapper">
+
+    <resultMap type="com.zhongzheng.common.core.domain.entity.store.StoreUser" id="StoreUserResult">
+        <result property="userId" column="user_id"/>
+        <result property="userAccount" column="user_account"/>
+        <result property="nickname" column="nickname"/>
+        <result property="realname" column="realname"/>
+        <result property="sex" column="sex"/>
+        <result property="idCard" column="id_card"/>
+        <result property="telphone" column="telphone"/>
+        <result property="openId" column="open_id"/>
+        <result property="unionId" column="union_id"/>
+        <result property="gzhOpenId" column="gzh_open_id"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateTime" column="update_time"/>
+        <result property="status" column="status"/>
+        <result property="storeId" column="store_id"/>
+        <result property="companyId" column="company_id"/>
+    </resultMap>
+
+
+    <select id="selectUserByUserName" parameterType="String" resultMap="StoreUserResult">
+        select * from store_user
+        where (u.user_account = #{userName} or u.telphone = #{userName,typeHandler=com.zhongzheng.common.type.EncryptHandler} or u.id_card = #{userName,typeHandler=com.zhongzheng.common.type.EncryptHandler}) and u.`status` != -1
+    </select>
+
+    <select id="selectUserList" parameterType="com.zhongzheng.common.core.domain.entity.store.StoreUser" resultType="com.zhongzheng.common.core.domain.entity.store.StoreUser">
+        select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.password, u.sex,
+        u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, u.code from
+        store_user u
+        <if test="roleName != null and roleName != ''">
+            left join store_user_role ur on ur.user_id = u.user_id
+            left join store_role r on ur.role_id = r.role_id
+        </if>
+        where u.del_flag = '0'
+        <if test="roleName != null and roleName != ''">
+            AND r.role_name = #{roleName}
+        </if>
+        <if test="userName != null and userName != ''">
+            AND u.user_name like concat('%', #{userName}, '%')
+        </if>
+        <if test="status != null and status != ''">
+            AND u.status = #{status}
+        </if>
+        <if test="phonenumber != null and phonenumber != ''">
+            AND u.phonenumber like concat('%', #{phonenumber}, '%')
+        </if>
+        <if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
+            AND date_format(u.create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
+        </if>
+        <if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
+            AND date_format(u.create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
+        </if>
+        <if test="statusArray != null and statusArray.size()!=0 ">
+            AND u.status in
+            <foreach collection="statusArray" item="item" index="index" open="(" close=")" separator=",">
+                #{item}
+            </foreach>
+        </if>
+        order by u.create_time desc
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+</mapper>

+ 15 - 0
zhongzheng-system/src/main/resources/mapper/modules/store/StoreUserRoleMapper.xml

@@ -0,0 +1,15 @@
+<?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="com.zhongzheng.modules.store.mapper.StoreUserRoleMapper">
+
+    <resultMap type="com.zhongzheng.common.core.domain.entity.store.StoreUserRole" id="StoreUserRoleResult">
+        <result property="userId" column="user_id"/>
+        <result property="roleId" column="role_id"/>
+        <result property="storeId" column="store_id"/>
+        <result property="companyId" column="company_id"/>
+    </resultMap>
+
+
+</mapper>