日期范围选择组件
This commit is contained in:
@@ -6,7 +6,7 @@ import { PickerCommon, PickerCommonRef } from '@/components/Picker'
|
|||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import styles from './index.module.scss'
|
import styles from './index.module.scss'
|
||||||
export interface DialogCalendarCardProps {
|
export interface DialogCalendarCardProps {
|
||||||
value?: Date
|
value?: Date | Date[]
|
||||||
searchType?: 'single' | 'range' | 'multiple'
|
searchType?: 'single' | 'range' | 'multiple'
|
||||||
onChange?: (date: Date | Date[]) => void
|
onChange?: (date: Date | Date[]) => void
|
||||||
visible: boolean
|
visible: boolean
|
||||||
@@ -22,7 +22,7 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
|
|||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
}) => {
|
}) => {
|
||||||
const [selected, setSelected] = useState<Date>(value || new Date())
|
const [selected, setSelected] = useState<Date | Date[]>(value || new Date())
|
||||||
const calendarRef = useRef<CalendarUIRef>(null);
|
const calendarRef = useRef<CalendarUIRef>(null);
|
||||||
const [type, setType] = useState<'year' | 'month' | 'time'>('year');
|
const [type, setType] = useState<'year' | 'month' | 'time'>('year');
|
||||||
const [selectedHour, setSelectedHour] = useState(8)
|
const [selectedHour, setSelectedHour] = useState(8)
|
||||||
@@ -32,6 +32,11 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
|
|||||||
const [pendingJump, setPendingJump] = useState<{ year: number; month: number } | null>(null)
|
const [pendingJump, setPendingJump] = useState<{ year: number; month: number } | null>(null)
|
||||||
const handleConfirm = () => {
|
const handleConfirm = () => {
|
||||||
if (type === 'year') {
|
if (type === 'year') {
|
||||||
|
if (searchType === 'range') {
|
||||||
|
if (onChange) onChange(selected);
|
||||||
|
onClose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
// 年份选择完成后,进入月份选择
|
// 年份选择完成后,进入月份选择
|
||||||
setType('time')
|
setType('time')
|
||||||
} else if (type === 'month') {
|
} else if (type === 'month') {
|
||||||
@@ -40,7 +45,13 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
|
|||||||
if (value) {
|
if (value) {
|
||||||
const year = value[0] as number
|
const year = value[0] as number
|
||||||
const month = value[1] as number
|
const month = value[1] as number
|
||||||
setSelected(new Date(year, month - 1, 1))
|
if (searchType === 'range') {
|
||||||
|
const delta = calculateMonthDifference(selected as Date, new Date(year, month - 1, 1))
|
||||||
|
console.log('xxxxx', calendarRef.current)
|
||||||
|
calendarRef.current?.gotoMonth(delta)
|
||||||
|
} else {
|
||||||
|
setSelected(new Date(year, month - 1, 1))
|
||||||
|
}
|
||||||
setPendingJump({ year, month })
|
setPendingJump({ year, month })
|
||||||
}
|
}
|
||||||
setType('year')
|
setType('year')
|
||||||
@@ -54,18 +65,31 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
|
|||||||
setSelectedMinute(minute)
|
setSelectedMinute(minute)
|
||||||
const hours = hour.toString().padStart(2, '0')
|
const hours = hour.toString().padStart(2, '0')
|
||||||
const minutes = minute.toString().padStart(2, '0')
|
const minutes = minute.toString().padStart(2, '0')
|
||||||
const finalDate = new Date(dayjs(selected).format('YYYY-MM-DD') + ' ' + hours + ':' + minutes)
|
const finalDate = new Date(dayjs(selected as Date).format('YYYY-MM-DD') + ' ' + hours + ':' + minutes)
|
||||||
if (onChange) onChange(finalDate)
|
if (onChange) onChange(finalDate)
|
||||||
}
|
}
|
||||||
onClose()
|
onClose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const calculateMonthDifference = (date1, date2) => {
|
||||||
|
if (!(date1 instanceof Date) || !(date2 instanceof Date)) {
|
||||||
|
throw new Error('Both arguments must be Date objects');
|
||||||
|
}
|
||||||
|
|
||||||
|
let months = (date2.getFullYear() - date1.getFullYear()) * 12;
|
||||||
|
months -= date1.getMonth();
|
||||||
|
months += date2.getMonth();
|
||||||
|
|
||||||
|
return months;
|
||||||
|
}
|
||||||
|
|
||||||
const handleChange = (d: Date | Date[]) => {
|
const handleChange = (d: Date | Date[]) => {
|
||||||
|
console.log('handleChange', d)
|
||||||
if (searchType === 'range') {
|
if (searchType === 'range') {
|
||||||
if (Array.isArray(d)) {
|
if (Array.isArray(d)) {
|
||||||
if (d.length === 2) {
|
if (d.length === 2) {
|
||||||
onChange?.(d as Date[])
|
setSelected(d as Date[])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,6 +101,7 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const onHeaderClick = (date: Date) => {
|
const onHeaderClick = (date: Date) => {
|
||||||
|
console.log('onHeaderClick', date)
|
||||||
setSelected(date)
|
setSelected(date)
|
||||||
setType('month')
|
setType('month')
|
||||||
}
|
}
|
||||||
@@ -101,8 +126,8 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (visible && value) {
|
if (visible && value) {
|
||||||
setSelected(value || new Date())
|
setSelected(value || new Date())
|
||||||
setSelectedHour(value ? dayjs(value).hour() : 8)
|
setSelectedHour(value ? dayjs(value as Date).hour() : 8)
|
||||||
setSelectedMinute(value ? dayjs(value).minute() : 0)
|
setSelectedMinute(value ? dayjs(value as Date).minute() : 0)
|
||||||
}
|
}
|
||||||
}, [value, visible])
|
}, [value, visible])
|
||||||
|
|
||||||
@@ -132,32 +157,32 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
|
|||||||
{
|
{
|
||||||
type === 'year' &&
|
type === 'year' &&
|
||||||
<View className={styles['calendar-container']}>
|
<View className={styles['calendar-container']}>
|
||||||
<CalendarUI
|
<CalendarUI
|
||||||
ref={calendarRef}
|
ref={calendarRef}
|
||||||
type={searchType}
|
type={searchType}
|
||||||
value={selected}
|
value={selected}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
showQuickActions={false}
|
showQuickActions={false}
|
||||||
onHeaderClick={onHeaderClick}
|
onHeaderClick={onHeaderClick}
|
||||||
/></View>
|
/></View>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
type === 'month' && <PickerCommon
|
type === 'month' && <PickerCommon
|
||||||
ref={pickerRef}
|
ref={pickerRef}
|
||||||
onChange={handleDateTimePickerChange}
|
onChange={handleDateTimePickerChange}
|
||||||
type="month"
|
type="month"
|
||||||
value={[selected.getFullYear(), selected.getMonth() + 1]}
|
value={[(selected as Date).getFullYear(), (selected as Date).getMonth() + 1]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
type === 'time' && <PickerCommon
|
type === 'time' && <PickerCommon
|
||||||
ref={hourMinutePickerRef}
|
ref={hourMinutePickerRef}
|
||||||
type="hour"
|
type="hour"
|
||||||
value={[selectedHour, selectedMinute]}
|
value={[selectedHour, selectedMinute]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
}
|
}
|
||||||
</CommonPopup>
|
</CommonPopup>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import images from '@/config/images'
|
|||||||
import styles from './index.module.scss'
|
import styles from './index.module.scss'
|
||||||
import { getMonth, getWeekend, getWeekendOfCurrentWeek } from '@/utils/timeUtils'
|
import { getMonth, getWeekend, getWeekendOfCurrentWeek } from '@/utils/timeUtils'
|
||||||
import { PopupPicker } from '@/components/Picker/index'
|
import { PopupPicker } from '@/components/Picker/index'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
interface NutUICalendarProps {
|
interface NutUICalendarProps {
|
||||||
type?: 'single' | 'range' | 'multiple'
|
type?: 'single' | 'range' | 'multiple'
|
||||||
value?: string | Date | String[] | Date[]
|
value?: string | Date | String[] | Date[]
|
||||||
@@ -16,7 +17,8 @@ interface NutUICalendarProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CalendarUIRef {
|
export interface CalendarUIRef {
|
||||||
jumpTo: (year: number, month: number) => void
|
jumpTo: (year: number, month: number) => void,
|
||||||
|
gotoMonth: (delta: number) => void,
|
||||||
}
|
}
|
||||||
|
|
||||||
const NutUICalendar = React.forwardRef<CalendarUIRef, NutUICalendarProps>(({
|
const NutUICalendar = React.forwardRef<CalendarUIRef, NutUICalendarProps>(({
|
||||||
@@ -28,27 +30,27 @@ const NutUICalendar = React.forwardRef<CalendarUIRef, NutUICalendarProps>(({
|
|||||||
onHeaderClick
|
onHeaderClick
|
||||||
}, ref) => {
|
}, ref) => {
|
||||||
// 根据类型初始化选中值
|
// 根据类型初始化选中值
|
||||||
// const getInitialValue = (): Date | Date[] => {
|
// const getInitialValue = (): Date | Date[] => {
|
||||||
// console.log(value,defaultValue,'today')
|
// console.log(value,defaultValue,'today')
|
||||||
|
|
||||||
// if (typeof value === 'string' && value) {
|
// if (typeof value === 'string' && value) {
|
||||||
// return new Date(value)
|
// return new Date(value)
|
||||||
// }
|
// }
|
||||||
// if (Array.isArray(value) && value.length > 0) {
|
// if (Array.isArray(value) && value.length > 0) {
|
||||||
// return value.map(item => new Date(item))
|
// return value.map(item => new Date(item))
|
||||||
// }
|
// }
|
||||||
// if (typeof defaultValue === 'string' && defaultValue) {
|
// if (typeof defaultValue === 'string' && defaultValue) {
|
||||||
// return new Date(defaultValue)
|
// return new Date(defaultValue)
|
||||||
// }
|
// }
|
||||||
// if (Array.isArray(defaultValue) && defaultValue.length > 0) {
|
// if (Array.isArray(defaultValue) && defaultValue.length > 0) {
|
||||||
// return defaultValue.map(item => new Date(item))
|
// return defaultValue.map(item => new Date(item))
|
||||||
// }
|
// }
|
||||||
// const today = new Date();
|
// const today = new Date();
|
||||||
// if (type === 'multiple') {
|
// if (type === 'multiple') {
|
||||||
// return [today]
|
// return [today]
|
||||||
// }
|
// }
|
||||||
// return today
|
// return today
|
||||||
// }
|
// }
|
||||||
const startOfMonth = (date: Date) => new Date(date.getFullYear(), date.getMonth(), 1)
|
const startOfMonth = (date: Date) => new Date(date.getFullYear(), date.getMonth(), 1)
|
||||||
|
|
||||||
const [selectedValue, setSelectedValue] = useState<Date | Date[]>()
|
const [selectedValue, setSelectedValue] = useState<Date | Date[]>()
|
||||||
@@ -59,23 +61,25 @@ const NutUICalendar = React.forwardRef<CalendarUIRef, NutUICalendarProps>(({
|
|||||||
// 当外部 value 变化时更新内部状态
|
// 当外部 value 变化时更新内部状态
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Array.isArray(value) && value.length > 0) {
|
if (Array.isArray(value) && value.length > 0) {
|
||||||
setSelectedValue(value.map(item => new Date(item)))
|
setSelectedValue(value.map(item => new Date(item)))
|
||||||
setCurrent(new Date(value[0]))
|
setCurrent(new Date(value[0] as Date))
|
||||||
}
|
}
|
||||||
if ((typeof value === 'string' || value instanceof Date) && value) {
|
if ((typeof value === 'string' || value instanceof Date) && value) {
|
||||||
setSelectedValue(new Date(value))
|
setSelectedValue(new Date(value))
|
||||||
setCurrent(new Date(value))
|
setCurrent(new Date(value))
|
||||||
}
|
}
|
||||||
}, [value])
|
}, [value])
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
jumpTo: (year: number, month: number) => {
|
jumpTo: (year: number, month: number) => {
|
||||||
calendarRef.current?.jumpTo(year, month)
|
calendarRef.current?.jumpTo(year, month)
|
||||||
|
},
|
||||||
|
gotoMonth: (delta: number) => {
|
||||||
|
gotoMonth(delta)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const handleDateChange = (newValue: any) => {
|
const handleDateChange = (newValue: any) => {
|
||||||
console.log('xxxxxxxxxxxxxxxxxxxxxx', newValue)
|
|
||||||
setSelectedValue(newValue)
|
setSelectedValue(newValue)
|
||||||
onChange?.(newValue as any)
|
onChange?.(newValue as any)
|
||||||
}
|
}
|
||||||
@@ -87,6 +91,7 @@ const NutUICalendar = React.forwardRef<CalendarUIRef, NutUICalendarProps>(({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const gotoMonth = (delta: number) => {
|
const gotoMonth = (delta: number) => {
|
||||||
|
console.log('aaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbb', delta)
|
||||||
const base = current instanceof Date ? new Date(current) : new Date()
|
const base = current instanceof Date ? new Date(current) : new Date()
|
||||||
base.setMonth(base.getMonth() + delta)
|
base.setMonth(base.getMonth() + delta)
|
||||||
const next = startOfMonth(base)
|
const next = startOfMonth(base)
|
||||||
@@ -101,6 +106,7 @@ const NutUICalendar = React.forwardRef<CalendarUIRef, NutUICalendarProps>(({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleHeaderClick = () => {
|
const handleHeaderClick = () => {
|
||||||
|
console.log('handleHeaderClick', current)
|
||||||
onHeaderClick && onHeaderClick(current)
|
onHeaderClick && onHeaderClick(current)
|
||||||
setvisible(true)
|
setvisible(true)
|
||||||
}
|
}
|
||||||
@@ -115,11 +121,11 @@ const NutUICalendar = React.forwardRef<CalendarUIRef, NutUICalendarProps>(({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const renderDay = (day: any) => {
|
const renderDay = (day: any) => {
|
||||||
const { date, month, year} = day;
|
const { date, month, year } = day;
|
||||||
const today = new Date()
|
const today = new Date()
|
||||||
if (date === today.getDate() && month === today.getMonth() + 1 && year === today.getFullYear()) {
|
if (date === today.getDate() && month === today.getMonth() + 1 && year === today.getFullYear()) {
|
||||||
return (
|
return (
|
||||||
<View class="day-container">
|
<View className="day-container">
|
||||||
{date}
|
{date}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
@@ -160,12 +166,21 @@ const NutUICalendar = React.forwardRef<CalendarUIRef, NutUICalendarProps>(({
|
|||||||
{
|
{
|
||||||
showQuickActions &&
|
showQuickActions &&
|
||||||
<View className={styles['quick-actions']}>
|
<View className={styles['quick-actions']}>
|
||||||
<View className={styles['quick-action']} onClick={selectWeekend}>本周末</View>
|
<View className={styles['quick-action']} onClick={selectWeekend}>本周末</View>
|
||||||
<View className={styles['quick-action']} onClick={selectWeek}>一周内</View>
|
<View className={styles['quick-action']} onClick={selectWeek}>一周内</View>
|
||||||
<View className={styles['quick-action']} onClick={selectMonth}>一个月</View>
|
<View className={styles['quick-action']} onClick={selectMonth}>一个月</View>
|
||||||
</View>
|
</View>
|
||||||
}
|
}
|
||||||
<View className={`${styles['calendar-card']} ${isBorder ? styles['border'] : ''}`}>
|
<View className={`${styles['calendar-card']} ${isBorder ? styles['border'] : ''}`}>
|
||||||
|
{
|
||||||
|
type === 'range' && (
|
||||||
|
<View className={styles['date-range-container']}>
|
||||||
|
<Text className={`${styles['date-text-placeholder']} ${value?.[0] ? styles['date-text'] : ''}`}>{value?.[0] ? dayjs(value?.[0] as Date).format('YYYY-MM-DD') : '起始时间'}</Text>
|
||||||
|
<Text>至</Text>
|
||||||
|
<Text className={`${styles['date-text-placeholder']} ${value?.[1] ? styles['date-text'] : ''}`}>{value?.[1] ? dayjs(value?.[1] as Date).format('YYYY-MM-DD') : '结束时间'}</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
{/* 自定义头部显示周一到周日 */}
|
{/* 自定义头部显示周一到周日 */}
|
||||||
<View className={styles['header']}>
|
<View className={styles['header']}>
|
||||||
<View className={styles['header-left']} onClick={handleHeaderClick}>
|
<View className={styles['header-left']} onClick={handleHeaderClick}>
|
||||||
@@ -173,16 +188,16 @@ const NutUICalendar = React.forwardRef<CalendarUIRef, NutUICalendarProps>(({
|
|||||||
<Image src={images.ICON_RIGHT_MAX} className={`${styles['month-arrow']}`} onClick={() => gotoMonth(1)} />
|
<Image src={images.ICON_RIGHT_MAX} className={`${styles['month-arrow']}`} onClick={() => gotoMonth(1)} />
|
||||||
</View>
|
</View>
|
||||||
<View className={styles['header-actions']}>
|
<View className={styles['header-actions']}>
|
||||||
<View className={styles['arrow-left-container']} onClick={() => gotoMonth(-1)}>
|
<View className={styles['arrow-left-container']} onClick={() => gotoMonth(-1)}>
|
||||||
<Image src={images.ICON_RIGHT_MAX} className={`${styles['arrow']} ${styles['left']}`} />
|
<Image src={images.ICON_RIGHT_MAX} className={`${styles['arrow']} ${styles['left']}`} />
|
||||||
</View>
|
</View>
|
||||||
<View className={styles['arrow-right-container']} onClick={() => gotoMonth(1)}>
|
<View className={styles['arrow-right-container']} onClick={() => gotoMonth(1)}>
|
||||||
<Image src={images.ICON_RIGHT_MAX} className={`${styles['arrow']}`} />
|
<Image src={images.ICON_RIGHT_MAX} className={`${styles['arrow']}`} />
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View className={styles['week-header']}>
|
<View className={styles['week-header']}>
|
||||||
{[ '周日', '周一', '周二', '周三', '周四', '周五', '周六'].map((day) => (
|
{['周日', '周一', '周二', '周三', '周四', '周五', '周六'].map((day) => (
|
||||||
<Text key={day} className={styles['week-day']}>
|
<Text key={day} className={styles['week-day']}>
|
||||||
{day}
|
{day}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -199,12 +214,12 @@ const NutUICalendar = React.forwardRef<CalendarUIRef, NutUICalendarProps>(({
|
|||||||
onPageChange={handlePageChange}
|
onPageChange={handlePageChange}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
{ visible && <PopupPicker
|
{visible && <PopupPicker
|
||||||
visible={visible}
|
visible={visible}
|
||||||
setvisible={setvisible}
|
setvisible={setvisible}
|
||||||
value={[current.getFullYear(), current.getMonth() + 1]}
|
value={[current.getFullYear(), current.getMonth() + 1]}
|
||||||
type="month"
|
type="month"
|
||||||
onChange={(value) => handleMonthChange(value)}/> }
|
onChange={(value) => handleMonthChange(value)} />}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,177 +1,217 @@
|
|||||||
.calendar-card {
|
.calendar-card {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
&.border{
|
|
||||||
border-radius: 12px;
|
&.border {
|
||||||
border: 0.5px solid rgba(0, 0, 0, 0.12);
|
border-radius: 12px;
|
||||||
margin-bottom: 6px;
|
border: 0.5px solid rgba(0, 0, 0, 0.12);
|
||||||
padding: 12px 12px 8px;
|
margin-bottom: 6px;
|
||||||
|
padding: 12px 12px 8px;
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 9px 4px 11px 4px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-range-container {
|
||||||
|
height: 55px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||||
|
color: #000;
|
||||||
|
padding: 0 4px;
|
||||||
|
font-size: 17.68px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-text-placeholder {
|
||||||
|
font-family: PingFang SC;
|
||||||
|
font-weight: 600;
|
||||||
|
font-style: Semibold;
|
||||||
|
font-size: 17.68px;
|
||||||
|
color: #3C3C4399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-text {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-text {
|
||||||
|
font-size: 17px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-actions {
|
||||||
|
display: flex;
|
||||||
|
width: 60px;
|
||||||
|
|
||||||
|
.arrow-left-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: flex-start;
|
||||||
padding: 9px 4px 11px 4px;
|
width: 50%;
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
.header-left {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
.header-text {
|
|
||||||
font-size: 17px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
.header-actions {
|
|
||||||
display: flex;
|
|
||||||
width: 60px;
|
|
||||||
.arrow-left-container {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
width: 50%;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
.arrow-right-container {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
width: 50%;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.month-arrow{
|
|
||||||
width: 8px;
|
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
.arrow {
|
|
||||||
width: 10px;
|
|
||||||
height: 24px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.arrow.left {
|
|
||||||
left: 9px;
|
|
||||||
transform: rotate(-180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.week-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(7, 1fr);
|
|
||||||
padding: 0 0 4px 0;
|
|
||||||
}
|
|
||||||
.week-item {
|
|
||||||
text-align: center;
|
|
||||||
color: rgba(60, 60, 67, 0.30);
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增的周一到周日头部样式
|
|
||||||
.week-header {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(7, 1fr);
|
|
||||||
padding: 8px 0;
|
|
||||||
}
|
|
||||||
.week-day {
|
|
||||||
text-align: center;
|
|
||||||
color: rgba(60, 60, 67, 0.30);
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(7, 1fr);
|
|
||||||
gap: 8px 0;
|
|
||||||
padding: 4px 0 16px;
|
|
||||||
}
|
|
||||||
.cell {
|
|
||||||
height: 44px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: 20px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.cell.empty {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.cell.disabled {
|
|
||||||
color: rgba(0,0,0,0.2);
|
|
||||||
}
|
|
||||||
.cell-text.selected {
|
|
||||||
width: 44px;
|
|
||||||
height: 44px;
|
|
||||||
border-radius: 22px;
|
|
||||||
background: rgba(0,0,0,0.9);
|
|
||||||
color: #fff;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 时间段选择样式
|
|
||||||
.cell-text.range-start {
|
|
||||||
width: 44px;
|
|
||||||
height: 44px;
|
|
||||||
border-radius: 22px;
|
|
||||||
background: rgba(0,0,0,0.9);
|
|
||||||
color: #fff;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cell-text.range-end {
|
|
||||||
width: 44px;
|
|
||||||
height: 44px;
|
|
||||||
border-radius: 22px;
|
|
||||||
background: rgba(0,0,0,0.9);
|
|
||||||
color: #fff;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cell-text.in-range {
|
|
||||||
width: 44px;
|
|
||||||
height: 44px;
|
|
||||||
border-radius: 22px;
|
|
||||||
background: rgba(0,0,0,0.1);
|
|
||||||
color: #000;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
display: flex;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
.btn {
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 44px;
|
|
||||||
border-radius: 22px;
|
|
||||||
background: rgba(0,0,0,0.06);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
.btn.primary {
|
|
||||||
background: #000;
|
|
||||||
color: #fff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hm-placeholder {
|
.arrow-right-container {
|
||||||
height: 240px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: flex-end;
|
||||||
|
width: 50%;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.month-arrow {
|
||||||
|
width: 8px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow {
|
||||||
|
width: 10px;
|
||||||
|
height: 24px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow.left {
|
||||||
|
left: 9px;
|
||||||
|
transform: rotate(-180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.week-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(7, 1fr);
|
||||||
|
padding: 0 0 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.week-item {
|
||||||
|
text-align: center;
|
||||||
|
color: rgba(60, 60, 67, 0.30);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增的周一到周日头部样式
|
||||||
|
.week-header {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(7, 1fr);
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.week-day {
|
||||||
|
text-align: center;
|
||||||
|
color: rgba(60, 60, 67, 0.30);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(7, 1fr);
|
||||||
|
gap: 8px 0;
|
||||||
|
padding: 4px 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell {
|
||||||
|
height: 44px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 20px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell.empty {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell.disabled {
|
||||||
|
color: rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell-text.selected {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
border-radius: 22px;
|
||||||
|
background: rgba(0, 0, 0, 0.9);
|
||||||
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时间段选择样式
|
||||||
|
.cell-text.range-start {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
border-radius: 22px;
|
||||||
|
background: rgba(0, 0, 0, 0.9);
|
||||||
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell-text.range-end {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
border-radius: 22px;
|
||||||
|
background: rgba(0, 0, 0, 0.9);
|
||||||
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell-text.in-range {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
border-radius: 22px;
|
||||||
|
background: rgba(0, 0, 0, 0.1);
|
||||||
|
color: #000;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
flex: 1;
|
||||||
|
height: 44px;
|
||||||
|
border-radius: 22px;
|
||||||
|
background: rgba(0, 0, 0, 0.06);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background: #000;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hm-placeholder {
|
||||||
|
height: 240px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
// CalendarRange 组件样式
|
// CalendarRange 组件样式
|
||||||
.calendar-range {
|
.calendar-range {
|
||||||
@@ -241,43 +281,56 @@
|
|||||||
.nut-calendarcard-header {
|
.nut-calendarcard-header {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
.nut-calendarcard-content{
|
|
||||||
.nut-calendarcard-days{
|
.nut-calendarcard-content {
|
||||||
&:first-child{
|
.nut-calendarcard-days {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(7, 1fr);
|
||||||
|
gap: 4px;
|
||||||
|
justify-items: center;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.nut-calendarcard-day{
|
|
||||||
margin-bottom:0px!important;
|
.nut-calendarcard-day {
|
||||||
|
margin-bottom: 0px !important;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
width: 44px!important;
|
width: 44px !important;
|
||||||
&.active{
|
|
||||||
background-color: #000!important;
|
&.active {
|
||||||
color: #fff!important;
|
background-color: #000 !important;
|
||||||
|
color: #fff !important;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
border-radius: 22px!important;
|
border-radius: 22px !important;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 44px!important;
|
width: 44px !important;
|
||||||
font-size: 24px!important;
|
font-size: 24px !important;
|
||||||
.day-container{
|
|
||||||
background-color: transparent!important;
|
.day-container {
|
||||||
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.weekend{
|
|
||||||
color: rgb(0,0,0)!important;
|
&.weekend {
|
||||||
&.active{
|
color: rgb(0, 0, 0) !important;
|
||||||
color: #fff!important;
|
|
||||||
|
&.active {
|
||||||
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.nut-calendarcard-day-inner{
|
|
||||||
|
.nut-calendarcard-day-inner {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
.day-container{
|
|
||||||
|
.day-container {
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
border-radius: 22px;
|
border-radius: 22px;
|
||||||
width: 44px;
|
width: 44px;
|
||||||
@@ -288,5 +341,22 @@
|
|||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
.nut-calendarcard-day.start,
|
||||||
|
.nut-calendarcard-day.end {
|
||||||
|
background-color: #000;
|
||||||
|
border-radius: 50%;
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nut-calendarcard-day-inner .day-container {
|
||||||
|
background-color: unset;
|
||||||
|
color: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nut-calendarcard-day.mid {
|
||||||
|
background-color: rgba(0, 0, 0, 0.12);
|
||||||
|
color: #000;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { View, Text, Button } from "@tarojs/components";
|
import { View, Text, Button } from "@tarojs/components";
|
||||||
import Taro, { useDidShow } from "@tarojs/taro";
|
import Taro, { useDidShow } from "@tarojs/taro";
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
import "./index.scss";
|
import "./index.scss";
|
||||||
import { DialogCalendarCard } from "@/components/index";
|
import { DialogCalendarCard } from "@/components/index";
|
||||||
@@ -56,8 +57,13 @@ const DownloadBill: React.FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const [currentTimeValue, setCurrentTimeValue] = useState<Date | Date[]>(new Date());
|
const [currentTimeValue, setCurrentTimeValue] = useState<Date | Date[]>(new Date());
|
||||||
const handleConfirm = (val) => {
|
const handleConfirm = (val: Date[]) => {
|
||||||
setCurrentTimeValue(val);
|
setCurrentTimeValue(val);
|
||||||
|
const [start, end] = val;
|
||||||
|
setDateRange({
|
||||||
|
start: dayjs(start).format("YYYY-MM-DD"),
|
||||||
|
end: dayjs(end).format("YYYY-MM-DD"),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<View className="download_bill_page">
|
<View className="download_bill_page">
|
||||||
|
|||||||
Reference in New Issue
Block a user