瑶都万能墙
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

255 lines
5.2 KiB

<template>
<view class="qrcode-container">
<navbar title="店铺二维码" leftClick @leftClick="$utils.navigateBack"/>
<!-- 加载状态 -->
<view class="loading-container" v-if="loading">
<view class="loading-spinner"></view>
<text class="loading-text">加载中...</text>
</view>
<!-- 二维码图片 -->
<view class="qrcode-wrapper" v-if="qrCodeUrl">
<image
class="qrcode-image"
:src="qrCodeUrl"
mode="aspectFit"
@load="imageLoaded"
@error="imageError"
@longpress="saveImage"
></image>
<text class="qrcode-tip" v-if="!loading && qrCodeUrl">扫描二维码查看店铺详情</text>
<text class="save-tip" v-if="!loading && qrCodeUrl">长按图片可保存到相册</text>
</view>
<!-- 错误状态 -->
<view class="error-container" v-if="!loading && !qrCodeUrl && hasError">
<text class="error-text">二维码加载失败,请重试</text>
<button class="retry-button" @click="loadQrCode">重新加载</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
shopId: '',
qrCodeUrl: '',
loading: true,
hasError: false,
}
},
onLoad(options) {
if (options.id) {
this.shopId = options.id;
this.loadQrCode();
} else {
this.loading = false;
this.hasError = true;
uni.showToast({
title: '缺少店铺ID参数',
icon: 'none'
});
}
},
methods: {
// 加载二维码
loadQrCode() {
if (!this.shopId) return;
this.loading = true;
this.hasError = false;
// 直接使用图片链接请求二维码
this.qrCodeUrl = `${this.$config.baseUrl}/city/shop/shopQrCode?id=${this.shopId}`;
// 由于image标签会自动处理加载状态,我们在imageLoaded和imageError中处理状态变化
},
// 图片加载成功
imageLoaded() {
this.loading = false;
},
// 图片加载失败
imageError() {
this.loading = false;
this.hasError = true;
this.qrCodeUrl = '';
uni.showToast({
title: '二维码加载失败',
icon: 'none'
});
},
// 保存图片到相册
saveImage() {
if (!this.qrCodeUrl) return;
uni.showLoading({
title: '保存中...'
});
// 下载图片
uni.downloadFile({
url: this.qrCodeUrl,
success: (res) => {
if (res.statusCode === 200) {
// 保存图片到相册
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
uni.hideLoading();
uni.showToast({
title: '保存成功',
icon: 'success'
});
},
fail: (err) => {
uni.hideLoading();
console.error('保存图片失败:', err);
// 如果是用户拒绝授权导致的失败
if (err.errMsg.indexOf('auth deny') >= 0 || err.errMsg.indexOf('authorize') >= 0) {
this.showAuthModal();
} else {
uni.showToast({
title: '保存失败',
icon: 'none'
});
}
}
});
} else {
uni.hideLoading();
uni.showToast({
title: '图片下载失败',
icon: 'none'
});
}
},
fail: () => {
uni.hideLoading();
uni.showToast({
title: '图片下载失败',
icon: 'none'
});
}
});
},
// 显示授权提示弹窗
showAuthModal() {
uni.showModal({
title: '提示',
content: '保存图片需要您授权访问相册权限',
confirmText: '去授权',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
// 打开设置页面
uni.openSetting({
success: (settingRes) => {
console.log('设置页面成功打开:', settingRes);
}
});
}
}
});
}
}
}
</script>
<style lang="scss" scoped>
.qrcode-container {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
background-color: #f5f5f5;
padding: 30rpx;
}
.loading-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-top: 200rpx;
.loading-spinner {
width: 80rpx;
height: 80rpx;
border: 6rpx solid #f3f3f3;
border-top: 6rpx solid #3B5CF0;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 20rpx;
}
.loading-text {
font-size: 28rpx;
color: #666;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
}
.qrcode-wrapper {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 100rpx;
background-color: #fff;
padding: 40rpx;
border-radius: 16rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
.qrcode-image {
width: 500rpx;
height: 500rpx;
margin-bottom: 30rpx;
}
.qrcode-tip {
font-size: 28rpx;
color: #666;
margin-top: 20rpx;
}
.save-tip {
font-size: 24rpx;
color: $uni-color-primary;
margin-top: 10rpx;
}
}
.error-container {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 200rpx;
.error-text {
font-size: 28rpx;
color: #999;
margin-bottom: 30rpx;
}
.retry-button {
background-color: #3B5CF0;
color: #fff;
font-size: 28rpx;
padding: 16rpx 40rpx;
border-radius: 40rpx;
border: none;
}
}
</style>