Files
iot-device-management-frontend/apps/web-antd/src/views/iot/rule/chain/api/node-metadata.ts

66 lines
2.5 KiB
TypeScript
Raw Normal View History

[F3] DAG 画布属性面板 + 动态表单机制 主会话(Opus)自做,覆盖任务卡 §2 全部文件。 核心文件: - apps/web-antd/src/views/iot/rule/chain/api/node-metadata.ts - GET /iot/rule/provider/metadata API 封装 - ProviderMetadata/FormCreateSchema/FormCreateRuleItem 类型定义 - apps/web-antd/src/views/iot/rule/chain/stores/selected-node.ts - Pinia store: current 节点 + dirty 标记 + metadata 缓存 - metadataByType O(1) 索引 + getSchemaByType/getMetadataByType 查表 - loadMetadata fetcher 可注入(测试 + 后端未就绪 fallback 到 mock) - apps/web-antd/src/views/iot/rule/chain/components/node-schema/index.ts - 7 种节点 mock schema (device_state/device_property/timer/expression/ property_set/alarm_trigger/notify) - buildMockMetadata() 供 fallback 使用 - apps/web-antd/src/views/iot/rule/chain/components/DynamicNodeForm.vue - @form-create/ant-design-vue 封装,schema 切换自动 resetFields - "i18n:" 前缀约定递归解析 title/placeholder/options.label/validate.message - 过滤 undefined 避免 configuration 写入噪声 - apps/web-antd/src/views/iot/rule/chain/components/DagPropertyPanel.vue - 面板容器:节点名称输入 + DynamicNodeForm - onMounted 加载 metadata,后端失败 fallback 到 mock(node-schema) 测试: - selected-node-store.spec.ts 13 用例(store actions / loadMetadata / getSchemaByType / reset) - node-schema.spec.ts 12 用例(mock schema 覆盖 5+ 种 / buildMockMetadata 映射) i18n: iot.dag.panel.* / iot.dag.field.* / iot.dag.option.* / iot.dag.validate.* zh-CN 与 en-US 同步新增。 Known Pitfalls 落地: - 评审 B5/H2: 模板变量用 ${data.x}/${alarm.x}/${trigger.x} 占位(notify template placeholder 字面展示,禁用旧 $[...] 语法) - form-create schema 切换时调用 fApi.resetFields 防止字段残留 - configuration 过滤 undefined 防止响应式写入 null - iot:subsystem:simple-list 权限 403 由 @vben/request 拦截器统一处理 - TS 严格模式零 any,configuration 类型 Record<string, unknown> 决策 5 双入口: - 本任务仅新建 chain/ 目录的组件 + store + API + mock schema - 路由追加由后续任务处理(项目采用动态菜单机制,静态路由 modules/iot.ts 仅放 hideInMenu 详情页;chain 的 list/edit 菜单由后端 menu 表配置) - 现有 iot/rule/scene/* 保持不变 ✓ 质检: - pnpm test:unit src/views/iot/rule/chain → 48/48 通过 - pnpm lint apps/web-antd/src/views/iot/rule/chain/ → 0 errors - pnpm check:type (web-antd) → chain 目录 0 errors(其他模块预存错误与本任务无关) note: DagPropertyPanel + DynamicNodeForm 的渲染集成测试留给 F7 edit.vue 真实画布 dogfood;本次 unit test 覆盖纯函数与 store。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 23:12:11 +08:00
/**
* F3 Provider Metadata API
*
* B4/B5/B6 Provider SPI form-create schema
* Pinia
*
* B4/B5/B6 使 mock F2 `useNodeCatalog` NodeTypeMeta
* `schema.rule`
*/
import type { NodeTypeMeta } from '#/components/iot-dag';
import { requestClient } from '#/api/request';
// ──────────────────────────────────────────────
// 类型定义
// ──────────────────────────────────────────────
/** form-create rule 单项 — 与 @form-create/ant-design-vue 的 Rule 对齐(宽松定义) */
export interface FormCreateRuleItem {
/** 组件类型select / input / DeviceSelector 等) */
type: string;
/** 字段名 */
field?: string;
/** 显示标题i18n key 或原始文案) */
title?: string;
/** 组件 props */
props?: Record<string, unknown>;
/** 下拉选项 */
options?: Array<{ label: string; value: boolean | number | string }>;
/** 校验规则antd Form rule 风格) */
validate?: Array<Record<string, unknown>>;
/** 默认值 */
value?: unknown;
/** 子项(嵌套表单) */
children?: FormCreateRuleItem[];
}
/** form-create schema完整 */
export interface FormCreateSchema {
/** 字段规则数组 */
rule: FormCreateRuleItem[];
/** 全局 optionsubmitBtn / resetBtn 等) */
option?: Record<string, unknown>;
}
/** Provider 节点元数据(含 schema比 NodeTypeMeta 多一层) */
export interface ProviderMetadata extends NodeTypeMeta {
/** 动态表单 schemaform-create 配置) */
schema: FormCreateSchema;
}
// ──────────────────────────────────────────────
// API
// ──────────────────────────────────────────────
/**
* Provider schema
*
* `GET /iot/rule/provider/metadata`
* B4/B5/B6 `ProviderMetadata[]`
*/
export function getProviderMetadata(): Promise<ProviderMetadata[]> {
return requestClient.get<ProviderMetadata[]>('/iot/rule/provider/metadata');
}