examtest_mp/components/dynamicForm/index.js

292 lines
7.9 KiB
JavaScript

// components/dynamicForm/index.js
import formatTime from './utils/formatTime';
Component({
/**
* 组件的属性列表
*/
properties: {
formData: Array,
showSubmitBtn: {
type: Boolean,
value: true
},
toSubmit: Number
},
//监听数据变化, 当toSubmit 值变化时, 代表父组件点击提交案例事件
observers: {
'toSubmit': function (e) {
if (e) {
this.formSubmit();
}
},
'formData': function () {
this.formInit();
}
},
/**
* 组件的初始数据
*/
data: {
pickerMap: {},
fileMap: {},
inputMap: {}
},
lifetimes: {
attached: function () {
this.formInit();
},
moved: function () { },
detached: function () { },
},
pageLifetimes: {
// 组件所在页面的生命周期函数
show: function () { },
hide: function () { },
resize: function () { },
},
/**
* 组件的方法列表
*/
methods: {
//表单初始化
formInit() {
const pickerMap = {}, fileMap = {}, inputMap = {}, dateMap = {};//存储各表单变化后的值,表单id为索引
const pickers = [], files = [], inputs = [], datePickers = [];
this.data.formData.forEach(val => {
switch (val.type) {
case 'picker':
pickers.push(val);
break;
case 'file':
files.push(val);
break;
case 'input':
case 'textarea':
inputs.push(val);
break;
case 'date':
datePickers.push(val);
break;
default:
break;
}
});
pickers.forEach(val => {
pickerMap[val.id] = {
original: val,
hasChoose: val.defaultIdx != 'undefined',
error:null,
idx: val.defaultIdx || 0
};
});
files.forEach(val => {
fileMap[val.id] = {
original: val,
error: null,
list: val.fileList
};
});
inputs.forEach(val => {
inputMap[val.id] = {
original: val,
value: val.defaultValue || '',
placeholder: val.placeholder,
error: null,
rules: val.rules ? val.rules.map(val => {
val.regular = new RegExp(val.regular);
return val;
}) : []
};
});
datePickers.forEach(val => {
dateMap[val.id] = {
original: val,
config: val.config,
completeTime: val.completeTime,
show: false,
hasChoose: !!val.config.initStartTime,
error: null,
startDate: val.config.initStartTime || formatTime(),
endDate: val.config.initEndTime || formatTime()
};
if (!val.completeTime){
dateMap[val.id].startDate = dateMap[val.id].startDate.split(' ')[0];
dateMap[val.id].endDate = dateMap[val.id].endDate.split(' ')[0];
}
});
this.setData({
pickers,
inputs,
datePickers,
files,
pickerMap,
inputMap,
fileMap,
dateMap
});
},
//提交表单
formSubmit() {
let formData = {};
const { pickerMap, inputMap, dateMap, fileMap } = this.data;
for (let i in this.data) { //获取表单数据后缀为Map
if (i.match(/Map$/)) {
formData = Object.assign({}, formData, this.data[i]);
}
}
let hasError = false;
for (let i in formData) {//循环验证所有表单数据规则
let info = formData[i];
if (info.original.type === 'input' || info.original.type === 'textarea') {
if (!info.value){
if (info.original.isRequired){
info.error = info.original.lable + '不可为空';
hasError = true;
}
} else if (info.rules){
for (let val of info.rules) {
if (!info.value.match(val.regular)) {
info.error = val.tips || '格式有误';
hasError = true;
break;
}
}
}
this.setData({
[`inputMap.${i}`]: info
});
} else if (info.original.type === 'file') {
if (info.list.length === 0 && info.original.isRequired) {
let error = '请选择文件';
if (info.original.accept === 'video') {
error = '请选择视频';
} else if (info.original.accept === 'image') {
error = '请选择图片';
}
info.error = error;
hasError = true;
this.setData({
[`fileMap.${i}`]: info
});
}
} else if (info.original.type === 'picker' || info.original.type === 'date'){
if (!info.hasChoose && info.original.isRequired){
info.error = '请选择' + info.original.lable;
hasError = true;
this.setData({
[`${info.original.type}Map.${i}`]: info
});
}
}
}
if (hasError) {
wx.showToast({
title: '表单填写有误',
icon: 'none'
});
return;
}
this.triggerEvent('dynamicFormSubmit', formData);
console.log(formData);
},
//更新数据劫持
updateData(key,val){
this.setData({
[key]: val
});
this.triggerEvent('dynamicFormChange', { key, val});
},
//显示选择器
datePickerShow(e) {
if (e.target.dataset.disabled) {
return;
}
this.setData({
[`dateMap.${e.target.dataset.id}.show`]: true
});
},
//隐藏时间选择器
datePickerHide(id) {
if (typeof id === 'object') {
id = id.target.id;
}
this.setData({
[`dateMap.${id}.show`]: false
});
},
//设置选择器时间
setPickerTime(e) {
const {dateMap} = this.data;
const { startTime, endTime } = e.detail;
const date = dateMap[e.target.id];
if (!date.hasChoose){
date.hasChoose = true;
date.error = null;
}
date.show = false;
date.startDate = date.completeTime ? startTime :startTime.split(' ')[0];
date.endDate = date.completeTime ?endTime :endTime.split(' ')[0];
this.updateData(`dateMap.${e.target.id}`,date);
},
//输入框
onInput(e) {
const { value } = e.detail;
const info = this.data.inputMap[e.target.id] || {};
if (!info) {
return;
}
info.value = e.detail.value;
info.error = null;
if (info.rules && info.value) {
for (let val of info.rules) {
if (!info.value.match(val.regular)) {
info.error = val.tips || '格式有误';
break;
}
}
}
this.updateData(`inputMap.${e.target.id}`, info);
},
//picker选择
onPickerChange(e) {
const { id } = e.target;
const picker = this.data.pickerMap[id];
if(!picker.hasChoose){
picker.hasChoose = true;
picker.error = null;
}
picker.idx = e.detail.value;
picker.data = this.data.pickers.filter(val => val.id === id)[0].range[e.detail.value];
this.updateData(`pickerMap.${e.target.id}`, picker);
},
// 选择文件
onFileRead(e) {
console.log(e);
for (let val of e.detail.file) {
const size = this.data.fileMap[e.target.id].original.maxSize;
if (val.size > size * 1024 * 1024) {
wx.showToast({
title: `请选择${size}MB以内的文件`,
icon: 'none'
});
return;
}
}
const files = this.data.fileMap[e.target.id];
files.error = null;
files.list = files.list.concat(e.detail.file);
this.updateData(`fileMap.${e.target.id}`, files);
},
//删除文件
onFileDelete(e) {
console.log(e);
const files = this.data.fileMap[e.target.id].list;
files.splice(e.detail.index, 1);
this.updateData(`fileMap.${e.target.id}.list`, files);
}
}
});