fischer-agentkit/docs/plans/2026-07-03-001-feat-bitable...

38 KiB
Raw Blame History

title type date origin
feat: Bitable P0 UX Polish + Agent Parity feat 2026-07-03 docs/brainstorms/2026-07-03-bitable-comparative-evaluation-requirements.md

Bitable P0 UX Polish + Agent Parity

Summary

引入统一设计 token 系统、补齐 grid 视图 UX 缺口(内联字段配置、记录详情抽屉、视图类型切换、分组与条件格式)、闭合 agent 对等缺口BitableTool 4 新动作 + DELETE /views 端点)。这是 bitable 从"功能残缺"到"grid 体验达飞书/Twenty 水准 + agent 对等"的 P0 交付,分 3 阶段R5 token 基座 → R1-R4 前端 UX → R15a 后端+agent 对等。

Problem Frame

bitable 后端 v1 齐备28 端点 + 公式引擎 + 三类采集但前端产品形态残缺——grid 体验未达竞品水准(列头编辑跳抽屉、无记录详情、无分组/条件格式、视觉无统一设计语言),且 BitableTool 仅 6 动作 vs 28 REST 端点存在系统性 agent 孤儿风险。P0 聚焦"已存在功能的 UX 打磨 + agent 对等最高优先级子项"P1/P2 功能广度延后。

origin 文档(docs/brainstorms/2026-07-03-bitable-comparative-evaluation-requirements.md已完成三向对比评估agentkit vs Twenty vs 飞书)、差距分析、优先级建议,本 plan 承接其 P0 范围R1/R2/R3/R4/R5/R15a


Scope

In Scope (P0)

  • R5: 统一设计 token 系统CSS 变量层:颜色/间距/圆角/字号)+ 字段类型图标 + 彩色 chip 升级
  • R1: 列内联字段配置(列头菜单直接编辑,不跳右侧抽屉)
  • R2: 记录详情侧边抽屉(行点击展开,全字段类型可视化展示与编辑)
  • R3: 视图类型切换与创建ViewSwitcher 暴露 5 种类型,禁用态标注"规划中"
  • R4: grid 视图内分组与条件格式(多字段分组 + 规则自动着色)
  • R15a: BitableTool 动作补全6→10 动作)+ DELETE /views 后端端点

Out of Scope (Deferred to P1/P2)

  • R6/R7: 看板/画廊视图实现P1
  • R8: 字段类型扩展 17 项 + schema V3 迁移P1
  • R9/R10: 公式库扩展 + 跨表关联增强P1
  • R11: 甘特/表单视图P2
  • R12/R13/R14: 自动化/仪表盘/细粒度权限P2
  • R15b/R15c: NL→表 agent 技能 / 定时采集 UIB 线,独立推进)
  • 并发编辑 UX、实时协作P1+
  • 大规模优化(列式存储/分区v3

Pre-conditions / Assumptions

  • 后端 v1 齐备且稳定28 端点 + 公式引擎 + 三类采集已就位)
  • ViewType 枚举已有 5 种类型grid/kanban/gantt/gallery/form—— 后端无需改枚举
  • CreateViewRequest 已接受 view_type 字段 —— R3 纯前端
  • UpdateViewRequest.config: dict 可直接存 group_by/conditional_formatting —— R4 后端无需改模型
  • vxe-table 4 作为 grid 实现基础(需先消除幽灵依赖)
  • PostgreSQL 性能足以支撑 v1/v2 规模(<10 万行);大规模延后 v3
  • P0 视觉风格对齐基于现有 Ant Design Vue + vxe-table 主题定制,不引入新 UI 库

Key Technical Decisions

KTD1. 设计 token 用 CSS 自定义属性层,不引入 Tailwind/Sass。src/agentkit/server/frontend/src/styles/bitable-tokens.css 定义 :root 下的 CSS 变量(--bitable-color-*/--bitable-spacing-*/--bitable-radius-*/--bitable-font-*),通过 Ant Design Vue 的 ConfigProvider token 覆盖与 vxe-table 的 CSS 变量对接。理由:零依赖、运行时可覆盖、与现有 Ant Design Vue 4 token 系统兼容。颜色调色板 8 色预设,全部满足 WCAG AA 对比度≥4.5:1

KTD2. vxe-table 幽灵依赖在 U1 显式声明。 src/agentkit/server/frontend/package.json 添加 vxe-tablevxe-pc-ui 版本声明(与主仓 node_modules 实际版本对齐),消除 hoisting 风险。这是 R1/R3/R4 实施的前置条件。

KTD3. R1 内联字段配置用 vxe-table header slot + 自定义 InlineFieldConfigurator 组件(混合方案)。 不用 vxe-table 内置编辑(功能受限),不自建完整列头组件(重复造轮子)。在 vxe-table 的 header slot 内渲染列名 + 下拉触发图标,下拉面板内嵌 InlineFieldConfigurator.vue(复用 FieldConfigForm.vue 的类型切换/选项管理逻辑,但不抽屉化)。FieldManagePanel.vue 保留作为批量管理入口。

KTD4. R2 记录详情抽屉单列纵向,宽度 480px与 FieldManagePanel 一致),>10 字段时扩展至 640px。 不用双列紧凑窄屏退化复杂、字段类型多时视觉混乱。sticky header 显示记录标题body 按字段顺序纵向排列每字段一行label + value。attachment/image 显示缩略图formula 显示只读计算结果lookup 显示关联值。宽度断点通过 design token 控制(--bitable-drawer-width/--bitable-drawer-width-wide)。

