自定义表单
提示:完整的流程审批表单因为流程权限等过于复杂所以不建议手写,最好还是用系统生成及拆分的代码进行二开,以下叙述的场景仅限于简单表单或者是对原表单的扩展。
PC端
项目引入了ant-design-vue的表单组件,具体文档点击查看 简单的并且可复用的表单,可以使用和框架表单一样的形式,编写一个公共组件,通过config.ts来编写表单配置,然后使用公共组件simpleFormItem来渲染表单各个字段的组件。这样可以做到表单的复用,减少代码量。
<template>
<div class="form">
<Form ref="formRef" :model="record">
<Row>
<template v-for="schema in config.schemas" :key="schema.field">
<Col :span="getColWidth(schema)">
<SimpleFormItem v-model:value="schema[schema.field]" :schema="schema" :refreshFieldObj="refreshFieldObj"/>
</Col>
</template>
</Row>
</Form>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref,unref, defineProps, watch, nextTick, computed, provide } from 'vue';
import SimpleFormItem from '/@/components/SimpleForm/src/components/SimpleFormItem.vue';
import { Form, Row, Col } from 'ant-design-vue';
const props = defineProps({
record: {
type: Object
},
config: {
type: Object
}
});
provide('formModel', props.record);
provide('formProps', ref(props.config.schemas));
const refreshFieldObj = ref<object>({});
const refreshAPI = (field) => {
if (!field) return;
if (!Object.keys(unref(refreshFieldObj)).includes(field)) {
unref(refreshFieldObj)[field] = 0;
}
unref(refreshFieldObj)[field]++;
};
const wrapWidth = ref(1080);
function getColWidth(schema) {
const compProps = schema.componentProps;
if (compProps?.responsive) {
if (compProps.respNewRow) {
return 24; // 响应式布局下独立成行
} else {
const wrapValue = wrapWidth.value;
if (wrapValue > import.meta.env.VITE_RESP_LG_WIDTH) {
return 8;
} else if (wrapValue > import.meta.env.VITE_RESP_MD_WIDTH) {
return 12;
} else {
return 24;
}
}
}
return schema.colProps?.span;
}
</script>
<style lang="less" scoped>
.views-item {
padding: 20px;
margin-top: 16px;
height: 700px;
overflow-y: scroll;
}
:deep(.ant-input-disabled) {
background-color: transparent;
border: none;
}
:deep(.ant-form-item-label > label) {
white-space: normal;
display: inline;
line-height: 32px;
}
</style>
<style lang="less">
.ant-input-affix-wrapper-disabled{
background-color: #fff;
}
.ant-select-disabled {
.ant-select-selector {
border: none !important;
background-color: transparent !important;
padding-left: 0 !important;
}
.ant-select-selection-item {
color: rgb(0 0 0 / 85%) !important;
}
.ant-select-arrow {
display: none;
}
}
</style>
当然如果个性化差异比较大,也可以自己写手写表单的各个组件。
<template>
<template>
<div class="views-item">
<Form ref="formRef" :model="record">
<Row>
<Col :span="12">
<FormItem label="责任类型" name="responsibilityType" :rules="[{ required: true, message: '请选择责任类型' }]">
<Select v-model="record.responsibilityType" :options="responsibilityTypeOptions" placeholder="请选择责任类型" allowClear />
</FormItem>
</Col>
<!--以下不一一列举-->
</Row>
</Form>
</div>
</template>
<style lang="less" scoped>
:deep(.ant-form-item-label > label) {
white-space: normal;
display: inline;
line-height: 32px;
}
</style>
<style lang="less">
.ant-select-disabled {
.ant-select-selector {
border: none !important;
background-color: transparent !important;
padding-left: 0 !important;
}
.ant-select-selection-item {
color: rgb(0 0 0 / 85%) !important;
}
.ant-select-arrow {
display: none;
}
}
</style>
如果想主动进行表单校验,可以使用ref来获取表单实例,然后调用validate方法进行校验。这里校验的返回值是一个Promise,需要使用await进行等待。resolve的值是一个对象,如果校验成功则为表单包含数据,如果校验失败则为失败信息。
const formRef = ref(); // 表单实例
const validate = async () => { // 表单校验
return await unref(formRef)?.validate(); // 表单校验
}
也可以使用相同方法触发重置表单(resetFields)、移除校验结果(clearValidate)等操作。
移动端
项目使用了uniapp的组件,组件源码均在路径@/uni_module下,表单组件在@/uni_module/uni-forms/components下,配置项和PC端类似。参照实际情况即可,可以自己编写也可以直接使用。