292 lines
7.9 KiB
JavaScript
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);
|
|
}
|
|
}
|
|
});
|