|
@@ -22,6 +22,22 @@
|
|
|
@change="handleParentChange"
|
|
@change="handleParentChange"
|
|
|
/>
|
|
/>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
|
|
+ <el-form-item label="引入历史课程" prop="historyCourseTypeId">
|
|
|
|
|
+ <el-button type="primary" size="small" style="margin-right: 10px"
|
|
|
|
|
+ title="仅年级类型可以引入历史课程"
|
|
|
|
|
+ :disabled="formData.ctParentId === 0"
|
|
|
|
|
+ @click="openHistoryCourseDialog">
|
|
|
|
|
+ 引用历史课程</el-button>
|
|
|
|
|
+ <el-switch
|
|
|
|
|
+ v-if="formData.ctParentId !== 0 && formData.historyCourseTypeId"
|
|
|
|
|
+ v-model="isCopyAllSections"
|
|
|
|
|
+ inactive-text="复制课程下所有小节:"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ />
|
|
|
|
|
+ <div v-if="importedCourseTypeInfo" class="imported-info">
|
|
|
|
|
+ 引入历史课程:{{ importedCourseTypeInfo }},{{ isCopyAllSections ? '(包括该课程下的所有课程小节)' : '(不包括课程小节)' }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-form-item>
|
|
|
<el-form-item label="课程类型节点" prop="ctTypeNode">
|
|
<el-form-item label="课程类型节点" prop="ctTypeNode">
|
|
|
<el-segmented
|
|
<el-segmented
|
|
|
v-model="formData.ctTypeNode"
|
|
v-model="formData.ctTypeNode"
|
|
@@ -51,10 +67,89 @@
|
|
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
|
|
</template>
|
|
</template>
|
|
|
</Dialog>
|
|
</Dialog>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 引用历史课程弹窗 -->
|
|
|
|
|
+ <Dialog title="引用历史课程类型" v-model="historyCourseDialogVisible" width="1000px">
|
|
|
|
|
+ <!-- 搜索工作栏 -->
|
|
|
|
|
+ <el-form
|
|
|
|
|
+ :model="historyCourseFormData"
|
|
|
|
|
+ inline
|
|
|
|
|
+ label-width="100px"
|
|
|
|
|
+ style="margin-bottom: 20px"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-form-item label="课程类型名称" prop="searchName">
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model="historyCourseFormData.searchName"
|
|
|
|
|
+ placeholder="请输入课程类型名称"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ @keyup.enter="searchHistoryCourseTypes"
|
|
|
|
|
+ class="!w-240px"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="课程类型节点" prop="searchTypeNode">
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ v-model="historyCourseFormData.searchTypeNode"
|
|
|
|
|
+ placeholder="请选择类型节点类型"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ class="!w-240px"
|
|
|
|
|
+ @change="searchHistoryCourseTypes"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-option label="ai通识课" value="1" />
|
|
|
|
|
+ <el-option label="ai实操课" value="2" />
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item>
|
|
|
|
|
+ <el-button @click="searchHistoryCourseTypes"><el-icon><Search /></el-icon> 搜索</el-button>
|
|
|
|
|
+ <el-button @click="resetHistoryCourseSearch"><el-icon><Refresh /></el-icon> 重置</el-button>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+
|
|
|
|
|
+ <el-table
|
|
|
|
|
+ :data="historyCourseTypes"
|
|
|
|
|
+ style="width: 100%; height: 400px; max-height: 500px; overflow: auto"
|
|
|
|
|
+ border
|
|
|
|
|
+ @row-click="selectHistoryCourseType"
|
|
|
|
|
+ :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
|
|
|
|
+ :stripe="true"
|
|
|
|
|
+ :highlight-current-row="true"
|
|
|
|
|
+ :show-overflow-tooltip="true"
|
|
|
|
|
+ :default-expand-all="false"
|
|
|
|
|
+ row-key="id"
|
|
|
|
|
+ current-row-key="id"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-table-column label="课程类型名称" align="center" prop="ctType"/>
|
|
|
|
|
+ <el-table-column label="节点类型" align="center" prop="ctTypeNode">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <el-tag type="info" v-if="scope.row.ctTypeNode === '0'">年级</el-tag>
|
|
|
|
|
+ <el-tag type="warning" v-else-if="scope.row.ctTypeNode === '1'">ai通识课</el-tag>
|
|
|
|
|
+ <el-tag type="warning" v-else>ai实操课</el-tag>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="封面" align="center" prop="ctTypeImage">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <el-image
|
|
|
|
|
+ v-if="scope.row.ctTypeImage"
|
|
|
|
|
+ :src="scope.row.ctTypeImage"
|
|
|
|
|
+ :preview-src-list="[scope.row.ctTypeImage]"
|
|
|
|
|
+ style="width: 100px; height: 80px; object-fit: cover"
|
|
|
|
|
+ />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="排序" align="center" prop="ctTypeSort" width="80" />
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+
|
|
|
|
|
+ <template #footer>
|
|
|
|
|
+ <span v-if="selectedHistoryCourseType" style="margin-right: 20px">引入历史课程:{{selectedHistoryCourseType?.ctType}}</span>
|
|
|
|
|
+ <el-button @click="confirmHistoryCourseType" type="primary" :disabled="!selectedHistoryCourseType">确 定</el-button>
|
|
|
|
|
+ <el-button @click="historyCourseDialogVisible = false">取 消</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </Dialog>
|
|
|
</template>
|
|
</template>
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import { CourseTypeApi, CourseTypeVO } from '@/api/bjdx/coursetype'
|
|
import { CourseTypeApi, CourseTypeVO } from '@/api/bjdx/coursetype'
|
|
|
import { defaultProps, handleTree } from '@/utils/tree'
|
|
import { defaultProps, handleTree } from '@/utils/tree'
|
|
|
|
|
+import { Search, Refresh } from '@element-plus/icons-vue'
|
|
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
|
|
|
|
|
/** 课程-类型 表单 */
|
|
/** 课程-类型 表单 */
|
|
|
defineOptions({ name: 'CourseTypeForm' })
|
|
defineOptions({ name: 'CourseTypeForm' })
|
|
@@ -67,6 +162,7 @@ const dialogTitle = ref('') // 弹窗的标题
|
|
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
|
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
|
|
const formData = ref({
|
|
const formData = ref({
|
|
|
|
|
+ historyCourseTypeId: undefined,
|
|
|
id: undefined,
|
|
id: undefined,
|
|
|
ctType: undefined,
|
|
ctType: undefined,
|
|
|
ctTypeImage: undefined,
|
|
ctTypeImage: undefined,
|
|
@@ -84,6 +180,42 @@ const formRules = reactive({
|
|
|
})
|
|
})
|
|
|
const formRef = ref() // 表单 Ref
|
|
const formRef = ref() // 表单 Ref
|
|
|
const courseTypeTree = ref() // 树形结构
|
|
const courseTypeTree = ref() // 树形结构
|
|
|
|
|
+const historyCourseDialogVisible = ref(false) // 历史课程弹窗可见性
|
|
|
|
|
+const historyCourseTypes = ref<CourseTypeVO[]>([]) // 历史课程类型列表
|
|
|
|
|
+const historyCourseFormData = reactive({
|
|
|
|
|
+ searchName: '', // 搜索名称
|
|
|
|
|
+ searchTypeNode: undefined // 搜索节点类型
|
|
|
|
|
+}) // 历史课程表单数据
|
|
|
|
|
+const selectedHistoryCourseType = ref<CourseTypeVO>() // 选中的历史课程类型
|
|
|
|
|
+const importedCourseTypeInfo = ref('') // 引入的课程类型信息
|
|
|
|
|
+
|
|
|
|
|
+// 开关状态变量
|
|
|
|
|
+const switchValue = ref(false)
|
|
|
|
|
+// 计算属性:控制是否复制所有小节的开关状态
|
|
|
|
|
+const isCopyAllSections = computed({
|
|
|
|
|
+ get() {
|
|
|
|
|
+ // 有historyCourseTypeId值则开启开关
|
|
|
|
|
+ return switchValue.value
|
|
|
|
|
+ },
|
|
|
|
|
+ set(value) {
|
|
|
|
|
+ if (value) {
|
|
|
|
|
+ // 当尝试打开开关但没有引入课程时,显示提示
|
|
|
|
|
+ if (!formData.value.historyCourseTypeId) {
|
|
|
|
|
+ ElMessage.warning('需要重新引入课程')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 当开关关闭时,清除historyCourseTypeId字段和导入信息
|
|
|
|
|
+ formData.value.historyCourseTypeId = undefined
|
|
|
|
|
+ importedCourseTypeInfo.value = ''
|
|
|
|
|
+ switchValue.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+ // 只有在有效的情况下才更新开关状态
|
|
|
|
|
+ if (formData.value.historyCourseTypeId || !value) {
|
|
|
|
|
+ switchValue.value = value
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
// 计算属性:判断父级ID是否为根节点(0)
|
|
// 计算属性:判断父级ID是否为根节点(0)
|
|
|
const isRootParent = computed(() => {
|
|
const isRootParent = computed(() => {
|
|
@@ -104,6 +236,12 @@ const handleParentChange = () => {
|
|
|
if (isRootParent.value) {
|
|
if (isRootParent.value) {
|
|
|
// 当父级是根节点时,强制设置为年级类型
|
|
// 当父级是根节点时,强制设置为年级类型
|
|
|
formData.value.ctTypeNode = '0'
|
|
formData.value.ctTypeNode = '0'
|
|
|
|
|
+ // 清除历史课程ID
|
|
|
|
|
+ formData.value.historyCourseTypeId = null
|
|
|
|
|
+ // 关闭复制小节开关
|
|
|
|
|
+ switchValue.value = false
|
|
|
|
|
+ // 清除导入信息
|
|
|
|
|
+ importedCourseTypeInfo.value = ''
|
|
|
} else {
|
|
} else {
|
|
|
// 当父级不是根节点时,如果当前类型是年级,则改为通识课
|
|
// 当父级不是根节点时,如果当前类型是年级,则改为通识课
|
|
|
if (formData.value.ctTypeNode === '0' || formData.value.ctTypeNode === 0) {
|
|
if (formData.value.ctTypeNode === '0' || formData.value.ctTypeNode === 0) {
|
|
@@ -149,6 +287,9 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
|
|
/** 提交表单 */
|
|
/** 提交表单 */
|
|
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
|
|
const submitForm = async () => {
|
|
const submitForm = async () => {
|
|
|
|
|
+
|
|
|
|
|
+ console.log('submitForm', formData.value)
|
|
|
|
|
+ return;
|
|
|
// 校验表单
|
|
// 校验表单
|
|
|
await formRef.value.validate()
|
|
await formRef.value.validate()
|
|
|
// 提交请求
|
|
// 提交请求
|
|
@@ -194,4 +335,70 @@ const getCourseTypeTree = async () => {
|
|
|
root.children = handleTree(filteredData, 'id', 'ctParentId')
|
|
root.children = handleTree(filteredData, 'id', 'ctParentId')
|
|
|
courseTypeTree.value.push(root)
|
|
courseTypeTree.value.push(root)
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/** 打开历史课程弹窗 */
|
|
|
|
|
+const openHistoryCourseDialog = async () => {
|
|
|
|
|
+ historyCourseDialogVisible.value = true
|
|
|
|
|
+ await getHistoryCourseTypes()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 获取历史课程类型数据 */
|
|
|
|
|
+const getHistoryCourseTypes = async () => {
|
|
|
|
|
+ const params = {
|
|
|
|
|
+ ctType: historyCourseFormData.searchName,
|
|
|
|
|
+ ctTypeNode: historyCourseFormData.searchTypeNode
|
|
|
|
|
+ }
|
|
|
|
|
+ const result = await CourseTypeApi.getCourseTypeList(params)
|
|
|
|
|
+ historyCourseTypes.value = handleTree(result, 'id', 'ctParentId')
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 搜索历史课程类型 */
|
|
|
|
|
+const searchHistoryCourseTypes = () => {
|
|
|
|
|
+ getHistoryCourseTypes()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 重置搜索条件 */
|
|
|
|
|
+const resetHistoryCourseSearch = () => {
|
|
|
|
|
+ historyCourseFormData.searchName = ''
|
|
|
|
|
+ historyCourseFormData.searchTypeNode = undefined
|
|
|
|
|
+ getHistoryCourseTypes()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 选择历史课程类型 */
|
|
|
|
|
+const selectHistoryCourseType = (courseType: CourseTypeVO) => {
|
|
|
|
|
+ if (courseType.ctTypeNode !== '0') {
|
|
|
|
|
+ selectedHistoryCourseType.value = courseType
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 确认选择历史课程类型 */
|
|
|
|
|
+const confirmHistoryCourseType = () => {
|
|
|
|
|
+ if (selectedHistoryCourseType.value) {
|
|
|
|
|
+ // 根据历史课程类型数据填充表单
|
|
|
|
|
+ formData.value.historyCourseTypeId = selectedHistoryCourseType.value.id || ''
|
|
|
|
|
+ formData.value.ctType = selectedHistoryCourseType.value.ctType || ''
|
|
|
|
|
+ formData.value.ctTypeImage = selectedHistoryCourseType.value.ctTypeImage || ''
|
|
|
|
|
+ formData.value.ctTypeNode = selectedHistoryCourseType.value.ctTypeNode || '0'
|
|
|
|
|
+ formData.value.ctTypeSort = selectedHistoryCourseType.value.ctTypeSort || 0
|
|
|
|
|
+ formData.value.ctTypeDescribe = selectedHistoryCourseType.value.ctTypeDescribe || ''
|
|
|
|
|
+
|
|
|
|
|
+ // 更新引入信息
|
|
|
|
|
+ importedCourseTypeInfo.value = selectedHistoryCourseType.value.ctType
|
|
|
|
|
+ // 设置historyCourseTypeId
|
|
|
|
|
+ formData.value.historyCourseTypeId = selectedHistoryCourseType.value.id
|
|
|
|
|
+ // 自动打开开关
|
|
|
|
|
+ switchValue.value = true
|
|
|
|
|
+
|
|
|
|
|
+ historyCourseDialogVisible.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+.imported-info {
|
|
|
|
|
+ margin-top: 8px;
|
|
|
|
|
+ color: #606266;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ line-height: 1.5;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|