Uniapp微信小程序实现简易生成表单生成器

1 篇文章 0 订阅
1 篇文章 0 订阅

在开发一些填报小程序,一些小型办公小程序的时候,难免会遇到较多的需要填写的表单信息,纯手撸表单耗时耗力。

TIP:类似于这种十种类型的表单,每种类型的表单并不一样

在这里插入图片描述
下面将分为三个部分

一、创建对应类型表单的结构体

下面是新建商机的表单结构体
字段详情看注释

//新建商机
export function Oppor() {
	return [{
			label: '客户名称', //表单label文字
			key: 'customer', //表单对应的字段属性名
			name: 'customername', //下拉选项中文名的属性名
			id: 'customerid', //下拉选项的id属性名
			formType: 'select',//表单类型 默认为单行文本
			remoteName: 'getCustomerName',//下拉框远程方法
			required: true,//必填校验
		}, {
			label: '商机名称',
			key: 'opportunityname',
			required: true,
		},
		{
			label: '客户对接人',
			key: 'customerdock',
			required: true,
		},
		{
			label: '预计金额',
			key: 'estimatedamount',
			unitName: '元',
			required: true,
		},
		{
			label: '商机描述',
			key: 'opportunitydescribe',
			formType: 'textarea',
			required: true,
		},
		{
			label: '工时',
			key: 'workhour',
			unitName: '时', //表单内容单位
			required: true,
		}
	]
}

二、对应的表单生成器模板

formProps就是上面的表单结构体
submitForm是保存事件(如有想法可改为插槽)
注意!!! 因为uniapp不支持通过props传子组件Function
所以remoteFun对应表单的远程方法,将通过另一种形式传递,并将修改uni-data-select组件的内部方法,实现远程调用接口。

	<DailyFormTemplate ref="dailyFormTemplate" @submitForm="submitForm"  :formProps="formProp"></DailyFormTemplate>

//js部分
//对应的远程方法
import {getProductLine,getCustomerName,getOpportunityName,getProjectName,getProductByProject,getProductByProductLine} from '@/http/api.js'
export default {
		components:{
			DailyFormTemplate
		},
		data() {
			return {
			//我们需要将remoteFun传进子组件DailyFormTemplate ,表单生成模板中
				remoteFun:{
				//标题一中remoteName绑定的对应的方法名
					getCustomerName,
				}
			}
		},
		mounted(){
		//我们需要将remoteFun传进子组件DailyFormTemplate ,表单生成模板中,初始化方法将remoteFun传入
			this.setRemote();
		},
		methods:{
		setRemote(){
			//将remoteFun传入,通过调用dailyFormTemplate里面定义的setRemote方法
		 	this.$refs.dailyFormTemplate.setRemote(this.remoteFun)
			},
		}
}

三、生成器模板代码

注意!!! 需要注意的是当前并不能直接使用远程方法,因为uni-data-select组件并不支持远程方法渲染,会导致数据无法回显,需要注意第四阶段进入uni-data-select组件修改

<template>
	<view class="continer">
		<uni-forms ref="form" :modelValue="form" :rules="rules">
			<view class="form_element" v-for="(item,index) in formProps" :key="index">

				<view class="form_title">
					<span v-if="item.required" class="is-required">*</span>
					{{item.label}}
				</view>
				<view v-if="!item.formType">
					<uni-forms-item :required="item.required?item.required:false" :name="item.key">
						<view class="input_box">
							<input :ref="item.key" class="uni-input formInput" v-model="form[item.key]"
								:placeholder="'请填写'+item.label" />
							<view class="unit" v-if="item.unitName">{{item.unitName}}</view>
						</view>
					</uni-forms-item>
				</view>
				<view v-if="item.formType==='select'">
					<uni-forms-item :required="item.required?item.required:false" :name="item.key">

						<uni-data-select :ref="item.key" v-model="form[item.key]" :getObjectParam="getObjectParam"
							:placeholder="'请选择'+item.label" @change="onchange($event,item)">
						</uni-data-select>
					</uni-forms-item>
					<!-- <input class="uni-input formInput" v-model="form[item.key]" :placeholder="'请填写'+item.label" /> -->
				</view>
				<view v-if="item.formType==='textarea'">
					<uni-forms-item :required="item.required?item.required:false" :name="item.key">

						<uni-easyinput :ref="item.key" type="textarea" :maxlength="-1" placeholderStyle="fontSize:28upx"
							v-model="form[item.key]" :placeholder="'请填写'+item.label" />
					</uni-forms-item>
					<!-- <input class="uni-input formInput" v-model="form[item.key]" :placeholder="'请填写'+item.label" /> -->
				</view>
			</view>
		</uni-forms>
	</view>
