角色管理查询页面优化,角色编辑表单优化,新增账号管理表单,查询列表页面

This commit is contained in:
dzl 2025-05-12 17:18:25 +08:00
parent 46acabc67b
commit 498d6bcbed
5 changed files with 746 additions and 116 deletions

View File

@ -91,6 +91,11 @@ const pages = [
path: '/RoleManage', path: '/RoleManage',
name: '角色管理', name: '角色管理',
isMenu: true isMenu: true
},
{
path: '/AccountManage',
name: '账号管理',
isMenu: true
} }
] ]
} }
@ -134,9 +139,6 @@ const getMenus = () => {
if (permcodes.length === 0) { if (permcodes.length === 0) {
return menus; return menus;
} }
if (!permcodes.includes(permcode)) {
return menus;
}
pages.forEach((item) => { pages.forEach((item) => {
let ipath = item.path; let ipath = item.path;
if (ipath === '') { if (ipath === '') {
@ -157,7 +159,7 @@ const getMenus = () => {
path: ipath path: ipath
} }
let ipermcode = permcode + '.' + ikey.toLowerCase().replace(/-/g, '.'); let ipermcode = permcode + '.' + ikey.toLowerCase().replace(/-/g, '.');
if (permcodes.includes(ipermcode) || ikey.toLowerCase() === 'home') { if (permcodes.some(item => item.includes(ipermcode)) || ikey.toLowerCase() === 'home') {
menus.push(menu) menus.push(menu)
if (item.children) { if (item.children) {
item.children.forEach((child) => { item.children.forEach((child) => {
@ -171,7 +173,7 @@ const getMenus = () => {
} }
menu.children = menu.children || []; menu.children = menu.children || [];
let cpermcode = permcode + '.' + ckey.toLowerCase().replace(/-/g, '.'); let cpermcode = permcode + '.' + ckey.toLowerCase().replace(/-/g, '.');
if (child['isMenu'] && permcodes.includes(cpermcode)) { if (child['isMenu'] && permcodes.some(item => item.includes(cpermcode))) {
menu.children.push({ menu.children.push({
key: ckey, key: ckey,
label: child.name, label: child.name,

View File

@ -0,0 +1,274 @@
<template>
<a-form
:label-col="{ xl: 7, lg: 5, md: 7, sm: 4 }"
:wrapper-col="{ xl: 17, lg: 19, md: 17, sm: 20 }"
>
<a-row :gutter="8">
<a-col
:xl="6"
:lg="12"
:md="12"
:sm="24"
:xs="24"
>
<a-form-item label="用户账号">
<a-input
v-model:value.trim="queryform.account"
placeholder="请输入用户账号"
allow-clear
></a-input>
</a-form-item>
</a-col>
<a-col
:xl="6"
:lg="12"
:md="12"
:sm="24"
:xs="24"
>
<a-form-item label="用户名称">
<a-input
v-model:value.trim="queryform.accountName"
placeholder="请输入用户名称"
allow-clear
></a-input>
</a-form-item>
</a-col>
<a-col
:xl="6"
:lg="12"
:md="12"
:sm="24"
:xs="24"
>
<a-form-item
class="ele-text-right"
:wrapper-col="{ span: 24 }"
>
<a-space>
<a-button
type="primary"
style="background-color: #5cc750"
@click="search"
>查询</a-button>
<a-button @click="reset">重置</a-button>
</a-space>
</a-form-item>
</a-col>
</a-row>
</a-form>
<!-- 数据操作 -->
<a-space style="margin-bottom: 10px">
<a-button
style="background-color: #5cc750"
type="primary"
class="ele-btn-icon"
@click="handleAdd('新增账号')"
>
<template #icon>
<plus-outlined />
</template>
<span>新增</span>
</a-button>
</a-space>
<a-table
bordered
:pagination="pagination"
:columns="columns"
:dataSource="dataSource"
:scroll="{ x: 'max-content' }"
>
<template #bodyCell="{ column ,record}">
<template v-if="column.key === 'action'">
<a-space>
<a @click="handleAdd('编辑账号',record)">编辑</a>
<a-divider type="vertical" />
<a>禁用</a>
<a-divider type="vertical" />
<a>删除</a>
</a-space>
</template>
</template>
</a-table>
<!-- 角色信息 -->
<a-modal
v-model:open="open"
:title="openTitle"
@ok="handleOkModal"
@cancel="handleCancelModal"
width="800px"
:maskClosable="false"
>
<AccountManage
:key="modalKey"
ref="formModel"
></AccountManage>
</a-modal>
</template>
<script setup>
import { ref, onMounted, reactive, nextTick } from 'vue';
import { message } from 'ant-design-vue'
import { callUser } from '@/apis/call.js'
import config from '@/utils/config.js'
import { getGUID } from '@/utils/tools'
import AccountManage from '@/views/form/accountmanage/AccountManage.vue';
const open = ref(false);
const openTitle = ref('');
const modalKey = ref(getGUID())
const formModel = ref(null);
const columns = [
{
title: '所属地区',
dataIndex: 'orgName',
width: 200,
key: 'orgName',
align: 'center'
},
{
title: '用户名称',
dataIndex: 'roleName',
width: 200,
key: 'roleName',
align: 'center'
},
{
title: '用户账号',
dataIndex: 'roleDescription',
width: 200,
key: 'roleDescription',
align: 'center'
},
{
title: '角色类型',
dataIndex: 'staffCount',
width: 200,
key: 'staffCount',
align: 'center'
},
{
title: '状态',
dataIndex: 'webCount',
width: 200,
key: 'webCount',
align: 'center'
},
{
title: '最近登录IP',
dataIndex: 'appletCount',
width: 200,
key: 'appletCount',
align: 'center'
},
{
title: '最近登录时间',
dataIndex: 'appletCount',
width: 200,
key: 'appletCount',
align: 'center'
},
{
title: '创建时间',
dataIndex: 'appletCount',
width: 200,
key: 'appletCount',
align: 'center'
},
{
title: '登录日志',
dataIndex: 'appletCount',
width: 200,
key: 'appletCount',
align: 'center'
},
{
title: '操作',
key: 'action',
width: 200,
align: 'center',
fixed: 'right',
}
];
const queryform = ref({
account: '',
accountName: '',
pageNum: config.pageParam.pageNum,
pageSize: config.pageParam.pageSize
})
//
const dataSource = ref([])
let pagination = reactive({
total: dataSource.value.length,
current: config.pageParam.pageNum,
pageSize: config.pageParam.pageSize,
showSizeChanger: true,
pageSizeOptions: config.pageParam.pageSizeOptions,
showQuickJumper: true
})
onMounted(() => {
getData();
})
const search = () => {
getData()
}
const reset = () => {
queryform.value = {
account: '',
accountName: '',
pageNum: config.pageParam.pageNum,
pageSize: config.pageParam.pageSize
}
getData()
}
const getData = async () => {
callUser("/staff/pageQueryStaffs", queryform.value).then((res) => {
if (res.code != 200) {
message.error(res.message)
dataSource.value = []
return
}
dataSource.value = res.data.records
});
}
const handleAdd = async (title, record) => {
modalKey.value = getGUID();
openTitle.value = title;
open.value = true;
nextTick(() => {
if (formModel.value) {
const params = record == null ? {} : {
roleName: record['roleName'],
roleDescription: record['roleDescription'],
roleId: record['roleId'],
orgId: record['orgId']
}
formModel.value.openForm(params);
} else {
console.log('formModel is not ready yet');
}
});
}
const handleOkModal = () => {
formModel.value.formSave(bres => {
open.value = false;
if (bres.code == 200) {
getData()
}
});
}
const handleCancelModal = () => {
formModel.value.resetAll(bres => {
if (bres) open.value = false;
});
}
</script>

View File

@ -11,10 +11,10 @@
:sm="24" :sm="24"
:xs="24" :xs="24"
> >
<a-form-item label="区域名称"> <a-form-item label="角色名称">
<a-input <a-input
v-model:value.trim="queryform.roleName" v-model:value.trim="queryform.roleName"
placeholder="请输入区域名称" placeholder="请输入角色名称"
allow-clear allow-clear
></a-input> ></a-input>
</a-form-item> </a-form-item>
@ -36,7 +36,7 @@
style="background-color: #5cc750" style="background-color: #5cc750"
@click="search" @click="search"
>查询</a-button> >查询</a-button>
<!-- <a-button>重置</a-button> --> <a-button @click="reset">重置</a-button>
</a-space> </a-space>
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -70,7 +70,15 @@
<a-divider type="vertical" /> <a-divider type="vertical" />
<a @click="handleAdd('编辑角色',record)">编辑</a> <a @click="handleAdd('编辑角色',record)">编辑</a>
<a-divider type="vertical" /> <a-divider type="vertical" />
<a>删除</a> <a-popconfirm
title="请确认您是否要删除该角色"
ok-text="确定"
cancel-text="取消"
placement="top"
@confirm="handleDel(record)"
>
<a href="#">删除</a>
</a-popconfirm>
</a-space> </a-space>
</template> </template>
</template> </template>
@ -84,7 +92,10 @@
width="800px" width="800px"
:maskClosable="false" :maskClosable="false"
> >
<RoleManage ref="formModel"></RoleManage> <RoleManage
:key="modalKey"
ref="formModel"
></RoleManage>
</a-modal> </a-modal>
</template> </template>
<script setup> <script setup>
@ -93,8 +104,10 @@ import { message } from 'ant-design-vue'
import { callUser } from '@/apis/call.js' import { callUser } from '@/apis/call.js'
import config from '@/utils/config.js' import config from '@/utils/config.js'
import RoleManage from '@/views/form/rolemanage/RoleManage.vue'; import RoleManage from '@/views/form/rolemanage/RoleManage.vue';
import { getGUID } from '@/utils/tools'
const open = ref(false); const open = ref(false);
const openTitle = ref(''); const openTitle = ref('');
const modalKey = ref(getGUID())
const formModel = ref(null); const formModel = ref(null);
const columns = [ const columns = [
@ -174,6 +187,15 @@ const search = () => {
getData() getData()
} }
const reset = () => {
queryform.value = {
roleName: '',
pageNum: config.pageParam.pageNum,
pageSize: config.pageParam.pageSize
}
getData()
}
const getData = async () => { const getData = async () => {
callUser("/roles/pageQueryRoles", queryform.value).then((res) => { callUser("/roles/pageQueryRoles", queryform.value).then((res) => {
if (res.code != 200) { if (res.code != 200) {
@ -186,6 +208,7 @@ const getData = async () => {
} }
const handleAdd = async (title, record) => { const handleAdd = async (title, record) => {
modalKey.value = getGUID();
openTitle.value = title; openTitle.value = title;
open.value = true; open.value = true;
nextTick(() => { nextTick(() => {
@ -193,7 +216,8 @@ const handleAdd = async (title, record) => {
const params = record == null ? {} : { const params = record == null ? {} : {
roleName: record['roleName'], roleName: record['roleName'],
roleDescription: record['roleDescription'], roleDescription: record['roleDescription'],
roleId: record['roleId'] roleId: record['roleId'],
orgId: record['orgId']
} }
formModel.value.openForm(params); formModel.value.openForm(params);
} else { } else {
@ -202,16 +226,26 @@ const handleAdd = async (title, record) => {
}); });
} }
const handleDel = async (record) => {
callUser("/roles/rolePermissionsDel/" + record['roleId'], {}, "get").then((res) => {
if (res.code != 200) {
message.error(res.message)
dataSource.value = []
return
}
message.success(res.message)
getData();
});
}
const handleOkModal = () => { const handleOkModal = () => {
formModel.value.formSave(bres => { formModel.value.formSave(bres => {
open.value = false; open.value = false;
if (bres) { if (bres.code == 200) {
getData() getData()
} }
}); });
} }
const handleCancelModal = () => { const handleCancelModal = () => {
formModel.value.resetAll(bres => { formModel.value.resetAll(bres => {
if (bres) open.value = false; if (bres) open.value = false;

View File

@ -0,0 +1,259 @@
<template>
<a-spin
:spinning="spinning"
:tip="tipContent"
>
<a-form
:model="form"
ref="formRef"
label-align="left"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
>
<a-row>
<a-col :span="24">
<a-form-item
label="角色名称"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 12 }"
name="roleName"
required
:rules="[{ required: true, message: '请输角色名称' }]"
>
<a-input
v-model:value="form.roleName"
placeholder="请输角色名称"
/>
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :span="24">
<a-form-item
label="角色描述"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 12 }"
name="roleDescription"
>
<a-input
v-model:value="form.roleDescription"
placeholder="请输入角色描述"
/>
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :span="24">
<a-form-item
label="菜单权限配置"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 21 }"
name="roleDescription"
>
<a-tabs v-model:activeKey="activeKey">
<a-tab-pane
key="1"
tab="运营后台"
>
<div style="border: solid 1px #ddd;margin-top: -15px;">
<a-tree
v-if="treeDataByWeb.length"
defaultExpandAll
v-model:checkedKeys="checkedKeysByWeb"
@check="checkNodeByWeb"
v-model:tree-data="treeDataByWeb"
checkable
>
<template #title="{ description }">
{{ description }}
</template>
</a-tree>
</div>
</a-tab-pane>
<a-tab-pane
key="2"
tab="运维小程序"
force-render
>
<div style="border: solid 1px #ddd;margin-top: -15px;">
<a-tree
v-if="treeDataByApplet.length"
v-model:checkedKeys="checkedKeysByApplet"
@check="checkNodeByApplet"
:tree-data="treeDataByApplet"
defaultExpandAll
checkable
>
<template #title="{ description }">
{{ description }}
</template>
</a-tree>
</div>
</a-tab-pane>
</a-tabs>
</a-form-item>
</a-col>
</a-row>
</a-form>
</a-spin>
</template>
<script setup>
import { ref } from 'vue'
import { callUser } from '@/apis/call.js'
import { message } from 'ant-design-vue'
import _, { constant } from 'lodash'
const formRef = ref();
const form = ref({});
const activeKey = ref("1")
const checkedKeysByWeb = ref([])
const checkedKeysByApplet = ref([])
const treeDataByWeb = ref([])
const treeDataByApplet = ref([])
const treeDataList = ref([])
const roleIdRef = ref(null);
const isAdd = ref(true);
const spinning = ref(false);
const tipContent = ref("加载中...");
const openForm = (params = {}) => {
isAdd.value = true;
form.value = { ...params }
loadPermissionsList(params['roleId']);
};
const loadPermissionsList = (roleId = null) => {
callUser("/permissions/list", {}, "get").then((res) => {
if (res.code != 200) {
message.error(res.message)
treeDataByWeb.value = []
treeDataByApplet.value = []
return
}
const dataList = res.data.map((item) => {
return { ...item, key: item.permId }
})
treeDataList.value = dataList;
const newDataListByWeb = buildTreeWithChildren(dataList, 1)
const newDataList = buildTreeWithChildren(dataList, 2)
treeDataByWeb.value = [{ description: "全部", key: "all", children: [...newDataListByWeb] }]
treeDataByApplet.value = [{ description: "全部", key: "all", children: [...newDataList] }]
if (roleId) {
isAdd.value = false;
roleIdRef.value = roleId
callUser("/rolePermissions/getRolePermissionsByRoleId/" + roleId, {}, "get").then((res) => {
if (res.code == 200) {
const webKeys = res.data.filter(item => item['permType'] == "1").map(item => {
return item['permId']
});
const appletKeys = res.data.filter(item => item['permType'] == "2").map(item => {
return item['permId']
});
checkedKeysByWeb.value = webKeys;
checkedKeysByApplet.value = appletKeys;
}
})
} else {
callOperate("/ebikesysrcostset/createSnowflakeId", {}, "get").then(res => {
if (res.code == 200) {
roleIdRef.value = res.data;
}
})
}
});
}
const checkNodeByWeb = (checkKeys, nodes) => {
const checkNodes = nodes.checkedNodes.filter(item => item['key'] != "all")
const leafKeys = getLeafKeys(checkNodes);
checkedKeysByWeb.value = leafKeys
}
const checkNodeByApplet = (checkKeys, nodes) => {
const checkNodes = nodes.checkedNodes.filter(item => item['key'] != "all")
const leafKeys = getLeafKeys(checkNodes);
checkedKeysByApplet.value = leafKeys
}
const getLeafKeys = (nodes) => {
let leafKeys = [];
nodes.forEach(node => {
if (!node.children || node.children.length === 0) {
leafKeys.push(node.key);
} else {
getLeafKeys(node.children)
}
});
return leafKeys;
};
const buildTreeWithChildren = (data, where) => {
const map = new Map();
const roots = [];
data.forEach(item => {
map.set(item.permId, { ...item });
});
data.forEach(item => {
if (item['permType'] == where) {
const child = map.get(item.permId);
child.code = child.permCode;
if (item.parentId === null || item.parentId === undefined) {
roots.push(child);
} else {
const parent = map.get(item.parentId);
if (parent) {
parent.children = parent.children || [];
child.code = child.permCode.replace(parent.permCode + ".", '');
parent.children.push(child);
} else {
roots.push(child);
}
}
}
});
return roots;
}
const formSave = (callBack) => {
formRef.value.validate().then((res) => {
tipContent.value = "保存中..."
spinning.value = true;
let url = "rolePermissionsAdd";
if (!isAdd.value) {
url = "rolePermissionsUpdate"
}
const params = _.cloneDeep(form.value);
params['roleId'] = roleIdRef.value;
params['rolePermissions'] = []
checkedKeysByWeb.value.map(item => {
params['rolePermissions'].push({ permId: item })
})
checkedKeysByApplet.value.map(item => {
params['rolePermissions'].push({ permId: item })
})
callUser("/roles/" + url, params).then((res) => {
if (res.code == 200) {
if (callBack) {
res.data = params;
callBack(res);
}
} else {
message.error(res.message)
spinning.value = false;
}
})
});
};
const resetAll = (callBack) => {
formRef.value.resetFields();
if (callBack) {
callBack(true, form.value);
}
}
defineExpose({ openForm, formSave, resetAll });
</script>

View File

@ -1,4 +1,8 @@
<template> <template>
<a-spin
:spinning="spinning"
:tip="tipContent"
>
<a-form <a-form
:model="form" :model="form"
ref="formRef" ref="formRef"
@ -92,13 +96,14 @@
</a-col> </a-col>
</a-row> </a-row>
</a-form> </a-form>
</a-spin>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { callUser } from '@/apis/call.js' import { callUser } from '@/apis/call.js'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import _ from 'lodash' import _, { constant } from 'lodash'
const formRef = ref(); const formRef = ref();
const form = ref({}); const form = ref({});
@ -108,8 +113,13 @@ const checkedKeysByApplet = ref([])
const treeDataByWeb = ref([]) const treeDataByWeb = ref([])
const treeDataByApplet = ref([]) const treeDataByApplet = ref([])
const treeDataList = ref([]) const treeDataList = ref([])
const roleIdRef = ref(null);
const isAdd = ref(true);
const spinning = ref(false);
const tipContent = ref("加载中...");
const openForm = (params = {}) => { const openForm = (params = {}) => {
isAdd.value = true;
form.value = { ...params } form.value = { ...params }
loadPermissionsList(params['roleId']); loadPermissionsList(params['roleId']);
}; };
@ -131,28 +141,54 @@ const loadPermissionsList = (roleId = null) => {
treeDataByWeb.value = [{ description: "全部", key: "all", children: [...newDataListByWeb] }] treeDataByWeb.value = [{ description: "全部", key: "all", children: [...newDataListByWeb] }]
treeDataByApplet.value = [{ description: "全部", key: "all", children: [...newDataList] }] treeDataByApplet.value = [{ description: "全部", key: "all", children: [...newDataList] }]
if (roleId) { if (roleId) {
isAdd.value = false;
roleIdRef.value = roleId
callUser("/rolePermissions/getRolePermissionsByRoleId/" + roleId, {}, "get").then((res) => { callUser("/rolePermissions/getRolePermissionsByRoleId/" + roleId, {}, "get").then((res) => {
if (res.code == 200) { if (res.code == 200) {
const checkKeys = res.data.map(item => { const webKeys = res.data.filter(item => item['permType'] == "1").map(item => {
return item['permId']; return item['permId']
});
const appletKeys = res.data.filter(item => item['permType'] == "2").map(item => {
return item['permId']
});
checkedKeysByWeb.value = webKeys;
checkedKeysByApplet.value = appletKeys;
}
}) })
checkedKeysByWeb.value = checkedKeysByApplet.value = checkKeys; } else {
callOperate("/ebikesysrcostset/createSnowflakeId", {}, "get").then(res => {
if (res.code == 200) {
roleIdRef.value = res.data;
} }
}) })
} }
}); });
} }
const checkNodeByWeb = (checkNodes) => { const checkNodeByWeb = (checkKeys, nodes) => {
const newcheckNodes = checkNodes.filter(item => item != "all") const checkNodes = nodes.checkedNodes.filter(item => item['key'] != "all")
checkedKeysByWeb.value = newcheckNodes const leafKeys = getLeafKeys(checkNodes);
checkedKeysByWeb.value = leafKeys
} }
const checkNodeByApplet = (checkNodes) => { const checkNodeByApplet = (checkKeys, nodes) => {
const newcheckNodes = checkNodes.filter(item => item != "all") const checkNodes = nodes.checkedNodes.filter(item => item['key'] != "all")
checkedKeysByApplet.value = newcheckNodes const leafKeys = getLeafKeys(checkNodes);
checkedKeysByApplet.value = leafKeys
} }
const getLeafKeys = (nodes) => {
let leafKeys = [];
nodes.forEach(node => {
if (!node.children || node.children.length === 0) {
leafKeys.push(node.key);
} else {
getLeafKeys(node.children)
}
});
return leafKeys;
};
const buildTreeWithChildren = (data, where) => { const buildTreeWithChildren = (data, where) => {
const map = new Map(); const map = new Map();
const roots = []; const roots = [];
@ -182,7 +218,32 @@ const buildTreeWithChildren = (data, where) => {
const formSave = (callBack) => { const formSave = (callBack) => {
formRef.value.validate().then((res) => { formRef.value.validate().then((res) => {
tipContent.value = "保存中..."
spinning.value = true;
let url = "rolePermissionsAdd";
if (!isAdd.value) {
url = "rolePermissionsUpdate"
}
const params = _.cloneDeep(form.value);
params['roleId'] = roleIdRef.value;
params['rolePermissions'] = []
checkedKeysByWeb.value.map(item => {
params['rolePermissions'].push({ permId: item })
})
checkedKeysByApplet.value.map(item => {
params['rolePermissions'].push({ permId: item })
})
callUser("/roles/" + url, params).then((res) => {
if (res.code == 200) {
if (callBack) {
res.data = params;
callBack(res);
}
} else {
message.error(res.message)
spinning.value = false;
}
})
}); });
}; };