refactor: 优化阅卷问题
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
785696659a
commit
58df855801
|
|
@ -6,6 +6,7 @@ import { useMarkingSettings } from '@/components/marking/composables/useMarkingS
|
||||||
import { useMarkingHistory } from '@/composables/marking/useMarkingHistory'
|
import { useMarkingHistory } from '@/composables/marking/useMarkingHistory'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
mode: string
|
||||||
isLandscape: boolean
|
isLandscape: boolean
|
||||||
currentQuestionIndex: number
|
currentQuestionIndex: number
|
||||||
totalQuestions: number
|
totalQuestions: number
|
||||||
|
|
@ -135,6 +136,7 @@ const currentHistoryIndexInList = computed(() => {
|
||||||
<!-- 题目选择器 -->
|
<!-- 题目选择器 -->
|
||||||
<wd-picker
|
<wd-picker
|
||||||
:model-value="currentQuestionIndex"
|
:model-value="currentQuestionIndex"
|
||||||
|
:disabled="mode === 'review'"
|
||||||
:columns="questionPickerColumns"
|
:columns="questionPickerColumns"
|
||||||
:value="String(currentQuestionIndex)"
|
:value="String(currentQuestionIndex)"
|
||||||
:title="`${currentQuestion?.question_major}.${currentQuestion?.question_minor}`"
|
:title="`${currentQuestion?.question_major}.${currentQuestion?.question_minor}`"
|
||||||
|
|
@ -152,7 +154,11 @@ const currentHistoryIndexInList = computed(() => {
|
||||||
|
|
||||||
<view class="flex items-baseline gap-2">
|
<view class="flex items-baseline gap-2">
|
||||||
<text class="text-16px text-slate-600 font-medium leading-none">
|
<text class="text-16px text-slate-600 font-medium leading-none">
|
||||||
{{ isViewingHistory ? historyModeText : `${currentTaskSubmit}/${totalQuestions}` }}
|
{{
|
||||||
|
mode === 'review'
|
||||||
|
? '回评模式'
|
||||||
|
: (isViewingHistory ? historyModeText : `${Math.min(currentTaskSubmit, totalQuestions)}/${totalQuestions}`)
|
||||||
|
}}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -242,6 +248,7 @@ const currentHistoryIndexInList = computed(() => {
|
||||||
<!-- 题目选择器 -->
|
<!-- 题目选择器 -->
|
||||||
<wd-picker
|
<wd-picker
|
||||||
:model-value="currentQuestionIndex"
|
:model-value="currentQuestionIndex"
|
||||||
|
:disabled="mode === 'review'"
|
||||||
:columns="questionPickerColumns"
|
:columns="questionPickerColumns"
|
||||||
:value="String(currentQuestionIndex)"
|
:value="String(currentQuestionIndex)"
|
||||||
:title="`${currentQuestion?.question_major}.${currentQuestion?.question_minor}`"
|
:title="`${currentQuestion?.question_major}.${currentQuestion?.question_minor}`"
|
||||||
|
|
@ -259,7 +266,7 @@ const currentHistoryIndexInList = computed(() => {
|
||||||
<view class="flex items-center gap-2">
|
<view class="flex items-center gap-2">
|
||||||
<!-- 题目序号 -->
|
<!-- 题目序号 -->
|
||||||
<text class="mr-2 text-14px text-slate-600 font-medium">
|
<text class="mr-2 text-14px text-slate-600 font-medium">
|
||||||
{{ currentTaskSubmit }}/{{ totalQuestions }}
|
{{ mode === 'review' ? '回评模式' : (isViewingHistory ? historyModeText : `${Math.min(currentTaskSubmit, totalQuestions)}/${totalQuestions}`) }}
|
||||||
</text>
|
</text>
|
||||||
|
|
||||||
<view class="flex gap-8px">
|
<view class="flex gap-8px">
|
||||||
|
|
@ -311,12 +318,17 @@ const currentHistoryIndexInList = computed(() => {
|
||||||
<!-- 作答区域和打分区域 - 左右分栏 -->
|
<!-- 作答区域和打分区域 - 左右分栏 -->
|
||||||
<view class="relative flex flex-1 overflow-hidden">
|
<view class="relative flex flex-1 overflow-hidden">
|
||||||
<!-- 左侧图片区域 -->
|
<!-- 左侧图片区域 -->
|
||||||
<view class="relative flex-1 overflow-hidden bg-slate-50">
|
<view
|
||||||
|
class="relative flex-1 overflow-hidden bg-slate-50"
|
||||||
|
:class="settings.quickScorePosition === 'left' ? 'order-2' : 'order-1'"
|
||||||
|
>
|
||||||
<slot name="content" :current-question="currentQuestion" />
|
<slot name="content" :current-question="currentQuestion" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 右侧打分区域 -->
|
<!-- 右侧打分区域 -->
|
||||||
<slot name="scoring" />
|
<view :class="settings.quickScorePosition === 'left' ? 'order-1' : 'order-2'">
|
||||||
|
<slot name="scoring" />
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -252,8 +252,6 @@ function createMarkingData(options: UseMarkingDataOptions) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重新获取下一题
|
// 重新获取下一题
|
||||||
questionData.value = []
|
|
||||||
currentMarkingSubmitData.value = []
|
|
||||||
markingStartTime.value = 0
|
markingStartTime.value = 0
|
||||||
await refetchQuestion()
|
await refetchQuestion()
|
||||||
processQuestionData()
|
processQuestionData()
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import type {
|
||||||
ExamStudentMarkingQuestionResponse,
|
ExamStudentMarkingQuestionResponse,
|
||||||
ExamStudentMarkingQuestionsResponse,
|
ExamStudentMarkingQuestionsResponse,
|
||||||
} from '@/api'
|
} from '@/api'
|
||||||
|
import { injectLocal, provideLocal } from '@vueuse/core'
|
||||||
import { examMarkingTaskApi } from '@/api'
|
import { examMarkingTaskApi } from '@/api'
|
||||||
|
|
||||||
// 分页响应接口
|
// 分页响应接口
|
||||||
|
|
@ -265,14 +266,16 @@ export const MarkingContextSymbol = Symbol('MarkingContext')
|
||||||
* 提供阅卷上下文
|
* 提供阅卷上下文
|
||||||
*/
|
*/
|
||||||
export function provideMarkingContext(context: MarkingContext) {
|
export function provideMarkingContext(context: MarkingContext) {
|
||||||
provide(MarkingContextSymbol, context)
|
provideLocal(MarkingContextSymbol, context)
|
||||||
|
|
||||||
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用阅卷上下文
|
* 使用阅卷上下文
|
||||||
*/
|
*/
|
||||||
export function useMarkingContext(): MarkingContext | null {
|
export function useMarkingContext(): MarkingContext | null {
|
||||||
return inject<MarkingContext>(MarkingContextSymbol) || null
|
return injectLocal<MarkingContext>(MarkingContextSymbol) || null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
import type {
|
||||||
|
MarkingDataProvider,
|
||||||
|
MarkingHistoryProvider,
|
||||||
|
MarkingHistoryRecord,
|
||||||
|
PaginatedResponse,
|
||||||
|
SubmitResponse,
|
||||||
|
} from './MarkingContext'
|
||||||
|
import type {
|
||||||
|
ExamBatchCreateMarkingTaskRecordRequest,
|
||||||
|
ExamStudentMarkingQuestionResponse,
|
||||||
|
} from '@/api'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { examMarkingTaskApi } from '@/api'
|
||||||
|
import { provideMarkingContext } from './MarkingContext'
|
||||||
|
|
||||||
|
// Store for the question to be reviewed
|
||||||
|
const currentReviewQuestion = ref<ExamStudentMarkingQuestionResponse | null>(null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前回评的题目
|
||||||
|
*/
|
||||||
|
export function setReviewQuestion(question: ExamStudentMarkingQuestionResponse) {
|
||||||
|
currentReviewQuestion.value = question
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回评数据提供者
|
||||||
|
* 直接返回预设的题目数据
|
||||||
|
*/
|
||||||
|
export class ReviewMarkingDataProvider implements MarkingDataProvider {
|
||||||
|
async getSingleQuestion(_taskId: number): Promise<ExamStudentMarkingQuestionResponse | null> {
|
||||||
|
return currentReviewQuestion.value
|
||||||
|
}
|
||||||
|
|
||||||
|
async getMultipleQuestions(
|
||||||
|
taskId: number,
|
||||||
|
_options: { count: number },
|
||||||
|
): Promise<{ questions: ExamStudentMarkingQuestionResponse[] } | null> {
|
||||||
|
const question = await this.getSingleQuestion(taskId)
|
||||||
|
return question ? { questions: [question] } : null
|
||||||
|
}
|
||||||
|
|
||||||
|
async submitRecords(data: ExamBatchCreateMarkingTaskRecordRequest): Promise<SubmitResponse | null> {
|
||||||
|
// 允许提交(重新打分)
|
||||||
|
const response = await examMarkingTaskApi.batchCreate({ ...data, is_review: true })
|
||||||
|
if (!response)
|
||||||
|
return null
|
||||||
|
|
||||||
|
return {
|
||||||
|
success_count: response.success_count || 0,
|
||||||
|
fail_data: response.fail_data?.map(item => ({ message: item.message || '' })),
|
||||||
|
success_data: response.success_data?.map(item => ({
|
||||||
|
id: item.id || 0,
|
||||||
|
question_id: item.question_id || 0,
|
||||||
|
score: item.score || 0,
|
||||||
|
remark: item.remark,
|
||||||
|
is_excellent: item.is_excellent || 0,
|
||||||
|
is_model: item.is_model || 0,
|
||||||
|
is_problem: item.is_problem || 0,
|
||||||
|
})),
|
||||||
|
is_end: response.is_end || false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async createProblemRecord(data: any): Promise<void> {
|
||||||
|
await examMarkingTaskApi.problemRecordCreate(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回评历史提供者
|
||||||
|
* 返回空历史,禁用历史功能
|
||||||
|
*/
|
||||||
|
export class ReviewMarkingHistoryProvider implements MarkingHistoryProvider {
|
||||||
|
async getHistoryPage(
|
||||||
|
_taskId: number,
|
||||||
|
_options: { page: number, page_size: number },
|
||||||
|
): Promise<PaginatedResponse<MarkingHistoryRecord>> {
|
||||||
|
return {
|
||||||
|
list: [],
|
||||||
|
page: 1,
|
||||||
|
page_size: 20,
|
||||||
|
total: 0,
|
||||||
|
has_more: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提供回评上下文
|
||||||
|
*/
|
||||||
|
export function provideReviewMarkingContext() {
|
||||||
|
provideMarkingContext({
|
||||||
|
dataProvider: new ReviewMarkingDataProvider(),
|
||||||
|
historyProvider: new ReviewMarkingHistoryProvider(),
|
||||||
|
isHistory: false,
|
||||||
|
defaultPosition: 'last',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -8,9 +8,10 @@
|
||||||
</route>
|
</route>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import type { MarkingDataProvider, MarkingHistoryProvider } from '@/composables/marking/MarkingContext'
|
||||||
import { useQueryClient } from '@tanstack/vue-query'
|
import { useQueryClient } from '@tanstack/vue-query'
|
||||||
import { watchImmediate, whenever } from '@vueuse/core'
|
import { watchImmediate, whenever } from '@vueuse/core'
|
||||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import AnswerDialog from '@/components/marking/components/dialog/AnswerDialog.vue'
|
import AnswerDialog from '@/components/marking/components/dialog/AnswerDialog.vue'
|
||||||
import AvgScoreDialog from '@/components/marking/components/dialog/AvgScoreDialog.vue'
|
import AvgScoreDialog from '@/components/marking/components/dialog/AvgScoreDialog.vue'
|
||||||
import FullscreenImageDialog from '@/components/marking/components/dialog/FullscreenImageDialog.vue'
|
import FullscreenImageDialog from '@/components/marking/components/dialog/FullscreenImageDialog.vue'
|
||||||
|
|
@ -19,7 +20,8 @@ import QuickScorePanel from '@/components/marking/components/QuickScorePanel.vue
|
||||||
import MarkingImageViewerNew from '@/components/marking/components/renderer/MarkingImageViewerNew.vue'
|
import MarkingImageViewerNew from '@/components/marking/components/renderer/MarkingImageViewerNew.vue'
|
||||||
import { provideMarkingData } from '@/components/marking/composables/useMarkingData'
|
import { provideMarkingData } from '@/components/marking/composables/useMarkingData'
|
||||||
import MarkingLayout from '@/components/marking/MarkingLayout.vue'
|
import MarkingLayout from '@/components/marking/MarkingLayout.vue'
|
||||||
import { cachedImages, DefaultMarkingDataProvider, DefaultMarkingHistoryProvider, provideMarkingContext, useMarkingContext } from '@/composables/marking/MarkingContext'
|
import { cachedImages, DefaultMarkingDataProvider, DefaultMarkingHistoryProvider, provideMarkingContext } from '@/composables/marking/MarkingContext'
|
||||||
|
import { ReviewMarkingDataProvider, ReviewMarkingHistoryProvider } from '@/composables/marking/ReviewMarkingContext'
|
||||||
import { provideMarkingHistory } from '@/composables/marking/useMarkingHistory'
|
import { provideMarkingHistory } from '@/composables/marking/useMarkingHistory'
|
||||||
import { provideMarkingNavigation } from '@/composables/marking/useMarkingNavigation'
|
import { provideMarkingNavigation } from '@/composables/marking/useMarkingNavigation'
|
||||||
import { useSafeArea } from '@/composables/useSafeArea'
|
import { useSafeArea } from '@/composables/useSafeArea'
|
||||||
|
|
@ -29,6 +31,10 @@ defineOptions({
|
||||||
name: 'GradingPage',
|
name: 'GradingPage',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
mode: string
|
||||||
|
}>()
|
||||||
|
|
||||||
// 获取屏幕边界到安全区域距离
|
// 获取屏幕边界到安全区域距离
|
||||||
const { safeAreaInsets } = useSafeArea()
|
const { safeAreaInsets } = useSafeArea()
|
||||||
|
|
||||||
|
|
@ -134,11 +140,12 @@ async function recalculateScale() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提供阅卷上下文(使用默认实现)
|
const markingDataProvider = props.mode === 'review' ? new ReviewMarkingDataProvider() : new DefaultMarkingDataProvider()
|
||||||
const markingDataProvider = new DefaultMarkingDataProvider()
|
const markingHistoryProvider = props.mode === 'review' ? new ReviewMarkingHistoryProvider() : new DefaultMarkingHistoryProvider()
|
||||||
provideMarkingContext({
|
|
||||||
|
const context = provideMarkingContext({
|
||||||
dataProvider: markingDataProvider,
|
dataProvider: markingDataProvider,
|
||||||
historyProvider: new DefaultMarkingHistoryProvider(),
|
historyProvider: markingHistoryProvider,
|
||||||
isHistory: false,
|
isHistory: false,
|
||||||
defaultPosition: 'last',
|
defaultPosition: 'last',
|
||||||
})
|
})
|
||||||
|
|
@ -456,11 +463,15 @@ const historyModeText = computed(() => {
|
||||||
|
|
||||||
// 上一题
|
// 上一题
|
||||||
async function handlePrevQuestion() {
|
async function handlePrevQuestion() {
|
||||||
|
if (props.mode === 'review')
|
||||||
|
return
|
||||||
await goToPrevQuestion()
|
await goToPrevQuestion()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 下一题
|
// 下一题
|
||||||
async function handleNextQuestion() {
|
async function handleNextQuestion() {
|
||||||
|
if (props.mode === 'review')
|
||||||
|
return
|
||||||
await goToNextQuestion()
|
await goToNextQuestion()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -571,20 +582,21 @@ const nextQuestionImages = computed(() => {
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<MarkingLayout
|
<MarkingLayout
|
||||||
|
:mode
|
||||||
:is-landscape="isLandscape"
|
:is-landscape="isLandscape"
|
||||||
:is-fullscreen="false"
|
:is-fullscreen="false"
|
||||||
:current-question-index="currentQuestionIndex"
|
:current-question-index="currentQuestionIndex"
|
||||||
:current-task-submit="navCurrentIndex || 0"
|
:current-task-submit="navCurrentIndex || 0"
|
||||||
:total-questions="totalQuestions"
|
:total-questions="totalQuestions"
|
||||||
:questions="questionsList"
|
:questions="questionsList"
|
||||||
:my-score="myScore"
|
:my-score="Number(myScore)"
|
||||||
:avg-score="avgScore"
|
:avg-score="Number(avgScore)"
|
||||||
:is-viewing-history="isViewingHistory"
|
:is-viewing-history="isViewingHistory"
|
||||||
:can-go-prev="canGoPrev"
|
:can-go-prev="canGoPrev"
|
||||||
:can-go-next="canGoNext"
|
:can-go-next="canGoNext"
|
||||||
:history-mode-text="historyModeText"
|
:history-mode-text="historyModeText"
|
||||||
:task-id="taskId"
|
:task-id="taskId"
|
||||||
:current-question-full-score="currentQuestion?.full_score || 0"
|
:current-question-full-score="fullScore"
|
||||||
:current-question-final-score="currentQuestion?.final_score || 0"
|
:current-question-final-score="currentQuestion?.final_score || 0"
|
||||||
@go-back="goBack"
|
@go-back="goBack"
|
||||||
@select-question="selectQuestion"
|
@select-question="selectQuestion"
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,12 @@
|
||||||
import { useInfiniteQuery, useQuery } from '@tanstack/vue-query'
|
import { useInfiniteQuery, useQuery } from '@tanstack/vue-query'
|
||||||
import { whenever } from '@vueuse/core'
|
import { whenever } from '@vueuse/core'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, nextTick, ref } from 'vue'
|
||||||
import { examMarkingTaskApi } from '@/api'
|
import { examMarkingTaskApi } from '@/api'
|
||||||
import ReviewHeader from '@/components/marking/review/ReviewHeader.vue'
|
import ReviewHeader from '@/components/marking/review/ReviewHeader.vue'
|
||||||
import ReviewImageRenderer from '@/components/marking/review/ReviewImageRenderer.vue'
|
import ReviewImageRenderer from '@/components/marking/review/ReviewImageRenderer.vue'
|
||||||
import ScoreEditDialog from '@/components/marking/review/ScoreEditDialog.vue'
|
import ScoreEditDialog from '@/components/marking/review/ScoreEditDialog.vue'
|
||||||
|
import { setReviewQuestion } from '@/composables/marking/ReviewMarkingContext'
|
||||||
import { useUserId } from '@/composables/useUserId'
|
import { useUserId } from '@/composables/useUserId'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
|
|
@ -126,46 +127,69 @@ function goBack() {
|
||||||
const scoreEditDialogRef = ref<InstanceType<typeof ScoreEditDialog>>()
|
const scoreEditDialogRef = ref<InstanceType<typeof ScoreEditDialog>>()
|
||||||
|
|
||||||
// 容器宽度
|
// 容器宽度
|
||||||
const containerWidth = ref(0)
|
// 默认给一个预估值,避免首次渲染时宽度为0导致缩放计算错误
|
||||||
|
// 预估逻辑:屏幕宽度 - 页面padding(32) - 卡片padding(32) - 内部预留(32)
|
||||||
|
const systemInfo = uni.getSystemInfoSync()
|
||||||
|
const containerWidth = ref(systemInfo.windowWidth - 96)
|
||||||
|
|
||||||
// 获取容器宽度
|
// 获取容器宽度
|
||||||
|
function updateContainerWidth() {
|
||||||
|
const query = uni.createSelectorQuery()
|
||||||
|
query.select('.image-container').boundingClientRect((data) => {
|
||||||
|
if (data && !Array.isArray(data) && data.width > 0) {
|
||||||
|
// 减去padding和边框,获取实际可用宽度
|
||||||
|
containerWidth.value = data.width - 32 // 32 = padding 16px * 2
|
||||||
|
console.log('[Review] Container width:', containerWidth.value)
|
||||||
|
}
|
||||||
|
}).exec()
|
||||||
|
}
|
||||||
|
|
||||||
whenever(() => historyData.value?.pages?.length, () => {
|
whenever(() => historyData.value?.pages?.length, () => {
|
||||||
setTimeout(() => {
|
// 使用 nextTick 确保 DOM 已更新
|
||||||
const query = uni.createSelectorQuery()
|
nextTick(() => {
|
||||||
query.select('.image-container').boundingClientRect((data) => {
|
// 稍微延迟以确保布局稳定
|
||||||
if (data && !Array.isArray(data)) {
|
setTimeout(updateContainerWidth, 200)
|
||||||
// 减去padding和边框,获取实际可用宽度
|
})
|
||||||
containerWidth.value = data.width - 32 // 32 = padding 16px * 2
|
|
||||||
console.log('[Review] Container width:', containerWidth.value)
|
|
||||||
}
|
|
||||||
}).exec()
|
|
||||||
}, 100)
|
|
||||||
}, { immediate: true })
|
}, { immediate: true })
|
||||||
|
|
||||||
// 处理图片点击编辑分数
|
let lastQuestionIndex = -1
|
||||||
async function handleImageClick(record: any) {
|
// 处理图片点击进入回评阅卷页
|
||||||
try {
|
function handleImageClick(record: any, index: number) {
|
||||||
const result = await scoreEditDialogRef.value?.open({
|
// 构造题目数据
|
||||||
currentScore: record.score,
|
const questionData = {
|
||||||
recordTask: record,
|
...record,
|
||||||
})
|
// 构造 tasks 对象,确保 grading 页面能正确识别任务
|
||||||
|
tasks: {
|
||||||
|
initial: {
|
||||||
|
id: record.task_id,
|
||||||
|
question_id: record.question_id,
|
||||||
|
task_type: 'initial',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 确保有 standard_answer 字段,防止报错
|
||||||
|
standard_answer: record.standard_answer || '',
|
||||||
|
// 映射分数
|
||||||
|
final_score: record.score,
|
||||||
|
}
|
||||||
|
|
||||||
if (result) {
|
// 设置回评题目
|
||||||
// 刷新历史记录
|
setReviewQuestion(questionData)
|
||||||
await refetchHistory()
|
lastQuestionIndex = index
|
||||||
uni.showToast({
|
|
||||||
title: '分数修改成功',
|
// 跳转到阅卷页(回评模式)
|
||||||
icon: 'success',
|
uni.navigateTo({
|
||||||
})
|
url: `/pages/marking/grading?taskId=${record.task_id}&questionId=${record.question_id}&examId=${examId.value}&subjectId=${subjectId.value}&type=single&taskType=initial&mode=review`,
|
||||||
}
|
})
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
if (error !== 'cancel') {
|
|
||||||
console.error('修改分数失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const refreshKey = ref(0)
|
||||||
|
onShow(async () => {
|
||||||
|
if (lastQuestionIndex !== -1) {
|
||||||
|
await refetchHistory()
|
||||||
|
refreshKey.value += 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 加载更多
|
// 加载更多
|
||||||
function loadMore() {
|
function loadMore() {
|
||||||
if (hasNextPage.value && !isFetchingNextPage.value) {
|
if (hasNextPage.value && !isFetchingNextPage.value) {
|
||||||
|
|
@ -210,12 +234,12 @@ function handleRefresh() {
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 历史记录列表 -->
|
<!-- 历史记录列表 -->
|
||||||
<view v-else-if="historyList.length > 0" :key="containerWidth" class="history-list">
|
<view v-else-if="historyList.length > 0" class="history-list">
|
||||||
<view
|
<view
|
||||||
v-for="record in historyList"
|
v-for="(record, index) in historyList"
|
||||||
:key="record.id"
|
:key="`${record.id}_${refreshKey}`"
|
||||||
class="history-item mb-4 rounded-3 bg-white p-4 shadow-sm"
|
class="history-item mb-4 rounded-3 bg-white p-4 shadow-sm"
|
||||||
@click="handleImageClick(record)"
|
@click="handleImageClick(record, index)"
|
||||||
>
|
>
|
||||||
<!-- 头部信息 -->
|
<!-- 头部信息 -->
|
||||||
<view class="item-header mb-3 flex items-center justify-between">
|
<view class="item-header mb-3 flex items-center justify-between">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue