合并分支:合并课程两步式向导与教学资源关联管理能力

This commit is contained in:
wangzhibiao committed 2026-10-09 21:33:35 +08:00
commit 9030d797f4
22 files changed
+1178 -291

No files matched your search

+17
View File
@@ -35,6 +35,23 @@ export function updateCourse(data) {
})
}
// 绑定课程教学资源
export function bindCourseResource(cId, data) {
return request({
url: '/train/course/' + cId + '/resources',
method: 'post',
data: data
})
}
// 解绑课程教学资源(不删除资源本身)
export function unbindCourseResource(cId, resourceId) {
return request({
url: '/train/course/' + cId + '/resources/' + resourceId,
method: 'delete'
})
}
// 删除课程信息
export function delCourse(cId) {
return request({
+380 -239
View File
@@ -2,34 +2,14 @@
<div class="app-container">
<el-form v-show="showSearch" ref="queryForm" :model="queryParams" size="small" :inline="true" label-width="68px">
<el-form-item label="课程编码" prop="cCode">
<el-input
v-model="queryParams.cCode"
placeholder="请输入课程编码"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.cCode" placeholder="请输入课程编码" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="课程名称" prop="cName">
<el-input
v-model="queryParams.cName"
placeholder="请输入课程名称"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.cName" placeholder="请输入课程名称" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="课程类型" prop="cType">
<el-select
v-model="queryParams.cType"
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 v-model="queryParams.cType" placeholder="请选择课程类型" clearable>
<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">
@@ -46,25 +26,10 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
v-hasPermi="['train:course:add']"
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
<el-button v-hasPermi="['train:course:add']" type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['train:course:edit']"
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
>修改</el-button>
<el-button v-hasPermi="['train:course:edit']" type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate">修改</el-button>
</el-col>
<right-toolbar :show-search.sync="showSearch" @queryTable="getList" />
</el-row>
@@ -79,26 +44,14 @@
</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="status" width="90">
<template slot-scope="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : 'info'">
{{ scope.row.status === 1 ? '正常' : '停用' }}
</el-tag>
<el-tag :type="scope.row.status === 1 ? 'success' : 'info'">{{ scope.row.status === 1 ? '正常' : '停用' }}</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" class-name="small-padding fixed-width" width="180">
<template slot-scope="scope">
<el-button
v-hasPermi="['train:course:edit']"
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改</el-button>
<el-button v-hasPermi="['train:course:edit']" size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
<el-button
v-if="scope.row.status === 1"
v-hasPermi="['train:course:edit']"
@@ -129,119 +82,207 @@
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改课程信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="90px">
<el-form-item label="课程编码" prop="cCode">
<el-input v-model="form.cCode" placeholder="请输入课程统一业务编码 (如 KC-2026-001)" maxlength="50" />
</el-form-item>
<el-form-item label="课程名称" prop="cName">
<el-input v-model="form.cName" placeholder="请输入课程名称" maxlength="100" />
</el-form-item>
<el-form-item label="课程类型" prop="cType">
<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%;" />
</el-form-item>
<el-form-item label="教学目标" prop="teachingObjective">
<el-input v-model="form.teachingObjective" type="textarea" :rows="3" placeholder="请输入教学目标" />
</el-form-item>
<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>
<el-radio :label="0">停用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" maxlength="500" />
</el-form-item>
<el-dialog :title="title" :visible.sync="open" width="820px" append-to-body @closed="reset">
<el-steps :active="activeStep" finish-status="success" simple class="course-steps">
<el-step title="课程基本信息" icon="el-icon-edit-outline" />
<el-step title="教学资源" icon="el-icon-folder-opened" />
</el-steps>
<el-form v-show="activeStep === 0" ref="form" :model="form" :rules="rules" label-width="90px" class="course-form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="课程编码" prop="cCode">
<el-input v-model="form.cCode" placeholder="如 KC-2026-001" maxlength="50" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="课程名称" prop="cName">
<el-input v-model="form.cName" placeholder="请输入课程名称" maxlength="100" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="课程类型" prop="cType">
<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-col>
<el-col :span="12">
<el-form-item label="课程学时" prop="cDuration">
<el-input-number v-model="form.cDuration" :min="1" :max="9999" style="width: 100%;" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="教学目标" prop="teachingObjective">
<el-input v-model="form.teachingObjective" type="textarea" :rows="3" placeholder="请输入教学目标" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="课程内容" prop="courseContent">
<el-input v-model="form.courseContent" type="textarea" :rows="4" placeholder="请输入课程内容/摘要" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio :label="1">正常</el-radio>
<el-radio :label="0">停用</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" :rows="2" maxlength="500" placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div v-show="activeStep === 1" class="resource-step">
<el-alert title="课程基本信息已保存,可关联资源库中的资料,或上传新资源后自动关联。" type="success" :closable="false" show-icon />
<el-card shadow="never" class="resource-card">
<div slot="header" class="card-header">
<span>已关联资源</span>
<el-tag size="small">{{ boundResources.length }} 项</el-tag>
</div>
<el-table :data="boundResources" empty-text="暂未关联教学资源" size="small">
<el-table-column label="资源名称" prop="resourceName" min-width="180" show-overflow-tooltip />
<el-table-column label="类型" prop="resourceType" width="110" align="center">
<template slot-scope="scope">
<dict-tag :options="dict.type.train_resource_type" :value="scope.row.resourceType" />
</template>
</el-table-column>
<el-table-column label="文件/地址" prop="resourceUrl" min-width="220" show-overflow-tooltip>
<template slot-scope="scope">
<el-link :href="resourceLink(scope.row)" target="_blank" type="primary" :underline="false">{{ resourceLabel(scope.row) }}</el-link>
</template>
</el-table-column>
<el-table-column label="操作" width="80" align="center">
<template slot-scope="scope">
<el-button type="text" size="mini" @click="handleUnbind(scope.row)">解除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-card shadow="never" class="resource-card">
<div slot="header">从资源库关联</div>
<div class="resource-bind-row">
<el-select v-model="resourceToBind" filterable clearable placeholder="搜索并选择已有教学资源" style="flex: 1">
<el-option
v-for="item in availableResourceOptions"
:key="item.resourceId"
:label="item.resourceName"
:value="item.resourceId"
/>
</el-select>
<el-button type="primary" :disabled="!resourceToBind" :loading="resourceActionLoading" @click="handleBindExisting">关联资源</el-button>
</div>
</el-card>
<el-card v-hasPermi="['train:resource:edit']" shadow="never" class="resource-card">
<div slot="header">上传并关联新资源</div>
<el-form ref="resourceForm" :model="resourceForm" :rules="resourceRules" label-width="90px">
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="资源名称" prop="resourceName">
<el-input v-model="resourceForm.resourceName" maxlength="150" placeholder="请输入资源名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="资源类型" prop="resourceType">
<el-select v-model="resourceForm.resourceType" placeholder="请选择资源类型" style="width: 100%">
<el-option v-for="item in resourceTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item v-if="isExternalLink" label="外部链接" prop="resourceUrl">
<el-input v-model="resourceForm.resourceUrl" maxlength="500" placeholder="请输入以 http(s):// 开头的地址" />
</el-form-item>
<el-form-item v-else label="资源文件" prop="resourceUrl">
<file-upload v-model="resourceForm.resourceUrl" :limit="1" :file-size="100" :file-type="fileTypes" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="资源描述" prop="description">
<el-input v-model="resourceForm.description" type="textarea" :rows="2" maxlength="500" placeholder="请输入资源描述/使用说明" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="resource-submit">
<el-button type="primary" icon="el-icon-upload" :loading="resourceActionLoading" @click="handleCreateAndBind">保存资源并关联</el-button>
</div>
</el-card>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
<template v-if="activeStep === 0">
<el-button type="primary" :loading="savingCourse" @click="saveCourseAndNext">保存并下一步</el-button>
<el-button @click="cancel">取消</el-button>
</template>
<template v-else>
<el-button @click="activeStep = 0">上一步</el-button>
<el-button type="primary" @click="finishWizard">完成</el-button>
</template>
</div>
</el-dialog>
</div>
</template>
<script>
import { listCourse, getCourse, addCourse, updateCourse, delCourse } from '@/api/train/course'
import { listResource, getResource } from '@/api/train/resource'
import {
listCourse,
getCourse,
addCourse,
updateCourse,
delCourse,
bindCourseResource,
unbindCourseResource
} from '@/api/train/course'
import { listResource, addResource } from '@/api/train/resource'
export default {
name: 'Course',
dicts: ['train_course_type'],
dicts: ['train_course_type', 'train_resource_type'],
data() {
const validateDuration = (rule, value, callback) => {
if (value !== undefined && value !== null && value !== '') {
const num = Number(value)
if (!Number.isInteger(num) || num <= 0) {
callback(new Error('课程学时必须为正整数'))
} else {
callback()
}
const num = Number(value)
if (value !== undefined && value !== null && value !== '' && (!Number.isInteger(num) || num <= 0)) {
callback(new Error('课程学时必须为正整数'))
} else {
callback()
}
}
const validateResourceUrl = (rule, value, callback) => {
if (!value) {
callback(new Error('资源文件或外部链接不能为空'))
} else if (Number(this.resourceForm.resourceType) === 5 && !/^https?:\/\//i.test(value)) {
callback(new Error('外部链接必须以 http:// 或 https:// 开头'))
} else {
callback()
}
}
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 课程信息表格数据
courseList: [],
// 弹出层标题
title: '',
// 是否显示弹出层
open: false,
// 课程资源下拉备选项
activeStep: 0,
savingCourse: false,
resourceActionLoading: false,
resourceOptions: [],
// 已选课程资源ID集合 (对应 form.resourceId 逗号分隔字符串)
resourceIdList: [],
// 查询参数
boundResources: [],
resourceToBind: null,
fileTypes: ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'pdf', 'txt', 'zip', 'rar', '7z', 'mp4', 'avi', 'mov', 'wmv', 'mp3', 'png', 'jpg', 'jpeg', 'gif', 'glb', 'gltf', 'obj', 'fbx'],
queryParams: {
pageNum: 1,
pageSize: 10,
@@ -250,9 +291,8 @@ export default {
cType: null,
status: null
},
// 表单参数
form: {},
// 表单校验
resourceForm: {},
rules: {
cCode: [
{ required: true, message: '课程编码不能为空', trigger: 'blur' },
@@ -262,71 +302,76 @@ export default {
{ required: true, message: '课程名称不能为空', trigger: 'blur' },
{ max: 100, message: '课程名称长度不能超过100个字符', trigger: 'blur' }
],
cDuration: [
{ validator: validateDuration, trigger: 'blur' }
]
cDuration: [{ validator: validateDuration, trigger: 'blur' }]
},
resourceRules: {
resourceName: [{ required: true, message: '资源名称不能为空', trigger: 'blur' }],
resourceType: [{ required: true, message: '资源类型不能为空', trigger: 'change' }],
resourceUrl: [{ validator: validateResourceUrl, trigger: ['blur', 'change'] }]
}
}
},
computed: {
resourceTypeOptions() {
return (this.dict.type.train_resource_type || []).map(item => ({
label: item.label,
value: /^\d+$/.test(String(item.value)) ? Number(item.value) : item.value
}))
},
isExternalLink() {
return Number(this.resourceForm.resourceType) === 5
},
availableResourceOptions() {
const boundIds = this.boundResources.map(item => String(item.resourceId))
return this.resourceOptions.filter(item => boundIds.indexOf(String(item.resourceId)) === -1)
}
},
watch: {
'resourceForm.resourceType'(newVal, oldVal) {
if (oldVal !== undefined && newVal !== oldVal && this.open) {
this.$set(this.resourceForm, 'resourceUrl', null)
this.$nextTick(() => {
if (this.$refs.resourceForm) {
this.$refs.resourceForm.clearValidate('resourceUrl')
}
})
}
}
},
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
}).finally(() => {
this.loading = false
})
},
// 取消按钮
getResourceOptions() {
return listResource({ pageNum: 1, pageSize: 1000 }).then(response => {
this.resourceOptions = response.rows || []
})
},
loadCourseResources() {
if (!this.form.cId) {
this.boundResources = []
return Promise.resolve()
}
return getCourse(this.form.cId).then(response => {
this.boundResources = response.data.resources || []
})
},
cancel() {
this.open = false
this.reset()
},
// 表单重置
reset() {
this.activeStep = 0
this.savingCourse = false
this.resourceActionLoading = false
this.form = {
cId: null,
cCode: null,
@@ -335,81 +380,125 @@ export default {
cDuration: null,
teachingObjective: null,
courseContent: null,
resourceId: null,
status: 1,
remark: null
}
this.resourceIdList = []
this.resetResourceForm()
this.resourceOptions = []
this.boundResources = []
this.resourceToBind = null
this.resetForm('form')
},
/** 搜索按钮操作 */
resetResourceForm() {
this.resourceForm = {
resourceId: null,
resourceName: null,
resourceType: 1,
resourceUrl: null,
description: null,
status: 1,
remark: null
}
this.resetForm('resourceForm')
},
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.cId)
this.single = selection.length !== 1
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.prepareResourceOptions([]).then(() => {
this.open = true
this.title = '添加课程'
})
this.title = '添加课程'
this.open = true
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const cId = row.cId || this.ids
const cId = (row && row.cId) || this.ids[0]
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
}
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) {
updateCourse(this.form).then(response => {
this.$modal.msgSuccess('修改成功')
this.open = false
this.getList()
})
} else {
addCourse(this.form).then(response => {
this.$modal.msgSuccess('新增成功')
this.open = false
this.getList()
})
}
}
this.form = { ...response.data }
this.form.status = this.form.status == null ? 1 : Number(this.form.status)
this.boundResources = response.data.resources || []
this.title = '修改课程'
this.open = true
})
},
/** 状态切换(停用/启用) */
saveCourseAndNext() {
this.$refs.form.validate(valid => {
if (!valid) {
return
}
this.savingCourse = true
const saving = this.form.cId ? updateCourse(this.form) : addCourse(this.form)
saving.then(response => {
if (!this.form.cId) {
this.form = { ...this.form, ...response.data }
}
return Promise.all([this.getResourceOptions(), this.loadCourseResources()])
}).then(() => {
this.activeStep = 1
this.$modal.msgSuccess('课程基本信息已保存')
this.getList()
}).finally(() => {
this.savingCourse = false
})
})
},
handleBindExisting() {
if (!this.resourceToBind) {
return
}
this.resourceActionLoading = true
bindCourseResource(this.form.cId, {
resourceId: this.resourceToBind,
sortNo: this.boundResources.length
}).then(() => {
this.$modal.msgSuccess('资源关联成功')
this.resourceToBind = null
return this.loadCourseResources()
}).finally(() => {
this.resourceActionLoading = false
})
},
handleCreateAndBind() {
this.$refs.resourceForm.validate(valid => {
if (!valid) {
return
}
this.resourceActionLoading = true
addResource(this.resourceForm).then(response => {
const resource = response.data
return bindCourseResource(this.form.cId, {
resourceId: resource.resourceId,
sortNo: this.boundResources.length
})
}).then(() => {
this.$modal.msgSuccess('资源已上传并关联')
this.resetResourceForm()
return Promise.all([this.getResourceOptions(), this.loadCourseResources()])
}).finally(() => {
this.resourceActionLoading = false
})
})
},
handleUnbind(resource) {
this.$modal.confirm(`确定解除资源《${resource.resourceName}》与当前课程的关联吗?资源本身不会被删除。`).then(() => {
return unbindCourseResource(this.form.cId, resource.resourceId)
}).then(() => {
this.$modal.msgSuccess('已解除关联')
return this.loadCourseResources()
}).catch(() => {})
},
finishWizard() {
this.open = false
this.getList()
},
handleStatusChange(row, newStatus) {
const actionText = newStatus === 1 ? '启用' : '停用'
const promptText = newStatus === 0
@@ -422,7 +511,6 @@ export default {
this.getList()
}).catch(() => {})
},
/** 删除按钮操作 */
handleDelete(row) {
this.$modal.confirm(`确定删除课程《${row.cName}》吗?`).then(() => {
return delCourse(row.cId)
@@ -430,7 +518,60 @@ export default {
this.$modal.msgSuccess('删除成功')
this.getList()
}).catch(() => {})
},
resourceLink(resource) {
if (!resource || !resource.resourceUrl) {
return ''
}
if (/^https?:\/\//i.test(resource.resourceUrl)) {
return resource.resourceUrl
}
return process.env.VUE_APP_BASE_API + resource.resourceUrl
},
resourceLabel(resource) {
if (!resource || !resource.resourceUrl) {
return ''
}
if (Number(resource.resourceType) === 5) {
return resource.resourceUrl
}
return resource.resourceUrl.substring(resource.resourceUrl.lastIndexOf('/') + 1)
}
}
}
</script>
<style scoped>
.course-steps {
margin-bottom: 24px;
}
.course-form {
padding: 0 12px;
}
.resource-step {
max-height: 62vh;
overflow-y: auto;
padding: 0 4px;
}
.resource-card {
margin-top: 16px;
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
}
.resource-bind-row {
display: flex;
gap: 12px;
}
.resource-submit {
text-align: right;
}
</style>