317 lines
6.1 KiB
Vue
317 lines
6.1 KiB
Vue
<template>
|
||
<view class="butler-page">
|
||
<!-- 页面加载状态 -->
|
||
<Loading type="page" :loading="pageLoading" />
|
||
|
||
<!-- 顶部背景图 -->
|
||
<view class="top-bg">
|
||
<image src="/static/title_bg.png" mode="aspectFill" class="bg-img" />
|
||
</view>
|
||
|
||
<!-- 自定义导航栏 -->
|
||
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||
<view class="navbar-content">
|
||
<view class="navbar-back" @click="handleBack">
|
||
<text class="back-icon">‹</text>
|
||
</view>
|
||
<text class="navbar-title">联系我们</text>
|
||
<view class="navbar-placeholder"></view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 内容区域 - 可滚动 -->
|
||
<scroll-view class="content-area" scroll-y
|
||
:style="{ marginTop: (statusBarHeight + 44) + 'px', height: 'calc(100vh - ' + (statusBarHeight + 44) + 'px)' }">
|
||
<view class="content-wrapper">
|
||
<view class="qrcode-card">
|
||
<!-- 二维码图片 -->
|
||
<view class="qrcode-wrapper">
|
||
<image v-if="butlerQrcode" class="qrcode-img" :src="butlerQrcode" mode="widthFix"
|
||
@click="previewQrcode" />
|
||
<view v-else class="qrcode-placeholder">
|
||
<text>暂无二维码</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 保存按钮 -->
|
||
<button class="btn-save" @click="saveQrcode" :disabled="!butlerQrcode || saving">
|
||
{{ saving ? '保存中...' : '保存图片' }}
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import {
|
||
ref,
|
||
computed,
|
||
onMounted
|
||
} from 'vue'
|
||
import {
|
||
useConfigStore
|
||
} from '@/store/config.js'
|
||
import {
|
||
getFullImageUrl
|
||
} from '@/utils/image.js'
|
||
import Loading from '@/components/Loading/index.vue'
|
||
|
||
const configStore = useConfigStore()
|
||
|
||
// 状态栏高度
|
||
const statusBarHeight = ref(20)
|
||
|
||
// 页面状态
|
||
const pageLoading = ref(true)
|
||
const saving = ref(false)
|
||
|
||
// 管家二维码
|
||
const butlerQrcode = computed(() => {
|
||
const qrcode = configStore.butlerQrcode
|
||
return qrcode ? getFullImageUrl(qrcode) : ''
|
||
})
|
||
|
||
// 获取系统信息
|
||
const getSystemInfo = () => {
|
||
try {
|
||
const res = uni.getSystemInfoSync()
|
||
statusBarHeight.value = res.statusBarHeight || 20
|
||
} catch (error) {
|
||
console.error('获取系统信息失败:', error)
|
||
}
|
||
}
|
||
|
||
// 返回上一页
|
||
const handleBack = () => {
|
||
uni.navigateBack()
|
||
}
|
||
|
||
// 预览二维码
|
||
const previewQrcode = () => {
|
||
if (!butlerQrcode.value) return
|
||
uni.previewImage({
|
||
urls: [butlerQrcode.value]
|
||
})
|
||
}
|
||
|
||
// 保存二维码到相册
|
||
const saveQrcode = async () => {
|
||
if (!butlerQrcode.value || saving.value) return
|
||
|
||
saving.value = true
|
||
|
||
try {
|
||
// 先下载图片
|
||
const downloadRes = await new Promise((resolve, reject) => {
|
||
uni.downloadFile({
|
||
url: butlerQrcode.value,
|
||
success: resolve,
|
||
fail: reject
|
||
})
|
||
})
|
||
|
||
if (downloadRes.statusCode !== 200) {
|
||
throw new Error('下载图片失败')
|
||
}
|
||
|
||
// 保存到相册
|
||
await new Promise((resolve, reject) => {
|
||
uni.saveImageToPhotosAlbum({
|
||
filePath: downloadRes.tempFilePath,
|
||
success: resolve,
|
||
fail: (err) => {
|
||
// 检查是否是权限问题
|
||
if (err.errMsg.includes('auth deny') || err.errMsg.includes(
|
||
'authorize')) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '需要您授权保存图片到相册',
|
||
confirmText: '去设置',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
uni.openSetting()
|
||
}
|
||
}
|
||
})
|
||
}
|
||
reject(err)
|
||
}
|
||
})
|
||
})
|
||
|
||
uni.showToast({
|
||
title: '保存成功',
|
||
icon: 'success'
|
||
})
|
||
} catch (error) {
|
||
console.error('保存图片失败:', error)
|
||
if (!error.errMsg?.includes('auth')) {
|
||
uni.showToast({
|
||
title: '保存失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
}
|
||
|
||
// 初始化页面
|
||
const initPage = async () => {
|
||
pageLoading.value = true
|
||
try {
|
||
getSystemInfo()
|
||
|
||
// 强制重新加载配置以获取最新的二维码
|
||
configStore.isLoaded = false
|
||
await configStore.loadAppConfig()
|
||
} catch (error) {
|
||
console.error('初始化页面失败:', error)
|
||
} finally {
|
||
pageLoading.value = false
|
||
}
|
||
}
|
||
|
||
onMounted(() => {
|
||
initPage()
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.butler-page {
|
||
height: 100vh;
|
||
background-color: #f5f6fa;
|
||
overflow: hidden;
|
||
}
|
||
|
||
// 顶部背景图
|
||
.top-bg {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 400rpx;
|
||
z-index: 0;
|
||
|
||
.bg-img {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
// 自定义导航栏
|
||
.custom-navbar {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 100;
|
||
|
||
.navbar-content {
|
||
height: 44px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0 24rpx;
|
||
|
||
.navbar-back {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.back-icon {
|
||
font-size: 56rpx;
|
||
color: #333;
|
||
font-weight: 300;
|
||
}
|
||
}
|
||
|
||
.navbar-title {
|
||
font-size: 34rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
|
||
.navbar-placeholder {
|
||
width: 80rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 内容区域
|
||
.content-area {
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
|
||
// 内容包裹层
|
||
.content-wrapper {
|
||
padding: 40rpx 0 80rpx;
|
||
}
|
||
|
||
// 二维码卡片
|
||
.qrcode-card {
|
||
background: #fff;
|
||
width: 90%;
|
||
margin: 0 auto;
|
||
border-radius: 24rpx;
|
||
padding: 60rpx 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
// 二维码容器
|
||
.qrcode-wrapper {
|
||
width: 100%;
|
||
max-width: 600rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 60rpx;
|
||
|
||
.qrcode-img {
|
||
width: 100%;
|
||
display: block;
|
||
}
|
||
|
||
.qrcode-placeholder {
|
||
width: 100%;
|
||
height: 100%;
|
||
background: #f5f5f5;
|
||
border-radius: 16rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
text {
|
||
font-size: 28rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 保存按钮
|
||
.btn-save {
|
||
width: 320rpx;
|
||
height: 88rpx;
|
||
line-height: 88rpx;
|
||
background: linear-gradient(135deg, #FFBDC2 0%, #FF8A93 100%);
|
||
border-radius: 44rpx;
|
||
font-size: 32rpx;
|
||
color: #fff;
|
||
border: none;
|
||
|
||
&::after {
|
||
border: none;
|
||
}
|
||
|
||
&[disabled] {
|
||
opacity: 0.6;
|
||
}
|
||
}
|
||
</style> |