¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <u-picker |
| | | ref="picker" |
| | | :show="show" |
| | | :closeOnClickOverlay="closeOnClickOverlay" |
| | | :columns="columns" |
| | | :title="title" |
| | | :itemHeight="itemHeight" |
| | | :showToolbar="showToolbar" |
| | | :visibleItemCount="visibleItemCount" |
| | | :defaultIndex="innerDefaultIndex" |
| | | :cancelText="cancelText" |
| | | :confirmText="confirmText" |
| | | :cancelColor="cancelColor" |
| | | :confirmColor="confirmColor" |
| | | @close="close" |
| | | @cancel="cancel" |
| | | @confirm="confirm" |
| | | @change="change" |
| | | > |
| | | </u-picker> |
| | | </template> |
| | | |
| | | <script> |
| | | function times(n, iteratee) { |
| | | let index = -1 |
| | | const result = Array(n < 0 ? 0 : n) |
| | | while (++index < n) { |
| | | result[index] = iteratee(index) |
| | | } |
| | | return result |
| | | } |
| | | import props from './props.js'; |
| | | import dayjs from '../../libs/util/dayjs.js'; |
| | | /** |
| | | * DatetimePicker æ¶é´æ¥æéæ©å¨ |
| | | * @description æ¤éæ©å¨ç¨äºæ¶é´æ¥æ |
| | | * @tutorial https://www.uviewui.com/components/datetimePicker.html |
| | | * @property {Boolean} show ç¨äºæ§å¶éæ©å¨çå¼¹åºä¸æ¶èµ· ( é»è®¤ false ) |
| | | * @property {Boolean} showToolbar æ¯å¦æ¾ç¤ºé¡¶é¨çæä½æ ( é»è®¤ true ) |
| | | * @property {String | Number} value ç»å®å¼ |
| | | * @property {String} title 顶鍿 é¢ |
| | | * @property {String} mode å±ç¤ºæ ¼å¼ mode=dateä¸ºæ¥æéæ©ï¼mode=time为æ¶é´éæ©ï¼mode=year-month为年æéæ©ï¼mode=datetimeä¸ºæ¥ææ¶é´éæ© ( é»è®¤ âdatetime ) |
| | | * @property {Number} maxDate å¯éçæå¤§æ¶é´ é»è®¤å¼ä¸ºå10å¹´ |
| | | * @property {Number} minDate å¯éçæå°æ¶é´ é»è®¤å¼ä¸ºå10å¹´ |
| | | * @property {Number} minHour å¯éçæå°å°æ¶ï¼ä»
mode=timeææ ( é»è®¤ 0 ) |
| | | * @property {Number} maxHour å¯éçæå¤§å°æ¶ï¼ä»
mode=timeææ ( é»è®¤ 23 ) |
| | | * @property {Number} minMinute å¯éçæå°åéï¼ä»
mode=timeææ ( é»è®¤ 0 ) |
| | | * @property {Number} maxMinute å¯éçæå¤§åéï¼ä»
mode=timeææ ( é»è®¤ 59 ) |
| | | * @property {Function} filter éé¡¹è¿æ»¤å½æ° |
| | | * @property {Function} formatter éé¡¹æ ¼å¼å彿° |
| | | * @property {Boolean} loading æ¯å¦æ¾ç¤ºå è½½ä¸ç¶æ ( é»è®¤ false ) |
| | | * @property {String | Number} itemHeight ååä¸ï¼å个é项çé«åº¦ ( é»è®¤ 44 ) |
| | | * @property {String} cancelText åæ¶æé®çæå ( é»è®¤ 'åæ¶' ) |
| | | * @property {String} confirmText 确认æé®çæå ( é»è®¤ '确认' ) |
| | | * @property {String} cancelColor åæ¶æé®çé¢è² ( é»è®¤ '#909193' ) |
| | | * @property {String} confirmColor 确认æé®çé¢è² ( é»è®¤ '#3c9cff' ) |
| | | * @property {String | Number} visibleItemCount æ¯åä¸å¯è§éé¡¹çæ°é ( é»è®¤ 5 ) |
| | | * @property {Boolean} closeOnClickOverlay æ¯å¦å
许ç¹å»é®ç½©å
³ééæ©å¨ ( é»è®¤ false ) |
| | | * @property {Array} defaultIndex ååçé»è®¤ç´¢å¼ |
| | | * @event {Function} close å
³é鿩卿¶è§¦å |
| | | * @event {Function} confirm ç¹å»ç¡®å®æé®ï¼è¿åå½åéæ©çå¼ |
| | | * @event {Function} change å½éæ©å¼ååæ¶è§¦å |
| | | * @event {Function} cancel ç¹å»åæ¶æé® |
| | | * @example <u-datetime-picker :show="show" :value="value1" mode="datetime" ></u-datetime-picker> |
| | | */ |
| | | export default { |
| | | name: 'datetime-picker', |
| | | mixins: [uni.$u.mpMixin, uni.$u.mixin, props], |
| | | data() { |
| | | return { |
| | | columns: [], |
| | | innerDefaultIndex: [], |
| | | innerFormatter: (type, value) => value |
| | | } |
| | | }, |
| | | watch: { |
| | | show(newValue, oldValue) { |
| | | if (newValue) { |
| | | this.updateColumnValue(this.innerValue) |
| | | } |
| | | }, |
| | | propsChange() { |
| | | this.init() |
| | | } |
| | | }, |
| | | computed: { |
| | | // 妿以ä¸è¿äºåéåçäºååï¼æå³çéè¦éæ°åå§åååçå¼ |
| | | propsChange() { |
| | | return [this.mode, this.maxDate, this.minDate, this.minHour, this.maxHour, this.minMinute, this.maxMinute, this.filter, ] |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.init() |
| | | }, |
| | | methods: { |
| | | init() { |
| | | this.innerValue = this.correctValue(this.value) |
| | | this.updateColumnValue(this.innerValue) |
| | | }, |
| | | // å¨å¾®ä¿¡å°ç¨åºä¸ï¼ä¸æ¯æå°å½æ°å½åpropsåæ°ï¼æ
åªè½éè¿refå½¢å¼è°ç¨ |
| | | setFormatter(e) { |
| | | this.innerFormatter = e |
| | | }, |
| | | // å
³ééæ©å¨ |
| | | close() { |
| | | if (this.closeOnClickOverlay) { |
| | | this.$emit('close') |
| | | } |
| | | }, |
| | | // ç¹å»å·¥å
·æ çåæ¶æé® |
| | | cancel() { |
| | | this.$emit('cancel') |
| | | }, |
| | | // ç¹å»å·¥å
·æ çç¡®å®æé® |
| | | confirm() { |
| | | this.$emit('confirm', { |
| | | value: this.innerValue, |
| | | mode: this.mode |
| | | }) |
| | | this.$emit('input', this.innerValue) |
| | | }, |
| | | //ç¨æ£åæªåè¾åºå¼,å½åºç°å¤ç»æ°åæ¶,æåºé误 |
| | | intercept(e,type){ |
| | | let judge = e.match(/\d+/g) |
| | | //夿æ¯å¦æºææ°å |
| | | if(judge.length>1){ |
| | | uni.$u.error("请å¿å¨è¿æ»¤ææ ¼å¼å彿°æ¶æ·»å æ°å") |
| | | return 0 |
| | | }else if(type&&judge[0].length==4){//夿æ¯å¦æ¯å¹´ä»½ |
| | | return judge[0] |
| | | }else if(judge[0].length>2){ |
| | | uni.$u.error("请å¿å¨è¿æ»¤ææ ¼å¼å彿°æ¶æ·»å æ°å") |
| | | return 0 |
| | | }else{ |
| | | return judge[0] |
| | | } |
| | | }, |
| | | // ååçååæ¶è§¦å |
| | | change(e) { |
| | | const { indexs, values } = e |
| | | let selectValue = '' |
| | | if(this.mode === 'time') { |
| | | // æ ¹æ®valueååç´¢å¼ï¼ä»ååæ°ç»ä¸ï¼ååºå½åæ¶é´çéä¸å¼ |
| | | selectValue = `${this.intercept(values[0][indexs[0]])}:${this.intercept(values[1][indexs[1]])}` |
| | | } else { |
| | | // å°éæ©çå¼è½¬ä¸ºæ°å¼ï¼æ¯å¦'03'转为æ°å¼ç3ï¼'2019'转为æ°å¼ç2019 |
| | | const year = parseInt(this.intercept(values[0][indexs[0]],'year')) |
| | | const month = parseInt(this.intercept(values[1][indexs[1]])) |
| | | let date = parseInt(values[2] ? this.intercept(values[2][indexs[2]]) : 1) |
| | | let hour = 0, minute = 0 |
| | | // æ¤æä»½çæå¤§å¤©æ° |
| | | const maxDate = dayjs(`${year}-${month}`).daysInMonth() |
| | | // year-month模å¼ä¸ï¼dateä¸ä¼åºç°å¨åä¸ï¼è®¾ç½®ä¸º1ï¼ä¸ºäºç¬¦ååè¾¹éè¦å1çéæ± |
| | | if (this.mode === 'year-month') { |
| | | date = 1 |
| | | } |
| | | // ä¸å
许è¶
è¿maxDateå¼ |
| | | date = Math.min(maxDate, date) |
| | | if (this.mode === 'datetime') { |
| | | hour = parseInt(this.intercept(values[3][indexs[3]])) |
| | | minute = parseInt(this.intercept(values[4][indexs[4]])) |
| | | } |
| | | // 转为æ¶é´æ¨¡å¼ |
| | | selectValue = Number(new Date(year, month - 1, date, hour, minute)) |
| | | } |
| | | // ååºåç¡®çåæ³å¼ï¼é²æ¢è¶
è¶è¾¹ççæ
åµ |
| | | selectValue = this.correctValue(selectValue) |
| | | this.innerValue = selectValue |
| | | this.updateColumnValue(selectValue) |
| | | // ååºchangeæ¶é´ï¼value为å½åéä¸çæ¶é´æ³ |
| | | this.$emit('change', { |
| | | value: selectValue, |
| | | // #ifndef MP-WEIXIN |
| | | // 微信å°ç¨åºä¸è½ä¼ éthiså®ä¾ï¼ä¼å 为循ç¯å¼ç¨èæ¥é |
| | | picker: this.$refs.picker, |
| | | // #endif |
| | | mode: this.mode |
| | | }) |
| | | }, |
| | | // æ´æ°ååçå¼ï¼è¿è¡è¡¥0ãæ ¼å¼åçæä½ |
| | | updateColumnValue(value) { |
| | | this.innerValue = value |
| | | this.updateColumns() |
| | | this.updateIndexs(value) |
| | | }, |
| | | // æ´æ°ç´¢å¼ |
| | | updateIndexs(value) { |
| | | let values = [] |
| | | const formatter = this.formatter || this.innerFormatter |
| | | const padZero = uni.$u.padZero |
| | | if (this.mode === 'time') { |
| | | // å°time模å¼çæ¶é´ç¨:åéææ°ç» |
| | | const timeArr = value.split(':') |
| | | // 使ç¨formatteræ ¼å¼åæ¹æ³è¿è¡ç®¡éå¤ç |
| | | values = [formatter('hour', timeArr[0]), formatter('minute', timeArr[1])] |
| | | } else { |
| | | const date = new Date(value) |
| | | values = [ |
| | | formatter('year', `${dayjs(value).year()}`), |
| | | // æä»½è¡¥0 |
| | | formatter('month', padZero(dayjs(value).month() + 1)) |
| | | ] |
| | | if (this.mode === 'date') { |
| | | // date模å¼ï¼éè¦æ·»å 天å |
| | | values.push(formatter('day', padZero(dayjs(value).date()))) |
| | | } |
| | | if (this.mode === 'datetime') { |
| | | // æ°ç»çpushæ¹æ³ï¼å¯ä»¥åå
¥å¤ä¸ªåæ° |
| | | values.push(formatter('day', padZero(dayjs(value).date())), formatter('hour', padZero(dayjs(value).hour())), formatter('minute', padZero(dayjs(value).minute()))) |
| | | } |
| | | } |
| | | |
| | | // æ ¹æ®å½åååçææå¼ï¼ä»ååé»è®¤å¼ä¸æ¾å°é»è®¤å¼å¨ååä¸çç´¢å¼ |
| | | const indexs = this.columns.map((column, index) => { |
| | | // éè¿å大å¼ï¼å¯ä»¥ä¿è¯ä¸ä¼åºç°æ¾ä¸å°ç´¢å¼ç-1æ
åµ |
| | | return Math.max(0, column.findIndex(item => item === values[index])) |
| | | }) |
| | | this.innerDefaultIndex = indexs |
| | | }, |
| | | // æ´æ°ååçå¼ |
| | | updateColumns() { |
| | | const formatter = this.formatter || this.innerFormatter |
| | | // è·åååçå¼ï¼å¹¶ä¸mapåï¼å¯¹ååçå
·ä½å¼è¿è¡è¡¥0æä½ |
| | | const results = this.getOriginColumns().map((column) => column.values.map((value) => formatter(column.type, value))) |
| | | this.columns = results |
| | | }, |
| | | getOriginColumns() { |
| | | // çæååçå¼ |
| | | const results = this.getRanges().map(({ type, range }) => { |
| | | let values = times(range[1] - range[0] + 1, (index) => { |
| | | let value = range[0] + index |
| | | value = type === 'year' ? `${value}` : uni.$u.padZero(value) |
| | | return value |
| | | }) |
| | | // è¿è¡è¿æ»¤ |
| | | if (this.filter) { |
| | | values = this.filter(type, values) |
| | | } |
| | | return { type, values } |
| | | }) |
| | | return results |
| | | }, |
| | | // éè¿æå¤§å¼åæå°å¼çææ°ç» |
| | | generateArray(start, end) { |
| | | return Array.from(new Array(end + 1).keys()).slice(start) |
| | | }, |
| | | // å¾åºåæ³çæ¶é´ |
| | | correctValue(value) { |
| | | const isDateMode = this.mode !== 'time' |
| | | if (isDateMode && !uni.$u.test.date(value)) { |
| | | // å¦ææ¯æ¥æç±»åï¼ä½æ¯å没æè®¾ç½®åæ³çå½åæ¶é´çè¯ï¼ä½¿ç¨æå°æ¶é´ä¸ºå½åæ¶é´ |
| | | value = this.minDate |
| | | } else if (!isDateMode && !value) { |
| | | // å¦ææ¯æ¶é´ç±»åï¼èåæ²¡æé»è®¤å¼çè¯ï¼å°±ç¨æå°æ¶é´ |
| | | value = `${uni.$u.padZero(this.minHour)}:${uni.$u.padZero(this.minMinute)}` |
| | | } |
| | | // æ¶é´ç±»å |
| | | if (!isDateMode) { |
| | | if (String(value).indexOf(':') === -1) return uni.$u.error('æ¶é´é误ï¼è¯·ä¼ éå¦12:24çæ ¼å¼') |
| | | let [hour, minute] = value.split(':') |
| | | // 对æ¶é´è¡¥é¶ï¼åæ¶æ§å¶å¨æå°å¼åæå¤§å¼ä¹é´ |
| | | hour = uni.$u.padZero(uni.$u.range(this.minHour, this.maxHour, Number(hour))) |
| | | minute = uni.$u.padZero(uni.$u.range(this.minMinute, this.maxMinute, Number(minute))) |
| | | return `${ hour }:${ minute }` |
| | | } else { |
| | | // å¦ææ¯æ¥ææ ¼å¼ï¼æ§å¶å¨æå°æ¥æåæå¤§æ¥æä¹é´ |
| | | value = dayjs(value).isBefore(dayjs(this.minDate)) ? this.minDate : value |
| | | value = dayjs(value).isAfter(dayjs(this.maxDate)) ? this.maxDate : value |
| | | return value |
| | | } |
| | | }, |
| | | // è·åæ¯åçæå¤§åæå°å¼ |
| | | getRanges() { |
| | | if (this.mode === 'time') { |
| | | return [ |
| | | { |
| | | type: 'hour', |
| | | range: [this.minHour, this.maxHour], |
| | | }, |
| | | { |
| | | type: 'minute', |
| | | range: [this.minMinute, this.maxMinute], |
| | | }, |
| | | ]; |
| | | } |
| | | const { maxYear, maxDate, maxMonth, maxHour, maxMinute, } = this.getBoundary('max', this.innerValue); |
| | | const { minYear, minDate, minMonth, minHour, minMinute, } = this.getBoundary('min', this.innerValue); |
| | | const result = [ |
| | | { |
| | | type: 'year', |
| | | range: [minYear, maxYear], |
| | | }, |
| | | { |
| | | type: 'month', |
| | | range: [minMonth, maxMonth], |
| | | }, |
| | | { |
| | | type: 'day', |
| | | range: [minDate, maxDate], |
| | | }, |
| | | { |
| | | type: 'hour', |
| | | range: [minHour, maxHour], |
| | | }, |
| | | { |
| | | type: 'minute', |
| | | range: [minMinute, maxMinute], |
| | | }, |
| | | ]; |
| | | if (this.mode === 'date') |
| | | result.splice(3, 2); |
| | | if (this.mode === 'year-month') |
| | | result.splice(2, 3); |
| | | return result; |
| | | }, |
| | | // æ ¹æ®minDateãmaxDateãminHourãmaxHourçè¾¹çå¼ï¼å¤æååçå¼å§åç»æè¾¹çå¼ |
| | | getBoundary(type, innerValue) { |
| | | const value = new Date(innerValue) |
| | | const boundary = new Date(this[`${type}Date`]) |
| | | const year = dayjs(boundary).year() |
| | | let month = 1 |
| | | let date = 1 |
| | | let hour = 0 |
| | | let minute = 0 |
| | | if (type === 'max') { |
| | | month = 12 |
| | | // æä»½çå¤©æ° |
| | | date = dayjs(value).daysInMonth() |
| | | hour = 23 |
| | | minute = 59 |
| | | } |
| | | // è·åè¾¹çå¼ï¼é»è¾æ¯ï¼å½å¹´è¾¾å°äºè¾¹çå¼(æå¤§ææå°å¹´)ï¼å°±æ£æ¥æå
许çæå¤§åæå°å¼ï¼ä»¥æ¤ç±»æ¨ |
| | | if (dayjs(value).year() === year) { |
| | | month = dayjs(boundary).month() + 1 |
| | | if (dayjs(value).month() + 1 === month) { |
| | | date = dayjs(boundary).date() |
| | | if (dayjs(value).date() === date) { |
| | | hour = dayjs(boundary).hour() |
| | | if (dayjs(value).hour() === hour) { |
| | | minute = dayjs(boundary).minute() |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return { |
| | | [`${type}Year`]: year, |
| | | [`${type}Month`]: month, |
| | | [`${type}Date`]: date, |
| | | [`${type}Hour`]: hour, |
| | | [`${type}Minute`]: minute |
| | | } |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | @import '../../libs/css/components.scss'; |
| | | </style> |