2991692032 4 weeks ago
parent ddf06225fd
commit 79d07d4fae

@ -9,6 +9,7 @@
- **增强文件存储**: 文件存储从本地上传改为阿里云OSS支持临时访问链接
- **添加数据库设计说明**: 详细说明了资源表和点赞表的设计
- **修正API参数说明**: 更新了资源列表接口中 `user` 参数的含义,改为 `uploaderUserId`
- **优化课程表时间安排**: 学期格式统一为"2024-2025第一学期"格式课程时间安排调整为13个标准时间段
### v1.1.0 (2025-01-26)
- 完成论坛功能模块的前后端集成
@ -1113,14 +1114,32 @@ CREATE TABLE `resource_likes` (
"location": "教学楼A-101",
"dayOfWeek": 1,
"startTime": "08:00:00",
"endTime": "09:40:00",
"endTime": "08:50:00",
"startWeek": 1,
"endWeek": 16,
"semester": "2023-1",
"semester": "2024-2025-1",
"color": "#4CAF50"
}
```
**参数说明**:
- `dayOfWeek`: 星期几1-71表示周一7表示周日
- `startTime`/`endTime`: 课程时间支持13个标准时间段
- 第1节课: 08:00-08:50
- 第2节课: 08:50-09:40
- 第3节课: 09:50-10:40
- 第4节课: 10:40-11:30
- 第5节课: 11:30-12:20
- 第6节课: 14:05-14:55
- 第7节课: 14:55-15:45
- 第8节课: 15:45-16:35
- 第9节课: 16:40-17:30
- 第10节课: 17:30-18:20
- 第11节课: 18:30-19:20
- 第12节课: 19:20-20:10
- 第13节课: 20:10-21:00
- `semester`: 学期格式为"YYYY-YYYY-X"(如:"2024-2025-1"表示2024-2025学年第一学期
响应结果:
```json
{
@ -1151,10 +1170,10 @@ CREATE TABLE `resource_likes` (
"location": "教学楼A-101",
"dayOfWeek": 1,
"startTime": "08:00:00",
"endTime": "09:40:00",
"endTime": "08:50:00",
"startWeek": 1,
"endWeek": 16,
"semester": "2023-1",
"semester": "2024-2025-1",
"color": "#4CAF50",
"status": 1,
"createdAt": "2023-05-01T12:00:00",
@ -1185,10 +1204,10 @@ CREATE TABLE `resource_likes` (
"location": "教学楼A-101",
"dayOfWeek": 1,
"startTime": "08:00:00",
"endTime": "09:40:00",
"endTime": "08:50:00",
"startWeek": 1,
"endWeek": 16,
"semester": "2023-1",
"semester": "2024-2025-1",
"color": "#4CAF50",
"status": 1,
"createdAt": "2023-05-01T12:00:00",
@ -1221,10 +1240,10 @@ CREATE TABLE `resource_likes` (
"location": "教学楼A-101",
"dayOfWeek": 1,
"startTime": "08:00:00",
"endTime": "09:40:00",
"endTime": "08:50:00",
"startWeek": 1,
"endWeek": 16,
"semester": "2023-1",
"semester": "2024-2025-1",
"color": "#4CAF50",
"status": 1,
"createdAt": "2023-05-01T12:00:00",
@ -1241,6 +1260,8 @@ CREATE TABLE `resource_likes` (
- **描述**: 获取当前用户在指定学期的课程
- **认证**: 需要JWT Token
**参数说明**: `semester`路径参数示例:"2024-2025-1"
响应结果:
```json
{
@ -1257,10 +1278,10 @@ CREATE TABLE `resource_likes` (
"location": "教学楼A-101",
"dayOfWeek": 1,
"startTime": "08:00:00",
"endTime": "09:40:00",
"endTime": "08:50:00",
"startWeek": 1,
"endWeek": 16,
"semester": "2023-1",
"semester": "2024-2025-1",
"color": "#4CAF50",
"status": 1,
"createdAt": "2023-05-01T12:00:00",
@ -1284,11 +1305,11 @@ CREATE TABLE `resource_likes` (
"teacher": "李教授",
"location": "教学楼B-202",
"dayOfWeek": 2,
"startTime": "10:00:00",
"endTime": "11:40:00",
"startTime": "09:50:00",
"endTime": "10:40:00",
"startWeek": 1,
"endWeek": 16,
"semester": "2023-1",
"semester": "2024-2025-1",
"color": "#2196F3"
}
```
@ -1574,7 +1595,7 @@ CREATE TABLE `courses` (
`end_time` TIME NOT NULL COMMENT '结束时间',
`start_week` TINYINT NOT NULL COMMENT '开始周次',
`end_week` TINYINT NOT NULL COMMENT '结束周次',
`semester` VARCHAR(20) DEFAULT NULL COMMENT '学期2023-1',
`semester` VARCHAR(20) DEFAULT NULL COMMENT '学期2024-2025-1',
`color` VARCHAR(20) DEFAULT NULL COMMENT '显示颜色',
`status` TINYINT DEFAULT 1 COMMENT '状态0-删除, 1-正常)',
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
@ -1603,9 +1624,27 @@ CREATE TABLE `schedules` (
**特性**:
- 支持学期管理和多学期课程数据
- 支持13个标准课程时间段的时间安排
- 支持时间冲突检测
- 支持课程和日程的颜色标记
- 支持日程提醒功能
- 学期格式统一为"YYYY-YYYY-X"格式
**课程时间安排说明**:
系统支持13个标准课程时间段
- 第1节课: 08:00-08:50
- 第2节课: 08:50-09:40
- 第3节课: 09:50-10:40
- 第4节课: 10:40-11:30
- 第5节课: 11:30-12:20
- 第6节课: 14:05-14:55
- 第7节课: 14:55-15:45
- 第8节课: 15:45-16:35
- 第9节课: 16:40-17:30
- 第10节课: 17:30-18:20
- 第11节课: 18:30-19:20
- 第12节课: 19:20-20:10
- 第13节课: 20:10-21:00
## 7. 待实现模块
@ -1613,4 +1652,4 @@ CREATE TABLE `schedules` (
- 搜索功能模块
- AI辅助学习模块
- 积分系统模块
- 积分系统模块

@ -60,26 +60,51 @@
<el-icon><Calendar /></el-icon>
添加日程
</el-button>
<el-button @click="createTestSchedule" type="warning" plain>
<el-icon><Calendar /></el-icon>
创建测试日程
</el-button>
</div>
</div>
<!-- 学期选择 -->
<div class="semester-selector">
<el-select v-model="currentSemester" placeholder="选择学期" size="default" @change="loadCourses">
<el-option label="2024春季学期" value="2024-1" />
<el-option label="2024秋季学期" value="2024-2" />
<el-option label="2023秋季学期" value="2023-2" />
<el-option label="2023春季学期" value="2023-1" />
<el-select v-model="currentSemester" placeholder="选择学期" size="default" @change="handleSemesterChange">
<el-option
v-for="(config, key) in semesterConfig"
:key="key"
:label="config.name"
:value="key"
/>
</el-select>
<div class="week-selector">
<el-button @click="previousWeek" circle size="small">
<el-icon><ArrowLeft /></el-icon>
</el-button>
<span class="current-week"> {{ currentWeek }} </span>
<el-select
v-model="currentWeek"
placeholder="选择周数"
size="small"
style="width: 120px;"
>
<el-option
v-for="week in getCurrentSemesterConfig().totalWeeks"
:key="week"
:label="`第 ${week} 周`"
:value="week"
/>
</el-select>
<el-button @click="nextWeek" circle size="small">
<el-icon><ArrowRight /></el-icon>
</el-button>
<el-button @click="goToCurrentWeek" size="small" type="primary" plain>
<el-icon><Calendar /></el-icon>
回到今天
</el-button>
</div>
</div>
</div>
@ -92,10 +117,16 @@
v-for="(day, index) in weekDays"
:key="index"
class="day-column"
:class="{ today: isToday(index) }"
:class="{
today: getDayDate(index).isToday,
'current-day': getDayDate(index).isToday
}"
>
<div class="day-name">{{ day }}</div>
<div class="day-date">{{ getDayDate(index) }}</div>
<div class="day-date" :class="{ 'today-date': getDayDate(index).isToday }">
{{ getDayDate(index).month }}/{{ getDayDate(index).date }}
<span v-if="getDayDate(index).isToday" class="today-indicator"></span>
</div>
</div>
</div>
@ -106,27 +137,44 @@
class="time-row"
>
<div class="time-cell">
<div class="time-period">{{ timeIndex + 1 }}</div>
<div class="time-range">{{ timeSlot }}</div>
<div class="time-period">{{ timeSlot }}</div>
</div>
<div
v-for="dayIndex in 7"
:key="dayIndex"
class="course-cell"
@click="addCourseToSlot(timeIndex, dayIndex)"
@click="addCourseToSlot(timeIndex, dayIndex - 1)"
>
<div
v-if="getCourseForSlot(timeIndex, dayIndex)"
class="course-item"
:style="{ backgroundColor: getCourseForSlot(timeIndex, dayIndex)?.color }"
@click.stop="editCourse(getCourseForSlot(timeIndex, dayIndex)!)"
>
<div class="course-name">{{ getCourseForSlot(timeIndex, dayIndex)?.name }}</div>
<div class="course-location">{{ getCourseForSlot(timeIndex, dayIndex)?.location }}</div>
<div class="course-teacher">{{ getCourseForSlot(timeIndex, dayIndex)?.teacher }}</div>
<!-- 显示所有项目课程和日程 -->
<div v-if="getItemsForSlot(timeIndex, dayIndex - 1).length > 0" class="slot-items">
<div
v-for="(item, itemIndex) in getItemsForSlot(timeIndex, dayIndex - 1)"
:key="itemIndex"
:class="item.type === 'course' ? 'course-item' : 'schedule-item'"
:style="{ backgroundColor: item.data.color }"
@click.stop="item.type === 'course' ? editCourse(item.data) : editSchedule(item.data)"
>
<!-- 课程内容 -->
<template v-if="item.type === 'course'">
<div class="course-name">{{ item.data.name }}</div>
<div class="course-location">{{ item.data.location }}</div>
<div class="course-teacher">{{ item.data.teacher }}</div>
</template>
<!-- 日程内容 -->
<template v-else>
<div class="schedule-name">{{ item.data.title }}</div>
<div class="schedule-location">{{ item.data.location }}</div>
<div class="schedule-time" v-if="item.data.isAllDay !== 1">
{{ formatTime(item.data.startTime) }}
</div>
<div class="schedule-time" v-else></div>
</template>
</div>
</div>
<!-- 空白时间段 -->
<div v-else class="empty-slot">
<el-icon class="add-icon"><Plus /></el-icon>
</div>
@ -221,21 +269,33 @@
<div class="form-row">
<el-form-item label="开始时间" prop="startTime">
<el-time-picker
v-model="courseForm.startTime"
format="HH:mm"
placeholder="选择开始时间"
<el-select
v-model="courseForm.startTime"
placeholder="选择开始时间"
style="width: 100%"
/>
>
<el-option
v-for="option in startTimeOptions"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
</el-form-item>
<el-form-item label="结束时间" prop="endTime">
<el-time-picker
v-model="courseForm.endTime"
format="HH:mm"
placeholder="选择结束时间"
<el-select
v-model="courseForm.endTime"
placeholder="选择结束时间"
style="width: 100%"
/>
>
<el-option
v-for="option in endTimeOptions"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
</el-form-item>
</div>
@ -409,7 +469,7 @@ const savingCourse = ref(false)
const savingSchedule = ref(false)
const showAddCourse = ref(false)
const showAddSchedule = ref(false)
const currentSemester = ref('2024-1')
const currentSemester = ref('2024-2025-1')
const currentWeek = ref(1)
//
@ -438,7 +498,17 @@ const courseForm = reactive({
})
//
const scheduleForm = reactive({
const scheduleForm = reactive<{
title: string
description: string
location: string
startTime: string | Date
endTime: string | Date
date: string
isAllDay: boolean
reminder: number
color: string
}>({
title: '',
description: '',
location: '',
@ -489,13 +559,71 @@ const scheduleRules: FormRules = {
//
const weekDays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
const timeSlots = [
'08:00-09:40',
'10:00-11:40',
'14:00-15:40',
'16:00-17:40',
'19:00-20:40'
'08:00-08:50', // 1
'08:50-09:40', // 2
'09:50-10:40', // 3
'10:40-11:30', // 4
'11:30-12:20', // 5
'14:05-14:55', // 6
'14:55-15:45', // 7
'15:45-16:35', // 8
'16:40-17:30', // 9
'17:30-18:20', // 10
'18:30-19:20', // 11
'19:20-20:10', // 12
'20:10-21:00' // 13
]
//
const courseTimeOptions = [
{ label: '第1节课 08:00-08:50', value: '08:00', endValue: '08:50' },
{ label: '第2节课 08:50-09:40', value: '08:50', endValue: '09:40' },
{ label: '第3节课 09:50-10:40', value: '09:50', endValue: '10:40' },
{ label: '第4节课 10:40-11:30', value: '10:40', endValue: '11:30' },
{ label: '第5节课 11:30-12:20', value: '11:30', endValue: '12:20' },
{ label: '第6节课 14:05-14:55', value: '14:05', endValue: '14:55' },
{ label: '第7节课 14:55-15:45', value: '14:55', endValue: '15:45' },
{ label: '第8节课 15:45-16:35', value: '15:45', endValue: '16:35' },
{ label: '第9节课 16:40-17:30', value: '16:40', endValue: '17:30' },
{ label: '第10节课 17:30-18:20', value: '17:30', endValue: '18:20' },
{ label: '第11节课 18:30-19:20', value: '18:30', endValue: '19:20' },
{ label: '第12节课 19:20-20:10', value: '19:20', endValue: '20:10' },
{ label: '第13节课 20:10-21:00', value: '20:10', endValue: '21:00' }
]
//
const startTimeOptions = courseTimeOptions.map(option => ({
label: `${option.value} (${option.label.split(' ')[0]}开始)`,
value: option.value + ':00' // HH:mm:ss
}))
//
const endTimeOptions = courseTimeOptions.map(option => ({
label: `${option.endValue} (${option.label.split(' ')[0]}结束)`,
value: option.endValue + ':00' // HH:mm:ss
}))
//
const courseColors = [
'#409EFF', //
'#67C23A', // 绿
'#E6A23C', //
'#F56C6C', //
'#909399', //
'#9C27B0', //
'#FF5722', //
'#4CAF50', // 绿
'#2196F3', //
'#FF9800', //
'#795548', //
'#607D8B' //
]
//
const getRandomColor = () => {
return courseColors[Math.floor(Math.random() * courseColors.length)]
}
//
const todayCourses = computed(() => {
const today = new Date().getDay()
@ -504,47 +632,295 @@ const todayCourses = computed(() => {
})
const todaySchedules = computed(() => {
//
const today = new Date()
const todayStr = today.toISOString().split('T')[0]
return schedules.value.filter(schedule => {
const scheduleDate = new Date(schedule.startTime).toISOString().split('T')[0]
return scheduleDate === todayStr
console.log('=== 今日日程调试信息 ===')
console.log('今天日期:', todayStr)
console.log('所有日程数据:', schedules.value)
const filteredSchedules = schedules.value.filter(schedule => {
const startDate = new Date(schedule.startTime).toISOString().split('T')[0]
const endDate = new Date(schedule.endTime).toISOString().split('T')[0]
//
const isInRange = todayStr >= startDate && todayStr <= endDate
console.log('日程:', schedule.title)
console.log('开始日期:', startDate, '结束日期:', endDate)
console.log('今天是否在范围内:', isInRange)
return isInRange
})
console.log('筛选后的今日日程:', filteredSchedules)
console.log('=== 调试信息结束 ===')
return filteredSchedules
})
//
//
const semesterConfig = {
'2024-2025-1': {
name: '2024-2025第一学期',
startDate: new Date(2024, 8, 2), // 202492
endDate: new Date(2025, 0, 19), // 2025119
totalWeeks: 20
},
'2024-2025-2': {
name: '2024-2025第二学期',
startDate: new Date(2025, 1, 24), // 2025224
endDate: new Date(2025, 5, 29), // 2025629
totalWeeks: 18
},
'2023-2024-1': {
name: '2023-2024第一学期',
startDate: new Date(2023, 8, 4), // 202394
endDate: new Date(2024, 0, 21), // 2024121
totalWeeks: 20
},
'2023-2024-2': {
name: '2023-2024第二学期',
startDate: new Date(2024, 1, 26), // 2024226
endDate: new Date(2024, 5, 30), // 2024630
totalWeeks: 18
},
'2022-2023-1': {
name: '2022-2023第一学期',
startDate: new Date(2022, 8, 5), // 202295
endDate: new Date(2023, 0, 15), // 2023115
totalWeeks: 20
},
'2022-2023-2': {
name: '2022-2023第二学期',
startDate: new Date(2023, 1, 27), // 2023227
endDate: new Date(2023, 6, 2), // 202372
totalWeeks: 18
}
}
//
const getCurrentSemester = () => {
const now = new Date()
//
const sortedSemesters = Object.entries(semesterConfig).sort((a, b) => {
return b[1].startDate.getTime() - a[1].startDate.getTime() //
})
for (const [semesterKey, config] of sortedSemesters) {
if (now >= config.startDate && now <= config.endDate) {
return semesterKey
}
}
//
let closestSemester = '2024-2025-1'
let minDistance = Infinity
for (const [semesterKey, config] of Object.entries(semesterConfig)) {
//
const distanceToStart = Math.abs(now.getTime() - config.startDate.getTime())
//
const distanceToEnd = Math.abs(now.getTime() - config.endDate.getTime())
//
const distance = Math.min(distanceToStart, distanceToEnd)
if (distance < minDistance) {
minDistance = distance
closestSemester = semesterKey
}
}
console.log('当前时间不在任何学期范围内,选择最接近的学期:', closestSemester)
return closestSemester
}
//
const getCurrentWeekInSemester = (semester: string) => {
const config = semesterConfig[semester as keyof typeof semesterConfig]
if (!config) return 1
const now = new Date()
// 1
if (now < config.startDate || now > config.endDate) {
return 1
}
//
const diffTime = now.getTime() - config.startDate.getTime()
const diffWeeks = Math.floor(diffTime / (7 * 24 * 60 * 60 * 1000)) + 1
return Math.max(1, Math.min(diffWeeks, config.totalWeeks))
}
//
const getWeekMondayDate = (semester: string, week: number) => {
const config = semesterConfig[semester as keyof typeof semesterConfig]
if (!config) return new Date()
const mondayDate = new Date(config.startDate)
mondayDate.setDate(config.startDate.getDate() + (week - 1) * 7)
return mondayDate
}
//
const getCurrentSemesterConfig = () => {
return semesterConfig[currentSemester.value as keyof typeof semesterConfig] || semesterConfig['2024-2025-1']
}
//
const handleSemesterChange = (newSemester: string) => {
console.log('学期切换到:', newSemester)
// 1
currentWeek.value = 1
//
loadCourses()
}
const isToday = (dayIndex: number) => {
const today = new Date().getDay()
const now = new Date()
const currentSemesterKey = getCurrentSemester()
// ""
if (currentSemester.value !== currentSemesterKey) {
return false
}
// ""
const currentWeekInSemester = getCurrentWeekInSemester(currentSemester.value)
if (currentWeek.value !== currentWeekInSemester) {
return false
}
const today = now.getDay()
const targetDay = dayIndex + 1
return today === 0 ? targetDay === 7 : today === targetDay
}
const getDayDate = (dayIndex: number) => {
const today = new Date()
const currentDayOfWeek = today.getDay()
const monday = new Date(today)
monday.setDate(today.getDate() - (currentDayOfWeek === 0 ? 6 : currentDayOfWeek - 1))
const monday = getWeekMondayDate(currentSemester.value, currentWeek.value)
const targetDate = new Date(monday)
targetDate.setDate(monday.getDate() + dayIndex)
return targetDate.getDate()
//
const now = new Date()
const isCurrentDay = (
targetDate.getFullYear() === now.getFullYear() &&
targetDate.getMonth() === now.getMonth() &&
targetDate.getDate() === now.getDate()
)
return {
date: targetDate.getDate(),
month: targetDate.getMonth() + 1,
isToday: isCurrentDay,
fullDate: targetDate
}
}
const getCourseForSlot = (timeIndex: number, dayIndex: number) => {
return courses.value.find(course => {
// dayIndex0-61-7
if (course.dayOfWeek !== dayIndex + 1) return false
//
const courseStart = course.startTime
const courseEnd = course.endTime
const slotTime = timeSlots[timeIndex]
//
if (currentWeek.value < course.startWeek || currentWeek.value > course.endWeek) {
return false
}
//
return slotTime.includes(courseStart.substring(0, 5))
//
const slotTimes = timeSlots[timeIndex].split('-')
const slotStart = slotTimes[0] // : "08:00"
const slotEnd = slotTimes[1] // : "08:50"
// ()
const courseStart = course.startTime.substring(0, 5) // "08:00:00" -> "08:00"
const courseEnd = course.endTime.substring(0, 5) // "09:40:00" -> "09:40"
//
// <= && <=
return courseStart <= slotStart && slotEnd <= courseEnd
})
}
//
const getScheduleForSlot = (timeIndex: number, dayIndex: number) => {
//
const targetDate = getDayDate(dayIndex)
const targetDateStr = `${targetDate.fullDate.getFullYear()}-${String(targetDate.fullDate.getMonth() + 1).padStart(2, '0')}-${String(targetDate.fullDate.getDate()).padStart(2, '0')}`
//
const slotTimes = timeSlots[timeIndex].split('-')
const slotStart = slotTimes[0] // : "08:00"
const slotEnd = slotTimes[1] // : "08:50"
return schedules.value.find(schedule => {
//
const startDate = new Date(schedule.startTime).toISOString().split('T')[0]
const endDate = new Date(schedule.endTime).toISOString().split('T')[0]
//
const isDateInRange = targetDateStr >= startDate && targetDateStr <= endDate
if (!isDateInRange) return false
//
if (schedule.isAllDay === 1) {
return timeIndex === 0
}
//
if (startDate !== endDate) {
//
if (targetDateStr === startDate) {
const scheduleStart = new Date(schedule.startTime).toTimeString().substring(0, 5)
return slotStart >= scheduleStart
}
//
else if (targetDateStr === endDate) {
const scheduleEnd = new Date(schedule.endTime).toTimeString().substring(0, 5)
return slotEnd <= scheduleEnd
}
//
else {
return true
}
} else {
//
const scheduleStart = new Date(schedule.startTime).toTimeString().substring(0, 5) // "08:00"
const scheduleEnd = new Date(schedule.endTime).toTimeString().substring(0, 5) // "09:40"
//
return scheduleStart < slotEnd && scheduleEnd > slotStart
}
})
}
//
const getItemsForSlot = (timeIndex: number, dayIndex: number) => {
const items: Array<{type: 'course' | 'schedule', data: any}> = []
//
const course = getCourseForSlot(timeIndex, dayIndex)
if (course) {
items.push({ type: 'course', data: course })
}
//
const schedule = getScheduleForSlot(timeIndex, dayIndex)
if (schedule) {
items.push({ type: 'schedule', data: schedule })
}
return items
}
const previousWeek = () => {
if (currentWeek.value > 1) {
currentWeek.value--
@ -552,17 +928,53 @@ const previousWeek = () => {
}
const nextWeek = () => {
if (currentWeek.value < 20) {
const maxWeeks = getCurrentSemesterConfig().totalWeeks
if (currentWeek.value < maxWeeks) {
currentWeek.value++
}
}
//
const goToCurrentWeek = () => {
//
const currentRealSemester = getCurrentSemester()
const currentRealWeek = getCurrentWeekInSemester(currentRealSemester)
//
if (currentSemester.value === currentRealSemester && currentWeek.value === currentRealWeek) {
const config = getCurrentSemesterConfig()
ElMessage.info(`当前已经是${config.name}${currentRealWeek}`)
return
}
//
if (currentSemester.value !== currentRealSemester) {
console.log('切换到当前学期:', currentRealSemester)
currentSemester.value = currentRealSemester
// handleSemesterChange
loadCourses()
}
//
currentWeek.value = currentRealWeek
console.log('回到今天 - 学期:', currentRealSemester, '周数:', currentRealWeek)
//
const config = getCurrentSemesterConfig()
ElMessage.success(`已切换到${config.name}${currentRealWeek}`)
}
const addCourseToSlot = (timeIndex: number, dayIndex: number) => {
//
courseForm.dayOfWeek = dayIndex + 1
const timeSlot = timeSlots[timeIndex].split('-')
courseForm.startTime = timeSlot[0]
courseForm.endTime = timeSlot[1]
if (timeIndex < courseTimeOptions.length) {
courseForm.startTime = courseTimeOptions[timeIndex].value + ':00'
//
courseForm.endTime = ''
}
//
courseForm.color = getRandomColor()
showAddCourse.value = true
}
@ -668,11 +1080,22 @@ const handleSaveSchedule = async () => {
let startTime, endTime
if (scheduleForm.isAllDay) {
startTime = `${scheduleForm.date}T00:00:00`
endTime = `${scheduleForm.date}T23:59:59`
// 使00:00:0023:59:59
const dateStr = scheduleForm.date
startTime = `${dateStr}T00:00:00`
endTime = `${dateStr}T23:59:59`
} else {
//
startTime = scheduleForm.startTime
endTime = scheduleForm.endTime
// DateISO
if (startTime && typeof startTime === 'object') {
startTime = (startTime as any).toISOString().slice(0, 19)
}
if (endTime && typeof endTime === 'object') {
endTime = (endTime as any).toISOString().slice(0, 19)
}
}
const scheduleData = {
@ -686,6 +1109,8 @@ const handleSaveSchedule = async () => {
color: scheduleForm.color
}
console.log('保存日程数据:', scheduleData)
let response
if (editingSchedule.value) {
response = await updateSchedule(editingSchedule.value.id, scheduleData) as any as ApiResponse<null>
@ -715,8 +1140,12 @@ const editCourse = (course: Course) => {
courseForm.teacher = course.teacher
courseForm.location = course.location
courseForm.dayOfWeek = course.dayOfWeek
courseForm.startTime = course.startTime
courseForm.endTime = course.endTime
courseForm.startTime = course.startTime.includes(':') && course.startTime.split(':').length === 3
? course.startTime
: course.startTime + ':00'
courseForm.endTime = course.endTime.includes(':') && course.endTime.split(':').length === 3
? course.endTime
: course.endTime + ':00'
courseForm.startWeek = course.startWeek
courseForm.endWeek = course.endWeek
courseForm.color = course.color
@ -733,10 +1162,15 @@ const editSchedule = (schedule: Schedule) => {
scheduleForm.color = schedule.color
if (schedule.isAllDay === 1) {
//
scheduleForm.date = new Date(schedule.startTime).toISOString().split('T')[0]
scheduleForm.startTime = ''
scheduleForm.endTime = ''
} else {
scheduleForm.startTime = schedule.startTime
scheduleForm.endTime = schedule.endTime
//
scheduleForm.date = ''
scheduleForm.startTime = new Date(schedule.startTime)
scheduleForm.endTime = new Date(schedule.endTime)
}
showAddSchedule.value = true
@ -816,7 +1250,7 @@ const resetCourseForm = () => {
courseForm.endTime = ''
courseForm.startWeek = 1
courseForm.endWeek = 16
courseForm.color = '#409EFF'
courseForm.color = getRandomColor()
courseFormRef.value?.clearValidate()
}
@ -830,7 +1264,7 @@ const resetScheduleForm = () => {
scheduleForm.date = ''
scheduleForm.isAllDay = false
scheduleForm.reminder = 30
scheduleForm.color = '#67C23A'
scheduleForm.color = getRandomColor()
scheduleFormRef.value?.clearValidate()
}
@ -870,18 +1304,69 @@ watch(showAddSchedule, (newVal) => {
}
})
//
watch(currentWeek, () => {
console.log('当前周数变化为:', currentWeek.value)
// getCourseForSlot使currentWeek.value
// Vue
})
//
onMounted(async () => {
console.log('课程表页面加载完成')
//
currentSemester.value = getCurrentSemester()
console.log('自动选择学期:', currentSemester.value)
//
currentWeek.value = getCurrentWeekInSemester(currentSemester.value)
console.log('自动定位到当前周:', currentWeek.value)
console.log('开始加载课程和日程数据...')
await loadCourses()
await loadSchedules()
//
const now = new Date()
const startOfYear = new Date(now.getFullYear(), 0, 1)
const weekNumber = Math.ceil((now.getTime() - startOfYear.getTime()) / (7 * 24 * 60 * 60 * 1000))
currentWeek.value = Math.min(weekNumber, 20)
console.log('数据加载完成,当前日程数据:', schedules.value)
console.log('今日日程计算结果:', todaySchedules.value)
})
const createTestSchedule = async () => {
console.log('开始创建测试日程')
const today = new Date()
const todayStr = today.toISOString().split('T')[0]
const testScheduleData = {
title: '测试日程',
description: '这是一个测试日程,用于验证今日日程显示功能',
location: '测试地点',
startTime: `${todayStr}T10:00:00`,
endTime: `${todayStr}T11:00:00`,
isAllDay: 0,
reminder: 30,
color: '#67C23A'
}
console.log('测试日程数据:', testScheduleData)
try {
const response = await createSchedule(testScheduleData) as any as ApiResponse<{ scheduleId: number }>
if (response.code === 200) {
ElMessage.success('测试日程创建成功!')
await loadSchedules() //
console.log('重新加载后的日程数据:', schedules.value)
console.log('重新计算的今日日程:', todaySchedules.value)
} else {
ElMessage.error(response.message || '创建测试日程失败')
console.error('创建测试日程失败:', response)
}
} catch (error) {
console.error('创建测试日程出错:', error)
ElMessage.error('创建测试日程出错')
}
}
</script>
<style scoped>
@ -1058,6 +1543,12 @@ onMounted(async () => {
color: var(--primary-700);
}
.day-column.current-day {
background: linear-gradient(135deg, var(--primary-100), var(--primary-200));
border: 2px solid var(--primary-400);
border-radius: 8px 8px 0 0;
}
.day-name {
font-size: 14px;
margin-bottom: 4px;
@ -1066,6 +1557,24 @@ onMounted(async () => {
.day-date {
font-size: 12px;
opacity: 0.8;
position: relative;
}
.day-date.today-date {
opacity: 1;
font-weight: 700;
color: var(--primary-700);
}
.today-indicator {
display: block;
font-size: 10px;
color: var(--primary-600);
background: var(--primary-200);
padding: 1px 4px;
border-radius: 4px;
margin-top: 2px;
font-weight: 600;
}
.table-body {
@ -1109,6 +1618,34 @@ onMounted(async () => {
background: var(--primary-50);
}
.slot-items {
height: 100%;
display: flex;
flex-direction: column;
gap: 2px;
}
.slot-items .course-item,
.slot-items .schedule-item {
flex: 1;
min-height: 0;
padding: 4px 6px;
}
.slot-items .course-name,
.slot-items .schedule-name {
font-size: 10px;
margin-bottom: 1px;
}
.slot-items .course-location,
.slot-items .course-teacher,
.slot-items .schedule-location,
.slot-items .schedule-time {
font-size: 8px;
line-height: 1.1;
}
.course-item {
height: 100%;
padding: 8px;
@ -1293,4 +1830,51 @@ onMounted(async () => {
grid-template-columns: 1fr 1fr;
gap: 16px;
}
.course-item {
height: 100%;
padding: 8px;
border-radius: 8px;
border-left: 4px solid rgba(0, 0, 0, 0.2);
cursor: pointer;
transition: var(--transition-base);
}
.course-item:hover {
transform: translateY(-1px);
box-shadow: var(--shadow-md);
}
.schedule-item {
height: 100%;
padding: 8px;
border-radius: 8px;
border-left: 4px dashed rgba(0, 0, 0, 0.3);
cursor: pointer;
transition: var(--transition-base);
opacity: 0.9;
}
.schedule-item:hover {
transform: translateY(-1px);
box-shadow: var(--shadow-md);
opacity: 1;
}
.course-name,
.schedule-name {
font-size: 12px;
font-weight: 600;
color: var(--gray-800);
margin-bottom: 2px;
}
.course-location,
.course-teacher,
.schedule-location,
.schedule-time {
font-size: 10px;
color: var(--gray-600);
line-height: 1.2;
}
</style>
Loading…
Cancel
Save