hookehuyr

docs: 为LangChain Agent添加完整的表单配置文档集

添加详细的文档集,为LangChain Agent生成表单配置提供完整的参考指南。包括:
- 数据结构总览:核心FormField、ComponentProps、Option等结构定义
- 组件类型参考:30+种表单组件的详细说明和配置要点
- 配置规范:component_props的完整属性规范和数据提交格式
- LangChain Agent使用指南:自然语言到组件的映射、必填识别、选项提取规则
- 示例数据:20+个真实配置示例和完整表单模板
- 规则控制系统:字段显示/隐藏规则的详细实现机制
- API接口文档:表单管理和数据操作的所有接口说明
- 页面数据提取指南:从实际运行表单中提取配置的方法
# 变更日志
记录项目开发过程中的重要变更和完成任务。
## 2026-03-16
### 16:54:40 - 完成任务
**影响文件**:
- `CLAUDE.md`
**变更摘要**:
- 无详细描述
# 数据结构总览
## 核心数据结构
### 1. 表单字段结构 (FormField)
每个表单字段都是一个对象,包含以下核心属性:
```typescript
interface FormField {
// 字段标识
key: string // 字段唯一标识,如 "field_1"
name: string // 表单验证用的名称,通常等于 key
// 字段值
value: any // 字段当前值
default?: any // 默认值
// 组件相关
component: Component // Vue 组件引用
component_props: ComponentProps // 组件属性配置
// 验证相关
required?: boolean // 是否必填
rules?: ValidationRule[] // 验证规则
type?: string // 表单输入类型(text/textarea等)
// 其他
index?: number // 字段排序索引
}
```
### 2. 组件属性结构 (ComponentProps)
```typescript
interface ComponentProps {
// 基础属性
tag: string // 组件类型标识(如 "input", "radio")
name: string // 组件名称
label: string // 字段标签(显示名称)
placeholder?: string // 占位符文本
default?: any // 默认值
// 显示控制
disabled?: boolean // 是否隐藏
disabled_show?: boolean // 隐藏时是否显示图标
readonly?: boolean // 是否只读
required?: boolean // 是否必填
// 选项类组件
options?: Option[] // 选项列表(radio/checkbox/select)
// 样式相关
align?: string // 文本对齐方式(left/center/right)
direction?: string // 排列方向(vertical/horizontal)
background_color?: string // 背景色
// 高级功能
note?: string // 提示文本(支持HTML)
is_camera_scan?: boolean // 是否启用微信扫一扫
camera_scan_type?: string // 扫码类型(ALL_CODE/QR_CODE/BAR_CODE)
// 图片上传
max_count?: number // 最大上传数量
max_size?: number // 最大文件大小(MB)
// 评分
x_score?: number // 分数值
// 分组相关
is_field_group?: boolean // 是否是集合组
group_field_name?: string // 所属组字段名
}
```
### 3. 选项结构 (Option)
用于 Radio、Checkbox、Picker 等组件:
```typescript
interface Option {
// 基础
title: string // 选项显示文本
value: any // 选项值
checked?: boolean // 是否默认选中
// 样式
color?: string // 选项颜色
background_color?: string // 背景色
// 状态
disabled?: boolean // 是否禁用
// 描述信息
desc_text?: string // 描述文本
desc_type?: string // 描述类型(text/url)
desc_url?: string // 描述链接URL
desc_btn_name?: string // 描述按钮名称
// 补充信息
is_input?: boolean // 是否需要输入补充信息
input_required?: boolean // 补充信息是否必填
input_placeholder?: string // 补充信息占位符
affix?: string // 补充信息值
}
```
### 4. API 响应结构
```typescript
interface APIResponse<T = any> {
code: number // 状态码:1=成功,其他=失败
msg: string // 响应消息
data: T // 响应数据
show?: boolean // 是否显示错误提示
}
```
## 数据流转
### 1. 表单渲染流程
```
后端API → 表单配置数据 → createComponentType() → 动态组件渲染
```
### 2. 表单提交流程
```
用户输入 → 组件v-model → item.value → addFormDataAPI() → 后端保存
```
## 关键概念
### 1. 动态组件系统
项目使用 `component_props.tag` 属性决定渲染哪种组件:
- 系统通过 `src/hooks/useComponentType.js` 中的 `createComponentType()` 函数
- 根据 `tag` 值动态分配对应的 Vue 组件
- 支持 30+ 种组件类型
### 2. 验证系统
- 基于 Vant Form 的验证系统
- 通过 `rules` 数组配置验证规则
- 必填项自动添加 `{ required: true, message: 'xxx' }`
### 3. 规则系统
- 字段可以通过规则控制其他字段的显示/隐藏
- 通过 `emit("active")` 触发规则检查
- 规则组件:`RuleField``MultiRuleField`
### 4. Cookie 保存
- 未完成表单自动保存到 Cookie
- 格式:`{ form_code: { field_key: value } }`
- 过期时间:1 天
### 5. 周期选择
- 某些表单支持周期选择
- 通过 API `/srv/?a=cycle_list` 获取可用周期
- 周期选择后 URL 会携带 `x_cycle` 参数
# 表单字段组件类型
## 支持的组件类型列表
项目支持 **30+ 种** 动态表单字段组件,通过 `component_props.tag` 属性指定。
## 文本输入类
### 1. input - 单行文本输入
- **组件**: `TextField`
- **用途**: 短文本输入,如姓名、标题等
- **特殊功能**: 微信扫一扫(`is_camera_scan`
### 2. textarea - 多行文本输入
- **组件**: `TextareaField`
- **用途**: 长文本输入,如备注、描述等
- **特性**: 自动高度(`autosize`
### 3. number - 数字输入
- **组件**: `NumberField`
- **用途**: 数字类型输入,如年龄、数量等
## 选择类
### 4. radio - 单项选择
- **组件**: `RadioField`
- **用途**: 单选选项,如性别、是否等
- **数据结构**: `options` 数组
- **特殊功能**:
- 选项颜色(`color`, `background_color`
- 补充信息输入(`is_input`
- 描述信息(`desc_text`, `desc_url`
### 5. checkbox - 多项选择
- **组件**: `CheckboxField`
- **用途**: 多选选项,如爱好、标签等
- **数据结构**: `options` 数组
- **排列方向**: `direction` (vertical/horizontal)
### 6. select - 单列选择器
- **组件**: `PickerField`
- **用途**: 下拉单选
- **数据结构**: `options` 数组
- **返回值**: 选中的 `value`
## 日期时间类
### 7. date - 日期选择器
- **组件**: `DatePickerField`
- **用途**: 选择日期
### 8. time - 时间选择器
- **组件**: `TimePickerField`
- **用途**: 选择时间
### 9. datetime - 日期时间选择器
- **组件**: `DateTimePickerField`
- **用途**: 选择日期和时间
### 10. calendar - 日历选择器
- **组件**: `CalendarField`
- **用途**: 日历形式选择日期
## 上传类
### 11. image_uploader - 图片上传
- **组件**: `ImageUploaderField`
- **用途**: 上传图片到七牛云
- **配置**:
- `max_count`: 最大数量
- `max_size`: 最大文件大小(MB)
- **返回值**: `[{ url, name }]`
### 12. file_uploader - 文件上传
- **组件**: `FileUploaderField`
- **用途**: 上传普通文件
## 特殊输入类
### 13. phone - 手机号输入
- **组件**: `PhoneField`
- **用途**: 手机号码输入和验证
- **验证**: 11位手机号格式
### 14. email - 邮箱输入
- **组件**: `EmailField`
- **用途**: 邮箱地址输入和验证
### 15. id_card - 身份证输入
- **组件**: `IdentityField`
- **用途**: 身份证号码输入和验证
### 16. name - 姓名输入
- **组件**: `NameField`
- **用途**: 中文姓名输入
### 17. gender - 性别选择
- **组件**: `GenderField`
- **用途**: 性别选择(男/女)
## 位置类
### 18. address - 地址选择器
- **组件**: `AreaPickerField`
- **用途**: 省/市/区三级联动选择
- **数据**: 使用 `@vant/area-data`
## 展示类
### 19. desc - 文字描述
- **组件**: `DesField`
- **用途**: 纯文字展示,不支持输入
### 20. divider - 分割线
- **组件**: `DividerField`
- **用途**: 视觉分割线
### 21. note - 富文本控件
- **组件**: `NoteField`
- **用途**: 富文本内容展示
### 22. marquee - 跑马灯
- **组件**: `MarqueeField`
- **用途**: 滚动公告文字
## 特殊功能类
### 23. sign - 电子签名
- **组件**: `SignField`
- **用途**: 手写签名板
- **依赖**: `vue-esign`
### 24. rate - 评分选择器
- **组件**: `RatePickerField`
- **用途**: 星级评分
### 25. appointment - 预约控件
- **组件**: `AppointmentField`
- **用途**: 时间段预约选择
- **数据结构**: 复杂的日期+时间段结构
### 26. rule - 活动规则控件
- **组件**: `RuleField`
- **用途**: 显示规则说明,支持弹窗
### 27. multi_rule - 活动规则控件(多选)
- **组件**: `MultiRuleField`
- **用途**: 多选规则选项
### 28. contact - 联系人控件
- **组件**: `ContactField`
- **用途**: 联系人信息输入
### 29. button - 按钮控件
- **组件**: `ButtonField`
- **用途**: 自定义按钮
### 30. custom - 自定义控件
- **组件**: `CustomField`
- **用途**: 完全自定义的组件
## 高级类
### 31. group - 组集合输入控件
- **组件**: `GroupField`
- **用途**: 将多个字段分组显示
- **配置**: `field_groups` 数组
### 32. org_picker - 树形选择控件
- **组件**: `OrgPickerField`
- **用途**: 组织架构树形选择
### 33. volunteer_group - 义工组别选择
- **组件**: `VolunteerGroupField`
- **用途**: 义工组别单选
### 34. table_editor - 表格编辑控件
- **组件**: `TableField`
- **用途**: 动态表格编辑,支持增删行
### 35. video - 视频控件
- **组件**: `VideoField`
- **状态**: 已注释,暂未使用
## 组件注册位置
所有组件在 `src/hooks/useComponentType.js` 中注册:
```javascript
export function createComponentType(data) {
_.each(data, (item, index) => {
// 统一名称
item.name = item.key
// 根据 tag 分配组件
if (item.component_props.tag === 'input') {
item.component = TextField;
}
if (item.component_props.tag === 'radio') {
item.component = RadioField;
}
// ... 更多组件
})
}
```
## 新增组件流程
1.`src/components/` 下创建组件目录
2. 创建 `index.vue` 组件文件
3.`src/hooks/useComponentType.js` 添加 if 判断分支
4. 组件必须支持以下 props:
- `item`: Object (包含 component_props 和 value)
- 必须通过 emit 发送 "active" 事件
# component_props 配置规范
## 通用属性
所有组件类型都支持的属性:
| 属性 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `tag` | string | ✅ | - | 组件类型标识,决定渲染哪个组件 |
| `name` | string | ✅ | - | 组件名称 |
| `label` | string | ✅ | - | 字段标签(显示名称) |
| `default` | any | ❌ | - | 默认值 |
| `placeholder` | string | ❌ | "请输入" | 占位符文本 |
| `required` | boolean | ❌ | false | 是否必填 |
| `disabled` | boolean | ❌ | false | 是否隐藏字段 |
| `disabled_show` | boolean | ❌ | false | 隐藏时是否显示闭眼图标 |
| `readonly` | boolean | ❌ | false | 是否只读 |
| `note` | string | ❌ | - | 提示文本(支持HTML) |
## 选项类组件属性
Radio、Checkbox、Picker 等组件额外支持:
| 属性 | 类型 | 说明 |
|------|------|------|
| `options` | Option[] | 选项列表数组 |
| `direction` | string | 排列方向:`vertical`(垂直)/ `horizontal`(水平) |
| `align` | string | 文本对齐:`left` / `center` / `right` |
### Option 结构
```typescript
interface Option {
title: string // 显示文本
value: any // 选项值
checked?: boolean // 默认选中
disabled?: boolean // 禁用状态
color?: string // 选项颜色
background_color?: string // 背景色
// 描述信息
desc_text?: string // 描述文本
desc_type?: string // "text" 或 "url"
desc_url?: string // 描述链接
desc_btn_name?: string // 描述按钮名称
// 补充信息
is_input?: boolean // 是否需要补充信息输入
input_required?: boolean // 补充信息是否必填
input_placeholder?: string // 补充信息占位符
affix?: string // 补充信息值
}
```
## 文本输入类属性
### input / textarea / number
| 属性 | 类型 | 说明 |
|------|------|------|
| `align` | string | 文本对齐方式 |
| `is_camera_scan` | boolean | 是否启用微信扫一扫 |
| `camera_scan_type` | string | 扫码类型:`ALL_CODE` / `QR_CODE` / `BAR_CODE` |
| `is_edit_camera_scan_result` | boolean | 是否允许编辑扫码结果 |
## 上传类属性
### image_uploader
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `max_count` | number | 9 | 最大上传数量 |
| `max_size` | number | 10 | 最大文件大小(MB) |
| `image_type` | string | "jpg/..." | 允许的图片类型 |
**返回值结构**:
```javascript
{
key: "image_uploader",
filed_name: "field_1",
value: [
{ url: "https://...", name: "image.jpg" }
]
}
```
### file_uploader
`image_uploader` 类似,用于普通文件上传。
## 日期时间类属性
### date / time / datetime / calendar
| 属性 | 类型 | 说明 |
|------|------|------|
| `min_date` | Date/Date[] | 最小可选日期 |
| `max_date` | Date/Date[] | 最大可选日期 |
| `formatter` | Function | 格式化函数 |
## 预约控件属性
### appointment
**复杂配置结构**:
```javascript
{
tag: "appointment",
label: "预约时间",
appointment_title: "选择入寺时间",
options: [
{
title: "03月27日", // 日期标题
placeholder: "剩余余量 9878", // 提示信息
disabled: false, // 是否禁用该日期
columns: [ // 时间段列表
{
checked: false,
disabled: false,
value: "1",
text: "16:00-17:30 余1399"
}
]
}
]
}
```
## 规则控件属性
### rule / multi_rule
| 属性 | 类型 | 说明 |
|------|------|------|
| `desc_text` | string | 规则内容(支持 `\n` 换行) |
| `desc_type` | string | `text`(弹窗)或 `url`(跳转) |
| `desc_url` | string | 规则详情链接 |
| `desc_btn_name` | string | 按钮名称,如"查看详情" |
## 组集合控件属性
### group
```javascript
{
tag: "group",
label: "物品详情",
field_groups: [
{
tag: "input",
label: "物品描述",
field_name: "field_10",
group_field_name: "field_4", // 所属组字段
// ... 其他属性
}
]
}
```
## 评分控件属性
### rate
| 属性 | 类型 | 说明 |
|------|------|------|
| `x_score` | number | 显示分值(会显示在标签旁) |
## 表格控件属性
### table_editor
| 属性 | 类型 | 说明 |
|------|------|------|
| `default` | string/html | 默认表格内容(HTML格式) |
## 特殊功能属性
### 微信扫码
`input` 类型支持:
```javascript
{
tag: "input",
is_camera_scan: true,
camera_scan_type: "ALL_CODE" // ALL_CODE | QR_CODE | BAR_CODE
}
```
### 补充信息
Radio、Checkbox 支持选择后输入补充信息:
```javascript
options: [
{
title: "其他",
value: "other",
is_input: true, // 启用补充输入
input_required: true, // 补充信息必填
input_placeholder: "请输入补充信息",
affix: "" // 补充信息值
}
]
```
### 显示隐藏控制
通过规则动态控制字段显示/隐藏:
```javascript
{
tag: "input",
disabled: false // true=隐藏,false=显示
}
```
## 样式属性
### 对齐方式
```javascript
{
align: "left" // left | center | right
}
```
### 颜色
选项类组件支持单独配置颜色:
```javascript
options: [
{
title: "重要",
value: "important",
color: "#ff0000", // 文字颜色
background_color: "#fff0f0" // 背景色
}
]
```
## 数据提交格式
### 普通字段
```javascript
{
key: "field_1",
value: "用户输入的值"
}
```
### 选项类字段(Radio)
```javascript
{
key: "field_1",
value: "选项值",
affix: "补充信息: xxx", // 如果有补充信息
type: "radio"
}
```
### 选项类字段(Checkbox)
```javascript
{
key: "field_1",
value: ["值1", "值2"], // 数组
type: "checkbox"
}
```
### 图片上传
```javascript
{
key: "field_1",
filed_name: "field_1",
value: [
{ url: "https://...", name: "image.jpg" }
],
type: "image_uploader"
}
```
# API 接口文档
## 基础配置
### 请求基础配置
所有请求默认携带参数:
```javascript
{
f: 'custom_form' // 固定参数
}
```
### 响应格式
```typescript
interface APIResponse<T = any> {
code: number // 1=成功,其他=失败
msg: string // 响应消息
data: T // 响应数据
show?: boolean // 是否显示错误提示(code !== 1 时)
}
```
### 请求封装
```javascript
import { fn, fetch } from '@/api/fn';
// GET 请求
fn(fetch.get('/srv/?a=xxx', params))
// POST 请求
fn(fetch.post('/srv/?a=xxx', params))
```
## 表单管理接口
### 1. 新增表单
**接口**: `/srv/?a=add_form`
**方法**: POST
**参数**:
```javascript
{
client_id: string, // 主体客户id
name: string, // 表单名称
note: string // 表单描述
}
```
### 2. 查询表单配置(字段和规则)
**接口**: `/srv/?a=query_form_all_field`
**方法**: GET
**参数**:
```javascript
{
f: "custom_form", // 固定参数
form_code: string, // 表单唯一标识(必填)
page_type: string, // 页面类型:add/edit/view(可选)
data_id: string, // 数据ID(编辑时使用)
flow_node_code: string // 流程节点代码(可选)
}
```
**返回**:
```javascript
{
code: 1,
msg: "OK",
data: {
id: 835950,
code: "nxqkbf",
name: "表单名称",
table_name: "customize_35697_nxqkbf",
max_field_num: 3,
field_list: [
{
tag: "input", // 组件类型
field_name: "field_1", // 字段名
label: "姓名", // 显示标签
required: true, // 是否必填
data_type: "text", // 数据类型
placeholder: "请输入",
disabled: false,
readonly: false
}
],
rule_list: [ // 字段显示/隐藏规则
{
field_names: ["field_2"],
mode: "SHOW",
logical_op: "OR",
expr_list: [...]
}
],
flow_process_list: null // 工作流流程列表
}
}
```
**调用示例**:
```bash
curl "https://oa-dev.onwall.cn/srv/?a=query_form_all_field&f=custom_form&form_code=nxqkbf"
```
---
### 2.1. 查询表单设置(表单级配置)
**接口**: `/srv/?a=query_form_setting`
**方法**: GET
**参数**:
```javascript
{
f: "custom_form", // 固定参数
form_code: string // 表单唯一标识(必填)
}
```
**返回**:
```javascript
{
code: 1,
msg: "OK",
data: [{
id: 835950,
code: "nxqkbf",
name: "表单名称",
max_field_num: 3, // 最大字段数
data_count: 7, // 已提交数据条数
extend: {
server_time: "2026-03-16 17:15:40",
is_back_user: false // 是否后台用户
},
property_list: {
sjsj_enable: 1, // 是否启用数据收集
commit_action: "text", // 提交动作类型
commit_text_type: "default",
commit_text_template: "提交成功", // 提交文本模板
edit_commit_action: "text",
edit_commit_text_type: "default",
edit_commit_text_template: "提交成功"
}
}]
}
```
**调用示例**:
```bash
curl "https://oa-dev.onwall.cn/srv/?a=query_form_setting&f=custom_form&form_code=nxqkbf"
```
---
### 2.2. 两个接口的区别
| 接口 | 获取内容 | 用途 |
|------|---------|------|
| `query_form_all_field` | 字段列表、规则列表 | 渲染表单结构 |
| `query_form_setting` | 表单配置、提交设置 | 获取表单级属性 |
### 3. 添加表单字段
**接口**: `/srv/?a=add_form_field`
**方法**: POST
**参数**:
```javascript
{
form_code: string, // 表单唯一标识
component_code: string // 组件标识
}
```
### 4. 添加表单字段属性设置
**接口**: `/srv/?a=add_form_setting`
**方法**: POST
**参数**:
```javascript
{
form_code: string, // 表单唯一标识
field_name: string, // 表单字段名(表单级属性可为空)
component_code: string, // 组件标识
property_code: string, // 属性标识
setting_value: string // 属性值(JSON数组字符串)
}
```
### 5. 查询表单设置
**接口**: `/srv/?a=query_form_setting`
**方法**: GET
**参数**:
```javascript
{
form_code: string // 表单唯一标识
}
```
**返回**:
```javascript
{
enable: number, // 0=停止表单,1=开启表单
is_time_range: number, // 0=不设定,1=设定
is_count_down: number, // 0=不显示,1=显示
begin_time: string, // 开启时间
end_time: string // 停止时间
}
```
### 6. 验证便当密码
**接口**: `/srv/?a=verify_password`
**方法**: POST
**参数**:
```javascript
{
form_code: string, // 表单唯一标识
mmtx_password: string // 用户输入的密码
}
```
### 7. 义工组长查询义工信息
**接口**: `/srv/?a=volunteer_source_leader`
**方法**: GET
**参数**:
```javascript
{
form_code: string, // 表单唯一标识
page_type: string, // 页面类型
force_back: string, // 是否强制后台账号模式检查
volunteer_source: string, // 报名渠道:self/leader
volunteer_phone: string // 义工手机号
}
```
## 数据管理接口
### 1. 添加表单数据
**接口**: `/srv/?a=add_formdata`
**方法**: POST
**参数**:
```javascript
{
form_code: string, // 表单唯一标识
data: object // 待添加的数据(JSON对象)
}
```
**示例**:
```javascript
{
form_code: "form_001",
data: {
field_1: "张三",
field_2: "13800138000",
field_3: ["选项1", "选项2"]
}
}
```
### 2. 查询表单数据
**接口**: `/srv/?a=query_formdata`
**方法**: GET
**参数**:
```javascript
{
form_code: string, // 表单唯一标识
id: string // 数据ID
}
```
### 3. 修改表单数据
**接口**: `/srv/?a=modi_formdata`
**方法**: POST
**参数**:
```javascript
{
form_code: string, // 表单唯一标识
id: string, // 数据ID
data: object // 待修改的数据(JSON对象)
}
```
### 4. 流程表单数据
**接口**: `/srv/?a=flow_formdata`
**方法**: POST
**参数**:
```javascript
{
form_code: string, // 表单唯一标识
data_id: string, // 数据ID
data: object, // 表单数据
flow_node_code: string, // 流程节点
flow_node_action_id: string, // 流程节点按钮ID
flow_content: string // 流程审批意见
}
```
## 组件接口
### 1. 查询组件
**接口**: `/srv/?a=query_component`
**方法**: GET
**参数**:
```javascript
{
group_code: string, // 分组标识
component_code: string, // 组件标识
name: string // 组件名称(模糊查询)
}
```
### 2. 查询部门列表
**接口**: `/srv/?a=flow_setting&t=flow_dept_list`
**方法**: GET
**参数**:
```javascript
{
form_code: string // 表单code
}
```
**请求头建议**:
```javascript
{
headers: {
"only-data": true, // 去重
"keep-data": true // 缓存
}
}
```
### 3. 查询角色列表
**接口**: `/srv/?a=flow_setting&t=flow_role_list`
**方法**: GET
**参数**:
```javascript
{
form_code: string // 表单code
}
```
### 4. 搜索用户部门角色
**接口**: `/srv/?a=flow_setting&t=search_user_dept_role`
**方法**: GET
**参数**:
```javascript
{
form_code: string, // 表单code
word: string // 搜索内容
}
```
## 通用接口
### 1. 发送验证码
**接口**: `/srv/?a=sms`
**方法**: POST
**参数**:
```javascript
{
phone: string // 手机号码
}
```
### 2. 获取七牛上传 Token
**接口**: `/srv/?a=upload`
**方法**: POST
**参数**:
```javascript
qs.stringify({
name: string, // 文件名
hash: string // 文件哈希(ETag)
})
```
### 3. 保存文件
**接口**: `/srv/?a=upload&t=save_file`
**方法**: POST
**参数**:
```javascript
qs.stringify({
format: string, // 图片格式
hash: string, // 文件哈希
height: number, // 图片高度
width: number, // 图片宽度
filekey: string // 七牛返回的文件key
})
```
## 周期接口
### 1. 获取周期列表
**接口**: `/srv/?a=cycle_list`
**方法**: GET
**参数**:
```javascript
{
form_code: string // 表单唯一标识
}
```
**返回**:
```javascript
{
is_cycle: boolean, // 是否需要周期选择
cycle_list: [ // 周期列表
{
cycle_id: string,
cycle_name: string,
start_date: string,
end_date: string
}
]
}
```
## HTTP 请求缓存控制
### 请求去重(only-data)
避免短时间内重复请求:
```javascript
fn(fetch.get('/api/xxx', params, {
headers: { "only-data": true }
}))
```
### 持久化缓存(keep-data)
缓存请求结果(30秒,最多50条):
```javascript
fn(fetch.get('/api/xxx', params, {
headers: { "keep-data": true }
}))
```
### 同时使用
```javascript
fn(fetch.get('/api/xxx', params, {
headers: {
"only-data": true,
"keep-data": true
}
}))
```
## 错误处理
### 特殊错误码
| 错误码 | 说明 | 处理 |
|--------|------|------|
| 402 | 未授权/登录失效 | 跳转登录页,show=false |
| 其他 | 业务错误 | 显示错误提示 |
### 402 处理示例
```javascript
if (response.data.code === 402) {
response.data.show = false; // 不显示默认错误
showToast({
message: '登录失效!将跳转到登录页面',
duration: 1500,
onClose: () => {
window.location.href = location.origin + '/admin/';
}
})
}
```
# 示例数据
## 完整表单配置示例
### 示例 1:用户信息表单
```javascript
{
key: "field_1",
value: "",
component_props: {
tag: "input",
name: "name",
label: "姓名",
placeholder: "请输入姓名",
required: true,
default: ""
}
}
```
### 示例 2:性别选择
```javascript
{
key: "field_2",
value: "",
component_props: {
tag: "gender",
name: "gender",
label: "性别",
required: true,
default: "",
options: [
{
title: "男",
value: "男",
checked: false
},
{
title: "女",
value: "女",
checked: false
}
]
}
}
```
### 示例 3:手机号输入
```javascript
{
key: "field_3",
value: "",
component_props: {
tag: "phone",
name: "phone",
label: "手机号",
placeholder: "请输入手机号",
required: true,
default: ""
}
}
```
### 示例 4:单项选择(带补充信息)
```javascript
{
key: "field_4",
value: "",
component_props: {
tag: "radio",
name: "category",
label: "报名类型",
required: true,
direction: "vertical",
default: "",
options: [
{
title: "个人报名",
value: "personal",
checked: true,
color: "#1989fa"
},
{
title: "团队报名",
value: "team",
checked: false,
color: "#ff976a"
},
{
title: "其他",
value: "other",
checked: false,
is_input: true, // 启用补充输入
input_required: true, // 补充信息必填
input_placeholder: "请说明具体类型",
desc_text: "请选择最符合的报名类型",
desc_type: "text",
desc_btn_name: "查看说明"
}
]
}
}
```
### 示例 5:多项选择
```javascript
{
key: "field_5",
value: [],
component_props: {
tag: "checkbox",
name: "hobbies",
label: "兴趣爱好",
required: false,
direction: "vertical",
options: [
{
title: "运动",
value: "sport",
checked: false,
background_color: "#f0f9ff"
},
{
title: "阅读",
value: "reading",
checked: false,
background_color: "#fff0f0"
},
{
title: "音乐",
value: "music",
checked: false,
background_color: "#f0fff0"
},
{
title: "旅游",
value: "travel",
checked: false,
background_color: "#fffaf0"
}
]
}
}
```
### 示例 6:下拉选择
```javascript
{
key: "field_6",
value: "",
component_props: {
tag: "select",
name: "city",
label: "所在城市",
placeholder: "请选择城市",
required: true,
options: [
{ text: "北京", value: "beijing" },
{ text: "上海", value: "shanghai" },
{ text: "广州", value: "guangzhou" },
{ text: "深圳", value: "shenzhen" }
]
}
}
```
### 示例 7:地址选择
```javascript
{
key: "field_7",
value: "",
component_props: {
tag: "address",
name: "address",
label: "详细地址",
placeholder: "请选择省市区",
required: true
}
}
```
### 示例 8:日期选择
```javascript
{
key: "field_8",
value: "",
component_props: {
tag: "date",
name: "birthday",
label: "出生日期",
placeholder: "请选择日期",
required: true
}
}
```
### 示例 9:图片上传
```javascript
{
key: "field_9",
value: [],
component_props: {
tag: "image_uploader",
name: "photos",
label: "上传照片",
required: true,
max_count: 3, // 最多3张
max_size: 5, // 最大5MB
default: []
}
}
```
### 示例 10:多行文本
```javascript
{
key: "field_10",
value: "",
component_props: {
tag: "textarea",
name: "description",
label: "个人简介",
placeholder: "请输入个人简介",
required: false,
default: ""
}
}
```
### 示例 11:电子签名
```javascript
{
key: "field_11",
value: "",
component_props: {
tag: "sign",
name: "signature",
label: "本人签名",
required: true,
default: ""
}
}
```
### 示例 12:评分
```javascript
{
key: "field_12",
value: "",
component_props: {
tag: "rate",
name: "rating",
label: "活动评分",
required: true,
x_score: 5, // 默认5分
default: ""
}
}
```
### 示例 13:身份证号
```javascript
{
key: "field_13",
value: "",
component_props: {
tag: "id_card",
name: "id_card",
label: "身份证号",
placeholder: "请输入身份证号",
required: true
}
}
```
### 示例 14:邮箱
```javascript
{
key: "field_14",
value: "",
component_props: {
tag: "email",
name: "email",
label: "电子邮箱",
placeholder: "请输入邮箱地址",
required: false
}
}
```
### 示例 15:预约控件
```javascript
{
key: "field_15",
value: "",
component_props: {
tag: "appointment",
name: "appointment_time",
label: "预约时间",
required: true,
appointment_title: "选择预约时间段",
options: [
{
title: "03月27日",
placeholder: "剩余余量 98",
disabled: false,
columns: [
{
checked: false,
disabled: false,
value: "1",
text: "09:00-10:30 余98"
},
{
checked: false,
disabled: false,
value: "2",
text: "14:00-15:30 余50"
},
{
checked: false,
disabled: true,
value: "3",
text: "16:00-17:30 余0"
}
]
},
{
title: "03月28日",
placeholder: "剩余余量 120",
disabled: false,
columns: [
{
checked: false,
disabled: false,
value: "4",
text: "09:00-10:30 余120"
},
{
checked: false,
disabled: false,
value: "5",
text: "14:00-15:30 余80"
}
]
}
]
}
}
```
### 示例 16:表格编辑
```javascript
{
key: "field_16",
value: "",
component_props: {
tag: "table_editor",
name: "table_data",
label: "物品清单",
default: "<table><tr><th>名称</th><th>数量</th></tr><tr><td>物品A</td><td>10</td></tr></table>"
}
}
```
### 示例 17:集合组
```javascript
{
key: "field_17",
value: "",
component_props: {
tag: "group",
name: "group_info",
label: "物品信息",
field_groups: [
{
tag: "input",
name: "item_name",
label: "物品名称",
field_name: "field_18",
group_field_name: "field_17",
placeholder: "请输入物品名称",
required: true
},
{
tag: "number",
name: "item_count",
label: "数量",
field_name: "field_19",
group_field_name: "field_17",
placeholder: "请输入数量",
required: true
}
]
}
}
```
### 示例 18:规则说明
```javascript
{
key: "field_20",
value: "",
component_props: {
tag: "rule",
name: "rule_info",
label: "活动规则",
default: "",
desc_text: "1. 活动时间:2024年3月1日-3月31日\n2. 参与资格:18岁以上\n3. 每人限参与一次",
desc_type: "text",
desc_btn_name: "查看完整规则"
}
}
```
### 示例 19:只读字段
```javascript
{
key: "field_21",
value: "系统自动生成",
component_props: {
tag: "input",
name: "readonly_field",
label: "申请编号",
readonly: true, // 只读
default: "系统自动生成"
}
}
```
### 示例 20:带提示的字段
```javascript
{
key: "field_22",
value: "",
component_props: {
tag: "input",
name: "username",
label: "用户名",
placeholder: "请输入用户名",
required: true,
note: "用户名长度为4-16个字符,支持字母、数字、下划线"
}
}
```
### 示例 21:带扫码的输入框
```javascript
{
key: "field_23",
value: "",
component_props: {
tag: "input",
name: "qr_code",
label: "二维码",
placeholder: "请输入或扫描二维码",
required: true,
is_camera_scan: true,
camera_scan_type: "QR_CODE" // ALL_CODE | QR_CODE | BAR_CODE
}
}
```
### 示例 22:分割线
```javascript
{
key: "field_24",
value: "",
component_props: {
tag: "divider",
name: "divider",
label: "分割线"
}
}
```
### 示例 23:富文本说明
```javascript
{
key: "field_25",
value: "",
component_props: {
tag: "note",
name: "rich_text",
label: "活动详情",
default: "<p>这是一段<strong>富文本</strong>内容</p>"
}
}
```
## 复杂表单完整示例
```javascript
const formConfig = [
// 基本信息
{
key: "field_name",
value: "",
component_props: {
tag: "name",
label: "姓名",
required: true,
placeholder: "请输入姓名"
}
},
{
key: "field_gender",
value: "",
component_props: {
tag: "gender",
label: "性别",
required: true
}
},
{
key: "field_phone",
value: "",
component_props: {
tag: "phone",
label: "手机号",
required: true,
placeholder: "请输入手机号"
}
},
// 报名信息
{
key: "field_type",
value: "",
component_props: {
tag: "radio",
label: "报名类型",
required: true,
direction: "vertical",
options: [
{ title: "个人报名", value: "personal", checked: true },
{ title: "团队报名", value: "team" },
{
title: "其他",
value: "other",
is_input: true,
input_placeholder: "请说明具体类型"
}
]
}
},
// 附加信息
{
key: "field_hobbies",
value: [],
component_props: {
tag: "checkbox",
label: "兴趣爱好",
direction: "vertical",
options: [
{ title: "运动", value: "sport" },
{ title: "阅读", value: "reading" },
{ title: "音乐", value: "music" }
]
}
},
// 时间选择
{
key: "field_date",
value: "",
component_props: {
tag: "date",
label: "活动日期",
required: true,
placeholder: "请选择日期"
}
},
// 图片上传
{
key: "field_photo",
value: [],
component_props: {
tag: "image_uploader",
label: "上传照片",
required: true,
max_count: 3,
max_size: 5
}
},
// 说明文字
{
key: "field_note",
value: "",
component_props: {
tag: "note",
label: "注意事项",
default: "<p>请确保所填信息真实有效</p>"
}
},
// 电子签名
{
key: "field_sign",
value: "",
component_props: {
tag: "sign",
label: "本人签名",
required: true
}
}
]
```
## 数据提交格式
### 提交到后端的格式
```javascript
{
form_code: "form_001",
data: {
field_name: "张三",
field_gender: "男",
field_phone: "13800138000",
field_type: {
key: "field_type",
value: "personal",
type: "radio"
},
field_hobbies: {
key: "field_hobbies",
value: ["sport", "music"],
type: "checkbox"
},
field_date: "2024-03-15",
field_photo: {
key: "field_photo",
value: [
{ url: "https://...", name: "photo1.jpg" }
],
type: "image_uploader"
},
field_sign: {
key: "field_sign",
value: "data:image/png;base64,...",
type: "sign"
}
}
}
```
## LangChain Agent 使用的提示词模板
```javascript
const FORM_GENERATION_PROMPT = `
你是一个表单配置生成专家。根据用户的自然语言描述,生成符合以下规范的表单字段配置。
## 组件类型映射
用户描述 → 组件类型:
- "姓名/名字" → name
- "性别" → gender
- "手机号/电话" → phone
- "邮箱" → email
- "身份证" → id_card
- "单选/单项选择" → radio
- "多选/多项选择" → checkbox
- "下拉/选择" → select
- "日期" → date
- "时间" → time
- "地址/省市区" → address
- "图片上传" → image_uploader
- "文件上传" → file_uploader
- "多行文本/描述/简介" → textarea
- "数字" → number
- "评分/打分" → rate
- "签名/电子签名" → sign
- "富文本/说明" → note
- "分割线" → divider
## 必填属性
- "必填/必须/一定要" → required: true
- "可选/非必须" → required: false
## 配置模板
### 文本输入
{
key: "field_{index}",
value: "",
component_props: {
tag: "input",
name: "{field_name}",
label: "{显示名称}",
placeholder: "请输入{显示名称}",
required: {是否必填}
}
}
### 单选/多选
{
key: "field_{index}",
value: "",
component_props: {
tag: "{radio|checkbox}",
name: "{field_name}",
label: "{显示名称}",
required: {是否必填},
direction: "vertical",
options: [
{ title: "{选项1}", value: "{value1}" },
{ title: "{选项2}", value: "{value2}" }
]
}
}
### 图片上传
{
key: "field_{index}",
value: [],
component_props: {
tag: "image_uploader",
name: "{field_name}",
label: "{显示名称}",
required: {是否必填},
max_count: {数量},
max_size: {大小MB}
}
}
请根据用户需求生成对应的表单配置JSON。
`;
```
# LangChain Agent 使用指南
## 概述
本文档为使用 LangChain 构建自然语言生成表单的 Agent 提供参考数据和配置指南。
## Agent 任务定义
**任务**:将用户的自然语言描述转换为表单字段配置 JSON
**输入**:自然语言描述
**输出**:表单字段配置数组
## 自然语言到组件映射
### 基础输入类
| 用户关键词 | 组件类型 | tag | 配置要点 |
|-----------|----------|-----|----------|
| 姓名、名字 | NameField | `name` | 必填通常为 true |
| 性别 | GenderField | `gender` | 选项:男/女 |
| 手机号、电话 | PhoneField | `phone` | 自动验证11位 |
| 邮箱 | EmailField | `email` | 自动验证格式 |
| 身份证 | IdentityField | `id_card` | 自动验证格式 |
| 数字、数量 | NumberField | `number` | 整数类型 |
| 单行文本、输入 | TextField | `input` | 最多255字符 |
| 多行文本、描述 | TextareaField | `textarea` | 支持自动高度 |
### 选择类
| 用户关键词 | 组件类型 | tag | 数据结构 |
|-----------|----------|-----|----------|
| 单选、单项选择 | RadioField | `radio` | options 数组 |
| 多选、多项选择 | CheckboxField | `checkbox` | options 数组 |
| 下拉、选择 | PickerField | `select` | options 数组 |
| 省、市、区、地址 | AreaPickerField | `address` | 三级联动 |
### 日期时间类
| 用户关键词 | 组件类型 | tag | 备注 |
|-----------|----------|-----|------|
| 日期、出生日期 | DatePickerField | `date` | - |
| 时间 | TimePickerField | `time` | - |
| 日期时间、开始时间 | DateTimePickerField | `datetime` | - |
| 日历 | CalendarField | `calendar` | 日历形式 |
### 上传类
| 用户关键词 | 组件类型 | tag | 配置参数 |
|-----------|----------|-----|----------|
| 图片、照片、上传图 | ImageUploaderField | `image_uploader` | max_count, max_size |
| 文件、附件、上传 | FileUploaderField | `file_uploader` | max_count, max_size |
### 特殊功能类
| 用户关键词 | 组件类型 | tag | 备注 |
|-----------|----------|-----|------|
| 签名、签字、电子签名 | SignField | `sign` | 手写签名板 |
| 评分、打分、星级 | RatePickerField | `rate` | 支持 x_score 显示 |
| 预约、时间段 | AppointmentField | `appointment` | 复杂配置 |
| 说明、富文本 | NoteField | `note` | HTML 内容 |
| 分割线、分隔 | DividerField | `divider` | - |
| 跑马灯、公告 | MarqueeField | `marquee` | 滚动文字 |
| 规则、说明 | RuleField | `rule` | 支持弹窗 |
| 按钮 | ButtonField | `button` | 自定义按钮 |
### 高级类
| 用户关键词 | 组件类型 | tag | 备注 |
|-----------|----------|-----|------|
| 表格、清单 | TableField | `table_editor` | 动态表格 |
| 分组、集合 | GroupField | `group` | field_groups 数组 |
| 树形选择、组织 | OrgPickerField | `org_picker` | 树结构 |
| 组别、义工组 | VolunteerGroupField | `volunteer_group` | 义工组选择 |
## 必填识别
### 强必填关键词
- 必填、必须、一定要、强制
- 不可缺少、不能为空
- 必须提供、务必填写
### 可选关键词
- 可选、非必须、非强制
- 选填、可以不填
- 如果有、尽量填写
### 默认规则
- 姓名通常必填
- 手机号通常必填
- 附件类通常选填
- 说明文字通常选填
## 数量识别
### 图片上传数量
- "一张图"、"1张" → max_count: 1
- "三张图"、"3张" → max_count: 3
- "最多5张" → max_count: 5
- "多张"、"若干" → max_count: 9(默认)
### 文件大小限制
- "5MB以内"、"小于5M" → max_size: 5
- "10MB" → max_size: 10
## 选项提取
### 单选/多选选项提取
**用户输入**:"性别:男、女、其他"
**提取结果**
```javascript
options: [
{ title: "男", value: "男" },
{ title: "女", value: "女" },
{ title: "其他", value: "其他" }
]
```
### 带描述的选项
**用户输入**:"同意(详见规则)、不同意"
**提取结果**
```javascript
options: [
{
title: "同意",
value: "agree",
desc_text: "点击查看详细规则",
desc_type: "text",
desc_btn_name: "详见规则"
},
{
title: "不同意",
value: "disagree"
}
]
```
### 带补充输入的选项
**用户输入**:"其他(需说明)"
**提取结果**
```javascript
options: [
{
title: "其他",
value: "other",
is_input: true,
input_required: true,
input_placeholder: "请说明具体情况"
}
]
```
## 复杂需求处理
### 分组需求
**用户输入**:"物品信息(包含物品名称和数量)"
**处理方式**
1. 识别为 group 类型
2. 创建 field_groups 数组
3. 每个子项作为独立字段
```javascript
{
key: "field_1",
value: "",
component_props: {
tag: "group",
label: "物品信息",
field_groups: [
{
tag: "input",
label: "物品名称",
field_name: "field_1_1",
group_field_name: "field_1"
},
{
tag: "number",
label: "数量",
field_name: "field_1_2",
group_field_name: "field_1"
}
]
}
}
```
### 选项依赖
**用户输入**:"选择'其他'时需要输入补充信息"
**处理方式**
- 在对应选项设置 `is_input: true`
- 设置 `input_required` 根据上下文判断
### 提示信息
**用户输入**:"用户名(4-16个字符,字母数字)"
**处理方式**
- label: "用户名"
- note: "4-16个字符,支持字母、数字、下划线"
## Prompt 模板
### 系统提示词
```python
FORM_BUILDER_SYSTEM_PROMPT = """
你是一个表单配置生成专家。你的任务是将用户的自然语言描述转换为符合规范的表单字段配置JSON。
## 输出格式
返回一个JSON数组,每个元素代表一个表单字段。
## 字段结构
每个字段必须包含:
- key: 字段唯一标识(格式:field_序号)
- value: 初始值
- component_props: 组件属性对象
- tag: 组件类型
- label: 显示名称
- required: 是否必填
- 其他属性根据组件类型而定
## 组件类型选择规则
根据用户描述选择最合适的组件类型:
- 文本输入:input(单行)、textarea(多行)、number(数字)
- 选择类:radio(单选)、checkbox(多选)、select(下拉)
- 日期时间:date、time、datetime
- 上传类:image_uploader、file_uploader
- 特殊:name、gender、phone、email、id_card、sign、rate等
## 选项提取规则
当用户列出选项时:
1. 识别是单选还是多选
2. 提取每个选项的标题和值
3. 检测是否有补充信息需求
4. 检测是否有描述信息
## 必填识别规则
- "必填、必须、一定要" → required: true
- "可选、选填" → required: false
- 姓名、手机号等基础信息通常必填
- 说明、附件类通常选填
请根据用户输入生成相应的表单配置。
"""
```
### 用户输入示例
```python
# 示例1:简单表单
user_input = "创建一个报名表单,包含姓名(必填)、性别(必填,男/女)、手机号(必填)"
# 示例2:带选项
user_input = "报名类型,单选,必填,选项:个人报名、团队报名"
# 示例3:图片上传
user_input = "上传证件照,最多3张,每张不超过5MB,必填"
# 示例4:分组
user_input = "物品清单,包含物品名称(必填)和数量(必填)"
# 示例5:复杂需求
user_input = "活动报名表,包含:姓名(必填)、性别(男/女/其他,其他需说明)、手机号(必填)、兴趣爱好(多选:运动、阅读、音乐、旅游)、活动日期(必填)、上传照片(最多3张)、本人签名(必填)"
```
## LangChain 工具调用
### 推荐使用 LangChain 的工具
1. **Structured Output** - 确保输出格式正确
2. **Few-shot Prompting** - 提供示例
3. **Output Parser** - 解析 JSON 输出
### 代码示例
```python
from langchain.output_parsers import PydanticOutputParser
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field
from typing import List, Optional
class FormField(BaseModel):
key: str = Field(description="字段唯一标识")
tag: str = Field(description="组件类型")
label: str = Field(description="显示名称")
required: bool = Field(description="是否必填")
placeholder: Optional[str] = Field(default="", description="占位符")
options: Optional[List[dict]] = Field(default=None, description="选项列表")
max_count: Optional[int] = Field(default=None, description="最大上传数量")
max_size: Optional[int] = Field(default=None, description="最大文件大小")
class FormConfiguration(BaseModel):
fields: List[FormField] = Field(description="表单字段列表")
# 创建解析器
parser = PydanticOutputParser(pydantic_object=FormConfiguration)
# 创建提示模板
prompt = ChatPromptTemplate.from_messages([
("system", FORM_BUILDER_SYSTEM_PROMPT),
("user", "{user_input}")
])
# 创建链
chain = prompt | llm | parser
# 调用
result = chain.invoke({"user_input": "创建一个用户信息表单..."})
```
## 验证和错误处理
### 输出验证
生成的 JSON 需要验证:
1. **结构验证**
- 是否是有效的 JSON 数组
- 每个字段是否包含必需属性
2. **类型验证**
- tag 值是否在支持的组件列表中
- required 是否为布尔值
- options 是否为数组
3. **业务验证**
- 必填字段是否合理
- 选项是否为空
- 数量限制是否合理
### 常见错误处理
| 错误 | 处理方式 |
|------|----------|
| 无法识别组件类型 | 询问用户具体需求 |
| 选项描述不清晰 | 提供选项模板让用户选择 |
| 必填不明确 | 默认为选填,提示用户确认 |
| 数量限制缺失 | 使用默认值(图片:3,文件:5) |
## 完整工作流程
```
用户输入
意图识别(新增/修改/查询)
实体提取(字段名、组件类型、选项)
配置生成(生成 component_props)
格式验证(JSON 结构、类型检查)
结果输出(表单配置 JSON)
```
## 最佳实践
1. **逐步确认**:复杂需求分步确认,而非一次性生成
2. **提供示例**:让用户选择最接近的示例
3. **默认值策略**:不确定时使用保守的默认值
4. **错误友好**:错误信息要具体指出问题和解决方案
# 规则控制系统
> **最后更新**: 2026-03-16
> **核心文件**: `src/views/index.vue`
## 📋 概述
规则控制系统通过动态配置来实现表单字段的显示/隐藏逻辑,是表单系统的核心功能之一。
### 核心特性
-**双模式控制**: 支持 SHOW(显示)和 HIDE(隐藏)两种规则模式
-**逻辑运算**: 支持 AND(且)和 OR(或)逻辑操作符
-**级联隐藏**: 控制字段被隐藏时,其控制的所有字段也会被隐藏
-**多规则支持**: 单个字段可以同时受多条规则控制
-**优先级机制**: HIDE 规则优先级高于 SHOW 规则
---
## 🏗️ 数据结构
### rule_list(规则列表)
规则列表位于 `formInfo.value['rule_list']`,是表单级别配置。
```typescript
interface Rule {
field_names: string[]; // 受此规则控制的字段名列表
mode: 'SHOW' | 'HIDE'; // 规则模式:显示或隐藏
logical_op: 'AND' | 'OR'; // 逻辑操作符
expr_list: RuleExpr[]; // 规则表达式列表
is_invalid?: boolean; // 规则是否无效(可选)
}
interface RuleExpr {
field_name: string; // 控制字段名
values: string[]; // 匹配值列表
}
```
### 规则流程图
```
┌─────────────────────────────────────────────────────────────┐
│ 规则控制系统架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ formInfo.rule_list │
│ ↓ │
│ ┌─────────────────────────────────────────────┐ │
│ │ checkRules() - 规则评估入口 │ │
│ └─────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────┐ │
│ │ 1. 收集规则涉及的所有字段 │ │
│ │ 2. 初始化字段状态(disabled=false) │ │
│ │ 3. 为每个字段分配规则(x_rules) │ │
│ │ 4. 合并重复规则 │ │
│ │ 5. 评估规则并设置 disabled 状态 │ │
│ └─────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────┐ │
│ │ evaluateMultipleRules() - 多规则评估 │ │
│ │ ↓ │ │
│ │ 分离 SHOW/HIDE 规则 │ │
│ │ ↓ │ │
│ │ SHOW 规则: any 满足 = 显示 │ │
│ │ HIDE 规则: any 满足 = 隐藏 │ │
│ │ ↓ │ │
│ │ HIDE 优先 → 隐藏 │ │
│ │ 否则 → 根据 SHOW 规则决定 │ │
│ └─────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────┐ │
│ │ handleCascadeHiding() - 级联隐藏 │ │
│ │ 如果控制字段被隐藏,其控制的所有字段 │ │
│ │ 也会被隐藏 │ │
│ └─────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
```
---
## 🔧 核心函数
### 1. checkRules()
规则评估的主入口函数,负责初始化和协调整个规则评估流程。
```javascript
const checkRules = () => {
const rule_list = formInfo.value['rule_list'] ? [...formInfo.value['rule_list']] : [];
// 1. 收集所有规则中涉及的字段
const fieldsInRules = new Set();
rule_list.forEach(rule => {
if (rule.field_names && Array.isArray(rule.field_names)) {
rule.field_names.forEach(fieldName => {
fieldsInRules.add(fieldName);
});
}
});
// 2. 初始化字段规则,只重置在规则中出现过的字段
formData.value.forEach(item => {
item.x_rules = [];
if (fieldsInRules.has(item.key) && item.component_props) {
item.component_props.disabled = false;
}
});
// 3. 收集每个字段的规则
rule_list.forEach(rule => {
formData.value.forEach(item => {
if (rule.field_names?.includes(item.key) && !rule.is_invalid) {
item.x_rules.push({
mode: rule.mode,
logical_op: rule.logical_op,
expr_list: rule.expr_list,
});
}
});
});
// 4. 合并规则
formData.value.forEach(item => {
const mergedRules = mergeAndDeduplicate(item.x_rules);
item.field_rules = mergedRules;
});
// 5. 处理规则逻辑 - 支持多条规则
formData.value.forEach(item => {
if (item.field_rules && item.field_rules.length > 0 && item.component_props) {
const finalDisabledState = evaluateMultipleRules(item.field_rules);
item.component_props.disabled = finalDisabledState;
}
});
// 6. 处理级联隐藏
handleCascadeHiding();
};
```
### 2. evaluateMultipleRules()
评估字段的所有规则,确定最终的显示/隐藏状态。
**核心逻辑**:
- SHOW 规则:任一满足即显示(some)
- HIDE 规则:任一满足即隐藏(some)
- HIDE 规则优先级更高
```javascript
const evaluateMultipleRules = (rulesList) => {
if (!rulesList || rulesList.length === 0) {
return false; // 没有规则时默认显示
}
let showRules = [];
let hideRules = [];
// 分离SHOW和HIDE规则
rulesList.forEach(rule => {
if (rule.mode === 'SHOW') {
showRules.push(rule);
} else if (rule.mode === 'HIDE') {
hideRules.push(rule);
}
});
// 评估SHOW规则
let showResult = true; // 默认显示
if (showRules.length > 0) {
// 如果有SHOW规则,需要至少一个SHOW规则条件满足才显示
showResult = showRules.some(rule => evaluateRuleCondition(rule));
}
// 评估HIDE规则
let hideResult = false; // 默认不隐藏
if (hideRules.length > 0) {
// 如果有HIDE规则,任何一个HIDE规则条件满足就隐藏
hideResult = hideRules.some(rule => evaluateRuleCondition(rule));
}
// 最终逻辑:HIDE规则优先级更高
if (hideResult) {
return true; // 隐藏
} else {
return !showResult; // SHOW规则不满足时隐藏
}
};
```
### 3. evaluateRuleCondition()
评估单条规则的条件是否满足。
**处理逻辑**:
1. 遍历规则表达式列表
2.`postData.value` 获取表单提交值
3. 处理字符串类型(单选、下拉):清理冒号前缀后匹配
4. 处理数组类型(多选):使用 lodash intersection 取交集
5. 根据逻辑操作符(AND/OR)计算最终结果
```javascript
const evaluateRuleCondition = (fieldRules) => {
if (!fieldRules || !fieldRules.expr_list || fieldRules.expr_list.length === 0) {
return false;
}
const results = [];
fieldRules.expr_list.forEach(expr => {
let form_submission_value = postData.value[expr.field_name];
const rule_matching_value = expr.values || [];
// 处理空值情况
if (form_submission_value === null || form_submission_value === undefined) {
results.push(false);
return;
}
let matchResult = false;
if (typeof form_submission_value === 'string') {
// 处理字符串类型(单选,下拉)
let cleanValue = form_submission_value;
if (form_submission_value.indexOf(':') !== -1) {
cleanValue = form_submission_value.split(':')[0];
}
matchResult = rule_matching_value.includes(cleanValue);
} else if (Array.isArray(form_submission_value)) {
// 处理数组类型(多选)
const cleanValues = form_submission_value.map(item => {
if (typeof item === 'string' && item.includes(':')) {
return item.split(':')[0].trim();
}
return item;
});
matchResult = _.intersection(rule_matching_value, cleanValues).length > 0;
}
results.push(matchResult);
});
// 根据逻辑操作符计算最终结果
if (fieldRules.logical_op === 'AND') {
return results.every(result => result === true);
} else { // OR
return results.some(result => result === true);
}
};
```
### 4. handleCascadeHiding()
处理级联隐藏逻辑,确保当控制字段被隐藏时,其控制的所有字段也会被隐藏。
```javascript
const handleCascadeHiding = () => {
const rule_list = formInfo.value['rule_list'] || [];
// 获取所有规则控制字段的映射
const ruleControlMap = new Map();
rule_list.forEach(rule => {
if (rule.expr_list && rule.expr_list.length > 0) {
const controlField = rule.expr_list[0].field_name;
if (!ruleControlMap.has(controlField)) {
ruleControlMap.set(controlField, []);
}
ruleControlMap.get(controlField).push({
field_names: rule.field_names || [],
mode: rule.mode
});
}
});
// 检查级联隐藏
formData.value.forEach(item => {
if (ruleControlMap.has(item.key) && item.component_props && item.component_props.disabled) {
// 如果控制字段被隐藏,则隐藏其控制的所有字段
const controlledRules = ruleControlMap.get(item.key);
controlledRules.forEach(rule => {
rule.field_names.forEach(fieldName => {
const targetField = formData.value.find(field => field.key === fieldName);
if (targetField && targetField.component_props) {
targetField.component_props.disabled = true;
}
});
});
}
});
};
```
---
## 🔄 触发机制
规则评估在以下时机触发:
### 1. 表单初始化时
表单数据加载完成后,调用 `checkRules()` 初始化所有字段的显示状态。
### 2. 字段值变化时
当用户修改表单字段值时,通过 `@active` 事件触发规则重新评估:
```vue
<component
v-for="item in formData"
:is="item.component_props.tag"
v-model="postData[item.key]"
@active="checkRules"
/>
```
### 3. 数据结构
- **formData**: 表单字段配置数组
- **postData**: 表单实际提交的数据
- **formInfo**: 表单元数据(包含 rule_list)
---
## 📊 实际示例
### 示例 1:简单 SHOW 规则
**场景**:只有当"用户类型"选择"企业用户"时,才显示"企业名称"字段。
```json
{
"rule_list": [
{
"field_names": ["company_name"],
"mode": "SHOW",
"logical_op": "OR",
"expr_list": [
{
"field_name": "user_type",
"values": ["enterprise"]
}
]
}
]
}
```
### 示例 2:HIDE 规则
**场景**:当"居住类型"选择"租房"时,隐藏"房产证号"字段。
```json
{
"rule_list": [
{
"field_names": ["property_cert_no"],
"mode": "HIDE",
"logical_op": "OR",
"expr_list": [
{
"field_name": "residence_type",
"values": ["rent"]
}
]
}
]
}
```
### 示例 3:AND 逻辑
**场景**:同时满足"年龄大于18"且"有收入证明"时,显示"信用卡申请"字段。
```json
{
"rule_list": [
{
"field_names": ["credit_card_application"],
"mode": "SHOW",
"logical_op": "AND",
"expr_list": [
{
"field_name": "age",
"values": ["adult", "senior"]
},
{
"field_name": "income_proof",
"values": ["yes"]
}
]
}
]
}
```
### 示例 4:OR 逻辑
**场景**:选择"VIP用户"或"企业用户"任一条件时,显示"专属客服"字段。
```json
{
"rule_list": [
{
"field_names": ["exclusive_service"],
"mode": "SHOW",
"logical_op": "OR",
"expr_list": [
{
"field_name": "user_type",
"values": ["vip"]
},
{
"field_name": "user_type",
"values": ["enterprise"]
}
]
}
]
}
```
### 示例 5:多规则控制
**场景**:字段受多条规则控制,HIDE 规则优先。
```json
{
"rule_list": [
{
"field_names": ["special_discount"],
"mode": "SHOW",
"logical_op": "OR",
"expr_list": [
{
"field_name": "membership_level",
"values": ["gold", "platinum"]
}
]
},
{
"field_names": ["special_discount"],
"mode": "HIDE",
"logical_op": "OR",
"expr_list": [
{
"field_name": "account_status",
"values": ["suspended", "banned"]
}
]
}
]
}
```
**结果**:即使满足 VIP 条件,如果账户被暂停,也不会显示特殊折扣字段。
### 示例 6:级联隐藏
**场景**
- 字段 A 控制字段 B 的显示
- 字段 B 控制字段 C 的显示
- 当字段 A 被隐藏时,字段 B 和 C 都应该被隐藏
```json
{
"rule_list": [
{
"field_names": ["field_b"],
"mode": "SHOW",
"logical_op": "OR",
"expr_list": [
{
"field_name": "field_a",
"values": ["show_b"]
}
]
},
{
"field_names": ["field_c"],
"mode": "SHOW",
"logical_op": "OR",
"expr_list": [
{
"field_name": "field_b",
"values": ["show_c"]
}
]
}
]
}
```
---
## 🎯 LangChain Agent 集成要点
### 自然语言到规则的映射
当用户用自然语言描述规则时,Agent 需要将其转换为规则配置:
| 用户描述 | mode | logical_op |
|---------|------|------------|
| "当...时显示" | SHOW | OR |
| "只有...才显示" | SHOW | AND |
| "当...时隐藏" | HIDE | OR |
| "只要...就隐藏" | HIDE | OR |
### Prompt 模板
```python
RULE_GENERATION_TEMPLATE = """
你是一个表单规则配置专家。根据用户的自然语言描述,生成规则配置。
用户描述:{user_description}
可用的字段:
{available_fields}
请生成规则配置,格式如下:
```json
{{
"rule_list": [
{{
"field_names": ["受控制的字段名"],
"mode": "SHOW" | "HIDE",
"logical_op": "AND" | "OR",
"expr_list": [
{{
"field_name": "控制字段名",
"values": ["值1", "值2"]
}}
]
}}
]
}}
```
规则说明:
1. mode: "SHOW" 表示满足条件时显示,"HIDE" 表示满足条件时隐藏
2. logical_op: "AND" 表示所有条件都要满足,"OR" 表示任一条件满足即可
3. HIDE 规则优先级高于 SHOW 规则
"""
```
### 示例对话
**用户输入**
```
"当用户类型是企业时,显示企业名称和统一社会信用代码字段"
```
**Agent 输出**
```json
{
"rule_list": [
{
"field_names": ["company_name", "credit_code"],
"mode": "SHOW",
"logical_op": "OR",
"expr_list": [
{
"field_name": "user_type",
"values": ["enterprise", "company"]
}
]
}
]
}
```
---
## ⚠️ 注意事项
### 1. 值格式处理
系统会自动处理带冒号的值(如 `"option1:选项1"`),只匹配冒号前的部分。
### 2. 空值处理
当控制字段的值为 `null``undefined` 时,规则匹配结果为 `false`
### 3. 多选字段
多选字段(checkbox)的值是数组,使用 lodash `intersection` 检查是否有交集。
### 4. 规则优先级
- HIDE 规则优先级高于 SHOW 规则
- 同类型规则之间使用 OR 逻辑(任一满足即可)
### 5. 性能考虑
- 每次字段值变化都会触发所有规则的重新评估
- 对于复杂表单,建议优化规则数量和复杂度
---
## 🔗 相关文档
- [00-数据结构总览.md](./00-数据结构总览.md)
- [02-component_props-配置规范.md](./02-component_props-配置规范.md)
- [05-LangChain-Agent-使用指南.md](./05-LangChain-Agent-使用指南.md)
# 页面数据提取指南
> **最后更新**: 2026-03-16
> **用途**: 从实际运行的表单页面中提取配置数据
## 📋 概述
当用户提供一个表单 URL(如 `https://oa-dev.onwall.cn/f/custom_form/front/index.html#/?code=nxqkbf`)时,需要从页面中提取完整的表单配置数据。
---
## 🏗️ 数据存储结构
### Pinia Store
表单数据存储在 Pinia store 中:
```javascript
// Store 名称: 'main'
// Store 定义: src/store/index.js
{
formInfo: {}, // 表单完整信息(包含字段列表、规则等)
formSetting: {}, // 表单数据收集设置
successInfo: {}, // 表单提交返回值
}
```
### formInfo 数据结构
```typescript
interface FormInfo {
name: string; // 表单名称
field_list: FieldItem[]; // 字段列表
rule_list?: Rule[]; // 规则列表(可选)
// ... 其他属性
}
interface FieldItem {
tag: string; // 组件类型
field_name: string; // 字段名
label: string; // 显示标签
required: boolean; // 是否必填
data_type: string; // 数据类型
default?: any; // 默认值
options?: Option[]; // 选项列表(选择类组件)
disabled?: boolean; // 是否禁用
readonly?: boolean; // 是否只读
placeholder?: string; // 占位符
// ... 其他属性
}
```
---
## 🌐 API 数据结构详解
### 核心 API 接口
表单系统有两个核心 API 接口,分别获取不同维度的数据:
| API 接口 | 获取内容 | 主要用途 |
|---------|---------|----------|
| `query_form_all_field` | 字段列表、规则列表 | 渲染表单结构 |
| `query_form_setting` | 表单级配置 | 获取表单属性 |
### API 1: query_form_all_field - 字段和规则
**请求**
```bash
GET https://oa-dev.onwall.cn/srv/?a=query_form_all_field&f=custom_form&form_code=nxqkbf
```
**响应结构**
```json
{
"code": 1,
"msg": "OK",
"data": {
"id": 835950,
"code": "nxqkbf",
"name": "测试LangChain",
"short_name": "customize_35697_nxqkbf",
"table_name": "customize_35697_nxqkbf",
"max_field_num": 3,
"description": null,
"rule_list": [],
"field_list": [...]
},
"flow_process_list": null
}
```
**field_list 字段类型详解**
```typescript
// 1. 页面头部 (page_header)
{
tag: "page_header",
field_name: "object_1",
label: "测试LangChain",
index: 0,
banner: {
ext: "png",
src: "https://cdn.ipadbiz.cn/...",
name: ""
},
banner_type: "image",
interaction_type: "h5show" // 仅展示,不可编辑
}
// 2. 输入框 (input)
{
tag: "input",
field_name: "field_2",
label: "标题",
index: 2,
required: false,
data_type: "text",
placeholder: "请输入",
disabled: false,
readonly: false,
default: "",
unique: false,
interaction_type: "h5edit" // 可编辑
}
// 3. 提交按钮 (page_commit)
{
tag: "page_commit",
field_name: "object_3",
text: "提交",
index: 1,
is_back: false,
back_title: "上一页",
interaction_type: "h5show"
}
```
### API 2: query_form_setting - 表单配置
**请求**
```bash
GET https://oa-dev.onwall.cn/srv/?a=query_form_setting&f=custom_form&form_code=nxqkbf
```
**响应结构**
```json
{
"code": 1,
"msg": "OK",
"data": [{
"id": 835950,
"code": "nxqkbf",
"name": "测试LangChain",
"max_field_num": 3,
"data_count": 7,
"client_id": 35697,
"extend": {
"server_time": "2026-03-16 17:15:40",
"is_back_user": false
},
"property_list": {
"sjsj_enable": 1,
"commit_action": "text",
"commit_text_type": "default",
"commit_text_template": "提交成功",
"edit_commit_action": "text",
"edit_commit_text_type": "default",
"edit_commit_text_template": "提交成功"
}
}]
}
```
**property_list 详解**
| 属性 | 类型 | 说明 |
|------|------|------|
| `sjsj_enable` | number | 是否启用数据收集(0=关闭,1=开启) |
| `commit_action` | string | 提交动作类型(text=显示文本) |
| `commit_text_template` | string | 提交成功后显示的文本 |
| `edit_commit_action` | string | 编辑提交动作 |
| `edit_commit_text_template` | string | 编辑提交成功文本 |
### 完整数据关系图
```
┌─────────────────────────────────────────────────────────────┐
│ 表单数据完整结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 表单 URL │
│ https://oa-dev.onwall.cn/f/custom_form/front/#/?code=xxx │
│ ↓ │
│ 提取 form_code │
│ ───────────────────────────────────────────────────────── │
│ ↓ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ API 1: query_form_all_field │ │
│ │ → 字段列表 (field_list) │ │
│ │ → 规则列表 (rule_list) │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ API 2: query_form_setting │ │
│ │ → 表单配置 (property_list) │ │
│ │ → 扩展信息 (extend) │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↓ │
│ 合并数据 → LangChain Agent 可用的完整表单配置 │
│ │
└─────────────────────────────────────────────────────────────┘
```
---
## 🔧 数据提取方法
### 方法 1: 直接 API 调用(推荐)
**核心原理**:直接调用后端 API 接口获取表单配置数据
**API 端点**
```
GET https://oa-dev.onwall.cn/srv/?a=query_form_all_field
```
**请求参数**
```javascript
{
f: "custom_form", // 固定参数
form_code: "nxqkbf", // 从 URL 参数中获取(必填)
page_type: "add", // 页面类型:add/edit/view(可选)
data_id: null, // 数据ID(编辑时使用)
flow_node_code: "", // 流程节点代码(流程表单使用)
force_back: "" // 强制后台模式标识
}
```
**✅ 重要**:此 API **不需要特殊认证**,可以直接通过 curl 或 HTTP 请求调用!
**调用方式**
```bash
# 使用 curl 直接调用
curl "https://oa-dev.onwall.cn/srv/?a=query_form_all_field&f=custom_form&form_code=nxqkbf"
```
```javascript
// 使用 fetch/axios
const response = await fetch('https://oa-dev.onwall.cn/srv/?a=query_form_all_field&f=custom_form&form_code=nxqkbf');
const data = await response.json();
// 或使用项目内部的 API 函数
import { queryFormAPI } from '@/api/form';
const { data } = await queryFormAPI({ form_code: 'nxqkbf' });
```
**完整 API 响应结构**
```json
{
"code": 1,
"msg": "OK",
"data": {
"id": 835950,
"code": "nxqkbf",
"name": "表单名称",
"field_list": [
{
"tag": "input",
"field_name": "field_1",
"label": "姓名",
"required": true,
"data_type": "text"
}
],
"rule_list": []
}
}
```
---
### 方法 2: Chrome DevTools MCP(需要登录)
**前提条件**:已使用浏览器登录系统
使用 Chrome DevTools MCP 工具直接从页面提取数据:
```javascript
// 在页面中执行以下脚本获取表单数据
const app = document.querySelector('#app').__vueParentComponent.appContext.app;
const pinia = app.config.globalProperties.$pinia;
const store = pinia.state.value.main;
// 获取表单信息
const formInfo = store.formInfo;
// 返回结果
JSON.stringify(formInfo, null, 2);
```
---
### 方法 3: Vue DevTools API(需要登录)
通过 Vue DevTools 获取组件状态:
```javascript
// 获取根组件
const rootComponent = document.querySelector('#app').__vueParentComponent;
// 获取 formInfo
const formInfo = rootComponent.ctx.formInfo;
// 返回结果
JSON.stringify(formInfo, null, 2);
```
---
## 📝 完整提取流程
### 方法 A: 直接 API 调用(需要登录态)
**适用场景**:在已登录环境下,需要批量获取表单配置
**步骤 1**: 解析 URL 获取 form_code
```javascript
// 从 URL 中提取 form_code
// URL: https://oa-dev.onwall.cn/f/custom_form/front/index.html#/?code=nxqkbf
const url = new URL('https://oa-dev.onwall.cn/f/custom_form/front/index.html');
const formCode = 'nxqkbf'; // 从 URL 参数 code 获取
```
**步骤 2**: 调用查询 API
```javascript
// 使用项目 API 函数
import { queryFormAPI } from '@/api/form';
async function getFormConfig(formCode) {
try {
const response = await queryFormAPI({
form_code: formCode,
page_type: 'add',
data_id: null,
flow_node_code: '',
force_back: ''
});
if (response && response.code === 1) {
return {
formName: response.data.name,
fieldList: response.data.field_list,
ruleList: response.data.rule_list || [],
bannerConfig: response.data.banner_config,
submitConfig: response.data.submit_config
};
}
} catch (error) {
console.error('获取表单配置失败:', error);
throw error;
}
}
```
**步骤 3**: 数据验证
```javascript
function validateFormConfig(data) {
const required = ['formName', 'fieldList'];
const missing = required.filter(key => !data[key]);
if (missing.length > 0) {
throw new Error(`缺少必要字段: ${missing.join(', ')}`);
}
if (!Array.isArray(data.fieldList) || data.fieldList.length === 0) {
throw new Error('字段列表为空或格式错误');
}
return true;
}
```
---
### 方法 B: 浏览器环境提取(Chrome DevTools)
**步骤 1**: 打开页面并登录
使用 Chrome DevTools MCP 打开 URL 并确保已登录:
```javascript
await mcp__chrome_devtools__navigate_page({
type: 'url',
url: 'https://oa-dev.onwall.cn/f/custom_form/front/index.html#/?code=nxqkbf',
timeout: 30000
});
```
**步骤 2**: 等待页面加载
等待数据加载完成:
```javascript
await mcp__chrome_devtools__wait_for({
text: '提交', // 等待提交按钮出现
timeout: 10000
});
```
**步骤 3**: 提取数据
执行脚本提取 formInfo:
```javascript
const result = await mcp__chrome_devtools__evaluate_script({
function: `() => {
try {
// 尝试从 Pinia store 获取
const app = document.querySelector('#app').__vueParentComponent?.appContext?.app;
if (app?.config?.globalProperties?.$pinia) {
const pinia = app.config.globalProperties.$pinia;
const store = pinia.state.value.main;
return {
success: true,
source: 'pinia',
data: store.formInfo
};
}
// 尝试从组件直接获取
const rootComponent = document.querySelector('#app').__vueParentComponent;
if (rootComponent?.ctx?.formInfo) {
return {
success: true,
source: 'component',
data: rootComponent.ctx.formInfo
};
}
return {
success: false,
error: '无法找到表单数据'
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}`
});
```
**步骤 4**: 解析数据
根据提取的数据,解析出:
1. **表单基本信息**: 表单名称、描述
2. **字段列表**: 所有字段的配置
3. **规则列表**: 字段显示/隐藏规则
4. **页眉配置**: banner、标题等
5. **提交配置**: 提交按钮配置
---
## 🎯 数据提取模板
```javascript
/**
* 从表单页面提取完整配置
*/
async function extractFormConfig(pageUrl) {
// 1. 打开页面
await mcp__chrome_devtools__navigate_page({
type: 'url',
url: pageUrl,
timeout: 30000
});
// 2. 等待页面加载
await mcp__chrome_devtools__wait_for({
text: '提交',
timeout: 10000
});
// 3. 提取数据
const result = await mcp__chrome_devtools__evaluate_script({
function: `() => {
const app = document.querySelector('#app').__vueParentComponent?.appContext?.app;
const pinia = app?.config?.globalProperties?.$pinia;
return pinia ? pinia.state.value.main.formInfo : null;
}`
});
// 4. 解析配置
if (result) {
return {
formName: result.name,
fieldList: result.field_list,
ruleList: result.rule_list || [],
metadata: {
extractedAt: new Date().toISOString(),
source: pageUrl
}
};
}
throw new Error('无法提取表单数据');
}
```
---
## 📊 真实 API 返回数据示例
### 测试表单: `nxqkbf`
**API 1: query_form_all_field 返回**
```json
{
"code": 1,
"msg": "OK",
"data": {
"id": 835950,
"code": "nxqkbf",
"name": "测试LangChain",
"short_name": "customize_35697_nxqkbf",
"table_name": "customize_35697_nxqkbf",
"max_field_num": 3,
"description": null,
"rule_list": [],
"field_list": [
{
"tag": "page_header",
"name": "page_header_0",
"index": 0,
"label": "测试LangChain",
"banner": {
"ext": "png",
"src": "https://cdn.ipadbiz.cn/space/FlBDc7PgmmN0fD4GdMW_xUCFgs5T.png"
},
"field_id": 835961,
"invisible": false,
"field_name": "object_1",
"banner_type": "image",
"interaction_type": "h5show"
},
{
"tag": "input",
"name": "input_2",
"index": 2,
"label": "标题",
"unique": false,
"default": "",
"disabled": false,
"field_id": 835962,
"readonly": false,
"required": false,
"data_type": "text",
"field_name": "field_2",
"is_encrypt": false,
"placeholder": "请输入",
"interaction_type": "h5edit"
},
{
"tag": "page_commit",
"name": "page_commit_1",
"text": "提交",
"index": 1,
"is_back": false,
"field_id": 835964,
"invisible": false,
"back_title": "上一页",
"field_name": "object_3",
"interaction_type": "h5show"
}
]
}
}
```
**API 2: query_form_setting 返回**
```json
{
"code": 1,
"msg": "OK",
"data": [{
"id": 835950,
"code": "nxqkbf",
"name": "测试LangChain",
"max_field_num": 3,
"data_count": 7,
"client_id": 35697,
"extend": {
"server_time": "2026-03-16 17:15:40",
"is_back_user": false
},
"property_list": {
"sjsj_enable": 1,
"commit_action": "text",
"commit_text_type": "default",
"commit_text_template": "提交成功",
"edit_commit_action": "text",
"edit_commit_text_type": "default",
"edit_commit_text_template": "提交成功"
}
}]
}
```
### 数据解析
从以上真实数据可以得出:
| 字段类型 | tag | field_name | 说明 |
|---------|-----|------------|------|
| 页面头部 | page_header | object_1 | 显示 banner 和标题 |
| 输入框 | input | field_2 | 用户可编辑的输入字段 |
| 提交按钮 | page_commit | object_3 | 表单提交按钮 |
**关键字段说明**
- `interaction_type: "h5show"` - 仅展示,不可编辑(如 banner、提交按钮)
- `interaction_type: "h5edit"` - 可编辑(如输入框)
- `field_name` - 数据提交时的字段名
- `required` - 是否必填
---
## 🎯 数据提取示例
### 输入 URL
```
https://oa-dev.onwall.cn/f/custom_form/front/index.html#/?code=nxqkbf
```
### 提取的数据结构
```json
{
"name": "用户信息采集表",
"field_list": [
{
"tag": "input",
"field_name": "field_1",
"label": "姓名",
"required": true,
"data_type": "text",
"placeholder": "请输入姓名",
"disabled": false,
"readonly": false
},
{
"tag": "gender",
"field_name": "field_2",
"label": "性别",
"required": false,
"data_type": "text",
"options": [
{ "title": "男", "value": "男" },
{ "title": "女", "value": "女" }
]
}
],
"rule_list": [
{
"field_names": ["field_3"],
"mode": "SHOW",
"logical_op": "OR",
"expr_list": [
{
"field_name": "field_1",
"values": ["VIP用户"]
}
]
}
]
}
```
---
## 🔄 数据转换
### 将页面数据转换为标准格式
提取的数据需要转换为 LangChain Agent 可理解的标准格式:
```javascript
function convertToStandardFormat(extractedData) {
return {
formName: extractedData.name,
fields: extractedData.field_list.map(field => ({
key: field.field_name,
component_props: {
tag: field.tag,
label: field.label,
required: field.required,
placeholder: field.placeholder || '',
options: field.options || [],
disabled: field.disabled || false,
readonly: field.readonly || false
}
})),
rules: extractedData.rule_list || []
};
}
```
---
## ⚠️ 注意事项
### 1. API 访问说明
**表单查询 API 可以直接访问,无需特殊认证!**
```bash
# 最简单的调用方式
curl "https://oa-dev.onwall.cn/srv/?a=query_form_all_field&f=custom_form&form_code=nxqkbf"
```
**完整 URL 格式**
```
https://oa-dev.onwall.cn/srv/?a=query_form_all_field&f=custom_form&form_code={form_code}
```
### 2. 数据验证
提取后需要验证数据完整性:
```javascript
function validateExtractedData(data) {
const required = ['name', 'field_list'];
const missing = required.filter(key => !data[key]);
if (missing.length > 0) {
throw new Error(`缺少必要字段: ${missing.join(', ')}`);
}
// 验证字段列表
if (!Array.isArray(data.field_list) || data.field_list.length === 0) {
throw new Error('字段列表为空或格式错误');
}
return true;
}
```
### 3. 错误处理
```javascript
try {
const config = await extractFormConfig(url);
validateExtractedData(config);
return convertToStandardFormat(config);
} catch (error) {
console.error('数据提取失败:', error.message);
// 返回错误信息
return {
success: false,
error: error.message,
url: url
};
}
```
### 4. URL 解析
从用户提供的表单 URL 中提取参数并构建 API 请求:
```javascript
// 示例 URL: https://oa-dev.onwall.cn/f/custom_form/front/index.html#/?code=nxqkbf
function parseFormUrl(url) {
const params = new URLSearchParams(url.split('?')[1]);
return {
// 基础参数
form_code: params.get('code'),
model: params.get('model'), // 预览模式
data_id: params.get('data_id'), // 数据 ID(编辑时)
page_type: params.get('page_type'), // add/edit/info/flow
flow_node_code: params.get('flow_node_code'), // 流程节点
force_back: params.get('force_back'), // 强制后台模式
x_cycle: params.get('x_cycle'), // 周期 ID
volunteer_source: params.get('volunteer_source'), // 义工来源
openid: params.get('openid'), // 微信 openid
};
}
// 使用示例
const url = 'https://oa-dev.onwall.cn/f/custom_form/front/index.html#/?code=nxqkbf&page_type=add';
const params = parseFormUrl(url);
// 构建完整的 API 请求
const apiParams = {
f: 'custom_form',
form_code: params.form_code,
page_type: params.page_type || 'add',
data_id: params.data_id || null,
flow_node_code: params.flow_node_code || '',
force_back: params.force_back || '',
x_cycle: params.x_cycle || '',
volunteer_source: params.volunteer_source || ''
};
```
**URL 参数说明**
| 参数 | 说明 | 示例值 | 必填 |
|------|------|--------|------|
| `code` | 表单代码 | `nxqkbf` | ✅ |
| `model` | 模式 | `preview` | ❌ |
| `page_type` | 页面类型 | `add`/`edit`/`info`/`flow` | ❌ |
| `data_id` | 数据 ID | `12345` | ❌ |
| `flow_node_code` | 流程节点代码 | `node_001` | ❌ |
| `force_back` | 强制后台模式 | `1` | ❌ |
| `x_cycle` | 周期 ID | `cycle_001` | ❌ |
| `volunteer_source` | 义工来源 | `self`/`leader` | ❌ |
| `openid` | 微信 openid | `oxxxxx` | ❌ |
**简化的 API 调用**
如果只需要获取表单结构,可以只传递必要的参数:
```bash
# 最小化调用(只需要 form_code)
curl "https://oa-dev.onwall.cn/srv/?a=query_form_all_field&f=custom_form&form_code=nxqkbf"
# 完整调用(包含所有 URL 参数)
curl "https://oa-dev.onwall.cn/srv/?a=query_form_all_field&f=custom_form&form_code=nxqkbf&page_type=add&data_id=null&flow_node_code=&force_back="
```
---
## 🔗 相关文档
- [00-数据结构总览.md](./00-数据结构总览.md)
- [01-表单字段组件类型.md](./01-表单字段组件类型.md)
- [06-规则控制系统.md](./06-规则控制系统.md)
- [03-API-接口文档.md](./03-API-接口文档.md)
# docs 文档索引
本文档目录为 LangChain Agent 设计表单生成功能提供完整的项目架构和数据结构参考。
## 文档列表
### 00-数据结构总览.md
**用途**:了解项目的核心数据结构
**内容**
- 表单字段结构 (FormField)
- 组件属性结构 (ComponentProps)
- 选项结构 (Option)
- API 响应结构
- 数据流转流程
**适合**:Agent 需要理解整体数据模型时
---
### 01-表单字段组件类型.md
**用途**:了解所有支持的组件类型
**内容**
- 30+ 种组件类型完整列表
- 每种组件的用途和配置要点
- 组件注册位置
- 新增组件流程
**适合**:Agent 需要选择合适的组件类型时
---
### 02-component_props-配置规范.md
**用途**:了解组件属性的详细配置
**内容**
- 通用属性(所有组件)
- 各类组件专属属性
- Option 结构详解
- 数据提交格式
- 样式属性
**适合**:Agent 生成具体组件配置时
---
### 03-API-接口文档.md
**用途**:了解后端 API 接口
**内容**
- 表单管理接口(增删改查)
- 数据管理接口
- 组件接口
- 通用接口(上传、验证码等)
- HTTP 缓存控制
**适合**:Agent 需要与后端交互时
---
### 04-示例数据.md
**用途**:提供各类组件的配置示例
**内容**
- 20+ 个真实配置示例
- 完整表单配置示例
- 数据提交格式示例
- LangChain Prompt 模板
**适合**:Few-shot Learning、Prompt 模板构建
---
### 05-LangChain-Agent-使用指南.md
**用途**:Agent 开发指南
**内容**
- 自然语言到组件映射表
- 必填/数量/选项识别规则
- 复杂需求处理
- Prompt 模板
- LangChain 代码示例
- 验证和错误处理
**适合****开发 LangChain Agent 的主要参考文档**
---
### 06-规则控制系统.md
**用途**:表单字段显示/隐藏规则系统
**内容**
- 规则系统概述(SHOW/HIDE 模式、AND/OR 逻辑)
- 规则数据结构(rule_list、Rule、RuleExpr)
- 核心函数分析(checkRules、evaluateMultipleRules、evaluateRuleCondition、handleCascadeHiding)
- 触发机制(@active 事件)
- 实际示例(简单/复杂/多规则/级联隐藏)
- LangChain Agent 集成要点
**适合**:Agent 需要生成规则配置或理解字段间依赖关系时
---
### 07-页面数据提取指南.md
**用途**:从实际运行的表单页面中提取配置数据
**内容**
- Pinia Store 数据存储结构
- 数据提取方法(Chrome DevTools MCP / Vue DevTools API / 直接 API)
- 完整提取流程(打开页面 → 等待加载 → 提取数据 → 解析配置)
- 数据提取模板和代码示例
- 数据转换和验证
**适合**:用户提供表单 URL 时,需要从页面提取完整配置
---
## 快速查找指南
### 按场景查找
| 场景 | 推荐文档 |
|------|----------|
| 理解项目架构 | 00-数据结构总览 |
| 选择组件类型 | 01-表单字段组件类型、05-LangChain-Agent-使用指南 |
| 生成配置 | 02-component_props-配置规范、04-示例数据 |
| Few-shot 示例 | 04-示例数据 |
| 开发 Agent | 05-LangChain-Agent-使用指南 |
| 生成规则配置 | 06-规则控制系统 |
| 理解字段依赖 | 06-规则控制系统 |
| **从 URL 提取表单** | **07-页面数据提取指南** |
### 按组件类型查找
| 组件类别 | 文档位置 |
|----------|----------|
| 文本输入类 | 01-表单字段组件类型(文档输入类) |
| 选择类 | 01-表单字段组件类型(选择类)、04-示例数据(示例4-6) |
| 日期时间类 | 01-表单字段组件类型(日期时间类)、04-示例数据(示例8) |
| 上传类 | 01-表单字段组件类型(上传类)、04-示例数据(示例9) |
| 特殊功能类 | 01-表单字段组件类型(特殊功能类)、04-示例数据(示例11-20) |
### 按属性查找
| 属性 | 文档位置 |
|------|----------|
| 通用属性 | 02-component_props-配置规范(通用属性) |
| options 配置 | 02-component_props-配置规范(选项类组件属性) |
| 图片上传配置 | 02-component_props-配置规范(上传类属性) |
| 样式属性 | 02-component_props-配置规范(样式属性) |
| 规则配置 | 06-规则控制系统(数据结构、触发机制) |
| 字段显示/隐藏 | 06-规则控制系统(SHOW/HIDE 模式) |
| 级联隐藏 | 06-规则控制系统(级联隐藏逻辑) |
## Agent 开发建议
### 1. 先读顺序
1. **05-LangChain-Agent-使用指南** - 了解 Agent 设计要点
2. **01-表单字段组件类型** - 了解可用的组件
3. **04-示例数据** - 获取 Few-shot 示例
4. **02-component_props-配置规范** - 深入了解配置细节
5. **06-规则控制系统** - 了解字段显示/隐藏规则(如需动态表单)
### 2. 关键数据结构
Agent 必须正确理解的核心结构:
```typescript
// 最核心的结构
FormField {
key: string
value: any
component_props: {
tag: string // 决定组件类型
label: string // 显示名称
required: boolean
// ... 其他属性
}
}
```
### 3. 组件类型映射表
直接参考 `05-LangChain-Agent-使用指南` 中的映射表,建立用户描述 → 组件类型的映射。
### 4. Few-shot 示例使用
`04-示例数据.md` 中提取典型示例作为 Prompt 的一部分,提高输出质量。
### 5. 验证策略
生成配置后,验证以下内容:
- [ ] tag 值是否有效(参考 01 文档的组件列表)
- [ ] required 是否为布尔值
- [ ] 选项类组件是否有 options 数组
- [ ] 上传类组件是否有合理的数量限制
## 数据流转图
```
用户自然语言
[Agent 解析]
意图识别 + 实体提取
组件类型选择 + 配置生成
[验证输出]
表单字段配置 JSON
createComponentType()
动态表单渲染
```
## 联系方式
如有问题或需要补充文档,请查阅:
- 项目源码:`src/hooks/useComponentType.js`
- 组件目录:`src/components/`
- API 目录:`src/api/`