全代码框架文档
首页
快速上手
前端组件
前端二开
首页
快速上手
前端组件
前端二开
  • 二开前准备
  • 对接移动办公
  • 表单介绍

    • 表单封装逻辑
    • 传值和formModel
    • 组件的封装
    • 显示隐藏控制
    • 字段事件
  • 基础二开

    • 值计算
    • 修改组件值
    • 自定义校验
    • 使用远程数据源
    • 为工具栏添加按钮
    • 为表单添加新字段
  • 高级二开

    • 自定义字段
    • 自定义页面
    • 弹窗
    • 表单
    • 表格

PC端逻辑

未绑定流程的表单和带流程的标配单赋值逻辑基本一致,在原始框架中,带流程的表单详情取值实际上取得是流程保存的一份冗余数据,而列表读取的是原始表单的数据,这样会导致数据不一致。在后续版本中,这个问题已经被修复。

赋值过程(表单初始化)

以流程表单为例,入口页面为SystemForm/src/Form,异步组件加载完成之后,会调用loadingCompleted函数。这个函数会调用ref的setWorkFlowForm,函数定义位于生成代码的components/Form.vue中。

对于非新建场景,id(就是默认的rowKey)存在,因此会调用setFormDataFromId,重新查一次表单数据,避免数据不一致问题,此时formModel实际上是有值的,但是值来自流程冗余,因此因此会调用setFormDataFromId会重新覆盖formModel的值。

async function setWorkFlowForm(obj) {
    try {
        let flowData = changeWorkFlowForm(cloneDeep(formProps), obj);
        let {buildOptionJson, uploadComponentIds, formModels, isViewProcess} = flowData;
        data.formDataProps = buildOptionJson;
        emits('changeUploadComponentIds', uploadComponentIds); //工作流中必须保存上传组件id【附件汇总需要】
        if (isViewProcess) {
            setDisabledForm(); //查看
        }
        state.formModel = formModels;
        if (formModels[RowKey]) {
            setFormDataFromId(formModels[RowKey], false)
        }
    } catch(ex) {

    }
}

最后,这个函数会调用SimpleForm/SimpleFormSetup的setFieldsValue函数完成表单赋值,因此,最上面template里formModel的定义仅仅是为了防止初值没有报错。

async function setFormDataFromId(rowId, skipUpdate) {
    try {
        const record = await getDevgaofirst(rowId);
        if (skipUpdate) {
            return record;
        }
        setFieldsValue(record);
        state.formModel = record;
        await getFormDataEvent(formEventConfigs, state.formModel, systemFormRef.value, formProps.schemas); //表单事件:获取表单数据
        return record;
    } catch (error) {

    }
}

取值过程(表单提交)

表单提交时调用的实际上是表单的校验函数,这个函数会返回表单的值:

async function saveLaunch() {
    data.submitLoading = true;
    loading.value = true;
    try {
        let validateForms = await formInformation.value.validateForm();

        if (validateForms.length > 0) {

        }
    }
    // 后面代码省略
}

需要注意的是,这个函数的返回值必须表单中有效的antd-vue表单字段,而且字段必须渲染出来(可以v-show不能v-if,隐藏字段会自动处理)。因此修改提交值可以在模块生成的form.vue中找到validate函数:

async function validate() {
    let values = [];
    try {
          values = await systemFormRef.value?.validate();
          //可以修改values,加入需要额外提交给后端的值
          if (data.formDataProps.hiddenComponent?.length) {
            // 其他代码省略
          }
    } finally {
    }
    return values;
}

表单值绑定(v-model)

在拆分后的CustomDevForm中,formModel为响应式的,下面是一个例子,直接利用formModel拼接字符串,同时保持表单样式(提交时不传值):

<template>
    <!-- 其余代码省略 -->
    <Col :span="getColWidth({responsive: true})">
        <FormItem label="vmodel演示">
            {{formModel.danXingWenBen5090 + '/' + formModel.danXingWenBen23227}}
        </FormItem>
    </Col>
</template>

效果如下: 演示

移动端逻辑

表述与PC端基本一致,不再赘述。流程表单赋值也修改为从原始表单获取而非流程表单。

赋值过程(表单初始化)

移动端赋值过程相对PC端简化很多,在流程层获取到流程数据后,向下传递,在FormInformation.vue层存贮到公共文件userFormInfo.js文件中。然后接着通过loadForm方法向下层组件传递。

// FormInformation.vue
function setFormModel() {
  try {
    if(state.platform=='wx'){
        // 无关代码省略
    }else{
      for (let index = 0; index < itemRefs.value.length; index++) {
        if (itemRefs.value[index]) {
          if(JSON.stringify(forms.formModels[index])!="{}"){
            //这里放入流程表单数据
            itemRefs.value[index].loadForm(forms.formModels[index]);
          }else{
            itemRefs.value[index].init();
          }
        }
      }
    }
  } catch (error) {

  }
}

system-form层同样触发下层form的loadForm方法。

// system-form层
async function loadForm(formModel) {
	await systemRef.value.loadForm(formModel)
}

在生成的表单文件form.vue中,通过传递过来的formModel的rowKey值查询一遍原始表单数据,最后赋值。

// form.vue
async function loadForm(val){
	let id = val[rowKey]
  formConfig.id = id;
  const {
    data
  } = await getxxx(id);
  if (data) {
    await formRef.value.setFormData({...props.formModel, ...data})
  }
}

取值过程(表单提交)

移动端与PC端不同的是,在提交表单的时候校验函数和获取表单值的函数是分别进行的,validate函数并没有返回表单的值。

// 流程提交参数
async function saveLaunch() {
    try {
        uni.showLoading();
        // 校验表单
        let validateForms = await flowInfoRef.value.validateForm();
        if (validateForms.length > 0) {
            let successValidate = validateForms.filter((ele) => {
                return ele.validate;
            });
            if (successValidate.length == validateForms.length) {
                // 获取表单值
                mainFormModels.value = await flowInfoRef.value.getFormModels();
                // 其他代码省略
            }
        }
    }
    // 其他代码省略
                
}

这里获取表单值的函数的最底层是在simpleForm.vue公共组件,在这里getFormData函数返回与表单双向绑定的formModelRef的值,然后每一层都有一个getFormData函数向外暴露,以方便在最外层获取表单的值。在FormInformation.vue中,因为原始框架支持多表单,所以对多个表单值进行了合并处理。

async function getFormModels() {
    let formModes = {};
    if(state.platform=='wx'){
        // 无关代码省略
    }else{
        for (let index = 0; index < forms.configs.length; index++) {
            if (itemRefs.value[index]) {
                try {
                    let formModel =  await itemRefs.value[index]?.getFormData();
                    if(itemRefs.value[index].formType==FormType.SYSTEM){
                        let formModelIdVal = await itemRefs.value[index]?.submit();
                        formModel = {...formModel,...formModelIdVal};
                    }
                    formModes[forms.configs[index].formKey] = formModel;
                } catch (error) {
                }
            }
        }
        // 无关代码省略
    }
}

表单值绑定(v-model)

该部分逻辑基本与PC端一致,不再赘述。

Last Updated:: 4/10/25, 10:11 AM
Contributors: gaoyunqi, DESKTOP-45LLIKH\11405
Prev
表单封装逻辑
Next
组件的封装