使用Vue+ElementUI撸了一个自用图片存储空间
其实先想想,自己想使用的图床需求是什么? 对于我来说简单的就是下面几个需求吧 + 存储照片 + 查看已存储的照片 + 删除存储的照片 + 分享照片链接 + 存储的空间大小展示
基于上面的几个需求,我使用了Vue
+ElementUi
写了一个简单的页面完成。后端我使用的是自己基于DRF
扩展的一套身份验证分离接口。图片会实时保存到我的服务器上,同时在二次确认删除后,图片也会从服务器上删除,不会占用空间。
先看看最终的效果图
至于页面布局那些我就不说了,这个可以根据自己的需求来随意调整样式。
Element
我是按需导入的,主要用到的组件有upload 上传文件组件
、progress 进度条展示
、image 图片
、button 按钮
、message 消息通知
、confirm 弹出确认
- 数据的获取 请求方式:GET 获取对应的页面数据,服务端会计算整体存储空间的占比然后前端,数据格式如下
{
"data": {
"img_list": [{
"id": 70,
"src": "2020_12_31_1_1609396959_1312.png"
}, {
"id": 68,
"src": "2020_12_31_1_1609396955_17838.png"
}],
"proportion": 35.67
},
"meta": {
"status_code": 20000,
"msg": "获取成功"
}
}
meta
中存储的主要就是状态码,通知等
data
中存储的就是对应的数据,proportion
就是百分比占比、img_list
就是图片列表
然后在确认状态码正确等,将数据处理赋值就行了。这里我是在methods
写了函数,同时也在created
中调用,也就是页面一打开自动就会请求。
- 新图片上传
<el-upload
drag
:before-upload="beforeUpload"
action=""
multiple
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">
将文件拖到此处,或<em>点击上传</em>
</div>
<div class="el-upload__tip" slot="tip">
只能上传jpg/png文件,且不超过500kb
</div>
</el-upload>
这个没什么好说的,基本就是官方的demo
仍上来了。要注意的是上传这里,我改了action
方法为:before-upload
方法,因为:before-upload
可以自定义函数,在上传的时候因为我还需要根据jwt
验证身份,所以直接使用action
貌似不是很容易做到(我在网上没找到很好的解决方法)。
上传函数大致如下
async beforeUpload(file) {
let fd = new FormData();
const fileName = file["uid"] + file.name;
fd.append("key", file, fileName);
const { data: res } = await this.$http.post("upload-image/", fd);
if (res.meta.status_code == 40001) {
// 存储空间已满
return this.$message.error(res.meta.msg);
} else if (res.meta.status_code != 20000) {
return this.$message.error("上传出现异常,请重新尝试");
}
// 上传图片成功,将对应的图片信息展示到页面上
this.urls.unshift(res.data);
this.proportion = res.proportion;
this.$message.success("上传成功");
这里后端要注意一下,可以封装
一下计算占比函数,和异步存写图片
,然后调用这样速度快很多。在GET
请求的时候图片的大小就传0,在POST
请求的时候就传新的图片大小,这样计算就是准确的。
-
前端渲染 其实这个没什么好说的,就是
v-for
循环渲染获取到的列表,然后对立面的图片展示,展示的时候下面顺带增加2个按钮,一个是复制地址
、一个是删除图片
-
删除图片 点击的时候 触发删除函数,把图片的名字同时传过去
<el-button
type="danger"
icon="el-icon-delete"
circle
@click="deleteImgDiaLog(url.src)"
></el-button>
async deleteImgDiaLog(imgName) {
// 确认删除图片弹出窗
this.deleteDialogVisible = true;
const confirmResult = await this.$confirm(
"此操作将永久删除该图片,且无法恢复。是否继续?",
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
).catch((err) => err);
// 如果用户确认删除,则返回值为字符串confirm
// 如果用户取消删除,则返回值为字符串 cancel
if (confirmResult !== "confirm") {
return this.$message.info("已取消删除");
}
const { data: res } = await this.$http.delete("upload-image/", {
data: { name: imgName },
});
if (res.meta.status_code != 20000) {
this.$message.error(res.meta.msg);
} else {
this.$message.success(res.meta.msg);
}
this.getPageInfo();
},
deleteDialogClose() {
// 删除图片的对话框关闭逻辑
this.deleteDialogVisible = false;
}
在引入message
、confirm
两个组件的时候,并不是直接Vue.use
注册的,我直接挂载到了Vue.prototupe
上
Vue.prototype.$message = Message // 全局挂载
Vue.prototype.$confirm = MessageBox.confirm
还有就是二次确认,这个只要看看页面提示就好了。貌似也没什么好说的。
- 复制图片地址
这个功能其实我是完全不知道怎么做的,但是别的网站,有时候复制要么还能在尾巴追加一大堆文字,要么就是不允许复制什么的。网上查询了很久,要么就是要用一个别的库实现(兼容性好),要么就用原生
javascript
实现(兼容性一般),不过反正我是自己用,chrome
支持就可以了。果然用原生 实现的思路就是,点击复制按钮的时候,触发函数,函数在页面上生成一个input
标签,然后选中这个标签,将标签的内容复制到粘贴板上,然后在销毁了这个标签。
copyImgLink(imgUrl) {
// 点击复制图片按钮,将对应的图片url复制到剪贴板上
const input = document.createElement('input')
document.body.appendChild(input)
input.setAttribute('value',imgUrl)
input.select()
const copyResult = document.execCommand('copy')
if (copyResult){
this.$message.success('复制成功')
} else {
this.$message.error('复制失败')
}
// 销毁标签
document.body.removeChild(input)
return
},
当然这个也只是我使用的第一个版本,以后具体怎么调整,在根据我实际使用的情况逐步在改吧。