Skip to content

Commit 8f0c668

Browse files
committed
fix(course): compute semester weeks from time store
1 parent 7cf50f2 commit 8f0c668

7 files changed

Lines changed: 58 additions & 25 deletions

File tree

src/modules/courseTable/components/WeekSelector.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010

1111
import Modal from '@/components/modal';
1212

13-
import useCourse from '@/store/course';
1413
import useTimeStore, { computeSemesterAndYear } from '@/store/time';
1514
import useVisualScheme from '@/store/visualScheme';
1615

@@ -29,6 +28,7 @@ const SEMESTER_LABELS: Record<string, string> = {
2928
const WeekSelector: FC<WeekSelectorProps> = ({
3029
currentWeek,
3130
showWeekPicker,
31+
totalWeeks,
3232
year,
3333
semester,
3434
semesterOptions,
@@ -37,7 +37,7 @@ const WeekSelector: FC<WeekSelectorProps> = ({
3737
}) => {
3838
const currentStyle = useVisualScheme(state => state.currentStyle);
3939
const getCurrentWeek = useTimeStore(state => state.getCurrentWeek);
40-
const schoolTime = useCourse(state => state.schoolTime);
40+
const schoolTime = useTimeStore(state => state.schoolTime);
4141

4242
// 根据 schoolTime 推算真实当前学期
4343
const actualSemester = useMemo(
@@ -257,7 +257,7 @@ const WeekSelector: FC<WeekSelectorProps> = ({
257257
</View>
258258
{/* 周次选择区域 */}
259259
<View style={styles.weekGrid}>
260-
{[...Array(20)].map((_, i) => (
260+
{Array.from({ length: totalWeeks }).map((_, i) => (
261261
<Pressable
262262
key={i}
263263
onPress={() => handleWeekSelect(i + 1)}

src/modules/courseTable/components/courseTable/StickyTop.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { StyleSheet, Text, View } from 'react-native';
33

44
import ThemeChangeText from '@/components/text';
55

6-
import useCourse from '@/store/course';
76
import useCourseTableAppearance from '@/store/courseTableAppearance';
87
import useTimeStore from '@/store/time';
98
import useVisualScheme from '@/store/visualScheme';
@@ -17,7 +16,7 @@ import {
1716
export const StickyTop: React.FC = memo(function StickyTop() {
1817
const currentStyle = useVisualScheme(state => state.currentStyle);
1918
const { selectedWeek } = useTimeStore();
20-
const schoolTime = useCourse(state => state.schoolTime);
19+
const schoolTime = useTimeStore(state => state.schoolTime);
2120
const { backgroundUri } = useCourseTableAppearance();
2221
const [dates, setDates] = useState<string[]>([]);
2322

src/modules/courseTable/components/courseTable/type.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ export interface SemesterWeekParams {
6363
export interface WeekSelectorProps {
6464
currentWeek: number;
6565
showWeekPicker: boolean;
66+
/** 当前学期总周数 */
67+
totalWeeks: number;
6668
/** 当前学年,如 "2025" */
6769
year: string;
6870
/** 当前学期,"1" | "2" | "3" */

src/modules/courseTable/index.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,21 +66,17 @@ const CourseTablePage: FC = () => {
6666
return new ExtensionStorage('group.release-20240916');
6767
}, []);
6868

69-
const {
70-
courses,
71-
updateCourses,
72-
setLastUpdate,
73-
setHolidayTime,
74-
schoolTime,
75-
setSchoolTime,
76-
} = useCourse();
69+
const { courses, updateCourses, setLastUpdate } = useCourse();
7770
const {
7871
semester,
7972
setSemester,
8073
year,
8174
setYear,
8275
selectedWeek,
8376
setSelectedWeek,
77+
setHolidayTime,
78+
schoolTime,
79+
setSchoolTime,
8480
showWeekPicker,
8581
setShowWeekPicker,
8682
} = useTimeStore();
@@ -93,6 +89,8 @@ const CourseTablePage: FC = () => {
9389
[studentId]
9490
);
9591

92+
const totalWeeks = useTimeStore(state => state.getSemesterWeekCount());
93+
9694
const syncCoursesToWidget = useCallback(
9795
(nextCourses: courseType[]) => {
9896
extensionStorage.set(
@@ -227,6 +225,10 @@ const CourseTablePage: FC = () => {
227225
}
228226
}, [schoolTime]);
229227

228+
useEffect(() => {
229+
setSelectedWeek(selectedWeek);
230+
}, [selectedWeek, setSelectedWeek, totalWeeks]);
231+
230232
// 启用 Live Activity 自动提醒
231233
useCourseLiveActivity(courses);
232234

@@ -278,6 +280,7 @@ const CourseTablePage: FC = () => {
278280
<WeekSelector
279281
currentWeek={selectedWeek}
280282
showWeekPicker={showWeekPicker}
283+
totalWeeks={totalWeeks}
281284
year={year}
282285
semester={semester}
283286
semesterOptions={semesterOptions}

src/store/course.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ interface CourseState {
1818
updateCourseNote: (id: string, note: string) => void;
1919
lastUpdate: number;
2020
setLastUpdate: (time: number) => void;
21-
holidayTime: number;
22-
setHolidayTime: (_time: number) => void;
23-
schoolTime: number;
24-
setSchoolTime: (_time: number) => void;
2521
}
2622

2723
const useCourse = create<CourseState>()(
@@ -66,10 +62,6 @@ const useCourse = create<CourseState>()(
6662
},
6763
lastUpdate: 0,
6864
setLastUpdate: (time: number) => set({ lastUpdate: time }),
69-
holidayTime: 0,
70-
setHolidayTime: (_time: number) => set({ holidayTime: _time }),
71-
schoolTime: 0,
72-
setSchoolTime: (_time: number) => set({ schoolTime: _time }),
7365
};
7466
},
7567
{

src/store/time.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
22
import { create } from 'zustand';
33
import { createJSONStorage, persist } from 'zustand/middleware';
44

5-
import useCourse from './course';
5+
import {
6+
calculateSemesterWeekCount,
7+
clampWeekToSemester,
8+
} from '@/utils/semesterWeeks';
69

710
/**
811
* 根据开学时间戳计算当前学期和学年
@@ -34,32 +37,48 @@ interface TimeState {
3437
setYear: (_year: string) => void;
3538
selectedWeek: number;
3639
setSelectedWeek: (_week: number) => void;
40+
holidayTime: number;
41+
setHolidayTime: (_time: number) => void;
42+
schoolTime: number;
43+
setSchoolTime: (_time: number) => void;
3744
showWeekPicker: boolean;
3845
setShowWeekPicker: (_opened: boolean) => void;
3946
getCurrentWeek: () => number;
47+
getSemesterWeekCount: () => number;
4048
/** 根据开学时间戳计算并更新 semester/year */
4149
computeAndSetSemester: (_startTimestamp: number) => void;
4250
}
4351

4452
const useTimeStore = create<TimeState>()(
4553
persist(
46-
set => {
54+
(set, get) => {
4755
return {
4856
semester: '',
4957
setSemester: (semester: string) => set({ semester }),
5058
year: '',
5159
setYear: (year: string) => set({ year }),
5260
selectedWeek: 1,
53-
setSelectedWeek: (week: number) => set({ selectedWeek: week }),
61+
setSelectedWeek: (week: number) => {
62+
const totalWeeks = get().getSemesterWeekCount();
63+
set({ selectedWeek: clampWeekToSemester(week, totalWeeks) });
64+
},
65+
holidayTime: 0,
66+
setHolidayTime: (_time: number) => set({ holidayTime: _time }),
67+
schoolTime: 0,
68+
setSchoolTime: (_time: number) => set({ schoolTime: _time }),
5469
showWeekPicker: false,
5570
setShowWeekPicker: (showWeekPicker: boolean) =>
5671
set({ showWeekPicker: showWeekPicker }),
5772
getCurrentWeek: () => {
58-
const startTimestamp = useCourse.getState().schoolTime * 1000;
73+
const startTimestamp = get().schoolTime * 1000;
5974
const diffTime = new Date().getTime() - startTimestamp;
6075
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
6176
return Math.floor(diffDays / 7) + 1;
6277
},
78+
getSemesterWeekCount: () => {
79+
const { schoolTime, holidayTime } = get();
80+
return calculateSemesterWeekCount(schoolTime, holidayTime);
81+
},
6382
computeAndSetSemester: (startTimestamp: number) => {
6483
const { semester, year } = computeSemesterAndYear(startTimestamp);
6584
set({ semester, year });

src/utils/semesterWeeks.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const SECONDS_PER_WEEK = 7 * 24 * 60 * 60;
2+
3+
export const DEFAULT_SEMESTER_WEEK_COUNT = 20;
4+
5+
export const calculateSemesterWeekCount = (
6+
schoolTime?: number,
7+
holidayTime?: number
8+
) => {
9+
if (!schoolTime || !holidayTime || holidayTime <= schoolTime) {
10+
return DEFAULT_SEMESTER_WEEK_COUNT;
11+
}
12+
13+
return Math.max(1, Math.ceil((holidayTime - schoolTime) / SECONDS_PER_WEEK));
14+
};
15+
16+
export const clampWeekToSemester = (week: number, totalWeeks: number) => {
17+
return Math.min(Math.max(week, 1), totalWeeks);
18+
};

0 commit comments

Comments
 (0)