diff --git a/test_mini/app.json b/test_mini/app.json
index 8bc0cf8..cc7cb9c 100644
--- a/test_mini/app.json
+++ b/test_mini/app.json
@@ -31,7 +31,11 @@
"pages/qtest/form",
"pages/main/start",
"pages/exam/index",
- "pages/exam/note"
+ "pages/exam/note",
+ "pages/admin/index",
+ "pages/admin/login",
+ "pages/admin/exam/add",
+ "pages/admin/exam/add2"
],
"window": {
"backgroundTextStyle": "light",
@@ -88,7 +92,7 @@
},
"plugins": {
"tencentvideo": {
- "version": "1.3.15",
+ "version": "1.3.31",
"provider": "wxa75efa648b60994b"
}
},
diff --git a/test_mini/components/dynamicForm/components/timePicker/timePicker.js b/test_mini/components/dynamicForm/components/timePicker/timePicker.js
new file mode 100644
index 0000000..0eb7587
--- /dev/null
+++ b/test_mini/components/dynamicForm/components/timePicker/timePicker.js
@@ -0,0 +1,566 @@
+
+Component({
+ /**
+ * 组件的属性列表
+ */
+ properties: {
+ pickerShow: {
+ type: Boolean,
+ observer:function(val){ //弹出动画
+ // console.log(this.data);
+ if(val){
+ let animation = wx.createAnimation({
+ duration: 500,
+ timingFunction: "ease"
+ });
+ let animationOpacity = wx.createAnimation({
+ duration: 500,
+ timingFunction: "ease"
+ });
+ setTimeout(() => {
+ animation.bottom(0).step();
+ animationOpacity.opacity(0.7).step();
+ this.setData({
+ animationOpacity: animationOpacity.export(),
+ animationData: animation.export()
+ })
+ }, 0);
+ }else{
+ let animation = wx.createAnimation({
+ duration: 100,
+ timingFunction: "ease"
+ });
+ let animationOpacity = wx.createAnimation({
+ duration: 500,
+ timingFunction: "ease"
+ });
+ animation.bottom(-320).step();
+ animationOpacity.opacity(0).step();
+ this.setData({
+ animationOpacity: animationOpacity.export(),
+ animationData: animation.export()
+ });
+ }
+
+ // 在picker滚动未停止前点确定,会使startValue数组各项归零,发生错误,这里判断并重新初始化
+ // 微信新增了picker滚动的回调函数,已进行兼容
+ if(this.data.startValue&&this.data.endValue){
+ let s = 0, e = 0;
+ let conf = this.data.config;
+
+ this.data.startValue.map(val => {
+ if (val == 0) {
+ s++
+ }
+ })
+ this.data.endValue.map(val => {
+ if (val == 0) {
+ e++;
+ }
+ });
+ let tmp={
+ hour:4,
+ minute:5,
+ second:6
+ }
+ let n = tmp[conf.column];
+ if (s>=n || e>=n) {
+ this.initPick(this.data.config);
+ this.setData({
+ startValue: this.data.startValue,
+ endValue: this.data.endValue,
+ });
+ }
+ }
+
+
+ }
+ },
+ config: Object
+ },
+
+ /**
+ * 组件的初始数据
+ */
+ data: {
+ // pickerShow:true
+ // limitStartTime: new Date().getTime()-1000*60*60*24*30,
+ // limitEndTime: new Date().getTime(),
+ // yearStart:2000,
+ // yearEnd:2100
+ },
+ detached: function() {
+ console.log("dele");
+ },
+ attached: function() {},
+ ready: function() {
+ this.readConfig();
+ this.initPick(this.data.config || null);
+ this.setData({
+ startValue: this.data.startValue,
+ endValue: this.data.endValue,
+ });
+
+
+
+
+ },
+ /**
+ * 组件的方法列表
+ */
+ methods: {
+ //阻止滑动事件
+ onCatchTouchMove(e) {
+
+ },
+ //读取配置项
+ readConfig() {
+ let limitEndTime = new Date().getTime();
+ let limitStartTime = new Date().getTime() - 1000 * 60 * 60 * 24 * 30;
+ if (this.data.config) {
+ let conf = this.data.config;
+
+ if (typeof conf.dateLimit == "number") {
+ limitStartTime =
+ new Date().getTime() - 1000 * 60 * 60 * 24 * conf.dateLimit;
+ }
+ if(conf.limitStartTime){
+
+ limitStartTime = new Date(conf.limitStartTime.replace(/-/g,'/')).getTime();
+ }
+
+ if (conf.limitEndTime) {
+ limitEndTime = new Date(conf.limitEndTime.replace(/-/g, '/')).getTime();
+ }
+
+ this.setData({
+ yearStart: conf.yearStart || 2000,
+ yearEnd: conf.yearEnd || 2100,
+ endDate: conf.endDate || false,
+ dateLimit: conf.dateLimit || false,
+ hourColumn:
+ conf.column == "hour" ||
+ conf.column == "minute" ||
+ conf.column == "second",
+ minColumn: conf.column == "minute" || conf.column == "second",
+ secColumn: conf.column == "second"
+ });
+ }
+
+ let limitStartTimeArr = formatTime(limitStartTime);
+ let limitEndTimeArr = formatTime(limitEndTime);
+
+ this.setData({
+ limitStartTime,
+ limitStartTimeArr,
+ limitEndTime,
+ limitEndTimeArr
+ });
+ },
+ //滚动开始
+ handlePickStart:function(e){
+ this.setData({
+ isPicking:true
+ })
+ },
+ //滚动结束
+ handlePickEnd:function(e){
+ this.setData({
+ isPicking:false
+ })
+ },
+ onConfirm: function() {
+ //滚动未结束时不能确认
+ if(this.data.isPicking){return}
+ let startTime = new Date(this.data.startPickTime.replace(/-/g, "/"));
+ let endTime = new Date(this.data.endPickTime.replace(/-/g, "/"));
+ if (startTime <= endTime || !this.data.endDate) {
+ this.setData({
+ startTime,
+ endTime
+ });
+ let startArr = formatTime(startTime).arr;
+ let endArr = formatTime(endTime).arr;
+ let format0 = function(num){
+ return num<10?'0'+num:num
+ }
+
+ let startTimeBack =
+ startArr[0] +
+ "-" +
+ format0(startArr[1]) +
+ "-" +
+ format0(startArr[2]) +
+ " " +
+ (this.data.hourColumn ? format0(startArr[3]) : "00") +
+ ":" +
+ (this.data.minColumn ? format0(startArr[4]) : "00") +
+ ":" +
+ (this.data.secColumn ? format0(startArr[5]) : "00");
+
+ let endTimeBack =
+ endArr[0] +
+ "-" +
+ format0(endArr[1]) +
+ "-" +
+ format0(endArr[2]) +
+ " " +
+ (this.data.hourColumn ? format0(endArr[3]) : "00") +
+ ":" +
+ (this.data.minColumn ? format0(endArr[4]) : "00") +
+ ":" +
+ (this.data.secColumn ? format0(endArr[5]) : "00");
+
+ let time = {
+ startTime: startTimeBack,
+ endTime: endTimeBack
+ };
+
+ //触发自定义事件
+ this.triggerEvent("setPickerTime", time);
+ this.triggerEvent("hidePicker", {});
+ } else {
+ wx.showToast({
+ icon: "none",
+ title: "时间不合理"
+ });
+ }
+ },
+ hideModal: function() {
+
+ this.triggerEvent("hidePicker", {});
+ },
+ changeStartDateTime: function(e) {
+ let val = e.detail.value;
+
+ this.compareTime(val, "start");
+ },
+
+ changeEndDateTime: function(e) {
+ let val = e.detail.value;
+ this.compareTime(val, "end");
+ },
+ //比较时间是否在范围内
+ compareTime(val, type) {
+ let h = val[3] ? this.data.HourList[val[3]] : "00";
+ let m = val[4] ? this.data.MinuteList[val[4]] : "00";
+ let s = val[5] ? this.data.SecondList[val[5]] : "00";
+ let time =
+ this.data.YearList[val[0]] +
+ "-" +
+ this.data.MonthList[val[1]] +
+ "-" +
+ this.data.DayList[val[2]] +
+ " " +
+ h +
+ ":" +
+ m +
+ ":" +
+ s;
+
+ let start = this.data.limitStartTime;
+ let end = this.data.limitEndTime;
+ let timeNum = new Date(time.replace(/-/g, '/')).getTime();
+ let year, month, day, hour, min, sec, limitDate;
+ let tempArr = []
+
+ if (!this.data.dateLimit){
+ limitDate = [
+ this.data.YearList[val[0]],
+ this.data.MonthList[val[1]],
+ this.data.DayList[val[2]],
+ this.data.HourList[val[3]],
+ this.data.MinuteList[val[4]],
+ this.data.SecondList[val[5]]]
+ } else if (type == "start" && timeNum > new Date(this.data.endPickTime.replace(/-/g, '/')) && this.data.config.endDate) {
+ limitDate = formatTime(this.data.endPickTime).arr;
+
+ } else if (type == "end" && timeNum < new Date(this.data.startPickTime.replace(/-/g, '/'))) {
+ limitDate = formatTime(this.data.startPickTime).arr;
+
+ } else if (timeNum < start) {
+ limitDate = this.data.limitStartTimeArr.arr;
+
+ } else if (timeNum > end) {
+ limitDate = this.data.limitEndTimeArr.arr;
+
+ } else {
+ limitDate = [
+ this.data.YearList[val[0]],
+ this.data.MonthList[val[1]],
+ this.data.DayList[val[2]],
+ this.data.HourList[val[3]],
+ this.data.MinuteList[val[4]],
+ this.data.SecondList[val[5]]
+ ]
+
+ }
+
+ year = limitDate[0];
+ month = limitDate[1];
+ day = limitDate[2];
+ hour = limitDate[3];
+ min = limitDate[4];
+ sec = limitDate[5];
+
+ if (type == "start") {
+ this.setStartDate(year, month, day, hour, min, sec);
+ } else if (type == "end") {
+ this.setEndDate(year, month, day, hour, min, sec);
+ }
+ },
+ getDays: function(year, month) {
+ let daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+ if (month === 2) {
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0
+ ? 29
+ : 28;
+ } else {
+ return daysInMonth[month - 1];
+ }
+ },
+ initPick: function(initData) {
+ const date = initData.initStartTime ? new Date(initData.initStartTime.replace(/-/g, '/')): new Date();
+ const endDate = initData.initEndTime ? new Date(initData.initEndTime.replace(/-/g, '/')) : new Date();
+ // const startDate = new Date(date.getTime() - 1000 * 60 * 60 * 24);
+ const startDate = date;
+ const startYear = date.getFullYear();
+ const startMonth = date.getMonth() + 1;
+ const startDay = date.getDate();
+ const startHour = date.getHours();
+ const startMinute = date.getMinutes();
+ const startSecond = date.getSeconds();
+
+ const endYear = endDate.getFullYear();
+ const endMonth = endDate.getMonth() + 1;
+ const endDay = endDate.getDate();
+ const endHour = endDate.getHours();
+ const endMinute = endDate.getMinutes();
+ const endSecond = endDate.getSeconds();
+
+ let YearList = [];
+ let MonthList = [];
+ let DayList = [];
+ let HourList = [];
+ let MinuteList = [];
+ let SecondList = [];
+
+ //设置年份列表
+ for (let i = this.data.yearStart; i <= this.data.yearEnd; i++) {
+ YearList.push(i);
+ }
+
+ // 设置月份列表
+ for (let i = 1; i <= 12; i++) {
+ MonthList.push(i);
+ }
+ // 设置日期列表
+ for (let i = 1; i <= 31; i++) {
+ DayList.push(i);
+ }
+ // 设置时列表
+ for (let i = 0; i <= 23; i++) {
+ if (0 <= i && i < 10) {
+ i = "0" + i;
+ }
+ HourList.push(i);
+ }
+ // 分|秒
+ for (let i = 0; i <= 59; i++) {
+ if (0 <= i && i < 10) {
+ i = "0" + i;
+ }
+ MinuteList.push(i);
+ SecondList.push(i);
+ }
+
+ this.setData({
+ YearList,
+ MonthList,
+ DayList,
+ HourList,
+ MinuteList,
+ SecondList
+ });
+
+ this.setStartDate(startYear, startMonth, startDay, startHour, startMinute, startSecond);
+ this.setEndDate(endYear, endMonth, endDay, endHour, endMinute, endSecond);
+
+ //!!!
+ // setTimeout(() => {
+ // this.setStartDate(nowYear, nowMonth, nowDay, nowHour, nowMinute)
+ // this.setEndDate(nowYear, nowMonth, nowDay, nowHour, nowMinute)
+ // }, 0);
+ },
+ setPickerDateArr(type, year, month, day, hour, minute, second) {
+ let yearIdx = 0;
+ let monthIdx = 0;
+ let dayIdx = 0;
+ let hourIdx = 0;
+ let minuteIdx = 0;
+ let secondIdx = 0;
+
+ this.data.YearList.map((v, idx) => {
+ if (parseInt(v) === year) {
+ yearIdx = idx;
+ }
+ });
+
+ this.data.MonthList.map((v, idx) => {
+ if (parseInt(v) === month) {
+ monthIdx = idx;
+ }
+ });
+
+ // 重新设置日期列表
+ let DayList = [];
+ for (let i = 1; i <= this.getDays(year, month); i++) {
+ DayList.push(i);
+ }
+
+ DayList.map((v, idx) => {
+ if (parseInt(v) === day) {
+ dayIdx = idx;
+ }
+ });
+ if (type == "start") {
+ this.setData({ startDayList: DayList });
+ } else if (type == "end") {
+ this.setData({ endDayList: DayList });
+ }
+
+ this.data.HourList.map((v, idx) => {
+ if (parseInt(v) === parseInt(hour)) {
+ hourIdx = idx;
+ }
+ });
+
+ this.data.MinuteList.map((v, idx) => {
+ if (parseInt(v) === parseInt(minute)) {
+ minuteIdx = idx;
+ }
+ });
+ this.data.SecondList.map((v, idx) => {
+ if (parseInt(v) === parseInt(second)) {
+ secondIdx = idx;
+ }
+ });
+
+ return {
+ yearIdx,
+ monthIdx,
+ dayIdx,
+ hourIdx,
+ minuteIdx,
+ secondIdx
+ };
+ },
+ setStartDate: function(year, month, day, hour, minute, second) {
+ let pickerDateArr = this.setPickerDateArr(
+ "start",
+ year,
+ month,
+ day,
+ hour,
+ minute,
+ second
+ );
+ this.setData({
+ startYearList: this.data.YearList,
+ startMonthList: this.data.MonthList,
+ // startDayList: this.data.DayList,
+ startHourList: this.data.HourList,
+ startMinuteList: this.data.MinuteList,
+ startSecondList: this.data.SecondList,
+ startValue: [
+ pickerDateArr.yearIdx,
+ pickerDateArr.monthIdx,
+ pickerDateArr.dayIdx,
+ pickerDateArr.hourIdx,
+ pickerDateArr.minuteIdx,
+ pickerDateArr.secondIdx
+ ],
+ startPickTime:
+ this.data.YearList[pickerDateArr.yearIdx] +
+ "-" +
+ this.data.MonthList[pickerDateArr.monthIdx] +
+ "-" +
+ this.data.DayList[pickerDateArr.dayIdx] +
+ " " +
+ this.data.HourList[pickerDateArr.hourIdx] +
+ ":" +
+ this.data.MinuteList[pickerDateArr.minuteIdx] +
+ ":" +
+ this.data.SecondList[pickerDateArr.secondIdx]
+ });
+ },
+ setEndDate: function(year, month, day, hour, minute, second) {
+ let pickerDateArr = this.setPickerDateArr(
+ "end",
+ year,
+ month,
+ day,
+ hour,
+ minute,
+ second
+ );
+
+ this.setData({
+ endYearList: this.data.YearList,
+ endMonthList: this.data.MonthList,
+ // endDayList: this.data.DayList,
+ endHourList: this.data.HourList,
+ endMinuteList: this.data.MinuteList,
+ endSecondList: this.data.SecondList,
+ endValue: [
+ pickerDateArr.yearIdx,
+ pickerDateArr.monthIdx,
+ pickerDateArr.dayIdx,
+ pickerDateArr.hourIdx,
+ pickerDateArr.minuteIdx,
+ pickerDateArr.secondIdx
+ ],
+ endPickTime:
+ this.data.YearList[pickerDateArr.yearIdx] +
+ "-" +
+ this.data.MonthList[pickerDateArr.monthIdx] +
+ "-" +
+ this.data.DayList[pickerDateArr.dayIdx] +
+ " " +
+ this.data.HourList[pickerDateArr.hourIdx] +
+ ":" +
+ this.data.MinuteList[pickerDateArr.minuteIdx] +
+ ":" +
+ this.data.SecondList[pickerDateArr.secondIdx]
+ });
+ },
+ }
+});
+
+
+function formatTime(date) {
+
+ if (typeof date == 'string' || 'number') {
+ try {
+ date = date.replace(/-/g, '/')//兼容ios
+ } catch (error) {
+ }
+ date = new Date(date)
+ }
+
+ const year = date.getFullYear()
+ const month = date.getMonth() + 1
+ const day = date.getDate()
+ const hour = date.getHours()
+ const minute = date.getMinutes()
+ const second = date.getSeconds()
+
+ return {
+ str: [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':'),
+ arr: [year, month, day, hour, minute, second]
+ }
+}
+function formatNumber(n) {
+ n = n.toString()
+ return n[1] ? n : '0' + n
+}
diff --git a/test_mini/components/dynamicForm/components/timePicker/timePicker.json b/test_mini/components/dynamicForm/components/timePicker/timePicker.json
new file mode 100644
index 0000000..e8cfaaf
--- /dev/null
+++ b/test_mini/components/dynamicForm/components/timePicker/timePicker.json
@@ -0,0 +1,4 @@
+{
+ "component": true,
+ "usingComponents": {}
+}
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/components/timePicker/timePicker.wxml b/test_mini/components/dynamicForm/components/timePicker/timePicker.wxml
new file mode 100644
index 0000000..963e0dd
--- /dev/null
+++ b/test_mini/components/dynamicForm/components/timePicker/timePicker.wxml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+ 取消
+ 确定
+
+
+
+
+
+ {{item}}年
+
+
+ {{item}}月
+
+
+ {{item}}日
+
+
+ {{item}}时
+
+
+ {{item}}分
+
+
+ {{item}}秒
+
+
+
+
+
+ 至
+
+
+ {{item}}年
+
+
+ {{item}}月
+
+
+ {{item}}日
+
+
+ {{item}}时
+
+
+ {{item}}分
+
+
+ {{item}}秒
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_mini/components/dynamicForm/components/timePicker/timePicker.wxss b/test_mini/components/dynamicForm/components/timePicker/timePicker.wxss
new file mode 100644
index 0000000..ec2c302
--- /dev/null
+++ b/test_mini/components/dynamicForm/components/timePicker/timePicker.wxss
@@ -0,0 +1,96 @@
+/* components/timePicker/timePicker.wxss */
+
+.picker-item{
+ line-height: 100rpx;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+/* 自定义时间 */
+.picker-container {
+ display: flex;
+ flex-direction: column;
+ /* justify-content: center; */
+ align-items: center;
+
+ width: 100%;
+ overflow: hidden;
+ position: fixed;
+ bottom: -640rpx;
+ left: 0;
+ /* height: 0; */
+ transition: height 0.5s;
+ z-index: 2000;
+ background: white;
+ border-top: 1px solid #EFEFF4;
+}
+.sensorType-screen{
+ width: 100vw;
+ /* height:400rpx; */
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: #000;
+ opacity: 0;
+ overflow: hidden;
+ z-index: 1999;
+ color: #fff;
+}
+.sensorTypePicker{
+ width: 690rpx;
+ height: 240rpx;
+ /* padding: 45px 0; */
+}
+.picker-item{
+ line-height: 100rpx;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: 32rpx;
+ /* overflow: hidden; */
+}
+.box{
+ padding: 0 20rpx;
+}
+
+/* 至 */
+.to{
+ width:100%;
+ display: flex;
+ justify-content: center;align-items: center;
+ color:rgb(138,138,138);
+ /* font-size:30rpx; */
+}
+
+/* 确定 */
+.sure{
+ width:100%;
+ height:90rpx;
+ border-top: 2rpx solid #EFEFF4;
+ display: flex;justify-content: center;align-items: center;
+ color: rgb(36,123,255);
+ font-size:16px;
+}
+
+.btn-box{
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: 2rpx solid #eee;
+}
+.pick_btn{
+ padding: 14rpx 30rpx;
+ color: #ccc;
+ /* background-color: #159; */
+}
+
+.show_picker{
+ /* height: 320px; */
+}
+.hide_picker{
+ /* height: 0; */
+}
diff --git a/test_mini/components/dynamicForm/index.js b/test_mini/components/dynamicForm/index.js
new file mode 100644
index 0000000..35cafe6
--- /dev/null
+++ b/test_mini/components/dynamicForm/index.js
@@ -0,0 +1,291 @@
+// 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);
+ }
+ }
+});
diff --git a/test_mini/components/dynamicForm/index.json b/test_mini/components/dynamicForm/index.json
new file mode 100644
index 0000000..9fe4286
--- /dev/null
+++ b/test_mini/components/dynamicForm/index.json
@@ -0,0 +1,8 @@
+{
+ "component": true,
+ "usingComponents": {
+ "van-icon": "./vant/icon/index",
+ "van-uploader": "./vant/uploader/index",
+ "time-picker": "./components/timePicker/timePicker"
+ }
+}
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/index.wxml b/test_mini/components/dynamicForm/index.wxml
new file mode 100644
index 0000000..931dec9
--- /dev/null
+++ b/test_mini/components/dynamicForm/index.wxml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+ {{item.lable}}
+
+
+ {{item.defaultValue || ''}}
+ {{inputMap[item.id].error}}
+
+
+
+
+ {{item.lable}}
+
+
+
+ {{pickerMap[item.id].hasChoose?item.range[pickerMap[item.id].idx].name:'请选择'}}
+
+
+
+ {{pickerMap[item.id].hasChoose?item.range[pickerMap[item.id].idx].name:''}}
+ {{pickerMap[item.id].error}}
+
+
+
+
+ {{item.lable}}
+
+
+ {{dateMap[item.id].hasChoose?(dateMap[item.id].config.endDate?dateMap[item.id].startDate+' ~ ' + dateMap[item.id].endDate: dateMap[item.id].startDate):'请选择'}}
+
+
+
+ {{dateMap[item.id].error}}
+
+
+
+
+
+ {{item.lable}}
+ {{inputMap[item.id].error}}
+
+
+
+ {{inputMap[item.id].value.length||0}}/{{item.maxLength}}
+
+
+
+
+
+
+
+ {{item.lable}}
+ {{fileMap[item.id].error}}
+
+
+
+
+
+
diff --git a/test_mini/components/dynamicForm/index.wxss b/test_mini/components/dynamicForm/index.wxss
new file mode 100644
index 0000000..f1b7e23
--- /dev/null
+++ b/test_mini/components/dynamicForm/index.wxss
@@ -0,0 +1,119 @@
+/* components/dynamicForm/index.wxss */
+.page{
+ background-color: #eeeeef;
+ padding-top: 1px;
+ padding-bottom: 1px;
+}
+.flex{
+ display: flex;
+ align-items: center;
+}
+.form-box{
+ padding: 0 30rpx 0px;
+ padding-right: 0;
+ margin: 30rpx;
+ box-sizing: border-box;
+ border-top: 1px solid #eee;
+ border-radius: 10rpx;
+ background-color: #fff;
+}
+.form-row{
+ position: relative;
+ display: flex;
+ align-items: center;
+ padding: 25rpx 0;
+ font-size: 30rpx;
+ border-bottom: 1px solid #eee;
+}
+.ipt-row{
+ align-items: flex-start;
+}
+.flex-start{
+ align-items: flex-start;
+}
+.picker-row{
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+.form-row:last-child{
+ border-bottom: none;
+}
+.form-lable{
+ position: relative;
+ min-width: 120rpx;
+ max-width: 200rpx;
+ word-break: break-all;
+ padding-right: 30rpx;
+ flex-shrink: 0;
+ flex-grow: 0;
+ font-weight: 700;
+}
+.field{
+ width: 100%;
+ flex-grow: 1;
+ min-height: 45rpx;
+ padding-right: 30rpx;
+ box-sizing: border-box;
+ line-height: 45rpx;
+}
+.error-info{
+ font-size: 24rpx;
+ color: #f00;
+}
+.required::before{
+ position: absolute;
+ top: 50%;
+ left: -18rpx;
+ transform: translateY(-35%);
+ content: '*';
+ color: #f00;
+ font-size: 36rpx;
+}
+.form-btn{
+ margin: 60rpx auto;
+ width: 400rpx;
+ background-color: #17e;
+ color: #fff;
+}
+.row-icon{
+ padding-right: 20rpx;
+}
+.img-box{
+ padding-top: 25rpx;
+ /* padding-bottom: 25rpx; */
+}
+.mb-24{
+ margin-bottom: 24rpx;
+}
+.area-lable{
+ position: relative;
+ font-size: 30rpx;
+ margin-right: 20rpx;
+ font-weight: 700;
+}
+.textarea-box{
+ padding-top: 20rpx;
+}
+.text-area{
+ position: relative;
+ width: 630rpx;
+ padding: 20rpx;
+ padding-bottom: 60rpx;
+ font-size: 30rpx;
+ min-height: 200rpx;
+ box-sizing: border-box;
+ border-radius: 8rpx;
+ border: 1px solid #eee;
+}
+.text-num{
+ position: absolute;
+ right: 20rpx;
+ bottom: 10px;
+ text-align: right;
+ color: #999;
+}
+
+.disabled{
+ opacity: 0.3;
+}
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/utils/formatTime.js b/test_mini/components/dynamicForm/utils/formatTime.js
new file mode 100644
index 0000000..50df5f2
--- /dev/null
+++ b/test_mini/components/dynamicForm/utils/formatTime.js
@@ -0,0 +1,29 @@
+const formatTime = date => {
+ if (!date) {
+ date = new Date();
+ }
+ if(typeof date === 'string'){
+ date = new Date(date);
+ if(!date){
+ date = new Date(date.replace(/-/g, '/'));//兼容IOS new Date()
+ }
+ }
+ if(typeof date === 'number'){
+ date = new Date(date);
+ }
+ const year = date.getFullYear();
+ const month = date.getMonth() + 1;
+ const day = date.getDate();
+ const hour = date.getHours();
+ const minute = date.getMinutes();
+ const second = date.getSeconds();
+
+ return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':');
+};
+
+const formatNumber = n => {
+ n = n.toString();
+ return n[1] ? n : '0' + n;
+};
+
+export default formatTime;
diff --git a/test_mini/components/dynamicForm/vant/common/color.d.ts b/test_mini/components/dynamicForm/vant/common/color.d.ts
new file mode 100644
index 0000000..386f307
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/common/color.d.ts
@@ -0,0 +1,7 @@
+export declare const RED = "#ee0a24";
+export declare const BLUE = "#1989fa";
+export declare const WHITE = "#fff";
+export declare const GREEN = "#07c160";
+export declare const ORANGE = "#ff976a";
+export declare const GRAY = "#323233";
+export declare const GRAY_DARK = "#969799";
diff --git a/test_mini/components/dynamicForm/vant/common/color.js b/test_mini/components/dynamicForm/vant/common/color.js
new file mode 100644
index 0000000..6b285bd
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/common/color.js
@@ -0,0 +1,7 @@
+export const RED = '#ee0a24';
+export const BLUE = '#1989fa';
+export const WHITE = '#fff';
+export const GREEN = '#07c160';
+export const ORANGE = '#ff976a';
+export const GRAY = '#323233';
+export const GRAY_DARK = '#969799';
diff --git a/test_mini/components/dynamicForm/vant/common/component.d.ts b/test_mini/components/dynamicForm/vant/common/component.d.ts
new file mode 100644
index 0000000..307a96c
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/common/component.d.ts
@@ -0,0 +1,3 @@
+import { VantComponentOptions, CombinedComponentInstance } from '../definitions/index';
+declare function VantComponent(vantOptions?: VantComponentOptions>): void;
+export { VantComponent };
diff --git a/test_mini/components/dynamicForm/vant/common/component.js b/test_mini/components/dynamicForm/vant/common/component.js
new file mode 100644
index 0000000..63ef1a9
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/common/component.js
@@ -0,0 +1,48 @@
+import { basic } from '../mixins/basic';
+import { observe } from '../mixins/observer/index';
+function mapKeys(source, target, map) {
+ Object.keys(map).forEach(key => {
+ if (source[key]) {
+ target[map[key]] = source[key];
+ }
+ });
+}
+function VantComponent(vantOptions = {}) {
+ const options = {};
+ mapKeys(vantOptions, options, {
+ data: 'data',
+ props: 'properties',
+ mixins: 'behaviors',
+ methods: 'methods',
+ beforeCreate: 'created',
+ created: 'attached',
+ mounted: 'ready',
+ relations: 'relations',
+ destroyed: 'detached',
+ classes: 'externalClasses'
+ });
+ const { relation } = vantOptions;
+ if (relation) {
+ options.relations = Object.assign(options.relations || {}, {
+ [`../${relation.name}/index`]: relation
+ });
+ }
+ // add default externalClasses
+ options.externalClasses = options.externalClasses || [];
+ options.externalClasses.push('custom-class');
+ // add default behaviors
+ options.behaviors = options.behaviors || [];
+ options.behaviors.push(basic);
+ // map field to form-field behavior
+ if (vantOptions.field) {
+ options.behaviors.push('wx://form-field');
+ }
+ // add default options
+ options.options = {
+ multipleSlots: true,
+ addGlobalClass: true
+ };
+ observe(vantOptions, options);
+ Component(options);
+}
+export { VantComponent };
diff --git a/test_mini/components/dynamicForm/vant/common/index.wxss b/test_mini/components/dynamicForm/vant/common/index.wxss
new file mode 100644
index 0000000..6e6891f
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/common/index.wxss
@@ -0,0 +1 @@
+.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{display:table;clear:both;content:""}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #eee;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/common/style/clearfix.wxss b/test_mini/components/dynamicForm/vant/common/style/clearfix.wxss
new file mode 100644
index 0000000..a0ca838
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/common/style/clearfix.wxss
@@ -0,0 +1 @@
+.van-clearfix:after{display:table;clear:both;content:""}
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/common/style/ellipsis.wxss b/test_mini/components/dynamicForm/vant/common/style/ellipsis.wxss
new file mode 100644
index 0000000..1e9dbc9
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/common/style/ellipsis.wxss
@@ -0,0 +1 @@
+.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/common/style/hairline.wxss b/test_mini/components/dynamicForm/vant/common/style/hairline.wxss
new file mode 100644
index 0000000..f64e2f8
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/common/style/hairline.wxss
@@ -0,0 +1 @@
+.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #eee;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/common/style/mixins/clearfix.wxss b/test_mini/components/dynamicForm/vant/common/style/mixins/clearfix.wxss
new file mode 100644
index 0000000..e69de29
diff --git a/test_mini/components/dynamicForm/vant/common/style/mixins/ellipsis.wxss b/test_mini/components/dynamicForm/vant/common/style/mixins/ellipsis.wxss
new file mode 100644
index 0000000..e69de29
diff --git a/test_mini/components/dynamicForm/vant/common/style/mixins/hairline.wxss b/test_mini/components/dynamicForm/vant/common/style/mixins/hairline.wxss
new file mode 100644
index 0000000..e69de29
diff --git a/test_mini/components/dynamicForm/vant/common/style/theme.wxss b/test_mini/components/dynamicForm/vant/common/style/theme.wxss
new file mode 100644
index 0000000..e69de29
diff --git a/test_mini/components/dynamicForm/vant/common/style/var.wxss b/test_mini/components/dynamicForm/vant/common/style/var.wxss
new file mode 100644
index 0000000..e69de29
diff --git a/test_mini/components/dynamicForm/vant/common/utils.d.ts b/test_mini/components/dynamicForm/vant/common/utils.d.ts
new file mode 100644
index 0000000..9fad27d
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/common/utils.d.ts
@@ -0,0 +1,8 @@
+///
+export declare function isDef(value: any): boolean;
+export declare function isObj(x: any): boolean;
+export declare function isNumber(value: any): boolean;
+export declare function range(num: number, min: number, max: number): number;
+export declare function nextTick(fn: Function): void;
+export declare function getSystemInfoSync(): WechatMiniprogram.GetSystemInfoSuccessCallbackResult;
+export declare function addUnit(value?: string | number): string | undefined;
diff --git a/test_mini/components/dynamicForm/vant/common/utils.js b/test_mini/components/dynamicForm/vant/common/utils.js
new file mode 100644
index 0000000..cc0f8f1
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/common/utils.js
@@ -0,0 +1,32 @@
+export function isDef(value) {
+ return value !== undefined && value !== null;
+}
+export function isObj(x) {
+ const type = typeof x;
+ return x !== null && (type === 'object' || type === 'function');
+}
+export function isNumber(value) {
+ return /^\d+(\.\d+)?$/.test(value);
+}
+export function range(num, min, max) {
+ return Math.min(Math.max(num, min), max);
+}
+export function nextTick(fn) {
+ setTimeout(() => {
+ fn();
+ }, 1000 / 30);
+}
+let systemInfo = null;
+export function getSystemInfoSync() {
+ if (systemInfo == null) {
+ systemInfo = wx.getSystemInfoSync();
+ }
+ return systemInfo;
+}
+export function addUnit(value) {
+ if (!isDef(value)) {
+ return undefined;
+ }
+ value = String(value);
+ return isNumber(value) ? `${value}px` : value;
+}
diff --git a/test_mini/components/dynamicForm/vant/icon/index.d.ts b/test_mini/components/dynamicForm/vant/icon/index.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/icon/index.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/test_mini/components/dynamicForm/vant/icon/index.js b/test_mini/components/dynamicForm/vant/icon/index.js
new file mode 100644
index 0000000..2cfe253
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/icon/index.js
@@ -0,0 +1,27 @@
+import { VantComponent } from '../common/component';
+VantComponent({
+ props: {
+ dot: Boolean,
+ info: null,
+ size: null,
+ color: String,
+ customStyle: String,
+ classPrefix: {
+ type: String,
+ value: 'van-icon'
+ },
+ name: {
+ type: String,
+ observer(val) {
+ this.setData({
+ isImageName: val.indexOf('/') !== -1
+ });
+ }
+ }
+ },
+ methods: {
+ onClick() {
+ this.$emit('click');
+ }
+ }
+});
diff --git a/test_mini/components/dynamicForm/vant/icon/index.json b/test_mini/components/dynamicForm/vant/icon/index.json
new file mode 100644
index 0000000..bf0ebe0
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/icon/index.json
@@ -0,0 +1,6 @@
+{
+ "component": true,
+ "usingComponents": {
+ "van-info": "../info/index"
+ }
+}
diff --git a/test_mini/components/dynamicForm/vant/icon/index.wxml b/test_mini/components/dynamicForm/vant/icon/index.wxml
new file mode 100644
index 0000000..b536511
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/icon/index.wxml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/test_mini/components/dynamicForm/vant/icon/index.wxss b/test_mini/components/dynamicForm/vant/icon/index.wxss
new file mode 100644
index 0000000..cf2c506
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/icon/index.wxss
@@ -0,0 +1 @@
+@import '../common/index.wxss';@font-face{font-weight:400;font-family:vant-icon;font-style:normal;font-display:auto;src:url(https://img.yzcdn.cn/vant/vant-icon-d3825a.woff2) format("woff2"),url(https://img.yzcdn.cn/vant/vant-icon-d3825a.woff) format("woff"),url(https://img.yzcdn.cn/vant/vant-icon-d3825a.ttf) format("truetype")}.van-icon{position:relative;font:normal normal normal 14px/1 vant-icon;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased}.van-icon,.van-icon:before{display:inline-block}.van-icon-add-o:before{content:"\F000"}.van-icon-add-square:before{content:"\F001"}.van-icon-add:before{content:"\F002"}.van-icon-after-sale:before{content:"\F003"}.van-icon-aim:before{content:"\F004"}.van-icon-alipay:before{content:"\F005"}.van-icon-apps-o:before{content:"\F006"}.van-icon-arrow-down:before{content:"\F007"}.van-icon-arrow-left:before{content:"\F008"}.van-icon-arrow-up:before{content:"\F009"}.van-icon-arrow:before{content:"\F00A"}.van-icon-ascending:before{content:"\F00B"}.van-icon-audio:before{content:"\F00C"}.van-icon-award-o:before{content:"\F00D"}.van-icon-award:before{content:"\F00E"}.van-icon-bag-o:before{content:"\F00F"}.van-icon-bag:before{content:"\F010"}.van-icon-balance-list-o:before{content:"\F011"}.van-icon-balance-list:before{content:"\F012"}.van-icon-balance-o:before{content:"\F013"}.van-icon-balance-pay:before{content:"\F014"}.van-icon-bar-chart-o:before{content:"\F015"}.van-icon-bars:before{content:"\F016"}.van-icon-bell:before{content:"\F017"}.van-icon-bill-o:before{content:"\F018"}.van-icon-bill:before{content:"\F019"}.van-icon-birthday-cake-o:before{content:"\F01A"}.van-icon-bookmark-o:before{content:"\F01B"}.van-icon-bookmark:before{content:"\F01C"}.van-icon-browsing-history-o:before{content:"\F01D"}.van-icon-browsing-history:before{content:"\F01E"}.van-icon-brush-o:before{content:"\F01F"}.van-icon-bulb-o:before{content:"\F020"}.van-icon-bullhorn-o:before{content:"\F021"}.van-icon-calender-o:before{content:"\F022"}.van-icon-card:before{content:"\F023"}.van-icon-cart-circle-o:before{content:"\F024"}.van-icon-cart-circle:before{content:"\F025"}.van-icon-cart-o:before{content:"\F026"}.van-icon-cart:before{content:"\F027"}.van-icon-cash-back-record:before{content:"\F028"}.van-icon-cash-on-deliver:before{content:"\F029"}.van-icon-cashier-o:before{content:"\F02A"}.van-icon-certificate:before{content:"\F02B"}.van-icon-chart-trending-o:before{content:"\F02C"}.van-icon-chat-o:before{content:"\F02D"}.van-icon-chat:before{content:"\F02E"}.van-icon-checked:before{content:"\F02F"}.van-icon-circle:before{content:"\F030"}.van-icon-clear:before{content:"\F031"}.van-icon-clock-o:before{content:"\F032"}.van-icon-clock:before{content:"\F033"}.van-icon-close:before{content:"\F034"}.van-icon-closed-eye:before{content:"\F035"}.van-icon-cluster-o:before{content:"\F036"}.van-icon-cluster:before{content:"\F037"}.van-icon-column:before{content:"\F038"}.van-icon-comment-circle-o:before{content:"\F039"}.van-icon-comment-circle:before{content:"\F03A"}.van-icon-comment-o:before{content:"\F03B"}.van-icon-comment:before{content:"\F03C"}.van-icon-completed:before{content:"\F03D"}.van-icon-contact:before{content:"\F03E"}.van-icon-coupon-o:before{content:"\F03F"}.van-icon-coupon:before{content:"\F040"}.van-icon-credit-pay:before{content:"\F041"}.van-icon-cross:before{content:"\F042"}.van-icon-debit-pay:before{content:"\F043"}.van-icon-delete:before{content:"\F044"}.van-icon-descending:before{content:"\F045"}.van-icon-description:before{content:"\F046"}.van-icon-desktop-o:before{content:"\F047"}.van-icon-diamond-o:before{content:"\F048"}.van-icon-diamond:before{content:"\F049"}.van-icon-discount:before{content:"\F04A"}.van-icon-down:before{content:"\F04B"}.van-icon-ecard-pay:before{content:"\F04C"}.van-icon-edit:before{content:"\F04D"}.van-icon-ellipsis:before{content:"\F04E"}.van-icon-empty:before{content:"\F04F"}.van-icon-envelop-o:before{content:"\F050"}.van-icon-exchange:before{content:"\F051"}.van-icon-expand-o:before{content:"\F052"}.van-icon-expand:before{content:"\F053"}.van-icon-eye-o:before{content:"\F054"}.van-icon-eye:before{content:"\F055"}.van-icon-fail:before{content:"\F056"}.van-icon-failure:before{content:"\F057"}.van-icon-filter-o:before{content:"\F058"}.van-icon-fire-o:before{content:"\F059"}.van-icon-fire:before{content:"\F05A"}.van-icon-flag-o:before{content:"\F05B"}.van-icon-flower-o:before{content:"\F05C"}.van-icon-free-postage:before{content:"\F05D"}.van-icon-friends-o:before{content:"\F05E"}.van-icon-friends:before{content:"\F05F"}.van-icon-gem-o:before{content:"\F060"}.van-icon-gem:before{content:"\F061"}.van-icon-gift-card-o:before{content:"\F062"}.van-icon-gift-card:before{content:"\F063"}.van-icon-gift-o:before{content:"\F064"}.van-icon-gift:before{content:"\F065"}.van-icon-gold-coin-o:before{content:"\F066"}.van-icon-gold-coin:before{content:"\F067"}.van-icon-good-job-o:before{content:"\F068"}.van-icon-good-job:before{content:"\F069"}.van-icon-goods-collect-o:before{content:"\F06A"}.van-icon-goods-collect:before{content:"\F06B"}.van-icon-graphic:before{content:"\F06C"}.van-icon-home-o:before{content:"\F06D"}.van-icon-hot-o:before{content:"\F06E"}.van-icon-hot-sale-o:before{content:"\F06F"}.van-icon-hot-sale:before{content:"\F070"}.van-icon-hot:before{content:"\F071"}.van-icon-hotel-o:before{content:"\F072"}.van-icon-idcard:before{content:"\F073"}.van-icon-info-o:before{content:"\F074"}.van-icon-info:before{content:"\F075"}.van-icon-invition:before{content:"\F076"}.van-icon-label-o:before{content:"\F077"}.van-icon-label:before{content:"\F078"}.van-icon-like-o:before{content:"\F079"}.van-icon-like:before{content:"\F07A"}.van-icon-live:before{content:"\F07B"}.van-icon-location-o:before{content:"\F07C"}.van-icon-location:before{content:"\F07D"}.van-icon-lock:before{content:"\F07E"}.van-icon-logistics:before{content:"\F07F"}.van-icon-manager-o:before{content:"\F080"}.van-icon-manager:before{content:"\F081"}.van-icon-map-marked:before{content:"\F082"}.van-icon-medal-o:before{content:"\F083"}.van-icon-medal:before{content:"\F084"}.van-icon-more-o:before{content:"\F085"}.van-icon-more:before{content:"\F086"}.van-icon-music-o:before{content:"\F087"}.van-icon-music:before{content:"\F088"}.van-icon-new-arrival-o:before{content:"\F089"}.van-icon-new-arrival:before{content:"\F08A"}.van-icon-new-o:before{content:"\F08B"}.van-icon-new:before{content:"\F08C"}.van-icon-newspaper-o:before{content:"\F08D"}.van-icon-notes-o:before{content:"\F08E"}.van-icon-orders-o:before{content:"\F08F"}.van-icon-other-pay:before{content:"\F090"}.van-icon-paid:before{content:"\F091"}.van-icon-passed:before{content:"\F092"}.van-icon-pause-circle-o:before{content:"\F093"}.van-icon-pause-circle:before{content:"\F094"}.van-icon-pause:before{content:"\F095"}.van-icon-peer-pay:before{content:"\F096"}.van-icon-pending-payment:before{content:"\F097"}.van-icon-phone-circle-o:before{content:"\F098"}.van-icon-phone-circle:before{content:"\F099"}.van-icon-phone-o:before{content:"\F09A"}.van-icon-phone:before{content:"\F09B"}.van-icon-photo-o:before{content:"\F09C"}.van-icon-photo:before{content:"\F09D"}.van-icon-photograph:before{content:"\F09E"}.van-icon-play-circle-o:before{content:"\F09F"}.van-icon-play-circle:before{content:"\F0A0"}.van-icon-play:before{content:"\F0A1"}.van-icon-plus:before{content:"\F0A2"}.van-icon-point-gift-o:before{content:"\F0A3"}.van-icon-point-gift:before{content:"\F0A4"}.van-icon-points:before{content:"\F0A5"}.van-icon-printer:before{content:"\F0A6"}.van-icon-qr-invalid:before{content:"\F0A7"}.van-icon-qr:before{content:"\F0A8"}.van-icon-question-o:before{content:"\F0A9"}.van-icon-question:before{content:"\F0AA"}.van-icon-records:before{content:"\F0AB"}.van-icon-refund-o:before{content:"\F0AC"}.van-icon-replay:before{content:"\F0AD"}.van-icon-scan:before{content:"\F0AE"}.van-icon-search:before{content:"\F0AF"}.van-icon-send-gift-o:before{content:"\F0B0"}.van-icon-send-gift:before{content:"\F0B1"}.van-icon-service-o:before{content:"\F0B2"}.van-icon-service:before{content:"\F0B3"}.van-icon-setting-o:before{content:"\F0B4"}.van-icon-setting:before{content:"\F0B5"}.van-icon-share:before{content:"\F0B6"}.van-icon-shop-collect-o:before{content:"\F0B7"}.van-icon-shop-collect:before{content:"\F0B8"}.van-icon-shop-o:before{content:"\F0B9"}.van-icon-shop:before{content:"\F0BA"}.van-icon-shopping-cart-o:before{content:"\F0BB"}.van-icon-shopping-cart:before{content:"\F0BC"}.van-icon-shrink:before{content:"\F0BD"}.van-icon-sign:before{content:"\F0BE"}.van-icon-smile-comment-o:before{content:"\F0BF"}.van-icon-smile-comment:before{content:"\F0C0"}.van-icon-smile-o:before{content:"\F0C1"}.van-icon-smile:before{content:"\F0C2"}.van-icon-star-o:before{content:"\F0C3"}.van-icon-star:before{content:"\F0C4"}.van-icon-stop-circle-o:before{content:"\F0C5"}.van-icon-stop-circle:before{content:"\F0C6"}.van-icon-stop:before{content:"\F0C7"}.van-icon-success:before{content:"\F0C8"}.van-icon-thumb-circle-o:before{content:"\F0C9"}.van-icon-thumb-circle:before{content:"\F0CA"}.van-icon-todo-list-o:before{content:"\F0CB"}.van-icon-todo-list:before{content:"\F0CC"}.van-icon-tosend:before{content:"\F0CD"}.van-icon-tv-o:before{content:"\F0CE"}.van-icon-umbrella-circle:before{content:"\F0CF"}.van-icon-underway-o:before{content:"\F0D0"}.van-icon-underway:before{content:"\F0D1"}.van-icon-upgrade:before{content:"\F0D2"}.van-icon-user-circle-o:before{content:"\F0D3"}.van-icon-user-o:before{content:"\F0D4"}.van-icon-video-o:before{content:"\F0D5"}.van-icon-video:before{content:"\F0D6"}.van-icon-vip-card-o:before{content:"\F0D7"}.van-icon-vip-card:before{content:"\F0D8"}.van-icon-volume-o:before{content:"\F0D9"}.van-icon-volume:before{content:"\F0DA"}.van-icon-wap-home-o:before{content:"\F0DB"}.van-icon-wap-home:before{content:"\F0DC"}.van-icon-wap-nav:before{content:"\F0DD"}.van-icon-warn-o:before{content:"\F0DE"}.van-icon-warning-o:before{content:"\F0DF"}.van-icon-warning:before{content:"\F0E0"}.van-icon-weapp-nav:before{content:"\F0E1"}.van-icon-wechat:before{content:"\F0E2"}.van-icon-youzan-shield:before{content:"\F0E3"}:host{display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-icon--image{width:1em;height:1em}.van-icon__image{width:100%;height:100%}.van-icon__info{z-index:1}
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/info/index.d.ts b/test_mini/components/dynamicForm/vant/info/index.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/info/index.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/test_mini/components/dynamicForm/vant/info/index.js b/test_mini/components/dynamicForm/vant/info/index.js
new file mode 100644
index 0000000..a7ce835
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/info/index.js
@@ -0,0 +1,12 @@
+import { VantComponent } from '../common/component';
+
+VantComponent({
+ props: {
+ dot: Boolean,
+ info: null,
+ customStyle: String
+ },
+ data: {
+ // classBem: utils.bem('info', { dot })
+ }
+});
diff --git a/test_mini/components/dynamicForm/vant/info/index.json b/test_mini/components/dynamicForm/vant/info/index.json
new file mode 100644
index 0000000..467ce29
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/info/index.json
@@ -0,0 +1,3 @@
+{
+ "component": true
+}
diff --git a/test_mini/components/dynamicForm/vant/info/index.wxml b/test_mini/components/dynamicForm/vant/info/index.wxml
new file mode 100644
index 0000000..7ad29be
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/info/index.wxml
@@ -0,0 +1,8 @@
+
+
+{{ dot ? '' : info }}
+
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/info/index.wxss b/test_mini/components/dynamicForm/vant/info/index.wxss
new file mode 100644
index 0000000..16e3f32
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/info/index.wxss
@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-info{position:absolute;top:0;right:0;box-sizing:border-box;white-space:nowrap;text-align:center;-webkit-transform:translate(50%,-50%);transform:translate(50%,-50%);-webkit-transform-origin:100%;transform-origin:100%;min-width:16px;min-width:var(--info-size,16px);padding:0 3px;padding:var(--info-padding,0 3px);color:#fff;color:var(--info-color,#fff);font-weight:500;font-weight:var(--info-font-weight,500);font-size:12px;font-size:var(--info-font-size,12px);font-family:PingFang SC,Helvetica Neue,Arial,sans-serif;font-family:var(--info-font-family,PingFang SC,Helvetica Neue,Arial,sans-serif);line-height:14px;line-height:calc(var(--info-size, 16px) - var(--info-border-width, 1px)*2);background-color:#ee0a24;background-color:var(--info-background-color,#ee0a24);border:1px solid #fff;border:var(--info-border-width,1px) solid var(--white,#fff);border-radius:16px;border-radius:var(--info-size,16px)}.van-info--dot{min-width:0;border-radius:100%;width:8px;width:var(--info-dot-size,8px);height:8px;height:var(--info-dot-size,8px);background-color:#ee0a24;background-color:var(--info-dot-color,#ee0a24)}
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/mixins/basic.js b/test_mini/components/dynamicForm/vant/mixins/basic.js
new file mode 100644
index 0000000..db7087e
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/mixins/basic.js
@@ -0,0 +1,22 @@
+export var basic = Behavior({
+ methods: {
+ $emit: function $emit() {
+ this.triggerEvent.apply(this, arguments);
+ },
+ getRect: function getRect(selector, all) {
+ var _this = this;
+
+ return new Promise(function (resolve) {
+ wx.createSelectorQuery().in(_this)[all ? 'selectAll' : 'select'](selector).boundingClientRect(function (rect) {
+ if (all && Array.isArray(rect) && rect.length) {
+ resolve(rect);
+ }
+
+ if (!all && rect) {
+ resolve(rect);
+ }
+ }).exec();
+ });
+ }
+ }
+});
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/mixins/button.js b/test_mini/components/dynamicForm/vant/mixins/button.js
new file mode 100644
index 0000000..676f4d9
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/mixins/button.js
@@ -0,0 +1,15 @@
+export var button = Behavior({
+ properties: {
+ id: String,
+ sessionFrom: String,
+ appParameter: String,
+ sendMessageImg: String,
+ sendMessagePath: String,
+ showMessageCard: String,
+ sendMessageTitle: String,
+ lang: {
+ type: String,
+ value: 'en'
+ }
+ }
+});
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/mixins/iphonex.js b/test_mini/components/dynamicForm/vant/mixins/iphonex.js
new file mode 100644
index 0000000..e33fb52
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/mixins/iphonex.js
@@ -0,0 +1,39 @@
+var isIPhoneX = null;
+
+function getIsIPhoneX() {
+ return new Promise(function (resolve, reject) {
+ if (isIPhoneX !== null) {
+ resolve(isIPhoneX);
+ } else {
+ wx.getSystemInfo({
+ success: function success(_ref) {
+ var model = _ref.model,
+ screenHeight = _ref.screenHeight;
+ var iphoneX = /iphone x/i.test(model);
+ var iphoneNew = /iPhone11/i.test(model) && screenHeight === 812;
+ isIPhoneX = iphoneX || iphoneNew;
+ resolve(isIPhoneX);
+ },
+ fail: reject
+ });
+ }
+ });
+}
+
+export var iphonex = Behavior({
+ properties: {
+ safeAreaInsetBottom: {
+ type: Boolean,
+ value: true
+ }
+ },
+ created: function created() {
+ var _this = this;
+
+ getIsIPhoneX().then(function (isIPhoneX) {
+ _this.set({
+ isIPhoneX: isIPhoneX
+ });
+ });
+ }
+});
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/mixins/link.js b/test_mini/components/dynamicForm/vant/mixins/link.js
new file mode 100644
index 0000000..63a120a
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/mixins/link.js
@@ -0,0 +1,24 @@
+export var link = Behavior({
+ properties: {
+ url: String,
+ linkType: {
+ type: String,
+ value: 'navigateTo'
+ }
+ },
+ methods: {
+ jumpLink: function jumpLink(urlKey) {
+ if (urlKey === void 0) {
+ urlKey = 'url';
+ }
+
+ var url = this.data[urlKey];
+
+ if (url) {
+ wx[this.data.linkType]({
+ url: url
+ });
+ }
+ }
+ }
+});
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/mixins/observer/behavior.js b/test_mini/components/dynamicForm/vant/mixins/observer/behavior.js
new file mode 100644
index 0000000..1df073f
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/mixins/observer/behavior.js
@@ -0,0 +1,43 @@
+export var behavior = Behavior({
+ created: function created() {
+ var _this = this;
+
+ if (!this.$options) {
+ return;
+ }
+
+ var cache = {};
+
+ var _this$$options = this.$options(),
+ computed = _this$$options.computed;
+
+ var keys = Object.keys(computed);
+
+ this.calcComputed = function () {
+ var needUpdate = {};
+ keys.forEach(function (key) {
+ var value = computed[key].call(_this);
+
+ if (cache[key] !== value) {
+ cache[key] = needUpdate[key] = value;
+ }
+ });
+ return needUpdate;
+ };
+ },
+ attached: function attached() {
+ this.set();
+ },
+ methods: {
+ // set data and set computed data
+ set: function set(data, callback) {
+ if (data) {
+ this.setData(data, callback);
+ }
+
+ if (this.calcComputed) {
+ this.setData(this.calcComputed());
+ }
+ }
+ }
+});
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/mixins/observer/index.js b/test_mini/components/dynamicForm/vant/mixins/observer/index.js
new file mode 100644
index 0000000..c878fd0
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/mixins/observer/index.js
@@ -0,0 +1,38 @@
+import { behavior } from './behavior';
+import { observeProps } from './props';
+export function observe(vantOptions, options) {
+ var watch = vantOptions.watch,
+ computed = vantOptions.computed;
+ options.behaviors.push(behavior);
+
+ if (watch) {
+ var props = options.properties || {};
+ Object.keys(watch).forEach(function (key) {
+ if (key in props) {
+ var prop = props[key];
+
+ if (prop === null || !('type' in prop)) {
+ prop = {
+ type: prop
+ };
+ }
+
+ prop.observer = watch[key];
+ props[key] = prop;
+ }
+ });
+ options.properties = props;
+ }
+
+ if (computed) {
+ options.methods = options.methods || {};
+
+ options.methods.$options = function () {
+ return vantOptions;
+ };
+
+ if (options.properties) {
+ observeProps(options.properties);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/mixins/observer/props.js b/test_mini/components/dynamicForm/vant/mixins/observer/props.js
new file mode 100644
index 0000000..57706da
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/mixins/observer/props.js
@@ -0,0 +1,32 @@
+export function observeProps(props) {
+ if (!props) {
+ return;
+ }
+
+ Object.keys(props).forEach(function (key) {
+ var prop = props[key];
+
+ if (prop === null || !('type' in prop)) {
+ prop = {
+ type: prop
+ };
+ }
+
+ var _prop = prop,
+ observer = _prop.observer;
+
+ prop.observer = function () {
+ if (observer) {
+ if (typeof observer === 'string') {
+ observer = this[observer];
+ }
+
+ observer.apply(this, arguments);
+ }
+
+ this.set();
+ };
+
+ props[key] = prop;
+ });
+}
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/mixins/open-type.js b/test_mini/components/dynamicForm/vant/mixins/open-type.js
new file mode 100644
index 0000000..98f09bb
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/mixins/open-type.js
@@ -0,0 +1,22 @@
+export var openType = Behavior({
+ properties: {
+ openType: String
+ },
+ methods: {
+ bindGetUserInfo: function bindGetUserInfo(event) {
+ this.$emit('getuserinfo', event.detail);
+ },
+ bindContact: function bindContact(event) {
+ this.$emit('contact', event.detail);
+ },
+ bindGetPhoneNumber: function bindGetPhoneNumber(event) {
+ this.$emit('getphonenumber', event.detail);
+ },
+ bindOpenSetting: function bindOpenSetting(event) {
+ this.$emit('opensetting', event.detail);
+ },
+ bindError: function bindError(event) {
+ this.$emit('error', event.detail);
+ }
+ }
+});
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/mixins/touch.js b/test_mini/components/dynamicForm/vant/mixins/touch.js
new file mode 100644
index 0000000..c31559b
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/mixins/touch.js
@@ -0,0 +1,21 @@
+export var touch = Behavior({
+ methods: {
+ touchStart: function touchStart(event) {
+ this.direction = '';
+ this.deltaX = 0;
+ this.deltaY = 0;
+ this.offsetX = 0;
+ this.offsetY = 0;
+ this.startX = event.touches[0].clientX;
+ this.startY = event.touches[0].clientY;
+ },
+ touchMove: function touchMove(event) {
+ var touch = event.touches[0];
+ this.deltaX = touch.clientX - this.startX;
+ this.deltaY = touch.clientY - this.startY;
+ this.offsetX = Math.abs(this.deltaX);
+ this.offsetY = Math.abs(this.deltaY);
+ this.direction = this.offsetX > this.offsetY ? 'horizontal' : this.offsetX < this.offsetY ? 'vertical' : '';
+ }
+ }
+});
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/mixins/transition.js b/test_mini/components/dynamicForm/vant/mixins/transition.js
new file mode 100644
index 0000000..3723eb1
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/mixins/transition.js
@@ -0,0 +1,73 @@
+export var transition = function transition(showDefaultValue) {
+ return Behavior({
+ properties: {
+ customStyle: String,
+ show: {
+ type: Boolean,
+ value: showDefaultValue,
+ observer: 'observeShow'
+ },
+ duration: {
+ type: Number,
+ value: 300
+ }
+ },
+ data: {
+ type: '',
+ inited: false,
+ display: false,
+ supportAnimation: true
+ },
+ attached: function attached() {
+ if (this.data.show) {
+ this.show();
+ }
+
+ this.detectSupport();
+ },
+ methods: {
+ detectSupport: function detectSupport() {
+ var _this = this;
+
+ wx.getSystemInfo({
+ success: function success(info) {
+ if (info && info.system && info.system.indexOf('iOS 8') === 0) {
+ _this.set({
+ supportAnimation: false
+ });
+ }
+ }
+ });
+ },
+ observeShow: function observeShow(value) {
+ if (value) {
+ this.show();
+ } else {
+ if (this.data.supportAnimation) {
+ this.set({
+ type: 'leave'
+ });
+ } else {
+ this.set({
+ display: false
+ });
+ }
+ }
+ },
+ show: function show() {
+ this.set({
+ inited: true,
+ display: true,
+ type: 'enter'
+ });
+ },
+ onAnimationEnd: function onAnimationEnd() {
+ if (!this.data.show) {
+ this.set({
+ display: false
+ });
+ }
+ }
+ }
+ });
+};
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/uploader/index.d.ts b/test_mini/components/dynamicForm/vant/uploader/index.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/uploader/index.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/test_mini/components/dynamicForm/vant/uploader/index.js b/test_mini/components/dynamicForm/vant/uploader/index.js
new file mode 100644
index 0000000..ccfd01f
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/uploader/index.js
@@ -0,0 +1,180 @@
+import { VantComponent } from '../common/component';
+import { isImageFile } from './utils';
+
+VantComponent({
+ props: {
+ disabled: Boolean,
+ multiple: Boolean,
+ uploadText: String,
+ useBeforeRead: Boolean,
+ previewSize: {
+ type: null,
+ value: 90
+ },
+ name: {
+ type: [Number, String],
+ value: ''
+ },
+ accept: {
+ type: String,
+ value: 'image'
+ },
+ sizeType: {
+ type: Array,
+ value: ['original', 'compressed']
+ },
+ capture: {
+ type: Array,
+ value: ['album', 'camera']
+ },
+ fileList: {
+ type: Array,
+ value: [],
+ observer: 'formatFileList'
+ },
+ maxSize: {
+ type: Number,
+ value: Number.MAX_VALUE
+ },
+ maxCount: {
+ type: Number,
+ value: 100
+ },
+ deletable: {
+ type: Boolean,
+ value: true
+ },
+ previewImage: {
+ type: Boolean,
+ value: true
+ },
+ previewFullImage: {
+ type: Boolean,
+ value: true
+ },
+ imageFit: {
+ type: String,
+ value: 'scaleToFill'
+ }
+ },
+ data: {
+ lists: [],
+ computedPreviewSize: '',
+ isInCount: true
+ },
+ methods: {
+ formatFileList() {
+ const { fileList = [], maxCount } = this.data;
+ const lists = fileList.map(item => (Object.assign(Object.assign({}, item), { isImage: typeof item.isImage === 'undefined' ? isImageFile(item) : item.isImage })));
+ this.setData({ lists, isInCount: lists.length < maxCount });
+ },
+ startUpload() {
+ if (this.data.disabled)
+ return;
+ const { name = '', capture, maxCount, multiple, maxSize, accept, sizeType,videoCfg={}, lists, useBeforeRead = false // 是否定义了 beforeRead
+ } = this.data;
+ let chooseFile = null;
+ const newMaxCount = maxCount - lists.length;
+ // 设置为只选择图片的时候使用 chooseImage 来实现
+ if (accept === 'image') {
+ chooseFile = new Promise((resolve, reject) => {
+ wx.chooseImage({
+ count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1,
+ sourceType: capture,
+ sizeType,
+ success: resolve,
+ fail: reject
+ });
+ });
+ }
+ else if (accept === 'video'){
+ chooseFile = new Promise((resolve, reject) => {
+ wx.chooseMedia({
+ count: videoCfg.count || 9,
+ mediaType: ['video'],
+ sourceType: videoCfg.sourceType || ['album', 'camera'],
+ maxDuration: videoCfg.maxDuration || 10,
+ camera: videoCfg.camera || 'back',
+ success: (res)=>{
+ res.isVideo = true;
+ resolve(res);
+ },
+ fail: reject
+ });
+ });
+ }
+ else {
+ chooseFile = new Promise((resolve, reject) => {
+ wx.chooseMessageFile({
+ count: multiple ? newMaxCount : 1,
+ type: 'file',
+ success: resolve,
+ fail: reject
+ });
+ });
+ }
+ chooseFile
+ .then((res) => {
+ const file = multiple ? res.tempFiles : res.tempFiles[0];
+ // 检查文件大小
+ if (file instanceof Array) {
+ const sizeEnable = file.every(item => item.size <= maxSize);
+ if (!sizeEnable) {
+ this.$emit('oversize', { name });
+ return;
+ }
+ }
+ else if (file.size > maxSize) {
+ this.$emit('oversize', { name });
+ return;
+ }
+ let upData = { file, name };
+ if(res.isVideo){
+ file.map(val=>{
+ val.isVideo = true;
+ return val;
+ });
+ }
+ // 触发上传之前的钩子函数
+ if (useBeforeRead) {
+ this.$emit('before-read', {
+ file,
+ name,
+ callback: (result) => {
+ if (result) {
+ // 开始上传
+ this.$emit('after-read', upData);
+ }
+ }
+ });
+ }
+ else {
+ this.$emit('after-read', upData);
+ }
+ })
+ .catch(error => {
+ this.$emit('error', error);
+ });
+ },
+ deleteItem(event) {
+ const { index } = event.currentTarget.dataset;
+ this.$emit('delete', { index, name: this.data.name });
+ },
+ doPreviewImage(event) {
+ if (!this.data.previewFullImage)
+ return;
+ const curUrl = event.currentTarget.dataset.url;
+ const images = this.data.lists
+ .filter(item => item.isImage)
+ .map(item => item.url || item.path);
+ this.$emit('click-preview', { url: curUrl, name: this.data.name });
+ wx.previewImage({
+ urls: images,
+ current: curUrl,
+ fail() {
+ wx.showToast({ title: '预览图片失败', icon: 'none' });
+ }
+ });
+ }
+ }
+});
diff --git a/test_mini/components/dynamicForm/vant/uploader/index.json b/test_mini/components/dynamicForm/vant/uploader/index.json
new file mode 100644
index 0000000..0a336c0
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/uploader/index.json
@@ -0,0 +1,6 @@
+{
+ "component": true,
+ "usingComponents": {
+ "van-icon": "../icon/index"
+ }
+}
diff --git a/test_mini/components/dynamicForm/vant/uploader/index.wxml b/test_mini/components/dynamicForm/vant/uploader/index.wxml
new file mode 100644
index 0000000..bbc7bfa
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/uploader/index.wxml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.name || item.url || item.path }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ uploadText }}
+
+
+
+
diff --git a/test_mini/components/dynamicForm/vant/uploader/index.wxss b/test_mini/components/dynamicForm/vant/uploader/index.wxss
new file mode 100644
index 0000000..1a22368
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/uploader/index.wxss
@@ -0,0 +1,3 @@
+@import '../common/index.wxss';.van-uploader{position:relative;display:inline-block}.van-uploader__wrapper{display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap}.van-uploader__slot:empty{display:none}.van-uploader__slot:not(:empty)+.van-uploader__upload{display:none!important}.van-uploader__upload{position:relative;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:80px;height:80px;margin:0 20rpx 20rpx 0;background-color:#fff;border:2px dashed #e0e0f0;border-radius:8px}.van-uploader__upload-icon{display:inline-block;width:48rpx;height:48rpx;color:#969799;font-size:24px}.van-uploader__upload-text{margin-top:8px;color:#969799;font-size:12px}.van-uploader__preview{position:relative;margin:0 20rpx 20rpx 0}.van-uploader__preview-image{display:block;width:80px;height:80px;border-radius:8px}
+.van-uploader__preview-video{display:block;width:80px;height:80px;border-radius:8px;overflow: hidden}
+.van-uploader__preview-delete{position:absolute;top:-8px;right:-8px;color:#969799;font-size:18px;background-color:#fff;border-radius:100%}.van-uploader__file{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;width:80px;height:80px;background-color:#f7f8fa;border-radius:8px}.van-uploader__file-icon{display:inline-block;width:20px;height:20px;color:#646566;font-size:20px}.van-uploader__file-name{box-sizing:border-box;width:100%;margin-top:8px;padding:0 5px;color:#646566;font-size:12px;text-align:center}
\ No newline at end of file
diff --git a/test_mini/components/dynamicForm/vant/uploader/utils.d.ts b/test_mini/components/dynamicForm/vant/uploader/utils.d.ts
new file mode 100644
index 0000000..d3bb3b5
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/uploader/utils.d.ts
@@ -0,0 +1,12 @@
+interface File {
+ path: string;
+ url: string;
+ size: number;
+ name: string;
+ type: string;
+ time: number;
+ image: boolean;
+}
+export declare function isImageUrl(url: string): boolean;
+export declare function isImageFile(item: File): boolean;
+export {};
diff --git a/test_mini/components/dynamicForm/vant/uploader/utils.js b/test_mini/components/dynamicForm/vant/uploader/utils.js
new file mode 100644
index 0000000..aa59dc1
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/uploader/utils.js
@@ -0,0 +1,16 @@
+const IMAGE_EXT = ['jpeg', 'jpg', 'gif', 'png', 'svg'];
+export function isImageUrl(url) {
+ return IMAGE_EXT.some(ext => url.indexOf(`.${ext}`) !== -1);
+}
+export function isImageFile(item) {
+ if (item.type) {
+ return item.type.indexOf('image') === 0;
+ }
+ if (item.path) {
+ return isImageUrl(item.path);
+ }
+ if (item.url) {
+ return isImageUrl(item.url);
+ }
+ return false;
+}
diff --git a/test_mini/components/dynamicForm/vant/wxs/add-unit.wxs b/test_mini/components/dynamicForm/vant/wxs/add-unit.wxs
new file mode 100644
index 0000000..27a22d8
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/wxs/add-unit.wxs
@@ -0,0 +1,14 @@
+/* eslint-disable */
+var REGEXP = getRegExp('^\d+(\.\d+)?$');
+
+function addUnit(value) {
+ if (value == null) {
+ return undefined;
+ }
+
+ return REGEXP.test('' + value) ? value + 'px' : value;
+}
+
+module.exports = {
+ addUnit: addUnit
+};
diff --git a/test_mini/components/dynamicForm/vant/wxs/array.wxs b/test_mini/components/dynamicForm/vant/wxs/array.wxs
new file mode 100644
index 0000000..610089c
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/wxs/array.wxs
@@ -0,0 +1,5 @@
+function isArray(array) {
+ return array && array.constructor === 'Array';
+}
+
+module.exports.isArray = isArray;
diff --git a/test_mini/components/dynamicForm/vant/wxs/bem.wxs b/test_mini/components/dynamicForm/vant/wxs/bem.wxs
new file mode 100644
index 0000000..93b2777
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/wxs/bem.wxs
@@ -0,0 +1,38 @@
+var array = require('./array.wxs');
+var object = require('./object.wxs');
+var PREFIX = 'van-';
+
+function join(name, mods) {
+ name = PREFIX + name;
+ mods = mods.map(function(mod) {
+ return name + '--' + mod;
+ });
+ mods.unshift(name);
+ return mods.join(' ');
+}
+
+function traversing(mods, conf) {
+ if (!conf) {
+ return;
+ }
+
+ if (typeof conf === 'string' || typeof conf === 'number') {
+ mods.push(conf);
+ } else if (array.isArray(conf)) {
+ conf.forEach(function(item) {
+ traversing(mods, item);
+ });
+ } else if (typeof conf === 'object') {
+ object.keys(conf).forEach(function(key) {
+ conf[key] && mods.push(key);
+ });
+ }
+}
+
+function bem(name, conf) {
+ var mods = [];
+ traversing(mods, conf);
+ return join(name, mods);
+}
+
+module.exports.bem = bem;
diff --git a/test_mini/components/dynamicForm/vant/wxs/memoize.wxs b/test_mini/components/dynamicForm/vant/wxs/memoize.wxs
new file mode 100644
index 0000000..261ae67
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/wxs/memoize.wxs
@@ -0,0 +1,54 @@
+/**
+ * Simple memoize
+ * wxs doesn't support fn.apply, so this memoize only support up to 2 args
+ */
+
+function isPrimitive(value) {
+ var type = typeof value;
+ return (
+ type === 'boolean' ||
+ type === 'number' ||
+ type === 'string' ||
+ type === 'undefined' ||
+ value === null
+ );
+}
+
+// mock simple fn.call in wxs
+function call(fn, args) {
+ if (args.length === 2) {
+ return fn(args[0], args[1]);
+ }
+
+ if (args.length === 1) {
+ return fn(args[0]);
+ }
+
+ return fn();
+}
+
+function serializer(args) {
+ if (args.length === 1 && isPrimitive(args[0])) {
+ return args[0];
+ }
+ var obj = {};
+ for (var i = 0; i < args.length; i++) {
+ obj['key' + i] = args[i];
+ }
+ return JSON.stringify(obj);
+}
+
+function memoize(fn) {
+ var cache = {};
+
+ return function() {
+ var key = serializer(arguments);
+ if (cache[key] === undefined) {
+ cache[key] = call(fn, arguments);
+ }
+
+ return cache[key];
+ };
+}
+
+module.exports.memoize = memoize;
diff --git a/test_mini/components/dynamicForm/vant/wxs/object.wxs b/test_mini/components/dynamicForm/vant/wxs/object.wxs
new file mode 100644
index 0000000..e077107
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/wxs/object.wxs
@@ -0,0 +1,13 @@
+/* eslint-disable */
+var REGEXP = getRegExp('{|}|"', 'g');
+
+function keys(obj) {
+ return JSON.stringify(obj)
+ .replace(REGEXP, '')
+ .split(',')
+ .map(function(item) {
+ return item.split(':')[0];
+ });
+}
+
+module.exports.keys = keys;
diff --git a/test_mini/components/dynamicForm/vant/wxs/utils.wxs b/test_mini/components/dynamicForm/vant/wxs/utils.wxs
new file mode 100644
index 0000000..d5c9d8c
--- /dev/null
+++ b/test_mini/components/dynamicForm/vant/wxs/utils.wxs
@@ -0,0 +1,10 @@
+/* eslint-disable */
+var bem = require('./bem.wxs').bem;
+var memoize = require('./memoize.wxs').memoize;
+var addUnit = require('./add-unit.wxs').addUnit;
+
+module.exports = {
+ bem: memoize(bem),
+ memoize: memoize,
+ addUnit: addUnit
+};
diff --git a/test_mini/images/examtest.svg b/test_mini/images/examtest.svg
new file mode 100644
index 0000000..cf8b452
--- /dev/null
+++ b/test_mini/images/examtest.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test_mini/images/资格证书.svg b/test_mini/images/资格证书.svg
new file mode 100644
index 0000000..22d2268
--- /dev/null
+++ b/test_mini/images/资格证书.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test_mini/pages/admin/exam/add.js b/test_mini/pages/admin/exam/add.js
new file mode 100644
index 0000000..dfa7683
--- /dev/null
+++ b/test_mini/pages/admin/exam/add.js
@@ -0,0 +1,68 @@
+// pages/admin/exam/add.js
+Page({
+
+ /**
+ * 页面的初始数据
+ */
+ data: {
+ form:{
+
+ }
+ },
+
+ /**
+ * 生命周期函数--监听页面加载
+ */
+ onLoad: function (options) {
+
+ },
+
+ /**
+ * 生命周期函数--监听页面初次渲染完成
+ */
+ onReady: function () {
+
+ },
+
+ /**
+ * 生命周期函数--监听页面显示
+ */
+ onShow: function () {
+
+ },
+
+ /**
+ * 生命周期函数--监听页面隐藏
+ */
+ onHide: function () {
+
+ },
+
+ /**
+ * 生命周期函数--监听页面卸载
+ */
+ onUnload: function () {
+
+ },
+
+ /**
+ * 页面相关事件处理函数--监听用户下拉动作
+ */
+ onPullDownRefresh: function () {
+
+ },
+
+ /**
+ * 页面上拉触底事件的处理函数
+ */
+ onReachBottom: function () {
+
+ },
+
+ /**
+ * 用户点击右上角分享
+ */
+ onShareAppMessage: function () {
+
+ }
+})
\ No newline at end of file
diff --git a/test_mini/pages/admin/exam/add.json b/test_mini/pages/admin/exam/add.json
new file mode 100644
index 0000000..8835af0
--- /dev/null
+++ b/test_mini/pages/admin/exam/add.json
@@ -0,0 +1,3 @@
+{
+ "usingComponents": {}
+}
\ No newline at end of file
diff --git a/test_mini/pages/admin/exam/add.wxml b/test_mini/pages/admin/exam/add.wxml
new file mode 100644
index 0000000..19c6621
--- /dev/null
+++ b/test_mini/pages/admin/exam/add.wxml
@@ -0,0 +1,81 @@
+
+新建考试
+基本信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+监考人信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+确定
+
\ No newline at end of file
diff --git a/test_mini/pages/admin/exam/add.wxss b/test_mini/pages/admin/exam/add.wxss
new file mode 100644
index 0000000..45f7d1b
--- /dev/null
+++ b/test_mini/pages/admin/exam/add.wxss
@@ -0,0 +1 @@
+/* pages/admin/exam/add.wxss */
\ No newline at end of file
diff --git a/test_mini/pages/admin/exam/add2.js b/test_mini/pages/admin/exam/add2.js
new file mode 100644
index 0000000..1c62d7d
--- /dev/null
+++ b/test_mini/pages/admin/exam/add2.js
@@ -0,0 +1,146 @@
+const app = getApp()
+const api = require("../../../utils/request.js");
+Page({
+ data: {
+ formData: [
+ {
+ type: 'input',
+ id:'name',
+ lable:'考试名称',
+ isRequired: true,//是否必填
+ maxLength: 20,//最大长度
+ defaultValue:'',//初始值
+ rules:[//规则验证数组
+ {
+ regular: '^\\S*$',//正则字符串
+ tips: '不能有空格'//错误提示
+ },
+ ]
+ },
+ {
+ type: 'input',
+ id:'place',
+ lable:'考试地点',
+ isRequired: true,//是否必填
+ maxLength: 50,//最大长度
+ defaultValue:'',//初始值
+ rules:[//规则验证数组
+ {
+ regular: '^\\S*$',//正则字符串
+ tips: '不能有空格'//错误提示
+ },
+ ]
+ },
+ {
+ type: 'input',
+ id: 'chance',
+ lable: '考试机会',
+ defaultValue: 3,
+ inputType: 'digit', //对应input组件type值(text,number)
+ placeholder: '请填写数字',
+ isRequired: true,//是否必填
+ //disabled:true,
+ rules: [
+
+ ]
+ },
+ {
+ type: 'picker',
+ id: 'workscope',
+ lable: '工作类别',
+ defaultIdx:0,//默认选择索引
+ // disabled:true,
+ isRequired:true,
+ range:[
+ {
+ id: 0,
+ name: '正常'
+ },
+ {
+ id: 1,
+ name: '异常'
+ },
+
+ ]
+ },
+ {
+ type: 'date',
+ id: 'daterange',
+ lable: '开关时间',
+ isRequired: true,
+ /* 显示完整时间包含时分秒;当使用endDate的时候关闭,不要同时打开, 否则日期将会换行;
+ 与config中的colum属性共同设置
+ */
+ completeTime:true, //显示完整时间, 包含时分秒
+ config: {
+ endDate: true,
+ dateLimit: true,
+ // initStartTime: "2020-01-01 12:32:44",
+ // initEndTime: "2020-12-01 12:32:44",
+ column: "minute",//day、hour、minute、secend
+ limitStartTime: "2000-01-01 00:00:59",
+ limitEndTime: "2100-01-01 00:00:59"
+ }
+ },
+ {
+ type: 'input',
+ id:'proctor_name',
+ lable:'监考人姓名',
+ isRequired: true,//是否必填
+ maxLength: 50,//最大长度
+ defaultValue:'',//初始值
+ rules:[//规则验证数组
+ {
+ regular: '^\\S*$',//正则字符串
+ tips: '不能有空格'//错误提示
+ },
+ ]
+ },
+ {
+ type: 'input',
+ id:'proctor_phone',
+ lable:'监考人联系方式',
+ isRequired: true,//是否必填
+ maxLength: 50,//最大长度
+ defaultValue:'',//初始值
+ rules:[//规则验证数组
+ {
+ regular: '^\\S*$',//正则字符串
+ tips: '不能有空格'//错误提示
+ },
+ ]
+ },
+ ],
+ toSubmit: Math.random()
+ },
+ onFormSubmit(e){
+ console.log('表单提交: ', e);
+ let x = {};
+ x.opentime = e.daterange.startDate;
+ x.endtime = e.daterange.endDate;
+ x.name = e.name
+ x.place = e.place
+ x.chance = e.chance
+ x.workscope = e.workscope
+ x.proctor_name = e.proctor_name
+ x.proctor_phone = e.proctor_phone
+ console.log(x)
+ },
+ onFormChange(e){
+ console.log('表单变化: ',e);
+ },
+ //变更数值, 触发表单提交事件
+ toSubmitChange(){
+ this.setData({
+ toSubmit: Math.random()
+ })
+ },
+ onLoad: function () {
+ api.requesta('/examtest/workscope/?can_exam=true', 'GET').then(res=>{
+ this.data.formData[3].range=res.data
+ this.setData({
+ formData: this.data.formData
+ })
+ })
+ },
+})
diff --git a/test_mini/pages/admin/exam/add2.json b/test_mini/pages/admin/exam/add2.json
new file mode 100644
index 0000000..9d2ea85
--- /dev/null
+++ b/test_mini/pages/admin/exam/add2.json
@@ -0,0 +1,5 @@
+{
+ "usingComponents": {
+ "d-form": "/components/dynamicForm/index"
+ }
+}
\ No newline at end of file
diff --git a/test_mini/pages/admin/exam/add2.wxml b/test_mini/pages/admin/exam/add2.wxml
new file mode 100644
index 0000000..c760dee
--- /dev/null
+++ b/test_mini/pages/admin/exam/add2.wxml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/test_mini/pages/admin/exam/add2.wxss b/test_mini/pages/admin/exam/add2.wxss
new file mode 100644
index 0000000..7d56591
--- /dev/null
+++ b/test_mini/pages/admin/exam/add2.wxss
@@ -0,0 +1 @@
+/* pages/admin/exam/add2.wxss */
\ No newline at end of file
diff --git a/test_mini/pages/admin/index.js b/test_mini/pages/admin/index.js
new file mode 100644
index 0000000..6846dd2
--- /dev/null
+++ b/test_mini/pages/admin/index.js
@@ -0,0 +1,86 @@
+// pages/admin/index.js
+const api = require("../../utils/request.js");
+Page({
+
+ /**
+ * 页面的初始数据
+ */
+ data: {
+
+ },
+
+ /**
+ * 生命周期函数--监听页面加载
+ */
+ onLoad: function (options) {
+ this.setData({
+ admininfo:getApp().globalData.admininfo
+ })
+ },
+ logout: function(){
+ wx.redirectTo({
+ url: '/pages/admin/login?type=nologin',
+ })
+ },
+ bindmp: function(){
+ wx.login({
+ success: res => {
+ // 发送 res.code 到后台换取 openId, sessionKey, unionId
+ api.requesta('/rbac/user/bindmp/','POST', {code:res.code}).then(res=>{
+ getApp().globalData.admininfo.mpopenid = res.data.mpopenid
+ wx.redirectTo({
+ url: '/pages/admin/index',
+ })
+ })
+ }
+ })
+ },
+ /**
+ * 生命周期函数--监听页面初次渲染完成
+ */
+ onReady: function () {
+
+ },
+
+ /**
+ * 生命周期函数--监听页面显示
+ */
+ onShow: function () {
+
+ },
+
+ /**
+ * 生命周期函数--监听页面隐藏
+ */
+ onHide: function () {
+
+ },
+
+ /**
+ * 生命周期函数--监听页面卸载
+ */
+ onUnload: function () {
+
+ },
+
+ /**
+ * 页面相关事件处理函数--监听用户下拉动作
+ */
+ onPullDownRefresh: function () {
+
+ },
+
+ /**
+ * 页面上拉触底事件的处理函数
+ */
+ onReachBottom: function () {
+
+ },
+
+ /**
+ * 用户点击右上角分享
+ */
+ onShareAppMessage: function () {
+
+ }
+})
\ No newline at end of file
diff --git a/test_mini/pages/admin/index.json b/test_mini/pages/admin/index.json
new file mode 100644
index 0000000..63f2663
--- /dev/null
+++ b/test_mini/pages/admin/index.json
@@ -0,0 +1,4 @@
+{
+ "usingComponents": {},
+ "navigationBarTitleText": "管理员控制台"
+}
\ No newline at end of file
diff --git a/test_mini/pages/admin/index.wxml b/test_mini/pages/admin/index.wxml
new file mode 100644
index 0000000..f72b21c
--- /dev/null
+++ b/test_mini/pages/admin/index.wxml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+ 账号:
+ {{admininfo.username}}
+
+ 昵称:
+ {{ admininfo.name }}
+
+ 角色:
+ {{ admininfo.roles }}
+
+
+ 已绑定微信
+
+
+
+
+
+
+
+
+
+ 功能列表
+
+
+
+
+
+
+ 发布考试
+
+
+
+
+
+ 考试记录
+
+
+
+
+
+ 出证记录
+
+
+
+
+
\ No newline at end of file
diff --git a/test_mini/pages/admin/index.wxss b/test_mini/pages/admin/index.wxss
new file mode 100644
index 0000000..38d2c4b
--- /dev/null
+++ b/test_mini/pages/admin/index.wxss
@@ -0,0 +1,9 @@
+/* pages/admin/index.wxss */
+.weui-grids {
+ border-top:none;
+}
+.weui-grid {
+ width: 25%;
+ border-right:none;
+ border-bottom:none;
+}
\ No newline at end of file
diff --git a/test_mini/pages/admin/login.js b/test_mini/pages/admin/login.js
new file mode 100644
index 0000000..c1f7ed2
--- /dev/null
+++ b/test_mini/pages/admin/login.js
@@ -0,0 +1,116 @@
+// pages/admin/login.js
+const api = require("../../utils/request.js");
+Page({
+
+ /**
+ * 页面的初始数据
+ */
+ data: {
+ form:{
+ username:'',
+ password:''
+ }
+ },
+ usernameChange: function (e) {
+ this.data.form.username = e.detail.value
+ },
+ passwordChange: function (e) {
+ this.data.form.password = e.detail.value
+ },
+ /**
+ * 生命周期函数--监听页面加载
+ */
+ onLoad: function (options) {
+ if(options.type=='nologin'){
+
+ }else{
+ this.mplogin()
+ }
+
+ },
+
+ /**
+ * 生命周期函数--监听页面初次渲染完成
+ */
+ onReady: function () {
+
+ },
+
+ /**
+ * 生命周期函数--监听页面显示
+ */
+ onShow: function () {
+
+ },
+
+ /**
+ * 生命周期函数--监听页面隐藏
+ */
+ onHide: function () {
+
+ },
+
+ /**
+ * 生命周期函数--监听页面卸载
+ */
+ onUnload: function () {
+
+ },
+
+ /**
+ * 页面相关事件处理函数--监听用户下拉动作
+ */
+ onPullDownRefresh: function () {
+
+ },
+
+ /**
+ * 页面上拉触底事件的处理函数
+ */
+ onReachBottom: function () {
+
+ },
+
+ /**
+ * 用户点击右上角分享
+ */
+ onShareAppMessage: function () {
+
+ },
+ denglu: function ( ) {
+ var form = this.data.form
+ api.requesta('/token/', 'POST', form).then(res => {
+ getApp().globalData.admintoken = res.data.token;
+ api.requesta('/rbac/user/info/', 'GET').then(res=>{
+ getApp().globalData.admininfo = res.data
+ wx.showToast({
+ title: '登录成功',
+ icon: 'none'
+ })
+ wx.redirectTo({
+ url: '/pages/admin/index',
+ })
+ })
+ })
+ },
+ mplogin: function(){
+ wx.showLoading({
+ title: '自动登陆中',
+ mask:true
+ })
+ wx.login({
+ success: res => {
+ // 发送 res.code 到后台换取 openId, sessionKey, unionId
+ api.requesta('/rbac/user/mplogin/','POST', {code:res.code}).then(res=>{
+ getApp().globalData.admintoken = res.data.token;
+ api.requesta('/rbac/user/info/', 'GET').then(res=>{
+ getApp().globalData.admininfo = res.data
+ wx.redirectTo({
+ url: '/pages/admin/index',
+ })
+ })
+ })
+ }
+ })
+ }
+})
\ No newline at end of file
diff --git a/test_mini/pages/admin/login.json b/test_mini/pages/admin/login.json
new file mode 100644
index 0000000..7035483
--- /dev/null
+++ b/test_mini/pages/admin/login.json
@@ -0,0 +1,4 @@
+{
+ "usingComponents": {},
+ "navigationBarTitleText": "管理员登录"
+}
\ No newline at end of file
diff --git a/test_mini/pages/admin/login.wxml b/test_mini/pages/admin/login.wxml
new file mode 100644
index 0000000..ee39079
--- /dev/null
+++ b/test_mini/pages/admin/login.wxml
@@ -0,0 +1,33 @@
+
+
+
+ 中科辐射学堂
+ 管理员登录
+
+
+
+
+
+ 账号
+
+
+
+
+
+
+
+ 密码
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test_mini/pages/admin/login.wxss b/test_mini/pages/admin/login.wxss
new file mode 100644
index 0000000..6c0a800
--- /dev/null
+++ b/test_mini/pages/admin/login.wxss
@@ -0,0 +1 @@
+/* pages/admin/login.wxss */
\ No newline at end of file
diff --git a/test_mini/pages/login/login.js b/test_mini/pages/login/login.js
index 56b237e..a02b457 100644
--- a/test_mini/pages/login/login.js
+++ b/test_mini/pages/login/login.js
@@ -107,6 +107,11 @@ Page({
url: '/pages/main/main',
})
},
+ goadmin: function(){
+ wx.redirectTo({
+ url: '/pages/admin/login',
+ })
+ },
denglu: function (data) {
api.request('/crm/consumer/register/', 'POST', data).then(res => {
getApp().onLaunch()
diff --git a/test_mini/pages/login/login.wxml b/test_mini/pages/login/login.wxml
index 83f347e..6d7eb8e 100644
--- a/test_mini/pages/login/login.wxml
+++ b/test_mini/pages/login/login.wxml
@@ -33,6 +33,7 @@
\ No newline at end of file
diff --git a/test_mini/pages/my/index.wxml b/test_mini/pages/my/index.wxml
index 4d9e547..7659c07 100644
--- a/test_mini/pages/my/index.wxml
+++ b/test_mini/pages/my/index.wxml
@@ -72,6 +72,13 @@
+ 管理员操作台
+
+
+ 管理员入口
+
+
+