ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Instatic Data Workspace 深度指南:可视化表结构与行级数据管理

Instatic Data Workspace 深度指南:可视化表结构与行级数据管理 Instatic Data Workspace 深度指南可视化表结构与行级数据管理【免费下载链接】InstaticThe open-source alternative to Webflow, Framer and WordPress. Agentic self-hosted visual CMS outputting clean static pages. Users, roles, plugins, content, database, its all there.项目地址: https://gitcode.com/GitHub_Trending/in/InstaticInstatic 的 Data Workspace 是管理data_tables表结构/字段 Schema与data_rows原始行数据的后台管理界面入口为/admin/data。本文从三栏布局的组件结构出发结合仓库源码src/admin/pages/data/与src/core/data/逐层讲解表 Schema 编辑、字段分级锁定、Repeater 结构化数据、只读表格网格、批量操作与导入导出等核心能力帮助读者完整掌握这套无 Zustand 状态库、纯 Hook 驱动的数据工作台的设计与使用。概览Data Workspace 是什么Data Workspace 是 Instatic 中负责表结构与原始行数据管理的后台工作区允许操作者完成两件事定义与编辑表 Schema字段类型、字段路由route、显示设置、主字段等直接查看与编辑行数据以只读电子表格read-only spreadsheet的形式浏览data_rows在右侧检查器中逐单元格编辑。值得强调的是该工作区没有独立的 Zustand store——所有数据获取与变更都通过 useDataWorkspace Hook 完成这使其与 Site/Content 等依赖编辑器 store 的工作区在架构上明确区隔架构测试 non-site-workspaces-no-editor-store.test.ts 对此有约束。从源码结构可以推断这一设计让 Data 工作区天然适合作为与编辑器解耦的纯数据管理面。入口页面 DataPage.tsx 通过AdminWorkspaceCanvasLayout组装出三栏工作区左侧DataSidebar表列表、中间DataCanvas表格网格、右侧DataInspector检查器。组件结构三栏布局与职责划分原文档给出了完整的组件树这里整理并标注职责DataPage.tsx └── DataCanvas.tsx ├── DataSidebar.tsx ← 表列表、新建表对话框、导入/导出入口 │ └── DataTableContextMenu.tsx ← 表级右键菜单 ├── DataGridSkeleton.tsx ← 未选中任何表时的全画布骨架屏 ├── DataGrid.tsx ← 容器持有交互状态装配各子组件 │ ├── DataGridToolbar.tsx ← 两行工具栏标题/副标题、搜索、添加行、排序指示 │ │ └── DataGridViewChips.tsx ← 状态/范围筛选胶囊All / Published / Scheduled / Drafts / ArchivedPage 表另有 Pages / Templates │ ├── DataGridHeaderRow.tsx ← 列头行全选复选框 每字段列头 │ │ └── DataGridHeaderCell.tsx ← 单列头类型图标 标签 排序箭头 │ ├── DataGridGroupHeader.tsx ← 可折叠状态分组头Published / Drafts / Archived │ ├── DataGridRow.tsx ← 数据行单元格 │ ├── DataGridSkeletonRows.tsx ← 行加载中的 shimmer 占位 │ ├── DataGridEmptyState.tsx ← 无数据提示区分空表与筛选无结果 │ ├── DataGridBulkActionBar.tsx ← 批量发布/导出/删除悬浮操作栏 │ ├── DataRowContextMenu.tsx ← 行级右键菜单 │ ├── dataGridRows.ts ← 纯函数筛选/排序/分组管道、列宽计算 │ ├── useDataGridSelection.ts ← 批量选中状态 Hook │ └── cells/ ← 各字段类型的展示与编辑组件 └── DataInspector.tsx ← 右侧检查器面板 ├── RowDetail.tsx ← 选中行逐单元格编辑器 └── TableSettings.tsx ← 未选中行Schema 与元数据编辑器 └── FieldsSection.tsx ← 持久化表的字段适配层 └── FieldSchemaComposer NewTableDialog.tsx └── FieldSchemaComposer ← 本地 Schema 草稿随表身份一起提交 ├── FieldRow.tsx ← 有序字段摘要 └── NewFieldDialog.tsx ← 新增/编辑字段定义与 Repeater 子字段组件源文件全部位于 src/admin/pages/data/components/。每个子组件都聚焦单一职责工具栏管搜索与添加行、列头管排序指示、分组头管状态折叠交互状态则由容器组件DataGrid.tsx统一持有。DataInspector行详情与表设置自动切换DataInspector.tsx 是右侧面板的开关枢纽当row: DataRow | null有值时渲染RowDetail逐单元格编辑器无值时渲染TableSettingsSchema 与元数据编辑器。切换完全由 props 驱动// DataInspector.tsx简化 {row ! null ? ( RowDetail row{row} table{table} ... / ) : ( TableSettings table{table} rows{rows} ... / )}这意味着取消选中行即可自然进入表设置视图——原文档特别注明曾在工具栏添加Table settings快捷键的做法已被移除因为选中态切换已经足够直观架构测试 dataPageToolbar.test.ts 专门防止该入口回归。TableSettings 与字段管理TableSettings.tsx 渲染可折叠分区General / Routing / Schema / Kind / Danger zone。Schema 分区委托给FieldsSection每个可编辑字段行都带有一个设为主字段star操作可在定义结构处直接指定主字段。系统表的精简面板对于系统表posts/pages/components/layouts面板被缩减为仅含 Schema且受data.system.tables.manage能力门控。General / Routing / Kind / Danger zone 全部隐藏因为系统表身份被冻结——服务端assertSystemTableUpdateAllowed会拒绝所有用户对身份字段与内建字段的修改见 systemTableGuard.ts。不过具备权限的管理员仍可在系统表上新增 / 编辑 / 删除自定义字段从符合条件的字段行中更换主字段。从 systemTableGuard.ts 的源码可以看出冻结规则的精确定义FROZEN_IDENTITY_KEYSname、slug、routeBase、singularLabel、pluralLabel任何差异写入都会被拒绝系统表的内建字段既不能删除、不能编辑、也不能新增新的builtIn字段而自定义字段完全不受限。共享 Schema 编排器 FieldSchemaComposerFieldSchemaComposer.tsx 是复用的字段列表交互组件被新建表流程与TableSettings共用拖拽排序基于原生 HTML5 拖拽 APIhandleDrop重排table.fields后调用onUpdateTable编辑打开NewFieldDialog作者面向的 label 在前、不可变的 machine id/type 并列其后删除经useConfirmDelete确认后以移除字段后的数组调用onUpdateTable新建字段通过NewFieldDialog。新建字段时NewFieldDialog会先从 label 推导 machine id直到作者手动编辑 ID。已存在的 ID 与类型保持固定从而保证已保存的行值键稳定详见下文禁止模式中的说明。FieldsSection.tsx通过fieldGuards.ts计算表专属的锁定、标签、内建与可删除集合再注入 ComposerNewTableDialog.tsx则给同一个 Composer 一份本地字段数组并在单次创建请求中随集合身份一起提交。字段分类fieldGuards.ts 的三级体系原文档的核心分级表在此完整保留这是理解 Data Workspace 权限模型的关键层级字段 ID编辑能力删除能力强制内建postTypetitle、slug无——整行锁定无编辑/删除按钮阻止可选内建postTypebody、featuredMedia、seoTitle、seoDescription仅 description 与 required 可编辑label 锁定允许系统表上的内建字段每个builtIn字段无——整行完全锁定阻止自定义字段其余全部完全可编辑允许主字段除外对应的判定函数全部实现在 fieldGuards.tsisMandatoryField(fieldId) // postType 上的 title 或 slug isOptionalBuiltIn(field) // builtIn: true 但非强制 isSystemBuiltInField(field, table) // 系统表上的内建字段——冻结 isFieldFullyLocked(field, table) // postType 强制 或 系统内建 → 不可编辑/删除/重排 isFieldDeletable(field, table) // 主字段或任何完全锁定字段 → false isLabelLocked(field, table) // postType 内建字段与系统内建 → true deleteTooltip(field, table) // 禁用按钮的提示文案或 undefined这些守卫函数在FieldsSection中读取FieldsSection自身不包含kind postType分支——分类职责被严格收敛在fieldGuards.ts架构上禁止在FieldsSection里内联分类逻辑。此外FIELD_TYPE_LABELS将每个DataFieldType映射为人类可读字符串被FieldRow与FieldSchemaComposer共享。值得注意的例外内建字段的行值单元格数据在已有记录上始终可编辑包括结构性系统表pages / components / layouts。唯一的值锁定发生在创建时刻protectedBuiltInCreateCellKeysystemTableGuard.ts 导出会拒绝为结构性系统表创建时提供内建单元格——这些行必须经由各自的创作界面诞生而不是通用行端点posts因kind postType豁免。服务端在 tables.ts 中强制执行。字段类型全景schemas.tsschemas.ts 是字段定义的单一事实来源Single Source of TruthDataFieldSchema是按type判别discriminated union的 TypeBox 联合类型共 16 种类型单元格值形态cells_json[fieldId]关键配置textstring \| nulldefaultValue、maxLength、placeholderlongTextstring \| nulldefaultValuerichTextstring \| nullformat: markdown \| htmlnumbernumber \| nullmin、max、step、integer、formatnumber/currency/percent、currencybooleanboolean \| nulldefaultValuedateISO 字符串 | null—dateTimeISO 字符串 | null—select选项 idstring| nulloptions[]id/label/value/color、defaultValuemultiSelect选项 id 数组string[]options[]urlstring \| null—emailstring \| null—media媒体 idstring| null单媒体 id 数组string[]多mediaKind: image \| video \| any、allowMultiplerelation行 idstring| null单行 id 数组string[]多targetTableId、allowMultiplerepeater有序{ id, cells }[]fields子字段、itemLabelFieldIdpageTree完整页节点树NodeTreePageNode单元格渲染Open editor →按钮跳转视觉编辑器fieldSchemaDataField[]单元格渲染Edit params (N)打开字段选择对话框component 行的params字段DATA_FIELD_TYPES以 const 数组导出全部类型字面量供架构测试与选择器迭代架构测试 binding-compatibility-coverage.test.ts 会确保它与DataFieldSchema联合不漂移。RepeaterItemFieldSchema刻意排除了repeater、pageTree、fieldSchema——Repeater v1 只建模一层深度的有序普通值集合避免递归 Schema 或嵌套文档树。五种表类型kinddata_tables与data_rows是统一存储五种表共享该存储见schemas.ts注释与DataTableKindSchemakind: postType—— 经 Content 管理页创作保留内建字段title、slug、body、featuredMedia、seoTitle、seoDescription带草稿/已发布/未发布工作流与版本kind: data—— 经 Data 管理页网格创作无内建、无版本工作流kind: page—— 编辑器管理的页面以 page-tree 单元格存储kind: component—— 编辑器管理的视觉组件kind: layout—— 编辑器管理的已保存布局快照。所有单元格值存放在cells_json按字段 id 键控slug与status是行上的反规范化列用于索引与路由查找。行状态DataRowStatusSchema为draft | published | unpublished | scheduled。scheduled行等待发布调度器 tickpublishScheduler.ts——scheduledPublishAt携带目标 ISO 时间tick 在now() scheduledPublishAt时调用publishDataRow(...)并将行翻转为published发布失败则回到draft。Repeater 结构化数据创作RepeaterCell.tsx 通过readRepeaterCell读取值、以emptyCellValue初始化嵌套单元格并将完整的有序值经由普通行草稿写回。嵌套的 relation 与 media 字段复用共享选择器多选媒体字段将MediaPickerModal置于真正的多选模式——单击切换资产、页脚一次性提交整个选集。当 Repeater 恰好只包含一个单值媒体字段时MediaRepeaterGallery.tsx 会替代通用结构化卡片复用 Media 工作区的展示方式渲染共享的AssetTile/AssetRow组件使用同一份持久化的 grid/list 切换偏好空槽位由多选选择器填充每个资产保持替换replace、重排reorder、移除remove操作移除条目永不删除底层 Media 库文件。含额外字段的 Repeater 继续使用通用卡片编辑器。DataGrid只读电子表格DataGrid.tsx 是data_rows上的只读电子表格单元格渲染为展示性的 chips / 缩略图 / 格式化值编辑在行检查器中打开。文件自身持有交互状态——搜索、状态筛选、排序、选中、分组折叠、列宽——并装配各个聚焦子组件。子组件职责一览文件职责DataGridToolbar.tsx两行工具栏标题 行数副标题、搜索框、Add row 按钮底行发布工作流表DataGridViewChips 活跃排序指示DataGridViewChips.tsx胶囊筛选All / Published / Scheduled / Drafts / Archived页面表为 Pages / TemplatesDataGridHeaderRow.tsx列头行前导全选复选框、每有序字段一个DataGridHeaderCell、尾部操作列DataGridHeaderCell.tsx单列头字段类型图标 标签 排序方向箭头裸buttonCSS-Grid 内rolecolumnheader为 §8.8 例外DataGridGroupHeader.tsx全宽可折叠分组头状态圆点 标签 计数裸button网格跨列展开开关§8.8 例外DataGridRow.tsx数据行复选框、主单元格、经CellDisplayRenderer渲染的字段单元格、尾部操作按钮DataGridSkeletonRows.tsxloading true时的逐行 shimmer 单元格与DataGridSkeleton共享列阶梯与粘性定位DataGridEmptyState.tsx网格内无数据提示区分空表与筛选无结果DataGridBulkActionBar.tsx选中 ≥1 行时经FloatingActionBar显示的悬浮操作栏发布 / 草稿 / 导出 / 删除DataGridSkeleton.tsx未选中任何表时由DataCanvas渲染的全画布骨架屏DataRowContextMenu.tsx行级右键菜单见下文右键菜单纯函数层dataGridRows.ts所有无副作用逻辑被抽离到 dataGridRows.ts不进入组件体列宽getColumnWidth(field, isPrimary, primaryWidth)按字段类型映射像素宽度字段排序getOrderedFields将主字段置首getSubtitleFieldId识别 slug 字段以折叠进主单元格筛选 排序管道filterAndSortRows({ rows, statusFilter, query, sort, … })依次应用状态胶囊、文本搜索、比较器排序分组groupRowsByStatus(visibleRows, hasPublishWorkflow, statusFilter)在活跃胶囊为all/pages/templates时将行装入RowGroup[]状态计数computeStatusCounts(rows)驱动胶囊徽标。原文档明确禁止把筛选/排序/分组逻辑写进DataGrid.tsx——容器只允许持有交互状态并装配子组件。选中状态useDataGridSelection.tsuseDataGridSelection.ts 返回DataGridSelection已勾选 id 集合、派生出的allChecked/someChecked/headerChecked标志以及toggleRow/toggleAll/clearSelection变更器。选中状态在筛选变化时保留表头复选框只反映当前可见行。单元格展示CellDisplayRenderer.tsx 依据field.type分发到cells/目录下对应的展示组件TextCell、NumberCell、BooleanCell、DateCell、DateTimeCell、EmailCell、UrlCell、SelectCell、MultiSelectCell、MediaCell、RelationCell、RepeaterCell、RichTextCell、LongTextCell、PageTreeCell、FieldSchemaCell。网格是只读的——CellEditorRenderer.tsx 只被检查器中的RowDetail.tsx使用。主列宽度经 usePrimaryColumnWidth.ts 持久化到localStorage键instatic-data-grid-primary-widths-v1见 persistence-keys.md。列头单元格通过getFieldIcon(field.type)({ size: 13 })直接调用函数而非 JSX 组件渲染类型图标以规避react-hooks/static-components对普通图标调用的 lint 规则。右键菜单与跨工作区一致性右键操作沿用 Site / Content / Media 工作区的同一模式DataGrid.tsx选中被右键的行、记录点击坐标并通过共享ContextMenu原语渲染DataRowContextMenu页面/组件行暴露Open in Site editorpostType 行暴露Edit in Content普通数据行暴露Open row发布工作流表postType、page、component在提供onSetRowStatus时暴露行级Publish、Move to draft、Archive行复制、导出、删除复用与 Add row、批量操作栏、行尾按钮相同的 workspace 处理器。复制调用buildDuplicateRowCellsduplicateRow.ts——深度克隆单元格、标题追加(copy)、并生成避免与既有兄弟行冲突的唯一 sluguniqueCopySlug会依次尝试-copy、-copy-2、-copy-3…DataSidebar.tsx选中被右键的表并渲染DataTableContextMenu暴露Open table、Table settings、Delete table系统表、有行的表、无表管理权限的会话菜单中禁用表删除解释性提示来自 Button 原语的aria-disabled路径。未被任何应用菜单处理的后台右键事件由 AdminContextMenuGuard 拦截——已有菜单在源头调用preventDefault()因此该守卫只在确实无人处理时展示危险闪烁。发布工作流与站点重载对系统page与component行的变更会通过requestCmsSiteReload()请求保留 Site 编辑器重载使/admin/site即使在编辑器 store 已水合后也能看到 Data 创建出的页面与视觉组件。在 useDataWorkspace.ts 中tableBacksSiteDocument判定kind page || kind component后createRow/duplicateRow/saveRow/deleteRow均会触发该重载。工具栏右侧的PublishActionGroupDataPage.tsx 中装配提供Save draft与Publish data发布前会先 flush 活跃草稿再对hasDraftChanges(row)已发布但updatedAt publishedAt或处于非 published 状态且具备canPublishContentEntry权限的行逐一publishRow并以 toast 汇报发布行数。scheduled状态不能通过批量状态设置器到达——它必须走专门的调度对话框SchedulePublishDialog携带目标时间戳调用/schedule端点。无 Store 的数据获取useDataWorkspaceuseDataWorkspace.ts 是整个工作区的数据中枢从源码可以看出几个关键设计深链支持工作区可直接通过?tableslugrowid链接定位。挂载时一次性捕获useInitialQueryParams()initialRowIdRef持有行 id 直到初始表的行加载完成一次性应用后清空活跃选择通过useUrlQuerySync镜像回 URL!loadingTables门控避免首帧抹掉入站深链双独立加载状态tables 与 rows 是两个独立 fetch故保留loadingTables/loadingRows与tablesError/rowsError的细粒度字段而不是合成单一 loading/error文档注明这是对WorkspaceLoadState的有意例外渲染期重置切换选中表时行状态在渲染期而非 effect 中通过trackedTableId比较重置避免 setState-in-effect 并防止重复点击同一表时误清空已加载行变更即列表同步createTable本地追加{ ...table, rowCount: 0 }updateTable保留既有rowCount更新端点返回无 rowCount 的裸DataTabledeleteTable后自动选下一个可用表行草稿saveRow对应saveCmsDataRowDraft草稿保存端点publishRow与setRowStatus分开对应服务端独立路由published 与 draft/unpublished 两条路径scheduled则强制走调度对话框。Hook 暴露的完整接口tables 列表、选中态、create/update/delete table、rows 列表、create/duplicate/save/delete row、publish/setRowStatus 等为DataPage.tsx中的工具栏、批量栏、右键菜单、检查器提供了统一的变更入口。导入 / 导出CMS Bundle 双向传输批量传输按方向拆分导入打开全局标准的 Site Import 模态框SiteImport。CMS 导出的SiteBundleJSON 在此被识别先经/admin/api/cms/import/preview预览再通过/admin/api/cms/import应用。成功导入会触发 admin 事件使已挂载的 Data 视图刷新表与行缓存——DataPage.tsx 监听CMS_SITE_BUNDLE_IMPORTED_EVENT并同时调用refreshTables()与refreshRows()导出由 ExportDialog.tsx 与 useExportEstimate.ts 负责先做计数估算再下载 CMS bundle JSON。两个入口都从DataSidebar打开。DataPage中的导出支持initialScope: all与selectedRowIds批量选中行导出导入/导出能力分别受canExportData/canImportData门控。禁止模式架构红线一览原文档给出的禁止模式完整保留如下它们既是架构测试的约束对象也是理解设计意图的捷径模式原因直接读写cells_json必须使用 cells.ts 中的 typed readers复制行时重新实现标题命名或 slug 冲突逻辑使用buildDuplicateRowCellsduplicateRow.ts内联比较字段分类从fieldGuards.ts导入在FieldsSection内添加kind postType分支分类归属fieldGuards.tsFieldsSection只读取isMandatoryField、isOptionalBuiltIn等创建后编辑字段的类型或 machine idNewFieldDialog编辑时禁用两者保证存储的行值键稳定允许 Repeater 嵌套 RepeaterRepeaterItemFieldSchema排除repeater、pageTree、fieldSchema在这些组件中手写useMemo/useCallbackReact Compiler 自动记忆化仅使用仓库文档化例外见 react-compiler.md把筛选/排序/分组逻辑写进DataGrid.tsx逻辑在dataGridRows.ts纯、无副作用DataGrid.tsx只持有交互状态并装配子组件把 DataGrid 当作内联单元格编辑器网格只读CellEditorRenderer.tsx属于检查器RowDetail.tsx而非网格在DataPage工具栏添加 Table settings 快捷键TableSettings通过取消选中行自动到达重复的工具栏入口已被移除dataPageToolbar.test.ts 防止回归数据模型与相关文档Data Workspace 面向的是data_tables含system标志、primaryFieldId、fields数组与data_rowscells、反规范化slug/status、可选seq全局同步序列、scheduledPublishAt、deletedAt软删除的统一存储。更完整的字段模型见 content-storage.mdUI 原语Button、Input、Select、Switch用法见 ui-primitives.md。事实依据文件清单Data 工作区全部组件src/admin/pages/data/检查器与字段管理模块src/admin/pages/data/components/DataInspector/DataField联合类型与DataFieldTypeschemas.tsisPostTypeBuiltInFieldId与强制字段 ID 常量fields.ts类型化单元格读取器cells.ts行复制标题副本 slug 冲突规避duplicateRow.ts系统表不可变规则服务端强制 客户端门控共用systemTableGuard.ts服务端表端点强制tables.ts发布调度 tickpublishScheduler.ts【免费下载链接】InstaticThe open-source alternative to Webflow, Framer and WordPress. Agentic self-hosted visual CMS outputting clean static pages. Users, roles, plugins, content, database, its all there.项目地址: https://gitcode.com/GitHub_Trending/in/Instatic创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表