07-页面数据提取指南.md 21.8 KB

页面数据提取指南

最后更新: 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: 解析数据

根据提取的数据,解析出:

  1. 表单基本信息: 表单名称、描述
  2. 字段列表: 所有字段的配置
  3. 规则列表: 字段显示/隐藏规则
  4. 页眉配置: banner、标题等
  5. 提交配置: 提交按钮配置

🎯 数据提取模板

/**
 * 从表单页面提取完整配置
 */
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="

🔗 相关文档