|  | @@ -49,18 +49,52 @@
 | 
	
		
			
				|  |  |          </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"
 | 
	
		
			
				|  |  | -          :key="icon"
 | 
	
		
			
				|  |  | -          :title="title"
 | 
	
		
			
				|  |  | +          v-for="item in sidebarIconList"
 | 
	
		
			
				|  |  | +          :key="item.icon"
 | 
	
		
			
				|  |  | +          :title="item.title"
 | 
	
		
			
				|  |  |            class="sidebar-icon"
 | 
	
		
			
				|  |  | -          @click="handleSidebarClick(handle)"
 | 
	
		
			
				|  |  | +          @click="handleSidebarClick(item)"
 | 
	
		
			
				|  |  |          >
 | 
	
		
			
				|  |  | -          <SvgIcon :icon-class="`sidebar-${icon}`" size="24" />
 | 
	
		
			
				|  |  | +          <SvgIcon :icon-class="`sidebar-${item.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" /></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" />
 | 
	
		
			
				|  |  | +              </template>
 | 
	
		
			
				|  |  | +            </li>
 | 
	
		
			
				|  |  | +          </ul>
 | 
	
		
			
				|  |  | +          <p v-if="loading">加载中...</p>
 | 
	
		
			
				|  |  | +          <p v-if="noMore">没有更多了</p>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +      </el-drawer>
 | 
	
		
			
				|  |  |      </div>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      <el-dialog
 | 
	
	
		
			
				|  | @@ -104,6 +138,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 +153,7 @@ import {
 | 
	
		
			
				|  |  |    ChapterGetBookChapterStructExpandList,
 | 
	
		
			
				|  |  |    GetBookBaseInfo,
 | 
	
		
			
				|  |  |    MangerGetBookMindMap,
 | 
	
		
			
				|  |  | +  PageQueryBookResourceList,
 | 
	
		
			
				|  |  |  } from '@/api/book';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  export default {
 | 
	
	
		
			
				|  | @@ -126,6 +163,8 @@ export default {
 | 
	
		
			
				|  |  |      MenuPopover,
 | 
	
		
			
				|  |  |      RichText,
 | 
	
		
			
				|  |  |      MindMap,
 | 
	
		
			
				|  |  | +    AudioPlay,
 | 
	
		
			
				|  |  | +    VideoPlay,
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    props: {
 | 
	
		
			
				|  |  |      projectId: {
 | 
	
	
		
			
				|  | @@ -191,9 +230,9 @@ export default {
 | 
	
		
			
				|  |  |          { 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: 'audio', title: '音频', handle: 'openDrawer', type: '1' },
 | 
	
		
			
				|  |  | +        { icon: 'image', title: '图片', handle: 'openDrawer', type: '0' },
 | 
	
		
			
				|  |  | +        { icon: 'video', title: '视频', handle: 'openDrawer', type: '2' },
 | 
	
		
			
				|  |  |          { icon: 'text', title: '文本', handle: '' },
 | 
	
		
			
				|  |  |          { icon: 'collect', title: '收藏', handle: '' },
 | 
	
		
			
				|  |  |          { icon: 'setting', title: '设置', handle: '' },
 | 
	
	
		
			
				|  | @@ -201,8 +240,27 @@ export default {
 | 
	
		
			
				|  |  |        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 +271,9 @@ export default {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      this.getBookChapterStructExpandList();
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  | +  mounted() {
 | 
	
		
			
				|  |  | +    this.calcDrawerPosition();
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  |    methods: {
 | 
	
		
			
				|  |  |      getProjectBaseInfo() {
 | 
	
		
			
				|  |  |        GetProjectBaseInfo({ id: this.projectId }).then(({ project_info }) => {
 | 
	
	
		
			
				|  | @@ -361,11 +422,16 @@ export default {
 | 
	
		
			
				|  |  |       * @param {string} handle - 处理函数名
 | 
	
		
			
				|  |  |       * @param {any} param - 处理函数参数
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  | -    handleSidebarClick(handle, param) {
 | 
	
		
			
				|  |  | -      if (typeof handle === 'string' && handle && typeof this[handle] === 'function') {
 | 
	
		
			
				|  |  | -        this[handle](param);
 | 
	
		
			
				|  |  | +    handleSidebarClick(item) {
 | 
	
		
			
				|  |  | +      let handle = item.handle;
 | 
	
		
			
				|  |  | +      if (typeof this[handle] === 'function') {
 | 
	
		
			
				|  |  | +        this[handle](item.type);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | +      // if (typeof handle === 'string' && handle && typeof this[handle] === 'function') {
 | 
	
		
			
				|  |  | +      //   this[handle](param);
 | 
	
		
			
				|  |  | +      // }
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      openMindMap() {
 | 
	
		
			
				|  |  |        MangerGetBookMindMap({ book_id: this.projectId }).then(({ content }) => {
 | 
	
		
			
				|  |  |          if (content) {
 | 
	
	
		
			
				|  | @@ -392,6 +458,66 @@ 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`,
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    // 打开抽屉并初始化加载
 | 
	
		
			
				|  |  | +    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 +697,52 @@ export default {
 | 
	
		
			
				|  |  |          cursor: pointer;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    .el-drawer__body {
 | 
	
		
			
				|  |  | +      .scroll-container {
 | 
	
		
			
				|  |  | +        display: flex;
 | 
	
		
			
				|  |  | +        flex-direction: column;
 | 
	
		
			
				|  |  | +        row-gap: 8px;
 | 
	
		
			
				|  |  | +        margin: 6px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        .list-item {
 | 
	
		
			
				|  |  | +          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;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 |