低代码可视化表单设计器 FcDesigner 远程请求教程:GET POST 变量鉴权

好用的低代码可视化表单设计器 FcDesigner 是一款基于 Vue 的开源工具(设计器项目名 form-create-designer),通过数据驱动表单渲染。可以拖拽生成表单规则,再由配套渲染器 form-create 加载 JSON 并渲染。面向政务、OA、ERP、电商、流程管理里要做动态表单的开发者和业务配置同学。

源码地址: Github | 文档 | 演示

审批单要按「申请人」拉部门下拉、录入页提交要带登录 Token、嵌进 OA 后所有接口都得改请求头------这些都是远程请求。FcDesigner 把请求收成一份 FetchConfigaction 是地址,method 只区分 GET / POSTquery 走 GET 参数,data 是携带数据,JSON body 要声明 dataType: 'json',鉴权放 headers。组件事件里用 api.fetch 当场发;表单事件 beforeFetch 在真正发出前改 config;也可以重写内置 fetch,让设计器和渲染器走同一套请求头。

选中组件后打开「设置事件」,左侧能建 change 这类事件。右侧「自定义」里拿到 $inject.api,就可以 api.fetch。截图里是值变化时请求 /api/change,成功后打日志。预览时改这个组件的值,就会发出这条请求。

FcDesigner 的远程请求 FetchConfig 怎么写?

数据结构

ts 复制代码
type FetchConfig = {
    //请求地址
    action: String;
    //请求方式
    method?: 'GET' | 'POST';
    //GET 参数
    query?: Object;
    //发送请求时携带的数据
    data?: Object;
    //携带数据的发送方式
    dataType?: 'json' | 'formData';
    //发送请求的请求头
    headers?: Object;
    //后置数据数据回调
    parse?: Function;
    //请求成功后的回调
    onSuccess: (body: any) => void
    //请求失败后的回调
    onError?: (e: Error | ProgressEvent) => void;
}

action 必填。method 不写时,后面 GET 示例就只配 queryquerydata 不要混用:GET 参数走 query,POST 携带的数据走 data。要把 body 做成 JSON,必须把 dataType 写成 'json',不要只改 headersparse 在请求完成后处理返回值。类型里还有 onSuccess / onError;本页可运行示例走的是 api.fetch(...).then(...)

审批单里怎么发 GET,录入页怎么发 POST?

基本示例:值变化时请求接口

场景: 审批单上有一个输入框。业务同学改完值(失焦或回车)就要打接口,把当前值带给后端。

按下面做:

  1. 选中这个输入框,打开「设置事件」。
  2. 「创建事件」里选值变化对应的 change
  3. 在「自定义」里写入下面这段,保存后点确定。
  4. 点顶部「预览」,改这个字段的值,不要只看画布。
js 复制代码
function change($inject) {
  const api = $inject.api;

  api.fetch({
    action: '/api/change?value=' + $inject.args[0]
  }).then(res=>{
    console.log('请求成功')
  })
}

$inject.api 是当前表单的 api$inject.args[0] 是这次变化带出来的值。预览后:改字段并发出 GET(地址里拼了当前值);请求成功会在控制台看到「请求成功」。嵌进 OA 时把 /api/change 换成你们的校验或查询地址。

再一个示例:按姓名拉 Select 选项

场景: 录入页已经填了 name。要根据这个姓名去拉「所属部门」下拉的 options,不能写死在设计器里。

把这段写进会跑 api.fetch 的事件(同样是「设置事件」里,事件函数里已经有 api):

js 复制代码
const formData = api.formData();
api.fetch({
    action: '/api/getdata',
    query: {
        name: formData.name
    }
}).then(res=>{
    api.getRule('select').props.options = res.data;
});

api.formData() 取出整表当前值。query.name 用的是字段 name。预览后:请求变成 GET /api/getdata,带查询参数 name;返回的 res.data 写进名为 select 的规则的 props.options。把 'select' 换成你画布上那个下拉的标识,把 name 换成申请人字段。

