本文使用原生的上传有局限性,ios手机能同时选择多张图片,而安卓手机只能一张一张上传,不能一次性选择多张。所以建议调用 微信JS SDK。
代码如下:
<template>
<div class="start-work viewport">
<div class="hd tc">
<div class="inner-wrap">
<div class="task-name">张三 - 幸福花园 19#404</div>
<div class="time">2018-08-08</div>
</div>
</div>
<!-- <div class="bd">
<dl class="start-pic">
<dt>开工照片</dt>
<dd class="cf">
<div class="add-pic fl">
<i class="icon iconfont icon-jia"></i>
</div>
<div class="pic-item fl" v-for="(item,index) in 1" :key="index">
<img src="" alt="">
</div>
</dd>
</dl>
</div> -->
<!--收货照片-->
<dl class="receipt-pic pub-section">
<dt>
<h3>收货照片 <span class="c-999">(限9张)</span></h3>
</dt>
<dd class="cf">
<div class="add-pic fl" v-if="formDatas.receive_imgs.length < 9">
<input name="files" type="file" id="file" accept="image/*" multiple="multiple" @change="imgChange($event)" />
<i class="icon iconfont icon-jia"></i>
<label for="file"></label>
</div>
<div class="pic-item fl" v-for="(item,index) in formDatas.receive_imgs" :key="index">
<!--<span v-if="item === true">
<mt-spinner type="snake" class="loading-more"></mt-spinner>
</span>-->
<img :src="item" alt="">
<span class="delete-pic" @click="deletePic(index)">
<i class="icon iconfont icon-icon-test"></i>
</span>
</div>
</dd>
</dl>
<div class="ft">
<!--允许开工-->
<div class="allow-start">
<div class="label">
周末是否允许开工
</div>
<div class="v">
<div class="j-radio l-txt" v-for="(type,index) in allowStartData" :key="index">
<label>
<span class="txt">{{type.label}}</span>
<input type="radio" name="houseType" v-model="allowStartType" :value="type.value" :checked="type.value === allowStartType ? true : false">
<span class="icon"></span>
</label>
</div>
</div>
</div>
<div class="start-btn">
<span class="btn" @click="strtWorkFn">
开工
</span>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import { Toast, Spinner} from 'mint-ui'
import Oss from '@/assets/js/util/aliyunOss.js'
Vue.component(Spinner.name, Spinner)
export default {
data () {
return {
allowStartType: '1',
allowStartData: [
{
label: '允许',
value: '1'
},
{
label: '不允许',
value: '2'
}
],
sign: {
accessid: '',
dir: '',
expire: '',
host: '',
policy: '',
signature: ''
},
formDatas: {
purchase_id: '',
receive_imgs: [],
products: [],
remark: ''
}
}
},
created () {
},
mounted () {
let _this = this
Oss.getSign(200).then((res) => { // 获取签名
_this.sign = res.data
console.log(_this.sign)
// console.log('this.sign', _this.sign)
}).catch((err) => {
console.log('err', err)
})
},
methods: {
apiUploadOss (ossData) {
let _this = this
// this.$http({
// url: this.sign.host,
// method: 'post',
// data: ossData,
// onUploadProgress (progressEvent) { // 原生获取上传进度的事件
// if (progressEvent.lengthComputable) {
// console.log(progressEvent)
// console.log('百分比', (progressEvent.loaded / progressEvent.total) * 100)
// }
// }
// }).then(function (res) {
// _this.formDatas.receive_imgs.push(_this.sign.host + '/' + ossData.get('key'))
// console.log('路劲:', _this.sign.host + '/' + ossData.get('key'))
// }).catch(function (err) {
// console.log(err)
// })
this.$http.post(_this.sign.host, ossData).then(function (res) {
_this.formDatas.receive_imgs.push(_this.sign.host + '/' + ossData.get('key'))
console.log('路劲:', _this.sign.host + '/' + ossData.get('key'))
}).catch(function (err) {
console.log(err)
})
},
imgChange (e) {
console.log('初次点击')
let _this = this
let files = e.target.files
console.log(files)
// 验证数量
if ((this.formDatas.receive_imgs.length + files.length) > 9) {
Toast('最多只能上传9张图片')
return
}
// 验证格式
for (let i = 0; i < files.length; i++) {
if (!/.(jpg|jpeg|png)$/.test(e.target.files[i].name)) {
Toast('文件必须是jpeg,jpg,png中的一种')
return
}
// else {
// this.formDatas.receive_imgs.push(true) // 表示加载中
// }
}
for (let i = 0; i < files.length; i++) {
let file = e.target.files[i] // 获取图片资源
let filename = file.name
// 获取最终需要上传的参数
let ossData = Oss.getFormDataParams(_this.sign, filename)
// 添加文件
let reader = new FileReader()
let oImg = new Image()
let uploadInfo = {}
console.log('ossData', ossData)
reader.onload = function (e) {
uploadInfo.imageBase64 = e.target.result
let src = uploadInfo.imageBase64
// $('#thumbnail-list').append("1->:"+getSizeByBase64(uploadInfo.imageBase64))
oImg.onload = function () {
src = Oss.compress(oImg, 0.8)
// 添加最后需要的参数
ossData.append('file', Oss.convertBase64UrlToBlob(src), filename)
// 开始上传
_this.apiUploadOss(ossData)
}
oImg.src = src
return true
}
reader.readAsDataURL(file)
}
},
deletePic (index) {
this.formDatas.receive_imgs.splice(index, 1)
console.log(this.formDatas.receive_imgs)
},
strtWorkFn () {
let _this = this
let work_on_weekend = '1'
if (this.allowStartType === '1') {
work_on_weekend = true
} else if (this.allowStartType === '2') {
work_on_weekend = false
}
this.$http.post('/api/steward/projects/' + _this.$route.query.contract_id + '/start', {contract_id: _this.$route.query.contract_id, work_on_weekend: work_on_weekend, work_images: _this.formDatas.receive_imgs}).then((res) => {
let datas = res.data
if (datas.code === 0) {
console.log(datas)
} else {
Toast({
message: datas.msg,
duration: 2000
})
}
})
}
}
}
</script>
<style lang="less" scoped >
@import (reference) "~less/base.less";
.start-work{
font-size:.28rem;
.hd{
background:#fff;
padding-left:.38rem;
.inner-wrap{
padding:.5rem .38rem .2rem 0;
}
}
// 收货图片
.receipt-pic{
padding: 0.5rem 0 0 0.4rem;
border-bottom:.1rem solid @c-f5;
h3{
border-bottom:1px solid @c-border;
padding-bottom: 0.2rem;
span{
font-size:.14rem;
color: @c-999;
}
}
dd {
padding:.44rem 0 .6rem;
.add-pic {
position:relative;
border: 2px dashed @c-999;
width: 1.34rem;
height: 1.34rem;
float: left;
text-align: center;
margin-right:.2rem;
box-sizing: border-box;
.icon-jia{
font-size:.54rem;
color:@c-999;
line-height:1.32rem;
}
label{
position:absolute;
top:0;
left:0;
z-index:1;
width:100%;
height:100%;
}
input{
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
}
.pic-item {
position:relative;
width: 1.34rem;
height: 1.34rem;
margin:0 .2rem .2rem 0;
img {
width: 100%;
height: 100%;
}
.delete-pic{
position:absolute;
top:-.15rem;
right:-.15rem;
background:@c-high;
border-radius: 50%;
z-index:1;
width:.38rem;
height:.38rem;
text-align: center;
line-height:.38rem;
.tc;
}
.icon-icon-test{
font-size:.12rem;
color:#fff;
display:inline-block;
transform: scale(0.8,0.8);
}
}
}
}
.ft{
background:#fff;
padding:.4rem .38rem .88rem;
.allow-start{
.display-flex;
line-height:.4rem;
.v{
flex: 1;
.tr;
}
.j-radio:last-child{
margin-left:.4rem;
}
}
.start-btn{
margin-top:2.5rem;
}
.btn{
.btn-main(100%,1rem,.28rem, 5px);
background:@c-main;
color:#fff;
}
}
}
</style>
aliyunOss.js文件,需要获取后台签名。
import Axios from 'axios'
export default {
getSign (module) {
return new Promise(function (resolve, reject) {
// Axios.post('http://test.enlife.jjcclife.com/api/user/upload/sign?token=e1411e831c3a054610427bca05385583', {
Axios.post('/api/images/sign', {
module: module
}).then(function (res) {
let datas = res.data
if (datas.code === SUCCESS_CODE) {
resolve(datas)
} else {
reject(datas)
}
}).catch(function (err) {
reject(err)
})
})
},
randomString (len) {
len = len || 32
let chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
let maxPos = chars.length
let pwd = ''
for (let i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos))
}
return pwd
},
convertBase64UrlToBlob (urlData) {
let bytes = window.atob(urlData.split(',')[1]) // 去掉url的头,并转换为byte
// 处理异常,将ascii码小于0的转换为大于0
let ab = new ArrayBuffer(bytes.length)
let ia = new Uint8Array(ab)
let mimeString = urlData.split(',')[0].split(':')[1].split(';')[0]
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i)
}
return new Blob([ab], {type: mimeString})
},
getFormDataParams (sign, fileName) {
// 构造formdata表单数据
let ossData = new FormData()
// let key = sign.dir + '/' + this.randomString() + '.' + fileName.split('.')[1]
let key = ''
if (/\/$/.test(sign.dir)) {
key = sign.dir + this.randomString() + '.' + fileName.split('.')[1]
} else {
key = sign.dir + '/' + this.randomString() + '.' + fileName.split('.')[1]
}
console.log('key', key)
ossData.append('OSSAccessKeyId', sign.accessid)
ossData.append('policy', sign.policy)
ossData.append('Signature', sign.signature)
ossData.append('success_action_status', 200)
ossData.append('key', key)
return ossData
},
compress (img, quality) {
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
// 瓦片canvas
let tCanvas = document.createElement('canvas')
let tctx = tCanvas.getContext('2d')
// let maxSize = 200 * 1024 // 200KB
quality = quality || 0.8 // 图片压缩质量
let initSize = img.src.length
let width = img.width
let height = img.height
// 如果图片大于四百万像素,计算压缩比并将大小压至400万以下
let ratio
if ((ratio = width * height / 4000000) > 1) {
ratio = Math.sqrt(ratio)
width /= ratio
height /= ratio
} else {
ratio = 1
}
canvas.width = width
canvas.height = height
// 铺底色
ctx.fillStyle = '#fff'
ctx.fillRect(0, 0, canvas.width, canvas.height)
// 如果图片像素大于100万则使用瓦片绘制
let count
if ((count = width * height / 1000000) > 1) {
count = ~~(Math.sqrt(count) + 1) // 计算要分成多少块瓦片
// 计算每块瓦片的宽和高
let nw = ~~(width / count)
let nh = ~~(height / count)
tCanvas.width = nw
tCanvas.height = nh
for (let i = 0; i < count; i++) {
for (let j = 0; j < count; j++) {
tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh)
ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh)
}
}
} else {
ctx.drawImage(img, 0, 0, width, height)
}
// 进行最小压缩
let ndata = canvas.toDataURL('image/jpeg', quality)
// console.log('压缩前:' + initSize)
// console.log('压缩后:' + ndata.length)
// console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + '%')
tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0
// document.write(ndata);
if (initSize > ndata.length) { // 压缩后比原来还大,就使用原图
return ndata
} else {
// return img.src
return ndata
}
}
}
卓越的云计算服务提供商,230万+用户正在享受阿里云"稳定,安全,低成本"的产品服务,金牌服务:免费体验,专业快速备案,7x24小时售后,服务器只选阿里云