From 44c33a628088c1de1880b55f072675b3db079fa8 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Mon, 3 Aug 2026 18:49:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9E=84=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 21 ++- README.md | 12 +- .../components/AdminSidebarMenu.test.ts | 2 +- src/{ => app}/components/AdminSidebarMenu.vue | 2 +- .../components/AdminSidebarMenuNode.vue | 2 +- src/{ => app}/layouts/AppLayout.test.ts | 2 +- src/{ => app}/layouts/AppLayout.vue | 10 +- .../pages}/ForbiddenView.test.ts | 0 src/{views => app/pages}/ForbiddenView.vue | 4 +- .../pages}/IntegrationUnavailableView.vue | 0 src/{views => app/pages}/ModuleView.vue | 0 src/{ => app}/router/index.test.ts | 15 +- src/app/router/index.ts | 85 ++++++++++ src/{ => app}/router/meta.d.ts | 0 .../access}/accessPreview.test.ts | 4 +- src/{stores => core/access}/accessPreview.ts | 4 +- src/{stores => core/auth}/auth.test.ts | 4 +- src/{stores => core/auth}/auth.ts | 7 +- src/{utils => core/auth}/jwt.ts | 0 src/core/auth/platformAuthorization.test.ts | 19 +++ src/core/auth/platformAuthorization.ts | 8 + src/core/dependencyBoundaries.test.ts | 48 ++++++ .../navigation/adminNavigation.test.ts | 0 src/{ => core}/navigation/adminNavigation.ts | 0 .../routing}/accessDecision.test.ts | 0 .../routing}/accessDecision.ts | 0 .../unsaved-work}/unsavedWork.test.ts | 2 +- .../unsaved-work}/unsavedWork.ts | 0 .../useUnsavedWorkRegistration.test.ts | 4 +- .../useUnsavedWorkRegistration.ts | 2 +- src/main.ts | 13 +- .../auth/pages}/LoginView.test.ts | 6 +- .../auth/pages}/LoginView.vue | 10 +- .../customers/pages}/CustomersView.test.ts | 12 +- .../customers/pages}/CustomersView.vue | 14 +- .../pages}/EnterpriseReviewsView.test.ts | 8 +- .../pages}/EnterpriseReviewsView.vue | 12 +- src/modules/customers/routes.ts | 16 ++ .../api/platformExportTasks.test.ts | 6 +- .../downloads}/api/platformExportTasks.ts | 2 +- src/modules/downloads/index.ts | 1 + .../pages}/DownloadCenterView.test.ts | 25 ++- .../downloads/pages}/DownloadCenterView.vue | 27 ++-- src/modules/downloads/routes.ts | 10 ++ .../api/platformFirstLegOrders.test.ts | 4 +- .../api/platformFirstLegOrders.ts | 2 +- .../PlatformFirstLegOrdersPanel.vue | 14 +- .../pages/FirstLegOrdersView.vue | 7 + src/modules/first-leg-orders/routes.ts | 10 ++ src/{ => modules/iam}/api/platformIam.test.ts | 12 +- src/{ => modules/iam}/api/platformIam.ts | 22 +-- src/modules/iam/index.ts | 1 + .../iam/pages}/InternalUsersView.test.ts | 8 +- .../iam/pages}/InternalUsersView.vue | 16 +- .../iam/pages}/PermissionsView.test.ts | 6 +- .../iam/pages}/PermissionsView.vue | 22 +-- .../iam/pages}/RolesView.test.ts | 8 +- .../iam/pages}/RolesView.vue | 22 +-- src/modules/iam/routes.ts | 22 +++ src/modules/iam/types.ts | 42 +++++ .../iam}/utils/permissionTree.test.ts | 4 +- src/{ => modules/iam}/utils/permissionTree.ts | 2 +- .../iam}/utils/platformPermission.test.ts | 2 +- .../iam}/utils/platformPermission.ts | 4 +- .../api/platformPartners.test.ts | 4 +- .../counterparties}/api/platformPartners.ts | 2 +- .../pages}/PartnersView.test.ts | 8 +- .../counterparties/pages}/PartnersView.vue | 14 +- .../api/platformExpressCompanies.test.ts | 4 +- .../api/platformExpressCompanies.ts | 2 +- .../pages}/ExpressCompaniesView.test.ts | 8 +- .../pages}/ExpressCompaniesView.vue | 14 +- src/modules/master-data/routes.ts | 16 ++ .../api/platformWarehouses.test.ts | 4 +- .../warehouses}/api/platformWarehouses.ts | 2 +- .../warehouses/pages}/WarehousesView.test.ts | 8 +- .../warehouses/pages}/WarehousesView.vue | 14 +- src/modules/warehouses/routes.ts | 10 ++ src/modules/warehouses/types.ts | 3 + .../components}/PrototypeModuleView.vue | 0 .../container-management}/ModuleView.vue | 2 +- .../customer-management}/ModuleView.vue | 2 +- .../modules/dashboard}/ModuleView.vue | 2 +- .../domestic-warehouse}/ModuleView.vue | 2 +- .../modules/fba-returns/ModuleView.vue | 5 + src/prototype/modules/finance/ModuleView.vue | 5 + src/prototype/modules/general/ModuleView.vue | 5 + src/prototype/modules/messages/ModuleView.vue | 5 + .../modules/overseas-business/ModuleView.vue | 5 + .../modules/overseas-delivery/ModuleView.vue | 5 + .../modules/overseas-inventory/ModuleView.vue | 5 + .../overseas-warehouse-orders/ModuleView.vue | 5 + src/prototype/modules/reports/ModuleView.vue | 5 + src/prototype/modules/sales/ModuleView.vue | 5 + .../modules/service-center/ModuleView.vue | 5 + .../modules/supplier-center/ModuleView.vue | 5 + .../modules/system-management/ModuleView.vue | 5 + .../modules/vehicle-management/ModuleView.vue | 5 + .../routes.ts} | 36 ++--- src/router/index.ts | 133 ---------------- .../api/http.safe-integer.test.ts | 0 src/{ => shared}/api/http.test.ts | 0 src/{ => shared}/api/http.ts | 0 src/{ => shared}/components/ApiErrorMeta.vue | 4 +- .../components}/AppDialog.test.ts | 0 .../components}/AppDialog.vue | 0 .../components}/AppDrawer.vue | 0 .../components}/CopyButton.vue | 2 +- .../components}/DataTable.test.ts | 0 .../components}/DataTable.vue | 0 .../components}/LoadErrorState.vue | 0 src/{ => shared}/components/MetricStrip.vue | 0 .../components}/QueryToolbar.vue | 0 src/{ => shared}/components/StatusBadge.vue | 0 src/shared/types/platformPermission.ts | 14 ++ src/{ => shared}/utils/copyText.test.ts | 0 src/{ => shared}/utils/copyText.ts | 0 src/types/admin.ts | 148 ------------------ src/views/FirstLegOrdersView.vue | 7 - .../prototype/fba-returns/ModuleView.vue | 5 - src/views/prototype/finance/ModuleView.vue | 5 - src/views/prototype/general/ModuleView.vue | 5 - src/views/prototype/messages/ModuleView.vue | 5 - .../overseas-business/ModuleView.vue | 5 - .../overseas-delivery/ModuleView.vue | 5 - .../overseas-inventory/ModuleView.vue | 5 - .../overseas-warehouse-orders/ModuleView.vue | 5 - src/views/prototype/reports/ModuleView.vue | 5 - src/views/prototype/sales/ModuleView.vue | 5 - .../prototype/service-center/ModuleView.vue | 5 - .../prototype/supplier-center/ModuleView.vue | 5 - .../system-management/ModuleView.vue | 5 - .../vehicle-management/ModuleView.vue | 5 - 133 files changed, 651 insertions(+), 603 deletions(-) rename src/{ => app}/components/AdminSidebarMenu.test.ts (98%) rename src/{ => app}/components/AdminSidebarMenu.vue (90%) rename src/{ => app}/components/AdminSidebarMenuNode.vue (92%) rename src/{ => app}/layouts/AppLayout.test.ts (98%) rename src/{ => app}/layouts/AppLayout.vue (92%) rename src/{views => app/pages}/ForbiddenView.test.ts (100%) rename src/{views => app/pages}/ForbiddenView.vue (88%) rename src/{views => app/pages}/IntegrationUnavailableView.vue (100%) rename src/{views => app/pages}/ModuleView.vue (100%) rename src/{ => app}/router/index.test.ts (80%) create mode 100644 src/app/router/index.ts rename src/{ => app}/router/meta.d.ts (100%) rename src/{stores => core/access}/accessPreview.test.ts (88%) rename src/{stores => core/access}/accessPreview.ts (92%) rename src/{stores => core/auth}/auth.test.ts (98%) rename src/{stores => core/auth}/auth.ts (96%) rename src/{utils => core/auth}/jwt.ts (100%) create mode 100644 src/core/auth/platformAuthorization.test.ts create mode 100644 src/core/auth/platformAuthorization.ts create mode 100644 src/core/dependencyBoundaries.test.ts rename src/{ => core}/navigation/adminNavigation.test.ts (100%) rename src/{ => core}/navigation/adminNavigation.ts (100%) rename src/{router => core/routing}/accessDecision.test.ts (100%) rename src/{router => core/routing}/accessDecision.ts (100%) rename src/{stores => core/unsaved-work}/unsavedWork.test.ts (97%) rename src/{stores => core/unsaved-work}/unsavedWork.ts (100%) rename src/{composables => core/unsaved-work}/useUnsavedWorkRegistration.test.ts (94%) rename src/{composables => core/unsaved-work}/useUnsavedWorkRegistration.ts (94%) rename src/{views => modules/auth/pages}/LoginView.test.ts (96%) rename src/{views => modules/auth/pages}/LoginView.vue (91%) rename src/{views => modules/customers/pages}/CustomersView.test.ts (96%) rename src/{views => modules/customers/pages}/CustomersView.vue (99%) rename src/{views => modules/customers/pages}/EnterpriseReviewsView.test.ts (97%) rename src/{views => modules/customers/pages}/EnterpriseReviewsView.vue (98%) create mode 100644 src/modules/customers/routes.ts rename src/{ => modules/downloads}/api/platformExportTasks.test.ts (91%) rename src/{ => modules/downloads}/api/platformExportTasks.ts (96%) create mode 100644 src/modules/downloads/index.ts rename src/{views => modules/downloads/pages}/DownloadCenterView.test.ts (75%) rename src/{views => modules/downloads/pages}/DownloadCenterView.vue (90%) create mode 100644 src/modules/downloads/routes.ts rename src/{ => modules/first-leg-orders}/api/platformFirstLegOrders.test.ts (97%) rename src/{ => modules/first-leg-orders}/api/platformFirstLegOrders.ts (98%) rename src/{ => modules/first-leg-orders}/components/PlatformFirstLegOrdersPanel.vue (98%) create mode 100644 src/modules/first-leg-orders/pages/FirstLegOrdersView.vue create mode 100644 src/modules/first-leg-orders/routes.ts rename src/{ => modules/iam}/api/platformIam.test.ts (96%) rename src/{ => modules/iam}/api/platformIam.ts (96%) create mode 100644 src/modules/iam/index.ts rename src/{views => modules/iam/pages}/InternalUsersView.test.ts (95%) rename src/{views => modules/iam/pages}/InternalUsersView.vue (97%) rename src/{views => modules/iam/pages}/PermissionsView.test.ts (94%) rename src/{views => modules/iam/pages}/PermissionsView.vue (96%) rename src/{views => modules/iam/pages}/RolesView.test.ts (93%) rename src/{views => modules/iam/pages}/RolesView.vue (95%) create mode 100644 src/modules/iam/routes.ts create mode 100644 src/modules/iam/types.ts rename src/{ => modules/iam}/utils/permissionTree.test.ts (96%) rename src/{ => modules/iam}/utils/permissionTree.ts (97%) rename src/{ => modules/iam}/utils/platformPermission.test.ts (93%) rename src/{ => modules/iam}/utils/platformPermission.ts (79%) rename src/{ => modules/master-data/counterparties}/api/platformPartners.test.ts (98%) rename src/{ => modules/master-data/counterparties}/api/platformPartners.ts (98%) rename src/{views => modules/master-data/counterparties/pages}/PartnersView.test.ts (95%) rename src/{views => modules/master-data/counterparties/pages}/PartnersView.vue (98%) rename src/{ => modules/master-data/express-companies}/api/platformExpressCompanies.test.ts (98%) rename src/{ => modules/master-data/express-companies}/api/platformExpressCompanies.ts (97%) rename src/{views => modules/master-data/express-companies/pages}/ExpressCompaniesView.test.ts (91%) rename src/{views => modules/master-data/express-companies/pages}/ExpressCompaniesView.vue (98%) create mode 100644 src/modules/master-data/routes.ts rename src/{ => modules/warehouses}/api/platformWarehouses.test.ts (97%) rename src/{ => modules/warehouses}/api/platformWarehouses.ts (98%) rename src/{views => modules/warehouses/pages}/WarehousesView.test.ts (97%) rename src/{views => modules/warehouses/pages}/WarehousesView.vue (97%) create mode 100644 src/modules/warehouses/routes.ts create mode 100644 src/modules/warehouses/types.ts rename src/{views => prototype/components}/PrototypeModuleView.vue (100%) rename src/{views/prototype/domestic-warehouse => prototype/modules/container-management}/ModuleView.vue (64%) rename src/{views/prototype/container-management => prototype/modules/customer-management}/ModuleView.vue (64%) rename src/{views/prototype/customer-management => prototype/modules/dashboard}/ModuleView.vue (64%) rename src/{views/prototype/dashboard => prototype/modules/domestic-warehouse}/ModuleView.vue (64%) create mode 100644 src/prototype/modules/fba-returns/ModuleView.vue create mode 100644 src/prototype/modules/finance/ModuleView.vue create mode 100644 src/prototype/modules/general/ModuleView.vue create mode 100644 src/prototype/modules/messages/ModuleView.vue create mode 100644 src/prototype/modules/overseas-business/ModuleView.vue create mode 100644 src/prototype/modules/overseas-delivery/ModuleView.vue create mode 100644 src/prototype/modules/overseas-inventory/ModuleView.vue create mode 100644 src/prototype/modules/overseas-warehouse-orders/ModuleView.vue create mode 100644 src/prototype/modules/reports/ModuleView.vue create mode 100644 src/prototype/modules/sales/ModuleView.vue create mode 100644 src/prototype/modules/service-center/ModuleView.vue create mode 100644 src/prototype/modules/supplier-center/ModuleView.vue create mode 100644 src/prototype/modules/system-management/ModuleView.vue create mode 100644 src/prototype/modules/vehicle-management/ModuleView.vue rename src/{router/prototypeModuleRoutes.ts => prototype/routes.ts} (83%) delete mode 100644 src/router/index.ts rename src/{ => shared}/api/http.safe-integer.test.ts (100%) rename src/{ => shared}/api/http.test.ts (100%) rename src/{ => shared}/api/http.ts (100%) rename src/{ => shared}/components/ApiErrorMeta.vue (93%) rename src/{components/common => shared/components}/AppDialog.test.ts (100%) rename src/{components/common => shared/components}/AppDialog.vue (100%) rename src/{components/common => shared/components}/AppDrawer.vue (100%) rename src/{components/common => shared/components}/CopyButton.vue (96%) rename src/{components/common => shared/components}/DataTable.test.ts (100%) rename src/{components/common => shared/components}/DataTable.vue (100%) rename src/{components/common => shared/components}/LoadErrorState.vue (100%) rename src/{ => shared}/components/MetricStrip.vue (100%) rename src/{components/common => shared/components}/QueryToolbar.vue (100%) rename src/{ => shared}/components/StatusBadge.vue (100%) create mode 100644 src/shared/types/platformPermission.ts rename src/{ => shared}/utils/copyText.test.ts (100%) rename src/{ => shared}/utils/copyText.ts (100%) delete mode 100644 src/types/admin.ts delete mode 100644 src/views/FirstLegOrdersView.vue delete mode 100644 src/views/prototype/fba-returns/ModuleView.vue delete mode 100644 src/views/prototype/finance/ModuleView.vue delete mode 100644 src/views/prototype/general/ModuleView.vue delete mode 100644 src/views/prototype/messages/ModuleView.vue delete mode 100644 src/views/prototype/overseas-business/ModuleView.vue delete mode 100644 src/views/prototype/overseas-delivery/ModuleView.vue delete mode 100644 src/views/prototype/overseas-inventory/ModuleView.vue delete mode 100644 src/views/prototype/overseas-warehouse-orders/ModuleView.vue delete mode 100644 src/views/prototype/reports/ModuleView.vue delete mode 100644 src/views/prototype/sales/ModuleView.vue delete mode 100644 src/views/prototype/service-center/ModuleView.vue delete mode 100644 src/views/prototype/supplier-center/ModuleView.vue delete mode 100644 src/views/prototype/system-management/ModuleView.vue delete mode 100644 src/views/prototype/vehicle-management/ModuleView.vue diff --git a/AGENTS.md b/AGENTS.md index f237e8ba..7bd02a44 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,20 +16,25 @@ ## 目录与职责 -- `src/views/`:路由级页面和业务编排;复杂、可复用的展示或交互下沉到组件。 -- `src/components/`:无路由依赖的复用组件,输入输出应有明确类型。 -- `src/layouts/`:应用壳层、导航和全局页面结构。 -- `src/router/`:路由、标题、登录保护和权限元数据;新增模块时同步维护导航与路由配置。 -- `src/stores/`:跨页面状态和业务动作;仅页面局部使用的状态留在组件内。 -- `src/api/`:HTTP 客户端和接口适配;页面与组件不得散落创建 Axios 实例。 +- `src/app/`:应用装配层,包含布局、根路由、全局守卫和启动入口;不承载具体业务或被业务模块反向依赖。 +- `src/core/`:认证会话、访问控制、导航配置、未保存工作保护和路由安全工具等全应用基础能力;可以被 `app` 和业务模块使用,但不得依赖业务模块。 +- `src/modules/`:按客户、仓库、头程订单、主数据、下载中心、IAM 等稳定业务领域组织页面、API、类型、组件和路由。新增业务页面必须进入对应模块,不再建立根级 `views/`。 +- `src/shared/`:与具体业务无关的后台公共 HTTP、组件和工具。模块专属能力先留在模块内部,只有被无关模块真实复用时才上移。 +- `src/prototype/`:未纳入当前迭代的原型页面和原型路由;正式模块不得依赖原型代码。 +- `src/modules/*/pages/`:路由级页面和业务编排;复杂展示、表单、抽屉和交互下沉到同模块组件或 composable。 +- `src/modules/*/routes.ts`:模块路由片段;由 `src/app/router/index.ts` 统一装配。新增模块时同步维护 `src/core/navigation/adminNavigation.ts`。 +- `src/core/*/` 与 `src/modules/*/stores/`:前者只放全应用基础状态,后者放领域状态;仅页面局部使用的状态留在页面或 composable。 +- `src/modules/*/api/`:领域接口适配;公共 Axios 客户端位于 `src/shared/api/http.ts`,页面与组件不得散落创建 Axios 实例。 - `VITE_API_BASE_URL` 控制浏览器请求前缀,`API_PROXY_TARGET` 控制 Vite 开发代理上游;后者只由开发服务器读取,不进入客户端构建。新增或变更环境变量时同步更新 `.env.example`,不得提交真实密钥或环境专属凭据。 -- `src/types/`:后台专属类型;跨应用共享的稳定契约放到 `packages/shared`。 +- 模块专属类型放在对应模块;跨应用共享的稳定契约放到 `packages/shared`。 - `src/styles/`:设计令牌和全局样式;优先复用现有 `--cc-*` 变量和组件样式。 +依赖方向保持为 `app -> modules/core/shared`、`modules -> core/shared`、`core -> shared`、`shared -> 无上层依赖`。模块间确需调用时只能引用对方根入口公开的 API 或契约,不得引用其他模块的页面、内部组件或内部目录。 + ## 业务与安全约束 - 菜单隐藏和前端路由守卫只改善体验,不能替代服务端鉴权。新增操作必须使用稳定的权限编码,并与 API 权限保持一致。 -- 认证统一经过 `src/stores/auth.ts` 和 `src/api/http.ts`;不要在页面中复制令牌读写或手工拼装 `Authorization`。 +- 认证统一经过 `src/core/auth/auth.ts` 和 `src/shared/api/http.ts`;不要在页面中复制令牌读写或手工拼装 `Authorization`。 - 当前登录和部分数据仍可能是模拟实现。接入 `services/api` 时删除对应模拟路径,不允许让生产逻辑静默回退到假数据。 - 删除、停用、改权限等高风险操作必须有明确确认、处理中、成功和失败反馈;失败时保留用户上下文,避免误以为已生效。 - 日志、提示和示例数据不得包含真实账号、令牌、客户隐私或生产数据。 diff --git a/README.md b/README.md index cc56a4f7..37f481a2 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,19 @@ pnpm build pnpm test ``` +## 源码结构 + +- `src/app/`:应用壳层、根路由和启动装配。 +- `src/core/`:认证、权限、导航、未保存工作保护等全应用基础能力。 +- `src/modules/`:按业务领域组织页面、接口、组件、类型和模块路由。 +- `src/shared/`:不依赖具体业务的 HTTP、基础组件和工具。 +- `src/prototype/`:尚未进入当前迭代的原型页面与路由,和正式业务代码隔离。 + +新增业务页面时,在对应 `src/modules//` 中就近放置页面、测试和领域能力,并从模块 `routes.ts` 导出路由片段;根路由只负责装配,菜单仍由 `src/core/navigation/adminNavigation.ts` 集中维护。跨模块调用必须经过模块根入口公开的 API,不能引用对方内部目录。 + 依赖和 `pnpm-lock.yaml` 均保存在当前前端项目中,不需要在仓库根目录安装 Node 依赖。 -工作台已从一期路由与菜单移除;登录后按当前角色进入第一个有权限的业务页面。一期 Admin 路由聚焦登录、客户及注册审核、平台收货仓、快递公司、往来单位、头程订单、内部用户、角色管理和菜单权限。 +工作台已从一期菜单和默认入口移除;登录后按当前角色进入第一个有权限的业务页面。历史工作台仍保留为不展示菜单的原型路由。一期 Admin 正式路由聚焦登录、客户及注册审核、平台收货仓、快递公司、往来单位、头程订单、内部用户、角色管理和菜单权限。 后台菜单仅展示已接入的一期模块;其余平台原型菜单保留为导航配置中的注释,待对应业务契约接入后再恢复展示。企业审核、仓库、头程订单、平台角色、菜单及按钮权限资源均接入真实接口;用户管理通过 IAM 统一维护平台账号和企业租户账号。运行时不再提供本地演示业务数据或静态角色预览。 diff --git a/src/components/AdminSidebarMenu.test.ts b/src/app/components/AdminSidebarMenu.test.ts similarity index 98% rename from src/components/AdminSidebarMenu.test.ts rename to src/app/components/AdminSidebarMenu.test.ts index def2ca02..b399c382 100644 --- a/src/components/AdminSidebarMenu.test.ts +++ b/src/app/components/AdminSidebarMenu.test.ts @@ -1,6 +1,6 @@ import { mount } from '@vue/test-utils' import { describe, expect, it } from 'vitest' -import { adminNavigation, filterAdminNavigation, type AdminNavigationNode } from '@/navigation/adminNavigation' +import { adminNavigation, filterAdminNavigation, type AdminNavigationNode } from '@/core/navigation/adminNavigation' import AdminSidebarMenu from './AdminSidebarMenu.vue' const stubs = { diff --git a/src/components/AdminSidebarMenu.vue b/src/app/components/AdminSidebarMenu.vue similarity index 90% rename from src/components/AdminSidebarMenu.vue rename to src/app/components/AdminSidebarMenu.vue index bf254295..9e2737dc 100644 --- a/src/components/AdminSidebarMenu.vue +++ b/src/app/components/AdminSidebarMenu.vue @@ -1,6 +1,6 @@