KTD5. R3 视图类型选择用 Ant Design Vue Dropdown + disabled items。 ViewSwitcher.vue 的"新建视图"按钮改为 Dropdown5 种类型列出未实现的kanban/gallery/gantt/formdisabled + tooltip "规划中"。点击 grid 调用 handleCreateViewview_type: 'grid'(不再硬编码)。后端 CreateViewRequest 已支持 view_type,无需后端改动。

KTD6. R4 分组与条件格式存入 View.config后端用 Pydantic 校验 config 子结构。 group_by: [{field_id, direction}](最多 3 字段)+ conditional_formatting: [{field_id, operator, value, color_key}]7 运算符)。前端 ViewConfigPanel.vue 新增分组与条件格式编辑器,提交时 PUT 进 config dict。后端 UpdateViewRequest.config 已是 dict[str, Any],但新增 Pydantic 校验模型GroupByItem/ConditionalFormatRule)在 service 层 validate config 子结构——operator 枚举校验、color_key 限定 8 色白名单、group_by 长度 ≤3。理由agent 通过 BitableTool 的 update_view 动作可直接写 config前端校验对 agent 路径无效,必须服务端 enforce闭合 ce-doc-review 安全 finding。颜色存语义 key'red'|'orange'|'yellow'|'green'|'blue'|'purple'|'gray'|'neutral'),前端 groupingRulesUtils.ts 提供 colorKeyToCssVar() 映射到 --bitable-cf-*,避免前端 CSS 实现细节持久化到数据库。

