新增:新增系统管理/部门管理/修改状态及删除功能(后续几天开始对现有代码进行优化,尤其要开始初步封装前后端 CRUD 组件,并针对现在使用的部分规范发起长期投票)
This commit is contained in:
parent
922b28126b
commit
693e825144
@ -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>,
|
||||||
@ -35,4 +35,15 @@ 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-button
|
<a-popconfirm content="确定删除吗,如果存在下级部门则一并删除,此操作不能撤销!" type="error" @ok="handleDelete(record)">
|
||||||
v-permission="['admin']"
|
<a-button
|
||||||
type="text"
|
v-permission="['admin']"
|
||||||
size="small"
|
type="text"
|
||||||
disabled
|
size="small"
|
||||||
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("删除成功");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user