From d80bf89cfa5df8e1533ec09f33cf012aa3a1dd60 Mon Sep 17 00:00:00 2001 From: Estrella Pan Date: Thu, 2 Jul 2026 21:33:02 +0200 Subject: [PATCH] =?UTF-8?q?fix(webui):=20restore=20config=20page=20?= =?UTF-8?q?=E2=80=94=20naive-ui=20theme=20crash=20and=20missing=20controls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two regressions from the component-system unification left the Config page blank or control-less: - App.vue passed var(--color-danger) as common.errorColor*; naive-ui runs JS color math (seemly rgba) on these tokens and threw "Invalid color value var(...)" while rendering NSelect, killing the whole page subtree. Error colors are now per-theme literals. - ab-setting.vue still referenced the deleted AbSwitch/AbSelect primitives, which auto-resolution silently rendered as nothing — every switch/select in settings vanished. Replaced with themed NSwitch/NSelect plus an items→options adapter for the old API. - Bumped naive-ui 2.39→2.44: 2.39 predates Vue 3.5 and crashed NTag rendering inside NDynamicTags ("theme.self undefined"). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01GTnuEgR78cBk32bLNKar3z --- webui/package.json | 2 +- webui/pnpm-lock.yaml | 75 ++++++++++++++--------------- webui/src/App.vue | 19 +++++--- webui/src/components/ab-label.vue | 2 +- webui/src/components/ab-setting.vue | 53 +++++++++++++++----- 5 files changed, 90 insertions(+), 61 deletions(-) diff --git a/webui/package.json b/webui/package.json index 2ff7857a..45bafd3f 100644 --- a/webui/package.json +++ b/webui/package.json @@ -24,7 +24,7 @@ "@vueuse/components": "^10.11.1", "@vueuse/core": "^10.11.1", "axios": "^1.7.9", - "naive-ui": "^2.39.0", + "naive-ui": "^2.44.1", "pinia": "^2.2.2", "vue": "^3.5.8", "vue-i18n": "^9.14.2", diff --git a/webui/pnpm-lock.yaml b/webui/pnpm-lock.yaml index b0b7c735..122282ec 100644 --- a/webui/pnpm-lock.yaml +++ b/webui/pnpm-lock.yaml @@ -21,8 +21,8 @@ importers: specifier: ^1.7.9 version: 1.18.1 naive-ui: - specifier: ^2.39.0 - version: 2.39.0(vue@3.5.8(typescript@4.9.5)) + specifier: ^2.44.1 + version: 2.44.1(vue@3.5.8(typescript@4.9.5)) pinia: specifier: ^2.2.2 version: 2.2.2(typescript@4.9.5)(vue@3.5.8(typescript@4.9.5)) @@ -1912,12 +1912,12 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/katex@0.16.7': - resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==} - '@types/lodash-es@4.17.12': resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + '@types/lodash@4.17.24': + resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==} + '@types/lodash@4.17.7': resolution: {integrity: sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==} @@ -2794,14 +2794,13 @@ packages: resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} engines: {node: '>= 0.4'} - date-fns-tz@2.0.1: - resolution: {integrity: sha512-fJCG3Pwx8HUoLhkepdsP7Z5RsucUi+ZBOxyM5d0ZZ6c4SdYustq0VMmOu6Wf7bli+yS/Jwp91TOCqn9jMcVrUA==} + date-fns-tz@3.2.0: + resolution: {integrity: sha512-sg8HqoTEulcbbbVXeg84u5UnlsQa8GS5QXMqjjYIhS4abEVVKIUwe0/l/UhrZdKaL/W5eWZNlbTeEIiOXTcsBQ==} peerDependencies: - date-fns: 2.x + date-fns: ^3.0.0 || ^4.0.0 - date-fns@2.30.0: - resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} - engines: {node: '>=0.11'} + date-fns@4.4.0: + resolution: {integrity: sha512-+1UMbeh68lH1SegH83CGWwpb6OHHbpSgr3+s5Eww5M4CAgswBpoWS0AjTOfEJ33HiYKz1hdj/KTFprzXHmq/6w==} date-time@3.1.0: resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==} @@ -4367,8 +4366,9 @@ packages: muggle-string@0.3.1: resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} - naive-ui@2.39.0: - resolution: {integrity: sha512-5oUJzRG+rtLSH8eRU+fJvVYiQids2BxF9jp+fwGoAqHOptEINrBlgBu9uy+95RHE5FLJ7Q/z41o+qkoGnUrKxQ==} + naive-ui@2.44.1: + resolution: {integrity: sha512-reo8Esw0p58liZwbUutC7meW24Xbn3EwNv91zReWKm2W4JPu+zfgJRn/F7aO0BFmvN+h2brA2M5lRvYqLq4kuA==} + engines: {node: '>=20'} peerDependencies: vue: ^3.0.0 @@ -5158,8 +5158,8 @@ packages: scule@1.3.0: resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} - seemly@0.3.8: - resolution: {integrity: sha512-MW8Qs6vbzo0pHmDpFSYPna+lwpZ6Zk1ancbajw/7E8TKtHdV+1DfZZD+kKJEhG/cAoB/i+LiT+5msZOqj0DwRA==} + seemly@0.3.10: + resolution: {integrity: sha512-2+SMxtG1PcsL0uyhkumlOU6Qo9TAQ/WyH7tthnPIOQB05/12jz9naq6GZ6iZ6ApVsO3rr2gsnTf3++OV63kE1Q==} semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} @@ -5926,8 +5926,8 @@ packages: peerDependencies: vue: ^3.0.1 - vueuc@0.4.63: - resolution: {integrity: sha512-QJT0z9yYWXdKpUq6f6IrAgJ83e34iTYMCVHjcAP8lCjldG0JzHnDfJYMpPWkNuLB5SdBZCbYGmYTKnTR+ff7CQ==} + vueuc@0.4.65: + resolution: {integrity: sha512-lXuMl+8gsBmruudfxnMF9HW4be8rFziylXFu1VHVNbLVhRTXXV4njvpRuJapD/8q+oFEMSfQMH16E/85VoWRyQ==} peerDependencies: vue: ^3.0.11 @@ -8511,11 +8511,11 @@ snapshots: '@types/json5@0.0.29': {} - '@types/katex@0.16.7': {} - '@types/lodash-es@4.17.12': dependencies: - '@types/lodash': 4.17.7 + '@types/lodash': 4.17.24 + + '@types/lodash@4.17.24': {} '@types/lodash@4.17.7': {} @@ -9620,13 +9620,11 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.1 - date-fns-tz@2.0.1(date-fns@2.30.0): + date-fns-tz@3.2.0(date-fns@4.4.0): dependencies: - date-fns: 2.30.0 + date-fns: 4.4.0 - date-fns@2.30.0: - dependencies: - '@babel/runtime': 7.25.6 + date-fns@4.4.0: {} date-time@3.1.0: dependencies: @@ -11375,28 +11373,27 @@ snapshots: muggle-string@0.3.1: {} - naive-ui@2.39.0(vue@3.5.8(typescript@4.9.5)): + naive-ui@2.44.1(vue@3.5.8(typescript@4.9.5)): dependencies: '@css-render/plugin-bem': 0.15.14(css-render@0.15.14) '@css-render/vue3-ssr': 0.15.14(vue@3.5.8(typescript@4.9.5)) - '@types/katex': 0.16.7 - '@types/lodash': 4.17.7 + '@types/lodash': 4.17.24 '@types/lodash-es': 4.17.12 async-validator: 4.2.5 css-render: 0.15.14 csstype: 3.1.3 - date-fns: 2.30.0 - date-fns-tz: 2.0.1(date-fns@2.30.0) + date-fns: 4.4.0 + date-fns-tz: 3.2.0(date-fns@4.4.0) evtd: 0.2.4 highlight.js: 11.10.0 lodash: 4.17.21 lodash-es: 4.17.21 - seemly: 0.3.8 + seemly: 0.3.10 treemate: 0.3.11 vdirs: 0.1.8(vue@3.5.8(typescript@4.9.5)) vooks: 0.2.12(vue@3.5.8(typescript@4.9.5)) vue: 3.5.8(typescript@4.9.5) - vueuc: 0.4.63(vue@3.5.8(typescript@4.9.5)) + vueuc: 0.4.65(vue@3.5.8(typescript@4.9.5)) nanoid@3.3.7: {} @@ -12193,7 +12190,7 @@ snapshots: scule@1.3.0: {} - seemly@0.3.8: {} + seemly@0.3.10: {} semver@5.7.2: {} @@ -12359,10 +12356,10 @@ snapshots: define-properties: 1.2.1 es-abstract: 1.23.3 es-errors: 1.3.0 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-symbols: 1.0.3 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 internal-slot: 1.0.7 regexp.prototype.flags: 1.5.2 set-function-name: 2.0.2 @@ -13048,13 +13045,13 @@ snapshots: sortablejs: 1.14.0 vue: 3.5.8(typescript@4.9.5) - vueuc@0.4.63(vue@3.5.8(typescript@4.9.5)): + vueuc@0.4.65(vue@3.5.8(typescript@4.9.5)): dependencies: '@css-render/vue3-ssr': 0.15.14(vue@3.5.8(typescript@4.9.5)) '@juggle/resize-observer': 3.4.0 css-render: 0.15.14 evtd: 0.2.4 - seemly: 0.3.8 + seemly: 0.3.10 vdirs: 0.1.8(vue@3.5.8(typescript@4.9.5)) vooks: 0.2.12(vue@3.5.8(typescript@4.9.5)) vue: 3.5.8(typescript@4.9.5) diff --git a/webui/src/App.vue b/webui/src/App.vue index 5fe5fa42..5bea43ea 100644 --- a/webui/src/App.vue +++ b/webui/src/App.vue @@ -17,13 +17,10 @@ if (isLoggedIn.value) { // Button/Select/Switch tokens reference the app's own CSS custom properties // directly (they resolve correctly under both `:root` and `.dark`), so they // don't need to be duplicated between the light/dark override objects below. +// 注意:common 里的颜色 token 会进入 naive-ui (seemly) 的 JS 颜色计算, +// 写 CSS 变量会抛 "[seemly/rgba]: Invalid color value var(...)" 并让整个 +// 页面渲染崩溃(Config 页曾因此白屏)——必须用字面量,按主题各写一份。 const primitiveOverrides: GlobalThemeOverrides = { - common: { - errorColor: 'var(--color-danger)', - errorColorHover: 'var(--color-danger)', - errorColorPressed: 'var(--color-danger)', - errorColorSuppl: 'var(--color-danger)', - }, Button: { borderRadiusTiny: 'var(--radius-sm)', borderRadiusSmall: 'var(--radius-sm)', @@ -38,7 +35,10 @@ const primitiveOverrides: GlobalThemeOverrides = { const lightOverrides: GlobalThemeOverrides = { ...primitiveOverrides, common: { - ...primitiveOverrides.common, + errorColor: '#EF4444', + errorColorHover: '#DC2626', + errorColorPressed: '#B91C1C', + errorColorSuppl: '#EF4444', primaryColor: '#6C4AB6', primaryColorHover: '#563A92', primaryColorPressed: '#4A3291', @@ -70,7 +70,10 @@ const lightOverrides: GlobalThemeOverrides = { const darkOverrides: GlobalThemeOverrides = { ...primitiveOverrides, common: { - ...primitiveOverrides.common, + errorColor: '#F87171', + errorColorHover: '#EF4444', + errorColorPressed: '#DC2626', + errorColorSuppl: '#F87171', primaryColor: '#8B6CC7', primaryColorHover: '#A78BDB', primaryColorPressed: '#7B5CB7', diff --git a/webui/src/components/ab-label.vue b/webui/src/components/ab-label.vue index f07ce032..f88e88ee 100644 --- a/webui/src/components/ab-label.vue +++ b/webui/src/components/ab-label.vue @@ -38,7 +38,7 @@ const abLabel = computed(() => { // Make inputs full-width on mobile :deep(input[ab-input]), - :deep(.ab-select), + :deep(.n-select), :deep(.n-dynamic-tags) { width: 100%; diff --git a/webui/src/components/ab-setting.vue b/webui/src/components/ab-setting.vue index 23e527b8..920dde43 100644 --- a/webui/src/components/ab-setting.vue +++ b/webui/src/components/ab-setting.vue @@ -1,32 +1,56 @@