小白如何制作出属于自己的utools插件(实战篇) 第二篇

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第四天

小白如何制作出属于自己的utools插件(实战篇) 第二篇

如何将vue项目做成utools插件

实现一个简单的pdf转换成word,ppt,excel的插件

我们要实现这样的页面

image.png

初始化vue项目

vue create pdf_office

image.png

image.png
如何选择vue2,然后一直点击回车即可,创建完后,读者可以调用一下目录来判断是否创建成功

cd pdf_office
yarn serve

进入网址后,查看是否呈现如下图所示,如果出现则代表创建成功

image.png

项目目录介绍

image.png

Menu.vue

主要展示的是菜单一栏

Other_PDF.vue

主要是其他文件转pdf的页面,该页面主要实现的功能如下

  1. 支持拖拽
  2. 支持多文件同时转换成pdf
  3. 将转换成功的文件保存在桌面上

PDF-Other.vue

主要是pdf转其他文件(word,ppt,excel)的页面,该页面主要实现的功能如下

  1. 支持拖拽
  2. 支持多个pdf文件同时转换成其他文件
  3. 将转换成功的文件保存在桌面上

request.js

对axios进行封装,其中加入了接口所需的token

App.vue

主页面,当前项目目前只需要一个页面,不需要多个页面

main.js

入口函数,初始化所有配置

项目介绍

该项目主要制作一个pdf转常见文档和其他文件转pdf的utools小插件,适合用于vue如何变成utools小插件

项目开始

第一步 下载依赖

首先无疑是先需要将整个项目所需要的依赖进行下载

当前项目需要以下依赖

image.png

因为为了快速开发,所以我们需要用到elementui进行开发,这样也大大减少了我们在布局中涉及的样式或者其他

第二步 初始化配置

下载好依赖后,我们就需要在main.js中进行设置一些配置项

import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.config.productionTip = false
Vue.use(ElementUI);
new Vue({
  render: h => h(App),
}).$mount('#app')

第三步 制作菜单

image.png
制作一个这样的菜单无疑对于资深的前端肯定比较简单,但是对我比较菜的我,只能运用flex布局来实现,长话短说,直接上代码

<!--
 * @Description: 
 * @Version: 1.0
 * @Autor: solid
 * @Date: 2022-10-25 18:43:28
 * @LastEditors: solid
 * @LastEditTime: 2022-10-26 14:14:44
-->
<template>
  <div class="menu">
    <div :class="outputFileType == 'docx' ? 'menu-item active' : 'menu-item'" @click="ChangeMethod('docx','PDFOther')">
      <img
        src="../assets/word.png"
        
        srcset=""
        style="width: 2em; object-fit: contain"
      />
      PDF转WORD
    </div>
    <div :class="outputFileType == 'xlsx' ? 'menu-item active' : 'menu-item'" @click="ChangeMethod('xlsx','PDFOther')"> 
      <img
        src="../assets/excel.png"
        
        srcset=""
        style="width: 2em; object-fit: contain"
      />
      PDF转EXCEL
    </div>
    <div :class="outputFileType == 'pptx' ? 'menu-item active' : 'menu-item'" @click="ChangeMethod('pptx','PDFOther')">
      <img
        src="../assets/ppt.png"
        
        srcset=""
        style="width: 2em; object-fit: contain"
      />
      PDF转PPT
    </div>
    <div :class="outputFileType == 'other' ? 'menu-item active' : 'menu-item'" @click="ChangeMethod('other','otherPDF')">
      <img
        src="../assets/others.png"
        
        srcset=""
        style="width: 2em; object-fit: contain"
      />
      其他转PDF
    </div>
  </div>
</template>

<script>
export default {
  name: "Menu",
  data() {
    return {
      outputFileType: "docx",
    };
  },
  methods: {
    ChangeMethod(outputFileType,t){
        this.outputFileType=outputFileType
        this.$emit("ChangeMethod",outputFileType,t)
    }
  },
};
</script>

<style>
.menu {
  flex-basis: 280px;
  display: flex;
  flex-direction: column;
}
.menu .menu-item {
  padding: 20px;
  font-size: 16px;
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  cursor: pointer;
}
.active{
  background: #eee;
}
</style>

app.vue 必然也要有一些代码

image.png

注意:这里可能会涉及到没有找到图片的提示,在文章末尾我会提供github地址,读者可以将源码下来了进行参考

image.png

