页面数据提取指南
最后更新: 2026-03-16 用途: 从实际运行的表单页面中提取配置数据
📋 概述
当用户提供一个表单 URL(如 https://oa-dev.onwall.cn/f/custom_form/front/index.html#/?code=nxqkbf)时,需要从页面中提取完整的表单配置数据。
🏗️ 数据存储结构
Pinia Store
表单数据存储在 Pinia store 中:
// Store 名称: 'main'
// Store 定义: src/store/index.js
{
formInfo: {}, // 表单完整信息(包含字段列表、规则等)
formSetting: {}, // 表单数据收集设置
successInfo: {}, // 表单提交返回值
}
formInfo 数据结构
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 - 字段和规则
请求:
GET https://oa-dev.onwall.cn/srv/?a=query_form_all_field&f=custom_form&form_code=nxqkbf
响应结构:
{
"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 字段类型详解:
// 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 - 表单配置
请求:
GET https://oa-dev.onwall.cn/srv/?a=query_form_setting&f=custom_form&form_code=nxqkbf
响应结构:
{
"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
请求参数:
{
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 请求调用!
调用方式:
# 使用 curl 直接调用
curl "https://oa-dev.onwall.cn/srv/?a=query_form_all_field&f=custom_form&form_code=nxqkbf"
// 使用 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 响应结构:
{
"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 工具直接从页面提取数据:
// 在页面中执行以下脚本获取表单数据
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 获取组件状态:
// 获取根组件
const rootComponent = document.querySelector('#app').__vueParentComponent;
// 获取 formInfo
const formInfo = rootComponent.ctx.formInfo;
// 返回结果
JSON.stringify(formInfo, null, 2);
📝 完整提取流程
方法 A: 直接 API 调用(需要登录态)
适用场景:在已登录环境下,需要批量获取表单配置
步骤 1: 解析 URL 获取 form_code
// 从 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
// 使用项目 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: 数据验证
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 并确保已登录:
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: 等待页面加载
等待数据加载完成:
await mcp__chrome_devtools__wait_for({
text: '提交', // 等待提交按钮出现
timeout: 10000
});
步骤 3: 提取数据
执行脚本提取 formInfo:
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: 解析数据
根据提取的数据,解析出:
- 表单基本信息: 表单名称、描述
- 字段列表: 所有字段的配置
- 规则列表: 字段显示/隐藏规则
- 页眉配置: banner、标题等
- 提交配置: 提交按钮配置
🎯 数据提取模板
/**
* 从表单页面提取完整配置
*/
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 返回
{
"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 返回
{
"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
提取的数据结构
{
"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 可理解的标准格式:
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 可以直接访问,无需特殊认证!
# 最简单的调用方式
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. 数据验证
提取后需要验证数据完整性:
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. 错误处理
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 请求:
// 示例 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 调用:
如果只需要获取表单结构,可以只传递必要的参数:
# 最小化调用(只需要 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="