KTD7. R4 条件格式规则构建器用列表式rule list非向导式、非 DSL。 每条规则一行:字段选择 + 运算符选择 + 值输入 + 颜色选择8 色 token 预设)+ 启用/禁用开关。规则按顺序优先(首条匹配 wins。预览实时着色当前 grid 数据样本。

KTD8. R4 分组交互:默认展开、首字段优先排序、分组头显示聚合行。 分组头显示分组字段值 + 计数(+ 求和/平均值如果字段为 number。多字段分组时层级嵌套可折叠/展开。拖拽分组字段调整层级顺序可选P0 不强制)。

KTD9. R15a 后端新增 DELETE /views/{view_id} 端点,复用现有 ownership 检查模式。 路由 @router.delete("/views/{view_id}", status_code=204),调用 service.delete_view(view_id),前置 _check_table_ownership(通过 view → table 关联查 owner。404-before-403 与现有 27 端点一致(见 docs/solutions/architecture-patterns/bitable-companion-service-security-reliability-patterns.md 模式 4X-Internal-Token 路径 ownership 语义:内部令牌绑定系统 agent 身份(user_id="__bitable_internal__"所有写操作记审计日志。agent 通过 BitableTool 调用 _delete_viewX-Internal-Token 透传但 ownership 检查仍执行——内部令牌仅 bypass ownership与现有 28 端点一致不等于全权。Test scenario 验证X-Internal-Token 调用 _delete_view 操作非自己资源时返回 404。

KTD10. R15a BitableTool 4 新动作与现有 6 动作同模式。 bitable_tool.py 新增 _create_view/_update_view/_update_field/_delete_view 4 个 async def复用现有 _call_api 内部方法JWT 或 X-Internal-Token 认证)。动作注册需同步更新两处(1) execute()handlers dict 添加 4 个映射;(2) input_schema.properties.action.enum 添加 4 个字符串(create_view/update_view/update_field/delete_view)。若只改 handlers 不改 enumagent 的 LLM 看不到新动作可选值4 个新动作实际不可调用。update_field 覆盖 R1 的 PATCH /fields/{id}create_view/update_view 覆盖 R3/R4 的视图操作,delete_view 覆盖新增的 DELETE 端点。

KTD11. 交付分 3 阶段,每阶段可独立验证。 Phase 1 (U1) token 基座 → Phase 2 (U2-U5) 前端 UX → Phase 3 (U6) 后端+agent。Phase 2 的 4 个 U-ID 可并行(共享 U1 token 但互不依赖Phase 3 依赖 Phase 2 的 U4 + U5create_view/update_view 的 view_type + group_by/conditional_formatting config 结构需与前端一致)。Phase 2 开始时即冻结 config schema 契约文档U6 可与 U4/U5 并行实现,仅集成测试在 Phase 2 完成后。


Implementation Units

Phase 1 — Foundation

U1: R5 Design Token System + vxe-table Dependency Declaration

Goal: 建立统一设计 token 系统CSS 变量层),重写 bitable 组件颜色/间距/圆角/字号,补齐字段类型图标与彩色 chip 升级,显式声明 vxe-table 依赖。这是 Phase 2 所有 UI 工作的前置基座。

Files:

  • src/agentkit/server/frontend/package.json — 添加 vxe-table + vxe-pc-ui 依赖声明
  • src/agentkit/server/frontend/src/styles/bitable-tokens.css (new) — CSS 自定义属性定义
  • src/agentkit/server/frontend/src/main.ts — import bitable-tokens.css
  • src/agentkit/server/frontend/src/components/bitable/BitableGrid.vue — 替换硬编码颜色为 token 引用
  • src/agentkit/server/frontend/src/components/bitable/ColumnHeaderMenu.vue — token 化
  • src/agentkit/server/frontend/src/components/bitable/SelectDisplay.vue — chip 升级8 色 token 调色板 + 对比度修复)
  • src/agentkit/server/frontend/src/components/bitable/SelectCellEditor.vue — token 化
  • src/agentkit/server/frontend/src/components/bitable/AttachmentCell.vue — token 化
  • src/agentkit/server/frontend/src/components/bitable/ImageCell.vue — token 化
  • src/agentkit/server/frontend/src/components/bitable/FileCard.vue — token 化
  • src/agentkit/server/frontend/src/views/BitableFileListView.vue — token 化
  • src/agentkit/server/frontend/src/views/BitableFileDetailView.vue — token 化
  • src/agentkit/server/frontend/src/components/bitable/FieldTypeIcon.vue (new) — 9 种字段类型图标Ant Design Outlined
  • src/agentkit/server/frontend/src/composables/useResponsiveBreakpoint.ts (new) — 768/1024/1440 断点 composable
  • src/agentkit/server/frontend/src/components/bitable/LoadingState.vue (new) — 统一加载态(骨架屏)
  • src/agentkit/server/frontend/src/components/bitable/ErrorState.vue (new) — 统一错误态(行内提示)

Approach:

  1. bitable-tokens.css 定义 4 类 token
    • 颜色:--bitable-color-primary/--bitable-color-bg/--bitable-color-text/--bitable-color-border/--bitable-cf-{red,orange,yellow,green,blue,purple,gray,neutral}(条件格式 8 色预设,全部 WCAG AA ≥4.5:1
    • 间距:--bitable-spacing-{xs,sm,md,lg,xl}4/8/12/16/24px
    • 圆角:--bitable-radius-{sm,md,lg}4/6/8px
    • 字号:--bitable-font-{xs,sm,md,lg}12/13/14/16px
    • 抽屉宽度:--bitable-drawer-width: 480px/--bitable-drawer-width-wide: 640px
  2. 逐组件 grep 硬编码 hex 颜色(#[0-9a-fA-F]{3,6}),替换为 token var()
  3. FieldTypeIcon.vue 映射 9 种类型到 Ant Design Outlined 图标text→FileTextOutlined, number→NumberOutlined, date→CalendarOutlined, select→TagOutlined, multiselect→TagsOutlined, attachment→PaperClipOutlined, image→PictureOutlined, formula→FunctionOutlined, lookup→LinkOutlined
  4. SelectDisplay.vue chip 配色从 8 色 token 调色板取色,每色确保 ≥4.5:1 对比度
  5. useResponsiveBreakpoint.ts 暴露 isMobile/isTablet/isDesktop 响应式断点768/1024/1440
  6. LoadingState.vue + ErrorState.vue 作为 bitable 内部统一加载/错误态组件(P0 提升理由U3 RecordDetailDrawer 异步加载需骨架屏避免白屏、U2/U4 提交需 loading 态防重复点击。U2-U5 Test scenarios 强制引用这两个组件证明确实被消费)
  7. useResponsiveBreakpoint.ts 在 U3抽屉 isMobile 时全屏覆盖)+ U5ViewConfigPanel isMobile 时改底部抽屉)显式消费
  8. R3/R4 后端假设验证Phase 1 退出条件grep + pytest round-trip 验证 CreateViewRequest 接受 view_typeUpdateViewRequest 接受任意 config dict。若验证失败Phase 2 需补后端工作项

Test scenarios:

  1. Given bitable-tokens.css, When grep #[0-9a-fA-F]{3,6} in bitable components, Then 零硬编码 hex全部用 var()
  2. Given FieldTypeIcon, When 渲染 9 种字段类型, Then 各有对应 Ant Design Outlined 图标
  3. Given SelectDisplay chip, When axe-core 扫描, Then 所有关键文本对比度 ≥4.5:1WCAG AA
  4. Given package.json, When npm ls vxe-table vxe-pc-ui, Then 两者均为显式声明依赖(非 hoisting
  5. Given useResponsiveBreakpoint, When viewport < 768px, Then isMobile === true
  6. Given LoadingState, When 异步加载, Then 显示骨架屏(非 spinner
  7. Given ErrorState, When 异步失败, Then 显示行内错误提示 + 重试按钮

Verification:

  • npm run typecheck 通过
  • npm run build:frontend 通过
  • axe-core 扫描 bitable 页面对比度全绿
  • grep 硬编码 hex 零匹配

Phase 2 — Frontend UX (depends on U1)

U2: R1 Inline Field Configuration

Goal: 列头菜单直接编辑字段(重命名/改类型/选项管理),不跳右侧 FieldManagePanel 抽屉。FieldManagePanel 保留作为批量管理入口。

Files:

  • src/agentkit/server/frontend/src/components/bitable/InlineFieldConfigurator.vue (new) — 内联字段配置面板(复用 FieldConfigForm 逻辑)
  • src/agentkit/server/frontend/src/components/bitable/ColumnHeaderMenu.vue — 菜单重构:编辑 → 内联展开(非跳抽屉)
  • src/agentkit/server/frontend/src/components/bitable/BitableGrid.vue — header slot 集成 InlineFieldConfigurator
  • src/agentkit/server/frontend/src/components/bitable/FieldManagePanel.vue — 保留,添加"批量管理"定位提示
  • src/agentkit/server/frontend/src/stores/bitable.ts — 复用现有 updateField action
  • src/agentkit/server/frontend/e2e/bitable-field-ops.spec.ts — extend: 内联编辑场景
  • src/agentkit/server/frontend/src/helpers/fieldRenderUtils.ts (new) — 纯函数:字段类型校验、类型转换兼容性检查

Approach:

  1. InlineFieldConfigurator.vueFieldConfigForm.vue 抽取核心逻辑(类型切换、选项管理、校验),以 inline panel 形式渲染(非抽屉)
  2. ColumnHeaderMenu.vue 的"编辑"项改为 toggle InlineFieldConfigurator 在列头下方展开
  3. 类型变更提交前调用 fieldRenderUtils.checkTypeCompatibility(oldType, newType, existingValues) —— 若现有值不可转换则显示警告 + 阻止提交
  4. 重命名/选项管理直接调用 store updateField(fieldId, patch) → PATCH /fields/{id}
  5. 键盘可达Tab 到列头菜单 → Enter 展开 → Tab 字段间切换 → Esc 关闭

Test scenarios:

  1. Given select 字段有 3 选项, When 点击列头菜单"编辑", Then InlineFieldConfigurator 内联展开(不跳右侧抽屉)
  2. Given 字段名变更提交, When PATCH /fields/{id}, Then 返回 200 + grid 在 1 帧内重渲染新标签
  3. Given 字段类型 text → number, When 现有记录值不可转换, Then 显示警告 + 阻止提交
  4. Given select 选项管理, When 新增/删除/重命名选项, Then 内联完成 + 提交后 chip 更新
  5. Given 键盘导航, When Tab 到列头菜单 → Enter, Then 展开 InlineFieldConfigurator + 焦点在首字段
  6. Given FieldManagePanel, When 从列头菜单"批量管理"打开, Then 仍可用(保留入口)

Verification:

  • npm run typecheck 通过
  • e2e bitable-field-ops.spec.ts 内联编辑场景通过
  • axe-core 键盘导航可达性通过

U3: R2 Record Detail Drawer

Goal: grid 行点击展开右侧详情抽屉显示所有字段类型的可视化展示与编辑。单列纵向480px>10 字段扩展 640px

Files:

  • src/agentkit/server/frontend/src/components/bitable/RecordDetailDrawer.vue (new) — 记录详情抽屉
  • src/agentkit/server/frontend/src/components/bitable/BitableGrid.vue — 行点击事件 → 打开抽屉
  • src/agentkit/server/frontend/src/stores/bitable.tscurrentRecord state + openRecordDetail/closeRecordDetail actions
  • src/agentkit/server/frontend/src/api/bitable.ts — 复用现有 queryRecords(按 record_id 查询)
  • src/agentkit/server/frontend/e2e/bitable-record-drawer.spec.ts (new) — 抽屉 e2e
  • src/agentkit/server/frontend/src/helpers/recordDrawerUtils.ts (new) — 纯函数字段值渲染格式化、attachment/image 缩略图 URL 生成

Approach:

  1. RecordDetailDrawer.vue 用 Ant Design Vue a-drawerwidth 绑定 design token--bitable-drawer-width / --bitable-drawer-width-wide
  2. sticky header 显示记录标题字段值(首个 text 类型字段)
  3. body 按字段顺序纵向排列,每字段一行:
    • label字段名 + FieldTypeIcon
    • value根据类型渲染text/number/date 直接显示select/multiselect 用 SelectDisplay chipattachment 显示文件名列表image 显示缩略图网格formula 显示只读计算结果lookup 显示关联表字段值)
  4. user-owned 字段可编辑inline edit → upsertagent-owned 字段只读
  5. 编辑提交调用 store upsertRecord → upsert 保留 agent 列(见 origin R2 验收标准)
  6. Esc 关闭抽屉

Test scenarios:

  1. Given grid 行, When 用户点击行, Then 右侧抽屉展开显示所有字段(含 attachment/formula/lookup
  2. Given 抽屉打开且字段为 attachment/image, When 渲染, Then 显示缩略图/预览(非原始 URL
  3. Given 抽屉打开且字段为 formula, When 渲染, Then 显示计算结果(只读,不可编辑)
  4. Given 抽屉中编辑 user-owned 字段并提交, When 后端 upsert, Then agent 列不被覆盖
  5. Given 字段数 ≤ 10, When 抽屉渲染, Then 宽度 480px
  6. Given 字段数 > 10, When 抽屉渲染, Then 宽度 640px
  7. Given 抽屉打开, When 按 Esc, Then 抽屉关闭

Verification:

  • npm run typecheck 通过
  • e2e bitable-record-drawer.spec.ts 通过
  • upsert 保留 agent 列(现有 test_service.py 覆盖)

U4: R3 View Type Switcher

Goal: ViewSwitcher 支持选 grid/kanban/gallery/gantt/form新建视图选类型不再硬编码 grid。未实现的以禁用态展示 + 标注"规划中"。

Files:

  • src/agentkit/server/frontend/src/components/bitable/ViewSwitcher.vue — "新建视图"改为 Dropdown + 5 类型选择
  • src/agentkit/server/frontend/src/views/BitableFileDetailView.vuehandleCreateView 接受 view_type 参数(不再硬编码 'grid'
  • src/agentkit/server/frontend/src/stores/bitable.tscreateView action 传 view_type
  • src/agentkit/server/frontend/src/api/bitable.tscreateView API 调用传 view_type
  • src/agentkit/server/frontend/e2e/bitable-view.spec.ts — extend: 类型选择场景
  • src/agentkit/server/frontend/src/helpers/viewSwitcherUtils.ts (new) — 纯函数视图类型元数据label/icon/disabled/tooltip

Approach:

  1. viewSwitcherUtils.ts 定义 5 种类型元数据:
    • grid: { label: '表格', icon: TableOutlined, disabled: false }
    • kanban: { label: '看板', icon: AppstoreOutlined, disabled: true, tooltip: '规划中' }
    • gallery: { label: '画廊', icon: PictureOutlined, disabled: true, tooltip: '规划中' }
    • gantt: { label: '甘特', icon: BarChartOutlined, disabled: true, tooltip: '规划中' }
    • form: { label: '表单', icon: FormOutlined, disabled: true, tooltip: '规划中' }
  2. ViewSwitcher.vue 的"新建视图"按钮改为 a-dropdown,列出 5 类型disabled 项设 disabled + tooltip
  3. handleCreateViewBitableFileDetailView.vue 接受 viewType: ViewType 参数,调用 store createView({ table_id, name, view_type })
  4. store createView 调用 API createViewview_type 字段
  5. 后端 CreateViewRequest 已支持 view_typeline 181无需后端改动

Test scenarios:

  1. Given ViewSwitcher, When 用户点击"新建视图", Then 显示 5 种类型选择grid/kanban/gallery/gantt/form
  2. Given kanban/gallery/gantt/form 未实现, When 渲染, Then 以禁用态展示 + 标注"规划中" tooltip
  3. Given 新建视图选 grid, When 创建, Then 调用 POST /views 传 view_type=grid(不再硬编码)
  4. Given 禁用态类型, When 点击, Then 不触发创建 + 显示"规划中" tooltip
  5. Given 后端 CreateViewRequest, When 接收 view_type 字段, Then 正确存储(现有后端已支持)

Verification:

  • npm run typecheck 通过
  • e2e bitable-view.spec.ts 类型选择场景通过
  • POST /views 请求体含 view_type 字段

U5: R4 Grouping + Conditional Formatting

Goal: grid 视图内多字段分组(最多 3 字段)+ 条件格式规则自动着色7 运算符)。分组与条件格式存入 View.config。

Files:

  • src/agentkit/server/frontend/src/components/bitable/ViewConfigPanel.vue — 新增分组 + 条件格式编辑器 tab
  • src/agentkit/server/frontend/src/components/bitable/GroupingEditor.vue (new) — 分组编辑器(字段选择 + 排序 + 聚合)
  • src/agentkit/server/frontend/src/components/bitable/ConditionalFormatEditor.vue (new) — 条件格式规则列表编辑器
  • src/agentkit/server/frontend/src/components/bitable/BitableGrid.vue — 分组渲染 + 条件格式着色逻辑
  • src/agentkit/server/frontend/src/stores/bitable.tsupdateViewConfig actionPATCH /views config
  • src/agentkit/server/frontend/src/api/bitable.ts — 复用现有 updateView
  • src/agentkit/server/frontend/e2e/bitable-grouping.spec.ts (new) — 分组 + 条件格式 e2e
  • src/agentkit/server/frontend/src/helpers/groupingRulesUtils.ts (new) — 纯函数:分组层级计算、聚合值计算、条件格式规则匹配
  • tests/unit/bitable/test_grouping.py (new) — 后端 config 存储测试
  • tests/unit/bitable/test_conditional_formatting.py (new) — 后端 config 存储测试

Approach:

  1. View.config schema前端约定 + 后端 Pydantic 校验,见 KTD6
    {
      group_by: [{ field_id: string, direction: 'asc' | 'desc' }],  // 最多 3 项
      conditional_formatting: [{
        field_id: string,
        operator: 'equals' | 'not-equals' | 'contains' | 'is-empty' | 'greater-than' | 'less-than' | 'between',
        value: string,
        color_key: 'red' | 'orange' | 'yellow' | 'green' | 'blue' | 'purple' | 'gray' | 'neutral'
      }]
    }
    
  2. GroupingEditor.vue:字段多选(最多 3+ 方向切换 + 拖拽排序层级
  3. ConditionalFormatEditor.vue:列表式规则编辑器,每行 = 字段 + 运算符 + 值 + 颜色8 色 key 预设)+ 启用开关
  4. BitableGrid.vue 分组渲染:按 group_by 字段层级嵌套,分组头显示字段值 + 计数 + number 字段聚合SUM/AVG默认展开可折叠
  5. BitableGrid.vue 条件格式着色:遍历 conditional_formatting 规则,首条匹配 wins单元格背景色用 var(colorKeyToCssVar(color_key))组合态约定:分组 + 条件格式同时启用时,条件格式仅作用于数据单元格,分组头不着色(避免视觉冲突)
  6. 提交时调用 store updateViewConfig(viewId, { group_by, conditional_formatting }) → PATCH /views config
  7. 后端 service 层用 Pydantic 校验 config 子结构(GroupByItem/ConditionalFormatRule),拒绝非法 operator/color_key/超长 group_by422

Test scenarios:

  1. Given grid 视图, When 用户开启分组, Then 支持最多 3 字段分组(对标飞书/Twenty
  2. Given 条件格式规则 operator=equals, When 单元格值匹配, Then 自动着色
  3. Given 两条规则匹配同一单元格, When 冲突, Then 首条规则优先(按用户排序)
  4. Given 着色, When 颜色来源审计, Then 全部来自 design token 调色板8 色预设,无硬编码 hex
  5. Given 分组头, When 渲染, Then 显示分组字段值 + 计数 + number 字段聚合SUM/AVG
  6. Given 多字段分组, When 渲染, Then 层级嵌套 + 可折叠/展开
  7. Given PATCH /views config, When 后端存储, Then config dict 含 group_by + conditional_formatting
  8. Given 7 运算符, When 测试 each, Then equals/not-equals/contains/is-empty/greater-than/less-than/between 全部正确匹配

Verification:

  • npm run typecheck 通过
  • e2e bitable-grouping.spec.ts 通过
  • pytest test_grouping.py + test_conditional_formatting.py 通过
  • grep 着色 hex 零匹配(全部用 token

Phase 3 — Agent Parity (depends on U4)

U6: R15a BitableTool 4 New Actions + DELETE /views Endpoint

Goal: BitableTool 从 6 动作扩展到 10 动作(新增 create_view/update_view/update_field/delete_view后端新增 DELETE /views/{view_id} 端点,消除 agent 孤儿风险。

Files:

  • src/agentkit/server/routes/bitable.py — 新增 DELETE /views/{view_id} 端点line ~660 后)
  • src/agentkit/bitable/service.py — 新增 delete_view(view_id) 方法
  • src/agentkit/bitable/repository.py — 新增 delete_view(view_id) 方法
  • src/agentkit/tools/bitable_tool.py — 新增 4 个 async def: _create_view/_update_view/_update_field/_delete_viewline ~466 后)
  • src/agentkit/server/frontend/src/api/bitable.ts — 新增 deleteView(viewId) 方法
  • src/agentkit/server/frontend/src/components/bitable/ViewSwitcher.vue — 视图删除入口(调用 deleteView
  • tests/unit/bitable/test_bitable_tool.py — extend: 4 新动作测试
  • tests/unit/bitable/test_routes.py — extend: DELETE /views 测试
  • src/agentkit/server/frontend/e2e/bitable-agent-parity.spec.ts (new) — agent 对等 e2e

Approach:

  1. 后端 DELETE /views/{view_id}:
    • 路由:@router.delete("/views/{view_id}", status_code=204)
    • 前置:通过 view_id 查 view → table_id → _check_table_ownership404-before-403
    • 调用 service.delete_view(view_id)repository.delete_view(view_id)
    • 返回 204 No Content
  2. BitableTool 4 新动作(复用现有 _call_api 内部方法):
    • _create_view(table_id, name, view_type, config) → POST /tables/{table_id}/views
    • _update_view(view_id, name, config) → PATCH /views/{view_id}
    • _update_field(field_id, name, type, config) → PATCH /fields/{field_id}
    • _delete_view(view_id) → DELETE /views/{view_id}
  3. 动作注册:在 BitableTool 的 _ACTIONS 字典(或等价注册机制)添加 4 项,总数 6→10
  4. 前端 api/bitable.ts 新增 deleteView(viewId) 调用 DELETE /views/{view_id}
  5. ViewSwitcher.vue 视图 tab 添加删除按钮dropdown 菜单或右键),调用 deleteView + 二次确认

Test scenarios:

  1. Given BitableTool, When 调用 create_view/update_view/update_field/delete_view, Then 4 个新动作全部可用6→10 动作)
  2. Given 视图列表, When 用户点击删除, Then 调用 DELETE /views/{id} + 二次确认
  3. Given DELETE /views/{view_id}, When 视图不存在, Then 返回 404
  4. Given DELETE /views/{view_id}, When 无所有权, Then 返回 404非 403existence disclosure 防护)
  5. Given R3/R4 配置变更, When agent 调用 create_view/update_viewtype/group_by/conditional_formatting, Then 配置成功写入(与 REST PATCH /views 等价)
  6. Given 字段配置, When agent 调用 update_field, Then 与 PATCH /fields/{id} 等价
  7. Given BitableTool 动作清单, When 审计, Then 10 个动作覆盖 28 端点中的核心 CRUDcreate_table/import_excel/import_database/collect_api/upsert_records/query_records/create_view/update_view/update_field/delete_view
  8. Given 内部 token 认证, When agent 调用 BitableTool, Then X-Internal-Token 透传成功

Verification:

  • ruff check src/ && ruff format src/ 通过
  • pytest test_bitable_tool.py + test_routes.py 通过
  • e2e bitable-agent-parity.spec.ts 通过
  • BitableTool 动作数 10验证 execute() 内 handlers dict keys + input_schema.properties.action.enum 均含 10 项)

Risks & Dependencies

Risks

Risk Likelihood Impact Mitigation
vxe-table 4 主题定制深度不足token 覆盖不到所有组件样式 U1 先做 token 映射 PoC验证 vxe-table CSS 变量可覆盖;不行则用 wrapper 组件 + scoped CSS
条件格式 7 运算符在 vxe-table 行渲染中性能差(大数据量) P0 假设 <10k 行,首版不做虚拟滚动优化;若 >10k 行降级为禁用条件格式提示
R4 分组渲染与 vxe-table 内置分组冲突 不用 vxe-table 内置分组,自建分组 wrapper 层(数据分桶 + 折叠 UIgrid 只渲染当前分组数据
BitableTool 4 新动作的 X-Internal-Token 透传在 agent 编排场景失效 U6 测试契约覆盖 agent 编排场景redis 标记);复用现有 6 动作的认证模式
design token 与 Ant Design Vue 4 ConfigProvider token 冲突 bitable-tokens.css 用 --bitable-* 前缀,不覆盖 Ant Design 全局 token

Dependencies

  • U1 → U2/U3/U4/U5: Phase 2 所有 UI 工作依赖 U1 token 系统 + vxe-table 依赖声明
  • U4 → U6: U6 的 create_view/update_view 动作需与 U4 的 view_type 一致
  • U5 → U6: U6 的 update_view 动作需与 U5 的 group_by/conditional_formatting config 结构一致Phase 2 开始时冻结 config schema 契约U6 可并行实现)
  • 外部依赖: vxe-table 4 + vxe-pc-ui版本与主仓 node_modules 对齐、Ant Design Vue 4 Outlined 图标
  • 既有约束: AGENTS.md 规则no-emoji、Pydantic v2、no-any、pytest asyncio_mode=auto、ruff check/formatpy311行宽 100

System-Wide Impact

后端改动

  • 新增端点: DELETE /api/v1/bitable/views/{view_id}U6—— 第 29 个端点
  • service/repository: 新增 delete_view 方法U6
  • 无 schema 迁移: View.config 已是 dict[str, Any]group_by/conditional_formatting 作为 config key 存储,无需 V2→V3 迁移
  • 无 FieldType 扩展: P0 不引入新字段类型R8 延后 P1

前端改动

  • 新组件: FieldTypeIcon/InlineFieldConfigurator/RecordDetailDrawer/GroupingEditor/ConditionalFormatEditor/LoadingState/ErrorState7 个)
  • 新 composable: useResponsiveBreakpoint
  • 新 helpers: fieldRenderUtils/recordDrawerUtils/viewSwitcherUtils/groupingRulesUtils4 个纯函数模块)
  • 新样式: bitable-tokens.cssdesign token 层)
  • 改动组件: BitableGrid/ColumnHeaderMenu/ViewSwitcher/ViewConfigPanel/SelectDisplay/FieldManagePanel + 2 个 viewtoken 化 + 功能集成)
  • package.json: 显式声明 vxe-table + vxe-pc-ui

