根据后端新增的字段:
Assignment.examMode: 是否为考试模式Assignment.examDuration: 考试时长(分钟)EngagementVO.submitted: 是否已交卷功能要求:
| 文件 | 修改内容 |
|---|---|
src/types/dto.ts |
AssignmentDTO 添加 examMode, examDuration 字段 |
src/types/vo.ts |
IAssignment, AssignmentVO 添加 examMode, examDuration 字段engagementVO 添加 submitted 字段 |
| 文件 | 修改内容 |
|---|---|
src/views/CourseSquare/component/CourseDetails/component/AssignmentDialogue/WritingAssignmentDialogue.vue |
添加考试模式开关和时长输入 |
| 文件 | 修改内容 |
|---|---|
src/hooks/useExamCountdown.ts |
新建考试倒计时hook |
| 文件 | 修改内容 |
|---|---|
src/views/HomeworkPage/component/HomeworkDetail.vue |
显示作业模式标签(普通作业/考试模式) |
src/views/EditPage/EditPage.vue |
集成倒计时显示 |
src/views/Home/component/Edit/index.vue |
考试模式提交时显示确认提示 |
src/types/dto.tsexport interface AssignmentDTO {
assignmentName: string;
description: string;
type: string;
descriptionFile?: string;
attachments?: string[];
startTime: string;
endTime: string;
examMode?: boolean; // 新增:是否为考试模式
examDuration?: number; // 新增:考试时长(分钟),仅考试模式有效
}
src/types/vo.ts// engagementVO 新增字段
export interface engagementVO {
"id": number,
"assignmentId": number,
"studentId": number,
"score": number,
"remark": string,
"fileUrl": string,
"version": number,
"status": string,
"fileKey": string,
"quillContent": string,
"textContent": string,
"htmlContent": string,
"submitted": boolean; // 新增:是否已交卷
}
// IAssignment 新增字段
export interface IAssignment {
// ... 现有字段
examMode?: boolean; // 新增
examDuration?: number; // 新增
}
// AssignmentVO 新增字段
export interface AssignmentVO {
// ... 现有字段
examMode?: boolean; // 新增
examDuration?: number; // 新增
}
src/hooks/useExamCountdown.ts(新建)功能:
interface UseExamCountdownOptions {
startTime: Date; // 作业开始时间
duration: number; // 考试时长(分钟)
onAutoSubmit: () => void; // 自动交卷回调
onWarning: () => void; // 5分钟警告回调
}
返回值:
- remainingTime: ref<number> // 剩余秒数
- isWarning: ref<boolean> // 是否进入5分钟警告期
- isExpired: ref<boolean> // 是否已过期
- formattedTime: computed // 格式化时间字符串 "HH:mm:ss"
WritingAssignmentDialogue.vue添加考试模式表单项:
<el-form-item label="作业模式">
<el-switch
v-model="newAssignmentInfo.examMode"
active-text="考试模式"
inactive-text="普通作业"
/>
</el-form-item>
<el-form-item v-if="newAssignmentInfo.examMode" label="考试时长">
<el-input-number
v-model="newAssignmentInfo.examDuration"
:min="1"
:max="300"
controls-position="right"
/>
<span style="margin-left: 10px;">分钟</span>
</el-form-item>
数据初始化修改:
const newAssignmentInfo = reactive<AssignmentDTO>({
// ... 现有字段
examMode: false,
examDuration: 60, // 默认60分钟
});
编辑时数据回填:
Object.assign(newAssignmentInfo, {
// ... 现有字段
examMode: assignment.examMode ?? false,
examDuration: assignment.examDuration ?? 60,
});
提交验证:
if (newAssignmentInfo.examMode && (!newAssignmentInfo.examDuration || newAssignmentInfo.examDuration < 1)) {
ElNotification({ title: '考试模式下考试时长不得为空', type: 'error' });
return;
}
HomeworkDetail.vue修改点:显示模式标识和时长
<div class="item">
<span style="font-weight: 600">作业模式: </span>
<el-tag :type="data.examMode ? 'warning' : 'success'">
{{ data.examMode ? '考试模式' : '普通作业' }}
</el-tag>
<span v-if="data.examMode && data.examDuration" style="margin-left: 10px;">
时长: {{ data.examDuration }}分钟
</span>
</div>
EditPage.vue考试模式下的布局调整:
<div class="my-work" >
<!-- 左侧:AI助手 + 词典(考试模式下正常显示) -->
<div class="my-work-slider">
<el-button class="back" ...>返回</el-button>
<AIChatter ... /> <!-- 考试模式下正常显示 -->
<Dictionaries /> <!-- 考试模式下正常显示 -->
</div>
<!-- 考试模式:显示倒计时横幅 -->
<div v-if="isExamMode" class="exam-countdown-header">
<el-tag type="warning">考试模式</el-tag>
<span class="countdown-time">{{ formattedTime }}</span>
<el-tag v-if="isWarning" type="danger" effect="plain">
距离结束还有5分钟,请及时暂存内容!
</el-tag>
</div>
<!-- 中间:编辑区 -->
<div class="my-work-input">
<Edit :engagement="dataForm.engagement" />
</div>
<!-- 右侧:作业要求和批改(考试模式下隐藏) -->
<Slider v-if="!isExamMode" ... />
</div>
考试倒计时集成:
import { useExamCountdown } from '@/hooks/useExamCountdown';
// 计算属性
const isExamMode = computed(() => dataForm.assignment?.examMode ?? false);
const examDuration = computed(() => dataForm.assignment?.examDuration ?? 0);
// 倒计时hook
const { remainingTime, isWarning, formattedTime, start: startCountdown } = useExamCountdown({
startTime: new Date(dataForm.assignment.startTime),
duration: examDuration.value,
onAutoSubmit: async () => {
ElMessage.warning('考试时间已到,正在自动提交...');
await handleStage(); // 自动暂存
await handleSubmit(); // 自动提交
},
onWarning: () => {
ElMessage.info('距离考试结束还有5分钟,请注意暂存您的内容!');
}
});
onMounted(() => {
if (isExamMode.value) {
startCountdown();
}
});
Edit/index.vue考试模式提交确认:
const handleSubmit = async () => {
if (isExamMode) {
// 考试模式:确认提示
await ElMessageBox.confirm(
'考试时间结束后将自动交卷,确认现在提交吗?提交后不可再修改。',
'确认交卷',
{
confirmButtonText: '确认提交',
cancelButtonText: '取消',
type: 'warning',
}
);
}
// 执行提交...
};
Props接收考试模式标识:
interface IEditProps {
engagement: engagementVO
isExamMode?: boolean;
}
defineProps<IEditProps>();
| 功能 | 普通作业模式 | 考试模式 |
|---|---|---|
| AI助手 | ✅ 正常显示 | ✅ 正常显示 |
| 词典 | ✅ 正常显示 | ✅ 正常显示 |
| 暂存按钮 | ✅ 显示 | ✅ 显示(考试期间可暂存) |
| 批改区域 | ✅ 显示 | ❌ 隐藏 |
| 倒计时 | ❌ 不显示 | ✅ 显示 |
| 提交次数限制 | 多次 | 仅一次 |
| 提交确认提示 | 无 | 有"不可修改"提示 |
| 5分钟警告 | 无 | 有暂存提示 |
| 自动交卷 | 无 | 倒计时结束自动暂存并提交 |
assignment 获取(教师设置),不是从 engagementstartTime + examDuration 计算结束时间