vue开发word(docx格式)文档预览

         最近开发了一个在软件内部预览word文档的功能,功能是根据后端返回服务器资源的下载地址直接进行前端预览,由于浏览器不支持.docx格式的文件直接打开,所以需要借助第三方的方法和插件进行开发,话不多说开始整活。

 🎇 mammonthjs官网:将word转换成html      方案一实现

✨ @vue-office/docx官网:将word转换成html    方案二实现

效果演示:

请看大屏幕:方案一实现效果               方案二实现效果


前言

        今天分享的两种方法其实原理都是将word文档的内容转换成html网页的形式进行预览展示,使用插件的好处是快速实现大致效果,缺点是只能保留最基本的标签样式,复杂的样式会丢失导致和wps或者office这种专业软件打开的效果不一致、不美观。解决方法,可以使用样式穿透对其内部标签样式进行优化,基本实现美观展示。

一、mammonthjs是什么?

       Mammoth.js 是一个开源的 JavaScript 库,旨在将 Microsoft Word 创建的 .docx 文件转换为 HTML 格式。这个库的设计目标是生成简单和干净的 HTML,主要通过使用文档中的语义信息来实现,而不是尝试精确复制文档的样式(如字体、颜色、大小等)。Mammoth.js 支持多种文档样式的转换,并允许用户自定义样式映射,以便将 Word 文档中的样式更准确地转换为 HTML 元素。

二、使用步骤

1.引入库

代码如下(示例):

npm install --save mammoth

2.使用示例(部分代码)

代码如下(示例):

<template>
  <div class="statistical-report">
    <el-form :inline="true" :model="formInline" border class="demo-form-inline">
      <el-form-item label="时间:">
        <el-radio-group
          v-model="formInline.rangeTime"
          size="small"
          @change="handleSelfTime"
        >
          <el-radio-button :label="1">近一月</el-radio-button>
          <el-radio-button :label="2">近三月</el-radio-button>
          <el-radio-button :label="3">近半年</el-radio-button>
          <el-radio-button :label="4">自定义</el-radio-button>
        </el-radio-group>
      </el-form-item>
      <el-form-item>
        <el-date-picker
          :disabled="selfFlag"
          v-model="formInline.time"
          type="daterange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          value-format="yyyy-MM-dd"
          @change="handleTime"
        />
      </el-form-item>
      <el-form-item label="告警类型:">
        <el-radio-group v-model="formInline.type">
          <el-radio label="week">周报</el-radio>
          <el-radio label="month">月报</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" @click="handleSearch">
          查询
        </el-button>
        <el-button @click="handleRest" icon="el-icon-refresh">重置</el-button>
      </el-form-item>
    </el-form>
    <div class="body-all">
      <div class="table-body" v-show="folded">
        <el-table
          ref="multipleTable"
          class="table-self"
          :data="tableData"
          highlight-current-row
          @selection-change="handleSelectionChange"
          @row-click="handleRowClick"
        >
          <el-table-column align="center" width="60" :resizable="false">
            <template slot-scope="{ row }">
              <el-radio v-model="multipleSelection.id" :label="row.id">
                {{ "" }}
              </el-radio>
            </template>
          </el-table-column>
          <el-table-column label="序号" width="50px" type="index" />
          <el-table-column
            prop="type"
            label="监管工作报告类型"
            align="center"
            width="150"
          >
            <template slot-scope="scope">
              <span v-if="scope.row.type === 'week'">周报</span>
              <span v-else>月报</span>
            </template>
          </el-table-column>
          <el-table-column
            prop="reportname"
            label="监管工作报告名称"
            align="center"
            width="150"
          >
          </el-table-column>
          <el-table-column prop="status" label="处置状态" align="center">
            已生成
          </el-table-column>
          <el-table-column label="操作" align="center">
            <template slot-scope="scope">
              <el-button
                type="text"
                size="small"
                @click="handleDownload(scope.row)"
                >下载</el-button
              >
            </template>
          </el-table-column>
        </el-table>
        <div class="fanYe">
          <el-pagination
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="formInline.page"
            :page-sizes="[10, 15, 20, 50, 100]"
            :page-size="formInline.limit"
            layout="total, sizes, prev, pager, next, jumper"
            :total="total"
          >
          </el-pagination>
        </div>
      </div>
      <div style="cursor: pointer" class="fr" v-show="!folded" @click="fold">
        <i class="el-icon-s-fold"></i>
      </div>
      <div style="cursor: pointer" class="fr" v-show="folded" @click="unfold">
        <i class="el-icon-s-unfold"></i>
      </div>
      <div class="rightContent">
        <div id="wordView" v-html="wordText" />
      </div>
    </div>
  </div>
