add:redux
parent
2a78e35d93
commit
9ca194b3a0
File diff suppressed because it is too large
Load Diff
@ -1,25 +1,25 @@
|
||||
{
|
||||
"miniprogramRoot": "dist/",
|
||||
"projectname": "flossom_miniapp",
|
||||
"description": "",
|
||||
"appid": "touristappid",
|
||||
"setting": {
|
||||
"urlCheck": true,
|
||||
"es6": false,
|
||||
"miniprogramRoot": "dist/",
|
||||
"projectname": "flossom_miniapp",
|
||||
"description": "",
|
||||
"appid": "wx815fb6fbd1f5ab3c",
|
||||
"setting": {
|
||||
"urlCheck": true,
|
||||
"es6": false,
|
||||
"enhance": false,
|
||||
"compileHotReLoad": false,
|
||||
"postcss": false,
|
||||
"preloadBackgroundData": false,
|
||||
"minified": false,
|
||||
"newFeature": true,
|
||||
"autoAudits": false,
|
||||
"coverView": true,
|
||||
"showShadowRootInWxmlPanel": false,
|
||||
"scopeDataCheck": false,
|
||||
"useCompilerModule": false
|
||||
},
|
||||
"compileType": "miniprogram",
|
||||
"simulatorType": "wechat",
|
||||
"simulatorPluginLibVersion": {},
|
||||
"condition": {}
|
||||
"postcss": false,
|
||||
"preloadBackgroundData": false,
|
||||
"minified": false,
|
||||
"newFeature": true,
|
||||
"autoAudits": false,
|
||||
"coverView": true,
|
||||
"showShadowRootInWxmlPanel": false,
|
||||
"scopeDataCheck": false,
|
||||
"useCompilerModule": false
|
||||
},
|
||||
"compileType": "miniprogram",
|
||||
"simulatorType": "wechat",
|
||||
"simulatorPluginLibVersion": {},
|
||||
"condition": {}
|
||||
}
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
import { Component } from 'react'
|
||||
|
||||
const objectToString = (style: object | string): string => {
|
||||
if (style && typeof style === 'object') {
|
||||
let styleStr = ''
|
||||
Object.keys(style).forEach(key => {
|
||||
const lowerCaseKey = key.replace(/([A-Z])/g, '-$1').toLowerCase()
|
||||
styleStr += `${lowerCaseKey}:${style[key]};`
|
||||
})
|
||||
return styleStr
|
||||
} else if (style && typeof style === 'string') {
|
||||
return style
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
export default class AtComponent<P, S> extends Component<P, S> {
|
||||
/**
|
||||
* 合并 style
|
||||
* @param {Object|String} style1
|
||||
* @param {Object|String} style2
|
||||
* @returns {String}
|
||||
*/
|
||||
mergeStyle(
|
||||
style1: object | string,
|
||||
style2: object | string
|
||||
): object | string {
|
||||
if (
|
||||
style1 &&
|
||||
typeof style1 === 'object' &&
|
||||
style2 &&
|
||||
typeof style2 === 'object'
|
||||
) {
|
||||
return Object.assign({}, style1, style2)
|
||||
}
|
||||
return objectToString(style1) + objectToString(style2)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
// 使用 HOC 以方便为各个页面复用这段逻辑
|
||||
function createErrorBoundary(Page) {
|
||||
return class ErrorBoundary extends Component {
|
||||
el = React.createRef();
|
||||
state = {
|
||||
hasError: null,
|
||||
};
|
||||
|
||||
static getDerivedStateFromError() {
|
||||
return {
|
||||
hasError: true,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidCatch(error, errorInfo) {
|
||||
console.log(error, errorInfo);
|
||||
}
|
||||
|
||||
/* Start 需要手动调用页面组件上的生命周期方法 **/
|
||||
componentDidShow() {
|
||||
return this.el.current?.componentDidShow?.();
|
||||
}
|
||||
|
||||
componentDidHide() {
|
||||
return this.el.current?.componentDidHide?.();
|
||||
}
|
||||
|
||||
onShareAppMessage() {
|
||||
return this.el.current?.onShareAppMessage?.();
|
||||
}
|
||||
|
||||
//...
|
||||
|
||||
/* End 需要手动调用页面组件上的生命周期方法 **/
|
||||
|
||||
render() {
|
||||
return this.state.hasError ? (
|
||||
<View>Something went wrong.</View>
|
||||
) : (
|
||||
<Page ref={this.el} />
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default createErrorBoundary;
|
||||
@ -0,0 +1,489 @@
|
||||
import classnames from "classnames";
|
||||
import dayjs from "dayjs";
|
||||
import React from "react";
|
||||
import Taro, { Events } from "@tarojs/taro";
|
||||
|
||||
import { Swiper, SwiperItem, View, Image } from "@tarojs/components";
|
||||
import {
|
||||
BaseEventOrig,
|
||||
ITouch,
|
||||
ITouchEvent,
|
||||
} from "@tarojs/components/types/common";
|
||||
import {
|
||||
AtCalendarBodyListGroup,
|
||||
AtCalendarBodyProps,
|
||||
AtCalendarBodyState,
|
||||
Calendar,
|
||||
} from "../../../../types/calendar";
|
||||
import { delayQuerySelector } from "../../../common/utils";
|
||||
import generateCalendarGroup from "../common/helper";
|
||||
import AtCalendarDateList from "../ui/date-list/index";
|
||||
import AtCalendarDayList from "../ui/day-list/index";
|
||||
|
||||
import "./isFolding.less";
|
||||
|
||||
const ANIMTE_DURATION = 300;
|
||||
|
||||
const defaultProps: Partial<AtCalendarBodyProps> = {
|
||||
marks: [],
|
||||
selectedDate: {
|
||||
end: Date.now(),
|
||||
start: Date.now(),
|
||||
},
|
||||
format: "YYYY-MM-DD",
|
||||
generateDate: Date.now(),
|
||||
};
|
||||
|
||||
// const events = new Events();
|
||||
|
||||
export default class AtCalendarBody extends React.Component<
|
||||
AtCalendarBodyProps,
|
||||
Readonly<AtCalendarBodyState>
|
||||
> {
|
||||
static defaultProps: Partial<AtCalendarBodyProps> = defaultProps;
|
||||
|
||||
public constructor(props: AtCalendarBodyProps) {
|
||||
super(props);
|
||||
const {
|
||||
validDates,
|
||||
marks,
|
||||
format,
|
||||
minDate,
|
||||
maxDate,
|
||||
generateDate,
|
||||
selectedDate,
|
||||
selectedDates,
|
||||
} = props;
|
||||
|
||||
this.generateFunc = generateCalendarGroup({
|
||||
validDates,
|
||||
format,
|
||||
minDate,
|
||||
maxDate,
|
||||
marks,
|
||||
selectedDates,
|
||||
});
|
||||
const listGroup = this.getGroups(generateDate, selectedDate);
|
||||
|
||||
this.state = {
|
||||
listGroup,
|
||||
offsetSize: 0,
|
||||
isAnimate: false,
|
||||
isFolding: false,
|
||||
temporaryCalendar: [],
|
||||
temporaryCalendarWeek: [],
|
||||
};
|
||||
}
|
||||
|
||||
public componentDidMount(): void {
|
||||
delayQuerySelector(".at-calendar-slider__main").then((res: any) => {
|
||||
if (res.length) {
|
||||
this.maxWidth = res[0]?.width;
|
||||
}
|
||||
});
|
||||
|
||||
this.onChangeFoldingCalendar();
|
||||
}
|
||||
|
||||
public UNSAFE_componentWillReceiveProps(
|
||||
nextProps: AtCalendarBodyProps
|
||||
): void {
|
||||
const {
|
||||
validDates,
|
||||
marks,
|
||||
format,
|
||||
minDate,
|
||||
maxDate,
|
||||
generateDate,
|
||||
selectedDate,
|
||||
selectedDates,
|
||||
} = nextProps;
|
||||
|
||||
this.generateFunc = generateCalendarGroup({
|
||||
validDates,
|
||||
format,
|
||||
minDate,
|
||||
maxDate,
|
||||
marks,
|
||||
selectedDates,
|
||||
});
|
||||
const listGroup = this.getGroups(generateDate, selectedDate);
|
||||
|
||||
this.setState({
|
||||
offsetSize: 0,
|
||||
listGroup,
|
||||
});
|
||||
}
|
||||
|
||||
private changeCount = 0;
|
||||
private currentSwiperIndex = 1;
|
||||
private startX = 0;
|
||||
private swipeStartPoint = 0;
|
||||
private isPreMonth = false;
|
||||
private maxWidth = 0;
|
||||
private isTouching = false;
|
||||
|
||||
private generateFunc: (
|
||||
generateDate: number,
|
||||
selectedDate: Calendar.SelectedDate,
|
||||
isShowStatus?: boolean
|
||||
) => Calendar.ListInfo<Calendar.Item>;
|
||||
|
||||
private getGroups = (
|
||||
generateDate: number,
|
||||
selectedDate: Calendar.SelectedDate
|
||||
): AtCalendarBodyListGroup => {
|
||||
const dayjsDate = dayjs(generateDate);
|
||||
const arr: AtCalendarBodyListGroup = [];
|
||||
const preList: Calendar.ListInfo<Calendar.Item> = this.generateFunc(
|
||||
dayjsDate.subtract(1, "month").valueOf(),
|
||||
selectedDate
|
||||
);
|
||||
|
||||
const nowList: Calendar.ListInfo<Calendar.Item> = this.generateFunc(
|
||||
generateDate,
|
||||
selectedDate,
|
||||
true
|
||||
);
|
||||
|
||||
const nextList: Calendar.ListInfo<Calendar.Item> = this.generateFunc(
|
||||
dayjsDate.add(1, "month").valueOf(),
|
||||
selectedDate
|
||||
);
|
||||
|
||||
const preListIndex =
|
||||
this.currentSwiperIndex === 0 ? 2 : this.currentSwiperIndex - 1;
|
||||
const nextListIndex =
|
||||
this.currentSwiperIndex === 2 ? 0 : this.currentSwiperIndex + 1;
|
||||
|
||||
arr[preListIndex] = preList;
|
||||
arr[nextListIndex] = nextList;
|
||||
arr[this.currentSwiperIndex] = nowList;
|
||||
|
||||
return arr;
|
||||
};
|
||||
|
||||
private handleTouchStart = (e: ITouchEvent): void => {
|
||||
if (!this.props.isSwiper) {
|
||||
return;
|
||||
}
|
||||
this.isTouching = true;
|
||||
this.startX = e.touches[0].clientX;
|
||||
};
|
||||
|
||||
private handleTouchMove = (e: ITouchEvent): void => {
|
||||
if (!this.props.isSwiper) {
|
||||
return;
|
||||
}
|
||||
if (!this.isTouching) return;
|
||||
|
||||
const { clientX } = e.touches[0];
|
||||
const offsetSize = clientX - this.startX;
|
||||
|
||||
this.setState({
|
||||
offsetSize,
|
||||
});
|
||||
};
|
||||
|
||||
private animateMoveSlide = (offset: number, callback?: () => void): void => {
|
||||
this.setState(
|
||||
{
|
||||
isAnimate: true,
|
||||
},
|
||||
() => {
|
||||
this.setState({
|
||||
offsetSize: offset,
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.setState(
|
||||
{
|
||||
isAnimate: false,
|
||||
},
|
||||
() => {
|
||||
callback?.();
|
||||
}
|
||||
);
|
||||
}, ANIMTE_DURATION);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
private handleTouchEnd = (): void => {
|
||||
if (!this.props.isSwiper) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { offsetSize } = this.state;
|
||||
|
||||
this.isTouching = false;
|
||||
const isRight = offsetSize > 0;
|
||||
|
||||
const breakpoint = this.maxWidth / 2;
|
||||
const absOffsetSize = Math.abs(offsetSize);
|
||||
|
||||
if (absOffsetSize > breakpoint) {
|
||||
const res = isRight ? this.maxWidth : -this.maxWidth;
|
||||
return this.animateMoveSlide(res, () => {
|
||||
this.props.onSwipeMonth(isRight ? -1 : 1);
|
||||
});
|
||||
}
|
||||
this.animateMoveSlide(0);
|
||||
};
|
||||
|
||||
private handleChange = (
|
||||
e: BaseEventOrig<{
|
||||
current: number;
|
||||
source: string;
|
||||
}>
|
||||
): void => {
|
||||
const { current, source } = e.detail;
|
||||
|
||||
if (source === "touch") {
|
||||
this.currentSwiperIndex = current;
|
||||
this.changeCount += 1;
|
||||
}
|
||||
};
|
||||
|
||||
private handleAnimateFinish = (): void => {
|
||||
if (this.changeCount > 0) {
|
||||
this.props.onSwipeMonth(
|
||||
this.isPreMonth ? -this.changeCount : this.changeCount
|
||||
);
|
||||
this.changeCount = 0;
|
||||
}
|
||||
};
|
||||
|
||||
private handleSwipeTouchStart = (
|
||||
e: ITouchEvent & { changedTouches: Array<ITouch> }
|
||||
): void => {
|
||||
const { clientY, clientX } = e.changedTouches[0];
|
||||
this.swipeStartPoint = this.props.isVertical ? clientY : clientX;
|
||||
};
|
||||
|
||||
private handleSwipeTouchEnd = (
|
||||
e: ITouchEvent & { changedTouches: Array<ITouch> }
|
||||
): void => {
|
||||
const { clientY, clientX } = e.changedTouches[0];
|
||||
this.isPreMonth = this.props.isVertical
|
||||
? clientY - this.swipeStartPoint > 0
|
||||
: clientX - this.swipeStartPoint > 0;
|
||||
};
|
||||
|
||||
private onChangeFoldingCalendar = () => {
|
||||
let { isFolding, listGroup } = this.state;
|
||||
isFolding = !isFolding;
|
||||
if (isFolding) {
|
||||
let toDay = dayjs().format("YYYY-MM-DD");
|
||||
let selectedDay = listGroup[1].list.find(
|
||||
(item) => item.isSelected
|
||||
)?.value;
|
||||
let startWeekDay = dayjs(selectedDay)
|
||||
.startOf("week")
|
||||
.add(1, "day")
|
||||
.format("YYYY-MM-DD");
|
||||
let temporaryCalendar = [0, 1, 2, 3, 4, 5, 6].map((dayIndex) => {
|
||||
let currentItemDay = dayjs(startWeekDay)
|
||||
.add(dayIndex, "day")
|
||||
.format("YYYY-MM-DD");
|
||||
return {
|
||||
isDisabled: false,
|
||||
isSelected: currentItemDay === selectedDay,
|
||||
isSelectedHead: currentItemDay === selectedDay,
|
||||
isSelectedTail: currentItemDay === selectedDay,
|
||||
isToday: toDay === currentItemDay,
|
||||
marks: [],
|
||||
text: Number(dayjs(currentItemDay).format("DD")),
|
||||
type: 0,
|
||||
value: currentItemDay,
|
||||
};
|
||||
});
|
||||
this.setState({ temporaryCalendar });
|
||||
} else {
|
||||
let temporaryCalendar = listGroup[1].list;
|
||||
this.setState({ temporaryCalendar });
|
||||
}
|
||||
this.setState({ isFolding });
|
||||
};
|
||||
|
||||
onDayClick(item: any) {
|
||||
let { temporaryCalendar } = this.state;
|
||||
let oldValueItem = temporaryCalendar.findIndex((ele) => ele.isSelected);
|
||||
let newValueItem = temporaryCalendar.findIndex(
|
||||
(ele) => ele.value === item.value
|
||||
);
|
||||
|
||||
temporaryCalendar[oldValueItem].isSelected = false;
|
||||
temporaryCalendar[oldValueItem].isSelectedHead = false;
|
||||
temporaryCalendar[oldValueItem].isSelectedTail = false;
|
||||
|
||||
temporaryCalendar[newValueItem].isSelected = true;
|
||||
temporaryCalendar[newValueItem].isSelectedHead = true;
|
||||
temporaryCalendar[newValueItem].isSelectedTail = true;
|
||||
|
||||
this.setState({ temporaryCalendar });
|
||||
this.props.onDayClick(item);
|
||||
}
|
||||
|
||||
onSelectDataChange(value: any) {
|
||||
let { temporaryCalendar } = this.state;
|
||||
let oldValueItem = temporaryCalendar.findIndex((ele) => ele.isSelected);
|
||||
let newValueItem = temporaryCalendar.findIndex(
|
||||
(ele) => ele.value === value
|
||||
);
|
||||
|
||||
temporaryCalendar[oldValueItem].isSelected = false;
|
||||
temporaryCalendar[oldValueItem].isSelectedHead = false;
|
||||
temporaryCalendar[oldValueItem].isSelectedTail = false;
|
||||
|
||||
temporaryCalendar[newValueItem].isSelected = true;
|
||||
temporaryCalendar[newValueItem].isSelectedHead = true;
|
||||
temporaryCalendar[newValueItem].isSelectedTail = true;
|
||||
|
||||
this.setState({ temporaryCalendar });
|
||||
this.props.onDayClick(temporaryCalendar[newValueItem]);
|
||||
}
|
||||
|
||||
public render(): JSX.Element {
|
||||
const { isSwiper } = this.props;
|
||||
const { isFolding, isAnimate, offsetSize, listGroup, temporaryCalendar } =
|
||||
this.state;
|
||||
|
||||
Taro.eventCenter.on(
|
||||
"onSelectDataChange",
|
||||
this.onSelectDataChange.bind(this)
|
||||
);
|
||||
|
||||
if (!isSwiper) {
|
||||
return (
|
||||
<View
|
||||
className={classnames(
|
||||
"main",
|
||||
"at-calendar-slider__main",
|
||||
`at-calendar-slider__main--${process.env.TARO_ENV}`
|
||||
)}
|
||||
>
|
||||
<AtCalendarDayList />
|
||||
<View
|
||||
className={classnames("main__body", "body", {
|
||||
"main__body--isFolding": isFolding,
|
||||
})}
|
||||
>
|
||||
<View className="body__slider body__slider--now">
|
||||
{/* <AtCalendarDateList
|
||||
list={temporaryCalendar}
|
||||
onClick={this.onDayClick.bind(this)}
|
||||
onLongClick={this.props.onLongClick}
|
||||
/> */}
|
||||
<AtCalendarDateList list={temporaryCalendar} />
|
||||
</View>
|
||||
</View>
|
||||
<View className="arrow_box" onClick={this.onChangeFoldingCalendar}>
|
||||
<Image
|
||||
className={classnames("arrow", {
|
||||
"arrow-rotate": isFolding,
|
||||
})}
|
||||
src={require("../../../img/index/arrow-down.png")}
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
/* 需要 Taro 组件库维护 Swiper 使 小程序 和 H5 的表现保持一致 */
|
||||
if (process.env.TARO_ENV === "h5") {
|
||||
return (
|
||||
<View
|
||||
className={classnames(
|
||||
"main",
|
||||
"at-calendar-slider__main",
|
||||
`at-calendar-slider__main--${process.env.TARO_ENV}`
|
||||
)}
|
||||
onTouchEnd={this.handleTouchEnd}
|
||||
onTouchMove={this.handleTouchMove}
|
||||
onTouchStart={this.handleTouchStart}
|
||||
>
|
||||
<AtCalendarDayList />
|
||||
<View
|
||||
className={classnames("main__body body", {
|
||||
"main__body--slider": isSwiper,
|
||||
"main__body--animate": isAnimate,
|
||||
})}
|
||||
style={{
|
||||
transform: isSwiper
|
||||
? `translateX(-100%) translate3d(${offsetSize},0,0)`
|
||||
: "",
|
||||
WebkitTransform: isSwiper
|
||||
? `translateX(-100%) translate3d(${offsetSize}px,0,0)`
|
||||
: "",
|
||||
}}
|
||||
>
|
||||
<View className="body__slider body__slider--pre">
|
||||
<AtCalendarDateList list={listGroup[0].list} />
|
||||
</View>
|
||||
<View className="body__slider body__slider--now">
|
||||
<AtCalendarDateList
|
||||
list={temporaryCalendar}
|
||||
onClick={this.props.onDayClick}
|
||||
onLongClick={this.props.onLongClick}
|
||||
/>
|
||||
</View>
|
||||
<View className="body__slider body__slider--next">
|
||||
<AtCalendarDateList list={listGroup[2].list} />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
className={classnames(
|
||||
"main",
|
||||
"at-calendar-slider__main",
|
||||
`at-calendar-slider__main--${process.env.TARO_ENV}`
|
||||
)}
|
||||
>
|
||||
<AtCalendarDayList />
|
||||
<Swiper
|
||||
circular
|
||||
current={1}
|
||||
skipHiddenItemLayout
|
||||
className={classnames("main__body", {
|
||||
"main__body--isFolding": isFolding,
|
||||
})}
|
||||
onChange={this.handleChange}
|
||||
vertical={this.props.isVertical}
|
||||
onAnimationFinish={this.handleAnimateFinish}
|
||||
onTouchEnd={this.handleSwipeTouchEnd}
|
||||
onTouchStart={this.handleSwipeTouchStart}
|
||||
>
|
||||
{listGroup.map((item, key) => (
|
||||
<SwiperItem key={key} itemId={key.toString()}>
|
||||
<AtCalendarDateList
|
||||
list={key === 1 ? temporaryCalendar : item.list}
|
||||
onClick={this.onDayClick.bind(this)}
|
||||
onLongClick={this.props.onLongClick}
|
||||
/>
|
||||
{/* <AtCalendarDateList
|
||||
list={item.list}
|
||||
onClick={this.props.onDayClick}
|
||||
onLongClick={this.props.onLongClick}
|
||||
/> */}
|
||||
</SwiperItem>
|
||||
))}
|
||||
</Swiper>
|
||||
|
||||
<View className="arrow_box" onClick={this.onChangeFoldingCalendar}>
|
||||
<Image
|
||||
className={classnames("arrow", {
|
||||
"arrow-rotate": isFolding,
|
||||
})}
|
||||
src={require("../../../img/index/arrow-down.png")}
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
.at-calendar-slider__main--weapp,
|
||||
.at-calendar-slider__main--swan {
|
||||
.main__body--isFolding {
|
||||
height: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 样式定制 */
|
||||
.at-calendar {
|
||||
// 仅缩放宽度,防止上下抖动
|
||||
// transform: scale(0.9, 1);
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
color: #333;
|
||||
}
|
||||
.at-calendar__header .header__flex-item {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.at-calendar__header .header__flex,
|
||||
.at-calendar__list.flex .flex__item-container .container-text {
|
||||
// color: #333;
|
||||
}
|
||||
.at-calendar__list.flex .flex__item {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.at-calendar__list.flex .flex__item--today {
|
||||
color: #333;
|
||||
font-weight: 400;
|
||||
}
|
||||
.at-calendar__list.flex
|
||||
.flex__item--selected-head.flex__item--selected-tail
|
||||
.flex__item-container {
|
||||
background: linear-gradient(0deg, #fff0da, #ffe4c0);
|
||||
}
|
||||
|
||||
.at-calendar__list.flex .flex__item-container {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
}
|
||||
|
||||
.arrow_box {
|
||||
width: 80rpx;
|
||||
height: 40rpx;
|
||||
margin: 0 auto;
|
||||
// margin-bottom: ;
|
||||
// padding: 40rpx 80rpx 14rpx;
|
||||
}
|
||||
.arrow {
|
||||
transform: rotate(180deg);
|
||||
transition-property: all;
|
||||
transition-duration: 0.5s;
|
||||
width: 24rpx;
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.arrow-rotate {
|
||||
transform: rotate(0);
|
||||
}
|
||||
/* 样式定制 */
|
||||
@ -0,0 +1,5 @@
|
||||
export const TYPE_PRE_MONTH = -1
|
||||
|
||||
export const TYPE_NOW_MONTH = 0
|
||||
|
||||
export const TYPE_NEXT_MONTH = 1
|
||||
@ -0,0 +1,123 @@
|
||||
import dayjs, { Dayjs } from 'dayjs'
|
||||
import _flow from 'lodash/flow'
|
||||
import { Calendar } from '../../../../types/calendar'
|
||||
import * as constant from './constant'
|
||||
import plugins from './plugins'
|
||||
|
||||
const TOTAL = 7 * 6
|
||||
|
||||
function getFullItem(
|
||||
item: Partial<Calendar.Item>,
|
||||
options: Calendar.GroupOptions,
|
||||
selectedDate: Calendar.SelectedDate,
|
||||
isShowStatus?: boolean
|
||||
): any {
|
||||
if (options.marks.find(x => x.value === item.value)) {
|
||||
item.marks = [
|
||||
{
|
||||
value: item.value as string
|
||||
}
|
||||
]
|
||||
}
|
||||
if (!isShowStatus) return item
|
||||
|
||||
const bindedPlugins = plugins.map(fn =>
|
||||
fn.bind(null, {
|
||||
options,
|
||||
selectedDate
|
||||
})
|
||||
)
|
||||
return _flow(bindedPlugins)(item)
|
||||
}
|
||||
|
||||
export default function generateCalendarGroup(
|
||||
options: Calendar.GroupOptions
|
||||
): (
|
||||
generateDate: number,
|
||||
selectedDate: Calendar.SelectedDate,
|
||||
isShowStatus?: boolean
|
||||
) => Calendar.ListInfo<Calendar.Item> {
|
||||
return function (
|
||||
generateDate: number,
|
||||
selectedDate: Calendar.SelectedDate,
|
||||
isShowStatus?: boolean
|
||||
): Calendar.ListInfo<Calendar.Item> {
|
||||
const date = dayjs(generateDate)
|
||||
|
||||
const { format } = options
|
||||
|
||||
// 获取生成日期的第一天 和 最后一天
|
||||
const firstDate = date.startOf('month')
|
||||
const lastDate = date.endOf('month')
|
||||
|
||||
const preMonthDate = date.subtract(1, 'month')
|
||||
|
||||
const list: Calendar.List<Calendar.Item> = []
|
||||
|
||||
const nowMonthDays: number = date.daysInMonth()// 获取这个月有多少天
|
||||
|
||||
// 因为把周日放到了最后,这里要减一天
|
||||
const preMonthLastDay = preMonthDate.endOf('month').subtract(1, 'day').day() // 获取上个月最后一天是周几
|
||||
|
||||
// 生成上个月的日期
|
||||
for (let i = 1; i <= preMonthLastDay + 1; i++) {
|
||||
const thisDate = firstDate.subtract(i, 'day').startOf('day')
|
||||
|
||||
let item = {
|
||||
marks: [],
|
||||
_value: thisDate,
|
||||
text: thisDate.date(),
|
||||
type: constant.TYPE_PRE_MONTH,
|
||||
value: thisDate.format(format)
|
||||
}
|
||||
|
||||
item = getFullItem(item, options, selectedDate, isShowStatus)
|
||||
|
||||
list.push(item)
|
||||
}
|
||||
list.reverse()
|
||||
|
||||
// 生成这个月的日期
|
||||
for (let i = 0; i < nowMonthDays; i++) {
|
||||
const thisDate = firstDate.add(i, 'day').startOf('day')
|
||||
let item = {
|
||||
marks: [],
|
||||
_value: thisDate,
|
||||
text: thisDate.date(),
|
||||
type: constant.TYPE_NOW_MONTH,
|
||||
value: thisDate.format(format)
|
||||
}
|
||||
|
||||
item = getFullItem(item, options, selectedDate, isShowStatus)
|
||||
|
||||
list.push(item)
|
||||
}
|
||||
|
||||
// 生成下个月的日期
|
||||
let i = 1
|
||||
while (list.length < TOTAL) {
|
||||
const thisDate = lastDate.add(i++, 'day').startOf('day')
|
||||
let item = {
|
||||
marks: [],
|
||||
_value: thisDate,
|
||||
text: thisDate.date(),
|
||||
type: constant.TYPE_NEXT_MONTH,
|
||||
value: thisDate.format(format)
|
||||
}
|
||||
|
||||
item = getFullItem(item, options, selectedDate, isShowStatus)
|
||||
|
||||
list.push(item)
|
||||
}
|
||||
|
||||
return {
|
||||
list,
|
||||
value: generateDate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getGenerateDate(date: Calendar.DateArg | undefined): Dayjs {
|
||||
// return dayjs(date)
|
||||
return dayjs(date).startOf('month')
|
||||
}
|
||||
@ -0,0 +1,124 @@
|
||||
import dayjs from 'dayjs'
|
||||
import _isEmpty from 'lodash/isEmpty'
|
||||
import { Calendar } from '../../../../types/calendar'
|
||||
|
||||
interface PluginArg {
|
||||
options: Calendar.GroupOptions
|
||||
|
||||
selectedDate: Calendar.SelectedDate
|
||||
}
|
||||
|
||||
export function handleActive(
|
||||
args: PluginArg,
|
||||
item: Calendar.Item
|
||||
): Calendar.Item {
|
||||
const { selectedDate } = args
|
||||
const { _value } = item
|
||||
|
||||
const { start, end } = selectedDate
|
||||
|
||||
const dayjsEnd = dayjs(end)
|
||||
const dayjsStart = start ? dayjs(start) : dayjsEnd
|
||||
|
||||
item.isSelected =
|
||||
_value?.isSame(dayjsEnd) ||
|
||||
_value?.isSame(dayjsStart) ||
|
||||
(_value?.isAfter(dayjsStart) && _value?.isBefore(dayjsEnd))
|
||||
|
||||
item.isSelectedHead = _value?.isSame(dayjsStart)
|
||||
item.isSelectedTail = _value?.isSame(dayjsEnd)
|
||||
|
||||
item.isToday = _value?.diff(dayjs(Date.now()).startOf('day'), 'day') === 0
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
export function handleMarks(
|
||||
args: PluginArg,
|
||||
item: Calendar.Item
|
||||
): Calendar.Item {
|
||||
const { options } = args
|
||||
const { _value } = item
|
||||
const { marks } = options
|
||||
|
||||
const markList = marks.filter(mark =>
|
||||
_value ? dayjs(mark.value).startOf('day').isSame(_value) : false
|
||||
)
|
||||
|
||||
item.marks = markList.slice(0, 1)
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
// export function handleSelectedDates (args: PluginArg): Calendar.Item {
|
||||
// const { item, options } = args
|
||||
// const { _value } = item
|
||||
// const { selectedDates } = options
|
||||
|
||||
// if (selectedDates.length === 0) return args
|
||||
|
||||
// _forEach(selectedDates, date => {
|
||||
// const { isSelected, isHead, isTail } = item
|
||||
|
||||
// // 如果当前 Item 已经具备了 三种状态下 无需继续判断 跳出循环
|
||||
// if (isSelected) {
|
||||
// return false
|
||||
// }
|
||||
|
||||
// const { start, end } = date
|
||||
|
||||
// const dayjsEnd = dayjs(end).startOf('day')
|
||||
// const dayjsStart = dayjs(start).startOf('day')
|
||||
|
||||
// item.isSelected =
|
||||
// item.isSelected ||
|
||||
// (_value.isAfter(dayjsStart) && _value.isBefore(dayjsEnd))
|
||||
|
||||
// item.isHead = item.isHead || _value.isSame(dayjsStart)
|
||||
|
||||
// item.isTail = item.isTail || _value.isSame(dayjsEnd)
|
||||
// })
|
||||
|
||||
// return item
|
||||
// }
|
||||
|
||||
export function handleDisabled(
|
||||
args: PluginArg,
|
||||
item: Calendar.Item
|
||||
): Calendar.Item {
|
||||
const { options } = args
|
||||
const { _value } = item
|
||||
const { minDate, maxDate } = options
|
||||
|
||||
const dayjsMinDate = dayjs(minDate)
|
||||
const dayjsMaxDate = dayjs(maxDate)
|
||||
|
||||
item.isDisabled =
|
||||
!!(minDate && _value?.isBefore(dayjsMinDate)) ||
|
||||
!!(maxDate && _value?.isAfter(dayjsMaxDate))
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
export function handleValid(
|
||||
args: PluginArg,
|
||||
item: Calendar.Item
|
||||
): Calendar.Item {
|
||||
const { options } = args
|
||||
const { _value } = item
|
||||
const { validDates } = options
|
||||
|
||||
if (!_isEmpty(validDates)) {
|
||||
const isInclude = validDates.some(date =>
|
||||
_value ? dayjs(date.value).startOf('day').isSame(_value) : false
|
||||
)
|
||||
|
||||
item.isDisabled = !isInclude
|
||||
}
|
||||
|
||||
delete item._value
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
export default [handleActive, handleMarks, handleDisabled, handleValid]
|
||||
@ -0,0 +1,77 @@
|
||||
import classnames from "classnames";
|
||||
import dayjs, { Dayjs } from "dayjs";
|
||||
import React from "react";
|
||||
import { Picker, Text, View } from "@tarojs/components";
|
||||
|
||||
import {
|
||||
AtCalendarControllerProps,
|
||||
AtCalendarControllerState,
|
||||
} from "../../../../types/calendar";
|
||||
|
||||
export default class AtCalendarController extends React.Component<
|
||||
AtCalendarControllerProps,
|
||||
AtCalendarControllerState
|
||||
> {
|
||||
public render(): JSX.Element {
|
||||
const { generateDate, minDate, maxDate, monthFormat, hideArrow } =
|
||||
this.props;
|
||||
const dayjsDate: Dayjs = dayjs(generateDate);
|
||||
const dayjsMinDate: Dayjs | boolean = !!minDate && dayjs(minDate);
|
||||
const dayjsMaxDate: Dayjs | boolean = !!maxDate && dayjs(maxDate);
|
||||
|
||||
const isMinMonth: boolean =
|
||||
dayjsMinDate && dayjsMinDate.startOf("month").isSame(dayjsDate);
|
||||
|
||||
const isMaxMonth: boolean =
|
||||
dayjsMaxDate && dayjsMaxDate.startOf("month").isSame(dayjsDate);
|
||||
|
||||
const minDateValue: string = dayjsMinDate
|
||||
? dayjsMinDate.format("YYYY-MM")
|
||||
: "";
|
||||
const maxDateValue: string = dayjsMaxDate
|
||||
? dayjsMaxDate.format("YYYY-MM")
|
||||
: "";
|
||||
|
||||
return (
|
||||
<View className="at-calendar__controller controller flex-justify-sb">
|
||||
{hideArrow ? null : (
|
||||
<View
|
||||
className={classnames("controller__arrow controller__arrow--left", {
|
||||
"controller__arrow--disabled": isMinMonth,
|
||||
})}
|
||||
onClick={this.props.onPreMonth.bind(this, isMinMonth)}
|
||||
/>
|
||||
)}
|
||||
<View style="display: flex;align-items: center;">
|
||||
<Picker
|
||||
mode="date"
|
||||
fields="day"
|
||||
end={maxDateValue}
|
||||
start={minDateValue}
|
||||
onChange={this.props.onSelectDate}
|
||||
value={dayjsDate.format("YYYY-MM-DD")}
|
||||
>
|
||||
{/* <Text className="controller__info"></Text> */}
|
||||
{/* <Text>{dayjsDate.format(monthFormat)}</Text> */}
|
||||
<Text>{dayjsDate.format("YYYY.MM.DD")}</Text>
|
||||
</Picker>
|
||||
<View
|
||||
style="margin-left:10rpx"
|
||||
className="at-icon at-icon-calendar"
|
||||
></View>
|
||||
</View>
|
||||
{hideArrow ? null : (
|
||||
<View
|
||||
className={classnames(
|
||||
"controller__arrow controller__arrow--right",
|
||||
{
|
||||
"controller__arrow--disabled": isMaxMonth,
|
||||
}
|
||||
)}
|
||||
onClick={this.props.onNextMonth.bind(this, isMaxMonth)}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,337 @@
|
||||
import classnames from "classnames";
|
||||
import dayjs, { Dayjs } from "dayjs";
|
||||
import React from "react";
|
||||
import Taro, { Events } from "@tarojs/taro";
|
||||
import { View } from "@tarojs/components";
|
||||
import { BaseEventOrig } from "@tarojs/components/types/common";
|
||||
import {
|
||||
AtCalendarDefaultProps,
|
||||
AtCalendarProps,
|
||||
AtCalendarPropsWithDefaults,
|
||||
AtCalendarState,
|
||||
Calendar,
|
||||
} from "../../../types/calendar";
|
||||
import AtCalendarBody from "./body/index";
|
||||
import AtCalendarController from "./controller/index";
|
||||
|
||||
// const events = new Events();
|
||||
|
||||
const defaultProps: AtCalendarDefaultProps = {
|
||||
validDates: [],
|
||||
marks: [],
|
||||
isSwiper: true,
|
||||
hideArrow: false,
|
||||
isVertical: false,
|
||||
selectedDates: [],
|
||||
isMultiSelect: false,
|
||||
format: "YYYY-MM-DD",
|
||||
currentDate: Date.now(),
|
||||
// monthFormat: "YYYY年MM月",
|
||||
monthFormat: "YYYY-MM-DD",
|
||||
};
|
||||
|
||||
export default class AtCalendar extends React.Component<
|
||||
AtCalendarProps,
|
||||
Readonly<AtCalendarState>
|
||||
> {
|
||||
static defaultProps: AtCalendarDefaultProps = defaultProps;
|
||||
|
||||
public constructor(props: AtCalendarProps) {
|
||||
super(props);
|
||||
|
||||
const { currentDate, isMultiSelect } = props as AtCalendarPropsWithDefaults;
|
||||
|
||||
this.state = this.getInitializeState(currentDate, isMultiSelect);
|
||||
}
|
||||
|
||||
public UNSAFE_componentWillReceiveProps(nextProps: AtCalendarProps): void {
|
||||
const { currentDate, isMultiSelect } = nextProps;
|
||||
if (!currentDate || currentDate === this.props.currentDate) return;
|
||||
|
||||
if (isMultiSelect && this.props.isMultiSelect) {
|
||||
const { start, end } = currentDate as Calendar.SelectedDate;
|
||||
const { start: preStart, end: preEnd } = this.props
|
||||
.currentDate as Calendar.SelectedDate;
|
||||
|
||||
if (start === preStart && preEnd === end) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const stateValue: AtCalendarState = this.getInitializeState(
|
||||
currentDate,
|
||||
isMultiSelect
|
||||
);
|
||||
|
||||
this.setState(stateValue);
|
||||
}
|
||||
|
||||
private getSingleSelectdState = (value: Dayjs): Partial<AtCalendarState> => {
|
||||
const { generateDate } = this.state;
|
||||
console.log("generateDate", generateDate);
|
||||
const stateValue: Partial<AtCalendarState> = {
|
||||
selectedDate: this.getSelectedDate(value.valueOf()),
|
||||
};
|
||||
|
||||
// const dayjsGenerateDate: Dayjs = value.startOf("month"); // 重置到月份第一天
|
||||
const dayjsGenerateDate: Dayjs = value;
|
||||
const generateDateValue: number = dayjsGenerateDate.valueOf();
|
||||
if (generateDateValue !== generateDate) {
|
||||
this.triggerChangeDate(dayjsGenerateDate);
|
||||
stateValue.generateDate = generateDateValue;
|
||||
}
|
||||
|
||||
return stateValue;
|
||||
};
|
||||
|
||||
private getMultiSelectedState = (
|
||||
value: Dayjs
|
||||
): Pick<AtCalendarState, "selectedDate"> => {
|
||||
const { selectedDate } = this.state;
|
||||
const { end, start } = selectedDate;
|
||||
|
||||
const valueUnix: number = value.valueOf();
|
||||
const state: Pick<AtCalendarState, "selectedDate"> = {
|
||||
selectedDate,
|
||||
};
|
||||
|
||||
if (end) {
|
||||
state.selectedDate = this.getSelectedDate(valueUnix, 0);
|
||||
} else {
|
||||
state.selectedDate.end = Math.max(valueUnix, +start);
|
||||
state.selectedDate.start = Math.min(valueUnix, +start);
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
private getSelectedDate = (
|
||||
start: number,
|
||||
end?: number
|
||||
): Calendar.SelectedDate => {
|
||||
const stateValue: Calendar.SelectedDate = {
|
||||
start,
|
||||
end: start,
|
||||
};
|
||||
|
||||
if (typeof end !== "undefined") {
|
||||
stateValue.end = end;
|
||||
}
|
||||
|
||||
return stateValue;
|
||||
};
|
||||
|
||||
private getInitializeState(
|
||||
currentDate: Calendar.DateArg | Calendar.SelectedDate,
|
||||
isMultiSelect?: boolean
|
||||
): AtCalendarState {
|
||||
let end: number;
|
||||
let start: number;
|
||||
let generateDateValue: number;
|
||||
|
||||
if (!currentDate) {
|
||||
const dayjsStart = dayjs();
|
||||
start = dayjsStart.startOf("day").valueOf();
|
||||
// generateDateValue = dayjsStart.startOf("month").valueOf(); // 初始化选择器时间为每月第一天
|
||||
generateDateValue = dayjsStart.startOf("day").valueOf();
|
||||
return {
|
||||
generateDate: generateDateValue,
|
||||
selectedDate: {
|
||||
start: "",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (isMultiSelect) {
|
||||
const { start: cStart, end: cEnd } = currentDate as Calendar.SelectedDate;
|
||||
|
||||
const dayjsStart = dayjs(cStart);
|
||||
|
||||
start = dayjsStart.startOf("day").valueOf();
|
||||
generateDateValue = dayjsStart.startOf("month").valueOf();
|
||||
|
||||
end = cEnd ? dayjs(cEnd).startOf("day").valueOf() : start;
|
||||
} else {
|
||||
const dayjsStart = dayjs(currentDate as Calendar.DateArg);
|
||||
|
||||
start = dayjsStart.startOf("day").valueOf();
|
||||
// generateDateValue = dayjsStart.startOf("month").valueOf(); // 初始化选择器时间为每月第一天
|
||||
generateDateValue = dayjsStart.startOf("day").valueOf();
|
||||
|
||||
end = start;
|
||||
}
|
||||
|
||||
return {
|
||||
generateDate: generateDateValue,
|
||||
selectedDate: this.getSelectedDate(start, end),
|
||||
};
|
||||
}
|
||||
|
||||
private triggerChangeDate = (value: Dayjs): void => {
|
||||
const { format } = this.props;
|
||||
|
||||
if (typeof this.props.onMonthChange !== "function") return;
|
||||
|
||||
this.props.onMonthChange(value.format(format));
|
||||
};
|
||||
|
||||
private setMonth = (vectorCount: number): void => {
|
||||
const { format } = this.props;
|
||||
const { generateDate } = this.state;
|
||||
|
||||
const _generateDate: Dayjs = dayjs(generateDate).add(vectorCount, "month");
|
||||
this.setState({
|
||||
generateDate: _generateDate.valueOf(),
|
||||
});
|
||||
|
||||
if (vectorCount && typeof this.props.onMonthChange === "function") {
|
||||
this.props.onMonthChange(_generateDate.format(format));
|
||||
}
|
||||
};
|
||||
|
||||
private handleClickPreMonth = (isMinMonth?: boolean): void => {
|
||||
if (isMinMonth === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setMonth(-1);
|
||||
|
||||
if (typeof this.props.onClickPreMonth === "function") {
|
||||
this.props.onClickPreMonth();
|
||||
}
|
||||
};
|
||||
|
||||
private handleClickNextMonth = (isMaxMonth?: boolean): void => {
|
||||
if (isMaxMonth === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setMonth(1);
|
||||
|
||||
if (typeof this.props.onClickNextMonth === "function") {
|
||||
this.props.onClickNextMonth();
|
||||
}
|
||||
};
|
||||
|
||||
// picker 选择时间改变时触发
|
||||
private handleSelectDate = (e: BaseEventOrig<{ value: string }>): void => {
|
||||
const { value } = e.detail;
|
||||
|
||||
const _generateDate: Dayjs = dayjs(value);
|
||||
const _generateDateValue: number = _generateDate.valueOf();
|
||||
|
||||
if (this.state.generateDate === _generateDateValue) return;
|
||||
|
||||
this.triggerChangeDate(_generateDate);
|
||||
this.setState({
|
||||
generateDate: _generateDateValue,
|
||||
});
|
||||
|
||||
Taro.eventCenter.trigger(
|
||||
"onSelectDataChange",
|
||||
dayjs(_generateDateValue).format("YYYY-MM-DD")
|
||||
);
|
||||
|
||||
console.log("this.state", this.state);
|
||||
};
|
||||
|
||||
private handleDayClick = (item: Calendar.Item): void => {
|
||||
console.log("handleDayClick", item);
|
||||
const { isMultiSelect } = this.props;
|
||||
const { isDisabled, value } = item;
|
||||
|
||||
if (isDisabled) return;
|
||||
|
||||
const dayjsDate: Dayjs = dayjs(value);
|
||||
|
||||
let stateValue: Partial<AtCalendarState> = {};
|
||||
|
||||
if (isMultiSelect) {
|
||||
stateValue = this.getMultiSelectedState(dayjsDate);
|
||||
} else {
|
||||
stateValue = this.getSingleSelectdState(dayjsDate);
|
||||
}
|
||||
|
||||
this.setState(stateValue as AtCalendarState, () => {
|
||||
this.handleSelectedDate();
|
||||
});
|
||||
|
||||
if (typeof this.props.onDayClick === "function") {
|
||||
this.props.onDayClick({ value: item.value });
|
||||
}
|
||||
};
|
||||
|
||||
private handleSelectedDate = (): void => {
|
||||
const selectDate = this.state.selectedDate;
|
||||
if (typeof this.props.onSelectDate === "function") {
|
||||
const info: Calendar.SelectedDate = {
|
||||
start: dayjs(selectDate.start).format(this.props.format),
|
||||
};
|
||||
|
||||
if (selectDate.end) {
|
||||
info.end = dayjs(selectDate.end).format(this.props.format);
|
||||
}
|
||||
|
||||
this.props.onSelectDate({
|
||||
value: info,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private handleDayLongClick = (item: Calendar.Item): void => {
|
||||
if (typeof this.props.onDayLongClick === "function") {
|
||||
this.props.onDayLongClick({ value: item.value });
|
||||
}
|
||||
};
|
||||
|
||||
public render(): JSX.Element {
|
||||
const { generateDate, selectedDate } = this.state;
|
||||
console.log(
|
||||
"render generateDate",
|
||||
dayjs(generateDate).format("YYYY-MM-DD")
|
||||
);
|
||||
const {
|
||||
validDates,
|
||||
marks,
|
||||
format,
|
||||
minDate,
|
||||
maxDate,
|
||||
isSwiper,
|
||||
className,
|
||||
hideArrow,
|
||||
isVertical,
|
||||
monthFormat,
|
||||
selectedDates,
|
||||
} = this.props as AtCalendarPropsWithDefaults;
|
||||
|
||||
return (
|
||||
<View className={classnames("at-calendar", className)}>
|
||||
<AtCalendarController
|
||||
minDate={minDate}
|
||||
maxDate={maxDate}
|
||||
hideArrow={hideArrow}
|
||||
monthFormat={monthFormat}
|
||||
generateDate={generateDate}
|
||||
onPreMonth={this.handleClickPreMonth}
|
||||
onNextMonth={this.handleClickNextMonth}
|
||||
onSelectDate={this.handleSelectDate}
|
||||
/>
|
||||
<AtCalendarBody
|
||||
validDates={validDates}
|
||||
marks={marks}
|
||||
format={format}
|
||||
minDate={minDate}
|
||||
maxDate={maxDate}
|
||||
isSwiper={isSwiper}
|
||||
isVertical={isVertical}
|
||||
selectedDate={selectedDate}
|
||||
selectedDates={selectedDates}
|
||||
generateDate={generateDate}
|
||||
onDayClick={this.handleDayClick}
|
||||
onSwipeMonth={this.setMonth}
|
||||
onLongClick={this.handleDayLongClick}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
import classnames from 'classnames'
|
||||
import React from 'react'
|
||||
import { Text, View } from '@tarojs/components'
|
||||
import { Calendar } from '../../../../../types/calendar'
|
||||
import * as constant from '../../common/constant'
|
||||
|
||||
const MAP: { [key: number]: string } = {
|
||||
[constant.TYPE_PRE_MONTH]: 'pre',
|
||||
[constant.TYPE_NOW_MONTH]: 'now',
|
||||
[constant.TYPE_NEXT_MONTH]: 'next'
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
list: Calendar.List<Calendar.Item>
|
||||
|
||||
onClick?: (item: Calendar.Item) => void
|
||||
|
||||
onLongClick?: (item: Calendar.Item) => void
|
||||
}
|
||||
|
||||
export default class AtCalendarList extends React.Component<Props> {
|
||||
private handleClick = (item: Calendar.Item): void => {
|
||||
if (typeof this.props.onClick === 'function') {
|
||||
this.props.onClick(item)
|
||||
}
|
||||
}
|
||||
|
||||
private handleLongClick = (item: Calendar.Item): void => {
|
||||
if (typeof this.props.onLongClick === 'function') {
|
||||
this.props.onLongClick(item)
|
||||
}
|
||||
}
|
||||
|
||||
public render(): JSX.Element | null {
|
||||
const { list } = this.props
|
||||
if (!list || list.length === 0) return null
|
||||
|
||||
return (
|
||||
<View className='at-calendar__list flex'>
|
||||
{list.map((item: Calendar.Item) => (
|
||||
<View
|
||||
key={`list-item-${item.value}`}
|
||||
onClick={this.handleClick.bind(this, item)}
|
||||
onLongPress={this.handleLongClick.bind(this, item)}
|
||||
className={classnames(
|
||||
'flex__item',
|
||||
`flex__item--${MAP[item.type]}`,
|
||||
{
|
||||
'flex__item--today': item.isToday,
|
||||
'flex__item--active': item.isActive,
|
||||
'flex__item--selected': item.isSelected,
|
||||
'flex__item--selected-head': item.isSelectedHead,
|
||||
'flex__item--selected-tail': item.isSelectedTail,
|
||||
'flex__item--blur':
|
||||
item.isDisabled ||
|
||||
item.type === constant.TYPE_PRE_MONTH ||
|
||||
item.type === constant.TYPE_NEXT_MONTH
|
||||
}
|
||||
)}
|
||||
>
|
||||
<View className='flex__item-container'>
|
||||
<View className='container-text'>{item.text}</View>
|
||||
</View>
|
||||
<View className='flex__item-extra extra'>
|
||||
{item.marks && item.marks.length > 0 ? (
|
||||
<View className='extra-marks'>
|
||||
{item.marks.map((mark, key) => (
|
||||
<Text key={key} className='mark'>
|
||||
{mark.value}
|
||||
</Text>
|
||||
))}
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
import React from "react";
|
||||
import { View } from "@tarojs/components";
|
||||
|
||||
export default class AtCalendarHeader extends React.Component {
|
||||
public render(): JSX.Element {
|
||||
return (
|
||||
<View className="at-calendar__header header">
|
||||
<View className="header__flex">
|
||||
<View className="header__flex-item">一</View>
|
||||
<View className="header__flex-item">二</View>
|
||||
<View className="header__flex-item">三</View>
|
||||
<View className="header__flex-item">四</View>
|
||||
<View className="header__flex-item">五</View>
|
||||
<View className="header__flex-item">六</View>
|
||||
<View className="header__flex-item">日</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
export default {
|
||||
component: true,
|
||||
};
|
||||
@ -0,0 +1 @@
|
||||
@import "~taro-ui/dist/style/components/modal.scss";
|
||||
@ -0,0 +1,3 @@
|
||||
export default {
|
||||
component: true,
|
||||
};
|
||||
@ -0,0 +1,39 @@
|
||||
.tab-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
pointer-events: auto;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.tab-bar-border {
|
||||
background-color: rgba(0, 0, 0, 0.33);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
|
||||
.tab-bar-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tab-bar-item cover-image {
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
}
|
||||
|
||||
.tab-bar-item cover-view {
|
||||
font-size: 20px;
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
import { Component } from "react";
|
||||
import Taro from "@tarojs/taro";
|
||||
import { CoverView, CoverImage } from "@tarojs/components";
|
||||
|
||||
import "./index.less";
|
||||
|
||||
export default class Index extends Component {
|
||||
state = {
|
||||
selected: 2,
|
||||
color: "#999",
|
||||
selectedColor: "#000",
|
||||
backgroundColor: "#ffffff",
|
||||
borderStyle: "black",
|
||||
list: [
|
||||
{
|
||||
pagePath: "pages/activity/activity",
|
||||
text: "活动",
|
||||
iconPath: "/img/tabar/1.png",
|
||||
selectedIconPath: "/img/tabar/11.png",
|
||||
},
|
||||
{
|
||||
pagePath: "pages/detect/detect",
|
||||
text: "发现",
|
||||
iconPath: "/img/tabar/2.png",
|
||||
selectedIconPath: "/img/tabar/22.png",
|
||||
},
|
||||
{
|
||||
pagePath: "pages/index/index",
|
||||
text: "主页",
|
||||
iconPath: "/img/tabar/3.png",
|
||||
selectedIconPath: "/img/tabar/33.png",
|
||||
},
|
||||
{
|
||||
pagePath: "pages/shop/shop",
|
||||
text: "商城",
|
||||
iconPath: "/img/tabar/4.png",
|
||||
selectedIconPath: "/img/tabar/44.png",
|
||||
},
|
||||
{
|
||||
pagePath: "pages/user/user",
|
||||
text: "我的",
|
||||
iconPath: "/img/tabar/5.png",
|
||||
selectedIconPath: "/img/tabar/55.png",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
switchTab(index, url) {
|
||||
this.setSelected(index);
|
||||
Taro.switchTab({ url: "/" + url });
|
||||
// setTimeout(() => this.setSelected(index));
|
||||
}
|
||||
|
||||
setSelected(idx: number) {
|
||||
console.log("setSelected", idx);
|
||||
this.setState({
|
||||
selected: idx,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { list, selected, color, selectedColor } = this.state;
|
||||
|
||||
return (
|
||||
<CoverView className="tab-bar">
|
||||
<CoverView className="tab-bar-border"></CoverView>
|
||||
{list.map((item, index) => {
|
||||
return (
|
||||
<CoverView
|
||||
key={item.pagePath}
|
||||
className="tab-bar-item"
|
||||
onClick={this.switchTab.bind(this, index, item.pagePath)}
|
||||
>
|
||||
<CoverImage
|
||||
src={selected === index ? item.selectedIconPath : item.iconPath}
|
||||
/>
|
||||
<CoverView
|
||||
style={{
|
||||
color: selected === index ? selectedColor : color,
|
||||
fontWeight: selected === index ? "500" : "bold",
|
||||
fontSize: "11px",
|
||||
}}
|
||||
>
|
||||
{item.text}
|
||||
</CoverView>
|
||||
</CoverView>
|
||||
);
|
||||
})}
|
||||
</CoverView>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: "模板页",
|
||||
});
|
||||
@ -0,0 +1,49 @@
|
||||
import { MpSplashDetail, WCUserLogin } from "../../utils/Interface";
|
||||
import { Component, PropsWithChildren, useEffect, useState } from "react";
|
||||
import Taro from "@tarojs/taro";
|
||||
// 引入 Swiper, SwiperItem 组件
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
Image,
|
||||
Video,
|
||||
Swiper,
|
||||
SwiperItem,
|
||||
} from "@tarojs/components";
|
||||
|
||||
import "taro-ui/dist/style/components/button.scss"; // 按需引入
|
||||
import "./activity.less";
|
||||
|
||||
const app = Taro.getApp();
|
||||
|
||||
import type CustomTabBar from "../../custom-tab-bar";
|
||||
export default class Activity extends Component<any, any> {
|
||||
pageCtx = Taro.getCurrentInstance().page;
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
name: "activity",
|
||||
};
|
||||
}
|
||||
|
||||
async onLoad() {
|
||||
console.log("app", app);
|
||||
}
|
||||
componentDidMount() {}
|
||||
|
||||
componentWillUnmount() {}
|
||||
|
||||
componentDidShow() {
|
||||
const tabbar = Taro.getTabBar<CustomTabBar>(this.pageCtx);
|
||||
tabbar?.setSelected(0);
|
||||
}
|
||||
|
||||
componentDidHide() {}
|
||||
|
||||
async initData() {}
|
||||
|
||||
render() {
|
||||
let { name } = this.state;
|
||||
return <View>{name}</View>;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: "模板页",
|
||||
});
|
||||
@ -0,0 +1,49 @@
|
||||
import { MpSplashDetail, WCUserLogin } from "../../utils/Interface";
|
||||
import { Component, PropsWithChildren, useEffect, useState } from "react";
|
||||
import Taro from "@tarojs/taro";
|
||||
// 引入 Swiper, SwiperItem 组件
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
Image,
|
||||
Video,
|
||||
Swiper,
|
||||
SwiperItem,
|
||||
} from "@tarojs/components";
|
||||
|
||||
import "taro-ui/dist/style/components/button.scss"; // 按需引入
|
||||
import "./detect.less";
|
||||
|
||||
const app = Taro.getApp();
|
||||
|
||||
import type CustomTabBar from "../../custom-tab-bar";
|
||||
export default class Detect extends Component<any, any> {
|
||||
pageCtx = Taro.getCurrentInstance().page;
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
name: "detect",
|
||||
};
|
||||
}
|
||||
|
||||
async onLoad() {
|
||||
console.log("app", app);
|
||||
}
|
||||
componentDidMount() {}
|
||||
|
||||
componentWillUnmount() {}
|
||||
|
||||
componentDidShow() {
|
||||
const tabbar = Taro.getTabBar<CustomTabBar>(this.pageCtx);
|
||||
tabbar?.setSelected(1);
|
||||
}
|
||||
|
||||
componentDidHide() {}
|
||||
|
||||
async initData() {}
|
||||
|
||||
render() {
|
||||
let { name } = this.state;
|
||||
return <View>{name}</View>;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
/* ----------------------------------------------
|
||||
* Generated by Animista on 2023-12-8 17:46:25
|
||||
* Licensed under FreeBSD License.
|
||||
* See http://animista.net/license for more info.
|
||||
* w: http://animista.net, t: @cssanimista
|
||||
* ---------------------------------------------- */
|
||||
|
||||
@-webkit-keyframes slide-left {
|
||||
0% {
|
||||
-webkit-transform: translateX(300rpx);
|
||||
transform: translateX(300rpx);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translateX(0);
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
@keyframes slide-left {
|
||||
0% {
|
||||
-webkit-transform: translateX(300rpx);
|
||||
transform: translateX(300rpx);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translateX(0);
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 左侧滑入动画 */
|
||||
.slide-left {
|
||||
-webkit-animation: slide-left 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
|
||||
animation: slide-left 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
.FadeOutFrame {
|
||||
opacity: 1;
|
||||
}
|
||||
.FadeOutFrame.fadeout {
|
||||
-webkit-transition: all 1.5s;
|
||||
-moz-transition: all 1.5s;
|
||||
-ms-transition: all 1.5s;
|
||||
-o-transition: all 1.5s;
|
||||
transition: all 1.5s;
|
||||
opacity: 0;
|
||||
}
|
||||
.FadeInFrame {
|
||||
opacity: 0;
|
||||
}
|
||||
.FadeInFrame.fadein {
|
||||
-webkit-transition: all 1.5s;
|
||||
-moz-transition: all 1.5s;
|
||||
-ms-transition: all 1.5s;
|
||||
-o-transition: all 1.5s;
|
||||
transition: all 1.5s;
|
||||
opacity: 1;
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
错误类型收集
|
||||
MiniProgramError 页面跳转错误
|
||||
@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: "模板页",
|
||||
});
|
||||
@ -0,0 +1,44 @@
|
||||
import { MpSplashDetail, WCUserLogin } from "../../utils/Interface";
|
||||
import { Component, PropsWithChildren, useEffect, useState } from "react";
|
||||
import Taro from "@tarojs/taro";
|
||||
// 引入 Swiper, SwiperItem 组件
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
Image,
|
||||
Video,
|
||||
Swiper,
|
||||
SwiperItem,
|
||||
} from "@tarojs/components";
|
||||
|
||||
import "taro-ui/dist/style/components/button.scss"; // 按需引入
|
||||
import "./template.less";
|
||||
|
||||
const app = Taro.getApp();
|
||||
|
||||
export default class Index extends Component<any, any> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
name: "template模板页",
|
||||
};
|
||||
}
|
||||
|
||||
async onLoad() {
|
||||
console.log("app", app);
|
||||
}
|
||||
componentDidMount() {}
|
||||
|
||||
componentWillUnmount() {}
|
||||
|
||||
componentDidShow() {}
|
||||
|
||||
componentDidHide() {}
|
||||
|
||||
async initData() {}
|
||||
|
||||
render() {
|
||||
let { name } = this.state;
|
||||
return <View>{name}</View>;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: "注册",
|
||||
});
|
||||
@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: "模板页",
|
||||
});
|
||||
@ -0,0 +1,49 @@
|
||||
import { MpSplashDetail, WCUserLogin } from "../../utils/Interface";
|
||||
import { Component, PropsWithChildren, useEffect, useState } from "react";
|
||||
import Taro from "@tarojs/taro";
|
||||
// 引入 Swiper, SwiperItem 组件
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
Image,
|
||||
Video,
|
||||
Swiper,
|
||||
SwiperItem,
|
||||
} from "@tarojs/components";
|
||||
|
||||
import "taro-ui/dist/style/components/button.scss"; // 按需引入
|
||||
import "./shop.less";
|
||||
|
||||
const app = Taro.getApp();
|
||||
|
||||
import type CustomTabBar from "../../custom-tab-bar";
|
||||
export default class Shop extends Component<any, any> {
|
||||
pageCtx = Taro.getCurrentInstance().page;
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
name: "shop",
|
||||
};
|
||||
}
|
||||
|
||||
async onLoad() {
|
||||
console.log("app", app);
|
||||
}
|
||||
componentDidMount() {}
|
||||
|
||||
componentWillUnmount() {}
|
||||
|
||||
componentDidShow() {
|
||||
const tabbar = Taro.getTabBar<CustomTabBar>(this.pageCtx);
|
||||
tabbar?.setSelected(3);
|
||||
}
|
||||
|
||||
componentDidHide() {}
|
||||
|
||||
async initData() {}
|
||||
|
||||
render() {
|
||||
let { name } = this.state;
|
||||
return <View>{name}</View>;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: "我的",
|
||||
});
|
||||
@ -0,0 +1,49 @@
|
||||
import { MpSplashDetail, WCUserLogin } from "../../utils/Interface";
|
||||
import { Component, PropsWithChildren, useEffect, useState } from "react";
|
||||
import Taro from "@tarojs/taro";
|
||||
// 引入 Swiper, SwiperItem 组件
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
Image,
|
||||
Video,
|
||||
Swiper,
|
||||
SwiperItem,
|
||||
} from "@tarojs/components";
|
||||
|
||||
import "taro-ui/dist/style/components/button.scss"; // 按需引入
|
||||
import "./user.less";
|
||||
|
||||
const app = Taro.getApp();
|
||||
|
||||
import type CustomTabBar from "../../custom-tab-bar";
|
||||
export default class User extends Component<any, any> {
|
||||
pageCtx = Taro.getCurrentInstance().page;
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
name: "user",
|
||||
};
|
||||
}
|
||||
|
||||
async onLoad() {
|
||||
console.log("app", app);
|
||||
}
|
||||
componentDidMount() {}
|
||||
|
||||
componentWillUnmount() {}
|
||||
|
||||
componentDidShow() {
|
||||
const tabbar = Taro.getTabBar<CustomTabBar>(this.pageCtx);
|
||||
tabbar?.setSelected(4);
|
||||
}
|
||||
|
||||
componentDidHide() {}
|
||||
|
||||
async initData() {}
|
||||
|
||||
render() {
|
||||
let { name } = this.state;
|
||||
return <View>{name}</View>;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
import { configureStore } from "@reduxjs/toolkit";
|
||||
// 导入counter模块下的reducer函数
|
||||
import counterReducer from "./features/counter";
|
||||
|
||||
const store = configureStore({
|
||||
reducer: {
|
||||
// 每个reducer都可以理解成一个子仓库
|
||||
counter: counterReducer,
|
||||
},
|
||||
});
|
||||
|
||||
export default store;
|
||||
@ -0,0 +1,231 @@
|
||||
import dayjs from 'dayjs'
|
||||
import { BaseEvent } from '@tarojs/components/types/common'
|
||||
|
||||
// #region Calendar
|
||||
declare namespace Calendar {
|
||||
export type DateArg = string | number
|
||||
|
||||
export type classNameType =
|
||||
| string
|
||||
| Array<string>
|
||||
| { [key: string]: boolean }
|
||||
|
||||
export interface Mark {
|
||||
value: DateArg
|
||||
}
|
||||
|
||||
export interface ValidDate {
|
||||
value: DateArg
|
||||
}
|
||||
|
||||
export interface Item {
|
||||
value: string
|
||||
|
||||
_value?: dayjs.Dayjs
|
||||
|
||||
text: number
|
||||
|
||||
type: number
|
||||
|
||||
marks: Array<Mark>
|
||||
|
||||
isActive?: boolean
|
||||
|
||||
isToday?: boolean
|
||||
|
||||
isBeforeMin?: boolean
|
||||
|
||||
isAfterMax?: boolean
|
||||
|
||||
isDisabled?: boolean
|
||||
|
||||
isSelected?: boolean
|
||||
|
||||
isSelectedHead?: boolean
|
||||
|
||||
isSelectedTail?: boolean
|
||||
}
|
||||
|
||||
export interface SelectedDate {
|
||||
end?: Calendar.DateArg
|
||||
|
||||
start: Calendar.DateArg
|
||||
}
|
||||
|
||||
export interface GroupOptions {
|
||||
validDates: Array<ValidDate>
|
||||
|
||||
marks: Array<Mark>
|
||||
|
||||
format: string
|
||||
|
||||
selectedDates: Array<SelectedDate>
|
||||
|
||||
minDate?: DateArg
|
||||
|
||||
maxDate?: DateArg
|
||||
}
|
||||
|
||||
export type List<T> = Array<T>
|
||||
|
||||
export type ListInfo<T> = {
|
||||
value: number
|
||||
|
||||
list: List<T>
|
||||
}
|
||||
}
|
||||
|
||||
export default Calendar
|
||||
export { Calendar }
|
||||
// #endregion
|
||||
|
||||
// #region AtCalendar
|
||||
export interface AtCalendarPropsBase {
|
||||
format?: string
|
||||
|
||||
validDates?: Array<Calendar.ValidDate>
|
||||
|
||||
minDate?: Calendar.DateArg
|
||||
|
||||
maxDate?: Calendar.DateArg
|
||||
|
||||
isSwiper?: boolean
|
||||
|
||||
marks?: Array<Calendar.Mark>
|
||||
|
||||
monthFormat?: string
|
||||
|
||||
hideArrow?: boolean
|
||||
|
||||
isVertical?: boolean
|
||||
|
||||
className?: Calendar.classNameType
|
||||
|
||||
onClickPreMonth?: () => void
|
||||
|
||||
onClickNextMonth?: () => void
|
||||
|
||||
onSelectDate?: (item: { value: Calendar.SelectedDate }) => void
|
||||
|
||||
onDayClick?: (item: { value: string }) => void
|
||||
|
||||
onDayLongClick?: (item: { value: string }) => void
|
||||
|
||||
onMonthChange?: (value: string) => void
|
||||
}
|
||||
|
||||
export interface AtCalendarSingleSelectedProps extends AtCalendarPropsBase {
|
||||
isMultiSelect?: false
|
||||
|
||||
currentDate?: Calendar.DateArg
|
||||
}
|
||||
|
||||
export interface AtCalendarMutilSelectedProps extends AtCalendarPropsBase {
|
||||
isMultiSelect?: true
|
||||
|
||||
currentDate?: Calendar.SelectedDate
|
||||
}
|
||||
|
||||
export type AtCalendarProps =
|
||||
| AtCalendarSingleSelectedProps
|
||||
| AtCalendarMutilSelectedProps
|
||||
|
||||
export interface AtCalendarDefaultProps {
|
||||
format: string
|
||||
|
||||
isSwiper: boolean
|
||||
|
||||
validDates: Array<Calendar.ValidDate>
|
||||
|
||||
marks: Array<Calendar.Mark>
|
||||
|
||||
currentDate: Calendar.DateArg | Calendar.SelectedDate
|
||||
|
||||
monthFormat: string
|
||||
|
||||
hideArrow: boolean
|
||||
|
||||
isVertical: boolean
|
||||
|
||||
isMultiSelect: boolean
|
||||
|
||||
selectedDates: Array<Calendar.SelectedDate>
|
||||
}
|
||||
|
||||
export interface AtCalendarState {
|
||||
generateDate: number
|
||||
|
||||
selectedDate: Calendar.SelectedDate
|
||||
}
|
||||
|
||||
export type AtCalendarPropsWithDefaults = AtCalendarProps &
|
||||
AtCalendarDefaultProps
|
||||
// #endregion
|
||||
|
||||
// #region AtCalendarController
|
||||
export interface AtCalendarControllerProps {
|
||||
generateDate: Calendar.DateArg
|
||||
|
||||
minDate?: Calendar.DateArg
|
||||
|
||||
maxDate?: Calendar.DateArg
|
||||
|
||||
hideArrow: boolean
|
||||
|
||||
monthFormat: string
|
||||
|
||||
onPreMonth: () => void
|
||||
|
||||
onNextMonth: () => void
|
||||
|
||||
onSelectDate: (e: BaseEvent) => void
|
||||
}
|
||||
|
||||
export interface AtCalendarControllerState { }
|
||||
// #endregion
|
||||
|
||||
// #region AtCalendarBody
|
||||
export type AtCalendarBodyListGroup = Array<Calendar.ListInfo<Calendar.Item>>
|
||||
|
||||
export interface AtCalendarBodyProps {
|
||||
format: string
|
||||
|
||||
validDates: Array<Calendar.ValidDate>
|
||||
|
||||
marks: Array<Calendar.Mark>
|
||||
|
||||
isSwiper: boolean
|
||||
|
||||
minDate?: Calendar.DateArg
|
||||
|
||||
maxDate?: Calendar.DateArg
|
||||
|
||||
isVertical: boolean
|
||||
|
||||
generateDate: number
|
||||
|
||||
selectedDate: Calendar.SelectedDate
|
||||
|
||||
selectedDates: Array<Calendar.SelectedDate> | []
|
||||
|
||||
onDayClick: (item: Calendar.Item) => void
|
||||
|
||||
onSwipeMonth: (vectorCount: number) => void
|
||||
|
||||
onLongClick: (item: Calendar.Item) => void
|
||||
}
|
||||
|
||||
export interface AtCalendarBodyState {
|
||||
|
||||
temporaryCalendarWeek: any
|
||||
temporaryCalendar: any
|
||||
|
||||
isFolding: boolean
|
||||
|
||||
isAnimate: boolean
|
||||
|
||||
offsetSize: number
|
||||
|
||||
listGroup: AtCalendarBodyListGroup
|
||||
}
|
||||
// #endregion
|
||||
Loading…
Reference in New Issue