Agent 对等影响

  • BitableTool 动作数 6→10覆盖视图 CRUD + 字段更新
  • agent 可通过 BitableTool 完成与人类等价的视图/字段操作(闭合 R15a 缺口)
  • 为 R15bNL→表 agent 编排铺路agent 可编排 create_table + create_field + create_view

测试影响

  • 新增后端测试: test_grouping.py/test_conditional_formatting.py + extend test_bitable_tool.py/test_routes.py
  • 新增前端 e2e: bitable-record-drawer.spec.ts/bitable-grouping.spec.ts/bitable-agent-parity.spec.ts
  • 新增前端 helpers: 4 个纯函数模块vitest 测试)

Test Strategy Summary

U-ID 后端单元测试 前端单元测试 e2e 测试 集成标记
U1 (R5) - helpers/designTokenAudit.tsgrep token 使用) bitable-view.spec.tsvisual regression -
U2 (R1) test_routes.pyPATCH /fields/{id} helpers/fieldRenderUtils.ts bitable-field-ops.spec.tsextend -
U3 (R2) test_service.pyupsert 保留 user 列) helpers/recordDrawerUtils.ts bitable-record-drawer.spec.tsnew -
U4 (R3) test_routes.pyPOST /views type 参数) helpers/viewSwitcherUtils.ts bitable-view.spec.tsextend -
U5 (R4) test_grouping.py + test_conditional_formatting.pynew helpers/groupingRulesUtils.ts bitable-grouping.spec.tsnew -
U6 (R15a) test_bitable_tool.py4 new actions+ test_routes.pyDELETE /views - bitable-agent-parity.spec.tsnew redisnotify_callback