第四步 实现pdf转其他文件

实现这个当然要先搭建页面,无疑我们先看看需求是什么?

  1. 支持拖拽
  2. 支持多个pdf文件同时转换成其他文件
  3. 将转换成功的文件保存在桌面上

首先我们在elementui中先找到如何支持文件上传并支持拖拽

image.png

下面就是我当时想到的代码
PDF-Other.vue

<!--
 * @Description: 
 * @Version: 1.0
 * @Autor: solid
 * @Date: 2022-10-21 17:19:33
 * @LastEditors: solid
 * @LastEditTime: 2022-10-26 14:23:55
-->
<template>
  <div >
    <div style="">
      <div style="box-sizing: border-box;">
        <el-upload
          accept=".pdf"
          action="#"
          :auto-upload="false"
          :on-change="handleChange"
          :on-remove="removeFile"
          list-type="picture"
          drag
          multiple
        >
          <div v-if="files.length == 0">
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">拖拽 PDF 文件到这</div>
          </div>
        </el-upload>
      </div>
      <div style="position: absolute; bottom: 0px">
        <el-button
          type="primary"
          style="width: 500px; height: 10vh; font-size: 2em"
          @click="UploadFile"
          >转换成{{ fordata.outputFileType }}</el-button
        >
      </div>
    </div>
  </div>
</template>

<script>
import { FileUpdate, FileUpdate2, FileStatus } from "@/api/file";
import "@/assets/common.css";
let api = window.api;
export default {
  name: "App",
  data() {
    return {
      showUploadList: true,
      fordata: {
        conversionMode: "blocks",
        dpi: 144,
        imageQuality: 85,
        outputFileType: "docx",
        files: [],
      },
      files: [],
      jobId: "",
      timer: "",
      loading: "",
    };
  },
  methods: {
    //上传前判断
    removeFile(_, filelist) {
      
      var files = [];
      for (const file of filelist) {
        files.push(file.raw);
      }
      this.files = files;
    },
    handleChange(file) {
      this.files.push(file.raw);
    },

    async UploadFile() {
      if (this.files.length == 0) {
        return this.$message.warning("文件不能为空!!!");
      }
      this.loading = this.$loading({
        lock: true,
        text: "正在进行转换.......",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.7)",
      });
      var files = [];
      for (const file of this.files) {
        let formData = new FormData();
        formData.append("file", file);
        var fileInfo = await FileUpdate(formData);
        files.push(fileInfo[0]);
      }
      this.fordata.files = files;
      var res = await FileUpdate2(this.fordata);
      this.jobId = res.jobId;
      this.timer = setInterval(() => {
        FileStatus({
          action: "getStatus",
          jobId: this.jobId,
        }).then((res) => {
          if (res.status == "done") {
            this.loading.close();
            this.$message.success("文件转换完成!!!!");
            var downloadURL =
              "https://filetools13.pdf24.org/client.php?mode=download&action=downloadJobResult&jobId=" +
              this.jobId;
            api.Download(downloadURL);
            clearInterval(this.timer);
          }
        });
      }, 2000);
    },
    ChangeMethod(outputFileType) {
      this.fordata.outputFileType = outputFileType;
    },
  },
  destroyed() {
    clearInterval(this.timer);
  },
};
</script>

这些基本能实现前面的需求,代码基本简单,api那一块代码可以不要看太多,因为这里作者也不想说,这个api的逻辑需要这么复杂,读者主要看页面设计即可
同理
其他文件转pdf,我也直接附上代码

<!--
 * @Description: 
 * @Version: 1.0
 * @Autor: solid
 * @Date: 2022-10-21 17:19:33
 * @LastEditors: solid
 * @LastEditTime: 2022-10-26 14:24:04
-->
<template>
  <div >
    <div style="">
      <div style="box-sizing: border-box;">
        <el-upload
          action="#"
          :auto-upload="false"
          :on-change="handleChange"
          :on-remove="removeFile"
          list-type="picture"
          drag
          multiple
        >
          <div v-if="files.length == 0">
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">拖拽文件到这</div>
          </div>
        </el-upload>
      </div>
      <div style="position: absolute; bottom: 0px">
        <el-button
          type="primary"
          style="width: 500px; height: 10vh; font-size: 2em"
          @click="UploadFile"
          >转换成PDF</el-button
        >
      </div>
    </div>
  </div>
</template>