</template>

<script>
	import formTypeMap from '../js/RelationClass.js'
	export default {
		props: {
			formProps: {
				type: Array,
				default: () => []
			},


		},
		computed: {
			reData: {
				get() {
					return function(val) {
						const that = this;
						if (this.remote) {
							return that.remote[val]();
						}
						return []

					}
				},
				set() {}

			},
		},
		data() {
			return {
				getObjectParam: {
					text: 'text',
					value: 'value'
				},
				remoteObj: {
					remoteOption: []
				},
				remote: null,
				form: {},
				// 校验规则
				rules: {},
			}
		},
		mounted() {

			this.setRules();

		},
		options: {
			styleIsolation: 'shared'
		},
		methods: {
			initSelect() {
				this.formProps.forEach(async item => {
					if (item.remoteName) {
						this.$refs[item.key][0].setMixinDatacomResData(this.remote[item.remoteName]())
					}

				})

			},
			setRemote(param) {
				this.remote = param
				
				this.initSelect();
			},
			async getRemoteFun(val) {
				let arr = await this.remote[val]()
				console.log(arr)
				return arr
			},
			setRules() {
				this.rules = {}
				this.formProps.forEach(item => {
					if (item.required) {
						this.rules[item.key] = {
							rules: [{
								required: true,
								errorMessage: `${item.label}不能为空`
							}]
						}
					}
				})
			},
			onchange(param, item) {
				// console.log(param,item)
				//判断该表单是否有关联操作
				if (item.relationForm) {

					item.relationForm.forEach(temp => {
						// formTypeMap.forEach(ftype=>{
						// 	if(ftype.type ===item.formType){
						// 		ftype.feedbackType(temp.type);
						// 	}
						// })
						if (item.formType === 'select') {
							//如果是下拉框
							if (temp.type === 'reload') {
								//重新加载
								let dataArr = []
								if (temp.searchParam) {
									temp.searchParam.forEach(ele => {

										dataArr.push({
											field: ele.field,
											operator: ele.operator,
											value: ele.fieldParam === 'id' ? param.value : param
												.text
										});
									})
								}
								//清除关联表单的内容
								this.$refs[temp.key][0].clearCurrent()
								this.$refs[temp.key][0].setMixinDatacomResData(this.remote[temp.event](dataArr))
							}

						}

					})
				}


			},
			validateForm() {
				let self = this;
				self.$refs.form.validate().then(res => {
					self.$emit("submitForm", res)

				}).catch(err => {
					console.log(err)
				})
			}
		}
	}
</script>

<style scoped>
	.continer {
		width: 100%;
		height: 100%;
	}

	.form_element {
		width: calc(100% - 40upx);
		padding: 20upx;
		border-bottom: 1px solid #ccc;
	}

	.form_title {
		width: 100%;
		font-weight: 800;
		font-size: 32upx;

	}

	.input_box {
		display: flex;
		align-items: center;
	}

	.unit {
		margin-right: 20upx;
	}

	/* ::v-deep .uni-section .uni-section-header__content {
		font-weight: 800;
	
	}
	
	::v-deep .uni-section .uni-section-header {
		padding: 0;
	} */
	::v-deep .uni-input {
		padding: 20upx 0 0 0;

	}

	::v-deep .uni-select {
		border: none;
		padding: 20upx 0 0 0;
	}

	::v-deep .uni-forms-item__label {
		display: none;
	}

	::v-deep .is-input-border {
		border: none;
		padding: 20upx 0 0 0;
	}

	::v-deep .input-padding {
		padding: 0;
	}

	::v-deep .uni-easyinput__content-textarea {}

	::v-deep .uni-textare {}

	.is-required {
		color: #dd524d;
		font-weight: bold;
		margin-right: 10upx;
	}
</style>

四、进入uni-data-select组件,添加一个支持远程接口的方法

