mrr.sj.front/pages/shop/photoAlbum/addPhoto.vue

718 lines
19 KiB
Vue
Raw Normal View History

2026-03-24 11:45:13 +08:00
<template>
<view class="container">
<custom-navbar :title="pageTexts[formData.type][formData.class_type].title1"
:leftImg="'/static/images/back.png'" :showUser="true" backgroundColor="#fff" titleColor="#000"
borderBottom="none"></custom-navbar>
<view class="review" v-if="imgItem.apply_state==1">
<view class="review-title">
<text class="review-title-text">审核中</text>
</view>
<text class="review-text">预计24小时完成审核通过后将自动生效</text>
</view>
<view class="review" v-if="imgItem.apply_state==2">
<view class="review-title">
<text class="review-title-text">审核成功<text style="color: #E8101E;">线上展示中</text></text>
</view>
</view>
<view class="review" v-if="imgItem.apply_state==3">
<view class="review-title">
<text class="review-title-text">已驳回</text>
</view>
<text class="review-text" v-if="imgItem.back_text">驳回原因{{ imgItem.back_text }}</text>
</view>
<view :class="{haveReview:imgItem.apply_state}">
<view class="container-card">
<view class="card-header">
<text class="card-title">{{ pageTexts[formData.type][formData.class_type].title2 }}</text>
<text class="card-title2">({{ formData.type==1?"上传1张照片":"上传1个视频" }})</text>
</view>
<view class="card-content flex-row-center-center" v-if="formData.type==1">
<view class="card-content-container">
<image v-if="formData.url" :src="formData.url" mode="aspectFill" class="preview-image"></image>
<view class="content-default" @click="chooseImage" v-else>
<image class="content-default-img" src="/static/images/icons/addPhoto.png"></image>
<text class="content-default-text">添加照片</text>
</view>
<view class="content-photo-title" v-if="formData.url" @click.stop="chooseImage">
替换图片
</view>
</view>
</view>
<view class="card-content flex-row-center-center" v-else>
<view class="card-content-container">
<image v-if="formData.url" @click="goVideo"
:src="formData.url+`?x-oss-process=video/snapshot,t_1000,m_fast,f_jpg,w_600,ar_auto`"
mode="aspectFill" class="preview-video"></image>
<view class="content-default2" @click="chooseImage" v-else>
<image class="content-default2-img" src="/static/images/icons/addPhoto.png"></image>
<text class="content-default2-text">添加视频</text>
</view>
<view class="content-photo-title" @click.stop="chooseImage" v-if="formData.url">
替换视频
</view>
<view class="content-photo-play" v-if="formData.url">
<image class="content-photo-play-img" mode="aspectFill" src="/static/images/icons/play.png">
</image>
</view>
</view>
</view>
</view>
<view class="container-card">
<view class="card-header">
<text class="card-title">{{ formData.type==1?"图片名称":"视频名称" }}</text>
</view>
<view class="card-content">
<view class="card-content-input">
<input maxlength="6" :placeholder="formData.type==1?`请输入图片名称`:`请输入视频名称`" v-model="formData.name"
placeholder-class="inputClass" :disabled="disabled" />
</view>
</view>
</view>
</view>
<!-- <view class="container-buttons flex-row-center-center" v-if="">
<view class="container-buttons-cancel flex-row-center-center">取消</view>
<view class="container-buttons-sure flex-row-center-center" @click="submitPhoto">提交</view>
</view> -->
<view class="container-buttons flex-row-center-center" v-if="imgItem.apply_state">
<view class="container-buttons-sure2 flex-row-center-center" v-if="disabled==true"
@click="disabled = false">编辑</view>
<view class="container-buttons-cancel flex-row-center-center" v-if="disabled==false"
@click="disabled = true">取消</view>
<view class="container-buttons-sure flex-row-center-center" @click="editPhoto" v-if="disabled==false">提交
</view>
</view>
<view class="container-buttons flex-row-center-center" v-else>
<view class="container-buttons-sure2 flex-row-center-center" @click="submitPhoto">提交</view>
</view>
<!-- 获取权限提示匡内容 -->
<view class="permission" :class="{ transform: isShowPer && nowQer === 'xc' }">
<view class="per-tit">美融融plus 对储存空间/照片权限申请说明</view>
<view class="per-cont">便于您使用该功能上传您的照片/图片/视频以及用于更换头像发布商品等场景中读取相册和文件内容</view>
</view>
<view class="permission" :class="{ transform: isShowPer && nowQer === 'xj' }">
<view class="per-tit">美融融plus 对相机拍摄权限申请说明</view>
<view class="per-cont">便于您使用该功能上传您的照片/图片/视频以及用于更换头像发布商品等场景中所需内容</view>
</view>
<video v-show="videoPlay" :src="videoUrl" controls id="myvideo" style="height: 0; width: 0; position: absolute; top: -999rpx; left: -999rpx;"
@fullscreenchange="screenChange"></video>
<uv-divider></uv-divider>
</view>
</template>
<script>
import request from "@/utils/request";
import uploadImage from '@/utils/albumUploadImage';
import permissionUtils from '@/utils/per';
import locationService from '@/utils/locationService';
export default {
components: {
},
data() {
return {
videoContext:null,
videoPlay: false,
videoUrl: "",
disabled: false,
isShowPer: false,
nowQer: 'xc',
formData: {
name: "",
url: "",
class_type: 1, //1主(图片/视频) 2环境(图片/视频) 3作品(图片/视频) 4其它(图片/视频)
type: 1, //1图片 2视频
},
pageTexts: {
1: {
1: {
title1: '添加店铺图片',
title2: '店铺主图',
},
2: {
title1: '添加环境图片',
title2: '环境图片',
},
3: {
title1: '添加作品图片',
title2: '作品图片',
},
4: {
title1: '添加其它图片',
title2: '其它图片',
},
},
2: {
1: {
title1: '添加店铺视频',
title2: '店铺主视频',
},
2: {
title1: '添加环境视频',
title2: '环境视频',
},
3: {
title1: '添加作品视频',
title2: '作品视频',
},
4: {
title1: '添加其它视频',
title2: '其它视频',
},
},
},
userInfo: {},
isSubmitting: false,
imgItem: {}
}
},
async onLoad(options) {
if (options.id) {
this.formData.class_type = options.id;
}
if (options.type) {
this.formData.type = options.type;
}
if (options.item) {
try {
this.imgItem = JSON.parse(decodeURIComponent(options.item));
this.formData.name = this.imgItem.auth_name
this.formData.url = this.imgItem.auth_url
this.formData.id = this.imgItem.id
this.formData.auth_id = this.imgItem.auth_id
this.disabled = true
} catch (e) {
}
}
let type = 3;
let result = await request.post("/user/getuser", {
type,
});
this.userInfo = result.data;
},
methods: {
screenChange(e) {
let fullScreen = e.detail.fullScreen; // 值true为进入全屏false为退出全屏
console.log(e, "全屏");
if (!fullScreen) {
//退出全屏
this.videoContext.pause()
plus.screen.lockOrientation('portrait-primary');
this.videoPlay = false; // 隐藏播放盒子
}
},
goVideo() {
// let urls = [this.formData.url]
// uni.navigateTo({
// url: `/pages/album/list?urls=${encodeURIComponent(JSON.stringify(urls))}`
// });
this.videoPlay = true; // 显示播放盒子
this.videoContext = uni.createVideoContext("myvideo", this); // this这个是实例对象 必传
this.videoUrl = this.formData.url;
this.videoContext.requestFullScreen({
direction: 90
});
this.videoContext.play();
},
async submitPhoto() {
// 1. 防连点核心逻辑如果正在提交中直接return阻止后续执行
if (this.isSubmitting) return;
// 2. 表单必填项校验:校验图片和名称是否填写
if (!this.formData.url) {
uni.showToast({
title: '请先上传店铺主图',
icon: 'none',
duration: 2000
});
return
}
if (!this.formData.name || this.formData.name.trim() === '') {
uni.showToast({
title: '请输入图片名称',
icon: 'none',
duration: 2000
});
return
}
try {
// 3. 开启提交锁 + 显示加载中提示
this.isSubmitting = true;
uni.showLoading({
title: '提交中...',
mask: true
});
// 4. 提交接口请求 【修复原代码传参BUGformData → this.formData】
const res = await request.post("/sj/imgVideo/add", this.formData);
if (res.code == 200) {
// 5. 提交成功:提示 + 延时返回上一页(用户能看到提示)
uni.showToast({
title: '提交成功',
icon: 'success'
});
setTimeout(() => {
uni.navigateBack({
delta: 1
}); // 返回上一级页面,核心需求
}, 1500);
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
});
}
} catch (err) {
// 6. 提交失败:异常提示
console.error('图片提交失败:', err);
uni.showToast({
title: '提交失败,请稍后重试',
icon: 'none',
duration: 2000
});
} finally {
// 7. 核心兜底:无论成功/失败/报错,都关闭加载 + 释放提交锁
uni.hideLoading();
this.isSubmitting = false;
}
},
async editPhoto() {
// 1. 防连点核心逻辑如果正在提交中直接return阻止后续执行
if (this.isSubmitting) return;
// 2. 表单必填项校验:校验图片和名称是否填写
if (!this.formData.url) {
uni.showToast({
title: '请先上传店铺主图',
icon: 'none',
duration: 2000
});
return
}
if (!this.formData.name || this.formData.name.trim() === '') {
uni.showToast({
title: '请输入图片名称',
icon: 'none',
duration: 2000
});
return
}
try {
// 3. 开启提交锁 + 显示加载中提示
this.isSubmitting = true;
uni.showLoading({
title: '提交中...',
mask: true
});
// 4. 提交接口请求 【修复原代码传参BUGformData → this.formData】
const res = await request.post("/sj/imgVideo/edit", this.formData);
if (res.code == 200) {
// 5. 提交成功:提示 + 延时返回上一页(用户能看到提示)
uni.showToast({
title: '提交成功',
icon: 'success'
});
setTimeout(() => {
uni.navigateBack({
delta: 1
}); // 返回上一级页面,核心需求
}, 1500);
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
});
}
} catch (err) {
// 6. 提交失败:异常提示
console.error('图片提交失败:', err);
uni.showToast({
title: '提交失败,请稍后重试',
icon: 'none',
duration: 2000
});
} finally {
// 7. 核心兜底:无论成功/失败/报错,都关闭加载 + 释放提交锁
uni.hideLoading();
this.isSubmitting = false;
}
},
// 打开相机
async openCamera() {
this.isShowPer = false;
let res = null
try {
uni.showLoading({
title: '上传中'
})
if (this.formData.type == 1) {
res = await uploadImage.handleUpload(this.userInfo.id, 3);
} else {
res = await uploadImage.handleUpload(this.userInfo.id, 3, ['album', 'camera'],
'video');
}
console.log('上传单张图片', res)
this.formData.url = res;
} catch (err) {
console.log(err)
uni.showToast({
title: '上传失败',
icon: 'none'
}); // 新增:上传失败提示
} finally {
uni.hideLoading(); // 移到这里,必执行
}
},
// 显示权限说明弹窗
showPermissionDialog(title, content) {
return new Promise((resolve) => {
uni.showModal({
title,
content,
confirmText: '去开启',
success(res) {
resolve(res.confirm);
}
});
});
},
// 选择图片
async chooseImage() {
if (this.disabled) return
try {
const systemInfo = uni.getSystemInfoSync()
if (systemInfo.platform === 'ios') {
this.openCamera();
} else {
let xcpermission = '';
let xjpermission = '';
if (systemInfo.platform === 'ios') {
xcpermission = 'photo_library',
xjpermission = 'camera'
} else {
xcpermission =
`android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE`
xjpermission = 'android.permission.CAMERA'
}
const xjfirstRequest = !plus.storage.getItem(`perm_${xjpermission}`)
const xcfirstRequest = !plus.storage.getItem(`perm_${xcpermission}`)
if (xcfirstRequest || xjfirstRequest) {
this.isShowPer = true;
}
// 1. 检查权限
// const { granted } = await permissionUtils.checkPermission('photo_library', '需要相册权限用于上传照片');
this.nowQer = 'xc';
const xc = await permissionUtils.checkPermission('photo_library',
'需要相册权限用于上传照片');
this.nowQer = 'xj';
const xj = await permissionUtils.checkPermission('camera', '需要相机权限用于拍摄照片');
this.isShowPer = false;
this.nowQer = '';
if (xc.granted && xj.granted) {
this.openCamera();
return;
}
// 2. 显示权限说明弹窗
const confirm = await this.showPermissionDialog(
'相机相册权限申请',
'我们需要访问您的相机以及相册以完成更换头像功能'
);
if (!confirm) return;
// 3. 请求权限
const result1 = await permissionUtils.requestPermission('photo_library',
'我们需要访问您的相册以上传图片/视频');
const result2 = await permissionUtils.requestPermission('camera',
'我们需要访问您的相机以上传图片/视频');
if (result1 && result2) {
this.openCamera();
} else {
locationService.openAppSettings();
// uni.showToast({ title: '相机权限被拒绝', icon: 'none' });
}
}
} catch (err) {
console.log(err)
}
},
}
}
</script>
<style lang="less">
.container {
.review {
background: #FAE7EC;
border-radius: 20rpx 20rpx 0rpx 0rpx;
margin: 20rpx;
padding: 26rpx 20rpx 30rpx 20rpx;
.review-title {
margin-bottom: 6rpx;
.review-title-text {
font-weight: 500;
font-size: 28rpx;
color: #E8101E;
line-height: 40rpx;
text-align: left;
font-style: normal;
}
}
.review-text {
font-weight: 400;
font-size: 24rpx;
color: #A43F45;
line-height: 33rpx;
text-align: left;
font-style: normal;
}
}
.container-card {
border-radius: 20rpx;
margin: 20rpx;
padding: 20rpx 20rpx 30rpx 20rpx;
background: #fff;
.card-header {
margin-bottom: 20rpx;
.card-title {
font-weight: 500;
font-size: 28rpx;
color: #1D2129;
line-height: 48rpx;
text-align: left;
font-style: normal;
}
.card-title2 {
font-weight: 400;
font-size: 24rpx;
color: #999999;
line-height: 33rpx;
text-align: left;
font-style: normal;
margin-left: 10rpx;
}
}
.card-content {
.card-content-container {
position: relative;
display: flex;
overflow: hidden;
border-radius: 20rpx;
}
.preview-image {
width: 370rpx;
height: 278rpx;
border-radius: 20rpx;
}
.preview-video {
width: 520rpx;
height: 220rpx;
border-radius: 20rpx;
}
.content-default {
width: 370rpx;
height: 278rpx;
background: #F5F5F5;
border-radius: 20rpx;
background: #F5F5F5;
border-radius: 20rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.content-default-img {
width: 42rpx;
height: 35rpx;
margin-bottom: 8rpx;
}
.content-default-text {
font-weight: 400;
font-size: 22rpx;
color: #666666;
line-height: 30rpx;
text-align: left;
font-style: normal;
display: block;
}
}
.content-default2 {
width: 520rpx;
height: 220rpx;
background: #F5F5F5;
border-radius: 20rpx;
background: #F5F5F5;
border-radius: 20rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.content-default2-img {
width: 42rpx;
height: 35rpx;
margin-bottom: 8rpx;
}
.content-default2-text {
font-weight: 400;
font-size: 22rpx;
color: #666666;
line-height: 30rpx;
text-align: left;
font-style: normal;
display: block;
}
}
.content-photo-title {
background: rgba(51, 51, 51, 0.6);
padding: 8rpx 0 6rpx 0;
position: absolute;
left: 0;
right: 0;
bottom: 0;
font-weight: 400;
font-size: 24rpx;
color: #FFFFFF;
line-height: 33rpx;
text-align: center;
font-style: normal;
}
.content-photo-play {
width: 25rpx;
height: 25rpx;
position: absolute;
right: 10rpx;
top: 6rpx;
.content-photo-play-img {
width: 25rpx;
height: 25rpx;
}
}
.card-content-input {
width: 670rpx;
height: 76rpx;
background: #F5F5F5;
border-radius: 20rpx;
box-sizing: border-box;
padding: 18rpx 20rpx;
.inputClass {
font-weight: 400;
font-size: 28rpx;
color: #BFBFBF;
line-height: 40rpx;
text-align: left;
font-style: normal;
}
}
}
}
.haveReview {
transform: translateY(-30rpx);
}
.container-buttons {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding: 30rpx 0;
background: #FFFFFF;
gap: 60rpx;
.container-buttons-cancel {
width: 278rpx;
height: 98rpx;
border-radius: 49rpx;
border: 1rpx solid #E8101E;
font-weight: 400;
font-size: 32rpx;
color: #E8101E;
text-align: center;
font-style: normal;
}
.container-buttons-sure {
width: 278rpx;
height: 98rpx;
background: #E8101E;
border-radius: 49rpx;
font-weight: 400;
font-size: 32rpx;
color: #FFFFFF;
text-align: center;
font-style: normal;
}
.container-buttons-sure2 {
width: 710rpx;
height: 98rpx;
background: #E8101E;
border-radius: 49rpx;
font-weight: 400;
font-size: 38rpx;
color: #FFFFFF;
text-align: left;
font-style: normal;
}
}
}
/* APP适配 */
/* #ifdef APP-PLUS */
.permission.transform {
top: calc(var(--status-bar-height) + 108rpx + 20rpx);
opacity: 1;
visibility: visible;
}
/* #endif */
</style>