Selaa lähdekoodia

表头分离表格改进

dusenyao 2 vuotta sitten
vanhempi
commit
b9f857190d

+ 91 - 83
src/components/Adult/Preview.vue

@@ -16,15 +16,15 @@
           <template
             v-if="
               item.detail &&
-                item.detail.wordsList &&
-                item.detail.wordsList.length == 0
+              item.detail.wordsList &&
+              item.detail.wordsList.length == 0
             "
           >
             <p
               v-if="item.detail.sentence"
               :class="[
                 'content-con',
-                /^[\u4e00-\u9fa5]/.test(item.detail.sentence) ? 'hasCn' : ''
+                /^[\u4e00-\u9fa5]/.test(item.detail.sentence) ? 'hasCn' : '',
               ]"
               v-html="item.detail.sentence"
             />
@@ -40,12 +40,11 @@
                 <template
                   v-if="
                     item.detail &&
-                      item.detail.wordsList &&
-                      item.detail.wordsList[indexCon + 1] &&
-                      item.detail.wordsList[indexCon + 1].chs &&
-                      chsFhList.indexOf(
-                        item.detail.wordsList[indexCon + 1].chs
-                      ) > -1
+                    item.detail.wordsList &&
+                    item.detail.wordsList[indexCon + 1] &&
+                    item.detail.wordsList[indexCon + 1].chs &&
+                    chsFhList.indexOf(item.detail.wordsList[indexCon + 1].chs) >
+                      -1
                   "
                 >
                   <div class="synthesis-box">
@@ -53,7 +52,7 @@
                       <span
                         class="pinyin"
                         :class="[
-                          noFont.indexOf(itemCon.pinyin) > -1 ? 'noFont' : ''
+                          noFont.indexOf(itemCon.pinyin) > -1 ? 'noFont' : '',
                         ]"
                         >{{ itemCon.pinyin }}</span
                       >
@@ -70,7 +69,7 @@
                             item.detail.wordsList[indexCon + 1].pinyin
                           ) > -1
                             ? 'noFont'
-                            : ''
+                            : '',
                         ]"
                         >{{ item.detail.wordsList[indexCon + 1].pinyin }}</span
                       >
@@ -84,29 +83,38 @@
                   <span
                     class="pinyin"
                     :class="[
-                      noFont.indexOf(itemCon.pinyin) > -1 ? 'noFont' : ''
+                      noFont.indexOf(itemCon.pinyin) > -1 ? 'noFont' : '',
                     ]"
-                    v-if="item.detail &&
-                      !(item.detail.wordsList &&
-                      item.detail.wordsList[indexCon - 1] &&
-                      item.detail.wordsList[indexCon - 1].chs &&
-                      chsFhList.indexOf(
-                        item.detail.wordsList[indexCon - 1].chs
-                      ) == -1&&chsFhList.indexOf(
-                        itemCon.chs
-                      ) > -1)"
+                    v-if="
+                      item.detail &&
+                      !(
+                        item.detail.wordsList &&
+                        item.detail.wordsList[indexCon - 1] &&
+                        item.detail.wordsList[indexCon - 1].chs &&
+                        chsFhList.indexOf(
+                          item.detail.wordsList[indexCon - 1].chs
+                        ) == -1 &&
+                        chsFhList.indexOf(itemCon.chs) > -1
+                      )
+                    "
                     >{{ itemCon.pinyin }}</span
                   >
-                  <span class="hanzi content-con"
-                  v-if="item.detail &&
-                      !(item.detail.wordsList &&
-                      item.detail.wordsList[indexCon - 1] &&
-                      item.detail.wordsList[indexCon - 1].chs &&
-                      chsFhList.indexOf(
-                        item.detail.wordsList[indexCon - 1].chs
-                      ) == -1&&chsFhList.indexOf(
-                        itemCon.chs
-                      ) > -1)">{{ itemCon.chs }}</span>
+                  <span
+                    class="hanzi content-con"
+                    v-if="
+                      item.detail &&
+                      !(
+                        item.detail.wordsList &&
+                        item.detail.wordsList[indexCon - 1] &&
+                        item.detail.wordsList[indexCon - 1].chs &&
+                        chsFhList.indexOf(
+                          item.detail.wordsList[indexCon - 1].chs
+                        ) == -1 &&
+                        chsFhList.indexOf(itemCon.chs) > -1
+                      )
+                    "
+                    >{{ itemCon.chs }}</span
+                  >
                 </template>
               </div>
             </div>
@@ -152,7 +160,7 @@
           (previewType == 'previewCheckShow' && item.previewShow) ||
           JSON.parse(previewGroupId).length == 0
             ? 'NNPE-Book-content-item'
-            : ''
+            : '',
         ]"
       >
         <el-checkbox
@@ -166,9 +174,9 @@
         <template
           v-if="
             !previewType ||
-              previewType == 'previewCheck' ||
-              (previewType == 'previewCheckShow' && item.previewShow) ||
-              JSON.parse(previewGroupId).length == 0
+            previewType == 'previewCheck' ||
+            (previewType == 'previewCheckShow' && item.previewShow) ||
+            JSON.parse(previewGroupId).length == 0
           "
         >
           <div
@@ -191,7 +199,7 @@
           <div
             class="title-little"
             :class="[
-              item.little_title_number || item.little_title ? 'marginTop' : ''
+              item.little_title_number || item.little_title ? 'marginTop' : '',
             ]"
           >
             <b v-html="item.little_title_number" />
@@ -200,7 +208,7 @@
           <div
             :class="[
               'NNPE-tableList',
-              item.is_bg ? 'NNPE-tableList-hasBg' : ''
+              item.is_bg ? 'NNPE-tableList-hasBg' : '',
             ]"
           >
             <div
@@ -210,7 +218,7 @@
               :class="[
                 indexs === item.table_list.length - 1
                   ? 'NNPE-tableList-tr-last'
-                  : ''
+                  : '',
               ]"
             >
               <div
