Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
962b0b7431 | |||
9b60e24364 | |||
def831f2dc | |||
dc9273132d | |||
0a0353f1f6 | |||
42ac82e7ce | |||
![]() |
15c966f7bb | ||
faa56d16b9 | |||
53eaef9fbd | |||
9a1a472ec9 | |||
![]() |
4c6a7fb91a |
BIN
.image/screenshot/000登录页面-H5.png
Normal file
After Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 210 KiB After Width: | Height: | Size: 211 KiB |
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 253 KiB |
Before Width: | Height: | Size: 286 KiB After Width: | Height: | Size: 252 KiB |
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 99 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 147 KiB |
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 146 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 375 KiB After Width: | Height: | Size: 305 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 89 KiB |
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 849 KiB After Width: | Height: | Size: 808 KiB |
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 99 KiB |
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 167 KiB After Width: | Height: | Size: 168 KiB |
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 150 KiB |
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 131 KiB |
20
CHANGELOG.md
@@ -1,3 +1,23 @@
|
||||
## [v3.0.1](https://github.com/Charles7c/continew-admin/compare/v3.0.0...v3.0.1) (2024-05-03)
|
||||
|
||||
### ✨ 新特性
|
||||
|
||||
* 新增验证码超时显示效果,超时后显示已过期请刷新 (GitHub#56) ([4c6a7fb](https://github.com/Charles7c/continew-admin/commit/4c6a7fb91ad195b86d776f8aef6aef81d07b2eb1))
|
||||
* 文件管理增加资源统计,统计总存储量、各类型文件存储占用 (GitHub#58) ([15c966f](https://github.com/Charles7c/continew-admin/commit/15c966f7bb255db3edea249f8d3354324cbdbf5b))
|
||||
|
||||
### 💎 功能优化
|
||||
|
||||
- 获取图片验证码 URL /img => /image ([9a1a472](https://github.com/Charles7c/continew-admin/commit/9a1a472ec996362cb918e79b9ce37bfa2639a10b))
|
||||
- 移除对部分 API 重复的权限校验 ([53eaef9](https://github.com/Charles7c/continew-admin/commit/53eaef9fbdfd6d0866a3d5e424d783e2e7bc0e17))
|
||||
- 优化代码生成模板 ([dc92731](https://github.com/Charles7c/continew-admin/commit/dc9273132dc8e266f2d44c834b9c2733256afdfe)) ([def831f](https://github.com/Charles7c/continew-admin/commit/def831f2dca0703f5ef8b84b0e695a32b171461d))
|
||||
|
||||
|
||||
### 🐛 问题修复
|
||||
|
||||
- 修复查询用户邮箱、手机号时未自动加密导致的错误 ([faa56d1](https://github.com/Charles7c/continew-admin/commit/faa56d16b92cbdb8f7e16c8b43c2916ae692d881))
|
||||
- 修复根据部门查询用户列表数据错误 ([42ac82e](https://github.com/Charles7c/continew-admin/commit/42ac82e7ceef9336741c2514470c0db36ab7075e))
|
||||
- 修复文件类型处理错误 ([9b60e24](https://github.com/Charles7c/continew-admin/commit/9b60e24364bfb4cc7cd9996a43579a062197cdf3))
|
||||
|
||||
## [v3.0.0](https://github.com/Charles7c/continew-admin/compare/v2.5.0...v3.0.0) (2024-04-27)
|
||||
|
||||
### ✨ 新特性
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<img src="https://img.shields.io/badge/License-Apache--2.0-blue.svg" alt="License" />
|
||||
</a>
|
||||
<a href="https://github.com/Charles7c/continew-admin" target="_blank">
|
||||
<img src="https://img.shields.io/badge/RELEASE-v3.0.0-%23ff3f59.svg" alt="Release" />
|
||||
<img src="https://img.shields.io/badge/RELEASE-v3.0.1-%23ff3f59.svg" alt="Release" />
|
||||
</a>
|
||||
<a href="https://app.codacy.com/gh/Charles7c/continew-admin/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade" target="_blank">
|
||||
<img src="https://app.codacy.com/project/badge/Grade/19e3e2395d554efe902c3822e65db30e" alt="Codacy Badge" />
|
||||
@@ -130,7 +130,7 @@ public class DeptController extends BaseController<DeptService, DeptResp, DeptDe
|
||||
## 系统截图
|
||||
|
||||
> [!TIP]
|
||||
> 受篇幅长度及功能更新频率影响,下方仅为系统 **部分** 功能于 **2024年4月27日** 进行的截图,更多新增功能及细节请登录演示环境或 clone 代码到本地启动查看。
|
||||
> 受篇幅长度及功能更新频率影响,下方仅为系统 **部分** 功能于 **2024年5月3日** 进行的截图,更多新增功能及细节请登录演示环境或 clone 代码到本地启动查看。
|
||||
|
||||
<table border="1" cellpadding="1" cellspacing="1" style="width: 500px">
|
||||
<tbody>
|
||||
|
@@ -48,4 +48,10 @@ public class CaptchaResp implements Serializable {
|
||||
*/
|
||||
@Schema(description = "验证码图片(Base64编码,带图片格式:data:image/gif;base64)", example = "data:image/png;base64,iVBORw0KGgoAAAAN...")
|
||||
private String img;
|
||||
|
||||
/**
|
||||
* 过期时间戳
|
||||
*/
|
||||
@Schema(description = "过期时间戳", example = "1714376969409")
|
||||
private Long expireTime;
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ export interface ${classNamePrefix}DetailResp {
|
||||
updateUserString: string
|
||||
</#if>
|
||||
}
|
||||
export interface ${classNamePrefix}Query extends PageQuery {
|
||||
export interface ${classNamePrefix}Query {
|
||||
<#if fieldConfigs??>
|
||||
<#list fieldConfigs as fieldConfig>
|
||||
<#if fieldConfig.showInQuery>
|
||||
@@ -30,10 +30,12 @@ export interface ${classNamePrefix}Query extends PageQuery {
|
||||
</#if>
|
||||
</#list>
|
||||
</#if>
|
||||
sort: Array<string>
|
||||
}
|
||||
export interface ${classNamePrefix}PageQuery extends ${classNamePrefix}Query, PageQuery {}
|
||||
|
||||
/** @desc 查询${businessName}列表 */
|
||||
export function list${classNamePrefix}(query: ${classNamePrefix}Query) {
|
||||
export function list${classNamePrefix}(query: ${classNamePrefix}PageQuery) {
|
||||
return http.get<PageRes<${classNamePrefix}Resp[]>>(`${'$'}{BASE_URL}`, query)
|
||||
}
|
||||
|
||||
|
@@ -28,7 +28,7 @@
|
||||
<span>新增</span>
|
||||
</a-button>
|
||||
<a-tooltip content="导出">
|
||||
<a-button v-permission="['${apiModuleName}:${apiName}:export']" @click="onExport">
|
||||
<a-button v-permission="['${apiModuleName}:${apiName}:export']" class="gi_hover_btn-border" @click="onExport">
|
||||
<template #icon>
|
||||
<icon-download />
|
||||
</template>
|
||||
@@ -74,7 +74,7 @@ const columns: TableInstanceColumns[] = [
|
||||
<#if fieldConfigs??>
|
||||
<#list fieldConfigs as fieldConfig>
|
||||
<#if fieldConfig.showInList>
|
||||
{ title: '${fieldConfig.comment}', dataIndex: '${fieldConfig.fieldName}' },
|
||||
{ title: '${fieldConfig.comment}', dataIndex: '${fieldConfig.fieldName}', slotName: ${fieldConfig.fieldName} },
|
||||
</#if>
|
||||
</#list>
|
||||
</#if>
|
||||
@@ -88,7 +88,7 @@ const columns: TableInstanceColumns[] = [
|
||||
}
|
||||
]
|
||||
|
||||
const queryForm: ${classNamePrefix}Query = reactive({
|
||||
const queryForm = reactive<${classNamePrefix}Query>({
|
||||
<#list fieldConfigs as fieldConfig>
|
||||
<#if fieldConfig.showInQuery>
|
||||
${fieldConfig.fieldName}: undefined,
|
||||
|
@@ -43,7 +43,7 @@ public enum FileTypeEnum implements IBaseEnum<Integer> {
|
||||
/**
|
||||
* 图片
|
||||
*/
|
||||
IMAGE(2, "图片", List.of("jpg", "png", "gif", "bmp", "webp", "ico", "psd", "tiff", "dwg", "jxr", "apng", "xcf")),
|
||||
IMAGE(2, "图片", List.of("jpg", "jpeg", "png", "gif", "bmp", "webp", "ico", "psd", "tiff", "dwg", "jxr", "apng", "xcf")),
|
||||
|
||||
/**
|
||||
* 文档
|
||||
|
@@ -16,9 +16,13 @@
|
||||
|
||||
package top.continew.admin.system.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import top.continew.admin.system.model.entity.FileDO;
|
||||
import top.continew.admin.system.model.resp.FileStatisticsResp;
|
||||
import top.continew.starter.data.mybatis.plus.base.BaseMapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 文件 Mapper
|
||||
*
|
||||
@@ -26,4 +30,12 @@ import top.continew.starter.data.mybatis.plus.base.BaseMapper;
|
||||
* @since 2023/12/23 10:38
|
||||
*/
|
||||
public interface FileMapper extends BaseMapper<FileDO> {
|
||||
|
||||
/**
|
||||
* 查询文件资源统计信息
|
||||
*
|
||||
* @return 文件资源统计信息
|
||||
*/
|
||||
@Select("SELECT type, COUNT(1) number, SUM(size) size FROM sys_file GROUP BY type")
|
||||
List<FileStatisticsResp> statistics();
|
||||
}
|
@@ -16,10 +16,14 @@
|
||||
|
||||
package top.continew.admin.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import top.continew.admin.common.config.mybatis.DataPermissionMapper;
|
||||
import top.continew.admin.system.model.entity.UserDO;
|
||||
import top.continew.starter.data.mybatis.plus.datapermission.DataPermission;
|
||||
import top.continew.starter.security.crypto.annotation.FieldEncrypt;
|
||||
|
||||
/**
|
||||
@@ -30,6 +34,17 @@ import top.continew.starter.security.crypto.annotation.FieldEncrypt;
|
||||
*/
|
||||
public interface UserMapper extends DataPermissionMapper<UserDO> {
|
||||
|
||||
/**
|
||||
* 分页查询列表
|
||||
*
|
||||
* @param page 分页条件
|
||||
* @param queryWrapper 查询条件
|
||||
* @return 分页列表信息
|
||||
*/
|
||||
@DataPermission
|
||||
IPage<UserDO> selectUserPage(@Param("page") IPage<UserDO> page,
|
||||
@Param(Constants.WRAPPER) QueryWrapper<UserDO> queryWrapper);
|
||||
|
||||
/**
|
||||
* 根据用户名查询
|
||||
*
|
||||
@@ -65,4 +80,20 @@ public interface UserMapper extends DataPermissionMapper<UserDO> {
|
||||
*/
|
||||
@Select("SELECT nickname FROM sys_user WHERE id = #{id}")
|
||||
String selectNicknameById(@Param("id") Long id);
|
||||
|
||||
/**
|
||||
* 根据邮箱查询数量
|
||||
*
|
||||
* @param email 邮箱
|
||||
* @return 用户数量
|
||||
*/
|
||||
Long selectCountByEmail(@FieldEncrypt @Param("email") String email, @Param("id") Long id);
|
||||
|
||||
/**
|
||||
* 根据手机号查询数量
|
||||
*
|
||||
* @param phone 手机号
|
||||
* @return 用户数量
|
||||
*/
|
||||
Long selectCountByPhone(@FieldEncrypt @Param("phone") String phone, @Param("id") Long id);
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ package top.continew.admin.system.model.query;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
@@ -68,6 +69,7 @@ public class LogQuery implements Serializable {
|
||||
*/
|
||||
@Schema(description = "操作时间", example = "2023-08-08 00:00:00,2023-08-08 23:59:59")
|
||||
@DateTimeFormat(pattern = DatePattern.NORM_DATETIME_PATTERN)
|
||||
@Size(max = 2, message = "操作时间必须是一个范围")
|
||||
private List<Date> createTime;
|
||||
|
||||
/**
|
||||
|
@@ -18,10 +18,9 @@ package top.continew.admin.system.model.query;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import top.continew.starter.data.core.annotation.Query;
|
||||
import top.continew.starter.data.core.enums.QueryType;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
@@ -45,7 +44,6 @@ public class UserQuery implements Serializable {
|
||||
* 关键词
|
||||
*/
|
||||
@Schema(description = "关键词", example = "zhangsan")
|
||||
@Query(columns = {"username", "nickname", "description"}, type = QueryType.LIKE)
|
||||
private String description;
|
||||
|
||||
/**
|
||||
@@ -58,8 +56,8 @@ public class UserQuery implements Serializable {
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description = "创建时间", example = "2023-08-08 00:00:00,2023-08-08 23:59:59")
|
||||
@Query(type = QueryType.BETWEEN)
|
||||
@DateTimeFormat(pattern = DatePattern.NORM_DATETIME_PATTERN)
|
||||
@Size(max = 2, message = "创建时间必须是一个范围")
|
||||
private List<Date> createTime;
|
||||
|
||||
/**
|
||||
|
@@ -26,7 +26,6 @@ import org.hibernate.validator.constraints.Length;
|
||||
import top.continew.admin.common.constant.RegexConstants;
|
||||
import top.continew.admin.common.enums.DisEnableStatusEnum;
|
||||
import top.continew.starter.extension.crud.model.req.BaseReq;
|
||||
import top.continew.starter.extension.crud.util.ValidateGroup;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
@@ -47,7 +46,7 @@ public class DeptReq extends BaseReq {
|
||||
* 上级部门 ID
|
||||
*/
|
||||
@Schema(description = "上级部门 ID", example = "2")
|
||||
@NotNull(message = "上级部门不能为空", groups = ValidateGroup.Crud.Add.class)
|
||||
@NotNull(message = "上级部门不能为空")
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.system.model.resp;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import top.continew.admin.system.enums.FileTypeEnum;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 文件资源统计信息
|
||||
*
|
||||
* @author Kils
|
||||
* @since 2024/4/30 14:30
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "文件资源统计信息")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class FileStatisticsResp implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 文件类型
|
||||
*/
|
||||
@Schema(description = "类型(1:其他;2:图片;3:文档;4:视频;5:音频)", type = "Integer", allowableValues = {"1", "2", "3", "4",
|
||||
"5"}, example = "2")
|
||||
private FileTypeEnum type;
|
||||
|
||||
/**
|
||||
* 大小(字节)
|
||||
*/
|
||||
@Schema(description = "大小(字节)", example = "4096")
|
||||
private Long size;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
@Schema(description = "数量", example = "1000")
|
||||
private Long number;
|
||||
|
||||
/**
|
||||
* 分类数据
|
||||
*/
|
||||
@Schema(description = "分类数据")
|
||||
private List<FileStatisticsResp> data;
|
||||
}
|
@@ -23,6 +23,8 @@ import top.continew.admin.system.model.resp.DeptResp;
|
||||
import top.continew.starter.data.mybatis.plus.service.IService;
|
||||
import top.continew.starter.extension.crud.service.BaseService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 部门业务接口
|
||||
*
|
||||
@@ -30,4 +32,12 @@ import top.continew.starter.extension.crud.service.BaseService;
|
||||
* @since 2023/1/22 17:54
|
||||
*/
|
||||
public interface DeptService extends BaseService<DeptResp, DeptResp, DeptQuery, DeptReq>, IService<DeptDO> {
|
||||
|
||||
/**
|
||||
* 查询子部门列表
|
||||
*
|
||||
* @param id ID
|
||||
* @return 子部门列表
|
||||
*/
|
||||
List<DeptDO> listChildren(Long id);
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ import top.continew.admin.system.model.entity.FileDO;
|
||||
import top.continew.admin.system.model.query.FileQuery;
|
||||
import top.continew.admin.system.model.req.FileReq;
|
||||
import top.continew.admin.system.model.resp.FileResp;
|
||||
import top.continew.admin.system.model.resp.FileStatisticsResp;
|
||||
import top.continew.starter.data.mybatis.plus.service.IService;
|
||||
import top.continew.starter.extension.crud.service.BaseService;
|
||||
|
||||
@@ -61,4 +62,11 @@ public interface FileService extends BaseService<FileResp, FileResp, FileQuery,
|
||||
* @return 文件数量
|
||||
*/
|
||||
Long countByStorageIds(List<Long> storageIds);
|
||||
|
||||
/**
|
||||
* 查询文件资源统计信息
|
||||
*
|
||||
* @return 资源统计信息
|
||||
*/
|
||||
FileStatisticsResp statistics();
|
||||
}
|
@@ -20,6 +20,7 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.continew.admin.common.enums.DisEnableStatusEnum;
|
||||
@@ -50,9 +51,17 @@ import java.util.Optional;
|
||||
@RequiredArgsConstructor
|
||||
public class DeptServiceImpl extends BaseServiceImpl<DeptMapper, DeptDO, DeptResp, DeptResp, DeptQuery, DeptReq> implements DeptService {
|
||||
|
||||
private final UserService userService;
|
||||
@Resource
|
||||
private UserService userService;
|
||||
private final RoleDeptService roleDeptService;
|
||||
|
||||
@Override
|
||||
public List<DeptDO> listChildren(Long id) {
|
||||
DatabaseType databaseType = MetaUtils.getDatabaseTypeOrDefault(SpringUtil
|
||||
.getBean(DynamicRoutingDataSource.class), DatabaseType.MYSQL);
|
||||
return baseMapper.lambdaQuery().apply(databaseType.findInSet(id, "ancestors")).list();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeAdd(DeptReq req) {
|
||||
String name = req.getName();
|
||||
@@ -150,18 +159,6 @@ public class DeptServiceImpl extends BaseServiceImpl<DeptMapper, DeptDO, DeptRes
|
||||
return parentDept;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询子部门列表
|
||||
*
|
||||
* @param id ID
|
||||
* @return 子部门列表
|
||||
*/
|
||||
private List<DeptDO> listChildren(Long id) {
|
||||
DatabaseType databaseType = MetaUtils.getDatabaseTypeOrDefault(SpringUtil
|
||||
.getBean(DynamicRoutingDataSource.class), DatabaseType.MYSQL);
|
||||
return baseMapper.lambdaQuery().apply(databaseType.findInSet(id, "ancestors")).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询子部门数量
|
||||
*
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
package top.continew.admin.system.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
@@ -34,6 +35,7 @@ import top.continew.admin.system.model.entity.StorageDO;
|
||||
import top.continew.admin.system.model.query.FileQuery;
|
||||
import top.continew.admin.system.model.req.FileReq;
|
||||
import top.continew.admin.system.model.resp.FileResp;
|
||||
import top.continew.admin.system.model.resp.FileStatisticsResp;
|
||||
import top.continew.admin.system.service.FileService;
|
||||
import top.continew.admin.system.service.StorageService;
|
||||
import top.continew.starter.core.constant.StringConstants;
|
||||
@@ -113,6 +115,19 @@ public class FileServiceImpl extends BaseServiceImpl<FileMapper, FileDO, FileRes
|
||||
return baseMapper.lambdaQuery().in(FileDO::getStorageId, storageIds).count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileStatisticsResp statistics() {
|
||||
FileStatisticsResp resp = new FileStatisticsResp();
|
||||
List<FileStatisticsResp> statisticsList = baseMapper.statistics();
|
||||
if (CollUtil.isEmpty(statisticsList)) {
|
||||
return resp;
|
||||
}
|
||||
resp.setData(statisticsList);
|
||||
resp.setSize(statisticsList.stream().mapToLong(FileStatisticsResp::getSize).sum());
|
||||
resp.setNumber(statisticsList.stream().mapToLong(FileStatisticsResp::getNumber).sum());
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fill(Object obj) {
|
||||
super.fill(obj);
|
||||
|
@@ -41,7 +41,6 @@ import top.continew.admin.system.model.resp.log.LoginLogExportResp;
|
||||
import top.continew.admin.system.model.resp.log.OperationLogExportResp;
|
||||
import top.continew.admin.system.service.LogService;
|
||||
import top.continew.starter.core.util.validate.CheckUtils;
|
||||
import top.continew.starter.core.util.validate.ValidationUtils;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.query.SortQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
@@ -66,7 +65,7 @@ public class LogServiceImpl implements LogService {
|
||||
|
||||
@Override
|
||||
public PageResp<LogResp> page(LogQuery query, PageQuery pageQuery) {
|
||||
QueryWrapper<LogDO> queryWrapper = this.handleQueryWrapper(query);
|
||||
QueryWrapper<LogDO> queryWrapper = this.buildQueryWrapper(query);
|
||||
IPage<LogResp> page = baseMapper.selectLogPage(pageQuery.toPage(), queryWrapper);
|
||||
return PageResp.build(page);
|
||||
}
|
||||
@@ -120,7 +119,7 @@ public class LogServiceImpl implements LogService {
|
||||
* @return 列表信息
|
||||
*/
|
||||
private List<LogResp> list(LogQuery query, SortQuery sortQuery) {
|
||||
QueryWrapper<LogDO> queryWrapper = this.handleQueryWrapper(query);
|
||||
QueryWrapper<LogDO> queryWrapper = this.buildQueryWrapper(query);
|
||||
this.sort(queryWrapper, sortQuery);
|
||||
return baseMapper.selectLogList(queryWrapper);
|
||||
}
|
||||
@@ -142,39 +141,28 @@ public class LogServiceImpl implements LogService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理查询条件
|
||||
* 构建 QueryWrapper
|
||||
*
|
||||
* @param query 查询条件
|
||||
* @return QueryWrapper
|
||||
*/
|
||||
private QueryWrapper<LogDO> handleQueryWrapper(LogQuery query) {
|
||||
QueryWrapper<LogDO> queryWrapper = new QueryWrapper<>();
|
||||
// 构建条件
|
||||
private QueryWrapper<LogDO> buildQueryWrapper(LogQuery query) {
|
||||
String description = query.getDescription();
|
||||
if (StrUtil.isNotBlank(description)) {
|
||||
queryWrapper.and(q -> q.like("t1.description", description).or().like("t1.module", description));
|
||||
}
|
||||
String module = query.getModule();
|
||||
if (StrUtil.isNotBlank(module)) {
|
||||
queryWrapper.eq("t1.module", module);
|
||||
}
|
||||
String ip = query.getIp();
|
||||
if (StrUtil.isNotBlank(ip)) {
|
||||
queryWrapper.and(q -> q.like("t1.ip", ip).or().like("t1.address", ip));
|
||||
}
|
||||
String createUserString = query.getCreateUserString();
|
||||
if (StrUtil.isNotBlank(createUserString)) {
|
||||
queryWrapper.and(q -> q.like("t2.username", createUserString).or().like("t2.nickname", createUserString));
|
||||
}
|
||||
List<Date> createTimeList = query.getCreateTime();
|
||||
if (CollUtil.isNotEmpty(createTimeList)) {
|
||||
ValidationUtils.throwIf(createTimeList.size() != 2, "[{}] 必须是一个范围", "createTime");
|
||||
queryWrapper.between("t1.create_time", createTimeList.get(0), createTimeList.get(1));
|
||||
}
|
||||
Integer status = query.getStatus();
|
||||
if (null != status) {
|
||||
queryWrapper.eq("t1.status", status);
|
||||
}
|
||||
return queryWrapper;
|
||||
List<Date> createTimeList = query.getCreateTime();
|
||||
return new QueryWrapper<LogDO>().and(StrUtil.isNotBlank(description), q -> q.like("t1.description", description)
|
||||
.or()
|
||||
.like("t1.module", description))
|
||||
.eq(StrUtil.isNotBlank(module), "t1.module", module)
|
||||
.and(StrUtil.isNotBlank(ip), q -> q.like("t1.ip", ip).or().like("t1.address", ip))
|
||||
.and(StrUtil.isNotBlank(createUserString), q -> q.like("t2.username", createUserString)
|
||||
.or()
|
||||
.like("t2.nickname", createUserString))
|
||||
.eq(null != status, "t1.status", status)
|
||||
.between(CollUtil.isNotEmpty(createTimeList), "t1.create_time", CollUtil.getFirst(createTimeList), CollUtil
|
||||
.getLast(createTimeList));
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,9 @@ import com.alicp.jetcache.anno.CacheInvalidate;
|
||||
import com.alicp.jetcache.anno.CacheType;
|
||||
import com.alicp.jetcache.anno.CacheUpdate;
|
||||
import com.alicp.jetcache.anno.Cached;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.x.file.storage.core.FileInfo;
|
||||
import org.dromara.x.file.storage.core.FileStorageService;
|
||||
@@ -38,6 +41,7 @@ import top.continew.admin.common.constant.CacheConstants;
|
||||
import top.continew.admin.common.enums.DisEnableStatusEnum;
|
||||
import top.continew.admin.common.util.helper.LoginHelper;
|
||||
import top.continew.admin.system.mapper.UserMapper;
|
||||
import top.continew.admin.system.model.entity.DeptDO;
|
||||
import top.continew.admin.system.model.entity.UserDO;
|
||||
import top.continew.admin.system.model.query.UserQuery;
|
||||
import top.continew.admin.system.model.req.UserBasicInfoUpdateReq;
|
||||
@@ -46,19 +50,20 @@ import top.continew.admin.system.model.req.UserReq;
|
||||
import top.continew.admin.system.model.req.UserRoleUpdateReq;
|
||||
import top.continew.admin.system.model.resp.UserDetailResp;
|
||||
import top.continew.admin.system.model.resp.UserResp;
|
||||
import top.continew.admin.system.service.FileService;
|
||||
import top.continew.admin.system.service.RoleService;
|
||||
import top.continew.admin.system.service.UserRoleService;
|
||||
import top.continew.admin.system.service.UserService;
|
||||
import top.continew.admin.system.service.*;
|
||||
import top.continew.starter.core.constant.StringConstants;
|
||||
import top.continew.starter.core.util.validate.CheckUtils;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
import top.continew.starter.extension.crud.service.CommonUserService;
|
||||
import top.continew.starter.extension.crud.service.impl.BaseServiceImpl;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 用户业务实现
|
||||
@@ -76,9 +81,20 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
||||
private final FileService fileService;
|
||||
private final FileStorageService fileStorageService;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
@Resource
|
||||
private DeptService deptService;
|
||||
@Value("${avatar.support-suffix}")
|
||||
private String[] avatarSupportSuffix;
|
||||
|
||||
@Override
|
||||
public PageResp<UserResp> page(UserQuery query, PageQuery pageQuery) {
|
||||
QueryWrapper<UserDO> queryWrapper = this.buildQueryWrapper(query);
|
||||
IPage<UserDO> page = baseMapper.selectUserPage(pageQuery.toPage(), queryWrapper);
|
||||
PageResp<UserResp> pageResp = PageResp.build(page, this.listClass);
|
||||
pageResp.getList().forEach(this::fill);
|
||||
return pageResp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long add(UserDO user) {
|
||||
user.setStatus(DisEnableStatusEnum.ENABLE);
|
||||
@@ -86,25 +102,6 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
||||
return user.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeAdd(UserReq req) {
|
||||
final String errorMsgTemplate = "新增失败,[{}] 已存在";
|
||||
String username = req.getUsername();
|
||||
CheckUtils.throwIf(this.isNameExists(username, null), errorMsgTemplate, username);
|
||||
String email = req.getEmail();
|
||||
CheckUtils.throwIf(StrUtil.isNotBlank(email) && this.isEmailExists(email, null), errorMsgTemplate, email);
|
||||
String phone = req.getPhone();
|
||||
CheckUtils.throwIf(StrUtil.isNotBlank(phone) && this.isPhoneExists(phone, null), errorMsgTemplate, phone);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterAdd(UserReq req, UserDO user) {
|
||||
Long userId = user.getId();
|
||||
baseMapper.lambdaUpdate().set(UserDO::getPwdResetTime, LocalDateTime.now()).eq(UserDO::getId, userId).update();
|
||||
// 保存用户和角色关联
|
||||
userRoleService.add(req.getRoleIds(), userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@CacheUpdate(key = "#id", value = "#req.nickname", name = CacheConstants.USER_KEY_PREFIX)
|
||||
@@ -157,17 +154,6 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
||||
super.delete(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fill(Object obj) {
|
||||
super.fill(obj);
|
||||
if (obj instanceof UserDetailResp detail) {
|
||||
List<Long> roleIdList = detail.getRoleIds();
|
||||
if (CollUtil.isNotEmpty(roleIdList)) {
|
||||
detail.setRoleNames(String.join(StringConstants.CHINESE_COMMA, roleService.listNameByIds(roleIdList)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String uploadAvatar(MultipartFile avatarFile, Long id) {
|
||||
@@ -217,8 +203,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
||||
public void updatePhone(String newPhone, String currentPassword, Long id) {
|
||||
UserDO user = super.getById(id);
|
||||
CheckUtils.throwIf(!passwordEncoder.matches(currentPassword, user.getPassword()), "当前密码错误");
|
||||
Long count = baseMapper.lambdaQuery().eq(UserDO::getPhone, newPhone).count();
|
||||
CheckUtils.throwIf(count > 0, "手机号已绑定其他账号,请更换其他手机号");
|
||||
CheckUtils.throwIf(this.isPhoneExists(newPhone, id), "手机号已绑定其他账号,请更换其他手机号");
|
||||
CheckUtils.throwIfEqual(newPhone, user.getPhone(), "新手机号不能与当前手机号相同");
|
||||
// 更新手机号
|
||||
baseMapper.lambdaUpdate().set(UserDO::getPhone, newPhone).eq(UserDO::getId, id).update();
|
||||
@@ -228,8 +213,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
||||
public void updateEmail(String newEmail, String currentPassword, Long id) {
|
||||
UserDO user = super.getById(id);
|
||||
CheckUtils.throwIf(!passwordEncoder.matches(currentPassword, user.getPassword()), "当前密码错误");
|
||||
Long count = baseMapper.lambdaQuery().eq(UserDO::getEmail, newEmail).count();
|
||||
CheckUtils.throwIf(count > 0, "邮箱已绑定其他账号,请更换其他邮箱");
|
||||
CheckUtils.throwIf(this.isEmailExists(newEmail, id), "邮箱已绑定其他账号,请更换其他邮箱");
|
||||
CheckUtils.throwIfEqual(newEmail, user.getEmail(), "新邮箱不能与当前邮箱相同");
|
||||
// 更新邮箱
|
||||
baseMapper.lambdaUpdate().set(UserDO::getEmail, newEmail).eq(UserDO::getId, id).update();
|
||||
@@ -277,6 +261,65 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
||||
return baseMapper.selectNicknameById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fill(Object obj) {
|
||||
super.fill(obj);
|
||||
if (obj instanceof UserDetailResp detail) {
|
||||
List<Long> roleIdList = detail.getRoleIds();
|
||||
if (CollUtil.isNotEmpty(roleIdList)) {
|
||||
detail.setRoleNames(String.join(StringConstants.CHINESE_COMMA, roleService.listNameByIds(roleIdList)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeAdd(UserReq req) {
|
||||
final String errorMsgTemplate = "新增失败,[{}] 已存在";
|
||||
String username = req.getUsername();
|
||||
CheckUtils.throwIf(this.isNameExists(username, null), errorMsgTemplate, username);
|
||||
String email = req.getEmail();
|
||||
CheckUtils.throwIf(StrUtil.isNotBlank(email) && this.isEmailExists(email, null), errorMsgTemplate, email);
|
||||
String phone = req.getPhone();
|
||||
CheckUtils.throwIf(StrUtil.isNotBlank(phone) && this.isPhoneExists(phone, null), errorMsgTemplate, phone);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterAdd(UserReq req, UserDO user) {
|
||||
Long userId = user.getId();
|
||||
baseMapper.lambdaUpdate().set(UserDO::getPwdResetTime, LocalDateTime.now()).eq(UserDO::getId, userId).update();
|
||||
// 保存用户和角色关联
|
||||
userRoleService.add(req.getRoleIds(), userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 QueryWrapper
|
||||
*
|
||||
* @param query 查询条件
|
||||
* @return QueryWrapper
|
||||
*/
|
||||
private QueryWrapper<UserDO> buildQueryWrapper(UserQuery query) {
|
||||
String description = query.getDescription();
|
||||
Integer status = query.getStatus();
|
||||
List<Date> createTimeList = query.getCreateTime();
|
||||
Long deptId = query.getDeptId();
|
||||
return new QueryWrapper<UserDO>().and(StrUtil.isNotBlank(description), q -> q.like("t1.username", description)
|
||||
.or()
|
||||
.like("t1.nickname", description)
|
||||
.or()
|
||||
.like("t1.description", description))
|
||||
.eq(null != status, "t1.status", status)
|
||||
.between(CollUtil.isNotEmpty(createTimeList), "t1.create_time", CollUtil.getFirst(createTimeList), CollUtil
|
||||
.getLast(createTimeList))
|
||||
.and(null != deptId, q -> {
|
||||
List<Long> deptIdList = deptService.listChildren(deptId)
|
||||
.stream()
|
||||
.map(DeptDO::getId)
|
||||
.collect(Collectors.toList());
|
||||
deptIdList.add(deptId);
|
||||
q.in("t1.dept_id", deptIdList);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 名称是否存在
|
||||
*
|
||||
@@ -296,7 +339,8 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
||||
* @return 是否存在
|
||||
*/
|
||||
private boolean isEmailExists(String email, Long id) {
|
||||
return baseMapper.lambdaQuery().eq(UserDO::getEmail, email).ne(null != id, UserDO::getId, id).exists();
|
||||
Long count = baseMapper.selectCountByEmail(email, id);
|
||||
return null != count && count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -307,6 +351,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
||||
* @return 是否存在
|
||||
*/
|
||||
private boolean isPhoneExists(String phone, Long id) {
|
||||
return baseMapper.lambdaQuery().eq(UserDO::getPhone, phone).ne(null != id, UserDO::getId, id).exists();
|
||||
Long count = baseMapper.selectCountByPhone(phone, id);
|
||||
return null != count && count > 0;
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,29 @@
|
||||
<?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="top.continew.admin.system.mapper.UserMapper">
|
||||
|
||||
<select id="selectUserPage" resultType="top.continew.admin.system.model.entity.UserDO">
|
||||
SELECT t1.*
|
||||
FROM sys_user AS t1
|
||||
LEFT JOIN sys_dept AS t2 ON t2.id = t1.dept_id
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
|
||||
<select id="selectCountByEmail" resultType="java.lang.Long">
|
||||
SELECT count(*)
|
||||
FROM sys_user
|
||||
WHERE email = #{email}
|
||||
<if test="id != null">
|
||||
AND id != #{id}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="selectCountByPhone" resultType="java.lang.Long">
|
||||
SELECT count(*)
|
||||
FROM sys_user
|
||||
WHERE phone = #{phone}
|
||||
<if test="id != null">
|
||||
AND id != #{id}
|
||||
</if>
|
||||
</select>
|
||||
</mapper>
|
@@ -17,6 +17,7 @@
|
||||
package top.continew.admin.webapi.common;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.lang.RegexPool;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
@@ -57,6 +58,7 @@ import top.continew.starter.messaging.mail.util.MailUtils;
|
||||
import top.continew.starter.web.model.R;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -96,13 +98,15 @@ public class CaptchaController {
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "获取图片验证码", description = "获取图片验证码(Base64编码,带图片格式:data:image/gif;base64)")
|
||||
@GetMapping("/img")
|
||||
@GetMapping("/image")
|
||||
public R<CaptchaResp> getImageCaptcha() {
|
||||
String uuid = IdUtil.fastUUID();
|
||||
String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + uuid;
|
||||
Captcha captcha = graphicCaptchaService.getCaptcha();
|
||||
long expireTime = LocalDateTimeUtil.toEpochMilli(LocalDateTime.now()
|
||||
.plusMinutes(captchaProperties.getExpirationInMinutes()));
|
||||
RedisUtils.set(captchaKey, captcha.text(), Duration.ofMinutes(captchaProperties.getExpirationInMinutes()));
|
||||
return R.ok(CaptchaResp.builder().uuid(uuid).img(captcha.toBase64()).build());
|
||||
return R.ok(CaptchaResp.builder().uuid(uuid).img(captcha.toBase64()).expireTime(expireTime).build());
|
||||
}
|
||||
|
||||
@Operation(summary = "获取邮箱验证码", description = "发送验证码到指定邮箱")
|
||||
|
@@ -16,17 +16,20 @@
|
||||
|
||||
package top.continew.admin.webapi.system;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import top.continew.admin.system.model.query.FileQuery;
|
||||
import top.continew.admin.system.model.req.FileReq;
|
||||
import top.continew.admin.system.model.resp.FileResp;
|
||||
import top.continew.admin.system.model.resp.FileStatisticsResp;
|
||||
import top.continew.admin.system.service.FileService;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.controller.BaseController;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import top.continew.starter.log.core.annotation.Log;
|
||||
import top.continew.starter.web.model.R;
|
||||
|
||||
/**
|
||||
* 文件管理 API
|
||||
@@ -36,6 +39,16 @@ import top.continew.starter.extension.crud.enums.Api;
|
||||
*/
|
||||
@Tag(name = "文件管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/system/file", api = {Api.PAGE, Api.UPDATE, Api.DELETE})
|
||||
public class FileController extends BaseController<FileService, FileResp, FileResp, FileQuery, FileReq> {
|
||||
|
||||
private final FileService fileService;
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "查询文件资源统计", description = "查询文件资源统计")
|
||||
@GetMapping("/statistics")
|
||||
public R<FileStatisticsResp> statistics() {
|
||||
return R.ok(fileService.statistics());
|
||||
}
|
||||
}
|
@@ -16,7 +16,6 @@
|
||||
|
||||
package top.continew.admin.webapi.system;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -49,14 +48,12 @@ import top.continew.starter.web.model.R;
|
||||
public class MenuController extends BaseController<MenuService, MenuResp, MenuResp, MenuQuery, MenuReq> {
|
||||
|
||||
@Override
|
||||
@SaCheckPermission("system:menu:add")
|
||||
public R<Long> add(@Validated(ValidateGroup.Crud.Add.class) @RequestBody MenuReq req) {
|
||||
this.checkPath(req);
|
||||
return super.add(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SaCheckPermission("system:menu:update")
|
||||
public R<Void> update(@Validated(ValidateGroup.Crud.Update.class) @RequestBody MenuReq req, @PathVariable Long id) {
|
||||
this.checkPath(req);
|
||||
return super.update(req, id);
|
||||
|
@@ -16,7 +16,6 @@
|
||||
|
||||
package top.continew.admin.webapi.system;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
@@ -48,14 +47,12 @@ import java.time.LocalDateTime;
|
||||
public class NoticeController extends BaseController<NoticeService, NoticeResp, NoticeDetailResp, NoticeQuery, NoticeReq> {
|
||||
|
||||
@Override
|
||||
@SaCheckPermission("system:notice:add")
|
||||
public R<Long> add(@Validated(ValidateGroup.Crud.Add.class) @RequestBody NoticeReq req) {
|
||||
this.checkTime(req);
|
||||
return super.add(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SaCheckPermission("system:notice:update")
|
||||
public R<Void> update(@Validated(ValidateGroup.Crud.Update.class) @RequestBody NoticeReq req,
|
||||
@PathVariable Long id) {
|
||||
this.checkTime(req);
|
||||
|
@@ -57,15 +57,13 @@ import top.continew.starter.web.model.R;
|
||||
public class UserController extends BaseController<UserService, UserResp, UserDetailResp, UserQuery, UserReq> {
|
||||
|
||||
@Override
|
||||
@SaCheckPermission("system:user:add")
|
||||
public R<Long> add(@Validated(ValidateGroup.Crud.Add.class) @RequestBody UserReq req) {
|
||||
String rawPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(req.getPassword()));
|
||||
ValidationUtils.throwIfNull(rawPassword, "密码解密失败");
|
||||
ValidationUtils.throwIf(!ReUtil
|
||||
.isMatch(RegexConstants.PASSWORD, rawPassword), "密码长度为 6 到 32 位,可以包含字母、数字、下划线,特殊字符,同时包含字母和数字");
|
||||
req.setPassword(rawPassword);
|
||||
Long id = baseService.add(req);
|
||||
return R.ok("新增成功", id);
|
||||
return super.add(req);
|
||||
}
|
||||
|
||||
@Operation(summary = "重置密码", description = "重置用户登录密码")
|
||||
|
@@ -33,7 +33,6 @@ import top.continew.admin.generator.model.req.GenConfigReq;
|
||||
import top.continew.admin.generator.model.resp.GeneratePreviewResp;
|
||||
import top.continew.admin.generator.model.resp.TableResp;
|
||||
import top.continew.admin.generator.service.GeneratorService;
|
||||
import top.continew.starter.core.autoconfigure.project.ProjectProperties;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
import top.continew.starter.web.model.R;
|
||||
@@ -54,7 +53,6 @@ import java.util.List;
|
||||
@RequestMapping("/generator")
|
||||
public class GeneratorController {
|
||||
|
||||
private final ProjectProperties projectProperties;
|
||||
private final GeneratorService generatorService;
|
||||
|
||||
@Operation(summary = "分页查询数据表", description = "分页查询数据表")
|
||||
|
@@ -5,7 +5,7 @@ project:
|
||||
# 应用名称
|
||||
app-name: continew-admin
|
||||
# 版本
|
||||
version: 3.0.0
|
||||
version: 3.0.1
|
||||
# 描述
|
||||
description: 持续迭代优化的前后端分离中后台管理系统框架,开箱即用,持续提供舒适的开发体验。
|
||||
# 基本包
|
||||
|