diff --git a/README.md b/README.md
index 5827e91e..e677fdec 100644
--- a/README.md
+++ b/README.md
@@ -238,7 +238,9 @@ snowy
QQ技术群:732230670(已满)、685395081
-微信技术群:因群达到200人以上,需加微信拉群
+微信技术群:
+
+因群达到200人以上,需加微信拉群,禁止群内艾特群主及管理员,私信提问技术问题无时间精力回答(免开尊口),请群内互动互助才是建群的意义,否则我认为你没有加群的必要
diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/enums/CommonGenderEnum.java b/snowy-common/src/main/java/vip/xiaonuo/common/enums/CommonGenderEnum.java
new file mode 100644
index 00000000..15171076
--- /dev/null
+++ b/snowy-common/src/main/java/vip/xiaonuo/common/enums/CommonGenderEnum.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.common.enums;
+
+import lombok.Getter;
+import vip.xiaonuo.common.exception.CommonException;
+
+/**
+ * 通用性别枚举
+ *
+ * @author xuyuxiang
+ * @date 2022/7/13 17:48
+ **/
+@Getter
+public enum CommonGenderEnum {
+
+ /** 未知 */
+ UNKNOWN("未知"),
+
+ /** 男 */
+ MAN("男"),
+
+ /** 女 */
+ WOMAN("女");
+
+ private final String value;
+
+ CommonGenderEnum(String value) {
+ this.value = value.toLowerCase();
+ }
+}
diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/listener/CommonDataChangeEventCenter.java b/snowy-common/src/main/java/vip/xiaonuo/common/listener/CommonDataChangeEventCenter.java
index ef29901d..b36bb2cb 100644
--- a/snowy-common/src/main/java/vip/xiaonuo/common/listener/CommonDataChangeEventCenter.java
+++ b/snowy-common/src/main/java/vip/xiaonuo/common/listener/CommonDataChangeEventCenter.java
@@ -191,7 +191,7 @@ public class CommonDataChangeEventCenter {
* @author xuyuxiang
* @date 2023/3/3 10:22
**/
- public static void doDeleteWithDataId(String dataType, List dataIdList) {
+ public static void doDeleteWithDataIdList(String dataType, List dataIdList) {
for (CommonDataChangeListener listener : listenerList) {
listener.doDeleteWithDataIdList(dataType, dataIdList);
}
diff --git a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevDictApi.java b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevDictApi.java
index 36a9d904..07b8f3b8 100644
--- a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevDictApi.java
+++ b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevDictApi.java
@@ -19,4 +19,12 @@ package vip.xiaonuo.dev.api;
* @date 2022/9/2 15:58
*/
public interface DevDictApi {
+
+ /**
+ * 根据类型跟子类型获得翻译后的label
+ *
+ * @author yubaoshan
+ * @date 2025/6/6 13:04
+ */
+ String getDictLabel(String typeCode, String value);
}
diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthClientController.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthClientController.java
index 5b20dbc5..75a13127 100644
--- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthClientController.java
+++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthClientController.java
@@ -26,10 +26,7 @@ import vip.xiaonuo.auth.core.annotation.SaClientCheckLogin;
import vip.xiaonuo.auth.core.enums.SaClientTypeEnum;
import vip.xiaonuo.auth.core.pojo.SaBaseClientLoginUser;
import vip.xiaonuo.auth.core.util.StpClientUtil;
-import vip.xiaonuo.auth.modular.login.param.AuthAccountPasswordLoginParam;
-import vip.xiaonuo.auth.modular.login.param.AuthGetPhoneValidCodeParam;
-import vip.xiaonuo.auth.modular.login.param.AuthPhoneValidCodeLoginParam;
-import vip.xiaonuo.auth.modular.login.param.AuthRegisterParam;
+import vip.xiaonuo.auth.modular.login.param.*;
import vip.xiaonuo.auth.modular.login.result.AuthPicValidCodeResult;
import vip.xiaonuo.auth.modular.login.service.AuthService;
import vip.xiaonuo.common.pojo.CommonResult;
@@ -65,25 +62,38 @@ public class AuthClientController {
}
/**
- * C端获取手机验证码
+ * C端获取手机登录验证码
*
* @author xuyuxiang
* @date 2022/7/8 9:26
**/
@ApiOperationSupport(order = 2)
- @Operation(summary = "C端获取手机验证码")
+ @Operation(summary = "C端获取手机登录验证码")
@GetMapping("/auth/c/getPhoneValidCode")
public CommonResult getPhoneValidCode(@Valid AuthGetPhoneValidCodeParam authGetPhoneValidCodeParam) {
return CommonResult.data(authService.getPhoneValidCode(authGetPhoneValidCodeParam, SaClientTypeEnum.C.getValue()));
}
+ /**
+ * C端获取邮箱登录验证码
+ *
+ * @author xuyuxiang
+ * @date 2022/7/8 9:26
+ **/
+ @ApiOperationSupport(order = 3)
+ @Operation(summary = "C端获取邮箱登录验证码")
+ @GetMapping("/auth/c/getEmailValidCode")
+ public CommonResult getEmailValidCode(@Valid AuthGetEmailValidCodeParam authGetEmailValidCodeParam) {
+ return CommonResult.data(authService.getEmailValidCode(authGetEmailValidCodeParam, SaClientTypeEnum.C.getValue()));
+ }
+
/**
* C端账号密码登录
*
* @author xuyuxiang
* @date 2021/10/15 13:12
**/
- @ApiOperationSupport(order = 3)
+ @ApiOperationSupport(order = 4)
@Operation(summary = "C端账号密码登录")
@PostMapping("/auth/c/doLogin")
public CommonResult doLogin(@RequestBody @Valid AuthAccountPasswordLoginParam authAccountPasswordLoginParam) {
@@ -96,20 +106,33 @@ public class AuthClientController {
* @author xuyuxiang
* @date 2021/10/15 13:12
**/
- @ApiOperationSupport(order = 4)
+ @ApiOperationSupport(order = 5)
@Operation(summary = "C端手机验证码登录")
@PostMapping("/auth/c/doLoginByPhone")
public CommonResult doLoginByPhone(@RequestBody @Valid AuthPhoneValidCodeLoginParam authPhoneValidCodeLoginParam) {
return CommonResult.data(authService.doLoginByPhone(authPhoneValidCodeLoginParam, SaClientTypeEnum.C.getValue()));
}
+ /**
+ * C端邮箱验证码登录
+ *
+ * @author xuyuxiang
+ * @date 2021/10/15 13:12
+ **/
+ @ApiOperationSupport(order = 6)
+ @Operation(summary = "C端邮箱验证码登录")
+ @PostMapping("/auth/c/doLoginByEmail")
+ public CommonResult doLoginByEmail(@RequestBody @Valid AuthEmailValidCodeLoginParam authEmailValidCodeLoginParam) {
+ return CommonResult.data(authService.doLoginByEmail(authEmailValidCodeLoginParam, SaClientTypeEnum.C.getValue()));
+ }
+
/**
* C端退出
*
* @author xuyuxiang
* @date 2021/10/15 13:12
**/
- @ApiOperationSupport(order = 5)
+ @ApiOperationSupport(order = 7)
@Operation(summary = "C端退出")
@SaClientCheckLogin
@GetMapping("/auth/c/doLogout")
@@ -124,7 +147,7 @@ public class AuthClientController {
* @author xuyuxiang
* @date 2021/10/15 13:12
**/
- @ApiOperationSupport(order = 6)
+ @ApiOperationSupport(order = 8)
@Operation(summary = "C端获取用户信息")
@SaClientCheckLogin
@GetMapping("/auth/c/getLoginUser")
@@ -138,7 +161,7 @@ public class AuthClientController {
* @author xuyuxiang
* @date 2021/10/15 13:12
**/
- @ApiOperationSupport(order = 7)
+ @ApiOperationSupport(order = 9)
@Operation(summary = "C端注册")
@PostMapping("/auth/c/register")
public CommonResult register(@RequestBody @Valid AuthRegisterParam authRegisterParam) {
diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java
index 1449431a..6545e0f5 100644
--- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java
+++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java
@@ -242,7 +242,7 @@ public class BizOrgServiceImpl extends ServiceImpl impleme
this.removeByIds(toDeleteOrgIdList);
// 发布删除事件
- CommonDataChangeEventCenter.doDeleteWithDataId(BizDataTypeEnum.ORG.getValue(), toDeleteOrgIdList);
+ CommonDataChangeEventCenter.doDeleteWithDataIdList(BizDataTypeEnum.ORG.getValue(), toDeleteOrgIdList);
}
}
diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/service/impl/BizPositionServiceImpl.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/service/impl/BizPositionServiceImpl.java
index a1967ee8..95233c60 100644
--- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/service/impl/BizPositionServiceImpl.java
+++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/service/impl/BizPositionServiceImpl.java
@@ -190,7 +190,7 @@ public class BizPositionServiceImpl extends ServiceImpl impl
bizUserExtService.remove(new LambdaQueryWrapper().in(BizUserExt::getUserId, bizUserIdList));
// 发布删除事件
- CommonDataChangeEventCenter.doDeleteWithDataId(BizDataTypeEnum.USER.getValue(), bizUserIdList);
+ CommonDataChangeEventCenter.doDeleteWithDataIdList(BizDataTypeEnum.USER.getValue(), bizUserIdList);
}
}
diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserServiceImpl.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserServiceImpl.java
index 72c44791..390bc212 100644
--- a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserServiceImpl.java
+++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserServiceImpl.java
@@ -54,6 +54,7 @@ import vip.xiaonuo.client.modular.user.service.ClientUserExtService;
import vip.xiaonuo.client.modular.user.service.ClientUserPasswordService;
import vip.xiaonuo.client.modular.user.service.ClientUserService;
import vip.xiaonuo.common.cache.CommonCacheOperator;
+import vip.xiaonuo.common.enums.CommonGenderEnum;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.page.CommonPageRequest;
@@ -942,6 +943,7 @@ public class ClientUserServiceImpl extends ServiceImpl implements DevConfigService {
+ /** 缓存前缀 */
private static final String CONFIG_CACHE_KEY = "dev-config:";
+ /** B端注册是否开启 */
+ private static final String SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_B";
+
+ /** C端注册是否开启 */
+ private static final String SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_C_KEY = "SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_C";
+
+ /** B端手机号登录是否开启 */
+ private static final String SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_B";
+
+ /** C端手机号登录是否开启 */
+ private static final String SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_C_KEY = "SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_C";
+
+ /** B端邮箱登录是否开启 */
+ private static final String SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_B";
+
+ /** C端邮箱登录是否开启 */
+ private static final String SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_C_KEY = "SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_C";
+
@Resource
private CommonCacheOperator commonCacheOperator;
@@ -91,9 +111,20 @@ public class DevConfigServiceImpl extends ServiceImpl sysBaseList() {
- DevConfigListParam devConfigListParam = new DevConfigListParam();
- devConfigListParam.setCategory(DevConfigCategoryEnum.SYS_BASE.getValue());
- return this.list(devConfigListParam);
+ LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
+ // 查询部分字段
+ lambdaQueryWrapper.select(DevConfig::getId, DevConfig::getConfigKey, DevConfig::getConfigValue,
+ DevConfig::getCategory, DevConfig::getSortCode, DevConfig::getRemark);
+ // 类型为系统基础的
+ lambdaQueryWrapper.eq(DevConfig::getCategory, DevConfigCategoryEnum.SYS_BASE.getValue());
+ // 或key为特殊的几个
+ lambdaQueryWrapper.or().in(DevConfig::getConfigKey, CollectionUtil.newArrayList(SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_B_KEY,
+ SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_C_KEY,
+ SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_B_KEY,
+ SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_C_KEY,
+ SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_B_KEY,
+ SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_C_KEY));
+ return this.list(lambdaQueryWrapper);
}
@Override
diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/provider/DevDictApiProvider.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/provider/DevDictApiProvider.java
index e9a5df0d..112f7fa3 100644
--- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/provider/DevDictApiProvider.java
+++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/provider/DevDictApiProvider.java
@@ -12,8 +12,10 @@
*/
package vip.xiaonuo.dev.modular.dict.provider;
+import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import vip.xiaonuo.dev.api.DevDictApi;
+import vip.xiaonuo.dev.modular.dict.service.DevDictService;
/**
* 字典API接口实现类
@@ -23,4 +25,17 @@ import vip.xiaonuo.dev.api.DevDictApi;
*/
@Service
public class DevDictApiProvider implements DevDictApi {
+
+ @Resource
+ private DevDictService devDictService;
+
+ /**
+ * 根据类型跟子类型获得翻译后的label
+ *
+ * @author yubaoshan
+ * @date 2025/6/6 13:04
+ */
+ public String getDictLabel(String typeCode, String value) {
+ return devDictService.getDictLabel(typeCode, value);
+ }
}
diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/DevDictService.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/DevDictService.java
index c45ca38e..ded44182 100644
--- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/DevDictService.java
+++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/DevDictService.java
@@ -91,4 +91,12 @@ public interface DevDictService extends IService {
* @date 2022/4/24 21:18
*/
DevDict queryEntity(String id);
+
+ /**
+ * 根据类型跟子类型获得翻译后的label
+ *
+ * @author yubaoshan
+ * @date 2025/6/6 13:04
+ */
+ String getDictLabel(String typeCode, String value);
}
diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/impl/DevDictServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/impl/DevDictServiceImpl.java
index 50a773fb..5eead300 100644
--- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/impl/DevDictServiceImpl.java
+++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/impl/DevDictServiceImpl.java
@@ -235,4 +235,20 @@ public class DevDictServiceImpl extends ServiceImpl impl
return null;
});
}
+
+ @Override
+ public String getDictLabel(String typeCode, String value) {
+ List devDictList = this.list(new LambdaQueryWrapper().eq(DevDict::getDictValue, typeCode));
+ if (ObjectUtil.isNotEmpty(devDictList) && devDictList.size() == 1) {
+ DevDict devDictClone = devDictList.get(0);
+ DevDict devDict = this.getOne(new LambdaQueryWrapper().eq(DevDict::getParentId, devDictClone.getId())
+ .eq(DevDict::getDictValue, value));
+ if (ObjectUtil.isNotEmpty(devDict)) {
+ return devDict.getDictLabel();
+ } else {
+ return null;
+ }
+ }
+ return null;
+ }
}
diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/controller/DevFileController.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/controller/DevFileController.java
index f4d81e1c..e2fa8863 100644
--- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/controller/DevFileController.java
+++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/controller/DevFileController.java
@@ -240,13 +240,27 @@ public class DevFileController {
devFileService.download(devFileIdParam, response);
}
+ /**
+ * 下载文件
+ *
+ * @author xuyuxiang
+ * @date 2022/6/21 15:44
+ **/
+ @ApiOperationSupport(order = 14)
+ @Operation(summary = "授权下载文件")
+ @CommonLog("授权下载文件")
+ @GetMapping(value = "/dev/file/authDownload", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
+ public void authDownload(@Valid DevFileIdParam devFileIdParam, HttpServletResponse response) throws IOException {
+ devFileService.authDownload(devFileIdParam, response);
+ }
+
/**
* 删除文件
*
* @author xuyuxiang
* @date 2022/4/24 20:00
*/
- @ApiOperationSupport(order = 14)
+ @ApiOperationSupport(order = 15)
@Operation(summary = "删除文件")
@CommonLog("删除文件")
@PostMapping(value = "/dev/file/delete")
@@ -262,6 +276,7 @@ public class DevFileController {
* @author 每天一点
* @date 2025/4/06 20:25
*/
+ @ApiOperationSupport(order = 16)
@Operation(summary = "物理删除文件")
@CommonLog("物理删除文件")
@PostMapping(value = "/dev/file/deleteAbsolute")
@@ -276,7 +291,7 @@ public class DevFileController {
* @author xuyuxiang
* @date 2022/6/21 15:44
**/
- @ApiOperationSupport(order = 15)
+ @ApiOperationSupport(order = 17)
@Operation(summary = "获取文件详情")
@GetMapping("/dev/file/detail")
public CommonResult detail(@Valid DevFileIdParam devFileIdParam) {
@@ -289,7 +304,7 @@ public class DevFileController {
* @author yubaoshan
* @date 2024/6/9 23:52
**/
- @ApiOperationSupport(order = 16)
+ @ApiOperationSupport(order = 18)
@Operation(summary = "根据文件url集合获取文件集合")
@PostMapping("/dev/file/getFileListByUrlList")
public CommonResult> getFileListByUrlList(@RequestBody @Valid DevFileUrlListParam devFileUrlListParam) {
diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java
index 0ddc6316..7ee22077 100644
--- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java
+++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java
@@ -73,6 +73,10 @@ public class DevFile extends CommonEntity {
@Schema(description = "文件下载路径")
private String downloadPath;
+ /** 文件下载是否需要授权 */
+ @Schema(description = "文件下载是否需要授权")
+ private Boolean isDownloadAuth;
+
/** 图片缩略图 */
@Schema(description = "图片缩略图")
private String thumbnail;
diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/DevFileService.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/DevFileService.java
index fc2e6041..fba70724 100644
--- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/DevFileService.java
+++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/DevFileService.java
@@ -73,6 +73,16 @@ public interface DevFileService extends IService {
**/
void download(DevFileIdParam devFileIdParam, HttpServletResponse response) throws IOException;
+
+ /**
+ * 授权下载文件
+ *
+ * @author xuyuxiang
+ * @date 2022/6/21 15:44
+ **/
+ void authDownload(DevFileIdParam devFileIdParam, HttpServletResponse response) throws IOException;
+
+
/**
* 删除文件
*
diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java
index 5f8ec4c9..0c864f2d 100644
--- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java
+++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java
@@ -18,9 +18,11 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
@@ -71,12 +73,12 @@ public class DevFileServiceImpl extends ServiceImpl impl
@Override
public String uploadReturnId(String engine, MultipartFile file) {
- return this.storageFile(engine, file, true);
+ return this.storageFile(engine, file, true, true);
}
@Override
public String uploadReturnUrl(String engine, MultipartFile file) {
- return this.storageFile(engine, file, false);
+ return this.storageFile(engine, file, false, false);
}
@Override
@@ -105,6 +107,33 @@ public class DevFileServiceImpl extends ServiceImpl impl
@Override
public void download(DevFileIdParam devFileIdParam, HttpServletResponse response) throws IOException {
+ unifiedDownload(devFileIdParam, response, false);
+// DevFile devFile;
+// try {
+// devFile = this.queryEntity(devFileIdParam.getId());
+// } catch (Exception e) {
+// CommonResponseUtil.renderError(response, e.getMessage());
+// return;
+// }
+// if(!devFile.getEngine().equals(DevFileEngineTypeEnum.LOCAL.getValue())) {
+// CommonResponseUtil.renderError(response, "非本地文件不支持此方式下载,id值为:" + devFile.getId());
+// return;
+// }
+// File file = FileUtil.file(devFile.getStoragePath());
+// if(!FileUtil.exist(file)) {
+// CommonResponseUtil.renderError(response, "找不到存储的文件,id值为:" + devFile.getId());
+// return;
+// }
+// CommonDownloadUtil.download(devFile.getName(), IoUtil.readBytes(FileUtil.getInputStream(file)), response);
+ }
+
+ @Override
+ public void authDownload(DevFileIdParam devFileIdParam, HttpServletResponse response) throws IOException {
+ unifiedDownload(devFileIdParam, response, true);
+ }
+
+ // 统一下载
+ private void unifiedDownload(DevFileIdParam devFileIdParam, HttpServletResponse response, boolean isDownloadAuth) throws IOException{
DevFile devFile;
try {
devFile = this.queryEntity(devFileIdParam.getId());
@@ -112,16 +141,21 @@ public class DevFileServiceImpl extends ServiceImpl impl
CommonResponseUtil.renderError(response, e.getMessage());
return;
}
- if(!devFile.getEngine().equals(DevFileEngineTypeEnum.LOCAL.getValue())) {
- CommonResponseUtil.renderError(response, "非本地文件不支持此方式下载,id值为:" + devFile.getId());
+ if (BooleanUtil.isTrue(devFile.getIsDownloadAuth()) && !isDownloadAuth){
+ CommonResponseUtil.renderError(response, "该文件需要授权下载,请使用授权接口authDownload进行下载!");
return;
}
- File file = FileUtil.file(devFile.getStoragePath());
- if(!FileUtil.exist(file)) {
- CommonResponseUtil.renderError(response, "找不到存储的文件,id值为:" + devFile.getId());
- return;
+ if(devFile.getEngine().equals(DevFileEngineTypeEnum.LOCAL.getValue())) {
+ File file = FileUtil.file(devFile.getStoragePath());
+ if(!FileUtil.exist(file)) {
+ CommonResponseUtil.renderError(response, "找不到存储的文件,id值为:" + devFile.getId());
+ return;
+ }
+ CommonDownloadUtil.download(devFile.getName(), IoUtil.readBytes(FileUtil.getInputStream(file)), response);
+ } else {
+ String storagePath = devFile.getStoragePath();
+ CommonDownloadUtil.download(devFile.getName(), HttpUtil.downloadBytes(storagePath), response);
}
- CommonDownloadUtil.download(devFile.getName(), IoUtil.readBytes(FileUtil.getInputStream(file)), response);
}
@Transactional(rollbackFor = Exception.class)
@@ -165,7 +199,7 @@ public class DevFileServiceImpl extends ServiceImpl impl
* @author xuyuxiang
* @date 2022/6/16 16:24
**/
- private String storageFile(String engine, MultipartFile file, boolean returnFileId) {
+ private String storageFile(String engine, MultipartFile file, boolean returnFileId, Boolean isDownloadAuth) {
// 如果引擎为空,默认使用本地
if(ObjectUtil.isEmpty(engine)) {
@@ -241,20 +275,32 @@ public class DevFileServiceImpl extends ServiceImpl impl
// 定义下载地址
String downloadUrl;
-
- // 下载路径,注意:本地文件下载地址设置为下载接口地址 + 文件id
- if(engine.equals(DevFileEngineTypeEnum.LOCAL.getValue())) {
- String apiUrl = commonProperties.getBackendUrl();
- if(ObjectUtil.isEmpty(apiUrl)) {
- throw new CommonException("后端域名地址未正确配置:snowy.config.common.backend-url为空");
- }
- downloadUrl= apiUrl + "/dev/file/download?id=" + fileId;
- devFile.setDownloadPath(downloadUrl);
- } else {
- // 阿里云、腾讯云、MINIO可以直接使用存储地址(公网)作为下载地址
- downloadUrl= storageUrl;
- devFile.setDownloadPath(devFile.getStoragePath());
+ String apiUrl = commonProperties.getBackendUrl();
+ if(ObjectUtil.isEmpty(apiUrl)) {
+ throw new CommonException("后端域名地址未正确配置:snowy.config.common.backend-url为空");
}
+ if (BooleanUtil.isTrue(isDownloadAuth)){
+ downloadUrl= apiUrl + "/dev/file/authDownload?id=" + fileId + "&tenCode=" + tenApi.getCurrentTenCode() + "&token=";
+ }else {
+ downloadUrl= apiUrl + "/dev/file/download?id=" + fileId;
+ }
+ devFile.setDownloadPath(downloadUrl);
+
+// // 下载路径,注意:本地文件下载地址设置为下载接口地址 + 文件id
+// if(engine.equals(DevFileEngineTypeEnum.LOCAL.getValue())) {
+// String apiUrl = commonProperties.getBackendUrl();
+// if(ObjectUtil.isEmpty(apiUrl)) {
+// throw new CommonException("后端域名地址未正确配置:snowy.config.common.backend-url为空");
+// }
+// downloadUrl= apiUrl + "/dev/file/download?id=" + fileId + "&tenCode=" + tenApi.getCurrentTenCode();
+// devFile.setDownloadPath(downloadUrl);
+// } else {
+// // 阿里云、腾讯云、MINIO可以直接使用存储地址(公网)作为下载地址
+// downloadUrl= storageUrl;
+// devFile.setDownloadPath(devFile.getStoragePath());
+// }
+
+ devFile.setIsDownloadAuth(isDownloadAuth);
this.save(devFile);
diff --git a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/basic/service/impl/GenBasicServiceImpl.java b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/basic/service/impl/GenBasicServiceImpl.java
index 393afd41..3990ef4e 100644
--- a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/basic/service/impl/GenBasicServiceImpl.java
+++ b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/basic/service/impl/GenBasicServiceImpl.java
@@ -98,7 +98,8 @@ public class GenBasicServiceImpl extends ServiceImpl i
private static final List GEN_FRONT_FILE_LIST = CollectionUtil.newArrayList(
JSONUtil.createObj().set("name", "Api.js.btl").set("path", "api"),
JSONUtil.createObj().set("name", "form.vue.btl").set("path", "views"),
- JSONUtil.createObj().set("name", "index.vue.btl").set("path", "views"));
+ JSONUtil.createObj().set("name", "index.vue.btl").set("path", "views"),
+ JSONUtil.createObj().set("name", "importModel.vue.btl").set("path", "views"));
private static final List GEN_MOBILE_FILE_LIST = CollectionUtil.newArrayList(
JSONUtil.createObj().set("name", "page.json.btl"),
@@ -242,6 +243,7 @@ public class GenBasicServiceImpl extends ServiceImpl i
}
addParam.setWhetherRetract(GenYesNoEnum.N.getValue());
addParam.setWhetherRequired(GenYesNoEnum.N.getValue());
+ addParam.setWhetherUnique(GenYesNoEnum.N.getValue());
addParam.setQueryWhether(GenYesNoEnum.N.getValue());
addParam.setSortCode(i);
GenConfig genConfig = BeanUtil.toBean(addParam, GenConfig.class);
@@ -330,27 +332,30 @@ public class GenBasicServiceImpl extends ServiceImpl i
schema = metaData.getUserName();
}
List columns = new ArrayList<>();
- rs = metaData.getColumns(null, schema, genBasicTableColumnParam.getTableName(), "%");
+ rs = metaData.getColumns(conn.getCatalog(), schema, genBasicTableColumnParam.getTableName(), "%");
if(!rs.isBeforeFirst()) {
- rs = metaData.getColumns(null, schema, genBasicTableColumnParam.getTableName().toLowerCase(), "%");
+ rs = metaData.getColumns(conn.getCatalog(), schema, genBasicTableColumnParam.getTableName().toLowerCase(), "%");
}
while (rs.next()) {
String columnName = rs.getString("COLUMN_NAME").toUpperCase();
- GenBasicTableColumnResult genBasicTableColumnResult = new GenBasicTableColumnResult();
- genBasicTableColumnResult.setColumnName(columnName);
- String remarks = rs.getString("REMARKS");
- if(ObjectUtil.isEmpty(remarks)) {
- genBasicTableColumnResult.setColumnRemark(columnName);
- } else {
- genBasicTableColumnResult.setColumnRemark(remarks);
+ boolean exist = columns.stream().anyMatch(dbsTableColumnResult -> dbsTableColumnResult.getColumnName().equals(columnName));
+ if(!exist) {
+ GenBasicTableColumnResult genBasicTableColumnResult = new GenBasicTableColumnResult();
+ genBasicTableColumnResult.setColumnName(columnName);
+ String remarks = rs.getString("REMARKS");
+ if(ObjectUtil.isEmpty(remarks)) {
+ genBasicTableColumnResult.setColumnRemark(columnName);
+ } else {
+ genBasicTableColumnResult.setColumnRemark(remarks);
+ }
+ String typeName = rs.getString("TYPE_NAME").toUpperCase();
+ if(ObjectUtil.isEmpty(typeName)) {
+ genBasicTableColumnResult.setTypeName("NONE");
+ } else {
+ genBasicTableColumnResult.setTypeName(typeName);
+ }
+ columns.add(genBasicTableColumnResult);
}
- String typeName = rs.getString("TYPE_NAME").toUpperCase();
- if(ObjectUtil.isEmpty(typeName)) {
- genBasicTableColumnResult.setTypeName("NONE");
- } else {
- genBasicTableColumnResult.setTypeName(typeName);
- }
- columns.add(genBasicTableColumnResult);
}
return columns;
} catch (SQLException sqlException) {
@@ -675,6 +680,10 @@ public class GenBasicServiceImpl extends ServiceImpl i
bindingJsonObject.set("deleteButtonId", IdWorker.getIdStr());
// 批量删除按钮ID
bindingJsonObject.set("batchDeleteButtonId", IdWorker.getIdStr());
+ // 导入按钮ID
+ bindingJsonObject.set("importButtonId", IdWorker.getIdStr());
+ // 导出按钮ID
+ bindingJsonObject.set("exportButtonId", IdWorker.getIdStr());
// 作者
bindingJsonObject.set("authorName", genBasic.getAuthorName());
// 生成时间
@@ -697,6 +706,7 @@ public class GenBasicServiceImpl extends ServiceImpl i
configItem.set("needPage", false);
configItem.set("needPageType", "none");
configItem.set("required", true);
+ configItem.set("unique", true);
configItem.set("needTableId", true);
bindingJsonObject.set("dbTableKeyJavaType", genConfig.getFieldJavaType());
bindingJsonObject.set("dbTableKeyRemark", genConfig.getFieldRemark());
@@ -712,6 +722,7 @@ public class GenBasicServiceImpl extends ServiceImpl i
configItem.set("needPage", false);
configItem.set("needPageType", "none");
configItem.set("required", false);
+ configItem.set("unique", false);
configItem.set("needTableId", false);
} else {
boolean needAddAndUpdate = genConfig.getWhetherAddUpdate().equalsIgnoreCase(GenYesNoEnum.Y.getValue());
@@ -720,6 +731,7 @@ public class GenBasicServiceImpl extends ServiceImpl i
configItem.set("needPage", genConfig.getQueryWhether().equalsIgnoreCase(GenYesNoEnum.Y.getValue()));
configItem.set("needPageType", genConfig.getQueryType());
configItem.set("required", genConfig.getWhetherRequired().equalsIgnoreCase(GenYesNoEnum.Y.getValue()));
+ configItem.set("unique", ObjectUtil.isNotEmpty(genConfig.getWhetherUnique()) && genConfig.getWhetherUnique().equalsIgnoreCase(GenYesNoEnum.Y.getValue()));
configItem.set("needTableId", false);
}
}
@@ -754,6 +766,20 @@ public class GenBasicServiceImpl extends ServiceImpl i
});
// 配置信息
bindingJsonObject.set("configList", configList);
+ // 获取必填字段
+ List requiredFieldList = configList.stream().filter(configItem -> configItem.getBool("required")).toList();
+ // 必填字段列表
+ bindingJsonObject.set("requiredFieldList", requiredFieldList);
+ // 必填字段字符串
+ bindingJsonObject.set("requiredFieldStr", StrUtil.join(StrUtil.COMMA + " ", requiredFieldList.stream().map(configItem ->
+ configItem.getStr("fieldNameCamelCase")).collect(Collectors.toList())));
+ // 获取唯一字段
+ List uniqueFieldList = configList.stream().filter(configItem -> configItem.getBool("unique")).toList();
+ // 唯一字段列表
+ bindingJsonObject.set("uniqueFieldList", uniqueFieldList);
+ // 唯一字段字符串
+ bindingJsonObject.set("uniqueFieldStr", StrUtil.join(StrUtil.COMMA + " ", uniqueFieldList.stream().map(configItem ->
+ configItem.getStr("fieldNameCamelCase")).collect(Collectors.toList())));
// 有排序字段
bindingJsonObject.set("hasSortCodeField", hasSortCodeField.get());
return bindingJsonObject;
diff --git a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/entity/GenConfig.java b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/entity/GenConfig.java
index 35111b1c..15427a6e 100644
--- a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/entity/GenConfig.java
+++ b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/entity/GenConfig.java
@@ -81,6 +81,10 @@ public class GenConfig extends CommonEntity {
@Schema(description = "必填")
private String whetherRequired;
+ /** 唯一 */
+ @Schema(description = "唯一")
+ private String whetherUnique;
+
/** 查询 */
@Schema(description = "查询")
private String queryWhether;
diff --git a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigAddParam.java b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigAddParam.java
index 2d5feffa..8ac6197a 100644
--- a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigAddParam.java
+++ b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigAddParam.java
@@ -80,6 +80,10 @@ public class GenConfigAddParam {
@Schema(description = "必填")
private String whetherRequired;
+ /** 唯一 */
+ @Schema(description = "唯一")
+ private String whetherUnique;
+
/** 查询 */
@Schema(description = "查询")
private String queryWhether;
diff --git a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigEditParam.java b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigEditParam.java
index 1485f30d..3f014042 100644
--- a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigEditParam.java
+++ b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigEditParam.java
@@ -91,6 +91,11 @@ public class GenConfigEditParam {
@NotBlank(message = "whetherRequired不能为空")
private String whetherRequired;
+ /** 唯一 */
+ @Schema(description = "唯一")
+ @NotBlank(message = "whetherUnique不能为空")
+ private String whetherUnique;
+
/** 查询 */
@Schema(description = "查询", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "queryWhether不能为空")
diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Controller.java.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Controller.java.btl
index 2c5356dd..5416802c 100644
--- a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Controller.java.btl
+++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Controller.java.btl
@@ -13,14 +13,15 @@
package ${packageName}.${moduleName}.modular.${busName}.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
import ${packageName}.common.annotation.CommonLog;
import ${packageName}.common.pojo.CommonResult;
import ${packageName}.${moduleName}.modular.${busName}.entity.${className};
@@ -33,6 +34,7 @@ import ${packageName}.${moduleName}.modular.${busName}.service.${className}Servi
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
+import java.io.IOException;
import java.util.List;
/**
@@ -120,4 +122,43 @@ public class ${className}Controller {
public CommonResult<${className}> detail(@Valid ${className}IdParam ${classNameFirstLower}IdParam) {
return CommonResult.data(${classNameFirstLower}Service.detail(${classNameFirstLower}IdParam));
}
+
+ /**
+ * 下载${functionName}导入模板
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ */
+ @Operation(summary = "下载${functionName}导入模板")
+ @GetMapping(value = "/${moduleName}/${busName}/downloadImportTemplate", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
+ public void downloadImportTemplate(HttpServletResponse response) throws IOException {
+ ${classNameFirstLower}Service.downloadImportTemplate(response);
+ }
+
+ /**
+ * 导入${functionName}
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ */
+ @Operation(summary = "导入${functionName}")
+ @CommonLog("导入${functionName}")
+ @SaCheckPermission("/${moduleName}/${busName}/importData")
+ @PostMapping("/${moduleName}/${busName}/importData")
+ public CommonResult importData(@RequestPart("file") MultipartFile file) {
+ return CommonResult.data(${classNameFirstLower}Service.importData(file));
+ }
+
+ /**
+ * 导出${functionName}
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ */
+ @Operation(summary = "导出${functionName}")
+ @SaCheckPermission("/${moduleName}/${busName}/exportData")
+ @PostMapping(value = "/${moduleName}/${busName}/exportData", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
+ public void exportData(@RequestBody List<${className}IdParam> ${classNameFirstLower}IdParamList, HttpServletResponse response) throws IOException {
+ ${classNameFirstLower}Service.exportData(${classNameFirstLower}IdParamList, response);
+ }
}
diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/EditParam.java.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/EditParam.java.btl
index e2bfa400..69cea808 100644
--- a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/EditParam.java.btl
+++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/EditParam.java.btl
@@ -12,6 +12,8 @@
*/
package ${packageName}.${moduleName}.modular.${busName}.param;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.DateTimeFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@@ -34,6 +36,10 @@ public class ${className}EditParam {
<% for(var i = 0; i < configList.~size; i++) { %>
<% if(configList[i].needEdit) { %>
/** ${configList[i].fieldRemark} */
+ <% if(configList[i].fieldJavaType == 'Date') { %>
+ @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
+ <% } else { %><% } %>
+ @ExcelProperty("${configList[i].fieldRemark}")
@Schema(description = "${configList[i].fieldRemark}"<% if(configList[i].required) { %>, requiredMode = Schema.RequiredMode.REQUIRED<% } %>)
<% if(configList[i].required) { %>
<% if(configList[i].fieldJavaType == 'String') { %>@NotBlank<% } else { %>@NotNull<% } %>(message = "${configList[i].fieldNameCamelCase}不能为空")
diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Service.java.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Service.java.btl
index e8daf4d5..3b229a43 100644
--- a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Service.java.btl
+++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Service.java.btl
@@ -12,14 +12,17 @@
*/
package ${packageName}.${moduleName}.modular.${busName}.service;
+import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.web.multipart.MultipartFile;
import ${packageName}.${moduleName}.modular.${busName}.entity.${className};
import ${packageName}.${moduleName}.modular.${busName}.param.${className}AddParam;
import ${packageName}.${moduleName}.modular.${busName}.param.${className}EditParam;
import ${packageName}.${moduleName}.modular.${busName}.param.${className}IdParam;
import ${packageName}.${moduleName}.modular.${busName}.param.${className}PageParam;
-
+import java.io.IOException;
import java.util.List;
/**
@@ -76,5 +79,29 @@ public interface ${className}Service extends IService<${className}> {
* @author ${authorName}
* @date ${genTime}
**/
- ${className} queryEntity(String id);
+ ${className} queryEntity(String ${dbTableKeyCamelCase});
+
+ /**
+ * 下载${functionName}导入模板
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ */
+ void downloadImportTemplate(HttpServletResponse response) throws IOException;
+
+ /**
+ * 导入${functionName}
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ **/
+ JSONObject importData(MultipartFile file);
+
+ /**
+ * 导出${functionName}
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ */
+ void exportData(List<${className}IdParam> ${classNameFirstLower}IdParamList, HttpServletResponse response) throws IOException;
}
diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/ServiceImpl.java.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/ServiceImpl.java.btl
index ddac0796..1ed78f4f 100644
--- a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/ServiceImpl.java.btl
+++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/ServiceImpl.java.btl
@@ -13,17 +13,31 @@
package ${packageName}.${moduleName}.modular.${busName}.service.impl;
import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.CollStreamUtil;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.excel.EasyExcel;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
import ${packageName}.common.enums.CommonSortOrderEnum;
import ${packageName}.common.exception.CommonException;
import ${packageName}.common.page.CommonPageRequest;
+import java.math.BigDecimal;
+import java.util.Date;
import ${packageName}.${moduleName}.modular.${busName}.entity.${className};
import ${packageName}.${moduleName}.modular.${busName}.mapper.${className}Mapper;
import ${packageName}.${moduleName}.modular.${busName}.param.${className}AddParam;
@@ -32,6 +46,11 @@ import ${packageName}.${moduleName}.modular.${busName}.param.${className}IdParam
import ${packageName}.${moduleName}.modular.${busName}.param.${className}PageParam;
import ${packageName}.${moduleName}.modular.${busName}.service.${className}Service;
+import vip.xiaonuo.common.util.CommonDownloadUtil;
+import vip.xiaonuo.common.util.CommonResponseUtil;
+
+import java.io.File;
+import java.io.IOException;
import java.util.List;
/**
@@ -77,18 +96,28 @@ public class ${className}ServiceImpl extends ServiceImpl<${className}Mapper, ${c
@Override
public void add(${className}AddParam ${classNameFirstLower}AddParam) {
${className} ${classNameFirstLower} = BeanUtil.toBean(${classNameFirstLower}AddParam, ${className}.class);
+ <% for(var i = 0; i < uniqueFieldList.~size; i++) { %>
+ <% if(!uniqueFieldList[i].needTableId) { %>
+ if(this.count(new LambdaQueryWrapper<${className}>().eq(${className}::get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}, ${classNameFirstLower}.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}())) > 0) {
+ throw new CommonException("存在重复的${uniqueFieldList[i].fieldRemark},值为:{}", ${classNameFirstLower}.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}());
+ }
+ <% } %>
+ <% } %>
this.save(${classNameFirstLower});
}
@Transactional(rollbackFor = Exception.class)
@Override
public void edit(${className}EditParam ${classNameFirstLower}EditParam) {
- <% for(var i = 0; i < configList.~size; i++) { %>
- <% if(configList[i].needTableId) { %>
- ${className} ${classNameFirstLower} = this.queryEntity(${classNameFirstLower}EditParam.get${configList[i].fieldNameCamelCaseFirstUpper}());
- <% } %>
- <% } %>
+ ${className} ${classNameFirstLower} = this.queryEntity(${classNameFirstLower}EditParam.get${dbTableKeyFirstUpper}());
BeanUtil.copyProperties(${classNameFirstLower}EditParam, ${classNameFirstLower});
+ <% for(var i = 0; i < uniqueFieldList.~size; i++) { %>
+ <% if(!uniqueFieldList[i].needTableId) { %>
+ if(this.count(new LambdaQueryWrapper<${className}>().ne(${className}::get${dbTableKeyFirstUpper}, ${classNameFirstLower}.get${dbTableKeyFirstUpper}()).eq(${className}::get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}, ${classNameFirstLower}.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}())) > 0) {
+ throw new CommonException("存在重复的${uniqueFieldList[i].fieldRemark},值为:{}", ${classNameFirstLower}.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}());
+ }
+ <% } %>
+ <% } %>
this.updateById(${classNameFirstLower});
}
@@ -96,20 +125,129 @@ public class ${className}ServiceImpl extends ServiceImpl<${className}Mapper, ${c
@Override
public void delete(List<${className}IdParam> ${classNameFirstLower}IdParamList) {
// 执行删除
- <% for(var i = 0; i < configList.~size; i++) { %>
- <% if(configList[i].needTableId) { %>
- this.removeByIds(CollStreamUtil.toList(${classNameFirstLower}IdParamList, ${className}IdParam::get${configList[i].fieldNameCamelCaseFirstUpper}));
- <% } %>
- <% } %>
+ this.removeByIds(CollStreamUtil.toList(${classNameFirstLower}IdParamList, ${className}IdParam::get${dbTableKeyFirstUpper}));
}
@Override
public ${className} detail(${className}IdParam ${classNameFirstLower}IdParam) {
- <% for(var i = 0; i < configList.~size; i++) { %>
- <% if(configList[i].needTableId) { %>
- return this.queryEntity(${classNameFirstLower}IdParam.get${configList[i].fieldNameCamelCaseFirstUpper}());
- <% } %>
+ return this.queryEntity(${classNameFirstLower}IdParam.get${dbTableKeyFirstUpper}());
+ }
+
+ @Override
+ public ${className} queryEntity(String ${dbTableKeyCamelCase}) {
+ ${className} ${classNameFirstLower} = this.getById(${dbTableKeyCamelCase});
+ if(ObjectUtil.isEmpty(${classNameFirstLower})) {
+ throw new CommonException("${functionName}不存在,${dbTableKeyCamelCase}值为:{}", ${dbTableKeyCamelCase});
+ }
+ return ${classNameFirstLower};
+ }
+
+ @Override
+ public void downloadImportTemplate(HttpServletResponse response) throws IOException {
+ File tempFile = null;
+ try {
+ List<${className}EditParam> dataList = CollectionUtil.newArrayList();
+ String fileName = "${functionName}导入模板_" + DateUtil.format(DateTime.now(), DatePattern.PURE_DATETIME_PATTERN) + ".xlsx";
+ tempFile = FileUtil.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName);
+ EasyExcel.write(tempFile.getPath(), ${className}EditParam.class).sheet("${functionName}").doWrite(dataList);
+ CommonDownloadUtil.download(tempFile, response);
+ } catch (Exception e) {
+ log.error(">>> ${functionName}导入模板下载失败:", e);
+ CommonResponseUtil.renderError(response, "${functionName}导入模板下载失败");
+ } finally {
+ FileUtil.del(tempFile);
+ }
+ }
+
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public JSONObject importData(MultipartFile file) {
+ try {
+ int successCount = 0;
+ int errorCount = 0;
+ JSONArray errorDetail = JSONUtil.createArray();
+ // 创建临时文件
+ File tempFile = FileUtil.writeBytes(file.getBytes(), FileUtil.file(FileUtil.getTmpDir() +
+ FileUtil.FILE_SEPARATOR + "${classNameFirstLower}ImportTemplate.xlsx"));
+ // 读取excel
+ List<${className}EditParam> ${classNameFirstLower}EditParamList = EasyExcel.read(tempFile).head(${className}EditParam.class).sheet()
+ .headRowNumber(1).doReadSync();
+ List<${className}> allDataList = this.list();
+ for (int i = 0; i < ${classNameFirstLower}EditParamList.size(); i++) {
+ JSONObject jsonObject = this.doImport(allDataList, ${classNameFirstLower}EditParamList.get(i), i);
+ if(jsonObject.getBool("success")) {
+ successCount += 1;
+ } else {
+ errorCount += 1;
+ errorDetail.add(jsonObject);
+ }
+ }
+ return JSONUtil.createObj()
+ .set("totalCount", ${classNameFirstLower}EditParamList.size())
+ .set("successCount", successCount)
+ .set("errorCount", errorCount)
+ .set("errorDetail", errorDetail);
+ } catch (Exception e) {
+ log.error(">>> ${functionName}导入失败:", e);
+ throw new CommonException("${functionName}导入失败");
+ }
+ }
+
+ public JSONObject doImport(List<${className}> allDataList, ${className}EditParam ${classNameFirstLower}EditParam, int i) {
+ <% for(var i = 0; i < requiredFieldList.~size; i++) { %>
+ ${requiredFieldList[i].fieldJavaType} ${requiredFieldList[i].fieldNameCamelCase} = ${classNameFirstLower}EditParam.get${requiredFieldList[i].fieldNameCamelCaseFirstUpper}();
<% } %>
+ if(ObjectUtil.hasEmpty(${requiredFieldStr})) {
+ return JSONUtil.createObj().set("index", i + 1).set("success", false).set("msg", "必填字段存在空值");
+ } else {
+ try {
+ int index = CollStreamUtil.toList(allDataList, ${className}::get${dbTableKeyFirstUpper}).indexOf(${classNameFirstLower}EditParam.get${dbTableKeyFirstUpper}());
+ ${className} ${classNameFirstLower};
+ boolean isAdd = false;
+ if(index == -1) {
+ isAdd = true;
+ ${classNameFirstLower} = new ${className}();
+ } else {
+ ${classNameFirstLower} = allDataList.get(index);
+ }
+ <% if(uniqueFieldList.~size > 1) { %>
+ if(isAdd) {
+ <% for(var i = 0; i < uniqueFieldList.~size; i++) { %>
+ <% if(!uniqueFieldList[i].needTableId) { %>
+ boolean repeat${uniqueFieldList[i].fieldNameCamelCaseFirstUpper} = allDataList.stream().anyMatch(tempData -> ObjectUtil
+ .isNotEmpty(tempData.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}()) && tempData.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}().equals(${classNameFirstLower}EditParam.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}()));
+ if(repeat${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}) {
+ return JSONUtil.createObj().set("index", i + 1).set("success", false).set("msg", "新增数据时字段【${uniqueFieldList[i].fieldRemark}(${uniqueFieldList[i].fieldNameCamelCase})】与数据库中数据重复,值为:" + ${classNameFirstLower}EditParam.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}());
+ }
+ <% } %>
+ <% } %>
+ } else {
+ <% for(var i = 0; i < uniqueFieldList.~size; i++) { %>
+ <% if(!uniqueFieldList[i].needTableId) { %>
+ boolean repeat${uniqueFieldList[i].fieldNameCamelCaseFirstUpper} = allDataList.stream().anyMatch(tempData -> ObjectUtil
+ .isNotEmpty(tempData.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}()) && tempData.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}()
+ .equals(${classNameFirstLower}EditParam.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}()) && !tempData.get${dbTableKeyFirstUpper}().equals(${classNameFirstLower}.get${dbTableKeyFirstUpper}()));
+ if(repeat${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}) {
+ return JSONUtil.createObj().set("index", i + 1).set("success", false).set("msg", "更新数据时字段【${uniqueFieldList[i].fieldRemark}(${uniqueFieldList[i].fieldNameCamelCase})】与数据库中数据重复,值为:" + ${classNameFirstLower}EditParam.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}());
+ }
+ <% } %>
+ <% } %>
+ }
+ <% } %>
+ BeanUtil.copyProperties(${classNameFirstLower}EditParam, ${classNameFirstLower});
+ if(isAdd) {
+ allDataList.add(${classNameFirstLower});
+ } else {
+ allDataList.remove(index);
+ allDataList.add(index, ${classNameFirstLower});
+ }
+ this.saveOrUpdate(${classNameFirstLower});
+ return JSONUtil.createObj().set("success", true);
+ } catch (Exception e) {
+ log.error(">>> 数据导入异常:", e);
+ return JSONUtil.createObj().set("success", false).set("index", i + 1).set("msg", "数据导入异常");
+ }
+ }
}
@Override
@@ -120,4 +258,27 @@ public class ${className}ServiceImpl extends ServiceImpl<${className}Mapper, ${c
}
return ${classNameFirstLower};
}
+
+ @Override
+ public void exportData(List<${className}IdParam> ${classNameFirstLower}IdParamList, HttpServletResponse response) throws IOException {
+ File tempFile = null;
+ try {
+ List<${className}EditParam> dataList;
+ if(ObjectUtil.isNotEmpty(${classNameFirstLower}IdParamList)) {
+ List ${dbTableKeyCamelCase}List = CollStreamUtil.toList(${classNameFirstLower}IdParamList, ${className}IdParam::get${dbTableKeyFirstUpper});
+ dataList = BeanUtil.copyToList(this.listByIds(${dbTableKeyCamelCase}List), ${className}EditParam.class);
+ } else {
+ dataList = BeanUtil.copyToList(this.list(), ${className}EditParam.class);
+ }
+ String fileName = "${functionName}_" + DateUtil.format(DateTime.now(), DatePattern.PURE_DATETIME_PATTERN) + ".xlsx";
+ tempFile = FileUtil.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName);
+ EasyExcel.write(tempFile.getPath(), ${className}EditParam.class).sheet("${functionName}").doWrite(dataList);
+ CommonDownloadUtil.download(tempFile, response);
+ } catch (Exception e) {
+ log.error(">>> ${functionName}导出失败:", e);
+ CommonResponseUtil.renderError(response, "${functionName}导出失败");
+ } finally {
+ FileUtil.del(tempFile);
+ }
+ }
}
diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/Api.js.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/Api.js.btl
index 40c57b7c..00344ef7 100644
--- a/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/Api.js.btl
+++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/Api.js.btl
@@ -24,5 +24,21 @@ export default {
// 获取${functionName}详情
${classNameFirstLower}Detail(data) {
return request('detail', data, 'get')
- }
+ },
+ // 下载${functionName}导入模板
+ ${classNameFirstLower}DownloadTemplate(data) {
+ return request('downloadImportTemplate', data, 'get', {
+ responseType: 'blob'
+ })
+ },
+ // 导入${functionName}
+ ${classNameFirstLower}Import(data) {
+ return request('importData', data)
+ },
+ // 导出${functionName}
+ ${classNameFirstLower}Export(data) {
+ return request('exportData', data, 'post', {
+ responseType: 'blob'
+ })
+ }
}
diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/importModel.vue.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/importModel.vue.btl
new file mode 100644
index 00000000..9d341f31
--- /dev/null
+++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/importModel.vue.btl
@@ -0,0 +1,129 @@
+
+
+ 导入数据格式严格按照系统模板进行数据录入,请点击 下载模板
+
+
+
+
+
+
+
+
+ 单击或拖动文件到此区域进行上传
+ 仅支持xls、xlsx格式文件
+
+
+
+
+
+ 导入总数:{{ impResultData.totalCount }} 条
+ 导入成功:{{ impResultData.successCount }} 条
+
+
失败条数:{{ impResultData.errorCount }} 条
+
+
+
+
+
+
+
+
+
diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/index.vue.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/index.vue.btl
index 4ab5315e..c5b6de7e 100644
--- a/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/index.vue.btl
+++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/index.vue.btl
@@ -82,11 +82,7 @@
:data="loadData"
:alert="options.alert.show"
bordered
- <% for(var i = 0; i < configList.~size; i++) { %>
- <% if(configList[i].needTableId) { %>
- :row-key="(record) => record.${configList[i].fieldNameCamelCase}"
- <% } %>
- <% } %>
+ :row-key="(record) => record.${dbTableKeyCamelCase}"
:tool-config="toolConfig"
:row-selection="options.rowSelection"
>
@@ -96,6 +92,14 @@
新增
+
+
+ 导入
+
+
+
+ 导出
+
+
@@ -161,12 +166,15 @@
<% } %>
import { cloneDeep } from 'lodash-es'
import Form from './form.vue'
+ import ImportModel from './importModel.vue'
+ import downloadUtil from '@/utils/downloadUtil'
import ${classNameFirstLower}Api from '@/api/${moduleName}/${classNameFirstLower}Api'
<% if (searchCount > 0) { %>
const searchFormState = ref({})
const searchFormRef = ref()
<% } %>
const tableRef = ref()
+ const importModelRef = ref()
const formRef = ref()
const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
<% if(searchCount > 3) { %>
@@ -245,17 +253,30 @@
const delete${className} = (record) => {
let params = [
{
- <% for(var i = 0; i < configList.~size; i++) { %>
- <% if(configList[i].needTableId) { %>
- ${configList[i].fieldNameCamelCase}: record.${configList[i].fieldNameCamelCase}
- <% } %>
- <% } %>
+ ${dbTableKeyCamelCase}: record.${dbTableKeyCamelCase}
}
]
${classNameFirstLower}Api.${classNameFirstLower}Delete(params).then(() => {
tableRef.value.refresh(true)
})
}
+ // 导出
+ const exportData = () => {
+ if (selectedRowKeys.value.length > 0) {
+ const params = selectedRowKeys.value.map((m) => {
+ return {
+ id: m
+ }
+ })
+ ${classNameFirstLower}Api.${classNameFirstLower}Export(params).then((res) => {
+ downloadUtil.resultDownload(res)
+ })
+ } else {
+ ${classNameFirstLower}Api.${classNameFirstLower}Export([]).then((res) => {
+ downloadUtil.resultDownload(res)
+ })
+ }
+ }
// 批量删除
const deleteBatch${className} = (params) => {
${classNameFirstLower}Api.${classNameFirstLower}Delete(params).then(() => {
diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Mysql.sql.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Mysql.sql.btl
index 1da419bc..5184a06f 100644
--- a/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Mysql.sql.btl
+++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Mysql.sql.btl
@@ -3,16 +3,19 @@
Date: ${genTime}
*/
-INSERT INTO `SYS_RESOURCE` VALUES ('${menuId}', '${parentId}', '${functionName}管理', '${busName}', '${menuCode}', 'MENU', '${moduleId}', 'MENU', '${menuPath}', '${menuComponent}', NULL, NULL, NULL, 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+INSERT INTO `SYS_RESOURCE` VALUES ('${menuId}', '${parentId}', '${functionName}管理', '${busName}', '${menuCode}', 'MENU', '${moduleId}', 'MENU', '${menuPath}', '${menuComponent}', NULL, NULL, NULL, NULL, NULL, 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
-INSERT INTO `SYS_RESOURCE` VALUES ('${addButtonId}', '${menuId}', '新增${functionName}', NULL, '${classNameFirstLower}Add', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+INSERT INTO `SYS_RESOURCE` VALUES ('${addButtonId}', '${menuId}', '新增${functionName}', NULL, '${classNameFirstLower}Add', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
-INSERT INTO `SYS_RESOURCE` VALUES ('${batchDeleteButtonId}', '${menuId}', '批量删除${functionName}', NULL, '${classNameFirstLower}BatchDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+INSERT INTO `SYS_RESOURCE` VALUES ('${batchDeleteButtonId}', '${menuId}', '批量删除${functionName}', NULL, '${classNameFirstLower}BatchDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
-INSERT INTO `SYS_RESOURCE` VALUES ('${editButtonId}', '${menuId}', '编辑${functionName}', NULL, '${classNameFirstLower}Edit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+INSERT INTO `SYS_RESOURCE` VALUES ('${editButtonId}', '${menuId}', '编辑${functionName}', NULL, '${classNameFirstLower}Edit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
-INSERT INTO `SYS_RESOURCE` VALUES ('${deleteButtonId}', '${menuId}', '删除${functionName}', NULL, '${classNameFirstLower}Delete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+INSERT INTO `SYS_RESOURCE` VALUES ('${deleteButtonId}', '${menuId}', '删除${functionName}', NULL, '${classNameFirstLower}Delete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+INSERT INTO `SYS_RESOURCE` VALUES ('${importButtonId}', '${menuId}', '导入${functionName}', NULL, '${classNameFirstLower}Import', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 5, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO `SYS_RESOURCE` VALUES ('${exportButtonId}', ${menuId}', '导出${functionName}', NULL, '${classNameFirstLower}Export', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 6, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
<% if (mobileModuleId != null && mobileModuleId != '') { %>
INSERT INTO `MOBILE_RESOURCE` VALUES ('${menuId}', '0', '${functionName}管理', NULL, 'MENU', '${mobileModuleId}', 'MENU', '/pages/${moduleName}/${busName}/index', 'apartment-outlined', '#1890ff', 'YES', 'ENABLE', 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Oracle.sql.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Oracle.sql.btl
index 77d568d3..a4f5285a 100644
--- a/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Oracle.sql.btl
+++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Oracle.sql.btl
@@ -3,16 +3,19 @@
Date: ${genTime}
*/
-INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${menuId}', '${parentId}', '${functionName}管理', '${busName}', '${menuCode}', 'MENU', '${moduleId}', 'MENU', '${menuPath}', '${menuComponent}', NULL, NULL, NULL, '99', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${menuId}', '${parentId}', '${functionName}管理', '${busName}', '${menuCode}', 'MENU', '${moduleId}', 'MENU', '${menuPath}', '${menuComponent}', NULL, NULL, NULL, NULL, NULL, '99', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
-INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${addButtonId}', '${menuId}', '新增${functionName}', NULL, '${classNameFirstLower}Add', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '1', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${addButtonId}', '${menuId}', '新增${functionName}', NULL, '${classNameFirstLower}Add', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '1', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
-INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${batchDeleteButtonId}', '${menuId}', '批量删除${functionName}', NULL, '${classNameFirstLower}BatchDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${batchDeleteButtonId}', '${menuId}', '批量删除${functionName}', NULL, '${classNameFirstLower}BatchDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
-INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${editButtonId}', '${menuId}', '编辑${functionName}', NULL, '${classNameFirstLower}Edit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '3', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${editButtonId}', '${menuId}', '编辑${functionName}', NULL, '${classNameFirstLower}Edit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '3', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
-INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${deleteButtonId}', '${menuId}', '删除${functionName}', NULL, '${classNameFirstLower}Delete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '4', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${deleteButtonId}', '${menuId}', '删除${functionName}', NULL, '${classNameFirstLower}Delete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '4', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${importButtonId}', '${menuId}', '导入${functionName}', NULL, '${classNameFirstLower}Import', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '5', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${exportButtonId}', '${menuId}', '导出${functionName}', NULL, '${classNameFirstLower}Export', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '6', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
<% if (mobileModuleId != null && mobileModuleId != '') { %>
INSERT INTO "SNOWY"."MOBILE_RESOURCE" VALUES ('${menuId}', '0', '${functionName}管理', NULL, 'MENU', '${mobileModuleId}', 'MENU', '/pages/${moduleName}/${busName}/index', 'apartment-outlined', '#1890ff', 'YES', 'ENABLE', 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java
index 58a7eea4..d3714047 100644
--- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java
+++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java
@@ -192,7 +192,7 @@ public class SysOrgServiceImpl extends ServiceImpl impleme
this.removeByIds(toDeleteOrgIdList);
// 发布删除事件
- CommonDataChangeEventCenter.doDeleteWithDataId(SysDataTypeEnum.ORG.getValue(), toDeleteOrgIdList);
+ CommonDataChangeEventCenter.doDeleteWithDataIdList(SysDataTypeEnum.ORG.getValue(), toDeleteOrgIdList);
}
}
diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/service/impl/SysPositionServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/service/impl/SysPositionServiceImpl.java
index 2059b746..503922ff 100644
--- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/service/impl/SysPositionServiceImpl.java
+++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/service/impl/SysPositionServiceImpl.java
@@ -146,7 +146,7 @@ public class SysPositionServiceImpl extends ServiceImpl getUserIdListByRoleIdList(List roleIdList) {
- return sysRelationService.getRelationObjectIdListByTargetIdListAndCategory(roleIdList,
+ List userIdList = sysRelationService.getRelationObjectIdListByTargetIdListAndCategory(roleIdList,
SysRelationCategoryEnum.SYS_USER_HAS_ROLE.getValue());
+ if(ObjectUtil.isEmpty(userIdList)){
+ return sysUserService.listByIds(userIdList).stream().map(SysUser::getId).collect(Collectors.toList());
+ } else {
+ return CollectionUtil.newArrayList();
+ }
}
@Override
public List getUserIdListByGroupIdList(List groupIdList) {
- return sysRelationService.getRelationObjectIdListByTargetIdListAndCategory(groupIdList,
+ List userIdList = sysRelationService.getRelationObjectIdListByTargetIdListAndCategory(groupIdList,
SysRelationCategoryEnum.SYS_USER_HAS_GROUP.getValue());
+ if(ObjectUtil.isEmpty(userIdList)){
+ return sysUserService.listByIds(userIdList).stream().map(SysUser::getId).collect(Collectors.toList());
+ } else {
+ return CollectionUtil.newArrayList();
+ }
}
@Override
diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysMenu.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysMenu.java
index bccb9c75..fc091669 100644
--- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysMenu.java
+++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysMenu.java
@@ -86,6 +86,14 @@ public class SysMenu extends CommonEntity {
@Schema(description = "是否可见")
private String visible;
+ /** 显示布局 */
+ @Schema(description = "显示布局")
+ private String displayLayout;
+
+ /** 缓存 */
+ @Schema(description = "缓存")
+ private String keepLive;
+
/** 排序码 */
@Schema(description = "排序码")
private Integer sortCode;
diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/enums/SysMenuWhetherEnum.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/enums/SysMenuWhetherEnum.java
new file mode 100644
index 00000000..7f257067
--- /dev/null
+++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/enums/SysMenuWhetherEnum.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.sys.modular.resource.enums;
+
+import lombok.Getter;
+
+/**
+ * 菜单是否与
+ *
+ * @author yubaoshan
+ * @date 2024/9/17 00:14
+ **/
+@Getter
+public enum SysMenuWhetherEnum {
+
+ /** 写入 */
+ YES("YES"),
+
+ /** 不写入 */
+ NO("NO");
+
+ private final String value;
+
+ SysMenuWhetherEnum(String value) {
+ this.value = value;
+ }
+}
diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuAddParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuAddParam.java
index 31d9a8ca..f569e1af 100644
--- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuAddParam.java
+++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuAddParam.java
@@ -74,6 +74,14 @@ public class SysMenuAddParam {
@Schema(description = "是否可见")
private String visible;
+ /** 显示布局 */
+ @Schema(description = "显示布局")
+ private String displayLayout;
+
+ /** 缓存 */
+ @Schema(description = "缓存")
+ private String keepLive;
+
/** 扩展信息 */
@Schema(description = "扩展信息")
private String extJson;
diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuEditParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuEditParam.java
index 60256834..db4b43b0 100644
--- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuEditParam.java
+++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuEditParam.java
@@ -79,6 +79,14 @@ public class SysMenuEditParam {
@Schema(description = "是否可见")
private String visible;
+ /** 显示布局 */
+ @Schema(description = "显示布局")
+ private String displayLayout;
+
+ /** 缓存 */
+ @Schema(description = "缓存")
+ private String keepLive;
+
/** 扩展信息 */
@Schema(description = "扩展信息")
private String extJson;
diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysButtonServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysButtonServiceImpl.java
index 476b9906..da092f92 100644
--- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysButtonServiceImpl.java
+++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysButtonServiceImpl.java
@@ -115,7 +115,9 @@ public class SysButtonServiceImpl extends ServiceImpl {
+ JSONUtil.createObj().set("title", "批量删除").set("code", classNameFirstLower + "BatchDelete").set("sortCode", 4),
+ JSONUtil.createObj().set("title", "导入" + functionName).set("code", classNameFirstLower + "Import").set("sortCode", 5),
+ JSONUtil.createObj().set("title", "导出" + functionName).set("code", classNameFirstLower + "Export").set("sortCode", 6)).forEach(jsonObject -> {
SysButtonAddParam sysButtonAddParam = new SysButtonAddParam();
BeanUtil.copyProperties(jsonObject, sysButtonAddParam);
sysButtonAddParam.setParentId(sysMenu.getId());
@@ -171,7 +173,7 @@ public class SysButtonServiceImpl extends ServiceImpl impl
this.removeByIds(toDeleteMenuIdList);
// 发布删除事件
- CommonDataChangeEventCenter.doDeleteWithDataId(SysDataTypeEnum.RESOURCE.getValue(), toDeleteMenuIdList);
+ CommonDataChangeEventCenter.doDeleteWithDataIdList(SysDataTypeEnum.RESOURCE.getValue(), toDeleteMenuIdList);
}
}
}
diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysModuleServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysModuleServiceImpl.java
index afc4540a..b8cf9655 100644
--- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysModuleServiceImpl.java
+++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysModuleServiceImpl.java
@@ -147,7 +147,7 @@ public class SysModuleServiceImpl extends ServiceImpl grantUser(@RequestBody @Valid SysRoleGrantUserParam sysRoleGrantUserParam) {
+ sysRoleGrantUserParam.setRemoveFirst(true);
sysRoleService.grantUser(sysRoleGrantUserParam);
return CommonResult.ok();
}
diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantUserParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantUserParam.java
index 385823cf..24747824 100644
--- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantUserParam.java
+++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantUserParam.java
@@ -39,4 +39,7 @@ public class SysRoleGrantUserParam {
@Schema(description = "授权用户信息")
@NotNull(message = "grantInfoList不能为空")
private List grantInfoList;
+
+ /** 是否先清空授权信息 */
+ private Boolean removeFirst = false;
}
diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/impl/SysRoleServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/impl/SysRoleServiceImpl.java
index a73be5a2..7c1b0dd4 100644
--- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/impl/SysRoleServiceImpl.java
+++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/impl/SysRoleServiceImpl.java
@@ -233,7 +233,7 @@ public class SysRoleServiceImpl extends ServiceImpl impl
this.removeByIds(sysRoleIdList);
// 发布删除事件
- CommonDataChangeEventCenter.doDeleteWithDataId(SysDataTypeEnum.ROLE.getValue(), sysRoleIdList);
+ CommonDataChangeEventCenter.doDeleteWithDataIdList(SysDataTypeEnum.ROLE.getValue(), sysRoleIdList);
}
}
@@ -326,8 +326,10 @@ public class SysRoleServiceImpl extends ServiceImpl impl
public void grantUser(SysRoleGrantUserParam sysRoleGrantUserParam) {
String id = sysRoleGrantUserParam.getId();
List grantInfoList = sysRoleGrantUserParam.getGrantInfoList();
- sysRelationService.remove(new LambdaQueryWrapper().eq(SysRelation::getTargetId, id)
- .eq(SysRelation::getCategory, SysRelationCategoryEnum.SYS_USER_HAS_ROLE.getValue()));
+ if(sysRoleGrantUserParam.getRemoveFirst()) {
+ sysRelationService.remove(new LambdaQueryWrapper().eq(SysRelation::getTargetId, id)
+ .eq(SysRelation::getCategory, SysRelationCategoryEnum.SYS_USER_HAS_ROLE.getValue()));
+ }
sysRelationService.saveBatch(grantInfoList.stream().map(userId -> {
SysRelation sysRelation = new SysRelation();
sysRelation.setObjectId(userId);
diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindEmailParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindEmailParam.java
index cb67619b..37af243e 100644
--- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindEmailParam.java
+++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindEmailParam.java
@@ -41,9 +41,4 @@ public class SysUserBindEmailParam {
@Schema(description = "验证码请求号")
@NotBlank(message = "validCodeReqNo不能为空")
private String validCodeReqNo;
-
- /** 新密码 */
- @Schema(description = "新密码")
- @NotBlank(message = "newPassword不能为空")
- private String newPassword;
}
diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserServiceImpl.java
index 1c030601..ad3a6a82 100644
--- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserServiceImpl.java
+++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserServiceImpl.java
@@ -65,6 +65,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
import vip.xiaonuo.common.cache.CommonCacheOperator;
+import vip.xiaonuo.common.enums.CommonGenderEnum;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.excel.CommonExcelCustomMergeStrategy;
import vip.xiaonuo.common.exception.CommonException;
@@ -93,6 +94,7 @@ import vip.xiaonuo.sys.modular.relation.service.SysRelationService;
import vip.xiaonuo.sys.modular.resource.entity.SysButton;
import vip.xiaonuo.sys.modular.resource.entity.SysMenu;
import vip.xiaonuo.sys.modular.resource.entity.SysModule;
+import vip.xiaonuo.sys.modular.resource.enums.SysMenuWhetherEnum;
import vip.xiaonuo.sys.modular.resource.enums.SysResourceCategoryEnum;
import vip.xiaonuo.sys.modular.resource.enums.SysResourceMenuTypeEnum;
import vip.xiaonuo.sys.modular.resource.service.SysButtonService;
@@ -447,7 +449,7 @@ public class SysUserServiceImpl extends ServiceImpl impl
sysUserExtService.remove(new LambdaQueryWrapper().in(SysUserExt::getUserId, sysUserIdList));
// 发布删除事件
- CommonDataChangeEventCenter.doDeleteWithDataId(SysDataTypeEnum.USER.getValue(), sysUserIdList);
+ CommonDataChangeEventCenter.doDeleteWithDataIdList(SysDataTypeEnum.USER.getValue(), sysUserIdList);
}
}
@@ -992,7 +994,7 @@ public class SysUserServiceImpl extends ServiceImpl impl
// 执行校验验证码
validValidCode(null, sysUserGetEmailValidCodeParam.getValidCode(), sysUserGetEmailValidCodeParam.getValidCodeReqNo());
// 根据邮箱获取用户信息,判断用户是否存在,如果存在则不能绑定该邮箱
- if (ObjectUtil.isEmpty(this.getUserByEmail(email))) {
+ if (ObjectUtil.isNotEmpty(this.getUserByEmail(email))) {
throw new CommonException("邮箱:{}已存在对应用户", email);
}
// 生成邮箱验证码的值,随机6为数字
@@ -1034,7 +1036,7 @@ public class SysUserServiceImpl extends ServiceImpl impl
// 执行校验验证码
validValidCode(null, sysUserGetEmailValidCodeParam.getValidCode(), sysUserGetEmailValidCodeParam.getValidCodeReqNo());
// 根据邮箱获取用户信息,判断用户是否存在,如果存在则不能绑定该邮箱
- if (ObjectUtil.isEmpty(this.getUserByEmail(email))) {
+ if (ObjectUtil.isNotEmpty(this.getUserByEmail(email))) {
throw new CommonException("邮箱:{}已存在对应用户", email);
}
// 生成邮箱验证码的值,随机6为数字
@@ -1074,7 +1076,7 @@ public class SysUserServiceImpl extends ServiceImpl impl
throw new CommonException("邮箱:{}格式错误", email);
}
// 根据邮箱获取用户信息,判断用户是否存在,如果存在则不能绑定该邮箱
- if (ObjectUtil.isEmpty(this.getUserByEmail(email))) {
+ if (ObjectUtil.isNotEmpty(this.getUserByEmail(email))) {
throw new CommonException("邮箱:{}已存在对应用户", email);
}
// 执行校验验证码
@@ -1253,6 +1255,20 @@ public class SysUserServiceImpl extends ServiceImpl impl
// 如果是首页,则设置affix
metaJsonObject.set("affix", true);
}
+ String menuMetaKeepLiveKey = "keepLive";
+ String menuMetaDisplayLayoutKey = "displayLayout";
+ // 设置缓存
+ if (ObjectUtil.isEmpty(sysMenu.getKeepLive()) || sysMenu.getKeepLive().equals(SysMenuWhetherEnum.NO.getValue())) {
+ metaJsonObject.set(menuMetaKeepLiveKey, false);
+ } else if (sysMenu.getKeepLive().equals(SysMenuWhetherEnum.YES.getValue())) {
+ metaJsonObject.set(menuMetaKeepLiveKey, true);
+ }
+ // 设置显示布局
+ if (ObjectUtil.isEmpty(sysMenu.getDisplayLayout()) || sysMenu.getDisplayLayout().equals(SysMenuWhetherEnum.YES.getValue())) {
+ metaJsonObject.set(menuMetaDisplayLayoutKey, true);
+ } else if (sysMenu.getDisplayLayout().equals(SysMenuWhetherEnum.NO.getValue())) {
+ metaJsonObject.set(menuMetaDisplayLayoutKey, false);
+ }
}
// 如果设置了不可见,那么设置为false,为了兼容已有,所以只是false的为不显示
if (ObjectUtil.isNotEmpty(sysMenu.getVisible()) && sysMenu.getVisible().equals("FALSE")) {
@@ -1347,10 +1363,10 @@ public class SysUserServiceImpl extends ServiceImpl impl
}
}
}
- List extJsonList = sysUserGrantResourceParam.getGrantInfoList().stream()
- .map(JSONUtil::toJsonStr).collect(Collectors.toList());
- sysRelationService.saveRelationBatchWithClear(sysUserGrantResourceParam.getId(), menuIdList, SysRelationCategoryEnum.SYS_USER_HAS_RESOURCE.getValue(), extJsonList);
}
+ List extJsonList = sysUserGrantResourceParam.getGrantInfoList().stream()
+ .map(JSONUtil::toJsonStr).collect(Collectors.toList());
+ sysRelationService.saveRelationBatchWithClear(sysUserGrantResourceParam.getId(), menuIdList, SysRelationCategoryEnum.SYS_USER_HAS_RESOURCE.getValue(), extJsonList);
}
@Override
@@ -1551,7 +1567,7 @@ public class SysUserServiceImpl extends ServiceImpl impl
FileUtil.FILE_SEPARATOR + "userImportTemplate.xlsx"));
// 读取excel
List sysUserImportParamList = EasyExcel.read(tempFile).head(SysUserImportParam.class).sheet()
- .headRowNumber(2).doReadSync();
+ .headRowNumber(3).doReadSync();
List allUserList = this.list();
for (int i = 0; i < sysUserImportParamList.size(); i++) {
JSONObject jsonObject = this.doImport(allUserList, sysUserImportParamList.get(i), i);
@@ -2147,6 +2163,7 @@ public class SysUserServiceImpl extends ServiceImpl impl
sysUserAddParam.setPhone(phone);
sysUserAddParam.setOrgId(this.getDefaultNewUserOrgId());
sysUserAddParam.setPositionId(this.getDefaultNewUserPositionId());
+ sysUserAddParam.setGender(CommonGenderEnum.UNKNOWN.getValue());
// 保存用户
this.add(sysUserAddParam, SysUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue());
// 获取用户信息
@@ -2182,6 +2199,7 @@ public class SysUserServiceImpl extends ServiceImpl impl
sysUserAddParam.setEmail(email);
sysUserAddParam.setOrgId(this.getDefaultNewUserOrgId());
sysUserAddParam.setPositionId(this.getDefaultNewUserPositionId());
+ sysUserAddParam.setGender(CommonGenderEnum.UNKNOWN.getValue());
// 保存用户
this.add(sysUserAddParam, SysUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue());
// 获取用户信息
@@ -2219,6 +2237,7 @@ public class SysUserServiceImpl extends ServiceImpl impl
sysUserAddParam.setPassword(password);
sysUserAddParam.setOrgId(this.getDefaultNewUserOrgId());
sysUserAddParam.setPositionId(this.getDefaultNewUserPositionId());
+ sysUserAddParam.setGender(CommonGenderEnum.UNKNOWN.getValue());
// 保存用户
this.add(sysUserAddParam, SysUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue());
// 获取用户信息
diff --git a/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java b/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java
index a2ccecd0..37b6ebe4 100644
--- a/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java
+++ b/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java
@@ -107,7 +107,7 @@ import java.util.Map;
@MapperScan(basePackages = {"vip.xiaonuo.**.mapper"})
public class GlobalConfigure implements WebMvcConfigurer {
- @Autowired
+ @Resource
private SaTokenConfig saTokenConfig;
private static final String COMMON_REPEAT_SUBMIT_CACHE_KEY = "common-repeatSubmit:";
@@ -118,7 +118,6 @@ public class GlobalConfigure implements WebMvcConfigurer {
public static final String[] NO_LOGIN_PATH_ARR = {
/* 主入口 */
"/",
-
/* 静态资源 */
"/favicon.ico",
"/doc.html",
@@ -133,11 +132,17 @@ public class GlobalConfigure implements WebMvcConfigurer {
"/auth/c/getPhoneValidCode",
"/auth/c/doLogin",
"/auth/c/doLoginByPhone",
+ "/auth/c/register",
+ "/auth/c/getEmailValidCode",
+ "/auth/c/doLoginByEmail",
"/auth/b/getPicCaptcha",
"/auth/b/getPhoneValidCode",
"/auth/b/doLogin",
"/auth/b/doLoginByPhone",
+ "/auth/b/register",
+ "/auth/b/getEmailValidCode",
+ "/auth/b/doLoginByEmail",
/* 三方登录相关 */
"/auth/third/render",
@@ -154,7 +159,10 @@ public class GlobalConfigure implements WebMvcConfigurer {
"/sys/userCenter/findPasswordGetPhoneValidCode",
"/sys/userCenter/findPasswordGetEmailValidCode",
"/sys/userCenter/findPasswordByPhone",
- "/sys/userCenter/findPasswordByEmail"
+ "/sys/userCenter/findPasswordByEmail",
+
+ /* 文件下载 */
+ "/dev/file/download"
};
/**
diff --git a/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql b/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql
index 5d067fa4..da226a7b 100644
--- a/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql
+++ b/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql
@@ -587,6 +587,7 @@ CREATE TABLE `DEV_FILE` (
`OBJ_NAME` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文件的对象名(唯一名称)',
`STORAGE_PATH` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文件存储路径',
`DOWNLOAD_PATH` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文件下载路径',
+ `IS_DOWNLOAD_AUTH` tinyint(1) NULL DEFAULT NULL COMMENT '文件下载是否需要授权',
`THUMBNAIL` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '图片缩略图',
`EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息',
`DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志',
@@ -847,6 +848,7 @@ CREATE TABLE `GEN_CONFIG` (
`WHETHER_RETRACT` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '列省略',
`WHETHER_ADD_UPDATE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否增改',
`WHETHER_REQUIRED` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '必填',
+ `WHETHER_UNIQUE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '唯一',
`QUERY_WHETHER` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '查询',
`QUERY_TYPE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '查询方式',
`SORT_CODE` int(11) NULL DEFAULT NULL COMMENT '排序',
@@ -1196,6 +1198,8 @@ CREATE TABLE `SYS_RESOURCE` (
`ICON` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标',
`COLOR` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '颜色',
`VISIBLE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否可见',
+ `DISPLAY_LAYOUT` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '显示布局',
+ `KEEP_LIVE` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '页签缓存',
`SORT_CODE` int(11) NULL DEFAULT NULL COMMENT '排序码',
`EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息',
`DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志',