@@ -220,7 +228,7 @@
                   'NNPE-tableList-item',
                   items.length == 1
                     ? 'NNPE-tableList-item-noMargin'
-                    : 'NNPE-tableList-item' + items.length
+                    : 'NNPE-tableList-item' + items.length,
                 ]"
               >
                 <template v-if="itemss.data">
@@ -231,12 +239,12 @@
                       :task-model="TaskModel"
                       :number="
                         index +
-                          '_' +
-                          indexs +
-                          '_' +
-                          indexss +
-                          '_' +
-                          currentTreeID
+                        '_' +
+                        indexs +
+                        '_' +
+                        indexss +
+                        '_' +
+                        currentTreeID
                       "
                     />
                   </template>
@@ -371,10 +379,10 @@
                   <template
                     v-if="
                       itemss.type == 'inputItem_chs' ||
-                        itemss.type == 'sentence_input_chs' ||
-                        itemss.type == 'sentence_judge_chs' ||
-                        itemss.type == 'sentence_record_chs' ||
-                        itemss.type == 'sentence_input_record_chs'
+                      itemss.type == 'sentence_input_chs' ||
+                      itemss.type == 'sentence_judge_chs' ||
+                      itemss.type == 'sentence_record_chs' ||
+                      itemss.type == 'sentence_input_record_chs'
                     "
                   >
                     <SentenceInput
@@ -512,9 +520,9 @@
                   <template
                     v-if="
                       itemss.type == 'record_control_mini' ||
-                        itemss.type == 'record_control_normal' ||
-                        itemss.type == 'record_control_pro' ||
-                        itemss.type == 'record_control_promax'
+                      itemss.type == 'record_control_normal' ||
+                      itemss.type == 'record_control_pro' ||
+                      itemss.type == 'record_control_promax'
                     "
                   >
                     <RecordModule
@@ -527,7 +535,7 @@
                   <template
                     v-if="
                       itemss.type == 'upload_control_chs' ||
-                        itemss.type == 'upload_control_preview_chs'
+                      itemss.type == 'upload_control_preview_chs'
                     "
                   >
                     <UploadControlView
@@ -563,12 +571,12 @@
                       :theme-color="themeColor"
                       :index-str="
                         index +
-                          '_' +
-                          indexs +
-                          '_' +
-                          indexss +
-                          '_' +
-                          currentTreeID
+                        '_' +
+                        indexs +
+                        '_' +
+                        indexss +
+                        '_' +
+                        currentTreeID
                       "
                       :task-model="TaskModel"
                     />
@@ -674,7 +682,7 @@ import VoiceMatrix from "./preview/VoiceMatrix.vue"; // 语音矩阵
 import SelectDrag from "./preview/SelectDrag.vue"; // 选择 -> 拖拽
 import FillDrag from "./preview/FillDrag.vue"; // 填空 -> 拖拽
 import ConfigurableTable from "./preview/ConfigurableTable.vue"; // 可配置表格
-import HeaderSeparate from "./preview/HeaderSeparate.vue"; // 表头分离表格
+import HeaderSeparate from "./preview/HeaderSparate/index.vue"; // 表头分离表格
 import RecordModule from "./preview/RecordModule.vue"; // 录音组件
 import UploadControlView from "./preview/UploadControlView.vue"; // 预览控件
 import DialogueAnswerViewChs from "./preview/DialogueArticleViewChs/DialogueAnswerViewChs.vue"; // 文章模板
@@ -727,7 +735,7 @@ export default {
     PdfView,
     PlayRecordView,
     SentenceModule,
-    OptionsList
+    OptionsList,
   },
   props: [
     "context",
@@ -741,7 +749,7 @@ export default {
     "TaskModel",
     "isShowSave",
     "previewType",
-    "previewGroupId"
+    "previewGroupId",
   ],
   data() {
     return {
@@ -759,24 +767,24 @@ export default {
       colorBox: [
         {
           touxiang: "#72B51D",
-          bg: "#E9F0DF"
+          bg: "#E9F0DF",
         },
         {
           touxiang: "#DE4444",
-          bg: "rgba(222, 68, 68, 0.1)"
+          bg: "rgba(222, 68, 68, 0.1)",
         },
         {
           touxiang: "#A7A7A7",
-          bg: "#ffffff"
+          bg: "#ffffff",
         },
         {
           touxiang: "#4D91F6",
-          bg: "#F1F7FF"
+          bg: "#F1F7FF",
         },
         {
           touxiang: "#FF8A00",
-          bg: "rgba(255, 138, 0, 0.1)"
-        }
+          bg: "rgba(255, 138, 0, 0.1)",
+        },
       ],
       chsFhList: [",", "。", "“", ":", "》", "《", "?", "!", ";"],
       noFont: ["~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")"], // 对应不要拼音字体
@@ -788,7 +796,7 @@ export default {
       answerTime: 0,
       answerTimeInterval: null, // 计时器
       groupIndexList: [], // 勾选groupid数组
-      groupCheckList: [] // checkbox 是否选中
+      groupCheckList: [], // checkbox 是否选中
     };
   },
   computed: {},
@@ -829,8 +837,8 @@ export default {
         }
       },
       // 深度观察监听
-      deep: true
-    }
+      deep: true,
+    },
   },
   // 生命周期 - 创建完成(可以访问当前this实例)
   created() {},
@@ -884,7 +892,7 @@ export default {
             let obj = {
               pinyin: sItem.pinyin,
               chs: sItem.chs,
-              isShow: true
+              isShow: true,
             };
             paraArr.push(obj);
           });
