源文件

This commit is contained in:
gyq
2024-05-23 14:39:33 +08:00
commit a1128dd791
2997 changed files with 500069 additions and 0 deletions

View 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>

View 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>