开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第四天
小白如何制作出属于自己的utools插件(实战篇) 第二篇
如何将vue项目做成utools插件
实现一个简单的pdf转换成word,ppt,excel的插件
我们要实现这样的页面
初始化vue项目
vue create pdf_office
如何选择vue2,然后一直点击回车即可,创建完后,读者可以调用一下目录来判断是否创建成功
cd pdf_office
yarn serve
进入网址后,查看是否呈现如下图所示,如果出现则代表创建成功
项目目录介绍
Menu.vue
主要展示的是菜单一栏
Other_PDF.vue
主要是其他文件转pdf的页面,该页面主要实现的功能如下
- 支持拖拽
- 支持多文件同时转换成pdf
- 将转换成功的文件保存在桌面上
PDF-Other.vue
主要是pdf转其他文件(word,ppt,excel)的页面,该页面主要实现的功能如下
- 支持拖拽
- 支持多个pdf文件同时转换成其他文件
- 将转换成功的文件保存在桌面上
request.js
对axios进行封装,其中加入了接口所需的token
App.vue
主页面,当前项目目前只需要一个页面,不需要多个页面
main.js
入口函数,初始化所有配置
项目介绍
该项目主要制作一个pdf转常见文档和其他文件转pdf的utools小插件,适合用于vue如何变成utools小插件
项目开始
第一步 下载依赖
首先无疑是先需要将整个项目所需要的依赖进行下载
当前项目需要以下依赖
因为为了快速开发,所以我们需要用到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')
第三步 制作菜单
制作一个这样的菜单无疑对于资深的前端肯定比较简单,但是对我比较菜的我,只能运用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 必然也要有一些代码
注意:这里可能会涉及到没有找到图片的提示,在文章末尾我会提供github地址,读者可以将源码下来了进行参考
第四步 实现pdf转其他文件
实现这个当然要先搭建页面,无疑我们先看看需求是什么?
- 支持拖拽
- 支持多个pdf文件同时转换成其他文件
- 将转换成功的文件保存在桌面上
首先我们在elementui中先找到如何支持文件上传并支持拖拽
下面就是我当时想到的代码
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也需要随着进行修改
效果图
最后一步
打包vue成单文件
yarn build
核心点
上面都是然后教你实现页面展示,但是更多值得学习的无疑就是如何调用utools的api以及如何在utools中使用nodejs并实现文件下载到本地
调用utools的api
如果看过我上一篇文章的读者可能就很快知道如何调用utools的api,这里也不废话多说,如果我们想调用utools的api的话则需要现在plugin.json配置perload,并在其指定文件下写相关代码
关于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即可调用下载功能
暂无评论内容