</template>
<script>
// docx文档预览(只能转换.docx文档,转换过程中复杂样式被忽,居中、首行缩进等)
import mammoth from "mammoth";
import kingDownload from "@/utils/KingDownload.js";  // 通用下载方法
import { selectByList } from "@/api/video/statisticalReportApi.js";  // 列表接口
export default {
  name: "StatisticalReport",
  data() {
    return {
      // 接口的数据
      queryStartTime: "",
      queryEndTime: "",
      // 搜索表单
      formInline: {
        rangeTime: null, //四选一
        time: null, // 时间段(数组)
        type: null,
        pageNum: 1,
        pageSize: 10,
      },
      total: 20,
      // table列表
      tableData: [],
      selfFlag: true,
      // ---------------
      folded: true, // table是否显示
      wordUrl: "", //预览pdf的地址
      wordText: "",
      multipleSelection: [],
      wordShow: "", //是否展示pdf
    };
  },
  computed: {
    // 当天时间yyyy-mm-dd
    endTime: {
      get() {
        return (
          new Date().getFullYear() +
          "-" +
          ("0" + (new Date().getMonth() + 1)).slice(-2) +
          "-" +
          ("0" + new Date().getDate()).slice(-2)
        );
      },
    },
    firstMonth: {
      get() {
        let now = new Date(); // 假设现在是 此时此刻的当天
        let targetDate = new Date(now);
        targetDate.setDate(now.getDate() - 30); // 往回推30天
        // 格式化日期
        let formattedStartDate = `${targetDate.getFullYear()}-${(
          "0" +
          (targetDate.getMonth() + 1)
        ).slice(-2)}-${("0" + targetDate.getDate()).slice(-2)}`;
        return formattedStartDate;
      },
    },
    secondMonth: {
      get() {
        let now = new Date(); // 假设现在是 此时此刻的当天
        let targetDate = new Date(now);
        targetDate.setDate(now.getDate() - 90); // 往回推90天
        // 格式化日期
        let formattedStartDate = `${targetDate.getFullYear()}-${(
          "0" +
          (targetDate.getMonth() + 1)
        ).slice(-2)}-${("0" + targetDate.getDate()).slice(-2)}`;
        return formattedStartDate;
      },
    },
    thirdMonth: {
      get() {
        let now = new Date(); // 假设现在是 此时此刻的当天
        let targetDate = new Date(now);
        targetDate.setDate(now.getDate() - 180); // 往回推180天
        // 格式化日期
        let formattedStartDate = `${targetDate.getFullYear()}-${(
          "0" +
          (targetDate.getMonth() + 1)
        ).slice(-2)}-${("0" + targetDate.getDate()).slice(-2)}`;
        return formattedStartDate;
      },
    },
  },
  mounted() {
    this.selectByList();
  },
  methods: {
    // 将word转换成html并展示
    getWordText() {
      const xhr = new XMLHttpRequest();
      xhr.open("get", this.wordUrl, true);
      xhr.responseType = "arraybuffer";
      xhr.onload = () => {
        if (xhr.status == 200) {
          mammoth
            .convertToHtml({ arrayBuffer: new Uint8Array(xhr.response) })
            .then((resultObject) => {
              this.$nextTick(() => {
                this.wordText = resultObject.value;
              });
            });
        }
      };
      xhr.send();
    },
    fold() {
      this.folded = true;
    },
    unfold() {
      this.folded = false;
    },
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    // 行点击事件
    handleRowClick(row, column, event) {
      this.multipleSelection = row;
      this.wordShow = true;
      this.wordUrl= row.downloadpath;
      this.getWordText();
    },
    // 下载
    handleDownload(e) {
      console.log(e, "下载");
      const path = e.downloadpath;
      kingDownload(path);
    },
    // 列表数据接口
    async selectByList(e) {
      const { code, rows, message, total } = await selectByList(e);
      if (code === 200) {
        this.tableData = rows;
        this.total = total;
        // 模拟第一行点击事件,默认选中第一行数据
        this.$nextTick(() => {
          this.handleRowClick(this.tableData[3]);
          this.$refs.multipleTable.setCurrentRow(this.tableData[3]);
        });
      } else {
        this.$message({
          message: message,
          type: "error",
        });
      }
    },
    // 时间切换
    handleSelfTime(e) {
      if (e === 4) {
        this.selfFlag = false;
        this.queryStartTime = "";
        this.queryEndTime = "";
      } else if (e === 1) {
        this.queryStartTime = this.firstMonth;
        this.queryEndTime = this.endTime;
        this.formInline.time = null;
        this.selfFlag = true;
      } else if (e === 2) {
        this.queryStartTime = this.secondMonth;
        this.queryEndTime = this.endTime;
        this.formInline.time = null;
        this.selfFlag = true;
      } else if (e === 3) {
        this.queryStartTime = this.thirdMonth;
        this.queryEndTime = this.endTime;
        this.formInline.time = null;
        this.selfFlag = true;
      } else {
        this.queryStartTime = "";
        this.queryEndTime = "";
        this.formInline.time = null;
        this.selfFlag = true;
      }
    },
    // 时间选择
    handleTime(e) {
      this.queryStartTime = e?.[0];
      this.queryEndTime = e?.[1];
    },
    // 重置
    handleRest() {
      this.formInline = {
        rangeTime: null, //四选一
        time: null, // 时间段(数组)
        type: null,
        pageNum: 1,
        pageSize: 10,
      };
      this.queryStartTime = "";
      this.queryEndTime = "";
    },
    // 按条件检索
    handleSearch() {
      let query = {
        beginTime: this.queryStartTime,
        endTime: this.queryEndTime,
        type: this.formInline.type,
        pageSize: this.formInline.pageSize,
        pageNum: this.formInline.pageNum,
      };
      this.selectByList(query);
    },
    handleSizeChange(val) {
      let query = {
        beginTime: this.queryStartTime,
        endTime: this.queryEndTime,
        type: this.formInline.type,
        pageSize: val,
      };
      this.formInline.pageSize = val;
      this.selectByList(query);
    },
    handleCurrentChange(val) {
      let query = {
        beginTime: this.queryStartTime,
        endTime: this.queryEndTime,
        type: this.formInline.type,
        pageNum: val,
      };
      this.formInline.pageNum = val;
      this.selectByList(query);
    },
  },
};
</script>

