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

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: [],
selectTableData: [],
columns: [
{
title: '操作',
dataIndex: 'action',
key: 'action',
align: 'center',
scopedSlots: { customRender: 'action' }
},
{
title: '名称',
dataIndex: 'name',

View File

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

View File

@@ -2,7 +2,6 @@
<div class="treetable" ref="treetable">
<a-table
bordered
:loading="loading"
:scroll="tableOption.scroll"
:columns="columns"
@@ -11,18 +10,19 @@
:row-class-name="(record, index) => rowClassName(record, index)"
row-key="key"
size="middle"
:row-selection="newTableOpt.select
?rowSelection:null"
:row-selection="newTableOpt.select ? rowSelection : null"
:indent-size="30"
:check-strictly="false"
@resizeColumn="handleResizeColumn"
>
<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">
<slot
v-bind="{record,index}"
v-bind="{ record, index }"
:name="column.scopedSlots ? column.scopedSlots.customRender : ''"
></slot>
</template>
</template>
@@ -102,7 +102,6 @@ export default {
},
computed: {
rowSelection() {
const { selectedRowKeys } = this
return {
checkStrictly: this.tableOption.checkStrictly,
@@ -114,7 +113,8 @@ export default {
hideDefaultSelections: true,
onSelect: (record, selected) => {
this.onSelect(record, selected)
}
},
}
}
},
@@ -154,7 +154,7 @@ export default {
onSelectChange(selectedRowKeys, selectedRows) {
this.selectedRowKeys = selectedRowKeys
this.selectedRows = selectedRows[selectedRows.length - 1]
this.selectedArr=selectedRows
this.selectedArr = selectedRows
this.$emit('getSelectedIds', selectedRowKeys)
},
onSelect(record, selected) {
@@ -269,7 +269,6 @@ export default {
flex-direction: column;
justify-content: space-between;
.pagination {
display: flex;
justify-content: flex-end;
@@ -282,22 +281,21 @@ export default {
:deep(.ant-table) {
// border-radius:20px 20px 0 0 !important;
overflow: hidden; /* 确保圆角生效 */
}
:deep(.ant-table-wrapper .ant-table.ant-table-bordered >.ant-table-container){
border-inline-start:none!important;
:deep(.ant-table-wrapper .ant-table.ant-table-bordered > .ant-table-container) {
border-inline-start: none !important;
}
:deep(.ant-table-wrapper .ant-table-cell){
background:none!important;
:deep(.ant-table-wrapper .ant-table-cell) {
background: none !important;
}
:deep(.ant-table-thead ){
:deep(.ant-table-thead) {
background: linear-gradient(0deg, rgba(61, 254, 250, 0.2), rgba(61, 254, 250, 0.2)),
linear-gradient(
90deg,
rgba(61, 254, 250, 0) 0%,
rgba(0, 255, 251, 0.15) 50.17%,
rgba(61, 254, 250, 0) 100%
)!important;
) !important;
}
:deep(.ant-table-thead > tr > th) {
border-inline: 1px solid transparent !important;
@@ -306,7 +304,7 @@ export default {
border-bottom: none !important; /* 可选:去除底部边框 */
}
:deep(.ant-pagination) {
:deep(.ant-pagination) {
.ant-pagination-item-link {
color: #fff !important;
height: 100% !important;
@@ -378,8 +376,8 @@ export default {
color: #fff;
background: #1c797a !important;
}
}
:deep(
}
:deep(
.ant-table-wrapper
.ant-table.ant-table-bordered
> .ant-table-container
@@ -388,14 +386,14 @@ export default {
) {
border-top: none !important;
border-inline-start: none !important;
}
:deep(.ant-checkbox-checked .ant-checkbox-inner) {
}
:deep(.ant-checkbox-checked .ant-checkbox-inner) {
background-color: var(--table-header-bg) !important;
border: none !important;
}
:deep(.ant-checkbox-indeterminate .ant-checkbox-inner:after) {
}
:deep(.ant-checkbox-indeterminate .ant-checkbox-inner:after) {
background-color: var(--table-header-bg) !important;
}
}
:deep(
.ant-table.ant-table-bordered
> .ant-table-container
@@ -441,12 +439,10 @@ export default {
}
:deep(.ant-table-container > .ant-table-content > table) {
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;
}
:deep(.ant-pagination-item-link) {
color: var(--theme-text-default) !important;
@@ -455,11 +451,17 @@ export default {
display: block !important;
// border: none !important;
}
:deep(.ant-table-wrapper .ant-table.ant-table-bordered >.ant-table-container >.ant-table-content >table){
border-top:none;
:deep(
.ant-table-wrapper
.ant-table.ant-table-bordered
> .ant-table-container
> .ant-table-content
> table
) {
border-top: none;
}
:deep(.ant-table-tbody) {
color: #fff!important;
color: #fff !important;
> tr {
&:hover {
> td {
@@ -499,8 +501,17 @@ export default {
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){
border-inline-end: none!important;
:deep(
.ant-table-wrapper
.ant-table.ant-table-bordered
> .ant-table-container
> .ant-table-body
> table
> tbody
> tr
> td
) {
border-inline-end: none !important;
}
:deep(.ant-table-thead) {
background: var(--table-header-bg);
@@ -510,11 +521,9 @@ export default {
> tr {
&:hover {
> .ant-table-cell {
background-color: transparent !important;
}
}
}
}
@@ -523,9 +532,9 @@ export default {
.ant-table.ant-table-bordered > .ant-table-container {
box-shadow: none !important;
&>.ant-table-body >table >tbody>tr>td{
& > .ant-table-body > table > tbody > tr > td {
border-bottom: none !important;
}
}
}
}
@@ -535,15 +544,11 @@ export default {
background-color: transparent !important;
}
:deep(.ant-table-wrapper .ant-table-thead th.ant-table-column-has-sorters:hover) {
background: var(--table-select) !important;
}
:deep(.ant-table-wrapper .ant-table-row-expand-icon){
background:#2c538a!important;
:deep(.ant-table-wrapper .ant-table-row-expand-icon) {
background: #2c538a !important;
}
</style>

View File

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

View File

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

View File

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

View File

@@ -151,7 +151,7 @@ export default {
is_edit: Boolean(+item.is_edit) || 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)
@@ -183,7 +183,7 @@ export default {
...routeItem,
...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
}
},
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 = {}) {
this.formStatus = type
switch (type) {
@@ -318,49 +275,70 @@ export default {
row = record
}
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(
perList,
newData,
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) => {
e.list.forEach((i) => {
if (i.key == 'permission') {
i.tableData = newData
if (record && record.role_id) {
i.selectTableData = this.extractAllIds(record.permission)
} else {
i.selectTableData = []
}
i.tableData = this.processedData
} else {
e.ruleForm[i.key] = row ? row[i.key] : ''
}
})
})
this.formModal = true
},
// 定义提取所有ID的函数
extractAllIds(treeData) {
const idSet = new Set()
async getPermissionList() {
let arr = []
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)
}
// 递归处理子节点
if (node.children && node.children.length > 0) {
node.children.forEach((child) => traverse(child))
}
}
// 处理所有根节点
treeData.forEach((node) => traverse(node))
return Array.from(idSet)
return arr
},
handlePagesizeChange(pageOption) {
this.pageOption.pageSize = pageOption.pageSize

View File

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