<script>
import { FileUpdate, Other2PDF, FileStatus } from "@/api/file";
let api = window.api;
export default {
  name: "App",
  data() {
    return {
      showUploadList: true,
      fordata: {
        files: [],
      },
      files: [],
      jobId: "",
      timer: "",
      loading: "",
    };
  },
  methods: {
    //上传前判断
    removeFile(_, filelist) {
      var files = [];
      for (const file of filelist) {
        files.push(file.raw);
      }
      this.files = files;
    },
    handleChange(file) {
      console.log(123123);
      this.files.push(file.raw);
    },

    async UploadFile() {
      if (this.files.length == 0) {
        return this.$message.warning("文件不能为空!!!");
      }
      this.loading = this.$loading({
        lock: true,
        text: "正在进行转换.......",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.7)",
      });
      var files = [];
      for (const file of this.files) {
        let formData = new FormData();
        formData.append("file", file);
        var fileInfo = await FileUpdate(formData);
        files.push(fileInfo[0]);
      }
      this.fordata.files = files;
      var res = await Other2PDF(this.fordata);
      this.jobId = res.jobId;
      this.timer = setInterval(() => {
        FileStatus({
          action: "getStatus",
          jobId: this.jobId,
        }).then((res) => {
          if (res.status == "done") {
            this.loading.close();
            this.$message.success("文件转换完成!!!!");
            clearInterval(this.timer);
            var downloadURL =
              "https://filetools13.pdf24.org/client.php?mode=download&action=downloadJobResult&jobId=" +
              this.jobId;
            api.Download(downloadURL);
            
          }
        });
      }, 2000);
    },
  },
  destroyed() {
    clearInterval(this.timer);
  },
};
</script>


APP.vue也需要随着进行修改

image.png

效果图

image.png

最后一步

打包vue成单文件

yarn build

核心点

上面都是然后教你实现页面展示,但是更多值得学习的无疑就是如何调用utools的api以及如何在utools中使用nodejs并实现文件下载到本地

调用utools的api

如果看过我上一篇文章的读者可能就很快知道如何调用utools的api,这里也不废话多说,如果我们想调用utools的api的话则需要现在plugin.json配置perload,并在其指定文件下写相关代码

image.png

关于plugin.json相关配置,可以直接看我相关文章,里面都有详细介绍,也可以直接去utools官网进行查看
.当我们配置好,就可以在perload.js文件写相关逻辑代码

  // Download the file
    https.get(fileUrl, (res) => {
        var filename,
            contentDisp = res.headers['content-disposition'];
        if (contentDisp && /^attachment/i.test(contentDisp)) {
            filename = contentDisp.toLowerCase()
                .split('filename=')[1]
                .split(';')[0]
                .replace(/"/g, '');
        } else {
            filename = path.basename(url.parse(fileUrl).path);
        }
        var filePath = utools.getPath('desktop') + "\\" + filename
        const file = fs.createWriteStream(filePath);
        res.pipe(file);
        // Close the file
        file.on('finish', () => {
            file.close();
            console.log(`File downloaded!`);
        });
    }).on("error", (err) => {
        console.log("Error: ", err.message);
    });

这段代码主要是用于根据前端传入url进行下载文件,其中utools.getPath(“desktop”) 就是调用utools的api,获取桌面路径
这里会有一个问题,就是如何index.html中调用perload.js,比较简单的思想就是定义全局变量或者全局对象即可

const fs = require('fs');
const https = require('https');
const path = require('path')
const url = require('url')
window.Download = function (fileUrl) {
    // Download the file
    https.get(fileUrl, (res) => {
        var filename,
            contentDisp = res.headers['content-disposition'];
        if (contentDisp && /^attachment/i.test(contentDisp)) {
            filename = contentDisp.toLowerCase()
                .split('filename=')[1]
                .split(';')[0]
                .replace(/"/g, '');
        } else {
            filename = path.basename(url.parse(fileUrl).path);
        }
        var filePath = utools.getPath('desktop') + "\\" + filename
        const file = fs.createWriteStream(filePath);
        res.pipe(file);
        // Close the file
        file.on('finish', () => {
            file.close();
            console.log(`File downloaded!`);
        });
    }).on("error", (err) => {
        console.log("Error: ", err.message);
    });
}
window.api = {
    Download,
}

我们只要在index.html中调用window.api.Download即可调用下载功能

github地址

OblivionTime/conversionTool

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容