vue使用hiprint实现打印(vue-plugin-hiprint)

发布时间 2023-07-18 16:53:43作者: zaijinyang

1、安装插件:

npm install vue-plugin-hiprint

  或

yarn add vue-plugin-hiprint

  

2、普通使用:

<template>
  <div class="box">
    <div class="box-tool">
      <el-button-group>
        <el-button type="primary" @click="print">浏览器打印</el-button>
        <el-button type="primary" @click="exportJson">导出JSON</el-button>
      </el-button-group>
    </div>
    <div class="box-content">
      <el-row :gutter="10">
        <el-col :xs="24" :sm="5" :md="5" :lg="5" :xl="5">
          <el-card class="box-content-card">
            <template #header>
              <div class="card-header">
                <span>基础工具</span>
              </div>
            </template>
            <div class="box-content-left">
              <div
                class="box-content-left-item ep-draggable-item"
                v-for="(item, index) in baseTools"
                :key="index"
                :tid="item.tid"
              >
                <el-image
                  style="width: 40px; height: 40px"
                  :src="item.icon"
                  fit="cover"
                />
                <p>{{ item.name }}</p>
              </div>
            </div>
          </el-card>
          <el-card class="box-content-card">
            <template #header>
              <div class="card-header">
                <span>辅助工具</span>
              </div>
            </template>
            <div class="box-content-left">
              <div
                class="box-content-left-item ep-draggable-item"
                v-for="(item, index) in assistTools"
                :key="index"
                :tid="item.tid"
              >
                <el-image
                  style="width: 40px; height: 40px"
                  :src="item.icon"
                  fit="cover"
                />
                <p>{{ item.name }}</p>
              </div>
            </div>
          </el-card>
        </el-col>
        <el-col :xs="24" :sm="14" :md="14" :lg="14" :xl="14">
          <el-card class="box-content-card box-content-center">
            <div id="hiprint-printTemplate"></div>
          </el-card>
        </el-col>
        <el-col :xs="24" :sm="5" :md="5" :lg="5" :xl="5">
          <el-card class="box-content-card box-content-right">
            <div id="PrintElementOptionSetting"></div>
          </el-card>
        </el-col>
      </el-row>
    </div>
  </div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { hiprint, defaultElementTypeProvider } from "vue-plugin-hiprint";
// 初始化 provider
hiprint.init({
  providers: [defaultElementTypeProvider()],
});
/**
 * 这里必须要在 onMounted 中去构建 左侧可拖拽元素 或者 设计器
 * 因为都是把元素挂载到对应容器中, 必须要先找到该容器
 */
onMounted(() => {
  buildLeftElement();
  buildDesigner();
});
/**
 * 构建左侧可拖拽元素
 * 注意: 可拖拽元素必须在 hiprint.init() 之后调用
 * 而且 必须包含 class="box-content-left-item" 否则无法拖拽进设计器
 */
const buildLeftElement = () => {
  hiprint.PrintElementTypeManager.buildByHtml($(".ep-draggable-item"));
};
/**
 * 构建设计器
 * 注意: 必须要在 onMounted 中去构建
 * 因为都是把元素挂载到对应容器中, 必须要先找到该容器
 */
let hiprintTemplate;
const buildDesigner = () => {
  $("#hiprint-printTemplate").empty(); // 先清空, 避免重复构建
  hiprintTemplate = new hiprint.PrintTemplate({
    settingContainer: "#PrintElementOptionSetting", // 元素参数容器
  });
  // 构建 并填充到 容器中
  hiprintTemplate.design("#hiprint-printTemplate");
};

/**
 * 浏览器打印
 */
const print = () => {
  // 打印数据,key 对应 元素的 字段名
  let printData = { name: "CcSimple" };
  // 参数: 打印时设置 左偏移量,上偏移量
  let options = { leftOffset: -1, topOffset: -1 };
  // 扩展
  let ext = {
    callback: () => {
      console.log("浏览器打印窗口已打开");
    },
    styleHandler: () => {
      // 重写 文本 打印样式
      return "<style>.hiprint-printElement-text{color:red !important;}</style>";
    },
  };
  // 调用浏览器打印
  hiprintTemplate.print(printData, options, ext);
};

const baseTools = ref([
  {
    id: 1,
    name: "文本",
    tid: "defaultModule.text",
    icon: require("@/assets/svg/文本.svg"),
  },
  {
    id: 2,
    name: "图片",
    tid: "defaultModule.image",
    icon: require("@/assets/svg/图片.svg"),
  },
  {
    id: 3,
    name: "多行文本",
    tid: "defaultModule.longText",
    icon: require("@/assets/svg/多行文本.svg"),
  },
  {
    id: 4,
    name: "内容表格",
    tid: "defaultModule.table",
    icon: require("@/assets/svg/内容表格.svg"),
  },
  {
    id: 5,
    name: "空表格",
    tid: "defaultModule.emptyTable",
    icon: require("@/assets/svg/表格.svg"),
  },
  {
    id: 6,
    name: "html",
    tid: "defaultModule.html",
    icon: require("@/assets/svg/html.svg"),
  },
  {
    id: 7,
    name: "自定义文本",
    tid: "defaultModule.customText",
    icon: require("@/assets/svg/文本.svg"),
  },
]);

const assistTools = ref([
  {
    id: 1,
    name: "横线",
    tid: "defaultModule.hline",
    icon: require("@/assets/svg/横线.svg"),
  },
  {
    id: 2,
    name: "竖线",
    tid: "defaultModule.vline",
    icon: require("@/assets/svg/竖线.svg"),
  },
  {
    id: 3,
    name: "矩形",
    tid: "defaultModule.rect",
    icon: require("@/assets/svg/矩形.svg"),
  },
  {
    id: 4,
    name: "椭圆",
    tid: "defaultModule.oval",
    icon: require("@/assets/svg/椭圆.svg"),
  },
]);

/**
 * @description: 导出json
 * @return {*}
 */
const exportJson = () => {
  if (hiprintTemplate) {
    down(`JSON数据_${Date.now()}`, JSON.stringify(hiprintTemplate.getJson() || {}));
  }
};

const down = (filename, text) => {
  var pom = document.createElement("a");
  pom.setAttribute(
    "href",
    "data:text/plain;charset=utf-8," + encodeURIComponent(text)
  );
  pom.setAttribute("download", filename);
  if (document.createEvent) {
    var event = document.createEvent("MouseEvents");
    event.initEvent("click", true, true);
    pom.dispatchEvent(event);
  } else {
    pom.click();
  }
};
</script>

<style lang="scss" scoped>
.box {
  width: 100%;

  &-tool {
    padding: 20px;
  }

  &-content {
    width: 98%;
    margin: 0 auto;
    &-card {
      margin-bottom: 20px;
    }

    &-left {
      display: flex;
      flex-wrap: wrap;

      &-item {
        width: 23%;
        background: white;
        padding: 4px 10px;
        margin-right: 10px;
        text-align: center;
        border-radius: 4px;
        box-shadow: 2px 2px 2px 2px rgba(171, 171, 171, 0.2);
        margin-bottom: 20px;
      }
    }

    &-center {
      height: calc(100vh - 100px);
      padding: 10px;
      overflow: auto;
    }
  }
}
</style>