|
|
@@ -0,0 +1,450 @@
|
|
|
+<template>
|
|
|
+ <div class="common-preview">
|
|
|
+ <div class="common-preview__header">
|
|
|
+ <div class="menu-container">
|
|
|
+ <MenuPopover :node-list="node_list" :book-name="courseware_info.book_name" @selectNode="selectNode" />
|
|
|
+ </div>
|
|
|
+ <!-- <div class="courseware">
|
|
|
+ <span class="name-path">{{ courseware_info.name_path }}</span>
|
|
|
+ <span class="flow-nodename">{{ courseware_info.cur_audit_flow_node_name }}</span>
|
|
|
+ <slot name="middle" :courseware="courseware_info"></slot>
|
|
|
+ <div class="group">
|
|
|
+ <el-checkbox v-model="isShowGroup">显示分组</el-checkbox>
|
|
|
+ <el-checkbox v-model="groupShowAll">分组显示全部</el-checkbox>
|
|
|
+ <el-checkbox v-model="isJudgeCorrect">判断对错</el-checkbox>
|
|
|
+ <el-checkbox v-model="isShowAnswer" :disabled="!isJudgeCorrect">显示答案</el-checkbox>
|
|
|
+ </div>
|
|
|
+ <span class="link">
|
|
|
+ <el-select v-model="lang" placeholder="请选择语言" size="mini" class="lang-select">
|
|
|
+ <el-option v-for="item in langList" :key="item.type" :label="item.name" :value="item.type" />
|
|
|
+ </el-select>
|
|
|
+ </span>
|
|
|
+ <div class="operator">
|
|
|
+ <slot name="operator" :courseware="courseware_info"></slot>
|
|
|
+ </div>
|
|
|
+ </div> -->
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="audit-content">
|
|
|
+ <div ref="previewMain" class="main-container">
|
|
|
+ <main :class="['preview-main']">
|
|
|
+ <span class="title" :style="{ backgroundColor: unified_attrib?.topic_color }">
|
|
|
+ <SvgIcon icon-class="menu-2" size="24" />
|
|
|
+ <span>{{ courseware_info.name_path }}</span>
|
|
|
+ </span>
|
|
|
+ <MobileCoursewarePreview
|
|
|
+ v-if="courseware_info.book_name"
|
|
|
+ ref="courserware"
|
|
|
+ :is-show-group="isShowGroup"
|
|
|
+ :group-show-all="groupShowAll"
|
|
|
+ :group-row-list="content_group_row_list"
|
|
|
+ :data="data"
|
|
|
+ :component-list="component_list"
|
|
|
+ :background="background"
|
|
|
+ :can-remark="isTrue(courseware_info.is_my_audit_task) && isTrue(courseware_info.is_can_add_audit_remark)"
|
|
|
+ :show-remark="false"
|
|
|
+ :component-remark-obj="remark_list_obj"
|
|
|
+ @computeScroll="computeScroll"
|
|
|
+ />
|
|
|
+ </main>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import MobileCoursewarePreview from '@/views/book/courseware/preview/MobileCoursewarePreview.vue';
|
|
|
+import MenuPopover from '@/views/personal_workbench/common/MenuPopover.vue';
|
|
|
+import { isTrue } from '@/utils/validate';
|
|
|
+import * as OpenCC from 'opencc-js';
|
|
|
+
|
|
|
+import { GetBookCoursewareInfo, GetCoursewareAuditRemarkList } from '@/api/project';
|
|
|
+import {
|
|
|
+ ContentGetCoursewareContent_View,
|
|
|
+ ChapterGetBookChapterStructExpandList,
|
|
|
+ GetBookBaseInfo,
|
|
|
+ GetLanguageTypeList,
|
|
|
+ GetBookUnifiedAttrib,
|
|
|
+} from '@/api/book';
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'CommonPreview',
|
|
|
+ components: {
|
|
|
+ MobileCoursewarePreview,
|
|
|
+ MenuPopover,
|
|
|
+ },
|
|
|
+ provide() {
|
|
|
+ return {
|
|
|
+ getLang: () => this.lang,
|
|
|
+ getChinese: () => this.chinese,
|
|
|
+ getLangList: () => this.langList,
|
|
|
+ convertText: this.convertText,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ book_id: this.$route.query.book_id || '',
|
|
|
+ select_node: '',
|
|
|
+ courseware_info: {
|
|
|
+ book_name: '',
|
|
|
+ is_can_start_edit: 'false',
|
|
|
+ is_can_submit_audit: 'false',
|
|
|
+ is_can_audit_pass: 'false',
|
|
|
+ is_can_audit_reject: 'false',
|
|
|
+ is_can_add_audit_remark: 'false',
|
|
|
+ is_can_finish_audit: 'false',
|
|
|
+ is_can_request_shangjia_book: 'false',
|
|
|
+ is_can_request_rollback_project: 'false',
|
|
|
+ is_can_shangjia_book: 'false',
|
|
|
+ is_can_rollback_project: 'false',
|
|
|
+ },
|
|
|
+ background: {
|
|
|
+ background_image_url: '',
|
|
|
+ background_position: {
|
|
|
+ left: 0,
|
|
|
+ top: 0,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ node_list: [],
|
|
|
+ data: { row_list: [] },
|
|
|
+ component_list: [],
|
|
|
+ content_group_row_list: [],
|
|
|
+ remark_list: [],
|
|
|
+ remark_list_obj: {}, // 存放以组件为对象的数组
|
|
|
+ visible: false,
|
|
|
+ remark_content: '',
|
|
|
+ submit_loading: false,
|
|
|
+ isTrue,
|
|
|
+ menuPosition: {
|
|
|
+ x: -1,
|
|
|
+ y: -1,
|
|
|
+ componentId: 'WHOLE',
|
|
|
+ },
|
|
|
+ sidebarIconList: [
|
|
|
+ { 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,
|
|
|
+ isShowGroup: false,
|
|
|
+ groupShowAll: true,
|
|
|
+ opencc: OpenCC.Converter({ from: 'cn', to: 'tw' }),
|
|
|
+ langList: [],
|
|
|
+ lang: 'ZH',
|
|
|
+ chinese: 'zh-Hans',
|
|
|
+ isJudgeCorrect: false,
|
|
|
+ isShowAnswer: false,
|
|
|
+ unified_attrib: {},
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ disabled() {
|
|
|
+ return this.loading || this.noMore;
|
|
|
+ },
|
|
|
+ noMore() {
|
|
|
+ return this.file_list.length >= this.total_count && this.total_count > 0;
|
|
|
+ },
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ isJudgeCorrect(newVal) {
|
|
|
+ if (!newVal) {
|
|
|
+ this.isShowAnswer = false;
|
|
|
+ }
|
|
|
+ this.simulateAnswer(newVal);
|
|
|
+ },
|
|
|
+ isShowAnswer() {
|
|
|
+ this.simulateAnswer();
|
|
|
+ },
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.getBookBaseInfo();
|
|
|
+ this.getBookChapterStructExpandList();
|
|
|
+ this.getBookUnifiedAttr();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ getBookBaseInfo() {
|
|
|
+ GetBookBaseInfo({ id: this.book_id }).then(({ book_info }) => {
|
|
|
+ this.courseware_info = { ...this.courseware_info, ...book_info, book_name: book_info.name };
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 得到教材课件信息
|
|
|
+ * @param {string} id - 课件ID
|
|
|
+ */
|
|
|
+ getBookCoursewareInfo(id) {
|
|
|
+ GetBookCoursewareInfo({ id, is_contain_producer: 'true', is_contain_auditor: 'true' }).then(
|
|
|
+ ({ courseware_info }) => {
|
|
|
+ this.courseware_info = { ...this.courseware_info, ...courseware_info };
|
|
|
+ this.getLangList();
|
|
|
+ },
|
|
|
+ );
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 得到课件内容(展示内容)
|
|
|
+ * @param {string} id - 课件ID
|
|
|
+ */
|
|
|
+ getCoursewareComponentContent_View(id) {
|
|
|
+ ContentGetCoursewareContent_View({ id }).then(({ content, component_list, content_group_row_list }) => {
|
|
|
+ if (content) {
|
|
|
+ const _content = JSON.parse(content);
|
|
|
+ this.data = _content;
|
|
|
+ this.background = {
|
|
|
+ background_image_url: _content.background_image_url,
|
|
|
+ background_position: _content.background_position,
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ this.data = { row_list: [] };
|
|
|
+ }
|
|
|
+
|
|
|
+ if (component_list) this.component_list = component_list;
|
|
|
+ if (content_group_row_list) this.content_group_row_list = JSON.parse(content_group_row_list) || [];
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ getLangList() {
|
|
|
+ GetLanguageTypeList({ book_id: this.courseware_info.book_id, is_contain_zh: 'true' }).then(
|
|
|
+ ({ language_type_list }) => {
|
|
|
+ this.langList = language_type_list;
|
|
|
+ },
|
|
|
+ );
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 得到教材章节结构展开列表
|
|
|
+ */
|
|
|
+ getBookChapterStructExpandList() {
|
|
|
+ ChapterGetBookChapterStructExpandList({
|
|
|
+ book_id: this.book_id,
|
|
|
+ node_deep_mode: 0,
|
|
|
+ is_contain_producer: 'true',
|
|
|
+ is_contain_auditor: 'true',
|
|
|
+ }).then(({ node_list }) => {
|
|
|
+ this.node_list = node_list;
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ getBookUnifiedAttr() {
|
|
|
+ GetBookUnifiedAttrib({ book_id: this.book_id }).then(({ content }) => {
|
|
|
+ if (content) {
|
|
|
+ this.unified_attrib = JSON.parse(content);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 选择节点
|
|
|
+ * @param {string} nodeId - 节点ID
|
|
|
+ */
|
|
|
+ selectNode(nodeId) {
|
|
|
+ this.getCoursewareComponentContent_View(nodeId);
|
|
|
+ this.getBookCoursewareInfo(nodeId);
|
|
|
+ this.getCoursewareAuditRemarkList(nodeId);
|
|
|
+ this.select_node = nodeId;
|
|
|
+ },
|
|
|
+ // 审校批注列表
|
|
|
+ getCoursewareAuditRemarkList(id) {
|
|
|
+ this.remark_list = [];
|
|
|
+ let remarkListObj = {};
|
|
|
+ GetCoursewareAuditRemarkList({
|
|
|
+ courseware_id: id,
|
|
|
+ }).then(({ remark_list }) => {
|
|
|
+ this.remark_list = remark_list;
|
|
|
+ if (!remark_list) return;
|
|
|
+ remarkListObj = remark_list.reduce((acc, item) => {
|
|
|
+ if (!acc[item.component_id]) {
|
|
|
+ acc[item.component_id] = [];
|
|
|
+ }
|
|
|
+ acc[item.component_id].push(item);
|
|
|
+ return acc;
|
|
|
+ }, {});
|
|
|
+
|
|
|
+ this.remark_list_obj = remarkListObj;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ dialogClose(type) {
|
|
|
+ this[`visible${type}`] = false;
|
|
|
+ },
|
|
|
+ // 计算previewMain滑动距离
|
|
|
+ computeScroll() {
|
|
|
+ this.$refs.courserware.handleResult(
|
|
|
+ this.$refs.previewMain.scrollTop,
|
|
|
+ this.$refs.previewMain.scrollLeft,
|
|
|
+ this.select_node,
|
|
|
+ );
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 文本转换
|
|
|
+ * @param {string} text - 要转换的文本
|
|
|
+ * @returns {string} - 转换后的文本
|
|
|
+ */
|
|
|
+ convertText(text) {
|
|
|
+ if (this.chinese === 'zh-Hant' && this.opencc) {
|
|
|
+ return this.opencc(text);
|
|
|
+ }
|
|
|
+ return text;
|
|
|
+ },
|
|
|
+
|
|
|
+ simulateAnswer(disabled = true) {
|
|
|
+ this.$refs.courserware.simulateAnswer(this.isJudgeCorrect, this.isShowAnswer, disabled);
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+@use '@/styles/mixin.scss' as *;
|
|
|
+
|
|
|
+.common-preview {
|
|
|
+ &__header {
|
|
|
+ position: sticky;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ z-index: 9;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ height: 40px;
|
|
|
+ padding: 6px 4px;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ background-color: #fff;
|
|
|
+ border-top: $border;
|
|
|
+ border-bottom: $border;
|
|
|
+
|
|
|
+ > .menu-container {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ width: 360px;
|
|
|
+ padding: 4px 8px;
|
|
|
+ border-right: $border;
|
|
|
+ }
|
|
|
+
|
|
|
+ > .courseware {
|
|
|
+ display: flex;
|
|
|
+ flex-grow: 1;
|
|
|
+ column-gap: 16px;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ height: 40px;
|
|
|
+
|
|
|
+ .name-path {
|
|
|
+ min-width: 200px;
|
|
|
+ height: 40px;
|
|
|
+ padding: 4px 8px;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 32px;
|
|
|
+ border-right: $border;
|
|
|
+ }
|
|
|
+
|
|
|
+ .lang-select {
|
|
|
+ :deep .el-input {
|
|
|
+ width: 100px;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep .el-input__inner {
|
|
|
+ height: 24px;
|
|
|
+ line-height: 24px;
|
|
|
+ background-color: #fff;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep .el-input__icon {
|
|
|
+ line-height: 24px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .flow-nodename {
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .group {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .operator {
|
|
|
+ display: flex;
|
|
|
+ column-gap: 8px;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ .link {
|
|
|
+ + .link {
|
|
|
+ margin-left: 0;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ margin-right: 8px;
|
|
|
+ color: #999;
|
|
|
+ content: '|';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .main-container {
|
|
|
+ flex: 1;
|
|
|
+ width: 100%;
|
|
|
+ overflow: auto;
|
|
|
+ }
|
|
|
+
|
|
|
+ main.preview-main {
|
|
|
+ display: flex;
|
|
|
+ flex: 1;
|
|
|
+ flex-direction: column;
|
|
|
+ row-gap: 5px;
|
|
|
+ width: 100%;
|
|
|
+ min-height: 100%;
|
|
|
+ padding: 5px;
|
|
|
+ margin: 0 auto;
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius: 4px;
|
|
|
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 10%);
|
|
|
+
|
|
|
+ .title {
|
|
|
+ display: inline-flex;
|
|
|
+ column-gap: 24px;
|
|
|
+ align-items: center;
|
|
|
+ width: 100%;
|
|
|
+ min-width: 280px;
|
|
|
+ height: 64px;
|
|
|
+ padding: 18px 24px;
|
|
|
+ font-size: 20px;
|
|
|
+ color: #fff;
|
|
|
+ background-color: #f44444;
|
|
|
+ border-top-left-radius: 12px;
|
|
|
+ border-top-right-radius: 16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .audit-content {
|
|
|
+ display: flex;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.tox-tinymce-aux {
|
|
|
+ z-index: 9999 !important;
|
|
|
+}
|
|
|
+</style>
|