mirror of
https://gitee.com/bootx/dax-pay-ui.git
synced 2025-09-02 10:26:32 +00:00
feat 权限管理
This commit is contained in:
@@ -18,7 +18,9 @@
|
||||
<div class="mt-10 font-medium text-white -enter-x">
|
||||
<span class="inline-block mt-4 text-3xl"> 开箱即用的中后台管理系统</span>
|
||||
</div>
|
||||
<div class="mt-5 font-normal text-white dark:text-gray-500 -enter-x"> 输入您的个人详细信息开始使用! </div>
|
||||
<div class="mt-5 font-normal text-white dark:text-gray-500 -enter-x"
|
||||
>基于Vite+Vue3打造,支持支付收单、工作流(Flowable)、三方对接等模块
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex w-full h-full py-5 xl:h-auto xl:py-0 xl:my-0 xl:w-6/12">
|
||||
|
@@ -78,6 +78,17 @@ export const existsByPermCodeNotId = (permCode, id) => {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单列表
|
||||
* @param clientCode
|
||||
*/
|
||||
export function allMenuTree(clientCode) {
|
||||
return defHttp.get<Result<MenuTree[]>>({
|
||||
url: '/perm/menu/allTree',
|
||||
params: { clientCode },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限_菜单
|
||||
*/
|
||||
@@ -85,7 +96,7 @@ export interface Menu extends BaseEntity {
|
||||
// 终端code
|
||||
clientCode?: string
|
||||
// 父id
|
||||
parentId: number | null
|
||||
parentId: number | null | string
|
||||
// 菜单名称
|
||||
title: string
|
||||
// 路由名称
|
||||
@@ -120,6 +131,13 @@ export interface Menu extends BaseEntity {
|
||||
remark?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单树
|
||||
*/
|
||||
export interface MenuTree extends Menu {
|
||||
children: []
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限_资源(码)
|
||||
*/
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<a-row :gutter="10">
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="终端">
|
||||
<a-select v-model:value="clientCode" @change="init" :default-value="clientCode" style="width: 100%">
|
||||
<a-select v-model:value="clientCode" @change="queryPage" :default-value="clientCode" style="width: 100%">
|
||||
<a-select-option v-for="o in clients" :key="o.code">{{ o.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
@@ -25,7 +25,7 @@
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="m-3 p-3 bg-white">
|
||||
<vxe-toolbar ref="xToolbar" custom zoom :refresh="{ query: init }">
|
||||
<vxe-toolbar ref="xToolbar" custom zoom :refresh="{ query: queryPage }">
|
||||
<template #buttons>
|
||||
<a-button type="primary" @click="add()"> 新建 </a-button>
|
||||
<a-button style="margin-left: 8px" @click="allTreeExpand(true)">展开所有</a-button>
|
||||
@@ -90,7 +90,7 @@
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
<menu-edit ref="menuEdit" @ok="init" />
|
||||
<menu-edit ref="menuEdit" @ok="queryPage" />
|
||||
<resource-list ref="resourceList" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -127,7 +127,7 @@
|
||||
onMounted(() => {
|
||||
vxeBind()
|
||||
initClients()
|
||||
init()
|
||||
queryPage()
|
||||
})
|
||||
|
||||
function vxeBind() {
|
||||
@@ -139,7 +139,7 @@
|
||||
clients = data
|
||||
}
|
||||
|
||||
async function init() {
|
||||
async function queryPage() {
|
||||
loading = true
|
||||
menuTree(clientCode).then((res) => {
|
||||
remoteTableData = res.data
|
||||
@@ -175,7 +175,7 @@
|
||||
onOk: () => {
|
||||
del(record.id).then(() => {
|
||||
notification.success({ message: '删除成功' })
|
||||
init()
|
||||
queryPage()
|
||||
})
|
||||
},
|
||||
})
|
||||
|
@@ -1,10 +1,18 @@
|
||||
<template>
|
||||
<basic-modal :loading="confirmLoading" v-bind="$attrs" :title="title" :visible="visible" :mask-closable="showable" @cancel="handleCancel">
|
||||
<a-form class="small-from-item" :model="form" ref="formRef" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-form
|
||||
class="small-from-item"
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
:validate-trigger="['blur', 'change']"
|
||||
:label-col="labelCol"
|
||||
:wrapper-col="wrapperCol"
|
||||
>
|
||||
<a-form-item label="主键" :hidden="true">
|
||||
<a-input v-model:value="form.id" :disabled="showable" />
|
||||
</a-form-item>
|
||||
<a-form-item label="编码" name="permCode">
|
||||
<a-form-item validate-first label="编码" name="permCode">
|
||||
<a-input v-model:value="form.permCode" :disabled="showable" placeholder="请输入编码" />
|
||||
</a-form-item>
|
||||
<a-form-item label="名称" name="title">
|
||||
@@ -30,10 +38,12 @@
|
||||
import { FormInstance, Rule } from 'ant-design-vue/lib/form'
|
||||
import { $ref } from 'vue/macros'
|
||||
import { nextTick } from 'vue'
|
||||
import { add, get, Resource, update } from './Menu.api'
|
||||
import { add, existsByPermCode, existsByPermCodeNotId, get, Resource, update } from './Menu.api'
|
||||
import { BasicModal } from '/@/components/Modal/'
|
||||
import { useValidate } from '/@/hooks/bootx/useValidate'
|
||||
|
||||
const emits = defineEmits(['ok'])
|
||||
|
||||
const { initFormModel, handleCancel, search, labelCol, wrapperCol, title, confirmLoading, visible, editable, showable, formEditType } =
|
||||
useFormEdit()
|
||||
const { existsByServer } = useValidate()
|
||||
@@ -49,19 +59,21 @@
|
||||
remark: '',
|
||||
} as Resource)
|
||||
const rules = {
|
||||
title: [{ required: true, message: '请输入权限名称', trigger: ['blur', 'change'] }],
|
||||
permCode: [{ required: true, message: '请输入权限编码', trigger: ['blur', 'change'] }],
|
||||
effect: [{ required: true, message: '' }],
|
||||
title: [{ required: true, message: '请输入权限名称' }],
|
||||
permCode: [
|
||||
{ required: true, message: '请输入权限编码' },
|
||||
{ validator: validateCode, trigger: 'blur' },
|
||||
],
|
||||
} as Record<string, Rule[]>
|
||||
const formRef: FormInstance = $ref()
|
||||
|
||||
// 事件
|
||||
const emits = defineEmits(['ok'])
|
||||
// 入口
|
||||
function init(id, editType: FormEditType, clientCode) {
|
||||
function init(id, editType: FormEditType, clientCode, parentId) {
|
||||
initFormModel(id, editType)
|
||||
resetForm()
|
||||
form.clientCode = clientCode
|
||||
console.log(parentId)
|
||||
form.parentId = parentId
|
||||
getInfo(id, editType)
|
||||
}
|
||||
|
||||
@@ -97,6 +109,12 @@
|
||||
formRef.resetFields()
|
||||
})
|
||||
}
|
||||
|
||||
// 校验
|
||||
function validateCode() {
|
||||
const { permCode, id } = form
|
||||
return existsByServer(permCode, id, formEditType, existsByPermCode, existsByPermCodeNotId)
|
||||
}
|
||||
defineExpose({
|
||||
init,
|
||||
})
|
||||
|
@@ -8,7 +8,7 @@
|
||||
:visible="visible"
|
||||
@close="visible = false"
|
||||
>
|
||||
<vxe-toolbar ref="xToolbar" custom zoom :refresh="{ query: init }">
|
||||
<vxe-toolbar ref="xToolbar" custom zoom :refresh="{ query: queryPage }">
|
||||
<template #buttons>
|
||||
<a-button type="primary" pre-icon="ant-design:plus-outlined" @click="add">新建</a-button>
|
||||
</template>
|
||||
@@ -30,7 +30,7 @@
|
||||
<a href="javascript:" @click="show(row)">查看</a>
|
||||
</span>
|
||||
<a-divider type="vertical" />
|
||||
<a href="javascript:" :disabled="row.admin" @click="edit(row)">编辑</a>
|
||||
<a href="javascript:" @click="edit(row)">编辑</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm title="是否删除该项" @confirm="remove(row)" okText="是" cancelText="否">
|
||||
<a href="javascript:" v-if="row.admin" disabled>删除</a>
|
||||
@@ -76,13 +76,14 @@
|
||||
|
||||
// 分页查询
|
||||
function queryPage() {
|
||||
loading.value = true
|
||||
resourceList(menuInfo.id).then(({ data }) => {
|
||||
tableData = data
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
function add() {
|
||||
resourceEdit.init(null, FormEditType.Add, menuInfo.clientCode)
|
||||
resourceEdit.init(null, FormEditType.Add, menuInfo.clientCode, menuInfo.id)
|
||||
}
|
||||
function edit(record: Menu) {
|
||||
resourceEdit.init(record.id, FormEditType.Edit, menuInfo.clientCode)
|
||||
|
@@ -32,6 +32,26 @@ export const add = (obj: Role) => {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存 角色分配菜单关系
|
||||
*/
|
||||
export function saveRoleMenu(obj) {
|
||||
return defHttp.post({
|
||||
url: `/role/menu/save`,
|
||||
data: obj,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存 角色请求权限关系
|
||||
*/
|
||||
export function saveRolePath(obj) {
|
||||
return defHttp.post({
|
||||
url: `/role/path/save`,
|
||||
data: obj,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*/
|
||||
@@ -95,6 +115,35 @@ export const findAll = () => {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户获取拥有的权限
|
||||
*/
|
||||
export function findPermissionIdsByRole(roleId, clientCode) {
|
||||
return defHttp.get<Result<string[]>>({
|
||||
url: `/role/menu/findPermissionIdsByRole`,
|
||||
params: { roleId, clientCode },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户id获取角色授权(请求权限列表)
|
||||
*/
|
||||
export function findPathsByUser() {
|
||||
return defHttp.get<Result<string[]>>({
|
||||
url: `/role/path/findPathsByUser`,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据角色id获取关联请求权限id
|
||||
*/
|
||||
export function findPathIdsByRole(roleId) {
|
||||
return defHttp.get<Result>({
|
||||
url: `/role/path/findIdsByRole`,
|
||||
params: { roleId },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色
|
||||
*/
|
||||
|
@@ -36,10 +36,10 @@
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item>
|
||||
<a href="javascript:" @click="handleRoleMenu(row)">菜单授权</a>
|
||||
<a href="javascript:" @click="handleRoleMenu(row)">菜单和权限码</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a href="javascript:" @click="handleRolePath(row)">请求授权</a>
|
||||
<a href="javascript:" @click="handleRolePath(row)">请求资源</a>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
@@ -56,6 +56,8 @@
|
||||
@page-change="handleTableChange"
|
||||
/>
|
||||
<role-edit ref="roleEdit" @ok="queryPage" />
|
||||
<role-menu-modal ref="roleMenuModal" />
|
||||
<role-path-modal ref="rolePathModal" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -72,12 +74,16 @@
|
||||
import { $ref } from 'vue/macros'
|
||||
import { QueryField, STRING } from '/@/components/Bootx/Query/Query'
|
||||
import Icon from '/@/components/Icon/src/Icon.vue'
|
||||
import RoleMenuModal from "./RoleMenuModal.vue";
|
||||
import RolePathModal from "./RolePathModal.vue";
|
||||
|
||||
// 使用hooks
|
||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, pages, model, loading } = useTablePage(queryPage)
|
||||
const { createMessage } = useMessage()
|
||||
|
||||
const roleEdit = ref()
|
||||
const roleEdit = $ref<any>()
|
||||
const roleMenuModal = $ref<any>()
|
||||
const rolePathModal = $ref<any>()
|
||||
// 查询条件
|
||||
const fields = [
|
||||
{ field: 'code', type: STRING, name: '角色编号', placeholder: '请输入角色编码' },
|
||||
@@ -106,20 +112,24 @@
|
||||
}
|
||||
// 新增
|
||||
function add() {
|
||||
roleEdit.value.init(null, FormEditType.Add)
|
||||
roleEdit.init(null, FormEditType.Add)
|
||||
}
|
||||
// 查看
|
||||
function edit(record) {
|
||||
roleEdit.value.init(record.id, FormEditType.Edit)
|
||||
roleEdit.init(record.id, FormEditType.Edit)
|
||||
}
|
||||
// 查看
|
||||
function show(record) {
|
||||
roleEdit.value.init(record.id, FormEditType.Show)
|
||||
roleEdit.init(record.id, FormEditType.Show)
|
||||
}
|
||||
// 菜单授权处理
|
||||
function handleRoleMenu(record) {}
|
||||
function handleRoleMenu(record) {
|
||||
roleMenuModal.init(record.id)
|
||||
}
|
||||
// 请求授权处理
|
||||
function handleRolePath(record) {}
|
||||
function handleRolePath(record) {
|
||||
rolePathModal.init(record.id)
|
||||
}
|
||||
// 删除
|
||||
function remove(record) {
|
||||
del(record.id).then(() => {
|
||||
|
205
src/views/modules/system/role/RoleMenuModal.vue
Normal file
205
src/views/modules/system/role/RoleMenuModal.vue
Normal file
@@ -0,0 +1,205 @@
|
||||
<template>
|
||||
<basic-drawer showFooter v-bind="$attrs" title="角色菜单和权限码配置" width="40%" :visible="visible" @close="handleCancel">
|
||||
<a-spin :spinning="loading">
|
||||
<a-input style="margin-bottom: 8px" placeholder="筛选" allowClear v-model:value="searchName" @change="search" />
|
||||
<a-tree
|
||||
:checkable="true"
|
||||
v-model:checkedKeys="checkedKeys"
|
||||
v-model:expandedKeys="expandedKeys"
|
||||
:checkStrictly="checkStrictly"
|
||||
:auto-expand-parent="autoExpandParent"
|
||||
:tree-data="treeData"
|
||||
@check="onCheck"
|
||||
@expand="onExpand"
|
||||
>
|
||||
<template #title="{ title }">
|
||||
<span v-if="title.toLowerCase().indexOf(searchName.toLowerCase()) > -1">
|
||||
{{ searchRenderStart(title, searchName) }}
|
||||
<span style="color: #f50">
|
||||
{{ searchRenderMiddle(title, searchName) }}
|
||||
</span>
|
||||
{{ searchRenderEnd(title, searchName) }}
|
||||
</span>
|
||||
<span v-else>{{ title }}</span>
|
||||
</template>
|
||||
</a-tree>
|
||||
</a-spin>
|
||||
<template #footer>
|
||||
<a-select style="min-width: 100px" @change="clientSwitch" v-model:value="clientCode">
|
||||
<a-select-option v-for="o in clients" :key="o.code">{{ o.name }}</a-select-option>
|
||||
</a-select>
|
||||
<a-dropdown style="margin-left: 5px" :trigger="['click']" placement="topCenter">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item key="1" @click="checkALL">全部勾选</a-menu-item>
|
||||
<a-menu-item key="2" @click="cancelCheckALL">取消全选</a-menu-item>
|
||||
<a-menu-item key="3" @click="expandAll">展开所有</a-menu-item>
|
||||
<a-menu-item key="4" @click="closeAll">合并所有</a-menu-item>
|
||||
<a-menu-item key="5" @click="switchCheckStrictly(false)">父子关联</a-menu-item>
|
||||
<a-menu-item key="6" @click="switchCheckStrictly(true)">取消关联</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button post-icon="ant-design:up-outlined"> 操作 </a-button>
|
||||
</a-dropdown>
|
||||
<a-button @click="visible = false" style="margin-right: 0.8rem">取消</a-button>
|
||||
<a-button @click="handleSubmit()" type="primary" :loading="loading" style="margin-right: 0.8rem">保存</a-button>
|
||||
</template>
|
||||
</basic-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { BasicDrawer } from '/@/components/Drawer'
|
||||
import { $ref } from 'vue/macros'
|
||||
import { findAll as findClients, Client } from '/@/views/modules/system/client/Client.api'
|
||||
import { getAppEnvConfig } from '/@/utils/env'
|
||||
import { findPermissionIdsByRole, saveRoleMenu } from '/@/views/modules/system/role/Role.api'
|
||||
import { treeDataTranslate } from '/@/utils/dataUtil'
|
||||
import XEUtils from 'xe-utils'
|
||||
import { allMenuTree, MenuTree } from '/@/views/modules/system/menu/Menu.api'
|
||||
|
||||
const { VITE_GLOB_APP_CLIENT } = getAppEnvConfig()
|
||||
|
||||
let loading = $ref(false)
|
||||
let roleId = $ref('')
|
||||
let visible = $ref(false)
|
||||
// 终端列表
|
||||
let clients = $ref([] as Client[])
|
||||
let clientCode = $ref(VITE_GLOB_APP_CLIENT)
|
||||
let searchName = $ref('')
|
||||
// 父子选项默认不受控
|
||||
let checkStrictly = $ref(true)
|
||||
// 所有的key
|
||||
let allTreeKeys = $ref<string[]>([])
|
||||
// 展开的key
|
||||
let expandedKeys = $ref<string[]>([])
|
||||
// 被选中的key
|
||||
let checkedKeys = $ref<string[]>([])
|
||||
let autoExpandParent = $ref(false)
|
||||
//菜单树信息
|
||||
let treeData = $ref<MenuTree[]>([])
|
||||
let treeList = $ref<MenuTree[]>([])
|
||||
|
||||
function init(id) {
|
||||
roleId = id
|
||||
initData()
|
||||
initAssign()
|
||||
}
|
||||
|
||||
function initData() {
|
||||
findClients().then(({ data }) => {
|
||||
clients = data
|
||||
})
|
||||
}
|
||||
|
||||
// 初始化菜单分配信息
|
||||
async function initAssign() {
|
||||
visible = true
|
||||
loading = true
|
||||
searchName = ''
|
||||
expandedKeys = []
|
||||
// 权限树
|
||||
await allMenuTree(clientCode).then((res) => {
|
||||
treeData = treeDataTranslate(res.data, 'id', 'title') as MenuTree[]
|
||||
generateTreeList(res.data)
|
||||
})
|
||||
// 当前角色已经选择的
|
||||
await findPermissionIdsByRole(roleId, clientCode).then((res) => {
|
||||
checkedKeys = res.data
|
||||
})
|
||||
// 所有的key值
|
||||
allTreeKeys = treeList.map((item) => item.id) as string[]
|
||||
loading = false
|
||||
}
|
||||
|
||||
// 保存
|
||||
function handleSubmit() {
|
||||
loading = true
|
||||
saveRoleMenu({
|
||||
roleId,
|
||||
clientCode,
|
||||
permissionIds: checkedKeys,
|
||||
}).then(() => {
|
||||
handleCancel()
|
||||
})
|
||||
}
|
||||
// 取消
|
||||
function handleCancel() {
|
||||
visible = false
|
||||
}
|
||||
// 树数据铺平
|
||||
function generateTreeList(treeData) {
|
||||
for (let i = 0; i < treeData.length; i++) {
|
||||
const node = treeData[i]
|
||||
treeList.push(node)
|
||||
if (node.children) {
|
||||
generateTreeList(node.children)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 搜索
|
||||
function search() {
|
||||
const value = XEUtils.toValueString(searchName).toLowerCase()
|
||||
expandedKeys = treeList
|
||||
.map((node) => {
|
||||
if (searchName && node.parentId && XEUtils.toValueString(node.title).toLowerCase().indexOf(value) > -1) {
|
||||
return node.parentId
|
||||
}
|
||||
})
|
||||
.filter((item, i, self) => item && self.indexOf(item) === i) as string[]
|
||||
}
|
||||
// 渲染搜索项目数据开始段
|
||||
function searchRenderStart(title, searchName) {
|
||||
return title.substring(0, title.toLowerCase().indexOf(searchName.toLowerCase()))
|
||||
}
|
||||
// 渲染搜索项目数据中间段
|
||||
function searchRenderMiddle(title, searchName) {
|
||||
return title.substring(
|
||||
title.toLowerCase().indexOf(searchName.toLowerCase()),
|
||||
title.toLowerCase().indexOf(searchName.toLowerCase()) + searchName.length,
|
||||
)
|
||||
}
|
||||
// 渲染搜索项目数据结束段
|
||||
function searchRenderEnd(title, searchName) {
|
||||
return title.substring(title.toLowerCase().indexOf(searchName.toLowerCase()) + searchName.length)
|
||||
}
|
||||
// 展开/收起节点时触发
|
||||
function onExpand(keys) {
|
||||
expandedKeys = keys
|
||||
autoExpandParent = false
|
||||
}
|
||||
// 点击复选框触发
|
||||
function onCheck(key) {
|
||||
if (checkStrictly) {
|
||||
checkedKeys = key.checked
|
||||
} else {
|
||||
checkedKeys = key
|
||||
}
|
||||
}
|
||||
// 展开全部
|
||||
function expandAll() {
|
||||
expandedKeys = allTreeKeys
|
||||
}
|
||||
// 合并全部
|
||||
function closeAll() {
|
||||
expandedKeys = []
|
||||
}
|
||||
// 全选
|
||||
function checkALL() {
|
||||
checkedKeys = allTreeKeys
|
||||
}
|
||||
// 全不选
|
||||
function cancelCheckALL() {
|
||||
checkedKeys = []
|
||||
}
|
||||
// 切换父子受控状态
|
||||
function switchCheckStrictly(v) {
|
||||
checkStrictly = v
|
||||
}
|
||||
// 终端切换
|
||||
function clientSwitch(item) {
|
||||
clientCode = item
|
||||
initAssign()
|
||||
}
|
||||
defineExpose({ init })
|
||||
</script>
|
||||
<style scoped></style>
|
88
src/views/modules/system/role/RolePathModal.vue
Normal file
88
src/views/modules/system/role/RolePathModal.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<basic-drawer forceRender showFooter v-bind="$attrs" title="请求资源权限配置" width="40%" :visible="visible" @close="handleCancel">
|
||||
<a-spin :spinning="loading">
|
||||
<vxe-table
|
||||
row-id="id"
|
||||
border="none"
|
||||
ref="xTable"
|
||||
size="small"
|
||||
:loading="loading"
|
||||
:data="tableData"
|
||||
:showHeader="true"
|
||||
:tree-config="{ children: 'children' }"
|
||||
:checkbox-config="{ labelField: 'name', checkRowKeys: checkedKeys }"
|
||||
>
|
||||
<vxe-column type="checkbox" title="权限名称" tree-node />
|
||||
<vxe-column field="code" title="权限代码" />
|
||||
</vxe-table>
|
||||
</a-spin>
|
||||
<template #footer>
|
||||
<a-space>
|
||||
<a-button @click="handleCancel()">取消</a-button>
|
||||
<a-button @click="handleSubmit()" type="primary" :loading="loading">保存</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</basic-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import BasicDrawer from '/@/components/Drawer/src/BasicDrawer.vue'
|
||||
import { $ref } from 'vue/macros'
|
||||
import { VxeTableInstance } from 'vxe-table'
|
||||
import { findPathIdsByRole, findPathsByUser, saveRoleMenu, saveRolePath } from "./Role.api";
|
||||
import XEUtils from 'xe-utils'
|
||||
|
||||
const xTable = $ref<VxeTableInstance>()
|
||||
|
||||
let loading = $ref(false)
|
||||
let roleId = $ref('')
|
||||
let visible = $ref(false)
|
||||
let checkedKeys = $ref<string[]>([])
|
||||
let tableData = $ref<string[]>([])
|
||||
|
||||
async function init(id) {
|
||||
visible = true
|
||||
loading = true
|
||||
roleId = id
|
||||
await findPathIdsByRole(roleId).then(({ data }) => {
|
||||
checkedKeys = data
|
||||
})
|
||||
await findPathsByUser().then(({ data }) => {
|
||||
const result = [] as any[]
|
||||
// 对数据进行分组
|
||||
XEUtils.each(XEUtils.groupBy(data, 'groupName'), (children, key) => {
|
||||
result.push({
|
||||
name: key,
|
||||
children: children,
|
||||
})
|
||||
})
|
||||
tableData = result
|
||||
xTable.reloadData(tableData)
|
||||
loading = false
|
||||
})
|
||||
}
|
||||
|
||||
// 保存
|
||||
function handleSubmit() {
|
||||
loading = true
|
||||
const checkedKeys = xTable
|
||||
.getCheckboxRecords()
|
||||
.map((res) => res.id)
|
||||
.filter((id) => id.indexOf('row_') === -1)
|
||||
saveRolePath({
|
||||
roleId,
|
||||
permissionIds: checkedKeys,
|
||||
}).then(() => {
|
||||
handleCancel()
|
||||
})
|
||||
}
|
||||
|
||||
// 取消
|
||||
function handleCancel() {
|
||||
visible = false
|
||||
}
|
||||
|
||||
defineExpose({ init })
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
2
types/web.d.ts
vendored
2
types/web.d.ts
vendored
@@ -35,5 +35,5 @@ export interface TablePageModel<T = any> {
|
||||
* 基础实体对象
|
||||
*/
|
||||
export interface BaseEntity {
|
||||
id?: number | null | undefined
|
||||
id?: number | string | null | undefined
|
||||
}
|
||||
|
Reference in New Issue
Block a user