Skip to content

源码扩展公式与行为

设计器里有两类很常用的能力:

名称你可以理解成用在哪里
公式计算器里的函数,如求和、拼接文字计算属性、表达式
行为(动作)点击按钮后要做的事,如跳转、隐藏、提示事件配置里的动作流

如果你只是在自己的业务项目里临时加一个,看这两篇就够了:

本文讲的是:改设计器源码,把公式/动作打进安装包,让大家装完就能用。

开始前你需要知道

  • 版本:FcDesigner Pro v6.x
  • 公式在电脑端、手机端填表时都可能用到,两边都要能算
  • 动作一般在设计器里配置,真正执行发生在预览/填表时

你要改哪里?两种做法

做法改哪些文件适合什么情况
做法 A(更省事)直接改 src/utils/formulas.jssrc/utils/behavior.js想做成「内置能力」,电脑+手机一起带上
做法 B(少动核心文件)src/extension/setting.jsupdateDesigner 里调用 API项目定制,想把改动集中在 extension

相关文件:

  • 公式:src/utils/formulas.js
  • 行为:src/utils/behavior.js
  • 打包入口:src/extension/setting.js

先搞清要填哪些字段

公式要填什么

字段怎么理解例子
name函数名字,必须全大写,且不能重复TOBOOL
menu放在哪个分组里math(数学)、string(文字)、date(日期)等
info给人看的说明返回 true 或 false
example示例TOBOOL(0) = false
handle真正计算公式的函数handle(val) { return !!val }

常用分组:mathstringdatecollectionconditionfeature

行为(动作)要填什么

字段怎么理解例子
name动作唯一名字(建议小驼峰)hideTopForm
menu动作分类page / model / form / other
label界面上显示的名字隐藏表单
info简短说明隐藏当前或最外层表单
rule配置这个动作时要填哪些项返回表单规则数组
handle动作真正执行时干什么调用 api.hideForm()

名字别和内置的撞车

如果 name 和已有公式/动作相同,会直接覆盖原来的。
除非你就是想替换,否则请用自己的前缀,例如 BIZ_TOBOOLbizHideForm

扩展公式

做法 A:直接改 formulas.js(推荐)

打开 src/utils/formulas.js,做 3 件事:

1)写计算函数(加到 formulas 对象里)

js
TOBOOL: function (val) {
    return !!val;
},

2)写示例(加到 formulaInfo 里)

js
TOBOOL: 'TOBOOL(0) = false, TOBOOL(1) = true',

3)挂到分组(加到 formulaTree 对应分组的 children 里)

js
{
    key: 'math',
    children: [
        // ...原来的函数
        'TOBOOL',
    ],
},

改完一般就够了:电脑端、手机端启动时都会自动读这份列表。

(可选)想做多语言说明,再去 src/locale/zh-cn.js 等文件里补文案。

做法 B:写在 extension 里

js
// src/extension/setting.js
updateDesigner(FcDesigner) {
    FcDesigner.setFormula([
        {
            menu: 'math',
            name: 'TOBOOL',
            info: '返回 true 或 false',
            example: 'TOBOOL(0) = false, TOBOOL(1) = true',
            handle(val) {
                return !!val;
            },
        },
    ]);

    // 注意:上面主要保证电脑端设计/填表可用。
    // 如果完整包还要保证手机端填表也能算,请再补一行:
    if (FcDesigner.formCreateMobile) {
        FcDesigner.formCreateMobile.setFormula('TOBOOL', val => !!val);
    }
},

为什么更推荐做法 A?

做法 A 改一次,电脑和手机都会带上。
做法 B 如果忘了给手机端再注册一次,就会出现「电脑能算、手机算不了」。

扩展行为(动作)

做法 A:直接改 behavior.js

打开 src/utils/behavior.js,做 4 件事:

1)写执行逻辑(加到 behavior 对象里)

js
hideTopForm(config, inject) {
    if (config.is_top) {
        inject.api.top.hideForm();
    } else {
        inject.api.hideForm();
    }
},

2)挂到分类(加到 behaviorTree

js
{
    key: 'form',
    children: [
        // ...原来的动作
        'hideTopForm',
    ],
},

3)写配置项(加到 behaviorRules,决定选中动作后右侧要填什么)

js
hideTopForm(designer) {
    return [
        {
            type: 'switch',
            field: 'is_top',
            title: '是否关闭最外层表单',
            value: false,
        },
    ];
},

4)写显示文案(加到 behaviorLocale

js
hideTopForm: {
    name: '隐藏表单',
    info: '隐藏当前或最外层表单',
},

更多写法可参考扩展行为,以及源码里已有的 hiddenredirectPage 等。

做法 B:写在 extension 里

js
// src/extension/setting.js
updateDesigner(FcDesigner) {
    FcDesigner.setBehavior([
        {
            menu: 'form',
            name: 'hideTopForm',
            label: '隐藏表单',
            info: '隐藏当前或最外层表单',
            rule() {
                return [
                    {
                        type: 'switch',
                        field: 'is_top',
                        title: '是否关闭最外层表单',
                        value: false,
                    },
                ];
            },
            handle(config, inject) {
                if (config.is_top) {
                    inject.api.top.hideForm();
                } else {
                    inject.api.hideForm();
                }
            },
        },
    ]);
},

保存后重启/刷新,在「事件 → 动作」里应能看到新动作。

完整示例:一次加上公式 + 动作

js
// src/extension/setting.js
import extend from './index';

export default {
    extend,
    componentViews: {},
    mobileComponentViews: {},
    updateDesigner(FcDesigner) {
        // 1. 加公式:折扣价
        FcDesigner.setFormula({
            menu: 'math',
            name: 'DISCOUNT',
            info: '计算折扣价',
            example: 'DISCOUNT(100, 0.8) = 80',
            handle(price, rate) {
                const p = Number(price);
                const r = Number(rate);
                if (Number.isNaN(p) || Number.isNaN(r)) return 0;
                return p * r;
            },
        });

        // 手机端也注册一份(完整包建议写)
        if (FcDesigner.formCreateMobile) {
            FcDesigner.formCreateMobile.setFormula('DISCOUNT', (price, rate) => {
                const p = Number(price);
                const r = Number(rate);
                if (Number.isNaN(p) || Number.isNaN(r)) return 0;
                return p * r;
            });
        }

        // 2. 加动作:发业务通知
        FcDesigner.setBehavior({
            menu: 'other',
            name: 'notifyBiz',
            label: '业务通知',
            info: '通知外部业务代码',
            rule() {
                return [
                    {
                        type: 'input',
                        field: 'code',
                        title: '通知编码',
                        $required: true,
                    },
                ];
            },
            handle(config, inject) {
                inject.api.top.emit('biz-notify', config.code, inject);
            },
        });
    },
};

常见问题排查

1. 面板里看不到新公式

→ 多半没挂到 formulaTree,或 menu 写成了不存在的分组。
检查分组名是否为:math / string / date 等已有名字。

2. 电脑能算,手机不能算

→ 你可能只用了做法 B,且忘了给 formCreateMobile 再注册。
更省事的办法:改回做法 A,直接改 formulas.js

3. 动作能选中,但点了没反应

→ 执行函数没写好,或事件根本没绑这个动作。
检查 behavior 里是否有同名函数,并打开浏览器控制台看报错。

4. 动作配置项没有标题

rule 里给字段补上 title

5. 和新公式/动作冲突了

name 重复被覆盖了。换一个不重复的名字。

升级和兼容注意

  • 只新增:一般不影响已经保存的老表单
  • 改名或删除:老表单里如果还引用旧名字,会失效,需要迁移或临时兼容两个名字
  • 只在 updateDesigner 里加的公式:不一定会进「单独打包的渲染器」。如果渲染器也要自带,请优先改 formulas.js

相关文档