课程类型支持下拉选择,增加课程资源id关联

This commit is contained in:
buliping committed 2026-10-09 09:13:51 +08:00
1 parent abb042ff1a
commit b78765c7ff
4 files changed
+140 -15

No files matched your search

@@ -43,6 +43,10 @@ public class TrainCourse extends BaseEntity
@Excel(name = "课程内容")
private String courseContent;
/** 课程资源ID,多个资源以英文逗号分隔,对应 train_resource.resource_id */
@Excel(name = "课程资源ID")
private String resourceId;
/** 课程状态 (1:正常, 0:停用) */
@Excel(name = "课程状态", readConverterExp = "1=正常,0=停用")
private Integer status;
@@ -180,6 +184,16 @@ public class TrainCourse extends BaseEntity
return courseContent;
}
public void setResourceId(String resourceId)
{
this.resourceId = resourceId;
}
public String getResourceId()
{
return resourceId;
}
public void setStatus(Integer status)
{
this.status = status;
@@ -210,6 +224,7 @@ public class TrainCourse extends BaseEntity
.append("cDuration", getcDuration())
.append("teachingObjective", getTeachingObjective())
.append("courseContent", getCourseContent())
.append("resourceId", getResourceId())
.append("status", getStatus())
.append("delFlag", getDelFlag())
.append("createBy", getCreateBy())
@@ -60,6 +60,8 @@ public class CourseDetailVO implements Serializable
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
private String resourceId;
/**
* 已关联的教学资源列表
* 注:当前 ISSUE-01-03 未实现真实 Course<->Resource 查询;
@@ -91,6 +93,7 @@ public class CourseDetailVO implements Serializable
vo.setCreateTime(course.getCreateTime());
vo.setUpdateBy(course.getUpdateBy());
vo.setUpdateTime(course.getUpdateTime());
vo.setResourceId(course.getResourceId());
// 资源绑定/解绑能力属于 P1,当前返回空列表保持响应结构稳定
vo.setResources(Collections.emptyList());
return vo;
@@ -286,6 +289,14 @@ public class CourseDetailVO implements Serializable
this.updateTime = updateTime;
}
public String getResourceId() {
return resourceId;
}
public void setResourceId(String resourceId) {
this.resourceId = resourceId;
}
public List<Object> getResources()
{
return resources;
@@ -12,6 +12,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="cDuration" column="c_duration" />
<result property="teachingObjective" column="teaching_objective" />
<result property="courseContent" column="course_content" />
<result property="resourceId" column="resource_id" />
<result property="status" column="status" />
<result property="delFlag" column="del_flag" />
<result property="createBy" column="create_by" />
@@ -22,7 +23,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
<sql id="selectTrainCourseVo">
select c_id, c_code, c_name, c_type, c_duration, teaching_objective, course_content, status, del_flag, create_by, create_time, update_by, update_time, remark from train_course
select c_id, c_code, c_name, c_type, c_duration, teaching_objective, course_content, resource_id, status, del_flag, create_by, create_time, update_by, update_time, remark from train_course
</sql>
<select id="selectTrainCourseList" parameterType="TrainCourse" resultMap="TrainCourseResult">
@@ -63,6 +64,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="cDuration != null">c_duration,</if>
<if test="teachingObjective != null and teachingObjective != ''">teaching_objective,</if>
<if test="courseContent != null and courseContent != ''">course_content,</if>
<if test="resourceId != null and resourceId != ''">resource_id,</if>
<if test="status != null">status,</if>
<if test="delFlag != null and delFlag != ''">del_flag,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
@@ -79,6 +81,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="cDuration != null">#{cDuration},</if>
<if test="teachingObjective != null and teachingObjective != ''">#{teachingObjective},</if>
<if test="courseContent != null and courseContent != ''">#{courseContent},</if>
<if test="resourceId != null and resourceId != ''">#{resourceId},</if>
<if test="status != null">#{status},</if>
<if test="delFlag != null and delFlag != ''">#{delFlag},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
@@ -98,6 +101,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="cDuration != null">c_duration = #{cDuration},</if>
<if test="teachingObjective != null">teaching_objective = #{teachingObjective},</if>
<if test="courseContent != null">course_content = #{courseContent},</if>
<if test="resourceId != null">resource_id = #{resourceId},</if>
<if test="status != null">status = #{status},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
+109 -14
View File
@@ -18,12 +18,19 @@
/>
</el-form-item>
<el-form-item label="课程类型" prop="cType">
<el-input
<el-select
v-model="queryParams.cType"
placeholder="请输入课程类型"
placeholder="请选择课程类型"
clearable
@keyup.enter.native="handleQuery"
/>
>
<el-option
v-for="dict in dict.type.train_course_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="课程状态" clearable>
@@ -66,10 +73,14 @@
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="课程编码" align="center" prop="cCode" min-width="120" :show-overflow-tooltip="true" />
<el-table-column label="课程名称" align="center" prop="cName" min-width="140" :show-overflow-tooltip="true" />
<el-table-column label="课程类型" align="center" prop="cType" width="120" />
<el-table-column label="课程类型" align="center" prop="cType" width="120">
<template slot-scope="scope">
<dict-tag :options="dict.type.train_course_type" :value="scope.row.cType" />
</template>
</el-table-column>
<el-table-column label="学时" align="center" prop="cDuration" width="80" />
<el-table-column label="教学目标" align="center" prop="teachingObjective" min-width="150" :show-overflow-tooltip="true" />
<el-table-column label="课程内容" align="center" prop="courseContent" min-width="160" :show-overflow-tooltip="true" />
<!-- <el-table-column label="教学目标" align="center" prop="teachingObjective" min-width="150" :show-overflow-tooltip="true" />
<el-table-column label="课程内容" align="center" prop="courseContent" min-width="160" :show-overflow-tooltip="true" />-->
<el-table-column label="状态" align="center" prop="status" width="90">
<template slot-scope="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : 'info'">
@@ -77,8 +88,8 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" min-width="120" :show-overflow-tooltip="true" />
<el-table-column label="创建时间" align="center" prop="createTime" width="160" />
<!-- <el-table-column label="备注" align="center" prop="remark" min-width="120" :show-overflow-tooltip="true" />
<el-table-column label="创建时间" align="center" prop="createTime" width="160" />-->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
<template slot-scope="scope">
<el-button
@@ -136,7 +147,14 @@
<el-input v-model="form.cName" placeholder="请输入课程名称" maxlength="100" />
</el-form-item>
<el-form-item label="课程类型" prop="cType">
<el-input v-model="form.cType" placeholder="请输入课程类型 (如 理论课/实操课)" maxlength="30" />
<el-select v-model="form.cType" placeholder="请选择课程类型" clearable style="width: 100%">
<el-option
v-for="dict in dict.type.train_course_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="课程学时" prop="cDuration">
<el-input-number v-model="form.cDuration" :min="1" :max="9999" placeholder="请输入课程学时" style="width: 100%;" />
@@ -147,6 +165,23 @@
<el-form-item label="课程内容" prop="courseContent">
<el-input v-model="form.courseContent" type="textarea" :rows="4" placeholder="请输入课程内容/摘要" />
</el-form-item>
<el-form-item label="课程资源" prop="resourceId">
<el-select
v-model="resourceIdList"
multiple
filterable
collapse-tags
placeholder="请选择课程资源 (可多选)"
style="width: 100%"
>
<el-option
v-for="item in resourceOptions"
:key="item.resourceId"
:label="item.resourceName"
:value="String(item.resourceId)"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio :label="1">正常</el-radio>
@@ -167,9 +202,11 @@
<script>
import { listCourse, getCourse, addCourse, updateCourse, delCourse } from '@/api/train/course'
import { listResource, getResource } from '@/api/train/resource'
export default {
name: 'Course',
dicts: ['train_course_type'],
data() {
const validateDuration = (rule, value, callback) => {
if (value !== undefined && value !== null && value !== '') {
@@ -200,6 +237,10 @@ export default {
title: '',
// 是否显示弹出层
open: false,
// 课程资源下拉备选项
resourceOptions: [],
// 已选课程资源ID集合 (对应 form.resourceId 逗号分隔字符串)
resourceIdList: [],
// 查询参数
queryParams: {
pageNum: 1,
@@ -229,13 +270,52 @@ export default {
},
created() {
this.getList()
this.getResourceOptions()
},
methods: {
/** 查询课程资源下拉备选项 (不做状态过滤,保证已选的停用资源也能正常回显) */
getResourceOptions() {
return listResource({ pageNum: 1, pageSize: 1000 }).then(response => {
this.resourceOptions = response.rows || []
return this.resourceOptions
}).catch(() => {
this.resourceOptions = this.resourceOptions || []
return this.resourceOptions
})
},
/** 课程资源ID字符串 -> 多选数组 (统一转成字符串,避免类型不一致导致无法勾选) */
parseResourceIds(value) {
if (value === null || value === undefined || value === '') {
return []
}
return String(value).split(',').map(item => String(item).trim()).filter(item => item !== '')
},
/** 保证已选资源在下拉选项中存在;element-ui 多选值若无对应 option 会不显示,故必须补齐后再回显 */
ensureResourceOptions(ids) {
const existingIds = this.resourceOptions.map(item => String(item.resourceId).trim())
const missingIds = ids.filter(id => existingIds.indexOf(id) === -1)
if (missingIds.length === 0) {
return Promise.resolve()
}
return Promise.all(missingIds.map(id => {
return getResource(id).then(response => {
if (response.data) {
this.resourceOptions.push(response.data)
}
}).catch(() => {})
}))
},
/** 备选项就绪后再回显已选资源 */
prepareResourceOptions(ids) {
const load = this.resourceOptions.length > 0 ? Promise.resolve() : this.getResourceOptions()
return Promise.resolve(load).then(() => this.ensureResourceOptions(ids))
},
/** 查询课程信息列表 */
getList() {
this.loading = true
listCourse(this.queryParams).then(response => {
this.courseList = response.rows
//console.log(response.rows);
this.total = response.total
this.loading = false
})
@@ -255,9 +335,11 @@ export default {
cDuration: null,
teachingObjective: null,
courseContent: null,
resourceId: null,
status: 1,
remark: null
}
this.resourceIdList = []
this.resetForm('form')
},
/** 搜索按钮操作 */
@@ -278,24 +360,37 @@ export default {
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
this.title = '添加课程'
this.prepareResourceOptions([]).then(() => {
this.open = true
this.title = '添加课程'
})
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const cId = row.cId || this.ids
getCourse(cId).then(response => {
//console.log(response.data);
this.form = response.data
if (this.form.status === undefined || this.form.status === null) {
this.form.status = 1
}
this.open = true
this.title = '修改课程'
})
const selectedIds = this.parseResourceIds(this.form.resourceId)
// 必须先保证这些ID在下拉备选项中存在,否则多选不会被勾选/显示
return this.prepareResourceOptions(selectedIds).then(() => {
//this.resourceIdList = selectedIds
//console.log("selectedIds===============");
//console.log(selectedIds);
this.$set(this,"resourceIdList",selectedIds);
this.open = true
this.title = '修改课程'
})
}).catch(() => {})
},
/** 提交按钮 */
submitForm() {
// 多选资源ID以逗号分隔写入 resource_id 字段
this.form.resourceId = this.resourceIdList.length > 0 ? this.resourceIdList.join(',') : null
this.$refs['form'].validate(valid => {
if (valid) {
if (this.form.cId != null) {