<style scoped lang="scss">
.statistical-report {
  padding: 12px;
  margin: 12px;
  background-color: #ffffff;
  .demo-form-inline {
    ::v-deep .el-form-item {
      margin-right: 18px;
      margin-bottom: 0;
    }
    ::v-deep .el-form-item__label {
      font-family: "Source Han Sans CN";
      font-weight: 400;
      font-size: 16px;
      color: #606163;
    }
    ::v-deep .el-radio-button {
      margin: 0 8px;
    }
    ::v-deep .el-radio-button--small .el-radio-button__inner {
      padding: 6px 10px;
      font-size: 14px;
      border-radius: 0;
      border: 1px solid #dcdfe6;
      box-sizing: border-box;
      border-radius: 3px;
    }
    ::v-deep .el-radio-button--small.is-active .el-radio-button__inner {
      border-left: none;
    }
    ::v-deep .el-radio {
      margin-right: 20px;
    }
  }
  .body-all {
    margin-top: 12px;
    border-top: 1px solid #e5e5e5; /* 修改水平线颜色为灰色 */
    display: flex;
    .table-body {
      flex: 1;
      margin-right: 20px;
      padding-top: 12px;
      .table-self {
        ::v-deep .el-table__header-wrapper th {
          background-color: #eff3fc;
        }
        margin-top: 10px;
      }

      .fanYe {
        padding: 10px;
        display: flex;
        justify-content: flex-end;
      }
    }
    .fr {
      margin-top: 12px;
    }
    .rightContent {
      flex: 2;
      padding: 15px 10px;
      margin-top: 12px;
      height: calc(100vh - 160px);
      overflow-y: scroll;
      // 在此对插件转换的html样式进行美化
      #wordView {
        ::v-deep p {
          text-align: left;
          font-size: 16px !important;
          img {
            // width: 100%;
            display: block;
            margin: 0 auto;
          }
        }
        ::v-deep table {
          width: 100%;
          border-collapse: collapse; /* 边框合并为一个单一的边框 */
          th,
          td {
            border: 1px solid #ddd; /* 单元格边框 */
            padding: 8px; /* 单元格内边距 */
            p {
              text-align: center; /* 文本左对齐 */
            }
          }

          th {
            background-color: #f2f2f2; /* 表头背景色 */
          }

          /* 如果你想为表格的每一行添加鼠标悬停效果,可以添加以下样式 */
          tr:hover {
            background-color: #f5f5f5; /* 鼠标悬停时的背景色 */
          }
        }
      }
      .noData {
        text-align: center;
        line-height: 40;
      }
    }
  }
}
</style>

