فهرست منبع

Merge branch 'lhd'

natasha 7 ماه پیش
والد
کامیت
ab5276f216
27فایلهای تغییر یافته به همراه2589 افزوده شده و 2 حذف شده
  1. BIN
      src/assets/structure/structure-1.png
  2. BIN
      src/assets/structure/structure-10.png
  3. BIN
      src/assets/structure/structure-11.png
  4. BIN
      src/assets/structure/structure-12.png
  5. BIN
      src/assets/structure/structure-13.png
  6. BIN
      src/assets/structure/structure-14.png
  7. BIN
      src/assets/structure/structure-15.png
  8. BIN
      src/assets/structure/structure-2.png
  9. BIN
      src/assets/structure/structure-3.png
  10. BIN
      src/assets/structure/structure-4.png
  11. BIN
      src/assets/structure/structure-5.png
  12. BIN
      src/assets/structure/structure-6.png
  13. BIN
      src/assets/structure/structure-7.png
  14. BIN
      src/assets/structure/structure-8.png
  15. BIN
      src/assets/structure/structure-9.png
  16. 6 1
      src/views/book/courseware/create/components/base/common/UploadFile.vue
  17. 284 0
      src/views/book/courseware/create/components/question/character_structure/CharacterStructure.vue
  18. 40 0
      src/views/book/courseware/create/components/question/character_structure/CharacterStructureSetting.vue
  19. 97 0
      src/views/book/courseware/create/components/question/newWord_template/NewWordTemplate.vue
  20. 32 0
      src/views/book/courseware/create/components/question/newWord_template/NewWordTemplateSetting.vue
  21. 0 1
      src/views/book/courseware/create/components/question/new_word/NewWord.vue
  22. 23 0
      src/views/book/courseware/data/bookType.js
  23. 147 0
      src/views/book/courseware/data/characterStructure.js
  24. 66 0
      src/views/book/courseware/data/newWordTemplate copy.js
  25. 66 0
      src/views/book/courseware/data/newWordTemplate.js
  26. 914 0
      src/views/book/courseware/preview/components/character_structure/CharacterStructurePreview.vue
  27. 914 0
      src/views/book/courseware/preview/components/newWord_template/NewWordTemplatePreview.vue

BIN
src/assets/structure/structure-1.png


BIN
src/assets/structure/structure-10.png


BIN
src/assets/structure/structure-11.png


BIN
src/assets/structure/structure-12.png


BIN
src/assets/structure/structure-13.png


BIN
src/assets/structure/structure-14.png


BIN
src/assets/structure/structure-15.png


BIN
src/assets/structure/structure-2.png


BIN
src/assets/structure/structure-3.png


BIN
src/assets/structure/structure-4.png


BIN
src/assets/structure/structure-5.png


BIN
src/assets/structure/structure-6.png


BIN
src/assets/structure/structure-7.png


BIN
src/assets/structure/structure-8.png


BIN
src/assets/structure/structure-9.png


+ 6 - 1
src/views/book/courseware/create/components/base/common/UploadFile.vue

