feat(教师端): 重构学生详情页签到和反馈功能
更新API路径和字段命名以匹配后端接口 添加状态格式化函数统一显示文本 实现分页加载和重置功能 完善反馈表单的提交和显示逻辑
Showing
2 changed files
with
188 additions
and
148 deletions
| 1 | /* | 1 | /* |
| 2 | * @Date: 2025-06-23 11:46:21 | 2 | * @Date: 2025-06-23 11:46:21 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-06-26 16:15:15 | 4 | + * @LastEditTime: 2025-06-27 09:55:12 |
| 5 | * @FilePath: /mlaj/src/api/teacher.js | 5 | * @FilePath: /mlaj/src/api/teacher.js |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | */ | 7 | */ |
| ... | @@ -15,9 +15,9 @@ const Api = { | ... | @@ -15,9 +15,9 @@ const Api = { |
| 15 | STUDENT_DETAIL: '/srv/?a=user&t=student_detail', | 15 | STUDENT_DETAIL: '/srv/?a=user&t=student_detail', |
| 16 | STUDENT_CHECKIN_LIST: '/srv/?a=checkin&t=student_checkin_list', | 16 | STUDENT_CHECKIN_LIST: '/srv/?a=checkin&t=student_checkin_list', |
| 17 | STUDENT_UPLOAD_LIST: '/srv/?a=checkin&t=student_upload_list', | 17 | STUDENT_UPLOAD_LIST: '/srv/?a=checkin&t=student_upload_list', |
| 18 | - STUDENT_CHECKIN_FEEDBACK_LIST: '/srv/?a=checkin_feedback&t=list', | 18 | + STUDENT_CHECKIN_FEEDBACK_LIST: '/srv/?a=feedback&t=list', |
| 19 | - ADD_CHECKIN_FEEDBACK: '/srv/?a=checkin_feedback&t=add', | 19 | + ADD_CHECKIN_FEEDBACK: '/srv/?a=feedback&t=add', |
| 20 | - DEL_CHECKIN_FEEDBACK: '/srv/?a=checkin_feedback&t=del', | 20 | + DEL_CHECKIN_FEEDBACK: '/srv/?a=feedback&t=del', |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | /** | 23 | /** | ... | ... |
| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | * @Author: hookehuyr hookehuyr@gmail.com | 2 | * @Author: hookehuyr hookehuyr@gmail.com |
| 3 | * @Date: 2025-06-19 17:12:19 | 3 | * @Date: 2025-06-19 17:12:19 |
| 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 5 | - * @LastEditTime: 2025-06-26 16:36:01 | 5 | + * @LastEditTime: 2025-06-27 10:49:01 |
| 6 | * @FilePath: /mlaj/src/views/teacher/studentPage.vue | 6 | * @FilePath: /mlaj/src/views/teacher/studentPage.vue |
| 7 | * @Description: 学生详情页面 | 7 | * @Description: 学生详情页面 |
| 8 | --> | 8 | --> |
| ... | @@ -94,7 +94,7 @@ | ... | @@ -94,7 +94,7 @@ |
| 94 | <!-- 状态筛选 --> | 94 | <!-- 状态筛选 --> |
| 95 | <div class="flex items-center justify-end mb-4"> | 95 | <div class="flex items-center justify-end mb-4"> |
| 96 | <div @click="showStatusPopup = true" class="flex items-center text-sm text-gray-600 cursor-pointer"> | 96 | <div @click="showStatusPopup = true" class="flex items-center text-sm text-gray-600 cursor-pointer"> |
| 97 | - <span>{{ statusFilter }}</span> | 97 | + <span>{{ formatStatus(statusFilter) }}</span> |
| 98 | <van-icon name="arrow-down" size="14" class="ml-1" /> | 98 | <van-icon name="arrow-down" size="14" class="ml-1" /> |
| 99 | </div> | 99 | </div> |
| 100 | </div> | 100 | </div> |
| ... | @@ -132,12 +132,13 @@ | ... | @@ -132,12 +132,13 @@ |
| 132 | 132 | ||
| 133 | <!-- 右侧:状态 --> | 133 | <!-- 右侧:状态 --> |
| 134 | <div class="flex items-center"> | 134 | <div class="flex items-center"> |
| 135 | - <span v-if="record.status === '正常'" class="text-green-600 text-sm mr-2">{{ record.status }}</span> | 135 | + <span v-if="record.status === 'checked'" class="text-green-600 text-sm mr-2">{{ formatStatus(record.status) }}</span> |
| 136 | - <span v-else-if="record.status === '迟到'" class="text-orange-500 text-sm mr-2">{{ record.status }}</span> | 136 | + <span v-else-if="record.status === 'absence'" class="text-orange-500 text-sm mr-2">{{ formatStatus(record.status) }}</span> |
| 137 | - <span v-else class="text-red-500 text-sm mr-2">{{ record.status }}</span> | 137 | + <span v-else class="text-red-500 text-sm mr-2">{{ formatStatus(record.status) }}</span> |
| 138 | 138 | ||
| 139 | - <van-icon v-if="record.status === '正常'" name="passed" color="#10b981" size="16" /> | 139 | + <van-icon v-if="record.status === 'checked'" name="passed" color="#10b981" size="16" /> |
| 140 | - <van-icon v-else-if="record.status === '迟到'" name="warning-o" color="#f59e0b" size="16" /> | 140 | + <van-icon v-else-if="record.status === 'absence'" name="warning-o" color="#f59e0b" size="16" /> |
| 141 | + <van-icon v-else-if="record.status === 'late'" name="warning-o" color="#f59e0b" size="16" /> | ||
| 141 | <van-icon v-else name="close" color="#ef4444" size="16" /> | 142 | <van-icon v-else name="close" color="#ef4444" size="16" /> |
| 142 | </div> | 143 | </div> |
| 143 | </div> | 144 | </div> |
| ... | @@ -153,7 +154,7 @@ | ... | @@ -153,7 +154,7 @@ |
| 153 | <div class="flex items-center justify-between mb-3"> | 154 | <div class="flex items-center justify-between mb-3"> |
| 154 | <div class="flex items-center"> | 155 | <div class="flex items-center"> |
| 155 | <van-icon name="calendar-o" size="16" color="#10b981" class="mr-2" /> | 156 | <van-icon name="calendar-o" size="16" color="#10b981" class="mr-2" /> |
| 156 | - <span class="text-sm text-gray-600">{{ evaluation.date }}</span> | 157 | + <span class="text-sm text-gray-600">{{ dayjs(evaluation.created_time).format('YYYY-MM-DD HH:mm:ss') }}</span> |
| 157 | </div> | 158 | </div> |
| 158 | <van-icon | 159 | <van-icon |
| 159 | name="delete-o" | 160 | name="delete-o" |
| ... | @@ -168,7 +169,7 @@ | ... | @@ -168,7 +169,7 @@ |
| 168 | <div class="flex items-start mb-3"> | 169 | <div class="flex items-start mb-3"> |
| 169 | <van-icon name="chat-o" size="16" color="#3b82f6" class="mr-2 mt-0.5" /> | 170 | <van-icon name="chat-o" size="16" color="#3b82f6" class="mr-2 mt-0.5" /> |
| 170 | <div class="flex-1"> | 171 | <div class="flex-1"> |
| 171 | - <p class="text-gray-800 text-sm leading-relaxed">{{ evaluation.content }}</p> | 172 | + <p class="text-gray-800 text-sm leading-relaxed">{{ evaluation.note }}</p> |
| 172 | </div> | 173 | </div> |
| 173 | </div> | 174 | </div> |
| 174 | 175 | ||
| ... | @@ -268,6 +269,7 @@ | ... | @@ -268,6 +269,7 @@ |
| 268 | </div> | 269 | </div> |
| 269 | </div> | 270 | </div> |
| 270 | </van-list> | 271 | </van-list> |
| 272 | + <van-empty v-show="activeTab === 'homework' && !checkinDataList.length" description="暂无数据" /> | ||
| 271 | <van-back-top right="5vw" bottom="10vh" /> | 273 | <van-back-top right="5vw" bottom="10vh" /> |
| 272 | <div style="height: 5rem;"></div> | 274 | <div style="height: 5rem;"></div> |
| 273 | 275 | ||
| ... | @@ -298,14 +300,14 @@ | ... | @@ -298,14 +300,14 @@ |
| 298 | <!-- 评分 --> | 300 | <!-- 评分 --> |
| 299 | <div class="mb-4"> | 301 | <div class="mb-4"> |
| 300 | <div class="text-sm text-gray-600 mb-2">评分</div> | 302 | <div class="text-sm text-gray-600 mb-2">评分</div> |
| 301 | - <van-rate v-model="commentForm.rating" :size="24" color="#ffd21e" void-color="#eee" /> | 303 | + <van-rate v-model="commentForm.score" :size="24" color="#ffd21e" void-color="#eee" :readonly="currentCommentPost.is_feedback" /> |
| 302 | </div> | 304 | </div> |
| 303 | 305 | ||
| 304 | <!-- 点评内容 --> | 306 | <!-- 点评内容 --> |
| 305 | <div class="mb-6"> | 307 | <div class="mb-6"> |
| 306 | <div class="text-sm text-gray-600 mb-2">点评内容</div> | 308 | <div class="text-sm text-gray-600 mb-2">点评内容</div> |
| 307 | <van-field | 309 | <van-field |
| 308 | - v-model="commentForm.content" | 310 | + v-model="commentForm.note" |
| 309 | type="textarea" | 311 | type="textarea" |
| 310 | placeholder="请输入点评内容..." | 312 | placeholder="请输入点评内容..." |
| 311 | rows="4" | 313 | rows="4" |
| ... | @@ -313,11 +315,12 @@ | ... | @@ -313,11 +315,12 @@ |
| 313 | show-word-limit | 315 | show-word-limit |
| 314 | :border="false" | 316 | :border="false" |
| 315 | class="bg-gray-50 rounded-lg" | 317 | class="bg-gray-50 rounded-lg" |
| 318 | + :readonly="currentCommentPost.is_feedback" | ||
| 316 | /> | 319 | /> |
| 317 | </div> | 320 | </div> |
| 318 | 321 | ||
| 319 | <!-- 操作按钮 --> | 322 | <!-- 操作按钮 --> |
| 320 | - <div class="flex gap-3"> | 323 | + <div v-if="!currentCommentPost.is_feedback" class="flex gap-3"> |
| 321 | <van-button | 324 | <van-button |
| 322 | block | 325 | block |
| 323 | type="default" | 326 | type="default" |
| ... | @@ -331,11 +334,20 @@ | ... | @@ -331,11 +334,20 @@ |
| 331 | type="primary" | 334 | type="primary" |
| 332 | @click="submitComment" | 335 | @click="submitComment" |
| 333 | class="flex-1" | 336 | class="flex-1" |
| 334 | - :disabled="!commentForm.content.trim()" | ||
| 335 | > | 337 | > |
| 336 | 提交 | 338 | 提交 |
| 337 | </van-button> | 339 | </van-button> |
| 338 | </div> | 340 | </div> |
| 341 | + <div v-else class="flex gap-3"> | ||
| 342 | + <van-button | ||
| 343 | + block | ||
| 344 | + type="default" | ||
| 345 | + @click="closeCommentPopup" | ||
| 346 | + class="flex-1" | ||
| 347 | + > | ||
| 348 | + 关闭 | ||
| 349 | + </van-button> | ||
| 350 | + </div> | ||
| 339 | </div> | 351 | </div> |
| 340 | </van-popup> | 352 | </van-popup> |
| 341 | 353 | ||
| ... | @@ -404,8 +416,9 @@ const showStatusPopup = ref(false) | ... | @@ -404,8 +416,9 @@ const showStatusPopup = ref(false) |
| 404 | const showCommentPopup = ref(false) | 416 | const showCommentPopup = ref(false) |
| 405 | const currentCommentPost = ref(null) | 417 | const currentCommentPost = ref(null) |
| 406 | const commentForm = ref({ | 418 | const commentForm = ref({ |
| 407 | - rating: 0, | 419 | + checkin_id: '', |
| 408 | - content: '' | 420 | + score: 0, |
| 421 | + note: '' | ||
| 409 | }) | 422 | }) |
| 410 | 423 | ||
| 411 | /** | 424 | /** |
| ... | @@ -413,15 +426,17 @@ const commentForm = ref({ | ... | @@ -413,15 +426,17 @@ const commentForm = ref({ |
| 413 | * @param {Object} post - 作业帖子对象 | 426 | * @param {Object} post - 作业帖子对象 |
| 414 | */ | 427 | */ |
| 415 | const openCommentPopup = (post) => { | 428 | const openCommentPopup = (post) => { |
| 429 | + console.warn(post); | ||
| 416 | currentCommentPost.value = post | 430 | currentCommentPost.value = post |
| 431 | + commentForm.value.checkin_id = post.id | ||
| 417 | // 如果已有点评,填充表单 | 432 | // 如果已有点评,填充表单 |
| 418 | - if (post.comment) { | 433 | + if (post.feedback_id) { |
| 419 | - commentForm.value.rating = post.comment.rating || 0 | 434 | + commentForm.value.score = post.feedback_score || 0 |
| 420 | - commentForm.value.content = post.comment.content || '' | 435 | + commentForm.value.note = post.feedback || '' |
| 421 | } else { | 436 | } else { |
| 422 | // 重置表单 | 437 | // 重置表单 |
| 423 | - commentForm.value.rating = 0 | 438 | + commentForm.value.score = 0 |
| 424 | - commentForm.value.content = '' | 439 | + commentForm.value.note = '' |
| 425 | } | 440 | } |
| 426 | showCommentPopup.value = true | 441 | showCommentPopup.value = true |
| 427 | } | 442 | } |
| ... | @@ -430,22 +445,28 @@ const openCommentPopup = (post) => { | ... | @@ -430,22 +445,28 @@ const openCommentPopup = (post) => { |
| 430 | * 关闭点评弹窗 | 445 | * 关闭点评弹窗 |
| 431 | */ | 446 | */ |
| 432 | const closeCommentPopup = () => { | 447 | const closeCommentPopup = () => { |
| 448 | + // 如果已点评,关闭弹窗 | ||
| 449 | + if (currentCommentPost.value && currentCommentPost.value.is_feedback) { | ||
| 450 | + showCommentPopup.value = false | ||
| 451 | + return | ||
| 452 | + } | ||
| 453 | + // 未点评的关闭重置显示 | ||
| 433 | showCommentPopup.value = false | 454 | showCommentPopup.value = false |
| 434 | currentCommentPost.value = null | 455 | currentCommentPost.value = null |
| 435 | - commentForm.value.rating = 0 | 456 | + commentForm.value.score = 0 |
| 436 | - commentForm.value.content = '' | 457 | + commentForm.value.note = '' |
| 437 | } | 458 | } |
| 438 | 459 | ||
| 439 | /** | 460 | /** |
| 440 | * 提交点评 | 461 | * 提交点评 |
| 441 | */ | 462 | */ |
| 442 | const submitComment = async () => { | 463 | const submitComment = async () => { |
| 443 | - if (!commentForm.value.content.trim()) { | 464 | + if (!commentForm.value.note.trim()) { |
| 444 | showFailToast('请输入点评内容') | 465 | showFailToast('请输入点评内容') |
| 445 | return | 466 | return |
| 446 | } | 467 | } |
| 447 | 468 | ||
| 448 | - if (commentForm.value.rating === 0) { | 469 | + if (commentForm.value.score === 0) { |
| 449 | showFailToast('请选择评分') | 470 | showFailToast('请选择评分') |
| 450 | return | 471 | return |
| 451 | } | 472 | } |
| ... | @@ -454,23 +475,23 @@ const submitComment = async () => { | ... | @@ -454,23 +475,23 @@ const submitComment = async () => { |
| 454 | showLoadingToast('提交中...') | 475 | showLoadingToast('提交中...') |
| 455 | 476 | ||
| 456 | // 这里应该调用API提交点评 | 477 | // 这里应该调用API提交点评 |
| 457 | - // await submitCommentAPI(currentCommentPost.value.id, commentForm.value) | 478 | + const { code, data } = await addCheckinFeedbackAPI(commentForm.value) |
| 458 | - | 479 | + if (code) { |
| 459 | - // 模拟API调用 | 480 | + commentForm.value.feedback_id = data.id |
| 460 | - await new Promise(resolve => setTimeout(resolve, 1000)) | 481 | + // 更新本地数据 |
| 461 | - | ||
| 462 | - // 更新本地数据 | ||
| 463 | - if (currentCommentPost.value) { | ||
| 464 | currentCommentPost.value.is_feedback = true | 482 | currentCommentPost.value.is_feedback = true |
| 465 | - currentCommentPost.value.comment = { | 483 | + checkinDataList.value.forEach(item => { |
| 466 | - rating: commentForm.value.rating, | 484 | + if (item.id === currentCommentPost.value.id) { |
| 467 | - content: commentForm.value.content, | 485 | + item.feedback_id = commentForm.value.feedback_id |
| 468 | - created_at: new Date().toISOString() | 486 | + item.feedback_score = commentForm.value.score |
| 469 | - } | 487 | + item.feedback = commentForm.value.note |
| 488 | + } | ||
| 489 | + }) | ||
| 490 | + | ||
| 491 | + showSuccessToast('点评提交成功') | ||
| 492 | + closeCommentPopup() | ||
| 470 | } | 493 | } |
| 471 | 494 | ||
| 472 | - showSuccessToast('点评提交成功') | ||
| 473 | - closeCommentPopup() | ||
| 474 | } catch (error) { | 495 | } catch (error) { |
| 475 | console.error('提交点评失败:', error) | 496 | console.error('提交点评失败:', error) |
| 476 | showFailToast('提交失败,请重试') | 497 | showFailToast('提交失败,请重试') |
| ... | @@ -492,101 +513,48 @@ const toggleCourseSelection = (course) => { | ... | @@ -492,101 +513,48 @@ const toggleCourseSelection = (course) => { |
| 492 | 513 | ||
| 493 | // 可以在这里添加其他业务逻辑,比如筛选相关数据 | 514 | // 可以在这里添加其他业务逻辑,比如筛选相关数据 |
| 494 | console.log('当前选中的课程:', selectedCourses.value) | 515 | console.log('当前选中的课程:', selectedCourses.value) |
| 516 | + | ||
| 517 | + resetAndReload() | ||
| 518 | + resetAndReloadRecords() | ||
| 519 | + resetAndReloadEvaluations() | ||
| 495 | } | 520 | } |
| 496 | 521 | ||
| 497 | // 状态选项 | 522 | // 状态选项 |
| 498 | const statusOptions = ref([ | 523 | const statusOptions = ref([ |
| 499 | { text: '按状态', value: '按状态' }, | 524 | { text: '按状态', value: '按状态' }, |
| 500 | - { text: '正常', value: '正常' }, | 525 | + { text: '正常', value: 'checked' }, |
| 501 | - { text: '迟到', value: '迟到' }, | 526 | + { text: '缺勤', value: 'absence' } |
| 502 | - { text: '缺勤', value: '缺勤' } | 527 | +]); |
| 503 | -]) | 528 | + |
| 529 | +const formatStatus = (status) => { | ||
| 530 | + const statusMap = { | ||
| 531 | + checked: '正常', | ||
| 532 | + absence: '缺勤' | ||
| 533 | + } | ||
| 534 | + return statusMap[status] || status | ||
| 535 | +} | ||
| 504 | 536 | ||
| 505 | // 记录列表 | 537 | // 记录列表 |
| 506 | -const records = ref([ | 538 | +const records = ref([]) |
| 507 | - { | ||
| 508 | - id: 1, | ||
| 509 | - date: '2023-11-20', | ||
| 510 | - time: '07:45', | ||
| 511 | - status: '正常' | ||
| 512 | - }, | ||
| 513 | - { | ||
| 514 | - id: 2, | ||
| 515 | - date: '2023-11-19', | ||
| 516 | - time: '07:50', | ||
| 517 | - status: '正常' | ||
| 518 | - }, | ||
| 519 | - { | ||
| 520 | - id: 3, | ||
| 521 | - date: '2023-11-18', | ||
| 522 | - time: '07:42', | ||
| 523 | - status: '正常' | ||
| 524 | - }, | ||
| 525 | - { | ||
| 526 | - id: 4, | ||
| 527 | - date: '2023-11-17', | ||
| 528 | - time: '08:10', | ||
| 529 | - status: '迟到' | ||
| 530 | - }, | ||
| 531 | - { | ||
| 532 | - id: 5, | ||
| 533 | - date: '2023-11-16', | ||
| 534 | - time: '07:48', | ||
| 535 | - status: '正常' | ||
| 536 | - }, | ||
| 537 | - { | ||
| 538 | - id: 6, | ||
| 539 | - date: '2023-11-15', | ||
| 540 | - time: '00:00', | ||
| 541 | - status: '缺勤' | ||
| 542 | - } | ||
| 543 | -]) | ||
| 544 | 539 | ||
| 545 | // 列表加载状态 | 540 | // 列表加载状态 |
| 546 | const recordLoading = ref(false) | 541 | const recordLoading = ref(false) |
| 547 | const recordFinished = ref(false) | 542 | const recordFinished = ref(false) |
| 543 | +const recordLimit = ref(100) | ||
| 544 | +const recordPage = ref(0) | ||
| 548 | 545 | ||
| 549 | // 删除对话框相关状态 | 546 | // 删除对话框相关状态 |
| 550 | const showDeleteDialog = ref(false) | 547 | const showDeleteDialog = ref(false) |
| 551 | const currentDeleteId = ref(null) | 548 | const currentDeleteId = ref(null) |
| 552 | 549 | ||
| 553 | // 班主任点评列表数据 | 550 | // 班主任点评列表数据 |
| 554 | -const evaluationList = ref([ | 551 | +const evaluationList = ref([]) |
| 555 | - { | ||
| 556 | - id: 1, | ||
| 557 | - date: '2023-11-20 14:30', | ||
| 558 | - content: '李华同学在本周的学习中表现优秀,课堂参与度很高,作业完成质量也很好。希望继续保持这种学习态度,在数学方面可以多加练习。', | ||
| 559 | - score: 4 | ||
| 560 | - }, | ||
| 561 | - { | ||
| 562 | - id: 2, | ||
| 563 | - date: '2023-11-15 16:45', | ||
| 564 | - content: '本周李华在语文课上积极发言,写作能力有明显提升。但需要注意课堂纪律,不要和同桌说话。总体表现良好。', | ||
| 565 | - score: 4 | ||
| 566 | - }, | ||
| 567 | - { | ||
| 568 | - id: 3, | ||
| 569 | - date: '2023-11-10 15:20', | ||
| 570 | - content: '李华同学这周在英语学习上进步很大,单词记忆和口语表达都有提升。建议多读英语文章,培养语感。', | ||
| 571 | - score: 5 | ||
| 572 | - }, | ||
| 573 | - { | ||
| 574 | - id: 4, | ||
| 575 | - date: '2023-11-05 17:10', | ||
| 576 | - content: '本周表现一般,上课有时会走神,作业完成情况还可以。希望能够更加专注学习,提高课堂效率。', | ||
| 577 | - score: 3 | ||
| 578 | - }, | ||
| 579 | - { | ||
| 580 | - id: 5, | ||
| 581 | - date: '2023-10-30 14:50', | ||
| 582 | - content: '李华同学在体育课上表现积极,团队合作意识强。学习方面需要加强时间管理,合理安排各科学习时间。', | ||
| 583 | - score: 4 | ||
| 584 | - } | ||
| 585 | -]) | ||
| 586 | 552 | ||
| 587 | // 班主任点评列表加载状态 | 553 | // 班主任点评列表加载状态 |
| 588 | const evaluationLoading = ref(false) | 554 | const evaluationLoading = ref(false) |
| 589 | const evaluationFinished = ref(false) | 555 | const evaluationFinished = ref(false) |
| 556 | +const evaluationLimit = ref(100) | ||
| 557 | +const evaluationPage = ref(0) | ||
| 590 | 558 | ||
| 591 | /** | 559 | /** |
| 592 | * 过滤后的记录列表 | 560 | * 过滤后的记录列表 |
| ... | @@ -624,21 +592,43 @@ const onStatusSelect = (option) => { | ... | @@ -624,21 +592,43 @@ const onStatusSelect = (option) => { |
| 624 | /** | 592 | /** |
| 625 | * 加载更多记录数据 | 593 | * 加载更多记录数据 |
| 626 | */ | 594 | */ |
| 627 | -const onRecordLoad = () => { | 595 | +const onRecordLoad = async () => { |
| 628 | - setTimeout(() => { | 596 | + const nextPage = recordPage.value; |
| 629 | - recordLoading.value = false | 597 | + // |
| 630 | - recordFinished.value = true | 598 | + const res = await getStudentCheckinListAPI({ |
| 631 | - }, 1000) | 599 | + limit: recordLimit.value, |
| 600 | + page: nextPage, | ||
| 601 | + user_id: route.params.id, | ||
| 602 | + group_id: selectedCourses.value.length ? selectedCourses.value[0]['id'] : '', | ||
| 603 | + }); | ||
| 604 | + if (res.code) { | ||
| 605 | + // 整理数据结构 | ||
| 606 | + records.value = [...records.value, ...res.data]; | ||
| 607 | + recordFinished.value = res.data.length < recordLimit.value; | ||
| 608 | + recordPage.value = nextPage + 1; | ||
| 609 | + } | ||
| 610 | + recordLoading.value = false; | ||
| 632 | } | 611 | } |
| 633 | 612 | ||
| 634 | /** | 613 | /** |
| 635 | * 加载更多班主任点评数据 | 614 | * 加载更多班主任点评数据 |
| 636 | */ | 615 | */ |
| 637 | -const onEvaluationLoad = () => { | 616 | +const onEvaluationLoad = async () => { |
| 638 | - setTimeout(() => { | 617 | + const nextPage = evaluationPage.value; |
| 639 | - evaluationLoading.value = false | 618 | + // |
| 640 | - evaluationFinished.value = true | 619 | + const res = await getCheckinFeedbackListAPI({ |
| 641 | - }, 1000) | 620 | + limit: evaluationLimit.value, |
| 621 | + page: nextPage, | ||
| 622 | + user_id: route.params.id, | ||
| 623 | + group_id: selectedCourses.value.length ? selectedCourses.value[0]['id'] : '', | ||
| 624 | + }); | ||
| 625 | + if (res.code) { | ||
| 626 | + // 整理数据结构 | ||
| 627 | + evaluationList.value = [...evaluationList.value, ...res.data]; | ||
| 628 | + evaluationFinished.value = res.data.length < evaluationLimit.value; | ||
| 629 | + evaluationPage.value = nextPage + 1; | ||
| 630 | + } | ||
| 631 | + evaluationLoading.value = false; | ||
| 642 | } | 632 | } |
| 643 | 633 | ||
| 644 | /** | 634 | /** |
| ... | @@ -653,12 +643,17 @@ const deleteEvaluation = (evaluationId) => { | ... | @@ -653,12 +643,17 @@ const deleteEvaluation = (evaluationId) => { |
| 653 | /** | 643 | /** |
| 654 | * 确认删除操作 | 644 | * 确认删除操作 |
| 655 | */ | 645 | */ |
| 656 | -const confirmDelete = () => { | 646 | +const confirmDelete = async () => { |
| 657 | // 这里应该调用API删除点评,暂时模拟删除操作 | 647 | // 这里应该调用API删除点评,暂时模拟删除操作 |
| 658 | - const index = evaluationList.value.findIndex(item => item.id === currentDeleteId.value) | 648 | + const { code } = await delCheckinFeedbackAPI({ |
| 659 | - if (index !== -1) { | 649 | + i: currentDeleteId.value |
| 660 | - evaluationList.value.splice(index, 1) | 650 | + }) |
| 661 | - showSuccessToast('删除成功') | 651 | + if (code) { |
| 652 | + const index = evaluationList.value.findIndex(item => item.id === currentDeleteId.value) | ||
| 653 | + if (index !== -1) { | ||
| 654 | + evaluationList.value.splice(index, 1) | ||
| 655 | + showSuccessToast('删除成功') | ||
| 656 | + } | ||
| 662 | } | 657 | } |
| 663 | showDeleteDialog.value = false | 658 | showDeleteDialog.value = false |
| 664 | currentDeleteId.value = null | 659 | currentDeleteId.value = null |
| ... | @@ -667,7 +662,7 @@ const confirmDelete = () => { | ... | @@ -667,7 +662,7 @@ const confirmDelete = () => { |
| 667 | /** | 662 | /** |
| 668 | * 取消删除操作 | 663 | * 取消删除操作 |
| 669 | */ | 664 | */ |
| 670 | -const cancelDelete = () => { | 665 | +const cancelDelete = async () => { |
| 671 | showDeleteDialog.value = false | 666 | showDeleteDialog.value = false |
| 672 | currentDeleteId.value = null | 667 | currentDeleteId.value = null |
| 673 | console.log('用户取消删除操作') | 668 | console.log('用户取消删除操作') |
| ... | @@ -680,17 +675,18 @@ const checkinDataList = ref([]); | ... | @@ -680,17 +675,18 @@ const checkinDataList = ref([]); |
| 680 | onMounted(async () => { | 675 | onMounted(async () => { |
| 681 | // 从路由参数获取学生ID | 676 | // 从路由参数获取学生ID |
| 682 | const studentId = route.params.id | 677 | const studentId = route.params.id |
| 683 | - console.log('学生详情页面已加载,学生ID:', studentId) | ||
| 684 | 678 | ||
| 685 | // 这里可以根据studentId调用API获取学生详细信息 | 679 | // 这里可以根据studentId调用API获取学生详细信息 |
| 686 | - loadStudentData(studentId) | 680 | + await loadStudentData(studentId) |
| 687 | 681 | ||
| 688 | - const current_date = route.query.date; | 682 | + // 加载作业记录 |
| 689 | - if (current_date) { | 683 | + onLoad() |
| 690 | - onLoad(current_date); | 684 | + |
| 691 | - } else { | 685 | + // 加载签到记录 |
| 692 | - onLoad(dayjs().format('YYYY-MM-DD')); | 686 | + onRecordLoad() |
| 693 | - } | 687 | + |
| 688 | + // 加载班主任点评 | ||
| 689 | + onEvaluationLoad() | ||
| 694 | }) | 690 | }) |
| 695 | 691 | ||
| 696 | /** | 692 | /** |
| ... | @@ -701,6 +697,7 @@ const loadStudentData = async (studentId) => { | ... | @@ -701,6 +697,7 @@ const loadStudentData = async (studentId) => { |
| 701 | const { code, data } = await getStudentDetailAPI({ i: studentId }) | 697 | const { code, data } = await getStudentDetailAPI({ i: studentId }) |
| 702 | if (code) { | 698 | if (code) { |
| 703 | studentInfo.value = data; | 699 | studentInfo.value = data; |
| 700 | + studentInfo.value?.lesson_list.sort((a, b) => a.title.length - b.title.length) | ||
| 704 | selectedCourses.value = [studentInfo.value.lesson_list[0] || ''] | 701 | selectedCourses.value = [studentInfo.value.lesson_list[0] || ''] |
| 705 | } | 702 | } |
| 706 | } | 703 | } |
| ... | @@ -722,6 +719,14 @@ const handleTabChange = (name) => { | ... | @@ -722,6 +719,14 @@ const handleTabChange = (name) => { |
| 722 | 719 | ||
| 723 | stopAllAudio(); | 720 | stopAllAudio(); |
| 724 | }) | 721 | }) |
| 722 | + | ||
| 723 | + if (name === 'homework') { | ||
| 724 | + resetAndReload() | ||
| 725 | + } else if (name === 'evaluation') { | ||
| 726 | + resetAndReloadEvaluations() | ||
| 727 | + } else if (name === 'statistics') { | ||
| 728 | + resetAndReloadRecords() | ||
| 729 | + } | ||
| 725 | }; | 730 | }; |
| 726 | 731 | ||
| 727 | // 存储所有视频播放器的引用 | 732 | // 存储所有视频播放器的引用 |
| ... | @@ -912,23 +917,22 @@ const handLike = async (post) => { | ... | @@ -912,23 +917,22 @@ const handLike = async (post) => { |
| 912 | 917 | ||
| 913 | const loading = ref(false) | 918 | const loading = ref(false) |
| 914 | const finished = ref(false) | 919 | const finished = ref(false) |
| 915 | -const limit = ref(3) | 920 | +const limit = ref(10) |
| 916 | const page = ref(0) | 921 | const page = ref(0) |
| 917 | 922 | ||
| 918 | const onLoad = async (date) => { | 923 | const onLoad = async (date) => { |
| 919 | const nextPage = page.value; | 924 | const nextPage = page.value; |
| 920 | - const current_date = date || route.query.date || dayjs().format('YYYY-MM-DD'); | ||
| 921 | // | 925 | // |
| 922 | - const res = await getCheckinTeacherListAPI({ | 926 | + const res = await getStudentUploadListAPI({ |
| 923 | limit: limit.value, | 927 | limit: limit.value, |
| 924 | page: nextPage, | 928 | page: nextPage, |
| 925 | - task_id: route.query.id, | 929 | + user_id: route.params.id, |
| 926 | - date: current_date | 930 | + group_id: selectedCourses.value.length ? selectedCourses.value[0]['id'] : '', |
| 927 | }); | 931 | }); |
| 928 | if (res.code) { | 932 | if (res.code) { |
| 929 | // 整理数据结构 | 933 | // 整理数据结构 |
| 930 | checkinDataList.value = [...checkinDataList.value, ...formatData(res.data)]; | 934 | checkinDataList.value = [...checkinDataList.value, ...formatData(res.data)]; |
| 931 | - finished.value = res.data.checkin_list.length < limit.value; | 935 | + finished.value = res.data.length < limit.value; |
| 932 | page.value = nextPage + 1; | 936 | page.value = nextPage + 1; |
| 933 | } | 937 | } |
| 934 | loading.value = false; | 938 | loading.value = false; |
| ... | @@ -936,7 +940,7 @@ const onLoad = async (date) => { | ... | @@ -936,7 +940,7 @@ const onLoad = async (date) => { |
| 936 | 940 | ||
| 937 | const formatData = (data) => { | 941 | const formatData = (data) => { |
| 938 | let formattedData = []; | 942 | let formattedData = []; |
| 939 | - formattedData = data?.checkin_list.map((item, index) => { | 943 | + formattedData = data?.map((item, index) => { |
| 940 | let images = []; | 944 | let images = []; |
| 941 | let audio = []; | 945 | let audio = []; |
| 942 | let videoList = []; | 946 | let videoList = []; |
| ... | @@ -980,12 +984,48 @@ const formatData = (data) => { | ... | @@ -980,12 +984,48 @@ const formatData = (data) => { |
| 980 | is_liked: item.is_like, | 984 | is_liked: item.is_like, |
| 981 | is_my: item.is_my, | 985 | is_my: item.is_my, |
| 982 | file_type: item.file_type, | 986 | file_type: item.file_type, |
| 983 | - is_feedback: item.is_feedback || false, // 是否已点评 | 987 | + is_feedback: item.feedback_id || false, // 是否已点评 |
| 988 | + feedback : item.feedback || '', | ||
| 989 | + feedback_id : item.feedback_id || '', | ||
| 990 | + feedback_score : item.feedback_score || 0, | ||
| 984 | comment: item.comment || null, // 点评内容 | 991 | comment: item.comment || null, // 点评内容 |
| 985 | } | 992 | } |
| 986 | }) | 993 | }) |
| 987 | return formattedData; | 994 | return formattedData; |
| 988 | } | 995 | } |
| 996 | + | ||
| 997 | +/** | ||
| 998 | + * 重置分页参数并重新加载数据 | ||
| 999 | + */ | ||
| 1000 | +const resetAndReload = () => { | ||
| 1001 | + page.value = 0; | ||
| 1002 | + checkinDataList.value = []; | ||
| 1003 | + finished.value = false; | ||
| 1004 | + loading.value = true; | ||
| 1005 | + onLoad(); | ||
| 1006 | +} | ||
| 1007 | + | ||
| 1008 | +/** | ||
| 1009 | + * 重置分页参数并重新加载数据 | ||
| 1010 | + */ | ||
| 1011 | +const resetAndReloadRecords = () => { | ||
| 1012 | + recordPage.value = 0; | ||
| 1013 | + records.value = []; | ||
| 1014 | + recordFinished.value = false; | ||
| 1015 | + recordLoading.value = true; | ||
| 1016 | + onRecordLoad(); | ||
| 1017 | +} | ||
| 1018 | + | ||
| 1019 | +/** | ||
| 1020 | + * 重置分页参数并重新加载数据 | ||
| 1021 | + */ | ||
| 1022 | +const resetAndReloadEvaluations = () => { | ||
| 1023 | + evaluationPage.value = 0; | ||
| 1024 | + evaluationList.value = []; | ||
| 1025 | + evaluationFinished.value = false; | ||
| 1026 | + evaluationLoading.value = true; | ||
| 1027 | + onEvaluationLoad(); | ||
| 1028 | +} | ||
| 989 | </script> | 1029 | </script> |
| 990 | 1030 | ||
| 991 | <style lang="less"> | 1031 | <style lang="less"> | ... | ... |
-
Please register or login to post a comment