公司动态
低代码界面原型怎样交付使用
低代码界面原型怎样交付使用生成式 UI 可以很快产出原型但原型与可交付功能之间仍隔着组件契约、状态管理、权限和安全校验。更稳妥的做法是让模型输出受限的 Schema由前端按白名单渲染而不是执行模型生成的任意代码。1. 原型不能直接视为生产代码将 LLM 输出直接用于生产环境时常见的问题有幻觉属性与类型污染模型经常凭空臆造某些不存在的 UI 组件属性。比如把 Element Plus 或 Ant Design 的on-change混用导致运行时控制台疯狂报错。缺乏状态闭环与校验规则生成表单时只画出了输入框却没有绑定真正的 Schema 校验机制更别提异步提交时的 Loading 锁定和 Duplicate 提防。样式与安全边界不清未经约束的 HTML、URL 或事件名可能绕过既有规范若把字符串交给innerHTML或动态执行更会引入 XSS 风险。因此模型输出应被当作不可信输入。为它定义 Schema、组件白名单和明确的降级结果比“修复一段生成的源码”更容易审计。2. 生成式 UI 确定性工程拦截架构在前端接入生成式 UI 时我们设计了一套生成-校验-沙箱-渲染四级闭环流程只有通过了 Schema 严格校验和脚本安全清洗的代码才会被送到前端引擎中动态渲染。3. Vue3/TypeScript 受限渲染示例下面的 Vue3 示例只接受两种声明式节点。它不是 JavaScript 执行沙箱安全性来自不执行模型提供的代码、只映射允许的属性和组件。Vue 的插值和属性绑定会转义普通字符串若业务确实需要渲染 HTML再针对该字段使用可信的净化策略。import { defineComponent, h, ref, computed, PropType } from vue; import { z } from zod; import DOMPurify from dompurify; // 1. 严格定义生产环境允许挂载的 UI 组件白名单与 Schema 约束 const ButtonSchema z.object({ type: z.enum([button]), label: z.string().max(50), variant: z.enum([primary, secondary, danger]).default(primary), disabled: z.boolean().optional(), }); const InputSchema z.object({ type: z.enum([input]), field: z.string().regex(/^[a-zA-Z0-9_]$/), placeholder: z.string().optional(), defaultValue: z.string().optional(), }); export const ComponentNodeSchema z.discriminatedUnion(type, [ ButtonSchema, InputSchema, ]); export type ComponentNode z.infertypeof ComponentNodeSchema; // 2. 动态安全渲染器组件 export const GenerativeUIRenderer defineComponent({ name: GenerativeUIRenderer, props: { rawSchema: { type: Object as PropTypeunknown, required: true, }, formData: { type: Object as PropTypeRecordstring, any, default: () ({}), } }, emits: [submit, update:formData], setup(props, { emit }) { const errorState refstring | null(null); // 校验与解析 Schema const validatedNode computedComponentNode | null(() { try { errorState.value null; return ComponentNodeSchema.parse(props.rawSchema); } catch (err: any) { errorState.value [UI-Schema-Error] 非法组件结构: ${err.message}; return null; } }); const handleInputChange (field: string, val: string) { const updated { ...props.formData, [field]: DOMPurify.sanitize(val) }; emit(update:formData, updated); }; return () { // 容错降级如果 AI 生成的结构非法渲染降级警告组件 if (errorState.value || !validatedNode.value) { return h(div, { class: ui-fallback-card border-red-500 p-4 }, [ h(p, { class: text-red-500 font-bold }, 生成式 UI 无法安全渲染), h(pre, { class: text-xs text-gray-500 }, errorState.value || 未知校验错误) ]); } const node validatedNode.value; // 渲染逻辑分支Button Component if (node.type button) { return h(button, { class: btn btn-${node.variant} ${node.disabled ? opacity-50 : }, disabled: node.disabled, onClick: () emit(submit, props.formData) }, DOMPurify.sanitize(node.label)); } // 渲染逻辑分支Input Component if (node.type input) { return h(input, { class: input-control border rounded p-2, placeholder: DOMPurify.sanitize(node.placeholder || ), value: props.formData[node.field] ?? node.defaultValue ?? , onInput: (e: Event) handleInputChange(node.field, (e.target as HTMLInputElement).value) }); } return null; }; } });4. 上线前检查将生成式 UI 接入主链路前可以检查以下事项Schema 规则闭环AI 输出应符合 Zod/JSON Schema不要将未验证的字符串交给innerHTML或eval。属性白名单防御所有组件 Attribute 只能采用白名单映射忽略大模型自动生成的离谱自定义属性。异常降级与修复流程Schema 解析失败时显示安全的降级组件如需让模型重试回传经过脱敏和裁剪的校验错误。状态边界为每个组件实例定义局部状态与允许共享的状态避免无意写入全局变量。性能预算根据设备范围和页面基线限定节点数、请求数和脚本耗时“100 个节点”并非通用阈值。5. 结语模型可以协助产出结构和文案前端仍要负责组件契约、数据流、权限和可观测性。将输出限制为可校验的 Schema才能让原型逐步进入可维护的业务流程。