表单页设计
云控专属可视化开发工具
- 全网独家定制
- 数据私有化部署
- 支持多级菜单管理
- 多用户分级管理
- 二次开发成本直降80%
全局方法
提供两个用于获取表单数据的全局方法:
| 方法名 | 说明 |
|---|---|
get[formName]ControlByName(name) | 根据字段 name 获取表单项(完整数据对象) |
get[formName]ValueByName(name) | 根据字段 name 获取表单项的值 |
说明
formName:表单名称(动态拼接)Control:返回完整字段对象(包含 label、type、value 等)name:表单字段唯一标识Value:仅返回字段值,多用于跨字段取值、表单联动及复杂校验场景(如确认密码校验)
表单 opt 配置
opt = {
list: [...], // 字段配置
form: {...}, // 表单配置
events: {...}, // 事件
config: {...} // 表单接口行为配置
}
字段列表 list
每个字段对象包含以下属性:
| 属性名 | 说明 | 类型 | 是否必填 | 默认值 |
|---|---|---|---|---|
type | 组件类型 | string | 是 | — |
name | 字段名(唯一标识) | string | 是 | — |
control | 组件属性配置 | object | 是 | {} |
formItem | 表单项配置(标签、校验规则) | object | 否 | {} |
customRules | 自定义校验规则 | array | 否 | [] |
config | 扩展配置(远程数据、联动等) | object | 否 | {} |
{
type: "input", // 组件类型,固定为 input
name: "username", // 字段名,绑定数据用的 key
control: {
modelValue: "", // 绑定的输入值,双向绑定
type: "text", // 输入框类型,如 text、password 等
placeholder: "请输入用户名", // 输入框占位提示文字
maxlength: 20, // 最大输入长度
minlength: 3, // 最小输入长度
showWordLimit: true, // 是否显示字数统计
clearable: true, // 是否显示清除按钮
disabled: false, // 是否禁用输入框
readonly: false, // 是否只读
autocomplete: "off", // 浏览器自动完成功能,off 禁用
autofocus: false, // 是否自动聚焦
tabindex: "1", // tab 键顺序
validateEvent: true, // 是否触发表单验证事件
inputStyle: { // 输入框自定义样式
color: "#333", // 字体颜色
fontSize: "14px" // 字体大小
},
size: "default", // 输入框尺寸,可选 small、default、large
options: [ // 选项数组,常用于 select、radio、checkbox 等
{ label: "选项1", value: "1" }, // 选项 label 和 value
{ label: "选项2", value: "2" }
],
multiple: false, // 是否多选,select 组件常用
filterable: true, // 是否支持搜索筛选,select 组件常用
rows: 4, // 多行文本框行数,textarea 专用
resize: "vertical", // textarea 是否允许调整大小及方向
autosize: { // textarea 自动高度配置
minRows: 2, // 最小行数
maxRows: 6 // 最大行数
},
buttonStyle: "outline", // radio 按钮样式
min: 0, // 输入数字类组件最小值,如 inputNumber、slider
max: 100, // 最大值
step: 1, // 步长
format: "yyyy-MM-dd", // 日期格式,datePicker 专用
placeholderTime: "选择时间", // 时间选择器占位提示
disabledDate: (date) => date < new Date(), // 禁用日期函数,禁止选择今天之前日期
showAlpha: false, // 颜色选择器是否显示透明度
activeColor: "#409EFF", // 颜色选择器主题色
checked: false, // 开关状态,switch 组件专用
icon: "Check", // 按钮图标名
loading: false, // 按钮加载状态
text: "提交", // 按钮文本
columns: [ // 表格列配置
{ label: "姓名", prop: "name" },
{ label: "年龄", prop: "age" }
],
data: [], // 表格数据
style: { // 容器样式
padding: "10px", // 内边距
backgroundColor: "#f5f5f5" // 背景颜色
},
height: 300, // 富文本编辑器高度
action: "/upload", // 上传接口地址
multipleUpload: false, // 是否支持多文件上传
showFileList: true // 是否显示文件列表
},
formItem: {
label: "确认密码", // 表单标签
rules: [
{
validator: (rule, value, callback) => { // 自定义验证函数
if (value === "") {
callback(new Error("请输入确认密码")); // 不符合规则时传入错误信息
} else {
const password = getform1ValueByName("password"); // 获取其他字段值进行校验
if (password === value) {
callback(); // 校验通过
} else {
callback(new Error("两次密码输入不一致")); // 校验失败错误提示
}
}
},
trigger: "blur" // 触发校验的时机
}
]
},
customRules: [
{
type: "required", // 必填规则类型
message: "必填项", // 提示信息
trigger: "blur" // 触发校验时机
}
],
config: {
optionsType: 1, // 自定义配置项类型
optionsFun: "demo/options", // 远程接口或本地方法名
method: "get", // 请求方法
linkage: "name1", // 关联的其他组件字段名
before: (params, { type, route, model }) => { // 请求前钩子,修改参数
console.log(type);
return params;
},
after: (res, success, type) => { // 请求后钩子,处理结果
console.log(type, res);
return res;
}
}
}
name 字段名
说明:绑定数据的字段名,在同一表单中必须唯一
| 项目 | 内容 |
|---|---|
| 类型 | string |
| 必填 | 是 |
| 默认值 | — |
| 示例 | "username" |
control 组件属性配置
| 属性名 | 说明 | 类型 | 是否必填 | 默认值 | 示例值 |
|---|---|---|---|---|---|
| modelValue | 绑定的输入值,通常双向绑定 | string | number | 否 | "" | "" |
| type | 输入框类型,如 text、password | string | 否 | "text" | "text" |
| placeholder | 输入框占位提示文字 | string | 否 | "" | "请输入用户名" |
| maxlength | 最大输入长度 | number | 否 | — | 20 |
| minlength | 最小输入长度 | number | 否 | — | 3 |
| showWordLimit | 是否显示字数统计 | boolean | 否 | false | true |
| clearable | 是否显示清除按钮 | boolean | 否 | false | true |
| disabled | 是否禁用输入框 | boolean | 否 | false | false |
| readonly | 是否只读 | boolean | 否 | false | false |
| autocomplete | 浏览器自动完成功能 | string | 否 | "off" | "off" |
| autofocus | 是否自动聚焦 | boolean | 否 | false | false |
| tabindex | tab 键顺序 | string | number | 否 | — | "1" |
| validateEvent | 是否触发表单验证事件 | boolean | 否 | true | true |
| inputStyle | 输入框自定义样式对象 | object | 否 | {} | { color: "#333", fontSize: "14px" } |
| size | 输入框尺寸,支持 small/default/large | string | 否 | "default" | "default" |
| options | 选项数组(常用于 select、radio 等) | Array<{ label: string; value: any }> | 否 | [] | [ { label: "选项1", value: "1" }, { label: "选项2", value: "2" } ] |
| multiple | 是否多选 | boolean | 否 | false | false |
| filterable | 是否支持搜索筛选 | boolean | 否 | false | true |
| rows | 多行文本框行数,textarea 专用 | number | 否 | 2 | 4 |
| resize | textarea 是否允许调整大小及方向 | string | 否 | "none" | "vertical" |
| autosize | textarea 自动高度配置 | object | 否 | null | { minRows: 2, maxRows: 6 } |
| buttonStyle | radio 按钮样式 | string | 否 | "outline" | "outline" |
| min | 数字类组件最小值 | number | 否 | 0 | 0 |
| max | 数字类组件最大值 | number | 否 | 100 | 100 |
| step | 数字类组件步长 | number | 否 | 1 | 1 |
| format | 日期格式,datePicker 专用 | string | 否 | "" | "yyyy-MM-dd" |
| placeholderTime | 时间选择器占位提示 | string | 否 | "" | "选择时间" |
| disabledDate | 禁用日期函数 | function | 否 | null | (date) => date < new Date() |
| showAlpha | 颜色选择器是否显示透明度 | boolean | 否 | false | false |
| activeColor | 颜色选择器主题色 | string | 否 | "#409EFF" | "#409EFF" |
| checked | 开关状态,switch 组件专用 | boolean | 否 | false | false |
| icon | 按钮图标名 | string | 否 | "" | "Check" |
| loading | 按钮加载状态 | boolean | 否 | false | false |
| text | 按钮文本 | string | 否 | "" | "提交" |
| columns | 表格列配置 | Array<{ label: string; prop: string }> | 否 | [] | [ { label: "姓名", prop: "name" }, { label: "年龄", prop: "age" } ] |
| data | 表格数据 | Array | 否 | [] | [] |
| style | 容器样式 | object | 否 | {} | { padding: "10px", backgroundColor: "#f5f5f5" } |
| height | 富文本编辑器高度 | number | 否 | 300 | 300 |
| action | 上传接口地址 | string | 否 | "" | "/upload" |
| multipleUpload | 是否支持多文件上传 | boolean | 否 | false | false |
| showFileList | 是否显示文件列表 | boolean | 否 | true | true |
formItem 表单项配置
| 属性名 | 说明 | 类型 | 是否必填 | 默认值 | 示例值 |
|---|---|---|---|---|---|
| label | 表单标签文字 | string | 否 | "" | "确认密码" |
| rules | 校验规则数组 | Array | 否 | 见自定义验证函数示例 |
校验示例
opt = {
list: [
{
type: "password",
name: "userPassword",
control:
{
modelValue: ""
},
config:
{},
formItem:
{
label: "密码",
rules: [
{
required: true,
message: "请输入密码",
trigger: "blur"
},
{
min: 6,
message: "密码长度不能少于6位",
trigger: "blur"
}]
}
},
{
type: "password",
name: "confirmPassword",
control:
{
modelValue: ""
},
config:
{},
formItem:
{
label: "确认密码",
rules: [
{
required: true,
message: "请再次输入密码",
trigger: "blur"
},
{
validator: (rule, value, callback) =>
{
// 👉 注意这里也要改
const password = getTestDemoValueByName("userPassword");
if (!value)
{
callback(new Error("请再次输入密码"));
}
else if (value !== password)
{
callback(new Error("两次密码输入不一致"));
}
else
{
callback();
}
},
trigger: "blur"
}]
}
}],
form:
{
size: "default",
labelWidth: "100px",
name: "TestDemo"
},
config:
{
submitCancel: true
}
}
customRules 自定义校验规则
| 属性名 | 说明 | 类型 | 是否必填 | 默认值 | 示例值 |
|---|---|---|---|---|---|
| type | 规则类型 | string | 是 | — | "required" |
| message | 规则提示信息 | string | 是 | — | "必填项" |
| trigger | 触发校验时机 | string | 是 | — | "blur" |
opt = {
list: [
{
type: "input",
control:
{
modelValue: "2@qq.com"
},
config:
{},
name: "inputEmail",
formItem:
{
label: "邮箱地址"
},
customRules: [
{
type: "required",
message: "必填项",
trigger: "blur"
},
{
type: "email",
message: "请输入邮箱地址",
trigger: "blur"
}]
},
],
form:
{
size: "default"
},
config:
{
submitCancel: true
},
events:
{
}
}
config 扩展配置
| 属性名 | 说明 | 类型 | 是否必填 | 默认值 | 示例值 |
|---|---|---|---|---|---|
| optionsType | 选项数据来源类型 | number | 否 | — | 1 |
| optionsFun | 远程接口 URL 地址 | string | 否 | — | "https://api.example.com/v1/getOptions" |
| method | 请求方法 | string | 否 | — | "post" |
| linkage | 关联其他组件字段名 | string | 否 | — | "name1" |
optionsType 取值说明:
| 值 | 说明 | 示例 |
|---|---|---|
0 | 固定选项:使用 options 数组中的静态数据,optionsFun 无需配置 | options: [{ label: "选项A", value: "a" }] |
1 | 远程接口:通过 optionsFun 配置的接口 URL 动态加载选项数据 | optionsFun: "https://api.example.com/v1/getOptions" |
2 | 数据字典:从系统字典中加载选项数据。字典可在**页面设计 → 表单配置 → 设置数据字典 中配置,也可在字典管理**中配置全局字典 | optionsFun: "dict_demo_status"(字典标识) |
各类型完整示例:
// optionsType: 0 —— 固定选项
{
type: "select",
name: "device_id",
control: {
modelValue: "",
appendToBody: true
},
options: [
{ label: "选项1", value: "1" },
{ label: "选项2", value: "2" }
],
config: {
optionsType: 0
},
formItem: {
label: "设备"
}
}
// optionsType: 1 —— 远程接口
{
type: "select",
name: "user_id",
control: {
modelValue: "",
appendToBody: true
},
options: [],
config: {
optionsType: 1,
optionsFun: "https://api.example.com/v1/getUserList",
method: "post",
value: "id"
},
formItem: {
label: "用户"
}
}
// optionsType: 2 —— 数据字典
{
type: "select",
name: "status",
control: {
modelValue: "",
appendToBody: true
},
options: [],
config: {
optionsType: 2,
optionsFun: "dict_order_status" // 字典标识
},
formItem: {
label: "订单状态"
}
}
events 组件事件
某些组件支持在 events 中配置事件回调,用于处理组件特定的交互行为。
| 事件名 | 适用组件 | 说明 | 参数 |
|---|---|---|---|
click | button | 按钮点击事件 | instance:组件上下文 |
submit | button(嵌套表单场景) | 子表单提交确认回调 | instance:包含 selected(子表单数据)、model、context 等 |
cancel | button(嵌套表单场景) | 子表单取消关闭回调 | instance:组件上下文 |
before | select / selectPlus | 远程选项数据请求发送前拦截,用于修改请求参数、注入 token 等 | instance:包含 headers、data、type、env、context 等 |
after | select / selectPlus | 远程选项数据加载完成后处理,用于数据格式映射 | instance:包含 response、type、success 等 |
click(按钮点击)
用于处理按钮点击事件,常见于以下业务场景:
- 请求数据:点击按钮触发接口请求,获取数据
- 数据处理:对接口返回数据进行提取、格式化、拼接等操作
- 更新组件:将处理后的数据回填给表单中的指定组件(如 textarea、table、input 等)
支持同步 / 异步操作,通常配合 env.runtime.request 使用,实现"点击按钮 → 请求数据 → 处理数据 → 回填组件"的完整闭环。
核心能力:
- 可控制按钮的
loading状态 - 可获取当前表单所有字段数据(
context.model) - 可更新任意表单组件的值(直接修改
context.model.xxx)
events: {
click: async (instance) => {
const { schema, env, context } = instance;
try {
// 1️⃣ 开启按钮 loading
schema.control.loading = true;
// 2️⃣ 发起请求
const response = await env.runtime.request({
url: "https://api.example.com/v1/generate",
method: "post",
data: {
topic: context.model.topic,
audience: context.model.target_audience
}
});
// 3️⃣ 处理返回数据
const list = response?.data?.data || [];
// 4️⃣ 更新给指定组件(回填数据)
// 场景A:更新给 textarea 组件(拼接为文本)
context.model.article_content = list
.map(item => item.content)
.join("\n\n");
// 场景B:更新给 table 组件(渲染为表格数据)
context.model.articleTable = list.map((item, index) => ({
id: index,
content: item.content
}));
env.runtime.ElMessage.success("生成成功");
} catch (err) {
console.error(err);
env.runtime.ElMessage.error("请求失败");
} finally {
// 5️⃣ 关闭按钮 loading
schema.control.loading = false;
}
}
}
submit(子表单提交回调)
当 button 组件配置了 config.source(子表单 ID)时,点击按钮会打开指定的子表单。子表单提交确认后触发 submit 事件,用于接收子表单返回的数据并回填到主表单。
核心参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
selected | Object | 子表单中表格字段的数据,键为表格字段的 name,值为已选中的行数据(数组) |
model | Object | 子表单所有字段的完整数据对象,表格字段的值为 JSON 字符串 |
context.model | Object | 主表单数据模型(推荐使用,通过它回填数据到主表单字段) |
env | Object | 运行环境(包含 runtime.ElMessage 等) |
model 与 selected 的关系:
// model:子表单所有字段的完整数据
model = {
article_topic: "如何提高学习效率",
target_audience: "大学生",
writing_style: "通俗易懂",
paragraph_count: 3,
articleTable: '[{"id":0,"content":"段落1"},{"id":1,"content":"段落2"},{"id":2,"content":"段落3"}]' // ⚠️ JSON 字符串
}
// selected:仅包含表格字段,值为已选中行的数组
selected = {
articleTable: [ // ✅ 数组,仅已选中的行
{ id: 0, content: "段落1" },
{ id: 2, content: "段落3" }
]
}
两种回填方式:
| 方式 | 数据来源 | 表格字段格式 | 适用场景 |
|---|---|---|---|
通过 selected 回填 | selected.表格字段名 | 数组 | 获取表格中用户勾选的数据,遍历处理后回填 |
通过 model 回填 | model.表格字段名 或 model.普通字段名 | JSON 字符串 | 直接存储完整数据(如保存到数据库)或获取普通字段值 |
events: {
submit: (instance) => {
const { selected, model, env, context } = instance;
console.warn("📌 子表单完整数据(model):", model);
console.warn("📌 表格已选数据(selected):", selected);
// =========================================================
// 方式一:通过 selected 回填(仅表格已选中的行)
// =========================================================
// selected.articleTable 是数组,直接遍历提取 content
const aiList = selected.articleTable || [];
const aiText = aiList
.filter(item => item && item.content)
.map(item => String(item.content))
.join("\n\n");
const oldText = context.model.article_content || "";
if (oldText && oldText.trim() !== "") {
context.model.article_content = oldText + "\n\n" + aiText;
} else {
context.model.article_content = aiText;
}
// =========================================================
// 方式二:通过 model 回填(子表单所有字段)
// =========================================================
// model.articleTable 是 JSON 字符串,可直接赋值给主表字段
context.model.articleTableJson = model.articleTable;
// 获取子表单普通字段的值
context.model.topic = model.article_topic;
context.model.audience = model.target_audience;
context.model.style = model.writing_style;
context.model.count = model.paragraph_count;
env.runtime.ElMessage.success("回填成功");
},
cancel: (instance) => {
console.log("子表单已取消");
}
}
cancel(子表单取消回调)
子表单点击取消或关闭时触发。
before(选项请求前拦截)
用于 select / selectPlus 组件远程加载选项数据前,对请求进行修改。更多参数详情请参考 before(instance)。
events: {
before: (instance) => {
const { headers, data, type, env } = instance;
// 注入 token
const newHeaders = {
...headers,
Authorization: "Bearer " + (env?.user?.token || "")
};
// 修改请求参数
const newData = {
...data,
status: 1 // 只加载启用状态的选项
};
return {
url: instance.url,
method: instance.method || "post",
headers: newHeaders,
data: newData
};
}
}
after(选项数据后处理)
用于 select / selectPlus 组件远程加载选项数据后,对返回结果进行数据映射或结构转换。更多参数详情请参考 after(instance)。
events: {
after: (instance) => {
const { type, success, response } = instance;
// 将后端返回的数据映射为组件所需的格式
return {
code: 200,
data: response?.data?.data?.list, // 提取选项数组
msg: response?.data?.msg
};
}
}
type 组件类型
{string}组件类型标识(必填)
组件类型用于标识当前表单项的类型,固定字符串,不可为空。
支持类型:
input:单行文本textarea:多行文本radio:单选框checkbox:多选框select:下拉选择datePicker:日期选择器timePicker:时间选择器colorPicker:颜色选择器switch:开关inputNumber:数字输入框cascader:级联选择器rate:评分slider:滑块treeSelect:树选择txt:文本展示title:标题tabs:标签页flex:布局容器card:卡片divider:分割线button:按钮table:表格component:自定义组件upload:上传tinymce:富文本编辑器grid:栅格布局div:普通容器
input(单行文本)
用于输入标题、名称、链接、UID 等简单字符串信息。
🔸type
固定值:"input"(单行文本输入组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 绑定的输入值 | string | number | "" |
| type | 输入框类型(text 等) | string | "text" |
| placeholder | 输入框占位提示文字 | string | "" |
| maxlength | 最大输入长度 | number | — |
| minlength | 最小输入长度 | number | — |
| showWordLimit | 是否显示字数统计 | boolean | false |
| clearable | 是否显示清除按钮 | boolean | false |
| disabled | 是否禁用输入框 | boolean | false |
| readonly | 是否只读 | boolean | false |
| autocomplete | 浏览器自动完成功能 | string | "off" |
| autofocus | 是否自动聚焦 | boolean | false |
| tabindex | tab 键顺序 | string | number | — |
| validateEvent | 是否触发表单验证事件 | boolean | true |
| inputStyle | 输入框自定义样式 | object | {} |
| size | 输入框尺寸(small等) | string | "default" |
{
"type": "input",
"name": "username",
"control": {
"modelValue": "",
"type": "text",
"placeholder": "请输入用户名",
"maxlength": 20,
"minlength": 3,
"showWordLimit": true,
"clearable": true,
"disabled": false,
"readonly": false,
"autocomplete": "off",
"autofocus": false,
"tabindex": "1",
"validateEvent": true,
"inputStyle": {},
"size": "default"
},
"formItem": {
"label": "用户名",
"rules": [
{
"validator": (rule, value, callback) => {
if (!/^[a-zA-Z]/.test(value)) {
callback(new Error("必须以字母开头"));
} else {
callback();
}
},
"trigger": "blur"
}
]
},
"customRules": [
{
"required": true,
"message": "请输入用户名",
"trigger": "blur"
},
{
"min": 3,
"max": 20,
"message": "长度在 3 到 20 个字符",
"trigger": "blur"
}
],
"config": {}
}
textarea(多行文本)
用于输入多行文本信息,如备注、评论、详细描述等。
🔸type
固定值:"textarea"(多行文本输入组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 绑定的输入值 | string | "" |
| placeholder | 输入框占位提示文字 | string | "" |
| maxlength | 最大输入长度 | number | — |
| minlength | 最小输入长度 | number | — |
| rows | 显示行数 | number | 2 |
| showWordLimit | 是否显示字数统计 | boolean | false |
| clearable | 是否显示清除按钮 | boolean | false |
| disabled | 是否禁用输入框 | boolean | false |
| readonly | 是否只读 | boolean | false |
| resize | 是否允许调整大小 | string | "none" |
| autofocus | 是否自动聚焦 | boolean | false |
| validateEvent | 是否触发表单验证事件 | boolean | true |
| inputStyle | 输入框自定义样式 | object | {} |
| size | 输入框尺寸 | string | "default" |
{
"type": "textarea",
"name": "description",
"control": {
"modelValue": "",
"placeholder": "请输入内容",
"maxlength": 500,
"minlength": 5,
"rows": 4,
"showWordLimit": true,
"clearable": true,
"disabled": false,
"readonly": false,
"resize": "vertical",
"autofocus": false,
"validateEvent": true,
"inputStyle": {},
"size": "default"
},
"formItem": {
"label": "描述",
"rules": [
{
"validator": (rule, value, callback) => {
if (!value || value.trim() === "") {
callback(new Error("请输入描述"));
} else {
callback();
}
},
"trigger": "blur"
}
]
},
"customRules": [
{
"required": true,
"message": "请输入描述",
"trigger": "blur"
}
],
"config": {}
}
radio(单选框)
用于在多个选项中选择一个。
🔸type
固定值:"radio"(单选框组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 绑定的选中值 | string | number | — |
| options | 选项数组 | Array<{label, value}> | [] |
| disabled | 是否禁用 | boolean | false |
| size | 单选框组尺寸 | string | "default" |
| border | 是否显示边框 | boolean | false |
{
"type": "radio",
"name": "gender",
"control": {
"modelValue": "male",
"options": [
{ "label": "男", "value": "male" },
{ "label": "女", "value": "female" }
],
"disabled": false,
"size": "default",
"border": false
},
"formItem": {
"label": "性别",
"rules": [
{
"validator": (rule, value, callback) => {
if (!value) {
callback(new Error("请选择性别"));
} else {
callback();
}
},
"trigger": "change"
}
]
},
"customRules": [
{
"required": true,
"message": "请选择性别",
"trigger": "change"
}
],
"config": {}
}
checkbox(多选框)
用于多选操作,用户可选择多个选项。
🔸type
固定值:"checkbox"(多选框组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 绑定的选中值数组 | array | [] |
| options | 选项数组 | Array<{label, value}> | [] |
| disabled | 是否禁用 | boolean | false |
| size | 多选框组尺寸 | string | "default" |
| min | 最小选中数量 | number | — |
| max | 最大选中数量 | number | — |
{
"type": "checkbox",
"name": "hobbies",
"control": {
"modelValue": ["reading", "traveling"],
"options": [
{ "label": "阅读", "value": "reading" },
{ "label": "旅行", "value": "traveling" },
{ "label": "运动", "value": "sports" }
],
"disabled": false,
"size": "default",
"min": 1,
"max": 3
},
"formItem": {
"label": "兴趣爱好",
"rules": [
{
"validator": (rule, value, callback) => {
if (!value || value.length === 0) {
callback(new Error("请选择至少一个爱好"));
} else {
callback();
}
},
"trigger": "change"
}
]
},
"customRules": [
{
"required": true,
"message": "请选择至少一个爱好",
"trigger": "change"
},
{
"type": "array",
"min": 1,
"message": "请选择至少一个爱好",
"trigger": "change"
}
],
"config": {}
}
select(下拉选择)
用于从下拉列表中选择一个或多个值。
🔸type
固定值:"select"(下拉选择组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 绑定的值(多选时为数组) | string | array | "" |
| options | 选项数组 | Array<{label, value}> | [] |
| multiple | 是否多选 | boolean | false |
| disabled | 是否禁用 | boolean | false |
| clearable | 是否显示清除按钮 | boolean | false |
| placeholder | 占位提示文字 | string | "" |
| filterable | 是否支持搜索过滤 | boolean | false |
| size | 组件尺寸 | string | "default" |
{
"type": "select",
"name": "country",
"control": {
"modelValue": "",
"options": [
{ "label": "中国", "value": "cn" },
{ "label": "美国", "value": "us" },
{ "label": "英国", "value": "uk" }
],
"multiple": false,
"disabled": false,
"clearable": true,
"placeholder": "请选择国家",
"filterable": true,
"size": "default"
},
"formItem": {
"label": "国家",
"rules": [
{
"validator": (rule, value, callback) => {
if (!value) {
callback(new Error("请选择国家"));
} else {
callback();
}
},
"trigger": "change"
}
]
},
"customRules": [
{
"required": true,
"message": "请选择国家",
"trigger": "change"
}
],
"config": {}
}
datePicker(日期选择器)
用于选择日期或日期范围。
🔸type
固定值:"datePicker"(日期选择器组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 绑定的值(范围模式为数组) | string | array | null | null |
| type | 选择器类型 | string | "date" |
| format | 展示格式 | string | — |
| valueFormat | 绑定值格式 | string | — |
| placeholder | 占位提示文字 | string | "" |
| disabled | 是否禁用 | boolean | false |
| clearable | 是否显示清除按钮 | boolean | false |
| editable | 输入框是否可编辑 | boolean | true |
| range | 是否为范围选择 | boolean | false |
| size | 组件尺寸 | string | "default" |
{
"type": "datePicker",
"name": "birthday",
"control": {
"modelValue": null,
"type": "date",
"format": "yyyy-MM-dd",
"valueFormat": "yyyy-MM-dd",
"placeholder": "选择日期",
"disabled": false,
"clearable": true,
"editable": true,
"range": false,
"size": "default"
},
"formItem": {
"label": "生日",
"rules": [
{
"validator": (rule, value, callback) => {
if (!value) {
callback(new Error("请选择日期"));
} else {
callback();
}
},
"trigger": "change"
}
]
},
"customRules": [
{
"required": true,
"message": "请选择日期",
"trigger": "change"
}
],
"config": {}
}
timePicker(时间选择器)
用于选择时间或时间范围。
🔸type
固定值:"timePicker"(时间选择器组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 绑定的值(范围模式为数组) | string | array | null | null |
| isRange | 是否为时间范围选择 | boolean | false |
| format | 显示格式 | string | "HH:mm:ss" |
| valueFormat | 绑定值格式 | string | "HH:mm:ss" |
| placeholder | 占位提示文字 | string | "" |
| disabled | 是否禁用 | boolean | false |
| clearable | 是否显示清除按钮 | boolean | false |
| size | 组件尺寸 | string | "default" |
{
"type": "timePicker",
"name": "meetingTime",
"control": {
"modelValue": null,
"isRange": false,
"format": "HH:mm:ss",
"valueFormat": "HH:mm:ss",
"placeholder": "选择时间",
"disabled": false,
"clearable": true,
"size": "default"
},
"formItem": {
"label": "会议时间",
"rules": [
{
"validator": (rule, value, callback) => {
if (!value) {
callback(new Error("请选择时间"));
} else {
callback();
}
},
"trigger": "change"
}
]
},
"customRules": [
{
"required": true,
"message": "请选择时间",
"trigger": "change"
}
],
"config": {}
}
colorPicker(颜色选择器)
用于选择颜色值。
🔸type
固定值:"colorPicker"(颜色选择器组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 绑定的颜色值 | string | "" |
| disabled | 是否禁用 | boolean | false |
| showAlpha | 是否显示透明度选择 | boolean | false |
| size | 组件尺寸 | string | "default" |
{
"type": "colorPicker",
"name": "themeColor",
"control": {
"modelValue": "#409EFF",
"disabled": false,
"showAlpha": false,
"size": "default"
},
"formItem": {
"label": "主题颜色",
"rules": [
{
"validator": (rule, value, callback) => {
if (!value) {
callback(new Error("请选择颜色"));
} else {
callback();
}
},
"trigger": "change"
}
]
},
"customRules": [
{
"required": true,
"message": "请选择颜色",
"trigger": "change"
}
],
"config": {}
}
switch(开关)
用于切换开/关状态。
🔸type
固定值:"switch"(开关组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 绑定的开关状态 | boolean | false |
| disabled | 是否禁用 | boolean | false |
| activeText | 开启时显示文字 | string | "" |
| inactiveText | 关闭时显示文字 | string | "" |
| activeColor | 开启时颜色 | string | "#409EFF" |
| inactiveColor | 关闭时颜色 | string | "#C0CCDA" |
{
"type": "switch",
"name": "isActive",
"control": {
"modelValue": true,
"disabled": false,
"activeText": "开",
"inactiveText": "关",
"activeColor": "#409EFF",
"inactiveColor": "#C0CCDA"
},
"formItem": {
"label": "是否激活",
"rules": [
{
"validator": (rule, value, callback) => {
callback();
},
"trigger": "change"
}
]
},
"customRules": [],
"config": {}
}
inputNumber(数字输入框)
用于输入数字,可以设置范围、步进等。
🔸type
固定值:"inputNumber"(数字输入框组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 绑定的数值 | number | 0 |
| min | 最小值 | number | — |
| max | 最大值 | number | — |
| step | 步进值 | number | 1 |
| disabled | 是否禁用 | boolean | false |
| size | 组件尺寸 | string | "default" |
{
"type": "inputNumber",
"name": "age",
"control": {
"modelValue": 18,
"min": 0,
"max": 120,
"step": 1,
"disabled": false,
"size": "default"
},
"formItem": {
"label": "年龄",
"rules": [
{
"validator": (rule, value, callback) => {
if (value === null || value === undefined) {
callback(new Error("请输入年龄"));
} else if (value < 0 || value > 120) {
callback(new Error("年龄范围为 0-120"));
} else {
callback();
}
},
"trigger": "blur"
}
]
},
"customRules": [
{
"type": "number",
"min": 0,
"max": 120,
"message": "年龄范围为 0-120",
"trigger": "blur"
}
],
"config": {}
}
cascader(级联选择器)
用于选择多级分类数据。
🔸type
固定值:"cascader"(级联选择器组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 绑定的选中值数组 | array | [] |
| options | 级联选项数据 | Array<{label, value, children}> | [] |
| disabled | 是否禁用 | boolean | false |
| clearable | 是否显示清除按钮 | boolean | false |
| placeholder | 占位提示文字 | string | "" |
| size | 组件尺寸 | string | "default" |
{
"type": "cascader",
"name": "address",
"control": {
"modelValue": [],
"options": [
{
"label": "浙江",
"value": "zj",
"children": [
{ "label": "杭州", "value": "hz" },
{ "label": "宁波", "value": "nb" }
]
},
{
"label": "江苏",
"value": "js",
"children": [
{ "label": "南京", "value": "nj" },
{ "label": "苏州", "value": "sz" }
]
}
],
"disabled": false,
"clearable": true,
"placeholder": "请选择地址",
"size": "default"
},
"formItem": {
"label": "地址",
"rules": [
{
"validator": (rule, value, callback) => {
if (!value || value.length === 0) {
callback(new Error("请选择地址"));
} else {
callback();
}
},
"trigger": "change"
}
]
},
"customRules": [
{
"required": true,
"message": "请选择地址",
"trigger": "change"
}
],
"config": {}
}
rate(评分)
用于评分选择,通常显示星星。
🔸type
固定值:"rate"(评分组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 当前评分 | number | 0 |
| max | 最大分数 | number | 5 |
| disabled | 是否禁用 | boolean | false |
| allowHalf | 是否允许半星评分 | boolean | false |
| showText | 是否显示文本说明 | boolean | false |
| showScore | 是否显示数字评分 | boolean | false |
| size | 组件尺寸 | string | "default" |
{
"type": "rate",
"name": "score",
"control": {
"modelValue": 3,
"max": 5,
"disabled": false,
"allowHalf": true,
"showText": false,
"showScore": false,
"size": "default"
},
"formItem": {
"label": "评分",
"rules": [
{
"validator": (rule, value, callback) => {
if (value === null || value === undefined || value === 0) {
callback(new Error("请评分"));
} else {
callback();
}
},
"trigger": "change"
}
]
},
"customRules": [
{
"required": true,
"message": "请评分",
"trigger": "change"
}
],
"config": {}
}
slider(滑动条)
用于选择数值范围或单个数值。
🔸type
固定值:"slider"(滑动条组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 当前数值(范围模式为数组) | number | array | 0 |
| min | 最小值 | number | 0 |
| max | 最大值 | number | 100 |
| step | 步长 | number | 1 |
| disabled | 是否禁用 | boolean | false |
| range | 是否范围选择 | boolean | false |
| showTooltip | 是否显示提示 | boolean | true |
| size | 组件尺寸 | string | "default" |
{
"type": "slider",
"name": "volume",
"control": {
"modelValue": 50,
"min": 0,
"max": 100,
"step": 1,
"disabled": false,
"range": false,
"showTooltip": true,
"size": "default"
},
"formItem": {
"label": "音量",
"rules": [
{
"validator": (rule, value, callback) => {
if (value === null || value === undefined) {
callback(new Error("请选择音量"));
} else {
callback();
}
},
"trigger": "change"
}
]
},
"customRules": [],
"config": {}
}
treeSelect(树形选择器)
用于选择树形结构中的某个或多个节点。
🔸type
固定值:"treeSelect"(树形选择器组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 绑定的值(多选时为数组) | array | string | [] |
| treeData | 树形数据 | Array<{label, id, children}> | [] |
| multiple | 是否多选 | boolean | false |
| disabled | 是否禁用 | boolean | false |
| clearable | 是否显示清除按钮 | boolean | false |
| placeholder | 占位提示文字 | string | "" |
| size | 组件尺寸 | string | "default" |
{
"type": "treeSelect",
"name": "category",
"control": {
"modelValue": [],
"treeData": [
{
"label": "电子产品",
"id": 1,
"children": [
{ "label": "手机", "id": 2 },
{ "label": "电脑", "id": 3 }
]
}
],
"multiple": true,
"disabled": false,
"clearable": true,
"placeholder": "请选择类别",
"size": "default"
},
"formItem": {
"label": "类别",
"rules": [
{
"validator": (rule, value, callback) => {
if (!value || (Array.isArray(value) && value.length === 0)) {
callback(new Error("请选择类别"));
} else {
callback();
}
},
"trigger": "change"
}
]
},
"customRules": [
{
"required": true,
"message": "请选择类别",
"trigger": "change"
}
],
"config": {}
}
txt(文本显示)
用于显示只读文本。
🔸type
固定值:"txt"(文本显示组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 显示的文本内容 | string | "" |
{
"type": "txt",
"name": "descriptionText",
"control": {
"modelValue": "这是只读文本"
},
"formItem": {
"label": "说明",
"rules": []
},
"customRules": [],
"config": {}
}
title(标题)
用于显示标题文本。
🔸type
固定值:"title"(标题组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 标题文本内容 | string | "" |
{
"type": "title",
"name": "pageTitle",
"control": {
"modelValue": "用户管理"
},
"formItem": {},
"customRules": [],
"config": {}
}
tabs(标签页)
用于创建标签页切换。
🔸type
固定值:"tabs"(标签页组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue | 当前激活的标签名 | string | "" |
| tabs | 标签数组 | Array<{label, name}> | [] |
{
"type": "tabs",
"name": "mainTabs",
"control": {
"modelValue": "tab1",
"tabs": [
{ "label": "标签1", "name": "tab1" },
{ "label": "标签2", "name": "tab2" }
]
},
"formItem": {},
"customRules": [],
"config": {}
}
flex(弹性布局)
用于布局弹性容器。
🔸type
固定值:"flex"(弹性布局组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| justify | 主轴对齐方式 | string | "start" |
| align | 侧轴对齐方式 | string | "stretch" |
| direction | 主轴方向 | string | "row" |
| wrap | 是否换行 | string | "nowrap" |
{
"type": "flex",
"name": "flexContainer",
"control": {
"justify": "start",
"align": "center",
"direction": "row",
"wrap": "nowrap"
},
"formItem": {},
"customRules": [],
"config": {}
}
card(卡片)
用于显示卡片容器。
🔸type
固定值:"card"(卡片组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| header | 卡片头部标题 | string | "" |
| bordered | 是否有边框 | boolean | false |
| shadow | 是否有阴影 | boolean | false |
{
"type": "card",
"name": "userCard",
"control": {
"header": "用户信息",
"bordered": true,
"shadow": true
},
"formItem": {},
"customRules": [],
"config": {}
}
divider(分割线)
用于分隔内容。
🔸type
固定值:"divider"(分割线组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| direction | 分割线方向 | string | "horizontal" |
| contentPosition | 内容位置 | string | "center" |
{
"type": "divider",
"name": "lineDivider",
"control": {
"direction": "horizontal",
"contentPosition": "center"
},
"formItem": {},
"customRules": [],
"config": {}
}
button(按钮)
用于触发操作。
🔸type
固定值:"button"(按钮组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| text | 按钮显示文本 | string | "" |
| type | 按钮类型 | string | "default" |
| size | 按钮尺寸 | string | "default" |
| disabled | 是否禁用 | boolean | false |
| loading | 是否加载中 | boolean | false |
| icon | 按钮图标名称 | string | "" |
{
"type": "button",
"name": "submitBtn",
"control": {
"text": "提交",
"type": "primary",
"size": "default",
"disabled": false,
"loading": false,
"icon": "Check"
},
"formItem": {},
"customRules": [],
"config": {}
}
table(表格)
用于显示表格数据。
🔸type
固定值:"table"(表格组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| columns | 表格列配置 | Array<{label, prop}> | [] |
| data | 表格数据 | Array<object> | [] |
{
"type": "table",
"name": "userTable",
"control": {
"columns": [
{ "label": "姓名", "prop": "name" },
{ "label": "年龄", "prop": "age" }
],
"data": []
},
"formItem": {},
"customRules": [],
"config": {}
}
component(自定义组件)
用于嵌入自定义组件。
🔸type
固定值:"component"(自定义组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| componentName | 自定义组件名称 | string | "" |
| props | 传递给自定义组件的属性 | object | {} |
{
"type": "component",
"name": "customComp",
"control": {
"componentName": "MyComponent",
"props": {}
},
"formItem": {},
"customRules": [],
"config": {}
}
upload(上传)
用于文件上传。
🔸type
固定值:"upload"(上传组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| action | 上传接口地址 | string | "" |
| multiple | 是否支持多文件上传 | boolean | false |
| accept | 接受的文件类型 | string | "" |
| fileList | 已上传文件列表 | array | [] |
| disabled | 是否禁用 | boolean | false |
| showFileList | 是否显示文件列表 | boolean | true |
| drag | 是否启用拖拽上传 | boolean | false |
| directory | 是否支持选择整个文件夹上传(浏览器需支持 webkitdirectory) | boolean | false |
| data | 上传时携带的额外参数,支持引用其他表单组件的值(见下方说明) | object | {} |
| limit | 最大上传数量 | number | 无限制 |
🔸data 参数说明
上传时携带的额外字段,会随文件一起提交到 action 接口。
- 支持静态值:
{ token: "abc123" } - 支持引用其他表单组件的值:用
$.字段名语法
例如:
"data": {
"category_id": "$.category_id"
}
表示上传时,把当前表单中 name = category_id 的组件的值一起提交。
🔸示例 1:普通单文件上传
{
"type": "upload",
"name": "avatar",
"control": {
"action": "/upload",
"multiple": false,
"accept": "image/*",
"fileList": [],
"disabled": false,
"showFileList": true
},
"formItem": {
"label": "头像上传",
"rules": [
{
"validator": (rule, value, callback) => {
if (!value || (Array.isArray(value) && value.length === 0)) {
callback(new Error("请上传文件"));
} else {
callback();
}
},
"trigger": "change"
}
]
},
"customRules": [
{
"required": true,
"message": "请上传文件",
"trigger": "change"
}
],
"config": {}
}
🔸示例 2:文件夹上传 + 携带其他表单字段
[
{
"type": "select",
"control": {
"modelValue": "",
"appendToBody": true,
"filterable": true
},
"options": [],
"config": {
"optionsType": 1,
"optionsFun": "http://api.example.com/api/ProductCategoryFullOptions",
"method": "post",
"value": "id"
},
"name": "category_id",
"formItem": {
"label": "平台-设备-群体-款式"
}
},
{
"type": "upload",
"control": {
"modelValue": "",
"action": "http://api.example.com/api/uploadMedia",
"limit": 10000,
"drag": true,
"directory": true,
"data": {
"category_id": "$.category_id"
}
},
"config": {},
"name": "media_url",
"formItem": {
"label": "媒体文件"
}
}
]
说明:
directory: true→ 用户点击上传区域时,可以选择整个文件夹,文件夹内所有文件会一起上传data: { category_id: "$.category_id" }→ 上传每个文件时,都会把当前表单中category_id的值作为额外参数一起提交limit: 10000→ 文件夹里可能有大量文件,需要把限制调大
---
#### tinymce(富文本编辑器)
用于编辑富文本内容。
**🔸type**
固定值:`"tinymce"`(富文本编辑器组件)
**🔸control 对象属性说明**
| 属性名 | 说明 | 类型 | 默认值 |
|------------|--------------------------|----------------------|-----------|
| modelValue | 富文本内容 | `string` | `""` |
| disabled | 是否禁用编辑 | `boolean` | `false` |
| height | 编辑器高度(像素) | `number` | `300` |
```js [示例]
{
"type": "tinymce",
"name": "content",
"control": {
"modelValue": "",
"disabled": false,
"height": 300
},
"formItem": {
"label": "内容",
"rules": [
{
"validator": (rule, value, callback) => {
if (!value) {
callback(new Error("请输入内容"));
} else {
callback();
}
},
"trigger": "blur"
}
]
},
"customRules": [
{
"required": true,
"message": "请输入内容",
"trigger": "blur"
}
],
"config": {}
}
grid(网格布局)
用于布局网格容器。
🔸type
固定值:"grid"(网格布局组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| cols | 列数 | number | 24 |
| gutter | 栅格间距 | number | 0 |
| justify | 主轴对齐方式 | string | "start" |
| align | 侧轴对齐方式 | string | "top" |
{
"type": "grid",
"name": "gridLayout",
"control": {
"cols": 4,
"gutter": 10,
"justify": "start",
"align": "top"
},
"formItem": {},
"customRules": [],
"config": {}
}
div(容器)
用于包裹内容的容器。
🔸type
固定值:"div"(容器组件)
🔸control 对象属性说明
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| style | 容器自定义样式 | object | {} |
{
"type": "div",
"name": "contentWrapper",
"control": {
"style": {
"padding": "10px",
"backgroundColor": "#f5f5f5"
}
},
"formItem": {},
"customRules": [],
"config": {}
}
表单配置 form
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| name | 表单标识,可根据此标识使用 get[formName]ControlByName 获取其他选项数据 | string | — |
| labelWidth | 表单标签宽度,如 "100px" | string | — |
| class | 表单样式名称,可快速选择内置好的表单布局类名,或自定义类名 | string | — |
| showColon | 统一设置表单 label 是否添加冒号 | boolean | false |
| size | 组件尺寸 | "default" | "small" | "large" | "default" |
form: {
name: "testForm", // 表单标识
labelWidth: "100px", // 表单标签宽度
class: "custom-form", // 表单样式名称
showColon: true, // 字段名后添加冒号
size: "default" // 组件尺寸
}
补充说明:
form.name:表单的唯一标识,可用于通过get[formName]ControlByName方法获取表单中其他控件的值form.labelWidth:统一设置所有表单项标签的宽度,支持px、%等单位form.class:支持传入内置类名或自定义 CSS 类名,用于快速调整表单布局样式form.showColon:全局控制表单标签后是否显示冒号,优先级低于formItem级别的配置form.size:统一设置表单内所有组件的尺寸,可被单个组件的size属性覆盖
事件 events
用于控制表单在 联动、校验、提交、请求生命周期 中的行为。
| 事件名 | 作用 | 是否必须 return | 说明 |
|---|---|---|---|
change | 字段变化联动 | ❌ 可选 | 字段值变化时触发,适用于表单联动、自动填充、计算、副作用(请求/提示/UI控制)。支持 直接修改 context.model 或 return 新对象 两种方式。不 return 时手动修改 model 仍生效。 |
validate | 校验结果回调 | ❌ 不需要 | 表单整体校验完成后触发,一般用于 统一错误提示。可从 fields 中提取第一条错误信息并展示。 |
before | 请求发送前拦截 | ✅ 必须 | 请求发送前的统一入口。用于注入 token、修改 headers、请求参数加密/签名、按 type 分支处理等。不 return 则请求不会发送。 |
after | 请求响应后处理 | ✅ 必须 | 请求完成后统一处理响应,用于 格式标准化,将不同后端数据结构统一转换为 { code, data, msg } 格式。 |
change(instance)
instance{Object}name{string} 当前变化字段名(唯一标识)value{any} 当前字段值prop{string} 字段标识(子表 / flex 时等同 name)options{Object} 当前组件配置(schema)env{Object} 运行环境(ElMessage / request 等)context{Object} 表单上下文context.model{Object} 当前表单数据(核心)context.props{Object} 组件参数
- 返回
{Object | void}
说明
字段值发生变化时触发,是表单联动的核心入口。
常见业务场景
- 字段联动:选择省份后自动填充城市下拉选项
- 自动计算:输入单价和数量后自动计算总价
- 数据回填:选择用户后自动填充手机号、邮箱等信息
- 副作用操作:字段变化时发请求、显示提示、控制其他组件显隐
返回值行为规范
| 行为 | 说明 |
|---|---|
| 不 return | 不触发系统自动更新,但通过 context.model.xxx = value 手动修改数据仍然生效,适用于简单赋值或副作用逻辑 |
| return 新对象 | 会整体覆盖 model,适用于多字段联动或复杂条件逻辑 |
⚠️ 注意:不建议同时使用 return 和 context.model 混合修改,会产生数据覆盖问题。
change: (instance) =>
{
const
{
name,
value,
model,
prop,
options,
env,
context
} = instance;
// ================= 调试日志 =================
console.groupCollapsed("🔄 [change] " + name);
console.log("instance:", instance);
console.groupEnd();
/**
* =========================================================
* 📌 示例1:仅监听(不修改数据)
* =========================================================
*/
if (name === "xxx")
{
env?.runtime?.ElMessage?.info("字段变化(仅监听)");
// ❗ 不 return
// ❗ 不修改 context.model
}
/**
* =========================================================
* 📌 示例2:使用 context.model 修改(推荐方式2)
* =========================================================
*
* 👉 适用于:
* - 简单赋值
* - 副作用逻辑
*/
if (name === "xxx")
{
context.model.otherField = value;
// ❗ 不 return
}
/**
* =========================================================
* 📌 示例3:return object(复杂联动)
* =========================================================
*
* 👉 适用于多字段 / 条件逻辑
*/
if (name === "xxx")
{
const newModel = {
...context.model,
// otherField: value,
// anotherField: "xxx"
};
// return newModel;
}
/**
* =========================================================
* 📌 示例4:副作用(请求 / 计算)
* =========================================================
*
* 👉 不需要 return
*/
if (name === "xxx")
{
// 示例:发请求
// const response = await env.runtime.request({
// url: "【请替换为你的接口地址】/api/xxx",
// method: "post",
// data: {
// model: context.model
// }
// });
// console.log("📦 response:", response);
}
/**
* =========================================================
* 📌 默认行为(无返回)
* =========================================================
*
* 👉 不 return:
* - 表示仅监听或手动处理
* - 系统不会自动修改数据
*/
}
validate(instance)
instance{Object}valid{boolean} 是否通过校验(true/false)fields{Object} 校验失败字段集合env{Object} 运行环境context{Object} 表单上下文
- 返回
{void}
说明
表单整体校验完成后触发,无论校验成功或失败都会执行。
常见业务场景
- 提取第一条错误信息并统一展示
- 自定义错误提示样式或位置
- 校验通过后执行额外逻辑(如日志上报)
⚠️ 注意:fields 结构为:
{
fieldName: [
{ message: "错误信息" }
]
}
validate: (instance) =>
{
const
{
valid,
fields,
env,
context
} = instance;
console.warn("【validate】执行", instance);
/**
* 📌 安全提取错误提示(只取第一条)
*/
const showError = (fields, defaultMsg = "表单校验失败") =>
{
try
{
if (!fields || typeof fields !== "object")
{
env.runtime.ElMessage.error(defaultMsg);
return;
}
const errorList = Object.values(fields);
if (!errorList.length)
{
env.runtime.ElMessage.error(defaultMsg);
return;
}
const firstItem = errorList[0];
if (!Array.isArray(firstItem) || !firstItem.length)
{
env.runtime.ElMessage.error(defaultMsg);
return;
}
const msg = firstItem[0]?.message;
env.runtime.ElMessage.error(msg || defaultMsg);
}
catch (e)
{
env.runtime.ElMessage.error(defaultMsg);
}
};
// ❌ 校验失败 → 自动提示
if (!valid)
{
showError(fields);
}
}
before(instance)
instance{Object}type{string} 请求类型get获取表单数据(详情回显)add新增提交edit编辑提交
headers{Object} 请求头(可修改)data{Object} 请求体数据(可修改)env{Object} 运行环境(包含user、runtime、router等)context{Object} 表单上下文(包含model等)
- 返回
{Object}完整的 axios 请求配置
说明
请求发送前的统一拦截入口,所有表单请求都会经过这里。
常见业务场景
- 注入
token到请求头 - 修改请求参数格式(过滤、加密、签名)
- 按
type分支处理不同请求类型 - 统一显示 loading 或提示信息
⚠️ 注意:
- 必须
return完整的请求配置对象 - 不
return或返回undefined→ 请求不会发送
before: (instance) =>
{
const
{
type,
headers,
data,
env,
context
} = instance;
// ================= 调试日志 =================
console.groupCollapsed("🚀 [before] " + type);
console.log("instance:", instance);
console.groupEnd();
// ================= 请求头重构 =================
const newHeaders = {
...headers,
Authorization: "Bearer " + (env?.user?.token || ""),
"Content-Type": "application/json"
};
// ================= 请求数据处理 =================
let newData = {
};
// ================= 请求前处理(按 type 分发) =================
switch (type)
{
case "get":
{
env?.runtime?.ElMessage?.info(
"正在加载表单数据(可在此处处理字段映射 / 默认值)"
);
newData = {
...data
};
break;
}
case "add":
{
env?.runtime?.ElMessage?.info(
"正在提交新增表单(可在此处处理提交参数格式)"
);
newData = {
...data
};
break;
}
case "edit":
{
env?.runtime?.ElMessage?.info(
"正在提交编辑表单(可在此处处理提交参数格式)"
);
newData = {
...data
};
break;
}
default:
{
newData = {
...data
};
break;
}
}
// ================= 返回 axios 配置 =================
return {
url: instance.url,
method: instance.method || "post",
headers: newHeaders,
timeout: instance.timeout || 30000,
data: newData
};
}
after(instance)
instance{Object}response{Object} 接口原始返回(axios response)type{string} 请求类型(get/add/edit)success{boolean} 请求是否成功env{Object} 运行环境context{Object} 表单上下文
- 返回
{Object}标准结构{ code, data, msg }
说明
请求完成后统一处理响应数据,所有接口返回都会经过这里。
核心职责
- 数据结构标准化:将不同后端接口的返回结构统一转换为
{ code, data, msg }格式 - 统一提示处理(成功/失败消息)
- 按
type分支处理不同请求类型的后续逻辑
标准返回格式
{
code: number, // 200 成功,400 业务失败,401 未授权
data: any, // 业务数据
msg: string // 提示信息
}
⚠️ 注意:
- 无论后端返回什么结构(对象、JSON字符串、普通字符串),最终都必须转换为标准格式
- 否则前端无法统一处理数据结构
after: (instance) =>
{
const
{
type,
success,
response,
env,
context
} = instance;
// ================= 调试日志 =================
console.groupCollapsed("📦 [after] " + type);
console.log("instance:", instance);
console.groupEnd();
// ================= 默认提示(演示用) =================
if (success)
{
switch (type)
{
// ================= 表单数据加载处理 =================
case "get":
{
env?.runtime?.ElMessage?.info(
"get 数据处理区:可在此处处理表单数据加载 / 字段映射 / 默认值填充"
);
break;
}
// ================= 表单数据新增处理 =================
case "add":
{
env?.runtime?.ElMessage?.info(
"add 数据处理区:可在此处处理新增提交后的返回结构 / 状态处理"
);
break;
}
// ================= 表单数据编辑处理 =================
case "edit":
{
env?.runtime?.ElMessage?.info(
"edit 数据处理区:可在此处处理编辑提交后的返回结构 / 字段同步"
);
break;
}
default:
{
env?.runtime?.ElMessage?.info(
"未知 type:" + type + ",可在此处扩展表单处理逻辑"
);
break;
}
}
}
return {
code: 200,
data: response?.data?.data,
msg: response?.data?.msg
};
}
接口行为配置 config
config: {
submitCancel: boolean, // 是否显示提交/取消
addUrl: string, // 新增接口
editUrl: string, // 编辑接口
getUrl: string // 查看详情接口
}
⚠️ 注意:
接口请求可能会涉及跨域问题。例如:当前页面运行在云控官网后台域名(如 http://cloud.jsdevhub.com),而接口地址是 http://47.94.105.29:66,会因浏览器同源策略被拦截。解决方式建议:后端开启 CORS 并允许跨域
平台内置接口
作为平台方,我们提供了两个内置接口,方便您在表单中获取设备列表和用户列表。这两个接口无需额外开发,直接在表单配置中引用即可。
设备列表接口
用于获取当前账户及其下级账户绑定的所有设备数据。
| 项目 | 内容 |
|---|---|
| 接口地址 | http://180.76.145.80/api/getDeviceList |
| 请求方式 | POST |
| 返回格式 | { code: 200, msg: "成功", data: [{ id, label }] } |
| 适用场景 | 设备选择、任务分配等 |
返回数据示例:
{
"code": 200,
"msg": "成功",
"data": [
{ "id": 58870, "label": "android7" },
{ "id": 10384, "label": "qwe001" },
{ "id": 10504, "label": "qwert1235" }
]
}
字段说明:
| 字段 | 说明 |
|---|---|
id | 设备 ID(存储值) |
label | 设备名称(显示值) |
用户列表接口
用于获取当前账户及其下级账户的所有用户数据。
| 项目 | 内容 |
|---|---|
| 接口地址 | http://180.76.145.80/api/getUserList |
| 请求方式 | POST |
| 返回格式 | { code: 200, msg: "成功", data: [{ id, label }] } |
| 适用场景 | 用户选择、用户关联等 |
返回数据示例:
{
"code": 200,
"msg": "成功",
"data": [
{ "id": 382, "label": "ceshi3" },
{ "id": 7750, "label": "ceshi22" }
]
}
字段说明:
| 字段 | 说明 |
|---|---|
id | 用户 ID(存储值) |
label | 用户名(显示值) |
在表单中引用
在表单字段的 config 中配置 optionsType: 1(远程接口),optionsFun 填入对应的接口地址即可。
设备选择示例:
{
type: "select",
name: "device_id",
control: {
modelValue: "",
placeholder: "请选择设备",
appendToBody: true
},
options: [],
config: {
optionsType: 1,
optionsFun: "http://180.76.145.80/api/getDeviceList",
method: "post",
value: "id" // 指定 value 字段为 id
},
formItem: {
label: "设备"
}
}
用户选择示例:
{
type: "select",
name: "user_id",
control: {
modelValue: "",
placeholder: "请选择用户",
appendToBody: true
},
options: [],
config: {
optionsType: 1,
optionsFun: "http://180.76.145.80/api/getUserList",
method: "post",
value: "id"
},
formItem: {
label: "用户"
}
}
💡 说明:这两个接口已内置支持,返回数据中的
id对应选项值,label对应选项显示文本。配置时需指定value: "id"以正确映射数据。
示例
列表添加/编辑表单
适用于列表页的数据新增/编辑场景,包含各类常用字段、校验、下拉动态加载、上传、时间联动及完整的请求拦截与响应处理。
opt = {
list: [
{
type: "input",
control:
{
modelValue: "",
placeholder: "请输入标题"
},
config:
{},
name: "label",
formItem:
{
label: "标题"
}
},
{
type: "selectPlus",
control:
{
modelValue: "",
appendToBody: true,
valueKey: "id",
filterable: true,
props:
{
label: "label",
value: "id"
}
},
options: [],
config:
{
optionsType: 1,
optionsFun: "http://47.94.105.29:66/api/DataListCaseCategoryList",
method: "post",
addUrl: "http://47.94.105.29:66/api/addDataListCaseCategory",
editUrl: "http://47.94.105.29:66/api/editDataListCaseCategory",
deleteUrl: "http://47.94.105.29:66/api/deleteDataListCaseCategory"
},
name: "category_id",
formItem:
{
label: "分类"
}
},
{
type: "input",
control:
{
modelValue: "",
placeholder: "请输入链接"
},
config:
{},
name: "link",
formItem:
{
label: "链接"
}
},
{
type: "input",
control:
{
modelValue: "",
placeholder: "请输入uid"
},
config:
{},
name: "uid",
formItem:
{
label: "UID"
}
},
{
type: "select",
control:
{
modelValue: "",
appendToBody: true,
placeholder: "请选择任务类型"
},
options: [],
config:
{
optionsType: 1,
optionsFun: "http://47.94.105.29:66/api/getFieldTaskTypeIdDict",
method: "post"
},
name: "task_type_id",
formItem:
{
label: "任务类型"
},
events:
{
after: (instance) =>
{
const
{
type,
success,
response,
env,
context
} = instance;
// ================= 调试日志 =================
console.groupCollapsed("📦 [after] " + type);
console.log("instance:", instance);
console.groupEnd();
return {
code: 200,
data: response?.data?.data?.list,
msg: response?.data?.msg
};
}
}
},
{
type: "select",
control:
{
modelValue: "",
appendToBody: true
},
options: [],
config:
{
optionsType: 1,
optionsFun: "http://180.76.145.80/api/getDeviceList",
method: "post",
value: "id"
},
name: "device_id",
formItem:
{
label: "设备"
}
},
{
type: "select",
control:
{
modelValue: "",
appendToBody: true
},
options: [],
config:
{
optionsType: 1,
optionsFun: "http://180.76.145.80/api/getUserList",
method: "post",
value: "id"
},
name: "user_id",
formItem:
{
label: "用户"
}
},
{
type: "upload",
control:
{
modelValue: "",
action: "http://47.94.105.29:66/api/upload",
multiple: true,
limit: 2,
listType: "picture-card"
},
config:
{
tip: "",
btnText: ""
},
name: "upload",
formItem:
{
label: "图片文件上传"
}
},
{
type: "datePicker",
control:
{
modelValue: "",
type: "datetime"
},
config:
{},
name: "datePicker",
formItem:
{
label: "日期选择器"
}
},
{
type: "timePicker",
control:
{
modelValue: ""
},
config:
{},
name: "timePicker",
formItem:
{
label: "时间选择器",
rules: [
{
required: true,
message: "请选择结束时间",
trigger: "change"
},
{
validator: (rule, value, callback) =>
{
const val = getTestDemoValueByName('datePicker')
if (value <= val)
{
callback(new Error('结束时间必须大于开始时间'))
}
else
{
callback()
}
},
trigger: "blur"
}]
}
},
{
type: "colorPicker",
control:
{
modelValue: ""
},
config:
{},
name: "colorPicker",
formItem:
{
label: "取色器"
}
},
{
type: "rate",
control:
{
modelValue: 0
},
config:
{},
name: "rate",
formItem:
{
label: "评分"
}
},
{
type: "slider",
control:
{
modelValue: 0
},
config:
{},
name: "slider",
formItem:
{
label: "滑块"
}
},
{
type: "inputNumber",
control:
{
modelValue: 0
},
config:
{},
name: "inputNumber",
formItem:
{
label: "计数器"
}
},
{
type: "button",
control:
{
label: "AI 内容生成",
style:
{
"margin-left": "100px",
"margin-bottom": "10px"
},
key: "none",
type: "info"
},
config:
{
source: 497,
openType: "drawer",
width: "100%"
},
events:
{
submit: (instance) =>
{
console.warn("📌 submit来源组件 / 行为:", instance);
const
{
selected,
model,
env,
context
} = instance;
var aiList = selected.articleTable || [];
var aiText = "";
if (Array.isArray(aiList) && aiList.length > 0)
{
aiText = aiList
.filter(function(item)
{
return item && item.content;
})
.map(function(item)
{
return String(item.content);
})
.join("\n\n"); // 👈 关键:双换行
}
var oldText = model.textarea || "";
// ❗ 不要 trim(重点)
if (oldText && oldText.trim() !== "")
{
context.model.textarea = oldText + "\n\n" + aiText;
}
else
{
context.model.textarea = aiText;
}
// api.ElMessage({
// message: "回填成功",
// type: "success"
// });
},
cancel: (instance) =>
{
console.log("取消了");
console.log("🚀 [cancel instance]:", instance);
}
}
},
{
type: "textarea",
control:
{
modelValue: "",
placeholder: "请输入多行文本,或者使用上方按钮通过AI快捷输入",
autosize:
{
minRows: 5,
maxRows: 8
}
},
config:
{},
name: "textarea",
formItem:
{
label: "多行文本"
}
},
{
type: "switch",
control:
{
modelValue: false,
activeValue: 1,
inactiveValue: 0
},
config:
{},
name: "switch",
formItem:
{
label: "开关"
}
},
{
type: "upload",
control:
{
modelValue: "",
action: "http://47.94.105.29:66/api/upload"
},
config:
{},
name: "play",
formItem:
{
label: "播放"
}
},
{
type: "upload",
control:
{
modelValue: "",
action: "http://47.94.105.29:66/api/upload"
},
config:
{},
name: "download",
formItem:
{
label: "下载链接"
}
},
{
type: "upload",
control:
{
modelValue: "",
action: "http://47.94.105.29:66/api/upload",
multiple: true,
limit: 2,
listType: "picture-card"
},
config:
{},
name: "image",
formItem:
{
label: "图片/文件"
}
},
{
type: "upload",
control:
{
modelValue: "",
action: "http://47.94.105.29:66/api/upload",
limit: 1,
drag: true
},
config:
{},
name: "video",
formItem:
{
label: "视频文件"
}
},
{
type: "input",
control:
{
modelValue: ""
},
config:
{},
name: "copy",
formItem:
{
label: "复制文本"
}
}],
form:
{
size: "default",
labelWidth: "100px",
name: "TestDemo"
},
events:
{
validate: (instance) =>
{
/**
* ===============================
* 📌 表单校验结果回调
* ===============================
*
* valid -> 是否通过校验(true / false)
* fields -> 校验失败字段集合(用于获取错误信息)
* env -> 运行环境(可调用 ElMessage 等能力)
* context -> 当前表单上下文数据
*/
const
{
valid,
fields,
env,
context
} = instance;
console.warn("【validate】执行", instance);
/**
* 📌 安全提取错误提示(只取第一条)
*/
const showError = (fields, defaultMsg = "表单校验失败") =>
{
try
{
if (!fields || typeof fields !== "object")
{
env.runtime.ElMessage.error(defaultMsg);
return;
}
const errorList = Object.values(fields);
if (!errorList.length)
{
env.runtime.ElMessage.error(defaultMsg);
return;
}
const firstItem = errorList[0];
if (!Array.isArray(firstItem) || !firstItem.length)
{
env.runtime.ElMessage.error(defaultMsg);
return;
}
const msg = firstItem[0]?.message;
env.runtime.ElMessage.error(msg || defaultMsg);
}
catch (e)
{
env.runtime.ElMessage.error(defaultMsg);
}
};
// ❌ 校验失败 → 自动提示
if (!valid)
{
showError(fields);
}
},
before: (instance) =>
{
/**
* =========================================================
* 🔧 before:请求发送前处理钩子(核心能力)
* =========================================================
*
* 👉 作用:
* - 统一修改请求参数(headers / data / config)
* - 注入 token / 鉴权信息
* - 请求预处理(日志 / 过滤 / 加密等)
*
*
* =========================================================
* 📦 instance:请求上下文
* =========================================================
* headers -> 请求头(可修改)
* data -> 请求体数据(可修改)
* type -> 请求类型(get / add / edit)
* env -> 运行环境(工具集合)
* context -> 表单页上下文(运行时数据)
*
* =========================================================
* 🧭 type:请求类型
* =========================================================
*
* get - 获取表单数据
* add - 新增表单数据
* edit - 编辑表单数据
*
* 💡 说明:
* - type 用于区分不同数据来源与操作行为
* - 可在 before / after 中做分支处理
*
* =========================================================
* 🌍 env:运行环境能力
* =========================================================
*
* env.runtime:
* - request
* - ElMessage
* - ElNotification
* - ElMessageBox
*
* env.user:
* - id
* - uname
* - token
*
* env.router:
* - 路由实例
*
* =========================================================
* 🌍 context:表单页上下文(运行时数据)
* =========================================================
*
* 👉 说明:
* context 表示当前表单页面的“运行时状态”,
* 可用于获取或修改表单数据
*
*
* ---------------------------------------------------------
* 📄 context.model:表单数据模型(核心)
* ---------------------------------------------------------
* - 当前表单的所有字段数据
* - 类型:object
*
*
* =========================================================
* 💡 默认行为说明
* =========================================================
* before 负责“修改请求”
* after 负责“处理响应”
*/
const
{
type,
headers,
data,
env,
context
} = instance;
// ================= 调试日志 =================
console.groupCollapsed("🚀 [before] " + type);
console.log("instance:", instance);
console.groupEnd();
// ================= 请求头重构 =================
const newHeaders = {
...headers,
Authorization: "Bearer " + (env?.user?.token || ""),
"Content-Type": "application/json"
};
// ================= 请求数据处理 =================
let newData = {
};
// ================= 请求前处理(按 type 分发) =================
switch (type)
{
case "get":
{
env?.runtime?.ElMessage?.info(
"正在加载表单数据(可在此处处理字段映射 / 默认值)"
);
newData = {
...data
};
break;
}
case "add":
{
env?.runtime?.ElMessage?.info(
"正在提交新增表单(可在此处处理提交参数格式)"
);
newData = {
...data
};
break;
}
case "edit":
{
env?.runtime?.ElMessage?.info(
"正在提交编辑表单(可在此处处理提交参数格式)"
);
newData = {
...data
};
break;
}
default:
{
newData = {
...data
};
break;
}
}
// ================= 返回 axios 配置 =================
return {
url: instance.url,
method: instance.method || "post",
headers: newHeaders,
timeout: instance.timeout || 30000,
data: newData
};
},
after: (instance) =>
{
/**
* =========================================================
* 🔧 after:请求结果后处理钩子(核心能力)
* =========================================================
*
* 👉 作用:
* - 统一接口返回结构(核心)
* - 提供默认行为(如提示)
* - 支持用户自定义扩展逻辑
*
*
* =========================================================
* 📦 instance:请求上下文(after 阶段)
* =========================================================
*
* response-> 接口返回结果(axios response)
* type -> 当前操作类型(get / add / edit)
* success -> 请求是否成功(boolean)
* env -> 运行环境(工具集合)
* context -> 表单页上下文(运行时数据)
*
*
* =========================================================
* 📄 response:接口响应数据(核心)
* =========================================================
* - 原始接口返回结果(通常为 axios response)
* - 常用访问方式:
*
* response.data -> 后端返回体
*
*
* =========================================================
* 🧭 type:当前操作类型
* =========================================================
* get -> 获取表单数据(回显)
* add -> 新增提交
* edit -> 编辑提交
*
*
* =========================================================
* ✅ success:请求是否成功
* =========================================================
* true -> 请求成功(进入 after 逻辑)
* false -> 请求失败(已由底层统一处理)
*
*
* =========================================================
* 🌍 env:运行环境
* =========================================================
* env.runtime:
* - request -> 网络请求方法(axios 封装)
* - ElMessage -> 消息提示
* - ElNotification -> 通知提示
* - ElMessageBox -> 弹窗
*
* env.user:
* - id
* - uname
* - token
*
* env.router:
* - 路由实例
*
*
* =========================================================
* 🌍 context:表单页上下文(运行时数据)
* =========================================================
*
* 👉 说明:
* context 表示当前表单页面的“运行时状态”,
* 可用于获取或修改表单数据
*
*
* ---------------------------------------------------------
* 📄 context.model:表单数据模型(核心)
* ---------------------------------------------------------
* - 当前表单的所有字段数据
* - 类型:object
*
*
* =========================================================
* 💡 默认行为(可删除)
* =========================================================
* - 根据 type 自动提示
* - 仅用于演示,实际项目可自行修改或删除
*/
const
{
type,
success,
response,
env,
context
} = instance;
// ================= 调试日志 =================
console.groupCollapsed("📦 [after] " + type);
console.log("instance:", instance);
console.groupEnd();
// ================= 默认提示(演示用) =================
if (success)
{
switch (type)
{
// ================= 表单数据加载处理 =================
case "get":
{
env?.runtime?.ElMessage?.info(
"get 数据处理区:可在此处处理表单数据加载 / 字段映射 / 默认值填充"
);
break;
}
// ================= 表单数据新增处理 =================
case "add":
{
env?.runtime?.ElMessage?.info(
"add 数据处理区:可在此处处理新增提交后的返回结构 / 状态处理"
);
break;
}
// ================= 表单数据编辑处理 =================
case "edit":
{
env?.runtime?.ElMessage?.info(
"edit 数据处理区:可在此处处理编辑提交后的返回结构 / 字段同步"
);
break;
}
default:
{
env?.runtime?.ElMessage?.info(
"未知 type:" + type + ",可在此处扩展表单处理逻辑"
);
break;
}
}
}
/**
* =========================================================
* 📦 统一返回数据格式(核心规范)
* =========================================================
*
* 👉 所有请求最终都会被转换为:
*
* {
* code: number,
* data: any,
* msg: string
* }
*
*
* ---------------------------------------------------------
* 🔢 code:状态码
* ---------------------------------------------------------
* 200 -> 请求成功
* 400 -> 业务失败(如参数错误)
* 401 -> 用户异常(登录失效,自动处理)
*
* 👉 用法:
* if (response.code === 200) { ... }
*
*
* ---------------------------------------------------------
* 📄 data:业务数据
* ---------------------------------------------------------
* - 接口核心数据
* - 类型:对象 或 数组
*
* 💡 示例:
* data = { id: 1, name: "张三" }
* data = [ { id: 1, name: "张三" }, { id: 2, name: "李四" } ]
*
*
* ---------------------------------------------------------
* 💬 msg:提示信息
* ---------------------------------------------------------
* - 用于 UI 提示
* - 一般来自后端
*
* 👉 用法:
* env.runtime.ElMessage.success(msg)
*
*
* =========================================================
* 💡 扩展说明(重要)
* =========================================================
* 不同后端接口返回结构可能不一致,
* 你需要在 after 中将数据“统一规范化”为标准格式:
*
* 👉 标准格式:
* {
* code: number,
* data: object,
* msg: string
* }
*
*
* =========================================================
* 📌 示例1:字段结构不一致(基础映射)
* =========================================================
*
* 后端返回:
* {
* code: 0,
* result: {...},
* message: "success"
* }
*
* 👉 转换:
* return {
* code: response.data.code,
* data: response.data.result,
* msg: response.data.message
* }
*
*
* =========================================================
* 📌 示例2:data 是 JSON 字符串(常见)
* =========================================================
*
* 后端返回:
* {
* code: 200,
* result: "{"id":1,"name":"张三"}",
* message: "ok"
* }
*
* 👉 转换:
* return {
* code: response.data.code,
* data: JSON.parse(response.data.result), // 字符串 → 对象
* msg: response.data.message
* }
*
*
* =========================================================
* 📌 示例3:复杂字符串解析
* =========================================================
*
* 后端返回:
* {
* code: 200,
* result: "id=1,name=张三,age=18"
* }
*
* 👉 转换:
* const obj = Object.fromEntries(
* response.data.result.split(",").map(item => item.split("="))
* );
*
* return {
* code: response.data.code,
* data: obj,
* msg: response.data.message
* }
*
*
* =========================================================
* ⚠️ 核心原则(非常重要)
* =========================================================
* 无论后端返回:
* - 对象
* - JSON字符串
* - 普通字符串
* - 拼接字符串
*
* 👉 最终都必须转换为:
* {
* code,
* data,
* msg
* }
*
* ❗否则前端无法统一处理数据结构
*/
return {
code: 200,
data: response?.data?.data,
msg: response?.data?.msg
};
},
change: (instance) =>
{
/**
* =========================================================
* 🔧 change:表单字段变化回调(核心能力)
* =========================================================
*
* 👉 作用:
* - 监听字段变化
* - 表单联动(自动填充 / 计算)
* - 执行副作用(请求 / 提示 / 控制UI)
*
*
* =========================================================
* 📦 instance:变化上下文(统一结构)
* =========================================================
*
* name -> 当前变化字段名
* value -> 当前字段值
* prop -> 字段标识(子表或flex时的prop 同 name)
* options -> 组件配置
*
* env -> 运行环境(工具集合)
* context -> 表单上下文(推荐使用)
*
*
* =========================================================
* 🌍 context(推荐使用)
* =========================================================
*
* context.model -> 当前表单数据(核心)
* context.props -> 组件参数
*
*
* =========================================================
* 💡 返回值行为规范(非常重要)
* =========================================================
*
* 👉 不 return:
* - 不触发系统自动更新
* - ✅ 可以通过 context.model 手动修改数据
*
* 👉 return object:
* - 覆盖整个 model(复杂联动)
*
* ⚠️ 注意:
* - 不建议同时使用 return + context.model
* - 避免数据冲突
*/
const
{
name,
value,
model,
prop,
options,
env,
context
} = instance;
// ================= 调试日志 =================
console.groupCollapsed("🔄 [change] " + name);
console.log("instance:", instance);
console.groupEnd();
/**
* =========================================================
* 📌 示例1:仅监听(不修改数据)
* =========================================================
*/
if (name === "xxx")
{
env?.runtime?.ElMessage?.info("字段变化(仅监听)");
// ❗ 不 return
// ❗ 不修改 context.model
}
/**
* =========================================================
* 📌 示例2:使用 context.model 修改(推荐方式2)
* =========================================================
*
* 👉 适用于:
* - 简单赋值
* - 副作用逻辑
*/
if (name === "xxx")
{
context.model.otherField = value;
// ❗ 不 return
}
/**
* =========================================================
* 📌 示例3:return object(复杂联动)
* =========================================================
*
* 👉 适用于多字段 / 条件逻辑
*/
if (name === "xxx")
{
const newModel = {
...context.model,
// otherField: value,
// anotherField: "xxx"
};
// return newModel;
}
/**
* =========================================================
* 📌 示例4:副作用(请求 / 计算)
* =========================================================
*
* 👉 不需要 return
*/
if (name === "xxx")
{
// 示例:发请求
// const response = await env.runtime.request({
// url: "【请替换为你的接口地址】/api/xxx",
// method: "post",
// data: {
// model: context.model
// }
// });
// console.log("📦 response:", response);
}
/**
* =========================================================
* 📌 默认行为(无返回)
* =========================================================
*
* 👉 不 return:
* - 表示仅监听或手动处理
* - 系统不会自动修改数据
*/
}
},
config:
{
submitCancel: true,
addUrl: "http://47.94.105.29:66/api/addDataListCase",
editUrl: "http://47.94.105.29:66/api/editDataListCase",
getUrl: "http://47.94.105.29:66/api/getDataListCase"
}
}
列表搜索表单
适用于列表页的搜索条件表单,仅包含搜索字段,无提交接口,通常与列表数据请求配合使用。
opt = {
list: [
{
type: "input",
control: {
modelValue: "",
placeholder: "请输入标题"
},
config: {},
name: "label",
formItem: {
label: "标题"
}
},
{
type: "input",
control: {
modelValue: "",
placeholder: "请输入链接"
},
config: {},
name: "link",
formItem: {
label: "链接"
}
},
{
type: "input",
control: {
modelValue: "",
placeholder: "请输入uid"
},
config: {},
name: "uid",
formItem: {
label: "UID"
}
},
{
type: "select",
control: {
modelValue: "",
appendToBody: true,
placeholder: "请选择任务类型"
},
options: [
{ label: "任务类型1", value: "1" },
{ label: "任务类型2", value: "2" },
{ label: "任务类型3", value: "3" },
{ label: "任务类型4", value: "4" }
],
config: {
optionsType: 0
},
name: "task_type_id",
formItem: {
label: "任务类型"
}
},
{
type: "select",
control: {
modelValue: "",
appendToBody: true
},
options: [],
config: {
optionsType: 1,
optionsFun: "http://47.94.105.29:66/api/DataListCaseCategoryTree",
method: "post",
value: "id",
label: ""
},
name: "category_id",
formItem: {
label: "选择分类"
}
},
{
type: "select",
control: {
modelValue: "",
appendToBody: true
},
options: [],
config: {
optionsType: 1,
optionsFun: "http://180.76.145.80/api/getDeviceAllList",
method: "post",
value: "id",
label: ""
},
name: "device_id",
formItem: {
label: "选择设备"
}
},
{
type: "select",
control: {
modelValue: "",
appendToBody: true
},
options: [],
config: {
optionsType: 1,
optionsFun: "http://180.76.145.80/api/getUserList",
method: "post",
label: "",
value: "id"
},
name: "user_id",
formItem: {
label: "选择用户"
}
}
],
form: {
size: "default",
labelWidth: "100px"
},
config: {
submitCancel: true
}
}
表单嵌套(打开另一个表单)
主表单中通过 button 按钮组件打开另一个表单(例如 AI 内容生成),并实现数据回填。配置时,config 中的 source 属性值(如下文的 497)即为子表单在“表单设计”列表页中的唯一记录 ID。您只需在表单设计列表中找到目标子表单对应的 ID 数字并填入,即可实现主表单与任意子表单的嵌套联动。下面展示主表单与子表单(ID = 497)的完整配置。
主表单(包含打开子表单的按钮)
opt = {
list: [
{
type: "button",
control:
{
label: "AI 内容生成",
style:
{
"margin-left": "100px",
"margin-bottom": "10px"
},
key: "none",
type: "info"
},
config:
{
source: 497, // 子表单的ID
openType: "drawer", // 打开方式
width: "100%" // 抽屉宽度
},
events:
{
submit: (instance) =>
{
console.warn("📌 submit来源组件 / 行为:", instance);
const
{
selected,
model,
env,
context
} = instance;
let aiList = selected.articleTable || [];
let aiText = "";
if (Array.isArray(aiList) && aiList.length > 0)
{
aiText = aiList
.filter(function(item)
{
return item && item.content;
})
.map(function(item)
{
return String(item.content);
})
.join("\n\n"); // 👈 关键:双换行
}
let oldText = model.article_content || "";
// ❗ 不要 trim(重点)
if (oldText && oldText.trim() !== "")
{
context.model.article_content = oldText + "\n\n" + aiText;
}
else
{
context.model.article_content = aiText;
}
env.runtime.ElMessage(
{
message: "回填成功",
type: "success"
});
},
cancel: (instance) =>
{
console.log("取消了");
console.log("🚀 [cancel instance]:", instance);
}
}
},
{
type: "textarea",
control:
{
modelValue: "",
placeholder: "请输入内容(多条内容用间隔一空行)",
autosize:
{
minRows: 30,
maxRows: 33
}
},
config:
{},
name: "article_content",
formItem:
{
label: "文章段落"
}
}],
form:
{
size: "default",
labelWidth: "100px"
},
config:
{
submitCancel: true
}
}
子表单(ID = 497,AI 内容生成)
opt = {
list: [
{
type: "div",
control:
{
marginBottom: "16px"
},
list: [
{
type: "input",
name: "article_topic",
control:
{
modelValue: "如何提高学习效率",
placeholder: "请输入文章主题"
},
formItem:
{
label: "文章主题"
}
},
{
type: "input",
name: "target_audience",
control:
{
modelValue: "大学生",
placeholder: "请输入目标读者"
},
formItem:
{
label: "目标人群"
}
},
{
type: "input",
name: "writing_style",
control:
{
modelValue: "通俗易懂",
placeholder: "请输入写作风格"
},
formItem:
{
label: "写作风格"
}
},
{
type: "inputNumber",
name: "paragraph_count",
control:
{
modelValue: 3,
placeholder: "请输入段落数量"
},
formItem:
{
label: "段落数量"
}
},
{
type: "button",
control:
{
label: "生成文章段落",
style:
{
marginLeft: "100px",
marginBottom: "10px"
},
loading: false,
key: "none"
},
events:
{
click: async (instance) =>
{
const
{
schema,
env,
context
} = instance;
try
{
// ===== loading =====
schema.control.loading = true;
env.runtime.ElMessage(
{
message: "正在生成内容(演示接口)...",
type: "info"
});
/**
* =========================================================
* 📌 模拟接口(演示用)
* 👉 这个地址一看就是假的,用户必须自己改
* =========================================================
*/
const response = await env.runtime.request(
{
url: "http://47.94.105.29:66/api/generateByStyle", // 👈 必须替换
method: "post",
data:
{
topic: context.model.article_topic,
audience: context.model.target_audience,
style: context.model.writing_style,
count: context.model.paragraph_count
},
timeout: 2000
});
console.log("📦 response:", response);
/**
* =========================================================
* 📌 数据处理(演示)
* =========================================================
*/
const list =
response?.data?.data || [
"这是示例段落1(未接入真实接口)",
"这是示例段落2(用于演示效果)",
"这是示例段落3(可自行替换接口)"
];
context.model.articleTable = list.map((text, index) => (
{
id: index,
content: text
}));
env.runtime.ElMessage.success("生成成功(演示数据)");
}
catch (err)
{
console.error(err);
env.runtime.ElMessage.error("请求失败(演示)");
}
finally
{
schema.control.loading = false;
}
}
}
}]
},
{
type: "div",
list: [
{
type: "table",
name: "articleTable",
control:
{
border: true,
height: "300",
style: "width: 100%"
},
config:
{
addBtnText: "新增段落",
delBtnText: "删除",
disabledEdit: true
},
list: [
{
type: "selection",
width: 60
},
{
name: "content",
type: "input",
formItem:
{
label: "文章内容"
},
control:
{
modelValue: "",
placeholder: "生成的内容会显示在这里"
},
column:
{
minWidth: 300
}
}]
}]
}],
form:
{
size: "default",
labelWidth: "100px"
},
config:
{
submitCancel: true,
getUrl: "",
editUrl: ""
}
}