解决按钮权限覆盖的问题,权限展示所有菜单,角色修改时回显子节点勾选的问题,统计分析生命周期获取数据接口问题

This commit is contained in:
ym1026
2025-11-12 14:13:10 +08:00
parent ac17c41900
commit 450aff0eff
8 changed files with 227 additions and 249 deletions

View File

@@ -534,6 +534,13 @@ export const roleOptions = [
tableData: [], tableData: [],
selectTableData: [], selectTableData: [],
columns: [ columns: [
{
title: '操作',
dataIndex: 'action',
key: 'action',
align: 'center',
scopedSlots: { customRender: 'action' }
},
{ {
title: '名称', title: '名称',
dataIndex: 'name', dataIndex: 'name',

View File

@@ -53,7 +53,8 @@
:table-option="{ :table-option="{
checkStrictly: false, checkStrictly: false,
selectTableData: item.selectTableData, selectTableData: item.selectTableData,
scroll: { y: 500 } scroll: { y: 500 },
select:false
}" }"
> >
<template #is_add="{ record }"> <template #is_add="{ record }">
@@ -409,7 +410,7 @@ export default {
} }
const { selectedRowKeys } = this.$refs.treeTable[0] const { selectedRowKeys } = this.$refs.treeTable[0]
const data = this.filterTreeData(selectedRowKeys, this.$refs.treeTable[0].tableData) const data = this.filterCheckedTree( this.$refs.treeTable[0].tableData)
const arr = data.map((item) => ({ const arr = data.map((item) => ({
...item, ...item,
@@ -431,7 +432,7 @@ export default {
if (this.action == 'edit') { if (this.action == 'edit') {
paramsDate.role_id = this.record.role_id paramsDate.role_id = this.record.role_id
} }
console.log(arr,"aaaaaaaaaaa")
const res = await postReq(menuApi[this.action], paramsDate) const res = await postReq(menuApi[this.action], paramsDate)
if (res.errcode === 0) { if (res.errcode === 0) {
this.$message.success('操作成功') this.$message.success('操作成功')
@@ -447,47 +448,18 @@ export default {
} }
}, },
// 定义筛选树形数据的函数 // 定义筛选树形数据的函数
filterTreeData(list1, list2) { filterCheckedTree(data) {
const keySet = new Set(list1) return data
.filter((item) => item.checked) // 过滤当前层级 checked 为 true 的节点
// 递归处理节点的函数 .map((item) => {
const filterNode = (node) => { // 深拷贝节点(避免修改原数据)
// 创建新节点对象(浅拷贝) const newItem = { ...item };
const newNode = Object.assign({}, node) // 递归处理 children
if (newItem.children && newItem.children.length > 0) {
// 临时删除children属性以便处理 newItem.children = this.filterCheckedTree(newItem.children);
const { children, ...rest } = newNode
// 处理子节点
let newChildren = []
if (children) {
newChildren = children.map((child) => filterNode(child)).filter((child) => child !== null)
} }
return newItem;
// 重建新节点 });
const resultNode = Object.assign(rest, {})
if (newChildren.length > 0) {
resultNode.children = newChildren
}
// 判断是否保留节点
if (keySet.has(node.key)) {
return resultNode
}
// 保留有符合条件子节点的父节点移除自身key
if (newChildren.length > 0) {
return resultNode
}
return null
}
// 处理根节点
const result = list2.map((node) => filterNode(node)).filter((node) => node !== null)
return result
}, },
getPerOperBoolean(data) { getPerOperBoolean(data) {
return { return {

View File

@@ -2,7 +2,6 @@
<div class="treetable" ref="treetable"> <div class="treetable" ref="treetable">
<a-table <a-table
bordered bordered
:loading="loading" :loading="loading"
:scroll="tableOption.scroll" :scroll="tableOption.scroll"
:columns="columns" :columns="columns"
@@ -11,18 +10,19 @@
:row-class-name="(record, index) => rowClassName(record, index)" :row-class-name="(record, index) => rowClassName(record, index)"
row-key="key" row-key="key"
size="middle" size="middle"
:row-selection="newTableOpt.select :row-selection="newTableOpt.select ? rowSelection : null"
?rowSelection:null"
:indent-size="30" :indent-size="30"
:check-strictly="false" :check-strictly="false"
@resizeColumn="handleResizeColumn" @resizeColumn="handleResizeColumn"
> >
<template #bodyCell="{ text, record, index, column }"> <template #bodyCell="{ text, record, index, column }">
<template v-if="column.key === 'action'">
<a-checkbox v-model:checked="record.checked" />
</template>
<template v-if="column.scopedSlots"> <template v-if="column.scopedSlots">
<slot <slot
v-bind="{ record, index }" v-bind="{ record, index }"
:name="column.scopedSlots ? column.scopedSlots.customRender : ''" :name="column.scopedSlots ? column.scopedSlots.customRender : ''"
></slot> ></slot>
</template> </template>
</template> </template>
@@ -102,7 +102,6 @@ export default {
}, },
computed: { computed: {
rowSelection() { rowSelection() {
const { selectedRowKeys } = this const { selectedRowKeys } = this
return { return {
checkStrictly: this.tableOption.checkStrictly, checkStrictly: this.tableOption.checkStrictly,
@@ -114,7 +113,8 @@ export default {
hideDefaultSelections: true, hideDefaultSelections: true,
onSelect: (record, selected) => { onSelect: (record, selected) => {
this.onSelect(record, selected) this.onSelect(record, selected)
} },
} }
} }
}, },
@@ -269,7 +269,6 @@ export default {
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
.pagination { .pagination {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
@@ -282,7 +281,6 @@ export default {
:deep(.ant-table) { :deep(.ant-table) {
// border-radius:20px 20px 0 0 !important; // border-radius:20px 20px 0 0 !important;
overflow: hidden; /* 确保圆角生效 */ overflow: hidden; /* 确保圆角生效 */
} }
:deep(.ant-table-wrapper .ant-table.ant-table-bordered > .ant-table-container) { :deep(.ant-table-wrapper .ant-table.ant-table-bordered > .ant-table-container) {
border-inline-start: none !important; border-inline-start: none !important;
@@ -441,12 +439,10 @@ export default {
} }
:deep(.ant-table-container > .ant-table-content > table) { :deep(.ant-table-container > .ant-table-content > table) {
border-inline-start: 1px solid var(--theme-bg) !important; border-inline-start: 1px solid var(--theme-bg) !important;
} }
:deep(.ant-table.ant-table-has-fix-left.ant-table-middle.ant-table-bordered) { :deep(.ant-table.ant-table-has-fix-left.ant-table-middle.ant-table-bordered) {
border-radius: 20px !important; border-radius: 20px !important;
} }
:deep(.ant-pagination-item-link) { :deep(.ant-pagination-item-link) {
color: var(--theme-text-default) !important; color: var(--theme-text-default) !important;
@@ -455,7 +451,13 @@ export default {
display: block !important; display: block !important;
// border: none !important; // border: none !important;
} }
:deep(.ant-table-wrapper .ant-table.ant-table-bordered >.ant-table-container >.ant-table-content >table){ :deep(
.ant-table-wrapper
.ant-table.ant-table-bordered
> .ant-table-container
> .ant-table-content
> table
) {
border-top: none; border-top: none;
} }
:deep(.ant-table-tbody) { :deep(.ant-table-tbody) {
@@ -499,7 +501,16 @@ export default {
border-inline-end: 1px solid var(--table-header-bg) !important; border-inline-end: 1px solid var(--table-header-bg) !important;
} }
} }
:deep(.ant-table-wrapper .ant-table.ant-table-bordered >.ant-table-container >.ant-table-body >table >tbody>tr>td){ :deep(
.ant-table-wrapper
.ant-table.ant-table-bordered
> .ant-table-container
> .ant-table-body
> table
> tbody
> tr
> td
) {
border-inline-end: none !important; border-inline-end: none !important;
} }
:deep(.ant-table-thead) { :deep(.ant-table-thead) {
@@ -510,11 +521,9 @@ export default {
> tr { > tr {
&:hover { &:hover {
> .ant-table-cell { > .ant-table-cell {
background-color: transparent !important; background-color: transparent !important;
} }
} }
} }
} }
@@ -535,15 +544,11 @@ export default {
background-color: transparent !important; background-color: transparent !important;
} }
:deep(.ant-table-wrapper .ant-table-thead th.ant-table-column-has-sorters:hover) { :deep(.ant-table-wrapper .ant-table-thead th.ant-table-column-has-sorters:hover) {
background: var(--table-select) !important; background: var(--table-select) !important;
} }
:deep(.ant-table-wrapper .ant-table-row-expand-icon) { :deep(.ant-table-wrapper .ant-table-row-expand-icon) {
background: #2c538a !important; background: #2c538a !important;
} }
</style> </style>

View File

@@ -19,13 +19,17 @@ function findNodeByRoute(tree, targetRoute) {
return null // 未找到 return null // 未找到
} }
function getBtns(arr) { function getBtns(arr) {
const curPermission = findNodeByRoute(JSON.parse(localStorage.getItem('permission')), '/user') const curPermission = findNodeByRoute(
JSON.parse(localStorage.getItem('permission')),
'/' + this.$route.name
)
// console.log(findNodeByRoute(JSON.parse(localStorage.getItem('permission')), '/user'), '55') // console.log(findNodeByRoute(JSON.parse(localStorage.getItem('permission')), '/user'), '55')
// console.log(this.$route, curPermission, localStorage.getItem('permission'), 'curPermission') // console.log(this.$route, curPermission, localStorage.getItem('permission'), 'curPermission')
const btns = [] const btns = []
// console.log(curPermission, 'curPermission') // console.log(curPermission, 'curPermission')
btnList.forEach((item) => { btnList.forEach((item) => {
console.log(item.disFlag, curPermission[item.disFlag], 'curPermission[item.disFlag]')
if (arr.includes(item.label)) { if (arr.includes(item.label)) {
// item.disabled = true // item.disabled = true
item.disabled = !Boolean(+curPermission[item.disFlag]) item.disabled = !Boolean(+curPermission[item.disFlag])

View File

@@ -53,6 +53,7 @@
:table-info="tableList[activeKey].tableInfo" :table-info="tableList[activeKey].tableInfo"
:table-data="tableList[activeKey].tableData" :table-data="tableList[activeKey].tableData"
@pagesizeChange="pagesizeChange" @pagesizeChange="pagesizeChange"
> >
</energyEchart> </energyEchart>
</a-spin> </a-spin>
@@ -635,20 +636,24 @@ export default {
}) })
}) })
}, },
immediate: true // 添加立即执行 // immediate: true // 添加立即执行
} }
}, },
async mounted() { mounted() {
console.log('mounted')
// 优先加载第一个页面(activeKey=1)所需的数据 // 优先加载第一个页面(activeKey=1)所需的数据
this.btnOptionList = this.$getBtns(['导出']) this.btnOptionList = this.$getBtns(['导出'])
await Promise.all([ Promise.all([
this.getStationList(), this.getStationList()
]).then(()=>{
this.getEchartsListForActiveKey(), this.getEchartsListForActiveKey(),
this.getTableListForActiveKey() this.getTableListForActiveKey()
]) this.getStatCharts()
this.startRealtimeRefresh()
})
// 初始化实时刷新 // 初始化实时刷新
this.startRealtimeRefresh()
}, },
beforeUnmount() { beforeUnmount() {
clearInterval(this.interval) // 组件销毁时清除定时器 clearInterval(this.interval) // 组件销毁时清除定时器
@@ -731,6 +736,7 @@ export default {
}, },
// 专门获取当前激活页面的表格数据 // 专门获取当前激活页面的表格数据
async getTableListForActiveKey() { async getTableListForActiveKey() {
console.log( this.stationId,'getTableListForActiveKey')
this.loading.table = true this.loading.table = true
if (!this.activeKey) return if (!this.activeKey) return
@@ -771,6 +777,7 @@ export default {
}, },
async getStationList() { async getStationList() {
console.log('getsStationList')
const params = { const params = {
page_size: 1000, page_size: 1000,
page: 1 page: 1
@@ -807,7 +814,7 @@ export default {
this.paramsDate.start_date = data.time ? data.time[0] : '' this.paramsDate.start_date = data.time ? data.time[0] : ''
this.paramsDate.end_date = data.time ? data.time[1] : '' this.paramsDate.end_date = data.time ? data.time[1] : ''
this.tableList[this.activeKey].pageOption.page = 1 this.tableList[this.activeKey].pageOption.page = 1
this.getStationList(), this.getEchartsListForActiveKey(), this.getTableListForActiveKey() this.getStationList(), this.getStatCharts(),this.getEchartsListForActiveKey(), this.getTableListForActiveKey()
}, },
changeStation() { changeStation() {
this.getStatCharts() this.getStatCharts()

View File

@@ -70,7 +70,8 @@ export default {
btnOptionList: [], btnOptionList: [],
paramsDate: {}, paramsDate: {},
tableOption: { tableOption: {
select: false select: false,
scroll:{y:600}
} }
} }
}, },
@@ -110,7 +111,7 @@ export default {
this.$refs.comTable.loading = false this.$refs.comTable.loading = false
// this.tableData = res.data // this.tableData = res.data
this.tableData = JSON.parse(localStorage.getItem('permission')).map((item) => { this.tableData = res.data.map((item) => {
return { return {
...item, ...item,
key: item.permission_id key: item.permission_id
@@ -203,6 +204,10 @@ export default {
padding: 20px 20px 0 20px; padding: 20px 20px 0 20px;
.content-table { .content-table {
height: calc(100% - 92px); height: calc(100% - 92px);
.treetable{
// overflow: scroll;
}
} }
} }
</style> </style>

View File

@@ -151,7 +151,7 @@ export default {
is_edit: Boolean(+item.is_edit) || false, is_edit: Boolean(+item.is_edit) || false,
is_view: Boolean(+item.is_view) || false, is_view: Boolean(+item.is_view) || false,
// 确保子权限容器存在 // 确保子权限容器存在
children: item.children ? [...item.children] : [] children: item.children ? [...item.children] :undefined
} }
permissionMap.set(item.permission_id, permissionItem) permissionMap.set(item.permission_id, permissionItem)
@@ -183,7 +183,7 @@ export default {
...routeItem, ...routeItem,
...permissionItem, ...permissionItem,
// 初始化子权限容器 // 初始化子权限容器
children: routeItem.children ? buildTree(routeItem.children) : [] children: routeItem.children ? buildTree(routeItem.children) : undefined
} }
// 特殊处理:父级权限的联动计算 // 特殊处理:父级权限的联动计算
@@ -204,52 +204,9 @@ export default {
node.is_del = node.children.some((child) => child.is_del === '1') ? true : false node.is_del = node.children.some((child) => child.is_del === '1') ? true : false
} }
}, },
async getPermissionList() {
let arr = []
const res = await getReq('/queryPermissionList', { page_size: 1000, page: 1 })
if (res.errcode === 0) {
arr = res.data
// const permissionData = JSON.parse(localStorage.getItem('permission'));
// const permissionData = res.data
// arr = permissionData.map((item) => ({
// ...item,
// key: item.permission_id,
// // 转换操作权限为布尔值
// ...this.getPerOperBoolean(item),
// // 递归处理children
// children: item.children
// ? item.children.map((child) => ({
// ...child,
// ...this.getPerOperBoolean(child),
// key: child.permission_id,
// // 继续递归处理子项
// children: child.children
// ? child.children.map((grandchild) => ({
// ...grandchild,
// ...this.getPerOperBoolean(grandchild)
// }))
// : []
// }))
// : []
// }))
}
return arr
},
// 新增专用方法处理操作权限转换
getPerOperBoolean(data) {
return {
is_add: data ? Boolean(+data.is_add) : false,
is_del: data ? Boolean(+data.is_del) : false,
is_edit: data ? Boolean(+data.is_edit) : false,
is_view: data ? Boolean(+data.is_view) : false
}
},
operateForm(type, record = {}) { operateForm(type, record = {}) {
this.formStatus = type this.formStatus = type
switch (type) { switch (type) {
@@ -318,49 +275,70 @@ export default {
row = record row = record
} }
const perList = await this.getPermissionList() const perList = await this.getPermissionList()
function markCheckedPermissions(tree, rolePerms) {
return tree.map((perm) => {
// 深拷贝权限项,避免污染原始数据
const node = { ...perm };
// 检查当前权限是否被角色勾选
const isChecked = rolePerms.some(
(rp) => rp.permission_id === node.permission_id
);
console.log(isChecked,rolePerms,"isChecked")
node.checked = isChecked;
// 递归处理子权限
if (node.children && node.children.length > 0) {
// 找到角色权限中对应的子权限列表
const roleChildPerms = rolePerms.find(
(rp) => rp.permission_id === node.permission_id
)?.children || [];
node.children = markCheckedPermissions(node.children, roleChildPerms);
}else {
node.children =undefined
}
return node;
});
}
const newData = markCheckedPermissions(perList, record.permission);
this.processedData = this.mergePermissionData( this.processedData = this.mergePermissionData(
perList, newData,
record && record.permission.length ? record.permission : [] record && record.permission.length ? record.permission : []
) )
const newData = JSON.parse(JSON.stringify(this.processedData)) // const newData = JSON.parse(JSON.stringify(this.processedData))
this.formModal = true
roleOptions.forEach((e, index) => { roleOptions.forEach((e, index) => {
e.list.forEach((i) => { e.list.forEach((i) => {
if (i.key == 'permission') { if (i.key == 'permission') {
i.tableData = newData i.tableData = this.processedData
if (record && record.role_id) {
i.selectTableData = this.extractAllIds(record.permission)
} else {
i.selectTableData = []
}
} else { } else {
e.ruleForm[i.key] = row ? row[i.key] : '' e.ruleForm[i.key] = row ? row[i.key] : ''
} }
}) })
}) })
this.formModal = true
}, },
// 定义提取所有ID的函数 async getPermissionList() {
extractAllIds(treeData) { let arr = []
const idSet = new Set() const res = await getReq('/queryPermissionList', { page_size: 1000, page: 1 })
if (res.errcode === 0) {
arr = res.data
// 递归遍历函数
const traverse = (node) => {
// 添加当前节点ID
if (node.permission_id) {
idSet.add(node.permission_id)
} }
// 递归处理子节点 return arr
if (node.children && node.children.length > 0) {
node.children.forEach((child) => traverse(child))
}
}
// 处理所有根节点
treeData.forEach((node) => traverse(node))
return Array.from(idSet)
}, },
handlePagesizeChange(pageOption) { handlePagesizeChange(pageOption) {
this.pageOption.pageSize = pageOption.pageSize this.pageOption.pageSize = pageOption.pageSize

View File

@@ -14,7 +14,7 @@ module.exports = defineConfig({
proxy: { proxy: {
'/api': { '/api': {
// 代理前缀,可以自定义(如 '/api' // 代理前缀,可以自定义(如 '/api'
target: 'http://192.168.0.187:19800', // 目标服务器地址 target: 'http://192.168.0.16:19801', // 目标服务器地址
changeOrigin: true, // 是否改变请求源(跨域必备) changeOrigin: true, // 是否改变请求源(跨域必备)
pathRewrite: { pathRewrite: {
'^/api': '' // 重写路径,去掉 '/api' 前缀 '^/api': '' // 重写路径,去掉 '/api' 前缀