✨ feat:新增日历组件
This commit is contained in:
parent
b0d0791fcc
commit
4822150647
@ -1,7 +1,7 @@
|
||||
import { formatImgUrl } from './format'
|
||||
import { analysisShortCodeApi } from './shortCode'
|
||||
import Taro from '@tarojs/taro'
|
||||
|
||||
import { SelectorQuery } from '@tarojs/taro/types/index'
|
||||
/**
|
||||
* 防抖
|
||||
* @param {*} fn
|
||||
@ -107,6 +107,33 @@ export const dataLoadingStatus = ({ list = [], total = 0, status = false }: { li
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function delay(delayTime = 25): Promise<null> {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve()
|
||||
}, delayTime)
|
||||
})
|
||||
}
|
||||
|
||||
function delayQuerySelector(
|
||||
selectorStr: string,
|
||||
delayTime = 500
|
||||
): Promise<any[]> {
|
||||
return new Promise(resolve => {
|
||||
const selector: SelectorQuery = Taro.createSelectorQuery()
|
||||
delay(delayTime).then(() => {
|
||||
selector
|
||||
.select(selectorStr)
|
||||
.boundingClientRect()
|
||||
.exec((res: any[]) => {
|
||||
resolve(res)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//全局分享监听
|
||||
export const shareShop = () => {
|
||||
const page = Taro.getCurrentInstance().page
|
||||
@ -142,3 +169,6 @@ export const shareShop = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
export {
|
||||
delayQuerySelector
|
||||
}
|
365
src/components/calendar/body/index.tsx
Normal file
365
src/components/calendar/body/index.tsx
Normal file
@ -0,0 +1,365 @@
|
||||
import classnames from 'classnames'
|
||||
import dayjs from 'dayjs'
|
||||
import React from 'react'
|
||||
import { Swiper, SwiperItem, View } from '@tarojs/components'
|
||||
import {
|
||||
BaseEventOrig,
|
||||
ITouch,
|
||||
ITouchEvent
|
||||
} from '@tarojs/components/types/common'
|
||||
import {
|
||||
AtCalendarBodyListGroup,
|
||||
AtCalendarBodyProps,
|
||||
AtCalendarBodyState,
|
||||
Calendar
|
||||
} from '../../../types/calendar'
|
||||
import { delayQuerySelector } from '@/common/util'
|
||||
import generateCalendarGroup from '../common/helper'
|
||||
import AtCalendarDateList from '../ui/date-list/index'
|
||||
import AtCalendarDayList from '../ui/day-list/index'
|
||||
|
||||
const ANIMTE_DURATION = 300
|
||||
|
||||
const defaultProps: Partial<AtCalendarBodyProps> = {
|
||||
marks: [],
|
||||
selectedDate: {
|
||||
end: Date.now(),
|
||||
start: Date.now()
|
||||
},
|
||||
format: 'YYYY-MM-DD',
|
||||
generateDate: Date.now()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
public componentDidMount(): void {
|
||||
delayQuerySelector('.at-calendar-slider__main').then(res => {
|
||||
this.maxWidth = res[0].width
|
||||
})
|
||||
}
|
||||
|
||||
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?: Function): void => {
|
||||
this.setState(
|
||||
{
|
||||
isAnimate: true
|
||||
},
|
||||
() => {
|
||||
this.setState({
|
||||
offsetSize: offset
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.setState(
|
||||
{
|
||||
isAnimate: false
|
||||
},
|
||||
() => {
|
||||
callback && 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
|
||||
}
|
||||
|
||||
public render(): JSX.Element {
|
||||
const { isSwiper } = this.props
|
||||
const { isAnimate, offsetSize, listGroup } = this.state
|
||||
|
||||
if (!isSwiper) {
|
||||
return (
|
||||
<View
|
||||
className={classnames(
|
||||
'main',
|
||||
'at-calendar-slider__main',
|
||||
`at-calendar-slider__main--${process.env.TARO_ENV}`
|
||||
)}
|
||||
>
|
||||
<AtCalendarDayList />
|
||||
<View className='main__body body'>
|
||||
<View className='body__slider body__slider--now'>
|
||||
<AtCalendarDateList
|
||||
list={listGroup[1].list}
|
||||
onClick={this.props.onDayClick}
|
||||
onLongClick={this.props.onLongClick}
|
||||
/>
|
||||
</View>
|
||||
</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={listGroup[1].list}
|
||||
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')}
|
||||
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={item.list}
|
||||
onClick={this.props.onDayClick}
|
||||
onLongClick={this.props.onLongClick}
|
||||
/>
|
||||
</SwiperItem>
|
||||
))}
|
||||
</Swiper>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
5
src/components/calendar/common/constant.ts
Normal file
5
src/components/calendar/common/constant.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export const TYPE_PRE_MONTH = -1
|
||||
|
||||
export const TYPE_NOW_MONTH = 0
|
||||
|
||||
export const TYPE_NEXT_MONTH = 1
|
118
src/components/calendar/common/helper.ts
Normal file
118
src/components/calendar/common/helper.ts
Normal file
@ -0,0 +1,118 @@
|
||||
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 as Array<Calendar.Mark>) = [{
|
||||
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').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).startOf('month')
|
||||
}
|
124
src/components/calendar/common/plugins.ts
Normal file
124
src/components/calendar/common/plugins.ts
Normal file
@ -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 =>
|
||||
dayjs(mark.value).startOf('day').isSame(_value)
|
||||
)
|
||||
|
||||
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 =>
|
||||
dayjs(date.value).startOf('day').isSame(_value)
|
||||
)
|
||||
|
||||
item.isDisabled = !isInclude
|
||||
}
|
||||
|
||||
delete item._value
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
export default [handleActive, handleMarks, handleDisabled, handleValid]
|
76
src/components/calendar/controller/index.tsx
Normal file
76
src/components/calendar/controller/index.tsx
Normal file
@ -0,0 +1,76 @@
|
||||
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'>
|
||||
{hideArrow ? null : (
|
||||
<View
|
||||
className={classnames('controller__arrow controller__arrow--left', {
|
||||
'controller__arrow--disabled': isMinMonth
|
||||
})}
|
||||
onClick={this.props.onPreMonth.bind(this, isMinMonth)}
|
||||
/>
|
||||
)}
|
||||
<Picker
|
||||
mode='date'
|
||||
fields='month'
|
||||
end={maxDateValue}
|
||||
start={minDateValue}
|
||||
onChange={this.props.onSelectDate}
|
||||
value={dayjsDate.format('YYYY-MM')}
|
||||
>
|
||||
<Text className='controller__info'>
|
||||
{dayjsDate.format(monthFormat)}
|
||||
</Text>
|
||||
</Picker>
|
||||
{hideArrow ? null : (
|
||||
<View
|
||||
className={classnames(
|
||||
'controller__arrow controller__arrow--right',
|
||||
{
|
||||
'controller__arrow--disabled': isMaxMonth
|
||||
}
|
||||
)}
|
||||
onClick={this.props.onNextMonth.bind(this, isMaxMonth)}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
319
src/components/calendar/index.tsx
Normal file
319
src/components/calendar/index.tsx
Normal file
@ -0,0 +1,319 @@
|
||||
import classnames from 'classnames'
|
||||
import dayjs, { Dayjs } from 'dayjs'
|
||||
import React from 'react'
|
||||
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 defaultProps: AtCalendarDefaultProps = {
|
||||
validDates: [],
|
||||
marks: [],
|
||||
isSwiper: true,
|
||||
hideArrow: false,
|
||||
isVertical: false,
|
||||
selectedDates: [],
|
||||
isMultiSelect: false,
|
||||
format: 'YYYY-MM-DD',
|
||||
currentDate: Date.now(),
|
||||
monthFormat: 'YYYY年MM月'
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
const stateValue: Partial<AtCalendarState> = {
|
||||
selectedDate: this.getSelectedDate(value.valueOf())
|
||||
}
|
||||
|
||||
const dayjsGenerateDate: Dayjs = value.startOf('month')
|
||||
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()
|
||||
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()
|
||||
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
private handleDayClick = (item: Calendar.Item): void => {
|
||||
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
|
||||
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>
|
||||
)
|
||||
}
|
||||
}
|
80
src/components/calendar/ui/date-list/index.tsx
Normal file
80
src/components/calendar/ui/date-list/index.tsx
Normal file
@ -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>
|
||||
)
|
||||
}
|
||||
}
|
20
src/components/calendar/ui/day-list/index.tsx
Normal file
20
src/components/calendar/ui/day-list/index.tsx
Normal file
@ -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>
|
||||
)
|
||||
}
|
||||
}
|
182
src/pages/refundPage/components/pickerTime/index.scss
Normal file
182
src/pages/refundPage/components/pickerTime/index.scss
Normal file
@ -0,0 +1,182 @@
|
||||
@import '../variables/default.scss';
|
||||
@import '../mixins/index.scss';
|
||||
|
||||
.at-calendar {
|
||||
overflow: hidden;
|
||||
|
||||
/* elements */
|
||||
&__header {
|
||||
.header__flex {
|
||||
@include display-flex;
|
||||
@include align-items(center);
|
||||
|
||||
height: 72px;
|
||||
color: $at-calendar-header-color;
|
||||
text-align: center;
|
||||
|
||||
&-item {
|
||||
@include flex(0 0 calc(100% / 7));
|
||||
|
||||
font-size: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__list {
|
||||
&.flex {
|
||||
@include display-flex;
|
||||
@include align-items();
|
||||
@include flex-wrap(wrap);
|
||||
|
||||
color: $at-calendar-day-color;
|
||||
|
||||
.flex__item {
|
||||
@include flex(0 0 calc(100% / 7));
|
||||
|
||||
font-size: 30px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
margin: 5px 0;
|
||||
|
||||
&-container {
|
||||
@include align-items(center);
|
||||
@include display-flex;
|
||||
|
||||
width: $at-calendar-day-size;
|
||||
height: $at-calendar-day-size;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 50%;
|
||||
|
||||
.container-text {
|
||||
@include flex;
|
||||
}
|
||||
}
|
||||
|
||||
&-extra {
|
||||
.extra-marks {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
line-height: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
|
||||
.mark {
|
||||
width: $at-calendar-mark-size;
|
||||
height: $at-calendar-mark-size;
|
||||
margin-right: 4px;
|
||||
display: inline-block;
|
||||
background-color: $at-calendar-main-color;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&--today {
|
||||
color: $at-calendar-main-color;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
&--blur {
|
||||
color: #e1e4e7;
|
||||
}
|
||||
|
||||
&--selected {
|
||||
color: white;
|
||||
background-color: rgba($color: $at-calendar-main-color, $alpha: 0.7);
|
||||
|
||||
&-head {
|
||||
border-top-left-radius: 40px;
|
||||
border-bottom-left-radius: 40px;
|
||||
}
|
||||
|
||||
&-tail {
|
||||
border-top-right-radius: 40px;
|
||||
border-bottom-right-radius: 40px;
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line */
|
||||
.extra-marks .mark {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
&-head.flex__item--selected-tail {
|
||||
background-color: transparent;
|
||||
|
||||
.flex__item-container {
|
||||
background-color: rgba(
|
||||
$color: $at-calendar-main-color,
|
||||
$alpha: 0.7
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__controller {
|
||||
@include display-flex;
|
||||
@include align-items(center);
|
||||
@include justify-content(center);
|
||||
|
||||
margin-bottom: 20px;
|
||||
|
||||
.controller__arrow {
|
||||
@include flex(0 0 40px);
|
||||
|
||||
height: 40px;
|
||||
border-radius: 12px;
|
||||
display: inline-block;
|
||||
background-size: 16px 24px;
|
||||
background-position: center;
|
||||
background-color: #f7f8fc;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAYCAYAAADzoH0MAAAAAXNSR0IArs4c6QAAAnFJREFUOBGVVF1rE0EUnXt3tzFtWmqjKYKfqIhVa1L8FQVRWtwnXwRhidXGDwQf81oCUQMioZRCHwNSgiD4lD9QSYVKsA8KbaW1jbamX8adnWsmMnESbYz7cs6ee8/ZnZm7y9h/Xk/Gs70TE9lOZQNFWsGx1IvDJoozxNDttNpmHOfyTssBj59PHxceP6keREDlYPvBGUMJzTD5LHuKhHtC70EEQe72atMAIoLu0MWzRPxInZnEdxZib2I37L2XEI/HsSvYd44AQrqZIW5b3J8fHR0sS/2ve5DJZIzFFexnSD262QAs+c1js45zyVU6KqIwnU5bS58x0mhGhusbaz153Sw9dW+QSr3yCdwJe4wCKlCigbAWiw7PAYDQdclrAclkxk8+iDBifr3JMq3lO86VQsVMuq549RQSU687mOcNANE+VfiFxuLd6NX3e5llD8qjskqb54E8n24mk5Yf3B6ab2auBsgGC8Q7QOJ1AS6ExrSZ12s6r57CyIi99cNgswywtkkIzDB2eSSdftmuGxp57RgfOfY38HlvRWVNqgmYsDb57sDkZK5hb1RHZQ9+U8bu37S/MtOc0zUg8G2U1yOV4WrTdcXrAqT4MDq0yokXVINEwb32pS9WOJfLmboueW0OGgtP05mj3IXTum6iuXHogDtr27an9D/eQBVijr2AiB/VvUQuePenNXZBfmhKrxEl6Hjv1vAHA2lJ1wRBcH9vf5+cH6k3DZANsei1eWCwIrm6uOf1Jsenq8v7Z4ActFJxrsBMo6gC0GAebPHq/Z6bqJoVyn/EQpGFK08MmF2B/Oj1wZKqtYzxeM5MJKY6dMNPQnnePR8FubkAAAAASUVORK5CYII=");
|
||||
|
||||
&--right {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.controller__info {
|
||||
@include flex(0 0 auto);
|
||||
|
||||
font-size: 30px;
|
||||
margin-left: 40px;
|
||||
margin-right: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.at-calendar-slider__main {
|
||||
.main__body {
|
||||
@include display-flex;
|
||||
|
||||
width: 100%;
|
||||
|
||||
&--animate {
|
||||
transition: transform 300ms cubic-bezier(0.36, 0.66, 0.04, 1);
|
||||
}
|
||||
|
||||
.body__slider {
|
||||
@include flex(0 0 100%);
|
||||
}
|
||||
}
|
||||
|
||||
&--weapp,
|
||||
&--swan {
|
||||
.main__body {
|
||||
height: 480px;
|
||||
}
|
||||
}
|
||||
}
|
146
src/pages/refundPage/components/pickerTime/index.tsx
Normal file
146
src/pages/refundPage/components/pickerTime/index.tsx
Normal file
@ -0,0 +1,146 @@
|
||||
import Popup from '@/components/popup'
|
||||
import React, { useState, memo, useEffect } from "react";
|
||||
import Taro from "@tarojs/taro";
|
||||
import { View } from "@tarojs/components";
|
||||
// import { AtIcon } from 'taro-ui'
|
||||
import './index.scss'
|
||||
|
||||
|
||||
|
||||
|
||||
interface Props {
|
||||
showTime: true | false,
|
||||
closePopup?: () => void
|
||||
}
|
||||
export default memo((props: Props) => {
|
||||
const {
|
||||
showTime = false,
|
||||
closePopup
|
||||
} = props
|
||||
//每月多少天
|
||||
let MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
||||
const WEEK_NAMES = ['日', '一', '二', '三', '四', '五', '六'];
|
||||
const LINES = [1, 2, 3, 4, 5, 6];
|
||||
const [year, setLoinsYear] = useState(0);
|
||||
let nowTime = new Date(Date.parse(new Date().toString()));
|
||||
const [month, seLoinstMonth] = useState(nowTime.getMonth());
|
||||
const [currentDate, setcurrentDate] = useState(new Date());
|
||||
const [tag, setTag] = useState(false);
|
||||
//获取当前月份
|
||||
const getMonth = (date: Date): number => {
|
||||
return date.getMonth();
|
||||
}
|
||||
//获取当前年份
|
||||
const getFullYear = (date: Date): number => {
|
||||
// console.log(date.getFullYear())
|
||||
return date.getFullYear();
|
||||
}
|
||||
|
||||
const getCurrentMonthDays = (month: number, year: number): number => {
|
||||
let _year = year + currentDate.getFullYear();
|
||||
if (_year % 100 != 0 && _year % 4 == 0 || _year % 400 == 0) {
|
||||
MONTH_DAYS = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
||||
}
|
||||
return MONTH_DAYS[month]
|
||||
}
|
||||
//当前月第一天是周几
|
||||
const getDateByYearMonth = (year: number, month: number, day: number = 1): Date => {
|
||||
var date = new Date()
|
||||
date.setFullYear(year)
|
||||
date.setMonth(month, day)
|
||||
return date
|
||||
}
|
||||
const getWeeksByFirstDay = (year: number, month: number): number => {
|
||||
var date = getDateByYearMonth(year, month)
|
||||
return date.getDay()
|
||||
}
|
||||
const getDayText = (line: number, weekIndex: number, weekDay: number, monthDays: number): any => {
|
||||
var number = line * 7 + weekIndex - weekDay + 1
|
||||
if (number <= 0 || number > monthDays) {
|
||||
return <View className="day-c" key={weekIndex}> </View>
|
||||
}
|
||||
return <View className="day-c" key={weekIndex}>
|
||||
<View className="day" onClick={() => clickItem(line)}>{number}</View>
|
||||
</View>
|
||||
}
|
||||
|
||||
const setCurrentYearMonth = (date) => {
|
||||
var month = getMonth(date)
|
||||
var year = getFullYear(date)
|
||||
setLoinsYear(year);
|
||||
seLoinstMonth(month)
|
||||
setTag(false)
|
||||
}
|
||||
|
||||
const monthChange = (monthChanged: number) => {
|
||||
if (tag) {
|
||||
return;
|
||||
} else {
|
||||
setTag(true)
|
||||
}
|
||||
|
||||
var monthAfter = month + monthChanged
|
||||
var date = getDateByYearMonth(year, monthAfter)
|
||||
setCurrentYearMonth(date)
|
||||
}
|
||||
const formatNumber = (num: number): string => {
|
||||
var _num = num + 1
|
||||
return _num < 10 ? `0${_num}` : `${_num}`
|
||||
}
|
||||
|
||||
// let monthDays = getCurrentMonthDays(month);
|
||||
let weekDay = getWeeksByFirstDay(year, month);
|
||||
|
||||
let _startX = 0;
|
||||
const clickItem = (item) => {
|
||||
console.log(item, 666)
|
||||
}
|
||||
return (
|
||||
<Popup title={'选择时间'} show={showTime} onClose={() => closePopup?.()}>
|
||||
<View className="loins-calendar"
|
||||
onTouchEnd={(val) => {
|
||||
if (_startX > val.changedTouches[0]['clientX'] + 30) {
|
||||
monthChange(1);
|
||||
}
|
||||
if (_startX < val.changedTouches[0]['clientX'] - 30) {
|
||||
monthChange(-1);
|
||||
}
|
||||
}} onTouchStart={(val) => {
|
||||
_startX = val.changedTouches[0]['clientX']
|
||||
|
||||
}}
|
||||
>
|
||||
<View className="loins-calendar-tabbar">
|
||||
<View>
|
||||
{/* <AtIcon value='chevron-left' size='30' color='#297AF8' onClick={() => {
|
||||
monthChange(-1);
|
||||
}}>
|
||||
</AtIcon> */}
|
||||
</View>
|
||||
<View className="loins-calendar-title">{year + currentDate.getFullYear()} 年 {formatNumber(month)}月</View>
|
||||
<View>
|
||||
{/* <AtIcon value='chevron-right' size='30' color='#297AF8' onClick={() => {
|
||||
monthChange(1);
|
||||
}}></AtIcon> */}
|
||||
</View>
|
||||
</View>
|
||||
{
|
||||
WEEK_NAMES.map((week, key) => {
|
||||
return <View className="title-c" key={key}>{week}</View>
|
||||
})
|
||||
}
|
||||
{
|
||||
LINES.map((l, key) => {
|
||||
return <View key={key} className="day-content" >
|
||||
{
|
||||
WEEK_NAMES.map((week, index) => {
|
||||
return getDayText(key, index, weekDay, getCurrentMonthDays(month, year))
|
||||
})
|
||||
}
|
||||
</View>
|
||||
})
|
||||
}
|
||||
</View>
|
||||
</Popup>
|
||||
)
|
||||
})
|
@ -1,64 +1,182 @@
|
||||
.loins-calendar {
|
||||
@import '../../../../styles/variables/default.scss';
|
||||
@import '../../../../styles/mixins/index.scss';
|
||||
|
||||
background-color: #ffffff;
|
||||
.at-calendar {
|
||||
overflow: hidden;
|
||||
|
||||
&-tabbar {
|
||||
padding: 43px 100px 30px 100px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
/* elements */
|
||||
&__header {
|
||||
.header__flex {
|
||||
@include display-flex;
|
||||
@include align-items(center);
|
||||
|
||||
&-title {
|
||||
font-size: 36px;
|
||||
font-family: Helvetica;
|
||||
color: #333333;
|
||||
line-height: 48px;
|
||||
}
|
||||
height: 72px;
|
||||
color: $at-calendar-header-color;
|
||||
text-align: center;
|
||||
|
||||
&-item {
|
||||
@include flex(0 0 calc(100% / 7));
|
||||
|
||||
.title-c {
|
||||
display: inline-block;
|
||||
width: calc(100% / 7);
|
||||
text-align: center;
|
||||
font-size: 30px;
|
||||
font-weight: 400;
|
||||
color: #606060;
|
||||
line-height: 40px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
width: 662rpx;
|
||||
margin-left: 44rpx;
|
||||
&__list {
|
||||
&.flex {
|
||||
@include display-flex;
|
||||
@include align-items();
|
||||
@include flex-wrap(wrap);
|
||||
|
||||
.day-content {
|
||||
color: $at-calendar-day-color;
|
||||
|
||||
.flex__item {
|
||||
@include flex(0 0 calc(100% / 7));
|
||||
|
||||
font-size: 30px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
margin: 5px 0;
|
||||
|
||||
.day-c {
|
||||
display: inline-block;
|
||||
width: calc(100% / 7);
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
&-container {
|
||||
@include align-items(center);
|
||||
@include display-flex;
|
||||
|
||||
.day {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
// background: #337FFF;
|
||||
// border-radius: 16px;
|
||||
line-height: 80px;
|
||||
font-size: 32px;
|
||||
font-weight: 500;
|
||||
color: #000;
|
||||
text-align: center;
|
||||
}
|
||||
width: $at-calendar-day-size;
|
||||
height: $at-calendar-day-size;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 50%;
|
||||
|
||||
.desc {
|
||||
height: 28px;
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
color: #202020;
|
||||
text-align: center;
|
||||
}
|
||||
.container-text {
|
||||
@include flex;
|
||||
}
|
||||
}
|
||||
|
||||
&-extra {
|
||||
.extra-marks {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
line-height: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
|
||||
.mark {
|
||||
width: $at-calendar-mark-size;
|
||||
height: $at-calendar-mark-size;
|
||||
margin-right: 4px;
|
||||
display: inline-block;
|
||||
background-color: $at-calendar-main-color;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&--today {
|
||||
color: $at-calendar-main-color;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
&--blur {
|
||||
color: #e1e4e7;
|
||||
}
|
||||
|
||||
&--selected {
|
||||
color: white;
|
||||
background-color: rgba($color: $at-calendar-main-color, $alpha: 0.7);
|
||||
|
||||
&-head {
|
||||
border-top-left-radius: 40px;
|
||||
border-bottom-left-radius: 40px;
|
||||
}
|
||||
|
||||
&-tail {
|
||||
border-top-right-radius: 40px;
|
||||
border-bottom-right-radius: 40px;
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line */
|
||||
.extra-marks .mark {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
&-head.flex__item--selected-tail {
|
||||
background-color: transparent;
|
||||
|
||||
.flex__item-container {
|
||||
background-color: rgba(
|
||||
$color: $at-calendar-main-color,
|
||||
$alpha: 0.7
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__controller {
|
||||
@include display-flex;
|
||||
@include align-items(center);
|
||||
@include justify-content(center);
|
||||
|
||||
margin-bottom: 20px;
|
||||
|
||||
.controller__arrow {
|
||||
@include flex(0 0 40px);
|
||||
|
||||
height: 40px;
|
||||
border-radius: 12px;
|
||||
display: inline-block;
|
||||
background-size: 16px 24px;
|
||||
background-position: center;
|
||||
background-color: #f7f8fc;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAYCAYAAADzoH0MAAAAAXNSR0IArs4c6QAAAnFJREFUOBGVVF1rE0EUnXt3tzFtWmqjKYKfqIhVa1L8FQVRWtwnXwRhidXGDwQf81oCUQMioZRCHwNSgiD4lD9QSYVKsA8KbaW1jbamX8adnWsmMnESbYz7cs6ee8/ZnZm7y9h/Xk/Gs70TE9lOZQNFWsGx1IvDJoozxNDttNpmHOfyTssBj59PHxceP6keREDlYPvBGUMJzTD5LHuKhHtC70EEQe72atMAIoLu0MWzRPxInZnEdxZib2I37L2XEI/HsSvYd44AQrqZIW5b3J8fHR0sS/2ve5DJZIzFFexnSD262QAs+c1js45zyVU6KqIwnU5bS58x0mhGhusbaz153Sw9dW+QSr3yCdwJe4wCKlCigbAWiw7PAYDQdclrAclkxk8+iDBifr3JMq3lO86VQsVMuq549RQSU687mOcNANE+VfiFxuLd6NX3e5llD8qjskqb54E8n24mk5Yf3B6ab2auBsgGC8Q7QOJ1AS6ExrSZ12s6r57CyIi99cNgswywtkkIzDB2eSSdftmuGxp57RgfOfY38HlvRWVNqgmYsDb57sDkZK5hb1RHZQ9+U8bu37S/MtOc0zUg8G2U1yOV4WrTdcXrAqT4MDq0yokXVINEwb32pS9WOJfLmboueW0OGgtP05mj3IXTum6iuXHogDtr27an9D/eQBVijr2AiB/VvUQuePenNXZBfmhKrxEl6Hjv1vAHA2lJ1wRBcH9vf5+cH6k3DZANsei1eWCwIrm6uOf1Jsenq8v7Z4ActFJxrsBMo6gC0GAebPHq/Z6bqJoVyn/EQpGFK08MmF2B/Oj1wZKqtYzxeM5MJKY6dMNPQnnePR8FubkAAAAASUVORK5CYII=");
|
||||
|
||||
&--right {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.controller__info {
|
||||
@include flex(0 0 auto);
|
||||
|
||||
font-size: 30px;
|
||||
margin-left: 40px;
|
||||
margin-right: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.at-calendar-slider__main {
|
||||
.main__body {
|
||||
@include display-flex;
|
||||
|
||||
width: 100%;
|
||||
|
||||
&--animate {
|
||||
transition: transform 300ms cubic-bezier(0.36, 0.66, 0.04, 1);
|
||||
}
|
||||
|
||||
.body__slider {
|
||||
@include flex(0 0 100%);
|
||||
}
|
||||
}
|
||||
|
||||
&--weapp,
|
||||
&--swan {
|
||||
.main__body {
|
||||
height: 480px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import Popup from '@/components/popup'
|
||||
import React, { useState, memo, useEffect } from "react";
|
||||
import Taro from "@tarojs/taro";
|
||||
import { View } from "@tarojs/components";
|
||||
import Taro, { getCurrentInstance } from "@tarojs/taro";
|
||||
import { View, Swiper, SwiperItem, Text } from "@tarojs/components";
|
||||
// import { AtIcon } from 'taro-ui'
|
||||
import './index.scss'
|
||||
|
||||
|
||||
import classnames from "classnames";
|
||||
import AtCalendar from "@/components/calendar/index"
|
||||
|
||||
|
||||
interface Props {
|
||||
@ -13,134 +13,15 @@ interface Props {
|
||||
closePopup?: () => void
|
||||
}
|
||||
export default memo((props: Props) => {
|
||||
const {
|
||||
let {
|
||||
showTime = false,
|
||||
closePopup
|
||||
} = props
|
||||
//每月多少天
|
||||
let MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
||||
const WEEK_NAMES = ['日', '一', '二', '三', '四', '五', '六'];
|
||||
const LINES = [1, 2, 3, 4, 5, 6];
|
||||
const [year, setLoinsYear] = useState(0);
|
||||
let nowTime = new Date(Date.parse(new Date().toString()));
|
||||
const [month, seLoinstMonth] = useState(nowTime.getMonth());
|
||||
const [currentDate, setcurrentDate] = useState(new Date());
|
||||
const [tag, setTag] = useState(false);
|
||||
//获取当前月份
|
||||
const getMonth = (date: Date): number => {
|
||||
return date.getMonth();
|
||||
}
|
||||
//获取当前年份
|
||||
const getFullYear = (date: Date): number => {
|
||||
// console.log(date.getFullYear())
|
||||
return date.getFullYear();
|
||||
}
|
||||
|
||||
const getCurrentMonthDays = (month: number, year: number): number => {
|
||||
let _year = year + currentDate.getFullYear();
|
||||
if (_year % 100 != 0 && _year % 4 == 0 || _year % 400 == 0) {
|
||||
MONTH_DAYS = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
||||
}
|
||||
return MONTH_DAYS[month]
|
||||
}
|
||||
//当前月第一天是周几
|
||||
const getDateByYearMonth = (year: number, month: number, day: number = 1): Date => {
|
||||
var date = new Date()
|
||||
date.setFullYear(year)
|
||||
date.setMonth(month, day)
|
||||
return date
|
||||
}
|
||||
const getWeeksByFirstDay = (year: number, month: number): number => {
|
||||
var date = getDateByYearMonth(year, month)
|
||||
return date.getDay()
|
||||
}
|
||||
const getDayText = (line: number, weekIndex: number, weekDay: number, monthDays: number): any => {
|
||||
var number = line * 7 + weekIndex - weekDay + 1
|
||||
if (number <= 0 || number > monthDays) {
|
||||
return <View className="day-c" key={weekIndex}> </View>
|
||||
}
|
||||
return <View className="day-c" key={weekIndex}>
|
||||
<View className="day" onClick={() => clickItem(line)}>{number}</View>
|
||||
</View>
|
||||
}
|
||||
|
||||
const setCurrentYearMonth = (date) => {
|
||||
var month = getMonth(date)
|
||||
var year = getFullYear(date)
|
||||
setLoinsYear(year);
|
||||
seLoinstMonth(month)
|
||||
setTag(false)
|
||||
}
|
||||
|
||||
const monthChange = (monthChanged: number) => {
|
||||
if (tag) {
|
||||
return;
|
||||
} else {
|
||||
setTag(true)
|
||||
}
|
||||
|
||||
var monthAfter = month + monthChanged
|
||||
var date = getDateByYearMonth(year, monthAfter)
|
||||
setCurrentYearMonth(date)
|
||||
}
|
||||
const formatNumber = (num: number): string => {
|
||||
var _num = num + 1
|
||||
return _num < 10 ? `0${_num}` : `${_num}`
|
||||
}
|
||||
|
||||
// let monthDays = getCurrentMonthDays(month);
|
||||
let weekDay = getWeeksByFirstDay(year, month);
|
||||
|
||||
let _startX = 0;
|
||||
const clickItem = (item) => {
|
||||
console.log(item, 666)
|
||||
}
|
||||
return (
|
||||
<Popup title={'选择时间'} show={showTime} onClose={() => closePopup?.()}>
|
||||
<View className="loins-calendar"
|
||||
onTouchEnd={(val) => {
|
||||
if (_startX > val.changedTouches[0]['clientX'] + 30) {
|
||||
monthChange(1);
|
||||
}
|
||||
if (_startX < val.changedTouches[0]['clientX'] - 30) {
|
||||
monthChange(-1);
|
||||
}
|
||||
}} onTouchStart={(val) => {
|
||||
_startX = val.changedTouches[0]['clientX']
|
||||
|
||||
}}
|
||||
>
|
||||
<View className="loins-calendar-tabbar">
|
||||
<View>
|
||||
{/* <AtIcon value='chevron-left' size='30' color='#297AF8' onClick={() => {
|
||||
monthChange(-1);
|
||||
}}>
|
||||
</AtIcon> */}
|
||||
</View>
|
||||
<View className="loins-calendar-title">{year + currentDate.getFullYear()} 年 {formatNumber(month)}月</View>
|
||||
<View>
|
||||
{/* <AtIcon value='chevron-right' size='30' color='#297AF8' onClick={() => {
|
||||
monthChange(1);
|
||||
}}></AtIcon> */}
|
||||
</View>
|
||||
</View>
|
||||
{
|
||||
WEEK_NAMES.map((week, key) => {
|
||||
return <View className="title-c" key={key}>{week}</View>
|
||||
})
|
||||
}
|
||||
{
|
||||
LINES.map((l, key) => {
|
||||
return <View key={key} className="day-content" >
|
||||
{
|
||||
WEEK_NAMES.map((week, index) => {
|
||||
return getDayText(key, index, weekDay, getCurrentMonthDays(month, year))
|
||||
})
|
||||
}
|
||||
</View>
|
||||
})
|
||||
}
|
||||
</View>
|
||||
</Popup>
|
||||
<AtCalendar />
|
||||
</Popup >
|
||||
)
|
||||
})
|
@ -3,7 +3,7 @@
|
||||
/* Project id 3619513 */
|
||||
// url('/src/styles/iconfont.ttf') format('truetype');
|
||||
src:
|
||||
url('/src/styles/iconfont.ttf?t=1663556335905') format('truetype');
|
||||
url('iconfont.ttf?t=1663556335905') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
|
18
src/styles/mixins/index.scss
Normal file
18
src/styles/mixins/index.scss
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Mixins
|
||||
*/
|
||||
|
||||
/* library */
|
||||
// @import './libs/absolute-center';
|
||||
// @import './libs/clearfix';
|
||||
// @import './libs/line';
|
||||
// @import './libs/overlay';
|
||||
// @import './libs/shade';
|
||||
@import './libs/tint';
|
||||
@import './libs/flex';
|
||||
// @import './libs/border';
|
||||
// @import './libs/active';
|
||||
// @import './libs/disabled';
|
||||
// @import './libs/placeholder';
|
||||
// @import './libs/alignhack';
|
||||
// @import './libs/hairline';
|
50
src/styles/mixins/libs/flex.scss
Normal file
50
src/styles/mixins/libs/flex.scss
Normal file
@ -0,0 +1,50 @@
|
||||
@mixin display-flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@mixin flex-wrap($value: nowrap) {
|
||||
flex-wrap: $value;
|
||||
}
|
||||
|
||||
@mixin align-items($value: stretch) {
|
||||
align-items: $value;
|
||||
@if $value == flex-start {
|
||||
-webkit-box-align: start;
|
||||
} @else if $value == flex-end {
|
||||
-webkit-box-align: end;
|
||||
} @else {
|
||||
-webkit-box-align: $value;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin align-content($value: flex-start) {
|
||||
align-content: $value;
|
||||
}
|
||||
|
||||
@mixin justify-content($value: flex-start) {
|
||||
justify-content: $value;
|
||||
@if $value == flex-start {
|
||||
-webkit-box-pack: start;
|
||||
} @else if $value == flex-end {
|
||||
-webkit-box-pack: end;
|
||||
} @else if $value == space-between {
|
||||
-webkit-box-pack: justify;
|
||||
} @else {
|
||||
-webkit-box-pack: $value;
|
||||
}
|
||||
}
|
||||
|
||||
/* Flex Item */
|
||||
@mixin flex($fg: 1, $fs: null, $fb: null) {
|
||||
flex: $fg $fs $fb;
|
||||
-webkit-box-flex: $fg;
|
||||
}
|
||||
|
||||
@mixin flex-order($n) {
|
||||
order: $n;
|
||||
-webkit-box-ordinal-group: $n;
|
||||
}
|
||||
|
||||
@mixin align-self($value: auto) {
|
||||
align-self: $value;
|
||||
}
|
23
src/styles/mixins/libs/tint.scss
Normal file
23
src/styles/mixins/libs/tint.scss
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Mixes a color with white. It's different from lighten()
|
||||
*
|
||||
* @param {color} $color
|
||||
* @param {number (percentage)} $percent [The amout of white to be mixed in]
|
||||
* @return {color}
|
||||
*
|
||||
* @example
|
||||
* .element {
|
||||
* background-color: tint(#6ecaa6 , 40%);
|
||||
* }
|
||||
*
|
||||
* // CSS Output
|
||||
* .element {
|
||||
* background-color: #a8dfc9;
|
||||
* }
|
||||
*/
|
||||
@function tint(
|
||||
$color,
|
||||
$percent
|
||||
) {
|
||||
@return mix(#FFF, $color, $percent);
|
||||
}
|
457
src/styles/variables/default.scss
Normal file
457
src/styles/variables/default.scss
Normal file
@ -0,0 +1,457 @@
|
||||
/**
|
||||
* Default variables
|
||||
*/
|
||||
|
||||
@import '../mixins/libs/tint';
|
||||
|
||||
$hd: 2 !default; // 基本单位
|
||||
|
||||
/* The Color of O2Team Brand */
|
||||
$color-brand: #6190E8 !default;
|
||||
$color-brand-light: #78A4F4 !default;
|
||||
$color-brand-dark: #346FC2 !default;
|
||||
|
||||
/* Color */
|
||||
$color-success: #13CE66 !default;
|
||||
$color-error: #FF4949 !default;
|
||||
$color-warning: #FFC82C !default;
|
||||
$color-info: #78A4FA !default;
|
||||
|
||||
/* Color Palette */
|
||||
$color-black-0: #000 !default;
|
||||
$color-black-1: #333 !default;
|
||||
$color-black-2: #7F7F7F !default;
|
||||
$color-black-3: #B2B2B2 !default;
|
||||
|
||||
$color-grey-0: #333 !default;
|
||||
$color-grey-1: #666 !default;
|
||||
$color-grey-2: #999 !default;
|
||||
$color-grey-3: #CCC !default;
|
||||
$color-grey-4: #E5E5E5 !default;
|
||||
$color-grey-5: #F0F0F0 !default;
|
||||
$color-grey-6: #F7F7F7 !default;
|
||||
|
||||
$color-white: #FFF !default;
|
||||
|
||||
/* Text Color */
|
||||
$color-text-base: #333 !default; // 文字的基本色
|
||||
$color-text-base-inverse: #FFF !default; // 反色
|
||||
$color-text-secondary: #36D57D !default; // 辅助色
|
||||
$color-text-placeholder: #C9C9C9 !default;
|
||||
$color-text-disabled: #CCC !default;
|
||||
$color-text-title: #2C405A !default; // 文章标题
|
||||
$color-text-paragraph: #3F536E !default; // 文章段落
|
||||
|
||||
/* Link */
|
||||
$color-link: #6190E8 !default;
|
||||
$color-link-hover: #79A1EB !default;
|
||||
$color-link-active: #4F7DE2 !default;
|
||||
$color-link-disabled: #BFBFBF !default;
|
||||
|
||||
/* 背景色 */
|
||||
$color-bg: #FFF !default;
|
||||
$color-bg-base: #FAFBFC !default;
|
||||
$color-bg-light: #ECF5FD !default;
|
||||
$color-bg-lighter: tint($color-bg-light, 50%) !default;
|
||||
$color-bg-grey: #F7F7F7 !default;
|
||||
|
||||
/* 边框颜色 */
|
||||
$color-border-base: #C5D9E8 !default;
|
||||
$color-border-split: tint($color-border-base, 20%) !default; // 分割线
|
||||
$color-border-light: tint($color-border-base, 30%) !default;
|
||||
$color-border-lighter: tint($color-border-base, 50%) !default;
|
||||
$color-border-lightest: tint($color-border-base, 80%) !default;
|
||||
$color-border-grey: #CCC !default;
|
||||
|
||||
/* 图标颜色 */
|
||||
$color-icon-base: #CCC !default;
|
||||
|
||||
/* Border Radius */
|
||||
$border-radius-sm: 2px * $hd !default;
|
||||
$border-radius-md: 4px * $hd !default;
|
||||
$border-radius-lg: 6px * $hd !default;
|
||||
$border-radius-circle: 50% !default;
|
||||
|
||||
/* 透明度 */
|
||||
$opacity-active: 0.6 !default; // Button 等组件点击态额透明度
|
||||
$opacity-disabled: 0.3 !default; // Button 等组件禁用态的透明度
|
||||
|
||||
/* Font */
|
||||
$font-size-xs: 10px * $hd !default; // 非常用字号,用于标签
|
||||
$font-size-sm: 12px * $hd !default; // 用于辅助信息
|
||||
$font-size-base: 14px * $hd !default; // 常用字号
|
||||
$font-size-lg: 16px * $hd !default; // 常规标题
|
||||
$font-size-xl: 18px * $hd !default; // 大标题
|
||||
$font-size-xxl: 20px * $hd !default; // 用于大号的数字
|
||||
|
||||
/* Line Height */
|
||||
$line-height-base: 1 !default; // 单行
|
||||
$line-height-en: 1.3 !default; // 英文多行
|
||||
$line-height-zh: 1.5 !default; // 中文多行
|
||||
|
||||
/* 水平间距 */
|
||||
$spacing-h-sm: 5px * $hd !default;
|
||||
$spacing-h-md: 8px * $hd !default;
|
||||
$spacing-h-lg: 12px * $hd !default;
|
||||
$spacing-h-xl: 16px * $hd !default;
|
||||
|
||||
/* 垂直间距 */
|
||||
$spacing-v-xs: 3px * $hd !default;
|
||||
$spacing-v-sm: 6px * $hd !default;
|
||||
$spacing-v-md: 9px * $hd !default;
|
||||
$spacing-v-lg: 12px * $hd !default;
|
||||
$spacing-v-xl: 15px * $hd !default;
|
||||
|
||||
/* 图标尺寸 */
|
||||
$icon-size-sm: 18px * $hd !default;
|
||||
$icon-size-md: 22px * $hd !default;
|
||||
$icon-size-lg: 36px * $hd !default;
|
||||
|
||||
/* z-index */
|
||||
$zindex-divider: 100 !default;
|
||||
$zindex-steps: 500 !default;
|
||||
$zindex-tab: 600 !default;
|
||||
$zindex-form: 700 !default;
|
||||
$zindex-nav: 800 !default;
|
||||
$zindex-search-bar: 800 !default;
|
||||
$zindex-indexes: 805 !default;
|
||||
$zindex-flot-layout: 810 !default;
|
||||
$zindex-drawer: 900 !default;
|
||||
$zindex-modal: 1000 !default;
|
||||
$zindex-action-sheet: 1010 !default;
|
||||
$zindex-picker: 1010 !default;
|
||||
$zindex-curtain: 1080 !default;
|
||||
$zindex-message: 1090 !default;
|
||||
$zindex-toast: 1090 !default;
|
||||
|
||||
/* timing function */
|
||||
$timing-func: cubic-bezier(0.36, 0.66, 0.04, 1) !default;
|
||||
|
||||
/**
|
||||
* CSS cubic-bezier timing functions
|
||||
* http://bourbon.io/docs/#timing-functions
|
||||
*/
|
||||
$ease-in-quad: cubic-bezier(0.550, 0.085, 0.680, 0.530) !default;
|
||||
$ease-in-cubic: cubic-bezier(0.550, 0.055, 0.675, 0.190) !default;
|
||||
$ease-in-quart: cubic-bezier(0.895, 0.030, 0.685, 0.220) !default;
|
||||
$ease-in-quint: cubic-bezier(0.755, 0.050, 0.855, 0.060) !default;
|
||||
$ease-in-sine: cubic-bezier(0.470, 0.000, 0.745, 0.715) !default;
|
||||
$ease-in-expo: cubic-bezier(0.950, 0.050, 0.795, 0.035) !default;
|
||||
$ease-in-circ: cubic-bezier(0.600, 0.040, 0.980, 0.335) !default;
|
||||
$ease-in-back: cubic-bezier(0.600, -0.280, 0.735, 0.045) !default;
|
||||
|
||||
$ease-out-quad: cubic-bezier(0.250, 0.460, 0.450, 0.940) !default;
|
||||
$ease-out-cubic: cubic-bezier(0.215, 0.610, 0.355, 1.000) !default;
|
||||
$ease-out-quart: cubic-bezier(0.165, 0.840, 0.440, 1.000) !default;
|
||||
$ease-out-quint: cubic-bezier(0.230, 1.000, 0.320, 1.000) !default;
|
||||
$ease-out-sine: cubic-bezier(0.390, 0.575, 0.565, 1.000) !default;
|
||||
$ease-out-expo: cubic-bezier(0.190, 1.000, 0.220, 1.000) !default;
|
||||
$ease-out-circ: cubic-bezier(0.075, 0.820, 0.165, 1.000) !default;
|
||||
$ease-out-back: cubic-bezier(0.175, 0.885, 0.320, 1.275) !default;
|
||||
|
||||
$ease-in-out-quad: cubic-bezier(0.455, 0.030, 0.515, 0.955) !default;
|
||||
$ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1.000) !default;
|
||||
$ease-in-out-quart: cubic-bezier(0.770, 0.000, 0.175, 1.000) !default;
|
||||
$ease-in-out-quint: cubic-bezier(0.860, 0.000, 0.070, 1.000) !default;
|
||||
$ease-in-out-sine: cubic-bezier(0.445, 0.050, 0.550, 0.950) !default;
|
||||
$ease-in-out-expo: cubic-bezier(1.000, 0.000, 0.000, 1.000) !default;
|
||||
$ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.150, 0.860) !default;
|
||||
$ease-in-out-back: cubic-bezier(0.680, -0.550, 0.265, 1.550) !default;
|
||||
|
||||
/**
|
||||
* 组件变量
|
||||
*/
|
||||
|
||||
/* Accordion */
|
||||
$at-accordion-color-arrow: $color-grey-3 !default;
|
||||
|
||||
/* Activity Indicator */
|
||||
$at-activity-indicator-font-size: 28px !default;
|
||||
$at-activity-indicator-font-color: $color-grey-2 !default;
|
||||
|
||||
/* Avatar */
|
||||
$at-avatar-color: $color-white !default;
|
||||
$at-avatar-bg-color: $color-grey-4 !default;
|
||||
$at-avatar-size-sm: 80px !default;
|
||||
$at-avatar-size-md: 100px !default;
|
||||
$at-avatar-size-lg: 120px !default;
|
||||
|
||||
/* Badge */
|
||||
$at-badge-color: $color-white !default;
|
||||
$at-badge-bg-color: $color-error !default;
|
||||
$at-badge-bg: $at-badge-bg-color !default;
|
||||
$at-badge-font-size: $font-size-xs !default;
|
||||
$at-badge-dot-size: 20px !default;
|
||||
|
||||
/* Button */
|
||||
$at-button-height: 92px !default;
|
||||
$at-button-height-sm: 60px !default;
|
||||
$at-button-color: $color-brand !default;
|
||||
$at-button-border-color-primary: $color-brand !default;
|
||||
$at-button-border-color-secondary: $color-brand !default;
|
||||
$at-button-bg: $at-button-color !default;
|
||||
|
||||
/* Float Button */
|
||||
$at-fab-size: 56px * $hd !default;
|
||||
$at-fab-size-sm: 40px * $hd !default;
|
||||
$at-fab-icon-size: 24px * $hd !default;
|
||||
$at-fab-bg-color: $color-brand;
|
||||
$at-fab-bg-color-active: $color-brand-dark;
|
||||
$at-fab-box-shadow:
|
||||
0 6px 10px -2px rgba(0, 0, 0, 0.2),
|
||||
0 12px 20px 0 rgba(0, 0, 0, 0.14),
|
||||
0 2px 36px 0 rgba(0, 0, 0, 0.12) !default;
|
||||
$at-fab-box-shadow-active:
|
||||
0 14px 16px -8px rgba(0, 0, 0, 0.2),
|
||||
0 24px 34px 4px rgba(0, 0, 0, 0.14),
|
||||
0 10px 44px 8px rgba(0, 0, 0, 0.12) !default;
|
||||
|
||||
/* Calendar */
|
||||
$at-calendar-day-size: 72px !default;
|
||||
$at-calendar-mark-size: 8px !default;
|
||||
$at-calendar-header-color: #B8BFC6 !default;
|
||||
$at-calendar-main-color: $color-brand !default;
|
||||
$at-calendar-day-color: #7C86A2 !default;
|
||||
|
||||
/* Card */
|
||||
$at-card-thumb-size: 32px !default;
|
||||
$at-card-icon-size: 32px !default;
|
||||
$at-card-title-color: $color-text-title !default;
|
||||
$at-card-extra-color: $color-text-title !default;
|
||||
$at-card-info-color: $color-text-base !default;
|
||||
$at-card-note-color: $color-grey-2 !default;
|
||||
|
||||
/* Checkbox */
|
||||
$at-checkbox-circle-size: 40px !default;
|
||||
$at-checkbox-icon-size: $font-size-sm !default;
|
||||
$at-checkbox-icon-color: $color-brand !default;
|
||||
$at-checkbox-icon-color-checked: $color-white !default;
|
||||
$at-checkbox-title-color: $color-text-base !default;
|
||||
$at-checkbox-title-font-size: $font-size-lg !default;
|
||||
$at-checkbox-desc-font-size: $font-size-sm !default;
|
||||
$at-checkbox-desc-color: $color-grey-2 !default;
|
||||
|
||||
/* Countdown */
|
||||
$at-countdown-font-size: $font-size-lg !default;
|
||||
$at-countdown-num-color: $color-text-base !default;
|
||||
$at-countdown-card-num-color: #FF4949 !default;
|
||||
$at-countdown-card-num-bg-color: $color-white !default;
|
||||
|
||||
/* Curtain */
|
||||
$at-curtain-btn-color: $color-white !default;
|
||||
|
||||
/* Divider */
|
||||
$at-divider-height: 112px;
|
||||
$at-divider-content-color: $color-brand !default;
|
||||
$at-divider-font-size: $font-size-lg !default;
|
||||
$at-divider-line-color: $color-grey-3 !default;
|
||||
|
||||
/* Drawer */
|
||||
$at-drawer-content-width: 460px !default;
|
||||
|
||||
/* FloatLayout */
|
||||
$float-layout-height-min: 600px !default;
|
||||
$float-layout-height-max: 950px !default;
|
||||
$float-layout-header-bg-color: $color-bg-grey !default;
|
||||
$float-layout-title-color: $color-text-base !default;
|
||||
$float-layout-title-font-size: $font-size-lg !default;
|
||||
$float-layout-btn-color: $color-grey-3 !default;
|
||||
|
||||
/* Grid */
|
||||
$at-grid-text-color: $color-text-base !default;
|
||||
$at-grid-font-size: $font-size-lg !default;
|
||||
$at-grid-img-size: 80px !default;
|
||||
$at-gird-img-size-sm: 50px !default;
|
||||
|
||||
/* ImagePicker */
|
||||
$at-image-picker-btn-add-color: $color-grey-3 !default;
|
||||
$at-image-picker-btn-remove-color: $color-white !default;
|
||||
$at-image-picker-btn-remove-bg-color: $color-grey-2 !default;
|
||||
|
||||
/* Indexes */
|
||||
$at-indexes-nav-color: $color-link !default;
|
||||
$at-indexes-nav-font-size: $font-size-sm !default;
|
||||
$at-indexes-title-color: $color-black-2 !default;
|
||||
$at-indexes-title-font-size: $font-size-sm !default;
|
||||
$at-indexes-title-bg-color: $color-grey-6 !default;
|
||||
|
||||
/* InputNumber */
|
||||
$at-input-number-text-color: $color-text-base !default;
|
||||
$at-input-number-font-size: $font-size-base !default;
|
||||
$at-input-number-font-size-lg: $font-size-xl !default;
|
||||
$at-input-number-btn-color: $color-brand !default;
|
||||
$at-input-number-btn-size: 30px !default;
|
||||
$at-input-number-btn-size-lg: 36px !default;
|
||||
$at-input-number-width-min: 80px !default;
|
||||
$at-input-number-width-min-lg: 120px !default;
|
||||
|
||||
/* Input */
|
||||
$at-input-label-color: $color-text-base !default;
|
||||
$at-input-text-color: $color-text-base !default;
|
||||
$at-input-font-size: $font-size-lg !default;
|
||||
$at-input-placeholder-color: $color-grey-3 !default;
|
||||
|
||||
/* List */
|
||||
$at-list-thumb-size: 56px !default;
|
||||
$at-list-arrow-color: $color-grey-3 !default;
|
||||
$at-list-text-color: $color-text-base !default;
|
||||
$at-list-content-color: $color-grey-2 !default;
|
||||
$at-list-extra-color: $color-grey-2 !default;
|
||||
$at-list-extra-width: 235px !default;
|
||||
|
||||
/* LoadMore */
|
||||
$at-load-more-height: 80PX !default;
|
||||
$at-load-more-tips-color: $color-grey-1 !default;
|
||||
$at-load-more-tips-size: $font-size-lg !default;
|
||||
|
||||
/* Loading */
|
||||
$at-loading-size: 36px !default;
|
||||
$at-loading-color: $color-brand !default;
|
||||
|
||||
/* Message */
|
||||
$at-message-color: $color-white !default;
|
||||
$at-message-font-size: $font-size-base !default;
|
||||
$at-message-bg-color: $color-info !default;
|
||||
|
||||
/* Modal */
|
||||
$at-modal-width: 540px !default;
|
||||
$at-modal-header-text-color: $color-text-base !default;
|
||||
$at-modal-content-text-color: $color-text-base !default;
|
||||
$at-modal-btn-default-color: $color-text-base !default;
|
||||
$at-modal-btn-confirm-color: $color-brand !default;
|
||||
$at-modal-bg-color: $color-white !default;
|
||||
|
||||
/* NavBar */
|
||||
$at-nav-bar-title-color: $color-text-base !default;
|
||||
$at-nav-bar-link-color: $color-brand !default;
|
||||
|
||||
/* NoticeBar */
|
||||
$at-noticebar-text-color: #DE8C17 !default;
|
||||
$at-noticebar-bg-color: #FCF6ED !default;
|
||||
$at-noticebar-font-size: $font-size-sm !default;
|
||||
$at-noticebar-icon-size: 30px !default;
|
||||
$at-noticebar-btn-close-size: 32px !default;
|
||||
$at-noticebar-btn-close-color: $color-grey-3 !default;
|
||||
|
||||
/* Pagination */
|
||||
$at-pagination-margin: 40px !default;
|
||||
$at-pagination-num-color: $color-text-base !default;
|
||||
$at-pagination-num-font-size: $font-size-base !default;
|
||||
$at-pagination-current-num-color: $color-brand !default;
|
||||
$at-pagination-icon-color: $color-text-base !default;
|
||||
$at-pagination-icon-font-size: 32px !default;
|
||||
|
||||
/* Progress */
|
||||
$at-progress-height: 16px !default;
|
||||
$at-progress-text-size: $font-size-sm !default;
|
||||
$at-progress-icon-size: $font-size-xl !default;
|
||||
$at-progress-inner-bg-color: $color-grey-6 !default;
|
||||
$at-progress-bar-bg-color: $color-brand-light !default;
|
||||
$at-progress-bar-bg-color-active: $color-white !default;
|
||||
|
||||
/* Radio */
|
||||
$at-radio-title-color: $color-text-base !default;
|
||||
$at-radio-title-size: $font-size-lg !default;
|
||||
$at-radio-desc-color: $color-grey-2 !default;
|
||||
$at-radio-desc-size: $font-size-sm !default;
|
||||
$at-radio-check-color: $color-brand !default;
|
||||
|
||||
/* Range */
|
||||
$at-range-slider-size: 28PX !default;
|
||||
$at-range-rail-height: 2PX !default;
|
||||
$at-range-rail-bg-color: #E9E9E9 !default;
|
||||
$at-range-track-bg-color: $color-brand !default;
|
||||
$at-range-slider-color: $color-white !default;
|
||||
$at-range-slider-shadow: 0 0 4PX 0 rgba(0, 0, 0, 0.2) !default;
|
||||
|
||||
/* Rate */
|
||||
$at-rate-icon-size: 20PX !default;
|
||||
$at-rate-star-color: #ECECEC !default;
|
||||
$at-rate-star-color-on: #FFCA3E !default;
|
||||
|
||||
/* SearchBar */
|
||||
$at-search-bar-btn-color: $color-white !default;
|
||||
$at-search-bar-btn-bg-color: $color-brand !default;
|
||||
|
||||
/* SegmentedControl */
|
||||
$at-segmented-control-color: $color-brand !default;
|
||||
$at-segmented-control-color-active: $color-white !default;
|
||||
$at-segmented-control-bg-color: transparent !default;
|
||||
$at-segmented-control-font-size: $font-size-base !default;
|
||||
|
||||
/* Slider */
|
||||
$at-slider-text-color: $color-grey-2 !default;
|
||||
$at-slider-text-size: $font-size-base !default;
|
||||
|
||||
/* Steps */
|
||||
$at-steps-circle-size: 56px !default;
|
||||
$at-steps-icon-size: $font-size-sm !default;
|
||||
$at-steps-color: $color-white !default;
|
||||
$at-steps-color-active: $color-grey-2 !default;
|
||||
$at-steps-bg-color: $color-grey-4 !default;
|
||||
$at-steps-bg-color-active: $color-brand !default;
|
||||
$at-steps-line-color: $color-grey-3 !default;
|
||||
$at-steps-title-color: $color-black-0 !default;
|
||||
$at-steps-title-size: $font-size-lg !default;
|
||||
$at-steps-desc-color: $color-grey-3 !default;
|
||||
$at-steps-desc-size: $font-size-sm !default;
|
||||
|
||||
/* SwipeAction */
|
||||
$at-swipe-action-color: $color-white !default;
|
||||
$at-swipe-action-font-size: $font-size-base !default;
|
||||
$at-swipe-action-bg-color: $color-white !default;
|
||||
$at-swipe-action-option-bg-color: $color-grey-2 !default;
|
||||
|
||||
/* Switch */
|
||||
$at-switch-title-color: $color-text-base !default;
|
||||
$at-switch-title-size: $font-size-base !default;
|
||||
|
||||
/* TabBar */
|
||||
$at-tab-bar-bg-color: $color-white !default;
|
||||
$at-tab-bar-color: $color-text-base !default;
|
||||
$at-tab-bar-color-active: $color-brand !default;
|
||||
$at-tab-bar-font-size: $font-size-base !default;
|
||||
$at-tab-bar-icon-color: $color-grey-0 !default;
|
||||
$at-tab-bar-icon-font-size: 48px !default;
|
||||
$at-tab-bar-icon-image-size: 50px !default;
|
||||
|
||||
/* Tabs */
|
||||
$at-tabs-color: $color-text-base !default;
|
||||
$at-tabs-color-active: $color-brand !default;
|
||||
$at-tabs-font-size: $font-size-base !default;
|
||||
$at-tabs-line-height: 1PX !default;
|
||||
$at-tabs-underline-color: $color-grey-5 !default;
|
||||
$at-tabs-bg-color: $color-bg !default;
|
||||
|
||||
/* Tag */
|
||||
$at-tag-height: 60px !default;
|
||||
$at-tag-height-sm: 40px !default;
|
||||
$at-tag-color: $color-grey-1 !default;
|
||||
$at-tag-color-primary: $color-grey-1 !default;
|
||||
$at-tag-color-active: $color-brand-light !default;
|
||||
$at-tag-color-primary-active: $color-text-base-inverse !default;
|
||||
$at-tag-font-size: $font-size-base !default;
|
||||
$at-tag-font-size-sm: $font-size-xs !default;
|
||||
$at-tag-bg-color: $color-bg-grey !default;
|
||||
$at-tag-bg-color-primary: $color-bg-grey !default;
|
||||
$at-tag-bg-color-active: $color-white !default;
|
||||
$at-tag-bg-color-primary-active: $at-tag-color-active !default;
|
||||
$at-tag-border-color: $at-tag-bg-color !default;
|
||||
$at-tag-border-color-primary: $at-tag-bg-color !default;
|
||||
$at-tag-border-color-active: $at-tag-color-active !default;
|
||||
|
||||
/* Textarea */
|
||||
$at-textarea-font-size: $font-size-lg !default;
|
||||
$at-textarea-tips-color: $color-text-placeholder !default;
|
||||
$at-textarea-tips-size: $font-size-base !default;
|
||||
|
||||
/* Timeline */
|
||||
$at-timeline-offset-left: 40px !default;
|
||||
$at-timeline-title-color: $color-grey-0 !default;
|
||||
$at-timeline-title-font-size: $font-size-base !default;
|
||||
$at-timeline-desc-color: $color-grey-1 !default;
|
||||
$at-timeline-desc-font-size: $font-size-sm !default;
|
||||
$at-timeline-dot-size: 24px !default;
|
||||
$at-timeline-dot-color: $color-bg !default;
|
||||
$at-timeline-dot-border-color: $color-brand-light !default;
|
||||
$at-timeline-line-color: $color-border-lighter !default;
|
225
src/types/calendar.d.ts
vendored
Normal file
225
src/types/calendar.d.ts
vendored
Normal file
@ -0,0 +1,225 @@
|
||||
import dayjs from 'dayjs'
|
||||
import { BaseEvent } from '@tarojs/components/types/common'
|
||||
|
||||
// #region Calendar
|
||||
declare namespace Calendar {
|
||||
export type DateArg = string | number | Date
|
||||
|
||||
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 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 interface SelectedDate {
|
||||
end?: Calendar.DateArg
|
||||
|
||||
start: Calendar.DateArg
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
isAnimate: boolean
|
||||
|
||||
offsetSize: number
|
||||
|
||||
listGroup: AtCalendarBodyListGroup
|
||||
}
|
||||
// #endregion
|
Loading…
x
Reference in New Issue
Block a user