diff --git a/app.js b/app.js index b262d8d..c19a5ae 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,6 @@ //app.js App({ - evn: 2, // 0: 开发版本;1:测试版本;2:生产版本 + evn: 0, // 0: 开发版本;1:测试版本;2:生产版本 tmplIds: [''], version: 152, xAppId: '503258978847953926', diff --git a/components/calendar/calendar.wxml b/components/calendar/calendar.wxml new file mode 100644 index 0000000..a9d50cb --- /dev/null +++ b/components/calendar/calendar.wxml @@ -0,0 +1,29 @@ + +
+ +
+ + + + + + + + + + + + {{ + computed.getButtonDisabled(type, currentDate) + ? confirmDisabledText + : confirmText + }} + + +
\ No newline at end of file diff --git a/components/calendar/components/header/index.d.ts b/components/calendar/components/header/index.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/components/calendar/components/header/index.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/components/calendar/components/header/index.js b/components/calendar/components/header/index.js new file mode 100644 index 0000000..bf9243f --- /dev/null +++ b/components/calendar/components/header/index.js @@ -0,0 +1,16 @@ +import { VantComponent } from '../../../common/component'; +VantComponent({ + props: { + title: { + type: String, + value: '日期选择', + }, + subtitle: String, + showTitle: Boolean, + showSubtitle: Boolean, + }, + data: { + weekdays: ['日', '一', '二', '三', '四', '五', '六'], + }, + methods: {}, +}); diff --git a/components/calendar/components/header/index.json b/components/calendar/components/header/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/calendar/components/header/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/calendar/components/header/index.wxml b/components/calendar/components/header/index.wxml new file mode 100644 index 0000000..eb8e4b4 --- /dev/null +++ b/components/calendar/components/header/index.wxml @@ -0,0 +1,16 @@ + + + + {{ title }} + + + + {{ subtitle }} + + + + + {{ item }} + + + diff --git a/components/calendar/components/header/index.wxss b/components/calendar/components/header/index.wxss new file mode 100644 index 0000000..4075e48 --- /dev/null +++ b/components/calendar/components/header/index.wxss @@ -0,0 +1 @@ +@import '../../../common/index.wxss';.van-calendar__header{-webkit-flex-shrink:0;flex-shrink:0;box-shadow:0 2px 10px rgba(125,126,128,.16);box-shadow:var(--calendar-header-box-shadow,0 2px 10px rgba(125,126,128,.16))}.van-calendar__header-subtitle,.van-calendar__header-title{text-align:center;height:44px;height:var(--calendar-header-title-height,44px);font-weight:500;font-weight:var(--font-weight-bold,500);line-height:44px;line-height:var(--calendar-header-title-height,44px)}.van-calendar__header-title+.van-calendar__header-title,.van-calendar__header-title:empty{display:none}.van-calendar__header-title:empty+.van-calendar__header-title{display:block!important}.van-calendar__weekdays{display:-webkit-flex;display:flex}.van-calendar__weekday{-webkit-flex:1;flex:1;text-align:center;font-size:12px;font-size:var(--calendar-weekdays-font-size,12px);line-height:30px;line-height:var(--calendar-weekdays-height,30px)} \ No newline at end of file diff --git a/components/calendar/components/month/index.js b/components/calendar/components/month/index.js new file mode 100644 index 0000000..4c872a9 --- /dev/null +++ b/components/calendar/components/month/index.js @@ -0,0 +1,157 @@ +import { VantComponent } from '../../../common/component'; +import { + getMonthEndDay, + compareDay, + getPrevDay, + getNextDay, +} from '../../utils'; +VantComponent({ + props: { + date: { + type: null, + observer: 'setDays', + }, + type: { + type: String, + observer: 'setDays', + }, + color: String, + minDate: { + type: null, + observer: 'setDays', + }, + maxDate: { + type: null, + observer: 'setDays', + }, + showMark: Boolean, + rowHeight: null, + formatter: { + type: null, + observer: 'setDays', + }, + currentDate: { + type: null, + observer: 'setDays', + }, + allowSameDay: Boolean, + showSubtitle: Boolean, + showMonthTitle: Boolean, + }, + data: { + visible: true, + days: [], + }, + methods: { + onClick(event) { + const { index } = event.currentTarget.dataset; + const item = this.data.days[index]; + if (item.type !== 'disabled') { + this.$emit('click', item); + } + }, + setDays() { + const days = []; + const startDate = new Date(this.data.date); + const year = startDate.getFullYear(); + const month = startDate.getMonth(); + const totalDay = getMonthEndDay( + startDate.getFullYear(), + startDate.getMonth() + 1 + ); + for (let day = 1; day <= totalDay; day++) { + const date = new Date(year, month, day); + const type = this.getDayType(date); + let config = { + date, + type, + text: day, + bottomInfo: this.getBottomInfo(type), + }; + if (this.data.formatter) { + config = this.data.formatter(config); + } + days.push(config); + } + this.setData({ days }); + }, + getMultipleDayType(day) { + const { currentDate } = this.data; + if (!Array.isArray(currentDate)) { + return ''; + } + const isSelected = (date) => + currentDate.some((item) => compareDay(item, date) === 0); + if (isSelected(day)) { + const prevDay = getPrevDay(day); + const nextDay = getNextDay(day); + const prevSelected = isSelected(prevDay); + const nextSelected = isSelected(nextDay); + if (prevSelected && nextSelected) { + return 'multiple-middle'; + } + if (prevSelected) { + return 'end'; + } + return nextSelected ? 'start' : 'multiple-selected'; + } + return ''; + }, + getRangeDayType(day) { + const { currentDate, allowSameDay } = this.data; + if (!Array.isArray(currentDate)) { + return; + } + const [startDay, endDay] = currentDate; + if (!startDay) { + return; + } + const compareToStart = compareDay(day, startDay); + if (!endDay) { + return compareToStart === 0 ? 'start' : ''; + } + const compareToEnd = compareDay(day, endDay); + if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) { + return 'start-end'; + } + if (compareToStart === 0) { + return 'start'; + } + if (compareToEnd === 0) { + return 'end'; + } + if (compareToStart > 0 && compareToEnd < 0) { + return 'middle'; + } + }, + getDayType(day) { + const { type, minDate, maxDate, currentDate } = this.data; + if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) { + return 'disabled'; + } + if (type === 'single') { + return compareDay(day, currentDate) === 0 ? 'selected' : ''; + } + if (type === 'multiple') { + return this.getMultipleDayType(day); + } + /* istanbul ignore else */ + if (type === 'range') { + return this.getRangeDayType(day); + } + }, + getBottomInfo(type) { + if (this.data.type === 'range') { + if (type === 'start') { + return '开始'; + } + if (type === 'end') { + return '结束'; + } + if (type === 'start-end') { + return '开始/结束'; + } + } + }, + }, +}); diff --git a/components/calendar/components/month/index.json b/components/calendar/components/month/index.json new file mode 100644 index 0000000..467ce29 --- /dev/null +++ b/components/calendar/components/month/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/components/calendar/components/month/index.wxml b/components/calendar/components/month/index.wxml new file mode 100644 index 0000000..55bab83 --- /dev/null +++ b/components/calendar/components/month/index.wxml @@ -0,0 +1,39 @@ + + + + + + {{ computed.formatMonthTitle(date) }} + + + + + {{ computed.getMark(date) }} + + + + + {{ item.topInfo }} + {{ item.text }} + + {{ item.bottomInfo }} + + + + + {{ item.topInfo }} + {{ item.text }} + + {{ item.bottomInfo }} + + + + + diff --git a/components/calendar/components/month/index.wxs b/components/calendar/components/month/index.wxs new file mode 100644 index 0000000..a057079 --- /dev/null +++ b/components/calendar/components/month/index.wxs @@ -0,0 +1,67 @@ +/* eslint-disable */ +var utils = require('../../utils.wxs'); + +function getMark(date) { + return getDate(date).getMonth() + 1; +} + +var ROW_HEIGHT = 64; + +function getDayStyle(type, index, date, rowHeight, color) { + var style = []; + var offset = getDate(date).getDay(); + + if (index === 0) { + style.push(['margin-left', (100 * offset) / 7 + '%']); + } + + if (rowHeight !== ROW_HEIGHT) { + style.push(['height', rowHeight + 'px']); + } + + if (color) { + if ( + type === 'start' || + type === 'end' || + type === 'multiple-selected' || + type === 'multiple-middle' + ) { + style.push(['background', color]); + } else if (type === 'middle') { + style.push(['color', color]); + } + } + + return style + .map(function(item) { + return item.join(':'); + }) + .join(';'); +} + +function formatMonthTitle(date) { + date = getDate(date); + return date.getFullYear() + '年' + (date.getMonth() + 1) + '月'; +} + +function getMonthStyle(visible, date, rowHeight) { + if (!visible) { + date = getDate(date); + + var totalDay = utils.getMonthEndDay( + date.getFullYear(), + date.getMonth() + 1 + ); + var offset = getDate(date).getDay(); + var padding = Math.ceil((totalDay + offset) / 7) * rowHeight; + + return 'padding-bottom:' + padding + 'px'; + } +} + +module.exports = { + getMark: getMark, + getDayStyle: getDayStyle, + formatMonthTitle: formatMonthTitle, + getMonthStyle: getMonthStyle +}; diff --git a/components/calendar/components/month/index.wxss b/components/calendar/components/month/index.wxss new file mode 100644 index 0000000..725e737 --- /dev/null +++ b/components/calendar/components/month/index.wxss @@ -0,0 +1 @@ +@import '../../../common/index.wxss';.van-calendar{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;height:100%;background-color:#fff;background-color:var(--calendar-background-color,#fff)}.van-calendar__month-title{text-align:center;height:44px;height:var(--calendar-header-title-height,44px);font-weight:500;font-weight:var(--font-weight-bold,500);font-size:14px;font-size:var(--calendar-month-title-font-size,14px);line-height:44px;line-height:var(--calendar-header-title-height,44px)}.van-calendar__days{position:relative;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-user-select:none;user-select:none}.van-calendar__month-mark{position:absolute;top:50%;left:50%;z-index:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);pointer-events:none;color:rgba(242,243,245,.8);color:var(--calendar-month-mark-color,rgba(242,243,245,.8));font-size:160px;font-size:var(--calendar-month-mark-font-size,160px)}.van-calendar__day,.van-calendar__selected-day{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;text-align:center}.van-calendar__day{position:relative;width:14.285%;height:64px;height:var(--calendar-day-height,64px);font-size:16px;font-size:var(--calendar-day-font-size,16px)}.van-calendar__day--end,.van-calendar__day--multiple-middle,.van-calendar__day--multiple-selected,.van-calendar__day--start,.van-calendar__day--start-end{color:#fff;color:var(--calendar-range-edge-color,#fff);background-color:#ee0a24;background-color:var(--calendar-range-edge-background-color,#ee0a24)}.van-calendar__day--start{border-radius:4px 0 0 4px;border-radius:var(--border-radius-md,4px) 0 0 var(--border-radius-md,4px)}.van-calendar__day--end{border-radius:0 4px 4px 0;border-radius:0 var(--border-radius-md,4px) var(--border-radius-md,4px) 0}.van-calendar__day--multiple-selected,.van-calendar__day--start-end{border-radius:4px;border-radius:var(--border-radius-md,4px)}.van-calendar__day--middle{color:#ee0a24;color:var(--calendar-range-middle-color,#ee0a24)}.van-calendar__day--middle:after{position:absolute;top:0;right:0;bottom:0;left:0;background-color:currentColor;content:"";opacity:.1;opacity:var(--calendar-range-middle-background-opacity,.1)}.van-calendar__day--disabled{cursor:default;color:#c8c9cc;color:var(--calendar-day-disabled-color,#c8c9cc)}.van-calendar__bottom-info,.van-calendar__top-info{position:absolute;right:0;left:0;font-size:10px;font-size:var(--calendar-info-font-size,10px);line-height:14px;line-height:var(--calendar-info-line-height,14px)}@media (max-width:350px){.van-calendar__bottom-info,.van-calendar__top-info{font-size:9px}}.van-calendar__top-info{top:6px}.van-calendar__bottom-info{bottom:4px}.van-calendar__selected-day{width:54px;width:var(--calendar-selected-day-size,54px);height:54px;height:var(--calendar-selected-day-size,54px);color:#fff;color:var(--calendar-selected-day-color,#fff);background-color:#ee0a24;background-color:var(--calendar-selected-day-background-color,#ee0a24);border-radius:4px;border-radius:var(--border-radius-md,4px)} \ No newline at end of file diff --git a/components/calendar/index.js b/components/calendar/index.js new file mode 100644 index 0000000..779d0ff --- /dev/null +++ b/components/calendar/index.js @@ -0,0 +1,290 @@ +import { VantComponent } from '../common/component'; +import { + ROW_HEIGHT, + getNextDay, + compareDay, + copyDates, + calcDateNum, + formatMonthTitle, + compareMonth, + getMonths, + getDayByOffset, +} from './utils'; +import Toast from '../toast/toast'; +import { requestAnimationFrame } from '../common/utils'; +VantComponent({ + props: { + title: { + type: String, + value: '日期选择', + }, + color: String, + show: { + type: Boolean, + observer(val) { + if (val) { + this.initRect(); + this.scrollIntoView(); + } + }, + }, + formatter: null, + confirmText: { + type: String, + value: '确定', + }, + rangePrompt: String, + defaultDate: { + type: null, + observer(val) { + this.setData({ currentDate: val }); + this.scrollIntoView(); + }, + }, + allowSameDay: Boolean, + confirmDisabledText: String, + type: { + type: String, + value: 'single', + observer: 'reset', + }, + minDate: { + type: null, + value: Date.now(), + }, + maxDate: { + type: null, + value: new Date( + new Date().getFullYear(), + new Date().getMonth() + 6, + new Date().getDate() + ).getTime(), + }, + position: { + type: String, + value: 'bottom', + }, + rowHeight: { + type: null, + value: ROW_HEIGHT, + }, + round: { + type: Boolean, + value: true, + }, + poppable: { + type: Boolean, + value: true, + }, + showMark: { + type: Boolean, + value: true, + }, + showTitle: { + type: Boolean, + value: true, + }, + showConfirm: { + type: Boolean, + value: true, + }, + showSubtitle: { + type: Boolean, + value: true, + }, + safeAreaInsetBottom: { + type: Boolean, + value: true, + }, + closeOnClickOverlay: { + type: Boolean, + value: true, + }, + maxRange: { + type: null, + value: null, + }, + }, + data: { + subtitle: '', + currentDate: null, + scrollIntoView: '', + }, + created() { + this.setData({ + currentDate: this.getInitialDate(), + }); + }, + mounted() { + if (this.data.show || !this.data.poppable) { + this.initRect(); + this.scrollIntoView(); + } + }, + methods: { + reset() { + this.setData({ currentDate: this.getInitialDate() }); + this.scrollIntoView(); + }, + initRect() { + if (this.contentObserver != null) { + this.contentObserver.disconnect(); + } + const contentObserver = this.createIntersectionObserver({ + thresholds: [0, 0.1, 0.9, 1], + observeAll: true, + }); + this.contentObserver = contentObserver; + contentObserver.relativeTo('.van-calendar__body'); + contentObserver.observe('.month', (res) => { + if (res.boundingClientRect.top <= res.relativeRect.top) { + // @ts-ignore + this.setData({ subtitle: formatMonthTitle(res.dataset.date) }); + } + }); + }, + getInitialDate() { + const { type, defaultDate, minDate } = this.data; + if (type === 'range') { + const [startDay, endDay] = defaultDate || []; + return [ + startDay || minDate, + endDay || getNextDay(new Date(minDate)).getTime(), + ]; + } + if (type === 'multiple') { + return defaultDate || [minDate]; + } + return defaultDate || minDate; + }, + scrollIntoView() { + requestAnimationFrame(() => { + const { currentDate, type, show, poppable, minDate, maxDate } = this.data + // @ts-ignore + const targetDate = type === 'single' ? currentDate : currentDate[0]; + const displayed = show || !poppable; + if (!targetDate || !displayed) { + return; + } + const months = getMonths(minDate, maxDate); + months.some((month, index) => { + if (compareMonth(month, targetDate) === 0) { + this.setData({ scrollIntoView: `month${index}` }); + return true + } + return false + }) + }) + }, + onOpen() { + this.$emit('open'); + }, + onOpened() { + this.$emit('opened'); + }, + onClose() { + this.$emit('close'); + }, + onClosed() { + this.$emit('closed'); + }, + onClickDay(event) { + const { date } = event.detail; + const { type, currentDate, allowSameDay } = this.data; + if (type === 'range') { + // @ts-ignore + const [startDay, endDay] = currentDate; + if (startDay && !endDay) { + const compareToStart = compareDay(date, startDay); + if (compareToStart === 1) { + this.select([startDay, date], true); + } else if (compareToStart === -1) { + this.select([date, null]); + } else if (allowSameDay) { + this.select([date, date]); + } + } else { + this.select([date, null]); + } + } else if (type === 'multiple') { + let selectedIndex; + // @ts-ignore + const selected = currentDate.some((dateItem, index) => { + const equal = compareDay(dateItem, date) === 0; + if (equal) { + selectedIndex = index; + } + return equal; + }); + if (selected) { + // @ts-ignore + const cancelDate = currentDate.splice(selectedIndex, 1); + this.setData({ currentDate }); + this.unselect(cancelDate); + } else { + // @ts-ignore + this.select([...currentDate, date]); + } + } else { + this.select(date, true); + } + }, + unselect(dateArray) { + const date = dateArray[0]; + if (date) { + this.$emit('unselect', copyDates(date)); + } + }, + select(date, complete) { + if (complete && this.data.type === 'range') { + const valid = this.checkRange(date); + if (!valid) { + // auto selected to max range if showConfirm + if (this.data.showConfirm) { + this.emit([ + date[0], + getDayByOffset(date[0], this.data.maxRange - 1), + ]); + } else { + this.emit(date); + } + return; + } + } + this.emit(date); + if (complete && !this.data.showConfirm) { + this.onConfirm(); + } + }, + emit(date) { + const getTime = (date) => (date instanceof Date ? date.getTime() : date); + this.setData({ + currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date), + }); + this.$emit('select', copyDates(date)); + }, + checkRange(date) { + const { maxRange, rangePrompt } = this.data; + if (maxRange && calcDateNum(date) > maxRange) { + Toast({ + context: this, + message: rangePrompt || `选择天数不能超过 ${maxRange} 天`, + }); + return false; + } + return true; + }, + onConfirm() { + if ( + this.data.type === 'range' && + !this.checkRange(this.data.currentDate) + ) { + return; + } + wx.nextTick(() => { + // @ts-ignore + this.$emit('confirm', copyDates(this.data.currentDate)); + }); + }, + }, +}); diff --git a/components/calendar/index.json b/components/calendar/index.json new file mode 100644 index 0000000..397d5ae --- /dev/null +++ b/components/calendar/index.json @@ -0,0 +1,10 @@ +{ + "component": true, + "usingComponents": { + "header": "./components/header/index", + "month": "./components/month/index", + "van-button": "../button/index", + "van-popup": "../popup/index", + "van-toast": "../toast/index" + } +} diff --git a/components/calendar/index.wxml b/components/calendar/index.wxml new file mode 100644 index 0000000..7df0b98 --- /dev/null +++ b/components/calendar/index.wxml @@ -0,0 +1,25 @@ + + + + + + + + + + + + diff --git a/components/calendar/index.wxs b/components/calendar/index.wxs new file mode 100644 index 0000000..2c04be1 --- /dev/null +++ b/components/calendar/index.wxs @@ -0,0 +1,37 @@ +/* eslint-disable */ +var utils = require('./utils.wxs'); + +function getMonths(minDate, maxDate) { + var months = []; + var cursor = getDate(minDate); + + cursor.setDate(1); + + do { + months.push(cursor.getTime()); + cursor.setMonth(cursor.getMonth() + 1); + } while (utils.compareMonth(cursor, getDate(maxDate)) !== 1); + + return months; +} + +function getButtonDisabled(type, currentDate) { + if (currentDate == null) { + return true; + } + + if (type === 'range') { + return !currentDate[0] || !currentDate[1]; + } + + if (type === 'multiple') { + return !currentDate.length; + } + + return !currentDate; +} + +module.exports = { + getMonths: getMonths, + getButtonDisabled: getButtonDisabled +}; diff --git a/components/calendar/index.wxss b/components/calendar/index.wxss new file mode 100644 index 0000000..1558a52 --- /dev/null +++ b/components/calendar/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-calendar{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;height:100%;height:var(--calendar-height,100%);background-color:#fff;background-color:var(--calendar-background-color,#fff)}.van-calendar__close-icon{top:11px}.van-calendar__popup--bottom,.van-calendar__popup--top{height:60%;height:var(--calendar-popup-height,60%)}.van-calendar__popup--left,.van-calendar__popup--right{height:100%}.van-calendar__body{-webkit-flex:1;flex:1;overflow:auto;-webkit-overflow-scrolling:touch}.van-calendar__footer{-webkit-flex-shrink:0;flex-shrink:0;padding:0 16px;padding:0 var(--padding-md,16px)}.van-calendar__footer--safe-area-inset-bottom{padding-bottom:env(safe-area-inset-bottom)}.van-calendar__footer+.van-calendar__footer,.van-calendar__footer:empty{display:none}.van-calendar__footer:empty+.van-calendar__footer{display:block!important}.van-calendar__confirm{height:36px!important;height:var(--calendar-confirm-button-height,36px)!important;margin:7px 0!important;margin:var(--calendar-confirm-button-margin,7px 0)!important;line-height:34px!important;line-height:var(--calendar-confirm-button-line-height,34px)!important} \ No newline at end of file diff --git a/components/calendar/utils.js b/components/calendar/utils.js new file mode 100644 index 0000000..281a35c --- /dev/null +++ b/components/calendar/utils.js @@ -0,0 +1,78 @@ +export const ROW_HEIGHT = 64; +export function formatMonthTitle(date) { + if (!(date instanceof Date)) { + date = new Date(date); + } + return `${date.getFullYear()}年${date.getMonth() + 1}月`; +} +export function compareMonth(date1, date2) { + if (!(date1 instanceof Date)) { + date1 = new Date(date1); + } + if (!(date2 instanceof Date)) { + date2 = new Date(date2); + } + const year1 = date1.getFullYear(); + const year2 = date2.getFullYear(); + const month1 = date1.getMonth(); + const month2 = date2.getMonth(); + if (year1 === year2) { + return month1 === month2 ? 0 : month1 > month2 ? 1 : -1; + } + return year1 > year2 ? 1 : -1; +} +export function compareDay(day1, day2) { + if (!(day1 instanceof Date)) { + day1 = new Date(day1); + } + if (!(day2 instanceof Date)) { + day2 = new Date(day2); + } + const compareMonthResult = compareMonth(day1, day2); + if (compareMonthResult === 0) { + const date1 = day1.getDate(); + const date2 = day2.getDate(); + return date1 === date2 ? 0 : date1 > date2 ? 1 : -1; + } + return compareMonthResult; +} +export function getDayByOffset(date, offset) { + date = new Date(date); + date.setDate(date.getDate() + offset); + return date; +} +export function getPrevDay(date) { + return getDayByOffset(date, -1); +} +export function getNextDay(date) { + return getDayByOffset(date, 1); +} +export function calcDateNum(date) { + const day1 = new Date(date[0]).getTime(); + const day2 = new Date(date[1]).getTime(); + return (day2 - day1) / (1000 * 60 * 60 * 24) + 1; +} +export function copyDates(dates) { + if (Array.isArray(dates)) { + return dates.map((date) => { + if (date === null) { + return date; + } + return new Date(date); + }); + } + return new Date(dates); +} +export function getMonthEndDay(year, month) { + return 32 - new Date(year, month - 1, 32).getDate(); +} +export function getMonths(minDate, maxDate) { + const months = []; + const cursor = new Date(minDate); + cursor.setDate(1); + do { + months.push(cursor.getTime()); + cursor.setMonth(cursor.getMonth() + 1); + } while (compareMonth(cursor, maxDate) !== 1); + return months; +} diff --git a/components/calendar/utils.wxs b/components/calendar/utils.wxs new file mode 100644 index 0000000..e57f6b3 --- /dev/null +++ b/components/calendar/utils.wxs @@ -0,0 +1,25 @@ +/* eslint-disable */ +function getMonthEndDay(year, month) { + return 32 - getDate(year, month - 1, 32).getDate(); +} + +function compareMonth(date1, date2) { + date1 = getDate(date1); + date2 = getDate(date2); + + var year1 = date1.getFullYear(); + var year2 = date2.getFullYear(); + var month1 = date1.getMonth(); + var month2 = date2.getMonth(); + + if (year1 === year2) { + return month1 === month2 ? 0 : month1 > month2 ? 1 : -1; + } + + return year1 > year2 ? 1 : -1; +} + +module.exports = { + getMonthEndDay: getMonthEndDay, + compareMonth: compareMonth +}; diff --git a/components/common/utils.js b/components/common/utils.js index cc0f8f1..778b2e5 100644 --- a/components/common/utils.js +++ b/components/common/utils.js @@ -30,3 +30,18 @@ export function addUnit(value) { value = String(value); return isNumber(value) ? `${value}px` : value; } +export function requestAnimationFrame(cb) { + const systemInfo = getSystemInfoSync(); + if (systemInfo.platform === 'devtools') { + return setTimeout(() => { + cb(); + }, 1000 / 30); + } + return wx + .createSelectorQuery() + .selectViewport() + .boundingClientRect() + .exec(() => { + cb(); + }); + } \ No newline at end of file diff --git a/components/common/validator.js b/components/common/validator.js new file mode 100644 index 0000000..1c7d1e9 --- /dev/null +++ b/components/common/validator.js @@ -0,0 +1,30 @@ +export function isFunction(val) { + return typeof val === 'function'; +} +export function isPlainObject(val) { + return val !== null && typeof val === 'object' && !Array.isArray(val); +} +export function isPromise(val) { + return isPlainObject(val) && isFunction(val.then) && isFunction(val.catch); +} +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 isBoolean(value) { + return typeof value === 'boolean'; +} +const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i; +const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i; +export function isImageUrl(url) { + return IMAGE_REGEXP.test(url); +} +export function isVideoUrl(url) { + return VIDEO_REGEXP.test(url); +} diff --git a/components/toast/index.d.ts b/components/toast/index.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/components/toast/index.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/components/toast/index.js b/components/toast/index.js new file mode 100644 index 0000000..c4c2ed9 --- /dev/null +++ b/components/toast/index.js @@ -0,0 +1,29 @@ +import { VantComponent } from '../common/component'; +VantComponent({ + props: { + show: Boolean, + mask: Boolean, + message: String, + forbidClick: Boolean, + zIndex: { + type: Number, + value: 1000, + }, + type: { + type: String, + value: 'text', + }, + loadingType: { + type: String, + value: 'circular', + }, + position: { + type: String, + value: 'middle', + }, + }, + methods: { + // for prevent touchmove + noop() {}, + }, +}); diff --git a/components/toast/index.json b/components/toast/index.json new file mode 100644 index 0000000..9b1b78c --- /dev/null +++ b/components/toast/index.json @@ -0,0 +1,9 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index", + "van-loading": "../loading/index", + "van-overlay": "../overlay/index", + "van-transition": "../transition/index" + } +} diff --git a/components/toast/index.wxml b/components/toast/index.wxml new file mode 100644 index 0000000..635e7d6 --- /dev/null +++ b/components/toast/index.wxml @@ -0,0 +1,33 @@ + + + + + {{ message }} + + + + + + {{ message }} + + + + + diff --git a/components/toast/index.wxss b/components/toast/index.wxss new file mode 100644 index 0000000..85dc7a8 --- /dev/null +++ b/components/toast/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss';.van-toast{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:initial;color:#fff;color:var(--toast-text-color,#fff);font-size:14px;font-size:var(--toast-font-size,14px);line-height:20px;line-height:var(--toast-line-height,20px);white-space:pre-wrap;word-wrap:break-word;background-color:rgba(0,0,0,.7);background-color:var(--toast-background-color,rgba(0,0,0,.7));border-radius:8px;border-radius:var(--toast-border-radius,8px)}.van-toast__container{position:fixed;top:50%;left:50%;width:-webkit-fit-content;width:fit-content;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);max-width:70%;max-width:var(--toast-max-width,70%)}.van-toast--text{min-width:96px;min-width:var(--toast-text-min-width,96px);padding:8px 12px;padding:var(--toast-text-padding,8px 12px)}.van-toast--icon{width:88px;width:var(--toast-default-width,88px);min-height:88px;min-height:var(--toast-default-min-height,88px);padding:16px;padding:var(--toast-default-padding,16px)}.van-toast--icon .van-toast__icon{font-size:36px;font-size:var(--toast-icon-size,36px)}.van-toast--icon .van-toast__text{padding-top:8px}.van-toast__loading{margin:10px 0}.van-toast--top{-webkit-transform:translateY(-30vh);transform:translateY(-30vh)}.van-toast--bottom{-webkit-transform:translateY(30vh);transform:translateY(30vh)} \ No newline at end of file diff --git a/components/toast/toast.d.ts b/components/toast/toast.d.ts new file mode 100644 index 0000000..1b2e209 --- /dev/null +++ b/components/toast/toast.d.ts @@ -0,0 +1,68 @@ +/// +declare type ToastMessage = string | number; +interface ToastOptions { + show?: boolean; + type?: string; + mask?: boolean; + zIndex?: number; + context?: + | WechatMiniprogram.Component.TrivialInstance + | WechatMiniprogram.Page.TrivialInstance; + position?: string; + duration?: number; + selector?: string; + forbidClick?: boolean; + loadingType?: string; + message?: ToastMessage; + onClose?: () => void; +} +declare function Toast( + toastOptions: ToastOptions | ToastMessage +): + | WechatMiniprogram.Component.Instance< + Record, + Record, + Record, + Record, + false + > + | undefined; +declare namespace Toast { + var loading: ( + options: string | number | ToastOptions + ) => + | WechatMiniprogram.Component.Instance< + Record, + Record, + Record, + Record, + false + > + | undefined; + var success: ( + options: string | number | ToastOptions + ) => + | WechatMiniprogram.Component.Instance< + Record, + Record, + Record, + Record, + false + > + | undefined; + var fail: ( + options: string | number | ToastOptions + ) => + | WechatMiniprogram.Component.Instance< + Record, + Record, + Record, + Record, + false + > + | undefined; + var clear: () => void; + var setDefaultOptions: (options: ToastOptions) => void; + var resetDefaultOptions: () => void; +} +export default Toast; diff --git a/components/toast/toast.js b/components/toast/toast.js new file mode 100644 index 0000000..4a1b63a --- /dev/null +++ b/components/toast/toast.js @@ -0,0 +1,70 @@ +import { isObj } from '../common/validator'; +const defaultOptions = { + type: 'text', + mask: false, + message: '', + show: true, + zIndex: 1000, + duration: 2000, + position: 'middle', + forbidClick: false, + loadingType: 'circular', + selector: '#van-toast', +}; +let queue = []; +let currentOptions = Object.assign({}, defaultOptions); +function parseOptions(message) { + return isObj(message) ? message : { message }; +} +function getContext() { + const pages = getCurrentPages(); + return pages[pages.length - 1]; +} +function Toast(toastOptions) { + const options = Object.assign( + Object.assign({}, currentOptions), + parseOptions(toastOptions) + ); + const context = options.context || getContext(); + const toast = context.selectComponent(options.selector); + if (!toast) { + console.warn('未找到 van-toast 节点,请确认 selector 及 context 是否正确'); + return; + } + delete options.context; + delete options.selector; + toast.clear = () => { + toast.setData({ show: false }); + if (options.onClose) { + options.onClose(); + } + }; + queue.push(toast); + toast.setData(options); + clearTimeout(toast.timer); + if (options.duration != null && options.duration > 0) { + toast.timer = setTimeout(() => { + toast.clear(); + queue = queue.filter((item) => item !== toast); + }, options.duration); + } + return toast; +} +const createMethod = (type) => (options) => + Toast(Object.assign({ type }, parseOptions(options))); +Toast.loading = createMethod('loading'); +Toast.success = createMethod('success'); +Toast.fail = createMethod('fail'); +Toast.clear = () => { + queue.forEach((toast) => { + toast.clear(); + }); + queue = []; +}; +Toast.setDefaultOptions = (options) => { + Object.assign(currentOptions, options); +}; +Toast.resetDefaultOptions = () => { + currentOptions = Object.assign({}, defaultOptions); +}; +export default Toast; diff --git a/pages/client/registe/index.js b/pages/client/registe/index.js index 83a2fa2..f3e3fa1 100644 --- a/pages/client/registe/index.js +++ b/pages/client/registe/index.js @@ -26,7 +26,7 @@ Page({ if(options.id){ wx.showLoading({ title: '正在获取', mask: true }) getCustomerInfo(options.id).then(result => { - this.setData({ customerInfo: result.data }) + this.setData({ customerInfo: result.data, ['form.mobile']: result.data.mobile }) const params = { id: 6 } params.metaData = { factoryId: app.userInfo.factoryId, diff --git a/pages/process/index/index.js b/pages/process/index/index.js index 12e79f5..238691f 100644 --- a/pages/process/index/index.js +++ b/pages/process/index/index.js @@ -30,23 +30,30 @@ Component({ // { status: 5, badge: '', name: '已关闭', icon: '/assets/image/icon_close.png' } ], show: false, - actions: [ - { name: '今年' }, - { name: '今月' }, - { name: '今日' }, - ], - form: {}, totalInfo: { totalMoney: 0, totalWeight: 0, availableCreditLine: 0, usedCreditLine: 0 - } + }, + vdate: [], + vdateString: '' }, lifetimes: { // 生命周期函数,可以为函数,或一个在methods段中定义的方法名 attached: function () { - this.setData({userInfo: app.userInfo, height: app.globalData.safeFragmentHeight - 100 }) + var min = new Date() + min.setFullYear(min.getFullYear() - 1, min.getMonth(), min.getDate()) + min.setHours(0, 0, 0) + var minDate = min.getTime() + var max = new Date(new Date().getTime() + 24 * 60 * 60 * 1000) + max.setHours(0, 0, 0) + var maxDate = max.getTime() + var today = new Date() + today.setHours(0, 0, 0) + var vdate = [today.getTime(), maxDate] + var vdateString = util.formatDate(new Date(), 'Y-M-D') + '至' + util.formatDate(max, 'Y-M-D') + this.setData({userInfo: app.userInfo, height: app.globalData.safeFragmentHeight - 100, minDate, maxDate, vdate, vdateString }) event.on('EventMessage', this, this.onEvent) }, detached: function () { @@ -55,7 +62,7 @@ Component({ }, methods: { onRestart: function () { - this.fetchStatisticsInfo() + this.fetchStatisticsInfo(this.data.vdate) }, onEvent: function (message) { if (message.what == 888) { @@ -89,8 +96,8 @@ Component({ outList: function(e){ }, - fetchStatisticsInfo: function(){ - getStatisticsInfo(this.data.form).then(result => { + fetchStatisticsInfo: function(vdate){ + getStatisticsInfo({startTime: util.formatTime(new Date(vdate[0]), 'Y-M-D'), endTime: util.formatTime(new Date(vdate[1]), 'Y-M-D')}).then(result => { if(Number(result.data.priceOrderNum) > 0){ this.data.tabList[0].badge = Number(result.data.priceOrderNum) } else { @@ -112,14 +119,15 @@ Component({ if(util.isEmpty(result.data.usedCreditLine)){ result.data.usedCreditLine = app.userInfo.usedCreditLine } - this.setData({ tabList: this.data.tabList, totalInfo: result.data }) + var vdateString = util.formatDate(new Date(vdate[0]), 'Y-M-D') + '至' + util.formatDate(new Date(vdate[1]), 'Y-M-D') + this.setData({ tabList: this.data.tabList, totalInfo: result.data, vdate, vdateString }) }).catch(err => { console.log(err) }) }, showSheet: function(){ - // this.setData({ show: true }) - // event.emit('TabMessage', { what: 99, visiable: false }) + this.setData({ show: true }) + event.emit('TabMessage', { what: 99, visiable: false }) }, onClose: function() { this.setData({ show: false }) @@ -128,7 +136,9 @@ Component({ }, 100) }, onSelect: function({detail}) { - console.log(detail) + const [start, end] = detail + this.onClose() + this.fetchStatisticsInfo([start.getTime(), end.getTime()]) }, toAuths: function(){ wx.navigateTo({ url: '/pages/htmls/auths/index' }) diff --git a/pages/process/index/index.json b/pages/process/index/index.json index 466d012..eb60529 100644 --- a/pages/process/index/index.json +++ b/pages/process/index/index.json @@ -7,6 +7,6 @@ "van-cell-group": "/components/cell-group/index", "van-info": "/components/info/index", "van-icon": "/components/icon/index", - "van-action-sheet": "/components/action-sheet/index" + "van-calendar": "/components/calendar/index" } } \ No newline at end of file diff --git a/pages/process/index/index.wxml b/pages/process/index/index.wxml index f1c91a8..7e84e1e 100644 --- a/pages/process/index/index.wxml +++ b/pages/process/index/index.wxml @@ -17,8 +17,8 @@ 收货统计 - 今日 - + {{vdateString}} + @@ -130,4 +130,5 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/project.config.json b/project.config.json index a2fa6d7..f4aade1 100644 --- a/project.config.json +++ b/project.config.json @@ -4,7 +4,7 @@ "ignore": [] }, "setting": { - "urlCheck": false, + "urlCheck": true, "es6": true, "enhance": true, "postcss": true, diff --git a/utils/util.js b/utils/util.js index b5ef4ef..aa181e7 100644 --- a/utils/util.js +++ b/utils/util.js @@ -5,7 +5,7 @@ const formatTime = date => { 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(':') + return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':') } const formatNumber = n => { @@ -32,12 +32,9 @@ function beforeDay(day, format) { function formatDate(date, format) { var formateArr = ['Y', 'M', 'D', 'h', 'm', 's']; var returnArr = []; - returnArr.push(date.getFullYear()); - returnArr.push(formatNumber(date.getMonth() + 1)); - returnArr.push(formatNumber(date.getDate())); - returnArr.push(formatNumber(date.getHours())); - returnArr.push(formatNumber(date.getMinutes())); - returnArr.push(formatNumber(date.getSeconds())); + returnArr.push(date.getFullYear()) + returnArr.push(formatNumber(date.getMonth() + 1)) + returnArr.push(formatNumber(date.getDate())) for (var i in returnArr) { format = format.replace(formateArr[i], returnArr[i]); }