246 lines
6.0 KiB
Vue
246 lines
6.0 KiB
Vue
<template>
|
|
<div class="step2-course-intro">
|
|
<div class="intro-header">
|
|
<span class="title">课程介绍</span>
|
|
</div>
|
|
|
|
<a-tabs v-model:activeKey="activeTab" type="card">
|
|
<a-tab-pane key="summary" tab="课程简介">
|
|
<div class="tab-content">
|
|
<a-textarea
|
|
v-model:value="formData.introSummary"
|
|
:rows="6"
|
|
placeholder="请输入课程整体简介,包括课程背景、核心理念、主要内容等"
|
|
show-count
|
|
:maxlength="1500"
|
|
@change="handleChange"
|
|
/>
|
|
</div>
|
|
</a-tab-pane>
|
|
|
|
<a-tab-pane key="highlights" tab="课程亮点">
|
|
<div class="tab-content">
|
|
<a-textarea
|
|
v-model:value="formData.introHighlights"
|
|
:rows="6"
|
|
placeholder="请输入课程特色亮点,如创新点、优势、特色活动等"
|
|
show-count
|
|
:maxlength="1500"
|
|
@change="handleChange"
|
|
/>
|
|
</div>
|
|
</a-tab-pane>
|
|
|
|
<a-tab-pane key="goals" tab="课程总目标">
|
|
<div class="tab-content">
|
|
<a-textarea
|
|
v-model:value="formData.introGoals"
|
|
:rows="6"
|
|
placeholder="请输入课程总体目标,包括知识目标、能力目标、情感目标等"
|
|
show-count
|
|
:maxlength="1500"
|
|
@change="handleChange"
|
|
/>
|
|
</div>
|
|
</a-tab-pane>
|
|
|
|
<a-tab-pane key="schedule" tab="内容安排">
|
|
<div class="tab-content">
|
|
<a-textarea
|
|
v-model:value="formData.introSchedule"
|
|
:rows="6"
|
|
placeholder="请输入课程内容安排,包括各阶段内容、时间安排等"
|
|
show-count
|
|
:maxlength="1500"
|
|
@change="handleChange"
|
|
/>
|
|
</div>
|
|
</a-tab-pane>
|
|
|
|
<a-tab-pane key="keyPoints" tab="重难点">
|
|
<div class="tab-content">
|
|
<a-textarea
|
|
v-model:value="formData.introKeyPoints"
|
|
:rows="6"
|
|
placeholder="请输入教学重点和难点,以及突破方法"
|
|
show-count
|
|
:maxlength="1500"
|
|
@change="handleChange"
|
|
/>
|
|
</div>
|
|
</a-tab-pane>
|
|
|
|
<a-tab-pane key="methods" tab="教学方法">
|
|
<div class="tab-content">
|
|
<a-textarea
|
|
v-model:value="formData.introMethods"
|
|
:rows="6"
|
|
placeholder="请输入教学方法和策略,如情境教学、游戏教学、互动教学等"
|
|
show-count
|
|
:maxlength="1500"
|
|
@change="handleChange"
|
|
/>
|
|
</div>
|
|
</a-tab-pane>
|
|
|
|
<a-tab-pane key="evaluation" tab="评价方式">
|
|
<div class="tab-content">
|
|
<a-textarea
|
|
v-model:value="formData.introEvaluation"
|
|
:rows="6"
|
|
placeholder="请输入评价方式和标准,包括过程评价和结果评价"
|
|
show-count
|
|
:maxlength="1500"
|
|
@change="handleChange"
|
|
/>
|
|
</div>
|
|
</a-tab-pane>
|
|
|
|
<a-tab-pane key="notes" tab="注意事项">
|
|
<div class="tab-content">
|
|
<a-textarea
|
|
v-model:value="formData.introNotes"
|
|
:rows="6"
|
|
placeholder="请输入教学注意事项,如安全提示、特殊需求等"
|
|
show-count
|
|
:maxlength="1500"
|
|
@change="handleChange"
|
|
/>
|
|
</div>
|
|
</a-tab-pane>
|
|
</a-tabs>
|
|
|
|
<div class="intro-footer">
|
|
<a-button v-if="currentTabIndex > 0" @click="prevTab">
|
|
上一个
|
|
</a-button>
|
|
<a-button v-if="currentTabIndex < 7" type="primary" @click="nextTab">
|
|
下一个
|
|
</a-button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive, watch, computed } from 'vue';
|
|
|
|
interface CourseIntroData {
|
|
introSummary: string;
|
|
introHighlights: string;
|
|
introGoals: string;
|
|
introSchedule: string;
|
|
introKeyPoints: string;
|
|
introMethods: string;
|
|
introEvaluation: string;
|
|
introNotes: string;
|
|
}
|
|
|
|
interface Props {
|
|
modelValue: Partial<CourseIntroData>;
|
|
}
|
|
|
|
const props = defineProps<Props>();
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'update:modelValue', value: CourseIntroData): void;
|
|
(e: 'change'): void;
|
|
}>();
|
|
|
|
const activeTab = ref('summary');
|
|
|
|
const tabKeys = ['summary', 'highlights', 'goals', 'schedule', 'keyPoints', 'methods', 'evaluation', 'notes'];
|
|
|
|
const formData = reactive<CourseIntroData>({
|
|
introSummary: '',
|
|
introHighlights: '',
|
|
introGoals: '',
|
|
introSchedule: '',
|
|
introKeyPoints: '',
|
|
introMethods: '',
|
|
introEvaluation: '',
|
|
introNotes: '',
|
|
});
|
|
|
|
// 监听外部值变化
|
|
watch(
|
|
() => props.modelValue,
|
|
(newVal) => {
|
|
if (newVal) {
|
|
Object.assign(formData, newVal);
|
|
}
|
|
},
|
|
{ immediate: true, deep: true }
|
|
);
|
|
|
|
// 计算当前tab索引
|
|
const currentTabIndex = computed(() => tabKeys.indexOf(activeTab.value));
|
|
|
|
// 上一个tab
|
|
const prevTab = () => {
|
|
const index = currentTabIndex.value;
|
|
if (index > 0) {
|
|
activeTab.value = tabKeys[index - 1];
|
|
}
|
|
};
|
|
|
|
// 下一个tab
|
|
const nextTab = () => {
|
|
const index = currentTabIndex.value;
|
|
if (index < tabKeys.length - 1) {
|
|
activeTab.value = tabKeys[index + 1];
|
|
}
|
|
};
|
|
|
|
// 处理变化
|
|
const handleChange = () => {
|
|
emit('update:modelValue', { ...formData });
|
|
emit('change');
|
|
};
|
|
|
|
// 验证
|
|
const validate = () => {
|
|
// 课程介绍为可选,不强制验证
|
|
return { valid: true, errors: [] };
|
|
};
|
|
|
|
defineExpose({
|
|
validate,
|
|
formData,
|
|
});
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.step2-course-intro {
|
|
.intro-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 16px;
|
|
|
|
.title {
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
|
|
.tab-content {
|
|
padding: 16px 0;
|
|
}
|
|
|
|
.intro-footer {
|
|
margin-top: 16px;
|
|
padding-top: 16px;
|
|
border-top: 1px solid #f0f0f0;
|
|
display: flex;
|
|
gap: 12px;
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
:deep(.ant-tabs-card) {
|
|
.ant-tabs-content {
|
|
min-height: 250px;
|
|
}
|
|
}
|
|
}
|
|
</style>
|