上一篇博客里写的elemntui删除图片,没有考虑到用户删除页面图片后并没有保存的骚操作,导致页面上的图片被清空了、存储图片文件夹里的图片被删除了,但是数据表里的图片地址并没有被删除。
因为用户只是点击了删除图片,但是并没有保存,所以我们要考虑用户是误操作的可能。总之,只要用户在删除图片后没有点击保存按钮,我们就不能让他把图片删除。
我考虑过手动上传、或者添加事务,很可惜这方面我还没学会,所以只能采用一些较为基本的方法和逻辑去实现它。其实并不复杂。
HTML代码
<div class="layui-upload">
<div class="layui-form-item">
<label class="layui-form-label">轮播图</label>
<div class="layui-input-block" style="width: 100%;">
<div id="app">
<el-upload action="__APP__/Manager/upload_images" list-type="picture-card" :auto-upload="true"
:on-success="handleAvatarSuccess" :before-upload="beforeUpload" :limit="1"
:on-error="uploadError" ref="upload" :on-remove="handleRemove" :key="clearThumbnail"
accept="image/jpeg,image/jpg,image/png">
<i slot="default" class="el-icon-plus"></i>
<div slot="file" slot-scope="{file}">
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="">
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
<i class="el-icon-zoom-in"></i>
</span>
<span v-if="!disabled" class="el-upload-list__item-delete"
@click="handleRemove(file)">
<i class="el-icon-delete"></i>
</span>
</span>
</div>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="image_url" alt="">
</el-dialog>
</div>
</div>
</div>
</div>
JavaScript代码
<script>
function edit(data) {
var controls = 0;//监测用户是否点击了删除缩略图按钮,0表示没有点击
var id = data.id;
var sequence = data.sequence;
var srcurl = data.imageurl;
var imageurl = srcurl.match(/src="([^"]+)"/)[1];
var categoryid = data.categoryid;
var categoryname = data.categoryname;
var organizeid = data.organizeid;
var organizename = data.organizename;
var enable = data.enable;
var description = data.description;
var image_url = "";//传入后端的图片地址
const regex = /src="(.*?)"/;
var imageurl = regex.exec(data.imageurl)[1];//用于图片回显在页面的图片地址
var isDelete = false;//判断是否删除图片
$('#upload').val(description);
$('#sequence').val(sequence);
layui.use(['upload', 'form', 'layer'], function () {
var upload = layui.upload;
var form = layui.form;
$ = layui.jquery;
var layer = layui.layer;
//上传图片
new Vue({
el: '#app',
data() {
return {
control: true,//控制器
image_url: '', //存储对话框中展示的图片链接地址
dialogVisible: false, //控制对话框是否显示
disabled: false, //控制按钮是否禁用
fileList: [],//存放上传时多个图片
clearThumbnail: false,//清空图片
};
},
mounted() {
if (imageurl) {
this.fileList.push(imageurl);//存入数据库已经存在的缩略图
// 将图片地址赋值给 file_list 属性
this.$nextTick(() => {
this.$refs.upload.fileList = [{ url: imageurl }];
});
console.log(imageurl)
} else {
return false;
}
console.log(JSON.stringify(this.fileList))
},
methods: {
// 上传文件之前
beforeUpload(file) {
//文件大小校验
if (file.size > 10 * 1024 * 1024) {
this.$message('文件过大,请上传小于10MB的文件〜')
return false
}
this.control = true;
isDelete = false;
return true
},
//上传成功
handleAvatarSuccess(response, file, fileList) {
console.log('上传成功的文件信息:', response, file, fileList);
image_url = response.data.src;
this.fileList.push(image_url);
description = response.data.description;
},
//上传失败
uploadError(err, file, fileList) {
this.$message({
type: 'warning',
message: '上传失败'
})
},
//输出被删除的文件信息
handleRemove(file) {
console.log("执行了删除操作:" + this.fileList[0]);
let _this = this;
url = this.fileList[0];
//清空页面上的图片,文件夹里的图片并没有被删除
$.post('__APP__/Manager/remove_image', { image_url: url }, function (res) {
_this.clearThumbnail = true;
_this.control = false;
isDelete = true;
}, 'json');
this.clearThumbnail = false;
},
//对应图片的链接地址存储到到image_url,预览图片
handlePictureCardPreview(file) {
this.image_url = this.fileList[0];
//this.image_url = file.url;
console.log(this.fileList[0])
if (this.control != false) {
this.dialogVisible = true;
}
},
}
});
form.on('submit(save)', function (data) {
var category = $('#category').val();//行业名
var organize = $('#organize').val();//组织名称
var sequence = $('#sequence').val();
var enable = 1;//是否可用,默认可用
var picture = image_url;//图片地址
var desc = description;//图片描述信息
var picture = "";
if (!sequence) {
sequence = 1;
}
if (!image_url) {
if (imageurl) {
var picture = imageurl;//图片回显的地址
}
} else {
var picture = image_url;//上传图片的地址
}
if (picture && isDelete) {
//删除文件夹里的图片
$.post('__APP__/Manager/remove_image', { image_url: picture, isDelete: isDelete }, function (res) {
if(res != 1){
return false;// 阻止表单提交
}
}, 'json');
picture = "";
}
if (!picture) {
layer.msg('轮播图不能为空', { icon: 5, time: 1000 });
return false; // 阻止表单提交
} else {
$.post('__URL__/edit_info_banner', {
id: id,
desc: desc,
sequence: sequence,
category: category,
organize: organize,
enable: enable,
picture: picture
}, function (res) {
if (res == 1) {
layer.msg('轮播图修改成功', { icon: 6, time: 1000 }, function () {
window.parent.layer.close(window.parent.layer.getFrameIndex(window.name));
window.parent.location.reload(); // 刷新父窗口页面
})
} else {
layer.msg('网络开小差啦,请重试', { icon: 5, time: 2000 }, function () {
return false;
})
}
}, 'json');
}
return false;
});
});
}
</script>
后端PHP代码(删除图片方法)
//删除图片
function remove_image(){
$isDelete = $_POST['isDelete'];//判断文件是否执行删除操作,false不执行删除,true执行删除
$url = $_POST['image_url'];
$picture = $_POST['picture'];
$content = $_POST['content'];
$pictures = $_POST['pictures'];
$contents = $_POST['contents'];
$pattern = '/<img.*?src=[\'"](.*?[\.jpg|\.jpeg|\.png])[\'"].*?>/i';
// 先定义一个函数来删除文件
function delete_file($file_path)
{
$res = 0;
if (file_exists($file_path)) {
if (unlink($file_path)) {
//文件删除成功
$res = 1;
} else {
//文件删除失败
$res = 0;
}
} else {
//文件不存在
$res = -1;
}
echo $res;
exit;
}
// 保存前删除图片
if (!empty($url)) {
$file_path = $_SERVER['DOCUMENT_ROOT'] . $url;
if($isDelete){
delete_file($file_path);
}else{
$res = 1;
echo $res;
}
}
}
我的逻辑是,在script方法的一开始,设置一个监测用户是否点击删除按钮的变量isDelete,赋初值为false。当用户点击删除图片按钮,该变量的值改编成true。
用户点击保存按钮的时候,表单监听器判断isDelete,如果是true,就把图片地址和isDelete扔给后台的删除图片方法;如果是false,就不执行任何操作。
后台删除图片方法也需要判断isDelete的值,true就执行删除操作,false不执行删除操作。
为啥让后台也需要判断isDelete呢?因为我在前端清空页面上的图片时,同样需要访问后台删除图片的方法,获得一个返回值来执行清空图片的操作。所以,为了防止【我只是清空页面上的图片,你就给我把文件夹里的图片删掉了?】这种乌龙的发生,就需要判断isDelete的值。
也许有更简便的方法,只是我暂时没有想到。
完结撒花。