From: CodeBuddy Date: Wed, 23 Sep 2026 02:29:33 +0000 (+0800) Subject: fix(vue): 修复配置站点纯白页与菜单交互失效 X-Git-Url: http://acesimba.cloud/gitweb/?a=commitdiff_plain;h=20cdd4926407efd4da8cf59ba0fbc4b83fa552e5;p=StationBuilder.git fix(vue): 修复配置站点纯白页与菜单交互失效 - App.vue: theme.getDesignToken 在 antd-vue 不存在, 改为 useToken() 注入 --ant-* 设计令牌, 否则整页无样式纯白 - Home.vue: 补 setLoading (React useState 残留未定义导致 onMounted 抛错数据不加载); SideMenu :on-click/:on-open-change 改为 @click/@open-change 事件绑定 - ui/parse.js: 新增 childContent() 处理 Vue vnode children 结构 (原直接读 props.children 为 React 写法, 导致 UiTable/Overlay/Actions 渲染 0 行) - ui/UiTabbedRegion.vue: antd-vue Tabs 无 items 属性, 改用 TabPane 子节点 - lib/api.js: loadRenderer 改为加载 echarts.min.js + dashboard-renderer.js (原 cube-renderer.js 404) --- diff --git a/src-vue/App.vue b/src-vue/App.vue index a2fcaab..046d179 100644 --- a/src-vue/App.vue +++ b/src-vue/App.vue @@ -1,5 +1,5 @@ diff --git a/src-vue/Home.vue b/src-vue/Home.vue index e400a6a..9b6020a 100644 --- a/src-vue/Home.vue +++ b/src-vue/Home.vue @@ -94,6 +94,7 @@ const sites = ref([]); const siteId = ref(null); const site = ref(null); const loading = ref(true); +const setLoading = (v) => (loading.value = v); const saving = ref(false); const dirty = ref(false); const domains = ref([]); @@ -513,8 +514,8 @@ function onMenuOpenChange(keys) { resourceNavOpen.value = keys.includes("resourc :collapsed="navCollapsed" :selected-keys="[domainArea ? 'domains' : projectArea ? 'projects' : page]" :open-keys="navCollapsed ? undefined : [...(resourceNavOpen ? ['resources'] : []), ...(systemNavOpen ? ['system'] : [])]" - :on-open-change="onMenuOpenChange" - :on-click="onMenuClick" + @open-change="onMenuOpenChange" + @click="onMenuClick" :items="menuItems" /> diff --git a/src-vue/lib/api.js b/src-vue/lib/api.js index 710c03a..9ae194a 100644 --- a/src-vue/lib/api.js +++ b/src-vue/lib/api.js @@ -71,20 +71,26 @@ export function domainTagColor(name) { } // Cube renderer loader (used by DashboardThumb / DomainPageThumb). +// Mirrors React page.tsx: echarts.min.js first, then dashboard-renderer.js, +// resolving window.renderDashboard; resets on failure so it can be retried. let rendererPromise = null; -export function loadRenderer() { - if (rendererPromise) return rendererPromise; - rendererPromise = new Promise((resolve, reject) => { - const w = window; - if (w.StationBuilderCubeRenderer) { - resolve(w.StationBuilderCubeRenderer); - return; - } +function loadScript(src) { + return new Promise((resolve, reject) => { const s = document.createElement("script"); - s.src = "/t/stationbuilder/cube-renderer.js"; - s.onload = () => (w.StationBuilderCubeRenderer ? resolve(w.StationBuilderCubeRenderer) : reject(new Error("renderer missing"))); + s.src = src; + s.onload = resolve; s.onerror = () => reject(new Error("renderer load failed")); document.head.appendChild(s); }); +} +export function loadRenderer() { + if (rendererPromise) return rendererPromise; + rendererPromise = loadScript("/t/stationbuilder/echarts.min.js") + .then(() => loadScript("/t/stationbuilder/dashboard-renderer.js")) + .then(() => window.renderDashboard) + .catch((error) => { + rendererPromise = null; + throw error; + }); return rendererPromise; } diff --git a/src-vue/ui/UiActions.vue b/src-vue/ui/UiActions.vue index 38786d4..755dae6 100644 --- a/src-vue/ui/UiActions.vue +++ b/src-vue/ui/UiActions.vue @@ -7,7 +7,7 @@ import { } from "ant-design-vue"; import { EllipsisOutlined } from "@ant-design/icons-vue"; import UiButton from "./UiButton.vue"; -import { elements, textOf, classOf } from "./parse.js"; +import { elements, textOf, classOf, childContent } from "./parse.js"; export default { setup() { @@ -78,7 +78,7 @@ export default { disabled: !!(a.props && a.props.disabled), onClick: (e) => triggerAction(a, e.domEvent || e), }, - () => textOf(a.props ? a.props.children : a.children) + () => textOf(childContent(a)) ) ); children.push( diff --git a/src-vue/ui/UiOverlay.vue b/src-vue/ui/UiOverlay.vue index b1a30a7..cb9f6af 100644 --- a/src-vue/ui/UiOverlay.vue +++ b/src-vue/ui/UiOverlay.vue @@ -2,7 +2,7 @@ import { h, useSlots, useAttrs, Fragment } from "vue"; import { Modal as AntModal } from "ant-design-vue"; import UiActions from "./UiActions.vue"; -import { elements, textOf, classOf } from "./parse.js"; +import { elements, textOf, classOf, childContent } from "./parse.js"; export default { setup() { @@ -15,10 +15,10 @@ export default { const inner = all.find((c) => /\b(modal|dlg-box)\b/.test(classOf(c))); if (!inner) return null; - const innerChildren = elements(inner.props?.children); + const innerChildren = elements(childContent(inner)); const header = innerChildren.find((p) => p.type === "header"); const heading = - (header ? elements(header.props.children) : []).find((p) => p.type === "h2") || + (header ? elements(childContent(header)) : []).find((p) => p.type === "h2") || innerChildren.find((p) => p.type === "h2"); const footer = innerChildren.find( (p) => @@ -44,15 +44,15 @@ export default { else if (attrs.onClick) close = attrs.onClick; else { const hdrBtn = header - ? elements(header.props.children).find( + ? elements(childContent(header)).find( (p) => p.props && p.props.onClick && !p.props.disabled ) : null; if (hdrBtn) close = hdrBtn.props.onClick; else if (footer) { - const cancel = elements(footer.props.children).find( + const cancel = elements(childContent(footer)).find( (p) => - textOf(p.props ? p.props.children : p.children).includes("取消") && + textOf(childContent(p)).includes("取消") && p.props && !p.props.disabled ); @@ -72,7 +72,7 @@ export default { const modalProps = { open: true, centered: true, - title: heading ? heading.props.children : undefined, + title: heading ? childContent(heading) : undefined, width, class: name + " station-ui-modal", closable: !!close, @@ -84,7 +84,7 @@ export default { const modalSlots = { default: () => body }; if (footer) { modalSlots.footer = () => - h(UiActions, { class: "station-modal-actions" }, () => footer.props.children); + h(UiActions, { class: "station-modal-actions" }, () => childContent(footer)); } else { modalProps.footer = null; } diff --git a/src-vue/ui/UiTabbedRegion.vue b/src-vue/ui/UiTabbedRegion.vue index 79c503a..5cb3c02 100644 --- a/src-vue/ui/UiTabbedRegion.vue +++ b/src-vue/ui/UiTabbedRegion.vue @@ -1,7 +1,7 @@ diff --git a/src-vue/ui/UiTable.vue b/src-vue/ui/UiTable.vue index fcdb491..b5bf2c9 100644 --- a/src-vue/ui/UiTable.vue +++ b/src-vue/ui/UiTable.vue @@ -1,6 +1,6 @@