//在methods中新增一个自定义方法,通过第三阶段initSelect的方法中调用,将对应的Promise对象传入,来修改组件的数据
	setMixinDatacomResData(param){
				param.then(res=>{
					this.mixinDatacomResData = res;
				})
				
			}

效果图
在这里插入图片描述

五、进阶表单——关联关系

由一个表单影响其他表单的操作-------关联表单关系
我们要回到第一部分,对应类型表单的结构体
例如下图,我们需要在项目名称下拉发生change的时候,改变产品名称表单的数据,需要通过relationForm数组绑定(可绑定多个)
relationForm的
key:代表对应受到影响的表单key,
type:受影响类型,
event:绑定受到影响后需要执行的远程方法,
searchParam:为调用方法需要传递的部分参数

//产品交付
export function BusinessDailyProduct() {
	return [{
			label: '项目名称',
			key: 'project',
			name: 'projectname', //下拉选项中文名的属性名
			id: 'projectid', //下拉选项的id属性名
			remoteName: 'getProjectName',
			formType: 'select',
			relationForm:[{key:'product',type:'reload',event:'getProductByProject',searchParam:[{fieldParam:'id', field:'projectid',operator:'eq',value:''}]}], //关联表单及其触发事件绑定
			required: true,
		}, {
			label: '产品名称',
			formType: 'select',
			key: 'product',
			name: 'productname', //下拉选项中文名的属性名
			id: 'productid', //下拉选项的id属性名
			// remoteName: 'getProductByProject',
			required: true,
		}, {
			label: '工时',
			key: 'workhour',
			unitName: '时',
			required: true,
		},
		{
			label: '工作内容',
			key: 'workcontent',
			formType: 'textarea',
			required: true,
		}, {
			label: '存在问题',
			key: 'existproblem',
			formType: 'textarea',
			required: true,
		},

	]
}


//对应的受影响的远程方法----上面的event
//根据项目获取对应的产品
export async function getProductByProject(searchCondition) {

	let res = await request({
		url: '/business/product/manage/list',
		method: 'post',
		data: new SearchCondition({searchCondition,}),

	})
	let arr = res.data.data.list.map(item => ({
		text: item.productname,
		value: item.id,
		...item
	}))

	return await arr;

}

下班了!,再见!!!!,下回聊

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要在Uniapp中开发微信小程序界面,你可以使用uni-form组件来创建,并使用uni-input组件来添加字段。 首先,你需要在页面中引入uni-form组件,然后在模板中使用uni-form标签来包裹内容。在uni-form标签中,你可以使用uni-input标签来创建输入框、uni-checkbox标签来创建复选框、uni-radio标签来创建选框,等等。 下面是一个示例代码,展示了如何在Uniapp中创建一个简界面: ```html <template> <view> <uni-form> <uni-input type="text" v-model="name" placeholder="请输入姓名"></uni-input> <uni-input type="number" v-model.number="age" placeholder="请输入年龄"></uni-input> <uni-checkbox-group v-model="hobbies"> <uni-checkbox value="reading">阅读</uni-checkbox> <uni-checkbox value="music">音乐</uni-checkbox> <uni-checkbox value="sports">运动</uni-checkbox> </uni-checkbox-group> <uni-radio-group v-model="gender"> <uni-radio value="male">男</uni-radio> <uni-radio value="female">女</uni-radio> </uni-radio-group> <uni-button type="primary" @click="submitForm">提交</uni-button> </uni-form> </view> </template> <script> export default { data() { return { name: '', age: '', hobbies: [], gender: '' }; }, methods: { submitForm() { // 在这里进行验证和提交逻辑 // 可以使用this.name、this.age等来获取字段的值 } } }; </script> ``` 在上面的示例中,我们使用了v-model指令来绑定字段的值到data中的数据。当用户在输入框中输入内容时,data中的对应字段也会更新。使用@click事件监听提交按钮的点击事件,并在submitForm方法中进行验证和提交逻辑。 要进行验证,你可以在submitForm方法中使用条件判断来检查字段的值是否符合要求。例如,你可以检查姓名是否为空、年龄是否为数字等。 这只是一个简的示例,你可以根据自己的需求进行更复杂的验证和提交逻辑。希望对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值