Parcourir la source

第一版纯前端导出

yangg il y a 7 mois
Parent
commit
4cc4c1b005
1 fichiers modifiés avec 153 ajouts et 35 suppressions
  1. 153 35
      src/views/project/components/dataList.vue

+ 153 - 35
src/views/project/components/dataList.vue

@@ -208,7 +208,8 @@
               </el-button>
               <template #dropdown>
                 <el-dropdown-menu>
-                  <el-dropdown-item command="word">Word格式</el-dropdown-item>
+                  <el-dropdown-item command="word">Word格式</el-dropdown-item
+                  ><!-- word -->
                   <el-dropdown-item command="pdf">PDF格式</el-dropdown-item>
                   <!-- <el-dropdown-item command="pdf-to-word"
                     >PDF转Word</el-dropdown-item
@@ -284,6 +285,8 @@ import elDragDialog from "@/directive/el-drag-dialog";
 import axios from "axios";
 import jsPDF from "jspdf";
 import html2canvas from "html2canvas";
+import htmlDocx from "html-docx-js/dist/html-docx"; // 需要先安装: npm install html-docx-js
+import { saveAs } from "file-saver"; // 需要先安装: npm install file-saver
 
 export default {
   components: {
@@ -409,8 +412,132 @@ export default {
         this.$message.error("PDF转Word失败,请稍后重试");
       }
     },
+    // 2. 替换原有的 exportDocument 方法
+    async exportDocument(template) {
+      try {
+        const templateData = JSON.parse(template.data || "[]");
+
+        // 创建文档内容
+        let contentData = `
+      <!DOCTYPE html>
+      <html>
+        <head>
+          <meta charset="UTF-8">
+          <style>
+            /* 保持现有样式 */
+            body {
+              font-family: SimSun, serif;
+              font-size: 12pt;
+              line-height: 1.5;
+            }
+            table {
+              width: 100%;
+              border-collapse: collapse;
+              margin: 8px 0;
+            }
+            td, th {
+              border: 1px solid black;
+              padding: 8px;
+              min-height: 18px;
+            }
+            p {
+              margin: 6px 0;
+            }
+            .template-textarea {
+              page-break-after: always;
+            }
+            img {
+              max-width: 100%;
+              height: auto;
+              display: block;
+              margin: 10px auto;
+            }
+          </style>
+        </head>
+        <body>`;
+
+        // 处理每个模版段落
+        for (const item of templateData) {
+          const tempDiv = document.createElement("div");
+          tempDiv.innerHTML = item.content;
+
+          // 处理图片
+          const images = tempDiv.getElementsByTagName("img");
+          for (const img of Array.from(images)) {
+            try {
+              // 如果图片已经是 base64 格式,直接使用
+              if (img.src.startsWith("data:image")) {
+                continue;
+              }
+
+              // 如果是URL,转换为base64
+              const response = await fetch(img.src);
+              const blob = await response.blob();
+              const base64 = await new Promise((resolve) => {
+                const reader = new FileReader();
+                reader.onloadend = () => resolve(reader.result);
+                reader.readAsDataURL(blob);
+              });
+              img.src = base64;
+            } catch (error) {
+              console.error("处理图片失败:", error);
+              // 如果转换失败,保留原始src
+            }
+          }
+
+          // 处理表格样式
+          const tables = tempDiv.getElementsByTagName("table");
+          Array.from(tables).forEach((table) => {
+            table.setAttribute("border", "1");
+            table.style.borderCollapse = "collapse";
+
+            const cells = table.getElementsByTagName("td");
+            Array.from(cells).forEach((cell) => {
+              cell.style.border = "1px solid black";
+              cell.style.padding = "8px";
+            });
+          });
+
+          // 处理文本样式
+          const textElements = tempDiv.getElementsByTagName("span");
+          Array.from(textElements).forEach((span) => {
+            const style = window.getComputedStyle(span);
+            span.style.color = style.color;
+            span.style.fontSize = style.fontSize;
+            span.style.fontWeight = style.fontWeight;
+          });
+
+          contentData += `
+        <div class="template-textarea">
+          ${tempDiv.innerHTML}
+        </div>`;
+        }
+
+        contentData += `
+        </body>
+      </html>`;
+
+        // 转换为 Word 文档
+        const converted = htmlDocx.asBlob(contentData, {
+          orientation: "portrait",
+          margins: {
+            top: "2.54cm",
+            right: "2.54cm",
+            bottom: "2.54cm",
+            left: "2.54cm",
+          },
+        });
+
+        // 下载文件
+        saveAs(converted, `${template.title}.docx`);
+        this.$message.success("导出成功");
+      } catch (error) {
+        console.error("导出Word文档失败:", error);
+        this.$message.error("导出文档失败,请稍后重试");
+      }
+    },
 
-    // 修改导出文档的方法,确保表格有边框
+    /* // 修改导出文档的方法,确保表格有边框
     async exportDocument(template) {
       try {
         const templateData = JSON.parse(template.data || "[]");
@@ -450,6 +577,17 @@ export default {
           if (textAlign && textAlign !== "left") {
             element.style.textAlign = textAlign;
           }
+
+          // 处理表格边框
+          if (element.tagName === "TABLE") {
+            element.style.borderCollapse = "collapse";
+            element.style.width = "100%";
+            element.style.border = "10px solid windowtext";
+            element.style.msoTableLspace = "0pt";
+            element.style.msoTableRspace = "0pt";
+            element.style.msoBorderAlt = "solid windowtext.5pt";
+            element.style.msoPaddingAlt = "0cm 5.4pt 0cm 5.4pt";
+          }
         };
 
         const contentContainer = document.createElement("div");
@@ -466,29 +604,6 @@ export default {
           const allElements = tempDiv.getElementsByTagName("*");
           Array.from(allElements).forEach((element) => {
             processStyles(element);
-
-            // 特别处理表格
-            if (element.tagName === "TABLE") {
-              element.style.borderCollapse = "collapse";
-              element.style.width = "100%";
-              element.style.border = "1pt solid windowtext";
-              element.style.msoTableLspace = "0pt";
-              element.style.msoTableRspace = "0pt";
-              element.style.msoBorderAlt = "solid windowtext .5pt";
-              element.style.msoPaddingAlt = "0cm 5.4pt 0cm 5.4pt";
-            }
-
-            // 处理表格单元格
-            if (element.tagName === "TD" || element.tagName === "TH") {
-              element.style.border = "1pt solid windowtext";
-              element.style.padding = "5pt";
-              element.style.msoBorderAlt = "solid windowtext .5pt";
-
-              if (element.tagName === "TH") {
-                element.style.backgroundColor = "#f0f0f0";
-                element.style.fontWeight = "bold";
-              }
-            }
           });
 
           templateSection.innerHTML = tempDiv.innerHTML;
@@ -532,34 +647,37 @@ export default {
         </w:WordDocument>
       </xml>
       <style>
-        /* 基础样式 */
+   
         body, div, table, td, p {
           font-family: "SimSun", "宋体", serif;
           font-size: 10.5pt;
           line-height: 1.5;
         }
         
-        /* 表格样式 */
-        table {
+
+      body table {
           border-collapse: collapse;
           width: 100%;
-          mso-table-layout-alt: fixed;
+          border: 10pt solid windowtext;
+          mso-table-lspace: 0pt;
+          mso-table-rspace: 0pt;
+          mso-border-alt: solid windowtext.5pt;
           mso-padding-alt: 0cm 5.4pt 0cm 5.4pt;
-          border:1px solid #000 !important;
         }
+
         
-        /* 分页样式 */
-        .template-textarea {
+
+       .template-textarea {
           page-break-after: always;
         }
         
-        /* Word特定样式 */
+
         @page {
           mso-page-orientation: portrait;
           margin: 1.0in;
         }
         
-        /* 确保中文正确显示 */
+   
         @font-face {
           font-family: "SimSun";
           panose-1: 2 1 6 0 3 1 1 1 1 1;
@@ -610,7 +728,7 @@ export default {
         console.error("导出文档失败:", error);
         this.$alert("导出文档时发生错误,请稍后重试。");
       }
-    },
+    }, */
     /* 客户名称 */
     getCusomName(phaseId) {
       const product = this.customList.find((item) => item.id === phaseId);