071faa482c
纳入 AGC Cargo workspace 的统一 rustfmt 检查与格式化入口 完成项目 TypeScript/Prettier 与 Rust 全量格式化 修复 Pingora expected executable 门禁的空白敏感误报 同步开发运维文档与 AGC skill pack 格式化忽略规则
2.8 KiB
2.8 KiB
本次后台表查询接入的可复用经验
需求落点
- 后台“总览”页的表统计仍保留,只把每张表的表名改成可点击跳转到
#tables?table=<name>。 - 新增独立
#tables页承载表选择、关键词搜索、结构化字段筛选、limit、行详情弹窗(详情内保留字段复制,列头漏斗按钮可按列添加条件;每条条件可勾选启用或停用,停用时保留字段和值;in/notIn使用逐项值标签,支持粘贴多行值,逗号不再作为隐式分隔符)。
后端实现要点
- 新增只读接口:
GET /admin/api/database/tablesGET /admin/api/database/tables/{table_name}/rows
- 表名必须来自 schema 白名单;再加一层 identifier 校验,避免任意 SQL 表名注入。
limit必须 clamp;本次实现使用默认 100、最大 500。search/filters不进入 SQL 字符串:- SQL 只负责
SELECT * FROM {table_name} LIMIT {limit} - 返回后在 api-server 内存中过滤
filters接受两种 JSON 形式:object(列名到等值,如{"user_id":"u1"})与条件数组(如[{"column":"points","op":"gt","value":"5"}],运算符含eq、ne、gt、gte、lt、lte、contains、notContains、startsWith、endsWith、in、notIn、isEmpty、isNotEmpty,允许同列多条件,条件间为 AND);非 object 且非数组直接 400,未知运算符或 value 形态不匹配也 400。数组中的eq/ne和其他标量运算符一样必须提供value;显式空值判断使用isEmpty/isNotEmpty
- SQL 只负责
- SpacetimeDB HTTP SQL 返回可能是 statement array + rows,解析时要兼容这一层结构。
前端实现要点
adminRoutes必须新增tables,AdminShell.routeIcons也要同步覆盖。AdminApp需要显式渲染AdminDatabaseTablesPage。- 预览表格数据行直接点击(或行自身聚焦后按 Enter / Space)打开详情,行内按钮 / 输入控件的键盘操作不冒泡打开详情;详情按钮不单独占列。详情字段仅提供复制操作,成功、剪贴板失败和空字段复制都使用右下角自动消失的 Toast,JSON 预览与平台亮色 / 暗色主题保持一致,表头保持单行并在空间不足时省略显示。表单和标题区查询按钮共用筛选完整性校验。
- worktree 下可能没有本地
node_modules/typescript/bin/tsc,而根目录有依赖;在验证前可以临时把根目录node_modules软链到 worktree 再执行npm run admin-web:typecheck,验证后删除软链,避免污染 git 状态。
验证结果
cargo test -p api-server admin_database -- --nocapture通过。cargo fmt --manifest-path Cargo.toml -p api-server -p shared-contracts --check通过。npm run admin-web:typecheck通过。npm run admin-web:build通过。npm run check:encoding通过。