Pārlūkot izejas kodu

更改地址打包

yangg 9 mēneši atpakaļ
vecāks
revīzija
9b338a436b
37 mainītis faili ar 417 papildinājumiem un 32 dzēšanām
  1. 1 1
      .env.development
  2. 1 1
      .env.production
  3. 15 0
      dist/ckeditor/config.js
  4. 40 0
      dist/ckeditor/custom-ckeditor.css
  5. 0 0
      dist/index.html
  6. 0 0
      dist/static/css/chunk-492156b8.a5bdf00d.css
  7. 0 0
      dist/static/js/app.4f31f699.js
  8. 0 0
      dist/static/js/chunk-0a97e1f4.078f84a0.js
  9. 0 0
      dist/static/js/chunk-173d8910.34d14705.js
  10. 0 0
      dist/static/js/chunk-227fce26.44eb40b6.js
  11. 0 0
      dist/static/js/chunk-2b49eda5.1f544992.js
  12. 0 20
      dist/static/js/chunk-2d216257.9bfc141b.js
  13. 0 0
      dist/static/js/chunk-35464144.478fb4b1.js
  14. 0 0
      dist/static/js/chunk-3d9675b3.75ba048f.js
  15. 0 0
      dist/static/js/chunk-3f40cf30.f070d76b.js
  16. 0 0
      dist/static/js/chunk-4139ed56.25124ea6.js
  17. 0 0
      dist/static/js/chunk-44eee83d.43170938.js
  18. 0 0
      dist/static/js/chunk-492156b8.870f5571.js
  19. 0 0
      dist/static/js/chunk-52f685c2.713b554c.js
  20. 0 0
      dist/static/js/chunk-5a3bdf57.14b3ef26.js
  21. 0 0
      dist/static/js/chunk-5b1b00c6.ae1b5c1e.js
  22. 0 0
      dist/static/js/chunk-5c1239a0.c5f505e5.js
  23. 0 0
      dist/static/js/chunk-6155c71d.802ce98e.js
  24. 0 0
      dist/static/js/chunk-62250b71.aba939b7.js
  25. 0 0
      dist/static/js/chunk-6a80e4ca.6018209b.js
  26. 0 0
      dist/static/js/chunk-716f2609.a9f590f9.js
  27. 0 0
      dist/static/js/chunk-980050cc.89f32864.js
  28. 0 0
      dist/static/js/chunk-aeb9b426.52e0f818.js
  29. 0 0
      dist/static/js/chunk-c5d7799a.fb698bf4.js
  30. 0 0
      dist/static/js/chunk-d649fd9a.87efbdda.js
  31. 0 0
      dist/static/js/chunk-db653464.903c2a41.js
  32. 0 0
      dist/static/js/chunk-e6bc7406.f6d6c8d3.js
  33. 0 0
      dist/static/js/chunk-f23301fc.0b0fb9a1.js
  34. 1 2
      package.json
  35. 15 0
      public/ckeditor/config.js
  36. 40 0
      public/ckeditor/custom-ckeditor.css
  37. 304 8
      src/views/document/com/view.vue

+ 1 - 1
.env.development

@@ -2,5 +2,5 @@
 ENV = 'development'
 port = 8080
 # base api
-VUE_APP_BASE_API = 'http://127.0.0.1:8000'
+VUE_APP_BASE_API = 'http://192.168.1.178:8000'
 #192.168.1.178

+ 1 - 1
.env.production

@@ -2,4 +2,4 @@
 ENV = 'production'
 port = 8080
 # base api
-VUE_APP_BASE_API = 'http://192.168.1.109:8000'
+VUE_APP_BASE_API = 'http://192.168.100.6:8083'

+ 15 - 0
dist/ckeditor/config.js

@@ -28,4 +28,19 @@ config.fontSize_sizes = '8/8px;9/9px;10/10px;11/11px;12/12px;14/14px;16/16px;18/
 
 // 可选:设置默认字体大小
 config.fontSize_defaultLabel = '12px';
+// 设置内容CSS
+config.contentsCss = '/public/ckeditor/custom-ckeditor.css';
+
+ // 允许额外的CSS类
+ config.extraAllowedContent = 'div(page-break)';
+
+ // 设置编辑器的宽度,高度可以设置为自动
+ config.width = '100%';
+ config.height = 'auto';
+
+ // 添加分页符插件(如果需要)
+ config.extraPlugins = 'pagebreak';
+
+ // 设置工具栏位置在编辑区域上方
+ config.toolbarLocation = 'top';
 };

+ 40 - 0
dist/ckeditor/custom-ckeditor.css

@@ -0,0 +1,40 @@
+/* A4 纸张样式 */
+.cke_editable {
+    width: 21cm;
+    min-height: 29.7cm;
+    padding: 2cm;
+    margin: 1cm auto;
+    border: 1px #D3D3D3 solid;
+    border-radius: 5px;
+    box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
+    background-color: white;
+}
+
+/* 打印样式 */
+@media print {
+    body {
+        background: none;
+    }
+    .cke_editable {
+        width: 21cm;
+        height: 29.7cm;
+        padding: 0;
+        margin: 0;
+        border: none;
+        border-radius: 0;
+        box-shadow: none;
+    }
+}
+
+/* 屏幕显示样式 */
+@media screen {
+    body {
+        background: #e0e0e0;
+    }
+}
+
+/* 设置页面大小 */
+@page {
+    size: A4;
+    margin: 0;
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/index.html


+ 0 - 0
dist/static/css/chunk-5c1239a0.a5bdf00d.css → dist/static/css/chunk-492156b8.a5bdf00d.css


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/static/js/app.4f31f699.js


+ 0 - 0
dist/static/js/chunk-0a97e1f4.bd73e29c.js → dist/static/js/chunk-0a97e1f4.078f84a0.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/static/js/chunk-173d8910.34d14705.js


+ 0 - 0
dist/static/js/chunk-227fce26.2ecbc8e4.js → dist/static/js/chunk-227fce26.44eb40b6.js


+ 0 - 0
dist/static/js/chunk-2b49eda5.1cb3dd72.js → dist/static/js/chunk-2b49eda5.1f544992.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 20
dist/static/js/chunk-2d216257.9bfc141b.js


+ 0 - 0
dist/static/js/chunk-35464144.e989ec83.js → dist/static/js/chunk-35464144.478fb4b1.js


+ 0 - 0
dist/static/js/chunk-3d9675b3.beefccde.js → dist/static/js/chunk-3d9675b3.75ba048f.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/static/js/chunk-3f40cf30.f070d76b.js


+ 0 - 0
dist/static/js/chunk-4139ed56.2d9727a0.js → dist/static/js/chunk-4139ed56.25124ea6.js


+ 0 - 0
dist/static/js/chunk-44eee83d.d4f2d109.js → dist/static/js/chunk-44eee83d.43170938.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/static/js/chunk-492156b8.870f5571.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/static/js/chunk-52f685c2.713b554c.js


+ 0 - 0
dist/static/js/chunk-5a3bdf57.3400f222.js → dist/static/js/chunk-5a3bdf57.14b3ef26.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/static/js/chunk-5b1b00c6.ae1b5c1e.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/static/js/chunk-5c1239a0.c5f505e5.js


+ 0 - 0
dist/static/js/chunk-6155c71d.0287d6b6.js → dist/static/js/chunk-6155c71d.802ce98e.js


+ 0 - 0
dist/static/js/chunk-62250b71.ae2cbef4.js → dist/static/js/chunk-62250b71.aba939b7.js


+ 0 - 0
dist/static/js/chunk-6a80e4ca.2b11c258.js → dist/static/js/chunk-6a80e4ca.6018209b.js


+ 0 - 0
dist/static/js/chunk-716f2609.2d35ed83.js → dist/static/js/chunk-716f2609.a9f590f9.js


+ 0 - 0
dist/static/js/chunk-980050cc.24df6813.js → dist/static/js/chunk-980050cc.89f32864.js


+ 0 - 0
dist/static/js/chunk-aeb9b426.5baa1efb.js → dist/static/js/chunk-aeb9b426.52e0f818.js


+ 0 - 0
dist/static/js/chunk-c5d7799a.9ca61231.js → dist/static/js/chunk-c5d7799a.fb698bf4.js


+ 0 - 0
dist/static/js/chunk-d649fd9a.646d932c.js → dist/static/js/chunk-d649fd9a.87efbdda.js


+ 0 - 0
dist/static/js/chunk-db653464.e37e0185.js → dist/static/js/chunk-db653464.903c2a41.js


+ 0 - 0
dist/static/js/chunk-e6bc7406.a678e16d.js → dist/static/js/chunk-e6bc7406.f6d6c8d3.js


+ 0 - 0
dist/static/js/chunk-f23301fc.2055040d.js → dist/static/js/chunk-f23301fc.0b0fb9a1.js


+ 1 - 2
package.json

@@ -26,13 +26,12 @@
     "cos-js-sdk-v5": "^1.4.22",
     "docx": "^8.5.0",
     "docxtemplater": "^3.46.0",
-   
     "docxtemplater-image-module-free": "^1.1.1",
     "driver.js": "0.9.5",
     "dropzone": "5.5.1",
     "echarts": "4.2.1",
     "element-ui": "^2.15.6",
-    "file-saver": "^2.0.1",
+    "file-saver": "^2.0.5",
     "fuse.js": "3.4.4",
     "handsontable": "^14.1.0",
     "handsontable-pro": "^6.2.3",

+ 15 - 0
public/ckeditor/config.js

@@ -28,4 +28,19 @@ config.fontSize_sizes = '8/8px;9/9px;10/10px;11/11px;12/12px;14/14px;16/16px;18/
 
 // 可选:设置默认字体大小
 config.fontSize_defaultLabel = '12px';
+// 设置内容CSS
+config.contentsCss = '/public/ckeditor/custom-ckeditor.css';
+
+ // 允许额外的CSS类
+ config.extraAllowedContent = 'div(page-break)';
+
+ // 设置编辑器的宽度,高度可以设置为自动
+ config.width = '100%';
+ config.height = 'auto';
+
+ // 添加分页符插件(如果需要)
+ config.extraPlugins = 'pagebreak';
+
+ // 设置工具栏位置在编辑区域上方
+ config.toolbarLocation = 'top';
 };

