|
@@ -149,16 +149,18 @@
|
|
|
watch(
|
|
|
() => props.modelValue,
|
|
|
(newValue) => {
|
|
|
+ // 如果正在进行权限选择操作,只更新checkedIds,不触发其他计算
|
|
|
+ if (isSelectingPermission) {
|
|
|
+ state.checkedIds = newValue || [];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
state.checkedIds = newValue || [];
|
|
|
|
|
|
// 当modelValue变化时,重新计算权限状态(无论数据是否为空都要计算)
|
|
|
- let appItem = initAppItem();
|
|
|
if (state.app.length > 0) {
|
|
|
+ let appItem = initAppItem();
|
|
|
initCalculate(state.app, appItem);
|
|
|
- }
|
|
|
-
|
|
|
- // 如果不是权限选择操作导致的变化,才重置展开状态
|
|
|
- if (!isSelectingPermission) {
|
|
|
calculateShow(appItem);
|
|
|
}
|
|
|
},
|
|
@@ -169,16 +171,18 @@
|
|
|
watch(
|
|
|
() => state.app,
|
|
|
(newApp) => {
|
|
|
+ // 如果正在进行权限选择操作,跳过所有处理
|
|
|
+ if (isSelectingPermission) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
// 无论数据是否为空都要初始化显示状态
|
|
|
let appItem = initAppItem();
|
|
|
if (newApp && newApp.length > 0) {
|
|
|
initCalculate(newApp, appItem);
|
|
|
}
|
|
|
|
|
|
- // 如果不是权限选择操作导致的变化,才重置展开状态
|
|
|
- if (!isSelectingPermission) {
|
|
|
- calculateShow(appItem);
|
|
|
- }
|
|
|
+ calculateShow(appItem);
|
|
|
},
|
|
|
);
|
|
|
|
|
@@ -189,19 +193,18 @@
|
|
|
return [];
|
|
|
}
|
|
|
|
|
|
- console.log('🔄 transformPermissionData - 输入数据:', data);
|
|
|
-
|
|
|
const result = data.map((item) => {
|
|
|
- console.log('🔄 transformPermissionData - 处理项目:', item);
|
|
|
-
|
|
|
const transformed = {
|
|
|
id: item.id,
|
|
|
- title: item.name, // 使用name作为title
|
|
|
+ title: item.name || item.label, // 优先使用name,备用label
|
|
|
icon: item.logo || 'menu', // 使用logo作为icon,默认为menu
|
|
|
children:
|
|
|
item.children && Array.isArray(item.children)
|
|
|
? transformPermissionData(item.children)
|
|
|
: [],
|
|
|
+ // 根据hasRelevance字段设置选中状态
|
|
|
+ checked: item.hasRelevance === '1',
|
|
|
+ indeterminate: false,
|
|
|
// 保留原始数据以备后用
|
|
|
_original: item,
|
|
|
};
|
|
@@ -218,40 +221,45 @@
|
|
|
state.loading = true;
|
|
|
|
|
|
try {
|
|
|
- // 调用新的权限树接口
|
|
|
- const response = await admin.auth.access.getTree();
|
|
|
-
|
|
|
- if (response.success && response.data !== null && response.data !== undefined) {
|
|
|
- console.log('🔍 getData - 原始响应数据:', response.data);
|
|
|
-
|
|
|
- // 转换数据格式(即使是空数组也要处理)
|
|
|
- const transformedData = Array.isArray(response.data)
|
|
|
- ? transformPermissionData(response.data)
|
|
|
- : [];
|
|
|
+ let permissionData = [];
|
|
|
|
|
|
- console.log('🔍 getData - 转换后数据:', transformedData);
|
|
|
+ // 根据type类型获取不同的数据
|
|
|
+ if (props.type === 'select' && props.role_id) {
|
|
|
+ // 权限选择模式且有角色ID,获取角色详情中的权限数据
|
|
|
+ console.log('🔍 获取角色权限数据, role_id:', props.role_id);
|
|
|
+ const roleResponse = await admin.auth.role.detail(props.role_id);
|
|
|
|
|
|
- // 根据type类型处理数据
|
|
|
- if (props.type === 'select') {
|
|
|
- // 权限选择模式,使用完整的权限数据
|
|
|
- state.app = transformedData;
|
|
|
- } else {
|
|
|
- // 其他模式(如list),也使用权限数据
|
|
|
- state.app = transformedData;
|
|
|
+ if (roleResponse.code == 200 && roleResponse.data && roleResponse.data.permissions) {
|
|
|
+ console.log('🔍 getData - 角色权限数据:', roleResponse.data.permissions);
|
|
|
+ permissionData = roleResponse.data.permissions;
|
|
|
}
|
|
|
+ } else {
|
|
|
+ // 其他模式,获取完整权限树
|
|
|
+ const response = await admin.auth.access.getTree();
|
|
|
|
|
|
- // 初始化显示状态(无论数据是否为空都要初始化)
|
|
|
- let appItem = initAppItem();
|
|
|
- if (transformedData.length > 0) {
|
|
|
- initCalculate(transformedData, appItem);
|
|
|
+ if (response.success && response.data !== null && response.data !== undefined) {
|
|
|
+ console.log('🔍 getData - 权限树数据:', response.data);
|
|
|
+ permissionData = response.data;
|
|
|
}
|
|
|
- calculateShow(appItem);
|
|
|
- } else {
|
|
|
- console.error('获取权限数据失败:', response.message || '数据为空');
|
|
|
- state.app = [];
|
|
|
+ }
|
|
|
|
|
|
- // 即使没有数据也要初始化显示状态
|
|
|
- let appItem = initAppItem();
|
|
|
+ // 转换数据格式(即使是空数组也要处理)
|
|
|
+ const transformedData = Array.isArray(permissionData)
|
|
|
+ ? transformPermissionData(permissionData)
|
|
|
+ : [];
|
|
|
+
|
|
|
+ console.log('🔍 getData - 转换后数据:', transformedData);
|
|
|
+
|
|
|
+ state.app = transformedData;
|
|
|
+
|
|
|
+ // 初始化显示状态(无论数据是否为空都要初始化)
|
|
|
+ let appItem = initAppItem();
|
|
|
+ if (transformedData.length > 0) {
|
|
|
+ initCalculate(transformedData, appItem);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果不是权限选择操作导致的变化,才重置展开状态
|
|
|
+ if (!isSelectingPermission) {
|
|
|
calculateShow(appItem);
|
|
|
}
|
|
|
} catch (error) {
|
|
@@ -260,7 +268,9 @@
|
|
|
|
|
|
// 异常情况下也要初始化显示状态
|
|
|
let appItem = initAppItem();
|
|
|
- calculateShow(appItem);
|
|
|
+ if (!isSelectingPermission) {
|
|
|
+ calculateShow(appItem);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
state.loading = false;
|
|
@@ -535,39 +545,36 @@
|
|
|
return checkedIdStr === itemIdStr || checkedIdNum === itemIdNum;
|
|
|
});
|
|
|
|
|
|
- if (isChecked) {
|
|
|
- if (!isEmpty(item.children)) {
|
|
|
- let arr = [];
|
|
|
- flattenData(item.children, arr);
|
|
|
- const allChildrenChecked = arr.every((k) => {
|
|
|
- const kIdStr = String(k.id);
|
|
|
- const kIdNum = Number(k.id);
|
|
|
- return state.checkedIds.some((checkedId) => {
|
|
|
- const checkedIdStr = String(checkedId);
|
|
|
- const checkedIdNum = Number(checkedId);
|
|
|
- return checkedIdStr === kIdStr || checkedIdNum === kIdNum;
|
|
|
- });
|
|
|
- });
|
|
|
+ // 先递归处理子项
|
|
|
+ if (!isEmpty(item.children)) {
|
|
|
+ initCalculate(item.children, item);
|
|
|
|
|
|
- if (allChildrenChecked) {
|
|
|
- item.checked = true;
|
|
|
- item.indeterminate = false;
|
|
|
- } else {
|
|
|
- item.checked = false;
|
|
|
- item.indeterminate = true;
|
|
|
- }
|
|
|
- } else {
|
|
|
+ // 检查子项的选中状态
|
|
|
+ const checkedChildren = item.children.filter((child) => child.checked);
|
|
|
+ const indeterminateChildren = item.children.filter((child) => child.indeterminate);
|
|
|
+
|
|
|
+ // 如果父级本身被明确选中,保持选中状态
|
|
|
+ if (isChecked) {
|
|
|
item.checked = true;
|
|
|
item.indeterminate = false;
|
|
|
+ } else if (checkedChildren.length === item.children.length) {
|
|
|
+ // 所有子项都选中
|
|
|
+ item.checked = true;
|
|
|
+ item.indeterminate = false;
|
|
|
+ } else if (checkedChildren.length > 0 || indeterminateChildren.length > 0) {
|
|
|
+ // 部分子项选中或有半选状态
|
|
|
+ item.checked = false;
|
|
|
+ item.indeterminate = true;
|
|
|
+ } else {
|
|
|
+ // 没有子项选中
|
|
|
+ item.checked = false;
|
|
|
+ item.indeterminate = false;
|
|
|
}
|
|
|
} else {
|
|
|
- item.checked = false;
|
|
|
+ // 叶子节点,直接根据是否在选中列表中设置状态
|
|
|
+ item.checked = isChecked;
|
|
|
item.indeterminate = false;
|
|
|
}
|
|
|
-
|
|
|
- if (!isEmpty(item.children)) {
|
|
|
- initCalculate(item.children, item);
|
|
|
- }
|
|
|
});
|
|
|
}
|
|
|
|
|
@@ -626,8 +633,9 @@
|
|
|
}
|
|
|
|
|
|
function handleSelect(checked, item) {
|
|
|
+ // 设置标志,阻止watch触发
|
|
|
+ isSelectingPermission = true;
|
|
|
manualChecked = true;
|
|
|
- isSelectingPermission = true; // 设置权限选择标志
|
|
|
|
|
|
// 计算所有子元素
|
|
|
doChecked(item, checked);
|
|
@@ -635,14 +643,17 @@
|
|
|
// 计算父元素
|
|
|
doCheckedParent(item);
|
|
|
|
|
|
- state.newIds = [];
|
|
|
- getCheckedIds(state.app);
|
|
|
- emit('update:modelValue', state.newIds);
|
|
|
+ // 收集选中的权限ID
|
|
|
+ const newIds = [];
|
|
|
+ getCheckedIds(state.app, newIds);
|
|
|
|
|
|
- // 延迟重置标志,确保watch执行完毕
|
|
|
- nextTick(() => {
|
|
|
+ // 直接发送事件,不更新state.newIds避免触发watch
|
|
|
+ emit('update:modelValue', newIds);
|
|
|
+
|
|
|
+ // 延迟重置标志
|
|
|
+ setTimeout(() => {
|
|
|
isSelectingPermission = false;
|
|
|
- });
|
|
|
+ }, 50);
|
|
|
}
|
|
|
|
|
|
function doChecked(item, checked) {
|
|
@@ -767,20 +778,8 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- watch(
|
|
|
- () => state.app,
|
|
|
- async () => {
|
|
|
- if (manualChecked) {
|
|
|
- state.newIds = [];
|
|
|
- getCheckedIds(state.app);
|
|
|
-
|
|
|
- emit('update:modelValue', state.newIds);
|
|
|
- }
|
|
|
- },
|
|
|
- {
|
|
|
- deep: true,
|
|
|
- },
|
|
|
- );
|
|
|
+ // 移除可能导致递归更新的watch监听器
|
|
|
+ // 权限选择的更新通过handleSelect函数直接处理
|
|
|
|
|
|
watch(
|
|
|
() => props.role_id,
|
|
@@ -792,13 +791,21 @@
|
|
|
},
|
|
|
);
|
|
|
|
|
|
- function getCheckedIds(data) {
|
|
|
+ function getCheckedIds(data, targetArray = null) {
|
|
|
+ const idsArray = targetArray || state.newIds;
|
|
|
+
|
|
|
data.forEach((i) => {
|
|
|
- if (i.checked || i.indeterminate) {
|
|
|
- state.newIds.push(i.id + '');
|
|
|
+ // 收集真正选中的权限(全选状态)
|
|
|
+ if (i.checked && !i.indeterminate) {
|
|
|
+ idsArray.push(i.id + '');
|
|
|
+ }
|
|
|
+ // 收集半选状态的父级权限(当子级被选中时,父级也要包含)
|
|
|
+ else if (i.indeterminate) {
|
|
|
+ idsArray.push(i.id + '');
|
|
|
}
|
|
|
+
|
|
|
if (!isEmpty(i.children)) {
|
|
|
- getCheckedIds(i.children);
|
|
|
+ getCheckedIds(i.children, idsArray);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
@@ -908,8 +915,6 @@
|
|
|
const indent = ' '.repeat(level);
|
|
|
|
|
|
for (const item of items) {
|
|
|
- console.log(`${indent}当前检查的item:`, item);
|
|
|
-
|
|
|
// 现在可以安全使用_original字段了
|
|
|
const originalData = item._original || {};
|
|
|
const itemName = originalData.name || '';
|
|
@@ -918,12 +923,6 @@
|
|
|
// 备用匹配:如果原始数据没有name,尝试使用转换后的title
|
|
|
const fallbackName = item.title || '';
|
|
|
|
|
|
- console.log(
|
|
|
- `${indent}检查权限: 名称="${itemName}", 备用名称="${fallbackName}", 父ID="${itemParentId}"`,
|
|
|
- );
|
|
|
- console.log(`${indent}原始数据:`, originalData);
|
|
|
- console.log(`${indent}item._original存在:`, !!item._original);
|
|
|
-
|
|
|
// 匹配权限名称和父ID(优先使用原始数据的name字段,备用title字段)
|
|
|
const nameMatches = itemName === name || (itemName === '' && fallbackName === name);
|
|
|
|
|
@@ -932,26 +931,12 @@
|
|
|
const isTopLevel = !parentId || parentId === '' || parentId === '0';
|
|
|
const itemIsTopLevel = !itemParentId || itemParentId === '' || itemParentId === '0';
|
|
|
|
|
|
- console.log(
|
|
|
- `${indent}🔍 匹配检查: 查找="${name}" vs 权限="${itemName}" vs 备用="${fallbackName}"`,
|
|
|
- );
|
|
|
- console.log(`${indent}🔍 父ID检查: 查找="${parentId}" vs 权限="${itemParentId}"`);
|
|
|
- console.log(
|
|
|
- `${indent}🔍 顶级检查: 查找顶级=${isTopLevel}, 权限顶级=${itemIsTopLevel}`,
|
|
|
- );
|
|
|
-
|
|
|
// 🎯 修复:父ID匹配逻辑
|
|
|
const parentIdMatches =
|
|
|
(isTopLevel && itemIsTopLevel) || String(itemParentId) === String(parentId);
|
|
|
|
|
|
- console.log(`${indent}🔍 父ID匹配结果: ${parentIdMatches}`);
|
|
|
- console.log(
|
|
|
- `${indent}🔍 详细比较: "${String(itemParentId)}" === "${String(parentId)}" = ${String(itemParentId) === String(parentId)}`,
|
|
|
- );
|
|
|
-
|
|
|
if (parentIdMatches) {
|
|
|
const matchedName = itemName || fallbackName;
|
|
|
- console.log(`${indent}✅ 找到匹配权限: ${matchedName}, ID: ${item.id}`);
|
|
|
return item.id;
|
|
|
} else {
|
|
|
console.log(`${indent}❌ 父ID不匹配,跳过此权限`);
|