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.
1460 lines
45 KiB
1460 lines
45 KiB
<template> |
|
<div style="padding: 24px"> |
|
<el-card shadow="hover" class="m-b-20"> |
|
<div class="flex-between"> |
|
<el-page-header @back="back" :content="curriculumName || courseName"></el-page-header> |
|
</div> |
|
</el-card> |
|
<el-card class="source-card" shadow="hover" style="background: none;"> |
|
<div class="flex"> |
|
<div class="cover" :class="{ 'is-word': showMask1 }"> |
|
<!--实验台不显示课程封面--> |
|
<img v-if="coverUrl" :src="coverUrl" alt="" width="100%" height="100%"> |
|
<template v-else-if="iframeSrc"> |
|
<iframe class="inner fileIframe" id="fileIframe" :src="iframeSrc" frameborder="0"></iframe> |
|
<template v-if="showMask"> |
|
<div class="mask" style="top: 0;width:100%;height: 48px;"></div> |
|
<div class="mask" style="top: 53px;width:100%;height: 30px;"></div> |
|
<div class="mask" style="bottom: 0;right: 40px;width:195px;height: 22px;background-color: #444;"></div> |
|
</template> |
|
<template v-if="showMask1"> |
|
<div class="word-mask" style="height: 40px;"></div> |
|
<div class="word-mask2" style="top: 55px;left: 28%;width: 44%;height: calc(100% - 80px);"></div> |
|
</template> |
|
<template v-if="showMask2"> |
|
<div class="excel-mask1" style="height: 48px;"></div> |
|
</template> |
|
</template> |
|
<div class="pdf inner" v-else-if="pdfSrc"> |
|
<img class="full" src="@/assets/img/screen/full.png" alt="" @click="fullScreen"> |
|
<p class="arrow"> |
|
<span @click="changePdfPage(0)" class="turn el-icon-arrow-left" |
|
:class="{ grey: currentPage == 1 }"></span> |
|
{{ currentPage }} / {{ pageCount }} |
|
<span @click="changePdfPage(1)" class="turn el-icon-arrow-right" |
|
:class="{ grey: currentPage == pageCount }"></span> |
|
</p> |
|
<div style='color:#393A3D;height: 30px;background: #393A3D;'></div> |
|
<pdf class="pdf-wrap" :src="pdfSrc" :page="currentPage" @num-pages="pageCount = $event" |
|
@page-loaded="currentPage = $event" @loaded="loadPdfHandler"> |
|
</pdf> |
|
</div> |
|
<div class="inner" v-else-if="playAuth"> |
|
<div class="video_wid" id="player"></div> |
|
</div> |
|
<div class="inner" v-else-if="videoSrc"> |
|
<video class="video" :key="videoSrc" width="100%" height="100%" autoplay controls> |
|
<source :src="videoSrc" type="video/mp4"> |
|
您的浏览器不支持 video 标签。 |
|
</video> |
|
</div> |
|
</div> |
|
<div class="catalog"> |
|
<div v-if="mallId" class="m-b-20"> |
|
<el-button v-if="mallId && !overdue" class="entry" type="primary" size="small" |
|
@click="showBuy">续费</el-button> |
|
<el-button v-if="practiceTheoreticalPaper" class="entry" type="primary" @click="entry(1)">进入理论</el-button> |
|
<el-button v-if="practicePracticeProject" class="entry" type="primary" @click="entry(0)">进入实训</el-button> |
|
</div> |
|
<div class="list"> |
|
<h4 class="title">{{ curriculumName || courseName }}</h4> |
|
<div> |
|
<h6 class="pro-title">当前教学进度</h6> |
|
<el-progress :stroke-width="12" :percentage="schedule" :format="percentFormat" |
|
:text-color="'#fff'"></el-progress> |
|
</div> |
|
<div class="types"> |
|
<div :class="['item', { active: type === 1 }]" @click="typeChange(1)"> |
|
<i class="icon el-icon-notebook-2"></i> 目录 |
|
</div> |
|
<div :class="['item', { active: type === 2 }]" @click="typeChange(2)"> |
|
<i class="icon el-icon-timer"></i> 教学进度 |
|
</div> |
|
</div> |
|
<div class="chapters"> |
|
<template v-if="type === 1"> |
|
<template v-if="chapterList.length"> |
|
<div class="chapter" v-for="(item, i) in chapterList" :key="i"> |
|
<div class="chapterName">{{ item.name }}</div> |
|
<div class="section" v-if="item.subsectionList.length"> |
|
<p class="sectionName" :class="{ active: curLink === `${item.name}${section.name}` }" |
|
v-for="(section, i) in item.subsectionList" :key="i" @click="preview(section, item.name)"> |
|
<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=""> |
|
{{ section.name }} |
|
</p> |
|
</div> |
|
</div> |
|
</template> |
|
</template> |
|
<div v-else class="section"> |
|
<p class="sectionName" v-for="(item, i) in progressList" :key="i" :title="item.projectName"> |
|
{{ i + 1 }}. |
|
{{ item.projectName }} |
|
<i :class="['icon', item.whetherToStudyOrNot ? 'el-icon-success' : 'circle']" |
|
@click.stop="studySection(item)"></i> |
|
</p> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</el-card> |
|
|
|
<div class="tabs"> |
|
<a class="item" v-for="(item, i) in tabs" :key="i" :class="{ active: item.id == active }" |
|
@click="tabChange(item)">{{ |
|
item.name }}</a> |
|
</div> |
|
<div class="flex"> |
|
<div class="tab-content"> |
|
<template v-if="active === 1"> |
|
<div class="page"> |
|
<div class="des" v-html="briefIntroduction"></div> |
|
</div> |
|
</template> |
|
<template v-if="active === 2"> |
|
<div class="page"> |
|
<template v-if="showNoteAdd || !notes.length"> |
|
<el-form class="form" ref="form" label-width="120px" center> |
|
<el-form-item class="required" label="笔记标题"> |
|
<el-input placeholder="请输入笔记标题" v-model="noteForm.noteName" maxlength="30" |
|
style="width: 400px"></el-input> |
|
</el-form-item> |
|
<el-form-item class="required" label="笔记内容"> |
|
<Editor api-key='rnk6zw9v267xqz7pf98twt1vmrvltmd436je7a642pckltda' v-model="noteForm.noteContent" |
|
:init="editorConfig" /> |
|
</el-form-item> |
|
</el-form> |
|
<div class="text-right"> |
|
<el-button v-if="notes.length" @click="showNoteAdd = false">取消</el-button> |
|
<el-button type="primary" @click="submitNote">保存</el-button> |
|
</div> |
|
</template> |
|
<template v-else> |
|
<div class="tool"> |
|
<ul class="filter"> |
|
<li> |
|
<label>搜索:</label> |
|
<el-input placeholder="请输入标题" v-model="noteKeyword" clearable></el-input> |
|
</li> |
|
</ul> |
|
<div> |
|
<el-button type="primary" @click="addNote">新增笔记</el-button> |
|
</div> |
|
</div> |
|
<el-timeline class="timeline"> |
|
<el-timeline-item placement="top" v-for="(item, i) in notes" :key="i"> |
|
<p class="sign">{{ item.createTime }}</p> |
|
<div class="ver"> |
|
{{ item.noteName }} |
|
<span class="action"> |
|
<i class="el-icon-edit-outline" @click="editNote(item)"></i> |
|
<i class="el-icon-delete" @click="delNote(item)"></i> |
|
</span> |
|
</div> |
|
<div class="des" v-html="item.noteContent"></div> |
|
</el-timeline-item> |
|
</el-timeline> |
|
</template> |
|
</div> |
|
</template> |
|
<template v-if="active === 4"> |
|
<div class="page"> |
|
<quill ref="quill" :border="true" v-model="comment" :height="150" :toTop="false" /> |
|
<div class="m-t-10 text-right"> |
|
<el-button type="primary" size="mini" @click="submitComment(0)">提交</el-button> |
|
</div> |
|
<ul class="msg"> |
|
<li v-for="(item, i) in comments" :key="i" :id="'comment' + item.commentId"> |
|
<div class="li-wrap"> |
|
<img :src="item.createUserAvatars" alt="" class="avatar"> |
|
<div class="texts"> |
|
<h6> |
|
<span class="name">{{ item.createUsername }}</span> |
|
发表于 {{ item.createTime }} |
|
</h6> |
|
<div class="m-t-8" v-html="item.content"></div> |
|
</div> |
|
<div class="action"> |
|
<i class="icon el-icon-chat-dot-square" @click="showReplay(item)"></i> |
|
<!-- 当前用户是管理员 || 该条评论是学生发的(没有createRoleName即是学生) || 当前用户的account==该条评论的创建人accountId --> |
|
<i v-if="(item.currentRoleName && item.currentRoleName.includes('管理员')) || !item.createRoleName || item.currentAccountId == item.createAccountId" |
|
class="icon el-icon-delete" @click="delComment(item)"></i> |
|
|
|
<!-- <div class="like-wrap" |
|
@click="like(item)"> |
|
<img v-if="item.isLike" |
|
class="icon" |
|
src="@/assets/img/like-up.png" |
|
alt=""> |
|
<img v-else |
|
class="icon" |
|
src="@/assets/img/like.png" |
|
alt=""> |
|
{{ item.likeCount || '' }} |
|
</div> --> |
|
</div> |
|
</div> |
|
<div class="reply" v-if="item.showReply"> |
|
<quill :border="true" v-model="item.replyContent" :toTop="false" :height="150" /> |
|
<div class="m-v-10 text-right"> |
|
<el-button type="primary" size="mini" @click="submitComment(item)">提交</el-button> |
|
</div> |
|
</div> |
|
<ul class="msg children" v-if="item.showChildren"> |
|
<li v-for="(reply, i) in item.children" :key="i" :id="'comment' + reply.commentId"> |
|
<div class="li-wrap"> |
|
<img class="avatar" :src="reply.createUserAvatars" alt=""> |
|
<div class="texts"> |
|
<div class="name">{{ reply.createUsername }}</div> |
|
<div class="flex m-v-8"> |
|
<template v-if="reply.level !== 2"> |
|
回复 |
|
<span class="reply-name">@{{ reply.replyUsername }}:</span> |
|
</template> |
|
<div v-html="reply.content"></div> |
|
</div> |
|
<div class="date">{{ reply.createTime }}</div> |
|
</div> |
|
<div class="action"> |
|
<i class="icon el-icon-chat-dot-square" @click="showReplay(reply)"></i> |
|
<!-- 当前用户是管理员 || 该条评论是学生发的(没有createRoleName即是学生) || 当前用户的account==该条评论的创建人accountId --> |
|
<i v-if="(reply.currentRoleName && reply.currentRoleName.includes('管理员')) || !reply.createRoleName || reply.currentAccountId == reply.createAccountId" |
|
class="icon el-icon-delete" @click="delComment(reply)"></i> |
|
<!-- <div class="like-wrap" |
|
@click="like(item, reply)"> |
|
<img v-if="reply.isLike" |
|
class="icon" |
|
src="@/assets/img/like-up.png" |
|
alt=""> |
|
<img v-else |
|
class="icon" |
|
src="@/assets/img/like.png" |
|
alt=""> |
|
{{ reply.likeCount || '' }} |
|
</div> --> |
|
</div> |
|
</div> |
|
<div class="reply" v-if="reply.showReply"> |
|
<quill :border="true" v-model="reply.replyContent" :toTop="false" :height="150" /> |
|
<div class="p-b-10 m-t-10 text-right"> |
|
<el-button type="primary" size="mini" @click="submitComment(item, reply)">提交</el-button> |
|
</div> |
|
</div> |
|
</li> |
|
</ul> |
|
<div v-if="item.children" class="toggle"><span @click="item.showChildren = !item.showChildren">{{ |
|
item.showChildren ? |
|
'收起所有回复' : `查看所有${item.children.length}条回复` }} <i class="el-icon-arrow-down"></i></span></div> |
|
</li> |
|
</ul> |
|
</div> |
|
</template> |
|
</div> |
|
<div class="rank"> |
|
<h6 class="title">练习成绩排行</h6> |
|
<el-select style="width: 100%" v-model="archProject" placeholder="请选择" @change="getMaximumScore"> |
|
<el-option v-for="(item, i) in progressList" :key="i" :label="item.projectName" |
|
:value="item.uuid"></el-option> |
|
</el-select> |
|
<div v-if="maximumScores.length" class="arches"> |
|
<div v-for="(item, i) in maximumScores" :key="i" class="line"> |
|
<div> |
|
<img :src="item.userAvatars" alt="" class="avatar"> |
|
<span class="name">{{ item.userName }}</span> |
|
</div> |
|
<span class="point">{{ item.highestScore }}分</span> |
|
</div> |
|
</div> |
|
<p v-else class="none">暂无数据</p> |
|
</div> |
|
</div> |
|
|
|
<el-dialog title="请选择项目" :visible.sync="projectVisible" width="828px" custom-class="project-dia" |
|
:close-on-click-modal="false"> |
|
<ul class="projects" v-loading="loading"> |
|
<template v-if="isTheory"> |
|
<li v-for="(item, i) in papers" :key="i" :class="{ active: curPaper == item.paperId }" |
|
@click="selectPaper(item)"> |
|
<img src="@/assets/img/project.png" alt=""> |
|
<span>{{ i + 1 }}. {{ item.paperName }}</span> |
|
</li> |
|
</template> |
|
<template v-else> |
|
<li v-for="(item, i) in projects" :key="i" :class="{ active: curProject == item.projectId }" |
|
@click="selectProject(item)"> |
|
<img src="@/assets/img/project.png" alt=""> |
|
<span>{{ i + 1 }}. {{ item.projectName }}</span> |
|
</li> |
|
</template> |
|
</ul> |
|
|
|
<span slot="footer" class="dialog-footer"> |
|
<el-button size="small" @click="projectVisible = false">取 消</el-button> |
|
<el-button size="small" type="primary" @click="toSub">确 定</el-button> |
|
</span> |
|
</el-dialog> |
|
|
|
<!-- 购买弹框 --> |
|
<el-dialog title="温馨提示" :visible.sync="buyVisible" width="420px" center :close-on-click-modal="false"> |
|
<div class="buy"> |
|
<p class="tips">该课程订阅期限已到期,若需要续费请扫码添加客服咨询</p> |
|
<img src="@/assets/img/wechat-code.jpeg" alt=""> |
|
</div> |
|
</el-dialog> |
|
|
|
<pdfDia :key="pdfVisible" :visible.sync="pdfVisible" :src.sync="pdfSrc" /> |
|
</div> |
|
</template> |
|
|
|
<script> |
|
import Util from "@/libs/util"; |
|
import Setting from "@/setting"; |
|
import { mapState } from "vuex"; |
|
import pdf from "vue-pdf"; |
|
import quill from "@/components/quill"; |
|
import pdfDia from '@/components/pdf' |
|
import Editor from '@tinymce/tinymce-vue' |
|
import editorConfig from '@/components/editor' |
|
export default { |
|
components: { pdf, pdfDia, quill, Editor }, |
|
data () { |
|
return { |
|
editorConfig, |
|
mallId: '', |
|
courseId: '', |
|
curriculumName: '', |
|
commentId: '', // 从右上角消息通知点进来用来定位评论的 |
|
notifyId: '', |
|
chapter: this.$route.query.chapter, |
|
section: this.$route.query.section, |
|
fromAdmin: this.$route.query.admin, // 是否从产品中心or实验台进来 |
|
type: 1, |
|
chapterList: [], // 章节列表 |
|
progressList: [], |
|
coverUrl: "", // 课程封面 |
|
courseName: "", // 课程名称 |
|
briefIntroduction: "", // 课程简介 |
|
teachingObjectives: "", // 课程目标 |
|
assessmentList: "", // 考核列表 |
|
systemIds: '', |
|
practicePracticeProject: 0, |
|
practiceTheoreticalPaper: 0, |
|
curLink: "", // 当前选中 |
|
playAuth: "", |
|
player: null, |
|
previewImg: "", |
|
iframeSrc: "", |
|
isWord: false, |
|
isPPT: false, |
|
isExcel: false, |
|
showMask: false, |
|
showMask1: false, |
|
showMask2: false, |
|
closePosi: { |
|
top: "80px" |
|
}, |
|
pdfVisible: false, |
|
pdfSrc: "", |
|
currentPage: 0, // pdf文件页码 |
|
pageCount: 0, // pdf文件总页数 |
|
fileType: "pdf", // 文件类型 |
|
videoSrc: '', |
|
desShrink: false, |
|
projectVisible: false, |
|
isTheory: 0, |
|
projects: [], |
|
papers: [], |
|
loading: false, |
|
curPaper: '', |
|
curProject: '', |
|
overdue: 0, //是否过期 |
|
buyVisible: false, |
|
active: 1, |
|
tabs: [ |
|
{ |
|
id: 1, |
|
name: '课程介绍' |
|
}, |
|
{ |
|
id: 2, |
|
name: '课程笔记' |
|
}, |
|
// { |
|
// id: 3, |
|
// name: '全国排行榜' |
|
// }, |
|
{ |
|
id: 4, |
|
name: '教学互动' |
|
} |
|
], |
|
schedule: 0, |
|
plan: '', |
|
noteKeyword: '', |
|
searchTimer: null, |
|
notes: [], |
|
showNoteAdd: false, |
|
noteContent: '', |
|
noteForm: { |
|
cid: +this.$route.query.courseId, |
|
noteContent: '', |
|
noteName: '', |
|
}, |
|
comments: [], |
|
comment: '', |
|
deleteIdentity: false, |
|
archProject: '', |
|
curReplyId: '', |
|
maximumScores: [], |
|
third: '', |
|
}; |
|
}, |
|
computed: { |
|
...mapState("user", [ |
|
"userId", "studentId", "roleId", "userName" |
|
]) |
|
}, |
|
watch: { |
|
'$route': { |
|
handler () { |
|
this.mallId = +this.$route.query.mallId || '' |
|
this.courseId = +this.$route.query.courseId |
|
this.curriculumName = this.$route.query.curriculumName |
|
this.commentId = this.$route.query.commentId // 从右上角消息通知点进来用来定位评论的 |
|
this.notifyId = this.$route.query.notifyId |
|
this.init() |
|
}, |
|
immediate: true |
|
}, |
|
noteKeyword: function (val) { |
|
clearTimeout(this.searchTimer); |
|
this.searchTimer = setTimeout(() => { |
|
this.getNote(); |
|
}, 500); |
|
} |
|
}, |
|
mounted () { |
|
|
|
}, |
|
methods: { |
|
back () { |
|
const { query } = this.$route |
|
this.fromAdmin ? |
|
this.$router.back() : |
|
(this.mallId || query.typeActive) ? this.$router.push(`/station?keyword=${query.keyword || ''}&active=${query.active || ''}&typeActive=${query.typeActive || 0}&page=${query.page || 1}`) : this.$router.back() |
|
}, |
|
init () { |
|
this.insertScript() |
|
this.getData() |
|
this.addRecord() |
|
}, |
|
async getData () { |
|
if (this.courseId) { |
|
let { data } = await this.$post(`${this.api.curriculumDetail}?cid=${this.courseId}&mallId=${this.mallId}`); |
|
this.courseName = data.curriculumName; |
|
// this.coverUrl = data.coverUrl; |
|
this.briefIntroduction = data.briefIntroduction; |
|
this.teachingObjectives = data.teachingObjectives; |
|
this.assessmentList = data.assessmentConfig; |
|
this.systemIds = data.systemIds |
|
this.practicePracticeProject = data.practicePracticeProject |
|
this.practiceTheoreticalPaper = data.practiceTheoreticalPaper |
|
this.queryProject() |
|
} |
|
this.getStatus() |
|
}, |
|
// 记录最近使用 |
|
async addRecord () { |
|
await this.$post(`${this.api.recordRecentUsage}?mallId=${this.mallId}&cid=${this.courseId}`) |
|
}, |
|
// 查询是否过期 |
|
async getStatus () { |
|
if (this.mallId) { |
|
const { isRenew } = await this.$get(this.api.whetherToRenewTheFee, { |
|
mallId: this.mallId |
|
}) |
|
// 1正常显示资源,0显示续费,-1试用 |
|
this.overdue = isRenew |
|
} |
|
this.getChapter() |
|
this.getProgress() |
|
}, |
|
// 获取章节小节 |
|
async getChapter () { |
|
if (this.courseId) { |
|
const res = await this.$get(this.api.curriculumChapter + '/' + this.courseId) |
|
this.chapterList = res.chapterList; |
|
const chapter = this.chapter === undefined ? 0 : +this.chapter |
|
const section = this.section === undefined ? 0 : +this.section |
|
const clist = this.chapterList[chapter] |
|
if (this.chapterList.length && clist.subsectionList && clist.subsectionList.length && !this.commentId) { |
|
this.preview(clist.subsectionList[section], clist.name, 1); |
|
} |
|
} |
|
}, |
|
// 获取学习进度 |
|
async getProgress () { |
|
if (this.courseId) { |
|
let res = await this.$post(`${this.api.courseLearningProgress}?courseId=${this.courseId}&systemId=${this.systemIds}&mallId=${this.mallId}`); |
|
res.list.forEach(e => { |
|
e.uuid = e.projectId || e.paperId |
|
}) |
|
this.progressList = res.list |
|
if (res.list.length) this.archProject = res.list[0].uuid |
|
this.maximumScores.length || this.getMaximumScore() |
|
this.plan = res.plan |
|
this.schedule = +(res.schedule.replace('%', '')) |
|
} |
|
}, |
|
// 获取最高分列表 |
|
async getMaximumScore () { |
|
const item = this.progressList.find(e => e.uuid === this.archProject) |
|
let { message } = await this.$post(`${this.api.maximumPracticeScoreList}?projectId=${item.projectId || ''}&paperId=${item.paperId || ''}&pageNum=1&pageSize=1000&mallId=${this.mallId}&cid=${this.courseId}`); |
|
const list = message.records |
|
list.forEach(e => { |
|
if (!e.userAvatars) e.userAvatars = 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png' |
|
}) |
|
this.maximumScores = list |
|
}, |
|
// 进度数字自定义 |
|
percentFormat (val) { |
|
return this.plan |
|
}, |
|
// 目录和进度切换 |
|
typeChange (id) { |
|
this.getChapter() |
|
this.type = id |
|
}, |
|
// 获取课程笔记 |
|
getNote () { |
|
this.$get(this.api.curriculumNoteList, { |
|
cid: this.courseId, |
|
search: this.noteKeyword |
|
}).then(res => { |
|
this.notes = res.curriculumNotes |
|
}).catch(res => { }) |
|
}, |
|
// 新增笔记 |
|
addNote () { |
|
this.noteForm = { |
|
cid: this.courseId, |
|
noteContent: '', |
|
noteName: '', |
|
} |
|
this.showNoteAdd = true |
|
}, |
|
// 保存笔记 |
|
submitNote () { |
|
const form = this.noteForm |
|
if (!form.noteName) return Util.errorMsg('请输入笔记标题') |
|
if (!form.noteContent) return Util.errorMsg('请输入笔记内容') |
|
this.$post(this.api[form.noteId ? 'updateNote' : 'addNote'], form).then(res => { |
|
this.getNote() |
|
Util.successMsg(form.noteId ? '修改成功' : '添加成功') |
|
this.showNoteAdd = false |
|
this.noteForm = { |
|
cid: this.courseId, |
|
noteContent: '', |
|
noteName: '', |
|
} |
|
}).catch(res => { }) |
|
}, |
|
// 删除笔记 |
|
delNote (row) { |
|
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", { |
|
type: "warning" |
|
}).then(() => { |
|
this.$post(`${this.api.deleteNotes}?noteId=${row.noteId}`).then(res => { |
|
Util.successMsg("删除成功"); |
|
this.getNote(); |
|
}).catch(res => { }) |
|
}).catch(() => { }) |
|
}, |
|
// 编辑笔记 |
|
editNote (row) { |
|
this.noteForm = JSON.parse(JSON.stringify(row)) |
|
this.showNoteAdd = true |
|
}, |
|
|
|
|
|
// 教学互动列表 |
|
getComment () { |
|
this.$get(this.api.commentTreeList, { |
|
mallId: this.mallId, |
|
}).then(res => { |
|
this.deleteIdentity = res.deleteIdentity |
|
const list = res.rootComments |
|
this.handleComments(list) |
|
this.comments = list |
|
this.$nextTick(async () => { |
|
if (this.curReplyId) { |
|
const el = document.querySelector('#comment' + this.curReplyId) |
|
el && el.scrollIntoView(false) |
|
} |
|
if (this.commentId) { |
|
this.active = 4 |
|
const el = document.getElementById('comment' + this.commentId) |
|
el && el.scrollIntoView(false) |
|
this.commentId = '' |
|
} |
|
}) |
|
}).catch(res => { }) |
|
}, |
|
// 递归处理评论参数 |
|
handleComments (list, parent = {}) { |
|
list.forEach(e => { |
|
if (!e.createUserAvatars) e.createUserAvatars = 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png' |
|
e.showChildren = false |
|
if (e.commentId == this.commentId) parent.showChildren = true |
|
if (e.commentId == this.curReplyId) e.showChildren = true |
|
e.showReply = false |
|
e.replyContent = '' |
|
if (e.children && e.children.length && parent.children) { |
|
e.children.forEach(n => n.showReplyName = true) |
|
parent.children.push(...e.children) |
|
} |
|
e.children && this.handleComments(e.children, parent.commentId ? parent : e) |
|
}) |
|
}, |
|
// 回复 |
|
showReplay (row) { |
|
row.showReply = !row.showReply |
|
}, |
|
// 删除评论 |
|
delComment (row) { |
|
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", { |
|
type: "warning" |
|
}).then(() => { |
|
this.$post(`${this.api.deleteAComment}?commentId=${row.commentId}`).then(res => { |
|
Util.successMsg("删除成功"); |
|
this.getComment(); |
|
}).catch(res => { }) |
|
}).catch(() => { }) |
|
}, |
|
// 保存评论 |
|
submitComment (row, reply) { |
|
const content = reply ? reply.replyContent : row ? row.replyContent : this.comment |
|
if (!content) return Util.errorMsg('请输入内容!') |
|
this.$post(this.api.addCommentStation, { |
|
mallId: this.mallId, |
|
content, |
|
// pid: reply ? reply.commentId : row ? row.commentId : 0, |
|
pid: row ? row.commentId : 0, |
|
replyAccountId: reply ? reply.createAccountId : row.createAccountId || '', |
|
status: row ? 2 : 1, |
|
replyCommentId: reply ? reply.commentId : row ? row.commentId : '' |
|
}).then(res => { |
|
this.comment = '' |
|
this.curReplyId = row ? row.commentId : '' |
|
this.getComment() |
|
}).catch(res => { }) |
|
}, |
|
// 评论点赞 |
|
like (row) { |
|
this.$post(`${this.api[row.isLike ? 'unlike' : 'commentAndLike']}?commentId=${row.commentId}`).then(res => { |
|
row.isLike = row.isLike ? 0 : 1 |
|
}).catch(res => { }) |
|
}, |
|
|
|
// 插入阿里云播放器脚本 |
|
insertScript () { |
|
const linkTag = document.createElement("link"); |
|
linkTag.id = "aliplayerLink"; |
|
linkTag.rel = "stylesheet"; |
|
linkTag.href = "https://g.alicdn.com/de/prismplayer/2.8.2/skins/default/aliplayer-min.css"; |
|
document.body.appendChild(linkTag); |
|
|
|
const scriptTag = document.createElement("script"); |
|
scriptTag.id = "aliplayerScript"; |
|
scriptTag.type = "text/javascript"; |
|
scriptTag.src = "https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js"; |
|
document.body.appendChild(scriptTag); |
|
this.$once("hook:beforeDestroy", function () { |
|
document.body.removeChild(document.querySelector("#aliplayerLink")); |
|
document.body.removeChild(document.querySelector("#aliplayerScript")); |
|
}); |
|
}, |
|
// 显示咨询弹框 |
|
showBuy () { |
|
this.buyVisible = true |
|
}, |
|
transferType (ext) { |
|
if ("jpg,jpeg,png,gif,svg,psd".includes(ext)) return "图片"; |
|
if ("mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv".includes(ext)) return "视频"; |
|
return ext; |
|
}, |
|
// tab切换 |
|
tabChange ({ id }) { |
|
this.active = id |
|
id == 2 && this.getNote() |
|
id == 4 && this.getComment() |
|
}, |
|
// 勾选/取消勾选学习进度 |
|
studySection (item) { |
|
item.whetherToStudyOrNot ? |
|
this.$post(`${this.api.deleteLearningProgress}?id=${item.learningProgressId}`).then(res => { |
|
this.getProgress() |
|
}).catch(res => { }) : |
|
this.$post(this.api.saveLearningProgress, { |
|
cid: this.courseId, |
|
projectId: item.projectId || '', |
|
paperId: item.paperId || '', |
|
}).then(res => { |
|
this.getProgress() |
|
}).catch(res => { }) |
|
}, |
|
preview (row, chapterName, showDia = 0) { |
|
// 如果没过期,则正常预览,否则显示购买弹框 |
|
if (this.overdue === 1 || showDia) { |
|
this.curLink = `${chapterName}${row.name}`; // 章节名称+小节名称,小节名称有重复的情况,如果只用小节名称判断,会有同时选中多个的情况 |
|
this.playAuth = '' |
|
this.coverUrl = '' |
|
this.pdfSrc = '' |
|
this.iframeSrc = '' |
|
this.videoSrc = '' |
|
this.isPPT = false; |
|
this.isWord = false; |
|
this.isExcel = false; |
|
if (this.transferType(row.fileType) == "视频") { |
|
// 阿里云视频点播 |
|
if (row.fileId) { |
|
this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => { |
|
this.playAuth = res.playAuth; |
|
// 如果已经产生了实例,则销毁重新创建,不然播放器会播放上一个视频 |
|
if (this.player) { |
|
this.player.dispose() |
|
this.player = null |
|
} |
|
this.$nextTick(() => { |
|
if (this.player) { |
|
this.player.replayByVidAndPlayAuth(row.fileId, this.playAuth); |
|
} else { |
|
this.player = new Aliplayer({ |
|
id: "player", |
|
width: "100%", |
|
autoplay: false, |
|
vid: row.fileId, |
|
playauth: this.playAuth, |
|
encryptType: 1 //当播放私有加密流时需要设置。 |
|
}); |
|
} |
|
}); |
|
}).catch(res => { }); |
|
} else { |
|
this.videoSrc = row.fileUrl |
|
} |
|
} else if (this.transferType(row.fileType) == "图片") { |
|
this.coverUrl = row.fileUrl; |
|
} else if (row.fileType == "pdf") { |
|
this.pdfSrc = row.fileUrl; |
|
} else { |
|
this.$get(`${this.api.curriculumGetSubsection}/${row.id}`).then(res => { |
|
if (row.fileType == "pptx") this.isPPT = true |
|
if (row.fileType == "doc" || row.fileType == "docx") this.isWord = true |
|
if (row.fileType == "xls" || row.fileType == "xlsx") this.isExcel = true |
|
if (this.isPPT) { |
|
this.showMask = true; |
|
} else { |
|
this.showMask = false; |
|
} |
|
if (this.isWord) { |
|
this.showMask1 = true; |
|
} else { |
|
this.showMask1 = false; |
|
} |
|
if (this.isExcel) { |
|
this.showMask2 = true; |
|
} else { |
|
this.showMask2 = false; |
|
} |
|
this.iframeSrc = res.previewUrl; |
|
}).catch(err => { }); |
|
} |
|
} else { |
|
this.showBuy() |
|
} |
|
}, |
|
closePlayer () { |
|
this.playAuth = '' |
|
this.player.pause(); |
|
}, |
|
closeIframe () { |
|
this.iframeSrc = '' |
|
this.showMask = false; |
|
this.showMask1 = false; |
|
}, |
|
closePdf () { |
|
this.pdfSrc = '' |
|
this.currentPage = 1; |
|
}, |
|
changePdfPage (val) { |
|
if (val === 0 && this.currentPage > 1) { |
|
this.currentPage--; |
|
} |
|
if (val === 1 && this.currentPage < this.pageCount) { |
|
this.currentPage++; |
|
} |
|
}, |
|
loadPdfHandler (e) { |
|
this.currentPage = 1; |
|
}, |
|
// pdf全屏 |
|
fullScreen () { |
|
this.pdfVisible = true |
|
}, |
|
// 选择试卷 |
|
selectPaper (item) { |
|
this.curPaper = item.paperId |
|
}, |
|
// 选择项目 |
|
selectProject (item) { |
|
this.curProject = item.projectId |
|
}, |
|
// 展示选择项目弹框 |
|
showProjectDia () { |
|
this.projectVisible = true |
|
}, |
|
// 查询项目 |
|
async queryProject () { |
|
if (this.mallId) { |
|
try { |
|
this.loading = true |
|
const res = await this.$get(this.api.getProjectBySystemId, { |
|
systemId: this.systemIds, |
|
cId: this.courseId, // 课程id |
|
mallId: this.mallId, |
|
permissions: 0 // 0: 练习,1: 考核 |
|
}) |
|
this.projects = res.projects // 实训项目 |
|
this.papers = res.exercisePaperList // 理论试卷 |
|
} finally { |
|
this.loading = false |
|
} |
|
} |
|
}, |
|
// 进入实验 |
|
entryProject (projectId = '', paperId = '') { |
|
this.$confirm(`是否要继续上次的${projectId ? '实验' : '理论试题'}?`, '提示', { |
|
confirmButtonText: '是', |
|
cancelButtonText: '否', |
|
type: 'success', |
|
closeOnClickModal: false |
|
}).then(() => { |
|
this.curProject = projectId |
|
this.curPaper = paperId |
|
this.toSub() |
|
}).catch(() => { |
|
this.showProjectDia() |
|
}) |
|
}, |
|
// 进入实验 |
|
async entry (isTheory) { |
|
this.isTheory = isTheory |
|
if (isTheory) { |
|
// 理论试卷 |
|
const res = await this.$post(`${this.api.getRecentTestPaperPracticeByCid}?cid=${this.courseId}`) |
|
if (res.recentCacheInfo) { |
|
this.entryProject('', res.recentCacheInfo.paperId) |
|
} else { |
|
this.showProjectDia(1) |
|
} |
|
} else { |
|
// 实训系统 |
|
// 查询上次做的项目(python跟沙盘接口不一样) |
|
if (this.systemIds.split(',').includes('19')) { // 沙盘 |
|
this.$post(`${this.api.getSandTableLastCache}?cid=${this.courseId}`).then(res => { |
|
// 返回了data则提示是否继续,否则,显示选择项目的弹框 |
|
if (res.getLastCache) { |
|
this.entryProject(+res.getLastCache) |
|
} else { |
|
this.showProjectDia() |
|
} |
|
}).catch(res => { |
|
this.showProjectDia() |
|
}) |
|
} else { // python |
|
// python只能存在一个打开的窗口 |
|
// const opened = +localStorage.getItem('opened') |
|
// if (opened) { |
|
// Util.errorMsg('Python系统限单页活跃,请切换至当前已有的活跃实验页面。', 5000) |
|
// return false |
|
// } else { |
|
// localStorage.setItem('opened', 1) |
|
// } |
|
|
|
this.$get(this.api.getTheMostRecentlyRunProject, { |
|
cid: this.courseId |
|
}).then(({ data }) => { |
|
// 返回了data则提示是否继续,否则,显示选择项目的弹框 |
|
if (data && data.length) { |
|
this.entryProject(data[0].projectId) |
|
} else { |
|
this.showProjectDia() |
|
} |
|
}).catch(res => { |
|
this.showProjectDia() |
|
}) |
|
} |
|
} |
|
}, |
|
// 进入python系统 |
|
toPython (projectId) { |
|
const id = this.systemIds |
|
let token = Util.local.get(Setting.tokenKey); |
|
Util.cookies.set('assessmentId', '', -1) |
|
Util.cookies.set('startTime', '', -1) |
|
Util.cookies.set('stopTime', '', -1) |
|
projectId ? Util.cookies.set('projectId', projectId) : Util.cookies.set('projectId', '', -1) |
|
Util.cookies.set('token', token) |
|
Util.cookies.set('mallId', this.mallId) |
|
Util.cookies.set('third', this.third) |
|
Util.cookies.set('courseId', this.courseId) |
|
Util.cookies.set('curriculumName', encodeURIComponent(this.curriculumName)) |
|
Util.cookies.set('systemId', id) |
|
Util.cookies.set('fromManager', 1) |
|
Util.cookies.set('isSubmit', '', -1) |
|
Util.cookies.set('competitionId', '', -1) |
|
Util.cookies.set('language', '', -1) |
|
Util.cookies.set('className', '', -1) |
|
Util.cookies.set('loaded', '', -1) |
|
// 8个python子系统都跳这个地址,子系统会通过cookie里的systemId识别展示哪套系统 |
|
location.href = process.env.NODE_ENV === 'development' ? |
|
`http://${location.hostname}:8085/#/` : |
|
Setting.isPro ? |
|
`https://${location.hostname}/pyTrials` : |
|
`${location.origin}/pyTrials` |
|
}, |
|
// 进入子系统 |
|
async toSub () { |
|
// 理论试卷 |
|
if (this.isTheory) { |
|
window.open(this.$router.resolve(`/theoryExam?paperId=${this.curPaper}&cid=${this.courseId}&mallId=${this.mallId}&curriculumName=${this.curriculumName}`).href) |
|
} else { |
|
// 实训 |
|
let curProject = this.projects.find(e => e.projectId == this.curProject) |
|
if (!curProject && this.projects.length) { |
|
curProject = this.projects[0] |
|
this.curProject = curProject.projectId |
|
} |
|
const { systemId } = curProject |
|
|
|
let token = Util.local.get(Setting.tokenKey); |
|
this.third = curProject.type === 2 ? (curProject.systemId === 28 ? 'low' : 'ai') : '' |
|
if (systemId == 11) { |
|
// 银行系统 |
|
sessionStorage.removeItem('projectId') |
|
sessionStorage.removeItem('submited') |
|
location.href = `${Setting.bankPath}/#/index/list?curriculumName=${this.curriculumName}&token=${token}&cid=${this.courseId}&mallId=${this.mallId}&systemId=${this.systemIds}&projectId=${this.curProject}&assessmentId=&classId=&stopTime=&test=true&manager=1` |
|
} else if (systemId == 12) { |
|
// 众筹系统 |
|
window.open(`http://${Setting.zcPath}?systemId=${systemId}&courseId=${this.courseId}&projectId=${this.curProject}&token=${token}&userId=${this.userId}&classId=1&mallId=${this.mallId}${Setting.isTest ? '&beta=1' : ''}`); |
|
} else if (systemId == 19) { |
|
// 沙盘 |
|
location.href = `${Setting.sandPath}/#/?curriculumName=${this.curriculumName}&token=${token}&cid=${this.courseId}&mallId=${this.mallId}&systemId=${this.systemIds}&projectId=${this.curProject}&assessmentId=&classId=&stopTime=&manager=1&referrer=${encodeURIComponent(location.href)}` |
|
} else { |
|
// python系统 |
|
this.toPython(this.curProject) |
|
} |
|
} |
|
} |
|
} |
|
}; |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
@import '../../../styles/page/station.scss'; |
|
$height: 700px; |
|
|
|
.page { |
|
border-radius: 0; |
|
|
|
.intro { |
|
font-size: 14px; |
|
color: #333; |
|
line-height: 24px; |
|
} |
|
|
|
/deep/.des { |
|
div, |
|
p, |
|
span { |
|
font-family: PingFangSC-Regular !important; |
|
} |
|
} |
|
} |
|
|
|
/deep/.source-card { |
|
.el-card__body { |
|
padding: 0; |
|
} |
|
} |
|
|
|
.video_wid, |
|
.cover { |
|
position: relative; |
|
width: 76%; |
|
height: $height !important; |
|
border: 0; |
|
} |
|
|
|
.cover { |
|
flex: 1; |
|
width: auto; |
|
} |
|
|
|
.cover { |
|
img { |
|
border-radius: 8px; |
|
} |
|
|
|
&.is-word { |
|
overflow: hidden; |
|
} |
|
} |
|
|
|
|
|
.fileIframe { |
|
height: $height !important; |
|
} |
|
|
|
.video_wid, |
|
.inner { |
|
width: 100%; |
|
height: 100% !important; |
|
border: 0; |
|
overflow: auto; |
|
} |
|
|
|
.cover.is-word { |
|
.inner { |
|
height: calc(100% + 38px) !important; |
|
margin-top: -38px; |
|
} |
|
} |
|
|
|
.video_wid:focus { |
|
outline: none; |
|
} |
|
|
|
.catalog { |
|
width: 296px; |
|
padding: 16px; |
|
margin-left: 12px; |
|
background-color: #252528; |
|
|
|
.entry { |
|
width: 48%; |
|
height: 40px; |
|
font-size: 17px; |
|
|
|
&:only-child { |
|
width: 100%; |
|
} |
|
} |
|
|
|
.types { |
|
display: flex; |
|
margin: 15px 0; |
|
|
|
.item { |
|
display: inline-flex; |
|
justify-content: center; |
|
align-items: center; |
|
width: 120px; |
|
height: 40px; |
|
color: #fff; |
|
background-color: #4e4e4e; |
|
border-radius: 4px; |
|
cursor: pointer; |
|
|
|
&:first-child { |
|
margin-right: 10px; |
|
} |
|
|
|
&:hover { |
|
background-color: $main-color; |
|
} |
|
|
|
&.active { |
|
background-color: $main-color; |
|
} |
|
} |
|
|
|
.icon { |
|
margin-right: 5px; |
|
font-size: 18px; |
|
} |
|
} |
|
|
|
.list { |
|
height: calc(700px - 104px); |
|
overflow-y: auto; |
|
|
|
.title { |
|
margin-bottom: 11px; |
|
color: #fff; |
|
font-size: 16px; |
|
} |
|
|
|
.pro-title { |
|
margin-bottom: 5px; |
|
color: #fff; |
|
font-size: 12px; |
|
} |
|
|
|
/deep/.el-progress-bar { |
|
width: 92%; |
|
} |
|
|
|
/deep/.el-progress__text { |
|
color: #fff; |
|
} |
|
|
|
.desc-wrap { |
|
position: relative; |
|
|
|
.desc { |
|
font-size: 12px; |
|
color: rgba(0, 0, 0, 0.65); |
|
line-height: 22px; |
|
@include mul-ellipsis(2); |
|
|
|
&.active { |
|
display: block; |
|
overflow: visible; |
|
} |
|
} |
|
|
|
.arrow { |
|
position: absolute; |
|
bottom: 2px; |
|
right: 0; |
|
display: flex; |
|
justify-content: space-between; |
|
width: 46px; |
|
background-color: #fff; |
|
|
|
span { |
|
font-size: 14px; |
|
color: rgba(0, 0, 0, 0.65); |
|
} |
|
|
|
img { |
|
width: 16px; |
|
cursor: pointer; |
|
} |
|
|
|
&.active { |
|
span { |
|
opacity: 0; |
|
} |
|
|
|
img { |
|
transform: rotate(180deg); |
|
} |
|
} |
|
} |
|
} |
|
|
|
.chapters { |
|
margin-top: 16px; |
|
max-height: calc(100% - 53px); |
|
overflow: auto; |
|
} |
|
|
|
.chapter { |
|
margin-bottom: 20px; |
|
} |
|
|
|
.chapterName { |
|
color: #fff; |
|
font-size: 14px; |
|
} |
|
|
|
.section { |
|
padding: 5px 15px; |
|
margin-top: 12px; |
|
background-color: #121214; |
|
} |
|
|
|
.sectionName { |
|
position: relative; |
|
padding-right: 15px; |
|
margin: 12px 0; |
|
font-size: 12px; |
|
color: #999; |
|
cursor: pointer; |
|
@include ellipsis; |
|
|
|
img { |
|
margin-right: 8px; |
|
} |
|
|
|
.icon { |
|
position: absolute; |
|
right: 0; |
|
font-size: 14px; |
|
color: #00c935; |
|
} |
|
|
|
.circle { |
|
width: 14px; |
|
height: 14px; |
|
border-radius: 50%; |
|
border: 1px solid #ccc; |
|
} |
|
|
|
&.active { |
|
color: #fff; |
|
} |
|
} |
|
} |
|
} |
|
|
|
.buy { |
|
text-align: center; |
|
|
|
.tips { |
|
margin-bottom: 10px; |
|
font-size: 14px; |
|
} |
|
|
|
img { |
|
width: 85%; |
|
} |
|
} |
|
|
|
.el-image-viewer__wrapper { |
|
transform: translateY(-10px); |
|
transition: transform 0.5s; |
|
|
|
&.active { |
|
transform: translateY(0); |
|
} |
|
} |
|
|
|
.el-image-viewer__close { |
|
z-index: 2000; |
|
top: 15px; |
|
right: 15px; |
|
|
|
&.doc-close { |
|
i { |
|
color: #000 !important; |
|
} |
|
} |
|
} |
|
|
|
.list::-webkit-scrollbar { |
|
width: 4px; |
|
} |
|
|
|
.list::-webkit-scrollbar-thumb { |
|
border-radius: 10px; |
|
background: rgba(0, 0, 0, 0.06); |
|
} |
|
|
|
.mask { |
|
z-index: 9; |
|
position: absolute; |
|
background-color: rgb(57, 58, 61); |
|
} |
|
|
|
.word-mask { |
|
z-index: 9; |
|
position: absolute; |
|
top: 0; |
|
right: 0; |
|
width: 100%; |
|
background-color: rgb(243, 242, 241); |
|
} |
|
|
|
.word-mask1 { |
|
z-index: 9; |
|
position: absolute; |
|
top: 0; |
|
right: 0; |
|
width: 100%; |
|
background-color: #185abd; |
|
} |
|
|
|
.word-mask2 { |
|
z-index: 9; |
|
position: absolute; |
|
background-color: transparent; |
|
} |
|
|
|
.excel-mask1 { |
|
z-index: 9; |
|
position: absolute; |
|
top: 0; |
|
left: 20%; |
|
width: 60%; |
|
background-color: #107c41; |
|
} |
|
|
|
/deep/.pdf-dia { |
|
border-radius: 0 !important; |
|
|
|
.el-dialog__header { |
|
display: none; |
|
} |
|
|
|
.el-dialog__body { |
|
padding: 0; |
|
} |
|
|
|
.el-dialog__headerbtn { |
|
top: 10px; |
|
|
|
.el-dialog__close { |
|
color: #fff; |
|
font-size: 16px; |
|
} |
|
} |
|
} |
|
|
|
.pdf { |
|
position: relative; |
|
margin-top: 0 !important; |
|
|
|
.full { |
|
position: absolute; |
|
top: 7px; |
|
right: 10px; |
|
cursor: pointer; |
|
} |
|
|
|
.arrow { |
|
padding: 10px 0; |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
font-size: 16px; |
|
color: #fff; |
|
background-color: #333; |
|
|
|
.turn { |
|
margin: 0 10px; |
|
font-size: 18px; |
|
cursor: pointer; |
|
} |
|
} |
|
|
|
.pdf-wrap { |
|
width: 80%; |
|
margin: 0 auto; |
|
} |
|
} |
|
|
|
.tabs { |
|
margin-bottom: 10px; |
|
} |
|
|
|
.tab-content { |
|
width: 80%; |
|
} |
|
|
|
.rank { |
|
width: calc(20% - 12px); |
|
padding: 20px; |
|
margin-left: 12px; |
|
background-color: #fff; |
|
|
|
.title { |
|
margin-bottom: 10px; |
|
font-size: 15px; |
|
font-weight: 400; |
|
} |
|
|
|
.arches { |
|
max-height: 223px; |
|
padding-right: 10px; |
|
margin-top: 20px; |
|
overflow: auto; |
|
} |
|
|
|
.line { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
margin-bottom: 10px; |
|
} |
|
|
|
.avatar { |
|
width: 35px; |
|
height: 35px; |
|
margin-right: 10px; |
|
} |
|
|
|
.point { |
|
font-weight: 600; |
|
color: $main-color; |
|
} |
|
|
|
.none { |
|
margin-top: 10px; |
|
text-align: center; |
|
font-size: 12px; |
|
color: #727272; |
|
} |
|
} |
|
|
|
/deep/.project-dia { |
|
.el-dialog__body { |
|
padding: 28px 32px; |
|
} |
|
} |
|
|
|
.projects { |
|
display: flex; |
|
flex-wrap: wrap; |
|
max-height: 400px; |
|
overflow: auto; |
|
|
|
li { |
|
display: inline-flex; |
|
align-items: center; |
|
width: 238px; |
|
padding: 16px; |
|
margin: 0 20px 20px 0; |
|
background-color: #f6f8fa; |
|
border-radius: 16px; |
|
cursor: pointer; |
|
|
|
&:hover { |
|
span { |
|
color: $main-color; |
|
} |
|
} |
|
|
|
&:nth-child(3n) { |
|
margin-right: 0; |
|
} |
|
|
|
&.active { |
|
background-color: #f2f7ff; |
|
|
|
span { |
|
color: #3988ff; |
|
} |
|
} |
|
} |
|
|
|
span { |
|
max-width: 140px; |
|
margin-left: 14px; |
|
font-size: 14px; |
|
color: #333; |
|
} |
|
} |
|
</style> |