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