测试约定: 后端 pytestasyncio_mode=auto标记 integration/redis/postgres前端 vitest纯函数抽 helpers/,不用 @vue/test-utilse2e Playwright。

Agent 对等测试契约: U6 交付时附 BitableTool 4 新动作的契约测试,验证 agent 能完成与人类等价的视图/字段操作。

横切测试(适用所有 U-ID:

  • WCAG AA 可访问性axe-core 扫描键盘导航 + 对比度 + ARIA role
  • 空状态:无字段/无记录/无视图的空状态文案
  • design token 审计grep 硬编码 hex 零匹配

Execution Posture

Posture signal: 标准 TDD后端 pytest first前端 helpers vitest first。后端 DELETE /views 端点用 TDD先写 test_routes.py 失败用例,再实现)。前端组件不强求 TDDVue 组件 TDD 投入产出比低),但纯函数 helpers 用 TDD。

Sequencing:

  1. Phase 1 (U1) —— token 基座,可独立验证
  2. Phase 2 (U2/U3/U4/U5) —— 4 个 U-ID 可并行(共享 U1 token 但互不依赖)
  3. Phase 3 (U6) —— 依赖 U4 的 view_type + U5 的 config 结构

Branch: feat/bitable-enhancement(当前分支)


Open Questions (Deferred to Execution)

