明树Git Lab

Commit f81a5cf9 authored by chenron's avatar chenron

部门管理

parent 28cffdfd
...@@ -46,6 +46,13 @@ const routes = [ ...@@ -46,6 +46,13 @@ const routes = [
// component: () => import('@/views/systemManage/index.vue'), // component: () => import('@/views/systemManage/index.vue'),
meta: { menuName: '系统管理', icon: 'tools' }, meta: { menuName: '系统管理', icon: 'tools' },
children: [ children: [
{
path: '/systemManage/departManage',
name: '部门管理',
title: 'departManage',
component: () => import('@/views/systemManage/departManage.vue'),
meta: { menuName: '部门管理',}
},
{ {
path: '/systemManage/userManage', path: '/systemManage/userManage',
name: '用户管理', name: '用户管理',
......
<template>
<div class="depart-manage" v-loading="loading">
<div class="search-origin">
<div class="origin-title">
<h3>组织列表</h3>
<span @click="handleAdd">+&nbsp; 新增组织</span>
</div>
<el-input placeholder="请输入部门名称" clearable>
<template #prefix>
<el-icon><search /></el-icon>
</template>
</el-input>
</div>
<div class="table-container">
<div class="origin-title">
<h3>部门管理</h3>
<el-button type="primary" @click="handleAdd"> 新增 </el-button>
</div>
<commonForm
v-model="searchForm"
:config="searchConfig"
:items="searchItems"
@submit="handleSearch"
@reset="handleReset"
/>
<common-table
:tableHeight="tableHeight"
:data="tableData"
:columns="tableColumns"
:total="total"
:current-page="currentPage"
:page-size="pageSize"
title=""
:border="true"
@size-change="handleSizeChange"
@current-page-change="handleCurrentPageChange"
>
<!-- <template #header-actions>
<el-button type="primary" @click="handleAdd">
<el-icon><Plus /></el-icon>
新增
</el-button>
</template> -->
<template #enable="{ row }">
<el-switch
:model-value="row.enable === 0 ? true : false"
@change="handleStatusChange($event, row)"
active-color="#13ce66"
inactive-color="#ff4949"
></el-switch>
</template>
<template #operations="{ row, index }">
<el-button type="text" size="small" @click="handleEdit(row, index)">
编辑
</el-button>
<el-button type="text" size="small" @click="handleDelete(row, index)">
删除
</el-button>
</template>
</common-table>
</div>
<el-dialog
v-model="dialogVisible"
:title="dialogTitle"
width="600px"
@close="handleDialogClose"
>
<commonForm
v-model="userForm"
:config="formConfig"
:items="formItems"
:rules="formRules"
@submit="handleFormSubmit"
@reset="handleFormReset"
/>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, getCurrentInstance, computed } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import commonForm from "@/components/common/commonForm.vue";
import CommonTable from "@/components/common/commonTable.vue";
const { proxy } = getCurrentInstance();
const loading = ref(false);
// 计算表格高度
const tableHeight = computed(() => {
const headerHeight = 50;
const paginationHeight = 50;
const rowHeight = 40;
const baseHeight = headerHeight + paginationHeight;
// 1.如果数据超过10条,固定显示10行的高度 + 滚动条;2.如果数据不超过10条,按实际行数计算高度
const maxRows = Math.min(tableData.value.length, 10);
const contentHeight = maxRows * rowHeight;
return `${baseHeight + contentHeight}px`;
});
// 数据转换函数
const convertToTreeData = (apiData) => {
return apiData.map((item) => ({
value: item.id.toString(),
label: item.name,
children: item.children ? convertToTreeData(item.children) : [],
}));
};
// 表格数据
const tableData = ref([]);
const total = ref(0);
const currentPage = ref(1);
const pageSize = ref(10);
// 表格列配置
const tableColumns = [
{
prop: "name",
label: "用户姓名",
minWidth: 100,
showOverflowTooltip: true,
},
{
prop: "departs",
label: "所属部门",
minWidth: 120,
showOverflowTooltip: true,
},
{
prop: "positions",
label: "岗位",
minWidth: 100,
showOverflowTooltip: true,
},
{
prop: "roles",
label: "角色",
minWidth: 100,
showOverflowTooltip: true,
},
{
prop: "mobile",
label: "手机号码",
minWidth: 100,
},
{
prop: "createdAt",
label: "创建时间",
minWidth: 160,
},
{
prop: "enable",
label: "状态",
width: 100,
slot: "enable",
align: "center",
},
{
prop: "operations",
label: "操作",
width: 160,
slot: "operations",
fixed: "right",
align: "center",
},
];
// 对话框相关
const dialogVisible = ref(false);
const dialogTitle = ref("新增用户");
const isEdit = ref(false);
const editIndex = ref(-1);
const searchForm = ref({
name: "",
});
const searchConfig = {
inline: false,
labelWidth: "80px",
showButtons: true,
submitText: "查询",
resetText: "重置",
};
const searchItems = [
{
type: "input",
prop: "name",
label: "部门名称",
placeholder: "请输入部门名称",
clearable: true,
span: 8,
},
];
// 用户表单数据
const userForm = ref({
name: "",
departs: [],
positions: [],
roles: [],
enable: "0",
});
// 用户表单配置
const formConfig = {
labelWidth: "100px",
showButtons: true,
submitText: "保存",
resetText: "取消",
};
const departmentData = ref([]);
const positionsData = ref([]);
const rolesData = ref([]);
const loadDepartmentData = () => {
proxy.$post({
url: "/api/user/depart/treeDepart",
data: {},
callback: (data) => {
departmentData.value = convertToTreeData(data);
},
error: (err) => {},
});
};
// 岗位下拉数据
const loadPositionsData = () => {
proxy.$post({
url: "/api/user/position/listPosition",
data: {},
callback: (data) => {
positionsData.value = convertToTreeData(data.rows);
},
error: (err) => {},
});
};
// 角色下拉数据
const loadRolesData = () => {
proxy.$post({
url: "/api/user/role/listRole",
data: {
page: 1,
pageSize: 10,
},
callback: (data) => {
rolesData.value = convertToTreeData(data.rows);
},
error: (err) => {},
});
};
// 用户表单项配置
const formItems = computed(() => [
{
type: "input",
prop: "name",
label: "用户姓名",
placeholder: "请输入用户姓名",
span: 12,
},
{
type: "tree",
prop: "departs",
label: "所属部门",
placeholder: "请选择部门",
data: departmentData.value,
clearable: true,
filterable: true,
checkStrictly: true,
renderAfterExpand: false,
showCheckbox: true,
multiple: true,
collapseTags: true,
maxCollapseTags: 2,
span: 12,
},
{
type: "tree",
prop: "positions",
label: "岗位",
placeholder: "请选择岗位",
data: positionsData.value,
clearable: true,
filterable: true,
checkStrictly: true,
renderAfterExpand: false,
showCheckbox: true,
multiple: true,
collapseTags: true,
maxCollapseTags: 2,
span: 12,
},
{
type: "tree",
prop: "roles",
label: "角色",
placeholder: "请选择角色",
data: rolesData.value,
clearable: true,
filterable: true,
checkStrictly: true,
renderAfterExpand: false,
showCheckbox: true,
multiple: true,
collapseTags: true,
maxCollapseTags: 2,
span: 12,
},
{
type: "input",
prop: "mobile",
label: "手机号码",
placeholder: "请输入手机号码",
span: 12,
},
{
type: "radio",
prop: "enable",
label: "状态",
span: 12,
options: [
{ label: "启用", value: "0" },
{ label: "停用", value: "1" },
],
},
]);
// 表单验证规则
const formRules = {};
const handleSizeChange = (size) => {
pageSize.value = size;
currentPage.value = 1;
loadTableData();
};
const handleCurrentPageChange = (page) => {
currentPage.value = page;
loadTableData();
};
// 新增用户
const handleAdd = () => {
isEdit.value = false;
dialogTitle.value = "新增用户";
userForm.value = {
name: "",
departs: [],
positions: [],
roles: [],
enable: "0",
};
loadDepartmentData();
loadPositionsData();
loadRolesData();
dialogVisible.value = true;
};
let currentID = ref();
// 编辑
const handleEdit = (row, index) => {
isEdit.value = true;
dialogTitle.value = "编辑用户";
editIndex.value = index;
proxy.$post({
url: "/api/user/manage/getUserInfo",
data: { id: row.id },
callback: (data) => {
userForm.value = { ...data };
currentID.value = data.id;
},
error: (err) => {
ElMessage.error("编辑失败:", err);
},
});
dialogVisible.value = true;
};
// 删除
const handleDelete = async (row, index) => {
try {
await ElMessageBox.confirm(`确定要删除用户"${row.name}"吗?`, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
});
proxy.$post({
url: "/api/user/manage/deleteUser",
data: { id: row.id },
callback: (data) => {
dialogVisible.value = false;
loadTableData();
ElMessage.success("删除成功");
},
error: (err) => {
ElMessage.error("删除失败:", err);
},
});
loadTableData();
} catch {}
};
const handleFormSubmit = (formData) => {
if (isEdit.value) {
// 编辑用户
const updateUser = {
...formData,
departs: Array.isArray(formData.departs) ? formData.departs : [],
positions: Array.isArray(formData.positions) ? formData.positions : [],
roles: Array.isArray(formData.roles) ? formData.roles : [],
id: currentID.value,
};
proxy.$post({
url: "/api/user/manage/updateUser",
data: updateUser,
callback: (data) => {
dialogVisible.value = false;
loadTableData();
ElMessage.success("用户信息更新成功");
},
error: (err) => {
ElMessage.error("用户信息更新失败:", err);
},
});
} else {
// 新增用户
const newUser = {
...formData,
departs: Array.isArray(formData.departs) ? formData.departs : [],
positions: Array.isArray(formData.positions) ? formData.positions : [],
roles: Array.isArray(formData.roles) ? formData.roles : [],
};
proxy.$post({
url: "/api/user/manage/createUser",
data: newUser,
callback: (data) => {
dialogVisible.value = false;
loadTableData();
ElMessage.success("用户添加成功");
},
error: (err) => {
ElMessage.error("用户添加失败:", err);
},
});
}
};
const handleFormReset = () => {
dialogVisible.value = false;
};
const handleDialogClose = () => {
dialogVisible.value = false;
};
// 处理状态切换
const handleStatusChange = (newValue, row) => {
const newEnableValue = newValue ? "0" : "1";
proxy.$post({
url: "/api/user/manage/updateUser",
data: {
id: row.id,
enable: newEnableValue,
},
callback: (data) => {
row.enable = newEnableValue;
loadTableData();
ElMessage.success(
`用户状态已${newEnableValue === "0" ? "启用" : "停用"}`
);
},
error: (err) => {
ElMessage.error("状态更新失败");
},
});
};
// 表格数据
const loadTableData = () => {
loading.value = true;
proxy.$post({
url: "/api/user/manage/listUser",
data: {
page: currentPage.value,
pageSize: pageSize.value,
},
callback: (data) => {
tableData.value = data.rows.map((item) => {
item.departs = item.departs.map((item) => item.name).join(",");
item.positions = item.positions.map((item) => item.name).join(",");
item.roles = item.roles.map((item) => item.name).join(",");
return item;
});
total.value = data.count;
loading.value = false;
},
error: (err) => {
loading.value = false;
ElMessage.error("加载数据失败");
},
});
};
onMounted(() => {
// loadTableData();
// loadDepartmentData();
// loadPositionsData();
// loadRolesData();
});
</script>
<style scoped lang="less">
.depart-manage {
padding: 20px;
background: rgba(157, 188, 218, 0.1);
height: 100%;
display: flex;
.search-origin {
background: rgba(255, 255, 255, 0.9);
border-radius: 8px;
padding: 20px;
margin-right: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
flex-shrink: 3;
width: 400px;
height: 845px;
}
.origin-title {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
span {
color: #2561ef;
cursor: pointer;
}
}
.table-container {
flex: 1;
background: rgba(255, 255, 255, 0.9);
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
}
.el-input__wrapper {
height: 35px;
}
</style>
<template> <template>
<div class="user-manage" v-loading="loading"> <div class="user-manage" v-loading="loading">
<!-- 查询表单 -->
<div class="search-form"> <div class="search-form">
<commonForm <commonForm
v-model="searchForm" v-model="searchForm"
...@@ -10,8 +9,6 @@ ...@@ -10,8 +9,6 @@
@reset="handleReset" @reset="handleReset"
/> />
</div> </div>
<!-- 用户列表表格 -->
<div class="table-container"> <div class="table-container">
<common-table <common-table
:tableHeight="tableHeight" :tableHeight="tableHeight"
...@@ -52,7 +49,6 @@ ...@@ -52,7 +49,6 @@
</common-table> </common-table>
</div> </div>
<!-- 用户表单对话框 -->
<el-dialog <el-dialog
v-model="dialogVisible" v-model="dialogVisible"
:title="dialogTitle" :title="dialogTitle"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment