源文件
This commit is contained in:
426
jeepay-ui-uapp-agent/components/JeepayUpLoad/JeepayUpLoad.vue
Normal file
426
jeepay-ui-uapp-agent/components/JeepayUpLoad/JeepayUpLoad.vue
Normal file
@@ -0,0 +1,426 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="default">
|
||||
<!-- 删除按钮 -->
|
||||
<view class="clear" v-if="vdata.hasImg && isShowClear && userIsShowClear">
|
||||
<!-- -->
|
||||
<image src="../../static/img/close.svg" @click.stop="logoutPopup.open()" mode="aspectFill"></image>
|
||||
<!-- <image src="../../static/img/clear.svg" @click.stop="logoutPopup.open()"></image> -->
|
||||
</view>
|
||||
<view @click="previewImg" class="img-bg" v-if="vdata.hasImg">
|
||||
<image :src="vdata.assemblyUrl" class="img-suc" mode="aspectFill"></image>
|
||||
</view>
|
||||
<image
|
||||
v-if="!vdata.hasImg"
|
||||
class="camera"
|
||||
@click="chooseImg(['album', 'camera'])"
|
||||
src="/static/iconImg/upload-picture.svg"
|
||||
></image>
|
||||
</view>
|
||||
<!-- 图片预览(手写非原生) -->
|
||||
<enlarge
|
||||
v-if="isPreview"
|
||||
:changeIsShow="props.isShowClear"
|
||||
:imgs="vdata.assemblyUrl"
|
||||
@enlargeClose="enlargeClose"
|
||||
@chooseImg="chooseImg"
|
||||
/>
|
||||
<!-- 删除图片二次确认 -->
|
||||
<uni-popup ref="logoutPopup" type="dialog">
|
||||
<uni-popup-dialog mode="base" :before-close="true" @close="logoutPopup.close()" @confirm="clear">
|
||||
<template #title>
|
||||
<view class="tip-content">确定要删除该图片吗?</view>
|
||||
</template>
|
||||
</uni-popup-dialog>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import appConfig from "@/config/appConfig.js"
|
||||
import { ref, reactive, watch, onMounted, nextTick } from "vue"
|
||||
import { $ossFilesForm, $imgInfoDetail } from "@/http/apiManager.js"
|
||||
import storageManage from "@/util/storageManage.js"
|
||||
import enlarge from "./enlarge.vue" // 图片预览
|
||||
import useBackPress from "@/hooks/useBackPress.js" // 返回阻断函数
|
||||
import { sm4DecryptByResData } from "@/util/encryptUtil.js"
|
||||
|
||||
const logoutPopup = ref(null) // 二次确认弹框
|
||||
|
||||
const props = defineProps({
|
||||
upLoadUrl: { type: String, default: "/api/ossFiles/singleFile" }, // 默认图片
|
||||
imgUrl: { type: String, default: "" }, // 默认图片
|
||||
recogObjectType: { type: String, default: "" }, // 识别对象类型(idcard, idcard_back, bankcard, business_license)
|
||||
uploadCount: { type: Number, default: 1 }, // 上传图片张数
|
||||
size: { type: Number, default: 2 }, // 图片限制大小,单位M
|
||||
imgTypes: { type: Array, default: () => ["jpg", "jpeg", "png"] }, // 图片类型限制,如: ['jpg', 'jpeg']
|
||||
isShowClear: { type: Boolean, default: true }, // 进件成功不展示删除按钮与更换按钮
|
||||
ocrFlag: { type: String, default: "" }, // ocr识别标志,图片类型: idCard-身份证,bankCard-银行卡, license-营业执照
|
||||
userIsShowClear: { type: Boolean, default: true }, // 在其余页面中是否展示删除按钮
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (props.imgUrl) {
|
||||
vdata.hasImg = true
|
||||
vdata.assemblyUrl = props.imgUrl
|
||||
}
|
||||
})
|
||||
|
||||
// 关闭图片预览
|
||||
const enlargeClose = () => {
|
||||
isPreview.value = false
|
||||
// #ifdef H5 || APP-PLUS
|
||||
inactive()
|
||||
// #endif
|
||||
}
|
||||
|
||||
const vdata = reactive({
|
||||
hasImg: false,
|
||||
assemblyUrl: "",
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.imgUrl,
|
||||
(newVal, oldVal) => {
|
||||
nextTick(() => {
|
||||
newVal ? (vdata.hasImg = true) : (vdata.hasImg = false)
|
||||
vdata.assemblyUrl = newVal
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
const emit = defineEmits(["uploadSuccess", "clear"])
|
||||
|
||||
// OCR识别函数
|
||||
function imgInfoDetail(res) {
|
||||
$imgInfoDetail({
|
||||
imgUrl: res.data,
|
||||
type: props.ocrFlag,
|
||||
}).then(({ bizData }) => {
|
||||
if (Object.keys(bizData).length < 1) {
|
||||
// uni.showToast({
|
||||
// title: '图片识别失败',
|
||||
// icon: 'none'
|
||||
// })
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: "图片识别成功,已自动回填内容,请检查核对",
|
||||
icon: "none",
|
||||
})
|
||||
}
|
||||
res.ocrInfo = bizData
|
||||
return emit("uploadSuccess", res)
|
||||
})
|
||||
}
|
||||
|
||||
function chooseImg(index) {
|
||||
console.log(index)
|
||||
if (props.isShowClear) {
|
||||
uni.chooseImage({
|
||||
count: props.uploadCount,
|
||||
sizeType: ["compressed"],
|
||||
sourceType: index,
|
||||
crop: { quality: 20 },
|
||||
|
||||
success: (chooseImageRes) => {
|
||||
isPreview.value = false //关闭图片预览
|
||||
const msg = beforeUpload(chooseImageRes)
|
||||
if (msg != "success") return uni.showToast({ title: msg, icon: "none" })
|
||||
|
||||
// 根据form信息,判断图片上传地址
|
||||
// 此处额外验证,上传的图片是否含有name属性,如果没有则用path代替
|
||||
let sourceFileName
|
||||
if (chooseImageRes.tempFiles[0].name) {
|
||||
sourceFileName = chooseImageRes.tempFiles[0].name
|
||||
} else {
|
||||
sourceFileName = chooseImageRes.tempFiles[0].path
|
||||
}
|
||||
|
||||
$ossFilesForm({
|
||||
bizType: "applyment",
|
||||
sourceFileName: sourceFileName,
|
||||
sourceFileSize: chooseImageRes.tempFiles[0].size,
|
||||
}).then(({ bizData }) => {
|
||||
let url,
|
||||
isOss,
|
||||
ossImgUrl = ""
|
||||
if (bizData.formActionUrl === "LOCAL_SINGLE_FILE_URL") {
|
||||
url = appConfig.env.JEEPAY_BASE_URL + props.upLoadUrl
|
||||
isOss = false
|
||||
} else {
|
||||
url = bizData.formActionUrl
|
||||
ossImgUrl = { data: bizData.ossFileUrl }
|
||||
isOss = true
|
||||
}
|
||||
|
||||
// 调用图片上传方法
|
||||
uploadImg(chooseImageRes.tempFilePaths, url, bizData.formParams, isOss, ossImgUrl)
|
||||
console.log(url,'bizData.formParamsbizData.formParamsbizData.formParams');
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 上传图片
|
||||
function uploadImg(tempFilePaths, url, formParams, isOss, ossImgUrl) {
|
||||
const token = storageManage.token()
|
||||
|
||||
var successCount = 0 //多图时,上传成功数量
|
||||
var qualification = [] //多图存储
|
||||
|
||||
uni.showLoading({ title: "上传中..." })
|
||||
//循环上传图片
|
||||
|
||||
tempFilePaths.forEach((tempFilePath) => {
|
||||
console.log(tempFilePath);
|
||||
uni.uploadFile({
|
||||
url: url,
|
||||
filePath: tempFilePath,
|
||||
name: "file",
|
||||
header: {
|
||||
itoken: token,
|
||||
},
|
||||
formData: formParams,
|
||||
// 代表完成的函数 注:此处可以传入三个函数 success (成功)/ fail(失败) / complete (完成)
|
||||
complete(res) {
|
||||
uni.hideLoading()
|
||||
|
||||
// oss接口特有情况
|
||||
if (isOss) {
|
||||
if (res.statusCode != 200) {
|
||||
return uni.showToast({ title: "请求失败,请重试", icon: "none" })
|
||||
}
|
||||
|
||||
// 如果存在OCR 识别信息,那么要调用ocr识别函数
|
||||
if (props.ocrFlag) return imgInfoDetail(ossImgUrl)
|
||||
emit("uploadSuccess", ossImgUrl)
|
||||
return (vdata.hasImg = true)
|
||||
}
|
||||
// res 即接口返回数据包
|
||||
let {
|
||||
statusCode, // 状态码
|
||||
data, // 数据
|
||||
msg, // 信息
|
||||
errMsg, // 错误信息
|
||||
} = res
|
||||
|
||||
// 接收请求,执行响应操作
|
||||
if (statusCode != 200) {
|
||||
uni.showToast({
|
||||
title: "请求失败,请重试,statusCode:" + statusCode,
|
||||
icon: "none",
|
||||
mask: true,
|
||||
duration: 2000,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof data == "string") {
|
||||
data = JSON.parse(data)
|
||||
}
|
||||
|
||||
// 图片上传解密
|
||||
if (data.encryptData) {
|
||||
data.data = sm4DecryptByResData(data.encryptData)
|
||||
}
|
||||
|
||||
//状态码为1001(未登录)
|
||||
if (data.code == 1001) {
|
||||
uni.showToast({
|
||||
title: "请登录",
|
||||
icon: "none",
|
||||
mask: true,
|
||||
duration: 1500,
|
||||
})
|
||||
setTimeout(function () {
|
||||
uni.reLaunch({
|
||||
url: "/pages/login/login",
|
||||
})
|
||||
}, 1500)
|
||||
return
|
||||
}
|
||||
|
||||
if (data.code != 0) {
|
||||
uni.showToast({
|
||||
title: data.msg || "请求失败,请重试",
|
||||
duration: 2000,
|
||||
mask: true,
|
||||
icon: "none",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 如果存在OCR 识别信息,那么要调用ocr识别函数
|
||||
if (props.ocrFlag) return imgInfoDetail(data)
|
||||
// 没有遇到以上的情况
|
||||
emit("uploadSuccess", data)
|
||||
vdata.hasImg = true
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
// 上传图片前的校验
|
||||
function beforeUpload(chooseImageRes) {
|
||||
const tempFiles = chooseImageRes.tempFiles
|
||||
|
||||
let msg = "success"
|
||||
|
||||
if (tempFiles) {
|
||||
for (let i = 0; i < tempFiles.length; i++) {
|
||||
// 图片地址
|
||||
let tempUrl = tempFiles[i].name || tempFiles[i].path
|
||||
if (!tempUrl) {
|
||||
msg = "请选择图片"
|
||||
return msg
|
||||
}
|
||||
// 校验图片大小
|
||||
if (tempFiles[i].size > props.size * 1024 * 1024) {
|
||||
msg = "单张图片请不超过" + props.size + "MB"
|
||||
return msg
|
||||
}
|
||||
// 校验后缀
|
||||
if (!checkSuffix(tempUrl)) {
|
||||
msg = "仅支持【" + props.imgTypes + "】格式的图片"
|
||||
return msg
|
||||
}
|
||||
}
|
||||
} else {
|
||||
msg = "请选择图片"
|
||||
return msg
|
||||
}
|
||||
|
||||
if (chooseImageRes.tempFilePaths.length > props.uploadCount) {
|
||||
msg = "最多上传" + props.uploadCount + "张图片"
|
||||
return msg
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
||||
// 校验图片后缀
|
||||
function checkSuffix(fileName) {
|
||||
const suffix = getFileSuffix(fileName).toLowerCase()
|
||||
if (props.imgTypes.includes(suffix)) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
// 获取图片后缀
|
||||
function getFileSuffix(fileName) {
|
||||
if (!fileName || fileName.indexOf(".") < 0 || fileName.length <= 1) {
|
||||
return ""
|
||||
}
|
||||
return fileName.substring(fileName.lastIndexOf(".") + 1)
|
||||
}
|
||||
|
||||
let isPreview = ref(false) // 图片预览是否展示
|
||||
// 预览图片
|
||||
function previewImg() {
|
||||
isPreview.value = true
|
||||
|
||||
// #ifdef H5 || APP-PLUS
|
||||
active()
|
||||
// #endif
|
||||
// onceVar.imgView(true)
|
||||
|
||||
// let urls = [];
|
||||
// urls.push(props.imgUrl)
|
||||
|
||||
// uni.previewImage({
|
||||
// urls: urls
|
||||
// });
|
||||
}
|
||||
|
||||
// 叉号 清除图片
|
||||
function clear() {
|
||||
vdata.hasImg = false
|
||||
emit("clear")
|
||||
logoutPopup.value.close()
|
||||
}
|
||||
|
||||
// #ifdef H5 || APP-PLUS
|
||||
const { active, inactive } = useBackPress(enlargeClose) // onBackPress 阻断返回
|
||||
// #endif
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
// 图片预览
|
||||
.preview-img {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: #000;
|
||||
z-index: 25;
|
||||
}
|
||||
.camera {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
}
|
||||
.default {
|
||||
position: relative;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 5rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1rpx dashed #cccdd9;
|
||||
}
|
||||
.img-bg {
|
||||
position: relative;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
background: #f1f1f1;
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 10;
|
||||
/* margin-right: 30rpx; */
|
||||
image {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.img-def {
|
||||
width: 43rpx;
|
||||
height: 37rpx;
|
||||
}
|
||||
|
||||
.img-suc {
|
||||
width: 100%;
|
||||
/* height: 180rpx; */
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.clear {
|
||||
position: absolute;
|
||||
top: -10rpx;
|
||||
left: 90rpx;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border-radius: 50%;
|
||||
z-index: 12;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
image {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
}
|
||||
.tip-content {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 120rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
color: #3981ff;
|
||||
}
|
||||
</style>
|
||||
171
jeepay-ui-uapp-agent/components/JeepayUpLoad/enlarge.vue
Normal file
171
jeepay-ui-uapp-agent/components/JeepayUpLoad/enlarge.vue
Normal file
@@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<view class="previewImage" :style="{ 'background-color': 'rgba(0,0,0,' + opacity + ')' }" @tap="close">
|
||||
<movable-area class="marea" scale-area>
|
||||
<movable-view
|
||||
:id="'movable-view-' + i"
|
||||
:key="'movable-view-' + i"
|
||||
class="mview"
|
||||
direction="all"
|
||||
:out-of-bounds="false"
|
||||
:inertia="true"
|
||||
damping="90"
|
||||
friction="2"
|
||||
scale="true"
|
||||
scale-min="1"
|
||||
scale-max="4"
|
||||
:scale-value="scale"
|
||||
>
|
||||
<image
|
||||
:id="'image-' + i"
|
||||
:key="'movable-view' + i"
|
||||
class="image"
|
||||
:src="imgs"
|
||||
:data-index="i"
|
||||
:data-src="img"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</movable-view>
|
||||
</movable-area>
|
||||
<view v-if="changeIsShow" class="change-img">
|
||||
<view class="change-item" style="border-bottom: 2rpx solid #1a1a1a" @click="chooseImg(['camera'])">
|
||||
<image src="/static/iconImg/photograph.svg"></image>
|
||||
<text>拍照</text>
|
||||
</view>
|
||||
<view class="change-item" @click="chooseImg(['album'])">
|
||||
<image src="/static/iconImg/album.svg"></image>
|
||||
<text>从相册选择</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ksj-previewImage", //插件名称
|
||||
props: {
|
||||
imgs: {
|
||||
//图片列表
|
||||
type: String,
|
||||
required: true,
|
||||
default: "",
|
||||
},
|
||||
//透明度,0到1之间。
|
||||
opacity: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
changeIsShow: { type: Boolean, default: true },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
swiper: false, //是否禁用
|
||||
show: false, //显示状态
|
||||
index: 0, //当前页
|
||||
deg: 0, //旋转角度
|
||||
time: 0, //定时器
|
||||
interval: 1000, //长按事件
|
||||
scale: 1, //缩放比例
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
chooseImg(type) {
|
||||
this.$emit("chooseImg", type)
|
||||
},
|
||||
|
||||
//旋转
|
||||
rotate(e) {
|
||||
this.deg = this.deg == 270 ? 0 : this.deg + 90
|
||||
},
|
||||
close() {
|
||||
this.$emit("enlargeClose")
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<!--使用scss,只在本组件生效-->
|
||||
<style lang="scss" scoped>
|
||||
.previewImage {
|
||||
z-index: 25;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #000000;
|
||||
user-select: none;
|
||||
.marea {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
.mview {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 692rpx;
|
||||
height: 692rpx;
|
||||
border-radius: 23rpx;
|
||||
left: 29rpx;
|
||||
top: 192rpx;
|
||||
overflow: hidden;
|
||||
.image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rotate {
|
||||
position: absolute;
|
||||
right: 10rpx;
|
||||
width: 120rpx;
|
||||
height: 56rpx;
|
||||
bottom: 10rpx;
|
||||
text-align: center;
|
||||
padding: 10rpx;
|
||||
.text {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
color: #fff;
|
||||
font-size: 30rpx;
|
||||
border-radius: 20rpx;
|
||||
border: 1rpx solid #f1f1f1;
|
||||
padding: 6rpx 22rpx;
|
||||
user-select: none;
|
||||
text-align: center;
|
||||
}
|
||||
.text:active {
|
||||
background-color: rgba(100, 100, 100, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
.change-img {
|
||||
position: fixed;
|
||||
width: 385rpx;
|
||||
height: 212rpx;
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
bottom: 5%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 30;
|
||||
|
||||
border-radius: 15rpx;
|
||||
.change-item {
|
||||
width: 100%;
|
||||
height: 106rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
image {
|
||||
width: 31rpx;
|
||||
height: 31rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
text {
|
||||
font-weight: 500;
|
||||
font-size: 33rpx;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user