三、mammonthjs是什么?

       @vue-office/docx是一个Vue组件库,专门用于在Vue项目中预览和编辑Microsoft Word (.docx)文件。这个库提供了与Word模板交互的JavaScript API,允许开发者生成动态的Word文档。它结合了Vue的组件化思想,使得在前端开发中对Word文档的操作变得更加便捷和高效。

四、使用步骤

1.引入库

代码如下(示例):这个插件非常难装,装了好几次才成功可能是网络问题也可能有各种限制(学会科学上网可能会好点)

#docx文档预览组件
npm install @vue-office/docx vue-demi@0.14.6

如果是vue2.6版本或以下还需要额外安装 @vue/composition-api

npm install @vue/composition-api

2.使用示例(部分代码)

代码如下(示例):

<template>
  <div class="statistical-report">
    <el-form :inline="true" :model="formInline" border class="demo-form-inline">
      <el-form-item label="时间:">
        <el-radio-group
          v-model="formInline.rangeTime"
          size="small"
          @change="handleSelfTime"
        >
          <el-radio-button :label="1">近一月</el-radio-button>
          <el-radio-button :label="2">近三月</el-radio-button>
          <el-radio-button :label="3">近半年</el-radio-button>
          <el-radio-button :label="4">自定义</el-radio-button>
        </el-radio-group>
      </el-form-item>
      <el-form-item>
        <el-date-picker
          :disabled="selfFlag"
          v-model="formInline.time"
          type="daterange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          value-format="yyyy-MM-dd"
          @change="handleTime"
        />
      </el-form-item>
      <el-form-item label="告警类型:">
        <el-radio-group v-model="formInline.type">
          <el-radio label="week">周报</el-radio>
          <el-radio label="month">月报</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" @click="handleSearch">
          查询
        </el-button>
        <el-button @click="handleRest" icon="el-icon-refresh">重置</el-button>
      </el-form-item>
    </el-form>
    <div class="body-all">
      <div class="table-body" v-show="folded">
        <el-table
          ref="multipleTable"
          class="table-self"
          :data="tableData"
          highlight-current-row
          @selection-change="handleSelectionChange"
          @row-click="handleRowClick"
        >
          <el-table-column align="center" width="60" :resizable="false">
            <template slot-scope="{ row }">
              <el-radio v-model="multipleSelection.id" :label="row.id">
                {{ "" }}
              </el-radio>
            </template>
          </el-table-column>
          <el-table-column label="序号" width="50px" type="index" />
          <el-table-column
            prop="type"
            label="监管工作报告类型"
            align="center"
            width="150"
          >
            <template slot-scope="scope">
              <span v-if="scope.row.type === 'week'">周报</span>
              <span v-else>月报</span>
            </template>
          </el-table-column>
          <el-table-column
            prop="reportname"
            label="监管工作报告名称"
            align="center"
            width="150"
          >
          </el-table-column>
          <el-table-column prop="status" label="处置状态" align="center">
            已生成
          </el-table-column>
          <el-table-column label="操作" align="center">
            <template slot-scope="scope">
              <el-button
                type="text"
                size="small"
                @click="handleDownload(scope.row)"
                >下载</el-button
              >
            </template>
          </el-table-column>
        </el-table>
        <div class="fanYe">
          <el-pagination
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="formInline.page"
            :page-sizes="[10, 15, 20, 50, 100]"
            :page-size="formInline.limit"
            layout="total, sizes, prev, pager, next, jumper"
            :total="total"
          >
          </el-pagination>
        </div>
      </div>
      <div style="cursor: pointer" class="fr" v-show="!folded" @click="fold">
        <i class="el-icon-s-fold"></i>
      </div>
      <div style="cursor: pointer" class="fr" v-show="folded" @click="unfold">
        <i class="el-icon-s-unfold"></i>
      </div>
      <div class="rightContent">
        <vue-office-docx
          v-show="isFlag"
          :src="wordUrl"
          @rendered="rendered($event)"
          @error="error($event)"
        />
        <el-empty
          v-show="!isFlag || total === 0"
          description="暂无报告"
        ></el-empty>
      </div>
    </div>
  </div>
</template>

