mali-applet-ui 1.0.155 → 1.0.157
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import XEUtils from 'xe-utils'
|
|
2
|
+
|
|
3
|
+
// 判断是否是闰年,
|
|
4
|
+
const isLeapYear = (year) => {
|
|
5
|
+
if (year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0)) {
|
|
6
|
+
return true
|
|
7
|
+
}
|
|
8
|
+
return false
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// 获取当前月份的总天数
|
|
12
|
+
const totalDaysByDate = (date) => {
|
|
13
|
+
const today = new Date(date)
|
|
14
|
+
const year = today.getFullYear()
|
|
15
|
+
const month = today.getMonth() + 1
|
|
16
|
+
let monthDay = 31
|
|
17
|
+
switch (month) {
|
|
18
|
+
case 1: monthDay = 31; break
|
|
19
|
+
case 2:
|
|
20
|
+
if (isLeapYear(year)) { monthDay = 29 } else { monthDay = 28 }
|
|
21
|
+
break
|
|
22
|
+
case 3: monthDay = 31; break
|
|
23
|
+
case 4: monthDay = 30; break
|
|
24
|
+
case 5: monthDay = 31; break
|
|
25
|
+
case 6: monthDay = 30; break
|
|
26
|
+
case 7: monthDay = 31; break
|
|
27
|
+
case 8: monthDay = 31; break
|
|
28
|
+
case 9: monthDay = 30; break
|
|
29
|
+
case 10: monthDay = 31; break
|
|
30
|
+
case 11: monthDay = 30; break
|
|
31
|
+
case 12: monthDay = 31; break
|
|
32
|
+
}
|
|
33
|
+
return monthDay
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 获取当前月份数据
|
|
37
|
+
const getDaysByDate = (date) => {
|
|
38
|
+
// 获取总天数
|
|
39
|
+
const totalDays = totalDaysByDate(date)
|
|
40
|
+
const days = []
|
|
41
|
+
const thisMonth = new Date(date)
|
|
42
|
+
const todayDate = new Date()
|
|
43
|
+
const today = XEUtils.toDateString(todayDate, 'yyyy-MM-dd')
|
|
44
|
+
for (let i = 1; i <= totalDays; i++) {
|
|
45
|
+
thisMonth.setDate(i)
|
|
46
|
+
const dateFormat = {
|
|
47
|
+
date: XEUtils.toDateString(thisMonth, 'yyyy-MM-dd'),
|
|
48
|
+
day: XEUtils.toDateString(thisMonth, 'd'),
|
|
49
|
+
statusList: []
|
|
50
|
+
}
|
|
51
|
+
if (dateFormat.date === today) {
|
|
52
|
+
dateFormat.isToday = true
|
|
53
|
+
} else {
|
|
54
|
+
if (todayDate.getTime() < thisMonth.getTime()) {
|
|
55
|
+
dateFormat.isNotYet = true
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
days.push(dateFormat)
|
|
59
|
+
}
|
|
60
|
+
const { previousMonth, nextMonth } = completion(date)
|
|
61
|
+
return [...previousMonth, ...days, ...nextMonth]
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 获取这个月的第一天和左后一天
|
|
65
|
+
const getMonthInfo = (date) => {
|
|
66
|
+
const designatedDate = new Date(date)
|
|
67
|
+
const nowMonth = designatedDate.getMonth() // 当前月
|
|
68
|
+
const nowYear = designatedDate.getFullYear() // 当前年
|
|
69
|
+
// 本月的开始时间
|
|
70
|
+
const monthStartDate = new Date(nowYear, nowMonth, 1)
|
|
71
|
+
// 本月的结束时间
|
|
72
|
+
const monthEndDate = new Date(nowYear, nowMonth + 1, 0)
|
|
73
|
+
return {
|
|
74
|
+
start: monthStartDate,
|
|
75
|
+
end: monthEndDate
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// 补全开头和结尾
|
|
79
|
+
const completion = (date) => {
|
|
80
|
+
const { start: startDate, end: endDate } = getMonthInfo(date)
|
|
81
|
+
const startWeek = startDate.getDay()
|
|
82
|
+
const endWeek = endDate.getDay()
|
|
83
|
+
const startDifference = startWeek
|
|
84
|
+
const endDifference = 7 - endWeek
|
|
85
|
+
const previousMonth = []
|
|
86
|
+
const nextMonth = []
|
|
87
|
+
const todayDate = new Date()
|
|
88
|
+
const today = XEUtils.toDateString(todayDate, 'yyyy-MM-dd')
|
|
89
|
+
for (let i = startDifference; i > 0; i--) {
|
|
90
|
+
let needDate = new Date(startDate.getTime())
|
|
91
|
+
needDate = needDate.setDate(needDate.getDate() - i)
|
|
92
|
+
needDate = new Date(needDate)
|
|
93
|
+
const dateFormat = {
|
|
94
|
+
date: XEUtils.toDateString(needDate, 'yyyy-MM-dd'),
|
|
95
|
+
day: XEUtils.toDateString(needDate, 'd'),
|
|
96
|
+
statusList: [],
|
|
97
|
+
isLastMonth: true
|
|
98
|
+
}
|
|
99
|
+
if (dateFormat.date === today) {
|
|
100
|
+
dateFormat.isToday = true
|
|
101
|
+
} else {
|
|
102
|
+
if (todayDate.getTime() < needDate.getTime()) {
|
|
103
|
+
dateFormat.isNotYet = true
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
previousMonth.push(dateFormat)
|
|
107
|
+
}
|
|
108
|
+
for (let i = 1; i < endDifference; i++) {
|
|
109
|
+
let needDate = new Date(endDate.getTime())
|
|
110
|
+
needDate = needDate.setDate(needDate.getDate() + i)
|
|
111
|
+
needDate = new Date(needDate)
|
|
112
|
+
const dateFormat = {
|
|
113
|
+
date: XEUtils.toDateString(needDate, 'yyyy-MM-dd'),
|
|
114
|
+
day: XEUtils.toDateString(needDate, 'd'),
|
|
115
|
+
statusList: [],
|
|
116
|
+
isNextMonth: true
|
|
117
|
+
}
|
|
118
|
+
if (dateFormat.date === today) {
|
|
119
|
+
dateFormat.isToday = true
|
|
120
|
+
} else {
|
|
121
|
+
if (todayDate.getTime() < needDate.getTime()) {
|
|
122
|
+
dateFormat.isNotYet = true
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
nextMonth.push(dateFormat)
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
previousMonth,
|
|
129
|
+
nextMonth
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// 获取日历数据
|
|
134
|
+
export const Calendar = (date) => {
|
|
135
|
+
return getDaysByDate(date)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// 每组多少
|
|
139
|
+
export const GroupArray = (list, num) => {
|
|
140
|
+
const arr = []
|
|
141
|
+
for (let i = 0; i < list.length; i += 7) {
|
|
142
|
+
arr.push(list.slice(i, i + 7))
|
|
143
|
+
}
|
|
144
|
+
return arr
|
|
145
|
+
}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="ml-calendar" :class="{'is-fold': isfold}">
|
|
3
|
+
<view class="ml-calendar-header">
|
|
4
|
+
<button class="ml-calendar-header-button" @tap="onLastMonth">
|
|
5
|
+
<ml-icon class="text-bold" name="arrow-left"></ml-icon>
|
|
6
|
+
</button>
|
|
7
|
+
<view class="ml-calendar-header-title">
|
|
8
|
+
<slot name="title">
|
|
9
|
+
<text>{{ monthTitle }}</text>
|
|
10
|
+
</slot>
|
|
11
|
+
</view>
|
|
12
|
+
<button class="ml-calendar-header-button" @tap="onNextMonth" :disabled="!isAfterMonth">
|
|
13
|
+
<ml-icon class="text-bold" name="arrow-right"></ml-icon>
|
|
14
|
+
</button>
|
|
15
|
+
</view>
|
|
16
|
+
|
|
17
|
+
<view class="ml-calendar-body" @touchstart="touchstartEvent" @touchend="touchendEvent">
|
|
18
|
+
<view class="ml-calendar-date-head">
|
|
19
|
+
<view class="ml-calendar-week-item" v-for="(week, index) in weekList" :key="index">
|
|
20
|
+
<view class="ml-calendar-week-box">{{ week }}</view>
|
|
21
|
+
</view>
|
|
22
|
+
</view>
|
|
23
|
+
|
|
24
|
+
<view class="ml-calendar-date-content" :style="contentStyle">
|
|
25
|
+
<view class="ml-calendar-date-week-list" v-for="(list, index) in months" :key="index">
|
|
26
|
+
<view class="ml-calendar-date-day-item" v-for="(item, key) in list" :key="key" @tap="onSelect(item)">
|
|
27
|
+
<view class="ml-calendar-date-day-box" :class="{'today': item.isToday, 'last-month': item.isLastMonth, 'next-month': item.isNextMonth, 'selected': selectDay === item.date, 'not-yet': item.isNotYet, 'disabled': item.disabled}">
|
|
28
|
+
<view class="ml-calendar-date-box-warpper">
|
|
29
|
+
<view class="ml-calendar-date-day-text" :class="{'today': item.isToday}" v-if="item.isToday">今</view>
|
|
30
|
+
<view class="ml-calendar-date-day-text" v-else>{{ item.day }}</view>
|
|
31
|
+
<view class="ml-calendar-date-day-dots">
|
|
32
|
+
<view class="ml-calendar-date-day-status" v-for="(status, sIndex) in item.statusList" :key="sIndex" :class="[`ss-${status}`]"></view>
|
|
33
|
+
</view>
|
|
34
|
+
<view class="ml-calendar-date-day-dots">
|
|
35
|
+
<view class="ml-calendar-date-day-status" :style="{ backgroundColor: item.color }" v-if="item.color"></view>
|
|
36
|
+
</view>
|
|
37
|
+
</view>
|
|
38
|
+
</view>
|
|
39
|
+
</view>
|
|
40
|
+
</view>
|
|
41
|
+
</view>
|
|
42
|
+
|
|
43
|
+
<view class="ml-calendar-fold-btn" @tap="toggleFold">
|
|
44
|
+
<ml-icon :name="isfold ? 'arrow-down' : 'arrow-top'"></ml-icon>
|
|
45
|
+
</view>
|
|
46
|
+
</view>
|
|
47
|
+
</view>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<script>
|
|
51
|
+
import { Calendar, GroupArray } from './calendar.js'
|
|
52
|
+
import XEUtils from 'xe-utils'
|
|
53
|
+
|
|
54
|
+
export default {
|
|
55
|
+
name: 'MlCalendar',
|
|
56
|
+
props: {
|
|
57
|
+
value: String,
|
|
58
|
+
scheduleMethod: Function
|
|
59
|
+
},
|
|
60
|
+
inject: {
|
|
61
|
+
currVM: {
|
|
62
|
+
from: '$pageVM',
|
|
63
|
+
default: null
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
data () {
|
|
67
|
+
return {
|
|
68
|
+
isfold: false,
|
|
69
|
+
selectMonth: new Date(),
|
|
70
|
+
weekList: ['日', '一', '二', '三', '四', '五', '六'],
|
|
71
|
+
months: [],
|
|
72
|
+
selectDay: ''
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
computed: {
|
|
76
|
+
monthTitle () {
|
|
77
|
+
return XEUtils.toDateString(this.selectMonth, 'yyyy年MM月')
|
|
78
|
+
},
|
|
79
|
+
contentStyle () {
|
|
80
|
+
const lineHeight = 94
|
|
81
|
+
if (this.isfold) {
|
|
82
|
+
return `height: ${lineHeight}rpx;`
|
|
83
|
+
}
|
|
84
|
+
return `height: ${(this.months.length || 5) * lineHeight}rpx;`
|
|
85
|
+
},
|
|
86
|
+
// 判断是否可进行下一月的切换
|
|
87
|
+
isAfterMonth () {
|
|
88
|
+
return true
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
watch: {
|
|
92
|
+
value () {
|
|
93
|
+
this.updateDate()
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
mounted () {
|
|
97
|
+
this.updateDate()
|
|
98
|
+
this.updateCalendar()
|
|
99
|
+
},
|
|
100
|
+
methods: {
|
|
101
|
+
updateDate () {
|
|
102
|
+
const currVal = XEUtils.toStringDate(this.value || new Date())
|
|
103
|
+
this.selectDay = XEUtils.toDateString(currVal, 'yyyy-MM-dd')
|
|
104
|
+
this.selectMonth = currVal
|
|
105
|
+
},
|
|
106
|
+
loadsChedule () {
|
|
107
|
+
if (this.scheduleMethod) {
|
|
108
|
+
Promise.resolve(this.scheduleMethod.call(this.currVM, { currMonth: this.selectMonth })).then(rest => {
|
|
109
|
+
if (rest) {
|
|
110
|
+
const dateMaps = {}
|
|
111
|
+
rest.forEach(item => {
|
|
112
|
+
dateMaps[item.date] = item
|
|
113
|
+
})
|
|
114
|
+
this.months.forEach(list => {
|
|
115
|
+
list.forEach(item => {
|
|
116
|
+
if (dateMaps[item.date]) {
|
|
117
|
+
const status = dateMaps[item.date].status
|
|
118
|
+
item.statusList = (XEUtils.isArray(status) ? status : [status]).slice(0, 2)
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
updateCalendar (date) {
|
|
127
|
+
if (!date) {
|
|
128
|
+
date = this.value
|
|
129
|
+
}
|
|
130
|
+
if (!date) {
|
|
131
|
+
date = new Date()
|
|
132
|
+
}
|
|
133
|
+
const dates = Calendar(this.selectMonth)
|
|
134
|
+
this.months = GroupArray(dates, 7)
|
|
135
|
+
this.loadsChedule()
|
|
136
|
+
},
|
|
137
|
+
toggleFold () {
|
|
138
|
+
this.isfold = !this.isfold
|
|
139
|
+
},
|
|
140
|
+
onSelect (item) {
|
|
141
|
+
if (item.disabled) {
|
|
142
|
+
return false
|
|
143
|
+
}
|
|
144
|
+
const value = item.date
|
|
145
|
+
this.selectDay = value
|
|
146
|
+
this.selectMonth = XEUtils.toStringDate(value)
|
|
147
|
+
if (item.isLastMonth) {
|
|
148
|
+
this.initCalendar()
|
|
149
|
+
} else if (item.isNextMonth) {
|
|
150
|
+
this.initCalendar()
|
|
151
|
+
}
|
|
152
|
+
this.$emit('input', value)
|
|
153
|
+
this.$emit('click', { value })
|
|
154
|
+
},
|
|
155
|
+
onLastMonth () {
|
|
156
|
+
this.selectMonth = XEUtils.getWhatMonth(this.selectMonth, -1)
|
|
157
|
+
this.updateCalendar()
|
|
158
|
+
},
|
|
159
|
+
onNextMonth () {
|
|
160
|
+
this.selectMonth = XEUtils.getWhatMonth(this.selectMonth, 1)
|
|
161
|
+
this.updateCalendar()
|
|
162
|
+
},
|
|
163
|
+
touchstartEvent (e) {
|
|
164
|
+
this.startPoint = e.changedTouches[0]
|
|
165
|
+
},
|
|
166
|
+
touchendEvent (e) {
|
|
167
|
+
const startPoint = this.startPoint
|
|
168
|
+
const endPoint = e.changedTouches[0]
|
|
169
|
+
if (startPoint.clientX > endPoint.clientX + 60) {
|
|
170
|
+
this.onLastMonth()
|
|
171
|
+
} else if (startPoint.clientX < endPoint.clientX - 60) {
|
|
172
|
+
this.onNextMonth()
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
</script>
|
|
178
|
+
|
|
179
|
+
<style lang="scss">
|
|
180
|
+
.ml-calendar {
|
|
181
|
+
width: 100%;
|
|
182
|
+
padding: 30rpx;
|
|
183
|
+
background-color: #FFFFFF;
|
|
184
|
+
.ml-calendar-header {
|
|
185
|
+
display: flex;
|
|
186
|
+
justify-content: space-between;
|
|
187
|
+
align-items: center;
|
|
188
|
+
margin-bottom: 10rpx;
|
|
189
|
+
.ml-calendar-header-title {
|
|
190
|
+
flex-grow: 1;
|
|
191
|
+
text-align: center;
|
|
192
|
+
margin: 0 30rpx;
|
|
193
|
+
font-size: 32rpx;
|
|
194
|
+
font-weight: bolder;
|
|
195
|
+
}
|
|
196
|
+
.ml-calendar-header-button {
|
|
197
|
+
flex-shrink: 0;
|
|
198
|
+
border: 1px solid #dddddd;
|
|
199
|
+
padding: 10rpx;
|
|
200
|
+
border-radius: 8rpx;
|
|
201
|
+
text-align: center;
|
|
202
|
+
margin: 0;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.ml-calendar-date-head {
|
|
207
|
+
display: flex;
|
|
208
|
+
align-items: center;
|
|
209
|
+
margin: 0 -10rpx;
|
|
210
|
+
margin-bottom: 10rpx;
|
|
211
|
+
.ml-calendar-week-item {
|
|
212
|
+
flex-grow: 1;
|
|
213
|
+
.ml-calendar-week-box {
|
|
214
|
+
color: #999999;
|
|
215
|
+
text-align: center;
|
|
216
|
+
width: 60rpx;
|
|
217
|
+
height: 60rpx;
|
|
218
|
+
margin: auto;
|
|
219
|
+
display: flex;
|
|
220
|
+
justify-content: center;
|
|
221
|
+
align-items: center;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.ml-calendar-date-content {
|
|
227
|
+
height: 500rpx;
|
|
228
|
+
overflow: hidden;
|
|
229
|
+
transition: height 0.3s ease-out;
|
|
230
|
+
.ml-calendar-date-week-list {
|
|
231
|
+
display: flex;
|
|
232
|
+
align-items: center;
|
|
233
|
+
margin: 0 -10rpx;
|
|
234
|
+
margin-bottom: 10rpx;
|
|
235
|
+
.ml-calendar-date-day-item {
|
|
236
|
+
flex-grow: 1;
|
|
237
|
+
}
|
|
238
|
+
.ml-calendar-date-day-box {
|
|
239
|
+
width: 64rpx;
|
|
240
|
+
height: 86rpx;
|
|
241
|
+
border-radius: 8rpx;
|
|
242
|
+
margin: auto;
|
|
243
|
+
border: 2px solid transparent;
|
|
244
|
+
.ml-calendar-date-box-warpper {
|
|
245
|
+
width: 100%;
|
|
246
|
+
height: 100%;
|
|
247
|
+
.ml-calendar-date-day-text {
|
|
248
|
+
font-weight: 500;
|
|
249
|
+
font-size: 30rpx;
|
|
250
|
+
text-align: center;
|
|
251
|
+
margin: 0 auto;
|
|
252
|
+
width: 60rpx;
|
|
253
|
+
height: 60rpx;
|
|
254
|
+
line-height: 60rpx;
|
|
255
|
+
border-radius: 50%;
|
|
256
|
+
&.today {
|
|
257
|
+
font-size: 22rpx;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
.ml-calendar-date-day-dots {
|
|
261
|
+
width: 100%;
|
|
262
|
+
line-height: 10rpx;
|
|
263
|
+
text-align: center;
|
|
264
|
+
}
|
|
265
|
+
.ml-calendar-date-day-status {
|
|
266
|
+
display: inline-block;
|
|
267
|
+
width: 14rpx;
|
|
268
|
+
height: 14rpx;
|
|
269
|
+
margin: 0 4rpx;
|
|
270
|
+
border-radius: 50%;
|
|
271
|
+
&.ss-primary {
|
|
272
|
+
background-color: $ml-theme-primary-color;
|
|
273
|
+
}
|
|
274
|
+
&.ss-success {
|
|
275
|
+
background-color: $ml-theme-success-color;
|
|
276
|
+
}
|
|
277
|
+
&.ss-info {
|
|
278
|
+
background-color: #909399;
|
|
279
|
+
}
|
|
280
|
+
&.ss-warning {
|
|
281
|
+
background-color: $ml-theme-warning-color;
|
|
282
|
+
}
|
|
283
|
+
&.ss-danger {
|
|
284
|
+
background-color: $ml-theme-error-color;
|
|
285
|
+
}
|
|
286
|
+
&.ss-gray {
|
|
287
|
+
background-color: $ml-gray-color;
|
|
288
|
+
}
|
|
289
|
+
&.ss-blue {
|
|
290
|
+
background-color: $ml-blue-color;
|
|
291
|
+
}
|
|
292
|
+
&.ss-green {
|
|
293
|
+
background-color: $ml-green-color;
|
|
294
|
+
}
|
|
295
|
+
&.ss-pink {
|
|
296
|
+
background-color: $ml-pink-color;
|
|
297
|
+
}
|
|
298
|
+
&.ss-orange {
|
|
299
|
+
background-color: $ml-orange-color;
|
|
300
|
+
}
|
|
301
|
+
&.ss-purple {
|
|
302
|
+
background-color: $ml-purple-color;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
&.today {
|
|
307
|
+
.ml-calendar-date-day-text {
|
|
308
|
+
color: $ml-theme-primary-color;
|
|
309
|
+
background-color: #c6e4ff;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
&.selected {
|
|
313
|
+
.ml-calendar-date-day-text {
|
|
314
|
+
color: #fff;
|
|
315
|
+
background-color: $ml-theme-primary-color;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
&.last-month,
|
|
319
|
+
&.next-month,
|
|
320
|
+
&.disabled {
|
|
321
|
+
.ml-calendar-date-day-text {
|
|
322
|
+
color: rgba(23, 26, 29, 0.4);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.ml-calendar-fold-btn {
|
|
330
|
+
text-align: center;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
</style>
|