新增:新增系统管理/部门管理/修改状态及删除功能(后续几天开始对现有代码进行优化,尤其要开始初步封装前后端 CRUD 组件,并针对现在使用的部分规范发起长期投票)

This commit is contained in:
Charles7c 2023-01-25 12:59:30 +08:00
parent 922b28126b
commit 693e825144
7 changed files with 175 additions and 27 deletions

View File

@ -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;
}

View File

@ -20,6 +20,7 @@ import java.util.List;
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.request.CreateDeptRequest;
import top.charles7c.cnadmin.system.model.vo.DeptVO;
@ -68,6 +69,24 @@ public interface DeptService {
*/
Long create(CreateDeptRequest request);
/**
* 修改状态
*
* @param ids
* ID 列表
* @param status
* 状态
*/
void updateStatus(List<Long> ids, DisEnableStatusEnum status);
/**
* 删除
*
* @param ids
* ID 列表
*/
void delete(List<Long> ids);
/**
* 检查部门名称是否存在
*

View File

@ -140,6 +140,20 @@ public class DeptServiceImpl implements DeptService {
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
public boolean checkDeptNameExist(String deptName, Long parentId, Long deptId) {
return deptMapper.exists(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getDeptName, deptName)

View File

@ -49,6 +49,7 @@ declare module '@vue/runtime-core' {
AMenuItem: typeof import('@arco-design/web-vue')['MenuItem']
AModal: typeof import('@arco-design/web-vue')['Modal']
AOption: typeof import('@arco-design/web-vue')['Option']
APopconfirm: typeof import('@arco-design/web-vue')['Popconfirm']
APopover: typeof import('@arco-design/web-vue')['Popover']
ARadio: typeof import('@arco-design/web-vue')['Radio']
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']
ATextarea: typeof import('@arco-design/web-vue')['Textarea']
ATooltip: typeof import('@arco-design/web-vue')['Tooltip']
ATreeSelect: typeof import('@arco-design/web-vue')['TreeSelect']
ATypographyParagraph: typeof import('@arco-design/web-vue')['TypographyParagraph']
ATypographyText: typeof import('@arco-design/web-vue')['TypographyText']
ATypographyTitle: typeof import('@arco-design/web-vue')['TypographyTitle']

View File

@ -2,12 +2,12 @@ import axios from 'axios';
import qs from 'query-string';
export interface DeptRecord {
deptId: string;
deptId?: number;
deptName: string;
parentId: number;
parentId?: number;
deptSort: number;
description: string;
status: number;
status?: number;
updateUserString: string;
updateTime: string;
children: Array<DeptRecord>,
@ -36,3 +36,14 @@ export interface CreateDeptReq {
export function createDept(req: CreateDeptReq) {
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}`);
}

View File

@ -19,7 +19,7 @@
<a-form-item field="status" hide-label>
<a-select
v-model="queryFormData.status"
:options="treeData"
:options="statusOptions"
placeholder="状态搜索"
allow-clear
style="width: 150px"
@ -163,9 +163,10 @@
v-model="record.status"
:checked-value="1"
:unchecked-value="2"
@change="handleChangeStatus(record, record.status)"
/>
</template>
<template #operations>
<template #operations="{ record }">
<a-button
v-permission="['admin']"
type="text"
@ -178,18 +179,18 @@
</template>
修改
</a-button>
<a-popconfirm content="确定删除吗,如果存在下级部门则一并删除,此操作不能撤销!" type="error" @ok="handleDelete(record)">
<a-button
v-permission="['admin']"
type="text"
size="small"
disabled
title="尚未开发"
>
<template #icon>
<icon-delete />
</template>
删除
</a-button>
</a-popconfirm>
</template>
</a-table>
@ -215,6 +216,7 @@
:allow-search="true"
:allow-clear="true"
:filter-tree-node="filterDept"
:fallback-option="false"
placeholder="请选择上级部门"
/>
</a-form-item>
@ -271,10 +273,17 @@
</template>
<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 { 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 type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
import { FormInstance } from '@arco-design/web-vue/es/form';
@ -393,6 +402,29 @@
};
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 = (
val: string | number | Record<string, any> | undefined,
e: Event
@ -460,13 +492,19 @@
);
const visible = ref(false);
const type = ref('新增');
const treeData = ref<TreeNodeData[]>();
const formRef = ref<FormInstance>();
const formData = reactive({
parentId: undefined,
const formData = ref<DeptRecord>({
deptId: undefined,
deptName: '',
parentId: undefined,
deptSort: 999,
description: '',
status: undefined,
updateUserString: '',
updateTime: '',
children: [],
});
const rules = computed((): Record<string, FieldRule[]> => {
return {
@ -494,20 +532,20 @@
const errors = await formRef.value?.validate();
if (errors) return false;
const res = await createDept({
parentId: formData.parentId || 0,
deptName: formData.deptName,
deptSort: formData.deptSort,
description: formData.description,
parentId: formData.value.parentId || 0,
deptName: formData.value.deptName,
deptSort: formData.value.deptSort,
description: formData.value.description,
});
if (!res.success) return false;
Message.success(res.msg);
handleCancel();
fetchData();
await fetchData();
return true;
};
const handleCancel = () => {
visible.value = false;
formRef.value?.resetFields()
formRef.value?.resetFields();
};
</script>

View File

@ -21,12 +21,15 @@ import java.util.List;
import lombok.RequiredArgsConstructor;
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 org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
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.system.model.query.DeptQuery;
import top.charles7c.cnadmin.system.model.request.CreateDeptRequest;
@ -67,4 +70,19 @@ public class DeptController {
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("删除成功");
}
}