From 805eea5bd6048dba70d329c9c340cac00b9f3ac9 Mon Sep 17 00:00:00 2001 From: ryan Date: Thu, 24 Sep 2026 11:44:43 +0800 Subject: [PATCH] docs: add design spec for cloudflare member move and ip-group search --- ...e-group-move-and-ip-group-search-design.md | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 docs/superpowers/specs/2026-09-24-cloudflare-group-move-and-ip-group-search-design.md diff --git a/docs/superpowers/specs/2026-09-24-cloudflare-group-move-and-ip-group-search-design.md b/docs/superpowers/specs/2026-09-24-cloudflare-group-move-and-ip-group-search-design.md new file mode 100644 index 00000000..f0b3fe57 --- /dev/null +++ b/docs/superpowers/specs/2026-09-24-cloudflare-group-move-and-ip-group-search-design.md @@ -0,0 +1,138 @@ +# Cloudflare 分组域名移动/批量操作与 IP 组查看搜索设计文档 + +- **日期**:2026-09-24 +- **状态**:已批准 (Approved) + +--- + +## 1. 目标与背景 (Goals & Context) + +1. **Cloudflare 分组域名管理增强**: + - 在 `/cloudflare/groups/[id]` 页面,为单个成员域名增加「移动」操作,支持迁移至其他可用分组; + - 增加表格行复选框多选机制与批量操作栏,支持「批量删除」与「批量移动」; + - 确保域名移动后,如果目标分组处于启用状态,自动重新排队向 Cloudflare 同步目标节点的新 IP。 +2. **WAF IP 组查看弹窗增强**: + - 在 `/ip-groups` 的「查看 IP 组」弹窗(`IPGroupViewDialog`)内,新增即时 IP 搜索与过滤功能,方便用户在包含大量 IP 条目时快速查找与定位。 + +--- + +## 2. 后端接口设计 (Backend API) + +### 2.1 数据模型与 DTO + +文件:`internal/apps/openflare/cloudflare/types.go` + +```go +type MemberMoveInput struct { + TargetGroupID uint `json:"target_group_id"` +} + +type MemberBatchMoveInput struct { + MemberIDs []uint `json:"member_ids"` + TargetGroupID uint `json:"target_group_id"` +} + +type MemberBatchRemoveInput struct { + MemberIDs []uint `json:"member_ids"` +} +``` + +### 2.2 路由端点 + +文件:`internal/apps/openflare/cloudflare/routers.go` +注册:`internal/router/v1/openflare/register_cloudflare.go` + +1. **单条移动**: + - 路径:`POST /api/v1/d/cloudflare/groups/:id/members/:memberId/move` + - 请求体:`MemberMoveInput` + - 响应:`200 OK` + `cloudflare.MemberItem` +2. **批量移动**: + - 路径:`POST /api/v1/d/cloudflare/groups/:id/members/batch-move` + - 请求体:`MemberBatchMoveInput` + - 响应:`200 OK` +3. **批量移出/删除**: + - 路径:`POST /api/v1/d/cloudflare/groups/:id/members/batch-remove` + - 请求体:`MemberBatchRemoveInput` + - 响应:`200 OK` + +### 2.3 业务逻辑层 + +文件:`internal/apps/openflare/cloudflare/logics.go` + +- `MoveMember(ctx context.Context, sourceGroupID, memberID, targetGroupID uint) (*MemberItem, error)` + - 检查 `targetGroupID != sourceGroupID`; + - 检查目标分组是否存在且非空; + - 查询原成员,更新 `GroupID = targetGroupID`,将 `SyncStatus` 置为 `pending`,清除 `LastError`,保存到数据库; + - 若目标分组 `Enabled == true`,调用 `DispatchMemberSync(ctx, member.ID, "cloudflare_member_move")` 排队执行远程 A 记录同步; + - 返回更新后的 `MemberItem`。 +- `BatchMoveMembers(ctx context.Context, sourceGroupID uint, input MemberBatchMoveInput) error` + - 校验目标分组有效性; + - 针对 `input.MemberIDs` 过滤去重,对每个成员执行分组归属更新并重置同步状态; + - 若目标分组启用,分发同步任务。 +- `BatchRemoveMembers(ctx context.Context, sourceGroupID uint, input MemberBatchRemoveInput) error` + - 针对每个 `memberID`,校验属于 `sourceGroupID`,调用 `DeleteManagedRecord(ctx, member.ID)` 清除 Cloudflare 上的 A 记录,并调用 `repository.DeleteCFPointingMember(ctx, member)`。 + +--- + +## 3. 前端交互设计 (Frontend UI & Interaction) + +### 3.1 Cloudflare 服务客户端扩展 + +文件:`frontend/lib/services/openflare/cloudflare.service.ts` + +- `moveMember(groupId: number, memberId: number, targetGroupId: number): Promise` +- `batchMoveMembers(groupId: number, memberIds: number[], targetGroupId: number): Promise` +- `batchRemoveMembers(groupId: number, memberIds: number[]): Promise` + +### 3.2 域名成员列表交互 (`frontend/app/(main)/cloudflare/groups/[id]/page-client.tsx`) + +1. **多选管理**: + - `selectedMemberIDs: Set` 状态; + - 表头 Checkbox 支持全部选中/取消选中(含半选状态); + - 每行首列为 Checkbox,行内可单选。 +2. **批量操作栏 (Batch Action Bar)**: + - 当 `selectedMemberIDs.size > 0` 时,在成员卡片头部或列表上方显示批量操作工具条: + - 已选条数提示(Badge); + - 「批量移动」按钮:唤起移动弹窗,包含选中的所有成员; + - 「批量删除」按钮:唤起确认弹窗,明确提示删除的数量与域名,确认后执行批量移出; + - 「取消选择」按钮:清空勾选。 +3. **行级「移动」操作**: + - 行右侧操作按钮区新增「移动」操作按钮; + - 点击唤起 `MemberMoveDialog` 弹窗。 +4. **移动域名弹窗 (`MemberMoveDialog`)**: + - 提取独立组件或子组件,接收待移动的成员列表和全部 Cloudflare 分组列表; + - 过滤排除当前分组,用户下拉选择目标分组; + - 点击确认后执行 `moveMutation` 或 `batchMoveMutation`。 + +### 3.3 WAF IP 组查看弹窗搜索 (`frontend/app/(main)/waf/components/ip-group-view-dialog.tsx`) + +1. **搜索框**: + - 在 DialogHeader 和 IP 列表表格之间,增加搜索过滤条; + - 带 `Search` 图标,清除按钮,响应输入并去除首尾空格; +2. **过滤行为**: + - `searchKeyword` 过滤 `entries` 列表,匹配 `entry.ip`; + - 更新汇总文案:如 `共 50 条 IP (匹配 3 条)`; + - 无匹配时展示特定空状态「未找到匹配的 IP 地址」。 + +--- + +## 4. 国际化与文案 (i18n) + +- `frontend/messages/fragments/cloudflare.zh-CN.json` & `cloudflare.en.json`: + - 增加移动相关文案:`move`, `batchMove`, `batchRemove`, `moveTitle`, `targetGroup`, `selectTargetGroup`, `batchRemoveConfirm`, 等。 +- `frontend/messages/fragments/security.zh-CN.json` & `security.en.json`: + - 增加 `viewDialog` 搜索框文案:`searchPlaceholder`, `matchedCount`, `noMatchFilter`。 + +--- + +## 5. 验证标准 (Verification Criteria) + +1. **后端单测**: + - 针对 `MoveMember`、`BatchMoveMembers`、`BatchRemoveMembers` 编写完整单元测试,验证成功与异常分支(如移到同一分组报错、不存在的分组报错等); + - 执行 `go test ./internal/apps/openflare/cloudflare/...` 全部通过。 +2. **前端测试与校验**: + - 更新或新增前端测试用例覆盖移动与批量删除逻辑; + - 执行 `make code-check` 保证 TypeScript、ESLint 与后端架构规则通过。 +3. **API 文档与更新日志**: + - 执行 `make swagger` 同步 OpenAPI 文档; + - 更新 `docs/changelog/index.md`。