因为实际的需求,使用vue的input组件,设置type=“file”,进行实现文件上传,并进行图片的预览,点击图片可进行删除操作
因为input组件原本的自身样式并没有办法与我设计图温和,所以在进行对input组件的宽高等处理后,通过定位的方式,将input组件至于最上层,并且设置opacity:0;达成最终的ui效果(具体的实现效果如下图)
(vue)页面布局
<div class='apply-reason'>
<div class='reason-box'>
<div class='apply-reason-title'>问题描述</div>
<div class='right'>
<img :src='ossAddr("/img/mine/camera.png")'>
<span>添加图片</span>
<input class="img-upload" @change='chooseImg' type="file">
</div>
</div>
<div class='textarea-box'>
<textarea v-model='content' maxlength='500' placeholder-class='textarea--placehoder' placeholder='请填写具体内容,帮助我们了解你的建议。'></textarea>
</div>
<template v-if="imgList.length!=0">
<div class='show-img flex'>
<div v-for="(item, index) in imgList" :key="index">
<div class='img'>
<span @click='deleteImage(index)' v-if="showDelete">X</span>
<img :src='item' @click='showDeleteBtn'>
</div>
</div>
</div>
</template>
</div>
(vue)页面样式
/* 申诉理由 */
.apply-reason{
/* height: 346px; */
padding: 26px 30px 0;
background: #fff;
margin-bottom: 20px;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.apply-reason-2{
height: 194px;
padding-bottom: 0;
}
.apply-reason-title{
font-size: 30px;/*px*/
color: #17181A;
/* padding-bottom: 27px; */
}
.textarea-box{
flex: 1;
position: relative;
padding-top: 30px;
}
.apply-reason>input{
min-height: 96px;
font-size: 28px;/*px*/
border: none;
outline: none;
flex: 1;
}
.textarea-box textarea{
height: 180px;
width: 100%;
font-size: 32px;/*px*/
color: #1A1717;
outline: none;
border: none;
line-height: 44px;
}
/* textarea placeholder样式*/
input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{
font-size: 28px;/*px*/
color: #BDC1C7;
}
input:-moz-placeholder,textarea:-moz-placeholder{
font-size: 28px;/*px*/
color: #BDC1C7;
}
input::-moz-placeholder,textarea::-moz-placeholder{
font-size: 28px;/*px*/
color: #BDC1C7;
}
input:-ms-input-placeholder,textarea:-ms-input-placeholder{
font-size: 28px;/*px*/
color: #BDC1C7;
}
.textarea-box span{
position: absolute;
bottom: 0;
right: 0;
font-size: 24px;/*px*/
color: #BDC1C7;
}
/* 图片上传 */
.right,
.reason-box{
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 28px;
border-bottom: 2px solid rgba(0, 0, 0, 0.08);
}
.right{
width: 168px;
border: none;
padding: 0;
position: relative;
}
.right img{
width: 38px;
margin-right: 10px;
max-height: 28px;
}
.right span{
font-size: 28px;/*px*/
color: #797C80;
}
.img-upload{
width: 100%;
height: 100%;
background: #fff;
position: absolute;
top: 0;
left: 0;
opacity: 0;
z-index: 19;
display: flex;
justify-content: center;
align-items: center;
}
/* 展示图片 */
.show-img{
justify-content: flex-start;
display: flex;
align-items: center;
height: 130px;
width: 100%;
border-top: 1px solid #eee;
padding: 20px 0;
}
.show-img .img{
width: 100px;
height: 100px;
border: 1px dotted #ddd;
border-radius: 10px;
margin-right: 20px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.show-img .img img{
max-width: 100%;
max-height: 100%;
}
.show-img .img span{
position: absolute;
top: -10px;
right: -10px;
z-index: 3;
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
border-radius: 50%;
background-color: red;
color: #fff;
font-size: 20px;/*px*/
overflow: hidden;
}
主要的业务逻辑代码
data () {
return {
imgList:[],
imgData: {
accept: 'image/gif, image/jpeg, image/png, image/jpg',
},
bean: {
type: '需求',
content: '',
contacts:'',//联系方式
},
content: '',
showDelete:false,
}
},
methods:{
// 点击删除图片
deleteImage(data){
const me = this;
me.imgList.splice(data,1),//传入图片的index,单击哪张,边删除哪张
},
// 点击显示删除符号
showDeleteBtn(){
this.showDelete = true;//初始showDelete 为false,点击时进行展示
},
chooseType(type){
this.bean.type = type
},
// 选择上传图片
chooseImg(event){
let me = this;
if (me.imgList.length<3){
me.uploadImg(event,(data)=>{
me.imgList.push(data);
})
} else {//可进行最多可上传3张图片的提示
return
}
},
//实现上传的真正函数
uploadImg(event,callBack){
let me = this;
let reader = new FileReader();
if(event.target.files[0]&&event.target.files[0]!=''){
var img1 = event.target.files[0];
}
let type = img1.type;
let size = img1.size;
if(me.imgData.accept.indexOf(type) == -1 || size>3145728){
// 提示选择符合规定的图片格式
return false;
}
// if(size>3145728){
// // 提示选择符合规定的图片格式
// return false;
// }
var uri = '';
let form = new FormData();
form.append('file',img1,img1.name)
this.$axios.post('/api/user/file/uploadImage.json',form,{
headers:{'Content-Type':'multipart/form-data'}
}).then(response=>{
uri = response.data.data.fullPath
reader.readAsDataURL(img1);
reader.onloadend=function(){
if(callBack){
callBack(uri)
}
}
})
},
// 提交
submit(){
let me = this;
me.contentFun();
api.userFeedbackUrl(me.bean).then(response => {
me.common.axiosSuccessFun({
this: me,
callBack(res){
// 提交成功会有一个弹窗提示,点击确定回到首页
}
}, response.data)
}).catch((res)=>{
me.common.axiosFailFun({
this: me
}, res)
})
},
// 处理图片路径的函数,通常在将内容上传给后台的时候,会进行一些内容的处理
contentFun(){
let str = '';
let imgList = this.imgList;
imgList.forEach(function (val) {
str += '<img src="' + val + '"/>';
})
let content = this.content + str;
this.bean.content = content;
},
}
基于微信小程序的上传图片实现预览,长按显示删除按钮,进行图片的删除,ui实现与上图一致
页面搭建,bindlongtap:长按触发
<view class='apply-reason'>
<view class='reason-box'>
<view class='apply-reason-title'>问题描述</view>
<view class='right' bindtap='chooseImg'>
<!-- mode='widthFix' -->
<image mode='aspectFill' src=''></image>
<text>添加图片</text>
</view>
</view>
<view class='textarea-box'>
<textarea bindinput='getContent' maxlength='500' placeholder-class='textarea--placehoder' placeholder='请填写具体内容,帮助我们了解你的建议。'></textarea>
</view>
<block wx:if="{{imgList.length!=0}}">
<view class='show-image flex'>
<block wx:for="{{imgList}}" wx:key="{{index}}">
<view class='image'>
<text bindtap='deleteImage' data-index='{{index}}' wx:if="{{showDelete}}">X</text>
<image mode='aspectFit' src='{{item}}' bindlongtap='showDeleteBtn'></image>
</view>
</block>
</view>
</block>
</view>
页面样式实现
/* 申诉理由 */
.apply-reason{
width: 100%;
/* height: 346rpx; */
padding: 27rpx 30rpx 14rpx;
background: #fff;
margin-bottom: 20rpx;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.apply-reason-title{
font-size: 30rpx;
color: #17181A;
/* padding-bottom: 27rpx; */
}
.textarea-box{
flex: 1;
position: relative;
padding-top: 30rpx;
}
.apply-reason input{
min-height: 96rpx;
font-size: 28rpx;
flex: 1;
}
.textarea-box textarea{
height: 180rpx;
width: 100%;
font-size: 32rpx;
color: #1A1717;
line-height: 44rpx;
}
.textarea--placehoder{
font-size: 28rpx;
color: #BDC1C7;
}
.textarea-box text{
position: absolute;
bottom: 0;
right: 0;
font-size: 24rpx;
color: #BDC1C7;
}
/* 图片上传 */
.right,
.reason-box{
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 28rpx;
border-bottom: 2rpx solid rgba(0, 0, 0, 0.08);
}
.right{
border: none;
padding: 0;
}
.right image{
width: 38rpx;
margin-right: 10rpx;
max-height: 28rpx;
}
.right text{
font-size: 28rpx;
color: #797C80;
}
/* 展示图片 */
.show-image{
justify-content: flex-start;
display: flex;
align-items: center;
height: 130rpx;
width: 100%;
border-top: 1px solid #eee;
padding: 20rpx 0;
}
.show-image .image{
width: 100rpx;
height: 100rpx;
border: 1px dotted #ddd;
border-radius: 10rpx;
margin-right: 20rpx;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.show-image .image image{
max-width: 100%;
max-height: 100%;
}
.show-image .image text{
position: absolute;
top: -10rpx;
right: -10rpx;
z-index: 3;
width: 30rpx;
height: 30rpx;
text-align: center;
line-height: 30rpx;
border-radius: 50%;
background-color: red;
color: #fff;
font-size: 20rpx;
overflow: hidden;
}
业务逻辑代码
import api from '../../../../config/api.js';
const app = getApp();
Page({
data: {
imgList:[],
bean: {
type: '需求',
content: ''
},
content: ''
},
chooseType(e) {
let me = this;
me.setData({
'bean.type': e.currentTarget.dataset.type
})
},
//获取input输入框中的内容
inputTap(e) {
let me = this;
me.setData({
['bean.' + e.currentTarget.dataset.name]: e.detail.value
})
},
提交内容
submit(){
let me = this;
me.content();
//进行内容提交的请求
}
})
},
getContent(e){
this.setData({
content: e.detail.value
})
},
content(){
let str = '';
let imgList = this.data.imgList;
imgList.forEach(function (val) {
str+=`<img src="${val}">`
})
let content = this.data.content + str;
this.setData({
'bean.content': content
})
},
chooseImg(){
let me = this;
if (me.data.imgList.length<3){
me.upLoadImg((data) => {
var imgList = me.data.imgList;
imgList.push(data);
me.setData({
imgList: imgList
})
});
} else {
//提示最多可上传3张图片
}
},
// 删除图片
deleteImage: function (e) {
let imgIndex = e.currentTarget.dataset.index;
let imgList = this.data.imgList;
imgList.splice(imgIndex, 1);
this.setData({
imgList: imgList
})
},
// 长按图片显示删除符号
showDeleteBtn: function () {
this.setData({
showDelete: true
})
},
//上传图片,第一步选择图片
upLoadImg(callBack){
var me = this;
wx.showActionSheet({
itemList: ["从相册中选择", "拍照"],
itemColor: "#333",
success: function (res) {
if (!res.cancel) {
wx.chooseImage({
count: 1,
sourceType: res.tapIndex == 0 ? ["album"] : ["camera"],
success: function (res) {
me.uploadImgStep2(res.tempFilePaths[0], callBack);
}
})
}
}
})
},
//图片上传第二步
uploadImgStep2(imgPath, callBack) {
let me = this;
var cookie = '';
var index = 0;
var path = '';
for (var key in this.getCookieSync('MAIN_SESSION')) {
if (index > 0) {
cookie += ';'
}
cookie += key + '=' + this.getCookieSync('MAIN_SESSION')[key]
index = index + 1;
}
var Header = {
'wx_small_program': 'wx_small_program',
'content-type': 'application/x-www-form-urlencoded;charset=utf-8',
'Cookie': cookie
}
wx.uploadFile({
url: api.upLoadImgUrl,
filePath: imgPath,
header: Header,
name: 'file',
formData: {
file: imgPath
},
success: function (res) {
if (res.statusCode != 200) {
wx.showModal({
title: '提示',
content: '上传失败',
showCancel: false
})
return;
} else {
if (callBack){
callBack(JSON.parse(res.data).data.fullPath);//上传成功,将返回的数据通过JSON进行处理,然后取出路径,将最后的路径作为参数传入callBack,在callBack中可以用其他参数名进行取得路径
}
}
},
fail: function (e) {
wx.showModal({
title: '提示',
content: '上传失败',
showCancel: false
})
},
complete: function () {
wx.hideToast(); //隐藏Toast
}
})
},
})