您好,登錄后才能下訂單哦!
這篇文章主要講解了“怎么用uni-popup實現菜鳥上門取件時間選擇器”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么用uni-popup實現菜鳥上門取件時間選擇器”吧!
因為目前我的項目只用到這三端,其他的都還沒測,所以兼容不保證
支付寶小程序開發者工具popup彈出來會直接滾到最頂部,顯示異常,但真機上面沒問題,可以不用管
環境 | 兼容 |
---|---|
支付寶小程序 | ? |
微信小程序 | ? |
H5 | ? |
1、彈窗從底部彈出
點擊蒙層不可關閉
彈窗header左側title , 右側關閉按鈕
2、左側日期選擇器
顯示近3天日期
顯示(今天、明天、周一、周二等)
3、右側時間選擇器
可選時間可配置
過期時間顯示 “已過期”
選中效果
當前已無可選時間,應該刪除今天日期,只可以選未來日期
先做一下基礎布局,簡單的分成上左右三大塊,并做一些基礎的配置
<template> <uni-popup mask-background-color="rgba(0, 0, 0, .8)" ref="datePickerPop" type="bottom" background-color="#fff" :is-mask-click="false" > <view class="date_pop"> <view class="popup_header"> <view class="pop_title">請選擇取件時間</view> <view class="pop-close" @click="handleClose('datePop')" /> </view> <!-- 日期 --> <view class="date_con"> <scroll-view scroll-y="true" class="date_box"> </scroll-view> <!-- 時間 --> <scroll-view scroll-y="true" class="time_box"> </scroll-view> </view> </view> </uni-popup> </template> <script> export default { name: 'TimePicker', props: { visible: { required: true, default: false } }, watch: { visible(newVal) { if (newVal) { if (!this.selectedDate.date_zh) { this.selectedDate = this.effectRecentDate[0]; } this.$refs.datePickerPop.open(); } else { this.$refs.datePickerPop.close(); } } }, methods: { handleClose() { this.$emit('update:visible', false); }, } }; </script> <style scoped lang="scss"> .date_pop { padding: 0; height: 750rpx; .popup_header { display: flex; align-items: center; justify-content: space-between; box-sizing: border-box; padding: 60rpx 40rpx; .pop_title { font-weight: bold; font-size: 32rpx; width: 90%; } .pop-close { width: 60rpx; height: 60rpx; background: url('~@/static/images/close.png'); background-size: 22rpx; background-position: center; background-repeat: no-repeat; } } .date_con { font-size: 28rpx; position: relative; height: 600rpx; } .date_box { position: absolute; top: 0; left: 0; width: 40%; height: 100%; background: #f7f7f9; overflow-y: scroll; .date_item { padding: 0 40rpx; line-height: 100rpx; } } .time_box { position: absolute; top: 0; right: 0; width: 60%; height: 100%; } .date_active { background: #fff; } } </style>
按照需求我重新設計了一下功能及交互
日期選擇器
日期可配置,支持顯示最近n天日期
顯示今天、明天、后臺及工作日
默認選中當日(今天)
時間選擇器
基礎功能
刪除過期時間
今日所有可選日期都過期之后刪除日期選框(今天)選項
選中時間后面打鉤,并關閉彈窗
可選功能
顯示已過期時間 (邏輯幾個版本之前已經刪除了,現在只剩類名,需要的同學可以大概看下代碼把它加上或者評論區留個言我把給你找找代碼 , 功能樣式就類似菜鳥)
直接刪除已過期時間
// 生成時間選擇器 最近n天的時間 /** *@n {Number} : 生成的天數 * */ setRecentData(n) { const oneDaySeconds = 60 * 1000 * 60 * 24; const today = +new Date(); let list = []; for (let i = 0; i < n; i++) { let formatTime = this.formatTime_zh(today + oneDaySeconds * i); list.push({ ...formatTime, week: i == 0 ? '今天' : i == 1 ? '明天' : formatTime.week }); } //設置一下默認選中日期 this.selectedDate = list[0]; return list; }, // 時間處理函數 formatTime_zh(date){ date = new Date(date); const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); const weekDay = date.getDay(); const formatNumber = (n) => { n = n.toString(); return n[1] ? n : '0' + n; }; const numToTxt = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; return { date_zh: `${formatNumber(month)}月${formatNumber(day)}日`, date_en: `${year}/${formatNumber(month)}/${formatNumber(day)}`, week: numToTxt[weekDay] }; },
最終數據格式如圖:
因為考慮到取件沒有那么快,至少要提前半小時下單,所以就有了下面的邏輯(我這里是90分鐘)
傳入 09:00-10:00 格式時間區間
截取過期時間, 和當前時間做對比
判斷已過期 、即將過期 、未過期
/** * @return {Number} 1:已過期 , 2:即將過期 , 3:未過期 * @time {String} 09:00-10:00 */ checkRemainingMinute(time) { if (!time) return; //過期時間 const outTime = time.toString().split('-')[1]; // 這里兼容一下iphone,iphone不支持yyyy-mm-dd hh:mm 格式時間 ,分隔符換為 / const fullYearDate = formatMinute(new Date(), '/'); const now = new Date(fullYearDate); const dateTime = this.currentDate + ' ' + outTime; const check = new Date(dateTime); const difference = check - now; const minutes = difference / (1000 * 60); // minutes <= 0 : 已過期 --> 1 // minutes <= 90 : 即將過期 --> 2 // minutes > 0 : 未過期 --> 3 return minutes <= 0 ? 1 : minutes <= 90 ? 2 : 3; } /** * @description yyyy-mm-dd hh:mm * @author wangxinu * @export * @param {*} cent * @returns */ formatMinute: (date, separator = '-') => { date = new Date(date); const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); const hour = date.getHours(); const minute = date.getMinutes(); const second = date.getSeconds(); const formatNumber = (n) => { n = n.toString(); return n[1] ? n : '0' + n; }; return `${formatNumber(year)}${separator}${formatNumber(month)}${separator}${formatNumber( day, )} ${formatNumber(hour)}:${formatNumber(minute)}`; },
data(){ return { appointment: [ '08:00-09:00', '09:00-10:00', '10:00-11:00', '11:00-12:00', '12:00-13:00', '13:00-14:00', '14:00-15:00', '15:00-16:00', '16:00-17:00', '17:00-18:00', '18:00-19:00', '19:00-20:00' ] } }, computed: { // 有效取件時間 effectAppointmentTime() { //取件時間列表 const appointment = this.appointment; // 未來日期返回全部 if (this.selectedDate.date_en != this.currentDate) { return appointment; } // 當日只返回有效時間 let list = appointment.filter((item) => this.checkRemainingMinute(item) != 1); // 當天取件時間長度>0 添加立即上門 if (list.length > 0) { list.unshift('立即上門'); } return list; } },
computed: { // 有效日期 effectRecentDate() { //查看有效時間列表 const effectAppointmentTime = this.effectAppointmentTime; // 當日取件時間全部失效 if (effectAppointmentTime.length == 0) { //刪除(今日) this.recentDateList.splice(0, 1); //修改默認選中日期 this.selectedDate = this.recentDateList[0]; return this.recentDateList; } else { return this.recentDateList; } }, },
// 時間選擇器修改函數 timeChange(date, type) { const dateList = this.recentDateList; if (type === 'date') { // 選擇日期 this.selectedDate = date; this.selectedTime = ''; } else { // 選擇時間 this.selectedTime = date; if (this.selectedDate.date_zh == '') { this.selectedDate = dateList[0]; } this.handleClose(); this.$emit('selectTime', this.selectedDate, this.selectedTime); } },
<template> <div class="page"> <button @click="timePicker_visible = true" type="primary">打開彈窗</button> <TimePicker :visible.sync="timePicker_visible" @selectTime="selectTime"/> </div> </template> <script> import TimePicker from './components/TimePicker'; export default { name: 'test', components: { TimePicker }, mixins: [], props: {}, data() { return { timePicker_visible: false }; }, methods:{ selectTime(date,time){ console.log('date',date) console.log('time',time) } } }; </script>
<template> <uni-popup mask-background-color="rgba(0, 0, 0, .8)" ref="datePickerPop" type="bottom" background-color="#fff" :is-mask-click="false" > <view class="date_pop"> <view class="popup_header"> <view class="pop_title">請選擇取件時間</view> <view class="pop-close" @click="handleClose('datePop')" /> </view> <!-- 日期 --> <view class="date_con"> <scroll-view scroll-y="true" class="date_box"> <view v-for="date in effectRecentDate" :key="date.date_zh" :class="[`date_item`, selectedDate.date_zh == date.date_zh ? `date_active` : ``]" @click="timeChange(date, 'date')" > {{ date.date_zh }}({{ date.week }}) </view> </scroll-view> <!-- 時間 --> <scroll-view scroll-y="true" class="time_box"> <view v-for="(time, index) in effectAppointmentTime" :key="index" :class="{ bottom: true, time_item: true, time_active: selectedTime === time }" @click="timeChange(effectAppointmentTime[index], `time`)" > {{ time }} </view> </scroll-view> </view> </view> </uni-popup> </template> <script> import { formatDate, toFixed, formatMinute } from '@/public/utils/utils'; export default { name: 'TimePicker', props: { visible: { required: true, default: false } }, watch: { visible(newVal) { if (newVal) { if (!this.selectedDate.date_zh) { this.selectedDate = this.effectRecentDate[0]; } this.$refs.datePickerPop.open(); } else { this.$refs.datePickerPop.close(); } } }, data() { // 生成取件日期 const recentDayNum = 5; this.toFixed = toFixed; return { currentDate: formatDate(new Date(), '/'), selectedTime: '', selectedDate: {}, recentDateList: this.setRecentData(recentDayNum), appointment: [ '08:00-09:00', '09:00-10:00', '10:00-11:00', '11:00-12:00', '12:00-13:00', '13:00-14:00', '14:00-15:00', '15:00-16:00', '16:00-17:00', '17:00-18:00', '18:00-19:00', '19:00-20:00' ] }; }, computed: { // 有效日期 effectRecentDate() { const effectAppointmentTime = this.effectAppointmentTime; // 當日取件時間全部失效 if (effectAppointmentTime.length == 0) { this.recentDateList.splice(0, 1); this.selectedDate = this.recentDateList[0]; console.log('this.selectedDate: ', this.selectedDate); return this.recentDateList; } else { return this.recentDateList; } }, // 有效取件時間 effectAppointmentTime() { const appointment = this.appointment; // 未來日期返回全部 if (this.selectedDate.date_en != this.currentDate) { return appointment; } let list = appointment.filter((item) => this.checkRemainingMinute(item) != 1); // 當日只返回有效時間 if (list.length > 0) { list.unshift('立即上門'); } return list; } }, methods: { handleClose() { this.$emit('update:visible', false); }, // 生成時間選擇器 最近n天的時間 setRecentData(n) { const oneDayTime = 60 * 1000 * 60 * 24; const today = +new Date(); let list = []; for (let i = 0; i < n; i++) { let formatTime = this.formatTime_zh(today + oneDayTime * i); list.push({ ...formatTime, week: i == 0 ? '今天' : i == 1 ? '明天' : formatTime.week }); } this.selectedDate = list[0]; return list; }, // 時間處理函數 formatTime_zh: (date) => { date = new Date(date); const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); const weekDay = date.getDay(); const formatNumber = (n) => { n = n.toString(); return n[1] ? n : '0' + n; }; const numToTxt = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; return { date_zh: `${formatNumber(month)}月${formatNumber(day)}日`, date_en: `${year}/${formatNumber(month)}/${formatNumber(day)}`, week: numToTxt[weekDay] }; }, // 時間選擇器修改函數 timeChange(date, type) { const dateList = this.recentDateList; if (type === 'date') { // 選擇日期 this.selectedDate = date; this.selectedTime = ''; } else { // 選擇時間 this.selectedTime = date; if (this.selectedDate.date_zh == '') { this.selectedDate = dateList[0]; } this.handleClose(); this.$emit('selectTime', this.selectedDate, this.selectedTime); } }, /** * @return {Number} 1:已過期 , 2:即將過期 , 3:未過期 */ checkRemainingMinute(time) { console.log('time: ', time); if (!time) return; const outTime = time.toString().split('-')[1]; const fullYearDate = formatMinute(new Date(), '/'); const now = new Date(fullYearDate); const dateTime = this.currentDate + ' ' + outTime; const check = new Date(dateTime); const difference = check - now; const minutes = difference / (1000 * 60); // minutes <= 0 : 已過期 --> 1 // minutes <= 90 : 即將過期 --> 2 // minutes > 0 : 未過期 --> 3 return minutes <= 0 ? 1 : minutes <= 90 ? 2 : 3; } } }; </script> <style scoped lang="scss"> .date_pop { padding: 0; height: 750rpx; .popup_header { display: flex; align-items: center; justify-content: space-between; box-sizing: border-box; padding: 60rpx 40rpx; .pop_title { font-weight: bold; font-size: 32rpx; width: 90%; } .pop-close { width: 60rpx; height: 60rpx; background: url('~@/static/images/close.png'); background-size: 22rpx; background-position: center; background-repeat: no-repeat; } } .date_con { font-size: 28rpx; position: relative; height: 600rpx; } .date_box { position: absolute; top: 0; left: 0; width: 40%; height: 100%; background: #f7f7f9; overflow-y: scroll; .date_item { padding: 0 40rpx; line-height: 100rpx; } .date_active { background: #fff; } } .time_box { position: absolute; top: 0; right: 0; width: 60%; height: 100%; .disabled { color: #ccc; &::after { content: '已過期'; margin-left: 130rpx; } } .outTime { color: #ccc; &::after { content: '即將過期'; margin-left: 100rpx; } } .time_item { padding: 0 40rpx; line-height: 100rpx; } } .time_active { color: #ff5b29; position: relative; &::after { position: absolute; content: '?'; right: 15%; margin: auto; } } } </style>
時間區域打開顯示對應選中時間位置
右側時間列表改后臺返回
感謝各位的閱讀,以上就是“怎么用uni-popup實現菜鳥上門取件時間選擇器”的內容了,經過本文的學習后,相信大家對怎么用uni-popup實現菜鳥上門取件時間選擇器這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。