@@ -932,8 +940,8 @@ export default {
         _this.cur = _this.contextData;
         _this.cur.cur_fn_data.forEach((item, index) => {
           this.groupCheckList.push(false);
-          selectGropuIdList.forEach(itemId => {
-            itemId.forEach(itemIds => {
+          selectGropuIdList.forEach((itemId) => {
+            itemId.forEach((itemIds) => {
               if (item.group_id && itemIds.indexOf(item.group_id[0]) > -1) {
                 item.previewShow = true;
               }
@@ -1015,11 +1023,11 @@ export default {
     },
     puaseAudio() {
       let audio = document.getElementsByTagName("audio");
-      audio.forEach(item => {
+      audio.forEach((item) => {
         item.pause();
       });
       let video = document.getElementsByTagName("video");
-      video.forEach(item => {
+      video.forEach((item) => {
         item.pause();
       });
     },
@@ -1052,7 +1060,7 @@ export default {
       let result = [];
       contextData.cur_fn_data.forEach((item, index) => {
         result[index] = {
-          table_list: []
+          table_list: [],
         };
         item.table_list.forEach((items, indexs) => {
           result[index].table_list[indexs] = [];
@@ -1061,13 +1069,13 @@ export default {
               let Bookanswer = itemss.data.Bookanswer;
               let obj = {
                 data: {
-                  Bookanswer
-                }
+                  Bookanswer,
+                },
               };
               result[index].table_list[indexs][indexss] = obj;
             } else {
               result[index].table_list[indexs][indexss] = {
-                data: null
+                data: null,
               };
             }
           });
@@ -1119,8 +1127,8 @@ export default {
         }
       });
       this.$forceUpdate();
-    }
-  } // 如果页面有keep-alive缓存功能,这个函数会触发
+    },
+  }, // 如果页面有keep-alive缓存功能,这个函数会触发
 };
 </script>
 <style lang="scss" scoped>
@@ -1519,4 +1527,4 @@ export default {
     top: 2px;
   }
 }
-</style>
+</style>

+ 54 - 35
src/components/Adult/inputModules/HeaderSeparate/components/CellEdit.vue

@@ -6,19 +6,37 @@
     :close-on-click-modal="false"
     :modal="false"
   >
-    <label>内容类型:</label>
-    <el-select v-model="cellData.type">
-      <el-option
-        v-for="{ value, label } in cellTypeList"
-        :key="value"
-        :label="label"
-        :value="value"
-      />
-    </el-select>
+    <el-form :model="cellData" :inline="true">
+      <el-form-item label="下划线">
+        <el-switch v-model="cellData.isUnderline" />
+      </el-form-item>
+      <el-form-item label="背景色">
+        <el-color-picker v-model="cellData.background" />
+      </el-form-item>
+      <el-form-item label="勾叉">
+        <el-switch v-model="cellData.isCross" />
+      </el-form-item>
+      <el-form-item label="合并行">
+        <el-input v-model="cellData.rowspan" class="rowspan" type="number" />
+      </el-form-item>
+      <el-form-item label="合并列">
+        <el-input v-model="cellData.colspan" class="colspan" type="number" />
+      </el-form-item>
+      <el-form-item label="内容类型">
+        <el-select v-model="cellData.type">
+          <el-option
+            v-for="{ value, label } in cellTypeList"
+            :key="value"
+            :label="label"
+            :value="value"
+          />
+        </el-select>
+      </el-form-item>
+    </el-form>
     <div class="dialog-container">
       <el-input v-show="cellData.type === 'content'" v-model="cellData.text" />
 
-      <sentence-segword-chs
+      <SentenceSegwordChs
         v-if="cellData.type === 'pinyin'"
         :cur-que="cellData.sentence_data"
         type="adultinput"
@@ -29,27 +47,18 @@
         <el-input v-model="cellData.message">
           <template slot="prepend">
             <el-select v-model="cellData.prefixOrSuffix">
-              <el-option
-                key="prefix"
-                label="前缀"
-                value="prefix"
-              />
-              <el-option
-                key="suffix"
-                label="后缀"
-                value="suffix"
-              />
+              <el-option key="prefix" label="前缀" value="prefix" />
+              <el-option key="suffix" label="后缀" value="suffix" />
             </el-select>
           </template>
         </el-input>
 
-        <sentence-segword-chs
+        <SentenceSegwordChs
           :cur-que="cellData.sentence_data"
           type="adultinput"
           :is-hide-py-position="true"
         />
       </template>
-
     </div>
     <div slot="footer">
       <el-button type="primary" @click="confirm">确定</el-button>
@@ -65,39 +74,39 @@ export default {
   props: {
     visible: {
       type: Boolean,
-      required: true
+      required: true,
     },
     body: {
       type: Array,
-      required: true
+      required: true,
     },
     curIndex: {
       type: Object,
-      required: true
-    }
+      required: true,
+    },
   },
   data() {
     return {
       cellTypeList: [
         {
           label: "内容",
-          value: "content"
+          value: "content",
         },
         {
           label: "拼音",
-          value: "pinyin"
+          value: "pinyin",
         },
         {
-          label: '前后缀 + 拼音',
-          value: 'prePinyin'
-        }
-      ]
+          label: "前后缀 + 拼音",
+          value: "prePinyin",
+        },
+      ],
     };
   },
   computed: {
     cellData() {
       return this.body[this.curIndex.row].content[this.curIndex.col];
-    }
+    },
   },
   methods: {
     close() {
@@ -106,8 +115,8 @@ export default {
 
     confirm() {
       this.$emit("close");
-    }
-  }
+    },
+  },
 };
 </script>
 
@@ -119,6 +128,16 @@ export default {
     width: 80px;
   }
 }
+::v-deep .set-up {
+  margin-bottom: 8px;
+}
+
+::v-deep .el-form {
+  .colspan,
+  .rowspan {
+    width: 70px;
+  }
+}
 </style>
 
 <style lang="scss">

+ 93 - 72
src/components/Adult/inputModules/HeaderSeparate/index.vue

@@ -3,22 +3,18 @@
     <div class="header-separate-options">
       <div>
         表头英文位置:
-        <el-radio
-          v-model="curQue.headerEnglishPosition"
-          label="top"
-        >上</el-radio>
-        <el-radio
-          v-model="curQue.headerEnglishPosition"
-          label="right"
-        >右</el-radio>
-        <el-radio
-          v-model="curQue.headerEnglishPosition"
-          label="bottom"
-        >下</el-radio>
-        <el-radio
-          v-model="curQue.headerEnglishPosition"
-          label="left"
-        >左</el-radio>
+        <el-radio v-model="curQue.headerEnglishPosition" label="top">
+          上
+        </el-radio>
+        <el-radio v-model="curQue.headerEnglishPosition" label="right">
+          右
+        </el-radio>
+        <el-radio v-model="curQue.headerEnglishPosition" label="bottom">
+          下
+        </el-radio>
+        <el-radio v-model="curQue.headerEnglishPosition" label="left">
+          左
+        </el-radio>
       </div>
       <div>
         单元格拼音位置:
@@ -30,7 +26,9 @@
       <div>
         首列对齐方式:
         <el-radio v-model="curQue.firstColAligin" label="center">居中</el-radio>
-        <el-radio v-model="curQue.firstColAligin" label="follow">跟随内容</el-radio>
+        <el-radio v-model="curQue.firstColAligin" label="follow">
+          跟随内容
+        </el-radio>
       </div>
       <div>
         内容对齐方式:
@@ -81,7 +79,7 @@
       </table>
     </div>
 
-    <cell-edit
+    <CellEdit
       :visible="visible"
       :body="curQue.tableData.body"
       :cur-index="curIndex"
@@ -91,7 +89,7 @@
 </template>
 
 <script>
-import CellEdit from './components/CellEdit';
+import CellEdit from "./components/CellEdit.vue";
 
 export default {
   components: { CellEdit },
@@ -111,16 +109,16 @@ export default {
             headers: [
               {
                 text: "",
-                english: ""
+                english: "",
               },
               {
                 text: "",
-                english: ""
+                english: "",
               },
               {
                 text: "",
-                english: ""
-              }
+                english: "",
+              },
             ],
             body: [
               {
@@ -128,8 +126,13 @@ export default {
                   {
                     type: "content",
                     text: "",
-                    message: '',
-                    prefixOrSuffix: 'prefix', // 前缀或后缀
+                    message: "",
+                    prefixOrSuffix: "prefix", // 前缀或后缀
+                    isUnderline: false, // 下划线
+                    background: "#fff", // 背景色
+                    isCross: false, // 勾叉
+                    rowspan: 1,
+                    colspan: 1,
                     sentence_data: {
                       type: "sentence_segword_chs",
                       name: "句子分词",
@@ -137,14 +140,19 @@ export default {
                       sentence: "", // 句子
                       segList: [], // 分词结果
                       seg_words: "",
-                      wordsList: []
-                    }
+                      wordsList: [],
+                    },
                   },
                   {
                     type: "content",
                     text: "",
-                    message: '',
-                    prefixOrSuffix: 'prefix',
+                    message: "",
+                    prefixOrSuffix: "prefix",
+                    isUnderline: false,
+                    background: "#fff",
+                    isCross: false,
+                    rowspan: 1,
+                    colspan: 1,
                     sentence_data: {
                       type: "sentence_segword_chs",
                       name: "句子分词",
@@ -152,14 +160,19 @@ export default {
                       sentence: "", // 句子
                       segList: [], // 分词结果
                       seg_words: "",
-                      wordsList: []
-                    }
+                      wordsList: [],
+                    },
                   },
                   {
                     type: "content",
                     text: "",
-                    message: '',
-                    prefixOrSuffix: 'prefix',
+                    message: "",
+                    prefixOrSuffix: "prefix",
+                    isUnderline: false,
+                    background: "#fff",
+                    isCross: false,
+                    rowspan: 1,
+                    colspan: 1,
                     sentence_data: {
                       type: "sentence_segword_chs",
                       name: "句子分词",
@@ -167,31 +180,31 @@ export default {
                       sentence: "", // 句子
                       segList: [], // 分词结果
                       seg_words: "",
-                      wordsList: []
-                    }
-                  }
-                ]
-              }
+                      wordsList: [],
+                    },
+                  },
+                ],
+              },
             ],
             colsConfig: {
-              width: [{ val: 100 }, { val: 100 }, { val: 100 }]
-            }
-          }
+              width: [{ val: 100 }, { val: 100 }, { val: 100 }],
+            },
+          },
         };
