赞
踩
在用户下单过程中,需要填写用户信息,包括:姓名,手机号,身份证号,邮箱等。这部分需要填写的内容由后端进行配置,可能只需要填写姓名+手机号。可能需要填写姓名+手机号+身份证号。后端配置的内容包含输入框标题text和输入框的key,用户个数可以添加,新增的用户同样满足后端配置的填写表单要求。
我们面对这个需求,可以想到的是首先把表单写成固定的表单,然后根据后端配置进行判断展示,但是这样对于后端配置的text和key就不能很好适配。
那我们考虑把text和key需要变成一个变量运用起来。
现在还有一个问题就是在于表单内容类型,包含普通输入框text,数字输入框number,身份证号输入框idcard带图片识别身份证号功能。
有这么多种类型的输入框,我们首先需要考虑将所有的输入框类型集合到一个输入框组件中。外部传递一个类型type,我们就返回对应的输入框。
然后对于后端配置的内容,我们根据它们返回的格式为data:[{text:“XXX”,key:“XXX”}]。我们需要对data进行循环再展示。
输入框组件 components/PersonInput.vue <template> <view class="conter"> <view class="label"> {{ label }} </view> <view> <input v-if="type === 'text'" :type="type" :value="inputVal" :placeholder="placeholder" class="input" placeholder-class="placeholder" @input="fieldInput" @blur="fiedBlur" /> <input v-if="type === 'number'" :type="type" :value="inputVal" :placeholder="placeholder" class="input" placeholder-class="placeholder" @input="fieldInput" @blur="fiedBlur" /> <input v-if="type === 'idcard'" :type="type" :value="inputVal" :placeholder="placeholder" class="input" placeholder-class="placeholder" @input="fieldInput" @blur="fiedBlur" /> <!-- 包含 --> <view v-if="label.includes('身份证') || type === 'idcard'" class="upload-box" > <view class="upload-item" @click="uploadIdCard"> <image class="img" :src="cardImg ? cardImg : imgDefault" mode="scaleToFill" /> <u-loading class="loading" mode="circle" color="#5fc970" :show="showLoading"></u-loading> </view> </view> </view> </view> </template> export default { name: "PersonInput", props: { // 输入框类型 type: { type: String, default: "text", }, // 标题文本 label: { type: String, default: "", }, // 输入框提示 placeholder: { type: String, default: "", }, // 输入框的值 inputVal: { type: String, default: "", }, //验证码 core: { type: String, default: "", }, boxType:{ type:[String,Number], default: "", }, cardImg:{ type:String, default: "", } }, data() { return { locationImg: "XXXXXX/", url: fileUrl, // 上传图片地址 file: null, //文件 isUploadRe: false, // imgDefault: "/u001.png",//默认的展示图片 showLoading:false,//是否展示加载动画 }; }, methods: { fieldInput(e) { this.$emit("input", e.detail.value); }, fiedBlur(e) { this.$emit("blur", e.detail.value); }, // 图片上传成功回调主要是用于身份证这里 uploadIdCard() { uni.chooseImage({ count: 1, sizeType: ["original", "compressed"], //可以指定是原图还是压缩图,默认二者都有 // sourceType: ['camera'], //从相册选择 success: (chooseImageRes) => { this.showLoading = true; const tempFilePaths2 = chooseImageRes.tempFilePaths; uni.uploadFile({ url: `XXXXXXX`, filePath: tempFilePaths2[0], formData: { parentKey: "miniApp", rentId: rentId, }, name: "file", success: (uploadFileRes) => { this.showLoading = false; let res = JSON.parse(uploadFileRes.data); if(res.state){ // 识别成功之后,调用回调函数 // "type": "Front", "name": "姓名","id": "身份证号","addr": "地址","gender": "性别" let param = { contact:res.result.name, idCard:res.result.id, } this.$emit('recognize',param,this.boxType,tempFilePaths2[0]) }else{ this.showLoading = false; uni.showToast({ title: `识别身份证号出错`, duration: 2000, icon: "none", }); } }, fail: (err) => { uni.showToast({ title: `${err}`, duration: 2000, icon: "none", }); }, }); }, }); }, }, };
下单页面使用 order.vue <template> //用户模块,用户只有一份信息 <view class="order-input" v-for="(item, index) in contacts" :key="index" > <PersonInput type="text" box-type="linkaddress" :cardImg="linkaddress.cardImg" :label="item.text" :inputVal="linkaddress[item.key]" v-model="linkaddress[item.key]" :placeholder="'请输入' + item.text" @recognize="recognize" @input=" e => { fieldInput(e, item.key); } " ></PersonInput> </view> // 游客信息 可以填写多个游客信息,选择人数的 <view class="order-input" v-for="(item, index) in formDate" :key="item.id" > <template v-for="(orderItem, itemIndex) in passenger" > <PersonInput type="text" :box-type="index" :cardImg="formDate[index].cardImg" :key="itemIndex" :label="orderItem.text" :inputVal="formDate[index][orderItem.key]" v-model="formDate[index][orderItem.key]" :placeholder="'请输入' + orderItem.text" @recognize="recognize" @input=" e => { fieldInput(e, orderItem.key); } " @blur=" e => { orderItem.key == 'idCard' ? fiedBlur(e, index) : ''; } " ></PersonInput> </template> <view class="chooseaddress" @tap="chooseaddress(index)" >选择</view > <view class="delbox" @tap.stop="DelRoom(index)" v-if="value > 1"> <text class="ddm-wc"></text> </view> </view> </template> data() { return { // 用户表单 linkaddress: {}, //游客数据,多条 formDate: [ { id: Date.now(), userName: "", idCard: "", singleRoomNum: 0 } ], } } // 手动选择联系人之后的数据回填 setNowItem(itemObj, index, cardImg) { if (index == "linkaddress") { let item = Object.assign(this.linkaddress, itemObj); this.contacts.forEach(obj => { if (Object.keys(item).includes(obj.key)) { this.$set(this.linkaddress, obj.key, item[obj.key]); } obj.key === "phoneNum" && this.$set(this.linkaddress, obj.key, item.telno); obj.key === "personAddress" && this.$set(this.linkaddress, obj.key, item.detailaddress); }); this.$set(this.linkaddress, "cardImg", cardImg); } else { let nowIndex = parseInt(index); let item = Object.assign(this.formDate[nowIndex], itemObj); this.passenger.forEach(obj => { if (Object.keys(item).includes(obj.key)) { this.$set(this.formDate[nowIndex], obj.key, item[obj.key]); } obj.key === "phone" && this.$set(this.formDate[nowIndex], obj.key, item.telno); obj.key === "userName" && this.$set(this.formDate[nowIndex], obj.key, item.contact); obj.key === "personAddress" && this.$set(this.formDate[nowIndex], obj.key, item.detailaddress); }); this.$set(this.formDate[nowIndex], "cardImg", cardImg); } }, /** * @description 身份证信息图片识别 * @param {res} Object 身份证识别结果数据 * */ recognize(res, index, cardImg) { this.setNowItem(res, index, cardImg); // }, /** * @description 用于处理新增客户信息时的动态添加对象 * @param {type} 'fictitious'为虚拟实名信息,即生成得客户信息需要有数据 * @param {index} 循环时的循环下标,用于处理一些循环事件 */ getPersonObj(type, index) { let newPersonObj = {}; newPersonObj = this.passenger.reduce( (acc, cur) => { acc[cur.key] = ""; return acc; }, {} ); newPersonObj = { ...newPersonObj, ...{ id: Date.now(), singleRoomNum: 0 } }; return newPersonObj; }, /** * @description 用于联系人过校验的方法 * */ validatePerson() { // 联系人过校验方法 for (let i = 0; i < this.contacts.length; i++) { let item = this.contacts[i]; if ( this.linkaddress.hasOwnProperty(item.key) && this.linkaddress[item.key] == "" ) { this.myShowToast(`请填写${item.text}!`); return false; } if (item.key == "phoneNum") { if ( this.linkaddress.hasOwnProperty("phoneNum") && !this.myreg.test(this.linkaddress.phoneNum) ) { uni.showToast({ title: "请输入正确的手机号码", icon: "none", duration: 2000 }); return false; } } else if ( this.linkaddress.hasOwnProperty("idCard") && !this.validateIdCard(this.linkaddress.idCard) ) { this.myShowToast(`请输入正确的身份证号`); return false; } } return true; }, /** * @description 用于游客信息过校验的方法 * */ validateFormDate(index) { // 联系人过校验方法 for ( let i = 0; i < this.passenger.length; i++ ) { let item = this.passenger[i]; if ( this.formDate[index].hasOwnProperty(item.key) && this.formDate[index][item.key] == "" ) { this.myShowToast(`请填写游客${index + 1}的${item.text}!`); return false; } if (item.key == "phone") { if ( this.formDate[index].hasOwnProperty("phone") && !this.myreg.test(this.formDate[index].phone) ) { uni.showToast({ title: `请正确填写游客${index + 1}手机号码`, icon: "none", duration: 2000 }); return false; } } if (item.key == "idCard") { if ( this.formDate[index].hasOwnProperty("idCard") && !this.validateIdCard(this.formDate[index].idCard) ) { this.myShowToast(`请正确填写游客${index + 1}身份证号`); return false; } } } return true; }, // 提交表单时的校验 submit(){ // 校验联系人输入信息格式 if (!this.validatePerson()) return false; for (let i = 0; i < this.formDate.length; i++) { if (!this.validateFormDate(i)) return false; } }
呼~经过上面这些代码,包括初始化,包括选择联系人信息的回填,都要于后端配置的信息进行挂钩。提交表单的时候还需要对配置的表单内容进行校验。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。