22 KiB
| title | type | date | origin |
|---|---|---|---|
| feat: Bitable UI Completeness — Stage 1 (File Layer + Default Fields + In-Table Field Ops + Select Editor) | feat | 2026-06-29 | docs/brainstorms/2026-06-29-bitable-ui-completeness-requirements.md |
Bitable UI Completeness — Stage 1
Summary
引入"多维表格文件"作为最上级容器,重构 文件 → 数据表 → 字段/记录 三层骨架,补齐新建表默认字段、表内列头字段操作、select 下拉编辑器。这是 4 阶段完善计划的第一阶段,聚焦让 bitable 从"功能残缺"到"用户主动建表体验可用"。
Problem Frame
bitable 后端 v1 齐备但前端产品形态残缺(见 origin 文档 Problem Frame)。三类核心缺口导致无法正常使用:缺最上级文件容器、新建表无默认字段、表内不能直接管理字段。此外 select 编辑器仍是文本输入。Stage 1 解决这四件事,让用户能完成"建文件 → 建表 → 表内配字段 → 填数据"的基本闭环。
Requirements
后端文件层
R1. 引入 BitableFile 实体作为最上级容器。Table 通过 file_id 外键归属文件。文件自有元数据(name/icon/description/owner_user_id),支持 CRUD。文件级 ownership 检查复用现有 _check_table_ownership 模式(见 docs/solutions/architecture-patterns/bitable-companion-service-security-reliability-patterns.md 模式 4)。
R2. 新建数据表时自动创建 5 个默认字段:标题(text,owner=user)、状态(select,预设"未开始/进行中/已完成"3 选项,owner=user)、日期(date,owner=user)、创建人(text,owner=agent)、创建时间(datetime,owner=agent)。默认字段遵循 Field Ownership 模型——agent-owned 字段由系统在记录创建时自动填充。
前端文件层与导航
R3. 三层导航层级:文件列表 → 文件详情(含多张表)→ 表内(字段/记录/视图)。文件列表是 /bitable 的新默认页,显示用户拥有的所有文件卡片。点文件卡片进入文件详情,左侧 sidebar 显示该文件的表列表,右侧显示选中表的 grid。
R4. 文件 CRUD UI:文件列表页有"新建文件"按钮(弹窗输入名称/选图标/选描述);文件卡片支持重命名、删除(带确认);文件详情 topbar 显示文件名与返回按钮。
前端表内体验
R5. 表内字段操作走列头下拉菜单。点 grid 列头弹出菜单:重命名、修改字段类型、隐藏、删除。不再依赖右侧"字段管理"弹层作为唯一入口(FieldManagePanel 保留作为批量管理入口)。删除字段需二次确认(会删除该列所有数据)。
R6. select/multiselect 字段编辑器使用下拉选项(带颜色标签),替换当前 VxeInput 文本输入。选项从字段 config.options 读取,编辑时显示为可搜索下拉,选中后写入 record value。
Key Technical Decisions
KTD1. BitableFile 作为独立实体,Table 加 file_id 外键。 不采用"轻量分组"方案(Table 加 group_name 字段)。理由:文件需要自己的 ownership/CRUD/元数据,轻量分组会在后续权限/共享能力上撞天花板。当前 schema V1 用 create_all 模式,无现有数据需迁移,引入文件层是干净的新增(origin KD2)。
KTD2. Schema 升级用 _SCHEMA_VERSION 递增 + 启动时迁移,不引入 alembic。 现有 src/agentkit/bitable/db.py 已有 _SCHEMA_VERSION = 1 与预留的 _apply_v2_migration 注释位。文件层引入升级到 V2:创建 bitable_files 表,给 bitable_tables 加 file_id 列。启动时 init_db() 检测版本并执行迁移。保持与现有模式一致,不为单次迁移引入 alembic 全套。
KTD3. 默认字段在 service 层 create_table 内创建,不在数据库层用 trigger。 service 层 create_table 在创建 Table 后立即批量创建 5 个默认 Field。理由:可测试、可复用、不依赖数据库特定语法。agent-owned 字段(创建人/创建时间)在 create_record 时由 service 自动填充当前 user_id 与 timestamp。
KTD4. 前端路由重构为嵌套结构。 /bitable → 文件列表;/bitable/:fileId → 文件详情(含表列表 sidebar);/bitable/:fileId/:tableId → 表内。当前 BitableView.vue 拆为 BitableFileListView.vue + BitableFileDetailView.vue。表内视图复用现有 BitableGrid + ViewSwitcher 等组件。
KTD5. 列头下拉菜单用 vxe-table 的 header slot + Ant Design Vue Dropdown。 不自建列头组件。vxe-table 支持自定义 header slot,在 slot 内渲染列名 + 下拉触发图标。菜单项调用现有 store 的 updateField/deleteField action(需新增)。
KTD6. select 编辑器用 vxe-table 自定义编辑器 + Ant Design Vue Select。 注册一个 SelectCellEditor 自定义编辑器,内部用 a-select(带搜索、颜色标签)。选项从 field.config.options 读取。multiselect 用 mode="multiple"。替换 BitableGrid.vue 中 select/multiselect 的 editRender: { name: 'VxeInput' }。
High-Level Technical Design
三层导航数据流
flowchart TB
A[/bitable 文件列表] --> B[选文件卡片]
B --> C[/bitable/:fileId 文件详情]
C --> D[左侧 sidebar 选表]
D --> E[/bitable/:fileId/:tableId 表内]
E --> F[BitableGrid + ViewSwitcher]
C --> G[新建表 - 自带默认字段]
后端文件层 schema 变更
flowchart LR
F[bitable_files] --1:N--> T[bitable_tables]
T --1:N--> FL[bitable_fields]
T --1:N--> R[bitable_records]
T --1:N--> V[bitable_views]
bitable_files: id, name, icon, description, owner_user_id, created_at, updated_at
bitable_tables: 新增 file_id 外键列
默认字段创建时序
sequenceDiagram
participant U as 用户
participant API as REST API
participant S as BitableService
participant R as Repository
U->>API: POST /files/{file_id}/tables {name}
API->>S: create_table(file_id, name)
S->>R: create Table record
S->>S: _build_default_fields(table_id)
S->>R: create_records_batch 5 fields
S-->>API: Table + 5 Fields
API-->>U: 201 Created
Implementation Units
U1. Backend: BitableFile entity + schema V2 migration
Goal: 引入 BitableFile Pydantic 模型 + ORM model + repository + service + REST endpoints,升级 schema 到 V2。
Requirements: R1
Dependencies: 无(基础单元)
Files:
src/agentkit/bitable/models.py— 新增BitableFilePydantic 模型src/agentkit/bitable/db.py— 新增FileModelORM;_SCHEMA_VERSION = 2;实现_apply_v2_migration(创建 files 表,给 tables 加 file_id 列);Table加file_id字段src/agentkit/bitable/repository.py— 新增FileRepository(CRUD + list_by_owner)src/agentkit/bitable/service.py— 新增BitableService的文件方法(create_file/list_files/get_file/update_file/delete_file);create_table改签名加file_id参数src/agentkit/server/routes/bitable.py— 新增/files端点(POST/GET/GET/:id/PUT/:id/DELETE/:id);/files/{file_id}/tablesPOST 端点;文件级 ownership 检查_check_file_ownershiptests/unit/bitable/test_file_crud.py— 新建测试文件
Approach:
BitableFile模型字段:id, name, icon (emoji 字符串), description, owner_user_id, created_at, updated_at- 文件 ownership 检查复用
_check_table_ownership模式(solutions doc 模式 4):404 before 403,internal token bypass delete_file级联删除该文件下所有 tables(及其 fields/records/views)—— 复用现有delete_table逻辑循环- schema V2 迁移用
ALTER TABLE bitable_tables ADD COLUMN file_id VARCHAR+CREATE TABLE bitable_files - 现有无 file_id 的 table 在迁移时创建一个"默认文件"并归属之(防御性,虽然 verifier 确认无现有数据)
Patterns to follow:
docs/solutions/architecture-patterns/bitable-companion-service-security-reliability-patterns.md模式 1(服务隔离)、模式 4(IDOR ownership 检查)- 现有
_check_table_ownershipinsrc/agentkit/server/routes/bitable.py
Test scenarios:
- Happy path: 创建文件 → 获取 → 列表 → 更新 → 删除
- Edge case: 删除文件时级联删除其下所有表(验证 tables/fields/records 都被清理)
- Error path: 非文件 owner 访问返回 404(不泄露存在性)
- Error path: internal token bypass ownership 检查
- Integration: 创建文件 → 在文件下创建 table → table.file_id 正确关联
- Covers AE1. 新建文件"销售管线"(文件创建部分)
Verification: pytest tests/unit/bitable/test_file_crud.py -v 全绿;ruff check src/agentkit/bitable/ 无 lint 错误。
U2. Backend: Default fields on table creation
Goal: create_table 自动创建 5 个默认字段;agent-owned 字段在 create_record 时自动填充。
Requirements: R2
Dependencies: U1(create_table 签名变更)
Files:
src/agentkit/bitable/service.py—create_table内调用_create_default_fields(table_id, owner_user_id);create_record内自动填充 agent-owned 字段(创建人 = owner_user_id,创建时间 = now)src/agentkit/bitable/models.py— 新增DEFAULT_FIELD_TEMPLATES常量(5 个默认字段定义)tests/unit/bitable/test_default_fields.py— 新建测试文件
Approach:
DEFAULT_FIELD_TEMPLATES:5 个字段定义,含 name/type/owner/config- 状态 select 字段 config:
{"options": [{"label":"未开始","value":"not_started","color":"default"},{"label":"进行中","value":"in_progress","color":"processing"},{"label":"已完成","value":"done","color":"success"}]} _create_default_fields用repository.create_records_batch一次创建 5 个 Fieldcreate_record检查 table 的 agent-owned 字段,若 values 未提供则自动填充
Patterns to follow:
- 现有
create_tableinsrc/agentkit/bitable/service.py - CONCEPTS.md Field Ownership 定义
Test scenarios:
- Happy path: 创建 table → 验证返回 5 个默认字段(名称/类型/owner 正确)
- Happy path: 状态字段 config.options 有 3 个预设选项
- Happy path: 创建 record → 创建人字段自动填充 owner_user_id
- Happy path: 创建 record → 创建时间字段自动填充当前 timestamp
- Edge case: 用户传 record values 时覆盖创建人字段 → agent-owned 字段不被用户覆盖
- Covers AE1. 新建表"客户"(默认字段部分)
Verification: pytest tests/unit/bitable/test_default_fields.py -v 全绿。
U3. Frontend: File layer store + API client + navigation restructure
Goal: 前端文件层 API client + store + 三层导航视图重构。
Requirements: R3, R4
Dependencies: U1(后端文件 API)
Files:
src/agentkit/server/frontend/src/api/bitable.ts— 新增IBitableFile类型 + file CRUD API 函数src/agentkit/server/frontend/src/stores/bitable.ts— 新增filesstate +loadFiles/createFile/updateFile/deleteFileactions;loadTables改为按 fileId 过滤src/agentkit/server/frontend/src/views/BitableFileListView.vue— 新建:文件列表页(卡片网格 + 新建按钮)src/agentkit/server/frontend/src/views/BitableFileDetailView.vue— 新建:文件详情页(topbar + 左侧表列表 sidebar + 右侧表内 grid)src/agentkit/server/frontend/src/views/BitableView.vue— 删除或改为 redirect 到/bitablesrc/agentkit/server/frontend/src/router/index.ts— 重构/bitable路由为嵌套:/bitable(文件列表)、/bitable/:fileId(文件详情)、/bitable/:fileId/:tableId(表内,可选拆为子路由或 query)src/agentkit/server/frontend/src/components/bitable/FileCard.vue— 新建:文件卡片组件(图标+名称+表数量+描述)src/agentkit/server/frontend/src/components/bitable/FileCreateModal.vue— 新建:创建文件弹窗src/agentkit/server/frontend/src/components/bitable/TableViewList.vue— 修改:props 加fileId,emit create 时带 fileId
Approach:
BitableFileListView布局:顶部"新建文件"按钮 + 卡片网格(每卡片显示 icon/name/表数量/描述/操作菜单)BitableFileDetailView布局:复用现有BitableView.vue的 topbar + sidebar + main 结构,但 topbar 显示文件名 + 返回按钮,sidebar 显示该文件的表列表- 路由用嵌套 children:
/bitable→ FileListView;/bitable/:fileId→ FileDetailView(内部根据是否选中 table 渲染 grid 或 placeholder) - 文件删除用
a-popconfirm二次确认
Patterns to follow:
- 现有
BitableView.vue的 topbar + sidebar + main 布局 - 现有
TableCreateModal.vue的弹窗模式 - Ant Design Vue Card / Modal / Popconfirm 组件
Test scenarios:
- Happy path: 访问 /bitable → 显示文件列表(空态有引导)
- Happy path: 点"新建文件" → 弹窗 → 输入名称 → 创建 → 列表刷新显示新卡片
- Happy path: 点文件卡片 → 跳转 /bitable/:fileId → 显示文件详情(sidebar 表列表)
- Happy path: 在文件详情点"新建表" → 表创建后 sidebar 显示
- Edge case: 删除文件 → popconfirm 确认 → 列表移除
- Error path: 访问不存在的 fileId → 显示 404 或回退到列表
- Covers AE1. 新建文件"销售管线"(前端流程)
Verification: npm run typecheck 通过;npm run dev 手动验证三层导航;e2e 测试在 U6 覆盖。
U4. Frontend: In-table field operations (column header dropdown)
Goal: grid 列头下拉菜单支持重命名/改类型/隐藏/删除字段。
Requirements: R5
Dependencies: U3(store 重构)
Files:
src/agentkit/server/frontend/src/components/bitable/BitableGrid.vue— 修改:列 header slot 渲染列名 + 下拉触发图标;移除 select/multiselect 的VxeInputeditRender(在 U5 完成)src/agentkit/server/frontend/src/components/bitable/ColumnHeaderMenu.vue— 新建:列头菜单组件(重命名/改类型/隐藏/删除)src/agentkit/server/frontend/src/components/bitable/FieldConfigForm.vue— 修改:支持重命名与改类型(可能复用现有表单)src/agentkit/server/frontend/src/stores/bitable.ts— 新增updateField(fieldId, patch)+deleteField(fieldId)+hideField(fieldId, viewId)actions
Approach:
- vxe-table column 配置加
header-class-name+ 使用headerslot 自定义渲染 - header slot 内:列名文本 + 一个
...图标触发a-dropdown - 菜单项:
- 重命名 → 弹
a-modal输入新名称 → 调store.updateField - 修改类型 → 弹
a-modal选新类型 → 调store.updateField(注意:改类型可能清空 config) - 隐藏 → 调
store.hideField(写入当前 view 的 hidden_fields) - 删除 →
a-popconfirm确认 → 调store.deleteField
- 重命名 → 弹
- 删除字段会级联删除该字段的所有 record values(后端已支持)
Patterns to follow:
- vxe-table header slot 文档
- Ant Design Vue Dropdown / Modal / Popconfirm
Test scenarios:
- Happy path: 点列头 → 菜单弹出 4 项
- Happy path: 重命名 → 输入新名称 → 表头实时更新
- Happy path: 隐藏字段 → 该列从 grid 消失(仍存在于字段管理面板)
- Happy path: 删除字段 → popconfirm 确认 → 该列与数据消失
- Edge case: 删除主键字段 → 提示不允许或确认后清除 primary_key_field_id
- Covers AE1. 用户点"标题"列头下拉 → 选"重命名"改为"公司名"
Verification: npm run typecheck 通过;手动验证列头菜单 4 个操作。
U5. Frontend: select/multiselect dropdown editor
Goal: select/multiselect 字段编辑器从文本输入改为下拉选项(带颜色标签)。
Requirements: R6
Dependencies: U4(BitableGrid 已修改)
Files:
src/agentkit/server/frontend/src/components/bitable/SelectCellEditor.vue— 新建:自定义编辑器组件(用 a-select)src/agentkit/server/frontend/src/components/bitable/BitableGrid.vue— 修改:select/multiselect 列的editRender指向自定义编辑器;移除ponytail: select editor uses text input注释src/agentkit/server/frontend/src/stores/bitable.ts— 可能需要getFieldOptions(fieldId)getter
Approach:
- 注册 vxe-table 自定义编辑器
SelectCellEditor:- props:
field(含 config.options) - 渲染
a-select:show-search、label-in-value、选项带颜色 tag - multiselect 用
mode="multiple"
- props:
BitableGrid.vuecolumn 配置:select/multiselect 的editRender: { name: 'SelectCellEditor', options: field.config.options }- 选项颜色用
a-tag :color="option.color"渲染
Patterns to follow:
- vxe-table 自定义编辑器文档
- Ant Design Vue Select + Tag
Test scenarios:
- Happy path: 双击 select 单元格 → 下拉弹出 3 个选项(带颜色)
- Happy path: 选一个选项 → 单元格值更新为 option.value
- Happy path: multiselect 字段 → 可多选
- Happy path: 搜索功能 → 输入文字过滤选项
- Edge case: 字段无 options config → 下拉为空 + 提示
- Covers R6
Verification: npm run typecheck 通过;手动验证 select 编辑器交互。
U6. E2E test coverage expansion
Goal: 扩展 e2e 测试覆盖 Stage 1 关键流程。
Requirements: Success Criteria(E2E 覆盖)
Dependencies: U3, U4, U5(前端功能完成)
Files:
src/agentkit/server/frontend/e2e/bitable-view.spec.ts— 修改:保留 B1/B2,扩展覆盖文件导航src/agentkit/server/frontend/e2e/bitable-file-flow.spec.ts— 新建:文件 CRUD + 三层导航流程src/agentkit/server/frontend/e2e/bitable-field-ops.spec.ts— 新建:列头字段操作 + select 编辑器
Approach:
bitable-file-flow.spec.ts:- 访问 /bitable → 验证文件列表渲染
- 新建文件 → 验证卡片出现
- 进入文件 → 验证 sidebar 表列表
- 新建表 → 验证默认字段显示
- 切换表 → 验证 grid 切换
bitable-field-ops.spec.ts:- 点列头 → 验证菜单弹出
- 重命名 → 验证表头更新
- 隐藏 → 验证列消失
- select 编辑器 → 验证下拉交互
Patterns to follow:
- 现有
bitable-view.spec.ts的 B1/B2 模式 - Playwright 测试模式
Test scenarios:
- Happy path: 文件列表 → 新建文件 → 进入 → 新建表(含默认字段)→ 切换表(完整流程)
- Happy path: 列头重命名 + 隐藏 + select 编辑器交互
- Smoke: /bitable 不白屏、核心元素可见(保留 B1/B2)
Verification: npx playwright test e2e/bitable-*.spec.ts 全绿。
Scope Boundaries
本次范围内(Stage 1)
R1-R6 全部 + U1-U6 全部。这是 origin 文档 4 阶段中的阶段一。
Deferred to Follow-Up Work
以下 R 在 origin 文档中定义,本次不实现,留给后续 lfg 调用:
- Stage 2(R7-R10):三类采集入口前端 UI(Excel/DB/API)、Agent 写入反馈 UI
- Stage 3(R11-R13):看板视图、画廊视图、公式编辑器增强
- Stage 4(R14-R17):权限模型、自动化触发器、表单视图、甘特视图
Outside this product's identity
(从 origin 文档继承)通用电子表格、ETL/数据管道平台、BI 仪表盘、知识库 RAG 替代。
System-Wide Impact
- 数据模型变更:新增
bitable_files表,bitable_tables加file_id列。schema V1 → V2 启动时迁移。 - API 边界:新增
/api/v1/bitable/files端点组。现有/tables端点改为/files/{file_id}/tables(保留旧端点兼容性,标记 deprecated)。 - 前端路由:
/bitable从单视图重构为嵌套路由。现有书签需重定向。 - 领域词汇:CONCEPTS.md 需补"多维表格文件/BitableFile"条目。
Risks & Dependencies
- 风险:schema V2 迁移若失败可能导致启动卡住。缓解:迁移用
try/except包裹,失败时 log 并继续(向后兼容 V1 表为"默认文件"归属)。 - 风险:vxe-table header slot 与自定义编辑器的集成可能在版本差异下行为不一致。缓解:U4/U5 实现时先写最小验证 demo。
- 依赖:U2 依赖 U1(create_table 签名变更)。U3 依赖 U1(前端调用后端文件 API)。U4/U5 依赖 U3(store 重构)。U6 依赖 U3/U4/U5。
- 依赖:现有
docs/solutions/architecture-patterns/bitable-companion-service-security-reliability-patterns.md的 10 个模式必须遵守(特别是 IDOR ownership 检查、batch 操作、async I/O)。
Open Questions
Resolve During Implementation
- 文件图标用 emoji 字符串还是预设图标集?默认用 emoji 字符串(前端用
a-input输入),实现时确认。 - 现有
/tables端点是否保留?保留并标记 deprecated,新端点/files/{file_id}/tables为推荐路径。 BitableView.vue删除还是保留为 redirect?改为 redirect 到/bitable。
Deferred to Implementation
- vxe-table header slot 的具体 API 形态(版本相关,实现时查文档确认)。
- select 编辑器在 multiselect 下的值序列化格式(数组 vs 逗号分隔字符串,复用现有后端约定)。
Sources & Research
- Origin requirements:
docs/brainstorms/2026-06-29-bitable-ui-completeness-requirements.md - 安全/可靠性模式:
docs/solutions/architecture-patterns/bitable-companion-service-security-reliability-patterns.md(10 个模式,本次实现必须遵守) - 现有后端实现:
src/agentkit/bitable/{models,db,repository,service}.py+src/agentkit/server/routes/bitable.py - 现有前端实现:
src/agentkit/server/frontend/src/views/BitableView.vue+src/agentkit/server/frontend/src/components/bitable/*.vue+src/agentkit/server/frontend/src/stores/bitable.ts - 领域词汇:
CONCEPTS.mdBitable/Field Ownership/Recalc 定义 - 飞书多维表格范式: 文件→表→字段/记录三层;列头下拉管理字段;新建表默认字段
- twentyhq/twenty 布局参考: https://github.com/twentyhq/twenty
- vxe-table 4 文档: header slot 与自定义编辑器
- Ant Design Vue 4: Card/Modal/Dropdown/Select/Popconfirm/Tag 组件