You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
426 lines
11 KiB
426 lines
11 KiB
<template> |
|
<el-drawer title="添加系统资源" :visible.sync="sourceVisible" size="1200px" :close-on-click-modal="false" |
|
custom-class="source-dia" @closed="closeDia"> |
|
<div class="overflow"> |
|
<div class="left"> |
|
<el-input style="width: 300px" placeholder="请输入资源名称" prefix-icon="el-icon-search" v-model="keyword" |
|
clearable></el-input> |
|
<div class="tabs mgb20"> |
|
<a class="item" v-for="(item, i) in tabs" :key="i" :class="{ active: i == active }" @click="tabChange(i)">{{ |
|
item |
|
}}</a> |
|
</div> |
|
|
|
<div class="course"> |
|
<div v-for="(course, i) in course" :key="i" class="item"> |
|
<div class="line"> |
|
<i :class="`el-icon-caret-right arrow ${course.shrink ? 'active' : ''}`" |
|
@click="course.shrink = !course.shrink"></i> |
|
<el-checkbox class="check" v-model="course.check" @change="checkCourse(course)"></el-checkbox> |
|
<img v-if="course.coverUrl" class="cover" :src="course.coverUrl" alt=""> |
|
<span class="course-name">{{ course.curriculumName }}</span> |
|
</div> |
|
<div v-if="course.shrink" class="chapters"> |
|
<!-- 章节 --> |
|
<div v-for="(chapter, j) in course.chapters" :key="j" class=""> |
|
<div class="line"> |
|
<i :class="`el-icon-caret-right arrow ${chapter.shrink ? 'active' : ''}`" |
|
@click="chapter.shrink = !chapter.shrink"></i> |
|
<el-checkbox class="check" v-model="chapter.check" @change="checkChapter(chapter, course)">{{ |
|
chapter.name |
|
}}</el-checkbox> |
|
</div> |
|
|
|
<!-- 小节 --> |
|
<div v-if="chapter.shrink" class="sections"> |
|
<div v-for="(section, k) in chapter.subsections" :key="k" class="line"> |
|
<img v-if="section.fileType === 'pptx'" src="@/assets/img/exts/ppt.png" alt=""> |
|
<img v-else-if="section.fileType === 'mp4'" src="@/assets/img/exts/video.png" alt=""> |
|
<img v-else-if="section.fileType === 'doc' || section.fileType === 'docx'" |
|
src="@/assets/img/exts/word.png" alt=""> |
|
<img v-else-if="section.fileType === 'xlsx' || section.fileType === 'xls'" |
|
src="@/assets/img/exts/excel.png" alt=""> |
|
<img v-else-if="section.fileType === 'txt'" src="@/assets/img/exts/txt.png" alt=""> |
|
<img v-else-if="section.fileType === 'pdf'" src="@/assets/img/exts/pdf.png" alt=""> |
|
<img v-else src="@/assets/img/exts/pic.png" alt=""> |
|
<el-checkbox class="check" v-model="section.check" @change="checkSection(section, chapter)">{{ |
|
section.name |
|
}}</el-checkbox> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="right"> |
|
<template v-if="checked.length"> |
|
<div class="flex-between m-b-10"> |
|
<p class="total">已选资源(共{{ checked.length }}个)</p> |
|
<el-button type="text" @click="batchDelChecked">批量移除</el-button> |
|
</div> |
|
|
|
<el-input placeholder="请输入资源名称" prefix-icon="el-icon-search" v-model="checkedKeyword" clearable></el-input> |
|
|
|
<div :class="['lines']"> |
|
<template v-for="(item, i) in checked"> |
|
<div v-if="item.name.includes(checkedKeyword)" :key="i" class="line"> |
|
<div class="check-left"> |
|
<el-checkbox v-model="item.check"></el-checkbox> |
|
<span class="serial">{{ i + 1 }}</span> |
|
<el-tooltip effect="dark" :content="item.name" placement="top-start"> |
|
<p class="checked-name ellipsis">{{ item.name }}</p> |
|
</el-tooltip> |
|
</div> |
|
<i class="el-icon-delete action-icon" @click="delChecked(item)"></i> |
|
</div> |
|
</template> |
|
</div> |
|
</template> |
|
<div v-else class="empty"> |
|
<img class="icon" src="@/assets/img/empty.svg" alt=""> |
|
<p>暂无数据</p> |
|
</div> |
|
|
|
</div> |
|
</div> |
|
|
|
<div class="btns"> |
|
<el-button @click="sourceVisible = false">取消</el-button> |
|
<el-button type="primary" :loading="submiting" @click="submit">确定</el-button> |
|
</div> |
|
</el-drawer> |
|
</template> |
|
<script> |
|
import Setting from '@/setting' |
|
import Util from '@/libs/util' |
|
import _ from 'lodash' |
|
export default { |
|
props: ['visible'], |
|
data () { |
|
return { |
|
sourceVisible: false, |
|
active: 'tab1', |
|
tabs: { |
|
tab1: '教学课程', |
|
tab2: '精品课程', |
|
tab3: '文件素材', |
|
}, |
|
keyword: '', |
|
searchTimer: null, |
|
checkedKeyword: '', |
|
|
|
allSections: [], |
|
course: [], |
|
|
|
checked: [], |
|
submiting: false, |
|
loaded: 0, |
|
}; |
|
}, |
|
watch: { |
|
'keyword': function (val) { |
|
clearTimeout(this.searchTimer) |
|
this.searchTimer = setTimeout(this.getCourse, 500) |
|
}, |
|
visible () { |
|
this.sourceVisible = this.visible |
|
this.visible && this.init() |
|
} |
|
}, |
|
mounted () { |
|
|
|
}, |
|
methods: { |
|
// 初始化 |
|
init () { |
|
this.getCourse() |
|
}, |
|
// 课程列表 |
|
async getCourse () { |
|
const { list } = await this.$post(`${this.api[this.active === 'tab1' ? 'curriculumTree' : 'boutiqueCurriculumTree']}?name=${this.keyword}`) |
|
if (list.length) { |
|
const all = [] |
|
list.forEach(e => { |
|
e.shrink = false |
|
e.check = false |
|
e.chapters.forEach(n => { |
|
n.shrink = false |
|
n.check = false |
|
all.push(...n.subsections) |
|
n.subsections.forEach(m => { |
|
m.check = false |
|
}) |
|
}) |
|
}) |
|
list[0].shrink = true |
|
list[0].chapters[0].shrink = true |
|
this.allSections = all |
|
} |
|
this.course = list |
|
}, |
|
initData () { |
|
this.page = 1; |
|
this.getData(); |
|
}, |
|
tabChange (index) { |
|
this.active = index |
|
this.getCourse() |
|
}, |
|
// 课程多选回调 |
|
checkCourse (row) { |
|
const { check } = row |
|
const { checked } = this |
|
row.chapters.forEach(e => { |
|
e.check = check |
|
e.subsections.forEach(n => { |
|
n.check = check |
|
const cur = checked.findIndex(m => m.id === n.id) |
|
if (check) { |
|
if (cur === -1) { |
|
const section = _.cloneDeep(n) |
|
section.check = false |
|
checked.push(section) |
|
} |
|
} else { |
|
cur !== -1 && checked.splice(cur, 1) |
|
} |
|
}) |
|
}) |
|
}, |
|
// 章节多选回调 |
|
checkChapter (row, course) { |
|
const { check } = row |
|
const { checked } = this |
|
row.subsections.forEach(n => { |
|
n.check = check |
|
const cur = checked.findIndex(m => m.id === n.id) |
|
if (check) { |
|
if (cur === -1) { |
|
const section = _.cloneDeep(n) |
|
section.check = false |
|
checked.push(section) |
|
} |
|
} else { |
|
cur !== -1 && checked.splice(cur, 1) |
|
} |
|
}) |
|
course.check = course.chapters.every(e => e.check) |
|
}, |
|
// 小节多选回调 |
|
async checkSection (row, chapter) { |
|
const { check } = row |
|
const { checked } = this |
|
const cur = checked.findIndex(m => m.id === row.id) |
|
if (check) { |
|
if (cur === -1) { |
|
const section = _.cloneDeep(row) |
|
section.check = false |
|
this.checked.push(section) |
|
} |
|
} else { |
|
cur !== -1 && this.checked.splice(cur, 1) |
|
} |
|
chapter.check = chapter.subsections.every(e => e.check) |
|
}, |
|
|
|
// 批量移除 |
|
async batchDelChecked (val) { |
|
try { |
|
const checked = this.checked.filter(e => e.check) |
|
if (checked.length) { |
|
checked.map(e => { |
|
const cur = this.allSections.find(n => n.id === e.id) |
|
if (cur) { |
|
cur.check = false |
|
} |
|
}) |
|
this.checked = this.checked.filter(e => !e.check) |
|
} else { |
|
Util.warningMsg('请选择数据') |
|
} |
|
} catch (e) { } |
|
}, |
|
// 已选单个删除 |
|
async delChecked (item) { |
|
try { |
|
const cur = this.allSections.find(e => e.id === item.id) |
|
if (cur) cur.check = false |
|
this.checked.splice(this.checked.findIndex(e => e.id === item.id), 1) |
|
} catch (e) { } |
|
}, |
|
// 提交 |
|
async submit () { |
|
try { |
|
if (this.submiting) return false |
|
this.submiting = true |
|
const { checked } = this |
|
const { chapterId, id } = this.$parent |
|
const result = checked.map(e => { |
|
return { |
|
chapterId, |
|
cid: id, |
|
resourceId: e.id, |
|
type: e.cid ? 0 : 1, |
|
} |
|
}) |
|
const res = await this.$post(this.api.combinationResource, result) |
|
this.sourceVisible = false |
|
this.$parent.getData() |
|
this.submiting = false |
|
} catch (e) { |
|
this.submiting = false |
|
} |
|
}, |
|
// 弹框关闭回调 |
|
closeDia () { |
|
this.$emit('update:visible', false) |
|
} |
|
} |
|
}; |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
/deep/.source-dia { |
|
.el-drawer__header { |
|
padding-bottom: 20px; |
|
margin-bottom: 0; |
|
border-bottom: 1px solid #eee; |
|
} |
|
|
|
.overflow { |
|
display: flex; |
|
} |
|
|
|
.btns { |
|
position: absolute; |
|
bottom: 0; |
|
left: 0; |
|
width: 100%; |
|
padding: 14px 0; |
|
text-align: center; |
|
background-color: #fff; |
|
box-shadow: 4px -2px 6px 0px rgba(198, 198, 198, 0.3500); |
|
} |
|
|
|
|
|
.empty { |
|
display: flex; |
|
flex-direction: column; |
|
justify-content: center; |
|
align-items: center; |
|
height: 100%; |
|
font-size: 14px; |
|
text-align: center; |
|
color: #a3a3a3; |
|
} |
|
|
|
.left { |
|
width: 700px; |
|
padding: 0 20px; |
|
padding: 15px; |
|
border-right: 1px solid #eee; |
|
box-sizing: border-box; |
|
|
|
.course { |
|
height: calc(100vh - 263px); |
|
overflow: auto; |
|
|
|
.item { |
|
padding: 10px; |
|
margin-bottom: 10px; |
|
background-color: #f9f9f9; |
|
} |
|
} |
|
|
|
.line { |
|
display: flex; |
|
align-items: center; |
|
} |
|
|
|
.arrow { |
|
font-size: 16px; |
|
color: #9f9f9f; |
|
cursor: pointer; |
|
transition: .3s; |
|
|
|
&.active { |
|
transform: rotate(90deg); |
|
} |
|
} |
|
|
|
.check { |
|
margin: 0 10px; |
|
} |
|
|
|
.cover { |
|
width: 100px; |
|
max-height: 80px; |
|
margin-right: 15px; |
|
} |
|
|
|
.course-name { |
|
font-size: 14px; |
|
color: #333; |
|
} |
|
|
|
.chapters { |
|
padding-left: 21px; |
|
margin-top: 10px; |
|
|
|
.line { |
|
margin-bottom: 10px; |
|
} |
|
} |
|
|
|
.chapter-name { |
|
font-size: 13px; |
|
color: #ccc; |
|
} |
|
|
|
.sections { |
|
padding-left: 26px; |
|
} |
|
} |
|
|
|
.right { |
|
flex: 1; |
|
padding: 15px; |
|
|
|
.lines { |
|
height: calc(100vh - 228px); |
|
padding-right: 10px; |
|
margin-top: 10px; |
|
overflow: auto; |
|
} |
|
|
|
.line { |
|
display: flex; |
|
padding: 5px 0; |
|
color: #333; |
|
} |
|
|
|
.serial { |
|
width: 32px; |
|
margin: 0 12px; |
|
text-align: center; |
|
white-space: nowrap; |
|
} |
|
|
|
.check-left { |
|
display: inline-flex; |
|
align-items: center; |
|
} |
|
|
|
.checked-name { |
|
width: 360px; |
|
margin-right: 20px; |
|
} |
|
|
|
.action-icon { |
|
font-size: 14px; |
|
cursor: pointer; |
|
} |
|
} |
|
} |
|
</style> |