值变化那条把参数拼进 action 字符串;这条用 query 对象。都是 GET,但 query 不用自己写 ?。预览后应发出 GET /api/getdata 并带上 name,下拉选项变成接口返回的 res.data

POST 提交并带 Token

场景: 嵌进 OA 的录入页要点提交。整份 formData 以 JSON POST 出去,请求头带登录态。Token 来自外部变量 globalToken

js 复制代码
const formData = api.formData();
//外部变量
const token = api.getData('globalToken');
api.fetch({
    action: '/api/submit',
    method: 'POST',
    dataType: 'json',
    data: formData,
    headers: {
        token: token
    }
}).then(res=>{
    // 表单提交成功
});

预览后:发出 POST /api/submitdata 是当前整份表单值,headers.token 等于 api.getData('globalToken')。不要漏 dataType: 'json',否则 body 不是 JSON。globalToken 是外部变量,本页只用 api.getData 读取,不展开它是怎么挂上的。提交事件里写这段,点预览再提交,才能看到这次 POST。

请求 URL 和 Header 里怎么写变量?

配置请求时可以用双大括号 {``{ }} 引用变量,链接、请求头、数据里都能写。例如 {``{token}} 会在请求时换成变量 token 的值;值是对象时,用 {``{variableName.attributeName}} 取属性。

截图是「全局数据源」的「请求配置」:请求链接写成 http://192.168.1.4:8081/id={``{$form.Fvixlz6gmhetc7c}},请求头 token 写成 {``{$cookie.token}}。魔棒会打开变量列表,当前表单字段在 $form 下面。你自己拖出来的字段 ID 和截图不同,以列表里的为准。

场景: 嵌进 OA 的审批单。详情接口路径里要带当前表单的 userId,鉴权走 Cookie 里的 token

js 复制代码
api.fetch({
    action: 'https://api.example.com/user/{{$form.userId}}/details',
    method: 'GET',
    headers: {
        'Authorization': 'Bearer {{$cookie.token}}'
    },
    data: {},
}).then(res=>{
    //todo
});

预览后:真正发出时,{``{$form.userId}} 换成表单字段 userId 的值,{``{$cookie.token}} 换成 Cookie 的 token。字段名必须和画布上的一致,Cookie 键必须叫 token

再一个示例:POST 的 data 引用表单字段

场景: 录入页更新资料。姓名、年龄已经在表单里,不要在事件里再手写一遍 api.formData()

js 复制代码
api.fetch({
    action: 'https://api.example.com/update',
    method: 'POST',
    dataType: 'json',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer {{$cookie.token}}'
    },
    data: {
        name: '{{$form.userName}}',
        age: '{{$form.userAge}}'
    },
}).then(res=>{
    //todo
});

预览后:POST JSON 到 /updatename / age 分别是字段 userNameuserAge 当时的值,Authorization 仍从 Cookie 取 token。本页列出的替换关系是:

  • {``{$cookie.token}} → Cookie 中的 token 字段
  • {``{$form.userId}} → 表单中的 userId 字段
  • {``{$form.userName}} → 表单中的 userName 字段
  • {``{$form.userAge}} → 表单中的 userAge 字段

{``{变量名}} 还能读内置变量、全局变量和外部传入的数据。定义方式不在本课展开;请求配置里先用上面这组。

怎么用 beforeFetch 在发出前改请求?

beforeFetch 在远程请求真正发出前触发。可以在这里改请求头、改 URL、加查询参数。注意:这里拿到的是最终请求数据 ,不再做模板变量解析。配置里写的 {``{ }} 此时已经替换完了。

按这三步配:

  1. 打开表单事件配置弹窗:进入设计器,点配置面板里的「事件」(截图上这一块标题是「表单事件」),打开事件配置。
  2. 在弹窗左侧选 beforeFetch。说明是「远程数据请求发送前触发」,函数签名是 function beforeFetch(config, data)
  3. 在右侧改 config,保存。

