Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
Y
yishuju-ui
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
何远江
yishuju-ui
Commits
f01c34f6
Commit
f01c34f6
authored
Jan 05, 2025
by
何远江
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加权限
parent
09a0b6f6
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
645 additions
and
62 deletions
+645
-62
index.vue
src/components/CommonModal/UserModal/index.vue
+112
-0
index.vue
src/components/ProTable/index.vue
+2
-1
index.vue
src/layouts/LayoutVertical/index.vue
+0
-1
vxe-table.js
src/plugins/vxe-table.js
+4
-1
auth.js
src/stores/modules/auth.js
+16
-2
menu.js
src/utils/menu.js
+36
-0
MenuFormModal.vue
src/views/system/menuMange/components/MenuFormModal.vue
+108
-43
index.vue
src/views/system/menuMange/index.vue
+46
-10
AllocationMenuModal.vue
...iews/system/roleManage/components/AllocationMenuModal.vue
+93
-0
AllocationUserModal.vue
...iews/system/roleManage/components/AllocationUserModal.vue
+97
-0
index.vue
src/views/system/roleManage/index.vue
+23
-3
AllocationUserModal.vue
...ws/system/tenantManage/components/AllocationUserModal.vue
+97
-0
index.vue
src/views/system/tenantManage/index.vue
+11
-1
No files found.
src/components/CommonModal/UserModal/index.vue
0 → 100644
View file @
f01c34f6
<
template
>
<vxe-modal
v-model=
"showModal"
@
hide=
"onHide"
title=
"用户选择"
width=
"900px"
show-maximize
show-footer
esc-closable
>
<el-form
inline
:model=
"searchParam"
>
<el-row
:gutter=
"12"
>
<el-col
:span=
"8"
>
<el-form-item
class=
"w-full"
label=
"用户名称:"
prop=
"username"
>
<el-input
v-model=
"searchParam.username"
/>
</el-form-item>
</el-col>
<el-col
:span=
"8"
>
<el-form-item
class=
"w-full"
label=
"昵称:"
prop=
"nickName"
>
<el-input
v-model=
"searchParam.nickName"
/>
</el-form-item>
</el-col>
<el-col
:span=
"8"
>
<el-form-item
class=
"w-full"
label=
"状态:"
prop=
"status"
>
<el-select
v-model=
"searchParam.status"
>
<el-option
label=
"启用"
value=
"enable"
/>
<el-option
label=
"禁用"
value=
"disable"
/>
</el-select>
</el-form-item>
</el-col>
<el-col>
<el-form-item>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"search"
>
搜索
</el-button>
<el-button
:icon=
"Delete"
@
click=
"reset"
>
重置
</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
<vxe-table
ref=
"xTable"
:data=
"tableData"
:loading=
"loading"
>
<vxe-column
type=
"checkbox"
width=
"50"
/>
<vxe-column
field=
"username"
title=
"用户账号"
minWidth=
"120"
/>
<vxe-column
field=
"nickName"
title=
"昵称"
minWidth=
"120"
/>
<vxe-column
field=
"phone"
title=
"手机号"
width=
"140"
/>
<vxe-column
field=
"status"
title=
"状态"
width=
"120"
>
<template
#
default=
"
{ row }">
<el-tag
:type=
"row.status == 'enable' ? 'primary' : 'danger'"
>
{{
row
.
status
==
'enable'
?
'启用'
:
'禁用'
}}
</el-tag>
</
template
>
</vxe-column>
</vxe-table>
<Pagination
:pageable=
"pageable"
:handleSizeChange=
"handleSizeChange"
:handleCurrentChange=
"handleCurrentChange"
/>
<
template
#
footer
>
<el-button
type=
"default"
@
click=
"showModal = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleConfirm"
>
确认
</el-button>
</
template
>
</vxe-modal>
</template>
<
script
setup
name=
"UserModal"
>
import
{
ref
,
onMounted
}
from
'vue'
;
import
{
ElMessage
}
from
'element-plus'
;
import
{
getUserPage
}
from
'@/api/user'
;
import
{
Search
,
Delete
}
from
'@element-plus/icons-vue'
;
import
Pagination
from
'@/components/Pagination/index.vue'
;
import
{
useProTable
}
from
'@/hooks/useProTable'
;
const
emits
=
defineEmits
([
'confirm'
]);
const
showModal
=
ref
(
false
);
const
xTable
=
ref
(
null
);
const
{
pageable
,
tableData
,
search
,
searchParam
,
reset
,
loading
,
handleSizeChange
,
handleCurrentChange
,
}
=
useProTable
(
getUserPage
,
{},
true
);
const
handleConfirm
=
async
()
=>
{
const
checkedList
=
xTable
.
value
.
getCheckboxRecords
();
if
(
!
checkedList
.
length
)
{
return
ElMessage
({
type
:
'warning'
,
message
:
'请选择有效数据!'
,
plain
:
true
,
});
}
emits
(
'confirm'
,
checkedList
);
showModal
.
value
=
false
;
};
const
onHide
=
()
=>
{};
const
openModal
=
()
=>
{
showModal
.
value
=
true
;
};
onMounted
(()
=>
{
search
();
});
defineExpose
({
openModal
,
});
</
script
>
src/components/ProTable/index.vue
View file @
f01c34f6
...
...
@@ -96,6 +96,7 @@
reset
,
handleSizeChange
,
handleCurrentChange
,
totalParam
,
}
=
useProTable
(
props
?.
api
,
props
.
initParam
,
...
...
@@ -156,7 +157,7 @@
const
_search
=
()
=>
{
search
();
emit
(
'search'
);
emit
(
'search'
,
totalParam
.
value
);
};
const
_reset
=
()
=>
{
...
...
src/layouts/LayoutVertical/index.vue
View file @
f01c34f6
...
...
@@ -45,7 +45,6 @@
const
route
=
useRoute
();
const
authStore
=
useAuthStore
();
const
globalStore
=
useGlobalStore
();
authStore
.
getAuthMenuList
();
const
accordion
=
computed
(()
=>
globalStore
.
accordion
);
const
isCollapse
=
computed
(()
=>
globalStore
.
isCollapse
);
...
...
src/plugins/vxe-table.js
View file @
f01c34f6
...
...
@@ -68,6 +68,7 @@ export function setupVxeTabele(app) {
border
:
true
,
stripe
:
true
,
round
:
true
,
size
:
'small'
,
resizableConfig
:
{
dragMode
:
'auto'
,
showDragTip
:
true
,
...
...
@@ -91,7 +92,9 @@ export function setupVxeTabele(app) {
keyField
:
'_ROW_KEY'
,
},
},
grid
:
{},
grid
:
{
size
:
'small'
},
});
lazyVxeUI
(
app
);
lazyVxeTable
(
app
);
...
...
src/stores/modules/auth.js
View file @
f01c34f6
import
{
defineStore
}
from
'pinia'
;
import
{
getShowMenuList
,
getFlatMenuList
,
getAllBreadcrumbList
}
from
'@/utils/menu'
;
import
{
getShowMenuList
,
getFlatMenuList
,
getAllBreadcrumbList
,
filterMenu
}
from
'@/utils/menu'
;
import
authMenuList
from
'@/assets/json/authMenuList.json'
;
import
{
getMenuTree
}
from
'@/api/menu'
;
import
{
useUserStore
}
from
'./user'
;
export
const
useAuthStore
=
defineStore
({
id
:
'admin-auth'
,
state
:
()
=>
({
...
...
@@ -27,12 +29,24 @@ export const useAuthStore = defineStore({
// Get AuthButtonList
async
getAuthButtonList
()
{
// const { data } = await getAuthButtonListApi();
const
{
userInfo
}
=
useUserStore
();
this
.
authButtonList
=
userInfo
.
permissions
;
// this.authButtonList = data;
},
// Get AuthMenuList
async
getAuthMenuList
()
{
// const { data } = await getAuthMenuListApi();
this
.
authMenuList
=
authMenuList
;
const
{
userInfo
}
=
useUserStore
();
if
(
userInfo
?.
menus
.
length
)
{
// 除了按钮的所有菜单
const
userMenus
=
userInfo
.
menus
.
filter
((
v
)
=>
v
.
type
!==
'2'
);
// 1、获取所有菜单
const
{
result
}
=
await
getMenuTree
();
// 2、递归菜单
this
.
authMenuList
=
filterMenu
(
result
,
userMenus
);
}
else
{
this
.
authMenuList
=
[];
}
},
// Set RouteName
async
setRouteName
(
name
)
{
...
...
src/utils/menu.js
View file @
f01c34f6
...
...
@@ -39,3 +39,39 @@ export const getAllBreadcrumbList = (menuList, parent = [], result = {}) => {
}
return
result
;
};
/**
* 通过全部菜单匹配用户的扁平菜单
* @param {*} menus 菜单列表
* @param {*} userMenus 用户菜单
* @param {*} menu 处理后的菜单
* @returns
*/
export
function
filterMenu
(
menus
,
userMenus
,
menu
=
[])
{
if
(
!
menus
?.
length
)
return
menu
;
menus
.
forEach
((
m
)
=>
{
if
(
userMenus
.
find
((
v
)
=>
v
.
id
===
m
.
id
))
{
const
target
=
{
path
:
m
.
path
,
name
:
m
.
name
,
redirect
:
m
.
redirect
,
component
:
m
.
component
,
meta
:
{
icon
:
m
.
icon
,
title
:
m
.
title
,
isLink
:
m
.
link
,
isHide
:
m
.
hide
===
'Y'
,
isFull
:
m
.
full
===
'Y'
,
isAffix
:
m
.
affix
===
'Y'
,
isKeepAlive
:
m
.
keepAlive
==
'Y'
,
activeMenu
:
m
.
activeMenu
,
},
};
menu
.
push
(
target
);
if
(
m
.
children
?.
length
)
{
target
.
children
=
filterMenu
(
m
.
children
,
userMenus
,
[]);
}
}
});
return
menu
;
}
src/views/system/menuMange/components/MenuFormModal.vue
View file @
f01c34f6
...
...
@@ -11,40 +11,61 @@
<el-form
ref=
"formRef"
:model=
"form"
inline
label-width=
"80px"
>
<el-row
:gutter=
"10"
>
<el-col
:span=
"24"
>
<el-form-item
class=
"w-full"
label=
"菜单类型"
prop=
"type"
>
<el-radio-group
v-model=
"form.type"
>
<el-radio-button
label=
"一级菜单"
value=
"0"
/>
<el-radio-button
label=
"子菜单"
value=
"1"
/>
<el-radio-button
label=
"按钮"
value=
"2"
/>
</el-radio-group>
</el-form-item>
</el-col>
<el-col
:span=
"24"
v-show=
"form.type != '0'"
>
<el-form-item
class=
"w-full"
label=
"父级菜单"
prop=
"parent"
>
<el-tree-select
clearable
ref=
"treeSelectRef"
v-model=
"form.parent"
:data=
"props.menuList"
highlight-current
check-strictly
node-key=
"name"
:current-node-key=
"form.parent"
:props=
"
{
label: 'title',
children: 'children',
}"
node-key="id"
:render-after-expand="false"
clearable
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
class=
"w-full"
label=
"菜单名称"
prop=
"
meta.
title"
>
<el-input
v-model=
"form.
meta.
title"
placeholder=
"标题"
/>
<el-form-item
class=
"w-full"
label=
"菜单名称"
prop=
"title"
>
<el-input
v-model=
"form.title"
placeholder=
"标题"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
class=
"w-full"
label=
"
图标"
prop=
"meta.icon
"
>
<el-input
v-model=
"form.
meta.icon"
placeholder=
"图标
"
/>
<el-form-item
class=
"w-full"
label=
"
访问路径"
prop=
"path
"
>
<el-input
v-model=
"form.
path"
placeholder=
"访问路径
"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
class=
"w-full"
label=
"访问路径"
prop=
"path"
>
<el-input
v-model=
"form.path"
placeholder=
"访问路径"
/>
<el-form-item
class=
"w-full"
label=
"菜单图标"
prop=
"icon"
>
<el-input
v-model=
"form.icon"
placeholder=
"菜单图标"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
class=
"w-full"
label=
"重定向"
prop=
"redirect"
>
<el-input
v-model=
"form.redirect"
placeholder=
"重定向路径"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
class=
"w-full"
label=
"
重定向"
prop=
"path
"
>
<el-input
v-model=
"form.
redirect"
placeholder=
"重定向
"
/>
<el-form-item
class=
"w-full"
label=
"
菜单Name"
prop=
"name
"
>
<el-input
v-model=
"form.
name"
placeholder=
"菜单Name
"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
class=
"w-full"
label=
"
菜单name"
prop=
"nam
e"
>
<el-input
v-model=
"form.
name"
placeholder=
"菜单name
"
/>
<el-form-item
class=
"w-full"
label=
"
权限编码"
prop=
"cod
e"
>
<el-input
v-model=
"form.
code"
placeholder=
"权限编码
"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
...
...
@@ -52,35 +73,34 @@
<el-input
v-model=
"form.component"
placeholder=
"组件路径"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
class=
"w-full"
label=
"外链地址"
prop=
"
isL
ink"
>
<el-input
v-model=
"form.
isL
ink"
placeholder=
"外链地址"
/>
<el-form-item
class=
"w-full"
label=
"外链地址"
prop=
"
l
ink"
>
<el-input
v-model=
"form.
l
ink"
placeholder=
"外链地址"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
class=
"w-full"
label=
"显示菜单"
prop=
"activeMenu"
>
<el-input
v-model=
"form.
meta.activeMenu
"
/>
<el-input
v-model=
"form.
activeMenu"
placeholder=
"显示菜单路径
"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"是否隐藏"
prop=
"
isH
ide"
>
<el-checkbox
v-model=
"form.
meta.isHide"
:true-value=
"1"
:false-value=
"0
"
/>
<el-form-item
label=
"是否隐藏"
prop=
"
h
ide"
>
<el-checkbox
v-model=
"form.
hide"
true-value=
"Y"
false-value=
"N
"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"是否全屏"
prop=
"
isF
ull"
>
<el-checkbox
v-model=
"form.
meta.isFull"
:true-value=
"1"
:false-value=
"0
"
/>
<el-form-item
label=
"是否全屏"
prop=
"
f
ull"
>
<el-checkbox
v-model=
"form.
full"
true-value=
"Y"
false-value=
"N
"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"是否固定"
prop=
"
isA
ffix"
>
<el-checkbox
v-model=
"form.
meta.isAffix"
:true-value=
"1"
:false-value=
"0
"
/>
<el-form-item
label=
"是否固定"
prop=
"
a
ffix"
>
<el-checkbox
v-model=
"form.
affix"
true-value=
"Y"
false-value=
"N
"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"是否缓存"
prop=
"
isK
eepAlive"
>
<el-checkbox
v-model=
"form.
meta.isKeepAlive"
:true-value=
"1"
:false-value=
"0
"
/>
<el-form-item
label=
"是否缓存"
prop=
"
k
eepAlive"
>
<el-checkbox
v-model=
"form.
keepAlive"
true-value=
"Y"
false-value=
"N
"
/>
</el-form-item>
</el-col>
</el-row>
...
...
@@ -88,53 +108,98 @@
<template
#
footer
>
<el-button
type=
"default"
@
click=
"showModal = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"submitForm"
>
提交
</el-button>
<el-button
:loading=
"loading"
type=
"primary"
@
click=
"submitForm"
>
提交
</el-button>
</
template
>
</vxe-modal>
</template>
<
script
setup
name=
"menuFormModal"
>
import
{
ref
,
reactive
,
computed
,
unref
}
from
'vue'
;
import
{
ref
,
computed
}
from
'vue'
;
import
{
saveMenu
}
from
'@/api/menu'
;
import
{
ElMessage
}
from
'element-plus'
;
const
emits
=
defineEmits
([
'success'
]);
const
props
=
defineProps
({
menuList
:
{
type
:
Array
,
default
:
()
=>
[],
},
});
const
currentMenu
=
ref
(
null
);
const
showModal
=
ref
(
false
);
const
formRef
=
ref
(
null
);
const
treeSelectRef
=
ref
(
null
);
const
loading
=
ref
(
false
);
const
isEdit
=
computed
(()
=>
!!
currentMenu
.
value
);
const
modalTitle
=
computed
(()
=>
(
isEdit
.
value
?
'编辑菜单'
:
'新增菜单'
));
const
form
=
reactive
({
parent
:
''
,
const
form
=
ref
({
type
:
'0'
,
parent
:
null
,
path
:
''
,
// 访问路径
name
:
''
,
// 组件 name
component
:
''
,
// 组件
名称
component
:
''
,
// 组件
路径
redirect
:
''
,
// 重定向
meta
:
{
icon
:
''
,
// icon
title
:
''
,
// 标题
isLink
:
''
,
// 是否外链接
isHide
:
0
,
// 是否隐藏
isFull
:
0
,
// 是否全屏
isAffix
:
1
,
// 是否固定
activeMenu
:
''
,
// 用于详情时,选中菜单路径
isKeepAlive
:
1
,
// 是否缓存
}
,
code
:
''
,
// 权限编码
icon
:
''
,
// icon
title
:
''
,
// 标题
link
:
''
,
// 外链地址,
hide
:
'N'
,
// 是否隐藏
full
:
'N'
,
// 是否全屏
affix
:
'N'
,
// 是否固定
activeMenu
:
'Y'
,
// 选中菜单的地址
keepAlive
:
'Y'
,
// 是否缓存
sortNo
:
1
,
});
const
submitForm
=
()
=>
{};
const
submitForm
=
async
()
=>
{
// console.log(treeSelectRef.value.getCurrentNode(), '---');
// return
const
params
=
{
...
form
.
value
,
parent
:
form
.
value
.
type
==
'first'
?
null
:
treeSelectRef
.
value
.
getCurrentNode
(),
};
try
{
await
formRef
.
value
.
validate
();
loading
.
value
=
true
;
await
saveMenu
(
params
);
ElMessage
({
type
:
'success'
,
message
:
isEdit
.
value
?
'修改成功!'
:
'新增成功!'
,
plain
:
true
,
});
emits
(
'success'
);
showModal
.
value
=
false
;
}
catch
{}
loading
.
value
=
false
;
};
const
onHide
=
()
=>
{
formRef
.
value
.
resetFields
();
form
.
value
=
{
type
:
'first'
,
parent
:
''
,
path
:
''
,
// 访问路径
name
:
''
,
// 组件 name
component
:
''
,
// 组件路径
redirect
:
''
,
// 重定向
code
:
''
,
// 权限编码
icon
:
''
,
// icon
title
:
''
,
// 标题
link
:
''
,
// 外链地址,
hide
:
'N'
,
// 是否隐藏
full
:
'N'
,
// 是否全屏
affix
:
'N'
,
// 是否固定
activeMenu
:
'Y'
,
// 选中菜单的地址
keepAlive
:
'Y'
,
// 是否缓存
sortNo
:
1
,
};
formRef
.
value
.
clearValidate
();
currentMenu
.
value
=
null
;
};
const
openModal
=
(
menu
)
=>
{
Object
.
assign
(
form
,
menu
);
menu
&&
(
form
.
value
=
menu
);
currentMenu
.
value
=
menu
;
showModal
.
value
=
true
;
};
...
...
src/views/system/menuMange/index.vue
View file @
f01c34f6
<
template
>
<div
class=
"table-box"
>
<ProTable
ref=
"proTable"
:config=
"config"
:show-pagination=
"false"
:data=
"menuData"
>
<ProTable
ref=
"proTable"
:config=
"config"
:show-pagination=
"false"
@
search=
"handleSearch"
:data=
"tableData"
>
<!-- 表格 header 按钮 -->
<template
#
left_buttons
>
<el-button
type=
"primary"
:icon=
"CirclePlus"
@
click=
"menuFormModalRef?.openModal()"
...
...
@@ -9,7 +15,7 @@
</
template
>
</ProTable>
<MenuFormModal
ref=
"menuFormModalRef"
:menuList=
"
authMenuList
"
/>
<MenuFormModal
ref=
"menuFormModalRef"
:menuList=
"
tableData"
@
success=
"onSuccess
"
/>
</div>
</template>
...
...
@@ -18,25 +24,27 @@
import
{
Delete
,
EditPen
,
CirclePlus
}
from
'@element-plus/icons-vue'
;
import
authMenuList
from
'@/assets/json/authMenuList.json'
;
import
ProTable
from
'@/components/ProTable/index.vue'
;
import
{
ElButton
}
from
'element-plus'
;
import
{
ElButton
,
ElMessage
,
ElMessageBox
}
from
'element-plus'
;
import
MenuIcon
from
'./components/MenuIcon.vue'
;
import
MenuFormModal
from
'./components/MenuFormModal.vue'
;
import
{
getMenuTree
,
deleteMenus
}
from
'@/api/menu'
;
import
{
onMounted
}
from
'vue'
;
const
proTable
=
ref
();
const
menuFormModalRef
=
ref
();
const
menuData
=
ref
(
authMenuList
);
const
tableData
=
ref
([]);
// 表格配置项
const
config
=
{
height
:
'auto'
,
stripe
:
false
,
// tree 不支持 stripe
treeConfig
:
{
rowField
:
'
name
'
,
rowField
:
'
id
'
,
childrenField
:
'children'
,
},
columns
:
[
{
field
:
'
meta.
title'
,
field
:
'title'
,
title
:
'菜单名称'
,
align
:
'left'
,
minWidth
:
240
,
...
...
@@ -44,12 +52,12 @@
treeNode
:
true
,
},
{
field
:
'
meta.
icon'
,
field
:
'icon'
,
title
:
'菜单图标'
,
minWidth
:
120
,
slots
:
{
default
:
({
row
})
=>
{
return
<
MenuIcon
width
=
{
20
}
iconName
=
{
row
.
meta
.
icon
}
/>
;
return
row
.
icon
&&
<
MenuIcon
width
=
{
20
}
iconName
=
{
row
.
icon
}
/>
;
},
},
},
...
...
@@ -68,7 +76,7 @@
<
ElButton
type
=
"primary"
icon
=
{
EditPen
}
link
onClick
=
{()
=>
handleEditClick
(
row
)}
>
编辑
<
/ElButton
>
<
ElButton
type
=
"primary"
icon
=
{
Delete
}
link
>
<
ElButton
type
=
"primary"
icon
=
{
Delete
}
link
onClick
=
{()
=>
handleDelete
(
row
)}
>
删除
<
/ElButton
>
<
/
>
...
...
@@ -79,7 +87,35 @@
],
};
const
handleEditClick
=
(
row
)
=>
{
const
onSuccess
=
()
=>
{
handleSearch
();
};
const
handleSearch
=
async
(
params
)
=>
{
const
{
result
}
=
await
getMenuTree
(
params
??
{});
tableData
.
value
=
result
;
};
const
handleEditClick
=
(
row
)
=>
menuFormModalRef
.
value
.
openModal
(
JSON
.
parse
(
JSON
.
stringify
(
row
)));
const
handleDelete
=
async
(
row
)
=>
{
await
ElMessageBox
.
confirm
(
'是否确认删除该菜单?'
,
'提示'
,
{
confirmButtonText
:
'确认'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
});
await
deleteMenus
(
row
.
id
);
ElMessage
({
type
:
'success'
,
message
:
'删除成功!'
,
plain
:
true
,
});
handleSearch
();
};
onMounted
(()
=>
{
handleSearch
();
});
</
script
>
src/views/system/roleManage/components/AllocationMenuModal.vue
0 → 100644
View file @
f01c34f6
<
template
>
<vxe-modal
v-model=
"showModal"
@
hide=
"onHide"
title=
"菜单权限分配"
width=
"800px"
show-maximize
show-footer
esc-closable
>
<el-tree
ref=
"treeRef"
:data=
"menuData"
show-checkbox
node-key=
"id"
default-expand-all
:default-checked-keys=
"defaultCheckedKeys"
:props=
"defaultProps"
/>
<template
#
footer
>
<el-button
type=
"default"
@
click=
"showModal = false"
>
取消
</el-button>
<el-button
:loading=
"loading"
type=
"primary"
@
click=
"submitForm"
>
提交
</el-button>
</
template
>
</vxe-modal>
</template>
<
script
setup
name=
"AllocationUserModal"
>
import
{
ref
,
onMounted
,
reactive
,
computed
}
from
'vue'
;
import
{
ElMessage
}
from
'element-plus'
;
import
{
getMenuTree
}
from
'@/api/menu'
;
import
{
saveRole
}
from
'@/api/role'
;
const
defaultProps
=
{
children
:
'children'
,
label
:
'title'
,
};
const
emits
=
defineEmits
([
'success'
]);
const
currentRole
=
ref
(
null
);
const
showModal
=
ref
(
false
);
const
treeRef
=
ref
(
null
);
const
menuData
=
ref
([]);
const
defaultCheckedKeys
=
computed
(()
=>
currentRole
.
value
?.
menus
.
map
((
v
)
=>
v
.
id
)
||
[]);
const
loading
=
ref
(
false
);
const
submitForm
=
async
()
=>
{
try
{
// 获取全选中节点
const
checkedNodes
=
treeRef
.
value
.
getCheckedNodes
();
// 获取半选中节点
const
halfCheckedNodes
=
treeRef
.
value
.
getHalfCheckedNodes
();
if
(
!
checkedNodes
.
length
)
{
return
ElMessage
.
info
(
'请选择要设置的权限!'
);
}
loading
.
value
=
true
;
const
params
=
{
...
currentRole
.
value
,
menus
:
checkedNodes
.
map
((
v
)
=>
({
id
:
v
.
id
})),
// menus: [...checkedNodes, ...halfCheckedNodes].map((v) => ({ id: v.id })),
};
await
saveRole
(
params
);
emits
(
'success'
);
ElMessage
({
type
:
'success'
,
message
:
'设置成功!'
,
plain
:
true
,
});
showModal
.
value
=
false
;
}
catch
{}
loading
.
value
=
false
;
};
const
onHide
=
()
=>
{
currentRole
.
value
=
null
;
treeRef
.
value
.
setCheckedNodes
([]);
};
const
openModal
=
(
role
)
=>
{
currentRole
.
value
=
role
;
showModal
.
value
=
true
;
};
const
initTreeData
=
async
()
=>
{
const
{
result
}
=
await
getMenuTree
();
menuData
.
value
=
result
;
};
onMounted
(()
=>
{
initTreeData
();
});
defineExpose
({
openModal
,
});
</
script
>
src/views/system/roleManage/components/AllocationUserModal.vue
0 → 100644
View file @
f01c34f6
<
template
>
<vxe-modal
v-model=
"showModal"
@
hide=
"onHide"
title=
"分配成员"
width=
"900px"
show-maximize
show-footer
esc-closable
>
<div
class=
"mb-1"
>
<el-button
type=
"primary"
@
click=
"userModalRef?.openModal"
>
新增成员
</el-button>
<el-button
type=
"danger"
@
click=
"handleRemove"
>
删除成员
</el-button>
</div>
<vxe-table
ref=
"xTable"
:data=
"tableData"
>
<vxe-column
type=
"checkbox"
width=
"50"
/>
<vxe-column
field=
"username"
title=
"用户账号"
minWidth=
"120"
/>
<vxe-column
field=
"nickName"
title=
"昵称"
minWidth=
"120"
/>
<vxe-column
field=
"status"
title=
"状态"
width=
"120"
>
<template
#
default=
"
{ row }">
<el-tag
:type=
"row.status == 'enable' ? 'primary' : 'danger'"
>
{{
row
.
status
==
'enable'
?
'启用'
:
'禁用'
}}
</el-tag>
</
template
>
</vxe-column>
</vxe-table>
<
template
#
footer
>
<el-button
type=
"default"
@
click=
"showModal = false"
>
取消
</el-button>
<el-button
:loading=
"loading"
type=
"primary"
@
click=
"submitForm"
>
提交
</el-button>
</
template
>
</vxe-modal>
<UserModal
ref=
"userModalRef"
@
confirm=
"hanldeConfirm"
/>
</template>
<
script
setup
name=
"AllocationUserModal"
>
import
{
ref
}
from
'vue'
;
import
{
ElMessage
}
from
'element-plus'
;
import
{
saveRole
}
from
'@/api/role'
;
import
UserModal
from
'@/components/CommonModal/UserModal/index.vue'
;
const
emits
=
defineEmits
([
'success'
]);
const
xTable
=
ref
(
null
);
const
showModal
=
ref
(
false
);
const
userModalRef
=
ref
(
null
);
const
loading
=
ref
(
false
);
const
tableData
=
ref
([]);
const
currentRole
=
ref
(
null
);
const
submitForm
=
async
()
=>
{
try
{
loading
.
value
=
true
;
const
params
=
{
...
currentRole
.
value
,
users
:
tableData
.
value
.
map
((
v
)
=>
({
id
:
v
.
id
})),
};
await
saveRole
(
params
);
emits
(
'success'
);
ElMessage
({
type
:
'success'
,
message
:
'添加成功!'
,
plain
:
true
,
});
showModal
.
value
=
false
;
}
catch
{}
loading
.
value
=
false
;
};
const
onHide
=
()
=>
{
currentRole
.
value
=
null
;
tableData
.
value
=
[];
};
const
openModal
=
(
role
)
=>
{
currentRole
.
value
=
role
;
tableData
.
value
=
role
.
users
;
showModal
.
value
=
true
;
};
const
hanldeConfirm
=
(
rows
)
=>
{
tableData
.
value
.
unshift
(...
rows
.
filter
((
row
)
=>
!
tableData
.
value
.
find
((
v
)
=>
v
.
id
==
row
.
id
)));
};
const
handleRemove
=
()
=>
{
const
checkedList
=
xTable
.
value
.
getCheckboxRecords
();
if
(
!
checkedList
.
length
)
{
return
ElMessage
({
type
:
'warning'
,
message
:
'请选择有效数据!'
,
plain
:
true
,
});
}
tableData
.
value
=
tableData
.
value
.
filter
((
row
)
=>
!
checkedList
.
find
((
v
)
=>
v
.
id
==
row
.
id
));
};
defineExpose
({
openModal
,
});
</
script
>
src/views/system/roleManage/index.vue
View file @
f01c34f6
...
...
@@ -8,6 +8,8 @@
</ProTable>
<RoleFormModal
ref=
"roleModalRef"
@
success=
"query"
/>
<AllocationMenuModal
ref=
"allocationMenuModalRef"
@
success=
"query"
/>
<AllocationUserModal
ref=
"allocationUserModalRef"
/>
</div>
</template>
...
...
@@ -15,11 +17,15 @@
import
{
ref
,
reactive
,
onMounted
}
from
'vue'
;
import
{
Plus
,
Delete
,
Edit
,
Setting
}
from
'@element-plus/icons-vue'
;
import
{
getRolePage
,
deleteRoles
}
from
'@/api/role'
;
import
RoleFormModal
from
'./components/RoleFormModal.vue'
;
import
{
ElMessageBox
,
ElMessage
,
ElButton
}
from
'element-plus'
;
import
RoleFormModal
from
'./components/RoleFormModal.vue'
;
import
AllocationMenuModal
from
'./components/AllocationMenuModal.vue'
;
import
AllocationUserModal
from
'./components/AllocationUserModal.vue'
;
const
proTable
=
ref
(
null
);
const
roleModalRef
=
ref
(
null
);
const
allocationMenuModalRef
=
ref
(
null
);
const
allocationUserModalRef
=
ref
(
null
);
const
config
=
reactive
({
columns
:
[
{
type
:
'checkbox'
,
width
:
50
},
...
...
@@ -35,10 +41,24 @@
<
ElButton
type
=
"primary"
link
icon
=
{
Edit
}
onClick
=
{()
=>
handleEdit
(
row
)}
>
编辑
<
/ElButton
>
<
ElButton
type
=
"primary"
link
icon
=
{
Setting
}
>
<
ElButton
type
=
"primary"
link
icon
=
{
Setting
}
onClick
=
{()
=>
allocationMenuModalRef
.
value
.
openModal
(
JSON
.
parse
(
JSON
.
stringify
(
row
)))
}
>
设置权限
<
/ElButton
>
<
ElButton
type
=
"primary"
link
icon
=
{
Setting
}
>
<
ElButton
type
=
"primary"
link
icon
=
{
Setting
}
onClick
=
{()
=>
allocationUserModalRef
.
value
.
openModal
(
JSON
.
parse
(
JSON
.
stringify
(
row
)))
}
>
设置成员
<
/ElButton
>
<
/
>
...
...
src/views/system/tenantManage/components/AllocationUserModal.vue
0 → 100644
View file @
f01c34f6
<
template
>
<vxe-modal
v-model=
"showModal"
@
hide=
"onHide"
title=
"分配成员"
width=
"900px"
show-maximize
show-footer
esc-closable
>
<div
class=
"mb-1"
>
<el-button
type=
"primary"
@
click=
"userModalRef?.openModal"
>
新增成员
</el-button>
<el-button
type=
"danger"
@
click=
"handleRemove"
>
删除成员
</el-button>
</div>
<vxe-table
ref=
"xTable"
:data=
"tableData"
>
<vxe-column
type=
"checkbox"
width=
"50"
/>
<vxe-column
field=
"username"
title=
"用户账号"
minWidth=
"120"
/>
<vxe-column
field=
"nickName"
title=
"昵称"
minWidth=
"120"
/>
<vxe-column
field=
"status"
title=
"状态"
width=
"120"
>
<template
#
default=
"
{ row }">
<el-tag
:type=
"row.status == 'enable' ? 'primary' : 'danger'"
>
{{
row
.
status
==
'enable'
?
'启用'
:
'禁用'
}}
</el-tag>
</
template
>
</vxe-column>
</vxe-table>
<
template
#
footer
>
<el-button
type=
"default"
@
click=
"showModal = false"
>
取消
</el-button>
<el-button
:loading=
"loading"
type=
"primary"
@
click=
"submitForm"
>
提交
</el-button>
</
template
>
</vxe-modal>
<UserModal
ref=
"userModalRef"
@
confirm=
"hanldeConfirm"
/>
</template>
<
script
setup
name=
"AllocationUserModal"
>
import
{
ref
}
from
'vue'
;
import
{
ElMessage
}
from
'element-plus'
;
import
{
saveTenant
}
from
'@/api/tenant'
;
import
UserModal
from
'@/components/CommonModal/UserModal/index.vue'
;
const
emits
=
defineEmits
([
'success'
]);
const
xTable
=
ref
(
null
);
const
showModal
=
ref
(
false
);
const
userModalRef
=
ref
(
null
);
const
loading
=
ref
(
false
);
const
tableData
=
ref
([]);
const
currentRole
=
ref
(
null
);
const
submitForm
=
async
()
=>
{
try
{
loading
.
value
=
true
;
const
params
=
{
...
currentRole
.
value
,
users
:
tableData
.
value
.
map
((
v
)
=>
({
id
:
v
.
id
})),
};
await
saveTenant
(
params
);
emits
(
'success'
);
ElMessage
({
type
:
'success'
,
message
:
'设置成功!'
,
plain
:
true
,
});
showModal
.
value
=
false
;
}
catch
{}
loading
.
value
=
false
;
};
const
onHide
=
()
=>
{
currentRole
.
value
=
null
;
tableData
.
value
=
[];
};
const
openModal
=
(
role
)
=>
{
currentRole
.
value
=
role
;
tableData
.
value
=
role
.
users
;
showModal
.
value
=
true
;
};
const
hanldeConfirm
=
(
rows
)
=>
{
tableData
.
value
.
unshift
(...
rows
.
filter
((
row
)
=>
!
tableData
.
value
.
find
((
v
)
=>
v
.
id
==
row
.
id
)));
};
const
handleRemove
=
()
=>
{
const
checkedList
=
xTable
.
value
.
getCheckboxRecords
();
if
(
!
checkedList
.
length
)
{
return
ElMessage
({
type
:
'warning'
,
message
:
'请选择有效数据!'
,
plain
:
true
,
});
}
tableData
.
value
=
tableData
.
value
.
filter
((
row
)
=>
!
checkedList
.
find
((
v
)
=>
v
.
id
==
row
.
id
));
};
defineExpose
({
openModal
,
});
</
script
>
src/views/system/tenantManage/index.vue
View file @
f01c34f6
...
...
@@ -8,6 +8,7 @@
</ProTable>
<TenantFormModal
ref=
"tenatModalRef"
@
success=
"query"
/>
<AllocationUserModal
ref=
"allocationUserModalRef"
@
success=
"query"
/>
</div>
</template>
...
...
@@ -16,10 +17,12 @@
import
{
Plus
,
Delete
,
Edit
,
Setting
}
from
'@element-plus/icons-vue'
;
import
{
getTenantPage
,
deleteTenants
}
from
'@/api/tenant'
;
import
TenantFormModal
from
'./components/TenantFormModal.vue'
;
import
AllocationUserModal
from
'./components/AllocationUserModal.vue'
;
import
{
ElMessageBox
,
ElMessage
,
ElButton
,
ElTag
}
from
'element-plus'
;
const
proTable
=
ref
(
null
);
const
tenatModalRef
=
ref
(
null
);
const
allocationUserModalRef
=
ref
(
null
);
const
config
=
reactive
({
columns
:
[
{
type
:
'checkbox'
,
width
:
50
},
...
...
@@ -48,7 +51,14 @@
<
ElButton
type
=
"primary"
link
icon
=
{
Edit
}
onClick
=
{()
=>
handleEdit
(
row
)}
>
编辑
<
/ElButton
>
<
ElButton
type
=
"primary"
link
icon
=
{
Setting
}
>
<
ElButton
type
=
"primary"
link
icon
=
{
Setting
}
onClick
=
{()
=>
allocationUserModalRef
.
value
.
openModal
(
JSON
.
parse
(
JSON
.
stringify
(
row
)))
}
>
设置成员
<
/ElButton
>
<
/
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment