4. 在线编码

4.1 在线编码说明

指在线写代码,写的内容会直接运行,全局已经定义了configs的变量,所有的数据通过configs获取。

变量 说明 例子
btnConfig 按钮配置 configs.btnConfig
context 表单上下文 configs.context
data 表单数据 configs.data
relation 联动,可以增加、触发联动 configs.relation
utils 工具类,可以弹窗,加载组件等 configs.utils

通用参数解释

变量 说明
formCode 组件的formCode ,
attrCode 组件的code,

4.1.1 context 上下文

变量 说明 入参 例子
addListener 添加监听方法,主要是事件执行前触发,事件执行后触发以及值改变时触发 { code: 唯一值即可; type: 'valueChange' | 'beforeEvent' | 'afterEvent'; handler: 回调方法 } configs.context.addListener({ code: ‘test’, type: ‘valueChange’,handler: ({ configs, extra, value }) => {} })
config 整体表单配置 configs.context.config
dictionary 表单数据字典,不包含明细表 configs.context.dictionary
form 表单,可用于校验值和获取值,具体参考antd form的api configs.context.form.getFieldValue()
getBtnConfig 获取按钮配置 { formCode: 空字符串,attrCode:按钮所在容器的attrCode,btnCode:按钮的code } configs.context.getBtnConfig({ formCode: ‘parentCode’, attrCode: ‘attrCode’, btnCode: ‘save’ })
getCompParams 获取由上下文传给组件的配置 { formCode: 组件的formCode,attrCode:组件的attrCode } configs.context.getCompParams({ formCode: ‘parentCode’, attrCode: ‘attrCode’})
getCompRef 获取组件对应api,比如获取明细表的数据字典,返回组件api,组件都有onChange的api { formCode: 组件的formCode,attrCode:组件的attrCode } configs.context.getCompRef({ formCode: ‘parentCode’, attrCode: ‘attrCode’}).getDictionary()
getConfig 获取组件配置,返回IConfig类型 { formCode: 组件的formCode,attrCode:组件的attrCode } configs.context.getConfig({ formCode: ‘parentCode’, attrCode: ‘attrCode’})
getDictionary 获取数据字典 configs.context.getDictionary()
getFormData 获取表单数据 configs.context.getFormData()
getFormId 获取表单id,如果创建则返回空 configs.context.getFormId()
refresh 刷新数据 configs.context.refresh()
refreshBtnConfigs 刷新按钮配置 { formCode: 空字符串,attrCode:按钮所在容器的attrCode } configs.context.refresh({ formCode: ‘parentCode’, attrCode: ‘attrCode’})
refreshConfigs 刷新配置 isDeep: 是否深度刷新,true的话比较整个配置会重新刷新 configs.context.refreshConfigs(true)
reset 编辑状态刷新为创建 configs.context.reset()
setBaseConfig 设置组件的基础配置,比如是否展示,是否编辑等,设置后需要调用refreshConfigs configs.context.setBaseConfig({formCode:’’,attrCode:’’, attr: ‘改变属性的key’, value: ‘改变属性的value’, extra: ‘如果是明细的话,对单行操作则需要填对应信息{ id:’’ }’})
setCompParams 设置需要传给组件的参数 { ‘对应组件的code’:{} } configs.context.setCompParams({ test: { onSearch: () => false } })
setFormData 设置表单内容,该方法改变值后不会触发联动,需要触发联动则需用getCompRef获取组件api,然后调用onChange,如:configs.context.getCompRef({formCode:’’,attrCode:’’}).onChange(1) configs.context.setFormData({a:12,b:21})
setRuleConfig 设置组件校验规则,比如必填等,设置后需要调用refreshConfigs configs.context.setRuleConfig({formCode:’’,attrCode:’’, attr: ‘改变属性的key’, value: ‘改变属性的value’, extra: ‘如果是明细的话,对单行操作则需要填对应信息{ id:’’ }’})
unlisten 注销监听 { code: 监听的值; type: ‘valueChange’ | ‘beforeEvent’ | ‘afterEvent’; } configs.context.unlisten({ code:’’, type: ‘valueChange’})

4.1.2 data 数据

