Skip to content
This repository was archived by the owner on Oct 27, 2021. It is now read-only.

Commit ea05332

Browse files
committed
feat: add Calendar
1 parent 8860f07 commit ea05332

File tree

14 files changed

+1116
-1
lines changed

14 files changed

+1116
-1
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"@tarojs/runtime": "3.0.0-beta.6",
4040
"@tarojs/taro": "3.0.0-beta.6",
4141
"classnames": "^2.2.6",
42+
"dayjs": "^1.8.27",
4243
"lodash": "^4.17.15",
4344
"vue": "^2.5.0",
4445
"vue-class-component": "^7.2.3",

src/app.config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export default {
2-
pages: ['pages/index/index'],
2+
pages: ['pages/demo/index'],
33
window: {
44
backgroundTextStyle: 'light',
55
navigationBarBackgroundColor: '#fff',
+294
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
import Vue from 'vue'
2+
import classNames from 'classnames'
3+
import dayjs from 'dayjs'
4+
import { Swiper, SwiperItem, View } from '@tarojs/components'
5+
import { delayQuerySelector } from '../../../utils/common'
6+
import generateCalendarGroup from '../common/helper'
7+
import AtCalendarDateList from '../ui/date-list/index'
8+
import AtCalendarDayList from '../ui/day-list/index'
9+
10+
const ANIMTE_DURATION = 300
11+
12+
const AtCalendarBody = Vue.extend({
13+
name: 'AtCalendarBody',
14+
props: {
15+
marks: {
16+
type: Array,
17+
default: () => [],
18+
},
19+
selectedDate: {
20+
type: Object,
21+
default: () => ({
22+
end: Date.now(),
23+
start: Date.now(),
24+
}),
25+
},
26+
selectedDates: {
27+
type: Object,
28+
default: () => [],
29+
},
30+
format: {
31+
type: String,
32+
default: 'YYYY-MM-DD',
33+
},
34+
generateDate: {
35+
type: [Number, String],
36+
default: Date.now(),
37+
},
38+
validDates: {
39+
type: Array,
40+
default: () => [],
41+
},
42+
minDate: {
43+
type: [String, Number, Date],
44+
default: '',
45+
},
46+
maxDate: {
47+
type: [String, Number, Date],
48+
default: '',
49+
},
50+
},
51+
data() {
52+
return {
53+
options: { addGlobalClass: true },
54+
state: {
55+
listGroup: [],
56+
offsetSize: 0,
57+
isAnimate: false,
58+
},
59+
}
60+
},
61+
created() {
62+
const {
63+
validDates,
64+
marks,
65+
format,
66+
minDate,
67+
maxDate,
68+
generateDate,
69+
selectedDate,
70+
selectedDates,
71+
} = this
72+
73+
this.generateFunc = generateCalendarGroup({
74+
validDates,
75+
format,
76+
minDate,
77+
maxDate,
78+
marks,
79+
selectedDates,
80+
})
81+
this.listGroup = this.getGroups(generateDate, selectedDate)
82+
},
83+
mounted() {
84+
delayQuerySelector(this, '.at-calendar-slider__main').then((res) => {
85+
this.maxWidth = res[0].width
86+
})
87+
},
88+
methods: {
89+
getGroups(generateDate, selectedDate) {
90+
const dayjsDate = dayjs(generateDate)
91+
const arr = []
92+
const preList = this.generateFunc(dayjsDate.subtract(1, 'month').valueOf(), selectedDate)
93+
94+
const nowList = this.generateFunc(generateDate, selectedDate, true)
95+
96+
const nextList = this.generateFunc(dayjsDate.add(1, 'month').valueOf(), selectedDate)
97+
98+
const preListIndex = this.currentSwiperIndex === 0 ? 2 : this.currentSwiperIndex - 1
99+
const nextListIndex = this.currentSwiperIndex === 2 ? 0 : this.currentSwiperIndex + 1
100+
101+
arr[preListIndex] = preList
102+
arr[nextListIndex] = nextList
103+
arr[this.currentSwiperIndex] = nowList
104+
105+
return arr
106+
},
107+
handleTouchStart(e) {
108+
if (!this.isSwiper) {
109+
return
110+
}
111+
this.isTouching = true
112+
this.startX = e.touches[0].clientX
113+
},
114+
handleTouchMove(e) {
115+
if (!this.isSwiper) {
116+
return
117+
}
118+
if (!this.isTouching) return
119+
120+
const { clientX } = e.touches[0]
121+
const offsetSize = clientX - this.startX
122+
123+
this.setState({
124+
offsetSize,
125+
})
126+
},
127+
animateMoveSlide(offset, callback) {
128+
this.setState(
129+
{
130+
isAnimate: true,
131+
},
132+
() => {
133+
this.setState({
134+
offsetSize: offset,
135+
})
136+
setTimeout(() => {
137+
this.setState(
138+
{
139+
isAnimate: false,
140+
},
141+
() => {
142+
callback && callback()
143+
}
144+
)
145+
}, ANIMTE_DURATION)
146+
}
147+
)
148+
},
149+
handleTouchEnd() {
150+
if (!this.isSwiper) {
151+
return
152+
}
153+
154+
const { offsetSize } = this.state
155+
156+
this.isTouching = false
157+
const isRight = offsetSize > 0
158+
159+
const breakpoint = this.maxWidth / 2
160+
const absOffsetSize = Math.abs(offsetSize)
161+
162+
if (absOffsetSize > breakpoint) {
163+
const res = isRight ? this.maxWidth : -this.maxWidth
164+
return this.animateMoveSlide(res, () => {
165+
this.onSwipeMonth(isRight ? -1 : 1)
166+
})
167+
}
168+
this.animateMoveSlide(0)
169+
},
170+
handleChange(e) {
171+
const { current, source } = e.detail
172+
173+
if (source === 'touch') {
174+
this.currentSwiperIndex = current
175+
this.changeCount += 1
176+
}
177+
},
178+
handleAnimateFinish() {
179+
if (this.changeCount > 0) {
180+
this.onSwipeMonth(this.isPreMonth ? -this.changeCount : this.changeCount)
181+
this.changeCount = 0
182+
}
183+
},
184+
handleSwipeTouchStart(e) {
185+
const { clientY, clientX } = e.changedTouches[0]
186+
this.swipeStartPoint = this.isVertical ? clientY : clientX
187+
},
188+
handleSwipeTouchEnd(e) {
189+
const { clientY, clientX } = e.changedTouches[0]
190+
this.isPreMonth = this.isVertical
191+
? clientY - this.swipeStartPoint > 0
192+
: clientX - this.swipeStartPoint > 0
193+
},
194+
},
195+
render() {
196+
const { isSwiper } = this
197+
const { isAnimate, offsetSize, listGroup } = this.state
198+
199+
if (!isSwiper) {
200+
return (
201+
<View
202+
className={classNames(
203+
'main',
204+
'at-calendar-slider__main',
205+
`at-calendar-slider__main--${process.env.TARO_ENV}`
206+
)}>
207+
<AtCalendarDayList />
208+
<View className="main__body body">
209+
<View className="body__slider body__slider--now">
210+
<AtCalendarDateList
211+
list={listGroup[1].list}
212+
onClick={this.onDayClick}
213+
onLongClick={this.onLongClick}
214+
/>
215+
</View>
216+
</View>
217+
</View>
218+
)
219+
}
220+
221+
/* 需要 Taro 组件库维护 Swiper 使 小程序 和 H5 的表现保持一致 */
222+
if (process.env.TARO_ENV === 'h5') {
223+
return (
224+
<View
225+
className={classNames(
226+
'main',
227+
'at-calendar-slider__main',
228+
`at-calendar-slider__main--${process.env.TARO_ENV}`
229+
)}
230+
onTouchEnd={this.handleTouchEnd}
231+
onTouchMove={this.handleTouchMove}
232+
onTouchStart={this.handleTouchStart}>
233+
<AtCalendarDayList />
234+
<View
235+
className={classNames('main__body body', {
236+
'main__body--slider': isSwiper,
237+
'main__body--animate': isAnimate,
238+
})}
239+
style={{
240+
transform: isSwiper ? `translateX(-100%) translate3d(${offsetSize},0,0)` : '',
241+
WebkitTransform: isSwiper ? `translateX(-100%) translate3d(${offsetSize}px,0,0)` : '',
242+
}}>
243+
<View className="body__slider body__slider--pre">
244+
<AtCalendarDateList list={listGroup[0].list} />
245+
</View>
246+
<View className="body__slider body__slider--now">
247+
<AtCalendarDateList
248+
list={listGroup[1].list}
249+
onClick={this.onDayClick}
250+
onLongClick={this.onLongClick}
251+
/>
252+
</View>
253+
<View className="body__slider body__slider--next">
254+
<AtCalendarDateList list={listGroup[2].list} />
255+
</View>
256+
</View>
257+
</View>
258+
)
259+
}
260+
261+
return (
262+
<View
263+
className={classNames(
264+
'main',
265+
'at-calendar-slider__main',
266+
`at-calendar-slider__main--${process.env.TARO_ENV}`
267+
)}>
268+
<AtCalendarDayList />
269+
<Swiper
270+
circular
271+
current={1}
272+
skipHiddenItemLayout
273+
className={classNames('main__body')}
274+
onChange={this.handleChange}
275+
vertical={this.isVertical}
276+
onAnimationFinish={this.handleAnimateFinish}
277+
onTouchEnd={this.handleSwipeTouchEnd}
278+
onTouchStart={this.handleSwipeTouchStart}>
279+
{listGroup.map((item, key) => (
280+
<SwiperItem key={item.value} itemId={key.toString()}>
281+
<AtCalendarDateList
282+
list={item.list}
283+
onClick={this.onDayClick}
284+
onLongClick={this.onLongClick}
285+
/>
286+
</SwiperItem>
287+
))}
288+
</Swiper>
289+
</View>
290+
)
291+
},
292+
})
293+
294+
export default AtCalendarBody
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const TYPE_PRE_MONTH = -1
2+
3+
export const TYPE_NOW_MONTH = 0
4+
5+
export const TYPE_NEXT_MONTH = 1

0 commit comments

Comments
 (0)