Bootstrap

Vue.js组件开发-使用Vue3如何实现上传word作为打印模版

使用Vue 3实现Word模板上传、解析和打印功能的完整解决方案:


一、实现步骤

  1. 安装依赖
  2. 创建文件上传组件
  3. 实现.docx文件解析
  4. 创建打印预览组件
  5. 实现打印功能
  6. 样式优化

二、完整代码实现

1. 安装依赖
npm install mammoth axios
2. 创建文件上传组件(FileUpload.vue)
<template>
  <div class="upload-container">
    <!-- 文件上传区域 -->
    <input 
      type="file" 
      ref="fileInput"
      accept=".docx"
      @change="handleFileUpload"
      class="upload-input"
    />
    <button @click="triggerFileInput" class="upload-button">
      选择Word模板
    </button>

    <!-- 错误提示 -->
    <div v-if="errorMessage" class="error-message">
      {{ errorMessage }}
    </div>
  </div>
</template>

<script>
import mammoth from 'mammoth';

export default {
  emits: ['upload-success'],
  data() {
    return {
      errorMessage: ''
    };
  },
  methods: {
    // 触发文件选择对话框
    triggerFileInput() {
      this.$refs.fileInput.click();
    },

    // 处理文件上传
    async handleFileUpload(event) {
      const file = event.target.files[0];
      this.errorMessage = '';

      // 校验文件类型
      if (!file || !file.name.endsWith('.docx')) {
        this.errorMessage = '仅支持.docx格式文件';
        return;
      }

      try {
        // 使用Mammoth解析Word文档
        const result = await mammoth.convertToHtml({ arrayBuffer: await file.arrayBuffer() });
        
        // 发出解析后的HTML内容和原始文件
        this.$emit('upload-success', {
          htmlContent: result.value,
          originalFile: file
        });

      } catch (error) {
        console.error('文件解析失败:', error);
        this.errorMessage = '文件解析失败,请检查文件格式';
      }
    }
  }
}
</script>

<style scoped>
.upload-container {
  margin: 20px;
  padding: 15px;
  border: 1px dashed #ccc;
}

.upload-input {
  display: none;
}

.upload-button {
  padding: 8px 15px;
  background: #409eff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.error-message {
  color: #f56c6c;
  margin-top: 10px;
}
</style>
3. 创建打印预览组件(PrintPreview.vue)
<template>
  <div class="print-preview">
    <!-- 预览区域 -->
    <div class="preview-content" v-html="processedContent"></div>

    <!-- 操作按钮 -->
    <div class="action-buttons">
      <button @click="printDocument" class="print-button">
        打印文档
      </button>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    htmlContent: {
      type: String,
      required: true
    }
  },
  computed: {
    // 处理HTML内容(可添加自定义处理)
    processedContent() {
      return this.htmlContent;
    }
  },
  methods: {
    // 打印文档
    printDocument() {
      const printWindow = window.open('', '_blank');
      printWindow.document.write(`
        <html>
          <head>
            <title>打印文档</title>
            <style>
              /* 打印样式优化 */
              @media print {
                body { margin: 0; }
                img { max-width: 100%; }
                table { width: 100%; border-collapse: collapse; }
              }
            </style>
          </head>
          <body>
            ${this.processedContent}
          </body>
        </html>
      `);
      
      printWindow.document.close();
      printWindow.print();
    }
  }
}
</script>

<style scoped>
.preview-content {
  max-width: 800px;
  margin: 20px auto;
  padding: 20px;
  border: 1px solid #ddd;
  background: white;
}

.action-buttons {
  text-align: center;
  margin-top: 20px;
}

.print-button {
  padding: 10px 20px;
  background: #67c23a;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
</style>
4. 主组件集成(App.vue)
<template>
  <div class="app-container">
    <h1>Word模板打印系统</h1>
    
    <FileUpload @upload-success="handleUploadSuccess" />
    
    <PrintPreview 
      v-if="showPreview"
      :html-content="templateContent"
    />
  </div>
</template>

<script>
import FileUpload from './components/FileUpload.vue';
import PrintPreview from './components/PrintPreview.vue';

export default {
  components: {
    FileUpload,
    PrintPreview
  },
  data() {
    return {
      templateContent: '',
      showPreview: false
    };
  },
  methods: {
    handleUploadSuccess({ htmlContent }) {
      this.templateContent = htmlContent;
      this.showPreview = true;
    }
  }
}
</script>

<style>
.app-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
  font-family: Arial, sans-serif;
}
</style>

三、使用说明

1. 功能特性
  • 支持.docx文件上传
  • 实时预览转换后的内容
  • 打印样式优化
  • 错误处理机制
2. 使用流程
  1. 点击"选择Word模板"按钮
  2. 选择.docx格式文件
  3. 自动显示转换后的预览内容
  4. 点击"打印文档"按钮进行打印
3. 注意事项
  • 仅支持.docx格式(Word 2007+)
  • 文档中的图片将被转换为Base64嵌入
  • 建议文档宽度不超过800px
  • 复杂表格样式建议使用CSS增强

四、扩展建议

1. 样式增强
/* 在PrintPreview组件中添加 */
.preview-content {
  font-family: 'SimSun'; /* 使用打印常用字体 */
  line-height: 1.6;
}

.preview-content table {
  border: 1px solid #000;
}

.preview-content td, .preview-content th {
  padding: 8px;
  border: 1px solid #ddd;
}
2. 服务端集成(可选)
// 如果需要保存模板
async saveTemplate() {
  try {
    await axios.post('/api/templates', {
      content: this.templateContent,
      fileName: this.uploadedFileName
    });
  } catch (error) {
    console.error('保存失败:', error);
  }
}
3. 水印功能(示例)
// 在printDocument方法中添加
const watermark = `
  <div style="
    position: absolute;
    opacity: 0.2;
    transform: rotate(-45deg);
    font-size: 48px;
    color: #666;
  ">
    机密文档
  </div>
`;

printWindow.document.body.innerHTML = watermark + this.processedContent;

该方案实现了完整的Word模板上传、解析和打印流程,包含完善的错误处理和样式优化,可直接集成到现有Vue项目中。可根据具体需求扩展模板管理、样式配置等功能。

;