-      }
+      },
     },
     changeCurQue: {
       type: Function,
-      required: true
-    }
+      required: true,
+    },
   },
   data() {
     return {
       visible: false,
       curIndex: {
         col: 0,
-        row: 0
-      }
+        row: 0,
+      },
     };
   },
   computed: {
@@ -201,7 +214,7 @@ export default {
     cols() {
       if (this.rows.length <= 0) return 0;
       return this.curQue.tableData.body[0].content.length;
-    }
+    },
   },
   created() {
     if (this.curQue.isFirst) {
@@ -215,8 +228,13 @@ export default {
         content.push({
           type: "content",
           text: "",
-          message: '',
-          prefixOrSuffix: 'prefix',
+          message: "",
+          prefixOrSuffix: "prefix",
+          isUnderline: false,
+          background: "#fff",
+          isCross: false,
+          rowspan: 1,
+          colspan: 1,
           sentence_data: {
             type: "sentence_segword_chs",
             name: "句子分词",
@@ -224,13 +242,13 @@ export default {
             sentence: "", // 句子
             segList: [], // 分词结果
             seg_words: "",
-            wordsList: []
-          }
+            wordsList: [],
+          },
         });
       });
       this.curQue.tableData.headers.push({
         text: "",
-        english: ""
+        english: "",
       });
       this.curQue.tableData.colsConfig.width.push({ val: 100 });
     },
