|
|
|
|
@ -16,28 +16,44 @@
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="subjectObj.course_content_status===0">
|
|
|
|
|
<el-button type="primary" size="small" @click="changeContentStatus(true)">发布课表</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="subjectObj.course_content_status===1">
|
|
|
|
|
<el-button type="primary" size="small" @click="changeContentStatus(false)">取消发布课表</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="subjectObj.course_content_status===1">
|
|
|
|
|
<el-button type="primary" size="small" @click="isSendMessage">短信通知</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<el-button type="primary" size="small" v-print="'#print'">下载并打印课表</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="subjectObj.course_content_status===1">
|
|
|
|
|
<el-button type="primary" size="small" @click="changeContentStatus(false)">取消发布课表</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="subjectObj.course_content_status===1">
|
|
|
|
|
<el-button type="primary" size="small" @click="isSendMessage">短信通知</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<el-button type="primary" size="small" v-print="'#print'">下载并打印课表</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="schedule" id="print">
|
|
|
|
|
<el-table :data="list" border style="width: 100%;height:300px;overflow: scroll;">
|
|
|
|
|
<el-table-column v-for="item in table_item" :prop="item.prop" :label="item.label"
|
|
|
|
|
<el-table-column v-for="item in table_item" :key="item.prop" :prop="item.prop" :label="item.label"
|
|
|
|
|
:width="item.width?item.width:''" :align="item.align">
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="操作" :width="180" align="center">
|
|
|
|
|
<!-- 课件列使用自定义模板 -->
|
|
|
|
|
<el-table-column label="课件" width="200" align="center">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<div v-if="scope.row.files && scope.row.files.length > 0">
|
|
|
|
|
<div v-for="file in scope.row.files" :key="file.id" class="file-item">
|
|
|
|
|
<el-link type="primary" @click="downloadFile(file)" :underline="false">
|
|
|
|
|
<i class="el-icon-document"></i>
|
|
|
|
|
{{ file.original_name }}
|
|
|
|
|
</el-link>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<span v-else class="no-files">暂无课件</span>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="操作" :width="220" align="center">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<el-button type="primary" size="small" style='margin-left:5px;margin-bottom:5px;'
|
|
|
|
|
@click="editClass('editor',scope.row.id)">编辑</el-button>
|
|
|
|
|
<el-button type="success" size="small" style='margin-left:5px;margin-bottom:5px;'
|
|
|
|
|
@click="uploadMaterial(scope.row)">上传课件</el-button>
|
|
|
|
|
<el-popconfirm style="margin:0 10px" @confirm="deleteList(scope.row.id)" title="确定删除吗?">
|
|
|
|
|
<el-button type="danger" size="small" slot="reference">删除</el-button>
|
|
|
|
|
</el-popconfirm>
|
|
|
|
|
@ -52,6 +68,65 @@
|
|
|
|
|
</Modal>
|
|
|
|
|
<imports ref="imports" :table-name="'course_contents'" :course_id="id+''" @refresh="refreshData"></imports>
|
|
|
|
|
<editClass ref="editClass" @refresh="getCousreContent"></editClass>
|
|
|
|
|
|
|
|
|
|
<!-- 上传课件模态框 -->
|
|
|
|
|
<el-dialog title="上传课件" :visible.sync="materialDialogVisible" width="600px" center>
|
|
|
|
|
<div class="material-upload-container">
|
|
|
|
|
<div class="course-info">
|
|
|
|
|
<h4>课程信息</h4>
|
|
|
|
|
<p><strong>日期:</strong>{{ selectedCourse.date }}</p>
|
|
|
|
|
<p><strong>时间:</strong>{{ selectedCourse.period }}</p>
|
|
|
|
|
<p><strong>主题:</strong>{{ selectedCourse.theme }}</p>
|
|
|
|
|
<p><strong>老师:</strong>{{ selectedCourse.teacher ? selectedCourse.teacher.name : '' }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="upload-section">
|
|
|
|
|
<h4>课件上传</h4>
|
|
|
|
|
<el-upload
|
|
|
|
|
ref="materialUpload"
|
|
|
|
|
:action="uploadAction"
|
|
|
|
|
:headers="uploadHeaders"
|
|
|
|
|
:file-list="materialFileList"
|
|
|
|
|
:on-success="handleMaterialUploadSuccess"
|
|
|
|
|
:on-remove="handleMaterialUploadRemove"
|
|
|
|
|
:on-error="handleMaterialUploadError"
|
|
|
|
|
:before-upload="beforeMaterialUpload"
|
|
|
|
|
multiple
|
|
|
|
|
drag
|
|
|
|
|
accept=".pdf,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.zip,.rar,.txt,.jpg,.jpeg,.png,.gif">
|
|
|
|
|
<i class="el-icon-upload"></i>
|
|
|
|
|
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
|
|
|
|
<div class="el-upload__tip" slot="tip">
|
|
|
|
|
支持 PDF、Word、PPT、Excel、压缩包、图片等格式,单个文件不超过50MB
|
|
|
|
|
</div>
|
|
|
|
|
</el-upload>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="material-list" v-if="materialFileList.length > 0">
|
|
|
|
|
<h4>已上传课件</h4>
|
|
|
|
|
<el-table :data="materialFileList" size="small" style="width: 100%">
|
|
|
|
|
<el-table-column prop="name" label="文件名" min-width="150"></el-table-column>
|
|
|
|
|
<el-table-column prop="size" label="大小" width="100" align="center">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
{{ formatFileSize(scope.row.size) }}
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="操作" width="120" align="center">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<el-button type="text" size="small" @click="downloadMaterial(scope.row)">
|
|
|
|
|
<i class="el-icon-download"></i> 下载
|
|
|
|
|
</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
|
|
|
<el-button @click="materialDialogVisible = false">取消</el-button>
|
|
|
|
|
<el-button type="primary" @click="saveMaterialFiles" :loading="saving">保存课件</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
@ -60,15 +135,17 @@
|
|
|
|
|
import {
|
|
|
|
|
index,
|
|
|
|
|
sendSms,
|
|
|
|
|
destroy
|
|
|
|
|
} from '@/api/course/courseContent.js'
|
|
|
|
|
import {
|
|
|
|
|
index as teacherIndex
|
|
|
|
|
destroy,
|
|
|
|
|
save as saveContent
|
|
|
|
|
} from '@/api/course/courseContent.js'
|
|
|
|
|
import {
|
|
|
|
|
index as teacherIndex
|
|
|
|
|
} from "@/api/info/teachers.js"
|
|
|
|
|
import {
|
|
|
|
|
show,
|
|
|
|
|
save
|
|
|
|
|
} from "@/api/course/index.js"
|
|
|
|
|
import { uploads } from '@/api/uploads.js'
|
|
|
|
|
import imports from "@/views/component/imports.vue"
|
|
|
|
|
import editClass from "../components/editClass.vue"
|
|
|
|
|
export default {
|
|
|
|
|
@ -116,7 +193,15 @@
|
|
|
|
|
prop: 'teacher.introduce',
|
|
|
|
|
label: '老师简介',
|
|
|
|
|
align: 'left'
|
|
|
|
|
}]
|
|
|
|
|
}],
|
|
|
|
|
materialDialogVisible: false, // 上传课件模态框的可见性
|
|
|
|
|
selectedCourse: {}, // 当前选中的课程内容
|
|
|
|
|
uploadAction: `${process.env.VUE_APP_UPLOAD_API}`, // 上传文件的URL
|
|
|
|
|
uploadHeaders: {
|
|
|
|
|
Authorization: `Bearer ${this.$store.getters.token}`
|
|
|
|
|
}, // 上传文件时的请求头
|
|
|
|
|
materialFileList: [], // 已上传的课件文件列表
|
|
|
|
|
saving: false // 保存状态
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
@ -145,13 +230,13 @@
|
|
|
|
|
show_relation: ['teacher', 'type_detail']
|
|
|
|
|
})
|
|
|
|
|
this.subjectObj = {}
|
|
|
|
|
this.subjectObj = this.base.deepCopy(res)
|
|
|
|
|
let teacher = []
|
|
|
|
|
if(res.teacher_detail.length>0){
|
|
|
|
|
res.teacher_detail.map(item=>{
|
|
|
|
|
teacher.push(item.name)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
this.subjectObj = this.base.deepCopy(res)
|
|
|
|
|
let teacher = []
|
|
|
|
|
if(res.teacher_detail.length>0){
|
|
|
|
|
res.teacher_detail.map(item=>{
|
|
|
|
|
teacher.push(item.name)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
this.subjectObj.teacherList = teacher.join(",")
|
|
|
|
|
},
|
|
|
|
|
// 导入
|
|
|
|
|
@ -159,7 +244,7 @@
|
|
|
|
|
this.$refs.imports.show()
|
|
|
|
|
},
|
|
|
|
|
refreshData() {
|
|
|
|
|
this.$emit('refresh')
|
|
|
|
|
this.$emit('refresh')
|
|
|
|
|
this.getTeachers()
|
|
|
|
|
this.getCourseDetail()
|
|
|
|
|
this.getCousreContent()
|
|
|
|
|
@ -169,18 +254,18 @@
|
|
|
|
|
if (this.list.length === 0) {
|
|
|
|
|
this.$Message.warning("请先导入课表")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if(flag){
|
|
|
|
|
this.subjectObj.course_content_status = 1
|
|
|
|
|
}else{
|
|
|
|
|
this.subjectObj.course_content_status = 0
|
|
|
|
|
}
|
|
|
|
|
if(flag){
|
|
|
|
|
this.subjectObj.course_content_status = 1
|
|
|
|
|
}else{
|
|
|
|
|
this.subjectObj.course_content_status = 0
|
|
|
|
|
}
|
|
|
|
|
save(this.subjectObj).then(res => {
|
|
|
|
|
this.$Message.success(flag?"发布成功":'已取消发布')
|
|
|
|
|
this.$emit('refresh')
|
|
|
|
|
this.getCourseDetail()
|
|
|
|
|
if(flag){
|
|
|
|
|
this.isSendMessage()
|
|
|
|
|
this.getCourseDetail()
|
|
|
|
|
if(flag){
|
|
|
|
|
this.isSendMessage()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
@ -211,13 +296,13 @@
|
|
|
|
|
this.$refs.editClass.id = id
|
|
|
|
|
this.$refs.editClass.setTeachers(this.teacher_options)
|
|
|
|
|
this.$refs.editClass.isShow = true
|
|
|
|
|
},
|
|
|
|
|
async getTeachers() {
|
|
|
|
|
const res = await teacherIndex({
|
|
|
|
|
page: 1,
|
|
|
|
|
page_size: 999
|
|
|
|
|
})
|
|
|
|
|
this.teacher_options = res.data
|
|
|
|
|
},
|
|
|
|
|
async getTeachers() {
|
|
|
|
|
const res = await teacherIndex({
|
|
|
|
|
page: 1,
|
|
|
|
|
page_size: 999
|
|
|
|
|
})
|
|
|
|
|
this.teacher_options = res.data
|
|
|
|
|
},
|
|
|
|
|
deleteList(id) {
|
|
|
|
|
var that = this;
|
|
|
|
|
@ -231,6 +316,80 @@
|
|
|
|
|
reject(error)
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
uploadMaterial(row) {
|
|
|
|
|
this.selectedCourse = row;
|
|
|
|
|
this.materialFileList = []; // 清空已上传文件列表
|
|
|
|
|
this.materialDialogVisible = true;
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.$refs.materialUpload.clearFiles(); // 清空上传组件的文件列表
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
handleMaterialUploadSuccess(response, file, fileList) {
|
|
|
|
|
this.$message.success('课件上传成功');
|
|
|
|
|
this.materialFileList = fileList;
|
|
|
|
|
},
|
|
|
|
|
handleMaterialUploadRemove(file, fileList) {
|
|
|
|
|
this.materialFileList = fileList;
|
|
|
|
|
},
|
|
|
|
|
handleMaterialUploadError(err, file, fileList) {
|
|
|
|
|
this.$message.error('课件上传失败: ' + err);
|
|
|
|
|
},
|
|
|
|
|
beforeMaterialUpload(file) {
|
|
|
|
|
const isLt50M = file.size / 1024 / 1024 < 50;
|
|
|
|
|
if (!isLt50M) {
|
|
|
|
|
this.$message.error('上传文件大小不能超过 50MB!');
|
|
|
|
|
}
|
|
|
|
|
return isLt50M;
|
|
|
|
|
},
|
|
|
|
|
downloadMaterial(file) {
|
|
|
|
|
window.open(file.url);
|
|
|
|
|
},
|
|
|
|
|
formatFileSize(size) {
|
|
|
|
|
if (size === 0) return '0 Bytes';
|
|
|
|
|
const k = 1024;
|
|
|
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
|
|
|
|
const i = Math.floor(Math.log(size) / Math.log(k));
|
|
|
|
|
return parseFloat((size / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
|
|
|
},
|
|
|
|
|
downloadFile(file) {
|
|
|
|
|
// 创建一个临时的a标签来下载文件
|
|
|
|
|
const link = document.createElement('a');
|
|
|
|
|
link.href = file.url;
|
|
|
|
|
link.download = file.original_name;
|
|
|
|
|
link.target = '_blank';
|
|
|
|
|
document.body.appendChild(link);
|
|
|
|
|
link.click();
|
|
|
|
|
document.body.removeChild(link);
|
|
|
|
|
},
|
|
|
|
|
async saveMaterialFiles() {
|
|
|
|
|
if (this.materialFileList.length === 0) {
|
|
|
|
|
this.$message.warning('请先上传课件文件');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.saving = true;
|
|
|
|
|
try {
|
|
|
|
|
// 提取文件ID数组
|
|
|
|
|
const fileIds = this.materialFileList.map(file => {
|
|
|
|
|
return file.response ? file.response.id : file.id;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 只传递课程ID和文件ID数组
|
|
|
|
|
const updateData = {
|
|
|
|
|
id: this.selectedCourse.id,
|
|
|
|
|
file_ids: fileIds
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
await saveContent(updateData);
|
|
|
|
|
this.$message.success('课件保存成功');
|
|
|
|
|
this.materialDialogVisible = false;
|
|
|
|
|
this.getCousreContent(); // 刷新列表
|
|
|
|
|
} catch (error) {
|
|
|
|
|
this.$message.error('保存失败: ' + error.message);
|
|
|
|
|
} finally {
|
|
|
|
|
this.saving = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
watch: {
|
|
|
|
|
isShow(newVal) {
|
|
|
|
|
@ -259,11 +418,11 @@
|
|
|
|
|
html,
|
|
|
|
|
div {
|
|
|
|
|
height: auto !important;
|
|
|
|
|
}
|
|
|
|
|
table th:last-child,
|
|
|
|
|
table th:last-child {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
table th:last-child,
|
|
|
|
|
table th:last-child {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -302,4 +461,60 @@
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
.material-upload-container {
|
|
|
|
|
.course-info {
|
|
|
|
|
background: #f5f7fa;
|
|
|
|
|
padding: 15px;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
|
|
|
|
h4 {
|
|
|
|
|
margin: 0 0 10px 0;
|
|
|
|
|
color: #303133;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p {
|
|
|
|
|
margin: 5px 0;
|
|
|
|
|
color: #606266;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.upload-section {
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
|
|
|
|
h4 {
|
|
|
|
|
margin: 0 0 10px 0;
|
|
|
|
|
color: #303133;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.material-list {
|
|
|
|
|
h4 {
|
|
|
|
|
margin: 0 0 10px 0;
|
|
|
|
|
color: #303133;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.file-item {
|
|
|
|
|
margin-bottom: 5px;
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-link {
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
|
|
i {
|
|
|
|
|
margin-right: 4px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.no-files {
|
|
|
|
|
color: #909399;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|