前端html生成word

所用的插件 html-docx  和  file-saver

项目中所用到的  生成运动会秩序册  核心代码如下 

<!--
 * @Author: gaopengli
 * @Date: 2021-09-09 15:01:26
 * @LastEditTime: 2021-10-13 19:59:06
 * @LastModifiedBy: gaopengli
 * @LastEditors: gaopengli
 * @Description: 描述
 * @FilePath: \frontend-admin\src\pages\eventManage\dataNote\components\dialog.book.vue
-->
<template>
  <div>
    <div id="oredrBookContent" class="order-book">
      <div>
        <div id="html-docx-config">
          <div id="first-page" titlePg="true">
            <h1 style="text-align: center; margin-bottom: 80px">
              {{ bookInfo.matchName }}{{ bookInfo.item }}
            </h1>

            <div
              style="font-size: 80px; margin-bottom: 90px; text-align: center"
            >
              秩
            </div>
            <div
              style="font-size: 80px; margin-bottom: 90px; text-align: center"
            >
              序
            </div>
            <div
              style="font-size: 80px; margin-bottom: 90px; text-align: center"
            >
              册
            </div>

            <div>
              <div
                style="text-align: center; font-size: 25px; font-weight: bold"
              >
                {{ bookInfo.startTime }}至{{ bookInfo.endTime }}
              </div>
              <div
                style="
                  text-align: center;
                  font-size: 25px;
                  margin-top: 30px;
                  font-weight: bold;
                "
              >
                {{ bookInfo.holdPlace }}
              </div>
            </div>
          </div>
          <div class="change-line"></div>
        </div>
        <div id="rule-page">
          <h2 style="text-align: center">
            {{ bookInfo.matchName }}{{ bookInfo.item }}项目竞赛规程
          </h2>
          <div v-html="bookInfo.ruleInfo"></div>
          <div class="change-line"></div>
        </div>
        <div id="notice-page">
          <h2 style="text-align: center">
            {{ bookInfo.matchName }}{{ bookInfo.item }}项目补充通知
          </h2>
          <div v-html="bookInfo.notice"></div>
          <div class="change-line"></div>
        </div>
        <div id="unit-page">
          <h2 style="text-align: center">各代表队名单</h2>
          <!-- <div>
            <span>运动员iiii:</span>
            <span
              v-for="(item, index) in 7"
              :key="`item_${index}`"
              style="padding-left: 15px"
            >
              <span>运动员&nbsp;</span>
              <span>运动员,运动员 &nbsp;&nbsp;&nbsp;&nbsp;</span>
              <br v-if="index % 3 === 2" />
            </span>
          </div> -->
          <div
            style="font-size: 22px; line-height: 30px; margin-top: 20px"
            v-for="(unitItem, index) in bookInfo.unitList"
            :key="`unit_${index}`"
          >
            <h3 style="text-align: center">{{ unitItem.unit }}</h3>
            <div
              v-for="(staff, index) in unitItem.supportStaffMap"
              :key="`staff_${index}`"
            >
              <span>{{ index }}:</span
              ><span
                v-for="(item, index) in staff"
                :key="`item_${index}`"
                style="padding-left: 5px"
                >{{ item }}</span
              >
            </div>
            <div style="font-size: 22px; line-height: 30px">运动员:</div>
            <div
              v-for="(athlete, index) in unitItem.athleteMap"
              :key="`athlete_${index}`"
            >
              <div>
                <span>{{ index }}:</span>
              </div>
              <div>
                <span
                  v-for="(item, index) in athlete"
                  :key="`item_${index}`"
                  style="padding-left: 15px"
                >
                  <span>{{ item.peopleName }}&nbsp;</span>

                  <span>{{ item.birthYear }},{{ item.age }} &nbsp;&nbsp;</span>

                  <br v-if="index % 3 === 2" />
                </span>
              </div>
            </div>
            <!--<div style="clear: both"></div> -->
            <!-- </div> -->
          </div>
          <div class="change-line"></div>
        </div>
        <div id="end-page">
          <h2 style="text-align: center">大会活动日程表</h2>
          <div v-html="bookInfo.matchSchedule"></div>
        </div>
      </div>
    </div>
    <el-button type="primary" @click="confirm">确定</el-button>
  </div>