@@ -280,7 +280,12 @@ export default {
       if (this.type === 'audio') {
         fileType = ['mp3', 'acc', 'wma', 'wav'];
         typeTip = '音频文件只能是 mp3、acc、wma、wav格式!';
-      } else if (this.type === 'picture' || this.type === 'image_text' || this.type === 'drawing') {
+      } else if (
+        this.type === 'picture' ||
+        this.type === 'image_text' ||
+        this.type === 'drawing' ||
+        this.type === 'character_structure'
+      ) {
         fileType = ['jpg', 'png', 'jpeg'];
         typeTip = '图片文件只能是 jpg、png、jpeg 格式!';
       } else if (this.type === 'video' || this.type === 'video_interaction') {

+ 284 - 0
src/views/book/courseware/create/components/question/character_structure/CharacterStructure.vue

@@ -0,0 +1,284 @@
+<template>
+  <ModuleBase :type="data.type">
+    <template #content>
+      <UploadFile
+        key="upload_image"
+        :courseware-id="courseware_id"
+        :component-id="id"
+        :type="data.type"
+        :file-list="data.image_list"
+        :file-id-list="data.image_id_list"
+        :label-text="labelText"
+        :accept-file-type="acceptFileType"
+        :icon-class="iconClass"
+        :limit="99"
+        :single-size="500"
+        @updateFileList="updateFileList"
+      />
+      <div class="structure-img-box">
+        <span>选择选项</span>
+        <el-checkbox-group v-model="data.structure_select_id" @change="handleChangeSelcet">
+          <el-checkbox v-for="item in data.structure_img_list" :label="item.file_id" :key="item.value"
+            ><img :src="item.type === 'local' ? require('@/assets/structure/' + item.value) : item.value"
+          /></el-checkbox>
+        </el-checkbox-group>
+      </div>
+      <div class="structure-img-box" v-if="data.structure_select_list.length > 0">
+        <span>已选选项</span>
+        <div v-for="(item, index) in data.structure_select_list" :key="item.value" class="select-item">
+          <img
+            :src="item.type === 'local' ? require('@/assets/structure/' + item.value) : item.value"
+            class="select-img"
+          />
+          <span>选项{{ index + 1 }}</span>
+        </div>
+      </div>
+      <div class="option-list" v-for="(item, index) in data.option_list" :key="index">
+        <div class="option-item">
+          <span>汉字</span>
+          <el-input v-model="item.content" @change="handleHanzi(item)" placeholder="请输入一个汉字"></el-input>
+        </div>
+        <div class="option-item" v-if="isEnable(data.property.is_enable_pinyin)">
+          <span>拼音</span>
+          <el-input v-model="item.pinyin"></el-input>
+        </div>
+        <div class="option-item">
+          <span>例子</span>
+          <el-radio-group v-model="item.is_example">
+            <el-radio :label="true">是</el-radio>
+            <el-radio :label="false">否</el-radio>
+          </el-radio-group>
+        </div>
+        <div class="option-item">
+          <span>答案</span>
+          <el-select v-model="item.answer">
+            <el-option
+              v-for="(item, index) in data.structure_select_list"
+              :key="item.file_id"
+              :label="'选项' + (index + 1)"
+              :value="item.file_id"
+              ><img
+                :src="item.type === 'local' ? require('@/assets/structure/' + item.value) : item.value"
+                class="small-img"
+            /></el-option>
+          </el-select>
+        </div>
+      </div>
+      <el-button icon="el-icon-plus" style="margin: 24px 0" @click="addElement">增加一个</el-button>
+    </template>
+  </ModuleBase>
+</template>
+
+<script>
+import ModuleMixin from '../../common/ModuleMixin';
+import UploadFile from '../../base/common/UploadFile.vue';
+
+import {
+  getCharacterStructureData,
+  structureList,
+  getOption,
+  isEnable,
+} from '@/views/book/courseware/data/characterStructure';
+import { GetStaticResources } from '@/api/app';
+
+export default {
+  name: 'CharacterStructurePage',
+  components: { UploadFile },
+  mixins: [ModuleMixin],
+  data() {
+    return {
+      data: getCharacterStructureData(),
+      structureList,
+      getOption,
+      labelText: '新增选项',
+      acceptFileType: '.jpg,.png,.jpeg',
+      iconClass: 'picture',
+      isEnable,
+    };
+  },
+  watch: {
+    // 'data.option_list': 'handleMindMap',
+  },
+  methods: {
+    updateFileList({ file_list, file_id_list, file_info_list }) {
+      this.data.image_list = file_list;
+      this.data.image_id_list = file_id_list;
+      this.data.file_id_list = file_id_list;
+      let file_new = [];
+      file_list.forEach((item) => {
+        if (item.file_id) {
+          let obj = {
+            value: item.file_url,
+            type: 'upload',
+            file_id: item.file_id,
+          };
+          file_new.push(obj);
+        }
+      });
+      this.data.structure_img_list = this.structureList.concat(file_new);
+    },
+    // 已选内容
+    handleChangeSelcet() {
+      let list = [];
+      this.data.structure_select_id.forEach((item) => {
+        let items = this.data.structure_img_list.find((p) => p.file_id === item);
+        list.push(items);
+      });
+      this.data.structure_select_list = list;
+    },
+    // 增加
+    addElement() {
+      this.data.option_list.push(getOption());
+    },
+    handleMindMap() {
+      // 思维导图数据
+      let node_list = [];
+      this.data.option_list.forEach((item) => {
+        node_list.push({
+          name: item.content.replace(/<[^>]*>?/gm, ''),
+          id: Math.random().toString(36).substring(2, 12),
+        });
+      });
+      this.data.mind_map.node_list = node_list;
+    },
+    handleHanzi(item) {
+      let cons = item.content.trim();
+      let MethodName = 'hz_resource_manager-GetMultHZStrokesContent';
+      let data = {
+        hz_str: cons,
+      };
+      GetStaticResources(MethodName, data)
+        .then((res) => {
+          for (let key in res) {
+            if (key != 'status' && key != ',' && res[key]) {
+              res[key] = JSON.parse(res[key]);
+            }
+          }
+          let hzDetailList = res;
+          let hz_list = [];
+          cons.split('').forEach((items) => {
+            let res = JSON.parse(JSON.stringify(hzDetailList[items]));
+            let obj = {
+              con: items,
+              hzDetail: {
+                hz_json: res,
+              },
+            };
+            hz_list.push(obj);
+          });
+          item.hz_info = hz_list;
+        })
+        .catch(() => {});
+
+      item.pinyin = cnchar.spell(cons, 'array', 'low', 'tone').join(' ');
+      this.handleMindMap();
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.upload-file {
+  display: flex;
+  column-gap: 12px;
+  align-items: center;
+  margin: 8px 0;
+
+  .file-name {
+    display: flex;
+    column-gap: 14px;
+    align-items: center;
+    justify-content: space-between;
+    max-width: 360px;
+    padding: 8px 12px;
+    font-size: 14px;
+    color: #1d2129;
+    background-color: #f7f8fa;
+
+    span {
+      display: flex;
+      column-gap: 14px;
+      align-items: center;
+    }
+  }
+
+  .svg-icon {
+    cursor: pointer;
+  }
+}
+
+.structure-img-box {
+  display: flex;
+  column-gap: 16px;
+  margin: 10px 0;
+
+  > span {
+    flex-shrink: 0;
+    width: 60px;
+    font-size: 14px;
+    color: #4e5969;
+  }
+
+  :deep .el-checkbox {
+    margin: 0 10px 10px;
+  }
+
+  :deep .el-checkbox__label {
+    height: 78px;
+    padding: 5px;
+    margin-left: 10px;
+    font-size: 0;
+    background: #f2f3f5;
+    border-radius: 3px;
+
+    img {
+      width: 68px;
+      height: 68px;
+    }
+  }
+
+  .select-img {
+    width: 78px;
+    height: 78px;
+    padding: 5px;
+    background: #f2f3f5;
+    border-radius: 3px;
+  }
+}
+
+.option-list {
+  display: flex;
+  gap: 15px;
+  padding: 10px;
+  margin-bottom: 10px;
+  border: 1px solid #dcdfe6;
+  border-radius: 5px;
+
+  .option-item {
+    display: flex;
+    align-items: center;
+
+    span {
+      flex-shrink: 0;
+      width: 40px;
+      font-size: 14px;
+      color: #4e5969;
+    }
+  }
+}
+
+.select-item {
+  width: 78px;
+  font-size: 14px;
+  color: #4e5969;
+  text-align: center;
+}
+
+.small-img {
+  width: 20px;
+  height: 20px;
+}
+
+:deep .el-select-dropdown__item {
+  line-height: 34px;
+}
+</style>

+ 40 - 0
src/views/book/courseware/create/components/question/character_structure/CharacterStructureSetting.vue

@@ -0,0 +1,40 @@
+<template>
+  <div>
+    <el-form :model="property" label-width="72px" label-position="left">
+      <SerailNumber :property="property" />
+      <el-form-item label="拼音显示">
+        <el-radio-group v-model="property.is_enable_pinyin">
+          <el-radio v-for="{ value, label } in showList" :key="value" :label="value">
+            {{ label }}
+          </el-radio>
+        </el-radio-group>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import SettingMixin from '@/views/book/courseware/create/components/common/SettingMixin';
+
+import { getCharacterStructureProperty, showList } from '@/views/book/courseware/data/characterStructure';
+
+export default {
+  name: 'CharacterStructureSetting',
+  mixins: [SettingMixin],
+  data() {
+    return {
+      property: getCharacterStructureProperty(),
+      showList,
+    };
+  },
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped>
+@use '@/styles/mixin.scss' as *;
+
+.el-form {
+  @include setting-base;
+}
+</style>

+ 97 - 0
src/views/book/courseware/create/components/question/newWord_template/NewWordTemplate.vue

@@ -0,0 +1,97 @@
+<template>
+  <ModuleBase :type="data.type">
+    <template #content>
+      <el-button icon="el-icon-plus" style="margin: 24px 0" @click="addElement">增加一个</el-button>
+    </template>
+  </ModuleBase>
+</template>
+
+<script>
+import ModuleMixin from '../../common/ModuleMixin';
+
+import { getNewWordTemplateData } from '@/views/book/courseware/data/newWordTemplate';
+
+export default {
+  name: 'NewWordTemplatePage',
+  components: {},
+  mixins: [ModuleMixin],
+  data() {
+    return {
+      data: getNewWordTemplateData(),
+    };
+  },
+  watch: {
+    // 'data.option': 'handleMindMap',
+  },
+  methods: {
+    // 删除行
+    handleDelete(index) {
+      this.data.option.splice(index, 1);
+    },
+    // 上移下移
+    moveElement(dItem, index, type) {
+      let obj = JSON.parse(JSON.stringify(dItem));
+      if (type == 'up' && index > 0) {
+        this.data.option.splice(index - 1, 0, obj);
+        this.data.option.splice(index + 1, 1);
+      }
+      if (type == 'down' && index < this.data.option.length - 1) {
+        this.data.option[index] = this.data.option.splice(index + 1, 1, this.data.option[index])[0];
+      }
+    },
+    // 增加
+    addElement() {
+      this.data.option.push(getOption());
+    },
+    handleMindMap() {
+      // 思维导图数据
+      let node_list = [];
+      this.data.option.forEach((item) => {
+        node_list.push({
+          name: item.con.replace(/<[^>]*>?/gm, ''),
+          id: Math.random().toString(36).substring(2, 12),
+        });
+      });
+      this.data.mind_map.node_list = node_list;
+    },
+    handleBlurCon() {
+      this.handleMindMap();
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.upload-file {
+  display: flex;
+  column-gap: 12px;
+  align-items: center;
+  margin: 8px 0;
+
+  .file-name {
+    display: flex;
+    column-gap: 14px;
+    align-items: center;
+    justify-content: space-between;
+    max-width: 360px;
+    padding: 8px 12px;
+    font-size: 14px;
+    color: #1d2129;
+    background-color: #f7f8fa;
+
+    span {
+      display: flex;
+      column-gap: 14px;
+      align-items: center;
+    }
+  }
+
+  .svg-icon {
+    cursor: pointer;
+  }
+}
+</style>
+<style lang="scss">
+.tox .tox-editor-header {
+  z-index: 3 !important;
+}
+</style>

+ 32 - 0
src/views/book/courseware/create/components/question/newWord_template/NewWordTemplateSetting.vue

@@ -0,0 +1,32 @@
+<template>
+  <div>
+    <el-form :model="property" label-width="72px" label-position="left">
+      <SerailNumber :property="property" />
+    </el-form>
+  </div>
+</template>
+
+<script>
+import SettingMixin from '@/views/book/courseware/create/components/common/SettingMixin';
+
+import { getNewWordTemplateProperty } from '@/views/book/courseware/data/newWordTemplate';
+
+export default {
+  name: 'NewWordTemplateSetting',
+  mixins: [SettingMixin],
+  data() {
+    return {
+      property: getNewWordTemplateProperty(),
+    };
+  },
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped>
+@use '@/styles/mixin.scss' as *;
+
+.el-form {
+  @include setting-base;
+}
+</style>

+ 0 - 1
src/views/book/courseware/create/components/question/new_word/NewWord.vue

@@ -573,7 +573,6 @@ export default {
     // 增加
     addElement() {
       this.data.new_word_list.push(getOption());
-      console.log(this.data.new_word_list);
     },
     // 获取数据
     handleBlurCon(row) {

+ 23 - 0
src/views/book/courseware/data/bookType.js

@@ -69,6 +69,10 @@ import Table from '../create/components/question/table/Table.vue';
 import TableSetting from '../create/components/question/table/TableSetting.vue';
 import DialogueArticlePage from '../create/components/question/dialogue_article/Article.vue';
 import DialogueArticleSetting from '../create/components/question/dialogue_article/ArticleSetting.vue';
+import NewWordTemplate from '../create/components/question/newWord_template/NewWordTemplate.vue';
+import NewWordTemplateSetting from '../create/components/question/newWord_template/NewWordTemplateSetting.vue';
+import CharacterStructure from '../create/components/question/character_structure/CharacterStructure.vue';
+import CharacterStructureSetting from '../create/components/question/character_structure/CharacterStructureSetting.vue';
 
 // 预览组件页面列表
 import AudioPreview from '@/views/book/courseware/preview/components/audio/AudioPreview.vue';
@@ -107,6 +111,9 @@ import VideoInteractionPreview from '../preview/components/video_interaction/Vid
 import ThreeModelPreview from '../preview/components/3d_model/3DModelPreview.vue';
 import TablePreview from '../preview/components/table/TablePreview.vue';
 import DialogueArticlePreview from '../preview/components/dialogue_article/index.vue';
+import NewWordTemplatePreview from '../preview/components/newWord_template/NewWordTemplatePreview.vue';
+import CharacterStructurePreview from '../preview/components/character_structure/CharacterStructurePreview.vue';
+
 
 export const bookTypeOption = [
   {
@@ -400,6 +407,22 @@ export const bookTypeOption = [
         set: DrawingSetting,
         preview: DrawingPreview,
       },
+      // {
+      //   value: 'newWord_template',
+      //   label: '生字',
+      //   icon: '',
+      //   component: NewWordTemplate,
+      //   set: NewWordTemplateSetting,
+      //   preview: NewWordTemplatePreview,
+      // },
+      {
+        value: 'character_structure',
+        label: '汉字结构',
+        icon: '',
+        component: CharacterStructure,
+        set: CharacterStructureSetting,
+        preview: CharacterStructurePreview,
+      },
     ],
   },
 ];

+ 147 - 0
src/views/book/courseware/data/characterStructure.js

@@ -0,0 +1,147 @@
+import {
+  displayList,
+  serialNumberTypeList,
+  serialNumberPositionList,
+  arrangeTypeList,
+  switchOption,
+  isEnable,
+} from '@/views/book/courseware/data/common';
+import { getRandomNumber } from '@/utils';
+
+export { arrangeTypeList, switchOption, isEnable };
+  
+  // 显示
+export const showList = [
+  {
+    value: 'true',
+    label: '显示',
+  },
+  {
+    value: 'false',
+    label: '不显示',
+  },
+];
+
+// 结构列表
+export const structureList = [
+  {
+    value: 'structure-1.png',
+    type: 'local',
+    file_id:'1'
+  },
+  {
+    value: 'structure-2.png',
+    type: 'local',
+    file_id:'2'
+  },
+  {
+    value: 'structure-3.png',
+    type: 'local',
+    file_id:'3'
+  },
+  {
+    value: 'structure-4.png',
+    type: 'local',
+    file_id:'4'
+  },
+  {
+    value: 'structure-5.png',
+    type: 'local',
+    file_id:'5'
+  },
+  {
+    value: 'structure-6.png',
+    type: 'local',
+    file_id:'6'
+  },
+  {
+    value: 'structure-7.png',
+    type: 'local',
+    file_id:'7'
+  },
+  {
+    value: 'structure-8.png',
+    type: 'local',
+    file_id:'8'
+  },
+  {
+    value: 'structure-9.png',
+    type: 'local',
+    file_id:'9'
+  },
+  {
+    value: 'structure-10.png',
+    type: 'local',
+    file_id:'10'
+  },
+  {
+    value: 'structure-11.png',
+    type: 'local',
+    file_id:'11'
+  },
+  {
+    value: 'structure-12.png',
+    type: 'local',
+    file_id:'12'
+  },
+  {
+    value: 'structure-13.png',
+    type: 'local',
+    file_id:'13'
+  },
+  {
+    value: 'structure-14.png',
+    type: 'local',
+    file_id:'14'
+  },
+  {
+    value: 'structure-15.png',
+    type: 'local',
+    file_id:'15'
+  },
+]
+
+export function getOption() {
+  return {
+    content: '',
+    pinyin: '',
+    mark: getRandomNumber(),
+    is_example: false,
+    answer: '',
+    hz_info: []
+  };
+}
+
+export function getCharacterStructureProperty() {
+  return {
+    serial_number: 1,
+    sn_type: serialNumberTypeList[0].value,
+    sn_position: serialNumberPositionList[3].value,
+    sn_display_mode: displayList[0].value,
+    
+    is_enable_pinyin: showList[0].value,
+  };
+}
+
+export function getCharacterStructureData() {
+  return {
+    type: 'character_structure',
+    title: '汉字结构',
+    property: getCharacterStructureProperty(),
+    option_list: [getOption()],
+    structure_img_list: structureList, 
+    structure_select_id: [], // 存放已选选项id
+    structure_select_list: [],
+    image_list: [],
+    image_id_list: [],
+    file_id_list: [],
+    mark: getRandomNumber(),
+    mind_map: {
+      node_list: [
+      ], // 思维导图数据
+    },
+    answer: {
+      answer_list: [],
+    },
+  };
+}

+ 66 - 0
src/views/book/courseware/data/newWordTemplate copy.js

@@ -0,0 +1,66 @@
+import {
+  displayList,
+  serialNumberTypeList,
+  serialNumberPositionList,
+  arrangeTypeList,
+  switchOption,
+  isEnable,
+} from '@/views/book/courseware/data/common';
+
+export { arrangeTypeList, switchOption, isEnable };
+
+// 显示
+export const showList = [
+  {
+    value: 'true',
+    label: '显示',
+  },
+  {
+    value: 'false',
+    label: '不显示',
+  },
+];
+
+// 汉字框
+export const frameList = [
+  {
+    value: 'tian',
+    label: '田字格',
+  },
+  {
+    value: 'fang',
+    label: '方框',
+  },
+  {
+    value: 'none',
+    label: '无',
+  },
+];
+
+export function getNewWordTemplateProperty() {
+  return {
+    serial_number: 1,
+    sn_type: serialNumberTypeList[0].value,
+    sn_position: serialNumberPositionList[3].value,
+    sn_display_mode: displayList[0].value,
+
+    is_enable_pinyin: showList[0].value,
+    
+  };
+}
+
+export function getNewWordTemplateData() {
+  return {
+    type: 'newWord_template',
+    title: '生字',
+    property: getNewWordTemplateProperty(),
+    content: '',
+    content_list: [],
+    mind_map: {
+      node_list: [{ name: '生字' }], // 思维导图数据
+    },
+    answer: {
+      answer_list: [],
+    },
+  };
+}

+ 66 - 0
src/views/book/courseware/data/newWordTemplate.js

@@ -0,0 +1,66 @@
+import {
+  displayList,
+  serialNumberTypeList,
+  serialNumberPositionList,
+  arrangeTypeList,
+  switchOption,
+  isEnable,
+} from '@/views/book/courseware/data/common';
+
+export { arrangeTypeList, switchOption, isEnable };
+
+// 显示
+export const showList = [
+  {
+    value: 'true',
+    label: '显示',
+  },
+  {
+    value: 'false',
+    label: '不显示',
+  },
+];
+
+// 汉字框
+export const frameList = [
+  {
+    value: 'tian',
+    label: '田字格',
+  },
+  {
+    value: 'fang',
+    label: '方框',
+  },
+  {
+    value: 'none',
+    label: '无',
+  },
+];
+
+export function getNewWordTemplateProperty() {
+  return {
+    serial_number: 1,
+    sn_type: serialNumberTypeList[0].value,
+    sn_position: serialNumberPositionList[3].value,
+    sn_display_mode: displayList[0].value,
+
+    is_enable_pinyin: showList[0].value,
+    
+  };
+}
+
+export function getNewWordTemplateData() {
+  return {
+    type: 'newWord_template',
+    title: '生字',
+    property: getNewWordTemplateProperty(),
+    content: '',
+    content_list: [],
+    mind_map: {
+      node_list: [{ name: '生字' }], // 思维导图数据
+    },
+    answer: {
+      answer_list: [],
+    },
+  };
+}

+ 914 - 0
src/views/book/courseware/preview/components/character_structure/CharacterStructurePreview.vue

@@ -0,0 +1,914 @@
+<!-- eslint-disable vue/no-v-html -->
+<template>
+  <div class="newWord-preview" :style="getAreaStyle()">
+    <SerialNumberPosition v-if="isEnable(data.property.sn_display_mode)" :property="data.property" />
+
+    <div class="main"></div>
+  </div>
+</template>
+
+<script>
+import { getCharacterStructureData } from '@/views/book/courseware/data/characterStructure';
+
+import PreviewMixin from '../common/PreviewMixin';
+
+export default {
+  name: 'CharacterStructurePreview',
+
+  components: {},
+  mixins: [PreviewMixin],
+  data() {
+    return {
+      data: getCharacterStructureData(),
+    };
+  },
+  watch: {
+    data: {
+      handler(val) {
+        if (val) {
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped>
+@use '@/styles/mixin.scss' as *;
+
+.newWord-preview {
+  @include preview-base;
+
+  .NPC-zhedie {
+    width: 1007px;
+
+    // width: 780px;
+    margin-bottom: 24px;
+
+    .aduioLine-box {
+      margin-bottom: 8px;
+    }
+
+    .practiceBox {
+      position: fixed;
+      top: 0;
+      left: 0;
+      z-index: 999;
+      box-sizing: border-box;
+      width: 100%;
+      height: 100vh;
+      overflow: hidden;
+      overflow-y: auto;
+      background: rgba(0, 0, 0, 19%);
+    }
+
+    .NPC-word-list {
+      overflow: auto;
+      background: #f7f7f7;
+
+      .NPC-word-tab-common,
+      .collocation,
+      .tabNum-box {
+        flex-shrink: 0;
+      }
+    }
+
+    .NPC-word-table {
+      width: 100%;
+
+      :deep p {
+        margin: 0;
+      }
+
+      > .NPC-word-tr {
+        margin-bottom: 8px;
+        background: #fff;
+        border-radius: 8px;
+
+        .NPC-word-row {
+          position: relative;
+          display: flex;
+
+          // flex-flow: wrap;
+          justify-content: flex-start;
+          padding: 8px 13px 8px 12px;
+          padding-right: 80px;
+          cursor: pointer;
+          border-radius: 8px;
+
+          &.active {
+            background: linear-gradient(0deg, rgba(0, 0, 0, 8%), rgba(0, 0, 0, 8%)), #fff;
+          }
+
+          .right-box {
+            position: absolute;
+            top: 8px;
+            right: 5px;
+            display: flex;
+            gap: 5px;
+          }
+
+          > span {
+            font-size: 16px;
+            line-height: 150%;
+            color: #000;
+          }
+        }
+
+        .NPC-word-tab-common {
+          box-sizing: border-box;
+          width: 125px;
+          padding-left: 8px;
+        }
+      }
+    }
+  }
+
+  .NPC-word-list {
+    padding: 20px 24px;
+    border: 1px solid rgba(0, 0, 0, 10%);
+    border-top: none;
+    border-radius: 0 0 8px 8px;
+  }
+
+  .detail-icon {
+    display: block;
+    width: 24px;
+    height: 24px;
+    cursor: pointer;
+    opacity: 0.5;
+  }
+
+  .tabNum-box {
+    position: relative;
+
+    .star-label {
+      position: absolute;
+      top: 1px;
+      right: -6px;
+      width: 6px;
+      height: 6px;
+    }
+  }
+
+  .play-btn {
+    display: block;
+    width: 16px;
+    height: 16px;
+    margin-top: 4px;
+    background: url('@/assets/fill/voice-pause-red.png') no-repeat left top;
+    background-size: 100% 100%;
+
+    &.active {
+      background: url('@/assets/fill/voice-play-red.png') no-repeat left top;
+      background-size: 100% 100%;
+    }
+  }
+
+  .tabNum {
+    display: block;
+    width: 16px;
+    height: 16px;
+    margin-top: 4px;
+    margin-left: 8px;
+    font-family: 'robot', 'alabo';
+    font-size: 12px;
+    line-height: 16px;
+    color: #fff;
+    text-align: center;
+    background: #de4444;
+    border-radius: 50%;
+  }
+
+  .NPC-word-tab-box {
+    width: 240px;
+
+    span {
+      display: block;
+      width: 100%;
+      margin: 2px 0;
+      color: #000;
+    }
+  }
+
+  .NPC-word-tab-pinyin {
+    font-family: 'League';
+
+    // white-space: nowrap;
+    font-size: 12px;
+    word-break: break-word;
+
+    &.NPC-word-tab-pinyin-red {
+      color: #e35454;
+    }
+
+    &.NPC-word-tab-pinyin-green {
+      color: #24b99e;
+    }
+
+    &.NPC-word-tab-pinyin-brown {
+      color: #bd8865;
+    }
+  }
+
+  .NPC-word-tab-word {
+    font-family: '楷体';
+    font-size: 16px;
+    white-space: nowrap;
+
+    &.NPC-word-tab-word-red {
+      color: #e35454;
+    }
+
+    &.NPC-word-tab-word-green {
+      color: #24b99e;
+    }
+
+    &.NPC-word-tab-word-brown {
+      color: #bd8865;
+    }
+
+    &-break {
+      word-break: break-word;
+      white-space: normal;
+    }
+  }
+
+  .NPC-word-tab-cixing {
+    box-sizing: border-box;
+
+    // width: 48px;
+    width: 60px;
+    font-family: 'robot', 'alabo';
+    text-align: left;
+    word-break: break-word;
+
+    // font-style: italic;  // 要求改为正体
+    &.NPC-word-tab-cixing-red {
+      color: #e35454;
+    }
+
+    &.NPC-word-tab-cixing-green {
+      color: #24b99e;
+    }
+
+    &.NPC-word-tab-cixing-brown {
+      color: #bd8865;
+    }
+
+    &.hasCn {
+      font-size: 13px;
+    }
+  }
+
+  .NPC-word-tab-def {
+    box-sizing: border-box;
+
+    // flex: 1;
+    font-family: 'robot', 'alabo';
+    word-break: break-word;
+    white-space: pre-wrap;
+
+    &.NPC-word-tab-def-red {
+      color: #e35454;
+    }
+
+    &.NPC-word-tab-def-green {
+      color: #24b99e;
+    }
+
+    &.NPC-word-tab-def-brown {
+      color: #bd8865;
+    }
+  }
+
+  .collocation {
+    display: flex;
+    width: 100%;
+
+    // padding-top: 8px;
+
+    > span {
+      flex-shrink: 0;
+      font-size: 16px;
+      font-weight: 400;
+      line-height: 24px;
+      color: #000;
+    }
+
+    > div b {
+      display: block;
+    }
+
+    > b,
+    > div b {
+      flex: 1;
+      font-family: 'robot', '楷体', 'alabo';
+      font-size: 16px;
+      font-weight: 400;
+      line-height: 24px;
+      color: rgba(0, 0, 0, 65%);
+    }
+  }
+
+  @keyframes firstrotate {
+    0% {
+      transform: rotateZ(0deg);
+    }
+
+    100% {
+      transform: rotateZ(180deg);
+    }
+  }
+
+  @keyframes huifuRotate {
+    0% {
+      transform: rotateZ(180deg);
+    }
+
+    100% {
+      transform: rotateZ(0deg);
+    }
+  }
+
+  .luyin-box-wordphrase {
+    height: 24px;
+  }
+
+  .NPC-word-tile {
+    display: flex;
+    flex-flow: wrap;
+    gap: 20px;
+    padding: 20px 0;
+  }
+
+  .writeTop {
+    position: relative;
+    display: flex;
+    column-gap: 8px;
+    width: 400px;
+
+    .left,
+    .right {
+      position: relative;
+      box-sizing: border-box;
+      width: 100%;
+      min-height: 270px;
+      padding: 8px 12px 18px;
+      overflow: hidden;
+      background: #fff;
+      border: 4px solid #fff;
+      border-radius: 24px;
+
+      .header-info {
+        display: flex;
+        justify-content: space-between;
+        width: 100%;
+        margin-bottom: 12px;
+
+        :deep .el-input__inner {
+          height: 24px;
+          padding: 0;
+          font-size: 24px;
+          font-weight: 400;
+          line-height: 100%;
+          color: rgba(0, 0, 0, 100%);
+          border: none;
+        }
+
+        .label {
+          :deep .el-input__inner {
+            text-align: right;
+          }
+        }
+      }
+    }
+
+    min-height: 332px;
+    transition: 0.6s;
+    perspective: 1000px;
+    transform-style: preserve-3d;
+
+    .left-preview {
+      padding-top: 40px;
+
+      // padding-bottom: 32px;
+      // position: absolute;
+      backface-visibility: hidden;
+    }
+
+    .header-info-preview {
+      position: absolute;
+      top: 0;
+      left: 0;
+      z-index: 1;
+      width: 100%;
+
+      h5 {
+        padding: 0 12px;
+        margin: 0;
+        font-size: 20px;
+        font-weight: 400;
+        line-height: 32px;
+        color: #000;
+      }
+
+      label {
+        position: absolute;
+        top: -4px;
+        right: -4px;
+        padding: 0 16px 0 8px;
+        font-size: 20px;
+        font-weight: 500;
+        line-height: 150%;
+        color: #fff;
+        background: #fff;
+        border-radius: 0 8px;
+      }
+    }
+
+    .left-big {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+
+    .del-btn {
+      position: absolute;
+      right: 8px;
+      bottom: 8px;
+      padding: 5px 8px;
+      font-size: 24px;
+      color: #fff;
+      cursor: pointer;
+      background: #f56767;
+      border-radius: 40px;
+    }
+
+    .overturn-btn {
+      position: absolute;
+      right: 8px;
+      bottom: 8px;
+      width: 40px;
+      height: 40px;
+      padding: 8px;
+      font-size: 24px;
+      line-height: 1;
+      color: #fff;
+      cursor: pointer;
+      background: #e0e0e0;
+      border-radius: 8px;
+    }
+
+    .el-icon-zoom-in,
+    .filt-check {
+      position: absolute;
+      bottom: 8px;
+      left: 8px;
+      width: 30px;
+      height: 30px;
+      font-size: 24px;
+      cursor: pointer;
+
+      :deep .el-checkbox__inner {
+        width: 24px;
+        height: 24px;
+      }
+
+      :deep .el-checkbox__inner::after {
+        left: 8px;
+        width: 6px;
+        height: 14px;
+      }
+    }
+
+    .right {
+      display: flex;
+      flex-flow: wrap;
+      row-gap: 8px;
+      align-items: center;
+      padding: 16px 24px 26px;
+
+      .card-label {
+        width: 100%;
+        height: 22px;
+        font-size: 14px;
+        font-weight: 400;
+        line-height: 22px;
+        color: #4e5969;
+      }
+
+      :deep .el-textarea {
+        height: 64px;
+      }
+
+      .config-box {
+        display: flex;
+        align-items: center;
+        width: 100%;
+
+        span {
+          margin-right: 8px;
+          font-size: 14px;
+          line-height: 20px;
+          color: #000;
+        }
+
+        .el-color-picker {
+          height: 32px;
+        }
+
+        :deep .el-color-picker__trigger {
+          height: 32px;
+        }
+
+        .el-radio {
+          margin-right: 8px;
+        }
+
+        .el-radio-group {
+          display: flex;
+        }
+
+        :deep .el-radio__input.is-checked .el-radio__inner {
+          background: #000;
+          border-color: #000;
+        }
+
+        :deep .el-radio__input.is-checked + .el-radio__label {
+          color: #000;
+        }
+      }
+    }
+
+    .right-preview {
+      display: block;
+      padding: 36px;
+
+      .pinyin-box {
+        margin-bottom: 8px;
+        font-family: 'League';
+        font-feature-settings: 'cv01' on;
+
+        // font-size: 18px;
+        line-height: 120%;
+        color: #de4444;
+        text-align: center;
+      }
+
+      .hz-box {
+        width: 100%;
+
+        .hz-item {
+          text-align: center;
+
+          :deep .strockplayInner {
+            width: 76px;
+            height: 76px;
+          }
+
+          p {
+            margin: 0 0 8px;
+            font-family: 'League';
+            font-size: 18px;
+            font-feature-settings: 'cv01' on;
+            line-height: 120%;
+            color: #de4444;
+          }
+        }
+      }
+
+      :deep .audio-wrapper {
+        box-sizing: border-box;
+        width: 50px;
+        height: 50px;
+        padding: 13px;
+        margin: 0 auto 8px;
+        cursor: pointer;
+        background: #f3f3f3;
+        border-radius: 40px;
+
+        .voice-play {
+          width: 24px;
+          height: 24px;
+        }
+      }
+
+      .definition_list-box {
+        margin-top: 16px;
+        white-space: pre;
+
+        > div {
+          display: flex;
+          margin-bottom: 8px;
+
+          label,
+          p {
+            width: 40px;
+            font-size: 14px;
+            font-weight: 400;
+            line-height: 150%;
+            color: #000;
+          }
+
+          label {
+            width: 47px;
+          }
+
+          p {
+            flex: 1;
+            line-height: 0;
+            word-break: break-word;
+            white-space: pre-wrap;
+          }
+        }
+      }
+
+      :deep p {
+        margin: 0;
+        line-height: 1.5;
+      }
+    }
+
+    .right-preview-rota {
+      transform: rotateY(180deg);
+    }
+
+    .item-image {
+      position: relative;
+      overflow: hidden;
+      font-size: 0;
+
+      // background: #f2f3f5;
+      border-radius: 8px;
+
+      .item-image-del {
+        position: absolute;
+        top: 8px;
+        right: 8px;
+        display: block;
+        width: 16px;
+        height: 16px;
+        padding: 8px;
+        font-size: 16px;
+        color: #ee3232;
+        cursor: pointer;
+        background-color: #fff;
+        border-radius: 50%;
+        box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 25%);
+      }
+    }
+
+    .item-con {
+      display: flex;
+      align-items: center;
+      width: 50%;
+      margin-top: 16px;
+
+      label {
+        width: 44px;
+        font-size: 14px;
+        font-weight: 400;
+        line-height: 22px;
+        color: #4e5969;
+      }
+
+      :deep .el-input__inner {
+        width: 235px;
+        height: 32px;
+        font-family: '楷体';
+        font-size: 14px;
+        font-weight: 400;
+        line-height: 22px;
+        background: #f2f3f5;
+        border: none;
+        border-radius: 2px;
+      }
+
+      .pinyin {
+        :deep .el-input__inner {
+          font-family: 'League';
+        }
+      }
+    }
+
+    .con-preview {
+      margin-top: 8px;
+      font-family: '楷体';
+      font-size: 38px;
+      font-weight: 400;
+      line-height: 100%;
+      color: #000;
+      text-align: center;
+
+      &-big {
+        margin: 0;
+        font-size: 86px;
+      }
+    }
+
+    .writeTop-row {
+      display: flex;
+      justify-content: center;
+    }
+  }
+
+  .flipped {
+    transform: rotateY(180deg);
+  }
+
+  .flipped-back {
+    transform: rotateY(180deg);
+  }
+
+  .hz-box {
+    display: flex;
+    width: max-content;
+  }
+
+  .writeTop-item {
+    border: 1px solid #de4444;
+  }
+
+  .writeTop-item-noLeft {
+    border-left: none;
+  }
+}
+
+.newWord-table {
+  .cell {
+    width: max-content;
+    white-space: nowrap;
+  }
+
+  :deep thead {
+    display: none;
+  }
+}
+</style>
+<style lang="scss">
+.NPC-zhedie {
+  .topTitle {
+    display: flex;
+    justify-content: space-between;
+    width: 100%;
+    height: 48px;
+    padding-right: 16px;
+    padding-left: 24px;
+    overflow: hidden;
+    background: #e35454;
+    border: 1px solid rgba(0, 0, 0, 10%);
+    border-radius: 8px 8px 0 0;
+
+    .NPC-top-left {
+      display: flex;
+      align-items: center;
+      justify-content: flex-start;
+
+      .NPC-topTitle-text {
+        margin-right: 8px;
+        font-family: 'sourceR';
+        font-size: 16px;
+        font-weight: bold;
+        color: #fff;
+        white-space: pre;
+      }
+    }
+
+    .NPC-top-right {
+      display: flex;
+      gap: 4px;
+      align-items: center;
+      justify-content: flex-start;
+      cursor: pointer;
+
+      &-text {
+        font-size: 14px;
+        font-weight: normal;
+        line-height: 16px;
+        color: #fff;
+      }
+
+      img {
+        width: 16px;
+        height: 16px;
+      }
+    }
+
+    img {
+      width: 24px;
+      height: 24px;
+    }
+
+    .rotate {
+      animation-name: firstrotate;
+      animation-timing-function: linear;
+      animation-direction: 2s;
+      animation-fill-mode: both;
+    }
+  }
+
+  .topTitleWhite {
+    display: flex;
+    justify-content: space-between;
+    width: 100%;
+    height: 48px;
+    padding-right: 16px;
+    padding-left: 24px;
+    overflow: hidden;
+    background: #fff;
+    border: 1px solid rgba(0, 0, 0, 10%);
+    border-radius: 8px 8px 0 0;
+
+    .NPC-top-left {
+      display: flex;
+      align-items: center;
+      justify-content: flex-start;
+
+      .NPC-topTitle-text {
+        margin-right: 8px;
+        font-family: 'sourceR';
+        font-size: 16px;
+        font-weight: bold;
+        color: #000;
+      }
+    }
+
+    .NPC-top-right {
+      display: flex;
+      align-items: center;
+      justify-content: flex-start;
+      cursor: pointer;
+
+      &-text {
+        font-size: 14px;
+        font-weight: normal;
+        line-height: 16px;
+        color: #000;
+      }
+
+      img {
+        width: 16px;
+        height: 16px;
+        margin-left: 4px;
+      }
+    }
+
+    img {
+      width: 24px;
+      height: 24px;
+    }
+
+    .rotate {
+      animation-name: firstrotate;
+      animation-timing-function: linear;
+      animation-direction: 2s;
+      animation-fill-mode: both;
+    }
+  }
+
+  .el-collapse-item__content {
+    padding-bottom: 0;
+  }
+
+  .el-slider__button {
+    width: 8px;
+    height: 8px;
+  }
+
+  .el-slider__runway {
+    padding: 0;
+    margin: 0;
+  }
+
+  .el-slider {
+    position: relative;
+
+    // top: -3px;
+  }
+
+  .el-collapse {
+    box-sizing: border-box;
+    background: #f7f7f7;
+    border-radius: 8px;
+  }
+
+  .el-collapse-item__wrap {
+    background: #f7f7f7;
+    border: 1px solid rgba(0, 0, 0, 10%);
+    border-top: 0;
+    border-radius: 0 0 8px 8px;
+  }
+
+  .el-collapse-item__arrow {
+    display: none;
+  }
+
+  .el-table__row {
+    padding: 4px 0;
+  }
+}
+</style>

+ 914 - 0
src/views/book/courseware/preview/components/newWord_template/NewWordTemplatePreview.vue

@@ -0,0 +1,914 @@
+<!-- eslint-disable vue/no-v-html -->
+<template>
+  <div class="newWord-preview" :style="getAreaStyle()">
+    <SerialNumberPosition v-if="isEnable(data.property.sn_display_mode)" :property="data.property" />
+
+    <div class="main"></div>
+  </div>
+</template>
+
+<script>
+import { getNewWordTemplateData } from '@/views/book/courseware/data/newWordTemplate';
+
+import PreviewMixin from '../common/PreviewMixin';
+
+export default {
+  name: 'NewWordPreview',
+
+  components: {},
+  mixins: [PreviewMixin],
+  data() {
+    return {
+      data: getNewWordTemplateData(),
+    };
+  },
+  watch: {
+    data: {
+      handler(val) {
+        if (val) {
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped>
+@use '@/styles/mixin.scss' as *;
+
+.newWord-preview {
+  @include preview-base;
+
+  .NPC-zhedie {
+    width: 1007px;
+
+    // width: 780px;
+    margin-bottom: 24px;
+
+    .aduioLine-box {
+      margin-bottom: 8px;
+    }
+
+    .practiceBox {
+      position: fixed;
+      top: 0;
+      left: 0;
+      z-index: 999;
+      box-sizing: border-box;
+      width: 100%;
+      height: 100vh;
+      overflow: hidden;
+      overflow-y: auto;
+      background: rgba(0, 0, 0, 19%);
+    }
+
+    .NPC-word-list {
+      overflow: auto;
+      background: #f7f7f7;
+
+      .NPC-word-tab-common,
+      .collocation,
+      .tabNum-box {
+        flex-shrink: 0;
+      }
+    }
+
+    .NPC-word-table {
+      width: 100%;
+
+      :deep p {
+        margin: 0;
+      }
+
+      > .NPC-word-tr {
+        margin-bottom: 8px;
+        background: #fff;
+        border-radius: 8px;
+
+        .NPC-word-row {
+          position: relative;
+          display: flex;
+
+          // flex-flow: wrap;
+          justify-content: flex-start;
+          padding: 8px 13px 8px 12px;
+          padding-right: 80px;
+          cursor: pointer;
+          border-radius: 8px;
+
+          &.active {
+            background: linear-gradient(0deg, rgba(0, 0, 0, 8%), rgba(0, 0, 0, 8%)), #fff;
+          }
+
+          .right-box {
+            position: absolute;
+            top: 8px;
+            right: 5px;
+            display: flex;
+            gap: 5px;
+          }
+
+          > span {
+            font-size: 16px;
+            line-height: 150%;
+            color: #000;
+          }
+        }
+
+        .NPC-word-tab-common {
+          box-sizing: border-box;
+          width: 125px;
+          padding-left: 8px;
+        }
+      }
+    }
+  }
+
+  .NPC-word-list {
+    padding: 20px 24px;
+    border: 1px solid rgba(0, 0, 0, 10%);
+    border-top: none;
+    border-radius: 0 0 8px 8px;
+  }
+
+  .detail-icon {
+    display: block;
+    width: 24px;
+    height: 24px;
+    cursor: pointer;
+    opacity: 0.5;
+  }
+
+  .tabNum-box {
+    position: relative;
+
+    .star-label {
+      position: absolute;
+      top: 1px;
+      right: -6px;
+      width: 6px;
+      height: 6px;
+    }
+  }
+
+  .play-btn {
+    display: block;
+    width: 16px;
+    height: 16px;
+    margin-top: 4px;
+    background: url('@/assets/fill/voice-pause-red.png') no-repeat left top;
+    background-size: 100% 100%;
+
+    &.active {
+      background: url('@/assets/fill/voice-play-red.png') no-repeat left top;
+      background-size: 100% 100%;
+    }
+  }
+
+  .tabNum {
+    display: block;
+    width: 16px;
+    height: 16px;
+    margin-top: 4px;
+    margin-left: 8px;
+    font-family: 'robot', 'alabo';
+    font-size: 12px;
+    line-height: 16px;
+    color: #fff;
+    text-align: center;
+    background: #de4444;
+    border-radius: 50%;
+  }
+
+  .NPC-word-tab-box {
+    width: 240px;
+
+    span {
+      display: block;
+      width: 100%;
+      margin: 2px 0;
+      color: #000;
+    }
+  }
+
+  .NPC-word-tab-pinyin {
+    font-family: 'League';
+
+    // white-space: nowrap;
+    font-size: 12px;
+    word-break: break-word;
+
+    &.NPC-word-tab-pinyin-red {
+      color: #e35454;
+    }
+
+    &.NPC-word-tab-pinyin-green {
+      color: #24b99e;
+    }
+
+    &.NPC-word-tab-pinyin-brown {
+      color: #bd8865;
+    }
+  }
+
+  .NPC-word-tab-word {
+    font-family: '楷体';
+    font-size: 16px;
+    white-space: nowrap;
+
+    &.NPC-word-tab-word-red {
+      color: #e35454;
+    }
+
+    &.NPC-word-tab-word-green {
+      color: #24b99e;
+    }
+
+    &.NPC-word-tab-word-brown {
+      color: #bd8865;
+    }
+
+    &-break {
+      word-break: break-word;
+      white-space: normal;
+    }
+  }
+
+  .NPC-word-tab-cixing {
+    box-sizing: border-box;
+
+    // width: 48px;
+    width: 60px;
+    font-family: 'robot', 'alabo';
+    text-align: left;
+    word-break: break-word;
+
+    // font-style: italic;  // 要求改为正体
+    &.NPC-word-tab-cixing-red {
+      color: #e35454;
+    }
+
+    &.NPC-word-tab-cixing-green {
+      color: #24b99e;
+    }
+
+    &.NPC-word-tab-cixing-brown {
+      color: #bd8865;
+    }
+
+    &.hasCn {
+      font-size: 13px;
+    }
+  }
+
+  .NPC-word-tab-def {
+    box-sizing: border-box;
+
+    // flex: 1;
+    font-family: 'robot', 'alabo';
+    word-break: break-word;
+    white-space: pre-wrap;
+
+    &.NPC-word-tab-def-red {
+      color: #e35454;
+    }
+
+    &.NPC-word-tab-def-green {
+      color: #24b99e;
+    }
+
+    &.NPC-word-tab-def-brown {
+      color: #bd8865;
+    }
+  }
+
+  .collocation {
+    display: flex;
+    width: 100%;
+
+    // padding-top: 8px;
+
+    > span {
+      flex-shrink: 0;
+      font-size: 16px;
+      font-weight: 400;
+      line-height: 24px;
+      color: #000;
+    }
+
+    > div b {
+      display: block;
+    }
+
+    > b,
+    > div b {
+      flex: 1;
+      font-family: 'robot', '楷体', 'alabo';
+      font-size: 16px;
+      font-weight: 400;
+      line-height: 24px;
+      color: rgba(0, 0, 0, 65%);
+    }
+  }
+
+  @keyframes firstrotate {
+    0% {
+      transform: rotateZ(0deg);
+    }
+
+    100% {
+      transform: rotateZ(180deg);
+    }
+  }
+
+  @keyframes huifuRotate {
+    0% {
+      transform: rotateZ(180deg);
+    }
+
+    100% {
+      transform: rotateZ(0deg);
+    }
+  }
+
+  .luyin-box-wordphrase {
+    height: 24px;
+  }
+
+  .NPC-word-tile {
+    display: flex;
+    flex-flow: wrap;
+    gap: 20px;
+    padding: 20px 0;
+  }
+
+  .writeTop {
+    position: relative;
+    display: flex;
+    column-gap: 8px;
+    width: 400px;
+
+    .left,
+    .right {
+      position: relative;
+      box-sizing: border-box;
+      width: 100%;
+      min-height: 270px;
+      padding: 8px 12px 18px;
+      overflow: hidden;
+      background: #fff;
+      border: 4px solid #fff;
+      border-radius: 24px;
+
+      .header-info {
+        display: flex;
+        justify-content: space-between;
+        width: 100%;
+        margin-bottom: 12px;
+
+        :deep .el-input__inner {
+          height: 24px;
+          padding: 0;
+          font-size: 24px;
+          font-weight: 400;
+          line-height: 100%;
+          color: rgba(0, 0, 0, 100%);
+          border: none;
+        }
+
+        .label {
+          :deep .el-input__inner {
+            text-align: right;
+          }
+        }
+      }
+    }
+
+    min-height: 332px;
+    transition: 0.6s;
+    perspective: 1000px;
+    transform-style: preserve-3d;
+
+    .left-preview {
+      padding-top: 40px;
+
+      // padding-bottom: 32px;
+      // position: absolute;
+      backface-visibility: hidden;
+    }
+
+    .header-info-preview {
+      position: absolute;
+      top: 0;
+      left: 0;
+      z-index: 1;
+      width: 100%;
+
+      h5 {
+        padding: 0 12px;
+        margin: 0;
+        font-size: 20px;
+        font-weight: 400;
+        line-height: 32px;
+        color: #000;
+      }
+
+      label {
+        position: absolute;
+        top: -4px;
+        right: -4px;
+        padding: 0 16px 0 8px;
+        font-size: 20px;
+        font-weight: 500;
+        line-height: 150%;
+        color: #fff;
+        background: #fff;
+        border-radius: 0 8px;
+      }
+    }
+
+    .left-big {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+
+    .del-btn {
+      position: absolute;
+      right: 8px;
+      bottom: 8px;
+      padding: 5px 8px;
+      font-size: 24px;
+      color: #fff;
+      cursor: pointer;
+      background: #f56767;
+      border-radius: 40px;
+    }
+
+    .overturn-btn {
+      position: absolute;
+      right: 8px;
+      bottom: 8px;
+      width: 40px;
+      height: 40px;
+      padding: 8px;
+      font-size: 24px;
+      line-height: 1;
+      color: #fff;
+      cursor: pointer;
+      background: #e0e0e0;
+      border-radius: 8px;
+    }
+
+    .el-icon-zoom-in,
+    .filt-check {
+      position: absolute;
+      bottom: 8px;
+      left: 8px;
+      width: 30px;
+      height: 30px;
+      font-size: 24px;
+      cursor: pointer;
+
+      :deep .el-checkbox__inner {
+        width: 24px;
+        height: 24px;
+      }
+
+      :deep .el-checkbox__inner::after {
+        left: 8px;
+        width: 6px;
+        height: 14px;
+      }
+    }
+
+    .right {
+      display: flex;
+      flex-flow: wrap;
+      row-gap: 8px;
+      align-items: center;
+      padding: 16px 24px 26px;
+
+      .card-label {
+        width: 100%;
+        height: 22px;
+        font-size: 14px;
+        font-weight: 400;
+        line-height: 22px;
+        color: #4e5969;
+      }
+
+      :deep .el-textarea {
+        height: 64px;
+      }
+
+      .config-box {
+        display: flex;
+        align-items: center;
+        width: 100%;
+
+        span {
+          margin-right: 8px;
+          font-size: 14px;
+          line-height: 20px;
+          color: #000;
+        }
+
+        .el-color-picker {
+          height: 32px;
+        }
+
+        :deep .el-color-picker__trigger {
+          height: 32px;
+        }
+
+        .el-radio {
+          margin-right: 8px;
+        }
+
+        .el-radio-group {
+          display: flex;
+        }
+
+        :deep .el-radio__input.is-checked .el-radio__inner {
+          background: #000;
+          border-color: #000;
+        }
+
+        :deep .el-radio__input.is-checked + .el-radio__label {
+          color: #000;
+        }
+      }
+    }
+
+    .right-preview {
+      display: block;
+      padding: 36px;
+
+      .pinyin-box {
+        margin-bottom: 8px;
+        font-family: 'League';
+        font-feature-settings: 'cv01' on;
+
+        // font-size: 18px;
+        line-height: 120%;
+        color: #de4444;
+        text-align: center;
+      }
+
+      .hz-box {
+        width: 100%;
+
+        .hz-item {
+          text-align: center;
+
+          :deep .strockplayInner {
+            width: 76px;
+            height: 76px;
+          }
+
+          p {
+            margin: 0 0 8px;
+            font-family: 'League';
+            font-size: 18px;
+            font-feature-settings: 'cv01' on;
+            line-height: 120%;
+            color: #de4444;
+          }
+        }
+      }
+
+      :deep .audio-wrapper {
+        box-sizing: border-box;
+        width: 50px;
+        height: 50px;
+        padding: 13px;
+        margin: 0 auto 8px;
+        cursor: pointer;
+        background: #f3f3f3;
+        border-radius: 40px;
+
+        .voice-play {
+          width: 24px;
+          height: 24px;
+        }
+      }
+
+      .definition_list-box {
+        margin-top: 16px;
+        white-space: pre;
+
+        > div {
+          display: flex;
+          margin-bottom: 8px;
+
+          label,
+          p {
+            width: 40px;
+            font-size: 14px;
+            font-weight: 400;
+            line-height: 150%;
+            color: #000;
+          }
+
+          label {
+            width: 47px;
+          }
+
+          p {
+            flex: 1;
+            line-height: 0;
+            word-break: break-word;
+            white-space: pre-wrap;
+          }
+        }
+      }
+
+      :deep p {
+        margin: 0;
+        line-height: 1.5;
+      }
+    }
+
+    .right-preview-rota {
+      transform: rotateY(180deg);
+    }
+
+    .item-image {
+      position: relative;
+      overflow: hidden;
+      font-size: 0;
+
+      // background: #f2f3f5;
+      border-radius: 8px;
+
+      .item-image-del {
+        position: absolute;
+        top: 8px;
+        right: 8px;
+        display: block;
+        width: 16px;
+        height: 16px;
+        padding: 8px;
+        font-size: 16px;
+        color: #ee3232;
+        cursor: pointer;
+        background-color: #fff;
+        border-radius: 50%;
+        box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 25%);
+      }
+    }
+
+    .item-con {
+      display: flex;
+      align-items: center;
+      width: 50%;
+      margin-top: 16px;
+
+      label {
+        width: 44px;
+        font-size: 14px;
+        font-weight: 400;
+        line-height: 22px;
+        color: #4e5969;
+      }
+
+      :deep .el-input__inner {
+        width: 235px;
+        height: 32px;
+        font-family: '楷体';
+        font-size: 14px;
+        font-weight: 400;
+        line-height: 22px;
+        background: #f2f3f5;
+        border: none;
+        border-radius: 2px;
+      }
+
+      .pinyin {
+        :deep .el-input__inner {
+          font-family: 'League';
+        }
+      }
+    }
+
+    .con-preview {
+      margin-top: 8px;
+      font-family: '楷体';
+      font-size: 38px;
+      font-weight: 400;
+      line-height: 100%;
+      color: #000;
+      text-align: center;
+
+      &-big {
+        margin: 0;
+        font-size: 86px;
+      }
+    }
+
+    .writeTop-row {
+      display: flex;
+      justify-content: center;
+    }
+  }
+
+  .flipped {
+    transform: rotateY(180deg);
+  }
+
+  .flipped-back {
+    transform: rotateY(180deg);
+  }
+
+  .hz-box {
+    display: flex;
+    width: max-content;
+  }
+
+  .writeTop-item {
+    border: 1px solid #de4444;
+  }
+
+  .writeTop-item-noLeft {
+    border-left: none;
+  }
+}
+
+.newWord-table {
+  .cell {
+    width: max-content;
+    white-space: nowrap;
+  }
+
+  :deep thead {
+    display: none;
+  }
+}
+</style>
+<style lang="scss">
+.NPC-zhedie {
+  .topTitle {
+    display: flex;
+    justify-content: space-between;
+    width: 100%;
+    height: 48px;
+    padding-right: 16px;
+    padding-left: 24px;
+    overflow: hidden;
+    background: #e35454;
+    border: 1px solid rgba(0, 0, 0, 10%);
+    border-radius: 8px 8px 0 0;
+
+    .NPC-top-left {
+      display: flex;
+      align-items: center;
+      justify-content: flex-start;
+
+      .NPC-topTitle-text {
+        margin-right: 8px;
+        font-family: 'sourceR';
+        font-size: 16px;
+        font-weight: bold;
+        color: #fff;
+        white-space: pre;
+      }
+    }
+
+    .NPC-top-right {
+      display: flex;
+      gap: 4px;
+      align-items: center;
+      justify-content: flex-start;
+      cursor: pointer;
+
+      &-text {
+        font-size: 14px;
+        font-weight: normal;
+        line-height: 16px;
+        color: #fff;
+      }
+
+      img {
+        width: 16px;
+        height: 16px;
+      }
+    }
+
+    img {
+      width: 24px;
+      height: 24px;
+    }
+
+    .rotate {
+      animation-name: firstrotate;
+      animation-timing-function: linear;
+      animation-direction: 2s;
+      animation-fill-mode: both;
+    }
+  }
+
+  .topTitleWhite {
+    display: flex;
+    justify-content: space-between;
+    width: 100%;
+    height: 48px;
+    padding-right: 16px;
+    padding-left: 24px;
+    overflow: hidden;
+    background: #fff;
+    border: 1px solid rgba(0, 0, 0, 10%);
+    border-radius: 8px 8px 0 0;
+
+    .NPC-top-left {
+      display: flex;
+      align-items: center;
+      justify-content: flex-start;
+
+      .NPC-topTitle-text {
+        margin-right: 8px;
+        font-family: 'sourceR';
+        font-size: 16px;
+        font-weight: bold;
+        color: #000;
+      }
+    }
+
+    .NPC-top-right {
+      display: flex;
+      align-items: center;
+      justify-content: flex-start;
+      cursor: pointer;
+
+      &-text {
+        font-size: 14px;
+        font-weight: normal;
+        line-height: 16px;
+        color: #000;
+      }
+
+      img {
+        width: 16px;
+        height: 16px;
+        margin-left: 4px;
+      }
+    }
+
+    img {
+      width: 24px;
+      height: 24px;
+    }
+
+    .rotate {
+      animation-name: firstrotate;
+      animation-timing-function: linear;
+      animation-direction: 2s;
+      animation-fill-mode: both;
+    }
+  }
+
+  .el-collapse-item__content {
+    padding-bottom: 0;
+  }
+
+  .el-slider__button {
+    width: 8px;
+    height: 8px;
+  }
+
+  .el-slider__runway {
+    padding: 0;
+    margin: 0;
+  }
+
+  .el-slider {
+    position: relative;
+
+    // top: -3px;
+  }
+
+  .el-collapse {
+    box-sizing: border-box;
+    background: #f7f7f7;
+    border-radius: 8px;
+  }
+
+  .el-collapse-item__wrap {
+    background: #f7f7f7;
+    border: 1px solid rgba(0, 0, 0, 10%);
+    border-top: 0;
+    border-radius: 0 0 8px 8px;
+  }
+
+  .el-collapse-item__arrow {
+    display: none;
+  }
+
+  .el-table__row {
+    padding: 4px 0;
+  }
+}
+</style>