2 次代碼提交 27cb32a643 ... 40243925f2

作者 SHA1 備註 提交日期
  dsy 40243925f2 Merge branch 'master' of http://60.205.254.193:3000/GCLS/eep_page 5 天之前
  dsy eaf0b0b056 全文设置 5 天之前

+ 24 - 0
src/api/book.js

@@ -258,3 +258,27 @@ export function GetCoursewareExercise(data) {
 export function GetCoursewareExerciseView(data) {
   return http.post(`${process.env.VUE_APP_EepServer}?MethodName=book_content_manager-GetCoursewareExercise_View`, data);
 }
+
+/**
+ * @description 保存教材全文设置
+ * @param {Object} data
+ */
+export function SaveBookUnifiedAttrib(data) {
+  return http.post(`${process.env.VUE_APP_EepServer}?MethodName=book_content_manager-SaveBookUnifiedAttrib`, data);
+}
+
+/**
+ * @description 应用教材全文设置
+ * @param {Object} data
+ */
+export function ApplyBookUnifiedAttrib(data) {
+  return http.post(`${process.env.VUE_APP_EepServer}?MethodName=book_content_manager-ApplyBookUnifiedAttrib`, data);
+}
+
+/**
+ * @description 得到教材全文设置
+ * @param {Object} data
+ */
+export function GetBookUnifiedAttrib(data) {
+  return http.post(`${process.env.VUE_APP_EepServer}?MethodName=book_content_manager-GetBookUnifiedAttrib`, data);
+}

+ 14 - 0
src/components/RichText.vue

@@ -353,7 +353,10 @@ export default {
           }
           break;
         }
+
         case 'fontSize':
