20260806224941
This commit is contained in:
1 parent
6baa339efa
commit
6938deef39
12 files changed
+367
-300
No files matched your search
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { computed, h, onBeforeUnmount, ref, watch } from "vue";
|
||||
import { computed, h, ref, watch } from "vue";
|
||||
import { message, Modal } from "antdv-next";
|
||||
import { Plus, Trash2 } from "@lucide/vue";
|
||||
import FmsLoadingOverlay from "@/components/FmsLoadingOverlay.vue";
|
||||
@@ -41,9 +41,7 @@ const treeLoading = ref(false);
|
||||
const expandedTreeKeys = ref([]);
|
||||
const selectedModuleId = ref(null);
|
||||
const skipLoad = ref(false);
|
||||
const expandTimer = ref(null);
|
||||
const activeTab = ref("basic");
|
||||
let expandDelayResolve = null;
|
||||
function buildTreeContextMenu(node) {
|
||||
const items = [];
|
||||
const iconSize = 14;
|
||||
@@ -361,71 +359,16 @@ async function loadModuleConfig(moduleId, options = {}) {
|
||||
}
|
||||
|
||||
// ---- 树节点选择 ----
|
||||
function clearExpandTimer() {
|
||||
if (expandTimer.value != null) {
|
||||
clearTimeout(expandTimer.value);
|
||||
expandTimer.value = null;
|
||||
}
|
||||
if (expandDelayResolve) {
|
||||
expandDelayResolve(false);
|
||||
expandDelayResolve = null;
|
||||
}
|
||||
}
|
||||
|
||||
function waitForExpandAnimation() {
|
||||
return new Promise((resolve) => {
|
||||
expandDelayResolve = (ready) => {
|
||||
resolve(ready);
|
||||
};
|
||||
expandTimer.value = setTimeout(() => {
|
||||
expandTimer.value = null;
|
||||
expandDelayResolve = null;
|
||||
resolve(true);
|
||||
}, 300);
|
||||
});
|
||||
}
|
||||
|
||||
function onTreeSelect(keys, info) {
|
||||
if (busy.value) return;
|
||||
if (info?.node?.isFmsRoot) {
|
||||
selectedModuleId.value = null;
|
||||
clearExpandTimer();
|
||||
return;
|
||||
}
|
||||
const nodeKey = info?.node?.key ?? keys[0];
|
||||
if (nodeKey == null) return;
|
||||
|
||||
const key = String(nodeKey);
|
||||
const node = findNode(key);
|
||||
const hasChildren = node?.children?.length;
|
||||
|
||||
clearExpandTimer();
|
||||
|
||||
if (!hasChildren) {
|
||||
// 叶子节点:立即加载数据
|
||||
selectedModuleId.value = key;
|
||||
return;
|
||||
}
|
||||
|
||||
// 父节点:处理展开/收起
|
||||
const expandedKeys = expandedTreeKeys.value.map(String);
|
||||
const isCurrentlyExpanded = expandedKeys.includes(key);
|
||||
|
||||
if (isCurrentlyExpanded) {
|
||||
// 收起:立即生效,同时加载数据
|
||||
expandedTreeKeys.value = expandedKeys.filter((item) => item !== key);
|
||||
selectedModuleId.value = key;
|
||||
} else {
|
||||
// 展开:立即高亮,下一帧发请求;结果回写最多等到展开动画结束。
|
||||
expandedTreeKeys.value = [...expandedKeys, key];
|
||||
skipLoad.value = true;
|
||||
selectedModuleId.value = key;
|
||||
loadedModuleId.value = null;
|
||||
void loadModuleConfig(key, {
|
||||
waitForPaint: true,
|
||||
applyReady: waitForExpandAnimation(),
|
||||
});
|
||||
}
|
||||
selectedModuleId.value = String(nodeKey);
|
||||
}
|
||||
|
||||
watch(selectedModuleId, (id) => {
|
||||
@@ -846,6 +789,8 @@ async function saveAll() {
|
||||
unsavedModuleIds.delete(moduleId);
|
||||
updateSavedTreeNode(moduleData);
|
||||
if (appStore.locale) await appStore.loadTranslations(appStore.locale);
|
||||
// 刷新权限数据,让菜单立即反映模块结构变更
|
||||
permissionStore.load().catch(() => {});
|
||||
message.success("保存成功");
|
||||
} catch (e) {
|
||||
message.error("保存失败:" + (e.message || e));
|
||||
@@ -1091,8 +1036,6 @@ void permissionStore
|
||||
.load()
|
||||
.then(loadTree)
|
||||
.catch((e) => message.error("模块树加载失败:" + (e.message || e)));
|
||||
|
||||
onBeforeUnmount(clearExpandTimer);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -1161,15 +1104,17 @@ onBeforeUnmount(clearExpandTimer);
|
||||
:disabled="busy"
|
||||
@update:checked="(v) => onSetField('b_canuse', v ? 1 : 0)"
|
||||
/>
|
||||
<a-divider type="vertical" />
|
||||
<span>显示菜单</span>
|
||||
<a-checkbox
|
||||
:checked="drafts.module?.b_canmenu === 1"
|
||||
:disabled="
|
||||
busy || ['data', 'data_category'].includes(drafts.module?.b_module_type)
|
||||
"
|
||||
@update:checked="(v) => onSetField('b_canmenu', v ? 1 : 0)"
|
||||
/>
|
||||
<template v-if="drafts.module?.b_module_type !== 'data'">
|
||||
<a-divider type="vertical" />
|
||||
<span>显示菜单</span>
|
||||
<a-checkbox
|
||||
:checked="drafts.module?.b_canmenu === 1"
|
||||
:disabled="
|
||||
busy || ['data', 'data_category'].includes(drafts.module?.b_module_type)
|
||||
"
|
||||
@update:checked="(v) => onSetField('b_canmenu', v ? 1 : 0)"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="drafts.module?.b_module_type === 'data'">
|
||||
<a-divider type="vertical" />
|
||||
<span>自动编码</span>
|
||||
|
||||
Reference in new issue
Block a user