|
@@ -49,18 +49,56 @@
|
|
|
</ul>
|
|
|
<p v-else style="text-align: center">暂无批注</p>
|
|
|
</div>
|
|
|
-
|
|
|
- <div class="sidebar">
|
|
|
+ <div ref="sidebarMenu" class="sidebar">
|
|
|
<div
|
|
|
- v-for="{ icon, title, handle } in sidebarIconList"
|
|
|
+ v-for="{ icon, title, handle, param } in sidebarIconList"
|
|
|
:key="icon"
|
|
|
:title="title"
|
|
|
class="sidebar-icon"
|
|
|
- @click="handleSidebarClick(handle)"
|
|
|
+ @click="handleSidebarClick(handle, param)"
|
|
|
>
|
|
|
<SvgIcon :icon-class="`sidebar-${icon}`" size="24" />
|
|
|
</div>
|
|
|
</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" style="overflow: auto">
|
|
|
+ <ul v-infinite-scroll="loadMore" class="scroll-container" infinite-scroll-disabled="disabled">
|
|
|
+ <li
|
|
|
+ v-for="(item, index) in file_list"
|
|
|
+ :key="index"
|
|
|
+ class="list-item"
|
|
|
+ @click="handleFileClick(item?.component_id)"
|
|
|
+ >
|
|
|
+ <template v-if="parseInt(drawerType) === 0">
|
|
|
+ <el-image :src="item.file_url" fit="contain" />
|
|
|
+ <span>{{ 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>{{ 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>
|
|
|
</div>
|
|
|
|
|
|
<el-dialog
|
|
@@ -104,6 +142,8 @@ import MenuPopover from '@/views/personal_workbench/common/MenuPopover.vue';
|
|
|
import RichText from '@/components/RichText.vue';
|
|
|
import { isTrue } from '@/utils/common';
|
|
|
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 {
|
|
|
GetBookCoursewareInfo,
|
|
@@ -117,6 +157,7 @@ import {
|
|
|
ChapterGetBookChapterStructExpandList,
|
|
|
GetBookBaseInfo,
|
|
|
MangerGetBookMindMap,
|
|
|
+ PageQueryBookResourceList,
|
|
|
} from '@/api/book';
|
|
|
|
|
|
export default {
|
|
@@ -126,6 +167,8 @@ export default {
|
|
|
MenuPopover,
|
|
|
RichText,
|
|
|
MindMap,
|
|
|
+ AudioPlay,
|
|
|
+ VideoPlay,
|
|
|
},
|
|
|
props: {
|
|
|
projectId: {
|
|
@@ -188,21 +231,41 @@ export default {
|
|
|
componentId: 'WHOLE',
|
|
|
},
|
|
|
sidebarIconList: [
|
|
|
- { icon: 'search', title: '搜索', handle: '' },
|
|
|
- { icon: 'mindmap', title: '思维导图', handle: 'openMindMap' },
|
|
|
- { icon: 'connect', title: '连接', handle: '' },
|
|
|
- { icon: 'audio', title: '音频', handle: '' },
|
|
|
- { icon: 'image', title: '图片', handle: '' },
|
|
|
- { icon: 'video', title: '视频', handle: '' },
|
|
|
- { icon: 'text', title: '文本', handle: '' },
|
|
|
- { icon: 'collect', title: '收藏', handle: '' },
|
|
|
- { icon: 'setting', title: '设置', handle: '' },
|
|
|
+ { icon: 'search', title: '搜索', handle: '', param: {} },
|
|
|
+ { icon: 'mindmap', title: '思维导图', handle: 'openMindMap', param: {} },
|
|
|
+ { icon: 'connect', 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: 'text', title: '文本', handle: '', param: {} },
|
|
|
+ { icon: 'file', title: '文件', handle: '', param: {} },
|
|
|
+ { icon: 'collect', title: '收藏', handle: '', param: {} },
|
|
|
+ { icon: 'setting', title: '设置', handle: '', param: {} },
|
|
|
],
|
|
|
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: false,
|
|
|
};
|
|
|
},
|
|
|
+ computed: {
|
|
|
+ disabled() {
|
|
|
+ return this.loading || this.noMore;
|
|
|
+ },
|
|
|
+ noMore() {
|
|
|
+ return this.file_list.length >= this.total_count && this.total_count > 0;
|
|
|
+ },
|
|
|
+ },
|
|
|
created() {
|
|
|
if (this.id) {
|
|
|
this.getBookCoursewareInfo(this.id);
|
|
@@ -213,6 +276,9 @@ export default {
|
|
|
}
|
|
|
this.getBookChapterStructExpandList();
|
|
|
},
|
|
|
+ mounted() {
|
|
|
+ this.calcDrawerPosition();
|
|
|
+ },
|
|
|
methods: {
|
|
|
getProjectBaseInfo() {
|
|
|
GetProjectBaseInfo({ id: this.projectId }).then(({ project_info }) => {
|
|
@@ -366,6 +432,7 @@ export default {
|
|
|
this[handle](param);
|
|
|
}
|
|
|
},
|
|
|
+
|
|
|
openMindMap() {
|
|
|
MangerGetBookMindMap({ book_id: this.projectId }).then(({ content }) => {
|
|
|
if (content) {
|
|
@@ -392,6 +459,70 @@ export default {
|
|
|
}
|
|
|
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.drawerType = type;
|
|
|
+ this.drawerVisible = true;
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.cur_page = 1;
|
|
|
+ this.file_list = [];
|
|
|
+ this.loadMore();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 加载更多数据
|
|
|
+ loadMore() {
|
|
|
+ if (this.disabled) return;
|
|
|
+ this.loading = true;
|
|
|
+ const params = {
|
|
|
+ page_capacity: this.page_capacity,
|
|
|
+ cur_page: this.cur_page,
|
|
|
+ book_id: this.projectId,
|
|
|
+ type: parseInt(this.drawerType),
|
|
|
+ };
|
|
|
+ PageQueryBookResourceList(params)
|
|
|
+ .then(({ total_count, resource_list }) => {
|
|
|
+ this.total_count = total_count;
|
|
|
+ this.file_list = this.cur_page === 1 ? resource_list : [...this.file_list, ...resource_list];
|
|
|
+ this.cur_page += this.cur_page;
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ this.loading = false;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ async handleFileClick(component_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',
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
@@ -571,6 +702,54 @@ export default {
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ .el-drawer__body {
|
|
|
+ .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: 100%;
|
|
|
+ border: none;
|
|
|
+ border-radius: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-image {
|
|
|
+ display: flex;
|
|
|
+ width: 30%;
|
|
|
+ height: 90px;
|
|
|
+ margin: 6px;
|
|
|
+ background-color: #ccc;
|
|
|
+ border-radius: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .video-play {
|
|
|
+ width: 30%;
|
|
|
+ margin: 6px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ p {
|
|
|
+ color: #999;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|