+        case 'lineHeight':
+        case 'color':
         case 'fontFamily': {
           editor.formatter.register('my_customformat', {
             inline: 'span',
@@ -364,6 +367,17 @@ export default {
           break;
         }
 
+        case 'align': {
+          if (val === 'LEFT') {
+            editor.execCommand('JustifyLeft');
+          } else if (val === 'MIDDLE') {
+            editor.execCommand('JustifyCenter');
+          } else if (val === 'RIGHT') {
+            editor.execCommand('JustifyRight');
+          }
+          break;
+        }
+
         default: {
           editor.formatter.toggle(type);
         }

+ 63 - 8
src/views/book/courseware/create/components/CreateCanvas.vue

@@ -76,6 +76,7 @@
                   :data-row="i"
                   :data-col="j"
                   :data-grid="k"
+                  :data-view-order="computedGridViewOrder(grid.id)"
                   :border-color="computedBorderColor(row.row_id)"
                   :style="computedGridStyle(grid, row.row_id)"
                   :component-move="componentMove(i, j, k)"
@@ -122,7 +123,7 @@
 
     <FullTextSettings
       :visible.sync="visibleFullTextSettings"
-      :settings="data.full_text_settings"
+      :settings="data.unified_attrib"
       @fullTextSettings="fullTextSettings"
     />
   </main>
@@ -167,10 +168,16 @@ export default {
         // 组件列表
         row_list: [],
         // 全文设置
-        full_text_settings: {
-          view_pinyin: 'false',
-          fontfamily: 'Arial,Helvetica,sans-serif',
-          fontsize: '12pt',
+        unified_attrib: {
+          topic_color: '#165dff',
+          font: '宋体,微软雅黑',
+          font_size: '12pt',
+          pinyin_size: '12pt',
+          line_height: 1.5,
+          text_color: '#1d2129',
+          align: 'LEFT',
+          view_pinyin: 'true',
+          pinyin_position: 'top',
         },
       },
       rowCheckList: {}, // 行复选框列表
@@ -353,10 +360,16 @@ export default {
     fullTextSettings(data) {
       this.$refs.component.forEach((item) => {
         item.updateProperty('view_pinyin', data.view_pinyin);
-        item.updateRichTextProperty('fontFamily', data.fontFamily);
-        item.updateRichTextProperty('fontSize', data.fontSize);
+        item.updateProperty('pinyin_position', data.pinyin_position);
+        item.updateRichTextProperty('fontFamily', data.font);
+        item.updateRichTextProperty('fontSize', data.font_size);
+        item.updateRichTextProperty('lineHeight', data.line_height);
+        item.updateRichTextProperty('color', data.text_color);
+        item.updateRichTextProperty('align', data.align);
+
+        item.setUnifiedAttr(data);
       });
-      this.data.full_text_settings = data;
+      this.data.unified_attrib = data;
     },
     /**
      * 保存课件内容
@@ -1201,6 +1214,48 @@ export default {
         marginTop,
       };
     },
+    /**
+     * 计算网格视图顺序
+     * @param {String} id 网格 ID
+     * @returns {Number} 顺序值
+     */
+    computedGridViewOrder(id) {
+      // 获取网格 id,是第几行第几列第几个网格,通过 data.row_list 计算
+      let rowIndex = -1;
+      let colIndex = -1;
+      let gridIndex = -1;
+
+      this.data.row_list.forEach((row, i) => {
+        row.col_list.forEach((col, j) => {
+          col.grid_list.forEach((grid, k) => {
+            if (grid.id === id) {
+              rowIndex = i;
+              colIndex = j;
+              gridIndex = k;
+            }
+          });
+        });
+      });
+
+      let order = 0;
+      // 计算前几行的网格数量
+      if (rowIndex > 0) {
+        for (let i = 0; i < rowIndex; i++) {
+          this.data.row_list[i].col_list.forEach((col) => {
+            order += col.grid_list.length;
+          });
+        }
+      }
+      // 计算当前行前几列的网格数量
+      if (colIndex > 0) {
+        for (let j = 0; j < colIndex; j++) {
+          order += this.data.row_list[rowIndex].col_list[j].grid_list.length;
+        }
+      }
+      // 加上当前列前面的网格数量
+      order += gridIndex + 1;
+      return order;
+    },
   },
 };
 </script>

+ 54 - 16
src/views/book/courseware/create/components/FullTextSettings.vue

@@ -7,9 +7,12 @@
     :before-close="handleClose"
     title="全文设置"
   >
-    <el-form ref="form" :model="formData" label-width="80px">
+    <el-form ref="form" :model="unified_attrib" label-width="80px" size="small">
+      <el-form-item label="主题色">
+        <el-color-picker v-model="unified_attrib.topic_color" />
+      </el-form-item>
       <el-form-item label="字体">
-        <el-select v-model="formData.fontFamily" placeholder="请选择字体" style="width: 100%">
+        <el-select v-model="unified_attrib.font" placeholder="请选择字体">
           <el-option label="楷体" value="楷体,微软雅黑" />
           <el-option label="黑体" value="黑体,微软雅黑" />
           <el-option label="宋体" value="宋体,微软雅黑" />
@@ -19,22 +22,50 @@
         </el-select>
       </el-form-item>
       <el-form-item label="字号">
-        <el-select v-model="formData.fontSize" placeholder="请选择字号" style="width: 100%">
+        <el-select v-model="unified_attrib.font_size" placeholder="请选择字号">
+          <el-option v-for="size in fontSizeList" :key="size" :label="size" :value="size" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="拼音字号">
+        <el-select v-model="unified_attrib.pinyin_size" placeholder="请选择拼音字号">
           <el-option v-for="size in fontSizeList" :key="size" :label="size" :value="size" />
         </el-select>
       </el-form-item>
-      <el-form-item label="全文拼音">
-        <el-switch v-model="formData.view_pinyin" active-value="true" inactive-value="false" />
+      <el-form-item label="行距">
+        <el-input-number v-model="unified_attrib.line_height" :min="0" :max="20" :step="0.1" />
+      </el-form-item>
+      <el-form-item label="文字颜色">
+        <el-color-picker v-model="unified_attrib.text_color" />
+      </el-form-item>
+      <el-form-item label="对齐方式">
+        <el-select v-model="unified_attrib.align" placeholder="请选择对齐方式">
+          <el-option label="左对齐" value="LEFT" />
+          <el-option label="居中" value="MIDDLE" />
+          <el-option label="右对齐" value="RIGHT" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="拼音">
+        <el-switch v-model="unified_attrib.view_pinyin" active-value="true" inactive-value="false" />
       </el-form-item>
-      <el-form-item>
-        <el-button type="primary" @click="confirm">确定</el-button>
-        <el-button @click="handleClose">取消</el-button>
+      <el-form-item label="拼音位置">
+        <el-radio-group v-model="unified_attrib.pinyin_position" :disabled="!isEnable(unified_attrib.view_pinyin)">
+          <el-radio v-for="{ value, label } in pinyinPositionList" :key="value" :label="value">
+            {{ label }}
+          </el-radio>
+        </el-radio-group>
       </el-form-item>
     </el-form>
+
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="handleClose">取 消</el-button>
+      <el-button type="primary" @click="confirm">确 定</el-button>
+    </div>
   </el-dialog>
 </template>
 
 <script>
+import { pinyinPositionList, isEnable } from '@/views/book/courseware/data/common';
+
 export default {
   name: 'FullTextSettings',
   props: {
@@ -49,7 +80,17 @@ export default {
   },
   data() {
     return {
-      // 8pt 到 36pt
+      unified_attrib: {
+        topic_color: '#FFBBCC', // 主题色
+        font: '宋体,微软雅黑', // 字体
+        font_size: '12pt', // 字号
+        pinyin_size: '12pt', // 拼音字号
+        line_height: 1.5, // 行距
+        text_color: '#1d2129', // 文字颜色
+        align: 'LEFT', // 对齐方式 LEFT:左对齐 MIDDLE:居中 RIGHT:右对齐
+        view_pinyin: 'true', // 启用拼音
+        pinyin_position: 'top', // 拼音位置
+      },
       fontSizeList: [
         '8pt',
         '10pt',
@@ -67,17 +108,14 @@ export default {
         '34pt',
         '36pt',
       ],
-      formData: {
-        view_pinyin: 'false',
-        fontFamily: 'Arial,Helvetica,sans-serif',
-        fontSize: '12pt',
-      },
+      pinyinPositionList,
+      isEnable,
     };
   },
   watch: {
     visible(val) {
       if (val) {
-        this.formData = { ...this.settings };
+        this.unified_attrib = { ...this.settings };
       }
     },
   },
@@ -87,7 +125,7 @@ export default {
     },
     confirm() {
       this.$emit('update:visible', false);
-      this.$emit('fullTextSettings', this.formData);
+      this.$emit('fullTextSettings', this.unified_attrib);
     },
   },
 };

+ 4 - 0
src/views/book/courseware/create/components/common/ModuleMixin.js

@@ -142,6 +142,10 @@ const mixin = {
         richText.setRichFormat(type, attr);
       });
     },
+    setUnifiedAttr(data) {
+      if (!data) return;
+      this.data.unified_attrib = data;
+    },
     handleComponentMove(data) {
       this.componentMove({ ...data, id: this.id });
     },

+ 8 - 0
src/views/personal_workbench/project/ProductionEditorialManage.vue

@@ -14,6 +14,7 @@
         </div>
         <span class="link" @click="visibleAuditSteps = true">设置审校步骤</span>
         <div class="operator flex">
+          <span class="link" @click="openBookUnifiedAttrib">全文设置</span>
           <span class="link" @click="addChapterDialog">添加章节节点</span>
           <span class="link" @click="addCoursewareDialog">添加教材内容节点</span>
           <span class="link" @click="$router.push({ path: `/personal_workbench/project` })">返回项目列表</span>
@@ -141,6 +142,7 @@
     />
 
     <UpdateName :name="name.name" :visible.sync="name.visible" @submit="updateName" />
+    <BookUnifiedAttr :visible.sync="visibleAttr" :book-id="book_id" />
   </div>
 </template>
 
@@ -151,6 +153,7 @@ import SetAuditSteps from './components/SetAuditSteps.vue';
 import MenuPage from '@/views/personal_workbench/common/menu.vue';
 import SetAuditor from './components/SetAuditor.vue';
 import UpdateName from './components/UpdateName.vue';
+import BookUnifiedAttr from './components/BookUnifiedAttr.vue';
 
 import { GetProjectBaseInfo } from '@/api/project';
 import {
@@ -175,6 +178,7 @@ export default {
     SetAuditSteps,
     SetAuditor,
     UpdateName,
+    BookUnifiedAttr,
   },
   data() {
     return {
@@ -203,6 +207,7 @@ export default {
         isCourse: false, // 是否是课件
         id: '', // 章节ID
       },
+      visibleAttr: false, // 教材属性设置弹窗
     };
   },
   created() {
@@ -277,6 +282,9 @@ export default {
         this.curSelectId = '';
       }
     },
+    openBookUnifiedAttrib() {
+      this.visibleAttr = true;
+    },
     addChapterDialog() {
       this.visible = true;
       this.addType = 'chapter';

+ 192 - 0
src/views/personal_workbench/project/components/BookUnifiedAttr.vue

@@ -0,0 +1,192 @@
+<template>
+  <el-dialog
+    title="全文设置"
+    :visible="visible"
+    width="600px"
+    :close-on-click-modal="false"
+    class="book-unified-attr"
+    @close="dialogClose"
+  >
+    <div class="setting-top">
+      <div class="form">
+        <el-form ref="form" :model="unified_attrib" label-width="80px" size="small">
+          <el-form-item label="主题色">
+            <el-color-picker v-model="unified_attrib.topic_color" />
+          </el-form-item>
+          <el-form-item label="字体">
+            <el-select v-model="unified_attrib.font" placeholder="请选择字体">
+              <el-option label="楷体" value="楷体,微软雅黑" />
+              <el-option label="黑体" value="黑体,微软雅黑" />
+              <el-option label="宋体" value="宋体,微软雅黑" />
+              <el-option label="Arial" value="Arial,Helvetica,sans-serif" />
+              <el-option label="Times New Roman" value="Times New Roman,times,serif" />
+              <el-option label="拼音" value="League" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="字号">
+            <el-select v-model="unified_attrib.font_size" placeholder="请选择字号">
+              <el-option v-for="size in fontSizeList" :key="size" :label="size" :value="size" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="拼音字号">
+            <el-select v-model="unified_attrib.pinyin_size" placeholder="请选择拼音字号">
+              <el-option v-for="size in fontSizeList" :key="size" :label="size" :value="size" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="行距">
+            <el-input-number v-model="unified_attrib.line_height" :min="0" :max="20" :step="0.1" />
+          </el-form-item>
+          <el-form-item label="文字颜色">
+            <el-color-picker v-model="unified_attrib.text_color" />
+          </el-form-item>
+          <el-form-item label="对齐方式">
+            <el-select v-model="unified_attrib.align" placeholder="请选择对齐方式">
+              <el-option label="左对齐" value="LEFT" />
+              <el-option label="居中" value="MIDDLE" />
+              <el-option label="右对齐" value="RIGHT" />
+            </el-select>
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <div class="tips">
+        <p>重置当前教材所有内容</p>
+        <p style="color: #f00">(不包含富文本的现有文字属性)</p>
+      </div>
+    </div>
+    <div class="setting-bottom">
+      <span>拼音</span>
+      <el-switch v-model="unified_attrib.view_pinyin" active-value="true" inactive-value="false" />
+      <span>拼音位置</span>
+      <el-radio-group v-model="unified_attrib.pinyin_position" :disabled="!isEnable(unified_attrib.view_pinyin)">
+        <el-radio v-for="{ value, label } in pinyinPositionList" :key="value" :label="value">
+          {{ label }}
+        </el-radio>
+      </el-radio-group>
+    </div>
+
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="dialogClose">取 消</el-button>
+      <el-button type="primary" @click="applyBookUnifiedAttr">确定</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { pinyinPositionList, isEnable } from '@/views/book/courseware/data/common';
+import { GetBookUnifiedAttrib, ApplyBookUnifiedAttrib } from '@/api/book';
+
+export default {
+  name: 'BookUnifiedAttrPage',
+  props: {
+    visible: {
+      type: Boolean,
+      required: true,
+    },
+    bookId: {
+      type: String,
+      required: true,
+    },
+  },
+  data() {
+    return {
+      unified_attrib: {
+        topic_color: '#FFBBCC', // 主题色
+        font: '宋体,微软雅黑', // 字体
+        font_size: '12pt', // 字号
+        pinyin_size: '12pt', // 拼音字号
+        line_height: 1.5, // 行距
+        text_color: '#1d2129', // 文字颜色
+        align: 'LEFT', // 对齐方式 LEFT:左对齐 MIDDLE:居中 RIGHT:右对齐
+        view_pinyin: 'true', // 启用拼音
+        pinyin_position: 'top', // 拼音位置
+      },
+      fontSizeList: [
+        '8pt',
+        '10pt',
+        '12pt',
+        '14pt',
+        '16pt',
+        '18pt',
+        '20pt',
+        '22pt',
+        '24pt',
+        '26pt',
+        '28pt',
+        '30pt',
+        '32pt',
+        '34pt',
+        '36pt',
+      ],
+      pinyinPositionList,
+      isEnable,
+    };
+  },
+  watch: {
+    visible(newVal) {
+      if (newVal) {
+        this.getBookUnifiedAttr();
+      }
+    },
+  },
+  methods: {
+    getBookUnifiedAttr() {
+      GetBookUnifiedAttrib({ bookId: this.bookId }).then(({ content }) => {
+        if (content) {
+          this.unified_attrib = JSON.parse(content);
+        }
+      });
+    },
+    applyBookUnifiedAttr() {
+      ApplyBookUnifiedAttrib({
+        bookId: this.bookId,
+        content: JSON.stringify(this.unified_attrib),
+      }).then(() => {
+        this.$message.success('应用成功');
+      });
+    },
+    dialogClose() {
+      this.$emit('update:visible', false);
+      this.$emit('close');
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.book-unified-attr {
+  .setting-top {
+    display: flex;
+
+    .form {
+      flex: 1;
+
+      .el-input-number {
+        width: calc(100% - 42px);
+      }
+    }
+
+    .tips {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+      width: 240px;
+      font-size: 12px;
+      line-height: 1.5;
+      text-align: center;
+      background-color: rgba(22, 93, 255, 8%);
+      border-radius: 8px;
+    }
+  }
+
+  .setting-bottom {
+    display: flex;
+    column-gap: 10px;
+    align-items: center;
+    padding-top: 20px;
+    margin-top: 20px;
+    border-top: $border;
+  }
+}
+</style>