正在进入ing...

使用Vue+ElementUI撸了一个自用图片存储空间

发布时间:2020-12-31 浏览量: 419 文章分类: 前端相关

其实先想想,自己想使用的图床需求是什么? 对于我来说简单的就是下面几个需求吧 + 存储照片 + 查看已存储的照片 + 删除存储的照片 + 分享照片链接 + 存储的空间大小展示

基于上面的几个需求,我使用了Vue+ElementUi写了一个简单的页面完成。后端我使用的是自己基于DRF扩展的一套身份验证分离接口。图片会实时保存到我的服务器上,同时在二次确认删除后,图片也会从服务器上删除,不会占用空间。

先看看最终的效果图

使用Vue+ElementUI撸了一个自用图片存储空间

至于页面布局那些我就不说了,这个可以根据自己的需求来随意调整样式。 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;
        }

在引入messageconfirm两个组件的时候,并不是直接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
        },

当然这个也只是我使用的第一个版本,以后具体怎么调整,在根据我实际使用的情况逐步在改吧。