cashier_app/components/JeepayUploadImg/JeepayUploadImg.vue

168 lines
4.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
图片上传组件
@author terrfly
@site https://www.jeequan.com
@date 2022/11/30 18:18
-->
<template>
<view style="flex-grow: 1">
<!-- 图片内 x 号的模式 -->
<template v-if="props.mode == 'img'">
<!-- 包含图片 -->
<template v-if="props.src">
<view class="image-wrapper">
<image v-if="!props.readonly" @tap="delImg" class="del-image" src="/static/iconImg/icon-x-white.svg" mode="scaleToFill" />
<image class="default-img" :src="props.src" @tap="preview"></image>
</view>
</template>
<template v-else>
<!-- 不包含图片 -->
<view @tap="chooseImageAndUpload" style="flex-grow: 1; display: flex; justify-content: space-between; align-items: center">
<image
v-if="!props.readonly"
style="width: 150rpx; height: 150rpx; background-color: #f7f7f7; border-radius: 15rpx"
src="/static/iconImg/default-img.svg"
mode="scaleToFill"
/>
<image src="/pageDevice/static/devIconImg/icon-arrow-sex.svg" mode="scaleToFill" style="width: 120rpx; height: 120rpx" />
</view>
</template>
</template>
<!-- 页面图片 加入 切换按钮 -->
<template v-if="props.mode == 'viewbtn'">
<image class="default-img" :src="props.src" @tap="preview" mode="aspectFill"></image>
<!-- 图片预览手写非原生 -->
<enlarge v-if="vdata.showEnlarge" :imgs="props.src" :changeIsShow="!props.readonly" @chooseImg="chooseImageAndUpload" @enlargeClose="vdata.showEnlarge = false" />
</template>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue';
import http from '@/http/http.js';
import infoBox from '@/commons/utils/infoBox.js';
import enlarge from './enlarge.vue'; // 图片预览
import { API_URL_SINGLE_FILE_UPLOAD, $ossFilesForm } from '@/http/apiManager.js';
// emit 父组件使用: v-model:src="val" 进行双向绑定。
const emit = defineEmits(['update:src', 'change']);
// 定义 父组件传参
const props = defineProps({
src: { type: String, default: '' }, // 双向绑定 文件地址
bizType: { type: String, default: '' }, // 业务类型
imgSize: { type: Number, default: 5 }, // 上传图片大小限制 默认 5 M
// 两种模式: img - 图片包含删除按钮支持删除, viewbtn-图片内支预览按钮切换。
mode: { type: String, default: 'img' },
// 预览模式, 不支持切换图片。
readonly: { type: Boolean, default: false }
});
// 定义响应式数据
const vdata = reactive({
showEnlarge: false,
action: '', // 文件form表单请求地址
uploadForm: {
action: '', // 请求地址
header: {}, // 请求头
params: {} // 参数
}
});
// 预览图片
function preview() {
if (props.mode == 'img') {
// 原生图片预览
uni.previewImage({ urls: [props.src] });
} else {
// 组件模式
vdata.showEnlarge = true;
}
}
// 删除图片
function delImg() {
emit('update:src', '');
emit('change', '');
}
// 选择图片 and 上传
function chooseImageAndUpload() {
// 最多选择一张图片 && 压缩图片 && 支持相册 和 相机
uni.chooseImage({ count: 1, sizeType: ['compressed'], sourceType: ['album', 'camera'] }).then((res) => {
let file = res.tempFiles[0];
// 预先检查
if (!beforeCheck(file)) {
return false;
}
// 检查通过
$ossFilesForm(props.bizType, file).then(({ bizData }) => {
// 本地方式
if (bizData.formActionUrl === 'LOCAL_SINGLE_FILE_URL') {
return http.upload(API_URL_SINGLE_FILE_UPLOAD, { bizType: props.bizType }, file).then(({ bizData }) => {
emit('update:src', bizData);
emit('change', bizData);
});
}
// oss 直传
uni.uploadFile({ url: bizData.formActionUrl, filePath: file.path, name: 'file', formData: bizData.formParams }).then((ossRes) => {
if (ossRes.statusCode == 200) {
// 上传成功
emit('update:src', bizData.ossFileUrl);
emit('change', bizData.ossFileUrl);
return false;
}
infoBox.showToast('oss服务响应异常');
});
});
});
}
function beforeCheck(file) {
return true;
}
defineExpose({
preview
});
</script>
<style lang="scss" scoped>
.default-img {
display: block;
width: 150rpx;
height: 150rpx;
background-color: #f7f7f7;
border-radius: 15rpx;
}
.image-wrapper {
position: relative;
width: 150rpx;
height: 150rpx;
margin-bottom: 20upx;
.del-image {
position: absolute;
top: -20rpx;
right: -20rpx;
z-index: 10;
width: 40rpx;
height: 40rpx;
border-radius: 50%;
background-color: tomato;
}
}
</style>