@@ -239,14 +257,13 @@ export default {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning",
-      })
-        .then(() => {
-          this.curQue.tableData.body.forEach(({ content }) => {
-            content.splice(i, 1);
-          });
-          this.curQue.tableData.headers.splice(i, 1);
-          this.curQue.tableData.colsConfig.width.splice(i, 1);
+      }).then(() => {
+        this.curQue.tableData.body.forEach(({ content }) => {
+          content.splice(i, 1);
         });
+        this.curQue.tableData.headers.splice(i, 1);
+        this.curQue.tableData.colsConfig.width.splice(i, 1);
+      });
     },
 
     addRow() {
@@ -255,8 +272,13 @@ export default {
         content.push({
           type: "content",
           text: "",
-          message: '', // 内容
-          prefixOrSuffix: 'prefix',
+          message: "", // 内容
+          prefixOrSuffix: "prefix",
+          isUnderline: false,
+          background: "#fff",
+          isCross: false,
+          rowspan: 1,
+          colspan: 1,
           sentence_data: {
             type: "sentence_segword_chs",
             name: "句子分词",
@@ -264,12 +286,12 @@ export default {
             sentence: "", // 句子
             segList: [], // 分词结果
             seg_words: "",
-            wordsList: []
-          }
+            wordsList: [],
+          },
         });
       }
       this.curQue.tableData.body.push({
-        content
+        content,
       });
     },
     deleteRow(i) {
@@ -277,24 +299,23 @@ export default {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning",
-      })
-        .then(() => {
-          if (this.rows <= 1) return this.$message.warning("必须留一行");
-          this.curQue.tableData.body.splice(i, 1);
-        });
+      }).then(() => {
+        if (this.rows <= 1) return this.$message.warning("必须留一行");
+        this.curQue.tableData.body.splice(i, 1);
+      });
     },
 
     edit(i, j) {
       this.curIndex = {
         col: j,
-        row: i
+        row: i,
       };
       this.visible = true;
     },
     close() {
       this.visible = false;
-    }
-  }
+    },
+  },
 };
 </script>
 

+ 0 - 372
src/components/Adult/preview/HeaderSeparate.vue