<script>
//引入VueOfficeDocx组件
import VueOfficeDocx from "@vue-office/docx";
//引入相关样式(此处没啥作用)
// import "@vue-office/docx/lib/index.css";
import kingDownload from "@/utils/KingDownload.js";
import { selectByList } from "@/api/video/statisticalReportApi.js";
export default {
  name: "StatisticalReport",
  components: {
    VueOfficeDocx,
  },
  data() {
    return {
      // 接口的数据
      queryStartTime: "",
      queryEndTime: "",
      // 搜索表单
      formInline: {
        rangeTime: null, //四选一
        time: null, // 时间段(数组)
        type: null,
        pageNum: 1,
        pageSize: 10,
      },
      total: 20,
      // table列表
      tableData: [],
      selfFlag: true,
      // ---------------
      folded: true, // table是否显示
      isFlag: true, // 为了做文档空状态的处理
      pdfUrl: "", //预览pdf的地址
      wordText: "",
      multipleSelection: [],
    };
  },
  computed: {
    // 当天时间yyyy-mm-dd
    endTime: {
      get() {
        return (
          new Date().getFullYear() +
          "-" +
          ("0" + (new Date().getMonth() + 1)).slice(-2) +
          "-" +
          ("0" + new Date().getDate()).slice(-2)
        );
      },
    },
    firstMonth: {
      get() {
        let now = new Date(); // 假设现在是 此时此刻的当天
        let targetDate = new Date(now);
        targetDate.setDate(now.getDate() - 30); // 往回推30天
        // 格式化日期
        let formattedStartDate = `${targetDate.getFullYear()}-${(
          "0" +
          (targetDate.getMonth() + 1)
        ).slice(-2)}-${("0" + targetDate.getDate()).slice(-2)}`;
        return formattedStartDate;
      },
    },
    secondMonth: {
      get() {
        let now = new Date(); // 假设现在是 此时此刻的当天
        let targetDate = new Date(now);
        targetDate.setDate(now.getDate() - 90); // 往回推90天
        // 格式化日期
        let formattedStartDate = `${targetDate.getFullYear()}-${(
          "0" +
          (targetDate.getMonth() + 1)
        ).slice(-2)}-${("0" + targetDate.getDate()).slice(-2)}`;
        return formattedStartDate;
      },
    },
    thirdMonth: {
      get() {
        let now = new Date(); // 假设现在是 此时此刻的当天
        let targetDate = new Date(now);
        targetDate.setDate(now.getDate() - 180); // 往回推180天
        // 格式化日期
        let formattedStartDate = `${targetDate.getFullYear()}-${(
          "0" +
          (targetDate.getMonth() + 1)
        ).slice(-2)}-${("0" + targetDate.getDate()).slice(-2)}`;
        return formattedStartDate;
      },
    },
  },
  mounted() {
    this.selectByList();
  },
  methods: {
    渲染未完成触发
    error(e) {
      this.isFlag = false;
    },
    // 渲染完成触发
    rendered(e) {
      this.isFlag = true;
    },
    fold() {
      this.folded = true;
    },
    unfold() {
      this.folded = false;
    },
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    // 行点击事件
    handleRowClick(row, column, event) {
      this.multipleSelection = row;
      this.wordUrl = row.downloadpath;
    },
    // 下载
    handleDownload(e) {
      const path = e.downloadpath;
      kingDownload(path);
    },
    // 列表数据接口
    async selectByList(e) {
      const { code, rows, message, total } = await selectByList(e);
      if (code === 200) {
        this.tableData = rows;
        this.total = total;
        // 模拟第一行点击事件,默认选中第一行数据
        this.$nextTick(() => {
          this.handleRowClick(this.tableData[0]);
          this.$refs.multipleTable.setCurrentRow(this.tableData[0]);
        });
      } else {
        this.$message({
          message: message,
          type: "error",
        });
      }
    },
    // 时间切换
    handleSelfTime(e) {
      if (e === 4) {
        this.selfFlag = false;
        this.queryStartTime = "";
        this.queryEndTime = "";
      } else if (e === 1) {
        this.queryStartTime = this.firstMonth;
        this.queryEndTime = this.endTime;
        this.formInline.time = null;
        this.selfFlag = true;
      } else if (e === 2) {
        this.queryStartTime = this.secondMonth;
        this.queryEndTime = this.endTime;
        this.formInline.time = null;
        this.selfFlag = true;
      } else if (e === 3) {
        this.queryStartTime = this.thirdMonth;
        this.queryEndTime = this.endTime;
        this.formInline.time = null;
        this.selfFlag = true;
      } else {
        this.queryStartTime = "";
        this.queryEndTime = "";
        this.formInline.time = null;
        this.selfFlag = true;
      }
    },
    // 时间选择
    handleTime(e) {
      this.queryStartTime = e?.[0];
      this.queryEndTime = e?.[1];
    },
    // 重置
    handleRest() {
      this.formInline = {
        rangeTime: null, //四选一
        time: null, // 时间段(数组)
        type: null,
        pageNum: 1,
        pageSize: 10,
      };
      this.queryStartTime = "";
      this.queryEndTime = "";
    },
    // 按条件检索
    handleSearch() {
      let query = {
        beginTime: this.queryStartTime,
        endTime: this.queryEndTime,
        type: this.formInline.type,
        pageSize: this.formInline.pageSize,
        pageNum: this.formInline.pageNum,
      };
      this.selectByList(query);
    },
    handleSizeChange(val) {
      let query = {
        beginTime: this.queryStartTime,
        endTime: this.queryEndTime,
        type: this.formInline.type,
        pageSize: val,
      };
      this.formInline.pageSize = val;
      this.selectByList(query);
    },
    handleCurrentChange(val) {
      let query = {
        beginTime: this.queryStartTime,
        endTime: this.queryEndTime,
        type: this.formInline.type,
        pageNum: val,
      };
      this.formInline.pageNum = val;
      this.selectByList(query);
    },
  },
};
</script>

