diff --git a/docs/architecture.md b/docs/architecture.md index 48247ed32..ddb1db30e 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -313,7 +313,7 @@ Client Key 费用账本独立累计各次 attempt 的实际费用,不能因请 ### 3.4 前端模块职责 -`frontend/src` 持有应用状态和业务交互,基础组件与主题算法由 `@codex-proxy/ui` 提供: +`frontend/src` 持有应用状态和业务交互,基础组件与主题算法由 `@codex-proxy/ui` 提供,组件目录与合同见 [UI 组件架构](../modules/ui/playground/guide/architecture.md): | 入口 | 职责 | | --- | --- | diff --git a/docs/development.md b/docs/development.md index 3e33d3420..1a86920e4 100644 --- a/docs/development.md +++ b/docs/development.md @@ -63,6 +63,8 @@ pnpm --dir frontend dev 后端职责和依赖方向见 [Workspace 边界](architecture.md#3-workspace-边界),页面与共享逻辑见 [前端模块职责](architecture.md#34-前端模块职责)。 先按所属模块定位,再跟踪请求、状态与展示的调用关系 +共享 UI 的命名与目录见[组件架构](../modules/ui/playground/guide/architecture.md) + ## 源码联调 宿主、组件库和官方插件保留独立仓库,通过 Git 子模块在同一目录开发: diff --git a/frontend/package.json b/frontend/package.json index c90605f8a..6ad7c1f02 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,7 +17,7 @@ }, "dependencies": { "@boxicons/vue": "1.0.1", - "@codex-proxy/ui": "github:zyycn/codex-proxy-ui#v0.3.2", + "@codex-proxy/ui": "github:zyycn/codex-proxy-ui#v0.4.0", "@fontsource-variable/inter": "^5.3.0", "@fontsource-variable/jetbrains-mono": "^5.3.0", "@lucide/vue": "^1.47.0", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 4f0a18e2d..19c5d66bc 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -170,8 +170,8 @@ importers: specifier: 1.0.1 version: 1.0.1(vue@3.5.43(typescript@6.0.3)) '@codex-proxy/ui': - specifier: github:zyycn/codex-proxy-ui#v0.3.2 - version: https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/83c92024dec82b5a644d6adca96a140c541684b0(axios@1.20.0(debug@4.4.3))(change-case@5.4.4)(vite@8.3.0(@types/node@26.6.2)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.43(typescript@6.0.3)) + specifier: github:zyycn/codex-proxy-ui#v0.4.0 + version: https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/db615f3d72975e0d09847a07d03ed5fe7ba8c8b0(axios@1.20.0(debug@4.4.3))(change-case@5.4.4)(vite@8.3.0(@types/node@26.6.2)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.43(typescript@6.0.3)) '@fontsource-variable/inter': specifier: ^5.3.0 version: 5.3.0 @@ -381,9 +381,9 @@ packages: resolution: {integrity: sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==} engines: {node: '>= 20.12.0'} - '@codex-proxy/ui@https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/83c92024dec82b5a644d6adca96a140c541684b0': - resolution: {gitHosted: true, integrity: sha512-9s6sXP8QrUZATh80wQnIMi68lORp+HuixhoXM2WANsgULqF0Rq270VHllSCNISUCj6aP8t5ugNDPkIrkAFpu3A==, tarball: https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/83c92024dec82b5a644d6adca96a140c541684b0} - version: 0.3.2 + '@codex-proxy/ui@https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/db615f3d72975e0d09847a07d03ed5fe7ba8c8b0': + resolution: {gitHosted: true, integrity: sha512-AhG9idgKHs9AWY1Fyo75wlVcBx3KXD3NEY1dF+sOg84PGAz/7mKq6Fb4xqkYqCT6UrduTjT3WbAw/2VhJJdblQ==, tarball: https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/db615f3d72975e0d09847a07d03ed5fe7ba8c8b0} + version: 0.4.0 engines: {node: '>=24'} peerDependencies: vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -537,6 +537,11 @@ packages: peerDependencies: vue: '>=3.0.1' + '@lucide/vue@1.54.0': + resolution: {integrity: sha512-fq5S0Fk3a3c2VPs+QRiiHZylZV+1pxyTyOYxoH507b/OdiqciUiEm83N7d7xijS8lDlsGFf12ad9AkLGVHRevg==} + peerDependencies: + vue: '>=3.0.1' + '@ota-meshi/ast-token-store@0.3.0': resolution: {integrity: sha512-XRO0zi2NIUKq2lUk3T1ecFSld1fMWRKE6naRFGkgkdeosx7IslyUKNv5Dcb5PJTja9tHJoFu0v/7yEpAkrkrTg==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} @@ -1319,8 +1324,8 @@ packages: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dompurify@3.4.15: - resolution: {integrity: sha512-EUBjM+B+lkDE41iE82DDSCfkoPGfXx8IxFxPMjNzm/Uk4xDet77rTN9wqlxlVg71kK7XGuUMv6wUxJUwwv+Xyw==} + dompurify@3.4.16: + resolution: {integrity: sha512-sqo+pNp3qRhCIpbgRi1y8Tgk27Bo2Ry7w0dC1NBeNTdZChWjz9Xb/KOoZbRP/R6pQZ80Qw8YhXw13hWWBbMRnQ==} dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} @@ -2003,8 +2008,8 @@ packages: markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} - marked@18.0.14: - resolution: {integrity: sha512-mBHK6FBHuBAlhgRe88w9F0O1AbwwXJUcQibUbC/QcdTbVGAD7aWza+xt3N6oT/jCZx3/OMeS+8rnuiHZcQ9s7A==} + marked@18.1.0: + resolution: {integrity: sha512-PamYXWWWg2nboG3oX5Ffzpy3EFZROqZJK9hSlMmUnekp7TxPs5DcT95vwd46m73/exfKCRVMtgXoPMI4FEJL6w==} engines: {node: '>= 20'} hasBin: true @@ -2777,17 +2782,17 @@ snapshots: fast-wrap-ansi: 0.2.2 sisteransi: 1.0.5 - '@codex-proxy/ui@https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/83c92024dec82b5a644d6adca96a140c541684b0(axios@1.20.0(debug@4.4.3))(change-case@5.4.4)(vite@8.3.0(@types/node@26.6.2)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.43(typescript@6.0.3))': + '@codex-proxy/ui@https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/db615f3d72975e0d09847a07d03ed5fe7ba8c8b0(axios@1.20.0(debug@4.4.3))(change-case@5.4.4)(vite@8.3.0(@types/node@26.6.2)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.43(typescript@6.0.3))': dependencies: '@ant-design/colors': 8.0.1 '@ant-design/fast-color': 3.0.1 - '@lucide/vue': 1.47.0(vue@3.5.43(typescript@6.0.3)) + '@lucide/vue': 1.54.0(vue@3.5.43(typescript@6.0.3)) '@vueuse/core': 15.0.0(vue@3.5.43(typescript@6.0.3)) '@vueuse/integrations': 15.0.0(axios@1.20.0(debug@4.4.3))(change-case@5.4.4)(sortablejs@1.15.7)(vue@3.5.43(typescript@6.0.3)) - dompurify: 3.4.15 + dompurify: 3.4.16 es-toolkit: 1.52.0 gsap: 3.15.0 - marked: 18.0.14 + marked: 18.1.0 sortablejs: 1.15.7 vue: 3.5.43(typescript@6.0.3) optionalDependencies: @@ -2955,6 +2960,10 @@ snapshots: dependencies: vue: 3.5.43(typescript@6.0.3) + '@lucide/vue@1.54.0(vue@3.5.43(typescript@6.0.3))': + dependencies: + vue: 3.5.43(typescript@6.0.3) + '@ota-meshi/ast-token-store@0.3.0': {} '@oxc-project/types@0.149.0': {} @@ -3581,7 +3590,7 @@ snapshots: diff-sequences@29.6.3: {} - dompurify@3.4.15: + dompurify@3.4.16: optionalDependencies: '@types/trusted-types': 2.0.7 @@ -4270,7 +4279,7 @@ snapshots: markdown-table@3.0.4: {} - marked@18.0.14: {} + marked@18.1.0: {} math-intrinsics@1.1.0: {} diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 8d0c05d35..a78fb6fd3 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,10 +1,7 @@ diff --git a/frontend/src/api/request/plugins/feedback.ts b/frontend/src/api/request/plugins/feedback.ts index 108254bcc..2e96e3ccf 100644 --- a/frontend/src/api/request/plugins/feedback.ts +++ b/frontend/src/api/request/plugins/feedback.ts @@ -1,5 +1,5 @@ import type { RequestContext, RequestNext } from './index' -import { toast } from '@codex-proxy/ui' +import { ZNotification } from '@codex-proxy/ui' import { ApiError, isSessionRequired } from './error' // 共享刷新 Promise 的同一个失败只提示一次,弱引用不保留已结束请求 @@ -13,7 +13,7 @@ export async function feedbackPlugin(context: RequestContext, next: RequestNext) if (error instanceof ApiError && error.kind !== 'cancelled' && !isSessionRequired(error) && !context.config.silent && context.isCurrent() && !reported.has(error)) { reported.add(error) - toast.error(error.message) + ZNotification.error({ message: error.message }) } throw error } diff --git a/frontend/src/api/request/plugins/session.ts b/frontend/src/api/request/plugins/session.ts index 4a534787f..3100c071a 100644 --- a/frontend/src/api/request/plugins/session.ts +++ b/frontend/src/api/request/plugins/session.ts @@ -1,6 +1,6 @@ import type { RequestConfig } from '../index' import type { RequestContext, RequestNext } from './index' -import { toast } from '@codex-proxy/ui' +import { ZNotification } from '@codex-proxy/ui' import { ApiError, isSessionRequired } from './error' // 会话失效是后端业务事实,登录凭据错误和 403 不清除已有会话 @@ -54,7 +54,7 @@ function expireSession(error: ApiError, config: RequestConfig, generation: numbe const alreadyHandled = unauthorizedHandled handleUnauthorizedOnce() if (!config.silent && !alreadyHandled) - toast.error(error.message) + ZNotification.error({ message: error.message }) } throw error } diff --git a/frontend/src/components/AccountGroupCheckboxGrid.vue b/frontend/src/components/AccountGroupCheckboxGrid.vue index 92912fdd2..72d0e5a0c 100644 --- a/frontend/src/components/AccountGroupCheckboxGrid.vue +++ b/frontend/src/components/AccountGroupCheckboxGrid.vue @@ -1,7 +1,7 @@ diff --git a/frontend/src/components/AppAboutModal.vue b/frontend/src/components/AppAboutModal.vue index 2786203d1..cc7743e2c 100644 --- a/frontend/src/components/AppAboutModal.vue +++ b/frontend/src/components/AppAboutModal.vue @@ -1,6 +1,6 @@ diff --git a/frontend/src/components/AppBrandMark.vue b/frontend/src/components/AppBrandMark.vue index f82e17a6b..baa40fcc6 100644 --- a/frontend/src/components/AppBrandMark.vue +++ b/frontend/src/components/AppBrandMark.vue @@ -31,7 +31,7 @@ const mistGradientId = `${id}-brand-mist` - + diff --git a/frontend/src/components/ProviderFilter.vue b/frontend/src/components/ProviderFilter.vue index cb8fe11f8..1aba937a5 100644 --- a/frontend/src/components/ProviderFilter.vue +++ b/frontend/src/components/ProviderFilter.vue @@ -1,5 +1,5 @@