123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655 |
- <template>
- <view class="tui-datetime-picker">
- <view class="tui-mask" :class="{ 'tui-mask-show': isShow }" @touchmove.stop.prevent="stop" catchtouchmove="stop"
- @tap="maskClick"></view>
- <view class="tui-header" :class="{ 'tui-show': isShow }">
- <view class="tui-picker-header" :class="{ 'tui-date-radius': radius }"
- :style="{ backgroundColor: headerBackground }" @touchmove.stop.prevent="stop" catchtouchmove="stop">
- <view class="tui-btn-picker" :style="{ color: cancelColor }" hover-class="tui-opacity"
- :hover-stay-time="150" @tap="hide">取消</view>
- <view class="tui-pickerdate__title" :style="{fontSize:titleSize+'rpx',color:titleColor}">{{title}}
- </view>
- <view class="tui-btn-picker" :style="{ color: color }" hover-class="tui-opacity" :hover-stay-time="150"
- @tap="btnFix">确定</view>
- </view>
- <view class="tui-date-header" :style="{ backgroundColor: unitBackground }" v-if="unitTop">
- <view class="tui-date-unit" v-if="type < 4 || type == 7 || type==8">年</view>
- <view class="tui-date-unit" v-if="type < 4 || type == 7 || type==8">月</view>
- <view class="tui-date-unit" v-if="type == 1 || type == 2 || type == 7 || type==8">日</view>
- <view class="tui-date-unit" v-if="type == 1 || type == 4 || type == 5 || type == 7 || type==8">时</view>
- <view class="tui-date-unit" v-if="(type == 1 || type > 3) && type!=8">分</view>
- <view class="tui-date-unit" v-if="type > 4 && type !=8">秒</view>
- </view>
- <view @touchstart.stop="pickerstart" class="tui-date__picker-body"
- :style="{ backgroundColor: bodyBackground,height:height+'rpx' }">
- <picker-view :value="value" @change="change" class="tui-picker-view">
- <picker-view-column v-if="!reset && (type < 4 || type == 7 || type==8)">
- <view class="tui-date__column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }"
- v-for="(item, index) in years" :key="index">
- {{ item }}
- <text class="tui-date__unit-text" v-if="!unitTop">年</text>
- </view>
- </picker-view-column>
- <picker-view-column v-if="!reset && (type < 4 || type == 7 || type==8)">
- <view class="tui-date__column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }"
- v-for="(item, index) in months" :key="index">
- {{ formatNum(item) }}
- <text class="tui-date__unit-text" v-if="!unitTop">月</text>
- </view>
- </picker-view-column>
- <picker-view-column v-if="!reset && (type == 1 || type == 2 || type == 7 || type==8)">
- <view class="tui-date__column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }"
- v-for="(item, index) in days" :key="index">
- {{ formatNum(item) }}
- <text class="tui-date__unit-text" v-if="!unitTop">日</text>
- </view>
- </picker-view-column>
- <picker-view-column v-if="!reset && (type == 1 || type == 4 || type == 5 || type == 7 || type==8)">
- <view class="tui-date__column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }"
- v-for="(item, index) in hours" :key="index">
- {{ formatNum(item) }}
- <text class="tui-date__unit-text" v-if="!unitTop">时</text>
- </view>
- </picker-view-column>
- <picker-view-column v-if="!reset && (type == 1 || type > 3) && type!=8">
- <view class="tui-date__column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }"
- v-for="(item, index) in minutes" :key="index">
- {{ formatNum(item) }}
- <text class="tui-date__unit-text" v-if="!unitTop">分</text>
- </view>
- </picker-view-column>
- <picker-view-column v-if="!reset && type > 4 && type!=8">
- <view class="tui-date__column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }"
- v-for="(item, index) in seconds" :key="index">
- {{ formatNum(item) }}
- <text class="tui-date__unit-text" v-if="!unitTop">秒</text>
- </view>
- </picker-view-column>
- </picker-view>
- </view>
- </view>
- </view>
- </template>
- <script>
- export default {
- name: 'tuiDatetime',
- emits: ['cancel', 'confirm'],
- props: {
- //1-日期+时间(年月日+时分) 2-日期(年月日) 3-日期(年月) 4-时间(时分) 5-时分秒 6-分秒 7-年月日 时分秒 8-年月日+小时
- type: {
- type: Number,
- default: 1
- },
- //年份区间
- startYear: {
- type: Number,
- default: 1980
- },
- //年份区间
- endYear: {
- type: Number,
- default: 2050
- },
- //显示标题
- title: {
- type: String,
- default: ''
- },
- //标题字体大小
- titleSize: {
- type: [Number, String],
- default: 34
- },
- //标题字体颜色
- titleColor: {
- type: String,
- default: '#333'
- },
- //"取消"字体颜色
- cancelColor: {
- type: String,
- default: '#888'
- },
- //"确定"字体颜色
- color: {
- type: String,
- default: '#5677fc'
- },
- //设置默认显示日期 2019-08-01 || 2019-08-01 17:01 || 2019/08/01
- setDateTime: {
- type: String,
- default: ''
- },
- //单位置顶
- unitTop: {
- type: Boolean,
- default: false
- },
- //圆角设置
- radius: {
- type: Boolean,
- default: false
- },
- //头部背景色
- headerBackground: {
- type: String,
- default: '#fff'
- },
- //根据实际调整,不建议使用深颜色
- bodyBackground: {
- type: String,
- default: '#fff'
- },
- //单位置顶时,单位条背景色
- unitBackground: {
- type: String,
- default: '#fff'
- },
- height: {
- type: [Number, String],
- default: 520
- },
- //点击遮罩 是否可关闭
- maskClosable: {
- type: Boolean,
- default: true
- }
- },
- data() {
- return {
- isShow: false,
- years: [],
- months: [],
- days: [],
- hours: [],
- minutes: [],
- seconds: [],
- year: 0,
- month: 0,
- day: 0,
- hour: 0,
- minute: 0,
- second: 0,
- startDate: '',
- endDate: '',
- value: [0, 0, 0, 0, 0, 0],
- reset: false,
- isEnd: true
- };
- },
- mounted() {
- setTimeout(() => {
- this.initData();
- }, 20)
- },
- computed: {
- yearOrMonth() {
- return `${this.year}-${this.month}`;
- },
- propsChange() {
- return `${this.setDateTime}-${this.type}-${this.startYear}-${this.endYear}`;
- }
- },
- watch: {
- yearOrMonth() {
- this.setDays();
- },
- propsChange() {
- this.reset = true;
- setTimeout(() => {
- this.initData();
- }, 20);
- }
- },
- methods: {
- stop() {},
- formatNum: function(num) {
- return num < 10 ? '0' + num : num + '';
- },
- generateArray: function(start, end) {
- return Array.from(new Array(end + 1).keys()).slice(start);
- },
- getIndex: function(arr, val) {
- let index = arr.indexOf(val);
- return ~index ? index : 0;
- },
- getCharCount(str) {
- let regex = new RegExp('/', 'g');
- let result = str.match(regex);
- return !result ? 0 : result.length;
- },
- //日期时间处理
- initSelectValue() {
- let fdate = this.setDateTime.replace(/\-/g, '/');
- if (this.type == 3 && this.getCharCount(fdate) === 1) {
- fdate += '/01'
- }
- fdate = fdate && fdate.indexOf('/') == -1 ? `2020/01/01 ${fdate}` : fdate;
- let time = null;
- if (fdate) time = new Date(fdate);
- else time = new Date();
- this.year = time.getFullYear();
- this.month = time.getMonth() + 1;
- this.day = time.getDate();
- this.hour = time.getHours();
- this.minute = time.getMinutes();
- this.second = time.getSeconds();
- },
- initData() {
- this.initSelectValue();
- this.reset = false;
- switch (this.type) {
- case 1:
- this.value = [0, 0, 0, 0, 0];
- this.setYears();
- this.setMonths();
- this.setDays();
- this.setHours();
- this.setMinutes();
- break;
- case 2:
- this.value = [0, 0, 0];
- this.setYears();
- this.setMonths();
- this.setDays();
- break;
- case 3:
- this.value = [0, 0];
- this.setYears();
- this.setMonths();
- break;
- case 4:
- this.value = [0, 0];
- this.setHours();
- this.setMinutes();
- break;
- case 5:
- this.value = [0, 0, 0];
- this.setHours();
- this.setMinutes();
- this.setSeconds();
- break;
- case 6:
- this.value = [0, 0];
- this.setMinutes();
- this.setSeconds();
- break;
- case 7:
- this.value = [0, 0, 0, 0, 0, 0];
- this.setYears();
- this.setMonths();
- this.setDays();
- this.setHours();
- this.setMinutes();
- this.setSeconds();
- break;
- case 8:
- this.value = [0, 0, 0, 0];
- this.setYears();
- this.setMonths();
- this.setDays();
- this.setHours();
- break;
- default:
- break;
- }
- },
- setYears() {
- this.years = this.generateArray(this.startYear, this.endYear);
- setTimeout(() => {
- this.$set(this.value, 0, this.getIndex(this.years, this.year));
- }, 8);
- },
- setMonths() {
- this.months = this.generateArray(1, 12);
- setTimeout(() => {
- this.$set(this.value, 1, this.getIndex(this.months, this.month));
- }, 8);
- },
- setDays() {
- if (this.type == 3 || this.type == 4) return;
- let totalDays = new Date(this.year, this.month, 0).getDate();
- totalDays = !totalDays || totalDays < 1 ? 1 : totalDays
- this.days = this.generateArray(1, totalDays);
- setTimeout(() => {
- this.$set(this.value, 2, this.getIndex(this.days, this.day));
- }, 8);
- },
- setHours() {
- this.hours = this.generateArray(0, 23);
- setTimeout(() => {
- let index = 0
- if (this.type == 8) {
- index = this.value.length - 1
- } else {
- index = this.type == 5 || this.type == 7 ? this.value.length - 3 : this.value.length - 2;
- }
- this.$set(this.value, index, this.getIndex(this.hours, this.hour));
- }, 8);
- },
- setMinutes() {
- this.minutes = this.generateArray(0, 59);
- setTimeout(() => {
- let index = this.type > 4 ? this.value.length - 2 : this.value.length - 1;
- this.$set(this.value, index, this.getIndex(this.minutes, this.minute));
- }, 8);
- },
- setSeconds() {
- this.seconds = this.generateArray(0, 59);
- setTimeout(() => {
- this.$set(this.value, this.value.length - 1, this.getIndex(this.seconds, this.second));
- }, 8);
- },
- show() {
- setTimeout(() => {
- this.isShow = true;
- }, 50);
- },
- hide() {
- this.isShow = false;
- this.$emit('cancel', {});
- },
- maskClick() {
- if (!this.maskClosable) return;
- this.hide()
- },
- change(e) {
- if(!this.isShow) return;
- this.value = e.detail.value;
- switch (this.type) {
- case 1:
- this.year = this.years[this.value[0]];
- this.month = this.months[this.value[1]];
- this.day = this.days[this.value[2]];
- this.hour = this.hours[this.value[3]];
- this.minute = this.minutes[this.value[4]];
- break;
- case 2:
- this.year = this.years[this.value[0]];
- this.month = this.months[this.value[1]];
- this.day = this.days[this.value[2]];
- break;
- case 3:
- this.year = this.years[this.value[0]];
- this.month = this.months[this.value[1]];
- break;
- case 4:
- this.hour = this.hours[this.value[0]];
- this.minute = this.minutes[this.value[1]];
- break;
- case 5:
- this.hour = this.hours[this.value[0]];
- this.minute = this.minutes[this.value[1]];
- this.second = this.seconds[this.value[2]];
- break;
- case 6:
- this.minute = this.minutes[this.value[0]];
- this.second = this.seconds[this.value[1]];
- break;
- case 7:
- this.year = this.years[this.value[0]];
- this.month = this.months[this.value[1]];
- this.day = this.days[this.value[2]];
- this.hour = this.hours[this.value[3]];
- this.minute = this.minutes[this.value[4]];
- this.second = this.seconds[this.value[5]];
- break;
- case 8:
- this.year = this.years[this.value[0]];
- this.month = this.months[this.value[1]];
- this.day = this.days[this.value[2]];
- this.hour = this.hours[this.value[3]];
- break;
- default:
- break;
- }
- this.isEnd = true
- },
- selectResult() {
- let result = {};
- let year = this.year;
- let month = this.formatNum(this.month || 0);
- let day = this.formatNum(this.day || 0);
- let hour = this.formatNum(this.hour || 0);
- let minute = this.formatNum(this.minute || 0);
- let second = this.formatNum(this.second || 0);
- switch (this.type) {
- case 1:
- result = {
- year: year,
- month: month,
- day: day,
- hour: hour,
- minute: minute,
- result: `${year}-${month}-${day} ${hour}:${minute}`
- };
- break;
- case 2:
- result = {
- year: year,
- month: month,
- day: day,
- result: `${year}-${month}-${day}`
- };
- break;
- case 3:
- result = {
- year: year,
- month: month,
- result: `${year}-${month}`
- };
- break;
- case 4:
- result = {
- hour: hour,
- minute: minute,
- result: `${hour}:${minute}`
- };
- break;
- case 5:
- result = {
- hour: hour,
- minute: minute,
- second: second,
- result: `${hour}:${minute}:${second}`
- };
- break;
- case 6:
- result = {
- minute: minute,
- second: second,
- result: `${minute}:${second}`
- };
- break;
- case 7:
- result = {
- year: year,
- month: month,
- day: day,
- hour: hour,
- minute: minute,
- second: second,
- result: `${year}-${month}-${day} ${hour}:${minute}:${second}`
- };
- break;
- case 8:
- result = {
- year: year,
- month: month,
- day: day,
- hour: hour,
- result: `${year}-${month}-${day} ${hour}:00`
- };
- break;
- default:
- break;
- }
- this.$emit('confirm', result);
- },
- waitFix() {
- if (this.isEnd) {
- this.selectResult()
- } else {
- setTimeout(() => {
- this.waitFix()
- }, 50)
- }
- },
- btnFix() {
- setTimeout(() => {
- this.waitFix()
- this.hide();
- }, 80);
- },
- pickerstart() {
- this.isEnd = false
- }
- }
- };
- </script>
- <style scoped>
- .tui-datetime-picker {
- position: relative;
- z-index: 996;
- }
- .tui-picker-view {
- height: 100%;
- box-sizing: border-box;
- }
- .tui-mask {
- position: fixed;
- z-index: 997;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- background-color: rgba(0, 0, 0, 0.6);
- visibility: hidden;
- opacity: 0;
- transition: all 0.3s ease-in-out;
- }
- .tui-mask-show {
- visibility: visible !important;
- opacity: 1 !important;
- }
- .tui-header {
- z-index: 998;
- position: fixed;
- bottom: 0;
- left: 0;
- width: 100%;
- transition: all 0.3s ease-in-out;
- transform: translateY(100%);
- }
- .tui-date-header {
- width: 100%;
- height: 52rpx;
- display: flex;
- align-items: center;
- justify-content: space-between;
- font-size: 26rpx;
- line-height: 26rpx;
- /* #ifdef MP */
- box-shadow: 0 15rpx 10rpx -15rpx #efefef;
- /* #endif */
- /* #ifndef MP */
- box-shadow: 0 15rpx 10rpx -15rpx #888;
- /* #endif */
- position: relative;
- z-index: 2;
- }
- .tui-date-unit {
- flex: 1;
- text-align: center;
- }
- .tui-show {
- transform: translateY(0);
- }
- .tui-picker-header {
- width: 100%;
- height: 90rpx;
- padding: 0 40rpx;
- display: flex;
- justify-content: space-between;
- align-items: center;
- box-sizing: border-box;
- font-size: 32rpx;
- position: relative;
- }
- .tui-date-radius {
- border-top-left-radius: 20rpx;
- border-top-right-radius: 20rpx;
- overflow: hidden;
- }
- .tui-picker-header::after {
- content: '';
- position: absolute;
- border-bottom: 1rpx solid #eaeef1;
- -webkit-transform: scaleY(0.5);
- transform: scaleY(0.5);
- bottom: 0;
- right: 0;
- left: 0;
- }
- .tui-date__picker-body {
- width: 100%;
- /* height: 520rpx; */
- overflow: hidden;
- }
- .tui-date__column-item {
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 36rpx;
- color: #333;
- }
- .tui-font-size_32 {
- font-size: 32rpx !important;
- }
- .tui-date__unit-text {
- font-size: 24rpx !important;
- padding-left: 8rpx;
- }
- .tui-btn-picker {
- padding: 16rpx;
- box-sizing: border-box;
- text-align: center;
- text-decoration: none;
- flex-shrink: 0;
- /* #ifdef H5 */
- cursor: pointer;
- /* #endif */
- }
- .tui-opacity {
- opacity: 0.5;
- }
- .tui-pickerdate__title {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- flex: 1;
- padding: 0 30rpx;
- box-sizing: border-box;
- text-align: center;
- }
- </style>
|