PickupTimePicker.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <template>
  2. <u-popup mode="bottom" v-model="show" @close="close" border-radius="40">
  3. <view class="pickup-time-picker">
  4. <view class="picker-header">
  5. <text class="title">期望快递上门时间</text>
  6. <view class="close-icon" @click="close">
  7. <u-icon name="close" size="24"></u-icon>
  8. </view>
  9. </view>
  10. <view class="picker-content">
  11. <!-- 左侧日期列表 -->
  12. <view class="date-list">
  13. <view v-for="(day, index) in weekDays" :key="index" class="date-item" :class="{
  14. 'active': selectedDayIndex === index,
  15. }" @click="selectDay(index)">
  16. <text>{{ day.text }}</text>
  17. </view>
  18. </view>
  19. <!-- 右侧时间列表 -->
  20. <view class="time-list">
  21. <view v-for="(time, index) in availableTimes" :key="index" class="time-item" :class="{
  22. 'disabled': isTimeDisabled(time),
  23. 'selected': selectedTimeIndex === index
  24. }" @click="selectTime(index, time)">
  25. <text>{{ time }}</text>
  26. <u-icon name="checkbox-mark" v-if="selectedTimeIndex === index" color="#07c160"></u-icon>
  27. </view>
  28. </view>
  29. </view>
  30. </view>
  31. </u-popup>
  32. </template>
  33. <script>
  34. export default {
  35. props: {
  36. show: {
  37. type: Boolean,
  38. default: false
  39. }
  40. },
  41. data() {
  42. return {
  43. selectedDayIndex: 0,
  44. selectedTimeIndex: -1,
  45. currentDayIndex: 0,
  46. weekDays: [],
  47. availableTimes: [
  48. '09:00-10:00',
  49. '10:00-11:00',
  50. '11:00-12:00',
  51. '12:00-13:00',
  52. '13:00-14:00',
  53. '14:00-15:00',
  54. '15:00-16:00',
  55. '16:00-17:00',
  56. '17:00-18:00'
  57. ]
  58. }
  59. },
  60. created() {
  61. this.initializeWeekDays()
  62. },
  63. methods: {
  64. initializeWeekDays() {
  65. const today = new Date()
  66. const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
  67. for (let i = 0; i < 5; i++) {
  68. const date = new Date(today)
  69. date.setDate(today.getDate() + i)
  70. let text = ''
  71. if (i === 0) {
  72. text = '今天'
  73. } else if (i === 1) {
  74. text = '明天'
  75. } else {
  76. text = weekdays[date.getDay()]
  77. }
  78. text += `(${date.getMonth() + 1}月${date.getDate()}日)`
  79. this.weekDays.push({
  80. text,
  81. date,
  82. isWeekend: date.getDay() === 0 || date.getDay() === 6
  83. })
  84. }
  85. },
  86. selectDay(index) {
  87. this.selectedDayIndex = index
  88. this.selectedTimeIndex = -1 // 切换日期时重置时间选择
  89. },
  90. selectTime(index, time) {
  91. if (this.isTimeDisabled(time)) return
  92. this.selectedTimeIndex = index
  93. const selectedDay = this.weekDays[this.selectedDayIndex]
  94. this.$emit('confirm', {
  95. date: selectedDay.date,
  96. day: selectedDay.text,
  97. time: time
  98. })
  99. this.close()
  100. },
  101. isTimeDisabled(time) {
  102. if (this.selectedDayIndex !== 0) return false
  103. const now = new Date()
  104. const [startTime] = time.split('-')
  105. const [hours, minutes] = startTime.split(':').map(Number)
  106. const timeDate = new Date()
  107. timeDate.setHours(hours, minutes, 0)
  108. return timeDate <= now
  109. },
  110. close() {
  111. this.$emit('update:show', false)
  112. }
  113. }
  114. }
  115. </script>
  116. <style lang="scss" scoped>
  117. .pickup-time-picker {
  118. background-color: #fff;
  119. border-radius: 16rpx 16rpx 0 0;
  120. .picker-header {
  121. padding: 30rpx;
  122. display: flex;
  123. justify-content: space-between;
  124. align-items: center;
  125. border-bottom: 1px solid #eee;
  126. .title {
  127. font-size: 32rpx;
  128. font-weight: 500;
  129. color: #333;
  130. }
  131. }
  132. .picker-content {
  133. display: flex;
  134. height: 760rpx;
  135. .date-list {
  136. width: 45%;
  137. background-color: #f8f8f8;
  138. .date-item {
  139. padding: 30rpx 20rpx;
  140. text-align: center;
  141. font-size: 28rpx;
  142. color: #333;
  143. &.active {
  144. background-color: #FFFFFF;
  145. color: #07c160;
  146. }
  147. &.weekend {
  148. color: #4099ef;
  149. }
  150. }
  151. }
  152. .time-list {
  153. flex: 1;
  154. padding: 0 20rpx;
  155. .time-item {
  156. padding: 20rpx 60rpx;
  157. display: flex;
  158. justify-content: space-between;
  159. align-items: center;
  160. font-size: 28rpx;
  161. color: #333;
  162. &.disabled {
  163. color: #999;
  164. }
  165. &.selected {
  166. color: #07c160;
  167. }
  168. .check-icon {
  169. color: #07c160;
  170. }
  171. }
  172. }
  173. }
  174. }
  175. </style>