index.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. <template>
  2. <div :class="ui" class="hc-date-calendar-box">
  3. <div class="hc-date-picker-box">
  4. <div class="hc-date-picker">
  5. <el-date-picker class="block" v-model="toPicker" type="month" size="large" @change="datePickerChange"/>
  6. </div>
  7. <div class="hc-date-btn-box">
  8. <div class="hc-div-btn" @click="prevMonthClick">
  9. <HcIcon name="arrow-left"/>
  10. </div>
  11. <div class="hc-div-btn" @click="nextMonthClick">
  12. <HcIcon name="arrow-right"/>
  13. </div>
  14. </div>
  15. </div>
  16. <div class="hc-date-weekdays">
  17. <template v-for="item in weekdays" :key="item">
  18. <div class="hc-date-weekdays-day">{{item}}</div>
  19. </template>
  20. </div>
  21. <div class="hc-date-dates">
  22. <template v-for="item in datesDay">
  23. <div class="hc-date-dates-day" :class="item.type" @click="datesDayClick(item)">{{item.key}}</div>
  24. </template>
  25. </div>
  26. </div>
  27. </template>
  28. <script setup>
  29. import {nextTick, watch, ref} from "vue";
  30. import dayjs from "dayjs"
  31. import 'dayjs/locale/zh-cn'
  32. import {getObjNullValue} from "vue-utils-plus";
  33. dayjs.locale('zh-cn')
  34. const props = defineProps({
  35. ui: {
  36. type: String,
  37. default: ''
  38. },
  39. recordDate: {
  40. type: Object,
  41. default: () => ({})
  42. },
  43. dateData: {
  44. type: Array,
  45. default: () => ([])
  46. },
  47. })
  48. //变量
  49. const weekdays = ['日', '一', '二', '三', '四', '五', '六'] //星期头
  50. const toDays = ref({year: '', month: '', date: '', obj: {}})
  51. const selectedDate = ref({year: '', month: ''}) //选择年月的日期
  52. const toPicker = ref('') //年月下拉框
  53. const selectedDatas = ref(props.dateData)
  54. const choiceDate = ref({year: '', month: '', date: ''}) //选择的日期,年月日
  55. const curDateData = ref([]) //设置的日期
  56. const datesDay = ref([]) //日期数据
  57. //事件
  58. const emit = defineEmits(['choice-date'])
  59. //监听
  60. watch(() => [
  61. props.dateData,
  62. props.recordDate,
  63. ], ([dateData,recordDate]) => {
  64. selectedDatas.value = dateData
  65. setCurDateData(dateData, recordDate)
  66. })
  67. //渲染完成
  68. nextTick(()=> {
  69. const toDayJs = dayjs();
  70. toDays.value = {
  71. year: toDayJs.get('year'),
  72. month: toDayJs.get('month') + 1,
  73. date: toDayJs.get('date'),
  74. obj: toDayJs
  75. }
  76. selectedDate.value = {
  77. year: toDayJs.get('year'),
  78. month: toDayJs.get('month') + 1
  79. }
  80. choiceDate.value = {
  81. year: toDayJs.get('year'),
  82. month: toDayJs.get('month') + 1,
  83. date: toDayJs.get('date')
  84. }
  85. toPicker.value = toDayJs.format('YYYY-MM')
  86. emit('choice-date', isDayDateFormat(toDays.value))
  87. setCurDateData(props.dateData, props.recordDate)
  88. })
  89. //处理设置的日期
  90. const setCurDateData = (dateData, recordDate) => {
  91. let curData = [];
  92. for (let i = 0; i < dateData.length; i++) {
  93. let toDate = dayjs(dateData[i]).format("YYYY-MM-DD");
  94. const toDayJs = dayjs(toDate);
  95. curData.push({
  96. year: toDayJs.get('year'),
  97. month: toDayJs.get('month') +1,
  98. date: toDayJs.get('date')
  99. })
  100. }
  101. curDateData.value = curData;
  102. //判断是否选择了日期
  103. if (getObjNullValue(recordDate)) {
  104. getDatesDay(recordDate.year, recordDate.month)
  105. } else {
  106. getDatesDay()
  107. }
  108. }
  109. //获取日期
  110. const getDatesDay = (year, month) => {
  111. if (year && month) {
  112. let toDate = dayjs(year + '-' + month).format("YYYY-MM-DD"); //格式化一下先
  113. let days = dayjs(toDate).daysInMonth(); //天数
  114. let monthOneDay = dayjs(toDate).startOf("month").format("YYYY-MM-DD"); //获取当月第一天
  115. let weekday = dayjs(monthOneDay, "YYYY-MM-DD").day(); //获取当月第一天是星期几
  116. toPicker.value = dayjs(year + '-' + month).format('YYYY-MM');
  117. setDatesDay(days,weekday)
  118. } else {
  119. const toDayJs = toDays.value?.obj ?? {};
  120. let days = toDayJs.daysInMonth(); //天数
  121. let monthOneDay = toDayJs.startOf("month").format("YYYY-MM-DD"); //获取当月第一天
  122. let weekday = dayjs(monthOneDay, "YYYY-MM-DD").day(); //获取当月第一天是星期几
  123. toPicker.value = toDayJs.format('YYYY-MM');
  124. setDatesDay(days,weekday)
  125. }
  126. }
  127. //设置日期
  128. const setDatesDay = (days,weekday) => {
  129. let datesDayData = [];
  130. const selected = selectedDate.value; //选择的日期
  131. const choiceData = choiceDate.value; //选择的日期
  132. const dayData = toDays.value; //今天日期
  133. //添加头部
  134. for (let i = 0; i < weekday; i++) {
  135. datesDayData.push({type: 'excluded', key: '-'})
  136. }
  137. //处理日期
  138. for (let i = 0; i < days; i++) {
  139. let day = i + 1, type = '';
  140. type = setCurDate(selected,day)
  141. if (selected.year === dayData.year && selected.month === dayData.month && dayData.date === day) {
  142. type += ' selected'
  143. }
  144. if (choiceData.year === selected.year && choiceData.month === selected.month && choiceData.date === day) {
  145. type += ' choice'
  146. }
  147. datesDayData.push({type: type, key: day})
  148. }
  149. //添加尾数
  150. let lastNum = 42 - (weekday + days);
  151. for (let i = 0; i < lastNum; i++) {
  152. datesDayData.push({type: 'excluded', key: '-'})
  153. }
  154. datesDay.value = datesDayData;
  155. }
  156. const setCurDate = (selected,day) => {
  157. const curDate = curDateData.value; //设置的日期
  158. for (let x = 0; x < curDate.length; x++) {
  159. if (selected.year === curDate[x].year && selected.month === curDate[x].month && curDate[x].date === day) {
  160. return 'cur'
  161. }
  162. }
  163. return ''
  164. }
  165. //上一月
  166. const prevMonthClick = () => {
  167. let {year,month} = selectedDate.value
  168. let years = year, months;
  169. if (month === 1) {
  170. years = year - 1;
  171. months = 12;
  172. } else {
  173. months = month - 1;
  174. }
  175. selectedDate.value = {
  176. year: years,
  177. month: months
  178. }
  179. getDatesDay(years,months)
  180. }
  181. //下一月
  182. const nextMonthClick = () => {
  183. let {year,month} = selectedDate.value
  184. let years, months;
  185. if (month === 12) {
  186. years = year + 1;
  187. months = 1;
  188. } else {
  189. years = year;
  190. months = month + 1;
  191. }
  192. selectedDate.value = {
  193. year: years,
  194. month: months
  195. }
  196. getDatesDay(years,months)
  197. }
  198. //天被点击
  199. const datesDayClick = (item) => {
  200. if (item.type !== 'excluded') {
  201. let {year,month} = selectedDate.value
  202. choiceDate.value = {year: year, month: month, date: item.key}
  203. getDatesDay(year, month)
  204. backChoiceDate()
  205. }
  206. }
  207. //下拉日期选择
  208. const datePickerChange = (val) => {
  209. const toDayJs = dayjs(val);
  210. toPicker.value = toDayJs.format('YYYY-MM')
  211. getDatesDay(toDayJs.year(), toDayJs.month() + 1)
  212. }
  213. //返回选择的日期
  214. const backChoiceDate = () => {
  215. //选择的日期处理
  216. const choiceVal = isDayDateFormat(choiceDate.value)
  217. //今天的日期处理
  218. const today = isDayDateFormat(toDays.value)
  219. //判断处理
  220. if (choiceVal.choice > today.choice) {
  221. backToDay()
  222. } else {
  223. emit('choice-date', choiceVal)
  224. }
  225. }
  226. //回到今天
  227. const backToDay = () => {
  228. const {year, month ,date} = toDays.value ?? {};
  229. selectedDate.value = {year: year, month: month}
  230. choiceDate.value = {year: year, month: month, date: date}
  231. getDatesDay(year,month)
  232. emit('choice-date', isDayDateFormat(toDays.value))
  233. }
  234. //格式转换
  235. const isDayDateFormat = ({year, month, date}) => {
  236. const today = {
  237. year: year,
  238. month: zpadStart(month, 2, '0'),
  239. date: zpadStart(date, 2, '0')
  240. }
  241. const choice = today.year + today.month + today.date
  242. const choices = `${today.year}-${today.month}-${today.date}`
  243. return {date: today, choice, choices, dates: {year, month, date}}
  244. }
  245. const zpadStart = (val, leng, pad) => {
  246. val += ''
  247. while (val.length < leng) {
  248. val = pad + val
  249. }
  250. return val
  251. }
  252. </script>
  253. <style lang="scss" scoped>
  254. @import './style.scss';
  255. </style>