fs-week-bar.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <template>
  2. <view class="fs-week-bar">
  3. <view class="fs-week-arrow" @click="handleChange('left')">
  4. <fs-icon type="icon-d-down" rotate="90" size="28rpx" :color="textColor"></fs-icon>
  5. </view>
  6. <view class="fs-week-list">
  7. <view
  8. class="fs-week-item"
  9. :class="{ 'fs-week-item-active': state.activeDate === item.fullDate }"
  10. v-for="(item, index) in state.week"
  11. :key="index"
  12. @click="handleClick(item)"
  13. >
  14. <view class="fs-week-item-hd">周{{ item.day }}</view>
  15. <view class="fs-week-item-bd">{{ item.date }}</view>
  16. </view>
  17. </view>
  18. <view class="fs-week-arrow" @click="handleChange('right')">
  19. <fs-icon type="icon-d-down" rotate="-90" size="28rpx" :color="textColor"></fs-icon>
  20. </view>
  21. </view>
  22. </template>
  23. <script>
  24. /**
  25. * 时间周组件
  26. * @description 时间周组件
  27. * @property {String} bgColor 背景颜色
  28. * @property {String} textColor 文字颜色
  29. * @property {String} activeColor 激活颜色
  30. * @property {String} activeDate 激活日期
  31. * @event {Function} change 左右箭头切换事件
  32. */
  33. export default {
  34. name: 'fs-week-bar'
  35. }
  36. </script>
  37. <script setup>
  38. import { ref, reactive, watch, nextTick } from 'vue'
  39. import dayjs from 'dayjs'
  40. const props = defineProps({
  41. bgColor: {
  42. type: String,
  43. default: '#fff'
  44. },
  45. textColor: {
  46. type: String,
  47. default: '#666666'
  48. },
  49. activeColor: {
  50. type: String,
  51. default: '#165DFF'
  52. },
  53. activeDate: {
  54. type: String,
  55. default: dayjs().format('YYYY-MM-DD')
  56. }
  57. })
  58. const emits = defineEmits(['change', 'click'])
  59. const state = reactive({
  60. week: [],
  61. radix: 0,
  62. activeDate: '',
  63. curDay: '',
  64. curDate: ''
  65. })
  66. const dayMap = {
  67. 1: '一',
  68. 2: '二',
  69. 3: '三',
  70. 4: '四',
  71. 5: '五',
  72. 6: '六',
  73. 7: '日'
  74. }
  75. const initWeek = () => {
  76. state.week = []
  77. for (let i = 1; i < state.curDay; i++) {
  78. const diffDay = state.curDay - i
  79. const date = dayjs(state.curDate)
  80. .subtract(diffDay, 'day')
  81. .add(7 * state.radix, 'day')
  82. state.week.push({
  83. day: dayMap[i],
  84. date: date.format('MM-DD'),
  85. fullDate: date.format('YYYY-MM-DD')
  86. })
  87. }
  88. for (let i = state.curDay; i <= 7; i++) {
  89. const diffDay = i - state.curDay
  90. const date = dayjs(state.curDate)
  91. .add(diffDay, 'day')
  92. .add(7 * state.radix, 'day')
  93. state.week.push({
  94. day: dayMap[i],
  95. date: date.format('MM-DD'),
  96. fullDate: date.format('YYYY-MM-DD')
  97. })
  98. }
  99. }
  100. const stopWatch = watch(
  101. () => props.activeDate,
  102. val => {
  103. const date = val || undefined
  104. state.activeDate = dayjs(date).format('YYYY-MM-DD')
  105. state.curDate = dayjs(date).format('YYYY-MM-DD')
  106. state.curDay = dayjs(date).day() || 7
  107. // state.radix = Math.floor((dayjs(date).diff(dayjs(), 'day') + state.curDay) / 7)
  108. initWeek()
  109. },
  110. { immediate: true }
  111. )
  112. const handleChange = type => {
  113. type === 'left' ? state.radix-- : state.radix++
  114. }
  115. watch(
  116. () => state.radix,
  117. val => {
  118. initWeek()
  119. emits('change', state.week)
  120. }
  121. )
  122. const handleClick = item => {
  123. stopWatch()
  124. state.activeDate = item.fullDate
  125. emits('click', item.fullDate)
  126. }
  127. </script>
  128. <style lang="scss" scoped>
  129. .fs-week {
  130. &-bar {
  131. display: flex;
  132. align-items: center;
  133. background-color: v-bind(bgColor);
  134. padding: 20rpx 0;
  135. }
  136. &-arrow {
  137. padding: 0 10rpx;
  138. }
  139. &-list {
  140. display: flex;
  141. flex: 1;
  142. }
  143. &-item {
  144. text-align: center;
  145. flex: 1;
  146. color: v-bind(textColor);
  147. &-active {
  148. color: v-bind(activeColor);
  149. }
  150. &-hd {
  151. font-size: 15px;
  152. font-weight: bold;
  153. }
  154. &-bd {
  155. font-size: 13px;
  156. }
  157. }
  158. }
  159. </style>