变量 说明 例子
allData 表单上所有数据 configs.data.allData
currentData 当前容器数据,比如执行在card上,就只拿到card里面的内容 configs.data.currentData
preData 同一事件里,上一环节执行事件结果,比如事件中会拿到前置事件的结果,后置事件会拿到事件中的结果 configs.data.preData
extraData 额外的数据,如果是明细表的操作按钮,可以获取到选中结果,如果是明细表的行按钮,可以获取到行数据,具体可以打印 configs.data.extraData

4.1.3 relation 联动

变量 说明 入参 例子
on 注册联动 {attrCode: 组件attrCode, formCode: 组件formCode, actionCode: 执行类型,类型有:blur(失焦执行)、focus(聚焦执行)、change(值改变执行)、search(搜索时执行)、create(打开创建时执行)、edit(打开编辑时执行)、destroyOnCreate(创建表单结束离开时执行)、destroyOnEdit(编辑表单结束离开时执行},{id:场景下唯一值, cb: 联动回调} configs.relation.on({attrCode:’’,formCode:’’,actionCode:’change’},{id: ‘唯一值,避免重复’, cb: (ctx) => {}})
emit 执行联动 {attrCode: 组件attrCode, formCode: 组件formCode, actionCode: 与on的actionCode相同},{attrCode: ‘可选’,formCode:’可选’,index:’明细表需要的序号’,id:’明细表需要的id’} configs.relation.emit({attrCode:’’,formCode:’’,actionCode:’change’}, {})

4.1.4 utils 工具类

变量 说明 例子
confirm 参考antd confirm用法 configs.utils.confirm({ title: ‘title’, content: ‘content’, onOk: () => {} })
notification 参考antd notification用法 configs.utils.notification.warning({ message: ‘warning’, description: ‘warning’ })
message 参考antd message用法 configs.utils.message.warning(‘message’)
useCompModal 入参:Content:组件, modalConfigs:modal配置,参考antd Modal,contentConfig:组件配置 configs.utils.useCompModal(Component, { title: ‘弹窗标题’}, {a: ‘组件入参1’, b: ‘组件入参2’})
loadCmp 拉取资源组件,入参:{sourceName: 资源名称,exposesKey:导出的资源} configs.utils.loadCmp({ sourceName:’lcp-page-component’, exposesKey: ‘charts’ })
fetch 调用接口,入参参考axios configs.utils.fetch({ url:’/apis/common/proxy/lcpGw/tz_api/服务编码/path路径’,method: ‘get’ ,params: {a:123}})
cache 缓存,可以获取以及存缓存,api有:setValue,getValue,clear;缓存实际挂载在window的天舟云缓存空间中 configs.utils.cache.setValue(‘key’, 123),configs.utils.cache.getValue(‘key’),configs.utils.cache.clear(‘key’)

4.1.5 extra 联动额外数据

变量 说明 例子
attrCode 当前触发的字段的code
formCode 当前触发的字段的formCode
id 如果在明细行行中,存在id
index 如果在明细行中,存在行下标,一般是数字,如果是树形明细表,下标是字符串 如果是1,表示第二行,如果是”1-2”,表示第1行的的第二个子行

4.2 示例

当请求成功后,我们希望按钮可以弹出对应提示信息,我们可以通过后置事件,配置在线编码

const preData = configs.data.preData;
if(preData.status!=="0"){
    configs.utils.notification.error({message:preData.message,content:preData.message});
}else{
    configs.utils.notification.success({message:"更新成功",content:"更新成功"});
}
const pageId = configs.context.globalContext.pageTools.getDetailPageId(configs.context.config);
configs.context.globalContext.pageTools.refresh(pageId);

获取元素/组件的值

方法一

const formData = configs.context.getFormData();
const aValue = formData?.['a'];

方法二

const aValue = configs.data.allData?.['a'];

设置元素/组件的值

仅改变值

configs.context.setFormData({ a: 123 });
configs.relation.emit({ attrCode: 'a', formCode: 'formCode', actionCode: 'change' }, { id: '如果是明细表,需要明细表行id', index: 0 });

仅改变值后会自动触发联动的做法

// 明细表的formCode一般是没有,所以formCode填空字符串
const aRef = configs.context.getCompRef({ formCode: `123`, attrCode: '12' });
aRef.onChange(123);

设置元素/组件可编辑状态

正常元素/组件

// 1 表示可编辑,0 表示不可编辑
configs.context.setBaseConfig({ formCode: `123`, attrCode: '12', attr: 'isEditable', value: '1' });
configs.context.refreshConfigs(true);

如果是明细表,需要加上id和index

configs.context.setBaseConfig({ formCode: `111`, attrCode: '12', attr: 'isEditable', value: '1', extra: { id: '123', index: 1} });
configs.context.refreshConfigs(true);

设置元素校验规则

// attr 有 | 'required' 'max' 'min' 'maxLength' 'minLength'  'len' 'special'  'compare' 'pattern' 'accuracy'
// 开启必填
configs.context.setRuleConfig({ formCode: '', attrCode: '', attr: 'required', value: '1', extra: { id: '如果是针对明细表某一行,需要写id,如果是主表对明细表操作,不写', index: '如果是针对明细表某一行,需要写index,如果是主表对明细表操作,不写' } })

设置元素/组件禁用状态

正常元素/组件

// 1 表示可用,0 表示禁用
configs.context.setBaseConfig({ formCode: `123`, attrCode: '12', attr: 'isEnabled', value: '1' });
configs.context.refreshConfigs(true);

如果是明细表,需要加上id和index

configs.context.setBaseConfig({ formCode: `111`, attrCode: '12', attr: 'isEnabled', value: '1', extra: { id: '123', index: 1} });
configs.context.refreshConfigs(true);

设置元素/组件隐藏显示状态

正常元素/组件

// 1 表示显示,0 表示隐藏
configs.context.setBaseConfig({ formCode: `123`, attrCode: '12', attr: 'isVisible', value: '1' });
configs.context.refreshConfigs(true);

如果是明细表,需要加上id和index

configs.context.setBaseConfig({ formCode: `111`, attrCode: '12', attr: 'isVisible', value: '1', extra: { id: '123', index: 1} });
configs.context.refreshConfigs(true);

设置按钮禁用状态

// formCode填按钮所在容器的formCode,attrCode填容器的code,btnCode填按钮的code,比如按钮所在容器是在card里面,点击设计器的card后,在设计配置可以看到对应的code,鼠标放上去可以看到对应的formCode。2.4版本后formCode可以在高级属性->表单组编码看到,如果没有,则填空字符串
// 如果是表单属性配置的表单按钮,formCode填空字符串,attrCode填'BTN_BLOCK_GLOBAL';
const btnConfig = configs.context.getBtnConfig({ formCode: ``, attrCode: '容器的code', btnCode: '123'});
if (!btnConfig.config.uiConfig) {
     btnConfig.config.uiConfig = {}
 }
 if (!btnConfig.config.uiConfig.attr) {
     btnConfig.config.uiConfig.attr = {}
 }
 // true 表示禁用,false 表示可用
btnConfig.config.uiConfig.attr.disabled = true;
configs.context.refreshBtnConfigs({ formCode: ``, attrCode: '12' });

设置按钮隐藏

// formCode填按钮所在容器的formCode,attrCode填容器的code,btnCode填按钮的code,比如按钮所在容器是在card里面,点击设计器的card后,在设计配置可以看到对应的code,鼠标放上去可以看到对应的formCode。2.4版本后formCode可以在高级属性->表单组编码看到,如果没有,则填空字符串
// 如果是表单属性配置的表单按钮,formCode填空字符串,attrCode填'BTN_BLOCK_GLOBAL';
const btnConfig = configs.context.getBtnConfig({ formCode: ``, attrCode: '容器的code', btnCode: '123'});
// 1 表示显示,0 表示隐藏
btnConfig.config.baseConfig.isVisible = '1';
configs.context.refreshBtnConfigs({ formCode: ``, attrCode: '12' });

明细表

  • 明细表是表单的一种元素,数据格式是数组,每一行数组都是一个对象,每一组对象都有ID的key,如果是新增一行数据,在当行数据需要加__add: true。
  • 如果是个树形的明细表,每一行的数据中都有children的key,children表示是子行,值是一个数组,数据格式明细表一样。
  • 如果有子行或者行数据中有children字段,说明是树形明细表。
    新增一行数据,利用context.getCompRef的能力实现新增一行并可以执行联动

    明细表新增一行

    const { context, data } = configs;
    const tableRef = context.getCompRef({ formCode: 'formCode', attrCode: 'attrCode' });
    let tableData = data?.allData?.['tableAttrCode'];
    if (!Array.isArray(tableData)) {
    tableData = [];
    }
    const id = +new Date()
    tableData.push({ ID: id, __add: true });
    // onChange可以改变值和触发联动
    tableRef?.onChange?.([...tableData], { id, formCode: 'formCode', attrCode: 'attrCode', index: tableData.length })

    明细表新增一行,并在子行插入其他元素的数据

    const { context, data } = configs;
    const tableRef = context.getCompRef({ formCode: 'formCode', attrCode: 'attrCode' });
    let tableData = data?.allData?.['tableAttrCode'];
    let aValue = data?.allData?.['aValue'];
    if (!Array.isArray(tableData)) {
    tableData = [];
    }
    const id = +new Date()
    const newRow = { ID: id, __add: true, children: [] };
    if (!Array.isArray(tableData)) {
    aValue = []
    }
    aValue?.forEach((_a) => {
    newRow.children.push({ ID: Math.random(), __add: true, aValue: _a})
    })
    tableData.push(newRow);
    // onChange可以改变值和触发联动
    tableRef?.onChange?.([...tableData], { id, formCode: 'formCode', attrCode: 'attrCode', index: tableData.length })

    弹窗点击确定

const { context } = configs;

// 通过弹窗等待用户确认
const isConfirmed = await new Promise(rs => {
configs.utils.confirm({
    title: '确认是否做什么事情',
    content: '',
    okText: '确认',
    cancelText: '取消',
    onOk: () => {
      // 确认
      rs(true);
    },
    onCancel() {
      // 取消
      rs(false)
    }
  })
});
if (isConfirmed) {
  // 做一些事情
}

弹窗提示

configs.utils.message.warning('message');

获取表单数据

例子1:

const formData = configs.context.getFormData();

例子2:

// allData 是表单上所有数据
const { allData } = configs.data;

获取用户信息

const userInfo = context.getContext()?.session?.user ?? {};
// 一般有账号,邮箱,用户id,名称,电话
const { account, email, id, name, telephone } = userInfo;

校验,可阻止后续事件执行

const { context } = configs;
const formData = context.getFormData();

const a = formData?.['a'];

if (a === 1) {
    // 后续事件可以拿到response内容,后续事件configs?.data的preData就是response
    response = { success: true, data1: { ttt: 1111 } }
} else {
    // success为false时,后续事件不继续执行
    response = { success: false }
}

跳转到对应tab

// 获取tab的ref,tab是没有formCode,所以填空字符串即可
const tabRef = context.getCompRef({ formCode: '', attrCode: 'TAB_62136AC9079FC'});
// 跳转到对应tab签
tabRef?.setTabKey?.('TABPANE_9AE31CDE5A86E');

调用天舟云内置保存事件

const saveHandler = configs.utils?.cache?.getCache?.()?.['FORMREGISTER']?.["__commonSave"]?.eventHandler;
console.log('--saveHandler', saveHandler);
const currentData = configs?.context?.getFormData?.();
const resp = await saveHandler?.({
    context: configs.context,
    data:{
        currentData,
        allData: currentData,
    },
    btnConfig: {
        scope: ['__GLOBAL_SCOPE'],
    }
})

组件调用天舟云内置保存事件

import CirCache from '@cvte/cir-cache';

const Page = () => {
  const cirCacheRef = useRef(new CirCache({ storage: 'memory' }));
  const detailRef = useRef()

  const handleSave = async () => {
    const context = detailRef.current?.RenderRef?.current?.getContext() ?? {};
    const saveHandler = (cirCacheRef.current?.getCache?.() as any)?.FORMREGISTER
      ?.__commonSave?.eventHandler;
    if (!saveHandler) {
      throw new Error('unexpected savehandler');
    }
    if (!context) {
      throw new Error('unexpected context');
    }
    const currentData = context.getFormData?.();
    const resp = await saveHandler({
      context,
      data: {
        currentData,
        allData: currentData
      },
      btnConfig: {
        scope: ['__GLOBAL_SCOPE']
      }
    });
    return resp;
  };

  return <DetailTemp ref={detailRef} {...其他参数} />

}

调用天舟云内置校验事件

const validateFn = configs.utils?.cache?.getCache?.()?.['FORMREGISTER']?.["__commonGetFormDetailData"]?.eventHandler;
// 会先校验,再返回保存的格式数据
const validatedFormData = await validateFn?.(configs);
// 如果能拿到数据,说明校验成功,如果失败,返回undefined

储存外部工具

// 系统里面储存内容
import CirCache from '@cvte/cir-cache';
const cache = new CirCache({ storage: 'memory' })
cache.setValue('your tool name', 123);

// 在线代码消费内容
const tool = configs.utils.cache.getValue('your tool name');
// tool()

调用history

// 前端2.4版本前
const { cache } = configs.utils || {};
cache.getValue('history-cache').push('/your/url');
// 前端2.4版本后内置history
const { extra } = configs.utils || {};
extra.getValue('history').push('/your/url');

调用搜索

// 说明是谁调用事件,方便排查链路
const owner = 'test';
// 获取事件总线
const subjectEventBus = configs.utils?.getSubjectEventBus?.();
// 调用搜索事件,
subjectEventBus.publishEvent({ owner, eventName: 'form:onSearch' , data: { name: '模糊查询的值,和code二选一', code: '精确查询的值,和name二选一', formCode: '目标字段的formCode', attrCode: '目标字段的attrCode', afterSearchOperate: 'firstOption或者noValue, 搜索后连接器判断noValue的话,不会执行连接器配置的联动,firstOption暂时没支持', id: '如果目标在明细表中,需要行id', index: '如果目标在明细表中,需要行序号'  }});

模板调用渲染上下文

// 列表和详情调用不一样
// 详情
const context = ref.current?.RenderRef?.current?.getContext() ?? {};
// 列表
const context = ref.current?.getRef?.()?.getRenderRef?.()?.getContext?.() ?? {};

请求映射

// 表单按钮接口请求
{
    // 表单数据
    data: {},
    // 表单配置
    page: {
        classId,
        layout: [],
        code,
        id,
    },
    // 获取组织和用户信息
    session: {
        org: {
            orgCode,
            id,
            orgName
        },
        user: {
            account,
            name,
        },
    },
    // 获取url上的query
    url: {}
    // 前置事件数据
    preData: {}
}
// 例子:${data.字段}:${page.id}
// 联动请求
{
response,
formData
}
// 列表
{
    extraData: {
        entity,
        ref: {
            selectedKeys,
            selectedRows
        }
    },
    page: {
        layout: [],
        pageCode,
        id,
    },
    preData,
    session: {
        org: {
            orgCode,
            id,
            orgName
        },
        user: {
            account,
            name,
        },
        url: {

        }
    }
}

明细表获取选择行数据

const tableRef = configs.context.getCompRef({ formCode: '', attrCode: '明细表code' });
const { selectedRows, selects } = tableRef?.getSelects?.() || {}

触发联动

configs.relation.emit({ formCode: '', attrCode: '', actionCode: 'change' })

监听联动

relation?.on?.(
      {
        // 监听当前设置选项映射的属性,发生选项值改变时
        // 则将配置了返回字段的属性值,改为该选项中映射字段的值
        actionCode: 'change',
        attrCode: '', // 属性字段编码;如果是监听明细表,那么此处要写明细表编码
        formCode: '', // 主表/明细表编码;如果是监听明细表,那么此处要写undefined
      },
      {
        // 内置联动id如果每次不唯一,那么每次都会增加无效的联动
        id: relationId,
        cbParams: {
            // 传给回调方法的参数
        },
        cb: async (relationCtx: IRelationClassOnConfigsFnCtx) => {
            // TODO
            const {
                cbParams, // 传给回调方法的参数
                id: relatedRowId, // 当前联动的行id
                index: relatedRowIndex, // 当前联动的行索引
                value: changedValue, // 当前触发联动的值内容
            } = relationCtx.extra || ({} as any);
        }
      },
    );

获取内置方法

// 前端tz-render@1.0.1.10版本后内置history,download,upload
const { extra } = configs.utils || {};
extra.getValue('history').push('/your/url');
extra.getValue('download')({ fileName: '文件名称', noTime: 是否加上时间, blob: 文件流 });
 const files = await extra.getValue('upload')({ fileType: 'file', fileAccept: '.xlsx,.xls,.et' });

调用模板

const { loadCmp } = configs?.utils || {};
// 调用列表模板
const Page = loadCmp({ sourceName: 'tz-render', exposesKey: 'Page'  });
// 调用表单模板
const Detail = loadCmp({ sourceName: 'tz-render', exposesKey: 'Detail'  });
// 参数参考:https://docs.cvte.com/docs/tzv16/216
作者:王浩彬  创建时间:2024-06-20 09:06
最后编辑:袁子涵  更新时间:2025-05-12 18:04