@qfei-design/make-app-actions
v0.3.1
Published
Headless Make record-action model, reusable React action bar and batch-edit modal, Ant Design adapter, and CanvasTable selection adapter.
Keywords
Readme
@qfei-design/make-app-actions
Make App 列表记录操作包,提供选择态操作模型、行级权限校验、批量编辑字段规则、通用 React 操作栏与批量编辑弹窗、Ant Design 适配器,以及 CanvasTable 选择快照适配。
安装
pnpm add @qfei-design/make-app-actionsAnt Design 宿主还需要安装 peer dependencies:
pnpm add react react-dom antd @ant-design/icons宿主入口引入一次样式:
import "@qfei-design/make-app-actions/styles.css";包与宿主边界
包负责:
- 单条选择显示编辑、删除,多条选择显示批量操作。
- 无可用操作时默认显示“暂无可用的操作”。
- 部分记录无权限时保留操作入口,并返回无权限行 key。
- 批量可编辑字段过滤、清空值归一化,以及供无原生批量接口宿主选用的串行执行辅助能力。
- 标准操作栏、可注入宿主设计系统的通用批量编辑 Modal、AntD 适配器和 CanvasTable 选择快照适配。
宿主负责:
- 在应用初始化、身份或租户变化、显式刷新时从
/api/make/app/principal/permission加载并缓存权限。 - 用
data.record.update/delete/bulkUpdate决定 action 的visible。 - 用
meta.field.update生成批量可编辑字段 key。 - 渲染具体字段控件、加载候选项、构造 Make mutation payload。
- 点击操作时先冻结不可变的完整操作快照,再通过
apps/service对该快照执行一次行级写权限预检。 - 批量修改时调用一次
apps/service批量接口,并负责删除确认、吐司、异常行高亮和列表刷新。
Core
import {
RECORD_SELECTION_ACTION_BULK_EDIT,
RECORD_SELECTION_ACTION_DELETE,
RECORD_SELECTION_ACTION_EDIT,
isRecordSelectionIntentResolved,
resolveRecordOperationPermission,
resolveRecordSelectionActionState,
validateRecordBatchEditSelectionLimit,
validateRecordSelectionAction,
} from "@qfei-design/make-app-actions";
const actions = [
{
key: RECORD_SELECTION_ACTION_EDIT,
label: "编辑",
permissionKey: "data.record.update",
scope: "single",
visible: canUpdate,
canOperateRecord: (record) =>
resolveRecordOperationPermission(record, "data.record.update"),
},
{
key: RECORD_SELECTION_ACTION_DELETE,
label: "删除",
permissionKey: "data.record.delete",
scope: "single",
visible: canDelete,
canOperateRecord: (record) =>
resolveRecordOperationPermission(record, "data.record.delete"),
},
{
key: RECORD_SELECTION_ACTION_BULK_EDIT,
label: "批量编辑",
permissionKey: "data.record.bulkUpdate",
scope: "multiple",
visible: canBulkUpdate && batchEditableFields.length > 0,
canOperateRecord: (record) =>
resolveRecordOperationPermission(record, "data.record.bulkUpdate"),
},
] as const;
const state = resolveRecordSelectionActionState({
actions: [...actions],
selectedRecords,
selectedCount,
totalCount,
});
const validation = validateRecordSelectionAction(action, selectedRecords);
if (!validation.ok) {
setAlertRowKeys(validation.unauthorizedRowKeys);
toast.error("勾选范围中存在无权限数据,请检查勾选范围");
}isRecordSelectionFullyResolved 只用于判断已加载记录是否足够执行本地逐行权限判断,不能用它阻止服务端可解析的跨页选择。宿主应使用 Canvas adapter 返回的 selectionIntent 与 isRecordSelectionIntentResolved 判断提交目标是否完整:include 保留全部明确选中的 ID,exclude 保留全选后取消的 ID,并通过总数校验选择快照。
批量编辑前使用 validateRecordBatchEditSelectionLimit 校验数量。默认只限制 include 模式最多 200 条;恰好 200 条允许,exclude 模式不应用该限制。超限后的吐司和选择态保留仍由宿主负责。
Make 宿主标准编排
data.record.update、data.record.delete和data.record.bulkUpdate是相互独立的权限点;宿主从当前缓存的 principal 权限分别计算按钮可见性。- 使用
selectionIntent区分明确选择的include模式和点击表头全选产生的exclude模式,不能根据selectedCount === totalCount推断全选。 - 用户点击操作时先冻结不可变的操作快照,包含完整
selectionIntent、数量和最近一次成功查询的filter/groupFilter;后续列表状态变化不得改写该快照。 - 打开单条编辑或批量编辑界面前,将同一份操作快照交给 Service,Service 对 Make 行级写权限执行一次预检。预检拒绝时直接阻止打开界面;不要拆成逐 ID 诊断请求。
- 提交批量修改时复用同一份操作快照,只调用一次 Service 批量接口。Service 再向 Make 发起一次批量写请求,不循环调用单条更新接口。
- 权限预检只是用户操作前的反馈层,最终写接口仍必须执行权威鉴权。
principal 权限只在应用初始化、身份或租户变化、显式刷新时重新加载。按钮点击和提交使用当前缓存,不为每次操作重复请求 principal 权限。
CanvasTable
import {
resolveCanvasSelectedRecordSnapshot,
} from "@qfei-design/make-app-actions/adapters/canvas-table";
const snapshot = resolveCanvasSelectedRecordSnapshot(
table.getSelectionInfo(),
loadedRecords,
totalCount,
);
if (
!isRecordSelectionIntentResolved({
selectionIntent: snapshot.selectionIntent,
selectedCount: snapshot.selectedCount,
totalCount: snapshot.totalCount,
})
) {
throw new Error("CanvasTable 选择快照不完整");
}adapter 返回的兼容字段包括 rowKeys、records、selectedCount 和 totalCount,并新增:
selectAll:保留用户是否点击表头全选的原始意图;手动选满全部记录时仍为false。selectionIntent.mode = "include":recordIDs是全部明确选中的 ID,不受已加载记录缓存限制。selectionIntent.mode = "exclude":excludedRecordIDs是表头全选后取消勾选的 ID。
CanvasTable 宿主仍负责:
selectable: { enabled: true, type: "multiple" }。- 使用
table.tableId监听selection:change。 - 关闭操作栏时调用
clearSelection()。 - 用公开的
setRowColors或rowStyleOptions标记无权限行。 - 取消某行选择时移除该行异常态;关闭操作栏时清空全部异常态。
- 不使用
selectedCount === totalCount或表头视觉状态推断全选模式。
CanvasTable adapter 不导入 @qfei-design/canvas-table,避免把浏览器端表格运行时带进 core 或 SSR 构建。
React 操作栏
非 AntD 宿主使用通用组件:
import { RecordSelectionActionBar } from "@qfei-design/make-app-actions/react";
<RecordSelectionActionBar
components={hostComponents}
state={state}
onAction={handleAction}
onClose={clearSelection}
/>;AntD 宿主可直接使用:
import {
AntdRecordSelectionActionBar,
} from "@qfei-design/make-app-actions/adapters/antd";
<AntdRecordSelectionActionBar
state={state}
onAction={handleAction}
onClose={clearSelection}
/>;操作栏使用绝对定位,宿主表格容器需要 position: relative。
批量编辑弹窗
非 AntD 宿主通过 MakeAppBatchEditComponents 注入 Modal、字段选择器和修改模式控件:
import {
RecordBatchEditModal,
type MakeAppBatchEditComponents,
} from "@qfei-design/make-app-actions/react";
const batchEditComponents: MakeAppBatchEditComponents = {
Modal: HostDialog,
FieldSelect: HostSelect,
ModeControl: HostRadioGroup,
};
<RecordBatchEditModal
components={batchEditComponents}
open={batchEditOpen}
fields={batchEditableFields}
selectedCount={selectedCount}
saving={saving}
onClose={closeBatchEdit}
onSubmit={handleBatchEditSubmit}
renderValueControl={(field, control) =>
renderHostFieldEditor(field, control)
}
/>;通用弹窗拥有字段、模式、当前值、校验、异步错误和防重复提交状态。注入的 Modal 只负责视觉壳与确认/取消按钮;FieldSelect、ModeControl 只把宿主控件的值变化回传给包。宿主仍通过 renderValueControl(field, { value, onChange, disabled, invalid, ariaDescribedBy }) 渲染实际 Make 字段控件,并把无障碍属性转交给真实输入控件。
AntD 宿主可直接使用适配器:
import {
AntdRecordBatchEditModal,
} from "@qfei-design/make-app-actions/adapters/antd";
<AntdRecordBatchEditModal
open={batchEditOpen}
fields={batchEditableFields}
selectedCount={selectedCount}
saving={saving}
onClose={closeBatchEdit}
onSubmit={handleBatchEditSubmit}
renderValueControl={(field, control) =>
renderHostFieldEditor(field, { disabled: control.disabled })
}
/>;弹窗负责字段选择、“新值 / 清空内容”模式、校验、计数文案和布局。宿主通过 renderValueControl 按 Make 字段类型提供 Select、Input、DatePicker、Identity Picker 等控件,并把第二个参数中的 disabled 转交给实际控件;提交期间适配器也会对顶层 AntD 控件强制设置 disabled,兼容原有的一参数回调。包不把复杂字段降级为普通 Input,也不包含自动化流程选项。通用 React 与 AntD 入口共享 BatchEditValueMode、BatchEditSubmit 和 RecordBatchEditModalLabels 类型。
提交时:
- 检查当前缓存中的
data.record.bulkUpdate。 - 检查目标字段
meta.field.update。 clear模式使用resolveBatchEditClearValue(field)。- 宿主基于预检前冻结的同一份操作快照构造 payload,并调用一次 Service 批量修改接口。
- 成功后关闭弹窗、刷新列表并清理本次选择;清理时不得覆盖用户在请求期间产生的更新选择态。
runRecordBatchMutation 是供非 Make 或没有原生批量接口的宿主选用的串行 fallback,不是 Make 宿主批量修改的默认执行路径。
完整导出见 PUBLIC_API.md。
