大屏页面初始化

This commit is contained in:
2026-03-06 15:43:05 +08:00
parent 4c62e80407
commit b9d209f7ef
12 changed files with 395 additions and 29 deletions

View File

@@ -0,0 +1,223 @@
<template>
<div class="role-auth-container">
<el-form
:model="formData"
class="role-info-form"
label-width="80px"
inline
>
<el-form-item label="角色编号:" class="form-col">
<el-input
v-model="formData.roleId"
disabled
class="info-input"
/>
</el-form-item>
<el-form-item label="角色名称:" class="form-col">
<el-input
v-model="formData.roleName"
class="info-input"
/>
</el-form-item>
</el-form>
<div class="menu-tree-wrapper">
<div class="tree-content">
<el-skeleton v-if="loading" :rows="10" animated />
<el-tree
v-else
ref="menuTreeRef"
:data="menuTreeData"
:props="treeProps"
:show-checkbox="true"
:default-expand-all="false"
node-key="id"
@check-change="handleCheckChange"
@check="handleCheck"
/>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, defineProps, defineExpose, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { getTreeMenuList } from '@/api/bizMenu'
import { getHomeRoleMenus } from '@/api/bizRole'
const props = defineProps({
formData: {
type: Object,
required: true,
default: () => ({
roleId: '',
roleName: '',
menuIds: []
})
}
})
const menuTreeData = ref([])
const loading = ref(false)
const menuTreeRef = ref(null)
const selectedMenuIds = ref([])
const getTreeListData = async () => {
try {
const res = await getTreeMenuList()
menuTreeData.value = res ?? []
} catch (error) {
console.error('加载菜单树失败:', error)
menuTreeData.value = []
}
}
const getRoleMenuIds = async () => {
try {
const reqParams = { roleId: props.formData.roleId }
const res = await getHomeRoleMenus(reqParams)
return (res ?? []).map(item => String(item?.menuId)).filter(id => id)
} catch (error) {
console.error('加载角色菜单权限失败:', error)
return []
}
}
const treeProps = reactive({
label: 'label',
children: 'children',
disabled: 'disabled'
})
onMounted(async () => {
loading.value = true
try {
const [_, roleMenuIds] = await Promise.all([
getTreeListData(),
getRoleMenuIds()
])
const propsMenuIds = (props.formData?.menuIds ?? []).map(id => String(id)).filter(id => id)
const defaultCheckedIds = roleMenuIds.length > 0 ? roleMenuIds : propsMenuIds
if (defaultCheckedIds.length > 0) {
selectedMenuIds.value = [...defaultCheckedIds]
setTimeout(() => {
if (menuTreeRef.value && menuTreeData.value.length) {
menuTreeRef.value.setCheckedKeys(defaultCheckedIds, false)
}
}, 300)
}
} catch (error) {
console.error('初始化权限数据失败:', error)
} finally {
loading.value = false
}
})
watch(() => props.formData.menuIds, (newVal) => {
if (!newVal || !newVal.length || !menuTreeRef.value) return
const menuIds = newVal.map(id => String(id)).filter(id => id)
if (menuIds.length) {
selectedMenuIds.value = [...menuIds]
menuTreeRef.value.setCheckedKeys(menuIds, false)
}
}, { deep: true })
const handleCheck = () => {
if (!menuTreeRef.value) return
selectedMenuIds.value = menuTreeRef.value.getCheckedKeys(false)
}
const handleCheckChange = (data, checked, indeterminate) => {
handleCheck()
}
const validate = async () => {
if (selectedMenuIds.value.length === 0) {
ElMessage.warning('请至少选择一个菜单权限!')
return false
}
return true
}
const resetForm = () => {
if (menuTreeRef.value) {
menuTreeRef.value.setCheckedKeys([])
selectedMenuIds.value = []
}
}
defineExpose({
validate,
resetForm,
getSelectedMenuIds: () => selectedMenuIds.value,
getLeafMenuIds: () => menuTreeRef.value ? menuTreeRef.value.getCheckedKeys(true) : []
})
</script>
<style scoped>
.role-auth-container {
width: 100%;
padding: 16px;
border: 1px solid rgba(64, 158, 255, 0.15);
border-radius: 8px;
box-sizing: border-box;
background: #fff;
}
.role-info-form {
margin-bottom: 16px;
padding-bottom: 12px;
border-bottom: 1px solid #e5e7eb;
width: 100%;
display: flex;
gap: 20px;
}
.form-col {
flex: 1;
min-width: 200px;
}
.info-input {
width: 100%;
}
:deep(.role-info-form .el-form-item) {
margin-bottom: 0;
width: 100%;
}
:deep(.role-info-form .el-input.is-disabled .el-input__inner) {
background-color: #f5f7fa;
color: #666;
}
.menu-tree-wrapper {
width: 100%;
}
.tree-content {
width: 100%;
height: 400px;
overflow-y: auto;
border: 1px solid #e5e7eb;
border-radius: 4px;
padding: 8px;
box-sizing: border-box;
}
:deep(.el-tree) {
--el-tree-node-content-hover-bg-color: #f5f7fa;
}
:deep(.el-tree-node__content) {
height: 36px;
line-height: 36px;
}
.tree-content::-webkit-scrollbar {
width: 6px;
}
.tree-content::-webkit-scrollbar-thumb {
background-color: #dcdfe6;
border-radius: 3px;
}
</style>