From 91031342b8ff1c1807685598efb28b6c8b12b1e9 Mon Sep 17 00:00:00 2001 From: "tao.chen" <93983997+taochen-ct@users.noreply.github.com> Date: Tue, 25 Aug 2026 11:27:26 +0800 Subject: [PATCH] refactor(frontend): consolidate features & components into single tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 把 components/admin/* 和 components/platform/* 共 11 个文件 移到对应 features// 下,components/ 只保留跨特性共享的 common/ 子目录(features/admin/* 之前和 components/admin/* 同名 共存,迫使 features/admin/AdminPages.tsx 出现 barrel,顺带消除了 barrel 副作用 CSS 丢失的隐患)。 新的目录约定: - features// = 特性模块,所有页面 / Modal / state / hooks / routes 都在内,无 components// 并列 - components/common/ = 仅放 ≥2 个特性共用的 widgets (Icon、Sidebar、Toast、Topbar、WelcomePanel) 改动: - 11 文件 git mv (components/{admin,platform}/* → features/*) - 8 文件的 Icon 相对路径 '../common/Icon' → '../../components/common/Icon' - 2 文件补 admin.css side-effect import(UserManagementPage / ProjectManagementPage 之前依赖 AdminPages barrel) - 3 文件(引用方)更新 import:SystemAdminPage、DashboardRoute、 ScriptsPage - 删除 features/admin/AdminPages.tsx barrel(无消费者) - 删除空目录 components/admin、components/platform 验证: - pnpm typecheck 通过 - pnpm build 通过,CSS 体积 35.11 kB 与重构前一致(无样式增减) - routes.ts / routes/platform.tsx 路径未动,route id 不变 踩坑: 第一轮把 '../common/Icon' 错改成 '../../../components/common/Icon', typecheck 报 11 个 Cannot find module。原因:features/admin/ 和 components/admin/ 都是 depth 2,'../../X' 在两边都解析到 app/X, 只有 '../X' 才需要多一层。正确改法是 '../../components/common/Icon'。 Co-Authored-By: Claude Fable 5 --- frontend/app/features/admin/AdminPages.tsx | 8 -------- .../admin/DashboardPage.tsx | 0 .../admin/ProjectManagementPage.tsx | 4 +++- frontend/app/features/admin/SystemAdminPage.tsx | 4 ++-- .../admin/UserManagementPage.tsx | 2 ++ .../admin/UserMultiSelect.tsx | 0 .../platform/CreateFolderModal.tsx | 2 +- .../platform/CreateScriptModal.tsx | 2 +- frontend/app/features/platform/DashboardRoute.tsx | 2 +- .../platform/DataResourceUploadModal.tsx | 2 +- .../platform/PublishModal.tsx | 2 +- .../platform/ScriptExplorer.tsx | 2 +- frontend/app/features/platform/ScriptsPage.tsx | 14 +++++++------- .../platform/TreeContextMenu.tsx | 2 +- .../platform/VersionReceiptModal.tsx | 2 +- 15 files changed, 22 insertions(+), 26 deletions(-) delete mode 100644 frontend/app/features/admin/AdminPages.tsx rename frontend/app/{components => features}/admin/DashboardPage.tsx (100%) rename frontend/app/{components => features}/admin/ProjectManagementPage.tsx (99%) rename frontend/app/{components => features}/admin/UserManagementPage.tsx (99%) rename frontend/app/{components => features}/admin/UserMultiSelect.tsx (100%) rename frontend/app/{components => features}/platform/CreateFolderModal.tsx (97%) rename frontend/app/{components => features}/platform/CreateScriptModal.tsx (99%) rename frontend/app/{components => features}/platform/DataResourceUploadModal.tsx (98%) rename frontend/app/{components => features}/platform/PublishModal.tsx (98%) rename frontend/app/{components => features}/platform/ScriptExplorer.tsx (99%) rename frontend/app/{components => features}/platform/TreeContextMenu.tsx (99%) rename frontend/app/{components => features}/platform/VersionReceiptModal.tsx (96%) diff --git a/frontend/app/features/admin/AdminPages.tsx b/frontend/app/features/admin/AdminPages.tsx deleted file mode 100644 index f616d08..0000000 --- a/frontend/app/features/admin/AdminPages.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import "../../styles/admin.css"; -import "../../styles/dashboard.css"; -import "../../styles/platform.css"; - -export { DashboardPage } from "../../components/admin/DashboardPage"; -export { UserManagementPage } from "../../components/admin/UserManagementPage"; -export { ProjectManagementPage } from "../../components/admin/ProjectManagementPage"; -export { SystemAdminPage } from "./SystemAdminPage"; diff --git a/frontend/app/components/admin/DashboardPage.tsx b/frontend/app/features/admin/DashboardPage.tsx similarity index 100% rename from frontend/app/components/admin/DashboardPage.tsx rename to frontend/app/features/admin/DashboardPage.tsx diff --git a/frontend/app/components/admin/ProjectManagementPage.tsx b/frontend/app/features/admin/ProjectManagementPage.tsx similarity index 99% rename from frontend/app/components/admin/ProjectManagementPage.tsx rename to frontend/app/features/admin/ProjectManagementPage.tsx index 5f3471e..92b8272 100644 --- a/frontend/app/components/admin/ProjectManagementPage.tsx +++ b/frontend/app/features/admin/ProjectManagementPage.tsx @@ -2,9 +2,11 @@ import { useEffect, useState } from "react"; import { ApiRequestError, type Employee, type Workspace, type WorkspaceMember } from "../../services/api"; import { useApi, useAuth } from "../../context/AuthContext"; -import Icon from "../common/Icon"; +import Icon from "../../components/common/Icon"; import { UserMultiSelect } from "./UserMultiSelect"; +import "../../styles/admin.css"; + const EMPTY_PROJECT_FORM = { workspace_code: "", workspace_name: "", diff --git a/frontend/app/features/admin/SystemAdminPage.tsx b/frontend/app/features/admin/SystemAdminPage.tsx index 8ab1d8e..da0febf 100644 --- a/frontend/app/features/admin/SystemAdminPage.tsx +++ b/frontend/app/features/admin/SystemAdminPage.tsx @@ -1,8 +1,8 @@ import { useState } from "react"; import Icon from "../../components/common/Icon"; -import { UserManagementPage } from "../../components/admin/UserManagementPage"; -import { ProjectManagementPage } from "../../components/admin/ProjectManagementPage"; +import { UserManagementPage } from "./UserManagementPage"; +import { ProjectManagementPage } from "./ProjectManagementPage"; import "../../styles/admin.css"; diff --git a/frontend/app/components/admin/UserManagementPage.tsx b/frontend/app/features/admin/UserManagementPage.tsx similarity index 99% rename from frontend/app/components/admin/UserManagementPage.tsx rename to frontend/app/features/admin/UserManagementPage.tsx index df5233d..973cab8 100644 --- a/frontend/app/components/admin/UserManagementPage.tsx +++ b/frontend/app/features/admin/UserManagementPage.tsx @@ -4,6 +4,8 @@ import { ApiRequestError, type Employee } from "../../services/api"; import { useApi, useAuth } from "../../context/AuthContext"; import Icon from "../../components/common/Icon"; +import "../../styles/admin.css"; + const EMPTY_FORM = { username: "", display_name: "", diff --git a/frontend/app/components/admin/UserMultiSelect.tsx b/frontend/app/features/admin/UserMultiSelect.tsx similarity index 100% rename from frontend/app/components/admin/UserMultiSelect.tsx rename to frontend/app/features/admin/UserMultiSelect.tsx diff --git a/frontend/app/components/platform/CreateFolderModal.tsx b/frontend/app/features/platform/CreateFolderModal.tsx similarity index 97% rename from frontend/app/components/platform/CreateFolderModal.tsx rename to frontend/app/features/platform/CreateFolderModal.tsx index 7a9ac44..e862fb1 100644 --- a/frontend/app/components/platform/CreateFolderModal.tsx +++ b/frontend/app/features/platform/CreateFolderModal.tsx @@ -1,5 +1,5 @@ import { type FormEvent } from "react"; -import Icon from "../common/Icon"; +import Icon from "../../components/common/Icon"; type CreateFolderModalProps = { open: boolean; diff --git a/frontend/app/components/platform/CreateScriptModal.tsx b/frontend/app/features/platform/CreateScriptModal.tsx similarity index 99% rename from frontend/app/components/platform/CreateScriptModal.tsx rename to frontend/app/features/platform/CreateScriptModal.tsx index b02ae45..e70ee0c 100644 --- a/frontend/app/components/platform/CreateScriptModal.tsx +++ b/frontend/app/features/platform/CreateScriptModal.tsx @@ -1,5 +1,5 @@ import { type FormEvent } from "react"; -import Icon from "../common/Icon"; +import Icon from "../../components/common/Icon"; import type { ScriptType, Visibility } from "../../services/api"; type NewScriptForm = { diff --git a/frontend/app/features/platform/DashboardRoute.tsx b/frontend/app/features/platform/DashboardRoute.tsx index e5e3d49..91fafa9 100644 --- a/frontend/app/features/platform/DashboardRoute.tsx +++ b/frontend/app/features/platform/DashboardRoute.tsx @@ -2,7 +2,7 @@ import { useEffect } from "react"; import { useNavigate } from "react-router"; import { useAuth } from "~/context/AuthContext"; -import { DashboardPage } from "../../components/admin/DashboardPage"; +import { DashboardPage } from "../admin/DashboardPage"; import { useScriptWorkspaceStore } from "./state/scriptWorkspaceStore"; export default function DashboardRoute() { diff --git a/frontend/app/components/platform/DataResourceUploadModal.tsx b/frontend/app/features/platform/DataResourceUploadModal.tsx similarity index 98% rename from frontend/app/components/platform/DataResourceUploadModal.tsx rename to frontend/app/features/platform/DataResourceUploadModal.tsx index 8f0f363..ac1038c 100644 --- a/frontend/app/components/platform/DataResourceUploadModal.tsx +++ b/frontend/app/features/platform/DataResourceUploadModal.tsx @@ -1,5 +1,5 @@ import { type FormEvent } from "react"; -import Icon from "../common/Icon"; +import Icon from "../../components/common/Icon"; import type { Visibility } from "../../services/api"; type DataResourceUploadModalProps = { diff --git a/frontend/app/components/platform/PublishModal.tsx b/frontend/app/features/platform/PublishModal.tsx similarity index 98% rename from frontend/app/components/platform/PublishModal.tsx rename to frontend/app/features/platform/PublishModal.tsx index 867a9fe..bb20c4d 100644 --- a/frontend/app/components/platform/PublishModal.tsx +++ b/frontend/app/features/platform/PublishModal.tsx @@ -1,5 +1,5 @@ import { type FormEvent } from "react"; -import Icon from "../common/Icon"; +import Icon from "../../components/common/Icon"; import type { ScriptItem, Visibility } from "../../services/api"; import { scriptIcon } from "../../features/platform/WorkspaceTree"; diff --git a/frontend/app/components/platform/ScriptExplorer.tsx b/frontend/app/features/platform/ScriptExplorer.tsx similarity index 99% rename from frontend/app/components/platform/ScriptExplorer.tsx rename to frontend/app/features/platform/ScriptExplorer.tsx index 3436cb1..d3957f1 100644 --- a/frontend/app/components/platform/ScriptExplorer.tsx +++ b/frontend/app/features/platform/ScriptExplorer.tsx @@ -1,5 +1,5 @@ import { type ChangeEvent, type MouseEvent as ReactMouseEvent, type RefObject, useMemo } from "react"; -import Icon from "../common/Icon"; +import Icon from "../../components/common/Icon"; import { WorkspaceTreeGroup } from "~/features/platform/WorkspaceTree"; import { useScriptWorkspaceStore } from "~/features/platform/state/scriptWorkspaceStore"; import type { ScriptItem, WorkspaceDirectory } from "~/services/api"; diff --git a/frontend/app/features/platform/ScriptsPage.tsx b/frontend/app/features/platform/ScriptsPage.tsx index b55d0d4..02d6d4a 100644 --- a/frontend/app/features/platform/ScriptsPage.tsx +++ b/frontend/app/features/platform/ScriptsPage.tsx @@ -1,14 +1,14 @@ import { type FormEvent, useEffect, useMemo, useRef } from "react"; import { useAuth } from "../../context/AuthContext"; -import { CreateFolderModal } from "../../components/platform/CreateFolderModal"; -import { CreateScriptModal } from "../../components/platform/CreateScriptModal"; -import { DataResourceUploadModal } from "../../components/platform/DataResourceUploadModal"; +import { CreateFolderModal } from "./CreateFolderModal"; +import { CreateScriptModal } from "./CreateScriptModal"; +import { DataResourceUploadModal } from "./DataResourceUploadModal"; import Icon from "../../components/common/Icon"; -import { PublishModal } from "../../components/platform/PublishModal"; -import { ScriptExplorer } from "../../components/platform/ScriptExplorer"; -import { TreeContextMenu } from "../../components/platform/TreeContextMenu"; -import { VersionReceiptModal } from "../../components/platform/VersionReceiptModal"; +import { PublishModal } from "./PublishModal"; +import { ScriptExplorer } from "./ScriptExplorer"; +import { TreeContextMenu } from "./TreeContextMenu"; +import { VersionReceiptModal } from "./VersionReceiptModal"; import { getSessionCache, useScriptWorkspaceStore } from "./state/scriptWorkspaceStore"; import { useUiStore } from "./state/uiStore"; diff --git a/frontend/app/components/platform/TreeContextMenu.tsx b/frontend/app/features/platform/TreeContextMenu.tsx similarity index 99% rename from frontend/app/components/platform/TreeContextMenu.tsx rename to frontend/app/features/platform/TreeContextMenu.tsx index 0e1a2ca..75253ea 100644 --- a/frontend/app/components/platform/TreeContextMenu.tsx +++ b/frontend/app/features/platform/TreeContextMenu.tsx @@ -1,4 +1,4 @@ -import Icon from "../common/Icon"; +import Icon from "../../components/common/Icon"; import type { ScriptItem, ScriptType } from "../../services/api"; type ContextMenuState = { diff --git a/frontend/app/components/platform/VersionReceiptModal.tsx b/frontend/app/features/platform/VersionReceiptModal.tsx similarity index 96% rename from frontend/app/components/platform/VersionReceiptModal.tsx rename to frontend/app/features/platform/VersionReceiptModal.tsx index 21396d9..964946d 100644 --- a/frontend/app/components/platform/VersionReceiptModal.tsx +++ b/frontend/app/features/platform/VersionReceiptModal.tsx @@ -1,4 +1,4 @@ -import Icon from "../common/Icon"; +import Icon from "../../components/common/Icon"; import type { StableVersion } from "../../services/api"; import { copyToClipboard } from "../../lib/clipboard";