|
@@ -29,7 +29,7 @@
|
|
|
<img v-if="project.cover_image_file_url.length > 0" :src="project.cover_image_file_url" alt="cover-image" />
|
|
<img v-if="project.cover_image_file_url.length > 0" :src="project.cover_image_file_url" alt="cover-image" />
|
|
|
</div>
|
|
</div>
|
|
|
<div class="info-content">
|
|
<div class="info-content">
|
|
|
- <div class="catalogue-icon">
|
|
|
|
|
|
|
+ <div class="catalogue-icon" @click="toggleNavigationShow">
|
|
|
<SvgIcon icon-class="catalogue" size="54" />
|
|
<SvgIcon icon-class="catalogue" size="54" />
|
|
|
</div>
|
|
</div>
|
|
|
<div class="courseware">
|
|
<div class="courseware">
|
|
@@ -58,8 +58,13 @@
|
|
|
</div>
|
|
</div>
|
|
|
</aside>
|
|
</aside>
|
|
|
|
|
|
|
|
- <div ref="previewMain" class="main-container">
|
|
|
|
|
- <div v-if="!navigationShow" class="catalogue-bar">
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ ref="previewMain"
|
|
|
|
|
+ class="main-container"
|
|
|
|
|
+ :style="{ paddingLeft: navigationShow ? '15px' : '315px', paddingRight: sidebarShow ? '15px' : '315px' }"
|
|
|
|
|
+ >
|
|
|
|
|
+ <!-- 左侧菜单栏 - 收缩 -->
|
|
|
|
|
+ <div v-if="!navigationShow" class="catalogue-bar" @click="toggleNavigationShow">
|
|
|
<SvgIcon icon-class="catalogue" size="54" />
|
|
<SvgIcon icon-class="catalogue" size="54" />
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
@@ -76,23 +81,128 @@
|
|
|
:background="background"
|
|
:background="background"
|
|
|
:can-remark="isTrue(courseware_info.is_my_audit_task) && isTrue(courseware_info.is_can_add_audit_remark)"
|
|
:can-remark="isTrue(courseware_info.is_my_audit_task) && isTrue(courseware_info.is_can_add_audit_remark)"
|
|
|
:show-remark="false"
|
|
:show-remark="false"
|
|
|
|
|
+ :project="project"
|
|
|
:component-remark-obj="remark_list_obj"
|
|
:component-remark-obj="remark_list_obj"
|
|
|
@computeScroll="computeScroll"
|
|
@computeScroll="computeScroll"
|
|
|
/>
|
|
/>
|
|
|
<div class="preview-right"></div>
|
|
<div class="preview-right"></div>
|
|
|
</main>
|
|
</main>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 右侧菜单栏 - 收缩 -->
|
|
|
|
|
+ <aside v-if="!sidebarShow" class="sidebar-bar">
|
|
|
|
|
+ <aside class="toolbar">
|
|
|
|
|
+ <div class="toolbar-special">
|
|
|
|
|
+ <!-- <img :src="require('@/assets/icon/sidebar-fullscreen.png')" alt="全屏" />
|
|
|
|
|
+ <img :src="require('@/assets/icon/sidebar-toolkit.png')" alt="工具箱" /> -->
|
|
|
|
|
+ <img :src="require(`@/assets/icon/arrow-down.png`)" alt="伸缩" @click="toggleSidebarShow" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </aside>
|
|
|
|
|
+ </aside>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="back-top" @click="backTop">
|
|
<div class="back-top" @click="backTop">
|
|
|
<img :src="require(`@/assets/icon/back-top.png`)" alt="返回顶部" />
|
|
<img :src="require(`@/assets/icon/back-top.png`)" alt="返回顶部" />
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 右侧工具栏 -->
|
|
|
|
|
+ <aside v-if="sidebarShow" ref="sidebarMenu" class="sidebar">
|
|
|
|
|
+ <aside class="toolbar">
|
|
|
|
|
+ <div class="toolbar-special">
|
|
|
|
|
+ <!-- <img :src="require('@/assets/icon/sidebar-fullscreen.png')" alt="全屏" />
|
|
|
|
|
+ <img :src="require('@/assets/icon/sidebar-toolkit.png')" alt="工具箱" /> -->
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-if="sidebarShow" class="toolbar-list">
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-for="{ icon, title, handle, param } in sidebarIconList"
|
|
|
|
|
+ :key="icon"
|
|
|
|
|
+ :class="['sidebar-item', { active: curToolbarIcon === icon }]"
|
|
|
|
|
+ :title="title"
|
|
|
|
|
+ @click="handleSidebarClick(handle, param, icon)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="sidebar-icon icon-mask"
|
|
|
|
|
+ :style="{
|
|
|
|
|
+ backgroundColor: curToolbarIcon === icon ? '#fff' : '#1E2129',
|
|
|
|
|
+ maskImage: `url(${require(`@/assets/icon/sidebar-${icon}.png`)})`,
|
|
|
|
|
+ }"
|
|
|
|
|
+ ></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="adjustable" @click="toggleSidebarShow">
|
|
|
|
|
+ <img :src="require(`@/assets/icon/arrow-up.png`)" alt="伸缩" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </aside>
|
|
|
|
|
+ <div class="content"></div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="back-top" @click="backTop">
|
|
|
|
|
+ <img :src="require(`@/assets/icon/back-top.png`)" alt="返回顶部" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <el-drawer
|
|
|
|
|
+ custom-class="custom-drawer"
|
|
|
|
|
+ :visible="drawerType.length > 0"
|
|
|
|
|
+ :with-header="false"
|
|
|
|
|
+ :modal="false"
|
|
|
|
|
+ size="25%"
|
|
|
|
|
+ :style="drawerStyle"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="infinite-list-wrapper">
|
|
|
|
|
+ <ul
|
|
|
|
|
+ v-infinite-scroll="loadMore"
|
|
|
|
|
+ class="scroll-container"
|
|
|
|
|
+ infinite-scroll-disabled="disabled"
|
|
|
|
|
+ :infinite-scroll-immediate="false"
|
|
|
|
|
+ >
|
|
|
|
|
+ <li
|
|
|
|
|
+ v-for="(item, index) in file_list"
|
|
|
|
|
+ :key="index"
|
|
|
|
|
+ class="list-item"
|
|
|
|
|
+ @click="handleFileClick(item?.courseware_id, item?.component_id)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <template v-if="parseInt(drawerType) === 0">
|
|
|
|
|
+ <el-image :src="item.file_url" fit="contain" />
|
|
|
|
|
+ <span class="text-box">{{ item.file_name.slice(0, item.file_name.lastIndexOf('.')) }}</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template v-else-if="parseInt(drawerType) === 1">
|
|
|
|
|
+ <AudioPlay
|
|
|
|
|
+ view-size="middle"
|
|
|
|
|
+ :file-id="item.file_id"
|
|
|
|
|
+ :file-name="item.file_name.slice(0, item.file_name.lastIndexOf('.'))"
|
|
|
|
|
+ :show-slider="true"
|
|
|
|
|
+ :audio-index="index"
|
|
|
|
|
+ />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template v-else-if="parseInt(drawerType) === 2">
|
|
|
|
|
+ <VideoPlay view-size="big" :file-id="item.file_id" :video-index="index" />
|
|
|
|
|
+ <span class="text-box">{{ item.file_name.slice(0, item.file_name.lastIndexOf('.')) }}</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </li>
|
|
|
|
|
+ </ul>
|
|
|
|
|
+ <p v-if="loading">加载中...</p>
|
|
|
|
|
+ <p v-if="noMore">没有更多了</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-drawer>
|
|
|
|
|
+ </aside>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+
|
|
|
|
|
+ <el-dialog title="" :visible="visibleMindMap" width="1100px" class="audit-dialog" @close="dialogClose('MindMap')">
|
|
|
|
|
+ <MindMap
|
|
|
|
|
+ v-if="isChildDataLoad"
|
|
|
|
|
+ ref="mindMapRef"
|
|
|
|
|
+ :project-id="projectId"
|
|
|
|
|
+ :mind-map-json-data="mindMapJsonData"
|
|
|
|
|
+ @child-click="handleNodeClick"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
import CoursewarePreview from '@/views/book/courseware/preview/CoursewarePreview.vue';
|
|
import CoursewarePreview from '@/views/book/courseware/preview/CoursewarePreview.vue';
|
|
|
import { isTrue } from '@/utils/validate';
|
|
import { isTrue } from '@/utils/validate';
|
|
|
|
|
+import MindMap from '@/components/MindMap.vue';
|
|
|
|
|
+import VideoPlay from '@/views/book/courseware/preview/components/common/VideoPlay.vue';
|
|
|
|
|
+import AudioPlay from '@/views/book/courseware/preview/components/common/AudioPlay.vue';
|
|
|
import * as OpenCC from 'opencc-js';
|
|
import * as OpenCC from 'opencc-js';
|
|
|
|
|
|
|
|
import { GetBookCoursewareInfo, GetCoursewareAuditRemarkList, GetProjectInfo } from '@/api/project';
|
|
import { GetBookCoursewareInfo, GetCoursewareAuditRemarkList, GetProjectInfo } from '@/api/project';
|
|
@@ -100,6 +210,8 @@ import {
|
|
|
ContentGetCoursewareContent_View,
|
|
ContentGetCoursewareContent_View,
|
|
|
ChapterGetBookChapterStructExpandList,
|
|
ChapterGetBookChapterStructExpandList,
|
|
|
GetBookBaseInfo,
|
|
GetBookBaseInfo,
|
|
|
|
|
+ MangerGetBookMindMap,
|
|
|
|
|
+ PageQueryBookResourceList,
|
|
|
GetLanguageTypeList,
|
|
GetLanguageTypeList,
|
|
|
GetBookUnifiedAttrib,
|
|
GetBookUnifiedAttrib,
|
|
|
} from '@/api/book';
|
|
} from '@/api/book';
|
|
@@ -108,6 +220,9 @@ export default {
|
|
|
name: 'CommonPreview',
|
|
name: 'CommonPreview',
|
|
|
components: {
|
|
components: {
|
|
|
CoursewarePreview,
|
|
CoursewarePreview,
|
|
|
|
|
+ MindMap,
|
|
|
|
|
+ VideoPlay,
|
|
|
|
|
+ AudioPlay,
|
|
|
},
|
|
},
|
|
|
provide() {
|
|
provide() {
|
|
|
return {
|
|
return {
|
|
@@ -118,9 +233,23 @@ export default {
|
|
|
};
|
|
};
|
|
|
},
|
|
},
|
|
|
data() {
|
|
data() {
|
|
|
|
|
+ const sidebarIconList = [
|
|
|
|
|
+ // { icon: 'search', title: '搜索', handle: '', param: {} },
|
|
|
|
|
+ { icon: 'mindmap', title: '思维导图', handle: 'openMindMap', param: {} },
|
|
|
|
|
+ // { icon: 'knowledge', title: '知识图谱', handle: '', param: {} },
|
|
|
|
|
+ // { icon: 'totalResources', title: '总资源', handle: '', param: {} },
|
|
|
|
|
+ // { icon: 'collect', title: '收藏', handle: '', param: {} },
|
|
|
|
|
+ { icon: 'audio', title: '音频', handle: 'openDrawer', param: { type: '1' } },
|
|
|
|
|
+ { icon: 'image', title: '图片', handle: 'openDrawer', param: { type: '0' } },
|
|
|
|
|
+ { icon: 'video', title: '视频', handle: 'openDrawer', param: { type: '2' } },
|
|
|
|
|
+ // { icon: 'note', title: '笔记', handle: '', param: {} },
|
|
|
|
|
+ // { icon: 'translate', title: '翻译', handle: '', param: {} },
|
|
|
|
|
+ // { icon: 'setting', title: '设置', handle: '', param: {} },
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
return {
|
|
return {
|
|
|
book_id: this.$route.query.book_id || '',
|
|
book_id: this.$route.query.book_id || '',
|
|
|
- select_node: '',
|
|
|
|
|
|
|
+ select_node: this.id,
|
|
|
courseware_info: {
|
|
courseware_info: {
|
|
|
book_name: '',
|
|
book_name: '',
|
|
|
is_can_start_edit: 'false',
|
|
is_can_start_edit: 'false',
|
|
@@ -151,6 +280,29 @@ export default {
|
|
|
remark_content: '',
|
|
remark_content: '',
|
|
|
submit_loading: false,
|
|
submit_loading: false,
|
|
|
isTrue,
|
|
isTrue,
|
|
|
|
|
+ menuPosition: {
|
|
|
|
|
+ x: -1,
|
|
|
|
|
+ y: -1,
|
|
|
|
|
+ componentId: 'WHOLE',
|
|
|
|
|
+ },
|
|
|
|
|
+ curToolbarIcon: this.isShowAudit ? 'audit' : '',
|
|
|
|
|
+ sidebarIconList,
|
|
|
|
|
+ visibleMindMap: false,
|
|
|
|
|
+ isChildDataLoad: false,
|
|
|
|
|
+ mindMapJsonData: {}, // 思维导图json数据
|
|
|
|
|
+ drawerType: '', // 抽屉类型
|
|
|
|
|
+ drawerStyle: {
|
|
|
|
|
+ top: '0',
|
|
|
|
|
+ height: '0',
|
|
|
|
|
+ right: '0',
|
|
|
|
|
+ },
|
|
|
|
|
+ page_capacity: 10,
|
|
|
|
|
+ cur_page: 1,
|
|
|
|
|
+ file_list: [],
|
|
|
|
|
+ total_count: 0,
|
|
|
|
|
+ loading: true,
|
|
|
|
|
+ lastLoadTime: 0,
|
|
|
|
|
+ minLoadInterval: 3 * 1000,
|
|
|
isShowGroup: false,
|
|
isShowGroup: false,
|
|
|
groupShowAll: true,
|
|
groupShowAll: true,
|
|
|
opencc: OpenCC.Converter({ from: 'cn', to: 'tw' }),
|
|
opencc: OpenCC.Converter({ from: 'cn', to: 'tw' }),
|
|
@@ -162,13 +314,24 @@ export default {
|
|
|
unified_attrib: {},
|
|
unified_attrib: {},
|
|
|
curSelectId: this.id,
|
|
curSelectId: this.id,
|
|
|
navigationShow: true,
|
|
navigationShow: true,
|
|
|
|
|
+ sidebarShow: true,
|
|
|
project: {
|
|
project: {
|
|
|
- editor: '', // 主编
|
|
|
|
|
|
|
+ editor: '', // 作者
|
|
|
cover_image_file_id: null, // 封面图片ID
|
|
cover_image_file_id: null, // 封面图片ID
|
|
|
cover_image_file_url: '', // 封面图片URL
|
|
cover_image_file_url: '', // 封面图片URL
|
|
|
},
|
|
},
|
|
|
};
|
|
};
|
|
|
},
|
|
},
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ disabled() {
|
|
|
|
|
+ const result = this.loading || this.noMore;
|
|
|
|
|
+ return result;
|
|
|
|
|
+ },
|
|
|
|
|
+ noMore() {
|
|
|
|
|
+ const result = this.file_list.length >= this.total_count;
|
|
|
|
|
+ return result;
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
watch: {
|
|
watch: {
|
|
|
isJudgeCorrect(newVal) {
|
|
isJudgeCorrect(newVal) {
|
|
|
if (!newVal) {
|
|
if (!newVal) {
|
|
@@ -180,6 +343,9 @@ export default {
|
|
|
this.simulateAnswer();
|
|
this.simulateAnswer();
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
|
|
+ mounted() {
|
|
|
|
|
+ this.calcDrawerPosition();
|
|
|
|
|
+ },
|
|
|
created() {
|
|
created() {
|
|
|
this.getBookBaseInfo();
|
|
this.getBookBaseInfo();
|
|
|
this.getBookChapterStructExpandList();
|
|
this.getBookChapterStructExpandList();
|
|
@@ -306,6 +472,150 @@ export default {
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
|
+ * 处理侧边栏图标点击事件
|
|
|
|
|
+ * @param {string} handle - 处理函数名
|
|
|
|
|
+ * @param {any} param - 处理函数参数
|
|
|
|
|
+ * @param {string} icon - 图标名称
|
|
|
|
|
+ */
|
|
|
|
|
+ handleSidebarClick(handle, param, icon) {
|
|
|
|
|
+ if (typeof handle === 'string' && handle && typeof this[handle] === 'function') {
|
|
|
|
|
+ this[handle](param);
|
|
|
|
|
+ }
|
|
|
|
|
+ this.curToolbarIcon = icon;
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ openMindMap() {
|
|
|
|
|
+ MangerGetBookMindMap({ book_id: this.projectId }).then(({ content }) => {
|
|
|
|
|
+ if (content) {
|
|
|
|
|
+ this.mindMapJsonData = JSON.parse(content);
|
|
|
|
|
+ this.isChildDataLoad = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ this.visibleMindMap = true;
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ async handleNodeClick(data) {
|
|
|
|
|
+ let [nodeId, componentId] = data.split('#');
|
|
|
|
|
+ if (nodeId) this.selectNode(nodeId);
|
|
|
|
|
+ if (componentId) {
|
|
|
|
|
+ let node = await this.$refs.courserware.findChildComponentByKey(componentId);
|
|
|
|
|
+ if (node) {
|
|
|
|
|
+ await this.$nextTick();
|
|
|
|
|
+ this.$refs.previewMain.scrollTo({
|
|
|
|
|
+ top: node.$el.offsetTop - 50,
|
|
|
|
|
+ left: node.$el.offsetLeft - 50,
|
|
|
|
|
+ behavior: 'smooth',
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ this.visibleMindMap = false;
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 计算抽屉滑出位置
|
|
|
|
|
+ calcDrawerPosition() {
|
|
|
|
|
+ const menu = this.$refs.sidebarMenu;
|
|
|
|
|
+ if (menu) {
|
|
|
|
|
+ const rect = menu.getBoundingClientRect();
|
|
|
|
|
+ this.drawerStyle = {
|
|
|
|
|
+ top: `${rect.top}px`,
|
|
|
|
|
+ height: `${rect.height}px`,
|
|
|
|
|
+ right: `${window.innerWidth - rect.left + 1}px`,
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 打开抽屉并初始化加载
|
|
|
|
|
+ * @param {Object} param - 抽屉参数
|
|
|
|
|
+ * @param {string} param.type - 抽屉类型(0: 图片, 1: 音频, 2: 视频)
|
|
|
|
|
+ */
|
|
|
|
|
+ openDrawer({ type }) {
|
|
|
|
|
+ if (this.drawerType === type) {
|
|
|
|
|
+ this.drawerType = '';
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 重置所有加载状态
|
|
|
|
|
+ this.resetLoadState();
|
|
|
|
|
+ this.drawerType = type; // 假设这是你的类型变量
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ // 确保DOM更新后触发加载
|
|
|
|
|
+ this.loadMore();
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ openAudit() {},
|
|
|
|
|
+ resetLoadState() {
|
|
|
|
|
+ this.cur_page = 1;
|
|
|
|
|
+ this.file_list = [];
|
|
|
|
|
+ this.total_count = 0;
|
|
|
|
|
+ this.loading = false;
|
|
|
|
|
+ this.lastLoadTime = 0; // 重置时间戳,允许立即加载
|
|
|
|
|
+ this.loadCount = 0;
|
|
|
|
|
+ },
|
|
|
|
|
+ // 加载更多数据
|
|
|
|
|
+ async loadMore() {
|
|
|
|
|
+ const now = Date.now();
|
|
|
|
|
+ // 只有当lastLoadTime不为0(不是第一次)且时间间隔太短时才return
|
|
|
|
|
+ if (this.lastLoadTime > 0 && now - this.lastLoadTime < this.minLoadInterval) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (this.disabled || this.loading) {
|
|
|
|
|
+ if (this.lastLoadTime > 0) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ this.loading = true;
|
|
|
|
|
+ const params = {
|
|
|
|
|
+ page_capacity: this.page_capacity,
|
|
|
|
|
+ cur_page: this.cur_page,
|
|
|
|
|
+ book_id: this.projectId,
|
|
|
|
|
+ type: parseInt(this.drawerType),
|
|
|
|
|
+ };
|
|
|
|
|
+ await PageQueryBookResourceList(params)
|
|
|
|
|
+ .then(({ total_count, resource_list }) => {
|
|
|
|
|
+ this.total_count = total_count;
|
|
|
|
|
+ // 记录加载前的滚动高度
|
|
|
|
|
+ const scrollContainer = this.$el.querySelector('.el-drawer__body');
|
|
|
|
|
+ const isAtBottom = this.isScrollAtBottom(scrollContainer);
|
|
|
|
|
+
|
|
|
|
|
+ this.file_list = this.cur_page === 1 ? resource_list : [...this.file_list, ...resource_list];
|
|
|
|
|
+ if (!resource_list || resource_list.length === 0) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ this.cur_page += 1;
|
|
|
|
|
+
|
|
|
|
|
+ // 只有当前已经在底部时才微调滚动位置
|
|
|
|
|
+ if (isAtBottom) {
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ // 轻微向上滚动,创造滚动空间
|
|
|
|
|
+ scrollContainer.scrollTop -= 5;
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .finally(() => {
|
|
|
|
|
+ this.loading = false;
|
|
|
|
|
+ this.lastLoadTime = now;
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ isScrollAtBottom(container) {
|
|
|
|
|
+ if (!container) return false;
|
|
|
|
|
+ return container.scrollHeight - container.scrollTop <= container.clientHeight + 5;
|
|
|
|
|
+ },
|
|
|
|
|
+ async handleFileClick(courseware_id, component_id) {
|
|
|
|
|
+ if (courseware_id) this.selectNode(courseware_id);
|
|
|
|
|
+ if (component_id) {
|
|
|
|
|
+ let node = await this.$refs.courserware.findChildComponentByKey(component_id);
|
|
|
|
|
+ if (node) {
|
|
|
|
|
+ await this.$nextTick();
|
|
|
|
|
+ this.$refs.previewMain.scrollTo({
|
|
|
|
|
+ top: node.offsetTop - 50,
|
|
|
|
|
+ left: node.offsetLeft - 50,
|
|
|
|
|
+ behavior: 'smooth',
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
* 文本转换
|
|
* 文本转换
|
|
|
* @param {string} text - 要转换的文本
|
|
* @param {string} text - 要转换的文本
|
|
|
* @returns {string} - 转换后的文本
|
|
* @returns {string} - 转换后的文本
|
|
@@ -350,6 +660,12 @@ export default {
|
|
|
toggleNavigationShow() {
|
|
toggleNavigationShow() {
|
|
|
this.navigationShow = !this.navigationShow;
|
|
this.navigationShow = !this.navigationShow;
|
|
|
},
|
|
},
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 切换右侧工具栏显示与隐藏
|
|
|
|
|
+ */
|
|
|
|
|
+ toggleSidebarShow() {
|
|
|
|
|
+ this.sidebarShow = !this.sidebarShow;
|
|
|
|
|
+ },
|
|
|
|
|
|
|
|
backTop() {
|
|
backTop() {
|
|
|
this.$refs.previewMain.scrollTo({
|
|
this.$refs.previewMain.scrollTo({
|
|
@@ -441,9 +757,12 @@ $total-width: $courseware-width + $courseware-left-margin + $courseware-right-ma
|
|
|
min-width: 1110px;
|
|
min-width: 1110px;
|
|
|
padding: 15px 0;
|
|
padding: 15px 0;
|
|
|
overflow: auto;
|
|
overflow: auto;
|
|
|
- background: #ececec;
|
|
|
|
|
|
|
+ background-color: #ececec;
|
|
|
|
|
|
|
|
.catalogue-bar {
|
|
.catalogue-bar {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 15px;
|
|
|
|
|
+ left: 0;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
justify-content: center;
|
|
@@ -455,11 +774,47 @@ $total-width: $courseware-width + $courseware-left-margin + $courseware-right-ma
|
|
|
border-radius: 2px;
|
|
border-radius: 2px;
|
|
|
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 40%);
|
|
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 40%);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ .sidebar-bar {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ right: 240px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ width: 60px;
|
|
|
|
|
+ height: calc(100vh - 166px);
|
|
|
|
|
+
|
|
|
|
|
+ .toolbar {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ width: 60px;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+
|
|
|
|
|
+ img {
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-special {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ row-gap: 16px;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ margin-bottom: 24px;
|
|
|
|
|
+ background-color: #fff;
|
|
|
|
|
+
|
|
|
|
|
+ img {
|
|
|
|
|
+ width: 36px;
|
|
|
|
|
+ height: 36px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.back-top {
|
|
.back-top {
|
|
|
position: absolute;
|
|
position: absolute;
|
|
|
- right: 24px;
|
|
|
|
|
|
|
+ right: 240px;
|
|
|
bottom: 0;
|
|
bottom: 0;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
place-content: center center;
|
|
place-content: center center;
|
|
@@ -618,6 +973,140 @@ $total-width: $courseware-width + $courseware-left-margin + $courseware-right-ma
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ .sidebar {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ width: $sidebar-width;
|
|
|
|
|
+
|
|
|
|
|
+ .toolbar {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ width: 60px;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ background-color: rgba(247, 248, 250, 100%);
|
|
|
|
|
+
|
|
|
|
|
+ img {
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-special {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ row-gap: 16px;
|
|
|
|
|
+ margin-bottom: 24px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-list {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ row-gap: 16px;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+
|
|
|
|
|
+ .sidebar-item {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+
|
|
|
|
|
+ .sidebar-icon {
|
|
|
|
|
+ width: 36px;
|
|
|
|
|
+ height: 36px;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.active {
|
|
|
|
|
+ background-color: #4095e5;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .content {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ background-color: #fff;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .back-top {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ place-content: center center;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ width: 60px;
|
|
|
|
|
+ height: 60px;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .el-drawer__body {
|
|
|
|
|
+ height: calc(100vh - 200px);
|
|
|
|
|
+ overflow-y: auto;
|
|
|
|
|
+
|
|
|
|
|
+ .scroll-container {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ row-gap: 8px;
|
|
|
|
|
+ margin: 6px;
|
|
|
|
|
+
|
|
|
|
|
+ .list-item {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ border: 1px solid #ccc;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+
|
|
|
|
|
+ :deep .el-slider {
|
|
|
|
|
+ .el-slider__runway {
|
|
|
|
|
+ background-color: #eee;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ :deep .audio-middle {
|
|
|
|
|
+ width: calc(25vw - 110px);
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .el-image {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ width: 30%;
|
|
|
|
|
+ min-width: 30%;
|
|
|
|
|
+ height: 90px;
|
|
|
|
|
+ margin: 6px;
|
|
|
|
|
+ background-color: #ccc;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .video-play {
|
|
|
|
|
+ width: 30%;
|
|
|
|
|
+ min-width: 30%;
|
|
|
|
|
+ margin: 6px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .text-box {
|
|
|
|
|
+ word-break: break-word;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ p {
|
|
|
|
|
+ color: #999;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+:deep .audit-dialog {
|
|
|
|
|
+ .el-dialog__body {
|
|
|
|
|
+ height: calc(100vh - 260px);
|
|
|
|
|
+ padding: 5px 20px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .mind-map-container .mind-map {
|
|
|
|
|
+ height: calc(100vh - 310px);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
</style>
|
|
</style>
|