+ 40 - 0
public/ckeditor/custom-ckeditor.css

@@ -0,0 +1,40 @@
+/* A4 纸张样式 */
+.cke_editable {
+    width: 21cm;
+    min-height: 29.7cm;
+    padding: 2cm;
+    margin: 1cm auto;
+    border: 1px #D3D3D3 solid;
+    border-radius: 5px;
+    box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
+    background-color: white;
+}
+
+/* 打印样式 */
+@media print {
+    body {
+        background: none;
+    }
+    .cke_editable {
+        width: 21cm;
+        height: 29.7cm;
+        padding: 0;
+        margin: 0;
+        border: none;
+        border-radius: 0;
+        box-shadow: none;
+    }
+}
+
+/* 屏幕显示样式 */
+@media screen {
+    body {
+        background: #e0e0e0;
+    }
+}
+
+/* 设置页面大小 */
+@page {
+    size: A4;
+    margin: 0;
+}

+ 304 - 8
src/views/document/com/view.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="com-viewer">
+    <!-- getComponentType() -->
     <div class="content" ref="content">
-      <template v-for="(item, index) in coms"
-        ><!-- getComponentType() -->
+      <template v-for="(item, index) in coms">
         <component
           :key="index"
           :is="item.type"
@@ -16,12 +16,13 @@
     </div>
     <div class="export">
       <el-button
-        @click="onExport"
+        @click="onExports"
         type="primary"
         :loading="exporting"
         :disabled="exporting"
         >导出</el-button
       >
+      <el-progress v-if="exporting" :percentage="exportProgress" />
     </div>
   </div>
 </template>
@@ -30,10 +31,11 @@
 import { exportDocument } from "@/api/document";
 import TextArea from "./components/TextView";
 import htmlDocx from "html-docx-js/dist/html-docx";
-import saveAs from "file-saver";
 import jsPDF from "jspdf";
+import html2canvas from "html2canvas";
 import { findData } from "@/api/sourceData";
-import { createDocument } from "html-to-docx";
+import HTMLtoDOCX from "html-to-docx";
+import { saveAs } from "file-saver";
 
 export default {
   name: "Viewer",
@@ -72,6 +74,7 @@ export default {
       comList: [],
       content: "",
       exporting: false, // 新增:用于跟踪导出状态
+      exportProgress: 0,
     };
   },
   methods: {
@@ -86,7 +89,7 @@ export default {
               formual = await this.getRemote(formual);
               el.content = eval(formual);
             } catch (error) {}
-          }else if(el.type == "variableNull"){
+          } else if (el.type == "variableNull") {
             console.log(el);
           }
         }
@@ -361,8 +364,73 @@ export default {
         });
 
         let contentData = `<!DOCTYPE html><html><head><meta charset="UTF-8"><style>
+          @page {
+            size: A4;
+            margin: 2cm;
+          }
+          body {
+            font-family: Arial, sans-serif;
+            font-size: 12pt;
+            line-height: 1.5;
+          }
+          table {
+            width: 100%;
+            border-collapse: collapse;
+          }
+          td, th {
+            border: 1px solid black;
+            padding: 5px;
+          }
+          .template-textarea {
+            page-break-after: always;
+          }
+           .toc-page {
+                page-break-before: always;
+                page-break-after: always;
+              }
+              .toc-content {
+                height: 100vh;
+                display: flex;
+                flex-direction: column;
+                justify-content: flex-start;
+                padding-top: 100px;
+              }
+              .toc-item {
+                display: flex;
+                justify-content: space-between;
+                margin-bottom: 10px;
+              }
+              .toc-text {
+                margin-right: 10px;
+              }
+              .toc-page-num {
+                flex-shrink: 0;
+              }
+              .toc-item::after {
+                content: "";
+                border-bottom: 1px dotted black;
+                flex-grow: 1;
+                order: 2;
+                margin: 0 5px;
+                position: relative;
+                top: -5px;
+              }
+              .toc-text {
+                order: 1;
+              }
+              .toc-page-num {
+                order: 3;
+              }
+              
+              .TOC {
+                display: none !important;
+              }
+        </style></head><body>${contentClone.innerHTML}</body></html>`; /*`<!DOCTYPE html><html><head><meta charset="UTF-8"><style>
       @media print {
          body {
+          width: 210mm;
+           height: 297mm;
+
                 margin: 0;
                 padding: 0;
               }
@@ -410,12 +478,12 @@ export default {
               .toc-page-num {
                 order: 3;
               }
-              /* 移除 WPS 自动添加的目录引用框 */
+              
               .TOC {
                 display: none !important;
               }
       }
-    </style></head><body><p class="header1"></p>${contentClone.innerHTML}</body></html>`;
+    </style></head><body><p class="header1"></p>${contentClone.innerHTML}</body></html>` 移除 WPS 自动添加的目录引用框 */
         contentData = contentData
           .replaceAll("<table ", `<table style="border-collapse: collapse;" `)
           .replaceAll("<td>", `<td style="border: 1px solid black;">`);
@@ -442,6 +510,234 @@ export default {
         this.exporting = false; // 无论成功还是失败,都将导出状态设置回 false
       }
     },
