Bläddra i källkod

Merge branch 'master' of http://60.205.254.193:3000/GCLS/eep_page

dsy 2 dagar sedan
förälder
incheckning
d07e23b1ff

+ 16 - 0
src/api/book.js

@@ -388,3 +388,19 @@ export function GetBookChapterStructExpandList(data) {
     data,
   );
 }
+
+/**
+ * @description 保存教材标题样式
+ * @param {Object} data
+ */
+export function SaveTitleStyle(data) {
+  return http.post(`${process.env.VUE_APP_EepServer}?MethodName=book_content_manager-SaveTitleStyle`, data);
+}
+
+/**
+ * @description 得到教材全标题样式
+ * @param {Object} data
+ */
+export function GetTitleStyle(data) {
+  return http.post(`${process.env.VUE_APP_EepServer}?MethodName=book_content_manager-GetTitleStyle`, data);
+}

+ 12 - 0
src/common/data.js

@@ -10,3 +10,15 @@ export const unified_attrib = {
   view_pinyin: 'false', // 启用拼音
   pinyin_position: 'top', // 拼音位置 top:上方 bottom:下方
 };
+
+export const unified_title = {
+  level: 1,
+  level_title: '一级标题', // 级别名称
+  font: '宋体,微软雅黑', // 字体
+  font_size: '14pt', // 字号
+  text_color: '#1d2129', // 文字颜色
+  bold: 'false', // 加粗
+  italic: 'false', //斜体
+  indent: 0, // 缩进
+};
+

+ 1 - 0
src/views/book/courseware/create/components/question/article/CheckPic.vue