</template>
<script>
import apis from '@/apis'
import $ from 'jquery'
import HtmlDocx from 'html-docx-js/dist/html-docx'
import saveAs from 'file-saver'
export default {
  data() {
    return {
      matchName: '厦门马拉松',
      projectName: '摔跤',
      leader: '王 成',
      coach: '何 利 林泽禹 宋虎成 陈 杨',
      worker: '林 畅',
      matchGroupId: '',
      styleList: [],
      bookInfo: {}
    }
  },
  methods: {
    /**
     * @description: 获取秩序册内容
     * @param {*}
     * @return {*}
     */
    getBookContent(data) {
      this.matchGroupId = data.matchGroupId
      this.$http
        .post(
          `${apis._api_MatchDocumentController_getOrderVolumesContent}?matchGroupId=${this.matchGroupId}`
        )
        .then(res => {
          if (res.data.code === 200) {
            let data = res.data.data
            console.log(data)
            this.bookInfo = data
            this.$nextTick(() => {
              this.confirm()
            })
          }
        })
    },
    confirm() {
      // 这段代码用来处理style标签的样式
      this.styleList = []
      let element = document.getElementsByClassName('style')
      if (element.length) {
        for (var i = 0; i < element.length; i++) {
          this.styleList.push(element[i].innerText.replace(/\s{2,}/g, ''))
        }
      }
      this.HtmlToDocx({
        exportElement: '#oredrBookContent', // 需要转换为word的html标签
        exportFileName: `${this.bookInfo.matchName}${this.bookInfo.item}项目秩序册.docx`, // 转换之后word文档的文件名称
        StringStyle: this.styleList.join(''), // css样式以字符窜的形式插入进去
        margins: {
          top: 1440,
          right: 1440,
          bottom: 1440,
          left: 1440,
          header: 720,
          footer: 720,
          gutter: 0
        } // word的边距配置
      })
    },
    /**
     * @description: html转成word
     * @param {*} params
     * @return {*}
     */
    HtmlToDocx(params) {
      var exportElement = params.exportElement
      var exportFileName = params.exportFileName
      var StringStyle = params.StringStyle
        ? params.StringStyle
        : '#main,	#main1 {height: 400px;width: 630px	}	.list {background: blue;padding: 10px	}	.list .page {background: yellow;padding: 5px;height: 20px;	}	.img {padding: 50px;	}	table {align-text: center;width: 100%;vertical-align: middle;border-top: 1px solid #ddd;border-left: 1px solid #ddd;	}	table td,	table th {width: 20%;height: 40px;border-right: 1px solid #ddd;border-bottom: 1px solid #ddd;	}	table p {text-indent: 0 !important;text-align: center;	}'

      var fistPageContent = $('#html-docx-config').html()

      var config = this.getDocumentConfig()
      console.log(fistPageContent, config)
      var Id = '#temporaryExportElement'
      $("<div id='temporaryExportElement'></div>")
        .html($(exportElement).html())
        .appendTo(document.body)
      this.convertImagesToBase64()
      var content =
        "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'><head></head><style>" +
        (StringStyle ? StringStyle.replace(/(\s{2,}|\n)/g, '') : '') +
        '</style><body>' +
        $(Id)
          .html()
          .replace(/\s{2,}/g, '') +
        '</body></html>'
      $('#temporaryExportElement').remove()
      let blobData = HtmlDocx.asBlob(content)
      // let timestamp = Date.parse(new Date())
      // 将blob转为file
      let files = new window.File(
        [blobData],
        `${this.bookInfo.matchName}${this.bookInfo.item}项目秩序册.docx`,
        {
          type: blobData.type
        }
      )
      console.log(files)
      this.uploadFiles(files)
      saveAs(HtmlDocx.asBlob(content), exportFileName)
    },
    /**
     * @description: 上传生成的文件
     * @param {*} files
     * @return {*}
     */
    uploadFiles(files) {
      this.$http
        .post(apis._api_file_uploadNoRename, {
          files: files,
          model: 'SSZH',
          IsFormData: true
        })
        .then(res => {
          let data = res.data.data
          if (res.data.code === 200) {
            console.log(res)
            this.creatBook(data[0].path)
          }
        })
    },
    /**
     * @description: 生成秩序册
     * @param {*} filePath 文档地址
     * @return {*}
     */
    creatBook(filePath) {
      this.$http
        .post(apis._api_MatchDocumentController_createOrderVolumes, {
          matchGroupId: this.matchGroupId,
          path: filePath
        })
        .then(res => {
          if (res.data.code === 200) {
            $('.page-break').remove() //防止重复换页
            this.$emit('onComplete')
            console.log(res)
          }
        })
    },
    /**
     * @description: 将图片转为base64格式
     * @param {*}
     * @return {*}
     */
    convertImagesToBase64() {
      var regularImages = document.querySelectorAll('img')
      var canvas = document.createElement('canvas')
      var ctx = canvas.getContext('2d')
      ;[].forEach.call(regularImages, function (img) {
        var imgElement = new Image()
        //设置图片跨域访问
        img.setAttribute('crossOrigin', 'anonymous')
        ctx.clearRect(0, 0, canvas.width, canvas.height)
        canvas.width = img.width
        canvas.height = img.height
        ctx.drawImage(img, 0, 0)
        var dataURL = canvas.toDataURL()
        imgElement.setAttribute('src', dataURL)
      })
      canvas.remove()
    },
    // 获取文档中word文档配置信息
    getDocumentConfig() {
      // 处理页眉
      var header = $('#page-header')
      $('#page-header').attr({ data: header.html() }).html('')
      // 处理首页
      var firstPageContent = ''
      if ($('#first-page').length && $('#page-content').length) {
        firstPageContent =
          "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'><head></head><body>" +
          $($('#first-page'))
            .html()
            .replace(/\s{2,}/g, '') +
          '</body></html>'
        $('#first-page').html('')
      }
      // 处理目录
      var content = $('#page-content')
      // 处理换行
      $(
        '<br clear=all style="page-break-before:always" mce_style="page-break-before:always" class="page-break">'
      ).insertAfter($('.change-line'))
      var footer = $('#page-footer')
      return {
        header: {
          text: header.attr('data') || '',
          align: header.attr('textAlign') || 'right'
        },
        footer: footer.length ? true : false,
        content: content.length,
        firstPage: firstPageContent,
        titlePg:
          $('#first-page').length && $('#first-page').attr('titlePg') === 'true'
            ? true
            : false
      }
    }
  }
}
</script>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值