以下来自 origin 文档 Outstanding Questions + ce-doc-review manual findingsP0 范围内可在实现时决策P1/P2 延后:

P0 范围内(实现时决策)

  • vxe-table 容量上限: P0 假设 <10k 行,若实测 >10k 行性能差则降级(禁用条件格式提示或虚拟滚动延后 P1
  • 条件格式规则构建器细节: 列表式KTD7预览实时着色当前 grid 数据样本
  • 分组交互细节: 默认展开、首字段优先排序、分组头显示聚合行KTD8
  • R2 抽屉宽度: 480px≤10 字段)/ 640px>10 字段KTD4
  • 禁用态视图路线图: tooltip "规划中"hardcode不读 configP0 不做投票机制)
  • 响应式断点: 768/1024/1440U1 useResponsiveBreakpoint
  • 加载/错误状态: 骨架屏LoadingState+ 行内提示ErrorStateU1 统一组件

延后 P1/P2不在本 plan 范围)

  • user 字段用户模型 (P1, R8): user_id 解析、跨表用户名查询
  • C 先行优先级策略实证依据 (P1, product): 用户访谈/A-B 数据
  • 并发编辑 UX (P1): agent + 用户双写入冲突解决、optimistic locking
  • schema V3 双向关联回滚策略 (P3, R8): drop column vs 保留为 text
  • R13 仪表盘图表库 buy-vs-build (P2): ECharts/Chart.js/AntV G2 选型
  • R6 看板组件选型 (P1): 自建 vs 现成库
  • R9 公式库第三方 parser (P1): 是否引入

From 2026-07-03 ce-plan Phase 5.3 headless ce-doc-review

ce-doc-review5 reviewersheadless pass 的 manual findings需实现时决策

  • 条件格式 WCAG 1.4.1 色盲可感知性 — U5 KTD7 (P1, design-lens, confidence 80)

    条件格式仅靠颜色区分8 色预设中红/绿/橙/黄对色盲用户不可区分。WCAG 1.4.1 要求颜色不能作为唯一区分手段。需实现时决策:(1) 规则增加可选 decoration 字段(下划线/加粗/斜体/图标);(2) 单元格着色同时附加左侧色条 + 图标。最小方案:规则编辑器默认勾选"同时加粗文本"。

  • RecordDetailDrawer 加载/错误/404 状态 — U3 (P1, design-lens, confidence 78)

    抽屉异步按 record_id 查询,需规定网络失败/记录被并发删除/权限丢失时的状态。U1 建了 LoadingState/ErrorStateU3 需强制引用:(1) 打开中显示骨架屏;(2) 查询 404 显示"记录不存在或已被删除" + 关闭按钮;(3) 查询 5xx 显示 ErrorState + 重试按钮。

  • 新编辑器组件空状态 — U3/U5 (P2, design-lens, confidence 72)

    RecordDetailDrawer 打开但记录 0 字段、GroupingEditor 可选字段 <1、ConditionalFormatEditor 0 条规则时的引导文案需定义。实现时补各组件空状态文案。

  • 保存中按钮状态 — U2/U4 (P2, design-lens, confidence 70)

    PATCH /fields、POST /views 提交期间按钮需 disabled + loading 图标,防重复点击。实现时在 U2 InlineFieldConfigurator + U4 ViewSwitcher 补 loading 态。

  • delete_view 硬删/软删 + 最后视图保护 — U6 (P2, security-lens, confidence 68)

    硬删不可逆agent 误调 _delete_view 即数据丢失。需决策:(1) soft deletedeleted_at 标记)+ 可恢复;(2) hard delete 但禁止删除表的最后一个视图(返回 409 Conflict。实现时在 U6 Test scenarios 补对应用例。

  • 分组 wrapper 与 vxe-table 交互限制 — U5 Risks (P3, feasibility, confidence 70)

    自建分组 wrapper 层会丢失跨分组多选、滚动位置、vxe-table 内置筛选与分组交互。P0 已知限制:不支持跨分组多选、折叠分组时虚拟滚动位置重置。后续 P1 优化。

  • U2 lookup 类型缺口 — U2 (P3, coherence, confidence 60)

    U2 复用 FieldConfigForm 的 8 类型lookup 字段内联编辑延后 R8P1。已知限制不阻塞 P0。

  • vxe-pc-ui 依赖必要性 — U1 KTD2 (P2, feasibility, confidence 80)

    KTD2 声明 vxe-pc-ui 但代码库仅 import vxe-table。需 U1 实施时验证 vxe-pc-ui 是否为 vxe-table v4 的 peer dependency。若非 peer dep 则移除,避免多余依赖。


Origin Traceability

本 plan 承接 origin 文档(docs/brainstorms/2026-07-03-bitable-comparative-evaluation-requirements.md)的 P0 范围:

R-ID origin 章节 本 plan U-ID 交付阶段
R5 Priority Recommendations P0 U1 Phase 1
R1 Priority Recommendations P0 U2 Phase 2
R2 Priority Recommendations P0 U3 Phase 2
R3 Priority Recommendations P0 U4 Phase 2
R4 Priority Recommendations P0 U5 Phase 2
R15a Priority Recommendations P0 (agent 对等最高优先级子项) U6 Phase 3

origin 文档的 Acceptance Criteria (P0) + 横切验收标准WCAG AA + 空状态)已映射到各 U-ID 的 Test scenarios。Agent 对等评估方法的 4 个新动作create_view/update_view/update_field/delete_view全部在 U6 实现。