mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-10-31 22:57:17 +08:00 
			
		
		
		
	优化:🔥 深度优化后端 CRUD 公共组件,并抽取前端下载功能到 CRUD 公共组件
1. 后端抽取导出功能到 CRUD 公共组件 2. 查询列表及导出接口支持排序参数 3. 深度优化 BaseServiceImpl 中的 CRUD 公共实现 4. 前端抽取公共下载组件 5. 优化部分细节并修复部分错误
This commit is contained in:
		| @@ -72,7 +72,7 @@ yarn dev | |||||||
| | :----------------------------------------------------------- | :----------- | :----------------------------------------------------------- | | | :----------------------------------------------------------- | :----------- | :----------------------------------------------------------- | | ||||||
| | [Vue](https://cn.vuejs.org/)                                 | 3.2.45       | 渐进式 JavaScript 框架,易学易用,性能出色,适用场景丰富的 Web 前端框架。 | | | [Vue](https://cn.vuejs.org/)                                 | 3.2.45       | 渐进式 JavaScript 框架,易学易用,性能出色,适用场景丰富的 Web 前端框架。 | | ||||||
| | [TypeScript](https://www.typescriptlang.org/zh/)             | 4.9.4        | TypeScript 是微软开发的一个开源的编程语言,通过在 JavaScript 的基础上添加静态类型定义构建而成。 | | | [TypeScript](https://www.typescriptlang.org/zh/)             | 4.9.4        | TypeScript 是微软开发的一个开源的编程语言,通过在 JavaScript 的基础上添加静态类型定义构建而成。 | | ||||||
| | [Arco Design Pro Vue](http://pro.arco.design/)               | 2.6.0        | 基于 Arco Design Vue 组件库的开箱即用的中后台前端解决方案。  | | | [Arco Design Pro Vue](http://pro.arco.design/)               | 2.6.1        | 基于 Arco Design Vue 组件库的开箱即用的中后台前端解决方案。  | | ||||||
| | [Spring Boot](https://spring.io/projects/spring-boot)        | 2.7.8        | 简化新 Spring 应用的初始搭建以及开发过程。                   | | | [Spring Boot](https://spring.io/projects/spring-boot)        | 2.7.8        | 简化新 Spring 应用的初始搭建以及开发过程。                   | | ||||||
| | [Undertow](https://undertow.io/)                             | 2.2.22.Final | 采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。 | | | [Undertow](https://undertow.io/)                             | 2.2.22.Final | 采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。 | | ||||||
| | [Sa-Token + JWT](https://sa-token.dev33.cn/)                 | 1.34.0       | 轻量级 Java 权限认证框架,让鉴权变得简单、优雅。             | | | [Sa-Token + JWT](https://sa-token.dev33.cn/)                 | 1.34.0       | 轻量级 Java 权限认证框架,让鉴权变得简单、优雅。             | | ||||||
| @@ -229,6 +229,7 @@ continew-admin  # 全局通用项目配置及依赖版本管理 | |||||||
|   │                │  ├─ query        # 公共查询条件 |   │                │  ├─ query        # 公共查询条件 | ||||||
|   │                │  ├─ request      # 公共请求对象 |   │                │  ├─ request      # 公共请求对象 | ||||||
|   │                │  └─ vo           # 公共 VO(View Object) |   │                │  └─ vo           # 公共 VO(View Object) | ||||||
|  |   │                ├─ service      # 公共业务接口 | ||||||
|   │                └─ util         # 公共工具类 |   │                └─ util         # 公共工具类 | ||||||
|   │                  ├─ helper        # 公共 Helper(助手) |   │                  ├─ helper        # 公共 Helper(助手) | ||||||
|   │                  ├─ holder        # 公共 Holder(持有者) |   │                  ├─ holder        # 公共 Holder(持有者) | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ public @interface CrudRequestMapping { | |||||||
|     /** |     /** | ||||||
|      * API 列表 |      * API 列表 | ||||||
|      */ |      */ | ||||||
|     Api[] api() default {Api.PAGE, Api.GET, Api.CREATE, Api.UPDATE, Api.DELETE}; |     Api[] api() default {Api.PAGE, Api.GET, Api.CREATE, Api.UPDATE, Api.DELETE, Api.EXPORT}; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * API 枚举 |      * API 枚举 | ||||||
| @@ -70,6 +70,10 @@ public @interface CrudRequestMapping { | |||||||
|         /** |         /** | ||||||
|          * 删除 |          * 删除 | ||||||
|          */ |          */ | ||||||
|         DELETE,; |         DELETE, | ||||||
|  |         /** | ||||||
|  |          * 导出 | ||||||
|  |          */ | ||||||
|  |         EXPORT,; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,6 +18,8 @@ package top.charles7c.cnadmin.common.base; | |||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
|  | import javax.servlet.http.HttpServletResponse; | ||||||
|  |  | ||||||
| import lombok.NoArgsConstructor; | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.Operation; | import io.swagger.v3.oas.annotations.Operation; | ||||||
| @@ -29,6 +31,7 @@ import org.springframework.validation.annotation.Validated; | |||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
|  |  | ||||||
| import top.charles7c.cnadmin.common.model.query.PageQuery; | import top.charles7c.cnadmin.common.model.query.PageQuery; | ||||||
|  | import top.charles7c.cnadmin.common.model.query.SortQuery; | ||||||
| import top.charles7c.cnadmin.common.model.vo.PageDataVO; | import top.charles7c.cnadmin.common.model.vo.PageDataVO; | ||||||
| import top.charles7c.cnadmin.common.model.vo.R; | import top.charles7c.cnadmin.common.model.vo.R; | ||||||
|  |  | ||||||
| @@ -76,13 +79,15 @@ public abstract class BaseController<S extends BaseService<V, D, Q, C>, V, D, Q, | |||||||
|      * |      * | ||||||
|      * @param query |      * @param query | ||||||
|      *            查询条件 |      *            查询条件 | ||||||
|  |      * @param sortQuery | ||||||
|  |      *            排序查询条件 | ||||||
|      * @return 列表信息 |      * @return 列表信息 | ||||||
|      */ |      */ | ||||||
|     @Operation(summary = "查询列表") |     @Operation(summary = "查询列表") | ||||||
|     @ResponseBody |     @ResponseBody | ||||||
|     @GetMapping("/all") |     @GetMapping("/list") | ||||||
|     protected R<List<V>> list(@Validated Q query) { |     protected R<List<V>> list(@Validated Q query, @Validated SortQuery sortQuery) { | ||||||
|         List<V> list = baseService.list(query); |         List<V> list = baseService.list(query, sortQuery); | ||||||
|         return R.ok(list); |         return R.ok(list); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -147,4 +152,20 @@ public abstract class BaseController<S extends BaseService<V, D, Q, C>, V, D, Q, | |||||||
|         baseService.delete(ids); |         baseService.delete(ids); | ||||||
|         return R.ok("删除成功"); |         return R.ok("删除成功"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 导出 | ||||||
|  |      * | ||||||
|  |      * @param query | ||||||
|  |      *            查询条件 | ||||||
|  |      * @param sortQuery | ||||||
|  |      *            排序查询条件 | ||||||
|  |      * @param response | ||||||
|  |      *            响应对象 | ||||||
|  |      */ | ||||||
|  |     @Operation(summary = "导出数据") | ||||||
|  |     @GetMapping("/export") | ||||||
|  |     protected void export(@Validated Q query, @Validated SortQuery sortQuery, HttpServletResponse response) { | ||||||
|  |         baseService.export(query, sortQuery, response); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,7 +18,10 @@ package top.charles7c.cnadmin.common.base; | |||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
|  | import javax.servlet.http.HttpServletResponse; | ||||||
|  |  | ||||||
| import top.charles7c.cnadmin.common.model.query.PageQuery; | import top.charles7c.cnadmin.common.model.query.PageQuery; | ||||||
|  | import top.charles7c.cnadmin.common.model.query.SortQuery; | ||||||
| import top.charles7c.cnadmin.common.model.vo.PageDataVO; | import top.charles7c.cnadmin.common.model.vo.PageDataVO; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -53,9 +56,11 @@ public interface BaseService<V, D, Q, C extends BaseRequest> { | |||||||
|      * |      * | ||||||
|      * @param query |      * @param query | ||||||
|      *            查询条件 |      *            查询条件 | ||||||
|  |      * @param sortQuery | ||||||
|  |      *            排序查询条件 | ||||||
|      * @return 列表信息 |      * @return 列表信息 | ||||||
|      */ |      */ | ||||||
|     List<V> list(Q query); |     List<V> list(Q query, SortQuery sortQuery); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查看详情 |      * 查看详情 | ||||||
| @@ -90,4 +95,16 @@ public interface BaseService<V, D, Q, C extends BaseRequest> { | |||||||
|      *            ID 列表 |      *            ID 列表 | ||||||
|      */ |      */ | ||||||
|     void delete(List<Long> ids); |     void delete(List<Long> ids); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 导出 | ||||||
|  |      * | ||||||
|  |      * @param query | ||||||
|  |      *            查询条件 | ||||||
|  |      * @param sortQuery | ||||||
|  |      *            排序查询条件 | ||||||
|  |      * @param response | ||||||
|  |      *            响应对象 | ||||||
|  |      */ | ||||||
|  |     void export(Q query, SortQuery sortQuery, HttpServletResponse response); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -16,20 +16,35 @@ | |||||||
|  |  | ||||||
| package top.charles7c.cnadmin.common.base; | package top.charles7c.cnadmin.common.base; | ||||||
|  |  | ||||||
|  | import java.util.Collections; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
|  | import javax.servlet.http.HttpServletResponse; | ||||||
|  |  | ||||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.data.domain.Sort; | ||||||
| import org.springframework.transaction.annotation.Transactional; | import org.springframework.transaction.annotation.Transactional; | ||||||
|  |  | ||||||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||||||
| import com.baomidou.mybatisplus.core.mapper.BaseMapper; | import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||||||
| import com.baomidou.mybatisplus.core.metadata.IPage; | import com.baomidou.mybatisplus.core.metadata.IPage; | ||||||
|  | import com.baomidou.mybatisplus.core.metadata.TableInfo; | ||||||
|  | import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; | ||||||
|  | import com.baomidou.mybatisplus.core.toolkit.Assert; | ||||||
| import com.baomidou.mybatisplus.core.toolkit.ReflectionKit; | import com.baomidou.mybatisplus.core.toolkit.ReflectionKit; | ||||||
|  |  | ||||||
| import cn.hutool.core.bean.BeanUtil; | import cn.hutool.core.bean.BeanUtil; | ||||||
|  | import cn.hutool.core.collection.CollUtil; | ||||||
|  | import cn.hutool.core.convert.Convert; | ||||||
|  | import cn.hutool.core.util.StrUtil; | ||||||
|  | import cn.hutool.extra.spring.SpringUtil; | ||||||
|  |  | ||||||
| import top.charles7c.cnadmin.common.model.query.PageQuery; | import top.charles7c.cnadmin.common.model.query.PageQuery; | ||||||
|  | import top.charles7c.cnadmin.common.model.query.SortQuery; | ||||||
| import top.charles7c.cnadmin.common.model.vo.PageDataVO; | import top.charles7c.cnadmin.common.model.vo.PageDataVO; | ||||||
|  | import top.charles7c.cnadmin.common.service.CommonUserService; | ||||||
|  | import top.charles7c.cnadmin.common.util.ExcelUtils; | ||||||
|  | import top.charles7c.cnadmin.common.util.ExceptionUtils; | ||||||
| import top.charles7c.cnadmin.common.util.helper.QueryHelper; | import top.charles7c.cnadmin.common.util.helper.QueryHelper; | ||||||
| import top.charles7c.cnadmin.common.util.validate.CheckUtils; | import top.charles7c.cnadmin.common.util.validate.CheckUtils; | ||||||
|  |  | ||||||
| @@ -65,32 +80,39 @@ public abstract class BaseServiceImpl<M extends BaseMapper<T>, T, V, D, Q, C ext | |||||||
|     public PageDataVO<V> page(Q query, PageQuery pageQuery) { |     public PageDataVO<V> page(Q query, PageQuery pageQuery) { | ||||||
|         QueryWrapper<T> queryWrapper = QueryHelper.build(query); |         QueryWrapper<T> queryWrapper = QueryHelper.build(query); | ||||||
|         IPage<T> page = baseMapper.selectPage(pageQuery.toPage(), queryWrapper); |         IPage<T> page = baseMapper.selectPage(pageQuery.toPage(), queryWrapper); | ||||||
|         return PageDataVO.build(page, voClass); |         PageDataVO<V> pageDataVO = PageDataVO.build(page, voClass); | ||||||
|  |         pageDataVO.getList().forEach(this::fill); | ||||||
|  |         return pageDataVO; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public List<V> list(Q query) { |     public List<V> list(Q query, SortQuery sortQuery) { | ||||||
|         QueryWrapper<T> queryWrapper = QueryHelper.build(query); |         List<V> list = this.list(query, sortQuery, voClass); | ||||||
|         List<T> entityList = baseMapper.selectList(queryWrapper); |         list.forEach(this::fill); | ||||||
|         return BeanUtil.copyToList(entityList, voClass); |         return list; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public D get(Long id) { |     public D get(Long id) { | ||||||
|         T entity = this.getById(id); |         T entity = this.getById(id); | ||||||
|         return BeanUtil.copyProperties(entity, detailVoClass); |         D detailVO = BeanUtil.copyProperties(entity, detailVoClass); | ||||||
|  |         this.fillDetail(detailVO); | ||||||
|  |         return detailVO; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 新增 |  | ||||||
|      * |  | ||||||
|      * @param request |  | ||||||
|      *            创建信息 |  | ||||||
|      * @return 自增 ID |  | ||||||
|      */ |  | ||||||
|     @Override |     @Override | ||||||
|     @Transactional(rollbackFor = Exception.class) |     @Transactional(rollbackFor = Exception.class) | ||||||
|     public abstract Long create(C request); |     public Long create(C request) { | ||||||
|  |         if (request == null) { | ||||||
|  |             return 0L; | ||||||
|  |         } | ||||||
|  |         // 保存信息 | ||||||
|  |         T entity = BeanUtil.copyProperties(request, entityClass); | ||||||
|  |         baseMapper.insert(entity); | ||||||
|  |         TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass); | ||||||
|  |         Object idValue = tableInfo.getPropertyValue(entity, this.currentEntityIdName()); | ||||||
|  |         return Convert.toLong(idValue); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     @Transactional(rollbackFor = Exception.class) |     @Transactional(rollbackFor = Exception.class) | ||||||
| @@ -105,6 +127,35 @@ public abstract class BaseServiceImpl<M extends BaseMapper<T>, T, V, D, Q, C ext | |||||||
|         baseMapper.deleteBatchIds(ids); |         baseMapper.deleteBatchIds(ids); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void export(Q query, SortQuery sortQuery, HttpServletResponse response) { | ||||||
|  |         List<D> list = this.list(query, sortQuery, detailVoClass); | ||||||
|  |         list.forEach(this::fillDetail); | ||||||
|  |         ExcelUtils.export(list, "导出数据", detailVoClass, response); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 查询列表 | ||||||
|  |      * | ||||||
|  |      * @param query | ||||||
|  |      *            查询条件 | ||||||
|  |      * @param sortQuery | ||||||
|  |      *            排序查询条件 | ||||||
|  |      * @param targetClass | ||||||
|  |      *            指定类型 | ||||||
|  |      * @return 列表信息 | ||||||
|  |      */ | ||||||
|  |     protected <E> List<E> list(Q query, SortQuery sortQuery, Class<E> targetClass) { | ||||||
|  |         QueryWrapper<T> queryWrapper = QueryHelper.build(query); | ||||||
|  |         // 设置排序 | ||||||
|  |         Sort sort = sortQuery.getSort(); | ||||||
|  |         for (Sort.Order order : sort) { | ||||||
|  |             queryWrapper.orderBy(order != null, order.isAscending(), StrUtil.toUnderlineCase(order.getProperty())); | ||||||
|  |         } | ||||||
|  |         List<T> entityList = baseMapper.selectList(queryWrapper); | ||||||
|  |         return CollUtil.isNotEmpty(entityList) ? BeanUtil.copyToList(entityList, targetClass) : Collections.emptyList(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 根据 ID 查询 |      * 根据 ID 查询 | ||||||
|      * |      * | ||||||
| @@ -118,6 +169,57 @@ public abstract class BaseServiceImpl<M extends BaseMapper<T>, T, V, D, Q, C ext | |||||||
|         return entity; |         return entity; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 填充数据 | ||||||
|  |      * | ||||||
|  |      * @param baseObj | ||||||
|  |      *            待填充列表信息 | ||||||
|  |      */ | ||||||
|  |     protected void fill(Object baseObj) { | ||||||
|  |         if (baseObj instanceof BaseVO) { | ||||||
|  |             BaseVO baseVO = (BaseVO)baseObj; | ||||||
|  |             Long createUser = baseVO.getCreateUser(); | ||||||
|  |             if (createUser == null) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             CommonUserService userService = SpringUtil.getBean(CommonUserService.class); | ||||||
|  |             baseVO.setCreateUserString(ExceptionUtils.exToNull(() -> userService.getNicknameById(createUser))); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 填充详情数据 | ||||||
|  |      * | ||||||
|  |      * @param detailObj | ||||||
|  |      *            待填充详情信息 | ||||||
|  |      */ | ||||||
|  |     protected void fillDetail(Object detailObj) { | ||||||
|  |         if (detailObj instanceof BaseDetailVO) { | ||||||
|  |             BaseDetailVO detailVO = (BaseDetailVO)detailObj; | ||||||
|  |             this.fill(detailVO); | ||||||
|  |  | ||||||
|  |             Long updateUser = detailVO.getUpdateUser(); | ||||||
|  |             if (updateUser == null) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             CommonUserService userService = SpringUtil.getBean(CommonUserService.class); | ||||||
|  |             detailVO.setUpdateUserString(ExceptionUtils.exToNull(() -> userService.getNicknameById(updateUser))); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取实体类 ID 名称 | ||||||
|  |      * | ||||||
|  |      * @return 实体类 ID 名称 | ||||||
|  |      */ | ||||||
|  |     protected String currentEntityIdName() { | ||||||
|  |         TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass); | ||||||
|  |         Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!"); | ||||||
|  |         String keyProperty = tableInfo.getKeyProperty(); | ||||||
|  |         Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!"); | ||||||
|  |         return keyProperty; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 获取实体类 Class 对象 |      * 获取实体类 Class 对象 | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -16,14 +16,13 @@ | |||||||
|  |  | ||||||
| package top.charles7c.cnadmin.common.model.query; | package top.charles7c.cnadmin.common.model.query; | ||||||
|  |  | ||||||
| import java.io.Serializable; | import javax.validation.constraints.Min; | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| import lombok.Data; | import lombok.Data; | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  |  | ||||||
|  | import org.hibernate.validator.constraints.Range; | ||||||
| import org.springdoc.api.annotations.ParameterObject; | import org.springdoc.api.annotations.ParameterObject; | ||||||
| import org.springframework.data.domain.Sort; | import org.springframework.data.domain.Sort; | ||||||
|  |  | ||||||
| @@ -32,7 +31,6 @@ import com.baomidou.mybatisplus.core.metadata.OrderItem; | |||||||
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||||
|  |  | ||||||
| import cn.hutool.core.collection.CollUtil; | import cn.hutool.core.collection.CollUtil; | ||||||
| import cn.hutool.core.util.ArrayUtil; |  | ||||||
| import cn.hutool.core.util.StrUtil; | import cn.hutool.core.util.StrUtil; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -44,7 +42,7 @@ import cn.hutool.core.util.StrUtil; | |||||||
| @Data | @Data | ||||||
| @ParameterObject | @ParameterObject | ||||||
| @Schema(description = "分页查询条件") | @Schema(description = "分页查询条件") | ||||||
| public class PageQuery implements Serializable { | public class PageQuery extends SortQuery { | ||||||
|  |  | ||||||
|     private static final long serialVersionUID = 1L; |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
| @@ -52,60 +50,44 @@ public class PageQuery implements Serializable { | |||||||
|      * 页码 |      * 页码 | ||||||
|      */ |      */ | ||||||
|     @Schema(description = "页码") |     @Schema(description = "页码") | ||||||
|     private int page; |     @Min(value = 1, message = "页码最小值为 1") | ||||||
|  |     private Integer page; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 每页记录数 |      * 每页条数 | ||||||
|      */ |      */ | ||||||
|     @Schema(description = "每页记录数") |     @Schema(description = "每页条数") | ||||||
|     private int size; |     @Range(min = 1, max = 1000, message = "每页条数(取值范围 1-1000)") | ||||||
|  |     private Integer size; | ||||||
|     /** |  | ||||||
|      * 排序条件 |  | ||||||
|      */ |  | ||||||
|     @Schema(description = "排序条件", example = "sort=published,desc&sort=title,asc") |  | ||||||
|     private String[] sort; |  | ||||||
|  |  | ||||||
|     /** 默认页码:1 */ |     /** 默认页码:1 */ | ||||||
|     private static final int DEFAULT_PAGE = 1; |     private static final int DEFAULT_PAGE = 1; | ||||||
|  |     /** 默认每页条数:10 */ | ||||||
|     /** 默认每页记录数:10 */ |  | ||||||
|     private static final int DEFAULT_SIZE = 10; |     private static final int DEFAULT_SIZE = 10; | ||||||
|     private static final String DELIMITER = ","; |     /** 默认每页最大条数:1000 */ | ||||||
|  |     private static final int DEFAULT_MAX_SIZE = 1000; | ||||||
|  |  | ||||||
|     public PageQuery() { |     public PageQuery() { | ||||||
|         this.page = DEFAULT_PAGE; |         this(DEFAULT_PAGE, DEFAULT_SIZE); | ||||||
|         this.size = DEFAULT_SIZE; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public int getPage() { |     public PageQuery(Integer page, Integer size) { | ||||||
|         return page < 0 ? DEFAULT_PAGE : page; |         this.setPage(page); | ||||||
|  |         this.setSize(size); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     public void setPage(Integer page) { | ||||||
|      * 解析排序条件为 Spring 分页排序实体 |         this.page = page == null ? DEFAULT_PAGE : page; | ||||||
|      * |     } | ||||||
|      * @return Spring 分页排序实体 |  | ||||||
|      */ |  | ||||||
|     public Sort getSort() { |  | ||||||
|         if (ArrayUtil.isEmpty(sort)) { |  | ||||||
|             return Sort.unsorted(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         List<Sort.Order> orders = new ArrayList<>(sort.length); |     public void setSize(Integer size) { | ||||||
|         if (sort[0].contains(DELIMITER)) { |         if (size == null) { | ||||||
|             // e.g "sort=published,desc&sort=title,asc" |             this.size = DEFAULT_SIZE; | ||||||
|             for (String s : sort) { |         } else if (size > DEFAULT_MAX_SIZE) { | ||||||
|                 String[] sortArr = s.split(DELIMITER); |             this.size = DEFAULT_MAX_SIZE; | ||||||
|                 Sort.Order order = new Sort.Order(Sort.Direction.valueOf(sortArr[1].toUpperCase()), sortArr[0]); |  | ||||||
|                 orders.add(order); |  | ||||||
|             } |  | ||||||
|         } else { |         } else { | ||||||
|             // e.g "sort=published,desc" |             this.size = size; | ||||||
|             Sort.Order order = new Sort.Order(Sort.Direction.valueOf(sort[1].toUpperCase()), sort[0]); |  | ||||||
|             orders.add(order); |  | ||||||
|         } |         } | ||||||
|         return Sort.by(orders); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|   | |||||||
| @@ -0,0 +1,80 @@ | |||||||
|  | /* | ||||||
|  |  * 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.charles7c.cnadmin.common.model.query; | ||||||
|  |  | ||||||
|  | import java.io.Serializable; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  |  | ||||||
|  | import org.springdoc.api.annotations.ParameterObject; | ||||||
|  | import org.springframework.data.domain.Sort; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.util.ArrayUtil; | ||||||
|  | import cn.hutool.core.util.StrUtil; | ||||||
|  |  | ||||||
|  | import top.charles7c.cnadmin.common.consts.CharConstants; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 排序查询条件 | ||||||
|  |  * | ||||||
|  |  * @author Charles7c | ||||||
|  |  * @since 2023/2/12 21:30 | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @ParameterObject | ||||||
|  | @Schema(description = "排序查询条件") | ||||||
|  | public class SortQuery implements Serializable { | ||||||
|  |  | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 排序条件 | ||||||
|  |      */ | ||||||
|  |     @Schema(description = "排序条件", example = "sort=published,desc&sort=title,asc") | ||||||
|  |     private String[] sort; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 解析排序条件为 Spring 分页排序实体 | ||||||
|  |      * | ||||||
|  |      * @return Spring 分页排序实体 | ||||||
|  |      */ | ||||||
|  |     public Sort getSort() { | ||||||
|  |         if (ArrayUtil.isEmpty(sort)) { | ||||||
|  |             return Sort.unsorted(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         List<Sort.Order> orders = new ArrayList<>(sort.length); | ||||||
|  |         if (StrUtil.contains(sort[0], CharConstants.COMMA)) { | ||||||
|  |             // e.g "sort=published,desc&sort=title,asc" | ||||||
|  |             for (String s : sort) { | ||||||
|  |                 List<String> sortList = StrUtil.split(s, CharConstants.COMMA); | ||||||
|  |                 Sort.Order order = | ||||||
|  |                     new Sort.Order(Sort.Direction.valueOf(sortList.get(1).toUpperCase()), sortList.get(0)); | ||||||
|  |                 orders.add(order); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             // e.g "sort=published,desc" | ||||||
|  |             Sort.Order order = new Sort.Order(Sort.Direction.valueOf(sort[1].toUpperCase()), sort[0]); | ||||||
|  |             orders.add(order); | ||||||
|  |         } | ||||||
|  |         return Sort.by(orders); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -102,7 +102,7 @@ public class PageDataVO<V> { | |||||||
|      * @param page |      * @param page | ||||||
|      *            页码 |      *            页码 | ||||||
|      * @param size |      * @param size | ||||||
|      *            每页记录数 |      *            每页条数 | ||||||
|      * @param list |      * @param list | ||||||
|      *            列表数据 |      *            列表数据 | ||||||
|      * @param <V> |      * @param <V> | ||||||
|   | |||||||
| @@ -0,0 +1,35 @@ | |||||||
|  | /* | ||||||
|  |  * 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.charles7c.cnadmin.common.service; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 公共用户业务接口 | ||||||
|  |  * | ||||||
|  |  * @author Charles7c | ||||||
|  |  * @since 2023/2/13 20:37 | ||||||
|  |  */ | ||||||
|  | public interface CommonUserService { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 根据 ID 查询昵称 | ||||||
|  |      * | ||||||
|  |      * @param userId | ||||||
|  |      *            用户 ID | ||||||
|  |      * @return 昵称 | ||||||
|  |      */ | ||||||
|  |     String getNicknameById(Long userId); | ||||||
|  | } | ||||||
| @@ -69,10 +69,10 @@ public class QueryHelper { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 获取指定类的所有属性(包括私有的和父类的) |      * 获取指定类型的所有属性(包括私有的和父类的) | ||||||
|      * |      * | ||||||
|      * @param clazz |      * @param clazz | ||||||
|      *            指定类 |      *            指定类型 | ||||||
|      * @param fieldList |      * @param fieldList | ||||||
|      *            属性列表 |      *            属性列表 | ||||||
|      * @param <Q> |      * @param <Q> | ||||||
|   | |||||||
| @@ -18,8 +18,6 @@ package top.charles7c.cnadmin.system.service; | |||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| import javax.servlet.http.HttpServletResponse; |  | ||||||
|  |  | ||||||
| import cn.hutool.core.lang.tree.Tree; | import cn.hutool.core.lang.tree.Tree; | ||||||
|  |  | ||||||
| import top.charles7c.cnadmin.common.base.BaseService; | import top.charles7c.cnadmin.common.base.BaseService; | ||||||
| @@ -53,14 +51,4 @@ public interface DeptService extends BaseService<DeptVO, DeptDetailVO, DeptQuery | |||||||
|      * @return 树列表 |      * @return 树列表 | ||||||
|      */ |      */ | ||||||
|     List<Tree<Long>> buildTree(List<DeptVO> list); |     List<Tree<Long>> buildTree(List<DeptVO> list); | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 导出 |  | ||||||
|      * |  | ||||||
|      * @param query |  | ||||||
|      *            查询条件 |  | ||||||
|      * @param response |  | ||||||
|      *            响应对象 |  | ||||||
|      */ |  | ||||||
|     void export(DeptQuery query, HttpServletResponse response); |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -84,7 +84,7 @@ public interface UserService { | |||||||
|      * 根据 ID 查询 |      * 根据 ID 查询 | ||||||
|      * |      * | ||||||
|      * @param userId |      * @param userId | ||||||
|      *            用户ID |      *            用户 ID | ||||||
|      * @return 用户信息 |      * @return 用户信息 | ||||||
|      */ |      */ | ||||||
|     UserDO getById(Long userId); |     UserDO getById(Long userId); | ||||||
|   | |||||||
| @@ -17,32 +17,24 @@ | |||||||
| package top.charles7c.cnadmin.system.service.impl; | package top.charles7c.cnadmin.system.service.impl; | ||||||
|  |  | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.Collections; |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Objects; | import java.util.Objects; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
| import javax.servlet.http.HttpServletResponse; |  | ||||||
|  |  | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
|  |  | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| import org.springframework.transaction.annotation.Transactional; | import org.springframework.transaction.annotation.Transactional; | ||||||
|  |  | ||||||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |  | ||||||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
|  |  | ||||||
| import cn.hutool.core.bean.BeanUtil; |  | ||||||
| import cn.hutool.core.collection.CollUtil; | import cn.hutool.core.collection.CollUtil; | ||||||
| import cn.hutool.core.lang.tree.Tree; | import cn.hutool.core.lang.tree.Tree; | ||||||
|  |  | ||||||
| import top.charles7c.cnadmin.common.base.BaseServiceImpl; | import top.charles7c.cnadmin.common.base.BaseServiceImpl; | ||||||
| import top.charles7c.cnadmin.common.base.BaseVO; |  | ||||||
| import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum; | import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum; | ||||||
| import top.charles7c.cnadmin.common.util.ExcelUtils; |  | ||||||
| import top.charles7c.cnadmin.common.util.ExceptionUtils; | import top.charles7c.cnadmin.common.util.ExceptionUtils; | ||||||
| import top.charles7c.cnadmin.common.util.TreeUtils; | import top.charles7c.cnadmin.common.util.TreeUtils; | ||||||
| import top.charles7c.cnadmin.common.util.helper.QueryHelper; |  | ||||||
| import top.charles7c.cnadmin.common.util.validate.CheckUtils; | import top.charles7c.cnadmin.common.util.validate.CheckUtils; | ||||||
| import top.charles7c.cnadmin.system.mapper.DeptMapper; | import top.charles7c.cnadmin.system.mapper.DeptMapper; | ||||||
| import top.charles7c.cnadmin.system.model.entity.DeptDO; | import top.charles7c.cnadmin.system.model.entity.DeptDO; | ||||||
| @@ -51,7 +43,6 @@ import top.charles7c.cnadmin.system.model.request.DeptRequest; | |||||||
| import top.charles7c.cnadmin.system.model.vo.DeptDetailVO; | import top.charles7c.cnadmin.system.model.vo.DeptDetailVO; | ||||||
| import top.charles7c.cnadmin.system.model.vo.DeptVO; | import top.charles7c.cnadmin.system.model.vo.DeptVO; | ||||||
| import top.charles7c.cnadmin.system.service.DeptService; | import top.charles7c.cnadmin.system.service.DeptService; | ||||||
| import top.charles7c.cnadmin.system.service.UserService; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 部门业务实现类 |  * 部门业务实现类 | ||||||
| @@ -64,38 +55,6 @@ import top.charles7c.cnadmin.system.service.UserService; | |||||||
| public class DeptServiceImpl extends BaseServiceImpl<DeptMapper, DeptDO, DeptVO, DeptDetailVO, DeptQuery, DeptRequest> | public class DeptServiceImpl extends BaseServiceImpl<DeptMapper, DeptDO, DeptVO, DeptDetailVO, DeptQuery, DeptRequest> | ||||||
|     implements DeptService { |     implements DeptService { | ||||||
|  |  | ||||||
|     private final UserService userService; |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public List<DeptVO> list(DeptQuery query) { |  | ||||||
|         List<DeptDO> deptList = this.listDept(query); |  | ||||||
|         List<DeptVO> list = BeanUtil.copyToList(deptList, DeptVO.class); |  | ||||||
|         list.forEach(this::fill); |  | ||||||
|         return list; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 查询列表 |  | ||||||
|      * |  | ||||||
|      * @param query |  | ||||||
|      *            查询条件 |  | ||||||
|      * @return 列表信息 |  | ||||||
|      */ |  | ||||||
|     private List<DeptDO> listDept(DeptQuery query) { |  | ||||||
|         QueryWrapper<DeptDO> queryWrapper = QueryHelper.build(query); |  | ||||||
|         queryWrapper.lambda().orderByAsc(DeptDO::getParentId).orderByAsc(DeptDO::getDeptSort) |  | ||||||
|             .orderByDesc(DeptDO::getCreateTime); |  | ||||||
|         List<DeptDO> deptList = baseMapper.selectList(queryWrapper); |  | ||||||
|         return CollUtil.isNotEmpty(deptList) ? deptList : Collections.emptyList(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public DeptDetailVO get(Long id) { |  | ||||||
|         DeptDetailVO deptDetailVO = super.get(id); |  | ||||||
|         this.fillDetail(deptDetailVO); |  | ||||||
|         return deptDetailVO; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     @Transactional(rollbackFor = Exception.class) |     @Transactional(rollbackFor = Exception.class) | ||||||
|     public Long create(DeptRequest request) { |     public Long create(DeptRequest request) { | ||||||
| @@ -103,11 +62,9 @@ public class DeptServiceImpl extends BaseServiceImpl<DeptMapper, DeptDO, DeptVO, | |||||||
|         boolean isExist = this.checkNameExist(deptName, request.getParentId(), request.getDeptId()); |         boolean isExist = this.checkNameExist(deptName, request.getParentId(), request.getDeptId()); | ||||||
|         CheckUtils.throwIf(() -> isExist, String.format("新增失败,'%s'已存在", deptName)); |         CheckUtils.throwIf(() -> isExist, String.format("新增失败,'%s'已存在", deptName)); | ||||||
|  |  | ||||||
|         // 保存部门信息 |         // 保存信息 | ||||||
|         DeptDO deptDO = BeanUtil.copyProperties(request, DeptDO.class); |         request.setStatus(DisEnableStatusEnum.ENABLE); | ||||||
|         deptDO.setStatus(DisEnableStatusEnum.ENABLE); |         return super.create(request); | ||||||
|         baseMapper.insert(deptDO); |  | ||||||
|         return deptDO.getDeptId(); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
| @@ -189,14 +146,6 @@ public class DeptServiceImpl extends BaseServiceImpl<DeptMapper, DeptDO, DeptVO, | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void export(DeptQuery query, HttpServletResponse response) { |  | ||||||
|         List<DeptDO> deptList = this.listDept(query); |  | ||||||
|         List<DeptDetailVO> list = BeanUtil.copyToList(deptList, DeptDetailVO.class); |  | ||||||
|         list.forEach(this::fillDetail); |  | ||||||
|         ExcelUtils.export(list, "部门数据", DeptDetailVO.class, response); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 检查名称是否存在 |      * 检查名称是否存在 | ||||||
|      * |      * | ||||||
| @@ -213,34 +162,12 @@ public class DeptServiceImpl extends BaseServiceImpl<DeptMapper, DeptDO, DeptVO, | |||||||
|             .eq(DeptDO::getParentId, parentId).ne(deptId != null, DeptDO::getDeptId, deptId)); |             .eq(DeptDO::getParentId, parentId).ne(deptId != null, DeptDO::getDeptId, deptId)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     @Override | ||||||
|      * 填充数据 |     public void fillDetail(Object detailObj) { | ||||||
|      * |         super.fillDetail(detailObj); | ||||||
|      * @param baseVO |         if (detailObj instanceof DeptDetailVO) { | ||||||
|      *            待填充列表信息 |             DeptDetailVO detailVO = (DeptDetailVO)detailObj; | ||||||
|      */ |             detailVO.setParentName(ExceptionUtils.exToNull(() -> this.get(detailVO.getParentId()).getDeptName())); | ||||||
|     private void fill(BaseVO baseVO) { |  | ||||||
|         Long createUser = baseVO.getCreateUser(); |  | ||||||
|         if (createUser == null) { |  | ||||||
|             return; |  | ||||||
|         } |         } | ||||||
|         baseVO.setCreateUserString(ExceptionUtils.exToNull(() -> userService.getById(createUser)).getNickname()); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 填充详情数据 |  | ||||||
|      * |  | ||||||
|      * @param detailVO |  | ||||||
|      *            待填充详情信息 |  | ||||||
|      */ |  | ||||||
|     private void fillDetail(DeptDetailVO detailVO) { |  | ||||||
|         this.fill(detailVO); |  | ||||||
|  |  | ||||||
|         Long updateUser = detailVO.getUpdateUser(); |  | ||||||
|         if (updateUser == null) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         detailVO.setUpdateUserString(ExceptionUtils.exToNull(() -> userService.getById(updateUser)).getNickname()); |  | ||||||
|         detailVO.setParentName(ExceptionUtils.exToNull(() -> this.get(detailVO.getParentId()).getDeptName())); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -16,8 +16,6 @@ | |||||||
|  |  | ||||||
| package top.charles7c.cnadmin.system.service.impl; | package top.charles7c.cnadmin.system.service.impl; | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
|  |  | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| @@ -25,15 +23,8 @@ import org.springframework.transaction.annotation.Transactional; | |||||||
|  |  | ||||||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
|  |  | ||||||
| import cn.hutool.core.bean.BeanUtil; |  | ||||||
|  |  | ||||||
| import top.charles7c.cnadmin.common.base.BaseDetailVO; |  | ||||||
| import top.charles7c.cnadmin.common.base.BaseServiceImpl; | import top.charles7c.cnadmin.common.base.BaseServiceImpl; | ||||||
| import top.charles7c.cnadmin.common.base.BaseVO; |  | ||||||
| import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum; | import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum; | ||||||
| import top.charles7c.cnadmin.common.model.query.PageQuery; |  | ||||||
| import top.charles7c.cnadmin.common.model.vo.PageDataVO; |  | ||||||
| import top.charles7c.cnadmin.common.util.ExceptionUtils; |  | ||||||
| import top.charles7c.cnadmin.common.util.validate.CheckUtils; | import top.charles7c.cnadmin.common.util.validate.CheckUtils; | ||||||
| import top.charles7c.cnadmin.system.mapper.RoleMapper; | import top.charles7c.cnadmin.system.mapper.RoleMapper; | ||||||
| import top.charles7c.cnadmin.system.model.entity.RoleDO; | import top.charles7c.cnadmin.system.model.entity.RoleDO; | ||||||
| @@ -42,7 +33,6 @@ import top.charles7c.cnadmin.system.model.request.RoleRequest; | |||||||
| import top.charles7c.cnadmin.system.model.vo.RoleDetailVO; | import top.charles7c.cnadmin.system.model.vo.RoleDetailVO; | ||||||
| import top.charles7c.cnadmin.system.model.vo.RoleVO; | import top.charles7c.cnadmin.system.model.vo.RoleVO; | ||||||
| import top.charles7c.cnadmin.system.service.RoleService; | import top.charles7c.cnadmin.system.service.RoleService; | ||||||
| import top.charles7c.cnadmin.system.service.UserService; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 角色业务实现类 |  * 角色业务实现类 | ||||||
| @@ -55,22 +45,6 @@ import top.charles7c.cnadmin.system.service.UserService; | |||||||
| public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleVO, RoleDetailVO, RoleQuery, RoleRequest> | public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleVO, RoleDetailVO, RoleQuery, RoleRequest> | ||||||
|     implements RoleService { |     implements RoleService { | ||||||
|  |  | ||||||
|     private final UserService userService; |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public PageDataVO<RoleVO> page(RoleQuery query, PageQuery pageQuery) { |  | ||||||
|         PageDataVO<RoleVO> pageDataVO = super.page(query, pageQuery); |  | ||||||
|         pageDataVO.getList().forEach(this::fill); |  | ||||||
|         return pageDataVO; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public RoleDetailVO get(Long id) { |  | ||||||
|         RoleDetailVO roleDetailVO = super.get(id); |  | ||||||
|         this.fillDetail(roleDetailVO); |  | ||||||
|         return roleDetailVO; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     @Transactional(rollbackFor = Exception.class) |     @Transactional(rollbackFor = Exception.class) | ||||||
|     public Long create(RoleRequest request) { |     public Long create(RoleRequest request) { | ||||||
| @@ -79,10 +53,8 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleVO, | |||||||
|         CheckUtils.throwIf(() -> isExist, String.format("新增失败,'%s'已存在", roleName)); |         CheckUtils.throwIf(() -> isExist, String.format("新增失败,'%s'已存在", roleName)); | ||||||
|  |  | ||||||
|         // 保存信息 |         // 保存信息 | ||||||
|         RoleDO roleDO = BeanUtil.copyProperties(request, RoleDO.class); |         request.setStatus(DisEnableStatusEnum.ENABLE); | ||||||
|         roleDO.setStatus(DisEnableStatusEnum.ENABLE); |         return super.create(request); | ||||||
|         baseMapper.insert(roleDO); |  | ||||||
|         return roleDO.getRoleId(); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
| @@ -95,12 +67,6 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleVO, | |||||||
|         super.update(request); |         super.update(request); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     @Transactional(rollbackFor = Exception.class) |  | ||||||
|     public void delete(List<Long> ids) { |  | ||||||
|         super.delete(ids); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 检查名称是否存在 |      * 检查名称是否存在 | ||||||
|      * |      * | ||||||
| @@ -114,34 +80,4 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleVO, | |||||||
|         return baseMapper.exists(Wrappers.<RoleDO>lambdaQuery().eq(RoleDO::getRoleName, roleName).ne(roleId != null, |         return baseMapper.exists(Wrappers.<RoleDO>lambdaQuery().eq(RoleDO::getRoleName, roleName).ne(roleId != null, | ||||||
|             RoleDO::getRoleId, roleId)); |             RoleDO::getRoleId, roleId)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 填充数据 |  | ||||||
|      * |  | ||||||
|      * @param baseVO |  | ||||||
|      *            待填充列表信息 |  | ||||||
|      */ |  | ||||||
|     private void fill(BaseVO baseVO) { |  | ||||||
|         Long createUser = baseVO.getCreateUser(); |  | ||||||
|         if (createUser == null) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         baseVO.setCreateUserString(ExceptionUtils.exToNull(() -> userService.getById(createUser)).getNickname()); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 填充详情数据 |  | ||||||
|      * |  | ||||||
|      * @param detailVO |  | ||||||
|      *            待填充详情信息 |  | ||||||
|      */ |  | ||||||
|     private void fillDetail(BaseDetailVO detailVO) { |  | ||||||
|         this.fill(detailVO); |  | ||||||
|  |  | ||||||
|         Long updateUser = detailVO.getUpdateUser(); |  | ||||||
|         if (updateUser == null) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         detailVO.setUpdateUserString(ExceptionUtils.exToNull(() -> userService.getById(updateUser)).getNickname()); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -36,6 +36,7 @@ import cn.hutool.core.util.StrUtil; | |||||||
| import top.charles7c.cnadmin.common.config.properties.LocalStorageProperties; | import top.charles7c.cnadmin.common.config.properties.LocalStorageProperties; | ||||||
| import top.charles7c.cnadmin.common.consts.FileConstants; | import top.charles7c.cnadmin.common.consts.FileConstants; | ||||||
| import top.charles7c.cnadmin.common.model.dto.LoginUser; | import top.charles7c.cnadmin.common.model.dto.LoginUser; | ||||||
|  | import top.charles7c.cnadmin.common.service.CommonUserService; | ||||||
| import top.charles7c.cnadmin.common.util.FileUtils; | import top.charles7c.cnadmin.common.util.FileUtils; | ||||||
| import top.charles7c.cnadmin.common.util.SecureUtils; | import top.charles7c.cnadmin.common.util.SecureUtils; | ||||||
| import top.charles7c.cnadmin.common.util.helper.LoginHelper; | import top.charles7c.cnadmin.common.util.helper.LoginHelper; | ||||||
| @@ -52,7 +53,7 @@ import top.charles7c.cnadmin.system.service.UserService; | |||||||
|  */ |  */ | ||||||
| @Service | @Service | ||||||
| @RequiredArgsConstructor | @RequiredArgsConstructor | ||||||
| public class UserServiceImpl implements UserService { | public class UserServiceImpl implements UserService, CommonUserService { | ||||||
|  |  | ||||||
|     private final UserMapper userMapper; |     private final UserMapper userMapper; | ||||||
|     private final LocalStorageProperties localStorageProperties; |     private final LocalStorageProperties localStorageProperties; | ||||||
| @@ -155,4 +156,9 @@ public class UserServiceImpl implements UserService { | |||||||
|         CheckUtils.throwIfNull(userDO, String.format("ID为 [%s] 的用户已不存在", userId)); |         CheckUtils.throwIfNull(userDO, String.format("ID为 [%s] 的用户已不存在", userId)); | ||||||
|         return userDO; |         return userDO; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String getNicknameById(Long userId) { | ||||||
|  |         return this.getById(userId).getNickname(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,8 +7,8 @@ export interface DeptRecord { | |||||||
|   deptId?: number; |   deptId?: number; | ||||||
|   deptName: string; |   deptName: string; | ||||||
|   parentId?: number; |   parentId?: number; | ||||||
|   deptSort: number; |  | ||||||
|   description?: string; |   description?: string; | ||||||
|  |   deptSort: number; | ||||||
|   status?: number; |   status?: number; | ||||||
|   createUserString?: string; |   createUserString?: string; | ||||||
|   createTime?: string; |   createTime?: string; | ||||||
| @@ -24,7 +24,7 @@ export interface DeptParam { | |||||||
| } | } | ||||||
|  |  | ||||||
| export function listDept(params: DeptParam) { | export function listDept(params: DeptParam) { | ||||||
|   return axios.get<DeptRecord[]>(`${BASE_URL}/all`, { |   return axios.get<DeptRecord[]>(`${BASE_URL}/list`, { | ||||||
|     params, |     params, | ||||||
|     paramsSerializer: (obj) => { |     paramsSerializer: (obj) => { | ||||||
|       return qs.stringify(obj); |       return qs.stringify(obj); | ||||||
| @@ -47,13 +47,3 @@ export function updateDept(req: DeptRecord) { | |||||||
| export function deleteDept(ids: number | Array<number>) { | export function deleteDept(ids: number | Array<number>) { | ||||||
|   return axios.delete(`${BASE_URL}/${ids}`); |   return axios.delete(`${BASE_URL}/${ids}`); | ||||||
| } | } | ||||||
|  |  | ||||||
| export function exportDept(params: DeptParam) { |  | ||||||
|   return axios.get(`${BASE_URL}/export`, { |  | ||||||
|     params, |  | ||||||
|     paramsSerializer: (obj) => { |  | ||||||
|       return qs.stringify(obj); |  | ||||||
|     }, |  | ||||||
|     responseType: 'blob', |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
|   | |||||||
							
								
								
									
										66
									
								
								continew-admin-ui/src/components/crud/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								continew-admin-ui/src/components/crud/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  | import axios from 'axios'; | ||||||
|  | import qs from 'query-string'; | ||||||
|  | import { Notification } from '@arco-design/web-vue'; | ||||||
|  | import dayjs from 'dayjs'; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 下载 | ||||||
|  |  * | ||||||
|  |  * @param url URL | ||||||
|  |  * @param params 查询条件 | ||||||
|  |  * @param fileName 文件名 | ||||||
|  |  */ | ||||||
|  | export default function download( | ||||||
|  |   url: string, | ||||||
|  |   params: any, | ||||||
|  |   fileName: string | undefined | ||||||
|  | ) { | ||||||
|  |   return axios | ||||||
|  |     .get(url, { | ||||||
|  |       params, | ||||||
|  |       paramsSerializer: (obj) => { | ||||||
|  |         return qs.stringify(obj); | ||||||
|  |       }, | ||||||
|  |       responseType: 'blob', | ||||||
|  |     }) | ||||||
|  |     .then(async (res) => { | ||||||
|  |       // 获取文件名 | ||||||
|  |       if (!fileName) { | ||||||
|  |         const contentDisposition = res.headers['content-disposition']; | ||||||
|  |         const pattern = new RegExp('filename=([^;]+\\.[^\\.;]+);*'); | ||||||
|  |         const result = pattern.exec(contentDisposition) || ''; | ||||||
|  |         // 对名字进行解码 | ||||||
|  |         fileName = window.decodeURI(result[1]); | ||||||
|  |       } else { | ||||||
|  |         fileName = `${fileName}_${dayjs().format('YYYYMMDDHHmmss')}`; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       // 创建下载的链接 | ||||||
|  |       const blob = new Blob([res.data], { | ||||||
|  |         type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8', | ||||||
|  |       }); | ||||||
|  |       const downloadElement = document.createElement('a'); | ||||||
|  |       const href = window.URL.createObjectURL(blob); | ||||||
|  |       downloadElement.style.display = 'none'; | ||||||
|  |       downloadElement.href = href; | ||||||
|  |       // 下载后文件名 | ||||||
|  |       downloadElement.download = fileName; | ||||||
|  |       document.body.appendChild(downloadElement); | ||||||
|  |       // 点击下载 | ||||||
|  |       downloadElement.click(); | ||||||
|  |       // 下载完成,移除元素 | ||||||
|  |       document.body.removeChild(downloadElement); | ||||||
|  |       // 释放掉 blob 对象 | ||||||
|  |       window.URL.revokeObjectURL(href); | ||||||
|  |     }) | ||||||
|  |     .catch((error) => { | ||||||
|  |       console.error(error); | ||||||
|  |       Notification.warning({ | ||||||
|  |         title: '警告', | ||||||
|  |         content: | ||||||
|  |           "如果您正在访问演示环境,点击导出会报错。这是由于演示环境开启了 Mock.js,而 Mock.js 会将 responseType 设置为 '',这不仅会导致关键判断出错,也会导致导出的文件无法打开。", | ||||||
|  |         duration: 10000, | ||||||
|  |         closable: true, | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  | } | ||||||
| @@ -13,6 +13,7 @@ import Chart from './chart/index.vue'; | |||||||
| import Breadcrumb from './breadcrumb/index.vue'; | import Breadcrumb from './breadcrumb/index.vue'; | ||||||
| import DateRangePicker from './date-range-picker/index.vue'; | import DateRangePicker from './date-range-picker/index.vue'; | ||||||
| import RightToolbar from './right-toolbar/index.vue'; | import RightToolbar from './right-toolbar/index.vue'; | ||||||
|  | import download from './crud'; | ||||||
|  |  | ||||||
| // Manually introduce ECharts modules to reduce packing size | // Manually introduce ECharts modules to reduce packing size | ||||||
|  |  | ||||||
| @@ -31,6 +32,10 @@ use([ | |||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   install(Vue: App) { |   install(Vue: App) { | ||||||
|  |     // 全局方法挂载 | ||||||
|  |     Vue.config.globalProperties.download = download; | ||||||
|  |  | ||||||
|  |     // 全局组件挂载 | ||||||
|     Vue.component('Chart', Chart); |     Vue.component('Chart', Chart); | ||||||
|     Vue.component('Breadcrumb', Breadcrumb); |     Vue.component('Breadcrumb', Breadcrumb); | ||||||
|     Vue.component('DateRangePicker', DateRangePicker); |     Vue.component('DateRangePicker', DateRangePicker); | ||||||
|   | |||||||
| @@ -15,8 +15,9 @@ export function encryptByMd5(txt: string) { | |||||||
|   return md5(txt).toString(); |   return md5(txt).toString(); | ||||||
| } | } | ||||||
|  |  | ||||||
| const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAM51dgYtMyF+tTQt80sfFOpSV27a7t9u' + | const publicKey = | ||||||
|   'aUVeFrdGiVxscuizE7H8SMntYqfn9lp8a5GH5P1/GGehVjUD2gF/4kcCAwEAAQ==' |   'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAM51dgYtMyF+tTQt80sfFOpSV27a7t9u' + | ||||||
|  |   'aUVeFrdGiVxscuizE7H8SMntYqfn9lp8a5GH5P1/GGehVjUD2gF/4kcCAwEAAQ=='; | ||||||
|  |  | ||||||
| export function encryptByRsa(txt: string) { | export function encryptByRsa(txt: string) { | ||||||
|   const encryptor = new JSEncrypt(); |   const encryptor = new JSEncrypt(); | ||||||
|   | |||||||
| @@ -1,16 +1,17 @@ | |||||||
| import axios from "axios"; | import axios from 'axios'; | ||||||
| import type { AxiosRequestConfig, AxiosResponse } from "axios"; | import type { AxiosRequestConfig, AxiosResponse } from 'axios'; | ||||||
| import { Message } from "@arco-design/web-vue"; | import { Message } from '@arco-design/web-vue'; | ||||||
| import { getToken } from "@/utils/auth"; | import { getToken } from '@/utils/auth'; | ||||||
|  |  | ||||||
| // default config | // default config | ||||||
| if (import.meta.env.VITE_API_BASE_URL) { | if (import.meta.env.VITE_API_BASE_URL) { | ||||||
|   axios.defaults.baseURL = import.meta.env.VITE_API_BASE_URL; |   axios.defaults.baseURL = import.meta.env.VITE_API_BASE_URL; | ||||||
|   axios.defaults.timeout = 60000 // 1 分钟 |   axios.defaults.timeout = 60000; // 1 分钟 | ||||||
| } | } | ||||||
|  |  | ||||||
| // request interceptors | // request interceptors | ||||||
| axios.interceptors.request.use((config: AxiosRequestConfig) => { | axios.interceptors.request.use( | ||||||
|  |   (config: AxiosRequestConfig) => { | ||||||
|     const token = getToken(); |     const token = getToken(); | ||||||
|     if (token) { |     if (token) { | ||||||
|       if (!config.headers) { |       if (!config.headers) { | ||||||
| @@ -35,9 +36,13 @@ export interface HttpResponse<T = unknown> { | |||||||
| } | } | ||||||
|  |  | ||||||
| // response interceptors | // response interceptors | ||||||
| axios.interceptors.response.use((response: AxiosResponse<HttpResponse>) => { | axios.interceptors.response.use( | ||||||
|  |   (response: AxiosResponse<HttpResponse>) => { | ||||||
|     // 二进制数据则直接返回 |     // 二进制数据则直接返回 | ||||||
|     if(response.request.responseType ===  'blob' || response.request.responseType ===  'arraybuffer'){ |     if ( | ||||||
|  |       response.request.responseType === 'blob' || | ||||||
|  |       response.request.responseType === 'arraybuffer' | ||||||
|  |     ) { | ||||||
|       return response; |       return response; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -49,7 +54,7 @@ axios.interceptors.response.use((response: AxiosResponse<HttpResponse>) => { | |||||||
|     // 操作失败,弹出错误提示 |     // 操作失败,弹出错误提示 | ||||||
|     Message.error({ |     Message.error({ | ||||||
|       content: res.msg, |       content: res.msg, | ||||||
|       duration: 3000 |       duration: 3000, | ||||||
|     }); |     }); | ||||||
|     // |     // | ||||||
|     // if (res.code === 401) { |     // if (res.code === 401) { | ||||||
| @@ -61,9 +66,9 @@ axios.interceptors.response.use((response: AxiosResponse<HttpResponse>) => { | |||||||
|     console.error(`err: ${error}`); |     console.error(`err: ${error}`); | ||||||
|     const res = error.response.data; |     const res = error.response.data; | ||||||
|     Message.error({ |     Message.error({ | ||||||
|       content: res.msg || "网络错误", |       content: res.msg || '网络错误', | ||||||
|       duration: 3000 |       duration: 3000, | ||||||
|     }); |     }); | ||||||
|     return Promise.reject(error); |     return Promise.reject(error); | ||||||
|   } |   } | ||||||
| ); | ); | ||||||
|   | |||||||
| @@ -302,7 +302,6 @@ | |||||||
|     createDept, |     createDept, | ||||||
|     updateDept, |     updateDept, | ||||||
|     deleteDept, |     deleteDept, | ||||||
|     exportDept, |  | ||||||
|   } from '@/api/system/dept'; |   } from '@/api/system/dept'; | ||||||
|   import listDeptTree from '@/api/common'; |   import listDeptTree from '@/api/common'; | ||||||
|  |  | ||||||
| @@ -341,6 +340,7 @@ | |||||||
|     queryParams: { |     queryParams: { | ||||||
|       deptName: undefined, |       deptName: undefined, | ||||||
|       status: undefined, |       status: undefined, | ||||||
|  |       sort: ['parentId,asc', 'deptSort,asc', 'createTime,desc'], | ||||||
|     }, |     }, | ||||||
|     // 表单数据 |     // 表单数据 | ||||||
|     form: {} as DeptRecord, |     form: {} as DeptRecord, | ||||||
| @@ -410,8 +410,9 @@ | |||||||
|       deptId: undefined, |       deptId: undefined, | ||||||
|       deptName: '', |       deptName: '', | ||||||
|       parentId: undefined, |       parentId: undefined, | ||||||
|       deptSort: 999, |  | ||||||
|       description: '', |       description: '', | ||||||
|  |       deptSort: 999, | ||||||
|  |       status: 1, | ||||||
|     }; |     }; | ||||||
|     proxy.$refs.formRef?.resetFields(); |     proxy.$refs.formRef?.resetFields(); | ||||||
|   }; |   }; | ||||||
| @@ -521,40 +522,8 @@ | |||||||
|   const handleExport = () => { |   const handleExport = () => { | ||||||
|     if (exportLoading.value) return; |     if (exportLoading.value) return; | ||||||
|     exportLoading.value = true; |     exportLoading.value = true; | ||||||
|     exportDept({ ...queryParams.value }) |     proxy | ||||||
|       .then(async (res) => { |       .download('/system/dept/export', { ...queryParams.value }, '部门数据') | ||||||
|         const blob = new Blob([res.data], { |  | ||||||
|           type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8', |  | ||||||
|         }); |  | ||||||
|         const contentDisposition = res.headers['content-disposition']; |  | ||||||
|         const pattern = new RegExp('filename=([^;]+\\.[^\\.;]+);*'); |  | ||||||
|         const result = pattern.exec(contentDisposition) || ''; |  | ||||||
|         // 对名字进行解码 |  | ||||||
|         const fileName = window.decodeURI(result[1]); |  | ||||||
|         // 创建下载的链接 |  | ||||||
|         const downloadElement = document.createElement('a'); |  | ||||||
|         const href = window.URL.createObjectURL(blob); |  | ||||||
|         downloadElement.style.display = 'none'; |  | ||||||
|         downloadElement.href = href; |  | ||||||
|         // 下载后文件名 |  | ||||||
|         downloadElement.download = fileName; |  | ||||||
|         document.body.appendChild(downloadElement); |  | ||||||
|         // 点击下载 |  | ||||||
|         downloadElement.click(); |  | ||||||
|         // 下载完成,移除元素 |  | ||||||
|         document.body.removeChild(downloadElement); |  | ||||||
|         // 释放掉 blob 对象 |  | ||||||
|         window.URL.revokeObjectURL(href); |  | ||||||
|       }) |  | ||||||
|       .catch(() => { |  | ||||||
|         proxy.$notification.warning({ |  | ||||||
|           title: '警告', |  | ||||||
|           content: |  | ||||||
|             "如果您正在访问演示环境,点击导出会报错。这是由于演示环境开启了 Mock.js,而 Mock.js 会将 responseType 设置为 '',这不仅会导致关键判断出错,也会导致导出的文件无法打开。", |  | ||||||
|           duration: 10000, |  | ||||||
|           closable: true, |  | ||||||
|         }); |  | ||||||
|       }) |  | ||||||
|       .finally(() => { |       .finally(() => { | ||||||
|         exportLoading.value = false; |         exportLoading.value = false; | ||||||
|       }); |       }); | ||||||
|   | |||||||
| @@ -63,6 +63,14 @@ | |||||||
|                 > |                 > | ||||||
|                   <template #icon><icon-delete /></template>删除 |                   <template #icon><icon-delete /></template>删除 | ||||||
|                 </a-button> |                 </a-button> | ||||||
|  |                 <a-button | ||||||
|  |                   :loading="exportLoading" | ||||||
|  |                   type="primary" | ||||||
|  |                   status="warning" | ||||||
|  |                   @click="handleExport" | ||||||
|  |                 > | ||||||
|  |                   <template #icon><icon-download /></template>导出 | ||||||
|  |                 </a-button> | ||||||
|               </a-space> |               </a-space> | ||||||
|             </a-col> |             </a-col> | ||||||
|             <a-col :span="12"> |             <a-col :span="12"> | ||||||
| @@ -383,6 +391,7 @@ | |||||||
|   const showQuery = ref(true); |   const showQuery = ref(true); | ||||||
|   const loading = ref(false); |   const loading = ref(false); | ||||||
|   const detailLoading = ref(false); |   const detailLoading = ref(false); | ||||||
|  |   const exportLoading = ref(false); | ||||||
|   const visible = ref(false); |   const visible = ref(false); | ||||||
|   const detailVisible = ref(false); |   const detailVisible = ref(false); | ||||||
|   const statusOptions = ref<SelectOptionData[]>([ |   const statusOptions = ref<SelectOptionData[]>([ | ||||||
| @@ -478,6 +487,7 @@ | |||||||
|       dataScopeDeptIds: undefined, |       dataScopeDeptIds: undefined, | ||||||
|       description: '', |       description: '', | ||||||
|       roleSort: 999, |       roleSort: 999, | ||||||
|  |       status: 1, | ||||||
|     }; |     }; | ||||||
|     proxy.$refs.formRef?.resetFields(); |     proxy.$refs.formRef?.resetFields(); | ||||||
|   }; |   }; | ||||||
| @@ -580,6 +590,19 @@ | |||||||
|     multiple.value = !rowKeys.length; |     multiple.value = !rowKeys.length; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * 导出 | ||||||
|  |    */ | ||||||
|  |   const handleExport = () => { | ||||||
|  |     if (exportLoading.value) return; | ||||||
|  |     exportLoading.value = true; | ||||||
|  |     proxy | ||||||
|  |       .download('/system/role/export', { ...queryParams.value }, '角色数据') | ||||||
|  |       .finally(() => { | ||||||
|  |         exportLoading.value = false; | ||||||
|  |       }); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * 修改状态 |    * 修改状态 | ||||||
|    * |    * | ||||||
|   | |||||||
| @@ -30,6 +30,7 @@ import org.springframework.web.bind.annotation.RestController; | |||||||
|  |  | ||||||
| import cn.hutool.core.lang.tree.Tree; | import cn.hutool.core.lang.tree.Tree; | ||||||
|  |  | ||||||
|  | import top.charles7c.cnadmin.common.model.query.SortQuery; | ||||||
| import top.charles7c.cnadmin.common.model.vo.R; | import top.charles7c.cnadmin.common.model.vo.R; | ||||||
| import top.charles7c.cnadmin.monitor.annotation.Log; | import top.charles7c.cnadmin.monitor.annotation.Log; | ||||||
| import top.charles7c.cnadmin.system.model.query.DeptQuery; | import top.charles7c.cnadmin.system.model.query.DeptQuery; | ||||||
| @@ -53,8 +54,8 @@ public class CommonController { | |||||||
|     @Log(ignore = true) |     @Log(ignore = true) | ||||||
|     @Operation(summary = "查询部门树", description = "查询树结构的部门列表") |     @Operation(summary = "查询部门树", description = "查询树结构的部门列表") | ||||||
|     @GetMapping("/tree/dept") |     @GetMapping("/tree/dept") | ||||||
|     public R<List<Tree<Long>>> listDeptTree(@Validated DeptQuery query) { |     public R<List<Tree<Long>>> listDeptTree(@Validated DeptQuery query, @Validated SortQuery sortQuery) { | ||||||
|         List<DeptVO> list = deptService.list(query); |         List<DeptVO> list = deptService.list(query, sortQuery); | ||||||
|         List<Tree<Long>> deptTreeList = deptService.buildTree(list); |         List<Tree<Long>> deptTreeList = deptService.buildTree(list); | ||||||
|         return R.ok(deptTreeList); |         return R.ok(deptTreeList); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -20,8 +20,6 @@ import static top.charles7c.cnadmin.common.annotation.CrudRequestMapping.Api; | |||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| import javax.servlet.http.HttpServletResponse; |  | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.Operation; | import io.swagger.v3.oas.annotations.Operation; | ||||||
| import io.swagger.v3.oas.annotations.tags.Tag; | import io.swagger.v3.oas.annotations.tags.Tag; | ||||||
|  |  | ||||||
| @@ -30,6 +28,7 @@ import org.springframework.web.bind.annotation.*; | |||||||
|  |  | ||||||
| import top.charles7c.cnadmin.common.annotation.CrudRequestMapping; | import top.charles7c.cnadmin.common.annotation.CrudRequestMapping; | ||||||
| import top.charles7c.cnadmin.common.base.BaseController; | import top.charles7c.cnadmin.common.base.BaseController; | ||||||
|  | import top.charles7c.cnadmin.common.model.query.SortQuery; | ||||||
| import top.charles7c.cnadmin.common.model.vo.R; | import top.charles7c.cnadmin.common.model.vo.R; | ||||||
| import top.charles7c.cnadmin.system.model.query.DeptQuery; | import top.charles7c.cnadmin.system.model.query.DeptQuery; | ||||||
| import top.charles7c.cnadmin.system.model.request.DeptRequest; | import top.charles7c.cnadmin.system.model.request.DeptRequest; | ||||||
| @@ -45,19 +44,13 @@ import top.charles7c.cnadmin.system.service.DeptService; | |||||||
|  */ |  */ | ||||||
| @Tag(name = "部门管理 API") | @Tag(name = "部门管理 API") | ||||||
| @RestController | @RestController | ||||||
| @CrudRequestMapping(value = "/system/dept", api = {Api.LIST, Api.GET, Api.CREATE, Api.UPDATE, Api.DELETE}) | @CrudRequestMapping(value = "/system/dept", api = {Api.LIST, Api.GET, Api.CREATE, Api.UPDATE, Api.DELETE, Api.EXPORT}) | ||||||
| public class DeptController extends BaseController<DeptService, DeptVO, DeptDetailVO, DeptQuery, DeptRequest> { | public class DeptController extends BaseController<DeptService, DeptVO, DeptDetailVO, DeptQuery, DeptRequest> { | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     @Operation(summary = "查询列表树") |     @Operation(summary = "查询列表树") | ||||||
|     public R<List<DeptVO>> list(@Validated DeptQuery query) { |     public R<List<DeptVO>> list(@Validated DeptQuery query, @Validated SortQuery sortQuery) { | ||||||
|         List<DeptVO> list = baseService.list(query); |         List<DeptVO> list = baseService.list(query, sortQuery); | ||||||
|         return R.ok(baseService.buildListTree(list)); |         return R.ok(baseService.buildListTree(list)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Operation(summary = "导出部门数据") |  | ||||||
|     @GetMapping("/export") |  | ||||||
|     public void export(@Validated DeptQuery query, HttpServletResponse response) { |  | ||||||
|         baseService.export(query, response); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -16,8 +16,6 @@ | |||||||
|  |  | ||||||
| package top.charles7c.cnadmin.webapi.controller.system; | package top.charles7c.cnadmin.webapi.controller.system; | ||||||
|  |  | ||||||
| import static top.charles7c.cnadmin.common.annotation.CrudRequestMapping.Api; |  | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.tags.Tag; | import io.swagger.v3.oas.annotations.tags.Tag; | ||||||
|  |  | ||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
| @@ -38,5 +36,5 @@ import top.charles7c.cnadmin.system.service.RoleService; | |||||||
|  */ |  */ | ||||||
| @Tag(name = "角色管理 API") | @Tag(name = "角色管理 API") | ||||||
| @RestController | @RestController | ||||||
| @CrudRequestMapping(value = "/system/role", api = {Api.PAGE, Api.GET, Api.CREATE, Api.UPDATE, Api.DELETE}) | @CrudRequestMapping("/system/role") | ||||||
| public class RoleController extends BaseController<RoleService, RoleVO, RoleDetailVO, RoleQuery, RoleRequest> {} | public class RoleController extends BaseController<RoleService, RoleVO, RoleDetailVO, RoleQuery, RoleRequest> {} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user