Commit 3097f94b by zhangxingmin

角色管理、菜单管理

parent d44aa23a
import request from '@/utils/request'
// 查询菜单列表
export function listMenu(query) {
export function listMenu(data) {
return request({
url: '/system/menu/list',
method: 'get',
params: query
url: '/user/api/sysMenu/page',
method: 'post',
data: data
})
}
// 查询菜单详细
export function getMenu(menuId) {
return request({
url: '/system/menu/' + menuId,
url: '/user/api/sysMenu/detail?menuBizId=' + menuId,
method: 'get'
})
}
......@@ -36,7 +36,7 @@ export function roleMenuTreeselect(roleId) {
// 新增菜单
export function addMenu(data) {
return request({
url: '/system/menu',
url: '/user/api/sysMenu/add',
method: 'post',
data: data
})
......@@ -45,7 +45,7 @@ export function addMenu(data) {
// 修改菜单
export function updateMenu(data) {
return request({
url: '/system/menu',
url: '/user/api/sysMenu/edit',
method: 'put',
data: data
})
......@@ -57,4 +57,12 @@ export function delMenu(menuId) {
url: '/system/menu/' + menuId,
method: 'delete'
})
}
\ No newline at end of file
}
//作用域切换搜索
export function searchScopeList(data) {
return request({
url: '/user/api/sysUser/scope/page',
method: 'post',
data: data
})
}
......@@ -120,7 +120,6 @@ export function deptTreeSelect(roleId) {
//作用域切换搜索
export function searchScopeList(data) {
debugger
return request({
url: '/user/api/sysUser/scope/page',
method: 'post',
......@@ -129,7 +128,6 @@ export function searchScopeList(data) {
}
// 修改项目状态
export function changeProjectStatus(data) {
debugger
return request({
url: '/user/api/sysProject/edit/status',
method: 'patch',
......
......@@ -113,7 +113,6 @@ export function addImportProjectMenuList(data) {
//分配角色-左侧待选列表
export function listLeftRole(data) {
debugger
return request({
url: '/user/api/relUserRole/candidate/project/userRolePage',
method: 'post',
......
import request from '@/utils/request'
// 查询角色列表
export function listRole(query) {
export function listRole(data) {
return request({
url: '/system/role/list',
method: 'get',
params: query
})
}
// 查询角色详细
export function getRole(roleId) {
return request({
url: '/system/role/' + roleId,
method: 'get'
url: '/user/api/sysRole/page',
method: 'post',
data: data
})
}
// 新增角色
export function addRole(data) {
return request({
url: '/system/role',
url: '/user/api/sysRole/add',
method: 'post',
data: data
})
}
// 修改角色
export function updateRole(data) {
return request({
url: '/system/role',
method: 'put',
data: data
})
}
// 角色数据权限
export function dataScope(data) {
return request({
url: '/system/role/dataScope',
method: 'put',
data: data
})
}
// 角色状态修改
export function changeRoleStatus(roleId, status) {
const data = {
roleId,
status
}
export function roleUpdate(data) {
return request({
url: '/system/role/changeStatus',
url: '/user/api/sysRole/edit',
method: 'put',
data: data
})
......@@ -65,55 +35,27 @@ export function delRole(roleId) {
})
}
// 查询角色已授权用户列表
export function allocatedUserList(query) {
// 编辑角色状态
export function roleStatusChange(roleBizId, status) {
return request({
url: '/system/role/authUser/allocatedList',
method: 'get',
params: query
url: `/user/api/sysRole/edit/status?roleBizId=${roleBizId}&status=${status}`,
method: 'patch'
})
}
// 查询角色未授权用户列表
export function unallocatedUserList(query) {
// 查询角色详情
export function getRoleDetail(roleBizId) {
return request({
url: '/system/role/authUser/unallocatedList',
method: 'get',
params: query
url: `/user/api/sysRole/detail?roleBizId=${roleBizId}`,
method: 'get'
})
}
// 取消用户授权角色
export function authUserCancel(data) {
//作用域切换搜索
export function searchScopeList(data) {
return request({
url: '/system/role/authUser/cancel',
method: 'put',
url: '/user/api/sysUser/scope/page',
method: 'post',
data: data
})
}
// 批量取消用户授权角色
export function authUserCancelAll(data) {
return request({
url: '/system/role/authUser/cancelAll',
method: 'put',
params: data
})
}
// 授权用户选择
export function authUserSelectAll(data) {
return request({
url: '/system/role/authUser/selectAll',
method: 'put',
params: data
})
}
// 根据角色ID查询部门树结构
export function deptTreeSelect(roleId) {
return request({
url: '/system/role/deptTree/' + roleId,
method: 'get'
})
}
......@@ -149,7 +149,6 @@ export function addImportTenantMenuList(data) {
//分配角色-左侧待选列表
export function listLeftRole(data) {
debugger
return request({
url: '/user/api/relUserRole/candidate/tenant/userRolePage',
method: 'post',
......
......@@ -38,7 +38,6 @@ export function updateUser(data) {
// 用户状态修改
export function changeUserStatus(data) {
debugger
return request({
url: '/user/api/sysUser/edit/status',
method: 'patch',
......
......@@ -55,7 +55,6 @@ const isCurrentTenant = (tenant) => {
// 切换租户
const handleTenantChange = async (tenant) => {
if (!isCurrentTenant(tenant)) {
debugger
// 切换租户
await userStore.switchTenant(tenant)
......
......@@ -84,6 +84,12 @@ function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
route.meta.title = route.menuName;
route.meta.icon = route.icon;
route.meta.isCache = route.isCache === 1;
//确保单子菜单的父菜单也显示
if (route.menuType === 1) {
route.alwaysShow = true; // 强制显示父菜单
}
// 新增:添加标签页显示属性(关键修改)
route.tagsView = true
route.hidden = route.isVisible === 0
......
......@@ -15,6 +15,7 @@ const useUserStore = defineStore(
name: '',
nickName: '',
avatar: '',
isSuperAdmin: 0,
roles: [],
permissions: [],
tenants: [], // 新增租户列表
......@@ -72,6 +73,7 @@ const useUserStore = defineStore(
this.name = user.userName
this.nickName = user.nickName
this.avatar = avatar
this.isSuperAdmin = user.isSuperAdmin
/* 初始密码提示 */
if(res.data.isDefaultModifyPwd) {
......
......@@ -10,34 +10,16 @@
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="菜单状态" clearable style="width: 200px">
<el-option
v-for="dict in sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['system:menu:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="Sort"
......@@ -51,34 +33,51 @@
v-if="refreshTable"
v-loading="loading"
:data="menuList"
row-key="menuId"
row-key="menuBizId"
:default-expand-all="isExpandAll"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column prop="menuName" label="菜单名称" :show-overflow-tooltip="true" width="160"></el-table-column>
<el-table-column prop="icon" label="图标" align="center" width="100">
<template #default="scope">
<svg-icon :icon-class="scope.row.icon" />
</template>
</el-table-column>
<el-table-column prop="orderNum" label="排序" width="60"></el-table-column>
<el-table-column prop="perms" label="权限标识" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="status" label="状态" width="80">
<template #default="scope">
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" width="160" prop="createTime">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="210" class-name="small-padding fixed-width">
<el-table-column prop="menuName" label="菜单名称" width="140px"></el-table-column>
<el-table-column prop="icon" label="图标" align="center">
<template #default="scope">
<svg-icon :icon-class="scope.row.icon" />
</template>
</el-table-column>
<el-table-column prop="menuType" label="类型">
<template #default="scope">
<dict-tag :options="sys_menu_type" :value="scope.row.menuType" />
</template>
</el-table-column>
<el-table-column prop="path" label="路由地址"></el-table-column>
<el-table-column prop="component" label="组件路径"></el-table-column>
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="sys_status" :value="scope.row.status" />
</template>
<!-- <template #default="scope">-->
<!-- <el-switch-->
<!-- v-model="scope.row.status"-->
<!-- :active-value="1"-->
<!-- :inactive-value="0"-->
<!-- @change="(val) => handleStatusChange(scope.row, $event)"-->
<!-- ></el-switch>-->
<!-- </template>-->
</el-table-column>
<el-table-column prop="scope" label="作用域">
<template #default="scope">
<dict-tag :options="sys_scope" :value="scope.row.scope" />
</template>
</el-table-column>
<el-table-column prop="tenantName" label="所属租户名称" width="110px"></el-table-column>
<el-table-column prop="projectName" label="所属项目名称" width="110px"></el-table-column>
<el-table-column label="操作" align="center" width="150px">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:menu:edit']">修改</el-button>
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['system:menu:add']">新增</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:menu:remove']">删除</el-button>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1">修改</el-button>
<!-- <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['system:menu:add']">新增</el-button>-->
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1">删除</el-button>
</template>
</el-table-column>
</el-table>
......@@ -90,10 +89,10 @@
<el-col :span="24">
<el-form-item label="上级菜单">
<el-tree-select
v-model="form.parentId"
v-model="form.parentBizId"
:data="menuOptions"
:props="{ value: 'menuId', label: 'menuName', children: 'children' }"
value-key="menuId"
:props="{ value: 'menuBizId', label: 'menuName', children: 'children' }"
value-key="menuBizId"
placeholder="选择上级菜单"
check-strictly
/>
......@@ -101,14 +100,16 @@
</el-col>
<el-col :span="24">
<el-form-item label="菜单类型" prop="menuType">
<el-radio-group v-model="form.menuType">
<el-radio value="M">目录</el-radio>
<el-radio value="C">菜单</el-radio>
<el-radio value="F">按钮</el-radio>
</el-radio-group>
<el-radio-group v-model="form.menuType">
<el-radio
v-for="dict in sys_menu_type"
:key="Number(dict.value)"
:value="Number(dict.value)"
>{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'F'">
<el-col :span="12" v-if="form.menuType != 3">
<el-form-item label="菜单图标" prop="icon">
<el-popover
placement="bottom-start"
......@@ -142,7 +143,7 @@
<el-input v-model="form.menuName" placeholder="请输入菜单名称" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType == 'C'">
<el-col :span="12" v-if="form.menuType == 2">
<el-form-item prop="routeName">
<template #label>
<span>
......@@ -155,7 +156,7 @@
<el-input v-model="form.routeName" placeholder="请输入路由名称" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'F'">
<el-col :span="12" v-if="form.menuType != 3">
<el-form-item>
<template #label>
<span>
......@@ -164,13 +165,16 @@
</el-tooltip>是否外链
</span>
</template>
<el-radio-group v-model="form.isFrame">
<el-radio value="0"></el-radio>
<el-radio value="1"></el-radio>
</el-radio-group>
<el-radio-group v-model="form.isExternal">
<el-radio
v-for="dict in sys_no_yes"
:key="Number(dict.value)"
:value="Number(dict.value)"
>{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'F'">
<el-col :span="12" v-if="form.menuType != 3">
<el-form-item prop="path">
<template #label>
<span>
......@@ -183,7 +187,7 @@
<el-input v-model="form.path" placeholder="请输入路由地址" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType == 'C'">
<el-col :span="12" v-if="form.menuType == 2">
<el-form-item prop="component">
<template #label>
<span>
......@@ -196,9 +200,9 @@
<el-input v-model="form.component" placeholder="请输入组件路径" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'M'">
<el-col :span="12" v-if="form.menuType != 1">
<el-form-item>
<el-input v-model="form.perms" placeholder="请输入权限标识" maxlength="100" />
<el-input v-model="form.permission" placeholder="请输入权限标识" maxlength="100" />
<template #label>
<span>
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasPermi('system:user:list')`)" placement="top">
......@@ -209,7 +213,7 @@
</template>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType == 'C'">
<el-col :span="12" v-if="form.menuType == 2">
<el-form-item>
<el-input v-model="form.query" placeholder="请输入路由参数" maxlength="255" />
<template #label>
......@@ -222,7 +226,7 @@
</template>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType == 'C'">
<el-col :span="12" v-if="form.menuType == 2">
<el-form-item>
<template #label>
<span>
......@@ -232,13 +236,16 @@
是否缓存
</span>
</template>
<el-radio-group v-model="form.isCache">
<el-radio value="0">缓存</el-radio>
<el-radio value="1">不缓存</el-radio>
</el-radio-group>
<el-radio-group v-model="form.isCache">
<el-radio
v-for="dict in sys_no_yes"
:key="Number(dict.value)"
:value="Number(dict.value)"
>{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'F'">
<el-col :span="12" v-if="form.menuType != 3">
<el-form-item>
<template #label>
<span>
......@@ -248,11 +255,11 @@
显示状态
</span>
</template>
<el-radio-group v-model="form.visible">
<el-radio-group v-model="form.isVisible">
<el-radio
v-for="dict in sys_show_hide"
:key="dict.value"
:value="dict.value"
v-for="dict in sys_visible"
:key="Number(dict.value)"
:value="Number(dict.value)"
>{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
......@@ -269,13 +276,98 @@
</template>
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in sys_normal_disable"
:key="dict.value"
:value="dict.value"
v-for="dict in sys_status"
:key="Number(dict.value)"
:value="Number(dict.value)"
>{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="15">
<el-form-item prop="scope">
<template #label>
<span>
<el-tooltip content="作用域" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
作用域
</span>
</template>
<el-radio-group v-model="form.scope" @change="handleScopeChange">
<el-radio
v-for="dict in sys_scope"
:key="Number(dict.value)"
:value="Number(dict.value)"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
v-if="[2].includes(form.scope)"
label="所属租户"
prop="tenantBizId">
<template #label>
<span>
<el-tooltip content="所属租户" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
所属租户
</span>
</template>
<el-select
v-model="form.tenantBizId"
filterable
remote
reserve-keyword
placeholder="请输入关键词搜索租户"
:remote-method="searchTenants"
:loading="tenantLoading"
>
<el-option
v-for="item in tenantOptions"
:key="item.tenantBizId"
:label="item.tenantName"
:value="item.tenantBizId"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="[3].includes(form.scope)"
label="所属项目"
prop="projectBizId">
<template #label>
<span>
<el-tooltip content="所属项目" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
所属项目
</span>
</template>
<el-select
v-model="form.projectBizId"
filterable
remote
reserve-keyword
placeholder="请输入关键词搜索项目"
:remote-method="searchProjects"
:loading="projectLoading"
>
<el-option
v-for="item in projectOptions"
:key="item.projectBizId"
:label="item.projectName"
:value="item.projectBizId"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
......@@ -289,12 +381,14 @@
</template>
<script setup name="Menu">
import { addMenu, delMenu, getMenu, listMenu, updateMenu } from "@/api/system/menu"
import { addMenu, delMenu, getMenu, listMenu, updateMenu,searchScopeList } from "@/api/system/menu"
import useUserStore from '@/store/modules/user'
import SvgIcon from "@/components/SvgIcon"
import IconSelect from "@/components/IconSelect"
const { proxy } = getCurrentInstance()
const { sys_show_hide, sys_normal_disable } = proxy.useDict("sys_show_hide", "sys_normal_disable")
const { sys_menu_type,sys_scope,sys_status,sys_visible,sys_no_yes} = proxy.useDict("sys_menu_type","sys_scope","sys_status","sys_visible","sys_no_yes")
const userStore = useUserStore()
const menuList = ref([])
const open = ref(false)
......@@ -309,13 +403,18 @@ const iconSelectRef = ref(null)
const data = reactive({
form: {},
queryParams: {
menuName: undefined,
visible: undefined
pageNo: 1,
pageSize: 999999,
loginTenantBizId: userStore.currentTenant.apiLoginTenantInfoResponse.tenantBizId,
menuName: undefined
},
rules: {
menuName: [{ required: true, message: "菜单名称不能为空", trigger: "blur" }],
orderNum: [{ required: true, message: "菜单顺序不能为空", trigger: "blur" }],
path: [{ required: true, message: "路由地址不能为空", trigger: "blur" }]
path: [{ required: true, message: "路由地址不能为空", trigger: "blur" }],
menuType: [{ required: true, message: "菜单类型不能为空", trigger: "blur" }],
scope: [{ required: true, message: "作用域不能为空", trigger: "blur" }],
},
})
......@@ -325,7 +424,7 @@ const { queryParams, form, rules } = toRefs(data)
function getList() {
loading.value = true
listMenu(queryParams.value).then(response => {
menuList.value = proxy.handleTree(response.data, "menuId")
menuList.value = proxy.handleTree(response.data.records, "menuBizId")
loading.value = false
})
}
......@@ -333,9 +432,9 @@ function getList() {
/** 查询菜单下拉树结构 */
function getTreeselect() {
menuOptions.value = []
listMenu().then(response => {
const menu = { menuId: 0, menuName: "主类目", children: [] }
menu.children = proxy.handleTree(response.data, "menuId")
listMenu(queryParams.value).then(response => {
const menu = { menuBizId: "0", menuName: "主类目", children: [] }
menu.children = proxy.handleTree(response.data.records, "menuBizId","parentBizId")
menuOptions.value.push(menu)
})
}
......@@ -348,18 +447,7 @@ function cancel() {
/** 表单重置 */
function reset() {
form.value = {
menuId: undefined,
parentId: 0,
menuName: undefined,
icon: undefined,
menuType: "M",
orderNum: undefined,
isFrame: "1",
isCache: "0",
visible: "0",
status: "0"
}
form.value = {}
proxy.resetForm("menuRef")
}
......@@ -385,14 +473,9 @@ function resetQuery() {
}
/** 新增按钮操作 */
function handleAdd(row) {
function handleAdd() {
reset()
getTreeselect()
if (row != null && row.menuId) {
form.value.parentId = row.menuId
} else {
form.value.parentId = 0
}
open.value = true
title.value = "添加菜单"
}
......@@ -410,8 +493,22 @@ function toggleExpandAll() {
async function handleUpdate(row) {
reset()
await getTreeselect()
getMenu(row.menuId).then(response => {
getMenu(row.menuBizId).then(response => {
form.value = response.data
// 根据作用域类型预加载关联数据
if (response.data.scope === 2) {
tenantOptions.value.push({
tenantBizId: response.data.tenantBizId,
tenantName: response.data.tenantName
});
}else if (response.data.scope === 3){
projectOptions.value.push({
projectBizId: response.data.projectBizId,
projectName: response.data.projectName
});
}
open.value = true
title.value = "修改菜单"
})
......@@ -421,7 +518,7 @@ async function handleUpdate(row) {
function submitForm() {
proxy.$refs["menuRef"].validate(valid => {
if (valid) {
if (form.value.menuId != undefined) {
if (form.value.menuBizId) {
updateMenu(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
......@@ -447,6 +544,71 @@ function handleDelete(row) {
proxy.$modal.msgSuccess("删除成功")
}).catch(() => {})
}
getList()
//========作用域-切换逻辑开始=========
const tenantOptions = ref([])
const tenantLoading = ref(false)
const projectOptions = ref([])
const projectLoading = ref(false)
// 作用域变更处理
function handleScopeChange(val) {
console.log('作用域变更:', val);
// 清空不需要的字段值
if (val === 2) {
form.value.projectBizId = '';
// 自动加载租户列表(可选)
searchTenants('');
} else if (val === 3) {
form.value.tenantBizId = '';
// 自动加载项目列表(可选)
searchProjects('');
} else if (val === 1) {
//系统级
form.value.tenantBizId = '';
form.value.projectBizId = '';
}
}
// 搜索租户方法
function searchTenants(query) {
tenantLoading.value = true;
try {
const params = {
loginTenantBizId: userStore.currentTenant.apiLoginTenantInfoResponse.tenantBizId,
scope: 2,name: query, pageNo:1, pageSize: 10 };
searchScopeList(params).then(response => {
tenantOptions.value = response.data.records
})
} catch (error) {
console.error('租户搜索失败', error);
tenantOptions.value = [];
} finally {
tenantLoading.value = false;
}
}
// 搜索项目方法
function searchProjects(query) {
projectLoading.value = true;
try {
const params = {
loginTenantBizId: userStore.currentTenant.apiLoginTenantInfoResponse.tenantBizId,
scope: 3,name: query, pageNo:1, pageSize: 10 };
searchScopeList(params).then(response => {
projectOptions.value = response.data.records
})
} catch (error) {
console.error('项目搜索失败', error);
projectOptions.value = [];
} finally {
projectLoading.value = false;
}
}
//========作用域-切换逻辑结束=========
</script>
......@@ -68,11 +68,14 @@
<el-table-column label="状态" align="center">
<template #default="scope">
<el-switch
v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1"
v-model="scope.row.status"
:active-value="1"
:inactive-value="0"
@change="(val) => handleStatusChange(scope.row, $event)"
></el-switch>
<dict-tag :options="sys_status" :value="scope.row.status"
v-if="userStore.isSuperAdmin === 0 && scope.row.scope === 1"/>
</template>
</el-table-column>
<el-table-column label="项目开始时间" align="center" prop="startTime">
......@@ -87,10 +90,13 @@
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200px">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handlePermission(scope.row)" >分配权限</el-button>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" >修改</el-button>
<el-button link type="primary" icon="Edit" @click="handlePermission(scope.row)"
v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1">分配权限</el-button>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1">修改</el-button>
<!-- <el-button link type="primary" icon="View" @click="handleUpdate(scope.row)" >详情</el-button>-->
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" >删除</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1">删除</el-button>
</template>
</el-table-column>
</el-table>
......
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" v-show="showSearch" :inline="true">
<el-form-item label="用户名称" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户名称"
clearable
style="width: 240px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input
v-model="queryParams.phonenumber"
placeholder="请输入手机号码"
clearable
style="width: 240px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="openSelectUser"
v-hasPermi="['system:role:add']"
>添加用户</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="CircleClose"
:disabled="multiple"
@click="cancelAuthUserAll"
v-hasPermi="['system:role:remove']"
>批量取消授权</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Close"
@click="handleClose"
>关闭</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="CircleClose" @click="cancelAuthUser(scope.row)" v-hasPermi="['system:role:remove']">取消授权</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<select-user ref="selectRef" :roleId="queryParams.roleId" @ok="handleQuery" />
</div>
</template>
<script setup name="AuthUser">
import selectUser from "./selectUser"
import { allocatedUserList, authUserCancel, authUserCancelAll } from "@/api/system/role"
const route = useRoute()
const { proxy } = getCurrentInstance()
const { sys_normal_disable } = proxy.useDict("sys_normal_disable")
const userList = ref([])
const loading = ref(true)
const showSearch = ref(true)
const multiple = ref(true)
const total = ref(0)
const userIds = ref([])
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
roleId: route.params.roleId,
userName: undefined,
phonenumber: undefined,
})
/** 查询授权用户列表 */
function getList() {
loading.value = true
allocatedUserList(queryParams).then(response => {
userList.value = response.rows
total.value = response.total
loading.value = false
})
}
/** 返回按钮 */
function handleClose() {
const obj = { path: "/system/role" }
proxy.$tab.closeOpenPage(obj)
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef")
handleQuery()
}
/** 多选框选中数据 */
function handleSelectionChange(selection) {
userIds.value = selection.map(item => item.userId)
multiple.value = !selection.length
}
/** 打开授权用户表弹窗 */
function openSelectUser() {
proxy.$refs["selectRef"].show()
}
/** 取消授权按钮操作 */
function cancelAuthUser(row) {
proxy.$modal.confirm('确认要取消该用户"' + row.userName + '"角色吗?').then(function () {
return authUserCancel({ userId: row.userId, roleId: queryParams.roleId })
}).then(() => {
getList()
proxy.$modal.msgSuccess("取消授权成功")
}).catch(() => {})
}
/** 批量取消授权按钮操作 */
function cancelAuthUserAll(row) {
const roleId = queryParams.roleId
const uIds = userIds.value.join(",")
proxy.$modal.confirm("是否取消选中用户授权数据项?").then(function () {
return authUserCancelAll({ roleId: roleId, userIds: uIds })
}).then(() => {
getList()
proxy.$modal.msgSuccess("取消授权成功")
}).catch(() => {})
}
getList()
</script>
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" v-show="showSearch" :inline="true" label-width="68px">
<el-form-item label="角色名称" prop="roleName">
<el-input
v-model="queryParams.roleName"
placeholder="请输入角色名称"
clearable
style="width: 240px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="权限字符" prop="roleKey">
<el-input
v-model="queryParams.roleKey"
placeholder="请输入权限字符"
clearable
style="width: 240px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="角色状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker
v-model="dateRange"
value-format="YYYY-MM-DD"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['system:role:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['system:role:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['system:role:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['system:role:export']"
>导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 表格数据 -->
<el-table v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="角色编号" prop="roleId" width="120" />
<el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" />
<el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" width="150" />
<el-table-column label="显示顺序" prop="roleSort" width="100" />
<el-table-column label="状态" align="center" width="100">
<template #default="scope">
<el-switch
v-model="scope.row.status"
active-value="0"
inactive-value="1"
@change="handleStatusChange(scope.row)"
></el-switch>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top" v-if="scope.row.roleId !== 1">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:role:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top" v-if="scope.row.roleId !== 1">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']"></el-button>
</el-tooltip>
<el-tooltip content="数据权限" placement="top" v-if="scope.row.roleId !== 1">
<el-button link type="primary" icon="CircleCheck" @click="handleDataScope(scope.row)" v-hasPermi="['system:role:edit']"></el-button>
</el-tooltip>
<el-tooltip content="分配用户" placement="top" v-if="scope.row.roleId !== 1">
<el-button link type="primary" icon="User" @click="handleAuthUser(scope.row)" v-hasPermi="['system:role:edit']"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
<div class="app-container">
<el-form
:model="queryParams"
ref="queryRef"
v-show="showSearch"
:inline="true"
label-width="68px"
>
<el-form-item label="角色名称" prop="roleName">
<el-input
v-model="queryParams.roleName"
placeholder="请输入角色名称"
clearable
style="width: 240px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="角色状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in sys_status"
:key="dict.value"
:label="dict.label"
:value="Number(dict.value)"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
</el-form-item>
</el-form>
<!-- 表格数据 -->
<el-table v-loading="loading" :data="roleList">
<el-table-column label="角色名称" prop="roleName" />
<el-table-column label="角色类型" prop="roleType" >
<template #default="scope">
<dict-tag :options="sys_role_type" :value="scope.row.roleType" />
</template>
</el-table-column>
<el-table-column label="作用域" prop="scope" >
<template #default="scope">
<dict-tag :options="sys_scope" :value="scope.row.scope" />
</template>
</el-table-column>
<el-table-column
label="所属租户名称"
prop="tenantName"
:show-overflow-tooltip="true"
width="150"
/>
<!-- 添加或修改角色配置对话框 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
<el-form ref="roleRef" :model="form" :rules="rules" label-width="100px">
<el-table-column
label="所属项目名称"
prop="projectName"
:show-overflow-tooltip="true"
width="150"
/>
<el-table-column label="状态" align="center" width="100">
<template #default="scope">
<el-switch
v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1"
v-model="scope.row.status"
:active-value="1"
:inactive-value="0"
@click="
evt => {
evt.preventDefault()
handleStatusChange(scope.row)
}
"
></el-switch>
<dict-tag :options="sys_status" :value="scope.row.status"
v-if="userStore.isSuperAdmin === 0 && scope.row.scope === 1"/>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1">修改</el-button>
<el-button link type="primary" icon="Delete"
v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改角色配置对话框 -->
<el-dialog :title="title" v-model="open" width="800px" append-to-body>
<el-form ref="roleRef" :model="form" :rules="rules" label-width="100px">
<el-row>
<el-col :span="12">
<el-form-item label="角色名称" prop="roleName">
<el-input v-model="form.roleName" placeholder="请输入角色名称" />
</el-form-item>
<el-form-item prop="roleKey">
<template #label>
<span>
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasRole('admin')`)" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
权限字符
</span>
</template>
<el-input v-model="form.roleKey" placeholder="请输入权限字符" />
<el-input v-model="form.roleName" placeholder="请输入角色名称" maxlength="30" />
</el-form-item>
<el-form-item label="角色顺序" prop="roleSort">
<el-input-number v-model="form.roleSort" controls-position="right" :min="0" />
</el-col>
<el-col :span="12">
<el-form-item label="角色类型" prop="roleType">
<el-select v-model="form.roleType" placeholder="请选择角色类型">
<el-option
v-for="dict in sys_role_type"
:key="dict.value"
:label="dict.label"
:value="Number(dict.value)"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in sys_normal_disable"
:key="dict.value"
:value="dict.value"
>{{ dict.label }}</el-radio>
</el-radio-group>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<!-- 作用域选择 -->
<el-form-item label="作用域" prop="scope">
<el-radio-group v-model="form.scope" @change="handleScopeChange">
<el-radio
v-for="dict in sys_scope"
:key="Number(dict.value)"
:value="Number(dict.value)"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="菜单权限">
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
<el-tree
class="tree-border"
:data="menuOptions"
show-checkbox
ref="menuRef"
node-key="id"
:check-strictly="!form.menuCheckStrictly"
empty-text="加载中,请稍候"
:props="{ label: 'label', children: 'children' }"
></el-tree>
</el-col>
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in sys_status"
:key="dict.value"
:value="Number(dict.value)"
>{{ dict.label }}</el-radio
>
</el-radio-group>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<!-- 所属租户 - 可搜索下拉框 -->
<el-form-item
v-if="[2].includes(form.scope)"
label="所属租户"
prop="tenantBizId"
>
<el-select
v-model="form.tenantBizId"
filterable
remote
reserve-keyword
placeholder="请输入关键词搜索租户"
:remote-method="searchTenants"
:loading="tenantLoading"
>
<el-option
v-for="item in tenantOptions"
:key="item.tenantBizId"
:label="item.tenantName"
:value="item.tenantBizId"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
<!-- 分配角色数据权限对话框 -->
<el-dialog :title="title" v-model="openDataScope" width="500px" append-to-body>
<el-form :model="form" label-width="80px">
<el-form-item label="角色名称">
<el-input v-model="form.roleName" :disabled="true" />
</el-form-item>
<el-form-item label="权限字符">
<el-input v-model="form.roleKey" :disabled="true" />
</el-form-item>
<el-form-item label="权限范围">
<el-select v-model="form.dataScope" @change="dataScopeSelectChange">
<el-option
v-for="item in dataScopeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
<!-- 所属项目 - 可搜索下拉框 -->
<el-form-item
v-if="[3].includes(form.scope)"
label="所属项目"
prop="projectBizId"
>
<el-select
v-model="form.projectBizId"
filterable
remote
reserve-keyword
placeholder="请输入关键词搜索项目"
:remote-method="searchProjects"
:loading="projectLoading"
>
<el-option
v-for="item in projectOptions"
:key="item.projectBizId"
:label="item.projectName"
:value="item.projectBizId"
/>
</el-select>
</el-form-item>
<el-form-item label="数据权限" v-show="form.dataScope == 2">
<el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
<el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
<el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
<el-tree
class="tree-border"
:data="deptOptions"
show-checkbox
default-expand-all
ref="deptRef"
node-key="id"
:check-strictly="!form.deptCheckStrictly"
empty-text="加载中,请稍候"
:props="{ label: 'label', children: 'children' }"
></el-tree>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="备注">
<el-input
v-model="form.description"
type="textarea"
placeholder="请输入内容"
></el-input>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitDataScope">确 定</el-button>
<el-button @click="cancelDataScope">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="Role">
import { addRole, changeRoleStatus, dataScope, delRole, getRole, listRole, updateRole, deptTreeSelect } from "@/api/system/role"
import { roleMenuTreeselect, treeselect as menuTreeselect } from "@/api/system/menu"
import {
addRole,
roleStatusChange,
delRole,
listRole,
getRoleDetail,
roleUpdate,
searchScopeList
} from '@/api/system/role'
import useUserStore from '@/store/modules/user'
const userStore = useUserStore()
const router = useRouter()
const { proxy } = getCurrentInstance()
const { sys_normal_disable } = proxy.useDict("sys_normal_disable")
const { sys_role_type, sys_scope, sys_status } = proxy.useDict(
'sys_role_type',
'sys_scope',
'sys_status'
)
const roleList = ref([])
const open = ref(false)
const loading = ref(true)
const showSearch = ref(true)
const ids = ref([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const title = ref("")
const title = ref('')
const dateRange = ref([])
const menuOptions = ref([])
const menuExpand = ref(false)
const menuNodeAll = ref(false)
const deptExpand = ref(true)
const deptNodeAll = ref(false)
const deptOptions = ref([])
const openDataScope = ref(false)
const menuRef = ref(null)
const deptRef = ref(null)
/** 数据范围选项*/
const dataScopeOptions = ref([
{ value: "1", label: "全部数据权限" },
{ value: "2", label: "自定数据权限" },
{ value: "3", label: "本部门数据权限" },
{ value: "4", label: "本部门及以下数据权限" },
{ value: "5", label: "仅本人数据权限" }
])
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
loginTenantBizId: userStore.currentTenant.apiLoginTenantInfoResponse.tenantBizId,
roleName: undefined,
roleKey: undefined,
status: undefined
},
rules: {
roleName: [{ required: true, message: "角色名称不能为空", trigger: "blur" }],
roleKey: [{ required: true, message: "权限字符不能为空", trigger: "blur" }],
roleSort: [{ required: true, message: "角色顺序不能为空", trigger: "blur" }]
},
roleName: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }],
roleType: [{ required: true, message: '角色类型不能为空', trigger: 'blur' }],
scope: [{ required: true, message: '作用域不能为空', trigger: 'blur' }],
status: [{ required: true, message: '状态不能为空', trigger: 'blur' }],
projectBizId: [{ required: true, message: '项目不能为空', trigger: 'blur' }],
tenantBizId: [{ required: true, message: '租户不能为空', trigger: 'blur' }]
}
})
const { queryParams, form, rules } = toRefs(data)
......@@ -299,10 +283,14 @@ const { queryParams, form, rules } = toRefs(data)
/** 查询角色列表 */
function getList() {
loading.value = true
listRole(proxy.addDateRange(queryParams.value, dateRange.value)).then(response => {
roleList.value = response.rows
total.value = response.total
loading.value = false
listRole(queryParams.value).then(response => {
if (response.code === 200) {
roleList.value = response.data.records
total.value = response.data.total
loading.value = false
} else {
proxy.$modal.msgError(response.msg)
}
})
}
......@@ -315,212 +303,108 @@ function handleQuery() {
/** 重置按钮操作 */
function resetQuery() {
dateRange.value = []
proxy.resetForm("queryRef")
proxy.resetForm('queryRef')
handleQuery()
}
/** 删除按钮操作 */
function handleDelete(row) {
const roleIds = row.roleId || ids.value
proxy.$modal.confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?').then(function () {
return delRole(roleIds)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => {})
}
/** 导出按钮操作 */
function handleExport() {
proxy.download("system/role/export", {
...queryParams.value,
}, `role_${new Date().getTime()}.xlsx`)
}
/** 多选框选中数据 */
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.roleId)
single.value = selection.length != 1
multiple.value = !selection.length
proxy.$modal
.confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?')
.then(function () {
return delRole(roleIds)
})
.then(() => {
getList()
proxy.$modal.msgSuccess('删除成功')
})
.catch(() => {})
}
/** 角色状态修改 */
function handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用"
proxy.$modal.confirm('确认要"' + text + '""' + row.roleName + '"角色吗?').then(function () {
return changeRoleStatus(row.roleId, row.status)
}).then(() => {
proxy.$modal.msgSuccess(text + "成功")
}).catch(function () {
row.status = row.status === "0" ? "1" : "0"
})
}
/** 更多操作 */
function handleCommand(command, row) {
switch (command) {
case "handleDataScope":
handleDataScope(row)
break
case "handleAuthUser":
handleAuthUser(row)
break
default:
break
}
}
/** 分配用户 */
function handleAuthUser(row) {
router.push("/system/role-auth/user/" + row.roleId)
}
/** 查询菜单树结构 */
function getMenuTreeselect() {
menuTreeselect().then(response => {
menuOptions.value = response.data
})
}
/** 所有部门节点数据 */
function getDeptAllCheckedKeys() {
// 目前被选中的部门节点
let checkedKeys = deptRef.value.getCheckedKeys()
// 半选中的部门节点
let halfCheckedKeys = deptRef.value.getHalfCheckedKeys()
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
return checkedKeys
console.log('row', row.status)
const newStatus = row.status === 0 ? 0 : 1 // 获取切换后的新状态
const text = newStatus === 0 ? '停用' : '启用' // 根据新状态显示文本
console.log('newStatus', newStatus)
proxy.$modal
.confirm(`确认要${text}"${row.roleName}"角色吗?`)
.then(function () {
return roleStatusChange(row.roleBizId, newStatus).then(() => {
proxy.$modal.msgSuccess(`${text}成功`)
// 请求成功后,更新状态
row.status = newStatus
getList()
})
})
.catch(() => {
// 操作取消时恢复原状态
row.status = row.status === 1 ? 0 : 1
// 用户取消操作,保持原状态不变
// 这里不需要做任何操作,因为switch会自动回滚
})
}
/** 重置新增的表单以及其他数据 */
function reset() {
if (menuRef.value != undefined) {
menuRef.value.setCheckedKeys([])
}
menuExpand.value = false
menuNodeAll.value = false
deptExpand.value = true
deptNodeAll.value = false
form.value = {
roleId: undefined,
roleName: undefined,
roleKey: undefined,
roleSort: 0,
status: "0",
menuIds: [],
deptIds: [],
menuCheckStrictly: true,
deptCheckStrictly: true,
remark: undefined
}
proxy.resetForm("roleRef")
form.value = {}
proxy.resetForm('roleRef')
}
/** 添加角色 */
function handleAdd() {
reset()
getMenuTreeselect()
form.value = {}
open.value = true
title.value = "添加角色"
title.value = '添加角色'
}
/** 修改角色 */
function handleUpdate(row) {
reset()
const roleId = row.roleId || ids.value
const roleMenu = getRoleMenuTreeselect(roleId)
getRole(roleId).then(response => {
form.value = response.data
form.value.roleSort = Number(form.value.roleSort)
open.value = true
nextTick(() => {
roleMenu.then((res) => {
let checkedKeys = res.checkedKeys
checkedKeys.forEach((v) => {
nextTick(() => {
menuRef.value.setChecked(v, true, false)
})
})
})
})
})
title.value = "修改角色"
}
/** 根据角色ID查询菜单树结构 */
function getRoleMenuTreeselect(roleId) {
return roleMenuTreeselect(roleId).then(response => {
menuOptions.value = response.menus
return response
})
}
/** 根据角色ID查询部门树结构 */
function getDeptTree(roleId) {
return deptTreeSelect(roleId).then(response => {
deptOptions.value = response.depts
return response
})
}
const roleBizId = row.roleBizId
getRoleDetail(roleBizId).then(response => {
if (response.code === 200) {
form.value = response.data
// 根据作用域类型预加载关联数据
if (response.data.scope === 2) {
tenantOptions.value.push({
tenantBizId: response.data.tenantBizId,
tenantName: response.data.tenantName
});
}else if (response.data.scope === 3){
projectOptions.value.push({
projectBizId: response.data.projectBizId,
projectName: response.data.projectName
});
}
/** 树权限(展开/折叠)*/
function handleCheckedTreeExpand(value, type) {
if (type == "menu") {
let treeList = menuOptions.value
for (let i = 0; i < treeList.length; i++) {
menuRef.value.store.nodesMap[treeList[i].id].expanded = value
}
} else if (type == "dept") {
let treeList = deptOptions.value
for (let i = 0; i < treeList.length; i++) {
deptRef.value.store.nodesMap[treeList[i].id].expanded = value
open.value = true
title.value = '修改角色'
} else {
proxy.$modal.msgError(response.msg)
}
}
}
/** 树权限(全选/全不选) */
function handleCheckedTreeNodeAll(value, type) {
if (type == "menu") {
menuRef.value.setCheckedNodes(value ? menuOptions.value : [])
} else if (type == "dept") {
deptRef.value.setCheckedNodes(value ? deptOptions.value : [])
}
}
/** 树权限(父子联动) */
function handleCheckedTreeConnect(value, type) {
if (type == "menu") {
form.value.menuCheckStrictly = value ? true : false
} else if (type == "dept") {
form.value.deptCheckStrictly = value ? true : false
}
}
/** 所有菜单节点数据 */
function getMenuAllCheckedKeys() {
// 目前被选中的菜单节点
let checkedKeys = menuRef.value.getCheckedKeys()
// 半选中的菜单节点
let halfCheckedKeys = menuRef.value.getHalfCheckedKeys()
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
return checkedKeys
})
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["roleRef"].validate(valid => {
proxy.$refs['roleRef'].validate(valid => {
if (valid) {
if (form.value.roleId != undefined) {
form.value.menuIds = getMenuAllCheckedKeys()
updateRole(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
if (form.value.roleBizId) {
roleUpdate(form.value).then(response => {
if (response.code === 200) {
proxy.$modal.msgSuccess('修改成功')
open.value = false
getList()
} else {
proxy.$modal.msgError(response.msg)
}
})
} else {
form.value.menuIds = getMenuAllCheckedKeys()
addRole(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
proxy.$modal.msgSuccess('新增成功')
open.value = false
getList()
})
......@@ -528,57 +412,75 @@ function submitForm() {
}
})
}
/** 取消按钮 */
function cancel() {
open.value = false
reset()
}
getList()
/** 选择角色权限范围触发 */
function dataScopeSelectChange(value) {
if (value !== "2") {
deptRef.value.setCheckedKeys([])
//========作用域-切换逻辑开始=========
const tenantOptions = ref([])
const tenantLoading = ref(false)
const projectOptions = ref([])
const projectLoading = ref(false)
// 作用域变更处理
function handleScopeChange(val) {
console.log('作用域变更:', val);
// 清空不需要的字段值
if (val === 2) {
form.value.projectBizId = '';
// 自动加载租户列表(可选)
searchTenants('');
} else if (val === 3) {
form.value.tenantBizId = '';
// 自动加载项目列表(可选)
searchProjects('');
} else if (val === 1) {
//系统级
form.value.tenantBizId = '';
form.value.projectBizId = '';
}
}
/** 分配数据权限操作 */
function handleDataScope(row) {
reset()
const deptTreeSelect = getDeptTree(row.roleId)
getRole(row.roleId).then(response => {
form.value = response.data
openDataScope.value = true
nextTick(() => {
deptTreeSelect.then(res => {
nextTick(() => {
if (deptRef.value) {
deptRef.value.setCheckedKeys(res.checkedKeys)
}
})
})
})
})
title.value = "分配数据权限"
}
// 搜索租户方法
function searchTenants(query) {
tenantLoading.value = true;
try {
const params = {
loginTenantBizId: userStore.currentTenant.apiLoginTenantInfoResponse.tenantBizId,
scope: 2,name: query, pageNo:1, pageSize: 10 };
/** 提交按钮(数据权限) */
function submitDataScope() {
if (form.value.roleId != undefined) {
form.value.deptIds = getDeptAllCheckedKeys()
dataScope(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
openDataScope.value = false
getList()
searchScopeList(params).then(response => {
tenantOptions.value = response.data.records
})
} catch (error) {
console.error('租户搜索失败', error);
tenantOptions.value = [];
} finally {
tenantLoading.value = false;
}
}
/** 取消按钮(数据权限)*/
function cancelDataScope() {
openDataScope.value = false
reset()
// 搜索项目方法
function searchProjects(query) {
projectLoading.value = true;
try {
const params = {
loginTenantBizId: userStore.currentTenant.apiLoginTenantInfoResponse.tenantBizId,
scope: 3,name: query, pageNo:1, pageSize: 10 };
searchScopeList(params).then(response => {
projectOptions.value = response.data.records
})
} catch (error) {
console.error('项目搜索失败', error);
projectOptions.value = [];
} finally {
projectLoading.value = false;
}
}
//========作用域-切换逻辑结束=========
getList()
</script>
<template>
<!-- 授权用户 -->
<el-dialog title="选择用户" v-model="visible" width="800px" top="5vh" append-to-body>
<el-form :model="queryParams" ref="queryRef" :inline="true">
<el-form-item label="用户名称" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户名称"
clearable
style="width: 180px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input
v-model="queryParams.phonenumber"
placeholder="请输入手机号码"
clearable
style="width: 180px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row>
<el-table @row-click="clickRow" ref="refTable" :data="userList" @selection-change="handleSelectionChange" height="260px">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</el-row>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleSelectUser">确 定</el-button>
<el-button @click="visible = false">取 消</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup name="SelectUser">
import { authUserSelectAll, unallocatedUserList } from "@/api/system/role"
const props = defineProps({
roleId: {
type: [Number, String]
}
})
const { proxy } = getCurrentInstance()
const { sys_normal_disable } = proxy.useDict("sys_normal_disable")
const userList = ref([])
const visible = ref(false)
const total = ref(0)
const userIds = ref([])
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
roleId: undefined,
userName: undefined,
phonenumber: undefined
})
// 显示弹框
function show() {
queryParams.roleId = props.roleId
getList()
visible.value = true
}
/**选择行 */
function clickRow(row) {
proxy.$refs["refTable"].toggleRowSelection(row)
}
// 多选框选中数据
function handleSelectionChange(selection) {
userIds.value = selection.map(item => item.userId)
}
// 查询表数据
function getList() {
unallocatedUserList(queryParams).then(res => {
userList.value = res.rows
total.value = res.total
})
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef")
handleQuery()
}
const emit = defineEmits(["ok"])
/** 选择授权用户操作 */
function handleSelectUser() {
const roleId = queryParams.roleId
const uIds = userIds.value.join(",")
if (uIds == "") {
proxy.$modal.msgError("请选择要分配的用户")
return
}
authUserSelectAll({ roleId: roleId, userIds: uIds }).then(res => {
proxy.$modal.msgSuccess(res.msg)
visible.value = false
emit("ok")
})
}
defineExpose({
show,
})
</script>
......@@ -167,7 +167,9 @@
import { getToken } from "@/utils/auth"
import useAppStore from '@/store/modules/app'
import { changeUserStatus, listTenant, resetUserPwd, delUser, getTenant, updateTenant, addTenant,changeTenantStatus } from "@/api/system/tenant"
import useUserStore from '@/store/modules/user'
const userStore = useUserStore()
const router = useRouter()
const appStore = useAppStore()
const { proxy } = getCurrentInstance()
......@@ -195,7 +197,7 @@ const data = reactive({
queryParams: {
pageNum: 1,
pageSize: 10,
loginTenantBizId: "tenant_1001",
loginTenantBizId: userStore.currentTenant.apiLoginTenantInfoResponse.tenantBizId,
tenantName: undefined,
contactName: undefined,
contactPhone: undefined,
......
......@@ -75,7 +75,11 @@
<el-table v-loading="importTenantProjectListLoading" :data="importTenantProjectList" @selection-change="importTenantProjectListHandleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="项目名称" prop="projectName" />
<el-table-column label="作用域" prop="scope" />
<el-table-column prop="scope" label="作用域">
<template #default="scope">
<dict-tag :options="sys_scope" :value="scope.row.scope" />
</template>
</el-table-column>
</el-table>
<pagination
v-show="importTenantProjectListTotal > 0"
......@@ -1017,7 +1021,7 @@ const loadMenuTree = async () => {
loadImportSelectedMenuList() // 加载选中的菜单列表,更新树勾选
} catch (error) {
console.error('加载菜单树失败:', error)
ElMessage.error('菜单加载失败')
proxy.$modal.msgError('菜单加载失败')
}
}
// 修改加载选中菜单列表的逻辑
......@@ -1046,7 +1050,7 @@ const loadImportSelectedMenuList = async () => {
} catch (error) {
console.error('加载选中的菜单列表失败:', error);
ElMessage.error('加载选中的菜单列表失败');
proxy.$modal.msgError('加载选中的菜单列表失败');
// 异常时也要恢复严格模式状态
isCheckStrictly.value = false;
}
......@@ -1068,11 +1072,11 @@ const saveImportSelectedMenuList = async () => {
})
getMenuList()
importTenantMenuListOpen.value = false
ElMessage.success('更新成功')
proxy.$modal.msgSuccess('更新成功')
} catch (error) {
console.error('更新失败:', error)
ElMessage.error('更新失败')
proxy.$modal.msgError('更新失败')
}
}
//========菜单-导入逻辑结束=========
......@@ -1324,7 +1328,7 @@ const loadFpMenuTree = async () => {
loadSelectedFpMenuList() // 加载选中的菜单列表,更新树勾选
} catch (error) {
console.error('加载菜单树失败:', error)
ElMessage.error('菜单加载失败')
proxy.$modal.msgError('菜单加载失败')
}
}
// 修改加载选中菜单列表的逻辑
......@@ -1353,7 +1357,7 @@ const loadSelectedFpMenuList = async () => {
} catch (error) {
console.error('加载选中的菜单列表失败:', error);
ElMessage.error('加载选中的菜单列表失败');
proxy.$modal.msgError('加载选中的菜单列表失败');
// 异常时也要恢复严格模式状态
fpMenuIsCheckStrictly.value = false;
}
......@@ -1377,11 +1381,11 @@ const saveFpMenuList = async () => {
getRoleList()
fpMenuOpen.value = false
ElMessage.success('更新成功')
proxy.$modal.msgSuccess('更新成功')
} catch (error) {
console.error('更新失败:', error)
ElMessage.error('更新失败')
proxy.$modal.msgError('更新失败')
}
}
//========分配菜单-导入逻辑结束=========
......
......@@ -132,9 +132,9 @@
<el-form-item label="账号" prop="userName">
<el-input v-model="form.userName" placeholder="请输入账号" />
</el-form-item>
<!-- <el-form-item label="密码" prop="password">-->
<!-- <el-input v-model="form.password" placeholder="请输入密码" />-->
<!-- </el-form-item>-->
<el-form-item label="密码" prop="password" v-show="!form.userBizId">
<el-input v-model="form.password" placeholder="请输入密码" />
</el-form-item>
<el-form-item label="姓名" prop="realName">
<el-input v-model="form.realName" placeholder="请输入姓名" />
</el-form-item>
......@@ -318,9 +318,10 @@ function handleUpdatePwd(row) {
/** 添加和修改用户提交按钮 */
function submitForm() {
debugger
proxy.$refs["userRef"].validate(valid => {
if (valid) {
if (form.value.userBizId != undefined) {
if (form.value.userBizId) {
updateUser(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
......
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