<style scoped lang="scss">
.statistical-report {
  padding: 12px;
  margin: 12px;
  background-color: #ffffff;
  .demo-form-inline {
    ::v-deep .el-form-item {
      margin-right: 18px;
      margin-bottom: 0;
    }
    ::v-deep .el-form-item__label {
      font-family: "Source Han Sans CN";
      font-weight: 400;
      font-size: 16px;
      color: #606163;
    }
    ::v-deep .el-radio-button {
      margin: 0 8px;
    }
    ::v-deep .el-radio-button--small .el-radio-button__inner {
      padding: 6px 10px;
      font-size: 14px;
      border-radius: 0;
      border: 1px solid #dcdfe6;
      box-sizing: border-box;
      border-radius: 3px;
    }
    ::v-deep .el-radio-button--small.is-active .el-radio-button__inner {
      border-left: none;
    }
    ::v-deep .el-radio {
      margin-right: 20px;
    }
  }
  .body-all {
    margin-top: 12px;
    border-top: 1px solid #e5e5e5; /* 修改水平线颜色为灰色 */
    display: flex;
    .table-body {
      flex: 1;
      margin-right: 20px;
      padding-top: 12px;
      .table-self {
        height: calc(100vh - 230px);
        overflow-y: scroll;
        ::v-deep .el-table__header-wrapper th {
          background-color: #eff3fc;
        }
        ::v-deep .el-table__empty-text {
          line-height: 500px;
          font-size: 16px;
        }
        margin-top: 10px;
      }

      .fanYe {
        padding: 10px;
        display: flex;
        justify-content: flex-end;
      }
    }
    .fr {
      margin-top: 12px;
    }
    .rightContent {
      flex: 2;
      padding: 15px 10px;
      margin-top: 12px;
      height: calc(100vh - 160px);
      overflow-y: scroll;
      .el-empty {
        height: calc(100vh - 220px);
      }
      // 此处进行样式优化
      ::v-deep article {
        padding: 26px;
        div {
          width: 100% !important;
          img {
            display: block;
            margin: 0 auto;
          }
        }
        table {
          width: 100% !important;
          border-collapse: collapse; /* 边框合并为一个单一的边框 */
          th,
          td {
            border: 1px solid #ddd; /* 单元格边框 */
            padding: 8px; /* 单元格内边距 */
          }
          th {
            background-color: #f2f2f2; /* 表头背景色 */
          }
          /* 如果你想为表格的每一行添加鼠标悬停效果,可以添加以下样式 */
          tr:hover {
            background-color: #f5f5f5; /* 鼠标悬停时的背景色 */
          }
        }
      }

      .noData {
        text-align: center;
        line-height: 40;
      }
    }
  }
}
</style>

五、拓展

vue-office还可以进行excel,pdf(这个比较常用)的预览开发


总结

    由于个人能力有限,此次开发时间紧迫只找到了以上两种适合word文档预览的插件,功能不是很完善但是基本的功能已经实现,样式的美化需要更多的投入和开发,好了这次就分享这么多,希望有其他见解的朋友来交流学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值