需求背景
甲方用户设备保修,乙方员工根据设备维护需要,在维护完成之后,在 Excel 维修任务文件上对检查维修的项目进行打勾,最后在下面输入一些备注信息。
调研
- 研究了 XLSX 等其他库,均不能完全实现需求,或是 API 太难用,或是样式显示有问题,Excel 文件中有图片,显示不全等等。最后在 Univer 和 LuckySheet 上研究。
- Univer 文档并不是很全面(是我太菜了,看不懂😭),怎么将数据导入到 Univer 中,在 UI 上显示。都不是很好实现,看文档,需要借助他们的后端服务等等,最后没能实现。相关 discussion:https://github.com/dream-num/univer/discussions/3425 。结论问题并没有解决,因为我换了 LuckySheet。🤣
- LuckySheet 是Univer 的前身,不同的是 Univer 支持 Word Excel PPT 三种,前者只支持一种。完全实现了我的需求。
实操
我的解决方案是:在后端将 Excel 模板文件传给前端,前端作展示和编辑、。之后乙方维护人员完成 Excel 文件编辑。再传给后端和工单进行绑定。
初始化项目
我使用的是 Vue3 + Vite + LuckySheet。
准备 LuckySheet
参考:https://blog.csdn.net/m0_59415345/article/details/136749058
在项目中 引入 LuckySheet 有两种方式:
通过 CDN 引入
直接在项目的 index.html
文件中引入 CDN 配置即可
1 2 3 4 5 6
| <link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/css/pluginsCss.css' /> <link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/plugins.css' /> <link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/css/luckysheet.css' /> <link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/assets/iconfont/iconfont.css' /> <script src="https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/js/plugin.js"></script> <script src="https://cdn.jsdelivr.net/npm/luckysheet/dist/luckysheet.umd.js"></script>
|
本地打包之后引入
本地引入是将 CDN 需要的文件在本地打包之后在引入,避免网络请求。
拉取代码
1
| git clone https://github.com/dream-num/Luckysheet.git
|
构建
1 2 3
| # 按照依赖 npm install npm install gulp -g
|
启动预览
可以在浏览器中看到如下页面:
打包
之后将 dist 中的文件全部复制到项目的 public 文件中,可以根据需要复制到不同位置,在引入时,注意路径即可。不需要引入 index.html
。
项目使用
这部分 CDN 引入和本地引入区别不大。只需要注意路径即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/css/pluginsCss.css' /> <link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/plugins.css' /> <link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/css/luckysheet.css' /> <link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/assets/iconfont/iconfont.css' /> <script src="https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/js/plugin.js"></script> <script src="https://cdn.jsdelivr.net/npm/luckysheet/dist/luckysheet.umd.js"></script>
<link rel='stylesheet' href='./public/plugins/css/pluginsCss.css' /> <link rel='stylesheet' href='./public/plugins/plugins.css' /> <link rel='stylesheet' href='./public/css/luckysheet.css' /> <link rel='stylesheet' href='./public/assets/iconfont/iconfont.css' /> <script src="./public/plugins/js/plugin.js"></script> <script src="./public/luckysheet.umd.js"></script>
|
项目页面
在初始化好的 Vite 项目中 App.vue 中写入如下代码:
注意需要安装 luckysheet
。不然会报错!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
| <template> <div class="upload"> <input id="uploadBtn" type="file" @change="loadExcel" /> </div> <div id="luckysheet" class="luckysheet"></div> </template>
<script lang="ts" setup> import { onMounted } from "vue" import LuckyExcel from 'luckyexcel' import axios from 'axios';
onMounted(() => { //如果这里luckysheet.create报错 //请使用 window.luckysheet.create luckysheet.create({ container: 'luckysheet'//这里需要和容器的id名称一致 })
// 从后端接口获取 excel 文件使用 loadExcel() })
// 按钮上传使用,注意区分 // const loadExcel = (evt) => { // const files = evt.target.files // if (files == null || files.length == 0) { // alert('请上传文件') // return // }
// let name = files[0].name // let suffixArr = name.split('.'), // suffix = suffixArr[suffixArr.length - 1] // if (suffix != 'xlsx' && suffix != "xls") { // alert('只能导入xlsx文件格式的Excel') // return // } // LuckyExcel.transformExcelToLucky(files[0], function (exportJson, luckysheetfile) { // if (exportJson.sheets == null || exportJson.sheets.length == 0) { // alert('导入失败!') // return // } // window.luckysheet.destroy() // window.luckysheet.create({ // container: 'luckysheet', //容器的Id // showinfobar: false, // data: exportJson.sheets, // title: exportJson.info.name, // userInfo: exportJson.info.name.creator // }) // }) // }
const loadExcel = async () => { // 发送 POST 请求到后端以获取 Excel 文件 try { // 接口地址 const response = await axios.post('http://localhost:8080/api/v1/download/task', { // taskId: '922364778947073' taskId: '822364778947073' // taskId: '722364778947073' // taskId: '622364778947073' }, { headers: { 'Content-Type': "application/json" }, responseType: 'blob' } );
// 将响应转换为 Blob // const blob = await response.blob();
// 将 ArrayBuffer 转换为 Blob const blob = new Blob([response.data])
const file = new File([blob], 'downloaded_file.xlsx', { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', });
console.log(file);
// // 创建一个临时的 URL // const url = URL.createObjectURL(file);
// // 创建一个链接元素 // const a = document.createElement('a'); // a.href = url; // a.download = file.name; // 设置下载文件名
// // 触发下载 // document.body.appendChild(a); // a.click();
// // 清理 // document.body.removeChild(a); // URL.revokeObjectURL(url); // 释放内存
LuckyExcel.transformExcelToLucky(file, function (exportJson, luckysheetfile) { if (exportJson.sheets == null || exportJson.sheets.length == 0) { alert('1221332, 导入失败!'); return; } window.luckysheet.destroy(); window.luckysheet.create({ container: 'luckysheet', // 容器的Id showinfobar: false, data: exportJson.sheets, title: exportJson.info.name, userInfo: exportJson.info.name.creator, }); });
} catch (error) { alert(`导入失败: ${error.message}`); } }
</script>
<style scoped> .luckysheet { margin: 0; padding: 0; position: absolute; width: 100%; height: 100%; left: 0; top: 30px; /* 调整此值以向下移动 */ }
.upload { position: absolute; left: 0; top: 0; z-index: 10; /* 确保按钮在最上层 */ background-color: white; /* 可选 */ border: 1px solid #ccc; /* 可选 */ padding: 5px; /* 可选 */ } </style>
|
注意上述代码的区别,一个 LoadExcel 方法是上传使用,有参数。另外一个是 onMounted 使用,没有参数。如果从后端传递,注意修改接口地址。
运行
最终效果如下:
仓库
相关代码和依赖已经放到:https://github.com/yuluo-yx/deigmata-paideias/tree/main/vue3-vite-lucksheet 中。