feat(课程包): 表单校验增强 - 教学环节必填标识与校验、核心资源必填标识

Made-with: Cursor
This commit is contained in:
zhonghua 2026-03-18 16:19:22 +08:00
parent a72984c860
commit 17dc815030
5 changed files with 74 additions and 9 deletions

View File

@ -174,6 +174,12 @@ const validate = () => {
const steps = lessonData.value.steps || []; const steps = lessonData.value.steps || [];
if (steps.length < 1) { if (steps.length < 1) {
errors.push('请至少添加一个教学环节'); errors.push('请至少添加一个教学环节');
} else {
steps.forEach((step, i) => {
if (!step.name?.trim()) errors.push(`${i + 1}个环节:请填写环节名称`);
if (!step.content?.trim()) errors.push(`${i + 1}个环节:请填写环节内容`);
if (!step.objective?.trim()) errors.push(`${i + 1}个环节:请填写教学目标`);
});
} }
return { valid: errors.length === 0, errors }; return { valid: errors.length === 0, errors };

View File

@ -175,6 +175,16 @@ const validate = () => {
if (duration != null && (duration < 15 || duration > 45)) { if (duration != null && (duration < 15 || duration > 45)) {
errors.push('集体课时长需在 15-45 分钟之间'); errors.push('集体课时长需在 15-45 分钟之间');
} }
const steps = lessonData.value.steps || [];
if (steps.length < 1) {
errors.push('请至少添加一个教学环节');
} else {
steps.forEach((step, i) => {
if (!step.name?.trim()) errors.push(`${i + 1}个环节:请填写环节名称`);
if (!step.content?.trim()) errors.push(`${i + 1}个环节:请填写环节内容`);
if (!step.objective?.trim()) errors.push(`${i + 1}个环节:请填写教学目标`);
});
}
return { valid: errors.length === 0, errors }; return { valid: errors.length === 0, errors };
}; };

View File

@ -267,6 +267,16 @@ const validate = () => {
if (duration != null && (duration < 15 || duration > 45)) { if (duration != null && (duration < 15 || duration > 45)) {
errors.push(`${domain.name}:时长需在 15-45 分钟之间`); errors.push(`${domain.name}:时长需在 15-45 分钟之间`);
} }
const steps = domain.lessonData.steps || [];
if (steps.length < 1) {
errors.push(`${domain.name}:请至少添加一个教学环节`);
} else {
steps.forEach((step, i) => {
if (!step.name?.trim()) errors.push(`${domain.name}:第${i + 1}个环节请填写环节名称`);
if (!step.content?.trim()) errors.push(`${domain.name}:第${i + 1}个环节请填写环节内容`);
if (!step.objective?.trim()) errors.push(`${domain.name}:第${i + 1}个环节请填写教学目标`);
});
}
} }
}); });

View File

@ -33,8 +33,11 @@
</a-form-item> </a-form-item>
</a-card> </a-card>
<!-- 核心资源仅集体课/领域课显示 --> <!-- 核心资源导入课/集体课/领域课显示 -->
<a-card v-if="showResources" size="small" title="核心资源" class="section-card"> <a-card v-if="showResources" size="small" class="section-card">
<template #title>
<span>核心资源 <span class="required-mark">*</span></span>
</template>
<a-row :gutter="16"> <a-row :gutter="16">
<a-col :span="8"> <a-col :span="8">
<a-form-item label="绘本动画"> <a-form-item label="绘本动画">

View File

@ -19,12 +19,15 @@
> >
<div class="step-header"> <div class="step-header">
<span class="step-order">{{ index + 1 }}</span> <span class="step-order">{{ index + 1 }}</span>
<a-input <div class="step-name-field">
v-model:value="step.name" <span class="field-label required">环节名称</span>
placeholder="环节名称(如:导入、讲解、练习等)" <a-input
style="flex: 1" v-model:value="step.name"
@change="handleChange" placeholder="如:导入、讲解、练习等"
/> style="flex: 1"
@change="handleChange"
/>
</div>
<span class="step-duration"> <span class="step-duration">
<a-input-number <a-input-number
v-model:value="step.duration" v-model:value="step.duration"
@ -47,6 +50,7 @@
</div> </div>
<div class="step-content"> <div class="step-content">
<span class="field-label required">环节内容</span>
<a-textarea <a-textarea
v-model:value="step.content" v-model:value="step.content"
placeholder="请输入教学环节的具体内容和操作步骤" placeholder="请输入教学环节的具体内容和操作步骤"
@ -56,9 +60,10 @@
</div> </div>
<div class="step-objective"> <div class="step-objective">
<span class="field-label required">教学目标</span>
<a-input <a-input
v-model:value="step.objective" v-model:value="step.objective"
placeholder="教学目标(可选)" placeholder="请输入该环节的教学目标"
@change="handleChange" @change="handleChange"
> >
<template #prefix> <template #prefix>
@ -252,12 +257,35 @@ defineExpose({
} }
} }
.field-label {
display: block;
font-size: 13px;
color: #666;
margin-bottom: 4px;
&.required::after {
content: ' *';
color: #ff4d4f;
}
}
.step-header { .step-header {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; gap: 12px;
margin-bottom: 12px; margin-bottom: 12px;
.step-name-field {
flex: 1;
display: flex;
flex-direction: column;
gap: 4px;
.field-label {
margin-bottom: 0;
}
}
.step-order { .step-order {
width: 28px; width: 28px;
height: 28px; height: 28px;
@ -284,9 +312,17 @@ defineExpose({
.step-content { .step-content {
margin-bottom: 12px; margin-bottom: 12px;
.field-label {
margin-bottom: 4px;
}
} }
.step-objective { .step-objective {
.field-label {
margin-bottom: 4px;
}
:deep(.ant-input-affix-wrapper) { :deep(.ant-input-affix-wrapper) {
background: #f5f5f5; background: #f5f5f5;
} }