场景: 嵌进 OA 后,Select 远程选项、提交、上传都会发请求。不想每个组件事件里都手写 Token,统一从 Cookie user-token 塞进 headers.token

js 复制代码
function getCookie(name) {
    name = name + '=';
    const decodedCookie = decodeURIComponent(document.cookie);
    const cookieArray = decodedCookie.split(';');
    for (let i = 0; i < cookieArray.length; i++) {
        let cookie = cookieArray[i];
        while (cookie.charAt(0) === ' ') {
            cookie = cookie.substring(1);
        }
        if (cookie.indexOf(name) === 0) {
            cookie = cookie.substring(name.length, cookie.length);
            try {
                return JSON.parse(cookie);
            } catch (e) {
                return cookie;
            }
        }
    }
    return null;
}
config.headers.token = getCookie('user-token');

这段写在 beforeFetch(config, data) 函数体里。预览后:任意远程请求发出前,headers.token 都会变成 Cookie user-token 的值。Cookie 里没有这个键时,getCookie 返回 null

再一个示例:URL 上拼 localStorage 的 user_id

场景: 审批单接口用查询参数区分当前登录人。人的 ID 在 localStorage.user_id,不想让业务同学在每个数据源里手填。

js 复制代码
function getLocalStorage(name) {
    const value = localStorage.getItem(name);
    if (value) {
        try {
            return JSON.parse(value);
        } catch (e) {
            return value;
        }
    }
    return null;
}
config.action += ('?=uid' + getLocalStorage('user_id'));

预览后:原来的 config.action 后面会接上 ?=uiduser_id。截图红框就是这一行。键名必须是 user_id。这里按官方示例拼接,不要改成自己发明的查询串格式。

把自定义 token 变量追加进 headers

场景: 录入页已经把 token 挂在表单能 getData 到的数据上,只想在现有 headers.token 后面再拼一段。

js 复制代码
config.headers.token += data.api.getData('token');

beforeFetch 第二个参数是 data,上面用 data.api.getData('token')。预览后:请求头里的 token 会在原值后面追加这段。这条是 +=,要求 config.headers.token 事先已经有值(例如前面用 {``{$cookie.token}} 配过)。

返回数据怎么 parse?设计器里的 fetch 怎么统一改?

基本示例:把接口的 items 抽成组件能用的数组

场景: 审批单下拉要 {id, name}。后端却包了一层:

json 复制代码
{
    "status": "success",
    "data": {
        "items": [
            { "id": 1, "name": "Item 1" },
            { "id": 2, "name": "Item 2" }
        ],
        "total": 2
    }
}

parse 是后置回调,请求完成后先走它,再给组件用。

截图在「数据处理」页,最简单的写法是 return res.data。套了 status / items 时,用下面这段:

js 复制代码
function parse (data) {
    if (data.status === 'success') {
        // 提取并格式化数据
        return data.data.items.map(item => ({
            id: item.id,
            name: item.name
        }));
    } else {
        throw new Error('请求失败');
    }
}

预览后:statussuccess 时,组件拿到的是 [{id, name}, ...];否则抛「请求失败」。返回键名按示例是 idname。截图里的 parse(res)return res.data,适合接口已经是组件能直接吃的结构;包了 statusitems 时用上面这段。

再一个示例:事件里手动 api.fetch

场景: 不走数据源配置,审批意见一变就按当前 name 再查一次。

js 复制代码
api.fetch({
    action: '/api/getdata',
    query: {
        name: api.getValue('name')
    }
}).then(res=>{
    //todo
});

和前面「按姓名拉 Select」那条的差别:这里用 api.getValue('name') 只取一个字段,而不是整份 formData。预览后:GET /api/getdata,查询参数是字段 name 的当前值。then 里按业务写后续赋值。

重写内置的请求方法

