date.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. <template>
  2. <div class="calendar-wrapper">
  3. <!-- 月份变换区 -->
  4. <div class="header rowJcAc" v-if="headerBar">
  5. <!-- <div class="pre " @click="changeMonth('pre')">上个月</div> -->
  6. <div class="yearMonth">
  7. <div class="arrowIcon rowJcAc" @click="changeMonth('pre')" v-if="monthOpen">
  8. <i class="el-icon-arrow-left"></i>
  9. </div>
  10. {{y+'-'+formatNum(m)}}
  11. <div class="arrowIcon rowJcAc" @click="changeMonth('next')" v-if="monthOpen">
  12. <i class="el-icon-arrow-right"></i>
  13. </div>
  14. </div>
  15. <!-- <div class="next" @click="changeMonth('next')">下个月</div> -->
  16. </div>
  17. <!-- 星期区 -->
  18. <div class="week">
  19. <div class="week-day" v-for="(item,index) in weekDay" :key="index">{{item}}</div>
  20. </div>
  21. <!-- 日历显示区 -->
  22. <div :class="{hide : !monthOpen}" class="content">
  23. <div :style="{top:positionTop + 'px'}" class="days">
  24. <div class="item rowJcAc" v-for="(item,index) in dates" :key="index">
  25. <div class="day" @click="selectOne(item,$event)" :class="{
  26. choose:choose==`${item.year}-${item.month}-${item.date}`,
  27. todayChoose: isTodayChoose(item.year,item.month,item.date) ,
  28. nolm:!item.isCurM,
  29. today:isToday(item.year,item.month,item.date),
  30. notallowed:isFutureDay(item.year,item.month,item.date)
  31. }">
  32. <div class="markDay" v-if="isMarkDay(item.year,item.month,item.date)"
  33. :class="[choose==`${item.year}-${item.month}-${item.date}` ? 'markDayChoose':'markDayNoChoose']">
  34. </div>
  35. <p>{{Number(item.date)}}
  36. <div :class="calendarDaycount(item.year,item.month,item.date)"></div>
  37. </p>
  38. </div>
  39. </div>
  40. </div>
  41. </div>
  42. <!-- 伸缩按钮:待定 -->
  43. <!--<div class="bottomLine rowJcAc" v-if="collapsible" @click="toggle">-->
  44. <!--<div></div>-->
  45. <!--</div>-->
  46. <!-- 伸缩按钮:待定 -->
  47. <!-- <img
  48. src="https://i.loli.net/2020/07/16/2MmZsucVTlRjSwK.png"
  49. mode="scaleToFill"
  50. v-if="collapsible"
  51. @click="toggle"
  52. class="weektoggle"
  53. :class="{ down: monthOpen }"
  54. /> -->
  55. <div class="date-what">
  56. <div class="d-w-info">
  57. <div class="d-w-i-color d-state-zc"></div>
  58. 正常
  59. </div>
  60. <div class="d-w-info">
  61. <div class="d-w-i-color d-state-t10"></div>
  62. ≤10
  63. </div>
  64. <div class="d-w-info">
  65. <div class="d-w-i-color d-state-b10"></div>
  66. >10
  67. </div>
  68. </div>
  69. </div>
  70. </template>
  71. <script>
  72. import Cookies from 'js-cookie'
  73. import {
  74. selectByMenuId
  75. } from '@/api/forest'
  76. import {
  77. getEventByCalendar
  78. } from '@/api/forest'
  79. export default {
  80. name: "ren-calendar",
  81. props: {
  82. // 星期几为第一天(0为星期日)
  83. weekstart: {
  84. type: Number,
  85. default: 0,
  86. },
  87. // 标记的日期
  88. markDays: {
  89. type: Array,
  90. default: () => {
  91. return [];
  92. },
  93. },
  94. //是否展示月份切换按钮
  95. headerBar: {
  96. type: Boolean,
  97. default: true,
  98. },
  99. // 是否展开
  100. open: {
  101. type: Boolean,
  102. default: true,
  103. },
  104. //是否可收缩
  105. collapsible: {
  106. type: Boolean,
  107. default: true,
  108. },
  109. //未来日期是否不可点击
  110. disabledAfter: {
  111. type: Boolean,
  112. default: true,
  113. },
  114. // 默认选中日期
  115. selectDate: {
  116. type: String,
  117. default: null
  118. },
  119. //日历点击是否可用
  120. canSelectDate: {
  121. type: Boolean,
  122. default: true,
  123. },
  124. },
  125. data() {
  126. return {
  127. weektext: ["日", "一", "二", "三", "四", "五", "六"],
  128. y: new Date().getFullYear(), // 年
  129. m: new Date().getMonth() + 1, // 月
  130. dates: [], // 当前月的日期数据
  131. positionTop: 0,
  132. monthOpen: false,
  133. choose: "",
  134. isCurM: true,
  135. eventByCalendarList:[]
  136. };
  137. },
  138. created() {
  139. setTimeout(() => {
  140. this.monthDay(this.y, this.m);
  141. }, 1000)
  142. // !this.open && this.toggle();
  143. },
  144. watch: {
  145. // 点击返回今天
  146. selectDate() {
  147. if (this.selectDate) {
  148. this.choose = this.selectDate
  149. this.y = Number(this.selectDate.split('-')[0])
  150. this.m = Number(this.selectDate.split('-')[1])
  151. this.monthDay(this.y, this.m);
  152. if (!this.monthOpen) {
  153. let index = -1;
  154. this.dates.forEach((i, x) => {
  155. this.isChoose(i.year, i.month, i.date) && (index = x);
  156. });
  157. this.positionTop = -((Math.ceil((index + 1) / 7) || 1) - 1) * 42;
  158. }
  159. }
  160. },
  161. m() {
  162. this.$emit('changeMonth', {
  163. year: this.y,
  164. month: this.m
  165. })
  166. },
  167. dates() {
  168. this.$emit('changeDates', {
  169. dates: this.dates
  170. })
  171. }
  172. },
  173. mounted() {
  174. if (this.selectDate) {
  175. this.choose = this.selectDate
  176. this.y = this.selectDate.split('-')[0]
  177. this.m = this.selectDate.split('-')[1]
  178. } else {
  179. this.choose = this.getToday().date;
  180. }
  181. this.toggle()
  182. },
  183. computed: {
  184. // 顶部星期栏
  185. weekDay() {
  186. return this.weektext
  187. .slice(this.weekstart)
  188. .concat(this.weektext.slice(0, this.weekstart));
  189. },
  190. },
  191. methods: {
  192. // 标记日期状态颜色
  193. calendarDaycount(y, m, d) {
  194. let day=y + "-" + this.formatNum(m) + "-" + this.formatNum(d)
  195. if(new Date(day)<new Date()){
  196. if(this.eventByCalendarList!=null&&this.eventByCalendarList.length>0){
  197. for (let i = 0; i < this.eventByCalendarList.length; i++) {
  198. if(this.eventByCalendarList[i].day==day){
  199. if(this.eventByCalendarList[i].daycount>0&&this.eventByCalendarList[i].daycount<=10){
  200. return "date-state-pointer d-state-t10"
  201. }else if(this.eventByCalendarList[i].daycount>10){
  202. return "date-state-pointer d-state-b10"
  203. }else{
  204. return "date-state-pointer d-state-zc"
  205. }
  206. }
  207. }
  208. }else{
  209. return "date-state-pointer d-state-b10"
  210. }
  211. }else{
  212. return "date-state-pointer";
  213. }
  214. },
  215. formatNum(num) {
  216. let res = Number(num);
  217. return res < 10 ? "0" + res : res;
  218. },
  219. getToday() {
  220. let date = new Date();
  221. let y = date.getFullYear();
  222. let m = date.getMonth();
  223. let d = date.getDate();
  224. let week = new Date().getDay();
  225. let weekText = ["日", "一", "二", "三", "四", "五", "六"];
  226. let formatWeek = "星期" + weekText[week];
  227. let today = {
  228. date: y + "-" + this.formatNum(m + 1) + "-" + this.formatNum(d),
  229. week: formatWeek,
  230. };
  231. return today;
  232. },
  233. // 获得某月的天数
  234. getMonthDays(y,month){
  235. let monthStartDate = new Date(y, month, 1);
  236. let monthEndDate = new Date(y, month + 1, 1);
  237. let days = (monthEndDate - monthStartDate)/(1000 * 60 * 60 * 24);
  238. console.log(days)
  239. return days;
  240. },
  241. // 获取当前月份数据
  242. async monthDay(y, month) {
  243. let eventType = []
  244. let eventTypeDl = []
  245. let req = await selectByMenuId({
  246. menuId: '41'
  247. })
  248. req.data.forEach(item => {
  249. eventType.push(item.eventTypeXl)
  250. eventTypeDl.push(item.eventType)
  251. })
  252. let yearMonth = []
  253. let day = new Date(y, month, 0).getDate();
  254. for (let i = 1; i <= day; i++) {
  255. let days = "";
  256. if (i < 10) {
  257. days = "0" + i;
  258. } else {
  259. days = i;
  260. }
  261. let aDate = y + "-" + this.formatNum(month) + "-" + days;
  262. yearMonth.push(aDate);
  263. }
  264. let param = {
  265. eventTypeId: eventType,
  266. eventTypeIdDl: eventTypeDl,
  267. yearMonth: yearMonth
  268. }
  269. // await getEventByCalendar(param).then(res => {
  270. // //获取日历颜色状态
  271. // this.eventByCalendarList=res.data;
  272. // })
  273. this.dates = [];
  274. let m = Number(month);
  275. let firstDayOfMonth = new Date(y, m - 1, 1).getDay(); // 当月第一天星期几
  276. let lastDateOfMonth = new Date(y, m, 0).getDate(); // 当月最后一天
  277. let lastDayOfLastMonth = new Date(y, m - 1, 0).getDate(); // 上一月的最后一天
  278. let weekstart = this.weekstart == 7 ? 0 : this.weekstart;
  279. let startDay = (() => {
  280. // 周初有几天是上个月的
  281. if (firstDayOfMonth == weekstart) {
  282. return 0;
  283. } else if (firstDayOfMonth > weekstart) {
  284. return firstDayOfMonth - weekstart;
  285. } else {
  286. return 7 - weekstart + firstDayOfMonth;
  287. }
  288. })();
  289. let endDay = 7 - ((startDay + lastDateOfMonth) % 7); // 结束还有几天是下个月的
  290. for (let i = 1; i <= startDay; i++) {
  291. this.dates.push({
  292. date: this.formatNum(lastDayOfLastMonth - startDay + i),
  293. day: weekstart + i - 1 || 7,
  294. month: m - 1 >= 1 ? this.formatNum(m - 1) : 12,
  295. year: m - 1 >= 1 ? y : y - 1,
  296. isCurM: false
  297. });
  298. }
  299. for (let j = 1; j <= lastDateOfMonth; j++) {
  300. this.dates.push({
  301. date: this.formatNum(j),
  302. day: (j % 7) + firstDayOfMonth - 1 || 7,
  303. month: this.formatNum(m),
  304. year: y,
  305. isCurM: true, //是否当前月份
  306. });
  307. }
  308. for (let k = 1; k <= endDay; k++) {
  309. this.dates.push({
  310. date: this.formatNum(k),
  311. day: (lastDateOfMonth + startDay + weekstart + k - 1) % 7 || 7,
  312. month: m + 1 <= 12 ? this.formatNum(m + 1) : 1,
  313. year: m + 1 <= 12 ? y : y + 1,
  314. isCurM: false
  315. });
  316. }
  317. },
  318. isFutureDay(y, m, d) {
  319. //是否未来日期
  320. let ymd = `${y}/${m}/${d}`;
  321. let formatDY = new Date(ymd.replace(/-/g, "/"));
  322. let showTime = formatDY.getTime();
  323. let curTime = new Date().getTime();
  324. if (showTime > curTime) {
  325. return true;
  326. } else {
  327. return false;
  328. }
  329. },
  330. // 标记日期
  331. isMarkDay(y, m, d) {
  332. let flag = false;
  333. for (let i = 0; i < this.markDays.length; i++) {
  334. let dy = `${y}-${m}-${d}`;
  335. if (this.markDays[i] == dy) {
  336. flag = true;
  337. break;
  338. }
  339. }
  340. return flag;
  341. },
  342. isToday(y, m, d) {
  343. let checkD = y + "-" + m + "-" + d;
  344. let today = this.getToday().date;
  345. if (checkD == today) {
  346. return true;
  347. } else {
  348. return false;
  349. }
  350. },
  351. isTodayChoose(year, month, day) {
  352. let checkD = year + "-" + month + "-" + day;
  353. let today = this.getToday().date;
  354. return this.choose == `${year}-${month}-${day}` && checkD == today
  355. },
  356. isChoose(y, m, d) {
  357. let checkD = y + "-" + m + "-" + d;
  358. return this.choose == checkD
  359. },
  360. // 展开收起
  361. toggle() {
  362. this.monthOpen = !this.monthOpen;
  363. if (this.monthOpen) {
  364. this.positionTop = 0;
  365. } else {
  366. let index = -1;
  367. this.dates.forEach((i, x) => {
  368. this.isChoose(i.year, i.month, i.date) && (index = x);
  369. });
  370. this.positionTop = -((Math.ceil((index + 1) / 7) || 1) - 1) * 42;
  371. }
  372. },
  373. // 点击回调
  374. selectOne(i) {
  375. if (!this.canSelectDate) {
  376. this.$message.warning("您点击的太快了,请慢一点!");
  377. return false;
  378. }
  379. let markDay = this.isMarkDay(i.year, i.month, i.date);
  380. let date = `${i.year}-${i.month}-${i.date}`;
  381. let selectD = new Date(date).getTime();
  382. let curTime = new Date().getTime();
  383. let week = new Date(date).getDay();
  384. let weekText = ["日", "一", "二", "三", "四", "五", "六"];
  385. let formatWeek = "星期" + weekText[week];
  386. let response = {
  387. date: date,
  388. week: formatWeek,
  389. };
  390. // if (!i.isCurM) {
  391. // // console.log('不在当前月范围内');
  392. // return false;
  393. // }
  394. if (selectD > curTime) {
  395. if (this.disabledAfter) {
  396. console.log("未来日期不可选");
  397. return false;
  398. } else {
  399. this.choose = date;
  400. if (markDay && i.isCurM) {
  401. this.$emit("onDayClick", response);
  402. }
  403. }
  404. } else {
  405. this.choose = date;
  406. if (i.isCurM) {
  407. this.$emit("onDayClick", response);
  408. } else {
  409. this.y = i.year
  410. this.m = i.month
  411. this.monthDay(this.y, this.m);
  412. this.$emit("onDayClick", response);
  413. }
  414. }
  415. this.$emit("setDate", response);
  416. // console.log(response);
  417. this.$emit("selectDay", date);
  418. },
  419. //改变年月
  420. changYearMonth(y, m) {
  421. this.monthDay(y, m);
  422. this.y = y;
  423. this.m = m;
  424. },
  425. changeMonth(type) {
  426. this.y = parseInt(this.y)
  427. this.m = parseInt(this.m)
  428. if (type == "pre") {
  429. if (this.m + 1 == 2) {
  430. this.m = 12;
  431. this.y = parseInt(this.y) - 1;
  432. } else {
  433. this.m = this.m - 1;
  434. }
  435. } else {
  436. if (this.m + 1 == 13) {
  437. this.m = 1;
  438. this.y = this.y + 1;
  439. } else {
  440. this.m = this.m + 1;
  441. }
  442. }
  443. this.monthDay(this.y, this.m);
  444. // this.$emit("changeMonth");
  445. },
  446. },
  447. };
  448. </script>
  449. <style lang="scss" scoped>
  450. .notallowed{
  451. cursor: not-allowed !important
  452. }
  453. @import '@/assets/styles/base.scss';
  454. //状态
  455. .d-state-zc {
  456. background-color: $date-state1;
  457. }
  458. .d-state-t10 {
  459. background-color: $date-state2;
  460. }
  461. .d-state-b10 {
  462. background-color: $date-state3;
  463. }
  464. .bottomLine {
  465. padding-top: 12px;
  466. padding-bottom: 12px;
  467. >div {
  468. width: 32px;
  469. height: 3px;
  470. background: none;
  471. border-radius: 2px;
  472. }
  473. }
  474. .nolm {
  475. color: #2b4376 !important;
  476. }
  477. .calendar-wrapper {
  478. text-align: center;
  479. .header {
  480. .yearMonth {
  481. font-size: 16px;
  482. line-height: 23px;
  483. color: $inBlue;
  484. margin: 0 32px;
  485. display: flex;
  486. justify-content: center;
  487. }
  488. }
  489. .week {
  490. display: flex;
  491. justify-content: space-around;
  492. width: 100%;
  493. align-items: center;
  494. height: 19px;
  495. line-height: 19px;
  496. font-size: 13px;
  497. font-weight: 600;
  498. margin-top: 5px;
  499. color: $inBlue;
  500. }
  501. .content {
  502. position: relative;
  503. transition: height 0.4s ease;
  504. .days {
  505. transition: top 0, 3s;
  506. display: flex;
  507. align-items: center;
  508. flex-wrap: wrap;
  509. position: relative;
  510. font-size: 14px;
  511. line-height: 19px;
  512. .item {
  513. position: relative;
  514. display: block;
  515. height: 33px;
  516. line-height: 33px;
  517. width: calc(100% / 7);
  518. .day {
  519. font-style: normal;
  520. display: inline-block;
  521. position: relative;
  522. vertical-align: middle;
  523. width: 30px;
  524. font-weight: 500;
  525. height: 30px;
  526. line-height: 30px;
  527. overflow: hidden;
  528. border-radius: 50%;
  529. cursor: pointer;
  530. color: #3d8bbc;
  531. font-size: 11px;
  532. .date-state-pointer {
  533. position: absolute;
  534. bottom: 1px;
  535. left: 50%;
  536. transform: translateX(-50%);
  537. width: 4px;
  538. height: 4px;
  539. border-radius: 5px;
  540. }
  541. &.choose {
  542. background-color: #3a4350;
  543. color: #fff !important;
  544. }
  545. &.todayChoose {
  546. background-color: #1A7AF8 !important;
  547. color: #fff;
  548. }
  549. }
  550. .notSigned {
  551. font-style: normal;
  552. width: 8rpx;
  553. height: 8rpx;
  554. background: #fa7268;
  555. border-radius: 10rpx;
  556. position: absolute;
  557. left: 50%;
  558. bottom: 0;
  559. pointer-events: none;
  560. }
  561. .today {
  562. color: #ffffff;
  563. background-color: #3c56b5;
  564. }
  565. .markDayNoChoose {
  566. background: #1A7AF8;
  567. }
  568. .markDayChoose {
  569. background: #fff;
  570. }
  571. .markDay {
  572. width: 4px;
  573. height: 4px;
  574. border-radius: 50%;
  575. position: absolute;
  576. left: 16px;
  577. bottom: 4px;
  578. pointer-events: none;
  579. }
  580. }
  581. }
  582. }
  583. .hide {
  584. height: 42px !important;
  585. }
  586. .arrowIcon {
  587. width: 40px;
  588. height: 23px;
  589. cursor: pointer;
  590. margin: 0 5px;
  591. }
  592. .arrowIcon:hover {
  593. background-color: #202e62;
  594. i {
  595. color: #fff;
  596. }
  597. }
  598. // .weektoggle {
  599. // width: 85px;
  600. // height: 32px;
  601. // position: relative;
  602. // left: 50%;
  603. // margin-left: -42px;
  604. // bottom: -42px;
  605. // &.down {
  606. // transform: rotate(180deg);
  607. // bottom: 0;
  608. // }
  609. // }
  610. .date-what{
  611. width: 100%;
  612. color: $inBlue;
  613. display: flex;
  614. align-items: center;
  615. padding:.4rem 1rem ;
  616. position: absolute;
  617. bottom: 0;
  618. justify-content: space-between;
  619. .d-w-info{
  620. display: flex;
  621. align-items: center;
  622. .d-w-i-color{
  623. width: 1rem;
  624. height: 1rem;
  625. margin-right: .5rem;
  626. border-radius: .2rem;
  627. }
  628. }
  629. }
  630. }
  631. </style>