当前位置:   article > 正文

H5移动端月历区间选择开始月份和结束月份_h5日历组件带开始结束时间

h5日历组件带开始结束时间

在做h5移动端app时,因业务需要,要做按日区间选择开始和结束日期,按月区间选择开始和结束月份,ui组件中有按日区间选择的,没有按月区间选择,所以结合业务自己写了一个。

  1. <template>
  2. <van-action-sheet
  3. v-model="showDate"
  4. position="bottom"
  5. @close="closeCalendar"
  6. title="选择月份"
  7. round
  8. :style="{ height: '80%' }"
  9. ref="monthDate"
  10. >
  11. <ul class="content">
  12. <li v-for="(item, index) in years" :key="index" v-scroll>
  13. <div class="monthTitle">{{ item.year }}年</div>
  14. <van-row>
  15. <van-col
  16. span="6"
  17. v-for="(childItem, key) in item.children"
  18. :key="key"
  19. :class="childItem.monthClass"
  20. >
  21. <div
  22. class="monthList"
  23. @click="selectList(item, childItem)"
  24. :class="childItem.isSelect === true ? 'isSelect' : ''"
  25. >
  26. <div :class="childItem.disabledMonth == true ? 'isDisabled' : ''">
  27. {{ childItem.month }}月
  28. </div>
  29. <div
  30. class="startEnd"
  31. :class="
  32. childItem.text == '开始' || childItem.text == '结束'
  33. ? 'fontSize'
  34. : ''
  35. "
  36. >
  37. {{ childItem.text }}
  38. </div>
  39. </div>
  40. </van-col>
  41. </van-row>
  42. </li>
  43. </ul>
  44. <div class="footBtn" default="footer">
  45. <div class="footBox">
  46. <van-button @click="onReset" type="primary">重 置</van-button>
  47. <van-button @click="onConfirm" type="primary">确 定</van-button>
  48. </div>
  49. </div>
  50. </van-action-sheet>
  51. </template>
  52. <script>
  53. import { Toast } from "vant";
  54. export default {
  55. props: {
  56. isAllowSameDay: {
  57. type: Boolean,
  58. },
  59. calendarshow: {
  60. type: Boolean,
  61. },
  62. yearLength: {
  63. type: Number,
  64. },
  65. defaultDate: {
  66. type: Array,
  67. required: true,
  68. },
  69. },
  70. data () {
  71. return {
  72. years: [],
  73. monthList: [
  74. "一",
  75. "二",
  76. "三",
  77. "四",
  78. "五",
  79. "六",
  80. "七",
  81. "八",
  82. "九",
  83. "十",
  84. "十一",
  85. "十二",
  86. ],
  87. showDate: this.calendarshow,
  88. selectArr: [],
  89. currentYear: new Date().getFullYear(), //当前年份
  90. currentMonth: new Date().getMonth() + 1, //当前月份
  91. startDefaultYear: new Date().getFullYear(), //开始年份
  92. startDefaultMonth: new Date().getMonth() + 1, //开始月份
  93. endDefaultYear: new Date().getFullYear(), //结束年份
  94. endDefaultMonth: new Date().getMonth() + 1, //结束月份
  95. startText: "开始",
  96. endText: "结束",
  97. startEndText: "开始/结束"
  98. };
  99. },
  100. directives: {
  101. // 自定义指令 月历定位到当前年份
  102. scroll: {
  103. inserted (el) {
  104. el.scrollIntoView();
  105. },
  106. },
  107. },
  108. watch: {
  109. calendarshow (val) {
  110. this.showDate = val; //显示隐藏月历
  111. },
  112. defaultDate (val) {
  113. this.startDefaultYear = val[0].getFullYear(); //开始年份
  114. this.startDefaultMonth = val[0].getMonth() + 1; //开始月份
  115. this.endDefaultYear = val[1].getFullYear(); //结束年份
  116. this.endDefaultMonth = val[1].getMonth() + 1; //结束月份
  117. this.setDefaultMonth();
  118. },
  119. },
  120. created () {
  121. this.initCalendar()
  122. },
  123. methods: {
  124. // 初始化月历
  125. initCalendar () {
  126. const that = this;
  127. for (let i = 1; i <= that.yearLength; i++) {
  128. const item = {
  129. year: that.currentYear - (that.yearLength - i),
  130. children: [],
  131. };
  132. for (let j = 0; j < that.monthList.length; j++) {
  133. let list = {
  134. month: that.monthList[j],
  135. isSelect: false,
  136. value: j + 1,
  137. text: "",
  138. };
  139. // 判断当前月之后的月份不可选
  140. if ((item.year == that.currentYear && j + 1 > that.currentMonth) || (item.year == that.currentYear - (that.yearLength - 1) && j + 1 < that.currentMonth)) {
  141. list.disabledMonth = true;
  142. } else {
  143. list.disabledMonth = false;
  144. }
  145. item.children.push(list);
  146. }
  147. that.years.push(item);
  148. }
  149. },
  150. // 设置默认值
  151. setDefaultMonth () {
  152. const that = this;
  153. const startYear = that.startDefaultYear; //默认开始年份
  154. const endYear = that.endDefaultYear; //默认结束年份
  155. const startMonth = that.startDefaultMonth; //默认开始的年份
  156. const endMonth = that.endDefaultMonth; //默认开始的年份
  157. that.selectArr = [];
  158. that.years.map((item) => {
  159. item.children.map((list) => {
  160. list.text = "";
  161. list.isSelect = false;
  162. // 当前起始年份、月份都相同
  163. if (startYear == endYear && startMonth == endMonth) {
  164. list.monthClass = "";
  165. if (item.year == startYear && list.value == startMonth) {
  166. list.text = that.startEndText;
  167. list.isSelect = true;
  168. that.monthSaveArr(startYear, startMonth, list.text);
  169. }
  170. } else {
  171. // 起始年份相同、月份不同
  172. if (item.year == startYear && list.value == startMonth) {
  173. list.text = that.startText;
  174. list.isSelect = true;
  175. that.monthSaveArr(item.year, list.value, list.text);
  176. }
  177. if (item.year == endYear && list.value == endMonth) {
  178. list.text = that.endText;
  179. list.isSelect = true;
  180. that.monthSaveArr(item.year, list.value, list.text);
  181. }
  182. }
  183. });
  184. });
  185. },
  186. // 选择的月份存入一个数组中
  187. monthSaveArr (year, month, text) {
  188. const dataItem = {
  189. year: year,
  190. month: month,
  191. text: text
  192. };
  193. this.selectArr.push(dataItem);
  194. },
  195. // 选择月份
  196. selectList (item, childItem) {
  197. const that = this;
  198. const selectStartYear = that.selectArr[0].year; //选择开始的年份
  199. const selectStartMonth = that.selectArr[0].month;//选择开始的月份
  200. // 大于当前月份不可选
  201. if (childItem.disabledMonth == true) {
  202. return;
  203. }
  204. // 开始月份 (如果数组为空 或者 已经选了开始结束月份为同一月) 选择开始月份
  205. if (that.selectArr.length == 0 || that.selectArr[0].text == that.startEndText) {
  206. that.cancelSelectMonth();
  207. childItem.text = that.startText;
  208. that.monthSaveArr(item.year, childItem.value, childItem.text);
  209. } else if (that.selectArr.length == 1) {
  210. if (item.year == selectStartYear && childItem.value == selectStartMonth) {
  211. // 开始、结束月份是否可选同一天
  212. if (that.isAllowSameDay == true) {
  213. childItem.isSelect = true;
  214. childItem.text = that.startEndText;
  215. that.monthSaveArr(item.year, childItem.value, childItem.text);
  216. return;
  217. } else {
  218. childItem.isSelect = true;
  219. childItem.text = that.startText;
  220. return;
  221. }
  222. }
  223. // 选择的月份不能超过12个月
  224. if ((item.year > this.selectArr[0].year && childItem.value >= this.selectArr[0].month) || (item.year - this.selectArr[0].year > 1)) {
  225. Toast("结束月份不能超过12个月");
  226. return;
  227. }
  228. if ((item.year == selectStartYear && childItem.value < selectStartMonth) || item.year < selectStartYear) {
  229. that.cancelSelectMonth();
  230. childItem.text = that.startText;
  231. that.monthSaveArr(item.year, childItem.value, childItem.text);
  232. } else {
  233. // 结束月份
  234. childItem.text = that.endText;
  235. that.monthSaveArr(item.year, childItem.value, childItem.text);
  236. that.setAreaBackground();
  237. }
  238. } else if (that.selectArr.length == 2) {
  239. that.cancelSelectMonth();
  240. childItem.text = that.startText;
  241. that.monthSaveArr(item.year, childItem.value, childItem.text);
  242. }
  243. childItem.isSelect = !childItem.isSelect;
  244. },
  245. // 取消已选中的月份
  246. cancelSelectMonth () {
  247. this.selectArr = [];
  248. this.years.map((item) => {
  249. item.children.map((ev) => {
  250. ev.text = "";
  251. ev.isSelect = false;
  252. ev.monthClass = "";
  253. });
  254. });
  255. },
  256. // 添加开始、结束区间的背景颜色
  257. setAreaBackground () {
  258. const startYear = this.selectArr[0].year; //开始年份
  259. const endYear = this.selectArr[1].year; //结束年份
  260. const startMonth = this.selectArr[0].month; //开始年份
  261. const endMonth = this.selectArr[1].month; //结束年份
  262. this.years.map((item) => {
  263. // 起始年份相同
  264. if (item.year == startYear && item.year == endYear) {
  265. item.children.map((ev) => {
  266. if (endMonth - startMonth >= 1) {
  267. if (ev.value == startMonth) {
  268. ev.monthClass = "calendarStartColor";
  269. } else if (ev.value == endMonth) {
  270. ev.monthClass = "calendarEndColor";
  271. } else if (ev.value > startMonth && ev.value < endMonth) {
  272. ev.monthClass = "calendarMiddleColor";
  273. }
  274. }
  275. })
  276. } else if (endYear > startYear) {
  277. // 开始年份小于结束年份
  278. if (item.year == startYear) {
  279. // 起始月份
  280. item.children.map((ev) => {
  281. if (ev.value == startMonth) {
  282. ev.monthClass = "calendarStartColor";
  283. } else if (ev.value > startMonth) {
  284. ev.monthClass = "calendarMiddleColor";
  285. }
  286. })
  287. } else if (item.year == endYear) {
  288. // 结束月份
  289. item.children.map((ev) => {
  290. if (ev.value == endMonth) {
  291. ev.monthClass = "calendarEndColor";
  292. } else if (ev.value < endMonth) {
  293. ev.monthClass = "calendarMiddleColor";
  294. }
  295. })
  296. } else if (item.year > startYear && item.year < endYear) {
  297. // 开始月份与结束月份区间的加背景色
  298. item.children.map((ev) => {
  299. ev.monthClass = "calendarMiddleColor";
  300. })
  301. }
  302. }
  303. });
  304. },
  305. // 确认
  306. onConfirm () {
  307. this.$emit("confirmMonth", this.selectArr);
  308. },
  309. // 重置日期
  310. onReset () {
  311. this.$emit("resetCalendar");
  312. },
  313. // 关闭
  314. closeCalendar () {
  315. this.$emit("closeCalendar");
  316. }
  317. }
  318. };
  319. </script>
  320. <style lang="stylus" scoped>
  321. /deep/.van-action-sheet__close {
  322. right: auto;
  323. left: 0px;
  324. }
  325. /deep/.van-action-sheet__header{
  326. font-size: 1rem;
  327. font-family: PingFang SC;
  328. font-weight: bold;
  329. color: #333333;
  330. }
  331. .content {
  332. font-family: PingFang SC;
  333. padding-bottom: 84px;
  334. /deep/.van-row {
  335. padding: 1.11rem 0 0 0;
  336. }
  337. /deep/.van-col--6 {
  338. margin-bottom: 1.11rem;
  339. position: relative;
  340. }
  341. .calendarStartColor{
  342. background-image: linear-gradient(to right, #fff , #e6f5fc);
  343. }
  344. .calendarEndColor{
  345. background-image: linear-gradient(to left,#fff , #e6f5fc);
  346. }
  347. .calendarMiddleColor {
  348. background-color: #e6f5fc;
  349. }
  350. .monthTitle {
  351. background: #E5E5E5;
  352. font-size: 0.83rem;
  353. font-weight: bold;
  354. color: #333333;
  355. padding: 0.61rem 0;
  356. }
  357. .monthList {
  358. width: 3rem;
  359. height: 2.22rem;
  360. display: flex;
  361. flex-flow: column;
  362. color: #333333;
  363. justify-items: center;
  364. align-items: center;
  365. border-radius: 0.56rem;
  366. margin: 0 auto;
  367. padding: 0 0.22rem 0.22rem 0.22rem;
  368. div:first-child {
  369. height: 0.81rem;
  370. line-height: 0.81rem;
  371. padding: 0.44rem 0 0.22rem 0;
  372. font-size: 0.89rem;
  373. font-weight: 500;
  374. }
  375. .startEnd {
  376. height: 0.61rem;
  377. line-height: 0.61rem;
  378. font-size: 0.53rem;
  379. font-weight: 500;
  380. color: #FFFEFE;
  381. }
  382. .fontSize {
  383. font-size: 0.61rem;
  384. }
  385. div {
  386. display: flex;
  387. flex-flow: row;
  388. }
  389. }
  390. .isDisabled {
  391. color: #ccc;
  392. }
  393. .isSelect {
  394. background: #0097E0;
  395. color: #fff;
  396. }
  397. }
  398. .footBtn {
  399. position: fixed;
  400. bottom: 0;
  401. width: 100%;
  402. padding: 0.66rem 0 1.53rem 0;
  403. display: flex;
  404. background: #fff;
  405. .footBox {
  406. padding: 0 16px;
  407. display: flex;
  408. flex-flow: row;
  409. width: 100%;
  410. }
  411. .van-button {
  412. border-radius: 2rem;
  413. height: 2.5rem;
  414. line-height: 2.5rem;
  415. flex: 1;
  416. margin: 0 1rem;
  417. font-size: 1rem;
  418. }
  419. .van-button:nth-child(1) {
  420. width: 80%;
  421. color: #000;
  422. font-size: 14px;
  423. background: white;
  424. border: 2px solid #666 !important;
  425. border-radius: 40px;
  426. margin: 0 1rem;
  427. }
  428. .van-button:nth-child(2) {
  429. width: 80%;
  430. color: #fff;
  431. font-size: 14px;
  432. background: white;
  433. border-radius: 40px;
  434. margin: 0 1rem;
  435. border: none;
  436. background: -webkit-gradient(linear, right top, left top, from(#0068b7), to(#0097e0));
  437. background: linear-gradient(-90deg, #0068b7, #0097e0);
  438. }
  439. }
  440. </style>

组件引用

  1. <month-filter :defaultDate="monthDate.monthDefaultDate" :calendarshow="monthDate.monthCalendarShow" :isAllowSameDay="monthDate.isAllowSameDay" :yearLength="monthDate.yearLength" @closeCalendar="monthDate.monthCalendarShow = false" @confirmMonth="selectMonth" @resetCalendar="resetMonthCalendar">
  2. </month-filter>
  3. monthDate:{
  4. monthCalendarShow:false,
  5. yearLength:10,
  6. monthDefaultDate:[
  7. new Date(), new Date() //设置区间
  8. ],
  9. isAllowSameDay:true // 可选同一个月份
  10. },
  11. // 选择月份区间
  12. selectMonth(data) {
  13. if(data.length ==2 ){
  14. // 这里是获取的开始和结束的值
  15. }else if(data.length==1){
  16. if(data[0].text !="开始/结束"){
  17. Toast("请选择正确的月份区间");
  18. return;
  19. }else{
  20. // 这里是开始和结束的月份相同
  21. }
  22. }
  23. this.monthDate.monthCalendarShow = false;
  24. },
  25. resetMonthCalendar(){ //重置月份}

 按月区间选择组件还可优化,欢迎大家给出意见,谢谢!

效果图如下:

开始月份到结束月份

 开始结束月份可选当月:

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/97601
推荐阅读
相关标签
  

闽ICP备14008679号