场景: 设计器画布、渲染器运行、文件上传都要带同一条 user-token。不想只靠某个表单的 beforeFetch

文件上传同样会调用 fetch。重写时要一起改 FcDesigner.designerForm.fetchFcDesigner.formCreate.fetch

js 复制代码
import FcDesigner from '@form-create/designer'
const globalFetch = FcDesigner.designerForm.fetch;

FcDesigner.designerForm.fetch = FcDesigner.formCreate.fetch = (config) => {
    config.headers.token = getCookie('user-token');
    return globalFetch(config);
}

getCookie 用前面 beforeFetch 示例里的那份即可。官方这段在 import FcDesigner 之后立刻覆盖两个 fetch:先把原函数存成 globalFetch,改完 config 必须 return globalFetch(config),不要丢掉内置实现。预览或运行后,所有走内置 fetch 的请求(含上传)都会先写入 headers.token,再交给原来的实现。只想改某一张审批单时,用该表的 beforeFetch,不要全局覆盖。

远程请求常见问题

Q: api.fetch 应该写在哪里?

A: 写在会拿到 api 的事件里。组件「设置事件」的 change 里用 const api = $inject.api,再 api.fetch。表单事件 beforeFetch 的参数是 (config, data),改的是即将发出的 config,不是再调一次 api.fetch。GET 拉选项那条用 api.formData()api.getRule('select');只取一个字段时用 api.getValue('name')

Q: GET 和 POST 差在哪?dataType 什么时候写?

A: GET 示例把参数放 querymethod 可以不写。POST 必须写 method: 'POST',携带数据放 data。要把 body 做成 JSON,必须 dataType: 'json',只改 Content-Type 不够。Token 一类鉴权放 headersmethod 的可选值在类型里只有 'GET' | 'POST'

Q: {{ }} 变量和 beforeFetch 谁先生效?

A: 配置里的 {``{$form.userId}}{``{$cookie.token}} 在请求执行时会被替换。beforeFetch 拿到的是替换之后的最终请求数据,不再解析模板变量。要改已经拼好的 URL 或 Header,在 beforeFetch 里改 config.action / config.headers

Q: 为什么重写 fetch 之后上传也带上 Token 了?

A: 文件上传同样调用 fetch。把 FcDesigner.designerForm.fetchFcDesigner.formCreate.fetch 一起换成你的函数后,设计器、渲染器、上传都会先经过你的 config.headers.token = getCookie('user-token'),再 return globalFetch(config)。只想改某张表的请求时,用该表的 beforeFetch,不要全局重写。

相关推荐
江湖有缘2 小时前
Docker开源项目: 基于Ubuntu系统部署ExpenseOwl自托管记账工具实战教程
ubuntu·docker·开源
m4Rk_4 小时前
【论文阅读】Agent 记忆机制(50):PACE——按下一步预测价值动态分配历史记忆粒度
论文阅读·人工智能·学习·开源·github
小强闯江湖4 小时前
ViewCompose:让原生 Android View 进入声明式时代
android·开源·kotlin
记忆张量MemTensor4 小时前
MemOS Skill 上线|一句话即可接入 MemOS Cloud
大数据·数据库·人工智能·typescript·开源
密瓜智能5 小时前
渝见开源,数智启新|密瓜智能参赛项目获评青年开源专项基金种子计划首批重点项目
开源
小小龙学IT5 小时前
zstd(Zstandard)开源压缩库实战指南:让数据又快又小
c++·开源
LadiesAndGentlemen5 小时前
概览篇:世界模型、空间智能与地理空间智能是什么关系
数据库·人工智能·自然语言处理·开源·aigc
欧阳天羲5 小时前
【开源答疑】激光灭蚊机器人|全套硬件资料说明、BOM选型、价格参考、避坑清单
机器人·开源
小小龙学IT5 小时前
GLM 开源图形学数学库深度解析:从向量、矩阵到四元数的完整实战
c++·矩阵·开源·mfc