@@ -294,6 +294,7 @@ export default {
       .sentence-box {
         .sentence {
           display: flex;
+          flex-flow: wrap;
           margin-top: 8px;
 
           b {

+ 1 - 1
src/views/book/courseware/preview/components/character/CharacterPreview.vue

@@ -61,7 +61,7 @@
                     <span
                       class="items-lian"
                       :style="{
-                        background:
+                        color:
                           data.unified_attrib && data.unified_attrib.topic_color ? data.unified_attrib.topic_color : '',
                       }"
                       >{{ items.con }}</span

+ 5 - 2
src/views/book/courseware/preview/components/table/TablePreview.vue

@@ -29,17 +29,20 @@
                 :style="{
                   borderTop: i === 0 ? '1px solid ' + data.property.border_color : '',
                   borderBottom: '1px solid ' + data.property.border_color,
+
                   borderLeft:
                     i === 0 && data.property.first_line_color
                       ? '1px solid ' + data.property.border_color
                       : j === 0
-                        ? '2px solid ' + data.property.decoration_color
+                        ? '2px solid ' +
+                          (data.property.decoration_color ? data.property.decoration_color : data.property.border_color)
                         : '1px dotted ' + data.property.border_color,
                   borderRight:
                     i === 0 && data.property.first_line_color
                       ? '1px solid ' + data.property.border_color
                       : j === row.length - 1
-                        ? '2px solid ' + data.property.decoration_color
+                        ? '2px solid ' +
+                          (data.property.decoration_color ? data.property.decoration_color : data.property.border_color)
                         : '1px dotted ' + data.property.border_color,
                   borderRadius: i === 0 && data.property.first_line_color ? '4px ' : '0',
                   background:

+ 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="openBookUnifiedTitle()">教材标题设置</span>
           <span class="link" @click="openBookUnifiedAttrib()">教材样式设置</span>
           <span class="link" @click="addChapterDialog()">添加章节节点</span>
           <span class="link" @click="addCoursewareDialog()">添加教材内容节点</span>
@@ -150,6 +151,7 @@
 
     <UpdateName :name="name.name" :visible.sync="name.visible" @submit="updateName" />
     <BookUnifiedAttr :visible.sync="visibleAttr" :book-id="book_id" />
+    <BookUnifiedTitle :visible.sync="visibleTitle" :book-id="book_id" />
   </div>
 </template>
 
@@ -161,6 +163,7 @@ 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 BookUnifiedTitle from './components/BookUnifiedTitle.vue';
 
 import { GetProjectBaseInfo } from '@/api/project';
 import {
@@ -186,6 +189,7 @@ export default {
     SetAuditor,
     UpdateName,
     BookUnifiedAttr,
+    BookUnifiedTitle,
   },
   data() {
     return {
@@ -216,6 +220,7 @@ export default {
         id: '', // 章节ID
       },
       visibleAttr: false, // 教材属性设置弹窗
+      visibleTitle: false, // 教材标题设置弹窗
     };
   },
   created() {
@@ -290,6 +295,9 @@ export default {
         this.curSelectId = '';
       }
     },
+    openBookUnifiedTitle() {
+      this.visibleTitle = true;
+    },
     openBookUnifiedAttrib() {
       this.visibleAttr = true;
     },

+ 274 - 0
src/views/personal_workbench/project/components/BookUnifiedTitle.vue

@@ -0,0 +1,274 @@
+<template>
+  <el-dialog
+    title="教材标题设置"
+    :visible="visible"
+    width="1200px"
+    :close-on-click-modal="false"
+    class="book-unified-title"
+    @close="dialogClose"
+  >
+    <div class="setting-top">
+      <div class="form">
+        <el-form ref="form" :model="formModel" label-width="50" size="small">
+          <!-- 5列标题级别设置 -->
+          <div class="levels-container">
+            <div class="level-column" v-for="(item, index) in titleSettings" :key="index">
+              <div class="level-header">{{ item.level_title }}</div>
+
+              <!-- 字体 -->
+              <el-form-item label="字体">
+                <el-select v-model="item.font" placeholder="请选择字体" style="width: 120px">
+                  <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="item.font_size" placeholder="请选择字号" style="width: 100px">
+                  <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="item.bold" active-value="true" inactive-value="false" />
+              </el-form-item>
+
+              <!-- 斜体 -->
+              <el-form-item label="斜体">
+                <el-switch v-model="item.italic" active-value="true" inactive-value="false" />
+              </el-form-item>
+
+              <!-- 文字颜色 -->
+              <el-form-item label="文字颜色">
+                <el-color-picker v-model="item.text_color" style="width: 40px" />
+              </el-form-item>
+
+              <!-- 缩进 -->
+              <el-form-item label="缩进">
+                <div style="display: flex; align-items: center">
+                  <el-input-number
+                    v-model="item.indent"
+                    :min="0"
+                    :max="10"
+                    :step="1"
+                    controls-position="right"
+                    placeholder="0"
+                    style="width: 80px"
+                  />
+                  <span style="margin-left: 8px; font-size: 12px; color: #909399">字符</span>
+                </div>
+              </el-form-item>
+            </div>
+          </div>
+        </el-form>
+      </div>
+    </div>
+
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="dialogClose">取 消</el-button>
+      <el-button type="primary" @click="saveBookUnifiedTitle">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { GetTitleStyle, ApplyBookUnifiedAttrib, SaveTitleStyle } from '@/api/book';
+import { unified_title } from '@/common/data';
+
+export default {
+  name: 'BookUnifiedTitlePage',
+  props: {
+    visible: {
+      type: Boolean,
+      required: true,
+    },
+    bookId: {
+      type: String,
+      required: true,
+    },
+  },
+  data() {
+    return {
+      fontSizeList: [
+        '8pt',
+        '10pt',
+        '12pt',
+        '14pt',
+        '16pt',
+        '18pt',
+        '20pt',
+        '22pt',
+        '24pt',
+        '26pt',
+        '28pt',
+        '30pt',
+        '32pt',
+        '34pt',
+        '36pt',
+      ],
+      titleSettings: [],
+      defaultTitleSettings: [],
+      formModel: {},
+    };
+  },
+  watch: {
+    visible(newVal) {
+      if (newVal) {
+        this.getBookUnifiedTitle();
+      }
+    },
+  },
+  created() {
+    this.initTitleSettings();
+  },
+  methods: {
+    initTitleSettings() {
+      // 各级别的默认字号
+      const defaultFontSizes = ['16pt', '14pt', '12pt', '10pt', '8pt'];
+
+      this.defaultTitleSettings = Array.from({ length: 5 }, (_, index) => {
+        return {
+          level: index + 1,
+          level_title: this.getLevelLabel(index + 1),
+          font: unified_title.font,
+          font_size: defaultFontSizes[index] || unified_title.font_size,
+          text_color: unified_title.text_color,
+          bold: unified_title.bold,
+          italic: unified_title.italic,
+          indent: unified_title.indent,
+        };
+      });
+    },
+    getLevelLabel(level) {
+      const labels = ['一级标题', '二级标题', '三级标题', '四级标题', '五级标题'];
+      return labels[level - 1];
+    },
+    async getBookUnifiedTitle() {
+      this.titleSettings = [];
+      let isSuccess = false;
+      await GetTitleStyle({ book_id: this.bookId }).then(({ title_list }) => {
+        if (title_list && title_list.length > 0) {
+          isSuccess = true;
+
+          for (let i = 1; i <= 5; i++) {
+            let en = title_list.find((x) => x.level == i);
+            let style = en.style ? JSON.parse(en.style) : {};
+            let defStyle = this.defaultTitleSettings[i - 1];
+            style = Object.assign({}, defStyle, style);
+
+            // 但这样会覆盖所有默认值,需要额外处理空值
+            Object.keys(style).forEach((key) => {
+              if (!style[key] && style[key] !== 0) {
+                style[key] = defStyle[key] || ''; // 用默认值替换空值
+              }
+            });
+            this.titleSettings.push(style);
+          }
+        }
+      });
+
+      if (!isSuccess) this.titleSettings = this.defaultTitleSettings;
+    },
+    applyBookUnifiedAttr() {
+      let loading = this.$loading({ fullscreen: true, text: '正在应用,请稍后...' });
+      ApplyBookUnifiedAttrib({
+        book_id: this.bookId,
+        content: JSON.stringify(this.unified_title),
+      })
+        .then(() => {
+          this.$message.success('应用成功');
+          this.dialogClose();
+        })
+        .finally(() => {
+          loading.close();
+        });
+    },
+    saveBookUnifiedTitle() {
+      let title_list = [];
+      this.titleSettings.forEach((config, index) => {
+        let tmp = { level: config.level, style: JSON.stringify(config) };
+        title_list.push(tmp);
+      });
+
+      let data = { book_id: this.bookId, title_list: title_list };
+
+      SaveTitleStyle(data).then(() => {
+        this.$message.success('保存成功');
+        this.dialogClose();
+      });
+    },
+    dialogClose() {
+      this.$emit('update:visible', false);
+      this.$emit('close');
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.book-unified-title {
+  .setting-top {
+    display: flex;
+
+    .form {
+      flex: 1;
+
+      .levels-container {
+        display: grid;
+        grid-template-columns: repeat(5, 1fr);
+        gap: 15px;
+      }
+
+      .level-column {
+        padding: 12px;
+
+        // background: #fafafa;
+        border: 1px solid #ebeef5;
+        border-radius: 4px;
+      }
+
+      .level-header {
+        padding-bottom: 6px;
+        margin-bottom: 12px;
+        font-weight: bold;
+        color: #333;
+        text-align: center;
+        border-bottom: 1px solid #ebeef5;
+      }
+
+      .el-select {
+        width: 150px !important;
+      }
+
+      .el-input-number {
+        width: calc(100% - 40px) !important;
+      }
+
+      .color-group {
+        display: flex;
+        column-gap: 10px;
+        align-items: center;
+
+        span {
+          white-space: nowrap;
+        }
+      }
+    }
+  }
+
+  .setting-bottom {
+    display: flex;
+    column-gap: 10px;
+    align-items: center;
+    padding-top: 20px;
+    margin-top: 20px;
+    border-top: $border;
+  }
+}
+</style>