From c74333c7e68bc0b09fb4bf68f4a10199097b3c15 Mon Sep 17 00:00:00 2001 From: CodeBuddy Date: Wed, 23 Sep 2026 06:36:47 +0800 Subject: [PATCH] =?utf8?q?Vue3=20=E7=A7=BB=E6=A4=8D=E7=89=88=20StationBuil?= =?utf8?q?der=20=E5=85=A8=E9=87=8F=E9=A1=B5=E9=9D=A2=E4=B8=8E=E9=83=A8?= =?utf8?q?=E7=BD=B2=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit - 在 src-vue 下完成 Vue3 + ant-design-vue 对 React 版 StationBuilder 的全量移植 (站点管理/基本信息/资产/页面配置/菜单配置/生成/结果/预览/领域方案/ 样式库/设备模板/内部工具/领域配置 等全部页面与向导、API 接线) - 抽取跨文件共用的 DeviceTemplateCard 到 src-vue/components/DeviceTemplateCard.js - Vue 使用独立 root(src-vue) 与 HTML 入口,与 React 的 index.html 解耦,避免影响 React 构建 - vite.local.config.js: base /t/stationbuilder-vue,outDir 固定 dist-vue - 部署:新增 stationbuilder-vue.service(vite preview :37834)、nginx /t/stationbuilder-vue* 门禁反代(任务 stationbuilder-vue)、tasks.json 新增可管理任务 - .gitignore 忽略 dist-vue 构建产物;不提交运行时 DB 数据 --- .gitignore | 2 + package-lock.json | 993 ++++++---------- package.json | 3 + src-vue/App.vue | 41 + src-vue/Home.vue | 685 +++++++++++ src-vue/components/Dashboard.vue | 5 + src-vue/components/DashboardThumb.vue | 48 + src-vue/components/DeviceTemplateCard.js | 475 ++++++++ src-vue/components/DomainPageThumb.vue | 51 + src-vue/components/DropdownButton.vue | 36 + src-vue/components/Field.vue | 14 + src-vue/components/ImagePage.vue | 9 + src-vue/components/Login.vue | 29 + src-vue/components/Modal.vue | 125 ++ src-vue/components/Pagination.vue | 52 + src-vue/components/Panel.vue | 27 + src-vue/components/PrimaryButton.vue | 24 + src-vue/components/ResourcePlaceholder.vue | 11 + src-vue/components/SearchInput.vue | 27 + src-vue/components/SideMenu.vue | 30 + src-vue/components/SiteEditTabs.vue | 24 + src-vue/components/StatusTag.vue | 17 + src-vue/components/Steps.vue | 24 + src-vue/components/SvgIcon.vue | 46 + src-vue/components/dropdown-button.less | 133 +++ src-vue/components/header.less | 242 ++++ src-vue/components/menu.less | 201 ++++ src-vue/components/pagination.less | 101 ++ src-vue/components/search-input.less | 36 + src-vue/index.html | 12 + src-vue/lib/api.js | 90 ++ src-vue/lib/meta.js | 54 + src-vue/main.js | 24 + src-vue/pages/Assets.vue | 284 +++++ src-vue/pages/Basic.vue | 245 ++++ src-vue/pages/Dashboard.vue | 5 + src-vue/pages/DeviceTemplates.vue | 251 ++++ src-vue/pages/DomainSettings.vue | 610 ++++++++++ src-vue/pages/Functions.vue | 435 +++++++ src-vue/pages/Generate.vue | 60 + src-vue/pages/ManualAssetConfiguration.vue | 1054 +++++++++++++++++ src-vue/pages/PageConfig.vue | 323 +++++ src-vue/pages/Placeholder.vue | 17 + src-vue/pages/Preview.vue | 145 +++ src-vue/pages/Projects.vue | 442 +++++++ src-vue/pages/Result.vue | 167 +++ src-vue/pages/SiteConfigurationContext.vue | 35 + src-vue/pages/StyleLibrary.vue | 145 +++ src-vue/pages/ToolSettings.vue | 51 + src-vue/pages/domain/CompanyDomainLibrary.vue | 127 ++ src-vue/pages/domain/DeviceImageField.vue | 24 + src-vue/pages/domain/DeviceTemplateCreate.vue | 68 ++ .../pages/domain/DomainCapabilityDetail.vue | 394 ++++++ src-vue/pages/domain/DomainDetail.vue | 48 + src-vue/pages/domain/DomainFunctionsStep.vue | 186 +++ src-vue/pages/domain/DomainGenerateReview.vue | 157 +++ src-vue/pages/domain/DomainKnowledgeStep.vue | 139 +++ .../pages/domain/DomainPagePreviewModal.vue | 93 ++ src-vue/pages/domain/DomainSteps.vue | 43 + src-vue/pages/domain/DomainStyleLibrary.vue | 67 ++ src-vue/pages/domain/DomainWizard.vue | 709 +++++++++++ src-vue/pages/domain/ImportDomainPackage.vue | 111 ++ src-vue/pages/domain/PackageModal.vue | 56 + src-vue/pages/domain/StyleEditorModal.vue | 173 +++ src-vue/pages/domain/StylePreview.vue | 23 + src-vue/pages/domain/domainCommon.js | 116 ++ src-vue/pages/domain/useConfirm.js | 59 + src-vue/site-menu-model.js | 115 ++ src-vue/styles/antd.less | 88 ++ src-vue/styles/brand-layout.css | 52 + src-vue/styles/globals.css | 579 +++++++++ src-vue/styles/site-workspace.css | 73 ++ src-vue/styles/styles.less | 51 + src-vue/styles/theme-overrides.css | 47 + src-vue/styles/theme.json | 62 + src-vue/styles/ui-layout-compat.css | 130 ++ src-vue/styles/ui-system.css | 92 ++ src-vue/ui/UiActions.vue | 107 ++ src-vue/ui/UiButton.vue | 54 + src-vue/ui/UiInput.vue | 88 ++ src-vue/ui/UiOverlay.vue | 96 ++ src-vue/ui/UiSelect.vue | 63 + src-vue/ui/UiTabbedRegion.vue | 52 + src-vue/ui/UiTable.vue | 88 ++ src-vue/ui/parse.js | 57 + vite.local.config.js | 48 + 86 files changed, 11856 insertions(+), 639 deletions(-) create mode 100644 src-vue/App.vue create mode 100644 src-vue/Home.vue create mode 100644 src-vue/components/Dashboard.vue create mode 100644 src-vue/components/DashboardThumb.vue create mode 100644 src-vue/components/DeviceTemplateCard.js create mode 100644 src-vue/components/DomainPageThumb.vue create mode 100644 src-vue/components/DropdownButton.vue create mode 100644 src-vue/components/Field.vue create mode 100644 src-vue/components/ImagePage.vue create mode 100644 src-vue/components/Login.vue create mode 100644 src-vue/components/Modal.vue create mode 100644 src-vue/components/Pagination.vue create mode 100644 src-vue/components/Panel.vue create mode 100644 src-vue/components/PrimaryButton.vue create mode 100644 src-vue/components/ResourcePlaceholder.vue create mode 100644 src-vue/components/SearchInput.vue create mode 100644 src-vue/components/SideMenu.vue create mode 100644 src-vue/components/SiteEditTabs.vue create mode 100644 src-vue/components/StatusTag.vue create mode 100644 src-vue/components/Steps.vue create mode 100644 src-vue/components/SvgIcon.vue create mode 100644 src-vue/components/dropdown-button.less create mode 100644 src-vue/components/header.less create mode 100644 src-vue/components/menu.less create mode 100644 src-vue/components/pagination.less create mode 100644 src-vue/components/search-input.less create mode 100644 src-vue/index.html create mode 100644 src-vue/lib/api.js create mode 100644 src-vue/lib/meta.js create mode 100644 src-vue/main.js create mode 100644 src-vue/pages/Assets.vue create mode 100644 src-vue/pages/Basic.vue create mode 100644 src-vue/pages/Dashboard.vue create mode 100644 src-vue/pages/DeviceTemplates.vue create mode 100644 src-vue/pages/DomainSettings.vue create mode 100644 src-vue/pages/Functions.vue create mode 100644 src-vue/pages/Generate.vue create mode 100644 src-vue/pages/ManualAssetConfiguration.vue create mode 100644 src-vue/pages/PageConfig.vue create mode 100644 src-vue/pages/Placeholder.vue create mode 100644 src-vue/pages/Preview.vue create mode 100644 src-vue/pages/Projects.vue create mode 100644 src-vue/pages/Result.vue create mode 100644 src-vue/pages/SiteConfigurationContext.vue create mode 100644 src-vue/pages/StyleLibrary.vue create mode 100644 src-vue/pages/ToolSettings.vue create mode 100644 src-vue/pages/domain/CompanyDomainLibrary.vue create mode 100644 src-vue/pages/domain/DeviceImageField.vue create mode 100644 src-vue/pages/domain/DeviceTemplateCreate.vue create mode 100644 src-vue/pages/domain/DomainCapabilityDetail.vue create mode 100644 src-vue/pages/domain/DomainDetail.vue create mode 100644 src-vue/pages/domain/DomainFunctionsStep.vue create mode 100644 src-vue/pages/domain/DomainGenerateReview.vue create mode 100644 src-vue/pages/domain/DomainKnowledgeStep.vue create mode 100644 src-vue/pages/domain/DomainPagePreviewModal.vue create mode 100644 src-vue/pages/domain/DomainSteps.vue create mode 100644 src-vue/pages/domain/DomainStyleLibrary.vue create mode 100644 src-vue/pages/domain/DomainWizard.vue create mode 100644 src-vue/pages/domain/ImportDomainPackage.vue create mode 100644 src-vue/pages/domain/PackageModal.vue create mode 100644 src-vue/pages/domain/StyleEditorModal.vue create mode 100644 src-vue/pages/domain/StylePreview.vue create mode 100644 src-vue/pages/domain/domainCommon.js create mode 100644 src-vue/pages/domain/useConfirm.js create mode 100644 src-vue/site-menu-model.js create mode 100644 src-vue/styles/antd.less create mode 100644 src-vue/styles/brand-layout.css create mode 100644 src-vue/styles/globals.css create mode 100644 src-vue/styles/site-workspace.css create mode 100644 src-vue/styles/styles.less create mode 100644 src-vue/styles/theme-overrides.css create mode 100644 src-vue/styles/theme.json create mode 100644 src-vue/styles/ui-layout-compat.css create mode 100644 src-vue/styles/ui-system.css create mode 100644 src-vue/ui/UiActions.vue create mode 100644 src-vue/ui/UiButton.vue create mode 100644 src-vue/ui/UiInput.vue create mode 100644 src-vue/ui/UiOverlay.vue create mode 100644 src-vue/ui/UiSelect.vue create mode 100644 src-vue/ui/UiTabbedRegion.vue create mode 100644 src-vue/ui/UiTable.vue create mode 100644 src-vue/ui/parse.js create mode 100644 vite.local.config.js diff --git a/.gitignore b/.gitignore index a920002..f3599b9 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,8 @@ yarn-error.log* next-env.d.ts tsconfig.tsbuildinfo /dist/ +/dist-vue/ +/src-vue/dist-vue/ /.wrangler/ /.sites-runtime/ /outputs/ diff --git a/package-lock.json b/package-lock.json index b3b83cc..462ab2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "version": "0.1.0", "dependencies": { "@ant-design/icons": "^6.0.0", + "@vitejs/plugin-vue": "^6.0.9", + "ant-design-vue": "^4.2.6", "antd": "^6.6.4", "drizzle-orm": "0.45.2", "mammoth": "^1.12.1", @@ -17,6 +19,7 @@ "react": "19.2.6", "react-dom": "19.2.6", "sharp": "0.34.5", + "vue": "^3.5.43", "xlsx": "^0.18.5" }, "devDependencies": { @@ -133,6 +136,28 @@ "integrity": "sha512-PRomU725ABMf/lnQp5HiB7my1kjEbFY0D10N4lXYxK6TIB1gKjIVD5MRThpDaezLgw1D774J8eOeeDB0M6wHrQ==", "license": "MIT" }, + "node_modules/@ant-design/icons-vue": { + "version": "7.0.1", + "resolved": "http://mirrors.tencent.com/npm/@ant-design/icons-vue/-/icons-vue-7.0.1.tgz", + "integrity": "sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^6.0.0", + "@ant-design/icons-svg": "^4.2.1" + }, + "peerDependencies": { + "vue": ">=3.0.3" + } + }, + "node_modules/@ant-design/icons-vue/node_modules/@ant-design/colors": { + "version": "6.0.0", + "resolved": "http://mirrors.tencent.com/npm/@ant-design/colors/-/colors-6.0.0.tgz", + "integrity": "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^3.4.0" + } + }, "node_modules/@ant-design/react-slick": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-2.0.0.tgz", @@ -282,20 +307,18 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, + "version": "7.29.7", + "resolved": "http://mirrors.tencent.com/npm/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, + "version": "7.29.7", + "resolved": "http://mirrors.tencent.com/npm/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -326,13 +349,11 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", - "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", - "dev": true, - "license": "MIT", + "version": "7.29.9", + "resolved": "http://mirrors.tencent.com/npm/@babel/parser/-/parser-7.29.9.tgz", + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", "dependencies": { - "@babel/types": "^7.29.0" + "@babel/types": "^7.29.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -385,14 +406,13 @@ } }, "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, + "version": "7.29.8", + "resolved": "http://mirrors.tencent.com/npm/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -551,6 +571,15 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "http://mirrors.tencent.com/npm/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/@drizzle-team/brocli": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/@drizzle-team/brocli/-/brocli-0.10.2.tgz", @@ -2188,23 +2217,10 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -3682,7 +3698,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", - "dev": true, "license": "MIT" }, "node_modules/@rollup/pluginutils": { @@ -3752,6 +3767,16 @@ "node": ">= 8.0.0" } }, + "node_modules/@simonwep/pickr": { + "version": "1.8.2", + "resolved": "http://mirrors.tencent.com/npm/@simonwep/pickr/-/pickr-1.8.2.tgz", + "integrity": "sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==", + "license": "MIT", + "dependencies": { + "core-js": "^3.15.1", + "nanopop": "^2.1.0" + } + }, "node_modules/@sindresorhus/is": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", @@ -4352,30 +4377,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", @@ -5096,182 +5097,144 @@ "dev": true, "license": "MIT" }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.9", + "resolved": "http://mirrors.tencent.com/npm/@vitejs/plugin-vue/-/plugin-vue-6.0.9.tgz", + "integrity": "sha512-rD/MORlhaZMlXWW0rEn4FB4wMinWC0z/D7Ye160S5+Rs1mC8ZDAdcDp4SjKfUhG5t8q1ktcPVw4xuTkPRlzrSA==", "license": "MIT", - "peer": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "vue": "^3.2.25" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, + "node_modules/@vue/compiler-core": { + "version": "3.5.43", + "resolved": "http://mirrors.tencent.com/npm/@vue/compiler-core/-/compiler-core-3.5.43.tgz", + "integrity": "sha512-zdiLhnbe1QQqgDT8xZMpNmyqZ3qlI+/Q/FHQco57Kwl/b05HhCzN6eVGN9QU9rbga4CrS0H5SYY8VGHZCt/1Hg==", "license": "MIT", - "peer": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" + "@babel/parser": "^7.29.8", + "@vue/shared": "3.5.43", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" + "node_modules/@vue/compiler-core/node_modules/entities": { + "version": "7.0.1", + "resolved": "http://mirrors.tencent.com/npm/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, + "node_modules/@vue/compiler-core/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "http://mirrors.tencent.com/npm/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.43", + "resolved": "http://mirrors.tencent.com/npm/@vue/compiler-dom/-/compiler-dom-3.5.43.tgz", + "integrity": "sha512-PEZoAk3NQmsn/ejMzSOCyTYqwGqczrWm70PuhBKjjv1+TCoQAaO/zOqNwjV+honlNstT5ILxtc+8r8UUfj+iEQ==", "license": "MIT", - "peer": true, "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "@vue/compiler-core": "3.5.43", + "@vue/shared": "3.5.43" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, - "license": "Apache-2.0", - "peer": true, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.43", + "resolved": "http://mirrors.tencent.com/npm/@vue/compiler-sfc/-/compiler-sfc-3.5.43.tgz", + "integrity": "sha512-FCbrG3XNCRl+js3huuKx4IVHBLTvMkJhVepjbxSPu1gn4yWLaYtGNQdjJGZaMytXB6qb76qQDDmDSLy/vkmleQ==", + "license": "MIT", "dependencies": { - "@xtuc/long": "4.2.2" + "@babel/parser": "^7.29.8", + "@vue/compiler-core": "3.5.43", + "@vue/compiler-dom": "3.5.43", + "@vue/compiler-ssr": "3.5.43", + "@vue/shared": "3.5.43", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.28", + "source-map-js": "^1.2.1" } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true, - "license": "MIT", - "peer": true + "node_modules/@vue/compiler-sfc/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "http://mirrors.tencent.com/npm/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.43", + "resolved": "http://mirrors.tencent.com/npm/@vue/compiler-ssr/-/compiler-ssr-3.5.43.tgz", + "integrity": "sha512-GF62orf7KiJX9RqrHNGrYBudsQGD0OhJ5nDs90O8UiDuS40+YMYomiXu6w6EuvtXuRDc3MSNis3EaaSKAVSWpg==", "license": "MIT", - "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" + "@vue/compiler-dom": "3.5.43", + "@vue/shared": "3.5.43" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, + "node_modules/@vue/reactivity": { + "version": "3.5.43", + "resolved": "http://mirrors.tencent.com/npm/@vue/reactivity/-/reactivity-3.5.43.tgz", + "integrity": "sha512-G/c9GyOZNI2jVaaS6OX1EF1SSFSv7H0ERqNTl4+DTFMlZmB5eVAB53aLQNam/7NL2NPtaDD7RdVrzf8uJzMuOA==", "license": "MIT", - "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" + "@vue/shared": "3.5.43" } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, + "node_modules/@vue/runtime-core": { + "version": "3.5.43", + "resolved": "http://mirrors.tencent.com/npm/@vue/runtime-core/-/runtime-core-3.5.43.tgz", + "integrity": "sha512-hU6U6VnVhBGQDpvlnnDlIB8ZGJBiOcgk2lh/0InltHiz3D8oSkluvuvY+do1G2H3+udeKFsmaBlgVYP7gXQzEw==", "license": "MIT", - "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" + "@vue/reactivity": "3.5.43", + "@vue/shared": "3.5.43" } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, + "node_modules/@vue/runtime-dom": { + "version": "3.5.43", + "resolved": "http://mirrors.tencent.com/npm/@vue/runtime-dom/-/runtime-dom-3.5.43.tgz", + "integrity": "sha512-Bb2Jc0YjjJdMt1SJmb9b2L/IWd3I8lIT9x9eS/xvvP9CiVgna0ffua74xKRmt4/uSJ+0r4iN8ex1jrqkhQGWQw==", "license": "MIT", - "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" + "@vue/reactivity": "3.5.43", + "@vue/runtime-core": "3.5.43", + "@vue/shared": "3.5.43", + "csstype": "^3.2.3" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, + "node_modules/@vue/server-renderer": { + "version": "3.5.43", + "resolved": "http://mirrors.tencent.com/npm/@vue/server-renderer/-/server-renderer-3.5.43.tgz", + "integrity": "sha512-l2Ygjv9NehV94PSBxNWsAHC0j/eIIKbn92mBuWXAPGLnn6HfJ6MH5ubsd+Nk0YoZ5FRuxWI1P2VSoh+dbPQhCQ==", "license": "MIT", - "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" + "@vue/compiler-ssr": "3.5.43", + "@vue/runtime-dom": "3.5.43", + "@vue/shared": "3.5.43" } }, + "node_modules/@vue/shared": { + "version": "3.5.43", + "resolved": "http://mirrors.tencent.com/npm/@vue/shared/-/shared-3.5.43.tgz", + "integrity": "sha512-uksS7YGMR5NZyr4JNq0Rp+QyLns0ueaz20KwzIPW9R0LH1Vnt4E+XUM29PNseEbf1www2gOuhuDi5AKOIXag9Q==", + "license": "MIT" + }, "node_modules/@xmldom/xmldom": { "version": "0.8.14", "resolved": "http://mirrors.tencent.com/npm/@xmldom/xmldom/-/xmldom-0.8.14.tgz", @@ -5281,22 +5244,6 @@ "node": ">=10.0.0" } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true, - "license": "Apache-2.0", - "peer": true - }, "node_modules/acorn": { "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", @@ -5310,20 +5257,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-phases": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "acorn": "^8.14.0" - } - }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -5373,65 +5306,96 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "ajv": "^8.0.0" + "color-convert": "^2.0.1" }, - "peerDependencies": { - "ajv": "^8.0.0" + "engines": { + "node": ">=8" }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", - "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", - "dev": true, + "node_modules/ant-design-vue": { + "version": "4.2.6", + "resolved": "http://mirrors.tencent.com/npm/ant-design-vue/-/ant-design-vue-4.2.6.tgz", + "integrity": "sha512-t7eX13Yj3i9+i5g9lqFyYneoIb3OzTvQjq9Tts1i+eiOd3Eva/6GagxBSXM1fOCjqemIu0FYVE1ByZ/38epR3Q==", "license": "MIT", - "peer": true, "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "@ant-design/colors": "^6.0.0", + "@ant-design/icons-vue": "^7.0.0", + "@babel/runtime": "^7.10.5", + "@ctrl/tinycolor": "^3.5.0", + "@emotion/hash": "^0.9.0", + "@emotion/unitless": "^0.8.0", + "@simonwep/pickr": "~1.8.0", + "array-tree-filter": "^2.1.0", + "async-validator": "^4.0.0", + "csstype": "^3.1.1", + "dayjs": "^1.10.5", + "dom-align": "^1.12.1", + "dom-scroll-into-view": "^2.0.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.15", + "resize-observer-polyfill": "^1.5.1", + "scroll-into-view-if-needed": "^2.2.25", + "shallow-equal": "^1.0.0", + "stylis": "^4.1.3", + "throttle-debounce": "^5.0.0", + "vue-types": "^3.0.0", + "warning": "^4.0.0" + }, + "engines": { + "node": ">=12.22.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "type": "opencollective", + "url": "https://opencollective.com/ant-design-vue" + }, + "peerDependencies": { + "vue": ">=3.2.0" } }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, + "node_modules/ant-design-vue/node_modules/@ant-design/colors": { + "version": "6.0.0", + "resolved": "http://mirrors.tencent.com/npm/@ant-design/colors/-/colors-6.0.0.tgz", + "integrity": "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==", "license": "MIT", - "peer": true + "dependencies": { + "@ctrl/tinycolor": "^3.4.0" + } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/ant-design-vue/node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "http://mirrors.tencent.com/npm/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/ant-design-vue/node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "http://mirrors.tencent.com/npm/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", + "license": "MIT" + }, + "node_modules/ant-design-vue/node_modules/compute-scroll-into-view": { + "version": "1.0.20", + "resolved": "http://mirrors.tencent.com/npm/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", + "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==", + "license": "MIT" + }, + "node_modules/ant-design-vue/node_modules/scroll-into-view-if-needed": { + "version": "2.2.31", + "resolved": "http://mirrors.tencent.com/npm/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz", + "integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "compute-scroll-into-view": "^1.0.20" } }, "node_modules/antd": { @@ -5555,6 +5519,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-tree-filter": { + "version": "2.1.0", + "resolved": "http://mirrors.tencent.com/npm/array-tree-filter/-/array-tree-filter-2.1.0.tgz", + "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==", + "license": "MIT" + }, "node_modules/array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", @@ -5692,6 +5662,12 @@ "node": ">= 0.4" } }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "http://mirrors.tencent.com/npm/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", + "license": "MIT" + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -5968,17 +5944,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.0" - } - }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -6022,14 +5987,6 @@ "dev": true, "license": "MIT" }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/compute-scroll-into-view": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", @@ -6080,6 +6037,20 @@ "url": "https://github.com/sponsors/mesqueeb" } }, + "node_modules/core-js": { + "version": "3.50.0", + "resolved": "http://mirrors.tencent.com/npm/core-js/-/core-js-3.50.0.tgz", + "integrity": "sha512-BRWgOLKkFeCgRudR6zrs8p9XJZcE14grzKMMssoYrk6krtuEZ7MTKPIY5RzOnqsEKIR9kst7wNzphttraT+Yqw==", + "hasInstallScript": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "http://mirrors.tencent.com/npm/core-util-is/-/core-util-is-1.0.3.tgz", @@ -6348,6 +6319,18 @@ "node": ">=0.10.0" } }, + "node_modules/dom-align": { + "version": "1.12.4", + "resolved": "http://mirrors.tencent.com/npm/dom-align/-/dom-align-1.12.4.tgz", + "integrity": "sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==", + "license": "MIT" + }, + "node_modules/dom-scroll-into-view": { + "version": "2.0.1", + "resolved": "http://mirrors.tencent.com/npm/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz", + "integrity": "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==", + "license": "MIT" + }, "node_modules/dot-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", @@ -7765,17 +7748,6 @@ "node": ">=0.10.0" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.8.x" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -7827,24 +7799,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause", - "peer": true - }, "node_modules/fastq": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", @@ -8110,14 +8064,6 @@ "node": ">=10.13.0" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true - }, "node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", @@ -8683,6 +8629,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-plain-object": { + "version": "3.0.1", + "resolved": "http://mirrors.tencent.com/npm/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -8873,39 +8828,6 @@ "node": ">= 0.4" } }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/jiti": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", @@ -8920,7 +8842,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -9401,21 +9322,6 @@ "dev": true, "license": "MIT" }, - "node_modules/loader-runner": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", - "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.11.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -9432,6 +9338,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "http://mirrors.tencent.com/npm/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "http://mirrors.tencent.com/npm/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -9443,7 +9361,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -9487,7 +9404,6 @@ "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -9570,14 +9486,6 @@ "node": ">= 0.4" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -9616,17 +9524,6 @@ "node": ">=4" } }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/miniflare": { "version": "4.20260515.0", "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260515.0.tgz", @@ -9679,9 +9576,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.19", + "resolved": "http://mirrors.tencent.com/npm/nanoid/-/nanoid-3.3.19.tgz", + "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==", "funding": [ { "type": "github", @@ -9696,6 +9593,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/nanopop": { + "version": "2.4.2", + "resolved": "http://mirrors.tencent.com/npm/nanopop/-/nanopop-2.4.2.tgz", + "integrity": "sha512-NzOgmMQ+elxxHeIha+OG/Pv3Oc3p4RU2aBhwWwAqDpXrdTbtRylbRLQztLy8dMMwfl6pclznBdfUhccEn9ZIzw==", + "license": "MIT" + }, "node_modules/napi-postinstall": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", @@ -10241,10 +10144,9 @@ } }, "node_modules/postcss": { - "version": "8.5.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", - "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", - "dev": true, + "version": "8.5.28", + "resolved": "http://mirrors.tencent.com/npm/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", "funding": [ { "type": "opencollective", @@ -10261,7 +10163,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.18", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -10523,16 +10425,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "http://mirrors.tencent.com/npm/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "license": "MIT" }, "node_modules/resolve": { "version": "2.0.0-next.7", @@ -10756,67 +10653,6 @@ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, - "node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", - "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/schema-utils/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/scroll-into-view-if-needed": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", @@ -10891,6 +10727,12 @@ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", "license": "MIT" }, + "node_modules/shallow-equal": { + "version": "1.2.1", + "resolved": "http://mirrors.tencent.com/npm/shallow-equal/-/shallow-equal-1.2.1.tgz", + "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==", + "license": "MIT" + }, "node_modules/sharp": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", @@ -11432,88 +11274,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/terser": { - "version": "5.47.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.47.1.tgz", - "integrity": "sha512-tPbLXTI6ohPASb/1YViL428oEHu6/qv1OxqYnfaonVCFHqx4+wCd95pHrQWsL5X4pl90CTyW9piSAsS2L0VoMw==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.0.tgz", - "integrity": "sha512-Eum+5ajkaOhf5KbM26osvv21kLD7BaGqQ1UA4Ami4arYwylmGUQTgHFpHDdmJod1q4QXa66p0to/FBKID+J1vA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "terser": "^5.31.1" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@minify-html/node": { - "optional": true - }, - "@swc/core": { - "optional": true - }, - "@swc/css": { - "optional": true - }, - "@swc/html": { - "optional": true - }, - "clean-css": { - "optional": true - }, - "cssnano": { - "optional": true - }, - "csso": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "html-minifier-terser": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "postcss": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, "node_modules/throttle-debounce": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", @@ -12471,19 +12231,49 @@ } } }, - "node_modules/watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", - "dev": true, + "node_modules/vue": { + "version": "3.5.43", + "resolved": "http://mirrors.tencent.com/npm/vue/-/vue-3.5.43.tgz", + "integrity": "sha512-o5qZoksdnjIKvW1srZ3ab7pcDNYAerBjRe54D0LBLfRdCYFrSgBHVXokMas35czQc0//lmx4/tuY4ZNQ+Rf2Ng==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.43", + "@vue/compiler-sfc": "3.5.43", + "@vue/runtime-dom": "3.5.43", + "@vue/server-renderer": "3.5.43", + "@vue/shared": "3.5.43" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-types": { + "version": "3.0.2", + "resolved": "http://mirrors.tencent.com/npm/vue-types/-/vue-types-3.0.2.tgz", + "integrity": "sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==", "license": "MIT", - "peer": true, "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" + "is-plain-object": "3.0.1" }, "engines": { - "node": ">=10.13.0" + "node": ">=10.15.0" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "http://mirrors.tencent.com/npm/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" } }, "node_modules/web-vitals": { @@ -12493,55 +12283,6 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/webpack": { - "version": "5.106.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.106.2.tgz", - "integrity": "sha512-wGN3qcrBQIFmQ/c0AiOAQBvrZ5lmY8vbbMv4Mxfgzqd/B6+9pXtLo73WuS1dSGXM5QYY3hZnIbvx+K1xxe6FyA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.16.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.28.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.20.0", - "es-module-lexer": "^2.0.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "loader-runner": "^4.3.1", - "mime-db": "^1.54.0", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.3", - "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.17", - "watchpack": "^2.5.1", - "webpack-sources": "^3.3.4" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, "node_modules/webpack-sources": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.1.tgz", @@ -12552,32 +12293,6 @@ "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/webpack/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index dedd5f2..7e54e08 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,8 @@ }, "dependencies": { "@ant-design/icons": "^6.0.0", + "@vitejs/plugin-vue": "^6.0.9", + "ant-design-vue": "^4.2.6", "antd": "^6.6.4", "drizzle-orm": "0.45.2", "mammoth": "^1.12.1", @@ -27,6 +29,7 @@ "react": "19.2.6", "react-dom": "19.2.6", "sharp": "0.34.5", + "vue": "^3.5.43", "xlsx": "^0.18.5" }, "devDependencies": { diff --git a/src-vue/App.vue b/src-vue/App.vue new file mode 100644 index 0000000..a2fcaab --- /dev/null +++ b/src-vue/App.vue @@ -0,0 +1,41 @@ + + + diff --git a/src-vue/Home.vue b/src-vue/Home.vue new file mode 100644 index 0000000..e400a6a --- /dev/null +++ b/src-vue/Home.vue @@ -0,0 +1,685 @@ + + + diff --git a/src-vue/components/Dashboard.vue b/src-vue/components/Dashboard.vue new file mode 100644 index 0000000..2b21815 --- /dev/null +++ b/src-vue/components/Dashboard.vue @@ -0,0 +1,5 @@ + diff --git a/src-vue/components/DashboardThumb.vue b/src-vue/components/DashboardThumb.vue new file mode 100644 index 0000000..4c09588 --- /dev/null +++ b/src-vue/components/DashboardThumb.vue @@ -0,0 +1,48 @@ + + + diff --git a/src-vue/components/DeviceTemplateCard.js b/src-vue/components/DeviceTemplateCard.js new file mode 100644 index 0000000..882c035 --- /dev/null +++ b/src-vue/components/DeviceTemplateCard.js @@ -0,0 +1,475 @@ +// Shared device-template card + helpers (ported from app/page.tsx). +// Extracted so both the DomainSettings page and the DeviceTemplates page can reuse it. +import { ref, computed, h } from "vue"; +import { Drawer, Button as AntButton } from "ant-design-vue"; +import { + EditOutlined, DeleteOutlined, CopyOutlined, PlusOutlined, RobotOutlined, + SearchOutlined, ControlOutlined, +} from "@ant-design/icons-vue"; +import UiButton from "../ui/UiButton.vue"; +import UiInput from "../ui/UiInput.vue"; +import UiSelect from "../ui/UiSelect.vue"; +import UiTable from "../ui/UiTable.vue"; +import UiActions from "../ui/UiActions.vue"; +import PrimaryButton from "../components/PrimaryButton.vue"; +import { fetchDb } from "../lib/api.js"; +import { useConfirm } from "../pages/domain/useConfirm.js"; +import { useStreamComplete, streamInto } from "../pages/domain/domainCommon.js"; + +// React local `Button` (PrimaryButton primary/default + "button" class). +const Button = PrimaryButton; + +const CP_RANGE_PRESETS = ["0~100", "0~1000", "-20~80", "-40~85", "0~50", "0~5", "0~1", "0~100%"]; + +function fileToBase64(file) { + return new Promise((resolve, reject) => { + const r = new FileReader(); + r.onload = () => { + const buf = new Uint8Array(r.result); + let bin = ""; + for (const b of buf) bin += String.fromCharCode(b); + resolve({ filename: file.name, mime: file.type || "application/octet-stream", data: btoa(bin) }); + }; + r.onerror = reject; + r.readAsArrayBuffer(file); + }); +} + +const DeviceImageField = { + props: { imageUrl: { type: String, default: null }, onPick: { type: Function, default: () => {} } }, + setup(p) { + const inputRef = ref(null); + return () => + h("div", { class: "device-img-field", onClick: () => inputRef.value && inputRef.value.click() }, [ + p.imageUrl + ? h("img", { src: p.imageUrl, alt: "设备图片" }) + : h("span", { class: "device-img-empty" }, "+ 点击上传设备图片"), + h("input", { + ref: inputRef, + type: "file", + accept: "image/*", + hidden: true, + onChange: (e) => { + const f = e.target.files && e.target.files[0]; + if (f) p.onPick(f); + e.target.value = ""; + }, + }), + ]); + }, +}; + +const DeviceTemplateCard = { + props: { + dev: { type: Object, default: () => ({}) }, + notify: { type: Function, default: () => {} }, + onChange: { type: Function, default: () => {} }, + onBack: { type: Function, default: () => {} }, + onViewCpPrompt: { type: Function, default: () => {} }, + }, + setup(p) { + const name = ref(p.dev.name); + const description = ref(p.dev.description || ""); + const imgPreview = ref(p.dev.image_path ? `/api/db/device-templates/${p.dev.id}/image` : null); + const imgB64 = ref(null); + const cps = ref((p.dev.collection_points || []).map((c) => ({ ...c, key: c.id, checked: false }))); + const aiOpen = ref(false); + const abortRef = ref(null); + const { confirm, el: confirmEl } = useConfirm(); + + const onPick = async (f) => { + imgPreview.value = URL.createObjectURL(f); + const b = await fileToBase64(f); + imgB64.value = { filename: b.filename, mime: b.mime, data: b.data }; + }; + const save = async () => { + const body = { name: name.value, description: description.value }; + if (imgB64.value) body.image = imgB64.value; + await fetchDb(`/device-templates/${p.dev.id}`, { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(body), + }); + p.notify("设备已保存"); + p.onChange(); + }; + const delDev = async () => { + if (!(await confirm("删除该设备模板?"))) return; + await fetchDb(`/device-templates/${p.dev.id}`, { method: "DELETE" }); + p.onChange(); + p.onBack(); + }; + const addCpRow = () => cps.value.push({ key: -(Date.now()), name: "", collect_note: "", unit: "", value_range: "", description: "", checked: false }); + const updCp = (k, field, val) => (cps.value = cps.value.map((c) => (c.key === k ? { ...c, [field]: val } : c))); + const toggleCp = (k) => (cps.value = cps.value.map((c) => (c.key === k ? { ...c, checked: !c.checked } : c))); + const allChecked = computed(() => cps.value.length > 0 && cps.value.every((c) => c.checked)); + const toggleAll = () => (cps.value = cps.value.map((c) => ({ ...c, checked: !allChecked.value }))); + const delCpRows = async () => { + const sel = cps.value.filter((c) => c.checked); + if (sel.length === 0) { p.notify("请先勾选要删除的采集点"); return; } + if (!(await confirm(`确定删除选中的 ${sel.length} 个采集点?`))) return; + for (const c of sel) if (c.id) await fetchDb(`/collection-points/${c.id}`, { method: "DELETE" }); + cps.value = cps.value.filter((c) => !c.checked); + p.onChange(); + }; + const saveCpRows = async () => { + try { + for (const c of cps.value) { + const payload = { name: c.name, collect_note: c.collect_note, unit: c.unit, value_range: c.value_range, description: c.description }; + if (c.id) await fetchDb(`/collection-points/${c.id}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }); + else await fetchDb(`/device-templates/${p.dev.id}/collection-points`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }); + } + p.notify("采集点已保存"); + p.onChange(); + } catch (e) { + p.notify("保存失败:" + (e && e.message ? e.message : e)); + } + }; + + const attrs = ref((p.dev.attributes || []).map((a) => ({ ...a, key: a.id, checked: false }))); + const addAttrRow = () => attrs.value.push({ key: -(Date.now()), keyword: "", name: "", value: "", unit: "", checked: false }); + const updAttr = (k, field, val) => (attrs.value = attrs.value.map((a) => (a.key === k ? { ...a, [field]: val } : a))); + const toggleAttr = (k) => (attrs.value = attrs.value.map((a) => (a.key === k ? { ...a, checked: !a.checked } : a))); + const allAttrChecked = computed(() => attrs.value.length > 0 && attrs.value.every((a) => a.checked)); + const toggleAllAttr = () => (attrs.value = attrs.value.map((a) => ({ ...a, checked: !allAttrChecked.value }))); + const delAttrRows = async () => { + const sel = attrs.value.filter((a) => a.checked); + if (sel.length === 0) { p.notify("请先勾选要删除的属性"); return; } + if (!(await confirm(`确定删除选中的 ${sel.length} 个属性?`))) return; + for (const a of sel) if (a.id) await fetchDb(`/attributes/${a.id}`, { method: "DELETE" }); + attrs.value = attrs.value.filter((a) => !a.checked); + p.onChange(); + }; + const saveAttrRows = async () => { + try { + for (const a of attrs.value) { + const payload = { keyword: a.keyword, name: a.name, value: a.value, unit: a.unit }; + if (a.id) await fetchDb(`/attributes/${a.id}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }); + else await fetchDb(`/device-templates/${p.dev.id}/attributes`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }); + } + p.notify("属性已保存"); + p.onChange(); + } catch (e) { + p.notify("保存失败:" + (e && e.message ? e.message : e)); + } + }; + + const alarmRules = ref( + Array.isArray(p.dev.alarm_rules) && p.dev.alarm_rules.length + ? p.dev.alarm_rules + : [ + { id: 1, name: "设备离线", level: "高", category: "故障", method: "自动", description: "设备连续 5 分钟无数据上报", enabled: true, sensitivityType: "duration", sensitivityValue: "5", typeName: "离线报警", triggers: [{ id: 11, name: "离线判断", source: "当前设备", compareType: "状态", point: "在线状态", operator: "=", threshold: "0" }] }, + { id: 2, name: "电压过高", level: "高", category: "报警", method: "自动", description: "供电电压超过额定上限", enabled: true, sensitivityType: "consecutive", sensitivityValue: "1", typeName: "阈值报警", triggers: [{ id: 21, name: "电压上限", source: "当前设备", compareType: "数值", point: "供电电压", operator: ">", threshold: "240" }] }, + ] + ); + const alarmQuery = ref(""); + const selectedAlarmIds = ref(new Set()); + const alarmDraft = ref(null); + const alarmFiltered = computed(() => + alarmRules.value.filter((rule) => !alarmQuery.value.trim() || `${rule.name} ${rule.description || ""}`.toLowerCase().includes(alarmQuery.value.trim().toLowerCase())) + ); + const newAlarmDraft = () => ({ + id: null, name: "", level: "高", category: "报警", method: "自动", description: "", enabled: true, + typeName: "阈值报警", sensitivityType: "consecutive", sensitivityValue: "1", + triggers: [{ id: -Date.now(), name: "规则 1", source: "当前设备", compareType: "数值", point: cps.value[0] ? cps.value[0].name : "", operator: ">", threshold: "" }], + }); + const editAlarm = (rule) => (alarmDraft.value = { ...rule, triggers: (rule.triggers || []).map((item) => ({ ...item })) }); + const saveAlarm = () => { + if (!alarmDraft.value || !alarmDraft.value.name || !alarmDraft.value.name.trim()) { p.notify("请填写报警名称"); return; } + if (!alarmDraft.value.triggers || !alarmDraft.value.triggers.length) { p.notify("请至少添加一条触发规则"); return; } + const isCreate = alarmDraft.value.id == null; + const saved = { ...alarmDraft.value, id: alarmDraft.value.id != null ? alarmDraft.value.id : Date.now() }; + alarmRules.value = isCreate ? [...alarmRules.value, saved] : alarmRules.value.map((rule) => (rule.id === saved.id ? saved : rule)); + alarmDraft.value = null; + p.notify(isCreate ? "报警规则已新增" : "报警规则已更新"); + }; + const copyAlarm = (rule) => { + const copied = { ...rule, id: Date.now(), name: `${rule.name} - 副本`, triggers: (rule.triggers || []).map((item, index) => ({ ...item, id: -(Date.now() + index) })) }; + alarmRules.value = [...alarmRules.value, copied]; + p.notify("已复制报警规则"); + }; + const removeAlarm = async (rule) => { + if (!(await confirm(`确定删除报警规则「${rule.name}」?`))) return; + alarmRules.value = alarmRules.value.filter((item) => item.id !== rule.id); + const next = new Set(selectedAlarmIds.value); next.delete(rule.id); selectedAlarmIds.value = next; + p.notify("报警规则已删除"); + }; + const toggleAlarm = (id) => (alarmRules.value = alarmRules.value.map((rule) => (rule.id === id ? { ...rule, enabled: !rule.enabled } : rule))); + const toggleAlarmSelect = (id) => { + const next = new Set(selectedAlarmIds.value); + if (next.has(id)) next.delete(id); else next.add(id); + selectedAlarmIds.value = next; + }; + const allAlarmsChecked = computed(() => alarmFiltered.value.length > 0 && alarmFiltered.value.every((rule) => selectedAlarmIds.value.has(rule.id))); + const toggleAllAlarms = () => { + const next = new Set(selectedAlarmIds.value); + if (allAlarmsChecked.value) alarmFiltered.value.forEach((rule) => next.delete(rule.id)); + else alarmFiltered.value.forEach((rule) => next.add(rule.id)); + selectedAlarmIds.value = next; + }; + const updateAlarmTrigger = (id, field, value) => + (alarmDraft.value = { ...alarmDraft.value, triggers: alarmDraft.value.triggers.map((item) => (item.id === id ? { ...item, [field]: value } : item)) }); + const addAlarmTrigger = () => + (alarmDraft.value = { ...alarmDraft.value, triggers: [...alarmDraft.value.triggers, { id: -Date.now(), name: `规则 ${alarmDraft.value.triggers.length + 1}`, source: "当前设备", compareType: "数值", point: cps.value[0] ? cps.value[0].name : "", operator: ">", threshold: "" }] }); + const removeAlarmTrigger = (id) => + (alarmDraft.value = { ...alarmDraft.value, triggers: alarmDraft.value.triggers.filter((item) => item.id !== id) }); + + const cpAi = useStreamComplete(); + const runCpComplete = async () => { + if (cpAi.completing.value) return; + cpAi.setCompleting(true); cpAi.setLog(""); + if (abortRef.value) abortRef.value.abort(); + const controller = new AbortController(); + abortRef.value = controller; + const wd = setTimeout(() => { controller.abort(); cpAi.setCompleting(false); p.notify("AI 采集点补全超时(>10 分钟),请重试"); }, 600000); + try { + const res = await fetch(`/api/db/device-templates/${p.dev.id}/complete-collection-points`, { method: "POST", signal: controller.signal }); + if (!res.ok || !res.body) throw new Error("HTTP " + res.status); + await streamInto(res, cpAi.setLog, () => {}); + const fresh = await fetchDb(`/device-templates/${p.dev.id}`); + cps.value = (fresh.collection_points || []).map((c, i) => ({ ...c, key: c.id || -(i + 1), checked: false })); + p.notify("AI 采集点补全已完成(已保存到该设备模板)"); + } catch (e) { + if (e && e.name === "AbortError" || (abortRef.value && abortRef.value.signal.aborted)) { + cpAi.setLog((prev) => prev + "\n⏹ 已停止\n"); + p.notify("AI 采集点补全已停止"); + } else { + p.notify("AI 采集点补全失败:" + (e && e.message ? e.message : e)); + } + } finally { + clearTimeout(wd); cpAi.setCompleting(false); abortRef.value = null; + } + }; + const stopCpComplete = async () => { + if (!cpAi.completing.value || !abortRef.value) return; + try { await fetchDb(`/device-templates/${p.dev.id}/complete-collection-points/stop`, { method: "POST" }); } catch {} + abortRef.value.abort(); + }; + const viewCpCompletePrompt = () => p.onViewCpPrompt(p.dev.id); + + return () => [ + confirmEl && h(confirmEl), + h("div", { class: "device-card" }, [ + h("div", { class: "device-card-head" }, [ + h("b", {}, name.value || "(未命名)"), + h(UiButton, { class: "text-button", onClick: delDev }, "删除设备"), + ]), + h("div", { class: "form-grid" }, [ + h("label", {}, ["设备名称", h(UiInput, { value: name.value, onChange: (e) => (name.value = e.target.value) })]), + h("label", { style: { gridColumn: "1 / -1" } }, ["设备图片", h(DeviceImageField, { imageUrl: imgPreview.value, onPick })]), + h("label", { style: { gridColumn: "1 / -1" } }, [ + "说明", + h(UiInput, { textarea: true, value: description.value, onChange: (e) => (description.value = e.target.value), rows: 2, placeholder: "设备说明,可描述其用途,特性,常见使用方式等。" }), + ]), + ]), + h("div", { class: "cp-list" }, [ + h("div", { class: "cp-list-head" }, [ + h("b", {}, "采集点"), + h("span", {}, [ + h(UiButton, { class: "text-button", onClick: addCpRow }, "+ 新增一行"), + h(UiButton, { class: "text-button", onClick: delCpRows }, "删除选中"), + h(UiButton, { class: "text-button", onClick: saveCpRows }, "保存采集点"), + ]), + ]), + h(UiTable, { class: "data-table cp-editor" }, () => [ + h("thead", {}, h("tr", {}, [ + h("th", { style: { width: 34 } }, h(UiInput, { type: "checkbox", checked: allChecked.value, onChange: toggleAll })), + h("th", {}, "名称"), h("th", {}, "说明"), h("th", {}, "单位"), h("th", {}, "数值范围"), h("th", {}, "描述"), + ])), + h("tbody", {}, [ + cps.value.length === 0 + ? h("tr", {}, h("td", { colSpan: 6, class: "muted" }, "暂无采集点,点「+ 新增一行」添加")) + : cps.value.map((c) => + h("tr", { key: c.key }, [ + h("td", {}, h(UiInput, { type: "checkbox", checked: !!c.checked, onChange: () => toggleCp(c.key) })), + h("td", {}, h(UiInput, { value: c.name, onChange: (e) => updCp(c.key, "name", e.target.value), placeholder: "名称" })), + h("td", {}, h(UiInput, { value: c.collect_note || "", onChange: (e) => updCp(c.key, "collect_note", e.target.value), placeholder: "说明" })), + h("td", {}, h(UiInput, { value: c.unit || "", onChange: (e) => updCp(c.key, "unit", e.target.value), placeholder: "单位" })), + h("td", {}, [ + h(UiSelect, { + value: CP_RANGE_PRESETS.includes(c.value_range) ? c.value_range : "__custom__", + onChange: (e) => updCp(c.key, "value_range", e.target.value === "__custom__" ? "" : e.target.value), + }, () => [ + ...CP_RANGE_PRESETS.map((pp) => h("option", { key: pp, value: pp }, pp)), + h("option", { value: "__custom__" }, "自定义…"), + ]), + !CP_RANGE_PRESETS.includes(c.value_range) + ? h(UiInput, { class: "cp-range-custom", value: c.value_range, onChange: (e) => updCp(c.key, "value_range", e.target.value), placeholder: "如 0~100" }) + : null, + ]), + h("td", {}, h(UiInput, { value: c.description || "", onChange: (e) => updCp(c.key, "description", e.target.value), placeholder: "描述" })), + ]) + ), + ]), + ]), + ]), + h("div", { class: "cp-list" }, [ + h("div", { class: "cp-list-head" }, [ + h("b", {}, "属性列表"), + h("span", {}, [ + h(UiButton, { class: "text-button", onClick: addAttrRow }, "+ 新增一行"), + h(UiButton, { class: "text-button", onClick: delAttrRows }, "删除选中"), + h(UiButton, { class: "text-button", onClick: saveAttrRows }, "保存属性"), + ]), + ]), + h(UiTable, { class: "data-table cp-editor" }, () => [ + h("thead", {}, h("tr", {}, [ + h("th", { style: { width: 34 } }, h(UiInput, { type: "checkbox", checked: allAttrChecked.value, onChange: toggleAllAttr })), + h("th", {}, "关键字"), h("th", {}, "属性名称"), h("th", {}, "属性值"), h("th", {}, "单位"), + ])), + h("tbody", {}, [ + attrs.value.length === 0 + ? h("tr", {}, h("td", { colSpan: 5, class: "muted" }, "暂无属性,点「+ 新增一行」添加")) + : attrs.value.map((a) => + h("tr", { key: a.key }, [ + h("td", {}, h(UiInput, { type: "checkbox", checked: !!a.checked, onChange: () => toggleAttr(a.key) })), + h("td", {}, h(UiInput, { value: a.keyword || "", onChange: (e) => updAttr(a.key, "keyword", e.target.value), placeholder: "关键字" })), + h("td", {}, h(UiInput, { value: a.name || "", onChange: (e) => updAttr(a.key, "name", e.target.value), placeholder: "属性名称" })), + h("td", {}, h(UiInput, { value: a.value || "", onChange: (e) => updAttr(a.key, "value", e.target.value), placeholder: "属性值" })), + h("td", {}, h(UiInput, { value: a.unit || "", onChange: (e) => updAttr(a.key, "unit", e.target.value), placeholder: "单位" })), + ]) + ), + ]), + ]), + ]), + h("div", { class: "cp-list alarm-rule-block" }, [ + h("div", { class: "alarm-rule-head" }, [ + h("b", {}, "报警规则"), + h("div", {}, [ + h("label", { class: "alarm-rule-search" }, [h(SearchOutlined), h(UiInput, { value: alarmQuery.value, onChange: (e) => (alarmQuery.value = e.target.value), placeholder: "报警名称" })]), + h(Button, { onClick: () => (alarmDraft.value = newAlarmDraft()) }, [h(PlusOutlined), " 新增"]), + ]), + ]), + h(UiTable, { class: "data-table alarm-rule-table" }, () => [ + h("thead", {}, h("tr", {}, [ + h("th", { style: { width: 42 } }, h(UiInput, { type: "checkbox", checked: allAlarmsChecked.value, onChange: toggleAllAlarms })), + h("th", {}, "报警名称"), h("th", {}, "报警等级"), h("th", {}, "报警类别"), h("th", {}, "处理方式"), h("th", {}, "报警描述"), + h("th", { style: { width: 76 } }, "开关"), h("th", { style: { width: 128 } }, "操作"), + ])), + h("tbody", {}, [ + alarmFiltered.value.length === 0 + ? h("tr", {}, h("td", { colSpan: 8, class: "muted" }, "暂无报警规则,点击“新增”进行配置")) + : alarmFiltered.value.map((rule) => + h("tr", { key: rule.id }, [ + h("td", {}, h(UiInput, { type: "checkbox", checked: selectedAlarmIds.value.has(rule.id), onChange: () => toggleAlarmSelect(rule.id) })), + h("td", {}, h(UiButton, { class: "link alarm-name-link", onClick: () => editAlarm(rule) }, rule.name)), + h("td", {}, rule.level), + h("td", {}, rule.category), + h("td", {}, rule.method), + h("td", { class: "alarm-description-cell", title: rule.description }, rule.description || "—"), + h("td", {}, h(UiButton, { type: "button", role: "switch", "aria-checked": rule.enabled, class: rule.enabled ? "alarm-switch on" : "alarm-switch", onClick: () => toggleAlarm(rule.id) }, [h("i")])), + h("td", {}, h("div", { class: "alarm-row-actions" }, [ + h(AntButton, { type: "text", title: "编辑", "aria-label": "编辑报警规则", icon: h(EditOutlined), onClick: () => editAlarm(rule) }), + h(AntButton, { type: "text", title: "复制", "aria-label": "复制报警规则", icon: h(CopyOutlined), onClick: () => copyAlarm(rule) }), + h(AntButton, { type: "text", danger: true, title: "删除", "aria-label": "删除报警规则", icon: h(DeleteOutlined), onClick: () => removeAlarm(rule) }), + ])), + ]) + ), + ]), + ]), + ]), + h("div", { class: "field-assist", style: { marginTop: 16 } }, [ + h(Button, { secondary: true, onClick: () => (aiOpen.value = true) }, [h(RobotOutlined), " AI 智能补全"]), + h("span", { class: "muted" }, "基于设备名称 / 领域 / 说明,AI 推荐合适的采集点并追加"), + ]), + h(Drawer, { + class: "alarm-rule-drawer", + title: alarmDraft.value && alarmDraft.value.id == null ? "新增报警规则" : "编辑报警规则", + width: 1000, + open: !!alarmDraft.value, + onClose: () => (alarmDraft.value = null), + footer: () => h("div", { class: "node-drawer-footer" }, [ + h(Button, { secondary: true, onClick: () => (alarmDraft.value = null) }, "取消"), + h(Button, { onClick: saveAlarm }, "确定"), + ]), + }, () => + alarmDraft.value + ? h("div", { class: "alarm-rule-form" }, [ + h("section", {}, [ + h("h3", {}, "基本信息"), + h("div", { class: "alarm-form-grid" }, [ + h("label", {}, [h("span", {}, [h("i", {}, "*"), " 报警名称"]), h(UiInput, { value: alarmDraft.value.name, onChange: (e) => (alarmDraft.value = { ...alarmDraft.value, name: e.target.value }), placeholder: "请输入报警名称" })]), + h("label", {}, [h("span", {}, [h("i", {}, "*"), " 报警等级"]), h(UiSelect, { value: alarmDraft.value.level, onChange: (e) => (alarmDraft.value = { ...alarmDraft.value, level: e.target.value }) }, () => [h("option", {}, "紧急"), h("option", {}, "高"), h("option", {}, "中"), h("option", {}, "低")])]), + h("label", { class: "wide" }, [h("span", {}, "报警描述"), h(UiInput, { value: alarmDraft.value.description, onChange: (e) => (alarmDraft.value = { ...alarmDraft.value, description: e.target.value }), placeholder: "请输入报警描述" })]), + ]), + ]), + h("section", {}, [ + h("h3", {}, "类别设定"), + h("div", { class: "alarm-form-grid" }, [ + h("label", {}, [h("span", {}, [h("i", {}, "*"), " 类别名称"]), h(UiSelect, { value: alarmDraft.value.category, onChange: (e) => (alarmDraft.value = { ...alarmDraft.value, category: e.target.value }) }, () => [h("option", {}, "报警"), h("option", {}, "故障"), h("option", {}, "事件"), h("option", {}, "通知")])]), + h("label", {}, [h("span", {}, [h("i", {}, "*"), " 类型名称"]), h(UiSelect, { value: alarmDraft.value.typeName, onChange: (e) => (alarmDraft.value = { ...alarmDraft.value, typeName: e.target.value }) }, () => [h("option", {}, "阈值报警"), h("option", {}, "离线报警"), h("option", {}, "状态报警"), h("option", {}, "组合报警")])]), + ]), + ]), + h("section", {}, [ + h("h3", {}, "灵敏度设定"), + h("div", { class: "alarm-sensitivity" }, [ + h("span", {}, [h("i", {}, "*"), " 灵敏度类型"]), + h("label", {}, [h(UiInput, { type: "radio", name: "alarm-sensitivity", checked: alarmDraft.value.sensitivityType === "duration", onChange: () => (alarmDraft.value = { ...alarmDraft.value, sensitivityType: "duration" }) }), " 持续时间"]), + h(UiInput, { type: "number", min: "1", value: alarmDraft.value.sensitivityType === "duration" ? alarmDraft.value.sensitivityValue : "", disabled: alarmDraft.value.sensitivityType !== "duration", onChange: (e) => (alarmDraft.value = { ...alarmDraft.value, sensitivityValue: e.target.value }) }), + h("em", {}, "秒,报警一次"), + h("label", {}, [h(UiInput, { type: "radio", name: "alarm-sensitivity", checked: alarmDraft.value.sensitivityType === "consecutive", onChange: () => (alarmDraft.value = { ...alarmDraft.value, sensitivityType: "consecutive" }) }), " 连续触发"]), + h(UiInput, { type: "number", min: "1", value: alarmDraft.value.sensitivityType === "consecutive" ? alarmDraft.value.sensitivityValue : "", disabled: alarmDraft.value.sensitivityType !== "consecutive", onChange: (e) => (alarmDraft.value = { ...alarmDraft.value, sensitivityValue: e.target.value }) }), + h("em", {}, "次,报警一次"), + ]), + ]), + h("section", {}, [ + h("h3", {}, "触发规则设定"), + h("div", { class: "alarm-trigger-panel" }, [ + h("header", {}, [ + h("b", {}, "触发规则列表"), + h("span", {}, [ + h(Button, { secondary: true, onClick: () => p.notify("规则策略设定将在后续接入") }, [h(ControlOutlined), " 规则策略设定"]), + h(Button, { onClick: addAlarmTrigger }, [h(PlusOutlined), " 新增"]), + ]), + ]), + h(UiTable, { class: "data-table alarm-trigger-table" }, () => [ + h("thead", {}, h("tr", {}, [ + h("th", {}, "名称"), h("th", {}, "报警来源"), h("th", {}, "比较类型"), h("th", {}, "监测点"), h("th", {}, "运算符号"), h("th", {}, "阈值"), h("th", {}, "操作"), + ])), + h("tbody", {}, alarmDraft.value.triggers.map((trigger) => + h("tr", { key: trigger.id }, [ + h("td", {}, h(UiInput, { value: trigger.name, onChange: (e) => updateAlarmTrigger(trigger.id, "name", e.target.value) })), + h("td", {}, h(UiSelect, { value: trigger.source, onChange: (e) => updateAlarmTrigger(trigger.id, "source", e.target.value) }, () => [h("option", {}, "当前设备"), h("option", {}, "关联设备")])), + h("td", {}, h(UiSelect, { value: trigger.compareType, onChange: (e) => updateAlarmTrigger(trigger.id, "compareType", e.target.value) }, () => [h("option", {}, "数值"), h("option", {}, "状态"), h("option", {}, "字符串")])), + h("td", {}, h(UiSelect, { value: trigger.point, onChange: (e) => updateAlarmTrigger(trigger.id, "point", e.target.value) }, () => [h("option", { value: "" }, "请选择"), ...cps.value.map((point) => h("option", { key: point.key, value: point.name }, point.name || "未命名采集点"))])), + h("td", {}, h(UiSelect, { value: trigger.operator, onChange: (e) => updateAlarmTrigger(trigger.id, "operator", e.target.value) }, () => [h("option", {}, ">"), h("option", {}, ">="), h("option", {}, "<"), h("option", {}, "<="), h("option", {}, "="), h("option", {}, "!=")])), + h("td", {}, h(UiInput, { value: trigger.threshold, onChange: (e) => updateAlarmTrigger(trigger.id, "threshold", e.target.value), placeholder: "请输入" })), + h("td", {}, h(AntButton, { type: "text", danger: true, title: "删除触发规则", icon: h(DeleteOutlined), onClick: () => removeAlarmTrigger(trigger.id) })), + ]) + )), + ]), + alarmDraft.value.triggers.length === 0 ? h("div", { class: "alarm-trigger-empty" }, "暂无数据") : null, + ]), + ]), + ]) + : null + ), + h(Drawer, { + title: "AI 智能补全", + width: 440, + open: aiOpen.value, + onClose: () => (aiOpen.value = false), + }, () => + h("div", { class: "ai-assist-drawer" }, [ + h("div", { class: "ai-assist-intro" }, [h(RobotOutlined), h("div", {}, [h("h3", {}, "补充采集点"), h("p", {}, "AI 将根据设备名称、所属领域和说明生成合适的采集点,并以追加模式写入该设备模板。")])]), + h("p", { class: "hint" }, "为当前设备模板补充一套合适的采集点(追加模式,不覆盖已手动录入的采集点)。"), + h(UiActions, { class: "drawer-actions" }, () => [ + h(Button, { disabled: cpAi.completing.value, onClick: runCpComplete }, cpAi.completing.value ? "采集中…" : "开始补全"), + cpAi.completing.value ? h(Button, { secondary: true, onClick: stopCpComplete }, "停止") : null, + h(Button, { secondary: true, onClick: viewCpCompletePrompt }, "查看提示词"), + ]), + (cpAi.completing.value || cpAi.log.value) + ? h("div", { class: "modal-console" }, [ + h("div", { class: "modal-console-head" }, "AI 智能补全"), + h("pre", { ref: cpAi.ref, class: "modal-console-body" }, cpAi.log.value || "(等待 AI 分析…)"), + ]) + : null, + ]) + ), + h("div", { style: { marginTop: 8 } }, [h(Button, { onClick: save }, "保存设备")]), + ]), + ]; + }, +}; + +export { DeviceImageField, DeviceTemplateCard, CP_RANGE_PRESETS, fileToBase64 }; diff --git a/src-vue/components/DomainPageThumb.vue b/src-vue/components/DomainPageThumb.vue new file mode 100644 index 0000000..1123b4d --- /dev/null +++ b/src-vue/components/DomainPageThumb.vue @@ -0,0 +1,51 @@ + + + diff --git a/src-vue/components/DropdownButton.vue b/src-vue/components/DropdownButton.vue new file mode 100644 index 0000000..ec4964f --- /dev/null +++ b/src-vue/components/DropdownButton.vue @@ -0,0 +1,36 @@ + + + diff --git a/src-vue/components/Field.vue b/src-vue/components/Field.vue new file mode 100644 index 0000000..a9f5da3 --- /dev/null +++ b/src-vue/components/Field.vue @@ -0,0 +1,14 @@ + + + diff --git a/src-vue/components/ImagePage.vue b/src-vue/components/ImagePage.vue new file mode 100644 index 0000000..d8ba186 --- /dev/null +++ b/src-vue/components/ImagePage.vue @@ -0,0 +1,9 @@ + + + diff --git a/src-vue/components/Login.vue b/src-vue/components/Login.vue new file mode 100644 index 0000000..eb4a4f2 --- /dev/null +++ b/src-vue/components/Login.vue @@ -0,0 +1,29 @@ + + + diff --git a/src-vue/components/Modal.vue b/src-vue/components/Modal.vue new file mode 100644 index 0000000..2fa371a --- /dev/null +++ b/src-vue/components/Modal.vue @@ -0,0 +1,125 @@ + + + diff --git a/src-vue/components/Pagination.vue b/src-vue/components/Pagination.vue new file mode 100644 index 0000000..a144b56 --- /dev/null +++ b/src-vue/components/Pagination.vue @@ -0,0 +1,52 @@ + + + diff --git a/src-vue/components/Panel.vue b/src-vue/components/Panel.vue new file mode 100644 index 0000000..958e894 --- /dev/null +++ b/src-vue/components/Panel.vue @@ -0,0 +1,27 @@ + + + diff --git a/src-vue/components/PrimaryButton.vue b/src-vue/components/PrimaryButton.vue new file mode 100644 index 0000000..0f54b97 --- /dev/null +++ b/src-vue/components/PrimaryButton.vue @@ -0,0 +1,24 @@ + + + diff --git a/src-vue/components/ResourcePlaceholder.vue b/src-vue/components/ResourcePlaceholder.vue new file mode 100644 index 0000000..f933177 --- /dev/null +++ b/src-vue/components/ResourcePlaceholder.vue @@ -0,0 +1,11 @@ + + + diff --git a/src-vue/components/SearchInput.vue b/src-vue/components/SearchInput.vue new file mode 100644 index 0000000..bc60a6d --- /dev/null +++ b/src-vue/components/SearchInput.vue @@ -0,0 +1,27 @@ + + + diff --git a/src-vue/components/SideMenu.vue b/src-vue/components/SideMenu.vue new file mode 100644 index 0000000..8e38284 --- /dev/null +++ b/src-vue/components/SideMenu.vue @@ -0,0 +1,30 @@ + + + diff --git a/src-vue/components/SiteEditTabs.vue b/src-vue/components/SiteEditTabs.vue new file mode 100644 index 0000000..2407915 --- /dev/null +++ b/src-vue/components/SiteEditTabs.vue @@ -0,0 +1,24 @@ + + + diff --git a/src-vue/components/StatusTag.vue b/src-vue/components/StatusTag.vue new file mode 100644 index 0000000..247c30f --- /dev/null +++ b/src-vue/components/StatusTag.vue @@ -0,0 +1,17 @@ + + + diff --git a/src-vue/components/Steps.vue b/src-vue/components/Steps.vue new file mode 100644 index 0000000..0e0f78c --- /dev/null +++ b/src-vue/components/Steps.vue @@ -0,0 +1,24 @@ + + + diff --git a/src-vue/components/SvgIcon.vue b/src-vue/components/SvgIcon.vue new file mode 100644 index 0000000..3f36d12 --- /dev/null +++ b/src-vue/components/SvgIcon.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/src-vue/components/dropdown-button.less b/src-vue/components/dropdown-button.less new file mode 100644 index 0000000..af58f02 --- /dev/null +++ b/src-vue/components/dropdown-button.less @@ -0,0 +1,133 @@ +//带有菜单的按钮 +.dropdown-btn { + height: 34px; + padding: 0; + border: 1px solid #C8C8C8; + background: #FFFFFF; + box-shadow: none; + border-radius: 4px; + cursor: pointer; + font-family: 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', + 'Helvetica Neue', sans-serif; + + &:hover, + &:focus { + border-color: #008CD6; + } + + &:focus { + outline: none; + box-shadow: 0px 2px 8px 0px rgba(0, 140, 214, 0.5); + } + + .btn-content { + height: 100%; + padding: 0 8px; + display: flex; + flex-wrap: nowrap; + justify-content: left; + } + + &.blue { + color: #008CD6; + } + + &.blue:not(.disabled):not([disabled]) .btn-content { + &:hover { + color: #006AA5; + border-color: #89898A; + } + + &:active, + &.ant-dropdown-open, + &.ant-dropdown-open:hover { + color: #008CD6; + background: linear-gradient(315deg, rgba(11, 76, 217, 0.1) 0%, rgba(0, 140, 214, 0.1) 100%), #FFFFFF; + border-color: #008CD6; + } + } + + &.filter { + color: #323233; + + .btn-content { + flex-direction: row-reverse; + padding: 0 8px; + height: 100%; + display: flex; + align-items: center; + gap: 4px; + font-size: 16px; + line-height: 24px; + + .filter-text { + font-weight: 400; + height: 24px; + line-height: 24px; + color: #323233; + display: inline-block; + max-width: 212px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + .text { + color: #89898A; + font-weight: 700; + } + + // 图标颜色由 currentColor 驱动 + .btn-icon { + display: block; + color: #89898A; + transition: color .3s ease-in; + } + + &.ant-dropdown-open { + .btn-icon { + color: var(--ant-color-primary); + } + } + + &:active:not([disabled]), + &.ant-dropdown-open, + &.ant-dropdown-open:hover { + background: transparent !important; + + .text { + color: #008CD6 !important; + } + } + } + } +} + +// 下拉菜单(挂载到 body) +.self-dropdown.ant-dropdown { + .ant-dropdown-menu { + max-height: 300px; + overflow-y: auto; + padding: 8px 0; + border: 1px solid #008CD6; + border-radius: 4px; + box-shadow: 0 2px 8px 0 rgba(50, 50, 51, 0.2); + + .ant-dropdown-menu-item { + font-size: 1rem; + line-height: 24px; + padding: 8px 12px; + + &.selected-menu, + &:hover, + &.selected, + &.selected:hover { + background: linear-gradient(180deg, rgba(0, 140, 214, 0.10) 0%, rgba(0, 110, 255, 0.10) 100%); + } + + .blue { + color: #008CD6; + } + } + } +} \ No newline at end of file diff --git a/src-vue/components/header.less b/src-vue/components/header.less new file mode 100644 index 0000000..5d389ff --- /dev/null +++ b/src-vue/components/header.less @@ -0,0 +1,242 @@ +@g-brand-hover: linear-gradient(180deg, rgba(0, 140, 214, 0.05) 0%, rgba(0, 110, 255, 0.05) 100%), #FFF; +@g-brand-active: linear-gradient(180deg, rgba(0, 140, 214, 0.10) 0%, rgba(0, 110, 255, 0.10) 100%), #FFF; + +.header { + background-color: var(--ant-color-bg-container); + box-shadow: 0px 2px 8px rgba(50, 50, 51, 0.20); + position: fixed; + width: 100%; + top: 0; + z-index: 100; + height: 56px; + + .top-bar { + height: 8px; + // 顶部品牌渐变条(token 表达不了) + background: linear-gradient(90deg, #008cd6 0%, #004280 100%); + } + + .header-info { + padding: 0 24px; + + // 折叠开关图标:常态 / hover / active 由 currentColor 驱动 + .menu-toggle { + color: #89898A; + cursor: pointer; + transition: color .3s ease-in; + + &:hover { + color: var(--ant-color-text-base); + } + + &:active { + color: var(--ant-color-primary); + } + } + + .portal-logo { + height: 40px; + min-width: auto; + margin-right: 12px + } + + .portal-name { + color: var(--ant-color-text-base); + font-size: 20px; + font-weight: 700; + line-height: 32px; + } + + .drop-menu { + cursor: pointer; + height: 48px; + display: flex; + align-items: center; + transition: .4s ease-in; + + &:hover { + background: @g-brand-hover; + + .nav-icon.drop { + color: var(--ant-color-text-base); + } + } + + .ant-dropdown-open { + height: 100%; + display: flex; + align-items: center; + background: @g-brand-active; + + &::after { + content: ''; + height: 3px; + width: 100%; + background: var(--ant-color-primary); + position: absolute; + bottom: 0; + } + } + + // 图标颜色由 SvgIcon 的 currentColor 驱动 + .file-icon { + cursor: pointer; + color: #89898A; + transition: color .3s ease-in; + + &.active { + color: var(--ant-color-primary); + } + } + + .nav-icon { + cursor: pointer; + transition: color .3s ease-in; + + &.drop { + color: #89898A; + + &.active { + color: var(--ant-color-primary); + } + } + } + } + + .right-content { + padding: 8px 0; + + // 右侧图标:常态 / hover / active 由 currentColor 驱动 + .switch-manage, + .right-icon { + svg { + color: #89898A; + transition: color .3s ease-in; + } + + &:hover svg { + color: var(--ant-color-text-base); + } + + &:active svg { + color: var(--ant-color-primary); + } + } + + .has-user { + width: 24px; + height: 24px; + line-height: 24px; + font-style: normal; + font-weight: 400; + font-size: 12px; + text-align: center; + color: var(--ant-color-primary); + // 品牌浅蓝,无对应 token + background: #B4E3F6; + mix-blend-mode: normal; + border-radius: 50%; + } + + .nav-icon { + display: flex; + width: 24px; + height: 24px; + } + } + } + + @media (max-width: 767px) { + .header-info { + padding: 0 12px; + + .portal-name { + font-size: 16px; + line-height: 24px; + } + } + } + + @media (max-width: 539px) { + .header-info { + .portal-logo { + display: none; + } + } + } +} + +// Header 内部工具类:嵌套在 .header 内,作用域不外泄, +// 避免与页面(含 LLM 生成的)类名冲突 —— 页面里能用的类必须都是显式定义的。 +.header { + .flex { + display: flex; + } + + .items-center { + align-items: center; + } + + .justify-center { + justify-content: center; + } + + .justify-between { + justify-content: space-between; + } + + .cursor-pointer { + cursor: pointer; + } + + .gray { + color: #89898A; + } + + .black { + color: var(--ant-color-text-base); + } + + .blue { + color: var(--ant-color-primary); + } + + .ml-1 { + margin-left: 4px; + } + + .ml-2 { + margin-left: 8px; + } + + .mr-4 { + margin-right: 16px; + } + + .mr-12 { + margin-right: 12px; + } + + .px-4 { + padding-left: 4px; + padding-right: 4px; + } + + .text-small { + font-size: 12px; + line-height: 16px; + } + + .text-normal { + font-size: 16px; + line-height: 24px; + } + + .bold { + font-weight: 700; + } + + .font-w-4 { + font-weight: 400; + } +} diff --git a/src-vue/components/menu.less b/src-vue/components/menu.less new file mode 100644 index 0000000..3da7fc9 --- /dev/null +++ b/src-vue/components/menu.less @@ -0,0 +1,201 @@ +// SideMenu 私有样式。选择器为全局 .ant-menu:折叠态子菜单由 antd 渲染到 body 下的 portal, +// 限定作用域会漏掉 popup(等效 L0 第 5 层兜底)。 +@g-brand-active: linear-gradient(180deg, rgba(0, 140, 214, 0.10) 0%, rgba(0, 110, 255, 0.10) 100%), #FFF; + +.ant-menu { + width: 316px; + height: 100%; + background: #E1E1E1; + + /* 折叠态弹出子菜单 */ + &.ant-menu-submenu-popup { + width: unset; + height: unset; + padding-left: 0; + border: 1px solid var(--ant-color-primary); + box-shadow: 0px 2px 8px 0px rgba(0, 140, 214, 0.5); + + .ant-menu { + width: unset; + height: unset; + + .ant-menu-item { + width: unset; + margin-inline: 0; + + &:hover { + background: @g-brand-active !important; + } + + &.ant-menu-item-selected { + &::before { + display: none; + } + } + } + + .ant-menu-submenu { + &:hover { + background: @g-brand-active !important; + } + + .ant-menu-submenu-title { + display: flex; + justify-content: space-between; + align-items: center; + padding-inline: 16px; + } + } + } + } + + .ant-menu-submenu-expand-icon { + width: auto; + } + + .ant-menu-item { + margin: 0; + margin-inline: 0; + width: 100%; + + /* 渐变背景:antd 用 background-color 无法设渐变,必须直接覆盖 background */ + &:hover { + background: @g-brand-active !important; + } + + &.ant-menu-item-selected { + background: @g-brand-active; + + &::before { + content: ""; + display: block; + position: absolute; + left: 0; + width: 4px; + height: 24px; + background-color: var(--ant-color-primary); + } + } + } + + .ant-menu-submenu { + .ant-menu-submenu-title { + margin: 0; + width: 100%; + &:hover { + background: @g-brand-active !important; + } + } + + &.ant-menu-submenu-selected { + background: #FAFAFA; + + .ant-menu-sub { + background: #FAFAFA; + } + } + + .ant-menu-sub { + position: relative; + + &::before { + content: ''; + width: 1px; + height: 100%; + background: #C8C8C8; + position: absolute; + left: 33px; + top: 0; + z-index: 2; + } + + .ant-menu-submenu { + svg { + position: relative; + left: -3px; + } + + .ant-menu-submenu-title { + margin: 0 0 0 3px; + } + + .ant-menu-sub { + .ant-menu-item { + .ant-menu-title-content { + &::before { + content: ''; + width: 1px; + height: 100%; + background: #C8C8C8; + position: absolute; + left: 53px; + top: 0; + } + } + } + } + } + + .ant-menu-item { + margin-left: 3px; + + &.ant-menu-item-selected { + &::before { + content: ""; + display: block; + position: relative; + left: -18px; + top: 0; + width: 4px; + height: 24px; + background-color: var(--ant-color-primary); + } + + .ant-menu-title-content { + margin-left: -4px; + } + } + } + } + } + + &.ant-menu-inline-collapsed { + width: 72px; + background: #E1E1E1; + border-right: 1px solid #C8C8C8; + + .ant-menu-item { + margin-top: 4px; + + &:hover { + background: @g-brand-active !important; + } + + &::before { + top: 8px; + } + } + + .ant-menu-submenu { + .ant-menu-submenu-title:hover { + background: @g-brand-active; + } + + &.ant-menu-submenu-selected { + position: relative; + background: @g-brand-active; + + &::before { + content: ""; + display: block; + position: absolute; + left: 0; + top: 8px; + width: 4px; + height: 24px; + background-color: var(--ant-color-primary); + } + } + } + } +} diff --git a/src-vue/components/pagination.less b/src-vue/components/pagination.less new file mode 100644 index 0000000..11ae9e2 --- /dev/null +++ b/src-vue/components/pagination.less @@ -0,0 +1,101 @@ +// 底部分页栏 +@g-brand-hover: linear-gradient(180deg, rgba(0, 140, 214, 0.05) 0%, rgba(0, 110, 255, 0.05) 100%), #FFF; +@g-brand-active: linear-gradient(180deg, rgba(0, 140, 214, 0.10) 0%, rgba(0, 110, 255, 0.10) 100%), #FFF; + +.page-footer { + background: var(--ant-color-bg-layout); + border-top: 1px solid #E1E1E1; + display: flex; + align-items: center; + justify-content: flex-end; + padding: 8px 24px; + + .pagination { + display: flex; + align-items: center; + gap: 8px; + + .page-indicator { + margin: 0 8px; + color: var(--ant-color-text-base); + } + + // 翻页箭头:常态 / hover / active / disabled 由 currentColor 驱动 + .page-icon { + color: #89898A; + cursor: pointer; + transition: color .3s ease-in; + + &:hover { + color: var(--ant-color-text-base); + } + + &:active { + color: var(--ant-color-primary); + } + + &.disabled { + color: #C0C0C0; + cursor: not-allowed; + pointer-events: none; + } + } + + .page-size { + margin-left: 24px; + } + } + + // Select(pageSize 切换) + .ant-select { + border-radius: var(--ant-border-radius); + + .ant-select-selector { + background: var(--ant-color-bg-layout); + border: none !important; + font-size: 16px; + line-height: 24px; + padding: 4px 8px; + + .ant-select-selection-item { + color: var(--ant-color-text-base); + } + } + + // 箭头图标通过 suffixIcon 传入,颜色由 currentColor 驱动 + .ant-select-arrow { + margin-left: 4px; + top: 40%; + right: 0; + width: 24px; + height: 24px; + color: #89898A; + transition: color .3s ease-in; + } + + &:hover { + .ant-select-selector { + background: @g-brand-hover; + } + + .ant-select-arrow { + color: var(--ant-color-text-base); + } + } + + &.ant-select-focused { + .ant-select-selector { + box-shadow: none; + background: @g-brand-active; + + .ant-select-selection-item { + color: var(--ant-color-primary); + } + } + + .ant-select-arrow { + color: var(--ant-color-primary); + } + } + } +} diff --git a/src-vue/components/search-input.less b/src-vue/components/search-input.less new file mode 100644 index 0000000..ec168b6 --- /dev/null +++ b/src-vue/components/search-input.less @@ -0,0 +1,36 @@ +// Input(作用域限定到本组件,避免影响页面上其它带 affix 的 Input) +.search-input.ant-input-affix-wrapper { + width: 240px; + padding: 4px 8px; + font-size: 1rem; + line-height: 24px; + border-color: #C8C8C8; + + &:hover { + border-color: #008CD6; + } + + .ant-input { + font-size: 1rem; + line-height: 24px; + } + + // 搜索图标:颜色由 currentColor 驱动 + .search-prefix svg { + color: #89898A; + transition: color .3s ease-in; + + &:hover { + color: var(--ant-color-text-base); + } + + &:active { + color: var(--ant-color-primary); + } + } + + &.ant-input-affix-wrapper-focused { + border-color: #008CD6; + box-shadow: 0px 2px 8px 0px rgba(0, 140, 214, 0.5); + } +} \ No newline at end of file diff --git a/src-vue/index.html b/src-vue/index.html new file mode 100644 index 0000000..f8656ce --- /dev/null +++ b/src-vue/index.html @@ -0,0 +1,12 @@ + + + + + + StationBuilder 建站工具 + + +
+ + + diff --git a/src-vue/lib/api.js b/src-vue/lib/api.js new file mode 100644 index 0000000..710c03a --- /dev/null +++ b/src-vue/lib/api.js @@ -0,0 +1,90 @@ +// Shared helpers ported from app/page.tsx (data layer + small utilities). + +export async function fetchDb(path, opts) { + const res = await fetch(`/api/db${path}`, opts); + if (!res.ok) { + const text = await res.text().catch(() => ""); + throw new Error(text || `HTTP ${res.status}`); + } + const ct = res.headers.get("content-type") || ""; + if (ct.includes("application/json")) return res.json(); + return res; +} + +export function downloadBlob(blob, filename) { + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = filename; + a.click(); + URL.revokeObjectURL(url); +} + +export function formatInstances(rule, count) { + if (!rule || count <= 0) return ""; + const pad = Math.max(2, String(count).length); + const parts = []; + for (let i = 1; i <= count; i++) { + const num = String(i).padStart(pad, "0"); + if (rule.includes("#")) { + parts.push(rule.replace(/#+/g, (m) => String(i).padStart(Math.max(pad, m.length), "0"))); + } else { + const sep = rule.endsWith("-") ? "" : "-"; + parts.push(`${rule}${sep}${num}`); + } + } + return parts.join("、"); +} + +export function buildMuLeaves(nodes, parent = "") { + const out = []; + for (const n of nodes) { + const myParent = parent ? `${parent}/${n.key}` : n.key; + if (n.tabs && n.tabs.length) { + for (const t of n.tabs) { + if (typeof t === "string") out.push({ key: `${myParent}/${t}`, label: t, parentMenu: parent || n.key }); + else out.push({ key: `${myParent}/${t.label}`, label: t.label, disabled: t.disabled, note: t.note, parentMenu: parent || n.key }); + } + } else if (n.children) { + out.push(...buildMuLeaves(n.children, myParent)); + } else { + out.push({ key: myParent, label: n.key, parentMenu: parent || "" }); + } + } + return out; +} + +export function countChars(v) { + return Array.from(v || "").length; +} + +export function domainTagColor(name) { + const map = { 数据中心: "blue", 智慧水务: "cyan", 燃气: "orange", "水务 · 自来水厂": "green", 新能源: "purple", 其他: "default" }; + if (map[name]) return map[name]; + const palette = ["blue", "cyan", "orange", "green", "purple", "red"]; + let hash = 0; + for (let i = 0; i < name.length; i++) { + hash = (hash << 5) - hash + name.charCodeAt(i); + hash |= 0; + } + return palette[Math.abs(hash) % palette.length]; +} + +// Cube renderer loader (used by DashboardThumb / DomainPageThumb). +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; + } + 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.onerror = () => reject(new Error("renderer load failed")); + document.head.appendChild(s); + }); + return rendererPromise; +} diff --git a/src-vue/lib/meta.js b/src-vue/lib/meta.js new file mode 100644 index 0000000..7d9c7f8 --- /dev/null +++ b/src-vue/lib/meta.js @@ -0,0 +1,54 @@ +// Port of page.tsx meta / SITE_EDIT_STEPS / MODELS constants. + +export const PAGE_KEYS = [ + "login", "projects", "siteEdit", "basic", "assets", "opsflow", "pageConfig", + "functions", "generate", "result", "preview", "domains", "domainDetail", + "styleLibrary", "deviceTemplates", "toolSettings", "domainSettings", "dashboard", + "report-dashboard", "report-doc", "basic-components", "func-components", "filters", + "datasource", "monitor-dashboard", "twin-model", "ops-template", "knowledge-template", +]; + +export const meta = { + login: { label: "内部登录", icon: "◇", subtitle: "使用公司账号登录" }, + projects: { label: "站点管理", icon: "▦", subtitle: "先建立上下级站点,再按模板配置各站点" }, + siteEdit: { label: "站点编辑", icon: "", subtitle: "维护已建站点的基本属性与参考资料" }, + basic: { label: "站点信息", icon: "▤", subtitle: "维护站点基本信息与参考资料" }, + assets: { label: "资产设置", icon: "▧", subtitle: "在一个工作区完成资产结构、设备节点、属性与数据绑定" }, + opsflow: { label: "运维流程配置", icon: "", subtitle: "" }, + pageConfig: { label: "页面配置", icon: "", subtitle: "选择站点所需的标准功能页面、领域仪表板及数字孪生场景" }, + functions: { label: "菜单配置", icon: "☷", subtitle: "设置应用基本信息,配置第四步已选择页面的菜单" }, + generate: { label: "生成确认", icon: "↻", subtitle: "确认生成范围,调用 Cube Skill 生成页面和模拟数据" }, + result: { label: "站点结果", icon: "◫", subtitle: "集中查看、预览、校验并下载站点交付物" }, + preview: { label: "Cube 页面预览", icon: "▣", subtitle: "检查单个 Cube 页面效果,并通过反馈快速重新生成" }, + domains: { label: "领域方案", icon: "◆", subtitle: "查看已沉淀的领域能力,并按需预览、下载或导入方案" }, + domainDetail: { label: "方案详情", icon: "◇", subtitle: "集中查看领域方案包含的资产、页面、知识与菜单能力" }, + deviceTemplates: { label: "设备模板", icon: "⬡", subtitle: "管理设备模板及采集点配置,供领域方案和站点复用" }, + styleLibrary: { label: "页面样式", icon: "❖", subtitle: "管理可复用的 Cube 页面视觉样式与预览资源" }, + toolSettings: { label: "内部工具配置", icon: "", subtitle: "配置 StationBuilder 使用的内部能力、AI 服务和默认模型" }, + domainSettings: { label: "领域配置", icon: "", subtitle: "维护领域分类,供领域方案与站点项目统一使用" }, + dashboard: { label: "仪表板", icon: "◈", subtitle: "仅展示仪表盘示意图片" }, + "report-dashboard": { label: "仪表板报表", icon: "", subtitle: "" }, + "report-doc": { label: "文档报表", icon: "", subtitle: "" }, + "basic-components": { label: "基础组件库", icon: "", subtitle: "" }, + "func-components": { label: "功能组件库", icon: "", subtitle: "" }, + filters: { label: "筛选器", icon: "", subtitle: "" }, + datasource: { label: "数据源", icon: "", subtitle: "" }, + "monitor-dashboard": { label: "监控仪表板", icon: "", subtitle: "" }, + "twin-model": { label: "数字孪生模型", icon: "", subtitle: "" }, + "ops-template": { label: "运维模板", icon: "", subtitle: "" }, + "knowledge-template": { label: "知识模板", icon: "", subtitle: "" }, +}; + +export const SITE_EDIT_STEPS = ["basic", "assets", "opsflow", "pageConfig", "functions"]; + +export const MODELS = [ + { name: "Auto", tag: "自动选择", rate: "—" }, + { name: "Hy3", tag: "免费", rate: "0.00x" }, + { name: "GLM-5.4", tag: "订阅优先", rate: "0.79x" }, + { name: "GLM-5.3", tag: "订阅优先", rate: "0.79x" }, + { name: "GLM-5.2", tag: "夜间折扣", rate: "0.79x" }, + { name: "GLM-5.1", tag: "", rate: "0.79x" }, + { name: "GLM-5v-Turbo", tag: "视觉理解", rate: "0.95x" }, + { name: "MiniMax-M3", tag: "高性价比", rate: "0.25x" }, + { name: "Kimi-K3", tag: "订阅优先", rate: "1.62x" }, +]; diff --git a/src-vue/main.js b/src-vue/main.js new file mode 100644 index 0000000..7efc450 --- /dev/null +++ b/src-vue/main.js @@ -0,0 +1,24 @@ +import { createApp } from "vue"; +import Antd from "ant-design-vue"; +import "ant-design-vue/dist/reset.css"; + +// Brand / layout styles — order mirrors the React app's src/main.tsx. +import "./styles/globals.css"; +import "./styles/site-workspace.css"; +import "./styles/ui-system.css"; +import "./styles/ui-layout-compat.css"; +import "./styles/antd.less"; +import "./styles/theme-overrides.css"; +import "./styles/styles.less"; +import "./styles/brand-layout.css"; + +// Brand component styles. +import "./components/menu.less"; +import "./components/header.less"; +import "./components/search-input.less"; +import "./components/pagination.less"; +import "./components/dropdown-button.less"; + +import App from "./App.vue"; + +createApp(App).use(Antd).mount("#root"); diff --git a/src-vue/pages/Assets.vue b/src-vue/pages/Assets.vue new file mode 100644 index 0000000..8127dc3 --- /dev/null +++ b/src-vue/pages/Assets.vue @@ -0,0 +1,284 @@ + + + diff --git a/src-vue/pages/Basic.vue b/src-vue/pages/Basic.vue new file mode 100644 index 0000000..ea79aae --- /dev/null +++ b/src-vue/pages/Basic.vue @@ -0,0 +1,245 @@ + + + diff --git a/src-vue/pages/Dashboard.vue b/src-vue/pages/Dashboard.vue new file mode 100644 index 0000000..2b21815 --- /dev/null +++ b/src-vue/pages/Dashboard.vue @@ -0,0 +1,5 @@ + diff --git a/src-vue/pages/DeviceTemplates.vue b/src-vue/pages/DeviceTemplates.vue new file mode 100644 index 0000000..2d9365c --- /dev/null +++ b/src-vue/pages/DeviceTemplates.vue @@ -0,0 +1,251 @@ + + + diff --git a/src-vue/pages/DomainSettings.vue b/src-vue/pages/DomainSettings.vue new file mode 100644 index 0000000..7120db3 --- /dev/null +++ b/src-vue/pages/DomainSettings.vue @@ -0,0 +1,610 @@ + + + diff --git a/src-vue/pages/Functions.vue b/src-vue/pages/Functions.vue new file mode 100644 index 0000000..b4a4adc --- /dev/null +++ b/src-vue/pages/Functions.vue @@ -0,0 +1,435 @@ + + + diff --git a/src-vue/pages/Generate.vue b/src-vue/pages/Generate.vue new file mode 100644 index 0000000..b0795d6 --- /dev/null +++ b/src-vue/pages/Generate.vue @@ -0,0 +1,60 @@ + + + diff --git a/src-vue/pages/ManualAssetConfiguration.vue b/src-vue/pages/ManualAssetConfiguration.vue new file mode 100644 index 0000000..a282eff --- /dev/null +++ b/src-vue/pages/ManualAssetConfiguration.vue @@ -0,0 +1,1054 @@ + + + diff --git a/src-vue/pages/PageConfig.vue b/src-vue/pages/PageConfig.vue new file mode 100644 index 0000000..524b331 --- /dev/null +++ b/src-vue/pages/PageConfig.vue @@ -0,0 +1,323 @@ + + + diff --git a/src-vue/pages/Placeholder.vue b/src-vue/pages/Placeholder.vue new file mode 100644 index 0000000..54a905e --- /dev/null +++ b/src-vue/pages/Placeholder.vue @@ -0,0 +1,17 @@ + + + diff --git a/src-vue/pages/Preview.vue b/src-vue/pages/Preview.vue new file mode 100644 index 0000000..772e538 --- /dev/null +++ b/src-vue/pages/Preview.vue @@ -0,0 +1,145 @@ + + + diff --git a/src-vue/pages/Projects.vue b/src-vue/pages/Projects.vue new file mode 100644 index 0000000..00d7846 --- /dev/null +++ b/src-vue/pages/Projects.vue @@ -0,0 +1,442 @@ + + + diff --git a/src-vue/pages/Result.vue b/src-vue/pages/Result.vue new file mode 100644 index 0000000..00bf34d --- /dev/null +++ b/src-vue/pages/Result.vue @@ -0,0 +1,167 @@ + + + diff --git a/src-vue/pages/SiteConfigurationContext.vue b/src-vue/pages/SiteConfigurationContext.vue new file mode 100644 index 0000000..4dfba62 --- /dev/null +++ b/src-vue/pages/SiteConfigurationContext.vue @@ -0,0 +1,35 @@ + + + diff --git a/src-vue/pages/StyleLibrary.vue b/src-vue/pages/StyleLibrary.vue new file mode 100644 index 0000000..a4e8ee1 --- /dev/null +++ b/src-vue/pages/StyleLibrary.vue @@ -0,0 +1,145 @@ + + + diff --git a/src-vue/pages/ToolSettings.vue b/src-vue/pages/ToolSettings.vue new file mode 100644 index 0000000..bd6d894 --- /dev/null +++ b/src-vue/pages/ToolSettings.vue @@ -0,0 +1,51 @@ + + + diff --git a/src-vue/pages/domain/CompanyDomainLibrary.vue b/src-vue/pages/domain/CompanyDomainLibrary.vue new file mode 100644 index 0000000..13b4188 --- /dev/null +++ b/src-vue/pages/domain/CompanyDomainLibrary.vue @@ -0,0 +1,127 @@ + + + diff --git a/src-vue/pages/domain/DeviceImageField.vue b/src-vue/pages/domain/DeviceImageField.vue new file mode 100644 index 0000000..44a6f80 --- /dev/null +++ b/src-vue/pages/domain/DeviceImageField.vue @@ -0,0 +1,24 @@ + + + diff --git a/src-vue/pages/domain/DeviceTemplateCreate.vue b/src-vue/pages/domain/DeviceTemplateCreate.vue new file mode 100644 index 0000000..d9b3d9a --- /dev/null +++ b/src-vue/pages/domain/DeviceTemplateCreate.vue @@ -0,0 +1,68 @@ + + + diff --git a/src-vue/pages/domain/DomainCapabilityDetail.vue b/src-vue/pages/domain/DomainCapabilityDetail.vue new file mode 100644 index 0000000..9e2e144 --- /dev/null +++ b/src-vue/pages/domain/DomainCapabilityDetail.vue @@ -0,0 +1,394 @@ + + + diff --git a/src-vue/pages/domain/DomainDetail.vue b/src-vue/pages/domain/DomainDetail.vue new file mode 100644 index 0000000..d9df74b --- /dev/null +++ b/src-vue/pages/domain/DomainDetail.vue @@ -0,0 +1,48 @@ + + + diff --git a/src-vue/pages/domain/DomainFunctionsStep.vue b/src-vue/pages/domain/DomainFunctionsStep.vue new file mode 100644 index 0000000..8ca92bc --- /dev/null +++ b/src-vue/pages/domain/DomainFunctionsStep.vue @@ -0,0 +1,186 @@ + + + diff --git a/src-vue/pages/domain/DomainGenerateReview.vue b/src-vue/pages/domain/DomainGenerateReview.vue new file mode 100644 index 0000000..a72b983 --- /dev/null +++ b/src-vue/pages/domain/DomainGenerateReview.vue @@ -0,0 +1,157 @@ + + + diff --git a/src-vue/pages/domain/DomainKnowledgeStep.vue b/src-vue/pages/domain/DomainKnowledgeStep.vue new file mode 100644 index 0000000..e2fb1fa --- /dev/null +++ b/src-vue/pages/domain/DomainKnowledgeStep.vue @@ -0,0 +1,139 @@ + + + diff --git a/src-vue/pages/domain/DomainPagePreviewModal.vue b/src-vue/pages/domain/DomainPagePreviewModal.vue new file mode 100644 index 0000000..7cf5511 --- /dev/null +++ b/src-vue/pages/domain/DomainPagePreviewModal.vue @@ -0,0 +1,93 @@ + + + diff --git a/src-vue/pages/domain/DomainSteps.vue b/src-vue/pages/domain/DomainSteps.vue new file mode 100644 index 0000000..73ae319 --- /dev/null +++ b/src-vue/pages/domain/DomainSteps.vue @@ -0,0 +1,43 @@ + + + diff --git a/src-vue/pages/domain/DomainStyleLibrary.vue b/src-vue/pages/domain/DomainStyleLibrary.vue new file mode 100644 index 0000000..9f99849 --- /dev/null +++ b/src-vue/pages/domain/DomainStyleLibrary.vue @@ -0,0 +1,67 @@ + + + diff --git a/src-vue/pages/domain/DomainWizard.vue b/src-vue/pages/domain/DomainWizard.vue new file mode 100644 index 0000000..063d9d7 --- /dev/null +++ b/src-vue/pages/domain/DomainWizard.vue @@ -0,0 +1,709 @@ + + + diff --git a/src-vue/pages/domain/ImportDomainPackage.vue b/src-vue/pages/domain/ImportDomainPackage.vue new file mode 100644 index 0000000..67e2ad2 --- /dev/null +++ b/src-vue/pages/domain/ImportDomainPackage.vue @@ -0,0 +1,111 @@ + + + diff --git a/src-vue/pages/domain/PackageModal.vue b/src-vue/pages/domain/PackageModal.vue new file mode 100644 index 0000000..3fadf85 --- /dev/null +++ b/src-vue/pages/domain/PackageModal.vue @@ -0,0 +1,56 @@ + + + diff --git a/src-vue/pages/domain/StyleEditorModal.vue b/src-vue/pages/domain/StyleEditorModal.vue new file mode 100644 index 0000000..6c0f831 --- /dev/null +++ b/src-vue/pages/domain/StyleEditorModal.vue @@ -0,0 +1,173 @@ + + + diff --git a/src-vue/pages/domain/StylePreview.vue b/src-vue/pages/domain/StylePreview.vue new file mode 100644 index 0000000..f2c4a76 --- /dev/null +++ b/src-vue/pages/domain/StylePreview.vue @@ -0,0 +1,23 @@ + + + diff --git a/src-vue/pages/domain/domainCommon.js b/src-vue/pages/domain/domainCommon.js new file mode 100644 index 0000000..ec1455f --- /dev/null +++ b/src-vue/pages/domain/domainCommon.js @@ -0,0 +1,116 @@ +// Shared helpers for the domain pages, ported faithfully from app/page.tsx. +// Pure helpers live here; components needing them import from this module. + +import { ref, watch } from "vue"; +import wastewaterPhoto from "../../../src/assets/solutions/wastewater-600x300.webp"; +import datacenterPhoto from "../../../src/assets/solutions/datacenter-600x300.webp"; +import energyPhoto from "../../../src/assets/solutions/energy-600x300.webp"; + +// ---- app/page.tsx:2606 ---- +export function friendlyDomainName(name) { + return /数据中心|AIDC/i.test(name || "") ? "AIDC 数据中心" : name || "其他领域"; +} + +// ---- app/page.tsx:2610 ---- +export function domainScene(domain) { + if (/数据中心|AIDC/i.test(domain)) + return { + code: "AIDC", + tone: "violet", + desc: "面向数据中心基础设施的资产、监控、能效与运维能力。", + twins: ["机房三维总览", "冷源系统孪生"], + wiki: ["数据中心基础设施百科", "制冷与供配电设备说明"], + }; + if (/水务|污水|自来水/i.test(domain)) + return { + code: "WATER", + tone: "blue", + desc: "覆盖水处理工艺、泵站设备、运行监控与标准运维资料。", + twins: ["厂区工艺流程孪生", "泵房设备场景"], + wiki: ["水处理工艺百科", "泵阀与仪表设备说明"], + }; + if (/新能源|储能|光伏/i.test(domain)) + return { + code: "ENERGY", + tone: "green", + desc: "覆盖储能与新能源场站的设备、运行页面和安全管理规则。", + twins: ["储能电站全景", "电池舱运行孪生"], + wiki: ["储能系统百科", "电池与变流器设备说明"], + }; + return { + code: "SITE", + tone: "gray", + desc: "沉淀该领域可复用的资产、页面、知识和菜单配置。", + twins: ["场站三维总览"], + wiki: ["领域基础百科", "设备与工艺说明"], + }; +} + +// ---- app/page.tsx:2617 ---- +export const SOLUTION_PHOTOS = { WATER: wastewaterPhoto, AIDC: datacenterPhoto, ENERGY: energyPhoto }; + +// ---- app/page.tsx:1936 ---- +export const DOMAIN_STEPS = [ + { key: "basic", label: "方案基本属性" }, + { key: "knowledge", label: "领域知识" }, + { key: "assets", label: "资产设置" }, + { key: "functions", label: "功能与菜单" }, + { key: "opsflow", label: "运维流程" }, + { key: "generate", label: "方案打包" }, + { key: "expert", label: "专家确认" }, +]; + +// ---- app/page.tsx:95 (Status tone) ---- +export function statusTone(v) { + const s = String(v); + if (/不可用|失败|异常|failed/.test(s)) return "bad"; + if (/完成|正常|成功|通过|推荐|可用|已配置|已生成|已上传|generated/.test(s)) return "ok"; + if (/生成中|校验中|告警|running/.test(s)) return "warn"; + return "muted"; +} + +// ---- app/page.tsx:1964 ---- +export async function streamInto(res, setLog, onEv) { + const reader = res.body.getReader(); + const dec = new TextDecoder(); + let buf = ""; + for (;;) { + const { done, value } = await reader.read(); + if (done) break; + buf += dec.decode(value, { stream: true }); + const lines = buf.split("\n"); + buf = lines.pop() || ""; + for (const line of lines) { + if (!line.trim()) continue; + try { + const ev = JSON.parse(line); + if (ev.log) setLog((prev) => prev + ev.log); + onEv(ev); + } catch (e) { + /* ignore malformed line */ + } + } + } +} + +// ---- app/page.tsx:1956 ---- +export function useStreamComplete() { + const completing = ref(false); + const log = ref(""); + const el = ref(null); + watch(log, () => { + const node = el.value; + if (node) node.scrollTop = node.scrollHeight; + }); + return { + completing, + setCompleting: (v) => { + completing.value = v; + }, + log, + setLog: (v) => { + log.value = typeof v === "function" ? v(log.value) : v; + }, + ref: el, + }; +} diff --git a/src-vue/pages/domain/useConfirm.js b/src-vue/pages/domain/useConfirm.js new file mode 100644 index 0000000..dc0a1cc --- /dev/null +++ b/src-vue/pages/domain/useConfirm.js @@ -0,0 +1,59 @@ +// Faithful port of React useConfirm() from app/page.tsx:1498. +// Returns { confirm, el } where `el` is a Vue component (render-fn) to mount. +import { ref, h } from "vue"; +import UiOverlay from "../../ui/UiOverlay.vue"; +import UiButton from "../../ui/UiButton.vue"; +import UiActions from "../../ui/UiActions.vue"; + +export function useConfirm() { + const state = ref({ open: false, message: "", resolve: null }); + + const confirm = (message) => + new Promise((resolve) => { + state.value = { open: true, message, resolve }; + }); + + const close = (v) => { + if (state.value.resolve) state.value.resolve(v); + state.value = { ...state.value, open: false }; + }; + + const ConfirmEl = { + setup() { + return () => + state.value.open + ? h( + UiOverlay, + { class: "dlg-backdrop", onClick: () => close(false) }, + () => [ + h( + "div", + { class: "dlg-box", onClick: (e) => e.stopPropagation() }, + [ + h("p", state.value.message), + h( + UiActions, + { class: "dlg-actions" }, + () => [ + h( + UiButton, + { class: "button secondary", onClick: () => close(false) }, + () => "取消" + ), + h( + UiButton, + { class: "button", onClick: () => close(true) }, + () => "确定" + ), + ] + ), + ] + ), + ] + ) + : null; + }, + }; + + return { confirm, el: ConfirmEl }; +} diff --git a/src-vue/site-menu-model.js b/src-vue/site-menu-model.js new file mode 100644 index 0000000..acbb024 --- /dev/null +++ b/src-vue/site-menu-model.js @@ -0,0 +1,115 @@ +export const APPLICATION_COLOR_SCHEMES = [ + { key: "blue", label: "蓝色", color: "#009fe3" }, + { key: "green", label: "绿色", color: "#23a77b" }, + { key: "orange", label: "橙色", color: "#ed8b2c" }, + { key: "purple", label: "紫色", color: "#8860c3" }, + { key: "red", label: "红色", color: "#df5c5c" }, +]; + +export function effectiveStandardPageKeys(site, leaves) { + const selected = site?.mu || []; + if (selected.length || site?.page_config?.standard_pages_initialized) return selected; + return leaves.filter((leaf) => !leaf.disabled).map((leaf) => leaf.key); +} + +export function selectedMenuSources(site, leaves) { + const twins = site?.page_config?.twin_ids || []; + const cubeIds = site?.page_config?.dashboard_ids ?? (site?.cubes || []).map((cube) => cube.id); + const standardKeys = effectiveStandardPageKeys(site, leaves); + return [ + ...twins.map((id) => ({ + key: `sc:${id}`, + name: id === "site-overview" ? "场站全景" : id === "process-scene" ? "工艺与设备场景" : id, + kind: "sc", + ref: id, + path: ["数字孪生"], + })), + ...(site?.cubes || []) + .filter((cube) => cubeIds.includes(cube.id)) + .map((cube) => ({ key: `cube:${cube.id}`, name: cube.name, kind: "cube", ref: cube.id, path: ["领域监控"] })), + ...leaves + .filter((leaf) => !leaf.disabled && standardKeys.includes(leaf.key)) + .map((leaf) => ({ key: `mu:${leaf.key}`, name: leaf.label, kind: "mu", ref: leaf.key, path: leaf.parentMenu ? leaf.parentMenu.split("/") : [] })), + ]; +} + +export function buildSiteMenu(site, leaves, saved = site?.menu || []) { + const result = []; + const used = new Set(); + const groups = new Map(); + const findSaved = (key, fallback) => + saved.find((item) => !used.has(item.id) && item.source_key === key) || + saved.find((item) => !used.has(item.id) && !item.source_key && fallback(item)); + const addGroup = (key, name, parent, locked = false) => { + if (groups.has(key)) return groups.get(key); + const aliases = key === "group:sc" ? ["数字孪生", "数字孪生场景"] : key === "group:cube" ? ["领域监控", "领域仪表板"] : [name]; + const existing = findSaved(key, (item) => !item.page_type && aliases.includes(item.label)); + const entry = { + id: existing?.id ?? key, + parent_id: parent, + label: locked ? name : existing?.label || name, + page_type: null, + ref_id: null, + source_key: key, + source_name: name, + }; + used.add(entry.id); + groups.set(key, entry); + result.push(entry); + return entry; + }; + const sc = addGroup("group:sc", "数字孪生", null, true); + const cube = addGroup("group:cube", "领域监控", null, true); + const sources = selectedMenuSources(site, leaves); + const dynamic = sources.filter((source) => source.kind !== "mu"); + dynamic.sort((a, b) => { + if (a.kind !== b.kind) return a.kind === "sc" ? -1 : 1; + const rank = (source) => { + const index = saved.findIndex((item) => item.source_key === source.key || (item.page_type === source.kind && String(item.ref_id) === String(source.ref))); + return index < 0 ? Number.MAX_SAFE_INTEGER : index; + }; + return rank(a) - rank(b); + }); + for (const source of [...dynamic, ...sources.filter((item) => item.kind === "mu")]) { + let parent = source.kind === "sc" ? sc.id : source.kind === "cube" ? cube.id : null; + if (source.kind === "mu") { + let path = ""; + for (const segment of source.path) { + path += `/${segment}`; + parent = addGroup(`group:mu:${path}`, segment, parent).id; + } + } + const existing = findSaved(source.key, (item) => item.page_type === source.kind && String(item.ref_id) === String(source.ref)); + const entry = { + id: existing?.id ?? source.key, + parent_id: parent, + label: existing?.label || source.name, + page_type: source.kind, + ref_id: source.ref, + source_key: source.key, + source_name: source.name, + }; + used.add(entry.id); + result.push(entry); + } + return orderMenu(result); +} + +export function orderMenu(menu) { + const result = []; + const used = new Set(); + const walk = (parent) => { + for (const item of menu.filter((item) => item.parent_id === parent)) { + if (used.has(item.id)) continue; + used.add(item.id); + result.push(item); + walk(item.id); + } + }; + walk(null); + return result; +} + +export function menuSelectionSignature(site, leaves) { + return JSON.stringify(selectedMenuSources(site, leaves).map((source) => [source.key, source.name, source.path])); +} diff --git a/src-vue/styles/antd.less b/src-vue/styles/antd.less new file mode 100644 index 0000000..7b82d3e --- /dev/null +++ b/src-vue/styles/antd.less @@ -0,0 +1,88 @@ +/* antd v6 兜底覆盖 + * + * 这是 L0 的第 5 层:token 与 CSS 变量都表达不了、只能靠选择器命中的覆盖。 + * 尽量少写 —— 内部选择器依赖 v6 的 DOM 结构,大版本升级即可能失效。 + * + * 能改 token 的 → src/theme.json + * 能改变量或只是渐变的 → src/theme/overrides.css + * + * 已知待收窄项(中性灰暂无对应 antd token):#EDEDED / #FAFAFA / #E1E1E1 / #89898A + */ + +// Breadcrumb:token 里没有字重项 +.ant-breadcrumb { + .ant-breadcrumb-item { + font-weight: 700; + } +} + +// Tabs 公共样式 +.ant-tabs { + background: #EDEDED; + font-family: var(--ant-font-family); + + .ant-tabs-nav { + margin-bottom: 0; + + &::before { + border-bottom: 1px solid #E1E1E1; + } + } + + &.ant-tabs-card { + .ant-tabs-tab { + padding: 12px 24px; + background: #EDEDED; + border-bottom: 1px solid #E1E1E1; + + .ant-tabs-tab-btn { + border: none; + font-weight: 700; + + &>span { + font-size: 1rem; + line-height: 24px; + font-weight: 700; + color: #89898A; + } + } + + &.ant-tabs-tab-active { + background: var(--ant-color-bg-container); + border: 1px solid #E1E1E1; + border-bottom-color: transparent; + + .ant-tabs-tab-btn { + &>span { + color: var(--ant-color-primary); + } + } + } + } + } + + .ant-tabs-content { + background: #FAFAFA; + } + + // Tabs 中数据条目数量应用此类名 + .count-badge { + background-color: #e1e1e1; + border: 1px solid #c8c8c8; + color: #c8c8c8; + border-radius: 9999px; + font-size: 12px; + min-width: 16px; + line-height: 16px; + font-weight: 700; + padding: 0 4px; + box-sizing: border-box; + margin-left: 8px; + + &.active { + background-color: #b6f0d3; + border: 1px solid var(--ant-color-success); + color: var(--ant-color-success); + } + } +} diff --git a/src-vue/styles/brand-layout.css b/src-vue/styles/brand-layout.css new file mode 100644 index 0000000..15a6a77 --- /dev/null +++ b/src-vue/styles/brand-layout.css @@ -0,0 +1,52 @@ +/* StationBuilder business layout on top of the Skill's unmodified brand files. + Keep the approved WISE-IoT header artwork and the existing configuration flow. */ +.sb-brand-shell.app-shell { padding-left:0; } +.sb-brand-shell>.body { min-width:0; } +.sb-brand-shell .sb-brand-nav { position:sticky; top:56px; align-self:flex-start; height:calc(100dvh - 56px); display:flex; flex-direction:column; background:var(--ant-color-border); overflow:auto; } +.sb-brand-nav>nav { flex:1; min-height:0; } +.sb-brand-nav>nav>.ant-menu { height:auto; min-height:100%; font-family:var(--ant-font-family); font-size:var(--ant-font-size); } +.sb-brand-nav .ant-menu-item,.sb-brand-nav .ant-menu-submenu-title { font-weight:400; } +.sb-brand-nav>.design-doc-link { position:static; margin:var(--ant-padding-sm) var(--ant-padding); height:var(--ant-control-height); flex-shrink:0; border-radius:var(--ant-border-radius); background:var(--ant-color-primary); color:var(--ant-color-text-light-solid); } +.sb-brand-shell .workspace.main { display:flex; flex-direction:column; padding:0; min-height:calc(100dvh - 56px); } +.sb-brand-shell .workspace>.page-heading { padding:var(--ant-padding) var(--ant-padding-lg); min-height:80px; background:var(--ant-color-bg-layout); gap:var(--ant-padding); } +.sb-brand-shell .page-heading h1 { font-size:var(--ant-font-size-heading-4); line-height:var(--ant-line-height-heading-4); font-weight:var(--ant-font-weight-strong); } +.sb-brand-shell .page-heading p { font-size:var(--ant-font-size-sm); line-height:var(--ant-line-height-sm); margin-top:var(--ant-padding-xxs); color:var(--ant-color-text-secondary); } +.sb-brand-shell .page-heading>div:last-child { display:flex; flex-wrap:nowrap; align-items:center; gap:var(--ant-padding-xs); } +.sb-brand-shell .workspace>.content { flex:1; min-width:0; padding:var(--ant-padding) var(--ant-padding-lg) var(--ant-padding-lg); } +.sb-brand-shell .workspace>.sticky-actions { position:sticky; inset:auto; bottom:0; width:100%; min-height:64px; height:auto; margin:0; padding:var(--ant-padding) var(--ant-padding-lg); border-top:1px solid var(--ant-color-border); background:var(--ant-color-bg-container); z-index:20; } +.sb-brand-shell .station-config-footer,.sb-brand-shell .sticky-actions>div { flex-wrap:nowrap; gap:var(--ant-padding-xs); } +.sb-brand-shell .filterbar.company-filterbar,.sb-brand-shell .station-list-toolbar { display:flex; align-items:center; gap:var(--ant-padding-xs); padding-block:var(--ant-padding); min-height:64px; height:auto; } +.sb-brand-shell .station-list-toolbar>div:last-child,.sb-brand-shell .filter-actions { margin-left:auto; display:flex; align-items:center; flex-wrap:nowrap; gap:var(--ant-padding-xs); } +.sb-brand-shell .search-input.ant-input-affix-wrapper { flex-shrink:0; max-width:100%; height:var(--ant-control-height); } +.sb-brand-shell .page-footer>.pagination { height:auto; min-height:0; padding:0; margin:0; border:0; background:transparent; } +.sb-brand-shell .page-footer .page-size { min-width:128px; } +.sb-brand-shell .station-ui-table .ant-table-cell { height:auto; line-height:var(--ant-line-height); padding-inline:var(--ant-padding); } +.sb-brand-shell .station-ui-table .ant-table-thead>tr>th { padding-block:var(--ant-padding-sm); text-align:left; border-bottom:2px solid var(--ant-color-primary); } +.sb-brand-shell .station-ui-table .ant-table-tbody>tr>td { padding-block:var(--ant-table-cell-padding-block); } +.sb-brand-shell .panel.ant-card>.ant-card-head.panel-head { display:block; min-height:48px; padding:0 var(--ant-padding-lg); } +.sb-brand-shell .panel.ant-card .ant-card-head-wrapper { gap:var(--ant-padding); } +.sb-brand-shell .panel.ant-card .ant-card-head-title { font-size:var(--ant-font-size); font-weight:var(--ant-font-weight-strong); } +.sb-brand-shell .panel.ant-card>.ant-card-body { padding:var(--ant-padding-lg); } +.sb-brand-shell .company-list-panel.ant-card>.ant-card-body { padding:0 var(--ant-padding) var(--ant-padding-sm); } +.sb-brand-shell .station-ui-tabs>.ant-tabs-nav { margin:0; background:var(--ant-color-fill-quaternary); } +.sb-brand-shell .station-ui-tabs>.ant-tabs-nav .ant-tabs-tab { padding:var(--ant-padding-sm) var(--ant-padding-lg); } +.sb-brand-shell .station-ui-tabs>.ant-tabs-content-holder { background:var(--ant-color-bg-layout); } +.sb-brand-shell .station-ui-tabs .ant-tabs-tab-btn b,.sb-brand-shell .station-ui-tabs .ant-tabs-tab-btn i { display:inline-flex; align-items:center; min-width:16px; line-height:16px; padding:0 4px; margin-left:8px; border:1px solid var(--ant-color-border); border-radius:9999px; } +.sb-brand-shell .station-ui-tabs .ant-tabs-tab-active .ant-tabs-tab-btn b { border-color:var(--ant-color-success); } +.sb-brand-shell .domain-capability-grid { gap:var(--ant-padding-sm); } +.sb-brand-shell .domain-capability-detail { height:calc(100dvh - 176px); min-height:800px; } +.sb-brand-shell .domain-capability-grid { flex:1; min-height:0; } +.sb-brand-shell .domain-capability-card { height:100%; min-height:0; max-height:none; } +.sb-brand-shell .domain-capability-card>footer { padding:var(--ant-padding-xs); min-height:48px; flex-wrap:nowrap; } +.sb-brand-shell .domain-capability-card>footer .ant-btn { padding-inline:var(--ant-padding-xs); } +.sb-brand-shell .dashboard-manager-actions { display:flex; flex-wrap:nowrap; align-items:center; gap:var(--ant-padding-xs); } +@media (max-width:1440px) { + .sb-brand-shell .domain-capability-detail { height:auto; min-height:0; } + .sb-brand-shell .domain-capability-grid { grid-template-columns:repeat(2,minmax(0,1fr)); } + .sb-brand-shell .domain-capability-card { height:520px; min-height:0; } +} +@media (max-width:1000px) { + .sb-brand-shell .workspace>.content { padding:var(--ant-padding); } + .sb-brand-shell .station-list-toolbar,.sb-brand-shell .filterbar.company-filterbar { overflow-x:auto; } + .sb-brand-shell .domain-capability-grid { grid-template-columns:1fr; } +} diff --git a/src-vue/styles/globals.css b/src-vue/styles/globals.css new file mode 100644 index 0000000..5dc49da --- /dev/null +++ b/src-vue/styles/globals.css @@ -0,0 +1,579 @@ +@import "tailwindcss"; +*{box-sizing:border-box}html,body{margin:0;min-height:100%;font-family:var(--ant-font-family);color:var(--ant-color-text-base);font-size:var(--ant-font-size-sm);background:var(--ant-color-bg-layout)}button,input,select,textarea{font:inherit;color:inherit}button{cursor:pointer}.app-shell{min-height:100vh;padding-top:56px;padding-left:192px}.topbar{position:fixed;z-index:50;left:0;right:0;top:0;height:56px;border-top:3px solid transparent;background-image:linear-gradient(var(--ant-color-bg-container),var(--ant-color-bg-container)),linear-gradient(90deg,var(--ant-color-primary),var(--ant-color-primary));background-origin:border-box;background-clip:padding-box,border-box;border-bottom:1px solid var(--ant-color-border);display:flex;align-items:center;padding:0 12px;gap:8px;box-shadow:0 1px 3px color-mix(in srgb,var(--ant-color-text-base) 7%,transparent)}.hamburger{border:0;background:transparent;font-size:var(--ant-font-size);color:var(--ant-color-text-secondary)}.brand-mark,.login-logo{color:var(--ant-color-primary);font-size:var(--ant-font-size-heading-3);line-height:1;font-weight:600}.topbar>strong{font-size:var(--ant-font-size)}.divider{height:19px;border-left:1px solid var(--ant-color-border);margin:0 4px}.top-actions{margin-left:auto;display:flex;align-items:center;gap:16px;color:var(--ant-color-text-secondary)}.top-actions>span{font-size:var(--ant-font-size);position:relative}.top-actions i{position:absolute;width:5px;height:5px;background:var(--ant-color-error);border-radius:50%;right:-2px;top:-2px}.top-actions small{font-size:var(--ant-font-size-sm);line-height:1.2}.avatar{width:23px;height:23px;border-radius:50%;background:var(--ant-color-primary-bg);color:var(--ant-color-primary);display:grid!important;place-items:center;font-size:var(--ant-font-size-sm)!important}.site-switcher{margin:4px 8px 4px;height:30px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);background:var(--ant-color-bg-container);color:var(--ant-color-text-base);font-size:var(--ant-font-size-sm);padding:0 8px;width:calc(100% - 18px)}.site-switcher:focus{outline:1px solid var(--ant-color-primary)}.side-nav{position:fixed;z-index:35;top:56px;bottom:0;left:0;width:190px;background:var(--ant-color-bg-layout);border-right:1px solid var(--ant-color-border);display:flex;flex-direction:column;padding:0}.side-title{height:48px;padding:16px 16px 0;font-weight:600;font-size:var(--ant-font-size)}.side-title span{float:right;color:var(--ant-color-text-secondary)}.side-nav>button{height:41px;border:0;background:transparent;text-align:left;padding:0 16px;display:flex;align-items:center;gap:12px;border-left:3px solid transparent;font-size:var(--ant-font-size)}.side-nav>button:hover{background:var(--ant-color-fill-quaternary);color:var(--ant-color-primary-hover)}.side-nav>button.active{background:var(--ant-color-primary-bg);color:var(--ant-color-primary);border-left-color:var(--ant-color-primary)}.side-nav>button b{width:18px;text-align:center}.side-nav>button em{font-style:normal;width:21px;height:21px;border:1px solid var(--ant-color-border);border-radius:50%;display:grid;place-items:center;font-size:var(--ant-font-size-sm);background:var(--ant-color-bg-container)}.side-nav>button.active em{background:var(--ant-color-primary);border-color:var(--ant-color-primary);color:var(--ant-color-bg-container)}.side-nav>small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);padding:20px 16px 8px;text-transform:uppercase;letter-spacing:.8px}.side-help{position:relative;margin:auto 12px 12px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);padding:12px;display:flex;flex-direction:column;gap:4px;font-size:var(--ant-font-size-sm)}.side-help span{color:var(--ant-color-text-secondary)} +.model-trigger{display:flex;align-items:center;justify-content:space-between;cursor:pointer;color:var(--ant-color-text-secondary)} +.model-trigger:hover{color:var(--ant-color-primary-hover)} +.model-trigger .caret{font-size:var(--ant-font-size-sm);margin-left:4px} +.model-backdrop{position:fixed;inset:0;z-index:60} +.model-popover{position:absolute;left:0;right:0;bottom:calc(100% + 6px);z-index:61;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);box-shadow:0 8px 22px color-mix(in srgb,var(--ant-color-text-base) 13%,transparent);padding:8px;display:flex;flex-direction:column;gap:4px} +.model-popover-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:4px} +.model-popover-head>span{font-weight:600;color:var(--ant-color-primary);font-size:var(--ant-font-size-sm)} +.model-popover-head>small{color:var(--ant-color-text-disabled);font-size:var(--ant-font-size-sm)} +.model-row{display:flex;align-items:center;gap:8px;padding:4px 8px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);background:var(--ant-color-bg-layout);font-size:var(--ant-font-size-sm);cursor:pointer} +.model-row input[type=radio]{margin:0;accent-color:var(--ant-color-primary)} +.model-row .model-name{font-weight:600;color:var(--ant-color-text-base);flex:1} +.model-row .model-tag{color:var(--ant-color-success);font-size:var(--ant-font-size-sm);background:var(--ant-color-bg-layout);border:1px solid var(--ant-color-success-bg);padding:4px 4px;border-radius:var(--ant-border-radius);white-space:nowrap} +.model-row .model-rate{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);min-width:34px;text-align:right} +.model-row.disabled{opacity:.45;cursor:not-allowed;background:var(--ant-color-bg-layout)} +.model-row.disabled .model-tag{color:var(--ant-color-text-secondary);background:var(--ant-color-bg-layout);border-color:var(--ant-color-border)} +.model-row:not(.disabled):hover{border-color:var(--ant-color-primary-bg);background:var(--ant-color-bg-layout)}.workspace{min-height:calc(100vh - 56px);padding-bottom:64px}.crumb{height:34px;padding:12px 20px 0;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.crumb b{color:var(--ant-color-primary)}.page-heading{min-height:60px;padding:4px 20px 12px;display:flex;align-items:center;justify-content:space-between}.page-heading h1{font-size:var(--ant-font-size-heading-4);margin:0 0 4px}.page-heading p{margin:0;color:var(--ant-color-text-secondary)}.button{border:1px solid var(--ant-color-primary-active);background:var(--ant-color-primary-active);color:var(--ant-color-bg-container);border-radius:var(--ant-border-radius);min-width:92px;height:31px;padding:0 16px;margin-left:8px}.button:hover{background:var(--ant-color-primary-hover)}.button.secondary{background:var(--ant-color-bg-container);color:var(--ant-color-text-secondary);border-color:var(--ant-color-border)}.button.secondary:hover{border-color:var(--ant-color-primary);color:var(--ant-color-primary)}.button:disabled{opacity:.55;cursor:not-allowed}.steps{height:70px;background:var(--ant-color-bg-container);border-top:1px solid var(--ant-color-border);border-bottom:1px solid var(--ant-color-border);display:grid;grid-template-columns:repeat(4,1fr);padding:0 24px}.steps button{border:0;background:transparent;display:flex;align-items:center;position:relative;text-align:left;color:var(--ant-color-text-secondary);padding:0 20px}.steps button>i{font-style:normal;width:29px;height:29px;border-radius:50%;border:1px solid var(--ant-color-border);display:grid;place-items:center;margin-right:12px;background:var(--ant-color-bg-container)}.steps button span{display:flex;flex-direction:column;gap:4px}.steps button small{font-size:var(--ant-font-size-sm)}.steps button>b{position:absolute;right:0;font-size:var(--ant-font-size-heading-3);color:var(--ant-color-text-disabled)}.steps button.active{color:var(--ant-color-text-base)}.steps button.active>i{background:var(--ant-color-primary);border-color:var(--ant-color-primary);color:var(--ant-color-text-light-solid)}.steps button.done>i{background:var(--ant-color-success);border-color:var(--ant-color-success);color:var(--ant-color-bg-container)}.steps button.locked{cursor:default}.content{padding:16px 20px}.panel{background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);margin-bottom:16px}.panel-head{min-height:43px;border-bottom:1px solid var(--ant-color-border);padding:8px 12px;display:flex;justify-content:space-between;align-items:center}.panel-head>strong{font-size:var(--ant-font-size)}.panel-head .button{height:28px}.panel-body{padding:12px}.summary-strip{display:grid;grid-template-columns:repeat(5,1fr);height:64px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);margin-bottom:16px}.summary-strip div{display:flex;align-items:center;justify-content:center;gap:8px;border-right:1px solid var(--ant-color-border)}.summary-strip div:last-child{border:0}.summary-strip b{font-size:var(--ant-font-size-heading-3)}.summary-strip span{color:var(--ant-color-text-secondary)}.filterbar{height:45px;display:flex;align-items:center;gap:8px;padding-bottom:12px;border-bottom:1px solid var(--ant-color-border)}.filterbar>label{width:205px;height:30px;border:1px solid var(--ant-color-border);display:flex;align-items:center;padding:0 8px;color:var(--ant-color-text-secondary)}.filterbar input{border:0;outline:0;width:100%;padding-left:8px}.filterbar select,.preview-toolbar select{height:30px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);padding:0 24px 0 8px}.filterbar>span{flex:1}.view-switch{display:flex}.view-switch button,.icon-button{width:31px;height:29px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container)}.view-switch button.active{background:var(--ant-color-primary);color:var(--ant-color-bg-container);border-color:var(--ant-color-primary)}.icon-button{border:0;font-size:var(--ant-font-size)}.data-table{width:100%;border-collapse:collapse}.data-table th{height:35px;background:var(--ant-color-bg-layout);color:var(--ant-color-text-secondary);text-align:left;font-size:var(--ant-font-size-sm);font-weight:600;border-bottom:1px solid var(--ant-color-border);padding:0 12px}.data-table td{height:48px;border-bottom:1px solid var(--ant-color-border);padding:8px 12px;font-size:var(--ant-font-size-sm)}.data-table tr:hover td{background:var(--ant-color-bg-layout)}.link{border:0;background:transparent;color:var(--ant-color-primary);padding:0}.site-icon{display:inline-grid;place-items:center;width:30px;height:30px;margin-right:8px;color:var(--ant-color-primary);border:1px solid var(--ant-color-border);background:var(--ant-color-bg-layout);font-size:var(--ant-font-size);vertical-align:middle}.site-icon.big{width:40px;height:40px;font-size:var(--ant-font-size-heading-3)}.status{display:inline-flex;align-items:center;justify-content:center;border-radius:var(--ant-border-radius);padding:4px 8px;font-size:var(--ant-font-size-sm);line-height:1.2;border:1px solid}.status.ok{color:var(--ant-color-success);background:var(--ant-color-bg-layout);border-color:var(--ant-color-success)}.status.warn{color:var(--ant-color-error);background:var(--ant-color-primary-bg);border-color:var(--ant-color-error-bg)}.status.bad{color:var(--ant-color-error);background:var(--ant-color-bg-layout);border-color:var(--ant-color-error)}.status.muted{color:var(--ant-color-text-secondary);background:var(--ant-color-bg-layout);border-color:var(--ant-color-border)}.dots,.trash{border:0;background:transparent;color:var(--ant-color-text-secondary)}.pagination{height:46px;display:flex;justify-content:flex-end;align-items:center;gap:8px;padding-top:12px}.pagination span{margin-right:12px;color:var(--ant-color-text-secondary)}.pagination button{width:28px;height:28px;border:0;background:var(--ant-color-bg-container)}.pagination button.active{background:var(--ant-color-primary-bg);color:var(--ant-color-primary)}.pagination select{border:0;background:var(--ant-color-bg-container)}.project-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;padding:12px 0}.project-grid article{border:1px solid var(--ant-color-border);padding:16px;cursor:pointer}.project-grid article:hover{border-color:var(--ant-color-primary);box-shadow:none}.project-grid article>div{display:flex;justify-content:space-between}.project-grid h3{margin:12px 0 4px}.project-grid p,.project-grid small{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.project-grid section{display:flex;gap:20px;border-top:1px solid var(--ant-color-border);border-bottom:1px solid var(--ant-color-border);padding:12px 0;margin:12px 0}.project-grid section span{display:flex;flex-direction:column}.project-grid section b{font-size:var(--ant-font-size)}.two-column{display:grid;grid-template-columns:1fr 340px;gap:16px}.two-column.equal{grid-template-columns:1fr 1fr}.basic-layout>.panel>.panel-body{padding:16px}.stack{display:flex;flex-direction:column}.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px}.form-grid>label{display:flex;flex-direction:column;gap:8px;font-size:var(--ant-font-size-sm);font-weight:600}.form-grid>label>input,.form-grid>label>select,.form-grid>label>textarea{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);border-radius:var(--ant-border-radius);padding:8px;outline:none;font-weight:400}.form-grid>label>input:focus,.form-grid>label>select:focus,.form-grid>label>textarea:focus{border-color:var(--ant-color-primary)}.form-grid>label>input,.form-grid>label>select{height:34px}.form-grid>label>textarea{min-height:80px;resize:vertical;line-height:1.6}.field{display:flex;flex-direction:column;gap:8px}.field>span{font-size:var(--ant-font-size-sm);font-weight:600}.field>span i{color:red;font-style:normal;margin-right:4px}.field input,.field select,.field textarea{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);border-radius:var(--ant-border-radius);padding:8px;outline:none}.field input,.field select{height:34px}.field textarea{min-height:130px;resize:vertical;line-height:1.6}.field textarea.small{min-height:80px}.field small{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.form-grid .field:nth-child(n+3){grid-column:1/-1}.upload{height:90px;border:1px dashed var(--ant-color-border);background:var(--ant-color-bg-layout);display:flex;flex-direction:column;justify-content:center;align-items:center;color:var(--ant-color-text-secondary);gap:4px}.upload b{color:var(--ant-color-primary);font-size:var(--ant-font-size-heading-4)}.ai-box{text-align:center;padding:12px}.ai-box>span{width:42px;height:42px;border-radius:50%;background:linear-gradient(135deg,var(--ant-color-primary),var(--ant-color-primary));color:var(--ant-color-text-light-solid);display:grid;place-items:center;margin:auto;font-weight:600}.ai-box h3{font-size:var(--ant-font-size);margin:12px}.ai-box p{color:var(--ant-color-text-secondary);line-height:1.7;text-align:left}.meter{height:7px;border-radius:var(--ant-border-radius);background:var(--ant-color-bg-layout);overflow:hidden}.meter i{display:block;height:100%;background:linear-gradient(90deg,var(--ant-color-primary),var(--ant-color-success));transition:width .35s}.tips{padding-left:24px;line-height:2;color:var(--ant-color-text-secondary)}.kpi-row{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}.kpi-row>div{height:75px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);padding:12px 16px;position:relative}.kpi-row span{display:block;color:var(--ant-color-primary);font-size:var(--ant-font-size-sm);margin-bottom:8px}.kpi-row b{font-size:var(--ant-font-size-heading-3)}.kpi-row small{margin-left:4px;color:var(--ant-color-text-secondary)}.kpi-row .status{margin-top:8px}.editable td{padding:8px}.editable input,.editable select{height:29px;border:1px solid var(--ant-color-border);width:100%;padding:0 8px;background:var(--ant-color-bg-container)}.editable .number{width:65px}.tree{line-height:2.2}.tree .l1{padding-left:24px}.tree .l2{padding-left:52px;color:var(--ant-color-text-secondary)}.tree span{border-radius:var(--ant-border-radius);background:var(--ant-color-bg-layout);padding:4px 8px;font-size:var(--ant-font-size-sm)}.file-card{display:flex;align-items:center;gap:12px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-layout);padding:12px}.file-card .excel{width:36px;height:42px;background:var(--ant-color-success);color:var(--ant-color-bg-container);display:grid;place-items:center;font-weight:600}.file-card>div{flex:1}.file-card p{margin:4px 0 0;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.checks{display:flex;gap:20px;color:var(--ant-color-success);padding:12px 4px 0;font-size:var(--ant-font-size-sm)}.tabs{height:46px;border-bottom:1px solid var(--ant-color-border);display:flex;gap:8px;margin:-12px -12px 0;padding-left:12px}.tabs button{padding:0 20px;border:0;border-bottom:2px solid transparent;background:var(--ant-color-bg-container)}.tabs button.active{color:var(--ant-color-primary);border-bottom-color:var(--ant-color-primary)}.tabs i{font-style:normal;border-radius:var(--ant-border-radius);background:var(--ant-color-bg-layout);padding:4px 8px;margin-left:4px}.section-toolbar{display:flex;justify-content:space-between;align-items:center;padding:16px 4px}.section-toolbar p{margin:4px 0 0;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.mu-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}.mu-grid article{border:1px solid var(--ant-color-border);display:grid;grid-template-columns:42% 58%;min-height:128px;cursor:pointer}.mu-grid article.selected{border:2px solid var(--ant-color-primary);background:var(--ant-color-bg-layout)}.mu-thumb{margin:8px;background:var(--ant-color-bg-layout);display:grid;place-items:center;position:relative;overflow:hidden}.mu-thumb:after{content:"";width:72%;height:40%;border:1px solid var(--ant-color-primary-bg);background:var(--ant-color-bg-container);box-shadow:none}.mu-thumb b{position:absolute;z-index:2;color:var(--ant-color-primary);font-size:var(--ant-font-size-heading-3)}.mu-grid article>div:last-child{padding:12px 12px 8px 0}.mu-grid header{display:flex;gap:8px;align-items:center}.mu-grid h3{font-size:var(--ant-font-size-sm);margin:0}.mu-grid p{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);line-height:1.5;min-height:32px}.mu-grid button{border:0;background:transparent;color:var(--ant-color-primary);padding:0}.blue{color:var(--ant-color-primary)}.type-tag{background:var(--ant-color-bg-layout);padding:4px 8px;border-radius:var(--ant-border-radius)}.wide-cell{min-width:300px}.menu-builder{display:grid;grid-template-columns:230px 1fr 240px;gap:16px;background:var(--ant-color-bg-layout);padding:16px}.page-pool,.menu-tree,.menu-preview{background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);padding:12px}.page-pool p{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.page-pool div{border:1px solid var(--ant-color-border);padding:12px;margin-top:8px;background:var(--ant-color-bg-layout)}.menu-tree section{border:1px solid var(--ant-color-border);margin-bottom:8px;padding:12px}.menu-tree section>span{float:right}.menu-tree section>div{margin:8px 0 0 16px;padding:8px;border-top:1px solid var(--ant-color-border)}.menu-tree i{font-style:normal;font-size:var(--ant-font-size-sm);background:var(--ant-color-bg-layout);color:var(--ant-color-primary);padding:4px;margin-right:8px}.menu-tree i.cube{background:var(--ant-color-bg-layout);color:var(--ant-color-primary)}.menu-tree>button{border:1px dashed var(--ant-color-border);background:var(--ant-color-bg-layout);width:100%;height:34px}.menu-preview aside{background:var(--ant-color-bg-layout);min-height:250px;display:flex;flex-direction:column;padding-top:12px}.menu-preview strong{padding:12px}.menu-preview button{border:0;background:transparent;text-align:left;padding:12px}.menu-preview button.active{background:var(--ant-color-primary-bg);color:var(--ant-color-primary)}.generate-layout{display:grid;grid-template-columns:1.1fr .9fr;gap:16px}.confirm-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.confirm-grid div{border:1px solid var(--ant-color-border);padding:12px;display:flex;flex-direction:column;gap:4px;position:relative}.confirm-grid span,.confirm-grid small{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.confirm-grid button{position:absolute;right:10px;top:10px;border:0;background:transparent;color:var(--ant-color-primary);font-size:var(--ant-font-size-sm)}.option-list{display:grid;grid-template-columns:1fr 1fr;gap:12px}.option-list label{display:flex;align-items:center;gap:8px}.task-panel{height:100%}.overall{background:var(--ant-color-bg-layout);border:1px solid var(--ant-color-primary);padding:12px}.overall>div:first-child{display:flex;justify-content:space-between;margin-bottom:8px}.overall p{margin:8px 0 0;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.task-list{padding:12px 0}.task-list>div{display:flex;align-items:center;border-bottom:1px solid var(--ant-color-border);padding:8px 4px}.task-list>div>i{font-style:normal;width:25px;height:25px;border-radius:50%;border:1px solid var(--ant-color-border);display:grid;place-items:center;margin-right:8px}.task-list>div>i.done{background:var(--ant-color-success);border-color:var(--ant-color-success);color:var(--ant-color-bg-container)}.task-list>div>i.spin{color:var(--ant-color-primary)}.task-list>div>span{display:flex;flex:1;flex-direction:column;gap:4px}.task-list small{color:var(--ant-color-text-secondary)}.task-panel>.panel-body>.button{width:100%;margin:4px 0}.result-header{display:flex;align-items:center;justify-content:space-between;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);padding:12px;margin-bottom:16px}.result-header>div{display:flex;align-items:center;gap:12px}.result-header h2{margin:0 0 4px}.result-header p{margin:0;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.result-layout{display:grid;grid-template-columns:1fr 280px;gap:16px}.result-pages{display:grid;grid-template-columns:1fr;gap:12px}.result-pages article{border:1px solid var(--ant-color-border)}.result-pages article>div:last-child{padding:12px}.result-pages article header{display:flex;justify-content:space-between}.result-pages h3{font-size:var(--ant-font-size-sm);margin:12px 0 4px}.result-pages p,.result-pages small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.result-pages footer{display:flex;margin-top:8px}.result-pages footer .button{margin:0 4px 0 0;min-width:68px;height:27px}.dashboard-thumb{height:115px;background:var(--ant-color-bg-layout);position:relative;padding:12px 12px 12px 36px}.dashboard-thumb>i{position:absolute;left:0;top:0;bottom:0;width:25px;background:var(--ant-color-fill-secondary)}.dashboard-thumb>header{display:block;height:10px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border)}.dashboard-thumb>section{display:flex;gap:4px;margin-top:4px}.dashboard-thumb>section b{height:22px;flex:1;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-primary)}.dashboard-thumb>footer{position:absolute;left:35px;right:46px;bottom:10px;height:50px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);display:flex;align-items:flex-end;gap:4px;padding:8px}.dashboard-thumb>footer em{flex:1;background:var(--ant-color-primary);height:45%}.dashboard-thumb>footer em:nth-child(2){height:75%}.dashboard-thumb>footer em:nth-child(4){height:92%}.dashboard-thumb>span{position:absolute;right:9px;bottom:10px;width:31px;height:50px;background:conic-gradient(var(--ant-color-success) 0 72%,var(--ant-color-fill-secondary) 72%)}.dashboard-thumb-live{position:relative;min-height:115px;background:var(--ant-color-bg-layout);border-bottom:1px solid var(--ant-color-border);overflow:hidden}.dashboard-thumb-live>div{position:relative}.thumb-empty{position:absolute;inset:0;display:grid;place-items:center;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}result-menu div{display:flex;justify-content:space-between;border-bottom:1px solid var(--ant-color-border);padding:12px 4px}.result-menu span{background:var(--ant-color-bg-layout);border-radius:var(--ant-border-radius);padding:4px 8px}.text-button{border:0;background:transparent;color:var(--ant-color-primary);margin-top:12px}.score{display:flex;align-items:center;justify-content:center;gap:12px;padding:12px}.score b{width:55px;height:55px;border-radius:50%;border:5px solid var(--ant-color-success);display:grid;place-items:center;font-size:var(--ant-font-size)}.score span{color:var(--ant-color-success)}.validation{padding-left:12px;list-style:none;line-height:2;color:var(--ant-color-success)}.preview-shell{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);margin:-4px}.preview-toolbar{height:45px;display:flex;align-items:center;justify-content:space-between;padding:0 12px;border-bottom:1px solid var(--ant-color-border)}.preview-toolbar>div{display:flex;align-items:center;gap:8px}.preview-toolbar button{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);height:29px;padding:0 12px}.preview-main{display:grid;grid-template-columns:1fr 300px;height:655px}.cube-canvas{position:relative;background:var(--ant-color-bg-layout);border-right:1px solid var(--ant-color-border);overflow:hidden}.cube-top{position:absolute;left:0;right:0;top:0;height:32px;background:var(--ant-color-bg-container);border-top:3px solid var(--ant-color-primary-active);border-bottom:1px solid var(--ant-color-border);display:flex;align-items:center;padding:0 12px;gap:16px}.cube-top b{color:var(--ant-color-primary)}.cube-top i{margin-left:auto;font-style:normal;color:var(--ant-color-text-secondary)}.cube-side{position:absolute;left:0;top:32px;bottom:0;width:130px;background:var(--ant-color-bg-layout);display:flex;flex-direction:column}.cube-side strong{padding:16px 12px}.cube-side button{height:37px;border:0;background:transparent;text-align:left;padding-left:12px}.cube-side button.active{background:var(--ant-color-primary-bg);color:var(--ant-color-primary)}.cube-content{position:absolute;left:130px;top:32px;right:0;bottom:0;padding:12px}.cube-content>header{display:flex;justify-content:space-between;align-items:center}.cube-content>header h2{font-size:var(--ant-font-size);margin:4px 0 8px}.cube-content>header span,.cube-content>header small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.cube-kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.cube-kpis>div{height:78px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);padding:8px;position:relative;display:flex;flex-direction:column}.cube-kpis span{font-size:var(--ant-font-size-sm);color:var(--ant-color-primary)}.cube-kpis b{font-size:var(--ant-font-size-heading-4);margin:4px 0}.cube-kpis small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.spark{position:absolute;right:9px;bottom:14px;width:42px;height:18px;border-top:3px solid var(--ant-color-primary);transform:skewY(-12deg);border-radius:50%}.spark.s1{transform:skewY(8deg)}.spark.s2{border-color:var(--ant-color-error)}.cube-grid{display:grid;grid-template-columns:1.7fr .8fr;gap:8px;margin-top:8px}.cube-grid>section{background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);padding:12px}.cube-grid h3{font-size:var(--ant-font-size-sm);margin:0 0 8px}.cube-grid h3 span,.cube-grid h3 button{float:right;border:0;background:transparent;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.line-chart{height:175px;position:relative}.line-chart>div{position:absolute;inset:0 0 20px;background:repeating-linear-gradient(to bottom,var(--ant-color-bg-container) 0,var(--ant-color-bg-container) 29px,var(--ant-color-fill-secondary) 30px)}.line-chart svg{position:absolute;left:0;right:0;top:0;height:145px;width:100%}.line-chart footer{position:absolute;left:0;right:0;bottom:0;display:flex;justify-content:space-between;font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.donut{width:115px;height:115px;border-radius:50%;background:conic-gradient(var(--ant-color-success) 0 80%,var(--ant-color-error-bg) 80% 92%,var(--ant-color-text-disabled) 92%);margin:12px auto;display:grid;place-items:center}.donut:before{content:"";position:absolute;width:72px;height:72px;background:var(--ant-color-bg-container);border-radius:50%}.donut b{z-index:1;font-size:var(--ant-font-size-heading-4);display:flex;flex-direction:column;align-items:center}.donut small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.donut-panel footer{display:flex;justify-content:space-around;font-size:var(--ant-font-size-sm)}.donut-panel footer i{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:4px}.green{background:var(--ant-color-success)}.orange{background:var(--ant-color-error-bg)}.gray{background:var(--ant-color-text-disabled)}.alarm-panel{grid-column:1/-1}.alarm-panel table{border-collapse:collapse;width:100%;font-size:var(--ant-font-size-sm)}.alarm-panel td{border-top:1px solid var(--ant-color-border);padding:8px}.inspector{background:var(--ant-color-bg-container);overflow:auto}.inspector>nav{height:42px;display:flex;border-bottom:1px solid var(--ant-color-border)}.inspector>nav button{flex:1;border:0;border-bottom:2px solid transparent;background:var(--ant-color-bg-container);font-size:var(--ant-font-size-sm)}.inspector>nav button.active{color:var(--ant-color-primary);border-bottom-color:var(--ant-color-primary)}.inspector-body{padding:16px}.inspector-body h3{font-size:var(--ant-font-size)}.inspector-body p{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);line-height:1.7}.inspector-body dl{display:grid;grid-template-columns:85px 1fr;border-top:1px solid var(--ant-color-border);margin:16px 0}.inspector-body dt,.inspector-body dd{margin:0;padding:8px 0;border-bottom:1px solid var(--ant-color-border);font-size:var(--ant-font-size-sm)}.inspector-body dt{color:var(--ant-color-text-secondary)}.component{padding:8px;border:1px solid var(--ant-color-border);margin-top:8px}.component span{float:right}.code-body header{text-align:right}.code-body header button{border:0;background:transparent;color:var(--ant-color-primary)}.code-body pre{font-size:var(--ant-font-size-sm);line-height:1.55;background:var(--ant-color-text-base);color:var(--ant-color-primary-bg);padding:12px;min-height:410px;overflow:auto}.inspector-body textarea{width:100%;height:120px;border:1px solid var(--ant-color-border);padding:8px;resize:none}.suggestion{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-layout);border-radius:var(--ant-border-radius);padding:4px 8px;margin:0 4px 8px 0;font-size:var(--ant-font-size-sm)}.inspector-body>.button{width:100%;margin:12px 0}.sticky-actions{position:fixed;z-index:20;left:232px;right:0;bottom:0;height:54px;background:var(--ant-color-bg-container);border-top:1px solid var(--ant-color-border);display:flex;align-items:center;justify-content:space-between;padding:0 20px;box-shadow:none}.toast{position:fixed;z-index:100;right:24px;top:56px;background:var(--ant-color-text-base);color:var(--ant-color-bg-container);padding:12px 20px;box-shadow:none}.toast b{color:var(--ant-color-success);margin-right:8px}.modal-backdrop{position:fixed;z-index:90;inset:0;background:color-mix(in srgb,var(--ant-color-bg-mask) 47%,transparent);display:grid;place-items:center}.modal{width:610px;max-height:78vh;background:var(--ant-color-bg-container);box-shadow:0 10px 30px color-mix(in srgb,var(--ant-color-text-base) 27%,transparent);display:flex;flex-direction:column}.modal>header{height:47px;border-bottom:1px solid var(--ant-color-border);display:flex;align-items:center;justify-content:space-between;padding:0 16px}.modal h2{font-size:var(--ant-font-size)}.modal>header button{border:0;background:transparent;font-size:var(--ant-font-size-heading-3);color:var(--ant-color-text-secondary)}.modal-body{padding:16px;overflow:auto;flex:1 1 auto;min-height:0}.modal>footer{border-top:1px solid var(--ant-color-border);padding:12px 16px;text-align:right}.modal-note{background:var(--ant-color-bg-layout);border-left:3px solid var(--ant-color-primary);padding:12px;margin-bottom:16px;color:var(--ant-color-primary)}.impact-title{font-weight:600;margin-bottom:8px}.impact-list{list-style:none;padding:0;border:1px solid var(--ant-color-border)}.impact-list li{display:flex;justify-content:space-between;padding:12px;border-bottom:1px solid var(--ant-color-border)}.impact-list span{color:var(--ant-color-primary)}.download-list{display:flex;flex-direction:column}.download-list label{padding:12px;border-bottom:1px solid var(--ant-color-border);display:flex;gap:8px}.download-list>div{margin-top:16px;background:var(--ant-color-bg-layout);padding:12px;display:flex;justify-content:space-between}.history-list>div{display:flex;align-items:center;gap:12px;border-bottom:1px solid var(--ant-color-border);padding:12px}.history-list i{font-style:normal;width:34px;height:34px;border-radius:50%;background:var(--ant-color-bg-layout);color:var(--ant-color-primary);display:grid;place-items:center}.history-list span{display:flex;flex:1;flex-direction:column;gap:4px}.history-list small{color:var(--ant-color-text-secondary)}.history-list button{border:0;background:transparent;color:var(--ant-color-primary)}.login-page{min-height:100vh;background:linear-gradient(145deg,var(--ant-color-bg-layout),var(--ant-color-bg-container) 55%,var(--ant-color-bg-layout));border-top:4px solid var(--ant-color-primary-active);display:flex;align-items:center;justify-content:center}.login-top{position:absolute;left:18px;top:14px;display:flex;align-items:center;gap:12px}.login-top b{font-size:var(--ant-font-size)}.login-top span{border-left:1px solid var(--ant-color-border);padding-left:12px;color:var(--ant-color-text-secondary)}.login-card{width:420px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);box-shadow:none;padding:44px;text-align:center}.login-logo{font-size:var(--ant-font-size-heading-2)}.login-card h1{font-size:var(--ant-font-size-heading-3)}.login-card p{color:var(--ant-color-text-secondary);line-height:1.6}.sso-button{width:100%;height:48px;margin:24px 0 12px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);display:flex;align-items:center;gap:12px;padding:0 12px}.sso-button b{flex:1;text-align:left}.sso-button i{font-style:normal;font-size:var(--ant-font-size);color:var(--ant-color-primary)}.login-card>small{color:var(--ant-color-text-secondary)}.login-page>footer{position:absolute;bottom:18px;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)} +.avatar-button{border:0;padding:0} +.design-link{margin-left:auto;color:var(--ant-color-primary);font-size:var(--ant-font-size-sm);text-decoration:none;padding:0 12px;border-right:1px solid var(--ant-color-border)} +.design-link:hover{text-decoration:underline}.avatar-button:hover{outline:1px solid var(--ant-color-primary)} +.steps{grid-template-columns:repeat(5,1fr)} +.domain-steps{grid-template-columns:repeat(7,1fr)} +.module-switch{padding:12px 8px 8px;border-bottom:1px solid var(--ant-color-border);display:grid;gap:8px}.module-switch>button{height:47px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);display:flex;align-items:center;text-align:left;padding:0 8px;gap:8px;font-size:var(--ant-font-size)}.module-switch>button>b{width:23px;height:23px;display:grid;place-items:center;background:var(--ant-color-bg-layout);color:var(--ant-color-text-secondary)}.module-switch>button>span{display:flex;flex-direction:column;font-weight:600;gap:4px}.module-switch>button small{font-weight:400;font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.module-switch>button.active{border-color:transparent;background:var(--ant-color-primary-bg);color:var(--ant-color-primary)}.module-switch>button:hover{background:var(--ant-color-fill-quaternary)}.module-switch>button.active>b{background:var(--ant-color-primary);color:var(--ant-color-bg-container)}.side-nav>.side-title{display:none} +.domain-hero{min-height:160px;background:linear-gradient(120deg,var(--ant-color-primary),var(--ant-color-primary) 58%,var(--ant-color-primary));color:var(--ant-color-bg-container);margin-bottom:16px;padding:28px 32px;display:flex;align-items:center;justify-content:space-between;position:relative;overflow:hidden}.domain-hero:after{content:"◆";position:absolute;right:34%;top:-55px;font-size:var(--ant-font-size-heading-2);color:color-mix(in srgb,var(--ant-color-text-light-solid) 4%,transparent);transform:rotate(16deg)}.domain-hero>div:first-child{max-width:640px;z-index:1}.domain-hero .eyebrow{font-size:var(--ant-font-size-sm);letter-spacing:2px;opacity:.8}.domain-hero h2{font-size:var(--ant-font-size-heading-3);margin:8px 0}.domain-hero p{margin:0;line-height:1.7;opacity:.86}.domain-hero-stats{display:grid;grid-template-columns:1fr 1fr;gap:4px;background:color-mix(in srgb,var(--ant-color-bg-container) 22%,transparent);z-index:1}.domain-hero-stats div{width:105px;height:58px;background:color-mix(in srgb,var(--ant-color-bg-container) 8%,transparent);display:flex;flex-direction:column;align-items:center;justify-content:center}.domain-hero-stats b{font-size:var(--ant-font-size-heading-4)}.domain-hero-stats span{font-size:var(--ant-font-size-sm);opacity:.8}.domain-filter label{width:300px}.domain-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;padding:16px 0 4px}.domain-grid article{border:1px solid var(--ant-color-border);border-top:3px solid var(--ant-color-border);padding:16px;min-height:230px;background:var(--ant-color-bg-container)}.domain-grid article.water{border-top-color:var(--ant-color-primary)}.domain-grid article.gas{border-top-color:var(--ant-color-error)}.domain-grid article.energy{border-top-color:var(--ant-color-error-bg)}.domain-grid article.dc{border-top-color:var(--ant-color-primary)}.domain-grid article>header{display:flex;justify-content:space-between;align-items:center}.domain-grid article>header>span{font-size:var(--ant-font-size-heading-2);color:var(--ant-color-primary)}.domain-grid article>header>div{display:flex;align-items:center;gap:8px}.domain-grid h3{font-size:var(--ant-font-size);margin:12px 0 8px}.domain-grid p{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);line-height:1.65;min-height:34px}.domain-metrics{display:grid;grid-template-columns:1fr 1fr;border-top:1px solid var(--ant-color-border);border-bottom:1px solid var(--ant-color-border);padding:8px 0;gap:8px}.domain-metrics span{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.domain-metrics b{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-base);margin-right:4px}.domain-grid footer{display:flex;justify-content:space-between;margin-top:12px}.domain-grid footer button{border:0;background:transparent;color:var(--ant-color-primary);font-size:var(--ant-font-size-sm)}.domain-grid footer button:last-child{border:1px solid var(--ant-color-primary-bg);padding:4px 8px}.solution-parts{display:grid;grid-template-columns:repeat(5,1fr);gap:12px}.solution-parts>div{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-layout);padding:12px;display:flex;gap:8px;min-height:80px}.solution-parts i{font-style:normal;font-size:var(--ant-font-size-heading-4);color:var(--ant-color-primary)}.solution-parts span{display:flex;flex-direction:column;gap:8px}.solution-parts small{font-size:var(--ant-font-size-sm);line-height:1.5;color:var(--ant-color-text-secondary)} +.solution-banner{min-height:126px;border:1px solid var(--ant-color-border);background:linear-gradient(100deg,var(--ant-color-bg-layout),var(--ant-color-bg-container));display:flex;align-items:center;padding:20px;margin-bottom:12px}.solution-logo{width:72px;height:72px;background:var(--ant-color-primary);color:var(--ant-color-bg-container);border-radius:var(--ant-border-radius);display:grid;place-items:center;font-size:var(--ant-font-size-heading-2);margin-right:20px}.solution-banner>div:nth-child(2){flex:1}.solution-banner h2{margin:4px 0;font-size:var(--ant-font-size-heading-4)}.solution-banner p{margin:0 0 8px;color:var(--ant-color-text-secondary)}.solution-banner small{margin-left:12px;color:var(--ant-color-text-secondary)}.solution-banner aside{display:flex}.solution-summary{display:grid;grid-template-columns:repeat(6,1fr);background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);margin-bottom:12px}.solution-summary>div{height:65px;border-right:1px solid var(--ant-color-border);display:flex;flex-direction:column;align-items:center;justify-content:center}.solution-summary b{font-size:var(--ant-font-size-heading-4)}.solution-summary span{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);margin-top:4px}.detail-grid{display:grid;grid-template-columns:1fr 310px;gap:12px}.asset-template{display:grid;grid-template-columns:1fr 1.3fr;gap:16px}.asset-tree{background:var(--ant-color-bg-layout);padding:12px;display:flex;flex-direction:column;gap:12px}.asset-tree span{padding-left:16px}.asset-tree em{font-style:normal;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.template-specs{display:grid;gap:8px}.template-specs>div{border:1px solid var(--ant-color-border);padding:8px}.template-specs p{margin:4px 0 0;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);line-height:1.45}.domain-page-list{display:grid;grid-template-columns:1fr 1fr;gap:12px}.domain-page-list article{display:grid;grid-template-columns:115px 1fr;border:1px solid var(--ant-color-border);min-height:145px}.domain-page-thumb{margin:8px;background:var(--ant-color-bg-layout);position:relative;padding:28px 8px 8px;display:grid;grid-template-columns:repeat(3,1fr);gap:4px}.domain-page-thumb span{position:absolute;left:7px;top:6px;color:var(--ant-color-primary)}.domain-page-thumb i{background:var(--ant-color-primary);height:40px}.domain-page-thumb i:nth-child(2){height:62px}.domain-page-thumb i:nth-child(3){height:50px}.domain-page-list section{padding:12px 8px 8px 0}.domain-page-list section>div{display:flex;justify-content:space-between}.domain-page-list h3{font-size:var(--ant-font-size-sm);margin:8px 0 4px}.domain-page-list section>b{font-size:var(--ant-font-size-sm);color:var(--ant-color-primary)}.domain-page-list p{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);line-height:1.5}.domain-page-list footer button{border:0;background:transparent;color:var(--ant-color-primary);padding:0;margin-right:12px;font-size:var(--ant-font-size-sm)}.flow-list{display:grid;gap:8px}.flow-list>div{display:flex;align-items:center;border:1px solid var(--ant-color-border);padding:8px}.flow-list i{font-style:normal;width:29px;height:29px;background:var(--ant-color-bg-layout);color:var(--ant-color-primary);display:grid;place-items:center;margin-right:8px}.flow-list span{display:flex;flex:1;flex-direction:column;gap:4px}.flow-list small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.flow-list em{font-style:normal;font-size:var(--ant-font-size-sm);color:var(--ant-color-primary)}.flow-list .future-item{border-style:dashed;opacity:.75}.solution-menu{display:flex;flex-direction:column}.solution-menu>b{padding:8px;background:var(--ant-color-bg-layout);margin-top:4px}.solution-menu>span{padding:8px 8px 8px 16px;border-bottom:1px solid var(--ant-color-border)}.solution-menu i{font-style:normal;font-size:var(--ant-font-size-sm);color:var(--ant-color-primary);margin-right:8px}.knowledge-list>div{display:flex;align-items:center;border-bottom:1px solid var(--ant-color-border);padding:8px 4px}.knowledge-list>div>i{font-style:normal;width:27px;color:var(--ant-color-primary)}.knowledge-list span{display:flex;flex:1;flex-direction:column;gap:4px}.knowledge-list small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.knowledge-list button{border:0;background:transparent;color:var(--ant-color-primary)} +.ai-config-layout{display:grid;grid-template-columns:1fr 370px;gap:16px}.wordbuddy-card{background:var(--ant-color-text-base);color:var(--ant-color-fill-secondary);border-radius:var(--ant-border-radius);overflow:hidden;box-shadow:none}.wordbuddy-card>header{height:58px;border-bottom:1px solid var(--ant-color-border);display:flex;justify-content:space-between;align-items:center;padding:0 16px}.wordbuddy-card>header>div{display:flex;gap:8px;align-items:center}.wb-logo{width:31px;height:31px;border-radius:var(--ant-border-radius);background:linear-gradient(135deg,var(--ant-color-primary),var(--ant-color-primary));display:grid;place-items:center;font-weight:600}.wordbuddy-card header section{display:flex;flex-direction:column}.wordbuddy-card header small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);margin-top:4px}.wordbuddy-card header label{display:flex;align-items:center;gap:8px}.model-list{padding:8px}.model-list>button{width:100%;min-height:56px;border:0;border-radius:var(--ant-border-radius);background:transparent;color:var(--ant-color-fill-secondary);display:flex;align-items:center;padding:8px 8px;text-align:left;position:relative}.model-list>button:hover,.model-list>button.selected{background:var(--ant-color-text-base)}.model-list>button>i{font-style:normal;width:25px;color:var(--ant-color-text-disabled);font-weight:600}.model-list>button>span{display:flex;flex:1;flex-direction:column;gap:4px}.model-list>button>span>b{font-size:var(--ant-font-size-sm)}.model-list>button small{font-size:var(--ant-font-size-sm);color:var(--ant-color-primary)}.model-list>button em{font-style:normal;font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.model-list>button>strong{color:var(--ant-color-text-disabled);font-size:var(--ant-font-size-sm);margin-right:24px}.model-list>button>u{position:absolute;right:9px;color:var(--ant-color-success);text-decoration:none;font-size:var(--ant-font-size)}.wordbuddy-card>footer{border-top:1px solid var(--ant-color-border);padding:8px}.wordbuddy-card>footer button{border:0;background:transparent;color:var(--ant-color-text-disabled)}.selected-model{display:flex;align-items:center;gap:12px;background:var(--ant-color-bg-layout);border:1px solid var(--ant-color-primary);padding:12px}.selected-model>span{width:42px;height:42px;border-radius:50%;background:linear-gradient(135deg,var(--ant-color-primary),var(--ant-color-primary));color:var(--ant-color-bg-container);display:grid;place-items:center}.selected-model section{flex:1}.selected-model h3{margin:4px 0;font-size:var(--ant-font-size)}.selected-model p{margin:0;font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.model-facts{display:grid;grid-template-columns:110px 1fr;margin:12px 0 0}.model-facts dt,.model-facts dd{margin:0;padding:8px;border-bottom:1px solid var(--ant-color-border);font-size:var(--ant-font-size-sm)}.model-facts dt{color:var(--ant-color-text-secondary)}.strategy-list{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:12px}.strategy-list label{border:1px solid var(--ant-color-border);padding:8px;display:flex;gap:8px}.strategy-list label>span{display:flex;flex-direction:column;gap:4px}.strategy-list small,.setting-row small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.setting-row{display:flex;align-items:center;border-top:1px solid var(--ant-color-border);padding:8px 4px}.setting-row>span{display:flex;flex:1;flex-direction:column;gap:4px}.context-list{display:grid;gap:8px}.context-list>span{display:flex;align-items:center;background:var(--ant-color-bg-layout);padding:8px}.context-list i{font-style:normal;width:25px;color:var(--ant-color-primary)}.context-list b{flex:1;font-size:var(--ant-font-size-sm)}.context-list em{font-style:normal;color:var(--ant-color-success);font-size:var(--ant-font-size-sm)}.token-estimate{display:flex;flex-direction:column;border-top:1px solid var(--ant-color-border);margin-top:12px;padding-top:12px;gap:4px}.token-estimate span{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)} +@media(max-width:1100px){.app-shell{padding-left:44px}.side-nav{display:none}.workspace{min-width:900px}.sticky-actions{left:42px}.top-actions small{display:none}.result-layout{grid-template-columns:1fr}.preview-main{grid-template-columns:1fr 260px}.mu-grid{grid-template-columns:repeat(2,1fr)}} + +/* 右下角浮动 AI 会话 */ +.ai-fab{position:fixed;right:22px;bottom:22px;z-index:80;width:54px;height:54px;border-radius:50%;border:0;background:transparent;box-shadow:0 8px 22px color-mix(in srgb,var(--ant-color-primary) 33%,transparent);display:grid;place-items:center;cursor:pointer;touch-action:none;user-select:none}.ai-fab-icon{width:54px;height:54px;border-radius:50%;object-fit:cover;-webkit-user-drag:none;user-drag:none;user-select:none;pointer-events:none} +.design-doc-link{display:block;margin-top:auto;margin-left:12px;margin-right:12px;margin-bottom:12px;padding:4px 8px;font-size:var(--ant-font-size-sm);line-height:1.4;font-weight:600;text-align:center;color:var(--ant-color-text-light-solid);text-decoration:none;border-radius:var(--ant-border-radius);background:linear-gradient(135deg,var(--ant-color-primary) 0%,var(--ant-color-primary-bg) 100%);box-shadow:none;opacity:.95;transition:opacity .15s} +.design-doc-link:hover{opacity:1;color:var(--ant-color-text-light-solid)} +.ai-fab:active{cursor:grabbing} +.ai-fab:hover:not(:active){transform:translateY(-1px);box-shadow:0 12px 26px color-mix(in srgb,var(--ant-color-primary-hover) 40%,transparent)} +.ai-dialog{position:fixed;right:22px;bottom:88px;z-index:81;width:25vw;min-width:320px;height:70vh;min-height:420px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);box-shadow:0 18px 48px color-mix(in srgb,var(--ant-color-text-base) 20%,transparent);display:flex;flex-direction:column;overflow:hidden} +.ai-dialog header{display:flex;align-items:center;gap:8px;padding:12px 12px;border-bottom:1px solid var(--ant-color-border);background:linear-gradient(135deg,var(--ant-color-primary),var(--ant-color-primary));color:var(--ant-color-text-light-solid)} +.ai-dialog .ai-dialog-logo{width:28px;height:28px;border-radius:var(--ant-border-radius);background:color-mix(in srgb,var(--ant-color-bg-container) 20%,transparent);display:grid;place-items:center;font-size:var(--ant-font-size)} +.ai-dialog .ai-dialog-title{flex:1;display:flex;flex-direction:column;line-height:1.25} +.ai-dialog .ai-dialog-title b{font-size:var(--ant-font-size-sm)} +.ai-dialog .ai-dialog-title small{font-size:var(--ant-font-size-sm);opacity:.85} +.ai-dialog .ai-close{border:0;background:transparent;color:var(--ant-color-text-light-solid);font-size:var(--ant-font-size-heading-4);line-height:1;width:28px;height:28px;border-radius:var(--ant-border-radius)} +.ai-dialog .ai-close:hover{background:color-mix(in srgb,var(--ant-color-bg-container) 20%,transparent)} +.ai-messages{flex:1;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:12px;background:var(--ant-color-bg-layout)} +.ai-welcome{width:100%;margin:auto 0;display:flex;flex-direction:column;gap:12px;color:var(--ant-color-text-base)}.ai-welcome-intro{display:flex;align-items:center;gap:12px;padding-bottom:4px}.ai-welcome-intro>span{width:32px;height:32px;border-radius:var(--ant-border-radius);background:var(--ant-color-bg-layout);color:var(--ant-color-primary);display:grid;place-items:center;flex:0 0 auto}.ai-welcome-intro>div{min-width:0}.ai-welcome-intro b{display:block;font-size:var(--ant-font-size);line-height:1.4}.ai-welcome-intro p{margin:4px 0 0;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);line-height:1.5}.ai-capability-list{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container)}.ai-capability-list>div{min-height:52px;padding:8px 12px;display:flex;align-items:center;gap:12px;border-bottom:1px solid var(--ant-color-border)}.ai-capability-list>div:last-child{border-bottom:0}.ai-capability-list i{width:22px;height:22px;border-radius:50%;background:var(--ant-color-bg-layout);color:var(--ant-color-primary);display:grid;place-items:center;flex:0 0 auto;font-size:var(--ant-font-size-sm);font-style:normal;font-weight:600}.ai-capability-list span{display:flex;flex-direction:column;gap:4px;min-width:0}.ai-capability-list b{font-size:var(--ant-font-size-sm);line-height:1.35;font-weight:600}.ai-capability-list small{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);line-height:1.35}.ai-welcome-tip{padding:8px 12px;background:var(--ant-color-bg-layout);border-left:3px solid var(--ant-color-primary);color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);line-height:1.5}.ai-welcome-tip b{color:var(--ant-color-text-base)} +.ai-bubble{display:flex;gap:8px;align-items:flex-start;max-width:88%} +.ai-bubble .ai-avatar{width:26px;height:26px;border-radius:50%;flex:0 0 auto;display:grid;place-items:center;font-size:var(--ant-font-size-sm);background:var(--ant-color-fill-secondary);color:var(--ant-color-primary)} +.ai-bubble.me{flex-direction:row-reverse;align-self:flex-end} +.ai-bubble.me .ai-avatar{background:linear-gradient(135deg,var(--ant-color-primary),var(--ant-color-primary));color:var(--ant-color-text-light-solid)} +.ai-bubble .ai-text{white-space:pre-wrap;word-break:break-word;font-size:var(--ant-font-size-sm);line-height:1.6;padding:8px 12px;border-radius:var(--ant-border-radius);background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border)} +.ai-bubble.me .ai-text{background:var(--ant-color-primary);color:var(--ant-color-text-light-solid);border-color:var(--ant-color-primary)} +.ai-dialog footer{display:flex;gap:8px;padding:8px;border-top:1px solid var(--ant-color-border);background:var(--ant-color-bg-container)} +.ai-dialog .ai-input{flex:1;resize:none;height:42px;max-height:120px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:8px 12px;font-size:var(--ant-font-size-sm);line-height:1.4;outline:none} +.ai-dialog .ai-input:focus{border-color:var(--ant-color-primary-bg)} +.ai-dialog .ai-send{border:0;background:var(--ant-color-primary);color:var(--ant-color-text-light-solid);border-radius:var(--ant-border-radius);padding:0 16px;font-size:var(--ant-font-size-sm);align-self:flex-end;height:42px} +.ai-dialog .ai-send:disabled{opacity:.5;cursor:not-allowed} +.ai-dialog .ai-send:not(:disabled):hover{background:var(--ant-color-primary-hover)} + +/* ===== 新建站点向导:基本属性 ===== */ +.domain-select{display:flex;align-items:center;gap:8px} +.domain-select input{flex:1;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);height:30px;padding:0 8px;background:var(--ant-color-bg-container)} +.domain-select input:focus{border-color:var(--ant-color-primary);outline:none} +.domain-add{display:flex;align-items:center;gap:8px;margin-top:8px} +.domain-add input{flex:1;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);height:30px;padding:0 8px;background:var(--ant-color-bg-container)} +.domain-add input:focus{border-color:var(--ant-color-primary);outline:none} +.file-list{list-style:none;margin:12px 0 0;padding:0;display:flex;flex-direction:column;gap:8px} +.file-list li{display:flex;align-items:center;gap:8px;background:var(--ant-color-bg-layout);border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:8px 8px;font-size:var(--ant-font-size-sm)} +.file-list a{color:var(--ant-color-primary);text-decoration:none} +.file-list a:hover{text-decoration:underline} +.file-list small{color:var(--ant-color-text-secondary);margin-left:auto} +.invalid{border-color:var(--ant-color-error)!important;background:var(--ant-color-bg-layout)!important} +.hint{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);margin:0 0 12px;line-height:1.6} + +/* ===== 可编辑表格内的输入控件 ===== */ +.data-table input,.data-table select,.data-table textarea{border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);height:28px;padding:0 8px;width:100%;background:var(--ant-color-bg-container);font-size:var(--ant-font-size-sm)} +.data-table input:focus,.data-table select:focus,.data-table textarea:focus{border-color:var(--ant-color-primary);outline:none} +.data-table .number{width:100%;text-align:right} +.data-table input::placeholder{color:var(--ant-color-text-disabled)} +/* 站点列表:列宽可手动拖动调整(拖拽表头右缘的分隔条) */ +.data-table.resizable-cols{table-layout:fixed;width:100%} +.data-table.resizable-cols th{position:relative} +.data-table .col-resizer{position:absolute;top:0;right:0;width:6px;height:100%;cursor:col-resize;z-index:2;user-select:none} +.data-table .col-resizer::after{content:"";position:absolute;top:0;right:2px;width:2px;height:100%;background:transparent} +.data-table .col-resizer:hover::after,.data-table .col-resizer.active::after{background:var(--ant-color-primary)} +/* 可编辑表格使用固定列宽,避免输入框在自动布局下被压窄(设备类型框变窄的 BUG) */ +.data-table.editable{table-layout:fixed} +.data-table.editable th:nth-child(1){width:40%} +.data-table.editable th:nth-child(2){width:92px} +.data-table.editable th:nth-child(3){width:56px} +.data-table.editable th:nth-child(4){width:auto} +.data-table.editable th:nth-child(5){width:48px} +.data-table.editable input,.data-table.editable select,.data-table.editable textarea{min-width:0;width:100%} +.data-table.editable .trash{border:0;background:transparent;color:var(--ant-color-error);font-size:var(--ant-font-size);cursor:pointer;line-height:1} +.data-table.editable .trash:hover{color:var(--ant-color-error)} +.data-table.editable .asset-eye-btn{border:0;background:transparent;color:var(--ant-color-primary);font-size:var(--ant-font-size);cursor:pointer;line-height:1;padding:0;display:inline-flex;align-items:center} +.data-table.editable .asset-eye-btn.disabled{color:var(--ant-color-text-disabled);cursor:default} + +/* ===== 领域方案库:列表筛选栏 + 可排序列头 ===== */ +.filter-bar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:12px} +.filter-bar .filter-search{flex:1 1 220px;min-width:180px;height:30px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:0 12px;font-size:var(--ant-font-size-sm);background:var(--ant-color-bg-container)} +.filter-bar .filter-search:focus{border-color:var(--ant-color-primary);outline:none} +.filter-bar select{height:30px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:0 8px;font-size:var(--ant-font-size-sm);background:var(--ant-color-bg-container);color:var(--ant-color-text-secondary)} +.filter-bar select:focus{border-color:var(--ant-color-primary);outline:none} +.filter-bar .filter-count{margin-left:auto;font-size:var(--ant-font-size-sm)} +.data-table th.sortable{cursor:pointer;user-select:none;white-space:nowrap} +.data-table th.sortable:hover{color:var(--ant-color-primary)} +.data-table th.sortable .sort-ind{color:var(--ant-color-primary);font-size:var(--ant-font-size-sm)} + +/* ===== Assets 资产配置 ===== */ +.empty-row td{background:var(--ant-color-bg-layout)} +.empty-row input{color:var(--ant-color-text-disabled);background:var(--ant-color-bg-layout)} +.empty-row input::placeholder{color:var(--ant-color-text-disabled)} +.asset-tree-preview{background:var(--ant-color-bg-layout);border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:12px 16px;font-size:var(--ant-font-size-sm)} +.tree-root{font-weight:600;color:var(--ant-color-text-secondary);margin-bottom:8px;display:flex;align-items:center;gap:4px} +.tree-branch{margin:4px 0 4px 16px;padding-left:12px;border-left:1px dashed var(--ant-color-border)} +.tree-node{display:flex;align-items:center;gap:8px;font-weight:600;color:var(--ant-color-text-secondary)} +.site-structure-title{margin-top:20px} +.site-structure{grid-column:2;margin-top:8px} +.site-structure .tree-branch{margin:4px 0 4px 0;padding-left:12px;border-left:1px solid var(--ant-color-border)} +.site-structure .tree-node{font-weight:400;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size)} +.site-structure .tree-node.current-site{color:var(--ant-color-primary);background:var(--ant-color-primary-bg);border-radius:var(--ant-border-radius);padding:4px 4px;margin-left:-4px} +.tree-count{background:var(--ant-color-primary-bg);color:var(--ant-color-primary-active);border-radius:var(--ant-border-radius);padding:0 8px;font-size:var(--ant-font-size-sm);font-weight:400} +.tree-leaves{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);line-height:1.7;margin:4px 0 0 20px;word-break:break-all} + +/* ===== Functions 功能与菜单 ===== */ +.mu-tree{display:flex;flex-direction:column;gap:16px} +.mu-group>b{display:block;color:var(--ant-color-primary-active);font-size:var(--ant-font-size-sm);margin-bottom:8px} +.mu-items{display:flex;flex-direction:column;gap:8px;padding:8px 0 4px 20px;border-left:1px dashed var(--ant-color-border);margin-left:8px} +.mu-items label{display:flex;align-items:flex-start;gap:8px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:8px 8px;background:var(--ant-color-bg-container);cursor:pointer;font-size:var(--ant-font-size-sm)} +.mu-items label:hover{border-color:var(--ant-color-primary-bg);background:var(--ant-color-bg-layout)} +.mu-items label.disabled{opacity:.5;cursor:not-allowed;background:var(--ant-color-bg-layout)} +.mu-items label input{margin-top:4px;accent-color:var(--ant-color-primary)} +.mu-items label span{display:flex;flex-direction:column;line-height:1.3} +.mu-items label small{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)} +.two-column>div:first-child{min-width:0} +.cube-editor{overflow-x:auto} +.cube-editor table{width:100%} +.cube-editor input{width:100%} +.cube-editor .cube-editor-table th:nth-child(1){width:120px} +.cube-editor .cube-editor-table th:nth-child(2){width:auto} +.cube-editor .cube-editor-table th:nth-child(3){width:140px} +.cube-editor .cube-editor-table th:nth-child(4){width:200px} +.cube-editor .cube-editor-table td:nth-child(3){white-space:nowrap;overflow:hidden;text-overflow:ellipsis} +.cube-actions{display:flex;gap:4px;white-space:nowrap} +.cube-actions button{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);border-radius:var(--ant-border-radius);height:26px;padding:0 8px;font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)} +.cube-actions button:hover{border-color:var(--ant-color-primary);color:var(--ant-color-primary)} +.cube-actions .trash{border-color:var(--ant-color-error-bg);color:var(--ant-color-error)} +.cube-actions .trash:hover{background:var(--ant-color-bg-layout);border-color:var(--ant-color-error)} +/* 醒目 AI 操作按钮(渐变蓝紫) */ +.btn-ai{display:inline-flex;align-items:center;gap:4px;background:linear-gradient(135deg,var(--ant-color-primary),var(--ant-color-primary));color:var(--ant-color-text-light-solid);border:1px solid transparent;border-radius:var(--ant-border-radius);height:26px;padding:0 12px;font-size:var(--ant-font-size-sm);font-weight:600;cursor:pointer;box-shadow:none;white-space:nowrap} +.btn-ai:hover{filter:brightness(1.08)} +.btn-ai:active{transform:translateY(1px)} +.btn-ai:disabled{opacity:.65;cursor:default;box-shadow:none} +.cube-actions .btn-ai{height:26px} +.menu-editor{display:flex;flex-direction:column;gap:12px} +.menu-row{display:grid;grid-template-columns:1.4fr 1fr 1.4fr auto;gap:8px;align-items:center} +.menu-row input,.menu-row select{border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);height:30px;padding:0 8px;background:var(--ant-color-bg-container);width:100%} +.menu-row .trash{border:1px solid var(--ant-color-error-bg);background:var(--ant-color-bg-container);color:var(--ant-color-error);border-radius:var(--ant-border-radius);height:30px;width:34px;font-size:var(--ant-font-size)} +.menu-row .trash:hover{background:var(--ant-color-bg-layout);border-color:var(--ant-color-error)} +.menu-preview .menu-tree{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container)} +.menu-preview .menu-root{padding:12px 12px;font-weight:600;border-bottom:1px solid var(--ant-color-border);background:var(--ant-color-bg-layout)} +.menu-preview .menu-section{padding:12px 12px;border-bottom:1px solid var(--ant-color-border)} +.menu-preview .menu-section:last-child{border-bottom:0} +.menu-preview .menu-section-title{font-size:var(--ant-font-size-sm);color:var(--ant-color-primary-active);font-weight:600;margin-bottom:8px} +.menu-preview .menu-leaf{padding:4px 0 4px 16px;font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);border-left:2px solid var(--ant-color-border);margin:4px 0 4px 4px} +.menu-preview .menu-leaf.cube{border-left-color:var(--ant-color-primary)} +.menu-preview .menu-leaf.muted{color:var(--ant-color-text-disabled);border-left-color:var(--ant-color-border)} + +/* ===== Generate 预览 line 面板 ===== */ +.line-panel{background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:12px 12px;display:flex;flex-direction:column;gap:8px} +.line-panel h3{margin:0;font-size:var(--ant-font-size-sm);display:flex;align-items:center;justify-content:space-between} +.line-panel h3 span{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);font-weight:400} + +/* ===== 生成提示词查看 ===== */ +.prompt-list{display:flex;flex-direction:column;gap:8px} +.prompt-row{display:flex;align-items:center;justify-content:space-between;gap:12px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:8px 12px;background:var(--ant-color-bg-container)} +.prompt-row span{display:flex;flex-direction:column;line-height:1.35;min-width:0} +.prompt-row span small{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);margin-top:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:420px} +.prompt-row b{font-size:var(--ant-font-size-sm)} +.prompt-view{margin:0;background:#0f1115;color:#e6edf3;border:1px solid #2a2f36;border-radius:6px;padding:14px;font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace;font-size:11.5px;line-height:1.6;white-space:pre-wrap;word-break:break-word;max-height:60vh;overflow:auto} + +/* ===== 站点列表:多选与删除 ===== */ +.data-table input[type=checkbox]{display:block;width:16px;height:16px;padding:0;margin:0 auto;appearance:none;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);box-shadow:none;background:var(--ant-color-bg-container);cursor:pointer;vertical-align:middle} +.data-table input[type=checkbox]:checked{border-color:var(--ant-color-primary);background-color:var(--ant-color-primary);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.2 6.6 11 12.5 4.8' fill='none' stroke='var(--ant-color-bg-container)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-position:center;background-repeat:no-repeat;background-size:14px 14px} +.data-table input[type=checkbox]:focus-visible{outline:2px solid var(--ant-color-primary-bg);outline-offset:1px} +.data-table thead th:first-child{width:34px;text-align:center} +.link.danger{color:var(--ant-color-error)} +.link.danger:hover{text-decoration:underline} +.project-grid article{position:relative} +.card-del{position:absolute;top:8px;right:8px;border:1px solid var(--ant-color-error-bg);background:var(--ant-color-bg-container);color:var(--ant-color-error);border-radius:var(--ant-border-radius);height:26px;padding:0 8px;font-size:var(--ant-font-size-sm);cursor:pointer} +.card-del:hover{background:var(--ant-color-bg-layout);border-color:var(--ant-color-error)} +.style-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;padding:16px 0 4px} +.style-card{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);display:flex;flex-direction:column} +.style-card .style-thumb{position:relative;aspect-ratio:16/9;min-height:200px;background:var(--ant-color-bg-layout);display:grid;place-items:center;cursor:zoom-in;overflow:hidden} +.style-card .style-thumb img{width:100%;height:100%;object-fit:contain} +.style-card .style-thumb .zoom{position:absolute;right:8px;bottom:8px;background:color-mix(in srgb,var(--ant-color-bg-mask) 53%,transparent);color:var(--ant-color-text-light-solid);width:24px;height:24px;border-radius:var(--ant-border-radius);display:grid;place-items:center;font-size:var(--ant-font-size-sm)} +.style-info{padding:12px 12px 4px} +.style-info h3{font-size:var(--ant-font-size);margin:0} +.style-info small{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)} +.style-card footer{display:flex;justify-content:flex-end;gap:16px;padding:8px 12px} +.style-lightbox{max-width:92vw;max-height:88vh} +.style-upload-row{display:flex;gap:12px;align-items:stretch} +.style-upload-prev{width:150px;height:120px;border:1px solid var(--ant-color-border);display:grid;place-items:center;background:var(--ant-color-bg-layout);overflow:hidden} +.style-upload-prev img{width:100%;height:100%;object-fit:contain} +.style-json-row{display:flex;gap:12px;align-items:flex-start} +.style-json-row textarea{flex:1;min-height:150px;resize:vertical;font-family:var(--ant-font-family);font-size:var(--ant-font-size-sm);line-height:1.5} +.style-json-row .upload{width:120px;height:64px;flex:0 0 auto;margin-top:4px} +.modal>footer .spacer{flex:1} +.style-picker{margin-top:20px;border-top:1px dashed var(--ant-color-border);padding-top:16px} +.style-picker h4{margin:0 0 4px;font-size:var(--ant-font-size)} +.style-picker h4 small{color:var(--ant-color-text-secondary);font-weight:400;font-size:var(--ant-font-size-sm);margin-left:8px} +.style-pick-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:12px;margin-top:8px} +.style-pick{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);padding:8px;display:flex;flex-direction:column;gap:8px;cursor:pointer;text-align:center;color:var(--ant-color-text-secondary)} +.style-pick:hover{border-color:var(--ant-color-primary)} +.style-pick.active{border:2px solid var(--ant-color-primary);background:var(--ant-color-bg-layout);color:var(--ant-color-primary)} +.style-pick-thumb{height:78px;background:var(--ant-color-bg-layout);display:grid;place-items:center;overflow:hidden} +.style-pick-thumb img{width:100%;height:100%;object-fit:contain} +.style-pick-thumb.none{color:var(--ant-color-text-disabled);font-size:var(--ant-font-size-sm)} +.style-pick span{font-size:var(--ant-font-size-sm);line-height:1.3} + +/* ========================================================================== */ +/* Company workspace standard — measured from the WISE-IoT service desk UI. */ +/* This final layer intentionally normalizes legacy prototype styles while the */ +/* remaining feature pages are migrated to shared company components. */ +/* ========================================================================== */ +:root{ + + + + + + +} +html,body{font-family:var(--ant-font-family);font-size:var(--ant-font-size);line-height:1.5;color:var(--ant-color-text-base);background:var(--ant-color-bg-container)} +.app-shell{min-height:100vh;padding-top:56px;padding-left:200px;background:var(--ant-color-bg-container)} +.topbar{height:56px;border-top:4px solid var(--ant-color-primary);border-bottom:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);background-image:none;box-shadow:none;padding:0 20px;gap:12px} +.topbar>strong{font-size:var(--ant-font-size-heading-3);color:var(--ant-color-primary);letter-spacing:-.3px}.topbar .brand-mark{font-size:var(--ant-font-size-heading-4);color:var(--ant-color-primary)} +.top-actions{gap:16px}.top-actions a{color:var(--ant-color-primary);text-decoration:none}.top-actions small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)} +.hamburger{font-size:var(--ant-font-size);color:var(--ant-color-text-secondary)}.divider{height:22px} +.side-nav{top:56px;width:200px;background:var(--ant-color-bg-layout);border-right:1px solid var(--ant-color-border)} +.module-switch{padding:0;border-bottom:1px solid var(--ant-color-border);display:flex;flex-direction:column;gap:0} +.module-switch>button{height:50px;border:0;border-radius:0;background:transparent;padding:0 20px;gap:12px;font-size:var(--ant-font-size);font-weight:600} +.module-switch>button>b{width:18px;height:auto;background:transparent;color:var(--ant-color-text-secondary)} +.module-switch>button>span{display:block;font-weight:600}.module-switch>button small{display:none} +.module-switch>button:hover{background:var(--ant-color-bg-layout)}.module-switch>button.active{background:var(--ant-color-primary-bg);color:var(--ant-color-primary)} +.module-switch>button.active>b{background:transparent;color:var(--ant-color-primary)} +.side-nav>small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);padding:20px 20px 8px;letter-spacing:0;text-transform:none} +.side-nav>button{height:44px;padding:0 20px;border-left:0;font-size:var(--ant-font-size);gap:12px} +.side-nav>button.active{background:var(--ant-color-primary-bg);color:var(--ant-color-primary);border-left:0;font-weight:600} +.side-nav>button em{width:20px;height:20px;font-size:var(--ant-font-size-sm)} +.site-switcher{height:32px;width:calc(100% - 32px);margin:8px 16px;border-color:var(--ant-color-border);border-radius:var(--ant-border-radius);font-size:var(--ant-font-size-sm)} +.side-help{margin:auto 16px 16px;border:0;border-top:1px solid var(--ant-color-border);background:transparent;padding:16px 4px 0} +.workspace{min-height:calc(100vh - 56px);padding-bottom:72px;background:var(--ant-color-bg-container)}.crumb{display:none} +.page-heading{min-height:64px;padding:12px 24px;background:var(--ant-color-bg-layout);border-bottom:1px solid var(--ant-color-border)} +.page-heading h1{font-size:var(--ant-font-size-heading-3);line-height:36px;font-weight:600;margin:0;color:var(--ant-color-text-base)} +.page-heading p{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);margin:0}.page-heading>div:last-child{display:flex;gap:8px} +.content{padding:0 24px 24px;background:var(--ant-color-bg-container)} +.button.ant-btn{min-width:112px;height:32px;margin:0;border-radius:var(--ant-border-radius);padding:0 24px;font-size:var(--ant-font-size);font-weight:600;box-shadow:none} +.button.ant-btn-primary{background:var(--ant-color-primary);border-color:var(--ant-color-primary)}.button.ant-btn-primary:hover{background:var(--ant-color-primary-hover)!important;border-color:var(--ant-color-primary-hover)!important} +.button.ant-btn-default,.button.secondary{background:var(--ant-color-bg-container);color:var(--ant-color-text-secondary);border-color:var(--ant-color-border)}.button.ant-btn-default:hover,.button.secondary:hover{color:var(--ant-color-primary)!important;border-color:var(--ant-color-primary)!important;background:var(--ant-color-bg-container)!important} +.steps{height:64px;border-top:0;border-bottom:1px solid var(--ant-color-border);padding:0 24px;background:var(--ant-color-bg-container)}.steps button{padding:0 20px;font-size:var(--ant-font-size)}.steps button>i{width:26px;height:26px}.steps button.active>i{background:var(--ant-color-primary);border-color:var(--ant-color-primary)} +.panel{border:1px solid var(--ant-color-border);border-radius:0;background:var(--ant-color-bg-container);margin:16px 0;box-shadow:none}.panel-head{min-height:48px;padding:0 16px;background:var(--ant-color-bg-container)}.panel-head>strong{font-size:var(--ant-font-size)}.panel-body{padding:16px} +.company-status-tabs{height:56px;display:flex;align-items:flex-end;border-bottom:1px solid var(--ant-color-border);gap:0;padding-top:8px} +.company-status-tabs > button{height:48px;min-width:120px;padding:0 24px;border:0;border-bottom:3px solid transparent;background:var(--ant-color-bg-container);color:var(--ant-color-text-secondary);font-size:var(--ant-font-size)} +.company-status-tabs > button span{margin-right:8px}.company-status-tabs > button b{display:inline-grid;place-items:center;min-width:24px;height:20px;padding:0 8px;border-radius:var(--ant-border-radius);background:var(--ant-color-bg-layout);color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)} +.company-status-tabs > button.active{color:var(--ant-color-primary);border-bottom-color:var(--ant-color-primary);font-weight:600}.company-status-tabs > button.active b{background:var(--ant-color-fill-secondary);color:var(--ant-color-success)} +.company-list-panel{margin-top:16px}.company-list-panel>.panel-body{padding:0 16px 12px} +.company-filterbar{height:auto;min-height:56px;padding:12px 0;gap:8px}.company-filterbar .search-field{width:240px;height:32px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:0 12px;background:var(--ant-color-bg-container)}.company-filterbar .search-field:focus-within{border-color:var(--ant-color-primary)} +.company-filterbar select{height:32px;min-width:160px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);background:var(--ant-color-bg-container);padding:0 28px 0 12px} +.filter-actions{margin-left:auto;display:flex;gap:8px}.filter-actions .button{min-width:96px} +.company-table{table-layout:fixed}.company-table th{height:44px;background:var(--ant-color-bg-layout);font-size:var(--ant-font-size);font-weight:600;padding:0 12px}.company-table td{height:50px;padding:8px 12px;font-size:var(--ant-font-size);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.company-table tbody tr{cursor:pointer}.company-table tbody tr:hover td{background:var(--ant-color-bg-layout)}.company-table th:first-child,.company-table td:first-child{width:44px;overflow:visible;text-overflow:clip}.company-table th:last-child,.company-table td:last-child{width:70px;text-align:center} +.company-record-link{font-size:var(--ant-font-size)}.company-record-link b{color:var(--ant-color-primary)} +.status.ant-tag{height:24px;line-height:21px;border-radius:var(--ant-border-radius);padding:0 12px;margin:0;font-size:var(--ant-font-size-sm)}.status.ok{color:var(--ant-color-success);background:var(--ant-color-success-bg);border-color:var(--ant-color-success)}.status.warn{color:var(--ant-color-warning);background:var(--ant-color-warning-bg);border-color:var(--ant-color-warning)}.status.bad{color:var(--ant-color-error);background:var(--ant-color-error-bg);border-color:var(--ant-color-error)}.status.muted{color:var(--ant-color-text-secondary);background:var(--ant-color-bg-layout);border-color:var(--ant-color-border)} +.pagination{height:56px;padding:12px 0 0;gap:0}.pagination span{border:1px solid var(--ant-color-border);height:32px;line-height:30px;padding:0 12px;margin-right:8px}.pagination button,.pagination select{height:32px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container)}.pagination button{width:34px}.pagination button.active{background:var(--ant-color-bg-container);color:var(--ant-color-text-base)}.pagination select{margin-left:8px;padding:0 12px} +.company-detail .detail-status{margin-bottom:20px}.company-detail h3{font-size:var(--ant-font-size);margin:20px 0 8px}.company-detail dl{display:grid;grid-template-columns:110px 1fr;margin:0}.company-detail dt,.company-detail dd{margin:0;padding:12px 0;border-bottom:1px solid var(--ant-color-border)}.company-detail dt{color:var(--ant-color-text-secondary)} +.ant-drawer .ant-drawer-header{min-height:64px;border-bottom:1px solid var(--ant-color-border)}.ant-drawer .ant-drawer-title{font-size:var(--ant-font-size-heading-4);font-weight:600}.ant-drawer .ant-drawer-body{padding:20px 24px} +.company-form-page{display:grid;grid-template-columns:220px minmax(0,860px);gap:32px;align-items:start;padding-top:20px} +.form-section-nav{position:sticky;top:76px;display:grid;grid-template-columns:32px 1fr;padding:4px 0;color:var(--ant-color-text-base)}.form-section-nav>i.form-section-nav-dot{width:8px;height:8px;border-radius:50%;background:var(--ant-color-primary);justify-self:center;align-self:center}.form-section-nav>span{font-size:var(--ant-font-size);font-weight:600;line-height:24px;margin-bottom:12px}.form-section-nav>a{grid-column:2;color:var(--ant-color-text-secondary);text-decoration:none;padding:8px 0 8px 12px;border-left:1px solid var(--ant-color-border)}.form-section-nav>a:hover{color:var(--ant-color-primary)} +.single-column-form{width:100%}.single-column-form .panel{margin:0}.single-column-form .panel-body{padding:20px 24px 32px}.single-column-form .form-grid{display:grid;grid-template-columns:1fr!important;gap:20px}.single-column-form .form-grid>*{grid-column:1!important}.single-column-form .field{max-width:680px;gap:8px}.single-column-form .field>span{font-size:var(--ant-font-size)}.single-column-form .field input,.single-column-form .field select{height:40px;border-radius:var(--ant-border-radius);padding:0 12px}.single-column-form .field textarea{min-height:112px;border-radius:var(--ant-border-radius);padding:12px 12px}.single-column-form .field textarea.small{min-height:88px}.single-column-form .field small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)} +.domain-select{display:grid;grid-template-columns:1fr auto;gap:12px;align-items:center}.domain-select .text-button{margin:0}.domain-add{max-width:520px}.domain-add .button{min-width:88px}.field-assist{display:flex;align-items:flex-end;justify-content:flex-start;gap:12px;margin-top:4px}.field-assist .button{flex:none;min-width:140px}.form-section-heading{max-width:680px;border-top:1px solid var(--ant-color-border);padding-top:20px;margin-top:4px}.form-section-heading h3{font-size:var(--ant-font-size);margin:0 0 4px}.form-section-heading p{margin:0;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.form-guidance{max-width:680px;padding:12px 16px;background:var(--ant-color-bg-layout);border-left:3px solid var(--ant-color-primary);display:flex;flex-direction:column;gap:4px}.form-guidance span{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.save-indicator{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)} +.upload{height:96px;border-color:var(--ant-color-border);background:var(--ant-color-bg-layout);border-radius:var(--ant-border-radius)}.upload b{font-size:var(--ant-font-size-heading-4)}.upload span{font-size:var(--ant-font-size)}.upload small{font-size:var(--ant-font-size-sm)} +.ai-assist-intro{display:flex;gap:16px;padding:16px;background:var(--ant-color-bg-layout);border:1px solid var(--ant-color-border)}.ai-assist-intro>.anticon{font-size:var(--ant-font-size-heading-3);color:var(--ant-color-primary)}.ai-assist-intro h3{font-size:var(--ant-font-size);margin:0 0 8px}.ai-assist-intro p{margin:0;color:var(--ant-color-text-secondary);line-height:1.7}.ai-assist-drawer .field>span{font-size:var(--ant-font-size);font-weight:600}.drawer-actions{display:flex;gap:8px;margin:20px 0}.drawer-actions .button{min-width:120px} +.result-header{min-height:72px;border:0;border-bottom:1px solid var(--ant-color-border);padding:12px 0;margin:0}.result-header h2{font-size:var(--ant-font-size-heading-4)}.result-header .site-icon{border-radius:var(--ant-border-radius);background:var(--ant-color-primary);color:var(--ant-color-text-light-solid);border:0;font-size:var(--ant-font-size)}.result-actions{display:flex;gap:8px}.result-actions .button{min-width:112px} +.kpi-row{border-bottom:1px solid var(--ant-color-border);gap:0;margin:0 0 16px}.kpi-row>div{height:72px;border:0;border-right:1px solid var(--ant-color-border);padding:12px 16px}.kpi-row>div:last-child{border-right:0}.kpi-row span{color:var(--ant-color-text-secondary)}.kpi-row b{font-size:var(--ant-font-size-heading-3)} +.result-layout{grid-template-columns:1fr}.result-pages{display:grid;grid-template-columns:1fr;gap:0}.result-pages article{display:grid;grid-template-columns:300px 1fr;min-height:180px;border:0;border-bottom:1px solid var(--ant-color-border);padding:16px 0}.result-pages article>div:last-child{padding:0 20px}.result-pages h3{font-size:var(--ant-font-size);margin:16px 0 8px}.result-pages p{font-size:var(--ant-font-size-sm);line-height:1.6}.result-pages footer{gap:8px}.result-pages footer .button{min-width:96px;height:32px;margin:0}.dashboard-thumb-live{min-height:160px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-layout)} +.text-button{color:var(--ant-color-primary);font-size:var(--ant-font-size)}.modal,.login-card{border-radius:var(--ant-border-radius)}.modal{box-shadow:0 6px 24px color-mix(in srgb,var(--ant-color-text-base) 13%,transparent)}.toast{top:68px;border-radius:var(--ant-border-radius);background:var(--ant-color-text-base)} +.ai-fab{box-shadow:0 4px 12px color-mix(in srgb,var(--ant-color-text-base) 20%,transparent)}.ai-dialog{border-radius:var(--ant-border-radius)}.ai-dialog header{background:var(--ant-color-primary)} +@media(max-width:1200px){.company-form-page{grid-template-columns:180px minmax(0,1fr);gap:20px}.single-column-form .field,.form-section-heading,.form-guidance{max-width:100%}} +@media(max-width:900px){.app-shell{padding-left:0}.side-nav{display:none}.workspace{min-width:0}.company-form-page{grid-template-columns:1fr}.form-section-nav{display:none}.content{padding:0 16px 20px}.page-heading{padding:12px 16px}.company-status-tabs{overflow-x:auto}.company-status-tabs > button{min-width:100px}.company-filterbar{align-items:stretch;flex-wrap:wrap}.filter-actions{margin-left:0;width:100%}.result-pages article{grid-template-columns:1fr}.sticky-actions{left:0}} + +/* Company navigation IA: global menu contains business modules only. */ +.side-nav{display:none!important} +.app-shell{padding-left:200px} +.company-side-nav{position:fixed;z-index:35;top:56px;bottom:0;left:0;width:200px;background:var(--ant-color-bg-layout);border-right:1px solid var(--ant-color-border);display:flex;flex-direction:column;color:var(--ant-color-text-base);font-family:var(--ant-font-family)} +.side-menu{padding:0;overflow:auto;flex:1}.menu-section{margin:0}.menu-section button{width:100%;border:0;background:transparent;color:inherit;text-align:left;font-family:var(--ant-font-family);font-weight:600} +.menu-section-title{height:56px;padding:0 20px;display:flex;align-items:center;justify-content:space-between;font-size:var(--ant-font-size-heading-4);line-height:56px} +.menu-section-title>span{display:block}.menu-section-title>.anticon{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-base)} +.menu-section-title:hover{background:var(--ant-color-fill-secondary)}.menu-section.current>.menu-section-title{color:var(--ant-color-text-base);font-weight:600} +.menu-section-items button{height:50px;padding:0 20px 0 40px;display:flex;align-items:center;font-size:var(--ant-font-size);line-height:50px;color:var(--ant-color-text-base)} +.menu-section-items button:hover{background:var(--ant-color-fill-secondary);color:var(--ant-color-primary)} +.menu-section-items button.active{background:var(--ant-color-primary-bg);color:var(--ant-color-primary);font-weight:600} +.extension-menu-items{padding-bottom:4px}.extension-menu-item{height:50px;padding:0 20px 0 40px;display:flex;align-items:center;font-size:var(--ant-font-size);line-height:50px;color:var(--ant-color-text-base);font-weight:600;cursor:default}.extension-submenu-title{justify-content:space-between;cursor:pointer}.extension-submenu-title>.anticon{font-size:var(--ant-font-size-sm);margin-right:4px}.extension-third-menu>div{height:50px;padding:0 20px 0 60px;display:flex;align-items:center;color:var(--ant-color-text-base);font-size:var(--ant-font-size);line-height:50px;font-weight:600;cursor:default}.extension-menu-section .extension-menu-item:hover,.extension-menu-section .extension-third-menu>div:hover{background:transparent;color:inherit} +.extension-third-menu>button{height:50px;padding:0 20px 0 60px;display:flex;align-items:center;color:var(--ant-color-text-base);font-size:var(--ant-font-size);line-height:50px;font-weight:600;cursor:pointer;border:0;background:transparent;width:100%;text-align:left;font-family:var(--ant-font-family)} +.extension-menu-section .extension-third-menu>button.clickable:hover{background:var(--ant-color-bg-layout);color:var(--ant-color-primary)} +.extension-menu-section .extension-third-menu>button.clickable.active{background:var(--ant-color-primary-bg);color:var(--ant-color-primary);font-weight:600} +.company-side-footer{position:relative;margin:auto 16px 16px;padding:16px 4px 0;border-top:1px solid var(--ant-color-border);display:flex;flex-direction:column;gap:8px;font-size:var(--ant-font-size-sm)} +.company-side-footer>b{color:var(--ant-color-primary)}.company-side-footer>button{height:26px;padding:0;border:0;background:transparent;display:flex;align-items:center;justify-content:space-between;color:var(--ant-color-text-secondary);text-align:left} +.company-model-menu{position:absolute;left:0;right:0;bottom:30px;padding:8px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);box-shadow:none} +.company-model-menu button{width:100%;height:32px;border:0;background:var(--ant-color-bg-container);display:flex;justify-content:space-between;align-items:center;padding:0 8px}.company-model-menu button:hover{background:var(--ant-color-bg-layout)}.company-model-menu span{color:var(--ant-color-primary);font-size:var(--ant-font-size-sm)} +.sticky-actions{left:200px} +@media(max-width:720px){.company-side-nav{display:none}.app-shell{padding-left:0}.sticky-actions{left:0}} + +.site-edit-switcher{display:flex;align-items:center;gap:12px;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size)}.site-edit-switcher select{width:220px;height:34px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);border-radius:var(--ant-border-radius);padding:0 32px 0 12px;color:var(--ant-color-text-base)}.site-edit-switcher select:focus{outline:1px solid var(--ant-color-primary);border-color:var(--ant-color-primary)} +.site-edit-tabs{height:64px;background:var(--ant-color-bg-container);border-top:1px solid var(--ant-color-border);border-bottom:1px solid var(--ant-color-border);display:flex;padding:0 24px;gap:0}.site-edit-tabs>button{height:64px;flex:1;min-width:0;border:0;border-bottom:3px solid transparent;background:var(--ant-color-bg-container);color:var(--ant-color-text-secondary);display:flex;align-items:center;gap:12px;padding:0 20px;font-size:var(--ant-font-size);text-align:left}.site-edit-tabs>button i{font-style:normal;width:26px;height:26px;border:1px solid var(--ant-color-border);border-radius:50%;display:grid;place-items:center;background:var(--ant-color-bg-container)}.site-edit-tabs>button:hover{color:var(--ant-color-primary);background:var(--ant-color-bg-layout)}.site-edit-tabs>button.active{color:var(--ant-color-primary);border-bottom-color:var(--ant-color-primary);font-weight:600}.site-edit-tabs>button.active i{background:var(--ant-color-primary);border-color:var(--ant-color-primary);color:var(--ant-color-text-light-solid)}.site-step-blank{min-height:calc(100vh - 286px);background:var(--ant-color-bg-container)} +.asset-config-shell{min-width:0}.asset-config-tabs{height:66px;display:flex;align-items:flex-end;border:1px solid var(--ant-color-border);border-bottom:0;background:var(--ant-color-bg-container);padding:0 20px;gap:36px}.asset-config-tabs>button{height:65px;min-width:210px;padding:12px 4px 8px;border:0;border-bottom:3px solid transparent;background:transparent;text-align:left;display:flex;flex-direction:column;justify-content:center;gap:4px;color:var(--ant-color-text-secondary)}.asset-config-tabs>button span{font-size:var(--ant-font-size);font-weight:600}.asset-config-tabs>button small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.asset-config-tabs>button.active{color:var(--ant-color-primary);border-bottom-color:var(--ant-color-primary)}.asset-config-tabs>button.active small{color:var(--ant-color-text-secondary)}.quick-asset-config{border-top:1px solid var(--ant-color-border);padding-top:16px}.manual-asset-list{border-top:1px solid var(--ant-color-border);padding-top:16px}.manual-asset-list>.panel{margin:0}.manual-asset-filter{padding:0 0 16px;margin-bottom:0}.asset-category{border-top:1px solid var(--ant-color-border);margin:0 -12px}.asset-category>header{height:46px;display:flex;align-items:center;gap:8px;padding:0 16px;background:var(--ant-color-bg-layout)}.asset-category>header strong{font-size:var(--ant-font-size)}.asset-category>header span{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.asset-category .company-table{margin:0}.asset-category .company-table th:first-child,.asset-category .company-table td:first-child{padding-left:40px}.asset-group-dialog{width:540px}.dialog-form{display:flex;flex-direction:column;gap:20px;margin:20px 0}.dialog-form input,.dialog-form select{height:38px;border:1px solid var(--ant-color-border);padding:0 12px;background:var(--ant-color-bg-container)} +.manual-asset-editor{border-top:1px solid var(--ant-color-border);padding-top:0;background:var(--ant-color-bg-container)}.asset-editor-title{height:64px;border:1px solid var(--ant-color-border);border-top:0;display:flex;align-items:center;padding:0 16px;gap:20px}.asset-editor-title>.text-button{margin:0;padding-right:20px;border-right:1px solid var(--ant-color-border)}.asset-editor-title>div{flex:1;display:flex;align-items:baseline;gap:12px}.asset-editor-title h2{font-size:var(--ant-font-size);margin:0}.asset-editor-title>div>span{color:var(--ant-color-text-secondary)}.asset-editor-title>.button{margin:0}.asset-editor-workbench{min-height:620px;border:1px solid var(--ant-color-border);border-top:0;display:grid;grid-template-columns:250px 1fr}.asset-editor-side{border-right:1px solid var(--ant-color-border);background:var(--ant-color-bg-layout)}.asset-editor-side>.field{padding:16px;border-bottom:1px solid var(--ant-color-border)}.asset-editor-side>.field input{background:var(--ant-color-bg-container)}.asset-batch-entry{width:100%;height:54px;border:0;border-bottom:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);text-align:left;padding:0 16px;font-size:var(--ant-font-size)}.asset-batch-entry:hover{color:var(--ant-color-primary);background:var(--ant-color-bg-layout)}.asset-template-panel{padding:16px;display:flex;flex-direction:column;gap:12px}.asset-template-panel>strong{font-size:var(--ant-font-size)}.asset-template-panel>select{height:34px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);padding:0 8px}.asset-template-panel>button{min-height:58px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);display:grid;grid-template-columns:24px 1fr;grid-template-rows:1fr 1fr;text-align:left;padding:8px;column-gap:8px}.asset-template-panel>button>span{grid-row:1/3;color:var(--ant-color-primary);align-self:center}.asset-template-panel>button>b{font-size:var(--ant-font-size-sm)}.asset-template-panel>button>small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.asset-template-panel>button:hover{border-color:var(--ant-color-primary)}.asset-tree-workspace{min-width:0;background:var(--ant-color-bg-layout)}.asset-editor-toolbar{height:52px;border-bottom:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);padding:0 12px;display:flex;align-items:center;justify-content:space-between}.asset-editor-toolbar>div{display:flex;align-items:center;gap:8px}.asset-editor-toolbar .button{margin:0;min-width:auto}.asset-tree-search{width:210px;height:30px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);display:flex;align-items:center;padding:0 8px;color:var(--ant-color-text-secondary)}.asset-tree-search input{border:0;outline:0;width:100%;padding-left:8px}.asset-tree-canvas{min-height:567px;padding:28px;overflow:auto}.asset-tree-root-card{width:220px;min-height:54px;margin:0 auto 24px;border:1px solid var(--ant-color-border);border-left:4px solid var(--ant-color-primary);background:var(--ant-color-bg-container);box-shadow:none;padding:8px 12px;display:flex;flex-direction:column;gap:4px;position:relative}.asset-tree-root-card:after{content:"";position:absolute;left:50%;bottom:-25px;height:24px;border-left:1px solid var(--ant-color-primary-bg)}.asset-tree-root-card small{color:var(--ant-color-text-secondary)}.asset-node-tree{display:flex;justify-content:center;align-items:flex-start;gap:20px}.asset-tree-branch{position:relative;display:flex;flex-direction:column;align-items:center}.asset-node-card{width:190px;min-height:50px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);box-shadow:none;display:grid;grid-template-columns:24px 1fr 22px;grid-template-rows:1fr 1fr;text-align:left;padding:8px 8px;column-gap:4px;position:relative}.asset-node-card>span{grid-row:1/3;color:var(--ant-color-primary);align-self:center}.asset-node-card>b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.asset-node-card>small{color:var(--ant-color-text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.asset-node-card>em{grid-column:3;grid-row:1/3;align-self:center;justify-self:end;font-style:normal;width:20px;height:20px;border-radius:50%;background:var(--ant-color-bg-layout);display:grid;place-items:center;color:var(--ant-color-text-secondary)}.asset-node-card:hover,.asset-node-card.selected{border-color:var(--ant-color-primary);box-shadow:none}.asset-tree-children{margin-top:28px;padding-top:0;display:flex;align-items:flex-start;justify-content:center;gap:16px;position:relative}.asset-tree-children:before{content:"";position:absolute;left:50%;top:-28px;height:28px;border-left:1px solid var(--ant-color-primary-bg)}.asset-tree-children>.asset-tree-branch:before{content:"";position:absolute;left:50%;top:-14px;height:14px;border-left:1px solid var(--ant-color-primary-bg)}.asset-tree-children>.asset-tree-branch:not(:only-child):after{content:"";position:absolute;top:-14px;left:-7px;right:-7px;border-top:1px solid var(--ant-color-primary-bg)}.asset-tree-empty{width:420px;margin:60px auto;text-align:center;display:flex;flex-direction:column;gap:8px;color:var(--ant-color-text-secondary)}.asset-tree-empty b{color:var(--ant-color-text-secondary)}.node-drawer-tabs{height:45px;border-bottom:1px solid var(--ant-color-border);display:flex;margin:-8px 0 20px}.node-drawer-tabs button{border:0;border-bottom:3px solid transparent;background:var(--ant-color-bg-container);padding:0 20px;font-size:var(--ant-font-size)}.node-drawer-tabs button.active{color:var(--ant-color-primary);border-bottom-color:var(--ant-color-primary)}.node-drawer-form{display:flex;flex-direction:column;gap:20px}.node-drawer-form input,.node-drawer-form select,.node-drawer-form textarea{width:100%;border:1px solid var(--ant-color-border);padding:8px;background:var(--ant-color-bg-container)}.node-drawer-form input,.node-drawer-form select{height:38px}.node-drawer-form textarea{min-height:110px}.node-config-list>header,.node-config-list>div{display:grid;grid-template-columns:1fr 1fr 90px;gap:8px;margin-bottom:8px}.node-config-list.binding>header,.node-config-list.binding>div{grid-template-columns:1fr 1fr}.node-config-list>header{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.node-config-list input{height:36px;border:1px solid var(--ant-color-border);padding:0 8px}.node-config-list>.button{margin:8px 0 0}.batch-create-dialog{width:min(760px,calc(100vw - 40px))}.batch-create-dialog .node-drawer-tabs{margin:12px 0 20px}.batch-table>header,.batch-table>div{display:grid;grid-template-columns:1.4fr 90px 1.4fr 32px;gap:8px;margin-bottom:8px}.batch-table>header{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.batch-table input{height:36px;border:1px solid var(--ant-color-border);padding:0 8px}.batch-table>.button{margin:8px 0 12px}.manual-excel-upload{height:180px;border:1px dashed var(--ant-color-border);background:var(--ant-color-bg-layout);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;cursor:pointer}.manual-excel-upload>b{font-size:var(--ant-font-size-heading-2);color:var(--ant-color-primary)}.manual-excel-upload>span{font-size:var(--ant-font-size)}.manual-excel-upload>small{color:var(--ant-color-text-secondary)} +@media(max-width:1100px){.asset-editor-workbench{grid-template-columns:220px 1fr}.asset-node-card{width:160px}.asset-tree-children{flex-direction:column}.asset-tree-children>.asset-tree-branch:after{display:none}.asset-config-tabs{gap:20px}.asset-config-tabs>button{min-width:180px}} + +/* Resource center list pages */ +.resource-list-panel>.panel-body{padding:0 16px 12px;overflow-x:auto} +.resource-table{min-width:980px;table-layout:auto}.resource-table th,.resource-table td{vertical-align:middle}.resource-table th:last-child,.resource-table td:last-child{width:64px;text-align:center} +.resource-table th:nth-child(3),.resource-table td:nth-child(3){width:76px}.resource-table th:nth-child(4),.resource-table td:nth-child(4),.resource-table th:nth-child(5),.resource-table td:nth-child(5),.resource-table th:nth-child(6),.resource-table td:nth-child(6){width:70px;text-align:center} +.resource-table th:nth-child(7),.resource-table td:nth-child(7){width:96px}.resource-table th:nth-child(8),.resource-table td:nth-child(8){width:180px} +.domain-resource-table th:first-child,.domain-resource-table td:first-child{width:260px;min-width:260px;text-align:left}.domain-resource-table .company-record-link{display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left} +.resource-detail>p{margin:8px 0;color:var(--ant-color-text-secondary);line-height:1.8;white-space:pre-wrap}.resource-detail-image{display:block;width:100%;max-height:220px;object-fit:contain;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-layout);margin-bottom:20px} +.device-resource-table{min-width:820px}.device-resource-table th:nth-child(1),.device-resource-table td:nth-child(1){width:280px;min-width:280px;text-align:left}.device-resource-table th:nth-child(2),.device-resource-table td:nth-child(2){width:90px;text-align:center}.device-resource-table th:nth-child(3),.device-resource-table td:nth-child(3){width:110px;text-align:left}.device-resource-table th:nth-child(4),.device-resource-table td.domain-cell{width:240px;min-width:180px;text-align:left;white-space:normal}.device-resource-table th:nth-child(5),.device-resource-table td:nth-child(5){width:64px;text-align:center}.device-resource-table .company-record-link{display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left} +.domain-tag-list{display:flex;flex-wrap:wrap;align-items:center;gap:8px} +.ant-tag.tag-new{display:inline-flex;align-items:center;height:24px;line-height:21px;border-radius:var(--ant-border-radius);padding:0 12px;font-size:var(--ant-font-size-sm);white-space:nowrap;margin:0} +.resource-name-cell{display:flex;align-items:center;gap:12px;min-width:0}.resource-name-cell>img,.resource-placeholder{flex:none;width:48px;height:36px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-layout);object-fit:cover;border-radius:var(--ant-border-radius)}.resource-placeholder{display:grid;place-items:center;color:var(--ant-color-text-secondary)}.resource-name-cell .company-record-link{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left} +.resource-point-list{border-top:1px solid var(--ant-color-border)}.resource-point-list>div{height:40px;border-bottom:1px solid var(--ant-color-border);display:flex;align-items:center;justify-content:space-between}.resource-point-list span{color:var(--ant-color-text-secondary)}.resource-point-list>p{color:var(--ant-color-text-secondary)} +.resource-back{height:44px;display:flex;align-items:center;border-bottom:1px solid var(--ant-color-border);margin:0 0 16px}.resource-back .text-button{margin:0} +.style-resource-panel{margin-top:16px}.style-resource-table{min-width:820px}.style-resource-table th:nth-child(1),.style-resource-table td:nth-child(1){width:260px;min-width:260px;text-align:left}.style-resource-table th:nth-child(2),.style-resource-table td:nth-child(2){width:140px}.style-resource-table th:nth-child(3),.style-resource-table td:nth-child(3){width:190px}.style-resource-table th:nth-child(4),.style-resource-table td:nth-child(4){width:130px}.style-resource-table th:nth-child(5),.style-resource-table td:nth-child(5){width:64px;text-align:center}.style-resource-table .company-record-link{display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}.style-list-thumbnail{display:block;width:96px;height:54px;object-fit:cover;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-layout);border-radius:var(--ant-border-radius)} +.style-drawer>img{display:block;width:100%;max-height:440px;object-fit:contain;background:var(--ant-color-bg-layout);border:1px solid var(--ant-color-border)}.style-drawer dl{display:grid;grid-template-columns:110px 1fr;margin-top:20px}.style-drawer dt,.style-drawer dd{margin:0;padding:12px 0;border-bottom:1px solid var(--ant-color-border)}.style-drawer dt{color:var(--ant-color-text-secondary)} +/* 生成过程只读终端 */ +.gen-right{display:flex;flex-direction:column;gap:16px} +.console-panel .panel-body{padding:0} +.gen-console{height:300px;max-height:42vh;overflow-y:auto;background:var(--ant-color-text-base);color:var(--ant-color-primary);font:12px/1.5 "SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace;padding:12px 12px} +.gen-console pre{margin:0;white-space:pre-wrap;word-break:break-word} +.gen-console pre:empty:before{content:""} +.modal-console{margin-top:12px;border:1px solid var(--ant-color-primary);border-radius:var(--ant-border-radius);overflow:hidden} +.modal-console-head{background:var(--ant-color-text-base);color:var(--ant-color-primary-bg);font-size:var(--ant-font-size-sm);padding:8px 12px;border-bottom:1px solid var(--ant-color-primary)} +.modal-console-body{background:var(--ant-color-text-base);color:var(--ant-color-primary);font:12px/1.5 "SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace;margin:0;padding:12px 12px;max-height:240px;overflow:auto;white-space:pre-wrap;word-break:break-word} + +/* ===== 视图切换(列表/卡片) ===== */ +.view-toggle{display:inline-flex;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);overflow:hidden} +.view-toggle button{border:0;background:var(--ant-color-bg-container);color:var(--ant-color-text-secondary);height:28px;padding:0 12px;font-size:var(--ant-font-size-sm)} +.view-toggle button+button{border-left:1px solid var(--ant-color-border)} +.view-toggle button.active{background:var(--ant-color-primary);color:var(--ant-color-text-light-solid)} +/* ===== 领域方案卡片视图 ===== */ +.domain-card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(245px,1fr));gap:12px;padding:8px 0} +.domain-card{border:1px solid var(--ant-color-border);border-top:3px solid var(--ant-color-primary);background:var(--ant-color-bg-container);padding:16px;display:flex;flex-direction:column;gap:8px;cursor:pointer;transition:.15s} +.domain-card:hover{box-shadow:none;border-top-color:var(--ant-color-primary-active)} +.domain-card>header{display:flex;align-items:center;justify-content:space-between;gap:8px} +.domain-card h3{font-size:var(--ant-font-size);margin:0} +.domain-card .badge{display:inline-block;align-self:flex-start;background:var(--ant-color-primary-bg);color:var(--ant-color-primary-active);border:1px solid var(--ant-color-primary);border-radius:var(--ant-border-radius);padding:4px 12px;font-size:var(--ant-font-size-sm)} +.domain-card .meta{display:flex;gap:16px;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)} +.domain-card .meta b{color:var(--ant-color-text-base);font-size:var(--ant-font-size-sm);margin-right:4px} + +/* 领域方案 7 步向导 */ +.placeholder-block{display:flex;flex-direction:column;gap:12px;padding:8px 4px} +.badge.todo{display:inline-block;align-self:flex-start;background:var(--ant-color-primary-bg);color:var(--ant-color-error);border:1px solid var(--ant-color-error-bg);border-radius:var(--ant-border-radius);padding:4px 12px;font-size:var(--ant-font-size-sm)} +/* Cube 页面来源徽标 */ +.badge.src-upload{display:inline-flex;align-items:center;gap:4px;background:var(--ant-color-bg-layout);color:var(--ant-color-primary);border:1px solid var(--ant-color-primary-bg);border-radius:var(--ant-border-radius);padding:4px 8px;font-size:var(--ant-font-size-sm)} +.badge.src-ai{display:inline-flex;align-items:center;gap:4px;background:var(--ant-color-bg-layout);color:var(--ant-color-primary);border:1px solid var(--ant-color-primary);border-radius:var(--ant-border-radius);padding:4px 8px;font-size:var(--ant-font-size-sm)} +.badge.src-manual{display:inline-flex;align-items:center;gap:4px;background:var(--ant-color-bg-layout);color:var(--ant-color-text-secondary);border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:4px 8px;font-size:var(--ant-font-size-sm)} + +/* 扩展菜单可点击项 */ +.extension-menu-section .extension-menu-item.clickable{cursor:pointer} +.extension-menu-section .extension-menu-item.clickable:hover{background:var(--ant-color-bg-layout);color:var(--ant-color-primary)} +.extension-menu-section .extension-menu-item.clickable.active{background:var(--ant-color-primary-bg);color:var(--ant-color-primary);font-weight:600} + +/* 仪表盘页面 */ +.dashboard-page{min-height:calc(100vh - 56px);padding:20px;background:var(--ant-color-bg-layout);display:flex;align-items:flex-start;justify-content:center} +.dashboard-page img{display:block;max-width:100%;height:auto;background:var(--ant-color-bg-container);box-shadow:none;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius)} +.domain-preview-canvas{background:var(--ant-color-text-base);height:64vh;border-radius:var(--ant-border-radius);overflow:auto} +.domain-preview-canvas .dashboard-thumb-live{min-height:0} +.domain-preview-feedback{margin-top:16px} +.domain-preview-feedback textarea{width:100%;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:8px;resize:vertical;line-height:1.6;margin-top:8px} +.domain-review-pages{display:grid;grid-template-columns:1fr;gap:12px} +.domain-review-page{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);overflow:hidden;transition:border-color .15s,box-shadow .15s} +.domain-review-page:hover{border-color:var(--ant-color-primary);box-shadow:none} +.domain-review-page .dashboard-thumb-live{border-bottom:0;min-height:240px} +.domain-review-page>div{padding:8px 12px;display:flex;align-items:center;justify-content:space-between;gap:8px} +.domain-review-page h4{margin:0;font-size:var(--ant-font-size-sm)} +.domain-review-page .review-zoom{font-size:var(--ant-font-size-sm);color:var(--ant-color-primary);white-space:nowrap} + +.domain-card .card-actions{display:flex;gap:16px;margin-top:4px;padding-top:8px;border-top:1px solid var(--ant-color-border)} +/* ===== 设备模版 ===== */ +.device-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(360px,1fr));gap:12px;padding:4px 0} +.device-card{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);padding:16px} +.device-card-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px} +.device-card-head b{font-size:var(--ant-font-size)} +.cp-list{margin-top:12px} +.cp-list>b{display:flex;align-items:center;gap:8px;font-size:var(--ant-font-size-sm)} +.cp-list .data-table{margin-top:8px} +.chk{display:flex;flex-wrap:wrap;gap:8px} +.chk-item{display:inline-flex;align-items:center;gap:4px;font-size:var(--ant-font-size-sm);background:var(--ant-color-bg-layout);border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:4px 8px;cursor:pointer} +.chk-item input{margin:0;accent-color:var(--ant-color-primary)} +/* ===== 方案详情:选用设备模版 ===== */ +.device-picker{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:8px} +.picker-item{display:flex;align-items:center;gap:8px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);border-radius:var(--ant-border-radius);padding:8px 12px;cursor:pointer} +.picker-item.on{border-color:var(--ant-color-primary);background:var(--ant-color-bg-layout)} +.picker-item input{margin:0;accent-color:var(--ant-color-primary)} +.picker-name{font-weight:600;font-size:var(--ant-font-size-sm)} +.picker-doms{margin-left:auto;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);max-width:42%;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} +/* ===== 设备模版:图片与采集点编辑 ===== */ +.device-list{display:grid;grid-template-columns:1fr;gap:16px;padding:4px 0} +.device-img-field{margin-top:8px;border:1px dashed var(--ant-color-border);border-radius:var(--ant-border-radius);width:160px;height:160px;background:var(--ant-color-bg-layout);display:flex;align-items:center;justify-content:center;cursor:pointer;overflow:hidden;position:relative} +.device-img-field:hover{border-color:var(--ant-color-primary);background:var(--ant-color-bg-layout)} +.device-img-field img{width:100%;height:100%;object-fit:cover;display:block} +.device-img-field .device-img-empty{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);text-align:center;padding:0 8px} +.cp-list-head{display:flex;align-items:center;justify-content:space-between;margin:12px 0 8px} +.cp-list-head span{display:flex;gap:12px} +.cp-editor td{padding:4px 8px;vertical-align:middle} +.cp-editor input,.cp-editor select{width:100%;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);height:30px;padding:0 8px;background:var(--ant-color-bg-container);font-size:var(--ant-font-size-sm)} +.cp-editor input:focus,.cp-editor select:focus{outline:1px solid var(--ant-color-primary)} +.cp-range-custom{margin-top:4px} +/* ===== 设备模板:报警规则 ===== */ +.alarm-rule-block{margin-top:20px;border-top:1px solid var(--ant-color-border);padding-top:8px}.alarm-rule-head{min-height:44px;display:flex;align-items:center;justify-content:space-between;gap:16px}.alarm-rule-head>b{font-size:var(--ant-font-size)}.alarm-rule-head>div{display:flex;align-items:center;gap:12px}.alarm-rule-head .button{height:32px;min-width:74px;margin:0}.alarm-rule-search{width:210px;height:32px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);background:var(--ant-color-bg-container);color:var(--ant-color-text-secondary);display:flex;align-items:center;gap:8px;padding:0 8px}.alarm-rule-search:focus-within{border-color:var(--ant-color-primary)}.alarm-rule-search input{width:100%;border:0;outline:0;background:transparent}.alarm-rule-table{margin-top:0!important;border-top:1px solid var(--ant-color-border)}.alarm-rule-table th{height:40px;border-bottom:2px solid var(--ant-color-primary);font-size:var(--ant-font-size-sm)}.alarm-rule-table td{height:48px;font-size:var(--ant-font-size-sm)}.alarm-rule-table input[type=checkbox]{accent-color:var(--ant-color-primary)}.alarm-name-link{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-base)}.alarm-name-link:hover{color:var(--ant-color-primary)}.alarm-description-cell{max-width:320px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.alarm-switch{width:25px;height:16px;padding:0;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);background:var(--ant-color-fill-secondary);position:relative;vertical-align:middle}.alarm-switch i{position:absolute;left:2px;top:2px;width:10px;height:10px;border-radius:50%;background:var(--ant-color-bg-container);transition:left .15s}.alarm-switch.on{border-color:var(--ant-color-primary);background:var(--ant-color-primary)}.alarm-switch.on i{left:11px}.alarm-row-actions{display:flex;align-items:center;gap:4px}.alarm-row-actions .ant-btn{width:30px;height:30px;padding:0;color:var(--ant-color-primary);font-size:var(--ant-font-size)}.alarm-row-actions .ant-btn-dangerous{color:var(--ant-color-error)} +.alarm-rule-drawer .ant-drawer-header{min-height:56px;padding:0 24px;border-bottom:1px solid var(--ant-color-border)}.alarm-rule-drawer .ant-drawer-title{font-size:var(--ant-font-size);font-weight:600}.alarm-rule-drawer .ant-drawer-body{padding:28px 32px 32px;overflow:auto;background:var(--ant-color-bg-container)}.alarm-rule-drawer .ant-drawer-footer{height:56px;padding:12px 24px;border-top:1px solid var(--ant-color-border)}.alarm-rule-form{display:flex;flex-direction:column;gap:28px}.alarm-rule-form section>h3{margin:0 0 20px;padding-left:16px;border-left:4px solid var(--ant-color-primary);font-size:var(--ant-font-size);line-height:19px}.alarm-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px 40px;padding:0 20px}.alarm-form-grid label{display:grid;grid-template-columns:100px minmax(0,1fr);align-items:center;gap:0}.alarm-form-grid label.wide{grid-column:1/-1}.alarm-form-grid label>span{text-align:right;padding-right:16px;color:var(--ant-color-text-secondary)}.alarm-form-grid i,.alarm-sensitivity i{font-style:normal;color:var(--ant-color-error)}.alarm-form-grid input,.alarm-form-grid select{width:100%;height:34px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);background:var(--ant-color-bg-container);padding:0 12px;outline:0}.alarm-form-grid input:focus,.alarm-form-grid select:focus{border-color:var(--ant-color-primary)}.alarm-sensitivity{display:flex;align-items:center;gap:12px;padding:0 28px}.alarm-sensitivity>span{margin-right:8px}.alarm-sensitivity label{display:flex;align-items:center;gap:8px}.alarm-sensitivity input[type=radio]{accent-color:var(--ant-color-primary)}.alarm-sensitivity input[type=number]{width:55px;height:34px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:0 8px}.alarm-sensitivity input:disabled{background:var(--ant-color-bg-layout);color:var(--ant-color-text-disabled)}.alarm-sensitivity em{font-style:normal;color:var(--ant-color-text-secondary);margin-right:16px}.alarm-trigger-panel{border:1px solid var(--ant-color-border);margin:0 20px;min-height:250px}.alarm-trigger-panel>header{height:48px;display:flex;align-items:center;justify-content:space-between;padding:0 12px;border-bottom:1px solid var(--ant-color-border)}.alarm-trigger-panel>header b{font-size:var(--ant-font-size)}.alarm-trigger-panel>header>span{display:flex;align-items:center;gap:8px}.alarm-trigger-panel>header .button{height:32px;min-width:72px;margin:0}.alarm-trigger-table{table-layout:fixed}.alarm-trigger-table th{border-bottom:2px solid var(--ant-color-primary);font-size:var(--ant-font-size-sm)}.alarm-trigger-table th:nth-child(1){width:120px}.alarm-trigger-table th:nth-child(2){width:125px}.alarm-trigger-table th:nth-child(3){width:110px}.alarm-trigger-table th:nth-child(4){width:160px}.alarm-trigger-table th:nth-child(5){width:90px}.alarm-trigger-table th:nth-child(6){width:auto}.alarm-trigger-table th:nth-child(7){width:64px}.alarm-trigger-table td{height:48px;padding:8px 8px}.alarm-trigger-table input,.alarm-trigger-table select{width:100%;height:30px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);padding:0 8px;outline:0}.alarm-trigger-table input:focus,.alarm-trigger-table select:focus{border-color:var(--ant-color-primary)}.alarm-trigger-empty{height:130px;display:grid;place-items:center;color:var(--ant-color-text-secondary)} +@media(max-width:900px){.alarm-rule-drawer .ant-drawer-content-wrapper{width:100vw!important}.alarm-form-grid{grid-template-columns:1fr}.alarm-form-grid label.wide{grid-column:auto}.alarm-sensitivity{flex-wrap:wrap}.alarm-rule-table{min-width:900px}.alarm-rule-block{overflow:auto}} +/* ===== 设备模版:列表视图 ===== */ +.list-toolbar{margin-bottom:12px} +.list-toolbar .search{border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);height:32px;padding:0 12px;width:320px;background:var(--ant-color-bg-container)} +.list-toolbar .search:focus{outline:1px solid var(--ant-color-primary)} +.device-tpl-list tbody tr{cursor:pointer} +.device-tpl-list tbody tr:hover{background:var(--ant-color-bg-layout)} +.tpl-thumb{width:48px;height:34px;object-fit:cover;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);display:block;background:var(--ant-color-bg-layout)} +.tpl-thumb-empty{color:var(--ant-color-text-disabled)} + +/* ===== 自定义确认 / 输入弹窗(替代原生 confirm/prompt,居中显示) ===== */ +.dlg-backdrop{position:fixed;inset:0;z-index:90;background:color-mix(in srgb,var(--ant-color-bg-mask) 35%,transparent);display:flex;align-items:center;justify-content:center;padding:20px} +.dlg-box{background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);box-shadow:0 12px 36px color-mix(in srgb,var(--ant-color-text-base) 20%,transparent);width:min(420px,100%);max-width:100%;padding:20px 24px} +.dlg-box p{margin:0 0 20px;font-size:var(--ant-font-size-sm);line-height:1.6;color:var(--ant-color-text-base);white-space:pre-wrap;word-break:break-word} +.dlg-box input{width:100%;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);height:32px;padding:0 8px;font-size:var(--ant-font-size-sm)} +.dlg-box input:focus{outline:1px solid var(--ant-color-primary)} +.dlg-actions{display:flex;justify-content:flex-end;gap:12px} +.dlg-actions .button{margin-left:0} +/* 领域方案库 · 管理领域 */ +.domain-manage-list{display:flex;flex-direction:column;gap:8px} +.domain-manage-row{display:flex;align-items:center;gap:12px;padding:8px 12px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);background:var(--ant-color-bg-container)} +.domain-manage-name{font-weight:600;color:var(--ant-color-text-base)} +.domain-manage-row .muted{font-size:var(--ant-font-size-sm)} +.text-button.danger{color:var(--ant-color-error)} +.text-button.danger:hover{text-decoration:underline} +.domain-create-dialog h2{margin:0 0 8px;font-size:var(--ant-font-size-heading-4)}.domain-create-dialog p{margin:0 0 16px;color:var(--ant-color-text-secondary)}.domain-create-dialog .dlg-actions{margin-top:20px}.domain-create-dialog .button{min-width:96px;margin:0} +.system-settings-page{max-width:920px;padding-top:16px}.system-settings-page>.panel{margin:0}.system-settings-page .panel-head{height:52px}.settings-form{max-width:680px;display:flex;flex-direction:column;gap:20px;padding:8px 8px 16px}.settings-form .field{gap:8px}.settings-form .field>span{font-size:var(--ant-font-size)}.settings-form input,.settings-form select{width:100%;height:40px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:0 12px;background:var(--ant-color-bg-container)}.settings-form input[readonly]{background:var(--ant-color-bg-layout);color:var(--ant-color-text-secondary)}.settings-note{padding:16px 16px;background:var(--ant-color-bg-layout);border-left:3px solid var(--ant-color-primary);display:flex;flex-direction:column;gap:4px}.settings-note span{color:var(--ant-color-text-secondary)}.settings-actions{display:flex;justify-content:flex-start}.settings-actions .button{margin:0}.settings-table-wrap{overflow-x:auto}.settings-domain-table{table-layout:auto;min-width:680px}.settings-domain-table th:first-child,.settings-domain-table td:first-child{width:260px;min-width:260px;text-align:left}.settings-domain-table th:nth-child(2),.settings-domain-table td:nth-child(2){width:auto}.settings-domain-table th:nth-child(3),.settings-domain-table td:nth-child(3){width:130px}.settings-domain-table th:nth-child(4),.settings-domain-table td:nth-child(4){width:100px;text-align:center}.settings-domain-table .text-button{margin:0} + +/* 领域方案库 · 左侧导航栏「领域分类」行内编辑(删除× / 新增+) */ +.domain-nav-row{display:flex;align-items:stretch;flex-wrap:nowrap} +.domain-nav-row>button:not(.domain-nav-del):not(.domain-nav-ok){flex:1;min-width:0;text-align:left;height:41px;border:0;background:transparent;padding:0 16px;display:flex;align-items:center;color:var(--ant-color-text-base);font-size:var(--ant-font-size-sm);white-space:nowrap} +.domain-nav-name{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} +.domain-nav-row>button b{width:18px;color:var(--ant-color-text-secondary);margin-right:8px;font-weight:400;flex:0 0 auto} +.domain-nav-row>button:hover{background:var(--ant-color-fill-quaternary)} +.domain-nav-row.active{background:var(--ant-color-primary-bg)} +.domain-nav-row>button.active:not(.domain-nav-del):not(.domain-nav-ok){background:var(--ant-color-primary-bg);color:var(--ant-color-primary);font-weight:600} +.domain-nav-row.active>button b,.domain-nav-row>button.active b{color:var(--ant-color-primary)} +.domain-nav-del{border:0;background:transparent;width:30px;color:var(--ant-color-text-disabled);font-size:var(--ant-font-size);line-height:1;flex:0 0 auto} +.domain-nav-del:hover{color:var(--ant-color-error);background:var(--ant-color-bg-layout)} +.domain-nav-ok{border:0;background:transparent;width:30px;color:var(--ant-color-success);font-size:var(--ant-font-size);flex:0 0 auto} +.domain-nav-ok:hover{background:var(--ant-color-bg-layout)} +.domain-nav-add-cta{display:block} +.domain-nav-add{height:34px;border:0;background:transparent;text-align:left;padding:0 16px;display:flex;align-items:center;color:var(--ant-color-primary);font-size:var(--ant-font-size-sm);width:100%} +.domain-nav-add:hover{background:var(--ant-color-primary-bg)} +.domain-nav-add b{margin-right:8px} +.domain-nav-row.add{align-items:center;padding:4px 8px} +.domain-nav-input{flex:1;min-width:0;margin:0 4px;height:28px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:0 8px;font-size:var(--ant-font-size-sm);background:var(--ant-color-bg-container)} +.domain-nav-input:focus{outline:1px solid var(--ant-color-primary);border-color:var(--ant-color-primary)} + +/* ===== 方案打包 / 方案概览(v0.32) ===== */ +.gen-overview{display:block} +.gen-overview .panel{margin-bottom:0} +.overview-info{display:grid;grid-template-columns:1fr 1fr;gap:12px 20px;padding:4px 4px 16px;border-bottom:1px solid var(--ant-color-border);margin-bottom:12px} +.overview-info>div{display:flex;flex-direction:column;gap:4px} +.overview-info span{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);font-weight:600;letter-spacing:.3px} +.overview-info b{font-size:var(--ant-font-size);color:var(--ant-color-text-base)} +.overview-info .overview-desc{grid-column:1 / -1} +.overview-info .overview-desc p{margin:0;font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);line-height:1.6;background:var(--ant-color-bg-layout);border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:8px 8px} +.overview-tabs{margin:0 0 12px} +.overview-tabs button{padding:0 16px;font-size:var(--ant-font-size-sm)} +.overview-body{min-height:120px} +.overview-body .muted{padding:12px 4px} +.dev-list{display:flex;flex-direction:column;gap:8px} +.dev-row{border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);overflow:hidden;background:var(--ant-color-bg-container)} +.dev-row-head{width:100%;border:0;background:transparent;display:flex;align-items:center;gap:12px;padding:12px 12px;text-align:left;cursor:pointer} +.dev-row-head:hover{background:var(--ant-color-bg-layout)} +.dev-row-head b{font-size:var(--ant-font-size-sm);flex:1} +.dev-count{font-size:var(--ant-font-size-sm);color:var(--ant-color-primary);background:var(--ant-color-bg-layout);border-radius:var(--ant-border-radius);padding:4px 8px} +.dev-caret{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)} +.dev-detail{border-top:1px solid var(--ant-color-border);padding:12px 12px;background:var(--ant-color-bg-layout)} +.dev-desc{margin:0 0 8px;font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);line-height:1.7} +.dev-cp b{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-base);display:block;margin-bottom:4px} +.dev-cp ul{margin:0;padding-left:20px;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);line-height:1.8} +.doc-list{display:flex;flex-direction:column;gap:8px} +.doc-item{display:flex;align-items:baseline;gap:12px;padding:8px 12px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);background:var(--ant-color-bg-container)} +.doc-item b{font-size:var(--ant-font-size-sm);flex:1} +.doc-item .muted{font-size:var(--ant-font-size-sm);white-space:nowrap} +.ops-placeholder{display:flex;flex-direction:column;gap:12px;padding:20px;border:1px dashed var(--ant-color-border);border-radius:var(--ant-border-radius);background:var(--ant-color-bg-layout)} +.ops-placeholder .status{align-self:flex-start} +.ops-placeholder p{margin:0;font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);line-height:1.7} +/* ===== 方案打包示意图弹窗(v0.32) ===== */ +.pkg-modal{width:560px} +.pkg-body{padding:20px} +.pkg-body .hint{margin:0 0 16px} +.pkg-box{display:flex;justify-content:center;padding:8px 0 16px} +.pkg-svg{width:240px;height:auto;filter:drop-shadow(0 8px 16px rgba(120,80,20,.18))} +.pkg-items{display:grid;grid-template-columns:1fr 1fr;gap:12px} +.pkg-item{display:flex;align-items:flex-start;gap:12px;padding:12px 12px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);background:var(--ant-color-bg-container);box-shadow:none} +.pkg-item:hover{border-color:var(--ant-color-primary-bg);box-shadow:none} +.pkg-icon{width:34px;height:34px;flex:0 0 auto;border-radius:var(--ant-border-radius);background:linear-gradient(135deg,var(--ant-color-bg-layout),var(--ant-color-primary-bg));color:var(--ant-color-primary);display:grid;place-items:center;font-size:var(--ant-font-size)} +.pkg-item-text{display:flex;flex-direction:column;gap:4px;min-width:0} +.pkg-item-text b{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-base)} +.pkg-item-text small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);line-height:1.5} + + +/* WISE-IoT Desk header — aligned to the reference application's native header. */ +.topbar.wise-header{height:56px;padding:0 8px 0 12px;gap:0;border-top:4px solid #008cd6;border-bottom:1px solid #c8c8c8;background:#fff;box-shadow:none;overflow:hidden;color:#787878} +.wise-header button{border:0;background:transparent;padding:0;box-shadow:none} +.wise-menu-button{flex:0 0 24px;width:24px;height:24px;margin-right:12px;color:#787878;display:grid;place-items:center} +.wise-menu-button img{display:block;width:24px;height:24px} +.wise-logo-link{flex:0 0 123px;width:123px;height:40px;display:block} +.wise-logo-link img{display:block;width:123px;height:40px} +.wise-product-switch{flex:0 0 auto;height:48px;margin-left:12px;display:flex;align-items:center;color:#787878;white-space:nowrap} +.wise-product-switch>img:first-child{width:24px;height:24px;margin-right:8px} +.wise-product-switch>span,.wise-product-switch>strong{font-family:Roboto,"Noto Sans SC","Microsoft YaHei",Arial,sans-serif;font-size:16px;line-height:24px;font-weight:700;color:#787878} +.wise-product-switch>strong{margin-left:6px} +.wise-product-switch>img:last-child{width:24px;height:24px} +.wise-header-actions{height:48px;margin-left:auto;display:flex;align-items:center;justify-content:flex-end;flex:0 0 auto} +.wise-header-actions>button:not(.wise-avatar){flex:0 0 40px;width:40px;height:40px;display:grid;place-items:center;border-radius:0} +.wise-header-actions>button:not(.wise-avatar):hover{background:#f5f5f5} +.wise-header-actions>button>img{display:block;width:24px;height:24px} +.wise-avatar{flex:0 0 24px;width:24px;height:24px;margin:0 8px;border-radius:50%!important;background:#dff3fc!important;color:#008cd6!important;font-size:12px;line-height:24px;text-align:center} +.wise-powered-divider{flex:0 0 1px;width:1px;height:24px;background:#dedede;margin:0 4px 0 5px} +.wise-powered-logo{display:block;flex:0 0 122px;width:122px;height:48px;object-fit:contain} +@media(max-width:1120px){.wise-powered-divider,.wise-powered-logo{display:none}.wise-avatar{margin-right:8px}} +@media(max-width:700px){.wise-header-secondary{display:none!important}.wise-product-switch>strong{display:none}.wise-header-actions>button:not(.wise-avatar){width:36px;flex-basis:36px}} +@media(max-width:560px){.wise-logo-link{display:none}.wise-product-switch{margin-left:4px}.wise-header-actions>button:nth-child(1),.wise-header-actions>button:nth-child(2){display:none}} + +/* 当前站点资产组编辑器:直接进入详情,不再经过资产组列表。 */ +.asset-editor-loading{min-height:680px;border:1px solid var(--ant-color-border);border-top:0;background:var(--ant-color-bg-container);display:flex;align-items:center;justify-content:center;gap:16px;color:var(--ant-color-text-secondary)}.asset-editor-loading.error{color:var(--ant-color-error)} +.manual-asset-editor{border-top:1px solid var(--ant-color-border);background:var(--ant-color-bg-container)}.asset-editor-title{height:58px;border:1px solid var(--ant-color-border);border-top:0;padding:0 20px}.asset-editor-title>div{display:flex;align-items:baseline;gap:20px}.asset-editor-title h2{font-size:var(--ant-font-size-heading-4);font-weight:600;color:var(--ant-color-text-base)}.asset-editor-title>div>span{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.asset-editor-workbench{min-height:680px;height:calc(100vh - 306px);grid-template-columns:232px minmax(720px,1fr);border-color:var(--ant-color-border)} +.asset-editor-side{background:var(--ant-color-bg-container);border-right:1px solid var(--ant-color-border)}.asset-editor-side>.field{padding:16px 20px 16px}.asset-editor-side>.field>span{font-size:var(--ant-font-size);font-weight:600;color:var(--ant-color-text-base);margin-bottom:8px}.asset-editor-side>.field input{height:36px;border:1px solid var(--ant-color-border);padding:0 8px}.asset-batch-entry{height:72px;padding:0 20px;font-size:var(--ant-font-size);color:var(--ant-color-text-base)}.asset-batch-entry:hover{color:var(--ant-color-primary);background:var(--ant-color-bg-layout)}.asset-template-panel{padding:16px 20px;gap:12px}.asset-template-panel>strong{font-size:var(--ant-font-size);font-weight:600;color:var(--ant-color-text-base)}.asset-template-panel>select{height:34px}.asset-template-panel>button{min-height:50px;border:0;background:transparent;grid-template-columns:24px 1fr;padding:8px 8px}.asset-template-panel>button:hover{background:var(--ant-color-bg-layout);border:0}.asset-template-panel>button>span{font-size:var(--ant-font-size)}.asset-template-panel>button>small{color:var(--ant-color-text-secondary)} +.asset-tree-workspace{background:var(--ant-color-bg-container);display:flex;flex-direction:column;min-height:0}.asset-editor-toolbar{height:49px;min-height:49px;padding:0 16px;position:relative}.asset-editor-toolbar>div{gap:4px}.asset-tool-group,.asset-canvas-tools{display:flex;align-items:center}.asset-tool-button.ant-btn{width:34px;min-width:34px;height:32px;padding:0;border-radius:var(--ant-border-radius);color:var(--ant-color-text-secondary);font-size:var(--ant-font-size)}.asset-tool-button.ant-btn:not(:disabled){color:var(--ant-color-primary)}.asset-tool-button.ant-btn:hover:not(:disabled){color:var(--ant-color-primary-hover);background:var(--ant-color-bg-layout)}.asset-tool-button.primary.ant-btn{color:var(--ant-color-primary)}.asset-tool-divider{height:22px;border-left:1px solid var(--ant-color-border);margin:0 4px}.asset-view-switch{position:absolute;left:50%;transform:translateX(-50%);height:32px;border:1px solid var(--ant-color-border);display:flex!important;gap:0!important}.asset-view-switch button{width:38px;border:0;border-right:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);color:var(--ant-color-text-secondary);font-size:var(--ant-font-size)}.asset-view-switch button:last-child{border-right:0}.asset-view-switch button.active{color:var(--ant-color-primary);background:var(--ant-color-bg-layout)}.asset-tree-search{width:172px;height:30px;margin-left:8px;color:var(--ant-color-text-secondary)}.asset-tree-search input{font-size:var(--ant-font-size-sm)} +.asset-tree-canvas{flex:1;min-height:625px;padding:44px;overflow:auto;background:var(--ant-color-bg-layout);cursor:grab;touch-action:none;user-select:none}.asset-tree-canvas.dragging{cursor:grabbing}.asset-tree-stage{width:max-content;min-width:100%;min-height:100%;display:flex;align-items:center;justify-content:center;transform-origin:center center;transition:transform .12s ease}.dragging .asset-tree-stage{transition:none}.asset-node-tree{display:flex;flex-direction:column;justify-content:center;align-items:flex-start;gap:28px;min-width:max-content}.asset-tree-branch{display:flex;flex-direction:row;align-items:center;position:relative}.asset-node-card{width:174px;min-height:42px;grid-template-columns:24px 1fr 22px;grid-template-rows:1fr 1fr;padding:8px 8px;border:0;border-radius:var(--ant-border-radius);box-shadow:none;background:var(--ant-color-bg-container);cursor:pointer}.asset-node-card>span{font-size:var(--ant-font-size)}.asset-node-card>b{font-size:var(--ant-font-size-sm);font-weight:600;color:var(--ant-color-text-secondary)}.asset-node-card>small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.asset-node-card>button{grid-column:3;grid-row:1/3;align-self:center;justify-self:end;width:19px;height:19px;border:0;border-radius:50%;padding:0;background:var(--ant-color-text-disabled);color:var(--ant-color-text-light-solid);display:grid;place-items:center;font-size:var(--ant-font-size-sm)}.asset-node-card>button:hover{background:var(--ant-color-primary)}.asset-node-card:hover,.asset-node-card.selected{border:0;box-shadow:none}.asset-node-card.matched{box-shadow:none}.asset-tree-children{margin:0 0 0 36px;padding:0 0 0 36px;display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:16px;position:relative}.asset-tree-children:before{left:0;top:21px;bottom:21px;height:auto;border-left:1px solid var(--ant-color-primary)}.asset-tree-children>.asset-tree-branch:before{content:"";position:absolute;left:-34px;top:50%;width:34px;height:0;border-top:1px solid var(--ant-color-primary)}.asset-tree-children>.asset-tree-branch:not(:only-child):after{display:none}.asset-tree-branch>.asset-node-card+.asset-tree-children:after{content:"";position:absolute;left:-34px;top:50%;width:34px;border-top:1px solid var(--ant-color-primary)}.asset-tree-empty{margin:80px auto;color:var(--ant-color-text-secondary)}.asset-tree-empty b{font-weight:600} +.asset-node-list{flex:1;min-height:625px;overflow:auto;background:var(--ant-color-bg-container)}.asset-node-list-head,.asset-node-list>button{height:43px;display:grid;grid-template-columns:minmax(260px,1.5fr) 120px minmax(180px,1fr) 90px;align-items:center;text-align:left;border:0;border-bottom:1px solid var(--ant-color-border);padding:0 16px;background:var(--ant-color-bg-container);color:var(--ant-color-text-secondary)}.asset-node-list-head{height:40px;background:var(--ant-color-bg-layout);font-size:var(--ant-font-size-sm);font-weight:600;color:var(--ant-color-text-secondary)}.asset-node-list>button:hover,.asset-node-list>button.selected{background:var(--ant-color-bg-layout)}.asset-node-list>button.selected{box-shadow:none}.asset-node-list>button>span:first-child{color:var(--ant-color-text-base)} +@media(max-width:1100px){.asset-editor-workbench{grid-template-columns:210px minmax(660px,1fr)}.asset-editor-title span{display:none}.asset-tree-search{width:130px}.asset-zoom-value{display:none}} + +/* Asset 节点配置抽屉:对齐原资产设定的三 Tab 信息架构。 */ +.asset-node-drawer .ant-drawer-header{min-height:56px;padding:0 24px;border-bottom:1px solid var(--ant-color-border)}.asset-node-drawer .ant-drawer-title{font-size:var(--ant-font-size);font-weight:600;color:var(--ant-color-text-base)}.asset-node-drawer .ant-drawer-body{padding:0;overflow:auto}.asset-node-drawer .ant-drawer-footer{height:56px;padding:12px 24px;border-top:1px solid var(--ant-color-border);background:var(--ant-color-bg-container)}.node-drawer-footer{display:flex;justify-content:flex-end;align-items:center;gap:8px}.node-drawer-footer .button{margin:0} +.asset-node-drawer .node-drawer-tabs{height:49px;margin:0;padding-left:20px;gap:0;border-bottom:1px solid var(--ant-color-border)}.asset-node-drawer .node-drawer-tabs button{height:49px;padding:0 20px;border-right:1px solid var(--ant-color-border);border-bottom:3px solid transparent;color:var(--ant-color-text-secondary)}.asset-node-drawer .node-drawer-tabs button:first-child{padding-left:0;margin-right:20px}.asset-node-drawer .node-drawer-tabs button.active{color:var(--ant-color-text-secondary);border-bottom-color:var(--ant-color-primary)} +.node-config-page{padding:24px 24px 48px;display:flex;flex-direction:column;gap:40px}.node-config-section>h3{height:22px;line-height:22px;margin:0 0 24px;padding-left:16px;border-left:4px solid var(--ant-color-primary);font-size:var(--ant-font-size);font-weight:600;color:var(--ant-color-text-base)}.node-config-section>h4,.binding-parameter-head h4{margin:0 0 12px;font-size:var(--ant-font-size);color:var(--ant-color-text-secondary)}.node-id-row{display:grid;grid-template-columns:105px 1fr;align-items:center;max-width:420px;margin:0 0 20px 48px;color:var(--ant-color-text-secondary)}.node-id-row b{font-weight:400;color:var(--ant-color-text-secondary)}.node-basic-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px 36px}.node-basic-grid .field,.node-property-grid .field{display:grid;grid-template-columns:105px minmax(0,1fr);align-items:center;gap:12px}.node-basic-grid .field>span,.node-property-grid .field>span{font-size:var(--ant-font-size);font-weight:400;color:var(--ant-color-text-secondary);text-align:right}.node-basic-grid .field input,.node-basic-grid .field select,.node-property-grid .field input{width:100%;height:34px;padding:0 12px;border:1px solid var(--ant-color-border)}.node-basic-grid .field:nth-child(5){grid-column:1/-1}.node-image-row{display:flex;align-items:flex-start;gap:12px;margin-left:20px}.node-image-preview{width:108px;height:108px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-layout);display:grid;place-items:center;overflow:hidden;color:var(--ant-color-text-disabled);font-size:var(--ant-font-size-heading-2);cursor:pointer}.node-image-preview img{width:100%;height:100%;object-fit:contain}.node-image-row>div{display:flex;flex-direction:column;align-items:flex-start;gap:4px}.node-upload-link{color:var(--ant-color-primary);font-size:var(--ant-font-size);cursor:pointer}.node-image-row small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-disabled)}.node-image-row .text-button{margin:4px 0 0}.node-config-section .ant-qrcode{margin-left:20px;padding:0;background:var(--ant-color-bg-container)} +.node-property-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px 36px}.node-property-grid .field{min-width:0}.node-property-grid .field:nth-last-child(2){grid-column:auto}.node-property-grid input[type="date"]{color:var(--ant-color-text-secondary)} +.binding-page{gap:28px}.edge-component-table{border:1px solid var(--ant-color-border);max-height:200px;overflow:auto}.edge-component-table>header,.edge-component-table>div{min-height:45px;display:grid;grid-template-columns:1.2fr 1fr 1fr 1.2fr 88px;align-items:center;padding:0 8px;border-bottom:1px solid var(--ant-color-border)}.edge-component-table>header{min-height:38px;background:var(--ant-color-bg-layout);border-bottom:2px solid var(--ant-color-primary);font-size:var(--ant-font-size-sm);font-weight:600;color:var(--ant-color-text-secondary)}.edge-component-table>div:last-child{border-bottom:0}.edge-component-table>div.active{background:var(--ant-color-bg-layout)}.edge-component-table b{font-weight:400}.edge-component-table>div>span:last-child{display:flex;justify-content:flex-end;gap:8px}.edge-component-table button{width:28px;height:28px;border:0;background:transparent;color:var(--ant-color-primary);font-size:var(--ant-font-size)}.edge-component-table button:hover{background:var(--ant-color-bg-layout)}.binding-component-tabs{height:42px;display:flex;align-items:flex-end;justify-content:center;margin-bottom:12px}.binding-component-tabs button{height:34px;padding:0 20px;border:0;border-right:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);color:var(--ant-color-text-disabled)}.binding-component-tabs button:last-child{border-right:0}.binding-component-tabs button.active{color:var(--ant-color-primary);font-weight:600}.binding-parameter-head{display:flex;align-items:center;justify-content:space-between;border:1px solid var(--ant-color-border);border-bottom:0;padding:8px 12px}.binding-parameter-head h4{margin:0}.binding-parameter-head .button{height:30px;margin:0}.binding-parameter-table{border:1px solid var(--ant-color-border);overflow:auto}.binding-parameter-table>header,.binding-parameter-table>div:not(.binding-empty){min-width:760px;display:grid;grid-template-columns:1fr 1.2fr 70px 64px 1fr 1.2fr 42px;align-items:center;gap:8px;padding:0 8px}.binding-parameter-table>header{height:38px;background:var(--ant-color-bg-layout);border-bottom:2px solid var(--ant-color-primary);font-size:var(--ant-font-size-sm);font-weight:600}.binding-parameter-table>div:not(.binding-empty){min-height:44px;border-bottom:1px solid var(--ant-color-border)}.binding-parameter-table input{width:100%;height:30px;border:1px solid var(--ant-color-border);padding:0 8px}.binding-parameter-table .trash{color:var(--ant-color-error)}.binding-empty{height:120px;display:grid;place-items:center;color:var(--ant-color-text-secondary)}.binding-import-backdrop{z-index:1300}.binding-import-dialog{width:min(620px,calc(100vw - 48px))} +@media(max-width:1200px){.asset-node-drawer .ant-drawer-content-wrapper{width:78vw!important}.node-basic-grid,.node-property-grid{grid-template-columns:1fr}.node-basic-grid .field:nth-child(5){grid-column:auto}}@media(max-width:760px){.asset-node-drawer .ant-drawer-content-wrapper{width:100vw!important}.node-basic-grid .field,.node-property-grid .field{grid-template-columns:90px minmax(0,1fr)}.node-config-page{padding:20px 16px}.edge-component-table>header,.edge-component-table>div{grid-template-columns:1.2fr 1fr 1fr 72px}.edge-component-table>header>span:nth-child(4),.edge-component-table>div>span:nth-child(4){display:none}} + +/* 领域方案:从分步编辑调整为领域能力展示。 */ +.domain-showcase-page{display:flex;flex-direction:column;gap:16px}.domain-showcase-intro{min-height:92px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);border-top:3px solid var(--ant-color-primary);display:grid;grid-template-columns:150px 1fr auto;align-items:center;padding:16px 20px;gap:24px}.domain-showcase-intro>div:first-child{display:flex;align-items:baseline;gap:8px;color:var(--ant-color-text-secondary)}.domain-showcase-intro>div:first-child b{font-size:var(--ant-font-size-heading-2);color:var(--ant-color-text-base)}.domain-showcase-intro>p{margin:0;padding-left:24px;border-left:1px solid var(--ant-color-border);color:var(--ant-color-text-secondary);line-height:1.8}.domain-showcase-total{display:flex;gap:20px}.domain-showcase-total span{display:flex;flex-direction:column;gap:4px;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.domain-showcase-total b{color:var(--ant-color-text-base);font-size:var(--ant-font-size)}.domain-showcase-filter{height:52px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);display:flex;align-items:center;gap:12px;padding:12px 12px}.domain-showcase-filter label{width:300px;height:32px;border:1px solid var(--ant-color-border);display:flex;align-items:center;padding:0 12px;color:var(--ant-color-text-secondary)}.domain-showcase-filter label:focus-within{border-color:var(--ant-color-primary)}.domain-showcase-filter label .station-ui-input.ant-input{flex:1;min-width:0;width:auto;height:100%;border:0;outline:0;padding-left:8px}.domain-showcase-filter select{height:32px;min-width:180px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);padding:0 32px 0 12px}.domain-showcase-filter>span{margin-left:auto;color:var(--ant-color-text-secondary)}.domain-showcase-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}.domain-showcase-card{min-height:340px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);border-top:3px solid var(--ant-color-primary);padding:20px;display:flex;flex-direction:column;cursor:pointer;transition:box-shadow .15s,border-color .15s}.domain-showcase-card:hover{border-color:var(--ant-color-primary-bg);box-shadow:none}.domain-showcase-card.violet{border-top-color:var(--ant-color-primary)}.domain-showcase-card.green{border-top-color:var(--ant-color-success)}.domain-showcase-card.gray{border-top-color:var(--ant-color-border)}.domain-showcase-card>header{height:42px;display:flex;align-items:flex-start;justify-content:space-between}.domain-showcase-card>header>div:last-child{display:flex;align-items:center;gap:8px}.domain-showcase-mark{font-size:var(--ant-font-size-sm);font-weight:600;letter-spacing:1px;color:var(--ant-color-primary);background:var(--ant-color-bg-layout);padding:8px 8px}.violet .domain-showcase-mark{color:var(--ant-color-primary);background:var(--ant-color-bg-layout)}.green .domain-showcase-mark{color:var(--ant-color-success);background:var(--ant-color-bg-layout)}.gray .domain-showcase-mark{color:var(--ant-color-text-secondary);background:var(--ant-color-bg-layout)}.domain-showcase-card h2{font-size:var(--ant-font-size);margin:16px 0 8px;color:var(--ant-color-text-base)}.domain-showcase-card>p{height:44px;margin:0;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);line-height:1.75;overflow:hidden}.domain-showcase-card>img.domain-showcase-photo{display:block;width:100%;aspect-ratio:2/1;object-fit:cover;margin:10px 0 0;background:var(--ant-color-bg-layout)}.domain-showcase-capabilities{display:grid;grid-template-columns:1fr 1fr;margin-top:16px;border:1px solid var(--ant-color-border)}.domain-showcase-capabilities>span{min-height:62px;padding:12px;display:grid;grid-template-columns:22px 1fr;grid-template-rows:auto auto;align-items:center;border-right:1px solid var(--ant-color-border);border-bottom:1px solid var(--ant-color-border)}.domain-showcase-capabilities>span:nth-child(2n){border-right:0}.domain-showcase-capabilities>span:nth-last-child(-n+2){border-bottom:0}.domain-showcase-capabilities .anticon{grid-row:1/3;color:var(--ant-color-primary);font-size:var(--ant-font-size)}.domain-showcase-capabilities b{font-size:var(--ant-font-size-sm)}.domain-showcase-capabilities small{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.domain-showcase-card>footer{margin-top:auto;padding-top:16px;display:flex;align-items:center;justify-content:space-between;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.domain-showcase-card>footer button{height:30px;border:0;background:transparent;color:var(--ant-color-primary);padding:0;font-weight:600}.domain-showcase-card>footer button:hover{text-decoration:underline} + +.domain-capability-detail{display:flex;flex-direction:column;gap:12px}.domain-capability-back{align-self:flex-start;border:0;background:transparent;color:var(--ant-color-primary);padding:0;height:28px}.domain-capability-head{min-height:156px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);border-top:3px solid var(--ant-color-primary);padding:24px;display:grid;grid-template-columns:76px 1fr auto;gap:20px;align-items:center}.domain-capability-head.violet{border-top-color:var(--ant-color-primary)}.domain-capability-head.green{border-top-color:var(--ant-color-success)}.domain-capability-head.gray{border-top-color:var(--ant-color-border)}.domain-capability-code{width:76px;height:76px;display:grid;place-items:center;background:var(--ant-color-bg-layout);color:var(--ant-color-primary);font-weight:600;font-size:var(--ant-font-size-sm);letter-spacing:.8px}.domain-capability-head.violet .domain-capability-code{color:var(--ant-color-primary);background:var(--ant-color-bg-layout)}.domain-capability-head.green .domain-capability-code{color:var(--ant-color-success);background:var(--ant-color-bg-layout)}.domain-capability-head.gray .domain-capability-code{color:var(--ant-color-text-secondary);background:var(--ant-color-bg-layout)}.domain-capability-copy>div{display:flex;align-items:center;gap:8px}.domain-capability-copy>div>span:last-child{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.domain-capability-copy h2{margin:8px 0 4px;font-size:var(--ant-font-size-heading-3)}.domain-capability-copy p{margin:0;color:var(--ant-color-text-secondary);line-height:1.6}.domain-capability-copy small{display:block;margin-top:8px;color:var(--ant-color-text-secondary)}.domain-capability-actions{display:flex;align-items:center;gap:4px}.domain-capability-summary{height:66px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);display:grid;grid-template-columns:repeat(4,1fr)}.domain-capability-summary span{display:flex;align-items:baseline;justify-content:center;gap:8px;border-right:1px solid var(--ant-color-border);color:var(--ant-color-text-secondary)}.domain-capability-summary span:last-child{border-right:0}.domain-capability-summary b{font-size:var(--ant-font-size-heading-3);color:var(--ant-color-text-base)}.domain-capability-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.domain-capability-card{min-height:286px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);display:flex;flex-direction:column}.domain-capability-card>header{height:72px;padding:12px 16px;border-bottom:1px solid var(--ant-color-border);display:grid;grid-template-columns:38px 1fr auto;align-items:center;gap:12px}.domain-capability-icon{width:36px;height:36px;background:var(--ant-color-bg-layout);color:var(--ant-color-primary);display:grid;place-items:center;font-size:var(--ant-font-size-heading-4)}.domain-capability-card>header h3{margin:0 0 4px;font-size:var(--ant-font-size)}.domain-capability-card>header p{margin:0;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.domain-capability-card>header>strong{font-size:var(--ant-font-size-sm);font-weight:600;color:var(--ant-color-text-secondary);background:var(--ant-color-bg-layout);padding:4px 8px}.domain-capability-body{min-height:158px;padding:16px;background:var(--ant-color-bg-layout)}.domain-capability-card>footer{height:50px;margin-top:auto;border-top:1px solid var(--ant-color-border);display:flex;align-items:center;justify-content:flex-end;padding:0 12px;gap:8px}.domain-capability-card>footer button{height:29px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);color:var(--ant-color-text-secondary);padding:0 12px}.domain-capability-card>footer button:first-child{color:var(--ant-color-primary);border-color:var(--ant-color-primary-bg)}.domain-capability-card>footer button.capability-edit-button{margin-right:auto}.domain-capability-card>footer button:hover{border-color:var(--ant-color-primary);color:var(--ant-color-primary)}.capability-device-tags{display:flex;flex-wrap:wrap;gap:8px}.capability-device-tags span{height:28px;display:flex;align-items:center;gap:8px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);padding:0 8px;color:var(--ant-color-text-secondary)}.capability-device-tags b{min-width:18px;height:18px;line-height:18px;text-align:center;border-radius:var(--ant-border-radius);background:var(--ant-color-bg-layout);color:var(--ant-color-primary);font-size:var(--ant-font-size-sm)}.capability-mini-tree{margin-top:16px;height:62px;display:flex;align-items:center;position:relative;padding-left:4px}.capability-mini-tree>i{width:10px;height:10px;border:2px solid var(--ant-color-primary);border-radius:50%;margin-right:8px}.capability-mini-tree>b{background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);padding:8px 12px;font-size:var(--ant-font-size-sm)}.capability-mini-tree>span{position:relative;margin-left:28px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);padding:8px 8px;font-size:var(--ant-font-size-sm)}.capability-mini-tree>span:before{content:"";position:absolute;left:-29px;top:50%;width:28px;border-top:1px solid var(--ant-color-primary)}.capability-page-pair{display:grid;grid-template-columns:1fr 1fr;gap:16px;height:128px}.mini-dashboard,.mini-twin{position:relative;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-layout);padding:20px 8px 8px;display:grid;grid-template-columns:1.2fr .8fr;gap:4px}.mini-dashboard:before{content:"仪表板";position:absolute;left:8px;top:5px;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.mini-dashboard i{background:var(--ant-color-primary)}.mini-dashboard i:nth-child(2),.mini-dashboard i:nth-child(3){background:var(--ant-color-primary-bg)}.mini-twin{overflow:hidden;background:linear-gradient(160deg,var(--ant-color-bg-layout),var(--ant-color-bg-layout))}.mini-twin:before{content:"SC 数字孪生";position:absolute;left:8px;top:5px;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.mini-twin i{width:38px;height:27px;background:var(--ant-color-primary);transform:skewY(-18deg);align-self:end;box-shadow:none}.mini-twin span{position:absolute;right:7px;bottom:5px;color:var(--ant-color-primary);font-size:var(--ant-font-size-sm)}.capability-file-list{display:flex;flex-direction:column;gap:8px}.capability-file-list span{height:36px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);display:flex;align-items:center;padding:0 8px;color:var(--ant-color-text-secondary)}.capability-file-list b{width:24px;height:24px;background:var(--ant-color-bg-layout);color:var(--ant-color-primary);display:grid;place-items:center;margin-right:8px;font-size:var(--ant-font-size-sm)}.capability-menu-preview{width:180px;min-height:126px;background:var(--ant-color-bg-layout);border:1px solid var(--ant-color-border);display:flex;flex-direction:column;padding:8px;margin:auto}.capability-menu-preview>b{height:27px;background:var(--ant-color-bg-container);padding:8px 8px;font-size:var(--ant-font-size-sm)}.capability-menu-preview>span{height:22px;padding:4px 12px;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.capability-menu-preview>span:first-of-type{background:var(--ant-color-primary-bg);color:var(--ant-color-primary)} + +.domain-capability-grid{grid-template-columns:repeat(4,minmax(0,1fr))}.domain-capability-card{height:calc(100vh - 450px);min-height:500px;max-height:680px}.domain-capability-card>header{height:auto;min-height:82px;padding:12px 16px;grid-template-columns:38px minmax(0,1fr)}.domain-capability-card>header>strong{grid-column:1/-1;justify-self:end}.domain-capability-body.capability-empty-slot{flex:1;min-height:0;padding:0;background:var(--ant-color-bg-container)}.domain-capability-body.capability-asset-content,.domain-capability-body.capability-page-content,.domain-capability-body.capability-twin-content,.domain-capability-body.capability-knowledge-content{flex:1;min-height:0;padding:16px;background:var(--ant-color-bg-container);overflow-y:auto;scrollbar-gutter:stable}.capability-section-title{height:30px;display:flex;align-items:flex-start;justify-content:space-between;border-bottom:1px solid var(--ant-color-border);margin-bottom:12px}.capability-section-title b{font-size:var(--ant-font-size);font-weight:600;color:var(--ant-color-text-base)}.capability-section-title span{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.device-template-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(86px,1fr));gap:8px}.device-template-tile{aspect-ratio:1/1;min-height:88px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:8px;text-align:center;cursor:pointer;transition:border-color .15s,box-shadow .15s}.device-template-tile:hover{border-color:var(--ant-color-primary-bg);box-shadow:none}.device-template-tile>span{width:38px;height:38px;display:grid;place-items:center;background:var(--ant-color-bg-layout);color:var(--ant-color-primary);font-size:var(--ant-font-size-heading-4)}.device-template-tile>b{width:100%;font-size:var(--ant-font-size-sm);font-weight:600;color:var(--ant-color-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.extension-page-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.extension-page-tile{min-width:0;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);overflow:hidden}.extension-page-tile .dashboard-thumb-live{height:92px;min-height:92px;border:0;border-bottom:1px solid var(--ant-color-border);background:var(--ant-color-bg-layout)}.extension-page-tile>b{display:block;height:34px;line-height:34px;padding:0 8px;font-size:var(--ant-font-size-sm);font-weight:600;color:var(--ant-color-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.extension-page-tile:hover{border-color:var(--ant-color-primary-bg);box-shadow:none}.twin-scene-card-list{display:flex;flex-direction:column;gap:12px}.twin-scene-card{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);overflow:hidden}.twin-scene-card .sc-scene{height:145px}.twin-scene-card .sc-scene:after{height:72px;bottom:7px}.twin-scene-card .sc-scene i{transform:scale(.7);transform-origin:left bottom}.twin-scene-card>div:last-child{height:42px;display:flex;align-items:center;justify-content:space-between;padding:0 12px}.twin-scene-card b{font-size:var(--ant-font-size-sm);font-weight:600}.twin-scene-card small{font-size:var(--ant-font-size-sm);color:var(--ant-color-success);background:var(--ant-color-bg-layout);padding:4px 8px}.knowledge-group+.knowledge-group{margin-top:20px}.knowledge-item-list{display:flex;flex-direction:column;gap:8px}.knowledge-item{min-height:55px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);display:grid;grid-template-columns:38px minmax(0,1fr);align-items:center;gap:12px;padding:8px}.knowledge-type{width:34px;height:34px;display:grid;place-items:center;background:var(--ant-color-bg-layout);color:var(--ant-color-primary);font-size:var(--ant-font-size)}.knowledge-type.link{background:var(--ant-color-bg-layout);color:var(--ant-color-primary)}.knowledge-item>div{min-width:0;display:flex;flex-direction:column;gap:4px}.knowledge-item b{font-size:var(--ant-font-size-sm);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.knowledge-item small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.knowledge-item:hover{border-color:var(--ant-color-primary-bg)}.device-template-empty{min-height:150px;display:grid;place-items:center;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)} + +.capability-preview-modal{width:min(1040px,94vw);max-width:94vw}.capability-preview-modal>.modal-body{min-height:520px;padding:20px}.capability-assets-preview,.capability-knowledge-preview{display:grid;grid-template-columns:1.2fr .8fr;gap:16px}.capability-assets-preview>section,.capability-knowledge-preview>section{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);padding:16px}.capability-assets-preview h3,.capability-knowledge-preview h3{margin:0 0 12px;font-size:var(--ant-font-size)}.capability-full-tree{min-height:380px;background:var(--ant-color-bg-layout);padding:24px}.capability-full-tree>b{display:block;width:180px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);padding:12px 12px;margin-bottom:20px}.capability-full-tree>div{margin:0 0 12px 36px;border-left:1px solid var(--ant-color-primary);padding-left:24px;position:relative}.capability-full-tree>div:before{content:"";position:absolute;left:0;top:13px;width:20px;border-top:1px solid var(--ant-color-primary)}.capability-full-tree span{display:block;width:170px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);padding:8px 8px}.capability-full-tree small{display:block;margin:4px 0 0 12px;color:var(--ant-color-text-secondary)}.capability-preview-tabs{height:44px;display:flex;border-bottom:1px solid var(--ant-color-border);margin-bottom:16px}.capability-preview-tabs button{height:44px;border:0;border-bottom:3px solid transparent;background:var(--ant-color-bg-container);padding:0 20px;color:var(--ant-color-text-secondary)}.capability-preview-tabs button.active{color:var(--ant-color-primary);border-bottom-color:var(--ant-color-primary)}.capability-preview-tabs b{font-size:var(--ant-font-size-sm);background:var(--ant-color-bg-layout);padding:4px 8px;border-radius:var(--ant-border-radius);margin-left:4px}.capability-dashboard-grid,.capability-twin-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}.capability-dashboard-grid article,.capability-twin-grid article{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container)}.capability-dashboard-grid .dashboard-thumb-live{height:230px!important;min-height:230px;background:var(--ant-color-bg-layout)}.capability-dashboard-grid article>div:last-child,.capability-twin-grid article>div:last-child{padding:12px 12px;display:flex;flex-direction:column;gap:4px}.capability-dashboard-grid article span,.capability-twin-grid article span{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.sc-scene{height:230px;position:relative;overflow:hidden;background:linear-gradient(#edf5f7,#d9e5e8);perspective:500px}.sc-scene:after{content:"";position:absolute;left:8%;right:8%;bottom:18px;height:105px;background:linear-gradient(160deg,#b7cbd1,#eef4f5);transform:rotateX(58deg);border:1px solid #9fb7bf}.sc-scene i{position:absolute;z-index:2;width:75px;height:62px;background:#779aa5;border:1px solid #63828c;box-shadow:9px -9px #aec4ca}.sc-scene i:nth-child(1){left:20%;bottom:68px}.sc-scene i:nth-child(2){left:43%;bottom:86px;background:#7daeb9}.sc-scene i:nth-child(3){left:62%;bottom:57px;width:56px;height:76px}.sc-scene i:nth-child(4){left:76%;bottom:96px;width:40px;height:45px;background:#51a7c6}.sc-scene>span{position:absolute;z-index:3;right:12px;top:10px;background:#ffffffdd;color:#477783;padding:4px 8px;font-size:10px}.capability-knowledge-preview>section>div{height:58px;border-bottom:1px solid var(--ant-color-border);display:flex;align-items:center;gap:12px}.capability-knowledge-preview>section>div>svg{font-size:var(--ant-font-size-heading-4);color:var(--ant-color-primary)}.capability-knowledge-preview>section>div>span:last-child{display:flex;flex-direction:column;gap:4px}.capability-knowledge-preview small{color:var(--ant-color-text-secondary)}.file-type{width:38px;height:27px;display:grid!important;place-items:center;background:var(--ant-color-bg-layout);color:var(--ant-color-primary);font-size:var(--ant-font-size-sm)}.capability-menu-full{display:grid;grid-template-columns:230px 1fr;min-height:500px;border:1px solid var(--ant-color-border)}.capability-menu-full aside{background:var(--ant-color-bg-layout);border-right:1px solid var(--ant-color-border);padding:12px}.capability-menu-full aside>b{display:block;padding:12px 8px;border-bottom:1px solid var(--ant-color-border)}.capability-menu-full aside>div{display:flex;flex-direction:column}.capability-menu-full aside strong{padding:12px 8px;font-weight:600}.capability-menu-full aside span{padding:8px 24px;color:var(--ant-color-text-secondary)}.capability-menu-full aside>div:first-of-type strong{background:var(--ant-color-primary-bg);color:var(--ant-color-primary)}.capability-menu-full>section{background:var(--ant-color-bg-layout)}.menu-screen-title{height:48px;background:var(--ant-color-bg-container);border-bottom:1px solid var(--ant-color-border);padding:16px 20px;font-weight:600}.menu-screen-canvas{display:grid;grid-template-columns:1fr 1fr;gap:16px;padding:24px}.menu-screen-canvas i{height:170px;background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);box-shadow:none}.menu-screen-canvas i:nth-child(2){box-shadow:none}.menu-screen-canvas i:nth-child(3){box-shadow:none}.menu-screen-canvas i:nth-child(4){box-shadow:none} + +.domain-import-page{max-width:980px}.domain-import-layout{display:grid;grid-template-columns:1fr 1fr;gap:24px;padding:8px}.domain-import-drop{min-height:310px;border:1px dashed var(--ant-color-primary-bg);background:var(--ant-color-bg-layout);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;text-align:center;padding:28px;cursor:pointer}.domain-import-drop:hover,.domain-import-drop.selected{border-color:var(--ant-color-primary);background:var(--ant-color-bg-layout)}.domain-import-drop>svg{font-size:var(--ant-font-size-heading-2);color:var(--ant-color-primary)}.domain-import-drop>b{font-size:var(--ant-font-size)}.domain-import-drop>span{max-width:320px;color:var(--ant-color-text-secondary);line-height:1.7}.domain-import-form{display:flex;flex-direction:column;gap:16px}.domain-import-form .field input,.domain-import-form .field select,.domain-import-form .field textarea{width:100%}.domain-package-check{margin:20px 8px 0;padding:16px;background:var(--ant-color-bg-layout);display:flex;align-items:center;gap:8px}.domain-package-check>b{margin-right:12px}.domain-package-check>span{background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);padding:8px 8px;color:var(--ant-color-text-secondary)}.domain-import-actions{display:flex;justify-content:flex-end;margin:16px 0 4px}.domain-maintain-modal{width:min(720px,92vw)}.domain-maintain-note{margin-top:20px;padding:12px 16px;background:var(--ant-color-bg-layout);border-left:3px solid var(--ant-color-primary);color:var(--ant-color-text-secondary)}.capability-package-modal{width:min(660px,92vw)}.capability-package-modal>.modal-body>div{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:16px}.capability-package-modal>.modal-body>div>span{min-height:70px;border:1px solid var(--ant-color-border);padding:12px;display:grid;grid-template-columns:28px 1fr;grid-template-rows:auto auto;align-items:center}.capability-package-modal svg{grid-row:1/3;color:var(--ant-color-primary);font-size:var(--ant-font-size-heading-4)}.capability-package-modal small{color:var(--ant-color-text-secondary)} +@media(max-width:1320px){.domain-showcase-grid{grid-template-columns:1fr 1fr}.domain-showcase-intro{grid-template-columns:130px 1fr}.domain-showcase-total{grid-column:1/-1;border-top:1px solid var(--ant-color-border);padding-top:12px}.domain-capability-grid{grid-template-columns:1fr 1fr}.domain-capability-card{height:390px;min-height:0}.domain-capability-body.capability-empty-slot{min-height:0}.domain-capability-mini-tree>span:nth-last-child(n+4){display:none}} +@media(max-width:900px){.domain-showcase-grid,.domain-capability-grid,.capability-assets-preview,.capability-knowledge-preview,.domain-import-layout{grid-template-columns:1fr}.domain-showcase-intro{grid-template-columns:1fr}.domain-showcase-intro>p{padding:0;border:0}.domain-capability-head{grid-template-columns:62px 1fr}.domain-capability-code{width:62px;height:62px}.domain-capability-actions{grid-column:1/-1;justify-content:flex-end}.domain-capability-summary{grid-template-columns:1fr 1fr;height:auto}.domain-capability-summary span{min-height:55px;border-bottom:1px solid var(--ant-color-border)}.domain-capability-summary span:nth-child(2n){border-right:0}.capability-dashboard-grid,.capability-twin-grid{grid-template-columns:1fr}} +.capability-dashboard-grid article span,.capability-twin-grid article span{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;line-height:1.55} +@media(max-width:600px){.domain-showcase-filter{height:auto;flex-wrap:wrap}.domain-showcase-filter label,.domain-showcase-filter select{width:100%;min-width:0}.domain-showcase-filter>span{width:100%;text-align:right}.domain-capability-head{grid-template-columns:1fr;padding:16px}.domain-capability-code{width:auto;height:38px;justify-self:start;padding:0 12px}.domain-capability-actions{width:100%;flex-direction:column}.domain-capability-actions .button{width:100%;margin:0}.domain-capability-card>header{grid-template-columns:38px 1fr}.domain-capability-card>header>strong{grid-column:2}.capability-mini-tree>span:nth-of-type(n+2){display:none}.capability-menu-full{grid-template-columns:1fr}.capability-menu-full>section{display:none}.capability-package-modal>.modal-body>div{grid-template-columns:1fr}.domain-package-check{align-items:flex-start;flex-wrap:wrap}.capability-preview-modal>.modal-body{padding:12px}} + +/* 领域扩展仪表板管理:用领域下拉框替代分类树。 */ +.domain-dashboard-manager{display:flex;flex-direction:column;gap:12px}.dashboard-manager-panel{min-height:620px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container)}.dashboard-manager-toolbar{height:54px;border-bottom:1px solid var(--ant-color-border);display:grid;grid-template-columns:300px 1fr auto;align-items:center}.dashboard-manager-toolbar>label{height:100%;display:flex;align-items:center;gap:12px;padding:0 12px;border-right:1px solid var(--ant-color-border)}.dashboard-manager-toolbar>label span{font-weight:600;white-space:nowrap}.dashboard-manager-toolbar select{height:32px;min-width:190px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);padding:0 28px 0 8px}.dashboard-manager-toolbar>strong{padding-left:20px;font-size:var(--ant-font-size)}.dashboard-manager-actions{display:flex;align-items:center;gap:8px;padding-right:12px}.dashboard-manager-actions .button{margin:0;min-width:72px}.dashboard-manager-search{width:220px;height:32px;border:1px solid var(--ant-color-border);display:flex!important;align-items:center;gap:8px;padding:0 8px!important}.dashboard-manager-search input{width:100%;height:28px;border:0;outline:0}.dashboard-manager-grid{display:grid;grid-template-columns:repeat(2,minmax(280px,354px));gap:24px;padding:20px 24px;align-content:start}.dashboard-manager-grid article{height:124px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);background:var(--ant-color-bg-container);padding:16px 44px 12px 16px;position:relative}.dashboard-manager-grid h3{margin:0 0 12px;font-size:var(--ant-font-size);font-weight:600}.dashboard-manager-grid p{margin:0 0 8px;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.dashboard-card-more{position:absolute;right:8px;top:10px;width:30px;height:30px;border:0;background:transparent;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-heading-4)}.dashboard-card-more:hover{background:var(--ant-color-bg-layout);color:var(--ant-color-primary)} +@media(max-width:1100px){.dashboard-manager-toolbar{height:auto;grid-template-columns:1fr}.dashboard-manager-toolbar>label{height:50px;border-right:0;border-bottom:1px solid var(--ant-color-border)}.dashboard-manager-toolbar>strong{height:44px;display:flex;align-items:center;padding-left:12px}.dashboard-manager-actions{padding:0 12px 12px}.dashboard-manager-grid{grid-template-columns:1fr 1fr}}@media(max-width:720px){.dashboard-manager-actions{flex-wrap:wrap}.dashboard-manager-search{width:100%}.dashboard-manager-grid{grid-template-columns:1fr;padding:12px}} + +/* 仪表板资源页视觉密度:宽屏四列,等宽卡片,不保留分类树的空白。 */ +.dashboard-manager-panel{min-height:calc(100vh - 154px);background:var(--ant-color-bg-layout);border-color:var(--ant-color-border)}.dashboard-manager-toolbar{height:56px;grid-template-columns:286px 1fr;background:var(--ant-color-bg-container)}.dashboard-manager-toolbar>label{padding:0 16px;gap:12px}.dashboard-manager-toolbar>label span{font-size:var(--ant-font-size);font-weight:600;color:var(--ant-color-text-base)}.dashboard-manager-toolbar select{height:32px;min-width:176px;border-color:var(--ant-color-border);border-radius:var(--ant-border-radius);color:var(--ant-color-text-secondary)}.dashboard-manager-actions{justify-self:end;gap:8px;padding-right:12px}.dashboard-manager-actions .button{height:32px;min-width:72px;padding:0 12px;border-radius:var(--ant-border-radius);font-weight:600}.dashboard-manager-search{width:210px;height:32px;background:var(--ant-color-bg-container);border-color:var(--ant-color-border);border-radius:var(--ant-border-radius);color:var(--ant-color-text-secondary)}.dashboard-manager-grid{grid-template-columns:repeat(4,minmax(0,1fr));gap:20px 20px;padding:20px 20px;align-items:start}.dashboard-manager-grid article{width:auto;height:124px;border-color:var(--ant-color-border);border-radius:var(--ant-border-radius);padding:16px 44px 12px 16px;box-shadow:none;transition:border-color .15s,box-shadow .15s}.dashboard-manager-grid article:hover{border-color:var(--ant-color-primary-hover);box-shadow:none}.dashboard-manager-grid h3{margin:0 0 12px;font-size:var(--ant-font-size);font-weight:600;color:var(--ant-color-text-base);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dashboard-manager-grid p{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.dashboard-card-more{right:8px;top:9px;transform:rotate(90deg)}.dashboard-card-more:hover{background:transparent;color:var(--ant-color-primary)} +@media(max-width:1550px){.dashboard-manager-grid{grid-template-columns:repeat(3,minmax(0,1fr))}} +@media(max-width:1120px){.dashboard-manager-toolbar{height:auto;grid-template-columns:1fr}.dashboard-manager-toolbar>label{height:50px;border-right:0;border-bottom:1px solid var(--ant-color-border)}.dashboard-manager-actions{justify-self:stretch;padding:0 12px 12px}.dashboard-manager-grid{grid-template-columns:repeat(2,minmax(0,1fr))}} +@media(max-width:720px){.dashboard-manager-actions{flex-wrap:wrap}.dashboard-manager-search{width:100%}.dashboard-manager-grid{grid-template-columns:1fr;padding:12px}} diff --git a/src-vue/styles/site-workspace.css b/src-vue/styles/site-workspace.css new file mode 100644 index 0000000..03eba25 --- /dev/null +++ b/src-vue/styles/site-workspace.css @@ -0,0 +1,73 @@ +/* Station hierarchy and five-step configuration: company-style flat workspaces. */ +.station-application-settings{display:flex;flex-direction:column;gap:16px} +.station-application-basic,.station-application-menu{background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border)} +.station-application-basic>header,.station-application-menu>header{display:flex;align-items:center;justify-content:space-between;min-height:52px;padding:12px 20px;border-bottom:1px solid var(--ant-color-border);gap:16px} +.station-application-settings h2{font-size:var(--ant-font-size);font-weight:600;margin:0;color:var(--ant-color-text-base)} +.station-application-settings h2 small{font-size:var(--ant-font-size-sm);font-weight:400;color:var(--ant-color-text-secondary);margin-left:12px} +.station-application-fields{display:grid;grid-template-columns:minmax(240px,1.2fr) minmax(280px,1.6fr) minmax(180px,.75fr);gap:32px;padding:20px;align-items:center} +.station-application-fields>label,.station-application-icon{display:flex;align-items:center;gap:16px;min-width:0} +.station-application-fields>label>span,.station-application-icon>span{flex-shrink:0;min-width:56px;white-space:nowrap;color:var(--ant-color-text-secondary)} +.station-application-fields i:not(.station-application-scheme i),.station-menu-edit-fields>label>span>i{color:var(--ant-color-error);font-style:normal} +.station-application-name input{width:100%;min-width:0} +.station-application-settings input:not([type=file]),.station-application-settings select,.station-menu-edit-fields input{font:inherit;height:32px;min-width:0;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:4px 12px;background:var(--ant-color-bg-container)} +.station-icon-control{display:flex;align-items:center;gap:12px;min-width:0} +.station-icon-image{flex-shrink:0;width:40px;height:40px;border:1px solid var(--ant-color-border);display:flex;align-items:center;justify-content:center;background:var(--ant-color-bg-layout);color:var(--ant-color-primary);font-size:var(--ant-font-size-heading-3)} +.station-icon-image img{width:100%;height:100%;object-fit:contain} +.station-icon-upload{font-size:var(--ant-font-size);color:var(--ant-color-primary);cursor:pointer;white-space:nowrap;flex-shrink:0} +.station-icon-upload.disabled{opacity:.5;cursor:default} +.station-icon-file{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:200px} +.station-icon-control>.link{border:0;background:none;white-space:nowrap;font-size:var(--ant-font-size-sm);padding:0} +.station-application-scheme>div{display:flex;align-items:center;gap:12px;flex:1;min-width:0} +.station-application-scheme>div>i{width:20px;height:20px;flex-shrink:0;border:1px solid color-mix(in srgb,var(--ant-color-border) 7%,transparent)} +.station-application-scheme select{width:100%} +.station-application-menu-actions{display:flex;align-items:center;gap:8px;white-space:nowrap} +.station-application-menu-scroll{height:calc(100vh - 515px);min-height:240px;overflow:auto} +.station-application-menu-table{table-layout:fixed;width:100%;min-width:680px} +.station-application-menu-table thead{position:sticky;top:0;z-index:1} +.station-application-menu-table th:first-child{width:40%}.station-application-menu-table th:nth-child(2){width:30%}.station-application-menu-table th:nth-child(3){width:18%}.station-application-menu-table th:last-child{width:120px} +.station-application-menu-table td{height:48px;padding:8px 16px;font-size:var(--ant-font-size)}.station-application-menu-table th{font-size:var(--ant-font-size);font-weight:600} +.station-application-menu-table tr.station-menu-group-row td{background:var(--ant-color-bg-layout);color:var(--ant-color-text-base)} +.station-menu-name{display:flex;align-items:center;gap:8px;min-width:0} +.station-menu-name>span:not(.station-menu-child-guide){white-space:nowrap;overflow:hidden;text-overflow:ellipsis} +.station-menu-name small{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);flex-shrink:0;font-weight:400} +.station-menu-disclosure{flex-shrink:0;border:0;background:none;width:16px;padding:0;color:var(--ant-color-text-secondary);cursor:pointer} +.station-menu-child-guide{width:16px;flex-shrink:0;align-self:stretch;position:relative} +.station-menu-child-guide:before{content:"";position:absolute;left:3px;top:3px;width:8px;height:9px;border-left:1px solid var(--ant-color-border);border-bottom:1px solid var(--ant-color-border)} +.station-menu-association{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ant-color-text-secondary)} +.station-application-settings .station-menu-row-actions .ant-btn{color:var(--ant-color-primary)}.station-application-settings .station-menu-row-actions .ant-btn:disabled{color:var(--ant-color-text-disabled)} +.station-application-menu-note{padding:12px 20px;display:flex;justify-content:space-between;gap:16px;border-top:1px solid var(--ant-color-border);font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)} +.station-menu-edit-fields{display:grid;gap:24px;padding-top:12px}.station-menu-edit-fields>label{display:grid;grid-template-columns:80px minmax(0,1fr);gap:16px;align-items:center}.station-menu-edit-fields>label>span{text-align:right;color:var(--ant-color-text-secondary)}.station-menu-edit-fields input[readonly]{background:var(--ant-color-bg-layout);color:var(--ant-color-text-secondary)} +.station-application-preview{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);min-height:calc(100vh - 150px)} +.station-application-preview>header{display:flex;align-items:center;gap:12px;border-top:3px solid var(--application-color);border-bottom:1px solid var(--ant-color-border);padding:16px;font-size:var(--ant-font-size)} +.station-application-preview>header img{height:36px;width:36px;object-fit:contain}.station-application-preview>header>.anticon{font-size:var(--ant-font-size-heading-3);color:var(--application-color)}.station-application-preview strong{font-weight:600} +.station-application-preview nav{padding:8px 0}.station-application-preview nav>button{display:flex;align-items:center;justify-content:space-between;width:100%;border:0;background:var(--ant-color-bg-container);padding:16px 20px;font:inherit;text-align:left;color:var(--ant-color-text-base);cursor:pointer} +.station-application-preview nav>button.group{background:var(--ant-color-bg-layout);font-size:var(--ant-font-size)}.station-application-preview nav>button.page.active{background:color-mix(in srgb,var(--application-color) 14%,var(--ant-color-bg-container));color:var(--application-color);border-left:3px solid var(--application-color)} +.station-menu-preview-current{display:flex;flex-direction:column;gap:12px;border-top:1px solid var(--ant-color-border);padding:20px;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.station-menu-preview-current b{font-size:var(--ant-font-size);font-weight:600;color:var(--ant-color-text-base)} +@media(max-width:1400px){.station-application-fields{gap:16px;grid-template-columns:minmax(210px,1.1fr) minmax(220px,1.2fr) minmax(150px,.75fr)}.station-icon-file{display:none}.station-application-menu-note>span:last-child{display:none}} +@media(max-width:1050px){.station-application-fields{grid-template-columns:1fr;gap:20px}.station-application-fields>label>span,.station-application-icon>span{width:70px}.station-application-name input{max-width:450px}.station-application-scheme>div{max-width:260px}} +.station-menu-configuration .station-menu-editor-table th:first-child{width:32%;white-space:nowrap}.station-menu-configuration .station-menu-editor-table th:nth-child(2){width:28%}.station-menu-configuration .station-menu-editor-table th:nth-child(3){width:20%}.station-menu-configuration .station-menu-editor-table th:last-child{width:110px;white-space:nowrap}.station-menu-configuration .station-menu-editor-table th,.station-menu-configuration .station-menu-editor-table td{font-size:var(--ant-font-size)} +@media(max-width:1400px){.station-menu-configuration .station-menu-live-preview{display:block;grid-column:1/-1;border-left:0;border-top:1px solid var(--ant-color-border);max-height:220px;overflow:auto}.station-menu-configuration .station-menu-live-preview nav{display:flex;flex-wrap:wrap}.station-menu-configuration .station-menu-live-preview nav>div{min-width:150px}} +.station-page-selection .station-module-grid{max-height:440px;overflow:auto}.station-page-selection .station-module-grid>section>div{grid-template-columns:repeat(2,minmax(0,1fr))}.station-page-selection .station-module-grid>section>div>label{font-size:var(--ant-font-size-sm)} +.station-hierarchy-workspace .station-hierarchy-table{min-width:1100px;table-layout:fixed} +.station-hierarchy-workspace .station-hierarchy-table th:first-child,.station-hierarchy-workspace .station-hierarchy-table td:first-child{width:28%;overflow:hidden} +.station-hierarchy-workspace .station-hierarchy-table th:nth-child(2){width:14%}.station-hierarchy-workspace .station-hierarchy-table th:nth-child(3){width:17%}.station-hierarchy-workspace .station-hierarchy-table th:nth-child(4){width:10%}.station-hierarchy-workspace .station-hierarchy-table th:nth-child(5){width:6%}.station-hierarchy-workspace .station-hierarchy-table th:nth-child(6){width:15%}.station-hierarchy-workspace .station-hierarchy-table th:last-child,.station-hierarchy-workspace .station-hierarchy-table td:last-child{width:130px} +.station-hierarchy-workspace .station-name-cell>.link{white-space:nowrap;overflow:hidden;text-overflow:ellipsis} +.station-hierarchy-workspace,.station-page-selection,.station-menu-configuration{font-size:var(--ant-font-size);color:var(--ant-color-text-base);min-width:0} +.station-list-panel,.station-template-panel,.station-page-module-panel,.station-menu-panel,.station-menu-app-info{background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border)} +.station-list-panel{min-height:calc(100vh - 260px);display:flex;flex-direction:column} +.station-hierarchy-note{display:flex;align-items:center;gap:12px;padding:16px;border-bottom:1px solid var(--ant-color-border);color:var(--ant-color-text-secondary);background:var(--ant-color-bg-layout)} +.station-hierarchy-note>.anticon{color:var(--ant-color-primary)}.station-hierarchy-note>span:last-child{margin-left:auto;white-space:nowrap} +.station-list-toolbar{display:flex;gap:12px;align-items:center;padding:16px}.station-list-toolbar>div{margin-left:auto;display:flex;gap:8px} +.station-search{display:flex;align-items:center;gap:8px;height:32px;width:260px;border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);padding:0 12px;background:var(--ant-color-bg-container);color:var(--ant-color-text-secondary)}.station-search input{border:0!important;outline:0;width:100%;height:28px;background:transparent} +.station-list-toolbar select,.station-basic-fields select,.station-basic-fields input,.station-basic-fields textarea,.station-create-template>select,.station-template-filter select,.station-menu-app-info input,.station-menu-editor-table input,.station-menu-editor-table select{border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);background:var(--ant-color-bg-container);padding:4px 12px;min-height:32px;font:inherit} +.station-list-toolbar select{width:190px}.station-table-scroll{overflow:auto;flex:1}.station-hierarchy-table th:first-child{width:29%}.station-hierarchy-table th:nth-child(3){width:19%}.station-hierarchy-table td{height:54px}.station-hierarchy-table th{white-space:nowrap}.station-name-cell{display:flex;align-items:center;gap:8px;min-width:210px}.station-name-cell>button:first-child:not(.link){border:0;background:none;width:18px;padding:0}.station-tree-spacer{width:18px}.station-name-cell small{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);border:1px solid var(--ant-color-border);padding:0 4px}.station-template-name{display:block}.station-pending-template{display:block;font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.station-table-actions{display:flex;align-items:center;white-space:nowrap} +.station-drawer-actions{display:flex;justify-content:flex-end;gap:8px}.station-drawer-note{padding:12px;background:var(--ant-color-bg-layout);color:var(--ant-color-text-secondary);margin:0 0 24px}.station-basic-fields{display:grid;gap:20px}.station-basic-fields>label{display:grid;grid-template-columns:100px 1fr;gap:12px;align-items:start}.station-basic-fields>label>span{padding-top:8px;text-align:right}.station-basic-fields i{color:var(--ant-color-error);font-style:normal}.station-basic-fields textarea{resize:vertical}.station-create-template{margin-top:32px;border-top:1px solid var(--ant-color-border);padding-top:16px}.station-create-template h3{font-size:var(--ant-font-size);font-weight:600}.station-template-modes{display:flex;gap:24px;margin-bottom:16px}.station-template-modes input{accent-color:var(--ant-color-primary)}.station-create-template>select{width:100%}.station-selected-template{padding:16px;border:1px solid var(--ant-color-primary-bg);background:var(--ant-color-bg-layout);margin-top:16px}.station-selected-template p,.station-template-footnote{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);line-height:1.7}.station-selected-template span{color:var(--ant-color-text-secondary)} +.station-config-context{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;padding:12px 16px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);font-size:var(--ant-font-size-sm)}.station-config-context>div{display:flex;align-items:center;gap:12px}.station-context-divider{height:16px;border-left:1px solid var(--ant-color-border)}.station-config-context>div:last-child>span{color:var(--ant-color-text-secondary)}.station-config-context .ant-tag{margin:0} +.station-template-panel{border-top:3px solid var(--ant-color-primary);margin-bottom:16px}.station-template-panel>header,.station-page-module-panel>header,.station-menu-panel>header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:20px 20px;border-bottom:1px solid var(--ant-color-border)}.station-template-panel h2,.station-page-module-panel h2,.station-menu-panel h2{font-size:var(--ant-font-size);font-weight:600;margin:0 0 8px}.station-template-panel>header p,.station-page-module-panel>header p,.station-menu-panel>header p{margin:0;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.station-template-panel>header>div:last-child,.station-menu-panel>header>div:last-child{display:flex;gap:8px;white-space:nowrap} +.station-template-filter{display:flex;align-items:center;gap:12px;padding:16px 20px;color:var(--ant-color-text-secondary)}.station-template-filter>span:last-child{margin-left:auto;font-size:var(--ant-font-size-sm)}.station-template-filter select{width:200px}.station-template-cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;padding:0 20px 20px;max-height:300px;overflow:auto}.station-template-cards>button{border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);text-align:left;padding:16px;min-width:0}.station-template-cards>button.selected{border-color:var(--ant-color-primary);background:var(--ant-color-bg-layout)}.station-template-cards>button>div{display:flex;align-items:center;gap:8px;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.station-template-cards .anticon{margin-left:auto;color:var(--ant-color-primary)}.station-template-cards h3{font-size:var(--ant-font-size);font-weight:600;margin:16px 0 8px}.station-template-cards p{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);height:34px;overflow:hidden;margin:0 0 16px}.station-template-cards footer{display:flex;gap:24px;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.station-template-cards footer b{color:var(--ant-color-text-base)}.station-template-empty{padding:28px;text-align:center;color:var(--ant-color-text-secondary)} +.station-overview-layout .form-section-nav{display:none}.station-overview-layout .company-form-page{display:block}.station-overview-layout .single-column-form{max-width:none}.station-overview-layout .company-form-page>.single-column-form{width:100%}.station-opsflow-blank{background:var(--ant-color-bg-container);border:1px solid var(--ant-color-border);min-height:calc(100vh - 342px)} +.station-unified-assets .asset-editor-workbench{height:calc(100vh - 390px);min-height:430px;grid-template-columns:220px minmax(0,1fr)}.station-unified-assets .asset-tree-canvas{min-height:0;height:calc(100% - 52px);overflow:auto}.station-unified-assets .asset-template-panel{max-height:calc(100vh - 575px);min-height:220px;overflow:auto}.station-unified-assets .asset-editor-toolbar{gap:8px;padding:0 8px}.station-unified-assets .asset-editor-toolbar>div{gap:4px}.station-unified-assets .asset-tree-search{width:160px}.station-unified-assets .asset-node-list{max-height:calc(100vh - 445px);overflow:auto} +.station-page-selection{display:flex;flex-direction:column;gap:16px}.station-selection-summary{display:flex;gap:28px;border-bottom:1px solid var(--ant-color-border);padding:12px 20px;color:var(--ant-color-text-secondary);background:var(--ant-color-bg-layout)}.station-selection-summary>span:last-child{margin-left:auto;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.station-module-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;padding:20px}.station-module-grid>section{border:1px solid var(--ant-color-border)}.station-module-grid>section>header{display:flex;justify-content:space-between;padding:12px;background:var(--ant-color-bg-layout);border-bottom:1px solid var(--ant-color-border)}.station-module-grid>section>header span{color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm)}.station-module-grid label{display:flex;gap:8px;align-items:center}.station-module-grid>section>div{display:grid;gap:12px;padding:16px;max-height:210px;overflow:auto}.station-page-selection input[type=checkbox]{accent-color:var(--ant-color-primary)} +.station-dashboard-selection{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px;padding:20px}.station-dashboard-selection article,.station-twin-selection article{border:1px solid var(--ant-color-border);min-width:0}.station-dashboard-image{display:block;width:100%;height:145px;padding:0;border:0;overflow:hidden;background:var(--ant-color-bg-layout);cursor:pointer;text-align:left;font:inherit}.station-dashboard-image:focus-visible{outline:2px solid var(--ant-color-primary);outline-offset:-2px}.station-dashboard-selection article.selected{border-color:var(--ant-color-primary)}.station-dashboard-selection article.selected footer{background:var(--ant-color-bg-layout)}.station-dashboard-image>div{height:100%}.station-dashboard-selection footer,.station-twin-selection footer{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-top:1px solid var(--ant-color-border)}.station-dashboard-selection footer label,.station-twin-selection footer label{display:flex;align-items:center;gap:8px}.station-twin-selection{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px;padding:20px}.station-twin-selection small{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)}.station-scene-thumb{height:145px;background:#edf4f6;position:relative;overflow:hidden}.station-scene-thumb>span{position:absolute;right:10px;top:10px;font-size:11px;color:#65909e}.station-scene-thumb>div{position:absolute;left:10%;right:10%;bottom:20px;height:45px;background:#d0e0e5;transform:skew(-20deg);border:1px solid #a5c3ce}.station-scene-thumb i{position:absolute;width:45px;height:43px;bottom:54px;background:#7ba8b6;border:1px solid #608a97;box-shadow:5px -5px #bfd2d9;z-index:1}.station-scene-thumb i:nth-of-type(1){left:18%}.station-scene-thumb i:nth-of-type(2){left:40%;bottom:70px}.station-scene-thumb i:nth-of-type(3){left:64%}.station-scene-thumb i:nth-of-type(4){left:80%;width:22px;height:28px;bottom:78px} +.station-menu-app-info{padding:16px 20px;margin-bottom:16px;display:flex;align-items:center;gap:20px}.station-menu-app-info label{display:flex;align-items:center;gap:16px}.station-menu-app-info input{width:300px}.station-menu-app-info p{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary);margin:0}.station-menu-workbench{display:grid;grid-template-columns:250px minmax(0,1fr) 220px;min-height:calc(100vh - 480px)}.station-menu-workbench>aside{background:var(--ant-color-bg-layout)}.station-menu-source{border-right:1px solid var(--ant-color-border);padding:16px}.station-menu-workbench h3{font-size:var(--ant-font-size);font-weight:600;margin:0 0 16px}.station-menu-workbench h3 small{color:var(--ant-color-text-secondary);float:right}.station-menu-source .station-search{width:100%;margin-bottom:16px}.station-menu-source>div{max-height:calc(100vh - 585px);min-height:230px;overflow:auto}.station-menu-source>div>button{display:flex;align-items:center;justify-content:space-between;width:100%;padding:12px 8px;margin-bottom:8px;border:1px solid var(--ant-color-border);background:var(--ant-color-bg-container);text-align:left}.station-menu-source b{font-size:var(--ant-font-size-sm);font-weight:400}.station-menu-source small{display:block;color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);margin-top:4px}.station-menu-source .anticon{color:var(--ant-color-primary)}.station-menu-source button:disabled{opacity:.5;cursor:default}.station-menu-editor-table{overflow:auto;max-height:calc(100vh - 445px)}.station-menu-editor-table .data-table{min-width:520px}.station-menu-editor-table td{padding:12px}.station-menu-editor-table input,.station-menu-editor-table select{width:100%}.station-menu-row-actions{display:flex;gap:0}.station-menu-row-actions .ant-btn{width:28px}.station-menu-live-preview{border-left:1px solid var(--ant-color-border);padding:16px 0}.station-menu-live-preview h3{padding:0 16px}.station-menu-live-preview>b{display:block;padding:16px;background:var(--ant-color-bg-layout);font-size:var(--ant-font-size);font-weight:600}.station-menu-live-preview nav>div{padding:16px;font-size:var(--ant-font-size)}.station-menu-live-preview nav>.group{background:var(--ant-color-bg-layout)}.station-menu-live-preview nav>.page{color:var(--ant-color-primary)}.station-menu-live-preview .anticon{float:right}.station-menu-empty{padding:60px 16px;color:var(--ant-color-text-secondary);text-align:center}.station-warning{color:var(--ant-color-error);background:var(--ant-color-bg-layout);padding:16px}.station-replace-confirm{max-width:520px} +@media(max-width:1400px){.station-menu-workbench{grid-template-columns:220px minmax(0,1fr)}.station-menu-live-preview{display:none}.station-hierarchy-note>span:last-child{display:none}.station-module-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.station-dashboard-selection,.station-twin-selection{grid-template-columns:repeat(3,minmax(0,1fr))}.station-unified-assets .asset-tree-search{width:120px}.station-template-cards{grid-template-columns:repeat(2,minmax(0,1fr))}} diff --git a/src-vue/styles/styles.less b/src-vue/styles/styles.less new file mode 100644 index 0000000..d9668db --- /dev/null +++ b/src-vue/styles/styles.less @@ -0,0 +1,51 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: var(--ant-font-family); + background: var(--ant-color-bg-layout); + color: var(--ant-color-text-base); +} + +#root { + min-height: 100vh; +} + +/* ===== 整体布局 ===== */ +// Header 高度(含 8px 顶部渐变条),同时也是内容区的避让量 +@header-height: 56px; + +.page { + display: flex; + flex-direction: column; + min-height: 100vh; + padding-top: @header-height; + + // 左右两栏:宽度全部交给 flex,不写死 calc + .body { + display: flex; + flex: 1 1 auto; + align-items: stretch; + } + + // 左栏宽度由 SideMenu 自身决定(展开 316px / 折叠 72px),随整页一起滚动 + .left-menu { + flex: 0 0 auto; + } + + /* 注:#ededed 暂无对应 antd token(colorBgLayout 已被覆盖为 #fafafa,与此值不同) */ + .main { + // flex:1 自动占满剩余宽度;min-width:0 允许收缩,避免内部宽内容把布局撑破 + flex: 1 1 auto; + min-width: 0; + padding: 8px 0 0; + background: #ededed; + + .page-header { + padding: 0 24px; + } + } +} diff --git a/src-vue/styles/theme-overrides.css b/src-vue/styles/theme-overrides.css new file mode 100644 index 0000000..6ac07e3 --- /dev/null +++ b/src-vue/styles/theme-overrides.css @@ -0,0 +1,47 @@ +/* ============================================================ + * overrides.css — L0 设计覆盖 + * + * 只放 antd token 表达不了的东西: + * - 渐变(token 只能设单一颜色) + * - 多层阴影 + * - 同一组件内不同部位要不同值(如表头 vs 表体) + * + * 能用 token 表达的一律写进 src/theme.json。 + * 消费品牌值一律用 var(--ant-*),不要硬编码。 + * ============================================================ */ + +/* ── Menu:hover / 选中的渐变背景 ── + * 载体在 src/components/menu/index.less(需覆盖 inline 与 portal 两种 DOM),此处不重复。 + */ + +/* ── Select 下拉 ── + * 注意:Select 没有 dropdownPadding / boxShadow 组件 token, + * 写 --ant-select-dropdown-padding / --ant-select-box-shadow 是空操作,必须用真实声明。 + */ +.ant-select-dropdown { + padding: 8px 0; + border: 1px solid var(--ant-color-primary); + box-shadow: 0 2px 8px 0 rgba(50, 50, 51, 0.2); +} + +.ant-select.ant-select-focused { + box-shadow: 0 2px 8px 0 rgba(50, 50, 51, 0.2); +} + +/* 选项 hover 渐变(渐变 token 表达不了) */ +.ant-select-dropdown .ant-select-item:hover, +.ant-select-dropdown .ant-select-item-option-active { + background: linear-gradient( + 180deg, + rgba(0, 140, 214, 0.10) 0%, + rgba(0, 110, 255, 0.10) 100% + ), #FFF !important; +} + +/* ── Table:表头与表体内边距不同 ── + * cellPaddingBlock 作用于所有单元格(已设 8),表头要 12, + * token 区分不了表头/表体,只能用变量。 + */ +.ant-table .ant-table-thead > tr > th { + --ant-table-cell-padding-block: 12px; +} diff --git a/src-vue/styles/theme.json b/src-vue/styles/theme.json new file mode 100644 index 0000000..c92f030 --- /dev/null +++ b/src-vue/styles/theme.json @@ -0,0 +1,62 @@ +{ + "token": { + "colorPrimary": "#008cd6", + "colorInfo": "#008cd6", + "colorSuccess": "#00cc66", + "colorError": "#f55d3e", + "colorWarning": "#ffa400", + "colorTextBase": "#323233", + "colorBgLayout": "#fafafa", + "fontSize": 16, + "borderRadius": 4, + "fontFamily": "'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif", + "fontFamilyCode": "\"Roboto\", \"Oxygen\", \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\", sans-serif" + }, + "components": { + "Table": { + "borderColor": "rgb(225,225,225)", + "headerColor": "rgb(50,50,51)", + "footerColor": "rgb(50,50,51)", + "rowHoverBg": "rgb(230,242,254)", + "rowSelectedBg": "rgb(230,242,254)", + "cellPaddingBlock": 8 + }, + "Button": { + "defaultActiveBorderColor": "rgb(0,140,214)", + "defaultActiveColor": "rgb(0,140,214)", + "defaultBorderColor": "rgb(200,200,200)", + "defaultColor": "rgb(137,137,138)", + "defaultHoverBorderColor": "rgb(137,137,138)", + "defaultHoverColor": "rgb(50,50,51)", + "defaultActiveBg": "rgb(229,243,252)", + "fontWeight": 600 + }, + "Switch": { + "handleSize": 12, + "trackHeight": 16, + "trackMinWidth": 24, + "trackPadding": 2, + "innerMaxMargin": 16 + }, + "Menu": { + "itemColor": "rgb(50,50,51)", + "itemHoverColor": "rgb(50,50,51)", + "subMenuItemBg": "rgb(255,255,255)", + "subMenuItemBorderRadius": 0, + "itemBorderRadius": 0 + }, + "Breadcrumb": { + "itemColor": "rgb(137,137,138)", + "lastItemColor": "rgb(137,137,138)", + "linkColor": "rgb(137,137,138)", + "linkHoverColor": "rgb(0,140,214)", + "separatorColor": "rgb(192,192,192)" + }, + "Select": { + "optionActiveBg": "rgb(229,242,253)", + "optionSelectedBg": "rgb(229,242,253)", + "optionSelectedColor": "rgb(0,140,214)", + "optionPadding": "8px 12px" + } + } +} diff --git a/src-vue/styles/ui-layout-compat.css b/src-vue/styles/ui-layout-compat.css new file mode 100644 index 0000000..c717ac4 --- /dev/null +++ b/src-vue/styles/ui-layout-compat.css @@ -0,0 +1,130 @@ +/* Layout-only compatibility for existing custom antd button surfaces. + * Preserves approved navigation, thumbnail and canvas sizing, including responsive rules. + * Branding and states remain owned by theme.json and ui-system.css. */ +.side-nav>button.station-ui-button.ant-btn{height:41px;border:0;text-align:left;padding:0 16px;display:flex;align-items:center;gap:12px;} +.side-nav>button.station-ui-button.ant-btn b{width:18px;text-align:center;} +.side-nav>button.station-ui-button.ant-btn em{width:21px;height:21px;border:1px solid var(--ant-color-border);border-radius:50%;display:grid;} +.steps button.station-ui-button.ant-btn{border:0;display:flex;align-items:center;position:relative;text-align:left;padding:0 20px;} +.steps button.station-ui-button.ant-btn>i{width:29px;height:29px;border-radius:50%;border:1px solid var(--ant-color-border);display:grid;margin-right:12px;} +.steps button.station-ui-button.ant-btn span{display:flex;flex-direction:column;gap:4px;} +.steps button.station-ui-button.ant-btn>b{position:absolute;right:0;} +.view-switch button.station-ui-button.ant-btn{width:31px;height:29px;border:1px solid var(--ant-color-border);} +.link.station-ui-button.ant-btn{border:0;padding:0;} +.trash.station-ui-button.ant-btn{border:0;} +.pagination button.station-ui-button.ant-btn{width:28px;height:28px;border:0;} +.tabs button.station-ui-button.ant-btn{padding:0 20px;border:0;} +.mu-grid button.station-ui-button.ant-btn{border:0;padding:0;} +.menu-tree>button.station-ui-button.ant-btn{border:1px dashed var(--ant-color-border);width:100%;height:34px;} +.menu-preview button.station-ui-button.ant-btn{border:0;text-align:left;padding:12px;} +.confirm-grid button.station-ui-button.ant-btn{position:static;border:0;margin:0;} +.text-button.station-ui-button.ant-btn{border:0;margin-top:12px;} +.preview-toolbar button.station-ui-button.ant-btn{border:1px solid var(--ant-color-border);height:29px;padding:0 12px;} +.cube-side button.station-ui-button.ant-btn{height:37px;border:0;text-align:left;padding-left:12px;} +.cube-grid h3 button.station-ui-button.ant-btn{border:0;} +.inspector>nav button.station-ui-button.ant-btn{flex:1;border:0;} +.code-body header button.station-ui-button.ant-btn{border:0;} +.modal>header button.station-ui-button.ant-btn{border:0;} +.history-list button.station-ui-button.ant-btn{border:0;} +.module-switch>button.station-ui-button.ant-btn{height:47px;border:1px solid var(--ant-color-border);display:flex;align-items:center;text-align:left;padding:0 8px;gap:8px;} +.module-switch>button.station-ui-button.ant-btn>b{width:23px;height:23px;display:grid;} +.module-switch>button.station-ui-button.ant-btn>span{display:flex;flex-direction:column;gap:4px;} +.domain-grid footer button.station-ui-button.ant-btn{border:0;} +.domain-grid footer button.station-ui-button.ant-btn:last-child{border:1px solid var(--ant-color-primary-bg);padding:4px 8px;} +.domain-page-list footer button.station-ui-button.ant-btn{border:0;padding:0;margin-right:12px;} +.knowledge-list button.station-ui-button.ant-btn{border:0;} +.model-list>button.station-ui-button.ant-btn{width:100%;min-height:56px;border:0;border-radius:var(--ant-border-radius);display:flex;align-items:center;padding:8px 8px;text-align:left;position:relative;} +.model-list>button.station-ui-button.ant-btn>i{width:25px;} +.model-list>button.station-ui-button.ant-btn>span{display:flex;flex:1;flex-direction:column;gap:4px;} +.model-list>button.station-ui-button.ant-btn>strong{margin-right:24px;} +.model-list>button.station-ui-button.ant-btn>u{position:absolute;right:9px;} +.wordbuddy-card>footer button.station-ui-button.ant-btn{border:0;} +.ai-fab.station-ui-button.ant-btn{position:fixed;right:22px;bottom:22px;width:54px;height:54px;border-radius:50%;border:0;display:grid;} +.ai-dialog .ai-close.station-ui-button.ant-btn{border:0;line-height:1;width:28px;height:28px;border-radius:var(--ant-border-radius);} +.data-table.editable .trash.station-ui-button.ant-btn{border:0;line-height:1;} +.data-table.editable .asset-eye-btn.station-ui-button.ant-btn{border:0;line-height:1;padding:0;display:inline-flex;align-items:center;} +.cube-actions button.station-ui-button.ant-btn{border:1px solid var(--ant-color-border);border-radius:var(--ant-border-radius);height:26px;padding:0 8px;} +.menu-row .trash.station-ui-button.ant-btn{border:1px solid var(--ant-color-error-bg);border-radius:var(--ant-border-radius);height:30px;width:34px;} +.menu-preview .menu-section-title.station-ui-button.ant-btn{margin-bottom:8px;} +.style-pick.station-ui-button.ant-btn{border:1px solid var(--ant-color-border);padding:8px;display:flex;flex-direction:column;gap:8px;text-align:center;} +.module-switch>button.station-ui-button.ant-btn{height:50px;border:0;border-radius:0;padding:0 20px;gap:12px;} +.module-switch>button.station-ui-button.ant-btn>b{width:18px;height:auto;} +.module-switch>button.station-ui-button.ant-btn>span{display:block;} +.module-switch>button.station-ui-button.ant-btn small{display:none;} +.side-nav>button.station-ui-button.ant-btn{height:44px;padding:0 20px;gap:12px;} +.side-nav>button.station-ui-button.ant-btn em{width:20px;height:20px;} +.steps button.station-ui-button.ant-btn{padding:0 20px;} +.steps button.station-ui-button.ant-btn>i{width:26px;height:26px;} +.company-status-tabs button.station-ui-button.ant-btn{height:48px;min-width:120px;padding:0 24px;border:0;} +.company-status-tabs button.station-ui-button.ant-btn span{margin-right:8px;} +.company-status-tabs button.station-ui-button.ant-btn b{display:inline-grid;min-width:24px;height:20px;padding:0 8px;border-radius:var(--ant-border-radius);} +.pagination button.station-ui-button.ant-btn{height:32px;border:1px solid var(--ant-color-border);} +.pagination button.station-ui-button.ant-btn{width:34px;} +.domain-select .text-button.station-ui-button.ant-btn{margin:0;} +@media (max-width:900px){.company-status-tabs button.station-ui-button.ant-btn{min-width:100px;}} +.menu-section button.station-ui-button.ant-btn{width:100%;border:0;text-align:left;} +.menu-section-title.station-ui-button.ant-btn{height:56px;padding:0 20px;display:flex;align-items:center;justify-content:space-between;line-height:56px;} +.menu-section-items button.station-ui-button.ant-btn{height:50px;padding:0 20px 0 40px;display:flex;align-items:center;line-height:50px;} +.extension-third-menu>button.station-ui-button.ant-btn{height:50px;padding:0 20px 0 60px;display:flex;align-items:center;line-height:50px;border:0;width:100%;text-align:left;} +.company-side-footer>button.station-ui-button.ant-btn{height:26px;padding:0;border:0;display:flex;align-items:center;justify-content:space-between;text-align:left;} +.company-model-menu button.station-ui-button.ant-btn{width:100%;height:32px;border:0;display:flex;justify-content:space-between;align-items:center;padding:0 8px;} +.site-edit-tabs>button.station-ui-button.ant-btn{height:64px;flex:1;min-width:0;border:0;display:flex;align-items:center;gap:12px;padding:0 20px;text-align:left;} +.site-edit-tabs>button.station-ui-button.ant-btn i{width:26px;height:26px;border:1px solid var(--ant-color-border);border-radius:50%;display:grid;} +.asset-config-tabs>button.station-ui-button.ant-btn{height:65px;min-width:210px;padding:12px 4px 8px;border:0;text-align:left;display:flex;flex-direction:column;justify-content:center;gap:4px;} +.asset-editor-title>.text-button.station-ui-button.ant-btn{margin:0;padding-right:20px;} +.asset-batch-entry.station-ui-button.ant-btn{width:100%;height:54px;border:0;text-align:left;padding:0 16px;} +.asset-template-panel>button.station-ui-button.ant-btn{min-height:58px;border:1px solid var(--ant-color-border);display:grid;text-align:left;padding:8px;column-gap:8px;} +.asset-template-panel>button.station-ui-button.ant-btn>span{align-self:center;} +.node-drawer-tabs button.station-ui-button.ant-btn{border:0;padding:0 20px;} +@media (max-width:1100px){.asset-config-tabs>button.station-ui-button.ant-btn{min-width:180px;}} +.domain-resource-table .company-record-link.station-ui-button.ant-btn{display:block;max-width:100%;overflow:hidden;white-space:nowrap;text-align:left;} +.device-resource-table .company-record-link.station-ui-button.ant-btn{display:block;max-width:100%;overflow:hidden;white-space:nowrap;text-align:left;} +.resource-name-cell .company-record-link.station-ui-button.ant-btn{min-width:0;overflow:hidden;white-space:nowrap;text-align:left;} +.resource-back .text-button.station-ui-button.ant-btn{margin:0;} +.style-resource-table .company-record-link.station-ui-button.ant-btn{display:block;max-width:100%;overflow:hidden;white-space:nowrap;text-align:left;} +.view-toggle button.station-ui-button.ant-btn{border:0;height:28px;padding:0 12px;} +.settings-domain-table .text-button.station-ui-button.ant-btn{margin:0;} +.domain-nav-row>button.station-ui-button.ant-btn:not(.domain-nav-del):not(.domain-nav-ok){flex:1;min-width:0;text-align:left;height:41px;border:0;padding:0 16px;display:flex;align-items:center;white-space:nowrap;} +.domain-nav-row>button.station-ui-button.ant-btn b{width:18px;margin-right:8px;flex:0 0 auto;} +.domain-nav-del.station-ui-button.ant-btn{border:0;width:30px;line-height:1;flex:0 0 auto;} +.domain-nav-ok.station-ui-button.ant-btn{border:0;width:30px;flex:0 0 auto;} +.domain-nav-add.station-ui-button.ant-btn{height:34px;border:0;text-align:left;padding:0 16px;display:flex;align-items:center;width:100%;} +.overview-tabs button.station-ui-button.ant-btn{padding:0 16px;} +.dev-row-head.station-ui-button.ant-btn{width:100%;border:0;display:flex;align-items:center;gap:12px;padding:12px 12px;text-align:left;} +.wise-header button.station-ui-button.ant-btn{border:0;padding:0;} +.wise-menu-button.station-ui-button.ant-btn{flex:0 0 24px;width:24px;height:24px;margin-right:12px;display:grid;} +.wise-product-switch.station-ui-button.ant-btn{flex:0 0 auto;height:48px;margin-left:12px;display:flex;align-items:center;white-space:nowrap;} +.wise-header-actions>button.station-ui-button.ant-btn:not(.wise-avatar){flex:0 0 40px;width:40px;height:40px;display:grid;border-radius:0;} +.wise-header-actions>button.station-ui-button.ant-btn>img{display:block;width:24px;height:24px;} +.wise-avatar.station-ui-button.ant-btn{flex:0 0 24px;width:24px;height:24px;margin:0 8px;border-radius:50%!important;line-height:24px;text-align:center;} +@media (max-width:1120px){.wise-avatar.station-ui-button.ant-btn{margin-right:8px;}} +@media (max-width:700px){.wise-header-actions>button.station-ui-button.ant-btn:not(.wise-avatar){width:36px;flex-basis:36px;}} +@media (max-width:560px){.wise-product-switch.station-ui-button.ant-btn{margin-left:4px;}} +@media (max-width:560px){.wise-header-actions>button.station-ui-button.ant-btn:nth-child(1),.wise-header-actions>button.station-ui-button.ant-btn:nth-child(2){display:none;}} +.asset-batch-entry.station-ui-button.ant-btn{height:72px;padding:0 20px;} +.asset-template-panel>button.station-ui-button.ant-btn{min-height:50px;border:0;padding:8px 8px;} +.asset-template-panel>button.station-ui-button.ant-btn:hover{border:0;} +.asset-view-switch button.station-ui-button.ant-btn{width:38px;border:0;} +.asset-node-card>button.station-ui-button.ant-btn{align-self:center;justify-self:end;width:19px;height:19px;border:0;border-radius:50%;padding:0;display:grid;} +.asset-node-list>button.station-ui-button.ant-btn{height:43px;display:grid;align-items:center;text-align:left;border:0;padding:0 16px;} +.asset-node-drawer .node-drawer-tabs button.station-ui-button.ant-btn{height:49px;padding:0 20px;} +.asset-node-drawer .node-drawer-tabs button.station-ui-button.ant-btn:first-child{padding-left:0;margin-right:20px;} +.node-image-row .text-button.station-ui-button.ant-btn{margin:4px 0 0;} +.edge-component-table button.station-ui-button.ant-btn{width:28px;height:28px;border:0;} +.binding-component-tabs button.station-ui-button.ant-btn{height:34px;padding:0 20px;border:0;} +.domain-showcase-card>footer button.station-ui-button.ant-btn{height:30px;border:0;padding:0;} +.domain-capability-back.station-ui-button.ant-btn{align-self:flex-start;border:0;padding:0;height:28px;} +.domain-capability-card>footer button.station-ui-button.ant-btn{height:29px;border:1px solid var(--ant-color-border);padding:0 12px;} +.domain-capability-card>footer button.station-ui-button.ant-btn.capability-edit-button{margin-right:auto;} +.capability-preview-tabs button.station-ui-button.ant-btn{height:44px;border:0;padding:0 20px;} +.dashboard-card-more.station-ui-button.ant-btn{position:absolute;right:8px;top:10px;width:30px;height:30px;border:0;} +.dashboard-card-more.station-ui-button.ant-btn{right:8px;top:9px;} +.station-icon-control>.link.station-ui-button.ant-btn{border:0;white-space:nowrap;padding:0;} +.station-menu-disclosure.station-ui-button.ant-btn{flex-shrink:0;border:0;width:16px;padding:0;} +.station-application-preview nav>button.station-ui-button.ant-btn{display:flex;align-items:center;justify-content:space-between;width:100%;border:0;padding:16px 20px;text-align:left;} +.station-hierarchy-workspace .station-name-cell>.link.station-ui-button.ant-btn{white-space:nowrap;overflow:hidden;} +.station-name-cell>button.station-ui-button.ant-btn:first-child:not(.link){border:0;width:18px;padding:0;} +.station-template-cards>button.station-ui-button.ant-btn{border:1px solid var(--ant-color-border);text-align:left;padding:16px;min-width:0;} +.station-template-cards>button.station-ui-button.ant-btn>div{display:flex;align-items:center;gap:8px;} +.station-dashboard-image.station-ui-button.ant-btn{display:block;width:100%;height:145px;padding:0;border:0;overflow:hidden;text-align:left;} +.station-menu-source>div>button.station-ui-button.ant-btn{display:flex;align-items:center;justify-content:space-between;width:100%;padding:12px 8px;margin-bottom:8px;border:1px solid var(--ant-color-border);text-align:left;} +.steps button.station-ui-button.ant-btn{height:100%;} diff --git a/src-vue/styles/ui-system.css b/src-vue/styles/ui-system.css new file mode 100644 index 0000000..9f82242 --- /dev/null +++ b/src-vue/styles/ui-system.css @@ -0,0 +1,92 @@ +/* Supplied Skill values are resolved in company-theme.tsx; no independent palette. */ +html,body,.ant-app{font-family:var(--ant-font-family);font-size:var(--ant-font-size);color:var(--ant-color-text-base);background:var(--ant-color-bg-layout)} +.workspace{background:var(--ant-color-bg-layout);min-width:0} +.page-heading{background:var(--ant-color-bg-layout)} +.company-side-nav{font-family:var(--ant-font-family)} +.company-side-nav .menu-section button{font-weight:400;font-size:var(--ant-font-size);border-radius:0} +.company-side-nav .menu-section-title{font-weight:600!important} +.company-side-nav .menu-section-items button.active{font-weight:400;background:var(--ant-color-primary-bg);color:var(--ant-color-primary)} +.company-side-nav .menu-section-items button:hover{background:var(--ant-table-row-hover-bg);color:var(--ant-color-primary)} +.extension-menu-item,.extension-third-menu>div,.extension-third-menu>button{font-family:var(--ant-font-family);font-size:var(--ant-font-size);font-weight:400} +.button.ant-btn{height:var(--ant-control-height);font-size:var(--ant-font-size);border-radius:var(--ant-border-radius);padding-inline:var(--ant-padding);margin-left:0;box-shadow:none} +.button.ant-btn-primary,.btn-ai.ant-btn{background:var(--ant-color-primary);border-color:var(--ant-color-primary);color:var(--ant-color-text-light-solid)} +.button.ant-btn-primary:not(:disabled):hover,.btn-ai.ant-btn:not(:disabled):hover{background:var(--ant-color-primary-hover);border-color:var(--ant-color-primary-hover)} +.button.secondary.ant-btn{background:var(--ant-color-bg-container);color:var(--ant-button-default-color);border-color:var(--ant-button-default-border-color)} +.button.secondary.ant-btn:not(:disabled):hover{color:var(--ant-button-default-hover-color);border-color:var(--ant-button-default-hover-border-color)} +.button.ant-btn:disabled,.button.ant-btn-primary:disabled{background:var(--ant-color-bg-container-disabled);border-color:var(--ant-color-border);color:var(--ant-color-text-disabled);opacity:1} +.station-ui-select{min-width:120px;height:var(--ant-control-height);font-size:var(--ant-font-size)} +.field>.station-ui-select,.form-grid .station-ui-select,.station-basic-fields .station-ui-select,.station-create-template>.station-ui-select,.node-basic-grid .station-ui-select,.alarm-form-grid .station-ui-select{width:100%} +.station-ui-input.ant-input{height:var(--ant-control-height);font-size:var(--ant-font-size);border-radius:var(--ant-border-radius);padding:var(--ant-padding-xxs) var(--ant-padding-xs)} +.station-ui-input.ant-input:focus{border-color:var(--ant-color-primary);box-shadow:0 0 0 2px var(--ant-color-primary-bg)} +.station-ui-input.ant-input:disabled{background:var(--ant-color-bg-container-disabled);color:var(--ant-color-text-disabled)} +.search-field>.station-ui-input,.station-search>.station-ui-input,.dashboard-manager-search>.station-ui-input{border:0!important;box-shadow:none!important;background:transparent!important;min-width:0;flex:1} +.station-ui-choice{flex-shrink:0;margin:0} +.station-ui-table{border-collapse:initial;max-width:100%} +.station-ui-table table{width:100%} +.station-ui-table .ant-table-thead>tr>th{font-size:var(--ant-font-size);font-weight:600;color:var(--ant-table-header-color);background:var(--ant-color-bg-layout);padding-block:var(--ant-padding-sm);border-color:var(--ant-table-border-color)} +.station-ui-table .ant-table-tbody>tr>td{font-size:var(--ant-font-size);font-weight:400;color:var(--ant-color-text-base);padding-block:var(--ant-padding-xs);border-color:var(--ant-table-border-color)} +.station-ui-table .ant-table-tbody>tr:hover>td,.station-ui-table .ant-table-tbody>tr>td.ant-table-cell-row-hover{background:var(--ant-table-row-hover-bg)} +.station-ui-table input[type=checkbox]{appearance:auto;width:auto;height:auto;padding:0;border:0;background:none;margin:0;opacity:0} +.station-ui-table .ant-checkbox-inner{border-radius:var(--ant-border-radius-sm)} +.ant-tag.status,.ant-tag.tag-new{border-radius:var(--ant-border-radius);font-size:var(--ant-font-size-sm);line-height:var(--ant-line-height-sm);padding:var(--ant-padding-xxs) var(--ant-padding-xs)} +.status.ok{color:var(--ant-color-success-text);background:var(--ant-color-success-bg);border-color:var(--ant-color-success-border)} +.status.warn{color:var(--ant-color-warning-text);background:var(--ant-color-warning-bg);border-color:var(--ant-color-warning-border)} +.status.bad{color:var(--ant-color-error-text);background:var(--ant-color-error-bg);border-color:var(--ant-color-error-border)} +.status.muted{color:var(--ant-color-text-secondary);background:var(--ant-color-fill-quaternary);border-color:var(--ant-color-border)} +.ant-drawer-title{font-size:var(--ant-font-size);font-weight:600} +.ant-drawer-body{background:var(--ant-color-bg-container)} +.ant-drawer-footer .station-drawer-actions,.ant-drawer-footer .drawer-actions{display:flex;flex-wrap:nowrap;justify-content:flex-end;gap:var(--ant-padding-xs)} +.domain-capability-actions,.domain-capability-card>footer,.filter-actions,.station-application-menu-actions,.sticky-actions>div{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--ant-padding-xs)} +.domain-capability-card>footer{overflow-x:auto;flex-shrink:0} +.domain-capability-card>footer .ant-btn{height:var(--ant-control-height);font-size:var(--ant-font-size);white-space:nowrap} +.domain-capability-card,.station-page-module-panel,.station-list-panel,.station-application-basic,.station-application-menu{background:var(--ant-color-bg-container);border-color:var(--ant-color-border);border-radius:var(--ant-border-radius)} +.domain-capability-card{overflow:hidden} +.domain-capability-card>header h3,.station-application-settings h2{font-size:var(--ant-font-size);font-weight:600} +.domain-capability-body{min-height:0;overflow:auto} +.device-template-tile b{font-size:var(--ant-font-size-sm);font-weight:400;line-height:var(--ant-line-height-sm)} +.station-dashboard-selection,.station-twin-selection{gap:var(--ant-padding);padding:var(--ant-padding)} +.station-application-settings input:not([type=file]),.station-menu-edit-fields input{border-radius:var(--ant-border-radius);height:var(--ant-control-height)} +.station-application-settings .station-menu-row-actions .ant-btn{color:var(--ant-color-primary)} +.station-application-settings .station-menu-row-actions .ant-btn:disabled{color:var(--ant-color-text-disabled)} +.station-hierarchy-workspace,.station-page-selection,.station-menu-configuration{font-size:var(--ant-font-size)} +.station-application-fields{gap:var(--ant-padding-lg);padding:var(--ant-padding-lg)} +.station-ui-table .station-menu-group-row>td{background:var(--ant-color-bg-layout)} +.station-ui-table .station-menu-group-row:hover>td{background:var(--ant-table-row-hover-bg)} +.station-opsflow-blank{background:var(--ant-color-bg-container)} +@media(max-width:1200px){.domain-capability-actions{overflow:auto;max-width:100%}.station-application-fields{gap:var(--ant-padding)}} +.panel.ant-card{border-radius:var(--ant-border-radius-lg)} +.panel.ant-card>.ant-card-head{padding-inline:var(--ant-padding);min-height:48px} +.panel.ant-card>.ant-card-head .ant-card-head-title{padding:var(--ant-padding-xs) 0;font-size:var(--ant-font-size);font-weight:600} +.panel.ant-card>.ant-card-body{padding:var(--ant-padding-lg)} +.company-list-panel.ant-card>.ant-card-body{padding:0 var(--ant-padding) var(--ant-padding-sm)} +.field.ant-form-item{display:block;gap:initial;margin:0;min-width:0} +.field.ant-form-item .ant-form-item-label{padding:0 0 var(--ant-padding-xs)} +.field.ant-form-item .ant-form-item-label>label{height:auto;font-size:var(--ant-font-size);font-weight:400;color:var(--ant-color-text-base)} +.field.ant-form-item .ant-form-item-extra{font-size:var(--ant-font-size-sm);color:var(--ant-color-text-secondary)} +.field.ant-form-item .ant-input:not(textarea){height:var(--ant-control-height)} +.station-ui-tabs.company-status-tabs,.station-ui-tabs.node-drawer-tabs,.station-ui-tabs.asset-config-tabs,.station-ui-tabs.binding-component-tabs,.station-ui-tabs.tabs{display:block;height:auto;padding-top:0;gap:initial;border:0;margin:0;background:transparent} +.station-ui-tabs>.ant-tabs-nav{margin:0 0 var(--ant-padding)} +.station-ui-tabs>.ant-tabs-nav .ant-tabs-tab{padding:var(--ant-padding-sm) var(--ant-padding);font-size:var(--ant-font-size);font-weight:400} +.station-ui-tabs>.ant-tabs-nav .ant-tabs-ink-bar{height:2px;background:var(--ant-color-primary)} +.station-ui-tabs .ant-tabs-tab-btn{font-weight:400} +.station-ui-tabs .ant-tabs-tab-btn b,.station-ui-tabs .ant-tabs-tab-btn i{margin-left:var(--ant-padding-xs);background:var(--ant-color-fill-secondary);color:var(--ant-color-text-secondary);font-size:var(--ant-font-size-sm);font-style:normal;font-weight:600;padding:0 var(--ant-padding-xxs);border-radius:var(--ant-border-radius)} +.station-ui-tabs .ant-tabs-tab-active .ant-tabs-tab-btn b{background:var(--ant-color-success-bg);color:var(--ant-color-success-text)} +.station-ui-tabs .ant-tabs-content-holder{min-width:0} +.station-ui-tabs .ant-tabs-content{background:var(--ant-color-bg-layout)} +.node-config-page .field.ant-form-item .ant-form-item-row{display:flex;flex-flow:row nowrap;align-items:center} +.node-config-page .field.ant-form-item .ant-form-item-label{flex:0 0 100px;padding:0 var(--ant-padding-xs) 0 0;text-align:right} +.node-config-page .field.ant-form-item .ant-form-item-control{flex:1;min-width:0} +.alarm-enable-switch.ant-switch{min-width:var(--ant-switch-track-min-width);height:var(--ant-switch-track-height);padding:0;border:0} +.station-inline-actions,.station-modal-actions,.station-drawer-actions,.drawer-actions,.result-actions,.settings-actions{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--ant-padding-xs)} +.station-modal-actions{justify-content:flex-end} +/* Ant Modal owns positioning, focus and chrome; old class names only identify business content. */ +.station-ui-modal.modal,.station-ui-modal.dlg-box{display:block;position:relative;inset:auto;margin-inline:auto;padding:0;max-width:calc(100vw - 32px);max-height:none;height:auto;background:none;border:0;border-radius:0;box-shadow:none;overflow:visible;z-index:auto;color:var(--ant-color-text-base);font-size:var(--ant-font-size)} +.station-ui-modal .ant-modal-container{padding:var(--ant-padding-lg);border-radius:var(--ant-border-radius-lg)} +.station-ui-modal .ant-modal-title{font-size:var(--ant-font-size-heading-4);font-weight:600} +.station-ui-modal .ant-modal-body{font-size:var(--ant-font-size);color:var(--ant-color-text-base)} +.station-ui-modal .modal-body{padding:0;max-height:70vh;overflow:auto} +.station-ui-modal .ant-modal-footer{margin-top:var(--ant-padding-lg)} +.station-ui-modal .station-modal-actions .ant-btn{margin:0} +.station-ui-select .ant-select-selector{font-size:var(--ant-font-size)} +.filterbar.company-filterbar{height:auto;min-height:48px;flex-wrap:nowrap} +.filterbar.company-filterbar .station-ui-select{flex-shrink:0;min-width:164px} diff --git a/src-vue/ui/UiActions.vue b/src-vue/ui/UiActions.vue new file mode 100644 index 0000000..38786d4 --- /dev/null +++ b/src-vue/ui/UiActions.vue @@ -0,0 +1,107 @@ + diff --git a/src-vue/ui/UiButton.vue b/src-vue/ui/UiButton.vue new file mode 100644 index 0000000..49ca81b --- /dev/null +++ b/src-vue/ui/UiButton.vue @@ -0,0 +1,54 @@ + + + diff --git a/src-vue/ui/UiInput.vue b/src-vue/ui/UiInput.vue new file mode 100644 index 0000000..9aabece --- /dev/null +++ b/src-vue/ui/UiInput.vue @@ -0,0 +1,88 @@ + + + diff --git a/src-vue/ui/UiOverlay.vue b/src-vue/ui/UiOverlay.vue new file mode 100644 index 0000000..b1a30a7 --- /dev/null +++ b/src-vue/ui/UiOverlay.vue @@ -0,0 +1,96 @@ + diff --git a/src-vue/ui/UiSelect.vue b/src-vue/ui/UiSelect.vue new file mode 100644 index 0000000..65624ae --- /dev/null +++ b/src-vue/ui/UiSelect.vue @@ -0,0 +1,63 @@ + + + diff --git a/src-vue/ui/UiTabbedRegion.vue b/src-vue/ui/UiTabbedRegion.vue new file mode 100644 index 0000000..79c503a --- /dev/null +++ b/src-vue/ui/UiTabbedRegion.vue @@ -0,0 +1,52 @@ + diff --git a/src-vue/ui/UiTable.vue b/src-vue/ui/UiTable.vue new file mode 100644 index 0000000..fcdb491 --- /dev/null +++ b/src-vue/ui/UiTable.vue @@ -0,0 +1,88 @@ + + + diff --git a/src-vue/ui/parse.js b/src-vue/ui/parse.js new file mode 100644 index 0000000..0495c41 --- /dev/null +++ b/src-vue/ui/parse.js @@ -0,0 +1,57 @@ +import { Fragment, Comment, Text } from "vue"; + +// Mirror React ui-system.tsx's Children/elements/textOf helpers for Vue vnodes. +// React used className; Vue vnodes carry `class`. We normalise both. + +function isVNode(n) { + return !!n && typeof n === "object" && n !== null && "type" in n; +} + +function classOf(vnode) { + const c = vnode && vnode.props ? vnode.props.class : undefined; + if (c == null) return ""; + if (typeof c === "string") return c; + if (Array.isArray(c)) return c.filter(Boolean).join(" "); + if (typeof c === "object") return Object.keys(c).filter((k) => c[k]).join(" "); + return String(c); +} + +function elements(children) { + if (children == null) return []; + const arr = Array.isArray(children) ? children : [children]; + const out = []; + for (const child of arr) { + if (!isVNode(child)) continue; + if (child.type === Fragment) { + out.push(...elements(child.children)); + } else if (child.type === Comment) { + // skip comments + } else { + out.push(child); + } + } + return out; +} + +function textOf(children) { + if (children == null) return ""; + const arr = Array.isArray(children) ? children : [children]; + let s = ""; + for (const child of arr) { + if (child == null) continue; + if (typeof child === "string" || typeof child === "number") { + s += String(child); + continue; + } + if (isVNode(child)) { + if (child.type === Text) { + s += String(child.children ?? ""); + continue; + } + s += textOf(child.children); + } + } + return s; +} + +export { isVNode, classOf, elements, textOf }; diff --git a/vite.local.config.js b/vite.local.config.js new file mode 100644 index 0000000..7ebf772 --- /dev/null +++ b/vite.local.config.js @@ -0,0 +1,48 @@ +import vue from "@vitejs/plugin-vue"; +import { fileURLToPath } from "node:url"; +import { defineConfig } from "vite"; + +// Self-contained local UI configuration for the Vue 3 rewrite of StationBuilder. +// Same application base path and business components as the React source; a client-only +// local preview without production hosting metadata or the RSC development runtime. +export default defineConfig({ + // Vue 使用独立的 root 与 HTML 入口,避免与 React 的 index.html 耦合。 + root: "src-vue", + base: "/t/stationbuilder-vue", + build: { + // root 已切到 src-vue,outDir 用绝对路径固定到仓库根 dist-vue, + // 与 stationbuilder-vue.service 的 vite preview 保持一致。 + outDir: fileURLToPath(new URL("./dist-vue", import.meta.url)), + emptyOutDir: true, + }, + resolve: { + alias: { + "@/assets": fileURLToPath(new URL("./src/assets", import.meta.url)), + "@": fileURLToPath(new URL("./src-vue", import.meta.url)), + }, + }, + server: { + host: "127.0.0.1", + allowedHosts: true, + hmr: { overlay: false }, + proxy: { + "/api/db": { + target: "http://127.0.0.1:37823", + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api\/db/, "/api"), + }, + "/api/chat": { + target: "http://127.0.0.1:37822", + changeOrigin: true, + }, + }, + }, + plugins: [ + vue({ + // StationBuilder serves its images from /public at the app base path, referenced as + // absolute /t/stationbuilder/... URLs. Disable SFC asset URL rewriting so these stay + // as runtime public URLs instead of being bundled as module imports. + template: { transformAssetUrls: false }, + }), + ], +}); -- 2.43.0