Files
vue3-element-admin/src/views/system/dept/index.vue

344 lines
9.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="app-container">
<div class="filter-section">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="关键字" prop="keywords">
<el-input
v-model="queryParams.keywords"
placeholder="部门名称"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="部门状态" prop="status">
<el-select v-model="queryParams.status" placeholder="全部" clearable style="width: 100px">
<el-option :value="1" label="正常" />
<el-option :value="0" label="禁用" />
</el-select>
</el-form-item>
<el-form-item class="search-buttons">
<el-button class="filter-item" type="primary" icon="search" @click="handleQuery">
搜索
</el-button>
<el-button icon="refresh" @click="handleResetQuery">重置</el-button>
</el-form-item>
</el-form>
</div>
<el-card shadow="hover" class="table-section">
<div class="table-section__toolbar">
<div class="table-section__toolbar--actions">
<el-button
v-hasPerm="['sys:dept:create']"
type="success"
icon="plus"
@click="openDialog()"
>
新增
</el-button>
<el-button
v-hasPerm="['sys:dept:delete']"
type="danger"
:disabled="selectIds.length === 0"
icon="delete"
@click="handleDelete()"
>
删除
</el-button>
</div>
</div>
<el-table
v-loading="loading"
:data="deptList"
row-key="id"
default-expand-all
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
class="table-section__content"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column prop="name" label="部门名称" min-width="200" />
<el-table-column prop="code" label="部门编号" width="200" />
<el-table-column prop="status" label="状态" width="100">
<template #default="scope">
<el-tag v-if="scope.row.status == 1" type="success">正常</el-tag>
<el-tag v-else type="info">禁用</el-tag>
</template>
</el-table-column>
<el-table-column prop="sort" label="排序" width="100" />
<el-table-column label="操作" fixed="right" align="left" width="200">
<template #default="scope">
<el-button
v-hasPerm="['sys:dept:create']"
type="primary"
link
size="small"
icon="plus"
@click.stop="openDialog(scope.row.id, undefined)"
>
新增
</el-button>
<el-button
v-hasPerm="['sys:dept:update']"
type="primary"
link
size="small"
icon="edit"
@click.stop="openDialog(scope.row.parentId, scope.row.id)"
>
编辑
</el-button>
<el-button
v-hasPerm="['sys:dept:delete']"
type="danger"
link
size="small"
icon="delete"
@click.stop="handleDelete(scope.row.id)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog
v-model="dialogState.visible"
:title="dialogState.title"
width="600px"
@closed="closeDialog"
>
<el-form ref="deptFormRef" :model="formData" :rules="rules" label-width="80px">
<el-form-item label="上级部门" prop="parentId">
<el-tree-select
v-model="formData.parentId"
placeholder="选择上级部门"
:data="deptOptions"
filterable
check-strictly
:render-after-expand="false"
/>
</el-form-item>
<el-form-item label="部门名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入部门名称" />
</el-form-item>
<el-form-item label="部门编号" prop="code">
<el-input v-model="formData.code" placeholder="请输入部门编码" />
</el-form-item>
<el-form-item label="显示排序" prop="sort">
<el-input-number
v-model="formData.sort"
controls-position="right"
style="width: 100px"
:min="0"
/>
</el-form-item>
<el-form-item label="部门状态">
<el-radio-group v-model="formData.status">
<el-radio :value="1">正常</el-radio>
<el-radio :value="0">禁用</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleSubmit">确定</el-button>
<el-button @click="closeDialog">取消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
defineOptions({
name: "Dept",
inheritAttrs: false,
});
import DeptAPI from "@/api/system/dept";
import type { DeptItem, DeptForm, DeptQueryParams } from "@/types/api";
import type { FormInstance, FormRules } from "element-plus";
// 表单引用
const queryFormRef = ref<FormInstance>();
const deptFormRef = ref<FormInstance>();
// 查询参数
const queryParams = reactive<DeptQueryParams>({});
// 列表数据
const deptList = ref<DeptItem[]>();
const deptOptions = ref<OptionItem[]>();
const loading = ref(false);
const selectIds = ref<string[]>([]);
// 弹窗状态
const dialogState = reactive({
title: "",
visible: false,
});
// 表单数据
const formData = reactive<DeptForm>({
status: 1,
parentId: "0",
sort: 1,
});
// 验证规则
const rules: FormRules = {
parentId: [{ required: true, message: "上级部门不能为空", trigger: "change" }],
name: [{ required: true, message: "部门名称不能为空", trigger: "blur" }],
code: [{ required: true, message: "部门编号不能为空", trigger: "blur" }],
sort: [{ required: true, message: "显示排序不能为空", trigger: "blur" }],
};
/**
* 加载部门列表数据
*/
function fetchData(): void {
loading.value = true;
DeptAPI.getList(queryParams)
.then((data) => {
deptList.value = data;
})
.finally(() => {
loading.value = false;
});
}
/**
* 查询按钮点击事件
*/
function handleQuery(): void {
fetchData();
}
/**
* 重置查询
*/
function handleResetQuery(): void {
queryFormRef.value?.resetFields();
fetchData();
}
/**
* 表格选择变化事件
*/
function handleSelectionChange(selection: DeptItem[]): void {
selectIds.value = selection.map((item) => item.id).filter(Boolean) as string[];
}
/**
* 打开弹窗
* @param parentId 父部门ID
* @param deptId 部门ID编辑时传入
*/
async function openDialog(parentId?: string, deptId?: string): Promise<void> {
const data = await DeptAPI.getOptions();
deptOptions.value = [
{
value: "0",
label: "顶级部门",
children: data,
},
];
dialogState.visible = true;
if (deptId) {
dialogState.title = "修改部门";
DeptAPI.getFormData(deptId).then((data) => {
Object.assign(formData, data);
});
} else {
dialogState.title = "新增部门";
formData.parentId = parentId || "0";
}
}
/**
* 提交表单
*/
function handleSubmit(): void {
deptFormRef.value?.validate((valid) => {
if (valid) {
loading.value = true;
const deptId = formData.id;
if (deptId) {
DeptAPI.update(deptId, formData)
.then(() => {
ElMessage.success("修改成功");
closeDialog();
fetchData();
})
.finally(() => (loading.value = false));
} else {
DeptAPI.create(formData)
.then(() => {
ElMessage.success("新增成功");
closeDialog();
fetchData();
})
.finally(() => (loading.value = false));
}
}
});
}
/**
* 删除部门
* @param deptId 部门ID
*/
function handleDelete(deptId?: number): void {
const deptIds = [deptId || selectIds.value].join(",");
if (!deptIds) {
ElMessage.warning("请勾选删除项");
return;
}
ElMessageBox.confirm("确认删除已选中的数据项?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(
() => {
loading.value = true;
DeptAPI.deleteByIds(deptIds)
.then(() => {
ElMessage.success("删除成功");
handleResetQuery();
})
.finally(() => (loading.value = false));
},
() => {
ElMessage.info("已取消删除");
}
);
}
/**
* 关闭弹窗
*/
function closeDialog(): void {
dialogState.visible = false;
deptFormRef.value?.resetFields();
deptFormRef.value?.clearValidate();
formData.id = undefined;
formData.parentId = "0";
formData.status = 1;
formData.sort = 1;
}
onMounted(() => {
fetchData();
});
</script>