@@ -1,372 +0,0 @@
-<template>
-  <div class="header-separate">
-    <table>
-      <colgroup>
-        <col
-          v-for="(item, i) in curQue.tableData.colsConfig.width"
-          :key="`col-${i}`"
-          :style="{ width: `${item.val}px` }"
-        >
-      </colgroup>
-
-      <thead>
-        <tr>
-          <th
-            v-for="({ text, english }, i) in curQue.tableData.headers"
-            :key="`th-${i}`"
-          >
-            <div class="thead-content" :style="theadStyle">
-              <span class="chs">{{ text }}</span><span class="english">{{ english }}</span>
-            </div>
-          </th>
-        </tr>
-      </thead>
-
-      <tbody
-        :style="{
-          'text-align': `${curQue.textAlign}`,
-        }"
-      >
-        <tr v-for="(row, i) in curQue.tableData.body" :key="`tr-${i}`">
-          <td
-            v-for="(col, j) in row.content"
-            :key="`td-${j}`"
-            :class="[
-              `${curQue.firstColAligin === 'center' ? 'col-center' : ''}`,
-            ]"
-          >
-            <template v-if="col.type === 'content'">
-              <template v-if="col.text.length > 0">
-                {{ col.text }}
-              </template>
-              <template v-else>
-                <el-input
-                  v-model="col.answer"
-                  type="textarea"
-                  :placeholder="`${isAnswerMode ? '' : '输入'}`"
-                  :disabled="isAnswerMode"
-                  :autosize="{ minRows: 1, maxRows: 6 }"
-                  @input="enterAnswer(i, j, $event)"
-                />
-              </template>
-            </template>
-
-            <div
-              v-else-if="col.type === 'pinyin'"
-              class="sentence"
-              :style="pinyinStyle"
-            >
-              <div>
-                <span
-                  v-for="({ pinyin, chs }, k) in col.sentence_data.wordsList"
-                  :key="`${
-                    curQue.pinyinPosition === 'top' ||
-                    curQue.pinyinPosition === 'left'
-                      ? 'pinyin'
-                      : 'chs'
-                  }-${k}`"
-                  :class="[
-                    `${
-                      curQue.pinyinPosition === 'top' ||
-                      curQue.pinyinPosition === 'left'
-                        ? 'pinyin'
-                        : 'chs'
-                    }`,
-                  ]"
-                >
-                  {{
-                    curQue.pinyinPosition === "top" ||
-                      curQue.pinyinPosition == "left"
-                      ? pinyin
-                      : chs
-                  }}
-                </span>
-              </div>
-              <div>
-                <span
-                  v-for="({ pinyin, chs }, k) in col.sentence_data.wordsList"
-                  :key="`${
-                    curQue.pinyinPosition === 'top' ||
-                    curQue.pinyinPosition === 'left'
-                      ? 'chs'
-                      : 'pinyin'
-                  }-${k}`"
-                  :class="[
-                    `${
-                      curQue.pinyinPosition === 'top' ||
-                      curQue.pinyinPosition === 'left'
-                        ? 'chs'
-                        : 'pinyin'
-                    }`,
-                  ]"
-                >
-                  {{
-                    curQue.pinyinPosition === "top" ||
-                      curQue.pinyinPosition == "left"
-                      ? chs
-                      : pinyin
-                  }}
-                </span>
-              </div>
-            </div>
-
-            <div
-              v-else-if="col.type === 'prePinyin'"
-              :style="{
-                'flex-direction':
-                  col.prefixOrSuffix === 'prefix' ? 'row' : 'row-reverse',
-              }"
-              class="pre-pinyin"
-            >
-              <span>{{ col.message }}</span>
-              <div class="right-pinyin">
-                <div>
-                  <span
-                    v-for="({ pinyin }, k) in col.sentence_data.wordsList"
-                    :key="`pre-pinyin-${k}`"
-                    class="pinyin"
-                  >
-                    {{ pinyin }}
-                  </span>
-                </div>
-                <div>
-                  <span
-                    v-for="({ pinyin, chs }, k) in col.sentence_data.wordsList"
-                    :key="`pre-chs-${k}`"
-                  >
-                    {{ chs }}
-                  </span>
-                </div>
-              </div>
-            </div>
-          </td>
-        </tr>
-      </tbody>
-    </table>
-  </div>
-</template>
-
-<script>
-export default {
-  props: {
-    curQue: {
-      type: Object,
-      required: true,
-    },
-    themeColor: {
-      type: String,
-      required: true,
-    },
-  },
-  data() {
-    return {
-      isAnswerMode: false,
-    };
-  },
-  computed: {
-    theadStyle() {
-      const hp = this.curQue.headerEnglishPosition;
-      if (hp === "top") {
-        return {
-          "flex-direction": "column-reverse",
-        };
-      }
-      if (hp === "right") {
-        return {
-          "flex-direction": "row",
-          "column-gap": "8px",
-        };
-      }
-      if (hp === "bottom") {
-        return {
-          "flex-direction": "column",
-        };
-      }
-      if (hp === "left") {
-        return {
-          "flex-direction": "row-reverse",
-          "column-gap": "8px",
-        };
-      }
-    },
-    pinyinStyle() {
-      let pyPos = this.curQue.pinyinPosition;
-      if (pyPos === "left") {
-        return {
-          "column-gap": "16px",
-        };
-      }
-
-      if (pyPos === "top") {
-        return {
-          "flex-direction": "column",
-        };
-      }
-
-      if (pyPos === "right") {
-        return {
-          "column-gap": "16px",
-        };
-      }
-
-      if (pyPos === "bottom") {
-        return {
-          "flex-direction": "column",
-        };
-      }
-    },
-  },
-  created() {
-    const Bookanswer = this.curQue.Bookanswer;
-    if (Bookanswer) {
-      this.isAnswerMode = true;
-      for (const key in Bookanswer) {
-        let { col, row, value } = Bookanswer[key];
-        this.curQue.tableData.body[col].content[row].answer = value;
-      }
-    } else {
-      this.$set(this.curQue, "Bookanswer", {});
-    }
-  },
-  methods: {
-    enterAnswer(i, j, value) {
-      this.curQue.Bookanswer[`${i}-${j}`] = {
-        col: i,
-        row: j,
-        value,
-      };
-    },
-  },
-};
-</script>
-
-<style lang="scss" scoped>
-.header-separate {
-  width: 100%;
-  margin-bottom: 16px;
-
-  table {
-    table-layout: fixed;
-    font-size: 16px;
-    border-collapse: separate;
-    border-spacing: 6px 0;
-
-    th {
-      color: #4d4c51;
-      font-weight: normal;
-      background-color: #efeff9;
-      padding: 4px 12px;
-      border: 2px solid #afb4d1;
-
-      .thead-content {
-        display: flex;
-        justify-content: center;
-
-        .english {
-          color: #000;
-        }
-      }
-    }
-
-    td {
-      color: #474747;
-      border-bottom: 1px solid transparent;
-      padding: 4px 12px;
-      min-height: 28px;
-
-      .sentence {
-        display: flex;
-      }
-
-      // 前缀 + 拼音
-      .pre-pinyin {
-        display: flex;
-        align-items: flex-end;
-
-        .right-pinyin {
-          row-gap: 2px;
-          flex-direction: column;
-          text-align: center;
-          display: flex;
-        }
-      }
-
-      &:first-child {
-        border-left: 2px solid transparent;
-        border-bottom-width: 1px;
-        border-image: linear-gradient(
-            transparent 6px,
-            #e7b576 6px,
-            #e7b576 calc(100% - 6px),
-            transparent calc(100% - 6px),
-            transparent calc(100% - 2px),
-            #cecece calc(100% - 2px)
-          )
-          2;
-        border-image-outset: 0 4px 0 0;
-
-        &.col-center {
-          text-align: center;
-        }
-      }
-
-      &:not(:last-child) {
-        position: relative;
-        // 用 ::after 模拟中间边框
-        &::after {
-          content: "";
-          position: absolute;
-          top: 0;
-          left: calc(100% + 2px);
-          width: 2px;
-          height: 100%;
-          display: inline-block;
-          background: repeating-linear-gradient(
-            transparent,
-            transparent 3px,
-            #cecece 3px,
-            #cecece 7px,
-            transparent 7px
-          );
-        }
-      }
-
-      // 中间的底部边框用 ::before 模拟
-      &:not(:first-child):not(:last-child)::before {
-        content: "";
-        position: absolute;
-        top: 100%;
-        left: 0;
-        width: 100%;
-        height: 1px;
-        display: inline-block;
-        background-color: #cecece;
-        box-shadow: 2px 0 #cecece, -2px 0 #cecece;
-      }
-
-      &:last-child {
-        border-right: 2px solid transparent;
-        border-bottom-width: 1px;
-        border-image: linear-gradient(
-            transparent 6px,
-            #e7b576 6px,
-            #e7b576 calc(100% - 6px),
-            transparent calc(100% - 6px),
-            transparent calc(100% - 2px),
-            #cecece calc(100% - 2px)
-          )
-          2;
-        border-image-outset: 0 0 0 4px;
-      }
-    }
-
-    .pinyin {
-      font-family: "GB-PINYINOK-B";
-    }
-
-    .chs {
-      font-family: "FZJCGFKTK";
-    }
-  }
-}
-</style>

+ 40 - 0
src/components/Adult/preview/HeaderSparate/CrossTick.vue

@@ -0,0 +1,40 @@
+<template>
+  <div class="cross-tick" @click="toggle">
+    <i
+      :class="[
+        { 'el-icon-check': status === statusList[1] },
+        { 'el-icon-close': status === statusList[2] },
+      ]"
+    />
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      status: "normal",
+      statusList: ["normal", "tick", "cross"],
+    };
+  },
+  methods: {
+    toggle() {
+      const index = this.statusList.findIndex((item) => this.status === item);
+      this.status =
+        index === this.statusList.length - 1
+          ? this.statusList[0]
+          : this.statusList[index + 1];
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.cross-tick {
+  height: 18px;
+  min-width: 18px;
+  width: 18px;
+  border: 1px solid #999;
+  cursor: pointer;
+}
+</style>

+ 456 - 0
src/components/Adult/preview/HeaderSparate/index.vue

@@ -0,0 +1,456 @@
+<template>
+  <div class="header-separate">
+    <table>
+      <colgroup>
+        <col
+          v-for="(item, i) in curQue.tableData.colsConfig.width"
+          :key="`col-${i}`"
+          :style="{ width: `${item.val}px` }"
+        />
+      </colgroup>
+
+      <thead>
+        <tr>
+          <th
+            v-for="({ text, english }, i) in curQue.tableData.headers"
+            :key="`th-${i}`"
+          >
+            <div class="thead-content" :style="theadStyle">
+              <span class="chs">{{ text }}</span
+              ><span class="english">{{ english }}</span>
+            </div>
+          </th>
+        </tr>
+      </thead>
+
+      <tbody
+        :style="{
+          'text-align': `${curQue.textAlign}`,
+        }"
+      >
+        <tr v-for="(row, i) in curQue.tableData.body" :key="`tr-${i}`">
+          <template v-for="(col, j) in row.content">
+            <td
+              v-if="tdIsShow(i, j)"
+              :key="`td-${j}`"
+              :colspan="col.colspan"
+              :rowspan="col.rowspan"
+              :class="[
+                { underline: col.isUnderline },
+                `${curQue.firstColAligin === 'center' ? 'col-center' : ''}`,
+              ]"
+              :style="{
+                'background-color': `${col.background}`,
+                display: tdHeaderIsNone(i, j),
+              }"
+            >
+              <div class="cell-wrap">
+                <template v-if="col.type === 'content'">
+                  <span v-if="col.text.length > 0" class="content">
+                    {{ col.text }}
+                  </span>
+                  <template v-else>
+                    <el-input
+                      v-model="col.answer"
+                      type="textarea"
+                      :placeholder="`${isAnswerMode ? '' : '输入'}`"
+                      :disabled="isAnswerMode"
+                      :autosize="{ minRows: 1, maxRows: 6 }"
+                      @input="enterAnswer(i, j, $event)"
+                    />
+                  </template>
+                </template>
+
+                <div
+                  v-else-if="col.type === 'pinyin'"
+                  class="sentence"
+                  :style="pinyinStyle"
+                >
+                  <div>
+                    <span
+                      v-for="({ pinyin, chs }, k) in col.sentence_data
+                        .wordsList"
+                      :key="`${
+                        curQue.pinyinPosition === 'top' ||
+                        curQue.pinyinPosition === 'left'
+                          ? 'pinyin'
+                          : 'chs'
+                      }-${k}`"
+                      :class="[
+                        `${
+                          curQue.pinyinPosition === 'top' ||
+                          curQue.pinyinPosition === 'left'
+                            ? 'pinyin'
+                            : 'chs'
+                        }`,
+                      ]"
+                    >
+                      {{
+                        curQue.pinyinPosition === "top" ||
+                        curQue.pinyinPosition == "left"
+                          ? pinyin
+                          : chs
+                      }}
+                    </span>
+                  </div>
+                  <div>
+                    <span
+                      v-for="({ pinyin, chs }, k) in col.sentence_data
+                        .wordsList"
+                      :key="`${
+                        curQue.pinyinPosition === 'top' ||
+                        curQue.pinyinPosition === 'left'
+                          ? 'chs'
+                          : 'pinyin'
+                      }-${k}`"
+                      :class="[
+                        `${
+                          curQue.pinyinPosition === 'top' ||
+                          curQue.pinyinPosition === 'left'
+                            ? 'chs'
+                            : 'pinyin'
+                        }`,
+                      ]"
+                    >
+                      {{
+                        curQue.pinyinPosition === "top" ||
+                        curQue.pinyinPosition == "left"
+                          ? chs
+                          : pinyin
+                      }}
+                    </span>
+                  </div>
+                </div>
+
+                <div
+                  v-else-if="col.type === 'prePinyin'"
+                  :style="{
+                    'flex-direction':
+                      col.prefixOrSuffix === 'prefix' ? 'row' : 'row-reverse',
+                  }"
+                  class="pre-pinyin"
+                >
+                  <span>{{ col.message }}</span>
+                  <div
+                    class="right-pinyin"
+                    :style="{
+                      'grid-template-columns': `repeat(${col.sentence_data.wordsList.length}, 1fr)`,
+                    }"
+                  >
+                    <span
+                      v-for="({ pinyin }, k) in col.sentence_data.wordsList"
+                      :key="`pre-pinyin-${k}`"
+                      class="pinyin"
+                    >
+                      {{ pinyin }}
+                    </span>
+                    <span
+                      v-for="({ pinyin, chs }, k) in col.sentence_data
+                        .wordsList"
+                      :key="`pre-chs-${k}`"
+                      class="chs"
+                    >
+                      {{ chs }}
+                    </span>
+                  </div>
+                </div>
+                <CrossTick v-if="col.isCross" />
+              </div>
+            </td>
+          </template>
+        </tr>
+      </tbody>
+    </table>
+  </div>
+</template>
+
+<script>
+import CrossTick from "./CrossTick.vue";
+
+export default {
+  components: { CrossTick },
+  props: {
+    curQue: {
+      type: Object,
+      required: true,
+    },
+    themeColor: {
+      type: String,
+      required: true,
+    },
+  },
+  data() {
+    return {
+      isAnswerMode: false,
+    };
+  },
+  computed: {
+    theadStyle() {
+      const hp = this.curQue.headerEnglishPosition;
+      if (hp === "top") {
+        return {
+          "flex-direction": "column-reverse",
+        };
+      }
+      if (hp === "right") {
+        return {
+          "flex-direction": "row",
+          "column-gap": "8px",
+        };
+      }
+      if (hp === "bottom") {
+        return {
+          "flex-direction": "column",
+        };
+      }
+      if (hp === "left") {
+        return {
+          "flex-direction": "row-reverse",
+          "column-gap": "8px",
+        };
+      }
+    },
+    pinyinStyle() {
+      let pyPos = this.curQue.pinyinPosition;
+      if (pyPos === "left") {
+        return {
+          "column-gap": "16px",
+        };
+      }
+
+      if (pyPos === "top") {
+        return {
+          "flex-direction": "column",
+        };
+      }
+
+      if (pyPos === "right") {
+        return {
+          "column-gap": "16px",
+        };
+      }
+
+      if (pyPos === "bottom") {
+        return {
+          "flex-direction": "column",
+        };
+      }
+    },
+  },
+  created() {
+    const Bookanswer = this.curQue.Bookanswer;
+    if (Bookanswer) {
+      this.isAnswerMode = true;
+      for (const key in Bookanswer) {
+        let { col, row, value } = Bookanswer[key];
+        this.curQue.tableData.body[col].content[row].answer = value;
+      }
+    } else {
+      this.$set(this.curQue, "Bookanswer", {});
+    }
+  },
+  methods: {
+    enterAnswer(i, j, value) {
+      this.curQue.Bookanswer[`${i}-${j}`] = {
+        col: i,
+        row: j,
+        value,
+      };
+    },
+    // 控制首尾表格显隐
+    tdHeaderIsNone(i, j) {
+      let body = this.curQue.tableData.body;
+      if (j !== 0 && j !== body[0].content.length - 1) return "table-cell";
+      let row = 1;
+      let rowIndex = body.findIndex((item, index) => {
+        let rowspan = item.content[j].rowspan;
+        let num = rowspan === undefined ? 1 : Number(rowspan);
+        if (num > 1) {
+          row = num;
+          return false;
+        }
+        if (index === i && row > 1) return true;
+        if (row > 0) row -= 1;
+        return false;
+      });
+      return rowIndex === -1 ? "table-cell" : "none";
+    },
+    // rowspan colspan 控制td是否生成,头尾td必生成,样式兼容
+    tdIsShow(i, j) {
+      let body = this.curQue.tableData.body;
+      if (j === 0 || j === body[0].content.length - 1) return true;
+      let col = 1;
+      let colIndex = body[i].content.findIndex(({ colspan }, index) => {
+        if (index > j) return false;
+        let num = colspan === undefined ? 1 : Number(colspan);
+        if (num > 1) {
+          col = num;
+          return false;
+        }
+        if (index === j && col > 1) return true;
+        if (col > 0) col -= 1;
+        return false;
+      });
+      let row = 1;
+      let rowIndex = body.findIndex((item, index) => {
+        let rowspan = item.content[j].rowspan;
+        let num = rowspan === undefined ? 1 : Number(rowspan);
+        if (num > 1) {
+          row = num;
+          return false;
+        }
+        if (index === i && row > 1) return true;
+        if (row > 0) row -= 1;
+        return false;
+      });
+      return colIndex === -1 && rowIndex === -1;
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.header-separate {
+  width: 100%;
+  margin-bottom: 16px;
+
+  table {
+    table-layout: fixed;
+    font-size: 16px;
+    border-collapse: separate;
+    border-spacing: 6px 0;
+
+    th {
+      color: #4d4c51;
+      font-weight: normal;
+      background-color: #efeff9;
+      padding: 4px 12px;
+      border: 2px solid #afb4d1;
+
+      .thead-content {
+        display: flex;
+        justify-content: center;
+
+        .english {
+          font-family: "robot", "GB-PINYINOK-B";
+          color: #000;
+        }
+      }
+    }
+
+    td {
+      color: #474747;
+      border-bottom: 1px solid transparent;
+      padding: 4px 12px;
+      min-height: 28px;
+
+      .cell-wrap {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+
+        .content {
+          font-family: "FZJCGFKTK", "GB-PINYINOK-B", "robot";
+        }
+      }
+
+      // 下划线
+      &.underline {
+        text-decoration: underline;
+      }
+
+      .sentence {
+        display: flex;
+      }
+
+      // 前缀 + 拼音
+      .pre-pinyin {
+        display: flex;
+        align-items: flex-end;
+
+        .right-pinyin {
+          row-gap: 2px;
+          text-align: center;
+          display: grid;
+        }
+      }
+
+      &:first-child {
+        border-left: 2px solid transparent;
+        border-bottom-width: 1px;
+        border-image: linear-gradient(
+            transparent 6px,
+            #e7b576 6px,
+            #e7b576 calc(100% - 6px),
+            transparent calc(100% - 6px),
+            transparent calc(100% - 2px),
+            #cecece calc(100% - 2px)
+          )
+          2;
+        border-image-outset: 0 4px 0 0;
+
+        &.col-center {
+          text-align: center;
+        }
+      }
+
+      &:not(:last-child) {
+        position: relative;
+        // 用 ::after 模拟中间边框
+        &::after {
+          content: "";
+          position: absolute;
+          top: 0;
+          left: calc(100% + 2px);
+          width: 2px;
+          height: 100%;
+          display: inline-block;
+          background: repeating-linear-gradient(
+            transparent,
+            transparent 3px,
+            #cecece 3px,
+            #cecece 7px,
+            transparent 7px
+          );
+        }
+      }
+
+      // 中间的底部边框用 ::before 模拟
+      &:not(:first-child):not(:last-child)::before {
+        content: "";
+        position: absolute;
+        top: 100%;
+        left: 0;
+        width: 100%;
+        height: 1px;
+        display: inline-block;
+        background-color: #cecece;
+        box-shadow: 2px 0 #cecece, -2px 0 #cecece;
+      }
+
+      &:last-child {
+        border-right: 2px solid transparent;
+        border-bottom-width: 1px;
+        border-image: linear-gradient(
+            transparent 6px,
+            #e7b576 6px,
+            #e7b576 calc(100% - 6px),
+            transparent calc(100% - 6px),
+            transparent calc(100% - 2px),
+            #cecece calc(100% - 2px)
+          )
+          2;
+        border-image-outset: 0 0 0 4px;
+      }
+    }
+
+    .pinyin {
+      font-family: "GB-PINYINOK-B";
+    }
+
+    .chs {
+      font-family: "FZJCGFKTK";
+    }
+  }
+}
+</style>