123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- <template>
- <view class="zzx-calendar">
- <view class="calendar-heander">
- <text @click="daysPre()" class="text-xl text-gray" style="margin-right: 30px;"> < </text>
- {{timeStr}}
- <text class="text-xl text-gray" @click="daysNext()" style="margin-left: 30px;"> > </text>
- <view class="back-today" @click="goback" v-if="showBack" style="height: 48rpx;line-height: 48rpx;width: 70rpx;margin-top: 1.5rpx;font-size:24rpx;">
- 今日
- </view>
- </view>
- <view class="calendar-weeks margin-top-sm">
- <view class="calendar-week border-bottom-dashed border-top-dashed" v-for="(week, index) in weeks" :key="index">
- {{week}}
- </view>
- </view>
- <view class="calendar-content margin-top-sm">
- <swiper class="calendar-swiper" :style="{
- width: '100%',
- height: sheight
- }" :indicator-dots="false" :autoplay="false" :duration="duration" :current="current" @change="changeSwp" :circular="true">
- <swiper-item class="calendar-item" v-for="sitem in swiper" :key="sitem">
- <view class="calendar-days">
- <template v-if="sitem === current">
- <view class="calendar-day" v-for="(item,index) in days" :key="index"
- :class="{
- 'day-hidden': !item.show
- }" @click="clickItem(item)">
- <!-- 显示打卡的时间并设置样式 -->
- <view v-if="item.info" class="date solid" :class="[
- item.isToday ? todayClass : '',
- item.fullDate === selectedDate ? 'color-text color-bg' : '',
- item.info.id != null ? 'round line-blue ' : 'line-white text-black',
- ]">
- {{item.info.id != null || item.fullDate === selectedDate ? item.time.getDate() : item.time.getDate()}}
- </view>
-
- <!-- 显示其他的时间和当前时间 -->
- <view v-else
- class="date"
- :class="[item.isToday ? todayClass : '',item.fullDate === selectedDate ? 'color-text color-bg' : 'text-gray']"
- >
- {{item.time.getDate()}}
- </view>
-
- </view>
- </template>
- <template v-else>
- <template v-if="current - sitem === 1 || current-sitem ===-2">
- <view class="calendar-day" v-for="(item,index) in predays" :key="index"
- :class="{
- 'day-hidden': !item.show
- }">
- <view
- class="date"
- :class="[
- item.isToday ? todayClass : ''
- ]"
- >
- {{item.time.getDate()}}
- </view>
- </view>
- </template>
- <template v-else>
- <view class="calendar-day" v-for="(item,index) in nextdays" :key="index"
- :class="{
- 'day-hidden': !item.show
- }">
- <view
- class="date"
- :class="[
- item.isToday ? todayClass : ''
- ]"
- >
- {{item.time.getDate()}}
- </view>
- </view>
- </template>
-
- </template>
-
- </view>
- </swiper-item>
- </swiper>
- <view class="mode-change" @click="changeMode" style="position: relative;">
- <view style="position: absolute;right: -1px;bottom: -4px;">
- <image v-if="showImage" src="../../static/other/calendar.png" style="width: 40rpx;height: 40rpx;border-radius: 20rpx 0 20rpx 0;"></image>
- <image v-else="showImage" src="../../static/other/calendarShow.png" style="width: 40rpx;height: 40rpx;border-radius: 20rpx 0 20rpx 0;"></image>
- </view>
- </view>
- </view>
- </view>
- </template>
- <script>
- import {gegerateDates, dateEqual,formatDate} from './generateDates.js';
- export default {
- props: {
- duration: {
- type: Number,
- default: 500
- },
- dotList: {
- type: Array, /// 打点日期列表
- default() {
- return [
- ]
- }
- },
- showBack: {
- type: Boolean, // 是否返回今日
- default: false
- },
- todayClass: {
- type: String, // 今日的自定义样式class
- default: 'is-today'
- },
- checkedClass: {
- type: String, // 选中日期的样式class
- default: 'is-checked'
- },
- dotStyle: {
- type: Object, // 打点日期的自定义样式
- default() {
- return {
- background: '#c6c6c6'
- }
- }
- }
- },
- watch:{
- dotList: function(newvalue){
- const days = this.days.slice(0);
- newvalue.forEach(item => {
- const index = days.findIndex(ditem => ditem.fullDate === item.date);
- if (index > 0) {
- days[index].info = item;
- }
- });
- this.days = days;
- let isweek = false;
- isweek = !!this.days.find(item => item.fullDate === this.selectedDate);
- let d = new Date(this.currentYear, this.currentMonth - 1, this.currentDate)
- const sel = new Date(this.selectedDate.replace('-', '/').replace('-', '/'));
- const isMonth = sel.getFullYear() === this.currentYear && (sel.getMonth() + 1) === this.currentMonth;
- if ((this.selectedDate && isMonth) || isweek) {
- d = new Date(this.selectedDate.replace('-', '/').replace('-', '/'))
- }
- this.initDate(d)
- }
- },
- computed: {
- sheight() {
- // 根据年月判断有多少行
- // 判断该月有多少天
- let h = '70rpx';
- if (!this.weekMode) {
- const d = new Date(this.currentYear, this.currentMonth, 0);
- const days = d.getDate(); // 判断本月有多少天
- let day = new Date(d.setDate(1)).getDay();
- if (day === 0) {
- day = 7;
- }
- const pre = 8 - day;
- const rows = Math.ceil((days-pre) / 7) + 1;
- h = 70 * rows + 'rpx'
- }
- return h
- },
- timeStr() {
- let str = '';
- const d = new Date(this.currentYear, this.currentMonth - 1, this.currentDate);
- const y = d.getFullYear();
- const m = (d.getMonth()+1) <=9 ? `0${d.getMonth()+1}` : d.getMonth()+1;
- str = `${y}年${m}月`;
- return str;
- },
- predays() {
- let pres = [];
- if (this.weekMode) {
- const d = new Date(this.currentYear, this.currentMonth - 1,this.currentDate)
- d.setDate(d.getDate() - 7);
- pres = gegerateDates(d, 'week')
- } else {
- const d = new Date(this.currentYear, this.currentMonth - 2,1)
- pres = gegerateDates(d, 'month')
- }
- return pres;
- },
- nextdays() {
- let nexts = [];
- if (this.weekMode) {
- const d = new Date(this.currentYear, this.currentMonth - 1,this.currentDate)
- d.setDate(d.getDate() + 7);
- nexts = gegerateDates(d, 'week')
- } else {
- const d = new Date(this.currentYear, this.currentMonth,1)
- nexts = gegerateDates(d, 'month')
- }
- return nexts;
- }
- },
- data() {
- return {
- weeks: ['一', '二', '三', '四', '五', '六', '日'],
- current: 1,
- currentYear: '',
- currentMonth: '',
- currentDate: '',
- days: [],
- weekMode: true,
- showImage:true,
- swiper: [0,1,2],
- // dotList: [], // 打点的日期列表
- selectedDate: formatDate(new Date(), 'yyyy-MM-dd'),
- selectedItem:null,
- };
- },
- methods: {
- changeSwp(e) {
- // console.log(e);
- const pre = this.current;
- const current = e.target.current;
- /* 根据前一个减去目前的值我们可以判断是下一个月/周还是上一个月/周
- *current - pre === 1, -2时是下一个月/周
- *current -pre === -1, 2时是上一个月或者上一周
- */
- this.current = current;
- if (current - pre === 1 || current - pre === -2) {
- this.daysNext();
- } else {
- this.daysPre();
- }
- },
- // 初始化日历的方法
- initDate(cur) {
- let date = ''
- if (cur) {
- date = new Date(cur)
- } else {
- date = new Date()
- }
- this.currentDate = date.getDate() // 今日日期 几号
- this.currentYear = date.getFullYear() // 当前年份
- this.currentMonth = date.getMonth() + 1 // 当前月份
- this.currentWeek = date.getDay() === 0 ? 7 : date.getDay() // 1...6,0 // 星期几
- const nowY = new Date().getFullYear() // 当前年份
- const nowM = new Date().getMonth() + 1
- const nowD = new Date().getDate() // 今日日期 几号
- const nowW = new Date().getDay();
- // this.selectedDate = formatDate(new Date(), 'yyyy-MM-dd')
- this.days = [];
- let days = [];
- if (this.weekMode) {
- days = gegerateDates(date, 'week');
- // this.selectedDate = days[0].fullDate;
- } else {
- days = gegerateDates(date, 'month');
- // const sel = new Date(this.selectedDate.replace('-', '/').replace('-', '/'));
- // const isMonth = sel.getFullYear() === this.currentYear && (sel.getMonth() + 1) === this.currentMonth;
- // if(!isMonth) {
- // this.selectedDate = formatDate(new Date(this.currentYear, this.currentMonth-1,1), 'yyyy-MM-dd')
- // }
- }
- days.forEach(day => {
- const dot = this.dotList.find(item => {
- return dateEqual(item.date, day.fullDate);
- })
- if (dot) {
- day.info = dot;
- }
- })
- this.days = days;
- },
- // 上一个
- daysPre () {
- if (this.weekMode) {
- const d = new Date(this.currentYear, this.currentMonth - 1,this.currentDate);
- d.setDate(d.getDate() - 7);
- this.initDate(d);
- } else {
- const d = new Date(this.currentYear, this.currentMonth -2, 1);
- this.initDate(d);
- }
- },
- // 下一个
- daysNext () {
- if (this.weekMode) {
- const d = new Date(this.currentYear, this.currentMonth - 1,this.currentDate);
- d.setDate(d.getDate() + 7);
- this.initDate(d);
- } else {
- const d = new Date(this.currentYear, this.currentMonth, 1);
- this.initDate(d);
- }
- },
- changeMode() {
- const premode = this.weekMode;
- let isweek = false;
- this.showImage = !this.showImage;
- if (premode) {
- isweek = !!this.days.find(item => item.fullDate === this.selectedDate);
- }
- this.weekMode =!this.weekMode;
- let d = new Date(this.currentYear, this.currentMonth - 1, this.currentDate)
- const sel = new Date(this.selectedDate.replace('-', '/').replace('-', '/'));
- const isMonth = sel.getFullYear() === this.currentYear && (sel.getMonth() + 1) === this.currentMonth;
- if ((this.selectedDate && isMonth) || isweek) {
- d = new Date(this.selectedDate.replace('-', '/').replace('-', '/'))
- }
- this.initDate(d)
- },
- // 点击日期
- clickItem(e) {
- this.selectedDate = e.fullDate;
- this.selectedItem = e;
- this.$emit('selected-change', e);
- },
- goback() {
- const d = new Date();
- this.initDate(d);
- uni.$emit('clickToday');
- var time =this.intervalTime.getTime();
- var data ={"fullDate":time,isToday:true,show:true,"info":undefined};
- this.clickItem(data);
- }
- },
- created() {
- this.initDate();
- },
- mounted() {
- }
- }
- </script>
- <style lang="scss" scoped>
- .zzx-calendar {
- width: 100%;
- height: auto;
- .calendar-heander {
- text-align: center;
- height: 60upx;
- line-height: 60upx;
- position: relative;
- font-size: 30upx;
- padding-top: 10rpx;
- .back-today {
- position: absolute;
- right: 0;
- width: 120upx;
- height: 35upx;
- line-height: 35upx;
- font-size: 20upx;
- top: 15upx;
- border-radius: 15upx 0 0 15upx;
- color: #ffffff;
- background-color: #0A8CD5;
- }
- }
- .calendar-weeks {
- width: 100%;
- display: flex;
- flex-flow:row nowrap;
- height: 60upx;
- line-height: 60upx;
- justify-content: center;
- align-items: center;
- font-size: 30upx;
- .calendar-week {
- width: calc(100% / 7);
- height: 100%;
- text-align: center;
- }
- .border-bottom-dashed{
- border-bottom: 0.5px dashed #ddd;
- }
- .border-top-dashed{
- border-top: 0.5px dashed #ddd;
- }
- }
- swiper {
- width: 100%;
- height: 60upx;
- }
- .calendar-content {
- min-height: 60upx;
- }
- .calendar-swiper {
- min-height: 70upx;
- transition: height ease-out 0.3s;
- }
- .calendar-item {
- margin: 0;
- padding: 0;
- height: 100%;
- }
- .calendar-days {
- display: flex;
- flex-flow: row wrap;
- width: 100%;
- height: 100%;
- overflow: hidden;
- font-size: 28upx;
- .calendar-day {
- width: calc(100% / 7);
- height: 70upx;
- text-align: center;
- display: flex;
- flex-flow: column nowrap;
- justify-content: flex-start;
- align-items: center;
- }
- }
- .day-hidden {
- visibility: hidden;
- }
- .mode-change {
- display: flex;
- justify-content: center;
- margin-top:10upx;
- .mode-arrow-top {
- width: 0;
- height:0;
- border-left: 12upx solid transparent;
- border-right: 12upx solid transparent;
- border-bottom: 10upx solid #0A8CD5;
- }
- .mode-arrow-bottom {
- width: 0;
- height:0;
- border-left: 12upx solid transparent;
- border-right: 12upx solid transparent;
- border-top: 10upx solid #0A8CD5;
- }
- }
- .is-today {
- background: #0A8CD5 !important;
- // border: 1upx solid #FF6633;
- border-radius: 50%;
- color: white !important;
- }
- .is-checked {
- background: #FF6633;
- color: #ffffff;
- }
- .date {
- width: 50upx;
- height: 50upx;
- line-height: 50upx;
- margin: 0 auto;
- border-radius: 50upx;
- }
- .dot-show {
- margin-top:4upx;
- width: 10upx;
- height: 10upx;
- background: #c6c6c6;
- border-radius: 10upx;
- }
- .color-text{
- color: #0A8CD5;
- }
- .color-bg{
- background-color: #C6E6FF;
- }
- .text-gray{
- color:#9e9e9e;
- }
- .line-blue::after, .lines-blue::after {
- border-color: #C6E6FF;
- }
- .text-black{
- color: #101010;
- }
- }
- </style>
|