<template>
|
<span class="upload-content pr">
|
<!-- <ladda-btn
|
:loading="upLoadLoading"
|
data-style="slide-down"
|
@click.native="uploadStart"
|
:class="uploadBtnClass"
|
>
|
<i :class="uploadBtnIcon"></i> {{uploadBtntext}}
|
</ladda-btn>-->
|
<slot></slot>
|
<div class="upload-progress" v-if="isShowProgress">
|
<b-progress
|
variant="warning"
|
striped
|
:style="`opacity: ${isShowProgress&&showProgress?1:0}`"
|
:value="progressValue"
|
height="5px"
|
/>
|
</div>
|
<input type="file" ref="fileInput" multiple @change="clickUpLoad">
|
<div class="drag-area py-4 px-4" v-show="isShowBox">
|
<div style="height:50px">
|
<label style="font-size:0.8rem">图片质量:</label>
|
<el-input-number
|
v-model="picQuality"
|
style="width:80px"
|
size="mini"
|
controls-position="right"
|
:min="1"
|
:max="100"
|
></el-input-number>
|
<label style="font-size:0.8rem;margin-left:100px">对比阈值:</label>
|
<el-input-number
|
v-model="threshold"
|
style="width:80px"
|
size="mini"
|
controls-position="right"
|
:min="1"
|
:max="100"
|
lable="对比阈值"
|
></el-input-number>
|
</div>
|
<div
|
ref="drag_area"
|
:class="['text-center files-area py-4 px-4',drag_class]"
|
@click="uploadStart('fileInput')"
|
@dragover="dragover($event)"
|
@drop="drop($event)"
|
@dragenter="dragenter($event)"
|
@dragleave="dragleave($event)"
|
v-if="isShowUpload"
|
>
|
<i class="el-icon-upload text-primary"></i>
|
<div class="el-upload__text text-light">
|
将文件拖到此处,或
|
<em class="text-primary cursor-pointer">点击上传</em>
|
</div>
|
<div
|
class="el-upload__tip text-light"
|
>{{limitTypes?`只能上传${limitTypes}文件`:''}}{{limitSize?` 文件大小不超过${limitSize}`:''}}</div>
|
</div>
|
<div class="showPhoto" v-if="!isShowUpload">
|
<div class="bigPhoto px-4 py-4" style>
|
<httpImg :src="photo.bigPhotoPath" style="max-width:350px;max-height:180px" alt/>
|
</div>
|
<div>
|
<label class="mt-3">人脸提取</label>
|
</div>
|
<el-row class="smallPhotos" :gutter="30">
|
<el-col
|
class="pointer py-2"
|
v-for="(item,index) in photo.smallPhotoPath"
|
:key="index"
|
:span="8"
|
>
|
<httpImg
|
class="duihao"
|
v-show="index == clickNum"
|
:src="'/static/img/duihao.png'"
|
width="20px"
|
height="20px"
|
alt
|
/>
|
<httpImg
|
:src="item"
|
style="max-width:100%;max-height:100%;height:110px"
|
@click.native="duihao($event,index)"
|
alt
|
/>
|
<div class="ml-5 mt-1" style="font-weight:bold">{{index+1}}</div>
|
</el-col>
|
</el-row>
|
<el-row>
|
<b-btn
|
variant="primary"
|
class="mb-2"
|
style="margin-left:50px;float:left"
|
@click="againUpload()"
|
>重新上传图片</b-btn>
|
<b-btn
|
variant="primary"
|
class="mb-2"
|
style="margin-right:50px;float:right"
|
@click="closeBox()"
|
>图片选择完成</b-btn>
|
</el-row>
|
</div>
|
</div>
|
<div class="upload-model" v-show="isShowBox" @click="isShowBox=false"></div>
|
</span>
|
</template>
|
<style src="@/vendor/styles/pages/messages.scss" lang="scss"></style>
|
<script>
|
import axios from 'axios'
|
import { guid } from '@/components/common/util.js'
|
import LaddaBtn from '@/vendor/libs/ladda/Ladda'
|
import httpImg from '@/components/common/httpImgByPan'
|
import { InputNumber, Row, Col, Button } from 'element-ui'
|
import { findLikerPics } from '../../server/searchImg.js'
|
export default {
|
name: 'uploadDrag',
|
props: {
|
threshold: {
|
default: 60,
|
type: Number
|
},
|
/* 上传控件列表是否删除功能 */
|
isDelFile: {
|
default: true,
|
type: Boolean
|
},
|
page: {
|
default: 1,
|
type: Number
|
},
|
length: {
|
default: 10,
|
type: Number
|
},
|
dateTime: {
|
default: () => [],
|
type: Array
|
},
|
tableType: {
|
default: 'commonList',
|
type: String
|
},
|
/* 类型限制(后缀名,分隔) 传入示例'.png,.jpg' 不限制为 '' */
|
limitTypes: {
|
default: '',
|
type: String
|
},
|
/* 文件大小限制 传入示例'1M' 单位支持G、M、K、B 无单位按B计算 不限制为 '' */
|
limitSize: {
|
default: '',
|
type: String
|
},
|
/* 上传按钮文字 */
|
uploadBtntext: {
|
default: '上传',
|
type: String
|
},
|
/* 上传按钮icon */
|
uploadBtnIcon: {
|
default: 'ion ion-md-cloud-upload',
|
type: String
|
},
|
uploadBtnClass: {
|
default: 'btn btn-primary',
|
type: String
|
},
|
isShowProgress: {
|
default: false,
|
type: Boolean
|
},
|
isDrag: {
|
default: false,
|
type: Boolean
|
},
|
idJson: {
|
default: null,
|
type: Object
|
}
|
/**
|
* 上传组件回值方法
|
* @description 上传组件回值方法
|
* @return { function } addFilesBaBackFN 添加上传成功后返回 {fileIds,fileList}
|
*/
|
},
|
data() {
|
return {
|
featureBase64: [],
|
userInfo: this.$store.getters.basicUserInfo,
|
isShowBox: false,
|
clickNum: 0,
|
isShowUpload: true,
|
photo: { bigPhotoPath: '', smallPhotoPath: [] },
|
realSmallPath: [], // 真路径,不含虚拟人像的路径
|
drag_class: '',
|
picQuality: 60,
|
// threshold: 60, 以图搜图一个实现需要,把这个属性让父组件设定。有问题在和霍文博交流
|
fileList: [],
|
erFileList: [],
|
suFileList: [],
|
fileIds: [],
|
upLoadLoading: false,
|
showProgress: false,
|
progressValue: 0
|
}
|
},
|
computed: {},
|
methods: {
|
// 霍文博添加,更改比分值
|
setthreshold(num) {
|
this.threshold = num
|
},
|
againUpload() {
|
this.isShowUpload = true
|
},
|
async closeBox() {
|
// 查询比对方法
|
let json = {
|
liker: this.threshold,
|
path: this.photo.smallPhotoPath[this.clickNum],
|
page: this.page,
|
length: this.$parent.tabType === 'map' ? 99999 : 40,
|
startDate: this.dateTime[0],
|
endDate: this.dateTime[1]
|
}
|
let res = await findLikerPics(json)
|
|
/* 结束上传按钮loding */
|
this.upLoadLoading = false
|
/* 隐藏拖拽框 */
|
this.isShowBox = false
|
/* 保存到localStorage里面,用来解决轨迹详情弹窗init bug start */
|
res.data['index'] = this.clickNum
|
let strEs =
|
res && res.data && res.data.esList
|
? JSON.stringify(res.data.esList)
|
: '[]'
|
localStorage.setItem('index', this.clickNum)
|
localStorage.setItem('esList', strEs)
|
/* end */
|
const realSmallPath = []
|
this.photo.smallPhotoPath.forEach(item => {
|
if (item.indexOf('group') !== -1) {
|
realSmallPath.push({ path: item })
|
}
|
})
|
res.data['smallPhotoPath'] = realSmallPath
|
res.data['featureBase64'] = this.featureBase64
|
res.data['param'] = json
|
this.$emit('showSearchImgList', {
|
result: res.data
|
})
|
this.isShowBox = false
|
},
|
duihao(e, index) {
|
var img = e.currentTarget
|
// 拼上的虚拟人像不能被点击触发搜图事件
|
if (img.src.indexOf('group') !== -1) {
|
this.clickNum = index
|
}
|
},
|
islimitTypes(fileObj) {
|
if (this.limitTypes === '') {
|
return 'success'
|
}
|
if (
|
this.limitTypes.indexOf(
|
fileObj.name.toLowerCase().replace(/^.+\./, '')
|
) === -1
|
) {
|
const msg = {
|
type: 'error',
|
errorType: '上传类型错误',
|
message:
|
/* ${fileObj && fileObj.name ? '“' + fileObj.name + '”' : ''} */
|
`上传文件必须是${this.limitTypes},请您核查`
|
}
|
// this.$toast(msg)
|
return msg
|
}
|
return 'success'
|
},
|
islimitSize(fileObj) {
|
if (this.limitSize === '') {
|
return 'success'
|
}
|
let size = 0
|
if (this.limitSize.indexOf('G') !== -1) {
|
size = this.limitSize.replace('G', '') * 1024 * 1024 * 1024
|
} else if (this.limitSize.indexOf('M') !== -1) {
|
size = this.limitSize.replace('M', '') * 1024 * 1024
|
} else if (this.limitSize.indexOf('K') !== -1) {
|
size = this.limitSize.replace('K', '') * 1024
|
} else if (this.limitSize.indexOf('B') !== -1) {
|
size = this.limitSize.replace('B', '')
|
} else {
|
size = this.limitSize
|
}
|
if (size < fileObj.size) {
|
const msg = {
|
type: 'error',
|
errorType: '上传大小错误',
|
message:
|
`${
|
fileObj && fileObj.name ? '“' + fileObj.name + '”' : ''
|
}必须小于` + this.limitSize
|
}
|
// this.$toast(msg)
|
return msg
|
}
|
return 'success'
|
},
|
uploadStart(type) {
|
this.$refs.fileInput.value = ''
|
this.fileList = []
|
this.erFileList = []
|
this.suFileList = []
|
if (this.isDrag && type !== 'fileInput') {
|
this.isShowBox = !this.isShowBox
|
} else {
|
this.$refs.fileInput.click()
|
}
|
},
|
/* 点击上传 */
|
clickUpLoad(e) {
|
if (e.target && e.target.files) {
|
this.handleUpLoad(e.target.files)
|
}
|
},
|
// 上传附件
|
handleUpLoad(files) {
|
/* 拿到上传文件 */
|
if (files.length === 0) {
|
return false
|
}
|
this.fileList = [...files]
|
/* 重置进度条 */
|
this.showProgress = true
|
this.progressValue = 0
|
/* 开启上传按钮loding */
|
this.upLoadLoading = true
|
/* 创建FormData文件对象 */
|
const fd = new FormData()
|
this.fileList.map((file, index) => {
|
/* 文件校验 start */
|
const islimitTypes = this.islimitTypes(file)
|
const islimitSize = this.islimitSize(file)
|
if (islimitTypes !== 'success') {
|
this.erFileList.push({
|
uuId: guid(),
|
file: file,
|
errorMsg: islimitTypes
|
})
|
return false
|
}
|
if (islimitSize !== 'success') {
|
this.erFileList.push({
|
uuId: guid(),
|
file: file,
|
errorMsg: islimitSize
|
})
|
return false
|
}
|
this.suFileList.push(file)
|
/* 文件校验 end */
|
// fd.append('files' + index, file)
|
fd.append('file', file)
|
fd.append('picQuality', this.picQuality)
|
})
|
// fd.append('files', this.suFileList)
|
/* 添加orgId officeId start */
|
// if (this.idJson && this.idJson.orgId) {
|
// fd.append('orgId', this.idJson.orgId)
|
// }
|
// if (this.idJson && this.idJson.officeId) {
|
// fd.append('officeId', this.idJson.officeId)
|
// }
|
/* 添加orgId officeId end */
|
fd.append('fileSource', 'FDFS')
|
if (this.fileList.length > this.erFileList.length) {
|
this.uploadServer(fd)
|
} else {
|
/* 回调传值 */
|
this.$emit('addFilesBaBackFN', {
|
suFileList: this.suFileList,
|
erFileList: this.erFileList,
|
fileList: this.fileList,
|
result: null
|
})
|
/* 结束上传按钮loding */
|
this.upLoadLoading = false
|
/* 隐藏拖拽框 */
|
// this.isShowBox = false
|
this.isShowUpload = false
|
}
|
},
|
async uploadServer(fd) {
|
this.$store.commit('HANDLE_LOADING_OPEN')
|
const token = JSON.parse(
|
sessionStorage.getItem('loginedInfo')
|
).access_token.split(' ')[1]
|
/* const token = JSON.parse(
|
sessionStorage.getItem('loginedInfo')
|
).access_token.split(' ')[1] */
|
try {
|
let res = await axios({
|
method: 'post',
|
url: `data/api-r/SearchPhoto/extractFace?access_token=${token}`,
|
data: fd,
|
name: 'file',
|
onUploadProgress: progressEvent => {
|
if (
|
this.isShowProgress &&
|
progressEvent.loaded &&
|
progressEvent.total
|
) {
|
this.progressValue =
|
(progressEvent.loaded / progressEvent.total) * 100
|
}
|
}
|
})
|
if (res && res.data) {
|
const result = res.data
|
this.featureBase64 = result.data.featureBase64
|
this.$toast({
|
type: result && result.success ? 'success' : 'error',
|
message: result.msg
|
})
|
this.progressValue = 0
|
this.showProgress = false
|
this.isShowUpload = false
|
this.photo.bigPhotoPath = result.data.bigPhotoPath
|
this.photo.smallPhotoPath = result.data.smallPhotoPath
|
if (result.data.smallPhotoPath.length % 3 !== 0) {
|
// 用虚拟人像补全整行
|
const length = result.data.smallPhotoPath.length % 3
|
for (var i = 0; i < 3 - length; i++) {
|
this.photo.smallPhotoPath.push('static/img/nobody.png')
|
}
|
}
|
// let errorArr = []
|
// // 根据与后台约定data数组返回的都是存在业务意义错误的对象
|
// if (result.data && result.data.length) {
|
// errorArr = result.data.map(file => {
|
// // 遍历前台抛给后台的fileList 进行比对赋值file文件及message
|
// for (var i = 0; i < this.suFileList.length; i++) {
|
// const iteam = this.suFileList[i]
|
// if (
|
// file.upload.fileName &&
|
// iteam.name === file.upload.fileName
|
// ) {
|
// return {
|
// uuId: guid(),
|
// file: iteam,
|
// photos: file.upload.path,
|
// baseList: file.baseList ? file.baseList : null,
|
// errorMsg: {
|
// type: 'error',
|
// errorType: '上传异常',
|
// message: file.reason ? file.reason : result.msg
|
// }
|
// }
|
// }
|
// }
|
// })
|
// }
|
/* 回调传值 */
|
// 处理错误文件列表 如果为0说明全部成功,(通过校验,并在后台成功完成注册添加)
|
// let erFileList =
|
// result && result.success
|
// ? this.erFileList
|
// : [...this.erFileList, ...errorArr]
|
// 全部成功无需打开业务弹窗
|
// if (erFileList.length > 0) {
|
// this.$emit('addFilesBaBackFN', {
|
// suFileList: result && result.success ? this.suFileList : [],
|
// erFileList: erFileList,
|
// fileList: this.fileList,
|
// result: res
|
// })
|
// }
|
// if (erFileList.length === 0) {
|
// this.$emit('successFN')
|
// }
|
}
|
} catch (error) {
|
this.$toast({
|
type: 'error',
|
message: '服务器错误!请联系管理员' // + error.message
|
})
|
this.progressValue = 0
|
this.showProgress = false
|
const errorArr = this.suFileList.map(file => {
|
return {
|
uuId: guid(),
|
file: file,
|
errorMsg: {
|
type: 'error',
|
errorType: '上传服务器错误',
|
message: error.message
|
}
|
}
|
})
|
this.erFileList = [...this.erFileList, ...errorArr]
|
/* 回调传值 */
|
this.$emit('addFilesBaBackFN', {
|
suFileList: [],
|
erFileList: this.erFileList,
|
fileList: this.fileList,
|
result: error
|
})
|
}
|
this.$store.commit('HANDLE_LOADING_CLOSE')
|
/* 结束上传按钮loding */
|
this.upLoadLoading = false
|
/* 隐藏拖拽框 */
|
// this.isShowBox = false
|
},
|
/* 拖拽函数 start */
|
dragleave(el) {
|
this.drag_class = ''
|
el.stopPropagation()
|
el.preventDefault()
|
},
|
dragenter(el) {
|
this.drag_class = 'active'
|
el.stopPropagation()
|
el.preventDefault()
|
},
|
dragover(el) {
|
this.drag_class = 'active'
|
el.stopPropagation()
|
el.preventDefault()
|
},
|
drop(el) {
|
el.stopPropagation()
|
el.preventDefault()
|
if (el.dataTransfer && el.dataTransfer.files) {
|
this.handleUpLoad(el.dataTransfer.files)
|
}
|
}
|
/* 拖拽函数 end */
|
},
|
created() {},
|
watch: {
|
progressValue(newVal, oldVal) {
|
if (newVal !== oldVal && newVal >= 100) {
|
setTimeout(() => {
|
this.showProgress = false
|
this.progressValue = 0
|
}, 1500)
|
}
|
},
|
threshold(newVal, oldVal) {
|
if (newVal !== oldVal) {
|
localStorage.setItem('threshold', this.threshold)
|
this.$emit('updateThreshold', newVal)
|
}
|
}
|
},
|
components: {
|
LaddaBtn,
|
httpImg,
|
elInputNumber: InputNumber,
|
elCol: Col,
|
elRow: Row,
|
elButton: Button
|
}
|
}
|
</script>
|
|
<style lang="scss" >
|
.upload-img-icon {
|
width: 60px;
|
background-size: 100%;
|
background-repeat: no-repeat;
|
background-position: center;
|
}
|
.upload-progress {
|
width: 96%;
|
position: absolute;
|
left: 2px;
|
bottom: 2px;
|
opacity: 1;
|
transition: all 0.5s;
|
}
|
.upload-content {
|
position: relative;
|
input[type='file'] {
|
position: absolute;
|
opacity: 0;
|
width: 82px;
|
height: 38px;
|
left: 0;
|
display: none;
|
}
|
}
|
.drag-area {
|
position: absolute;
|
z-index: 100 !important;
|
right: 0;
|
top: 35px;
|
z-index: 5;
|
background: #fff;
|
border-radius: 5px;
|
.files-area {
|
width: 420px;
|
background: #fff;
|
border: 1px dashed #d9d9d9;
|
border-radius: 5px;
|
}
|
.files-area.active {
|
border: 2px dashed #35bde7;
|
}
|
.files-area:hover {
|
border: 1px dashed #35bde7;
|
}
|
.el-icon-upload {
|
font-size: 60px;
|
margin-bottom: 10px;
|
}
|
}
|
.upload-model {
|
position: fixed;
|
top: 0;
|
left: 0;
|
right: 0;
|
bottom: 0;
|
z-index: 99;
|
background: rgba(0, 0, 0, 0.2);
|
}
|
.showPhoto {
|
width: 420px;
|
background: #fff;
|
border-radius: 5px;
|
}
|
.bigPhoto {
|
width: 420px;
|
height: 250px;
|
background: #f1f1f1;
|
border: 1px dashed #d9d9d9;
|
border-radius: 5px;
|
vertical-align: middle;
|
display: table-cell;
|
text-align: center;
|
}
|
.duihao {
|
position: absolute;
|
bottom: 33px;
|
right: 55px;
|
}
|
.pointer {
|
cursor: pointer;
|
position: relative;
|
}
|
.smallPhotos {
|
height: 310px;
|
overflow-y: auto;
|
}
|
</style>
|