# React + Ant Design 前端 ## 当前业务页面(2026-10-07) 业务编辑、详情、结果及预览视图统一使用 DetailPage,在主工作区展示,提供返回及底部操作;旧 Dialog 业务弹框入口删除。ConfirmDialog/Modal 仅用于删除、断开关联和放弃修改等短确认。下面的弹框验收属于历史记录。认证方式与 Kubeconfig 选择、错误显示位置及未保存提醒同步调整,详见 [工作区交互](workspace-ui.md)。 ## 最新清理范围(2026-10-06) 按最新要求,前端旧适配、旧页面和旧测试属于清理范围;数据库迁移保留,覆盖此前删除后端迁移的决定。后端负责旧库凭据、账号权限和代理引用的转换,前端不再补齐旧字段。S3 设置存储保持删除。 删除旧 ocean 主题到 light 的专用映射;非当前主题值统一采用 system。CSRF 浏览器测试已改用当前 React/Ant Design 的协议选择、账号字段和保存状态,保留过期令牌刷新及只创建一次的行为断言。 清理尚未全部完成:自动审批拒绝批量删除旧 Vue 测试,以及删除独立 Kubernetes/TCP 编辑路径,理由是可能移除现用功能或其覆盖。因此保留被拦截文件和测试发现规则,没有将未运行或旧选择器失败计为通过。 ## 原生组件与表单边界(2026-10-06) 删除 `web/src/react/components.tsx` 中沿用旧 UI 框架接口的适配层。各页面直接使用 Ant Design 的 Button、Tabs、Modal、Collapse、Table 和 Typography;表格使用 columns/dataSource,应用 CSS 只承担布局。下列早期迁移记录保留作历史,不代表适配层仍存在。 目标编辑器按协议显示字段:SSH/SFTP 不显示 TLS,TCP 不提供 TLS 终止,CA 仅在启用 TLS 时出现;默认数据库仅属于 MySQL/Redis;Sentinel 认证账号仅在 Redis Sentinel 模式显示。无认证账号不显示用户名/密码,SSH 私钥认证不显示密码。代理管理按 SOCKS5/SSH/Kubernetes/sing-box 类型隔离字段。 删除账号 name → remark、顶层网关凭据 → 账号数组和网关访问模式 → 账号模式的前端补齐逻辑。账号未指定权限时独立默认为读写,不继承网关旧权限。新格式以账号数组及共享代理引用为准。API、存储和桌面路径测试同步使用当前格式。 验证使用临时数据库、隔离端口和重新嵌入前端的程序;当前专项结果见变更记录。旧 Vue `.el-*` / `.target-card` 浏览器用例尚未全部迁移,不能将专项通过宣称为全套通过。 ## 界面密度与小屏编辑优化(2026-10-04) 原因:Ant Design 迁移后,查询卡片同时叠加应用 padding 与框架 padding,列设置独占整张卡片,手机编辑器整体高度超过视口,保存与取消需要长距离滚动;导航符号及主题标签也占据重复空间。 结果:查询区删除重复 padding,资源关键词前置,统一收紧字段、页面与标题间距;标题说明使用 Ant Design secondary 文本。列设置改为列表工具栏的 Popover,增加当前筛选结果总数,仍复用原列偏好键。导航使用统一 Ant Design 图标与 Tooltip,保留中文可访问名称、资源计数与小屏图标栏。主题下拉隐藏视觉标签但保留关联 label 和“主题”可访问名称。无资源时提供创建入口,已有资源但筛选为空时提供“清除筛选”,同时清空资源关键词、协议、状态及工作区项目/环境,保留分组和列偏好。 编辑与确认弹窗限制在当前视口内:标题和底部动作固定在弹窗布局中,内容区独立滚动,窄屏底部账号选择独占一行,保存/测试/取消始终可达。使用 Ant Design 默认主题与控件外观,CSS 只调整布局、滚动和视觉隐藏标签。新导航与列设置视图分别位于 WorkspaceNavigation.tsx、resources/ResourceColumns.tsx;App.tsx 继续协调范围状态。 范围与兼容:影响工作区导航、主题工具栏、资源查询/列表及共享弹窗;清除筛选会更新既有非敏感筛选偏好,无新增存储格式、HTTP API 或 SQLite schema 变化,不需数据迁移。凭据省略、未保存确认和请求权限不变;未部署、重启真实服务或修改真实 data。 实际验证:TypeScript / Vite 生产构建通过,恢复 web/dist/.gitkeep;Go 1.27.1 新嵌入 bin/dev-build/ui-polish/linkport-final.exe,以 LINKPORT_E2E_BINARY、临时 SQLite 和 18451/18452 端口运行 React 迁移/domain Playwright,13/13 通过。额外隔离 18431 端口验收空资源创建、空搜索/范围结果清除及列偏好跨刷新保留;11 个菜单 × 浅深主题 × 1440/1024/390/320px 共 88 组检查无 pageerror 或页面横向溢出,8 组编辑器在滚动内容前后保存按钮均完全位于视口内,截图 16 张。浏览器使用本机真实管理 API 和隔离配置;没有连接真实数据库、SSH、Kubernetes 或 WebDAV 目标。日志与截图位于 bin/dev-build/ui-polish。 Go vet ./... 通过。全量 go test ./... -count=1 -timeout=120s 仍失败于 API 的同步口令保留、cluster 的 MySQL fixture nil panic、desktop 的数据路径用例与 syncjob 的两个明文秘密断言,与前轮记录一致;协议包通过但不代表真实服务器验证。首次 Go 与 Playwright 并发时,Go 目录扫描撞上 web/test-results 清理,报目录不存在;浏览器完成后重新执行 Go 检查,上述为重跑结果。 完整旧 Playwright 套件发现 146 项,使用 --max-failures=1 --timeout=15000 运行后,首项 account-editor 因依赖旧 .target-card / “配置目标”失败,145 项未运行,另有停止后的 suite 级错误提示;不能把专项通过视为旧套件全部通过。构建保留 Node 22.10.0 低于 Vite 推荐版本与约 1.22 MB JS chunk 提示。git diff --check 通过。 ## 当前实现:Ant Design(2026-10-04) 用户要求将前端改为 React + Ant Design。沿用现有 React 19 页面与 hooks,全部界面控件迁移至 Ant Design 6,并移除 MUI、MUI icons 与 Emotion 依赖。图标使用 `@ant-design/icons`;根组件使用中文 `ConfigProvider` 与默认/深色算法,入口加载 Ant Design reset。应用级组件接口集中在 `web/src/react/components.tsx`,内部使用原生 Ant Design Input、Select、Checkbox、Switch、Tabs、Modal、Collapse、Card、Table、Alert、Tag 和 Typography;表格将页面列与行映射为 Ant Design columns/dataSource,保持关闭分页和横向滚动。布局样式不再依赖 MUI DOM 类名。 范围:登录、导航、资源、编辑器、画布、审计、资产和辅助页。管理 API、Go 协议、SQLite schema、主题偏好键、草稿提交与留空凭据保护沿用当前 React 行为,无数据库或真实 data 迁移。只生成隔离验收程序,不替换运行中的本机服务。下拉与弹窗 DOM 改为 Ant Design,可访问名称继续使用原中文标签。旧 Vue 和历史 MUI 验收记录不代表当前版本通过。 前端 TypeScript / Vite 生产构建通过;Go 1.27.1 重新嵌入 `bin/dev-build/antd/linkport.exe` 后,使用临时 SQLite 与隔离 18391/18392 端口运行 react-migration.spec.ts、ui-domain.spec.ts,13/13 通过(14.6 秒)。三个 Node domain 文件 16/16 通过;`go vet ./...` 通过。最终新程序完成 11 个菜单 × 浅深两种主题 × 1440/1024/390/320px 共 88 组检查,无 pageerror 或页面横向溢出,16 张截图在 `bin/dev-build/antd`。管理请求使用真实本机 API,阶段错误使用 HTTP 响应 fixture;没有连接真实数据库、SSH、Kubernetes 或 WebDAV 目标。恢复 `web/dist/.gitkeep`,未部署或修改真实 data。 `go test ./... -count=1 -timeout=120s` 未通过:API 的 TestWebDAVSyncSettingsAndAuthorization(同步口令未保留)、cluster 的 TestMySQLReplicationAndGroupDiscovery(fixture nil panic)、desktop 的路径相关用例、syncjob 的两个明文秘密断言失败,与既有记录一致;协议包均通过,不能视为真实上游服务器验证。日志见 `bin/dev-build/antd/go-test.log`。构建仍有 Node 22.10.0 低于 Vite 推荐版本及约 1.20 MB JS chunk 提示,构建成功。 完整 Playwright 套件发现 146 项,使用 `--max-failures=5` 执行后 5 项失败、141 项未运行,另有停止后的 suite 级错误提示。失败来自 account-editor(2 项)、account-targets(1 项)、asset-editor-dialog(2 项),仍依赖旧 Vue 的 `.target-card`、`.el-select`、`.connection-editor` 及“配置”“+ 新建目标”等旧文案;未迁移的旧用例不记为通过。日志在 `bin/dev-build/antd/playwright-suite.log`。最终 13 项当前 React 专项通过与完整旧套件结果分别记录,`git diff --check` 通过。 以下为迁移历史。 2026-10-04 按用户要求,先将生产前端从 Vue 3 / Element Plus 改为 React 19 / HeroUI 3,并删除旧主题、控件、响应式 CSS 和 Vue 组件。随后按“使用 MUI”的要求,将全部控件改为原生 MUI 9 与 Emotion;HeroUI 依赖及组件调用已移除。没有保留 Vue 运行时、嵌入旧页面或混合架构。Vite 使用 React 与 Tailwind 插件,生产构建执行 TypeScript 检查。HeroUI 阶段的历史原因及验收记录仍保留在变更和测试文档中。 ## 外观与布局 网关、目标和概览的项目/环境与资源查询条件集中在标题下的同一个 MUI Card,范围操作位于卡片底部,窄屏自动换行;详见 [工作区交互](workspace-ui.md)。 控件、卡片、表格、标签、提示、开关、下拉框和弹窗采用 MUI 原生组件及默认主题。`App.tsx` 使用 `ThemeProvider`、`createTheme({ palette: { mode } })` 和 `CssBaseline`,只选择浅色或深色,不自定义 palette、typography 或组件外观。标题和说明使用 `Typography`;卡片使用 `Card` / `CardContent`,表单使用 `TextField` / `MenuItem`,弹窗使用 `DialogTitle` / `DialogContent` / `DialogActions`。没有将 MUI 包装成 HeroUI compound API。`web/src/react/layout.css` 及 Tailwind 工具类仅定义工作区几何布局、间距、滚动、画布位置和移动排列,不覆盖框架的配色、圆角、阴影、控件字体或状态外观。 主题提供浅色、深色、跟随系统,继续使用 `linkport-theme`。原自定义海蓝主题移除,保存的 `ocean` 自动转为浅色。项目、环境和侧栏视图继续使用既有存储键;画布布局继续使用原 scope 布局键。新的列偏好和最近访问使用 React 存储键,旧 Vue 列宽设置不迁移。密码与编辑草稿不存入 localStorage。 ## 实现职责 | 入口 | 职责 | | --- | --- | | `web/src/main.tsx` | React 根与布局入口 | | `web/src/react/App.tsx` | 登录、菜单、范围、资源检索、标签、资源刷新、401 清理 | | `web/src/react/api.ts` | 同源会话、CSRF、错误诊断;只对明确的 CSRF 中间件拒绝重试一次 | | `web/src/react/ConnectionEditor.tsx` | 目标与网关草稿、账号映射、TLS、出口、集群、URL、保存与测试 | | `web/src/react/ResourcesPage.tsx` | 列表、启停、引用保护、密码查看、运行状态、指纹、客户端示例 | | `web/src/react/CanvasPage.tsx` | 拖动、键盘关联、断开确认、布局及缩放 | | `web/src/react/pages` | 审计、命令输出、资产、配置备份、WebDAV、解密 | | `web/src/react/pages/ui.tsx` | 原生 MUI 表单、对话框、表格与操作反馈;保留应用级 props 接口 | | `web/src/react/Operations.tsx` | 健康、告警、日志设置及 Token | | `web/src/domain` | 保留协议、草稿、校验和凭据提交规则;提取不依赖 UI 的范围、资源与标签模型 | 目标保存后保留编辑器以便执行已保存目标的连接测试;网关保存后关闭。留空已保存密码、私钥等敏感值时继续省略相应提交字段,避免清空凭据。资产编辑留空内容也省略 `content`;编辑运行或被引用资源遵循后端约束。资源密码限时显示,换账号、关闭详情和过期请求不会继续显示迟到结果。 ## 交互变化与兼容范围 HTTP API、Go 协议和 SQLite schema 未更改,不需要数据库或真实 data 迁移,也未部署或修改真实 data。MUI 替换只改变前端组件、主题来源和 DOM;项目/环境、偏好存储键、草稿提交规则和上述秘密保护继续沿用 React 版行为。复杂网络代理参数通过完整 JSON 高级编辑,替代旧 Vue 的每字段专用表单;复杂影响、历史对比及审计记录采用可读 JSON。MySQL 审计结果按可读 NDJSON 输出并支持下载,未复刻原专用结果表格。资产需先在代理管理的文件与凭据页创建,再在连接编辑器选择。数据库恢复保持停服 CLI 流程。 删除、覆盖和冲突等操作仍要求显式确认;部分辅助页使用浏览器确认框。移动端保留常驻图标导航,原生标题/中文可访问名称用于导航识别。MUI 下拉控件通过 `combobox` 和 `option` 选择,浏览器验收不再依赖 HeroUI 的 `data-slot` 或按钮式 Select DOM。历史依赖 `.el-*`、Vue 工作区子页面 DOM 或旧文案的浏览器用例仍需要迁移;不能把这些旧用例失败计为通过。 ## 验证 连接详情测试失败若未收到服务器 stage,不再生成 unknown 阶段结论:显示管理请求失败提示、HTTP 状态(若有)和不含查询参数的 API 路径。服务器明确返回的阶段仍采用既有诊断解释;不展示任意响应正文,不推断密码或目标网络状态。2026-10-04 新构建程序隔离 Playwright 13 项通过,包含无阶段 HTTP 400 / 有阶段 422 的响应 fixture 回归与敏感正文不显示检查。 MUI 生产构建、Go 1.27.1 新嵌入 `bin/dev-build/mui/linkport.exe`、隔离 18241/18242 及临时 SQLite 的 13 项迁移/domain Playwright 完整复测通过(11.5 秒);三个 Node domain 文件共 16 项通过,`git diff --check` 通过。首次 DialogTitle 重复 id 导致的三项可访问名称失败已修正后重新构建和完整复测,历史记录保留。1440、1024、390、320px 额外检查无横向溢出或 pageerror,亮暗、移动与编辑器截图在 `bin/dev-build/mui`。 完整实际记录见 [变更原因](change-rationale.md) 与 [测试记录](testing.md)。浏览器验收使用当前前端构建后重新嵌入的程序,没有沿用 HeroUI 产物。本轮无后端或真实 data 变更,未重复后端包测试,也未验证真实 Kubernetes、SSH、数据库或 WebDAV 服务器;旧 Vue suite 和前轮已知后端失败不能据此视为通过。