+    /* 前端导出word */
+    async onExports() {
+      if (this.exporting) return;
+      this.exporting = true;
+
+      try {
+        let contentClone = this.$refs.content.cloneNode(true);
+        console.log(contentClone);
+
+        // 等待所有图片加载完成
+        await this.waitForImages(contentClone);
+
+        // 将图片转换为 Base64
+        const imgPromises = Array.from(
+          contentClone.querySelectorAll("img")
+        ).map((img) => this.convertImageToBase64(img));
+
+        await Promise.all(imgPromises);
+
+        // 处理输入框
+        contentClone.querySelectorAll('input[type="text"]').forEach((input) => {
+          const span = document.createElement("span");
+          span.textContent = input.value;
+          input.parentNode.replaceChild(span, input);
+        });
+
+        // 创建HTML内容
+        let contentData = `
+      <!DOCTYPE html>
+      <html>
+        <head>
+          <meta charset="UTF-8">
+          <style>
+            @page {
+              size: A4;
+              margin: 2cm;
+            }
+            body {
+              font-family: Arial, sans-serif;
+              font-size: 12pt;
+              line-height: 1.5;
+            }
+            table {
+              width: 100%;
+              border-collapse: collapse;
+            }
+            td, th {
+              border: 1px solid black;
+              padding: 5px;
+            }
+            .template-textarea {
+              page-break-after: always;
+            }
+            img {
+              max-width: 100%;
+              height: auto;
+            }
+          </style>
+        </head>
+        <body>${contentClone.innerHTML}</body>
+      </html>
+    `;
+
+        // 创建文档选项
+        const options = {
+          margin: {
+            top: "2cm",
+            right: "2cm",
+            bottom: "2cm",
+            left: "2cm",
+          },
+          table: { row: { cantSplit: true } },
+          footer: {
+            default:
+              '<p style="color: #444; font-size: 10pt">页码: {page} / {pages}</p>',
+          },
+          pageNumber: true,
+        };
+
+        // 创建文档
+        const docxBlob = await HTMLtoDOCX(contentData, null, options);
+
+        // 保存文件
+        saveAs(docxBlob, `${this.docAttr.title}.docx`);
+
+        this.$message.success("文档导出成功");
+      } catch (error) {
+        console.error("导出文档时发生错误:", error);
+        this.$message.error("导出文档时发生错误,请稍后重试");
+      } finally {
+        this.exporting = false;
+      }
+    },
+
+    // 新增方法:等待所有图片加载完成
+    async waitForImages(element) {
+      const images = element.getElementsByTagName("img");
+      const imagePromises = Array.from(images).map((img) => {
+        if (img.complete) {
+          return Promise.resolve();
+        } else {
+          return new Promise((resolve) => {
+            img.onload = img.onerror = resolve;
+          });
+        }
+      });
+      await Promise.all(imagePromises);
+    },
+    // 新增方法:将图片转换为Base64
+    async convertImageToBase64(img) {
+      if (img.src.startsWith("data:")) {
+        return;
+      }
+      try {
+        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 converting image to Base64:", error);
+      }
+    },
+    /* 终 */
+    /* pdf导出 */
+    async onExportPDF() {
+      if (this.exporting) return;
+      this.exporting = true;
+      this.exportProgress = 0;
+
+      try {
+        const content = this.$refs.content;
+
+        // 保存原始样式
+        const originalStyle = {
+          height: content.style.height,
+          overflow: content.style.overflow,
+          position: content.style.position,
+        };
+
+        // 临时修改样式以确保所有内容可见
+        content.style.height = "auto";
+        content.style.overflow = "visible";
+        content.style.position = "absolute";
+
+        // 等待图片加载
+        await this.waitForImages(content);
+
+        const pdf = new jsPDF("p", "pt", "a4");
+        const pageHeight = pdf.internal.pageSize.getHeight();
+        const pageWidth = pdf.internal.pageSize.getWidth();
+
+        // 设置超时
+        const timeout = setTimeout(() => {
+          throw new Error("PDF export timed out");
+        }, 60000); // 60秒超时
+
+        await this.addContentToPDF(content, pdf, pageWidth, pageHeight);
+
+        clearTimeout(timeout);
+
+        pdf.save(`${this.docAttr.title || "document"}.pdf`);
+
+        // 恢复原始样式
+        Object.assign(content.style, originalStyle);
+
+        this.$message.success("PDF导出成功");
+      } catch (error) {
+        console.error("Export to PDF failed:", error);
+        this.$message.error(`PDF导出失败:${error.message}`);
+      } finally {
+        this.exporting = false;
+        this.exportProgress = 0;
+      }
+    },
+
+    async waitForImages(element) {
+      const images = element.getElementsByTagName("img");
+      const imagePromises = Array.from(images).map((img) => {
+        if (img.complete) return Promise.resolve();
+        return new Promise((resolve) => {
+          img.onload = img.onerror = resolve;
+        });
+      });
+      await Promise.all(imagePromises);
+    },
+
+    async addContentToPDF(element, pdf, pageWidth, pageHeight, topOffset = 0) {
+      const totalHeight = element.scrollHeight;
+      const canvas = await html2canvas(element, {
+        scale: 2,
+        useCORS: true,
+        logging: false,
+        windowWidth: pageWidth,
+        windowHeight: pageHeight,
+        y: topOffset,
+        ignoreElements: (element) => {
+          // 忽略使用已弃用的 -ms-high-contrast 的元素
+          const style = window.getComputedStyle(element);
+          return style.getPropertyValue("-ms-high-contrast") !== "none";
+        },
+      });
+
+      const imgData = canvas.toDataURL("image/jpeg", 1.0);
+      const imgWidth = pageWidth;
+      const imgHeight = (canvas.height * imgWidth) / canvas.width;
+
+      pdf.addImage(imgData, "JPEG", 0, 0, imgWidth, imgHeight);
+
+      this.exportProgress = Math.min(
+        100,
+        Math.round(((topOffset + pageHeight) / totalHeight) * 100)
+      );
+
+      if (canvas.height > pageHeight) {
+        pdf.addPage();
+        await this.addContentToPDF(
+          element,
+          pdf,
+          pageWidth,
+          pageHeight,
+          topOffset + pageHeight
+        );
+      }
+    },
 
     /* onExport() {
       let contentData = `<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body><p class="header1"></p> ${this.$refs.content.innerHTML} </body></html>`;

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels