Migrate the workspace to React and Ant Design, improve account forms and responsive layouts, support outbound diagnostics and SSH fingerprint confirmation, and persist the management startup port. Preserve database migrations, remove S3 settings storage, and improve gateway audit handling.
15 KiB
全模块设计模式与扩展边界
当前 React + Ant Design(2026-10-04)
按用户最新要求,生产前端使用 React 19 与 Ant Design 6,删除 MUI / Emotion 依赖。App.tsx 通过 ConfigProvider 选择默认浅色或深色算法并提供中文语言包,组件外观来自 Ant Design。web/src/react/components.tsx 将现有页面接口映射到 Input、Select、Switch、Checkbox、Tabs、Modal、Collapse、Card、Table、Alert、Tag 与 Typography,避免组件库替换影响领域逻辑;应用 CSS 仅管理布局。接口、SQLite schema、主题偏好键及秘密省略规则不变,无数据迁移。当前验证见 React 迁移;下面 MUI / HeroUI 记录为历史,不代表当前版本验收。
2026-10-04 前端实现已迁移为 React,最新界面采用原生 MUI 9 / Emotion,先前 HeroUI 已移除。当前导航、会话和 ThemeProvider / CssBaseline 组合根是 web/src/react/App.tsx,请求边界是 web/src/react/api.ts,业务视图位于 web/src/react,纯领域规则仍位于 web/src/domain。pages/ui.tsx 保留应用级 Field / Pick / Dialog / Table 接口,内部直接使用 MUI TextField、MenuItem、Dialog 和 Table 系列;不模拟另一框架的 compound API。主题仅选择 palette.mode,布局 CSS 不承担组件外观。此次框架替换无 API、SQLite schema 或真实 data 迁移,也不移动 Go 模块边界。下文 Vue composable 路径属于历史记录,已经删除;当前模块映射与交互变化见 React 迁移。
当前前端生产构建及新嵌入 bin/dev-build/mui/linkport.exe 的 13 项迁移/domain Playwright 完整复测通过,三个 Node domain 文件共 16 项通过;首次 MUI DialogTitle 标题 id 重复问题已修正后重新构建。此轮没有改动或重复测试后端包,历史已知失败和真实协议验证边界保留,详见 测试记录。
2026-09-27 的重构覆盖启动、领域模型、API、运行网关、协议、出口、集群、存储、后台任务和前端,并逐项审查工具与基础设施边界。采用 Go 函数、消费者侧接口和 Vue composable 表达设计模式,没有增加依赖或通用框架。下表区分实际拆分与已经具备清晰边界而保留的模块;不要求每个文件都发生改动。
| 模块 | 模式 | 解决的问题 | 实现入口 |
|---|---|---|---|
| 网络出口 | 策略 + 工厂 | 选择出口与 SOCKS5 字节握手混在同一函数,新增出口容易碰到其他协议 | internal/outbound/strategy.go 的 newDialStrategy |
| 公共拨号策略 | 装饰器 | 各出口都需要按调用校验配置、设置建连期限并释放 context | internal/outbound/dial.go 的 withConnectionOptions |
| 网关操作 | 命令 | server.go 同时处理认证、分发和启停/测试/主机指纹业务 |
internal/api/gateway_actions.go 的 gatewayActions |
| 前端资源目录 | 门面 + 依赖注入 | App.vue 在刷新、保存、401 和退出中分别维护缓存及竞态控制 |
web/src/composables/useResourceCatalog.ts |
| 启动与命令 | 组合根 + 命令 | 数据初始化、维护命令、TLS、运行恢复和 HTTP 生命周期混在 run 中 |
cmd/linkport/{main,commands,bootstrap,management}.go |
| 协议注册 | 工厂 | 启动入口直接依赖全部协议实现 | internal/protocol/handlers.go 的 NewHandlers |
| API 请求 | 管线 + 适配器 | 身份验证、会话绑定和锁内路由与领域操作耦合 | internal/api/{authorization,routes}.go |
| 网关会话 | 会话对象 + 装饰器 | 接受循环同时管理审计、认证、流量和异常释放 | internal/gateway/{session,instance}.go |
| 集群发现 | 策略 + 遍历模板 | 节点调度直接绑定各协议探测函数 | internal/cluster/{cluster,strategies}.go |
| 告警 | 规则评估 + 通知适配器 | 生命周期、告警规则和 HTTP 投递混合 | internal/alerts/{engine,conditions,notifier,repository}.go |
| 同步与备份 | 端口与适配器 | 调度/租约与 WebDAV 传输、冲突流程混合 | internal/syncjob/{engine,transfer,repository}.go、internal/backup/object_store.go |
| 备份编码 | 编解码边界 | 数据快照和加密信封难以独立维护 | internal/store/backup_codec.go |
| 连接编辑 | 草稿工厂 + 载荷构建器 | 默认值、旧账号适配与提交白名单集中在 App | web/src/domain/connectionDraft.ts |
| 凭据、分页与画板 | 会话状态 + 加载模板 + 浏览器适配器 | 请求失效、计时清理、游标和 DOM 生命周期散落在视图 | useSecretReveal、useCursorPage、useCanvasFullscreen、useCanvasMeasurements |
全模块覆盖清单
| 范围 | 处理结果与保留边界 |
|---|---|
cmd/linkport |
拆分组合根、独立/维护命令、证书/运行恢复和管理服务生命周期;独立命令仍先于数据初始化 |
internal/model |
proxy.go 保留配置快照;网关账号结构及应用逻辑归入 gateway_account.go;runtime.go 集中 Handler/DialFunc/TestResult;其余配置、校验、脱敏、凭据规则按原领域划分保留 |
internal/api |
认证适配、路由及锁边界和网关命令拆分;目标、出口、资产、配置、审计、监控、令牌和工具端点继续归属各领域文件 |
internal/gateway |
会话审计/认证/释放与实例停止独立;健康检查、持久目标、连接列表、运行中更新和目标切换保留专门模块 |
internal/protocol |
工厂集中全部 11 个协议名;9 个处理目录继续实现 Handler,可准备会话的协议继续实现 SessionPreparer;wire/auth/SQL policy 不改写 |
protocol/transport、protocol/amqpprobe |
保留公共连接装饰器、账号检查与 AMQP 探测适配器,避免重复包装 |
internal/outbound |
已完成策略/工厂/选项装饰器;SSH、SOCKS5、Kubernetes、sing-box、持久传输及诊断继续按传输划分 |
internal/cluster |
固定协议探测策略与遍历模板分离;Redis 与数据库探测实现保留 |
internal/store |
备份编解码独立;资源仓储、历史、迁移、审计分片与快照一致性维持原领域边界,没有泛型仓储或 SQL/schema 变更 |
internal/alerts |
Repository 接口、规则与通知分离,Engine 只编排生命周期、持久化和重试 |
internal/syncjob |
Repository 接口、调度/租约与传输流程分离,配置修订和完整替换仍由 store 保证 |
internal/backup |
增加条件对象存储接口与 WebDAV 适配器;已有 S3 签名、WebDAV HTTP 和加密同步格式保持独立 |
web/src |
App 协调页面;资源目录、连接草稿、凭据会话、游标和画板浏览器逻辑抽离;既有 API/CSRF、页签、作用域、未保存守卫、配置历史、资产、监控、同步及领域函数继续复用 |
internal/desktop |
保留数据路径策略、平台构建标签、进程锁、设置页面与打开浏览器的独立适配文件 |
internal/security |
保留 Vault 加密与平台私有文件权限适配,未更改密码学或权限策略 |
internal/localcert、cmd/devcert |
保留单用途证书生成模块与薄 CLI 入口 |
internal/cryptotool、internal/navicat |
保留独立解密算法/兼容格式边界,API 仍只做输入与响应适配 |
internal/buildinfo、根 version.go |
保留构建元信息与嵌入默认版本的单向依赖 |
internal/testutil、deploy/fixtures |
保留测试出口适配器与隔离 fixture;不进入生产业务流程 |
web/embed.go、scripts、部署配置 |
保留静态资源适配器、构建锁、工具链、路径/版本、缓存、打包和验收脚本的独立边界;不修改发布和部署行为 |
已移除的 SQLite 文件浏览模块不重新引入;残留空目录不视为待重写模块。第三方依赖、生成文件和真实 data 不属于本轮重构对象。
启动、模型与请求管线
run 是组合根:选择命令、准备带进程锁的数据目录、打开 Store、配置管理员、创建 TLS 和协议工厂、恢复 Manager,最后进入管理服务。commands.go 区分无需打开应用数据的命令与需要已打开 Store 的维护命令;保留版本输出、参数错误、迁移提示、密码输入和退出顺序。management.go 独占监听器、首次设置、浏览器启动、小时清理和 30 秒关闭期限。
模型配置不依赖运行模块。runtime.go 集中协议协作接口,gateway_account.go 集中账号的有效性、目标映射、应用与校验;只是文件职责移动,公开名称、JSON 标签、秘密字段和只读上限不变。
API 顺序保持为来源检查、登录特例、Bearer/本地开发/cookie 身份验证、作用域与 CSRF、路由分发。requestIdentity 按请求传递会话和确认绑定 ID;Token 响应继续经过脱敏 writer。dispatchMutation 保留原 ops 锁范围,列表与 WebDAV 等原先锁外流程不移动到锁内。新增端点应在领域文件实现并显式选择路由和锁边界。
运行会话、协议与集群
connectionSession 包装 Handler 执行,集中审计上下文、账号认证计数、流量统计和完成事件。保留接受时快照、Manager.mu/auditMu 顺序、panic 恢复以及释放连接名额、关闭 socket、完成 WaitGroup、取消 context 的顺序。instance.stopLocked 只负责停止标记/取消/关闭监听;waitStopped 必须在 Manager 锁外等待和关闭持久目标。
protocol.NewHandlers 每次返回独立 map,HTTP/HTTPS、SSH/SFTP 仍分别调用构造器。新增业务协议先实现 model.Handler,再加入工厂及协议模型/界面,不向 main.go 增加协议依赖。
集群遍历注入探测函数,生产入口选用私有策略目录。节点顺序、拓扑筛选、Sentinel 到数据节点的账号切换、20 秒总体期限、3 秒单次探测和 64 节点限制不变。
告警、同步和持久化
告警的 Repository 是消费者需要的存储端口,具体的条件更新和去重仍由 Store 完成。规则评估器按既有顺序产生活跃条件;Webhook 适配器保持 HMAC、5 秒期限、禁重定向及最多三次投递。手动 Check 不发送通知。
同步 Engine 保留 TryLock、外部操作 guard、持久 lease、60 秒期限及完成记录;transfer.go 负责基线、冲突和条件对象读写。WebDAV ObjectStore 直接复用原传输,强 ETag、路径限制和取消语义不变;存储端继续保证快照一致性、配置 revision 和完整替换原子性。
backup_codec.go 负责现有 PBKDF2/AES-GCM 信封。口令检查、密钥派生、数据库快照读取的顺序与密文格式保留;同步加密也复用此编解码边界。依据 safe-sql-updates 与 query-before-update 检查并保留已有 SQL、锁和事务边界,本轮没有引入更新语句或迁移。
出口策略与装饰器
flowchart LR
P[Proxy 配置] --> F[newDialStrategy]
F --> S[直连 / SOCKS5 / SSH / Kubernetes / sing-box]
S --> D[withConnectionOptions]
D --> C[统一 DialFunc]
Dialer 仍是协议处理器、健康检查和网关调用的公共入口。工厂只选择函数和默认超时,不创建连接或外部进程;SOCKS5 握手实现独立在 socks5.go。装饰器每次调用校验 ConnectionOptions,然后创建有期限的子 context。各策略继续在调用时读取 KeepAlive,避免指针选项变化后使用缓存值。
默认期限仍为 Kubernetes 30 秒、其他出口 5 秒;显式配置优先,调用者更短的期限不会被延长。成功连接的生命周期仍由原有传输实现负责。保留 SOCKS5 认证/目标协商的错误包装与诊断阶段、域名透传和失败清理;未知出口模式仍直接拒绝,失败不回退直连。
增加出口时,在对应传输文件实现拨号函数,再在工厂中增加选择分支,并验证域名传递、期限、错误诊断和取消清理。无需修改协议 Handler。
网关命令分发
server.go 组织公共请求管线,authorization.go 适配身份与 CSRF,routes.go 保留路由顺序及 ops 串行锁。网关列表交给 proxies.go,资源路径及方法校验交给 proxyRoutes;只有通过校验的 POST 操作才从私有命令表选择处理函数。
命令覆盖 target、start、stop、test、probe、confirm-host-key、reveal-password。gatewayActionRequest 按请求传递配置快照、会话和会话 ID,不把凭据或状态存入全局命令表。
启停仍使用 Manager.StartFrom / StopAndPersist 的原有保存回调,保留保存失败与生命周期冲突的 HTTP 状态区别。SSH 指纹确认继续校验会话、目标地址、过期时间与指纹。路由仍先查询网关,再检查操作及方法,保持既有 404/405 优先级。
新增网关动作应放入对应领域函数,在命令表声明入口,并检查 Token 权限与请求校验。命令表不负责授权。
前端资源门面
useResourceCatalog 注入 request 和 report,持有网关、目标、出口及文件资产列表。对外提供 refresh、acceptSavedResponse 和 clear,隐藏刷新代次、整体提交和加载状态维护。
- 五个读取接口全部成功且代次仍有效时,一次性发布四类列表和范围元数据;部分失败保留先前缓存。
- 创建/保存响应按资源 ID 更新对应列表,并使此前在途读取失效,旧读取不能覆盖已保存版本。
- 退出或 401 调用
clear,清空资源并使在途读取失效。 - 页面协调回调拿到
isCurrent,概览异步数据仍同时检查范围与请求代次。
App.vue 继续负责作用域、页面、标签、会话、审计加载及导航。门面不依赖 Element Plus、路由或 localStorage,测试可以直接注入可控 Promise 验证竞争顺序。useApi 的 CSRF 限定重试机制未改动。
连接草稿工厂接收范围和 ID 生成器;编辑适配器深复制配置,兼容旧账号;保存构建器维持目标/网关白名单、空秘密字段省略、SSH 和无账号规则。凭据会话通过请求代次避免已关闭页面被旧响应填回,并保持 30 秒清理。事件与命令复用游标加载模板,旧响应/失败不能覆盖新筛选。画板全屏与 DOM 测量分开处理事件、ResizeObserver 和卸载清理;绑定规则与布局不变。
本轮按 multilingual-ui 审查前端;该技能的 Shopee 专用 i18n 路径不适用于本项目,且没有新增或修改产品文案。现有持久连接 SSR 测试中“必须重启网关”的旧断言已对齐此前运行中编辑功能的“修正配置并保存后重试”指引,未更改界面或运行行为。
兼容与验证
这是结构重构,不变更产品文案、HTTP 路径/载荷/状态约定、配置字段、数据库结构、协议或已有功能。没有数据迁移,也没有操作真实 data。旧配置及本轮之前的工作区改动均保留。
验证使用隔离数据库、本机协议 fixture 和注入请求,不作为真实远端服务器验收。新增回归检查出口期限及无直连回退、命令路由/会话绑定、资源刷新的并发次序;全量测试和构建的实际结果见 测试记录。