Browse Source

处理目录及模版更新bug

yangg 9 months ago
parent
commit
af9b280279

File diff suppressed because it is too large
+ 0 - 0
dist/index.html


File diff suppressed because it is too large
+ 0 - 0
dist/static/css/chunk-35dc6acc.360612b2.css


File diff suppressed because it is too large
+ 0 - 0
dist/static/css/chunk-76923785.74470b11.css


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/app.dbaeaae7.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/chunk-35dc6acc.3133869a.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/chunk-5f6e410d.5f435a71.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/chunk-6155c71d.66490d87.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/chunk-76923785.a196589a.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/chunk-f321ba56.3183b641.js


+ 2 - 2
src/views/dashboard/admin/components/TransactionTable.vue

@@ -24,7 +24,7 @@
 </template>
 </template>
 
 
 <script>
 <script>
-  import{searchDocument,deleteDocument,pageDocument} from'@/api/document';
+  import{searchDocument,deleteDocument,pageDocument,searchlistDoc} from'@/api/document';
 export default {
 export default {
   filters: {
   filters: {
     statusFilter(status) {
     statusFilter(status) {
@@ -48,7 +48,7 @@ export default {
   },
   },
   methods: {
   methods: {
     fetchData() {
     fetchData() {
-      pageDocument({
+      searchlistDoc({
            page:1,
            page:1,
            pageSize:8,
            pageSize:8,
            title:'',
            title:'',

+ 1 - 1
src/views/document/com/components/Attribute/Directory/index.vue

@@ -3,7 +3,7 @@
     <el-form class="dirceForm">
     <el-form class="dirceForm">
       <template v-for="(sub,itIndex) in coms"  >
       <template v-for="(sub,itIndex) in coms"  >
         <template v-for="(item,itemIndex) in sub.attrs">
         <template v-for="(item,itemIndex) in sub.attrs">
-          <el-form-item :key="'item-' + itIndex + '-' + itemIndex"  v-if="item.type=='Directory'" :label="item.id "><!-- + ' (引用名:[' + item.id + '])' -->
+          <el-form-item :key="'item-' + itIndex + '-' + itemIndex"  v-if="item.type=='Directory'" :label="item.id+':'"><!-- + ' (引用名:[' + item.id + '])' -->
             <el-input type="textarea" v-model="item.content"></el-input>
             <el-input type="textarea" v-model="item.content"></el-input>
           </el-form-item>
           </el-form-item>
         </template>
         </template>

+ 6 - 3
src/views/document/com/components/TextArea/index.vue

@@ -380,10 +380,13 @@ export default {
           const level = _this.com.attrs[i].level || 1; // 默认为1级目录
           const level = _this.com.attrs[i].level || 1; // 默认为1级目录
           const attrId = _this.com.attrs[i].id;
           const attrId = _this.com.attrs[i].id;
 
 
-          // 创建一个更灵活的正则表达式模式
-          const directoryRegex = new RegExp(`{{\\s*${attrId}\\s*}}`, "g");
+          // 创建一个更灵活的正则表达式模式,匹配可能存在的div包裹
+          const directoryRegex = new RegExp(
+            `<div[^>]*>\\s*{{\\s*${attrId}\\s*}}\\s*</div>|{{\\s*${attrId}\\s*}}`,
+            "g"
+          );
 
 
-          // 替换内容,直接在标题标签上应用类名
+          // 替换内容,直接生成标题标签
           data = data.replace(directoryRegex, (match, offset, string) => {
           data = data.replace(directoryRegex, (match, offset, string) => {
             // 根据级别创建适当的HTML标签
             // 根据级别创建适当的HTML标签
             const tag = `h${Math.min(level, 6)}`; // 限制最大级别为h6
             const tag = `h${Math.min(level, 6)}`; // 限制最大级别为h6

+ 15 - 1
src/views/document/com/components/TextView/index.vue

@@ -187,6 +187,20 @@ export default {
           data = data.replace("{{" + attrId + "}}", result);
           data = data.replace("{{" + attrId + "}}", result);
         } else if (_this.com.attrs[i].type == "Directory") {
         } else if (_this.com.attrs[i].type == "Directory") {
           const directoryContent = _this.com.attrs[i].content;
           const directoryContent = _this.com.attrs[i].content;
+          const level = _this.com.attrs[i].level || 1; // 默认为1级目录
+          const attrId = _this.com.attrs[i].id;
+
+          // 创建一个更灵活的正则表达式模式
+          const directoryRegex = new RegExp(`{{\\s*${attrId}\\s*}}`, "g");
+
+          // 替换内容,直接在标题标签上应用类名
+          data = data.replace(directoryRegex, (match, offset, string) => {
+            // 根据级别创建适当的HTML标签
+            const tag = `h${Math.min(level, 6)}`; // 限制最大级别为h6
+            const className = `directory-level-${level}`;
+            return `<${tag} class="${className}">${directoryContent}</${tag}>`;
+          });
+          /* const directoryContent = _this.com.attrs[i].content;
           const attrId = _this.com.attrs[i].id;
           const attrId = _this.com.attrs[i].id;
 
 
           // Create a more flexible regex pattern
           // Create a more flexible regex pattern
@@ -211,7 +225,7 @@ export default {
               // Otherwise, just replace the placeholder
               // Otherwise, just replace the placeholder
               return directoryContent;
               return directoryContent;
             }
             }
-          });
+          }); */
         } else {
         } else {
           //处理常量及其它
           //处理常量及其它
           data = data.replace("{{" + attrId + "}}", _this.com.attrs[i].content);
           data = data.replace("{{" + attrId + "}}", _this.com.attrs[i].content);

+ 37 - 3
src/views/document/com/editor.vue

@@ -120,7 +120,7 @@
                         <el-button
                         <el-button
                           circle
                           circle
                           size="mini"
                           size="mini"
-                          v-if="it.isEdit !== 1&&type !== 'document'"
+                          v-if="it.isEdit !== 1 && type !== 'document'"
                           @click="onEdit(index, 1)"
                           @click="onEdit(index, 1)"
                         >
                         >
                           <svg-icon icon-class="edit" />
                           <svg-icon icon-class="edit" />
@@ -259,8 +259,18 @@ export default {
     coms: {
     coms: {
       handler(val) {
       handler(val) {
         if (val == null) return;
         if (val == null) return;
+        const newComList = JSON.parse(JSON.stringify(val));
+        
+        // 比较新旧值,只有在真正变化时才更新
+        if (JSON.stringify(this.comList) !== JSON.stringify(newComList)) {
+          this.comList = newComList;
+        }
+        /*  console.log("val", val);
         this.comList = JSON.parse(JSON.stringify(val));
         this.comList = JSON.parse(JSON.stringify(val));
-        console.log('comList',this.comList);
+        console.log("comList", this.comList); */
+      /*   console.log("val", val);
+        this.comList = this.carefulCopy(val);
+        console.log("comList", this.comList); */
       },
       },
       immediate: true, //立即执行
       immediate: true, //立即执行
       deep: true,
       deep: true,
@@ -316,10 +326,34 @@ export default {
     this.templateId = this.$route.query.templateId;
     this.templateId = this.$route.query.templateId;
   },
   },
   methods: {
   methods: {
+    carefulCopy(items) {
+      return items.map(item => {
+        const newItem = { ...item };
+        
+        // 深拷贝 attrs 数组
+        if (Array.isArray(newItem.attrs)) {
+          newItem.attrs = newItem.attrs.map(attr => ({...attr}));
+        }
+
+        // 深拷贝 content,如果它是一个对象或数组
+        if (typeof newItem.content === 'object' && newItem.content !== null) {
+          newItem.content = JSON.parse(JSON.stringify(newItem.content));
+        }
+
+        // 处理特殊的 type,如 Table
+        if (newItem.type === 'Table') {
+          newItem.tableHeader = [...newItem.tableHeader];
+          newItem.tableData = newItem.tableData.map(row => ({...row}));
+        }
+
+        // 保留其他属性的引用
+        return newItem;
+      });
+    },
     handleComContentUpdate(index, updatedCom) {
     handleComContentUpdate(index, updatedCom) {
       // 更新本地的 coms 数组
       // 更新本地的 coms 数组
       this.$set(this.coms, index, updatedCom);
       this.$set(this.coms, index, updatedCom);
-      
+
       // 触发父组件的更新
       // 触发父组件的更新
       this.$emit("onRebuild", this.coms);
       this.$emit("onRebuild", this.coms);
     },
     },

+ 41 - 0
src/views/document/com/view.scss

@@ -13,6 +13,47 @@
       border-radius: 10px;
       border-radius: 10px;
       padding:10px;
       padding:10px;
       margin-bottom: 10px;
       margin-bottom: 10px;
+      .template-textarea{
+        .rich-editor{
+          .directory-level-1 {
+            font-size: 24px;
+            font-weight: bold;
+            margin-left: 0;
+          }
+          
+          .directory-level-2 {
+            font-size: 20px;
+            font-weight: bold;
+            margin-left: 20px;
+          }
+          
+          .directory-level-3 {
+            font-size: 18px;
+            font-weight: bold;
+            margin-left: 40px;
+          }
+          
+          .directory-level-4 {
+            font-size: 16px;
+            font-weight: bold;
+            margin-left: 60px;
+          }
+          
+          .directory-level-5 {
+            font-size: 14px;
+            font-weight: bold;
+            margin-left: 80px;
+          }
+          
+          .directory-level-6 {
+            font-size: 12px;
+            font-weight: normal;
+            margin-left: 100px;
+          }
+        }
+      }
+
+     
   }
   }
   .export{
   .export{
     display: flex;
     display: flex;

+ 46 - 27
src/views/document/com/view.vue

@@ -316,7 +316,7 @@ export default {
         const templateTextareas =
         const templateTextareas =
           contentClone.querySelectorAll(".template-textarea");
           contentClone.querySelectorAll(".template-textarea");
 
 
-        if (templateTextareas.length > 0) {
+       /*  if (templateTextareas.length > 0) {
           // 创建空白页和目录页
           // 创建空白页和目录页
           const blankPage = document.createElement("div");
           const blankPage = document.createElement("div");
           blankPage.className = "blank-page";
           blankPage.className = "blank-page";
@@ -340,22 +340,41 @@ export default {
 
 
           // 生成目录内容
           // 生成目录内容
           let tocHtml = "";
           let tocHtml = "";
-          templateTextareas.forEach((textarea, index) => {
-            const title = textarea.querySelector("h1, h2, h3, h4, h5, h6");
-            if (title) {
+          let currentLevel = 0;
+          let pageNumber = 2; // 从第2页开始计数
+
+          templateTextareas.forEach((textarea) => {
+            const headings = textarea.querySelectorAll(
+              "h1, h2, h3, h4, h5, h6"
+            );
+            headings.forEach((heading) => {
+              const level = parseInt(heading.tagName.charAt(1));
+              const title = heading.textContent.trim();
+
+              // 计算缩进
+              let indent = "";
+              for (let i = 1; i < level; i++) {
+                indent += "&nbsp;&nbsp;&nbsp;&nbsp;";
+              }
+
+              // 添加目录项
               tocHtml += `
               tocHtml += `
-                <div class="toc-item">
-                  <span class="toc-text">${title.textContent}</span>
-                  <span class="toc-page-num">${index + 2}</span>
-                </div>
-              `;
-              title.id = `section-${index + 2}`;
-            }
+            <div class="toc-item" style="margin-left: ${(level - 1) * 20}px;">
+              <span class="toc-text">${indent}${title}</span>
+              <span class="toc-page-num">${pageNumber}</span>
+            </div>
+          `;
+
+              heading.id = `section-${pageNumber}`;
+              currentLevel = level;
+            });
+
+            pageNumber++; // 每个模板对应一页
           });
           });
 
 
           // 将目录内容插入到目录页中
           // 将目录内容插入到目录页中
           contentClone.querySelector("#toc").innerHTML = tocHtml;
           contentClone.querySelector("#toc").innerHTML = tocHtml;
-        }
+        } */
 
 
         contentClone.querySelectorAll('input[type="text"]').forEach((input) => {
         contentClone.querySelectorAll('input[type="text"]').forEach((input) => {
           const span = document.createElement("span");
           const span = document.createElement("span");
@@ -537,33 +556,33 @@ export default {
           }
           }
         });
         });
         contentClone.querySelectorAll("table").forEach((table, tableIndex) => {
         contentClone.querySelectorAll("table").forEach((table, tableIndex) => {
-      table.style.cssText = `
+          table.style.cssText = `
         border-collapse: separate !important;
         border-collapse: separate !important;
         width: 100% !important;
         width: 100% !important;
         border: none !important;
         border: none !important;
       `;
       `;
 
 
-      table.querySelectorAll("tr").forEach((row, rowIndex) => {
-        row.querySelectorAll("td, th").forEach((cell, cellIndex) => {
-          let cellStyle = `
+          table.querySelectorAll("tr").forEach((row, rowIndex) => {
+            row.querySelectorAll("td, th").forEach((cell, cellIndex) => {
+              let cellStyle = `
             padding: 5px !important;
             padding: 5px !important;
             border: 0.1px solid #000000 !important;
             border: 0.1px solid #000000 !important;
           `;
           `;
 
 
-          // 移除顶部边框(除了第一行)
-          if (rowIndex !== 0) {
-            cellStyle += 'border-top: none !important;';
-          }
+              // 移除顶部边框(除了第一行)
+              if (rowIndex !== 0) {
+                cellStyle += "border-top: none !important;";
+              }
 
 
-          // 移除左侧边框(除了第一列)
-          if (cellIndex !== 0) {
-            cellStyle += 'border-left: none !important;';
-          }
+              // 移除左侧边框(除了第一列)
+              if (cellIndex !== 0) {
+                cellStyle += "border-left: none !important;";
+              }
 
 
-          cell.style.cssText += cellStyle;
+              cell.style.cssText += cellStyle;
+            });
+          });
         });
         });
-      });
-    });
         // 等待所有图片加载完成并转换为 Base64
         // 等待所有图片加载完成并转换为 Base64
         const images = contentClone.querySelectorAll("img");
         const images = contentClone.querySelectorAll("img");
         for (let img of images) {
         for (let img of images) {

+ 80 - 15
src/views/document/create.vue

@@ -1285,9 +1285,11 @@ export default {
       this.operation = "drag";
       this.operation = "drag";
     },
     },
 
 
-    onRebuild(e) {
-      let _this = this;
-      _this.coms = [...e];
+    onRebuild(updatedComList) {
+      this.coms = [...updatedComList];
+      this.$nextTick(() => {
+        this.$forceUpdate();
+      });
     },
     },
     //初始化当前用户信息
     //初始化当前用户信息
     async initCurrentUser() {
     async initCurrentUser() {
@@ -1565,7 +1567,7 @@ export default {
         createDocument(_this.docAttr).then((res) => {
         createDocument(_this.docAttr).then((res) => {
           if (res.status != 200) return; //保存文档
           if (res.status != 200) return; //保存文档
           _this.docAttr.id = res.data;
           _this.docAttr.id = res.data;
-          _this.articleId=res.data
+          _this.articleId = res.data;
           _this.$alert("文档保存成功");
           _this.$alert("文档保存成功");
           _this.docVisible = false;
           _this.docVisible = false;
           _this.docForm = {
           _this.docForm = {
@@ -1595,6 +1597,7 @@ export default {
       _this.docAttr.projects = JSON.stringify(_this.docAttr.linkProject);
       _this.docAttr.projects = JSON.stringify(_this.docAttr.linkProject);
       _this.docAttr.data = JSON.stringify(_this.coms);
       _this.docAttr.data = JSON.stringify(_this.coms);
       _this.docAttr.is_template = 1;
       _this.docAttr.is_template = 1;
+      _this.docAttr.id = this.$route.query.articleId;
       _this.docAttr.user_name = _this.$store.state.user.name;
       _this.docAttr.user_name = _this.$store.state.user.name;
       _this.docAttr.user_id = _this.$store.state.user.id;
       _this.docAttr.user_id = _this.$store.state.user.id;
       updateDocument(_this.docAttr).then((res) => {
       updateDocument(_this.docAttr).then((res) => {
@@ -1775,11 +1778,15 @@ export default {
       }
       }
 
 
       let com = _this.coms[_this.comIndex];
       let com = _this.coms[_this.comIndex];
-      let uniqueId = "Directory" + (com.attrs.length + 1);
+      let uniqueId = `Directory_${_this.comIndex}_${com.attrs.length + 1}`;
 
 
-      // 查找现有的目录内容
-      let existingDirectory = com.attrs.find(
-        (attr) => attr.type === "Directory"
+      // 获取当前层级
+      let currentLevel = e.content.level || 1;
+
+      // 生成带有模块索引和层级的内容
+      let numberedContent = this.generateNumberedContent(
+        _this.comIndex,
+        currentLevel
       );
       );
 
 
       let data = {
       let data = {
@@ -1787,21 +1794,79 @@ export default {
         id: uniqueId,
         id: uniqueId,
         name: "目录信息",
         name: "目录信息",
         intro: "目录信息",
         intro: "目录信息",
-        content: existingDirectory ? existingDirectory.content : "目录信息",
-        level: e.content.level,
+        content: numberedContent,
+        level: currentLevel,
+        moduleIndex: _this.comIndex,
       };
       };
 
 
-      // 始终添加新的目录项
-      com.attrs.push(data);
+      // 使用 $set 来确保响应式更新
+      this.$set(com.attrs, com.attrs.length, data);
 
 
-      console.log(_this.coms);
+      // 强制更新视图
+      this.$forceUpdate();
+
+      // 使用 nextTick 确保 DOM 更新后再检查
+      this.$nextTick(() => {
+        if (!com.attrs[com.attrs.length - 1].content) {
+          this.$set(
+            com.attrs[com.attrs.length - 1],
+            "content",
+            numberedContent
+          );
+          this.$forceUpdate();
+        }
+      });
 
 
-      // 在插入命令中使用新的唯一ID
+      // 使用新的唯一 ID 在插入命令中
       _this.insertCmd = {
       _this.insertCmd = {
-        content: `<div class="directory-level-${e.content.level}">{{${uniqueId}}}</div>`,
+        content: `{{${uniqueId}}}`,
       };
       };
     },
     },
 
 
+    generateNumberedContent(moduleIndex, level) {
+      let numberedContent = "";
+      let prefix = this.generateLevelPrefix(moduleIndex, level);
+
+      if (this.coms[moduleIndex].type === "TextArea") {
+        numberedContent = `${prefix}\n`;
+      }
+
+      return numberedContent.trim();
+    },
+
+    generateLevelPrefix(moduleIndex, level) {
+      let prefix = [];
+      let currentModule = this.coms[moduleIndex];
+
+      // 获取当前模块中已存在的目录项
+      let existingDirectories = currentModule.attrs.filter(
+        (attr) => attr.type === "Directory"
+      );
+
+      // 计算当前层级的序号
+      let currentLevelCount =
+        existingDirectories.filter((dir) => dir.level === level).length + 1;
+
+      // 构建多级序号
+      for (let i = 1; i <= level; i++) {
+        if (i === 1) {
+          prefix.push(moduleIndex + 1);
+        } else if (i === level) {
+          prefix.push(currentLevelCount);
+        } else {
+          // 对于中间层级,找到最近的上级目录项
+          let parentLevel = existingDirectories
+            .filter((dir) => dir.level === i - 1)
+            .pop();
+          prefix.push(
+            parentLevel ? parentLevel.content.split(" ")[0].split(".").pop() : 1
+          );
+        }
+      }
+
+      return prefix.join(".");
+    },
+
     onInsertProductAttr(e) {
     onInsertProductAttr(e) {
       let _this = this;
       let _this = this;
       this.showProductAttr = false;
       this.showProductAttr = false;

Some files were not shown because too many files changed in this diff