mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-10-31 10:57:13 +08:00 
			
		
		
		
	新增:新增系统管理/部门管理/修改状态及删除功能(后续几天开始对现有代码进行优化,尤其要开始初步封装前后端 CRUD 组件,并针对现在使用的部分规范发起长期投票)
This commit is contained in:
		| @@ -0,0 +1,46 @@ | |||||||
|  | /* | ||||||
|  |  * 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.request; | ||||||
|  |  | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | import javax.validation.constraints.NotNull; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  |  | ||||||
|  | import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 修改状态信息 | ||||||
|  |  * | ||||||
|  |  * @author Charles7c | ||||||
|  |  * @since 2023/1/24 19:51 | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class UpdateStatusRequest implements Serializable { | ||||||
|  |  | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 状态(1启用 2禁用) | ||||||
|  |      */ | ||||||
|  |     @Schema(description = "状态(1启用 2禁用)") | ||||||
|  |     @NotNull(message = "状态非法") | ||||||
|  |     private DisEnableStatusEnum status; | ||||||
|  | } | ||||||
| @@ -20,6 +20,7 @@ import java.util.List; | |||||||
|  |  | ||||||
| import cn.hutool.core.lang.tree.Tree; | import cn.hutool.core.lang.tree.Tree; | ||||||
|  |  | ||||||
|  | import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum; | ||||||
| import top.charles7c.cnadmin.system.model.query.DeptQuery; | import top.charles7c.cnadmin.system.model.query.DeptQuery; | ||||||
| import top.charles7c.cnadmin.system.model.request.CreateDeptRequest; | import top.charles7c.cnadmin.system.model.request.CreateDeptRequest; | ||||||
| import top.charles7c.cnadmin.system.model.vo.DeptVO; | import top.charles7c.cnadmin.system.model.vo.DeptVO; | ||||||
| @@ -68,6 +69,24 @@ public interface DeptService { | |||||||
|      */ |      */ | ||||||
|     Long create(CreateDeptRequest request); |     Long create(CreateDeptRequest request); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 修改状态 | ||||||
|  |      * | ||||||
|  |      * @param ids | ||||||
|  |      *            ID 列表 | ||||||
|  |      * @param status | ||||||
|  |      *            状态 | ||||||
|  |      */ | ||||||
|  |     void updateStatus(List<Long> ids, DisEnableStatusEnum status); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 删除 | ||||||
|  |      * | ||||||
|  |      * @param ids | ||||||
|  |      *            ID 列表 | ||||||
|  |      */ | ||||||
|  |     void delete(List<Long> ids); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 检查部门名称是否存在 |      * 检查部门名称是否存在 | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -140,6 +140,20 @@ public class DeptServiceImpl implements DeptService { | |||||||
|         return sysDept.getDeptId(); |         return sysDept.getDeptId(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     @Transactional(rollbackFor = Exception.class) | ||||||
|  |     public void updateStatus(List<Long> ids, DisEnableStatusEnum status) { | ||||||
|  |         deptMapper.update(null, | ||||||
|  |             Wrappers.<SysDept>lambdaUpdate().set(SysDept::getStatus, status).in(SysDept::getDeptId, ids)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     @Transactional(rollbackFor = Exception.class) | ||||||
|  |     public void delete(List<Long> ids) { | ||||||
|  |         deptMapper.deleteBatchIds(ids); | ||||||
|  |         deptMapper.delete(Wrappers.<SysDept>lambdaQuery().in(SysDept::getParentId, ids)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public boolean checkDeptNameExist(String deptName, Long parentId, Long deptId) { |     public boolean checkDeptNameExist(String deptName, Long parentId, Long deptId) { | ||||||
|         return deptMapper.exists(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getDeptName, deptName) |         return deptMapper.exists(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getDeptName, deptName) | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								continew-admin-ui/components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								continew-admin-ui/components.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -49,6 +49,7 @@ declare module '@vue/runtime-core' { | |||||||
|     AMenuItem: typeof import('@arco-design/web-vue')['MenuItem'] |     AMenuItem: typeof import('@arco-design/web-vue')['MenuItem'] | ||||||
|     AModal: typeof import('@arco-design/web-vue')['Modal'] |     AModal: typeof import('@arco-design/web-vue')['Modal'] | ||||||
|     AOption: typeof import('@arco-design/web-vue')['Option'] |     AOption: typeof import('@arco-design/web-vue')['Option'] | ||||||
|  |     APopconfirm: typeof import('@arco-design/web-vue')['Popconfirm'] | ||||||
|     APopover: typeof import('@arco-design/web-vue')['Popover'] |     APopover: typeof import('@arco-design/web-vue')['Popover'] | ||||||
|     ARadio: typeof import('@arco-design/web-vue')['Radio'] |     ARadio: typeof import('@arco-design/web-vue')['Radio'] | ||||||
|     ARadioGroup: typeof import('@arco-design/web-vue')['RadioGroup'] |     ARadioGroup: typeof import('@arco-design/web-vue')['RadioGroup'] | ||||||
| @@ -73,6 +74,7 @@ declare module '@vue/runtime-core' { | |||||||
|     ATag: typeof import('@arco-design/web-vue')['Tag'] |     ATag: typeof import('@arco-design/web-vue')['Tag'] | ||||||
|     ATextarea: typeof import('@arco-design/web-vue')['Textarea'] |     ATextarea: typeof import('@arco-design/web-vue')['Textarea'] | ||||||
|     ATooltip: typeof import('@arco-design/web-vue')['Tooltip'] |     ATooltip: typeof import('@arco-design/web-vue')['Tooltip'] | ||||||
|  |     ATreeSelect: typeof import('@arco-design/web-vue')['TreeSelect'] | ||||||
|     ATypographyParagraph: typeof import('@arco-design/web-vue')['TypographyParagraph'] |     ATypographyParagraph: typeof import('@arco-design/web-vue')['TypographyParagraph'] | ||||||
|     ATypographyText: typeof import('@arco-design/web-vue')['TypographyText'] |     ATypographyText: typeof import('@arco-design/web-vue')['TypographyText'] | ||||||
|     ATypographyTitle: typeof import('@arco-design/web-vue')['TypographyTitle'] |     ATypographyTitle: typeof import('@arco-design/web-vue')['TypographyTitle'] | ||||||
|   | |||||||
| @@ -2,12 +2,12 @@ import axios from 'axios'; | |||||||
| import qs from 'query-string'; | import qs from 'query-string'; | ||||||
|  |  | ||||||
| export interface DeptRecord { | export interface DeptRecord { | ||||||
|   deptId: string; |   deptId?: number; | ||||||
|   deptName: string; |   deptName: string; | ||||||
|   parentId: number; |   parentId?: number; | ||||||
|   deptSort: number; |   deptSort: number; | ||||||
|   description: string; |   description: string; | ||||||
|   status: number; |   status?: number; | ||||||
|   updateUserString: string; |   updateUserString: string; | ||||||
|   updateTime: string; |   updateTime: string; | ||||||
|   children: Array<DeptRecord>, |   children: Array<DeptRecord>, | ||||||
| @@ -36,3 +36,14 @@ export interface CreateDeptReq { | |||||||
| export function createDept(req: CreateDeptReq) { | export function createDept(req: CreateDeptReq) { | ||||||
|   return axios.post('/system/dept', req); |   return axios.post('/system/dept', req); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | export interface UpdateDeptStatusReq { | ||||||
|  |   status: number; | ||||||
|  | } | ||||||
|  | export function updateDeptStatus(ids: Array<number>, req: UpdateDeptStatusReq) { | ||||||
|  |   return axios.patch(`/system/dept/${ids}`, req); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export function deleteDept(ids: Array<number>) { | ||||||
|  |   return axios.delete(`/system/dept/${ids}`); | ||||||
|  | } | ||||||
| @@ -19,7 +19,7 @@ | |||||||
|               <a-form-item field="status" hide-label> |               <a-form-item field="status" hide-label> | ||||||
|                 <a-select |                 <a-select | ||||||
|                   v-model="queryFormData.status" |                   v-model="queryFormData.status" | ||||||
|                   :options="treeData" |                   :options="statusOptions" | ||||||
|                   placeholder="状态搜索" |                   placeholder="状态搜索" | ||||||
|                   allow-clear |                   allow-clear | ||||||
|                   style="width: 150px" |                   style="width: 150px" | ||||||
| @@ -163,9 +163,10 @@ | |||||||
|                 v-model="record.status" |                 v-model="record.status" | ||||||
|                 :checked-value="1" |                 :checked-value="1" | ||||||
|                 :unchecked-value="2" |                 :unchecked-value="2" | ||||||
|  |                 @change="handleChangeStatus(record, record.status)" | ||||||
|               /> |               /> | ||||||
|             </template> |             </template> | ||||||
|             <template #operations> |             <template #operations="{ record }"> | ||||||
|               <a-button |               <a-button | ||||||
|                 v-permission="['admin']" |                 v-permission="['admin']" | ||||||
|                 type="text" |                 type="text" | ||||||
| @@ -178,18 +179,18 @@ | |||||||
|                 </template> |                 </template> | ||||||
|                 修改 |                 修改 | ||||||
|               </a-button> |               </a-button> | ||||||
|  |               <a-popconfirm content="确定删除吗,如果存在下级部门则一并删除,此操作不能撤销!" type="error" @ok="handleDelete(record)"> | ||||||
|                 <a-button |                 <a-button | ||||||
|                   v-permission="['admin']" |                   v-permission="['admin']" | ||||||
|                   type="text" |                   type="text" | ||||||
|                   size="small" |                   size="small" | ||||||
|                 disabled |  | ||||||
|                 title="尚未开发" |  | ||||||
|                 > |                 > | ||||||
|                   <template #icon> |                   <template #icon> | ||||||
|                     <icon-delete /> |                     <icon-delete /> | ||||||
|                   </template> |                   </template> | ||||||
|                   删除 |                   删除 | ||||||
|                 </a-button> |                 </a-button> | ||||||
|  |               </a-popconfirm> | ||||||
|             </template> |             </template> | ||||||
|           </a-table> |           </a-table> | ||||||
|  |  | ||||||
| @@ -215,6 +216,7 @@ | |||||||
|                   :allow-search="true" |                   :allow-search="true" | ||||||
|                   :allow-clear="true" |                   :allow-clear="true" | ||||||
|                   :filter-tree-node="filterDept" |                   :filter-tree-node="filterDept" | ||||||
|  |                   :fallback-option="false" | ||||||
|                   placeholder="请选择上级部门" |                   placeholder="请选择上级部门" | ||||||
|                 /> |                 /> | ||||||
|               </a-form-item> |               </a-form-item> | ||||||
| @@ -271,10 +273,17 @@ | |||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
|   import { computed, nextTick, reactive, ref, watch } from 'vue'; |   import { computed, nextTick, ref, watch } from 'vue'; | ||||||
|   import useLoading from '@/hooks/loading'; |   import useLoading from '@/hooks/loading'; | ||||||
|   import { FieldRule, Message, TableInstance, TreeNodeData } from '@arco-design/web-vue'; |   import { FieldRule, Message, TableInstance, TreeNodeData } from '@arco-design/web-vue'; | ||||||
|   import { getDeptList, DeptRecord, DeptParams, createDept } from '@/api/system/dept'; |   import { | ||||||
|  |     getDeptList, | ||||||
|  |     DeptRecord, | ||||||
|  |     DeptParams, | ||||||
|  |     createDept, | ||||||
|  |     updateDeptStatus, | ||||||
|  |     deleteDept, | ||||||
|  |   } from '@/api/system/dept'; | ||||||
|   import getDeptTree from '@/api/common'; |   import getDeptTree from '@/api/common'; | ||||||
|   import type { TableColumnData } from '@arco-design/web-vue/es/table/interface'; |   import type { TableColumnData } from '@arco-design/web-vue/es/table/interface'; | ||||||
|   import { FormInstance } from '@arco-design/web-vue/es/form'; |   import { FormInstance } from '@arco-design/web-vue/es/form'; | ||||||
| @@ -393,6 +402,29 @@ | |||||||
|   }; |   }; | ||||||
|   fetchData(); |   fetchData(); | ||||||
|  |  | ||||||
|  |   // 改变状态 | ||||||
|  |   const handleChangeStatus = async (record: DeptRecord, val: number) => { | ||||||
|  |     if (record.deptId) { | ||||||
|  |       const res = await updateDeptStatus([record.deptId], { status: val }); | ||||||
|  |       if (res.success) { | ||||||
|  |         Message.success(res.msg); | ||||||
|  |       } else { | ||||||
|  |         record.status = (record.status === 1) ? 2 : 1; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   // 删除 | ||||||
|  |   const handleDelete = async (record: DeptRecord) => { | ||||||
|  |     if (record.deptId) { | ||||||
|  |       const res = await deleteDept([record.deptId]); | ||||||
|  |       if (res.success) { | ||||||
|  |         Message.success(res.msg); | ||||||
|  |         await fetchData(); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|   const handleSelectDensity = ( |   const handleSelectDensity = ( | ||||||
|     val: string | number | Record<string, any> | undefined, |     val: string | number | Record<string, any> | undefined, | ||||||
|     e: Event |     e: Event | ||||||
| @@ -460,13 +492,19 @@ | |||||||
|   ); |   ); | ||||||
|  |  | ||||||
|   const visible = ref(false); |   const visible = ref(false); | ||||||
|  |   const type = ref('新增'); | ||||||
|   const treeData = ref<TreeNodeData[]>(); |   const treeData = ref<TreeNodeData[]>(); | ||||||
|   const formRef = ref<FormInstance>(); |   const formRef = ref<FormInstance>(); | ||||||
|   const formData = reactive({ |   const formData = ref<DeptRecord>({ | ||||||
|     parentId: undefined, |     deptId: undefined, | ||||||
|     deptName: '', |     deptName: '', | ||||||
|  |     parentId: undefined, | ||||||
|     deptSort: 999, |     deptSort: 999, | ||||||
|     description: '', |     description: '', | ||||||
|  |     status: undefined, | ||||||
|  |     updateUserString: '', | ||||||
|  |     updateTime: '', | ||||||
|  |     children: [], | ||||||
|   }); |   }); | ||||||
|   const rules = computed((): Record<string, FieldRule[]> => { |   const rules = computed((): Record<string, FieldRule[]> => { | ||||||
|     return { |     return { | ||||||
| @@ -494,20 +532,20 @@ | |||||||
|     const errors = await formRef.value?.validate(); |     const errors = await formRef.value?.validate(); | ||||||
|     if (errors) return false; |     if (errors) return false; | ||||||
|     const res = await createDept({ |     const res = await createDept({ | ||||||
|       parentId: formData.parentId || 0, |       parentId: formData.value.parentId || 0, | ||||||
|       deptName: formData.deptName, |       deptName: formData.value.deptName, | ||||||
|       deptSort: formData.deptSort, |       deptSort: formData.value.deptSort, | ||||||
|       description: formData.description, |       description: formData.value.description, | ||||||
|     }); |     }); | ||||||
|     if (!res.success) return false; |     if (!res.success) return false; | ||||||
|     Message.success(res.msg); |     Message.success(res.msg); | ||||||
|     handleCancel(); |     handleCancel(); | ||||||
|     fetchData(); |     await fetchData(); | ||||||
|     return true; |     return true; | ||||||
|   }; |   }; | ||||||
|   const handleCancel = () => { |   const handleCancel = () => { | ||||||
|     visible.value = false; |     visible.value = false; | ||||||
|     formRef.value?.resetFields() |     formRef.value?.resetFields(); | ||||||
|   }; |   }; | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,12 +21,15 @@ import java.util.List; | |||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.Operation; | import io.swagger.v3.oas.annotations.Operation; | ||||||
|  | import io.swagger.v3.oas.annotations.Parameter; | ||||||
|  | import io.swagger.v3.oas.annotations.enums.ParameterIn; | ||||||
| import io.swagger.v3.oas.annotations.tags.Tag; | import io.swagger.v3.oas.annotations.tags.Tag; | ||||||
|  |  | ||||||
| import org.springframework.http.MediaType; | import org.springframework.http.MediaType; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
|  |  | ||||||
|  | import top.charles7c.cnadmin.common.model.request.UpdateStatusRequest; | ||||||
| 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.CreateDeptRequest; | import top.charles7c.cnadmin.system.model.request.CreateDeptRequest; | ||||||
| @@ -67,4 +70,19 @@ public class DeptController { | |||||||
|  |  | ||||||
|         return R.ok("新增成功", deptService.create(request)); |         return R.ok("新增成功", deptService.create(request)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Operation(summary = "修改部门状态") | ||||||
|  |     @PatchMapping("/{ids}") | ||||||
|  |     public R updateStatus(@PathVariable List<Long> ids, @Validated @RequestBody UpdateStatusRequest request) { | ||||||
|  |         deptService.updateStatus(ids, request.getStatus()); | ||||||
|  |         return R.ok(String.format("%s成功", request.getStatus().getDescription())); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Operation(summary = "删除部门") | ||||||
|  |     @Parameter(name = "ids", description = "ID 列表", in = ParameterIn.PATH) | ||||||
|  |     @DeleteMapping("/{ids}") | ||||||
|  |     public R delete(@PathVariable List<Long> ids) { | ||||||
|  |         deptService.delete(ids); | ||||||
|  |         return R.ok("删除成功"); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user