成品如图所示,具体代码见下方
编写日历页面
<!--components/calendar/calendar.wxml-->
<view class="calendar">
<view class="title flex">
<view class="flex">
<picker value="{{selectDay.year+'-'+(selectDay.month+1)}}" bindchange="editMonth" mode="date" fields="month" class="year-month">{{selectDay.year}}.{{selectDay.month>8?selectDay.month+1:"0"+(selectDay.month+1)}}</picker>
<view class="last-icon" bindtap="lastMonth"> </view>
<view class="next-icon" bindtap="nextMonth"> </view>
</view>
<view catchtap="openChange" class="flex open">
<view>{{open?"收起":"展开"}}</view>
</view>
</view>
<!-- 日历头部 -->
<view class="flex-around calendar-week">
<view class="view">日</view>
<view class="view">一</view>
<view class="view">二</view>
<view class="view">三</view>
<view class="view">四</view>
<view class="view">五</view>
<view class="view">六</view>
</view>
<!-- 日历主体 -->
<view class="calendar-main">
<view class="date-group" style="height:{{open? dateList.length/7*72 : 72}}rpx;">
<view class="flex-start flex-wrap date-transform" style="transform: translateY({{open?0:-72*transform}}rpx);">
<view wx:for="{{dateList}}" wx:key="dateList" class="day">
<view class="bg {{(item.year === selectDay.year && item.month === selectDay.month) ?'': 'other-month'}} {{item.dateString === selectDay.dateString?'select':''}}" catchtap="selectChange" data-date="{{item.date}}" data-year="{{item.year}}" data-month="{{item.month}}" data-date-string="{{item.dateString}}">
{{item.date}}
</view>
<view class="spot" wx:if="{{item.spot}}"></view>
</view>
</view>
</view>
</view>
</view>
编写日历样式
/* components/calendar/calendar.wxss */
.flex {
display: flex;
justify-content: space-between;
align-items: center;
}
.flex-start {
display: flex;
justify-content: flex-start;
align-items: center;
}
.flex-center {
display: flex;
justify-content: center;
align-items: center;
}
.flex-end {
display: flex;
justify-content: flex-end;
align-items: center;
}
.flex-around {
display: flex;
justify-content: space-around;
align-items: center;
}
.flex1 {
flex: 1;
}
.flex-wrap {
flex-wrap: wrap;
}
.align-start {
align-items: flex-start;
}
.align-end {
align-items: flex-end;
}
.align-stretch {
align-items: stretch;
}
.calendar {
background-color: #fff;
}
.calendar .title {
font-size: 40rpx;
color: #333;
padding: 30rpx;
line-height: 60rpx;
}
.calendar .title .year-month {
margin-right: 20rpx;
}
.calendar .title .last-icon {
width: 0;
height: 0;
border-right: 24rpx solid #999;
border-top: 12rpx solid transparent;
border-bottom: 12rpx solid transparent;
margin-left: 10rpx;
}
.calendar .title .next-icon {
width: 0;
height: 0;
border-left: 24rpx solid #999;
border-top: 12rpx solid transparent;
border-bottom: 12rpx solid transparent;
margin-left: 40rpx;
}
.calendar .title .open {
background-color: #f6f6f6;
color: #999;
font-size: 22rpx;
line-height: 36rpx;
border-radius: 18rpx;
padding: 0 14rpx;
}
.calendar .calendar-week {
line-height: 40rpx;
padding: 0 25rpx;
font-size: 28rpx;
color: #999;
}
.calendar .calendar-week .view {
width: 100rpx;
text-align: center;
}
.calendar .calendar-main {
padding: 30rpx 25rpx;
}
.calendar .calendar-main .date-group {
transition: all 0.3s;
overflow: hidden;
}
.calendar .calendar-main .date-transform {
transition: all 0.3s;
}
.calendar .calendar-main .day {
position: relative;
width: 100rpx;
color: #666;
text-align: center;
height: 72rpx;
}
.calendar .calendar-main .day .bg {
height: 56rpx;
line-height: 56rpx;
font-size: 28rpx;
color: #333;
font-weight: bold;
}
.calendar .calendar-main .day .select {
width: 56rpx;
border-radius: 50%;
text-align: center;
color: #fff;
background: #409eff;
margin: 0 auto;
}
.calendar .calendar-main .day .other-month {
color: #ccc;
}
.calendar .calendar-main .day .spot {
width: 8rpx;
height: 8rpx;
background-color: #409eff;
border-radius: 50%;
margin: 6rpx auto 0;
}
编写js
! function (t, e) {
"object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).dayjs = e()
}(this, (function () {
"use strict";
var t = 1e3,
e = 6e4,
n = 36e5,
r = "millisecond",
i = "second",
s = "minute",
u = "hour",
a = "day",
o = "week",
f = "month",
h = "quarter",
c = "year",
d = "date",
$ = "Invalid Date",
l = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,
y = /\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,
M = {
name: "en",
weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_")
},
m = function (t, e, n) {
var r = String(t);
return !r || r.length >= e ? t : "" + Array(e + 1 - r.length).join(n) + t
},
g = {
s: m,
z: function (t) {
var e = -t.utcOffset(),
n = Math.abs(e),
r = Math.floor(n / 60),
i = n % 60;
return (e <= 0 ? "+" : "-") + m(r, 2, "0") + ":" + m(i, 2, "0")
},
m: function t(e, n) {
if (e.date() < n.date()) return -t(n, e);
var r = 12 * (n.year() - e.year()) + (n.month() - e.month()),
i = e.clone().add(r, f),
s = n - i < 0,
u = e.clone().add(r + (s ? -1 : 1), f);
return +(-(r + (n - i) / (s ? i - u : u - i)) || 0)
},
a: function (t) {
return t < 0 ? Math.ceil(t) || 0 : Math.floor(t)
},
p: function (t) {
return {
M: f,
y: c,
w: o,
d: a,
D: d,
h: u,
m: s,
s: i,
ms: r,
Q: h
} [t] || String(t || "").toLowerCase().replace(/s$/, "")
},
u: function (t) {
return void 0 === t
}
},
v = "en",
D = {};
D[v] = M;
var p = function (t) {
return t instanceof _
},
S = function t(e, n, r) {
var i;
if (!e) return v;
if ("string" == typeof e) {
var s = e.toLowerCase();
D[s] && (i = s), n && (D[s] = n, i = s);
var u = e.split("-");
if (!i && u.length > 1) return t(u[0])
} else {
var a = e.name;
D[a] = e, i = a
}
return !r && i && (v = i), i || !r && v
},
w = function (t, e) {
if (p(t)) return t.clone();
var n = "object" == typeof e ? e : {};
return n.date = t, n.args = arguments, new _(n)
},
O = g;
O.l = S, O.i = p, O.w = function (t, e) {
return w(t, {
locale: e.$L,
utc: e.$u,
x: e.$x,
$offset: e.$offset
})
};
var _ = function () {
function M(t) {
this.$L = S(t.locale, null, !0), this.parse(t)
}
var m = M.prototype;
return m.parse = function (t) {
this.$d = function (t) {
var e = t.date,
n = t.utc;
if (null === e) return new Date(NaN);
if (O.u(e)) return new Date;
if (e instanceof Date) return new Date(e);
if ("string" == typeof e && !/Z$/i.test(e)) {
var r = e.match(l);
if (r) {
var i = r[2] - 1 || 0,
s = (r[7] || "0").substring(0, 3);
return n ? new Date(Date.UTC(r[1], i, r[3] || 1, r[4] || 0, r[5] || 0, r[6] || 0, s)) : new Date(r[1], i, r[3] || 1, r[4] || 0, r[5] || 0, r[6] || 0, s)
}
}
return new Date(e)
}(t), this.$x = t.x || {}, this.init()
}, m.init = function () {
var t = this.$d;
this.$y = t.getFullYear(), this.$M = t.getMonth(), this.$D = t.getDate(), this.$W = t.getDay(), this.$H = t.getHours(), this.$m = t.getMinutes(), this.$s = t.getSeconds(), this.$ms = t.getMilliseconds()
}, m.$utils = function () {
return O
}, m.isValid = function () {
return !(this.$d.toString() === $)
}, m.isSame = function (t, e) {
var n = w(t);
return this.startOf(e) <= n && n <= this.endOf(e)
}, m.isAfter = function (t, e) {
return w(t) < this.startOf(e)
}, m.isBefore = function (t, e) {
return this.endOf(e) < w(t)
}, m.$g = function (t, e, n) {
return O.u(t) ? this[e] : this.set(n, t)
}, m.unix = function () {
return Math.floor(this.valueOf() / 1e3)
}, m.valueOf = function () {
return this.$d.getTime()
}, m.startOf = function (t, e) {
var n = this,
r = !!O.u(e) || e,
h = O.p(t),
$ = function (t, e) {
var i = O.w(n.$u ? Date.UTC(n.$y, e, t) : new Date(n.$y, e, t), n);
return r ? i : i.endOf(a)
},
l = function (t, e) {
return O.w(n.toDate()[t].apply(n.toDate("s"), (r ? [0, 0, 0, 0] : [23, 59, 59, 999]).slice(e)), n)
},
y = this.$W,
M = this.$M,
m = this.$D,
g = "set" + (this.$u ? "UTC" : "");
switch (h) {
case c:
return r ? $(1, 0) : $(31, 11);
case f:
return r ? $(1, M) : $(0, M + 1);
case o:
var v = this.$locale().weekStart || 0,
D = (y < v ? y + 7 : y) - v;
return $(r ? m - D : m + (6 - D), M);
case a:
case d:
return l(g + "Hours", 0);
case u:
return l(g + "Minutes", 1);
case s:
return l(g + "Seconds", 2);
case i:
return l(g + "Milliseconds", 3);
default:
return this.clone()
}
}, m.endOf = function (t) {
return this.startOf(t, !1)
}, m.$set = function (t, e) {
var n, o = O.p(t),
h = "set" + (this.$u ? "UTC" : ""),
$ = (n = {}, n[a] = h + "Date", n[d] = h + "Date", n[f] = h + "Month", n[c] = h + "FullYear", n[u] = h + "Hours", n[s] = h + "Minutes", n[i] = h + "Seconds", n[r] = h + "Milliseconds", n)[o],
l = o === a ? this.$D + (e - this.$W) : e;
if (o === f || o === c) {
var y = this.clone().set(d, 1);
y.$d[$](l), y.init(), this.$d = y.set(d, Math.min(this.$D, y.daysInMonth())).$d
} else $ && this.$d[$](l);
return this.init(), this
}, m.set = function (t, e) {
return this.clone().$set(t, e)
}, m.get = function (t) {
return this[O.p(t)]()
}, m.add = function (r, h) {
var d, $ = this;
r = Number(r);
var l = O.p(h),
y = function (t) {
var e = w($);
return O.w(e.date(e.date() + Math.round(t * r)), $)
};
if (l === f) return this.set(f, this.$M + r);
if (l === c) return this.set(c, this.$y + r);
if (l === a) return y(1);
if (l === o) return y(7);
var M = (d = {}, d[s] = e, d[u] = n, d[i] = t, d)[l] || 1,
m = this.$d.getTime() + r * M;
return O.w(m, this)
}, m.subtract = function (t, e) {
return this.add(-1 * t, e)
}, m.format = function (t) {
var e = this,
n = this.$locale();
if (!this.isValid()) return n.invalidDate || $;
var r = t || "YYYY-MM-DDTHH:mm:ssZ",
i = O.z(this),
s = this.$H,
u = this.$m,
a = this.$M,
o = n.weekdays,
f = n.months,
h = function (t, n, i, s) {
return t && (t[n] || t(e, r)) || i[n].slice(0, s)
},
c = function (t) {
return O.s(s % 12 || 12, t, "0")
},
d = n.meridiem || function (t, e, n) {
var r = t < 12 ? "AM" : "PM";
return n ? r.toLowerCase() : r
},
l = {
YY: String(this.$y).slice(-2),
YYYY: this.$y,
M: a + 1,
MM: O.s(a + 1, 2, "0"),
MMM: h(n.monthsShort, a, f, 3),
MMMM: h(f, a),
D: this.$D,
DD: O.s(this.$D, 2, "0"),
d: String(this.$W),
dd: h(n.weekdaysMin, this.$W, o, 2),
ddd: h(n.weekdaysShort, this.$W, o, 3),
dddd: o[this.$W],
H: String(s),
HH: O.s(s, 2, "0"),
h: c(1),
hh: c(2),
a: d(s, u, !0),
A: d(s, u, !1),
m: String(u),
mm: O.s(u, 2, "0"),
s: String(this.$s),
ss: O.s(this.$s, 2, "0"),
SSS: O.s(this.$ms, 3, "0"),
Z: i
};
return r.replace(y, (function (t, e) {
return e || l[t] || i.replace(":", "")
}))
}, m.utcOffset = function () {
return 15 * -Math.round(this.$d.getTimezoneOffset() / 15)
}, m.diff = function (r, d, $) {
var l, y = O.p(d),
M = w(r),
m = (M.utcOffset() - this.utcOffset()) * e,
g = this - M,
v = O.m(this, M);
return v = (l = {}, l[c] = v / 12, l[f] = v, l[h] = v / 3, l[o] = (g - m) / 6048e5, l[a] = (g - m) / 864e5, l[u] = g / n, l[s] = g / e, l[i] = g / t, l)[y] || g, $ ? v : O.a(v)
}, m.daysInMonth = function () {
return this.endOf(f).$D
}, m.$locale = function () {
return D[this.$L]
}, m.locale = function (t, e) {
if (!t) return this.$L;
var n = this.clone(),
r = S(t, e, !0);
return r && (n.$L = r), n
}, m.clone = function () {
return O.w(this.$d, this)
}, m.toDate = function () {
return new Date(this.valueOf())
}, m.toJSON = function () {
return this.isValid() ? this.toISOString() : null
}, m.toISOString = function () {
return this.$d.toISOString()
}, m.toString = function () {
return this.$d.toUTCString()
}, M
}(),
T = _.prototype;
return w.prototype = T, [
["$ms", r],
["$s", i],
["$m", s],
["$H", u],
["$W", a],
["$M", f],
["$y", c],
["$D", d]
].forEach((function (t) {
T[t[1]] = function (e) {
return this.$g(e, t[0], t[1])
}
})), w.extend = function (t, e) {
return t.$i || (t(e, _, w), t.$i = !0), w
}, w.locale = S, w.isDayjs = p, w.unix = function (t) {
return w(1e3 * t)
}, w.en = D[v], w.Ls = D, w.p = {}, w
}));