返回 AiToEarn
1 import { ForwardedRef, forwardRef, memo, useEffect, useState } from 'react';
2 import styles from './cycleSelects.module.scss';
3 import { Button, Select } from 'antd';
4 import dayjs from 'dayjs';
5 import isoWeek from 'dayjs/plugin/isoWeek';
6
7 dayjs.extend(isoWeek);
8
9 export enum CycleTypeEnum {
10 Week = 'week',
11 Month = 'month',
12 }
13
14 type CycleItemType = {
15 value: string;
16 label: string;
17 };
18
19 export interface ICycleselectsRef {}
20
21 export interface ICycleselectsProps {
22 onChange: (params: { type: CycleTypeEnum; value: string }) => void;
23 defaultType: CycleTypeEnum;
24 disable?: boolean;
25 }
26
27 const CycleseCore = ({
28 title,
29 options,
30 onChange,
31 onActiveClick,
32 isActive,
33 value,
34 }: {
35 onChange: (value: string) => void;
36 title: string;
37 options: CycleItemType[];
38 onActiveClick: () => void;
39 isActive: boolean;
40 value: string;
41 }) => {
42 return (
43 <div className="cycleSelects-item">
44 {isActive}
45 {isActive ? (
46 <>
47 <div className="cycleSelects-item-label">{title}</div>
48 <Select options={options} value={value} onChange={onChange}></Select>
49 </>
50 ) : (
51 <Button onClick={onActiveClick}>{title}</Button>
52 )}
53 </div>
54 );
55 };
56
57 /**
58 * 获取指定数量的月份
59 * @param {number} skipMonths 跳过的月份数(当前月不算)
60 * @param {number} numberOfMonths 获取的月份数
61 */
62 function getMonths(skipMonths: number, numberOfMonths: number) {
63 const currentMonth = dayjs().startOf('month'); // 当前月的开始时间
64 const months: CycleItemType[] = [];
65
66 for (let i = 0; i < numberOfMonths; i++) {
67 const month = currentMonth.subtract(skipMonths + i + 1, 'month');
68 months.push({
69 label: month.format('YYYY年MM月'),
70 value: month.format('YYYY-MM-DD'),
71 });
72 }
73
74 return months;
75 }
76
77 /**
78 * 获取指定周范围的周
79 * @param {number} skipWeeks 跳过的周数(当前周不算)
80 * @param {number} numberOfWeeks 获取的周数
81 */
82 function getWeekRanges(skipWeeks: number, numberOfWeeks: number) {
83 const currentWeekStart = dayjs().startOf('isoWeek'); // 当前周的开始时间(周一)
84 const ranges: CycleItemType[] = [];
85
86 for (let i = 0; i < numberOfWeeks; i++) {
87 const startOfWeek = currentWeekStart
88 .subtract(skipWeeks + i + 1, 'week')
89 .startOf('isoWeek');
90 const endOfWeek = startOfWeek.endOf('isoWeek');
91 ranges.push({
92 label: `${startOfWeek.format('MM月DD日')} - ${endOfWeek.format('MM月DD日')}`,
93 value: startOfWeek.format('YYYY-MM-DD'),
94 });
95 }
96
97 return ranges;
98 }
99
100 /**
101 * 获取指定数量的日期
102 * @param {number} skipDays 跳过的天数(当前日不算)
103 * @param {number} numberOfDays 获取的天数
104 */
105 function getDays(skipDays: number, numberOfDays: number) {
106 const currentDay = dayjs().startOf('day'); // 当前天的起始时间
107 const days: CycleItemType[] = [];
108
109 for (let i = 0; i < numberOfDays; i++) {
110 const day = currentDay.subtract(skipDays + i + 1, 'day');
111 days.push({
112 value: day.format('YYYY年MM月DD日'),
113 label: day.format('YYYY-MM-DD'),
114 });
115 }
116
117 return days;
118 }
119
120 const Cycleselects = memo(
121 forwardRef(
122 (
123 { onChange, defaultType, disable }: ICycleselectsProps,
124 ref: ForwardedRef<ICycleselectsRef>,
125 ) => {
126 // 1周榜 2=月榜
127 const [active, setActive] = useState<CycleTypeEnum>(defaultType);
128 const [value, setValue] = useState('');
129 const [weekOptions, setWeekOptions] = useState<CycleItemType[]>([]);
130 const [monthsOptions, setMonthsOptions] = useState<CycleItemType[]>([]);
131
132 useEffect(() => {
133 const weekOptions = getWeekRanges(1, 3);
134 setWeekOptions(weekOptions);
135
136 const monthsOptions = getMonths(0, 3);
137 setMonthsOptions(monthsOptions);
138
139 if (defaultType === CycleTypeEnum.Week) {
140 setValue(weekOptions[0].value);
141 }
142 }, []);
143
144 useEffect(() => {
145 if (!value) return;
146 onChange({
147 type: active,
148 value,
149 });
150 }, [value]);
151
152 useEffect(() => {
153 if (active === CycleTypeEnum.Week) {
154 if (weekOptions[0]?.value) setValue(weekOptions[0]?.value);
155 return;
156 }
157 if (active === CycleTypeEnum.Month) {
158 if (monthsOptions[0]?.value) setValue(monthsOptions[0]?.value);
159 return;
160 }
161 }, [active]);
162
163 return (
164 <div className={styles.cycleSelects}>
165 <CycleseCore
166 value={value}
167 isActive={active === CycleTypeEnum.Week}
168 onActiveClick={() => {
169 if (disable) return;
170 setActive(CycleTypeEnum.Week);
171 }}
172 onChange={setValue}
173 title="周榜"
174 options={weekOptions}
175 />
176
177 <CycleseCore
178 value={value}
179 isActive={active === CycleTypeEnum.Month}
180 onActiveClick={() => {
181 if (disable) return;
182 setActive(CycleTypeEnum.Month);
183 }}
184 onChange={setValue}
185 title="月榜"
186 options={monthsOptions}
187 />
188 </div>
189 );
190 },
191 ),
192 );
193 Cycleselects.displayName = 'Cycleselects';
194
195 export default Cycleselects;
196
196 lines Plain Text