3 files added
	
		
		5 files modified
	
		
		1 files deleted
	
	
 
	
	
	
	
	
	
	
	
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | /* 蓝色圆形加减按钮 */ | 
|---|
|  |  |  | .blue-btn-circle{ | 
|---|
|  |  |  | display: inline-block; | 
|---|
|  |  |  | height: 24px; | 
|---|
|  |  |  | width: 24px; | 
|---|
|  |  |  | line-height: 24px; | 
|---|
|  |  |  | text-align: center; | 
|---|
|  |  |  | box-sizing: border-box; | 
|---|
|  |  |  | font-size: 14px!important; | 
|---|
|  |  |  | border-radius: 50%!important; | 
|---|
|  |  |  | background: #518EFF; | 
|---|
|  |  |  | border-radius: 4px; | 
|---|
|  |  |  | color: #FFFFFF; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .blue-outline-btn-circle{ | 
|---|
|  |  |  | display: inline-block; | 
|---|
|  |  |  | height: 24px; | 
|---|
|  |  |  | width: 24px; | 
|---|
|  |  |  | line-height: 22px; | 
|---|
|  |  |  | text-align: center; | 
|---|
|  |  |  | box-sizing: border-box; | 
|---|
|  |  |  | font-size: 12px!important; | 
|---|
|  |  |  | border-radius: 50%; | 
|---|
| New file | 
|  |  |  | 
|---|
|  |  |  | <template> | 
|---|
|  |  |  | <view class="date-time-picker" v-if="visible"> | 
|---|
|  |  |  | <view class="date-time-mask" @click.stop="hide"></view> | 
|---|
|  |  |  | <view class="date-time-container" @click.stop="handleEvent"> | 
|---|
|  |  |  | <view class="time-picker-tool" v-if='isShowToolBar'> | 
|---|
|  |  |  | <view :class="[cancelButtonClass]" @click.stop="cancel"> | 
|---|
|  |  |  | <text>{{cancelButtonText}}</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view :class="[toolBarTitleClass]"> | 
|---|
|  |  |  | <text>{{toolBarTitle}}</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view :class="[confirmButtonClass]" @click.stop="confirm"> | 
|---|
|  |  |  | <text>{{confirmButtonText}}</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <picker-view class="picker-view" :indicator-style="indicatorStyleString" :value="dateTime" @change="dateTimePickerChange"> | 
|---|
|  |  |  | <picker-view-column data-id='year' v-if='isShowYear'> | 
|---|
|  |  |  | <view class="item" v-for="(item,index) in years" :key="index">{{item}}年</view> | 
|---|
|  |  |  | </picker-view-column> | 
|---|
|  |  |  | <picker-view-column data-id='month' v-if='isShowMonth'> | 
|---|
|  |  |  | <view class="item" v-for="(item,index) in months" :key="index">{{item}}月</view> | 
|---|
|  |  |  | </picker-view-column> | 
|---|
|  |  |  | <picker-view-column data-id='day' v-if='isShowDay'> | 
|---|
|  |  |  | <view class="item" v-for="(item,index) in days" :key="index">{{item}}日</view> | 
|---|
|  |  |  | </picker-view-column> | 
|---|
|  |  |  | <picker-view-column data-id='hour' v-if='isShowHour'> | 
|---|
|  |  |  | <view class="item" v-for="(item,index) in hours" :key="index">{{item}}时</view> | 
|---|
|  |  |  | </picker-view-column> | 
|---|
|  |  |  | <picker-view-column data-id='minute' v-if='isShowMinute'> | 
|---|
|  |  |  | <view class="item" v-for="(item,index) in minutes" :key="index">{{item}}分</view> | 
|---|
|  |  |  | </picker-view-column> | 
|---|
|  |  |  | <picker-view-column data-id='second' v-if='isShowSecond'> | 
|---|
|  |  |  | <view class="item" v-for="(item,index) in seconds" :key="index">{{item}}秒</view> | 
|---|
|  |  |  | </picker-view-column> | 
|---|
|  |  |  | </picker-view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </template> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <script> | 
|---|
|  |  |  | import { | 
|---|
|  |  |  | getOneMonthDays, | 
|---|
|  |  |  | getTimeArray, | 
|---|
|  |  |  | addZero, | 
|---|
|  |  |  | getIndexOfArray | 
|---|
|  |  |  | } from './uitls/util.js' | 
|---|
|  |  |  | export default { | 
|---|
|  |  |  | name: 'DateTimePicker', | 
|---|
|  |  |  | props: { | 
|---|
|  |  |  | startYear: { | 
|---|
|  |  |  | type: Number, | 
|---|
|  |  |  | default: 1900 | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | endYear: { | 
|---|
|  |  |  | type: Number, | 
|---|
|  |  |  | default: new Date().getFullYear() | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | isShowToolBar: { | 
|---|
|  |  |  | type: Boolean, | 
|---|
|  |  |  | default: true | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | cancelButtonText: { | 
|---|
|  |  |  | type: String, | 
|---|
|  |  |  | default: '取消' | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | cancelButtonClass: { | 
|---|
|  |  |  | type: String, | 
|---|
|  |  |  | default: 'cancel-btn' | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | toolBarTitle: { | 
|---|
|  |  |  | type: String, | 
|---|
|  |  |  | default: '请选择' | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | toolBarTitleClass: { | 
|---|
|  |  |  | type: String, | 
|---|
|  |  |  | default: 'tool-title' | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | confirmButtonText: { | 
|---|
|  |  |  | type: String, | 
|---|
|  |  |  | default: '确定' | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | confirmButtonClass: { | 
|---|
|  |  |  | type: String, | 
|---|
|  |  |  | default: 'confirm-btn' | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | datestring: { | 
|---|
|  |  |  | type: String, | 
|---|
|  |  |  | default: '' | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | type: { | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * date 年月日 | 
|---|
|  |  |  | * year-month 年月 | 
|---|
|  |  |  | * year 年 | 
|---|
|  |  |  | * datetime 年月日 时分 | 
|---|
|  |  |  | * datetime-all 年月日 时分秒 | 
|---|
|  |  |  | * time 时分秒 | 
|---|
|  |  |  | * hour-minute 时分 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | type: String, | 
|---|
|  |  |  | default: 'date' | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | indicatorStyle: { | 
|---|
|  |  |  | type: Object, | 
|---|
|  |  |  | default: null | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | data() { | 
|---|
|  |  |  | return { | 
|---|
|  |  |  | visible: false, | 
|---|
|  |  |  | dateTime: [], | 
|---|
|  |  |  | days: [], | 
|---|
|  |  |  | indicatorStyleString: '' | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | watch: { | 
|---|
|  |  |  | indicatorStyle(val){ | 
|---|
|  |  |  | this.getIndicatorStyle(); | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | type() { | 
|---|
|  |  |  | this.initDateTime() | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | datestring(){ | 
|---|
|  |  |  | this.initDateTime() | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | computed: { | 
|---|
|  |  |  | years() { | 
|---|
|  |  |  | return this.initTimeData(this.endYear, this.startYear); | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | isShowYear() { | 
|---|
|  |  |  | return this.type !== 'time' && this.type !== 'hour-minute'; | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | months() { | 
|---|
|  |  |  | return this.initTimeData(12, 1); | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | isShowMonth() { | 
|---|
|  |  |  | return this.type !== 'year' && this.type !== 'time' && this.type !== 'hour-minute'; | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | isShowDay() { | 
|---|
|  |  |  | return this.type === 'date' || this.type === 'datetime' || this.type === 'datetime-all'; | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | hours() { | 
|---|
|  |  |  | return this.initTimeData(23, 0); | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | isShowHour() { | 
|---|
|  |  |  | return this.type !== 'date' && this.type !== 'year-month' && this.type !== 'year'; | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | minutes() { | 
|---|
|  |  |  | return this.initTimeData(59, 0); | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | isShowMinute() { | 
|---|
|  |  |  | return this.type !== 'date' && this.type !== 'year-month' && this.type !== 'year'; | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | seconds() { | 
|---|
|  |  |  | return this.initTimeData(59, 0); | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | isShowSecond() { | 
|---|
|  |  |  | return this.type === 'datetime-all' || this.type === 'time'; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | methods: { | 
|---|
|  |  |  | getIndicatorStyle(){ | 
|---|
|  |  |  | if(this.indicatorStyle){ | 
|---|
|  |  |  | for(let key in this.indicatorStyle){ | 
|---|
|  |  |  | this.indicatorStyleString += `${key}:${this.indicatorStyle[key]};` | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | handleEvent() { | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | cancel() { | 
|---|
|  |  |  | this.hide(); | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | confirm() { | 
|---|
|  |  |  | this.formatDate(); | 
|---|
|  |  |  | this.hide(); | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | show() { | 
|---|
|  |  |  | this.visible = true; | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | hide() { | 
|---|
|  |  |  | this.visible = false; | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | initDateTime() { | 
|---|
|  |  |  | let value; | 
|---|
|  |  |  | if (this.datestring.length > 0) { | 
|---|
|  |  |  | if (this.type === 'year') { | 
|---|
|  |  |  | value = new Date(this.datestring, 0); | 
|---|
|  |  |  | } else if (this.type === 'time' || this.type === 'hour-minute') { | 
|---|
|  |  |  | let date = new Date(); | 
|---|
|  |  |  | let ary = this.datestring.split(':'); | 
|---|
|  |  |  | ary.forEach((item, index) => { | 
|---|
|  |  |  | if (index == 0) { | 
|---|
|  |  |  | date.setHours(item) | 
|---|
|  |  |  | } else if (index == 1) { | 
|---|
|  |  |  | date.setMinutes(item) | 
|---|
|  |  |  | } else if (index == 2) { | 
|---|
|  |  |  | date.setSeconds(item) | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | value = date; | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | value = new Date(this.datestring.replace(/-/g, '/')); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | value = new Date(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | let len, timeArray, index; | 
|---|
|  |  |  | let array = getTimeArray(value); | 
|---|
|  |  |  | let [year, month, day, hour, minute, second] = array; | 
|---|
|  |  |  | this.days = this.initTimeData(getOneMonthDays(year, month-1), 1); | 
|---|
|  |  |  | let names = ['year', 'month', 'day', 'hour', 'minute', 'second']; | 
|---|
|  |  |  | switch (this.type) { | 
|---|
|  |  |  | case "date": | 
|---|
|  |  |  | len = 3; | 
|---|
|  |  |  | break; | 
|---|
|  |  |  | case "year-month": | 
|---|
|  |  |  | len = 2; | 
|---|
|  |  |  | break; | 
|---|
|  |  |  | case "year": | 
|---|
|  |  |  | len = 1; | 
|---|
|  |  |  | break; | 
|---|
|  |  |  | case "datetime": | 
|---|
|  |  |  | len = 5; | 
|---|
|  |  |  | break; | 
|---|
|  |  |  | case "datetime-all": | 
|---|
|  |  |  | len = 6; | 
|---|
|  |  |  | break; | 
|---|
|  |  |  | case "time": | 
|---|
|  |  |  | len = 3; | 
|---|
|  |  |  | break; | 
|---|
|  |  |  | case "hour-minute": | 
|---|
|  |  |  | len = 2; | 
|---|
|  |  |  | break; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | timeArray = new Array(len).fill(0); | 
|---|
|  |  |  | if (this.type === 'time' || this.type === 'hour-minute') { | 
|---|
|  |  |  | names = names.slice(3); | 
|---|
|  |  |  | array = array.slice(3); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | timeArray = timeArray.map((item, index) => { | 
|---|
|  |  |  | const name = names[index]; | 
|---|
|  |  |  | return getIndexOfArray(array[index], this[name + 's']) | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | this.dateTime = timeArray; | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | initTimeData(end, start) { | 
|---|
|  |  |  | let timeArray = []; | 
|---|
|  |  |  | while (start <= end) { | 
|---|
|  |  |  | timeArray.push(start); | 
|---|
|  |  |  | start++; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return timeArray; | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | formatDate() { | 
|---|
|  |  |  | let names = ['year', 'month', 'day', 'hour', 'minute', 'second']; | 
|---|
|  |  |  | let dateString, formatDateArray = []; | 
|---|
|  |  |  | if (this.type === 'date' || this.type === 'year-month' || this.type === 'year') { | 
|---|
|  |  |  | formatDateArray = this.dateTime.map((item, index) => { | 
|---|
|  |  |  | return this[names[index] + 's'][item] < 10 ? addZero(this[names[index] + 's'][item]) : this[names[index] + 's'][item]; | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | dateString = formatDateArray.join('-'); | 
|---|
|  |  |  | } else if (this.type === 'time' || this.type === 'hour-minute') { | 
|---|
|  |  |  | names = names.splice(3); | 
|---|
|  |  |  | formatDateArray = this.dateTime.map((item, index) => { | 
|---|
|  |  |  | return this[names[index] + 's'][item] < 10 ? addZero(this[names[index] + 's'][item]) : this[names[index] + 's'][item]; | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | dateString = formatDateArray.join(':'); | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | let name1 = names.splice(0, 3); | 
|---|
|  |  |  | formatDateArray = this.dateTime.map((item, index) => { | 
|---|
|  |  |  | if (index > 2) { | 
|---|
|  |  |  | return this[names[index - 3] + 's'][item] < 10 ? addZero(this[names[index - 3] + 's'][item]) : this[names[index - 3] + 's'][item]; | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | return this[name1[index] + 's'][item] < 10 ? addZero(this[name1[index] + 's'][item]) : this[name1[index] + 's'][item]; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | dateString = formatDateArray.splice(0, 3).join('-') + ' ' + formatDateArray.join(':'); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | this.$emit('change', dateString) | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | dateTimePickerChange(e) { | 
|---|
|  |  |  | let columns = e.target.value; | 
|---|
|  |  |  | if (this.type === 'date' || this.type === 'datetime' || this.type === 'datetime-all') { | 
|---|
|  |  |  | this.dateTime.splice(0, 1, columns[0]); | 
|---|
|  |  |  | if (columns[0] != this.dateTime[0]) { | 
|---|
|  |  |  | this.days = this.initTimeData(getOneMonthDays(this.years[this.dateTime[0]], this.months[this.dateTime[1]]), 1); | 
|---|
|  |  |  | if (this.dateTime[1] == 1) { | 
|---|
|  |  |  | if (this.dateTime[2] === this.days.length - 1) { | 
|---|
|  |  |  | if (getOneMonthDays(this.years[columns[0]], this.dateTime[1]) < getOneMonthDays(this.years[this.dateTime[0]],this.dateTime[1])) { | 
|---|
|  |  |  | this.dateTime.splice(2, 1, this.days.length - 1) | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | this.dateTime.splice(1, 1, columns[1]); | 
|---|
|  |  |  | this.days = this.initTimeData(getOneMonthDays(this.years[this.dateTime[0]], this.dateTime[1]), 1); | 
|---|
|  |  |  | if (columns[1] != this.dateTime[1]) { | 
|---|
|  |  |  | if (this.dateTime[1] == 1) { | 
|---|
|  |  |  | if (this.dateTime[2] === this.days.length - 1) { | 
|---|
|  |  |  | if (getOneMonthDays(this.years[columns[0]], this.dateTime[1]) < getOneMonthDays(this.years[this.dateTime[0]], | 
|---|
|  |  |  | this.dateTime[1])) { | 
|---|
|  |  |  | this.dateTime.splice(2, 1, this.days.length - 1) | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | if (this.dateTime[2] > this.days.length - 1) { | 
|---|
|  |  |  | this.dateTime.splice(2, 1, this.days.length - 1) | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | this.dateTime.splice(2, 1, columns[2]) | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | this.dateTime.splice(2, 1, columns[2]) | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | if (columns.length > 2) { | 
|---|
|  |  |  | columns.splice(3).forEach((column, index) => { | 
|---|
|  |  |  | this.dateTime.splice(index + 3, 1, column); | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | columns.forEach((column, index) => { | 
|---|
|  |  |  | this.dateTime.splice(index, 1, column); | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | } | 
|---|
|  |  |  | if (!this.isShowToolBar) { | 
|---|
|  |  |  | this.formatDate(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | mounted() { | 
|---|
|  |  |  | this.getIndicatorStyle(); | 
|---|
|  |  |  | this.initDateTime(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | </script> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <style lang='scss' scoped> | 
|---|
|  |  |  | .date-time-picker { | 
|---|
|  |  |  | .date-time-mask { | 
|---|
|  |  |  | position: fixed; | 
|---|
|  |  |  | top: 0; | 
|---|
|  |  |  | bottom: 0; | 
|---|
|  |  |  | left: 0; | 
|---|
|  |  |  | right: 0; | 
|---|
|  |  |  | background-color: rgba($color: #000000, $alpha: .5); | 
|---|
|  |  |  | z-index: 998; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .date-time-container { | 
|---|
|  |  |  | position: fixed; | 
|---|
|  |  |  | height: 50%; | 
|---|
|  |  |  | bottom: 0; | 
|---|
|  |  |  | right: 0; | 
|---|
|  |  |  | left: 0; | 
|---|
|  |  |  | background-color: #f6f6f6; | 
|---|
|  |  |  | z-index: 1000; | 
|---|
|  |  |  | display: flex; | 
|---|
|  |  |  | flex-direction: column; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .time-picker-tool { | 
|---|
|  |  |  | height: 80rpx; | 
|---|
|  |  |  | display: flex; | 
|---|
|  |  |  | align-items: center; | 
|---|
|  |  |  | justify-content: space-between; | 
|---|
|  |  |  | font-size: 28rpx; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .cancel-btn { | 
|---|
|  |  |  | padding: 0 28rpx; | 
|---|
|  |  |  | box-sizing: border-box; | 
|---|
|  |  |  | color: #969799; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .tool-title { | 
|---|
|  |  |  | font-weight: 500; | 
|---|
|  |  |  | font-size: 16px; | 
|---|
|  |  |  | max-width: 50%; | 
|---|
|  |  |  | overflow: hidden; | 
|---|
|  |  |  | white-space: nowrap; | 
|---|
|  |  |  | text-overflow: ellipsis; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .confirm-btn { | 
|---|
|  |  |  | padding: 0 28rpx; | 
|---|
|  |  |  | box-sizing: border-box; | 
|---|
|  |  |  | color: #576b95; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .picker-view { | 
|---|
|  |  |  | width: 100%; | 
|---|
|  |  |  | flex: 1; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .item { | 
|---|
|  |  |  | font-size: 34rpx; | 
|---|
|  |  |  | display: flex; | 
|---|
|  |  |  | align-items: center; | 
|---|
|  |  |  | justify-content: center; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | </style> | 
|---|
| New file | 
|  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 获取某年某月有多少天 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | export const getOneMonthDays = (year,month)=>{ | 
|---|
|  |  |  | month = Number(month); | 
|---|
|  |  |  | const baseMonthsDays = [31,28,31,30,31,30,31,31,30,31,30,31]; | 
|---|
|  |  |  | if(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)){ | 
|---|
|  |  |  | if(month === 1){ | 
|---|
|  |  |  | baseMonthsDays[month] = 29; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return baseMonthsDays[month]; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 获取日期的年月日时分秒 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | export const getTimeArray = (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,hour,minute,second]; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 小于10的数字前面补0 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | export const addZero = (num)=>{ | 
|---|
|  |  |  | return num < 10 ? '0' + num : num; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 获取当前值在数组中的索引 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | export const getIndexOfArray = (value,array)=>{ | 
|---|
|  |  |  | let index = array.findIndex(item => item == value); | 
|---|
|  |  |  | return index > -1 ? index : 0; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "path": "./pages/workbench/orderDetail", | 
|---|
|  |  |  | "path": "pages/workbench/orderDetail", | 
|---|
|  |  |  | "style": { | 
|---|
|  |  |  | "navigationBarTitleText": "订单详情", | 
|---|
|  |  |  | "navigationBarBackgroundColor":"#FFFFFF", | 
|---|
|  |  |  | 
|---|
|  |  |  | "scrollIndicator": "none" | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "path": "pages/workbench/confirmService", | 
|---|
|  |  |  | "style": { | 
|---|
|  |  |  | "navigationBarTitleText": "确认订单", | 
|---|
|  |  |  | "navigationBarBackgroundColor":"#FFFFFF", | 
|---|
|  |  |  | "navigationBarTextStyle":"black", | 
|---|
|  |  |  | "app-plus":{ | 
|---|
|  |  |  | "scrollIndicator": "none" | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | ], | 
|---|
|  |  |  | "globalStyle": { | 
|---|
| New file | 
|  |  |  | 
|---|
|  |  |  | <template> | 
|---|
|  |  |  | <!-- 确认服务单 --> | 
|---|
|  |  |  | <view> | 
|---|
|  |  |  | <view class="header flex align-center mt-10"> | 
|---|
|  |  |  | <image class="header-img" src="../../static/images/head-img.jpg"></image> | 
|---|
|  |  |  | <view class="ml-10"> | 
|---|
|  |  |  | <view class="font-16"> | 
|---|
|  |  |  | <text>李某</text> | 
|---|
|  |  |  | <text class="ml-20">15588881111</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <text class="font-14 gray mt-5">普通会员</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="font-16 content"> | 
|---|
|  |  |  | <view class="content-row flex align-center justify-between"> | 
|---|
|  |  |  | <text>预约时间</text> | 
|---|
|  |  |  | <text class="gray" @click="selectDatePicker()">{{time}}</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <date-time-picker ref='date-time' type='datetime' @change='dateTimeChange'></date-time-picker> | 
|---|
|  |  |  | <view class="content-row flex align-center justify-between"> | 
|---|
|  |  |  | <text>预约技师</text> | 
|---|
|  |  |  | <view class="blue"> | 
|---|
|  |  |  | <picker mode="selector" :range="technicianList" @change="technicianChange"> | 
|---|
|  |  |  | <view> | 
|---|
|  |  |  | <text class="mr-5">{{technician}}</text> | 
|---|
|  |  |  | <text class="iconfont iconjiantouarrow486"></text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </picker> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="content"> | 
|---|
|  |  |  | <view class="content-row flex align-center" v-for="item in 3"> | 
|---|
|  |  |  | <image class="product-img" src="../../static/images/product.jpg" mode="aspectFill"></image> | 
|---|
|  |  |  | <view class="flex justify-between align-center flex-1 ml-10"> | 
|---|
|  |  |  | <view class="flex flex-v"> | 
|---|
|  |  |  | <text class="font-12">面部护理</text> | 
|---|
|  |  |  | <text class="font-10 gray mt-5">时长: 30分钟</text> | 
|---|
|  |  |  | <text class="font-10 gray mt-5">有效期至: 2021-12-20</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view> | 
|---|
|  |  |  | <text class="font-16">×1</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="content-row right"> | 
|---|
|  |  |  | <text class="font-16 blue">共3项服务</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="content input-row flex"> | 
|---|
|  |  |  | <text class="mr-10">备注</text> | 
|---|
|  |  |  | <input type="text" value="" placeholder="客户需求" placeholder-class='placeholder'/> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <button class="sticky-footer blue-btn">确认提交</button> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </template> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <script> | 
|---|
|  |  |  | import DateTimePicker from '../../components/bory-dateTimePicker/bory-dateTimePicker.vue' | 
|---|
|  |  |  | export default{ | 
|---|
|  |  |  | components:{ | 
|---|
|  |  |  | DateTimePicker | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | data(){ | 
|---|
|  |  |  | return{ | 
|---|
|  |  |  | time:'2020-12-12 19:06', | 
|---|
|  |  |  | technicianList:['赵姐','钱姐','孙姐'], | 
|---|
|  |  |  | technician:'赵姐' | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | methods:{ | 
|---|
|  |  |  | selectDatePicker () { | 
|---|
|  |  |  | this.$refs['date-time'].show(); | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | dateTimeChange(value) { | 
|---|
|  |  |  | this.time=value | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | technicianChange(e){ | 
|---|
|  |  |  | this.technician = this.technicianList[e.detail.value]; | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | </script> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <style> | 
|---|
|  |  |  | page{ | 
|---|
|  |  |  | background: #F6F6F8; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .header{ | 
|---|
|  |  |  | background: #FFFFFF; | 
|---|
|  |  |  | border: 1px solid #EDEAF4; | 
|---|
|  |  |  | border-radius: 4px; | 
|---|
|  |  |  | box-shadow:0 6px 6px rgba(237,234,244,0.5); | 
|---|
|  |  |  | padding: 10px; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .header-img{ | 
|---|
|  |  |  | width: 48px; | 
|---|
|  |  |  | height: 48px; | 
|---|
|  |  |  | border-radius: 50%; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .content{ | 
|---|
|  |  |  | margin: 10px; | 
|---|
|  |  |  | padding: 0 10px; | 
|---|
|  |  |  | background: #FFFFFF; | 
|---|
|  |  |  | border: 1px solid #EDEAF4; | 
|---|
|  |  |  | border-radius: 4px; | 
|---|
|  |  |  | box-shadow:0 6px 6px rgba(237,234,244,0.5); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .content-row{ | 
|---|
|  |  |  | border-bottom: 1px solid #EDEAF4; | 
|---|
|  |  |  | padding: 10px 5px; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .content-row:nth-last-child(1){ | 
|---|
|  |  |  | border: 0; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .product-img{ | 
|---|
|  |  |  | width: 53px; | 
|---|
|  |  |  | height: 53px; | 
|---|
|  |  |  | border-radius: 4px; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .input-row{ | 
|---|
|  |  |  | padding: 10px; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | </style> | 
|---|
|  |  |  | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="order"> | 
|---|
|  |  |  | <view class="flex justify-between order-number"> | 
|---|
|  |  |  | <text class="font-14">订单号: N202012123556</text> | 
|---|
|  |  |  | <text class="font-14 blue">已完成</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="flex justify-between order-content"> | 
|---|
|  |  |  | <view class="flex flex-v"> | 
|---|
|  |  |  | <text class="font-12">李某某</text> | 
|---|
|  |  |  | <text class="font-12 gray mt-10">2020-12-15 18:11:01</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="flex flex-v"> | 
|---|
|  |  |  | <text class="font-12">应付金额</text> | 
|---|
|  |  |  | <text class="font-12 mt-10">实付金额</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="flex flex-v"> | 
|---|
|  |  |  | <text class="font-12">¥ 8000.00</text> | 
|---|
|  |  |  | <text class="font-12 mt-10">¥ 8000.00</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="flex justify-end"> | 
|---|
|  |  |  | <navigator url="./orderDetail"> | 
|---|
|  |  |  | <button class="blue-btn small-btn">查看详情</button> | 
|---|
|  |  |  | </navigator> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </template> | 
|---|
|  |  |  | 
|---|
|  |  |  | <navigator url="../confirmOrder"> | 
|---|
|  |  |  | <button class="blue-btn btn mr-0">提交订单</button> | 
|---|
|  |  |  | </navigator> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <uni-popup ref="popup" type="bottom"> | 
|---|
|  |  |  | <shopping-cart></shopping-cart> | 
|---|
|  |  |  | 
|---|
|  |  |  | <template> | 
|---|
|  |  |  | <view> | 
|---|
|  |  |  | <text>选择套餐</text> | 
|---|
|  |  |  | <view class="header"> | 
|---|
|  |  |  | <search-bar placeholder="商品名称、编号、拼音" class="ml-10 mr-10"></search-bar> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="content"> | 
|---|
|  |  |  | <view class="content-box"> | 
|---|
|  |  |  | <view class="content-box-title"> | 
|---|
|  |  |  | <text>项目</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="flex align-center content-box-row" v-for="item in 2"> | 
|---|
|  |  |  | <image class="product-img" mode="aspectFill" src="../../static/images/product.jpg"></image> | 
|---|
|  |  |  | <view class="flex flex-v ml-10 flex-1"> | 
|---|
|  |  |  | <text class="font-12">面部护理</text> | 
|---|
|  |  |  | <text class="font-10 gray mt-5">时长: 30分钟</text> | 
|---|
|  |  |  | <text class="font-10 gray mt-5">有效期至: 2021-01-02</text> | 
|---|
|  |  |  | <view class="mt-5 flex align-center justify-between"> | 
|---|
|  |  |  | <text class="font-12 blue">剩余次数: 2次</text> | 
|---|
|  |  |  | <view> | 
|---|
|  |  |  | <text class="iconfont iconjian blue-outline-btn-circle mr-20"></text> | 
|---|
|  |  |  | <text class="iconfont iconjia blue-btn-circle"></text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <view class="content-box mt-10"> | 
|---|
|  |  |  | <view class="content-box-title"> | 
|---|
|  |  |  | <text>套餐</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="flex flex-v content-box-row" v-for="item in 2"> | 
|---|
|  |  |  | <view class="font-12 flex align-center justify-between"> | 
|---|
|  |  |  | <text>时尚补水套餐</text> | 
|---|
|  |  |  | <text class="red">即将过期</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="flex align-center mt-5"> | 
|---|
|  |  |  | <image class="product-img" mode="aspectFill" src="../../static/images/product.jpg"></image> | 
|---|
|  |  |  | <view class="flex flex-v ml-10 flex-1"> | 
|---|
|  |  |  | <text class="font-12">面部护理</text> | 
|---|
|  |  |  | <text class="font-10 gray mt-5">时长: 30分钟</text> | 
|---|
|  |  |  | <text class="font-10 gray mt-5">有效期至: 2021-01-02</text> | 
|---|
|  |  |  | <view class="mt-5 flex align-center justify-between"> | 
|---|
|  |  |  | <text class="font-12 blue">剩余次数: 2次</text> | 
|---|
|  |  |  | <view> | 
|---|
|  |  |  | <text class="iconfont iconjian blue-outline-btn-circle mr-20"></text> | 
|---|
|  |  |  | <text class="iconfont iconjia blue-btn-circle"></text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="flex align-center mt-10"> | 
|---|
|  |  |  | <image class="product-img" mode="aspectFill" src="../../static/images/product.jpg"></image> | 
|---|
|  |  |  | <view class="flex flex-v ml-10 flex-1"> | 
|---|
|  |  |  | <text class="font-12">面部护理</text> | 
|---|
|  |  |  | <text class="font-10 gray mt-5">时长: 30分钟</text> | 
|---|
|  |  |  | <text class="font-10 gray mt-5">有效期至: 2021-01-02</text> | 
|---|
|  |  |  | <view class="mt-5 flex align-center justify-between"> | 
|---|
|  |  |  | <text class="font-12 blue">剩余次数: 2次</text> | 
|---|
|  |  |  | <view> | 
|---|
|  |  |  | <text class="iconfont iconjian blue-outline-btn-circle mr-20"></text> | 
|---|
|  |  |  | <text class="iconfont iconjia blue-btn-circle"></text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="font-12 mt-5"> | 
|---|
|  |  |  | <text>有效期至: 2021-01-03</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <view class="shopping flex align-center justify-between"> | 
|---|
|  |  |  | <view class="flex align-center"> | 
|---|
|  |  |  | <view class="shopping-icon iconfont iconicongouwuche gray" @click="openShoppingCart"> | 
|---|
|  |  |  | <view class="shopping-icon-num flex align-center justify-center"> | 
|---|
|  |  |  | <text class="font-10">19</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <text class="font-14 blue ml-10">¥110.00</text> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <navigator url="./confirmService" hover-class="none"> | 
|---|
|  |  |  | <button class="blue-btn btn mr-0">提交订单</button> | 
|---|
|  |  |  | </navigator> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | <uni-popup ref="popup" type="bottom"> | 
|---|
|  |  |  | <shopping-cart></shopping-cart> | 
|---|
|  |  |  | </uni-popup> | 
|---|
|  |  |  | </view> | 
|---|
|  |  |  | </template> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <script> | 
|---|
|  |  |  | import searchBar from '../../components/searchBar/index.vue'; | 
|---|
|  |  |  | import uniPopup from '@/components/uni-popup/uni-popup.vue' | 
|---|
|  |  |  | import shoppingCart from './selectProduct/shoppingCart.vue' | 
|---|
|  |  |  | export default { | 
|---|
|  |  |  | components:{ | 
|---|
|  |  |  | searchBar, | 
|---|
|  |  |  | uniPopup, | 
|---|
|  |  |  | shoppingCart | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | data(){ | 
|---|
|  |  |  | return{ | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | methods:{ | 
|---|
|  |  |  | openShoppingCart(){ | 
|---|
|  |  |  | this.$refs.popup.open() | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | </script> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <style> | 
|---|
|  |  |  | page{ | 
|---|
|  |  |  | background: #F6F6F8; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .header{ | 
|---|
|  |  |  | background: #FFFFFF; | 
|---|
|  |  |  | border-bottom-left-radius: 4px; | 
|---|
|  |  |  | border-bottom-right-radius: 4px; | 
|---|
|  |  |  | box-shadow:0 6px 6px rgba(237,234,244,0.5); | 
|---|
|  |  |  | padding-bottom: 5px; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .content{ | 
|---|
|  |  |  | padding: 10px; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .content-box{ | 
|---|
|  |  |  | background: #FFFFFF; | 
|---|
|  |  |  | padding: 10px; | 
|---|
|  |  |  | border: 1px solid #EDEAF4; | 
|---|
|  |  |  | border-radius: 4px; | 
|---|
|  |  |  | box-shadow:0 6px 6px rgba(237,234,244,0.5); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .content-box-title{ | 
|---|
|  |  |  | padding: 10px 5px; | 
|---|
|  |  |  | border-bottom: 1px solid #EDEAF4; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .content-box-row{ | 
|---|
|  |  |  | padding: 10px 0; | 
|---|
|  |  |  | border-bottom: 1px solid #EDEAF4; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .content-box-row:nth-last-child(1){ | 
|---|
|  |  |  | border: 0; | 
|---|
|  |  |  | padding-bottom: 0; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .product-img{ | 
|---|
|  |  |  | width: 80px; | 
|---|
|  |  |  | height: 80px; | 
|---|
|  |  |  | border-radius: 4px; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .shopping{ | 
|---|
|  |  |  | background: #FFFFFF; | 
|---|
|  |  |  | padding: 10px 10px; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .shopping-icon{ | 
|---|
|  |  |  | font-size: 28px; | 
|---|
|  |  |  | position: relative; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .shopping-icon-num{ | 
|---|
|  |  |  | width: 20px; | 
|---|
|  |  |  | height: 20px; | 
|---|
|  |  |  | background: #518EFF; | 
|---|
|  |  |  | border-radius: 50%; | 
|---|
|  |  |  | color: #FFFFFF; | 
|---|
|  |  |  | position: absolute; | 
|---|
|  |  |  | right: -10px; | 
|---|
|  |  |  | top: -10px; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | </style> | 
|---|