193 lines
4.4 KiB
Vue
193 lines
4.4 KiB
Vue
<script setup>
|
||
import { ref } from "vue";
|
||
import { onLoad } from "@dcloudio/uni-app";
|
||
import Container from "@/components/Container.vue";
|
||
import { getDeviceDetailAPI } from "@/apis";
|
||
import useStore from "@/store";
|
||
import { storeToRefs } from "pinia";
|
||
|
||
const store = useStore();
|
||
const { device } = storeToRefs(store);
|
||
const deviceId = ref("");
|
||
const qrImageUrl = ref("");
|
||
const qrSaved = ref(false);
|
||
const loading = ref(true);
|
||
|
||
const loadQrCode = async () => {
|
||
if (!deviceId.value) {
|
||
loading.value = false;
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await getDeviceDetailAPI(deviceId.value);
|
||
const detail = response?.detail || response?.data?.detail;
|
||
qrImageUrl.value = String(detail?.qrCodeUrl ?? "").trim();
|
||
} catch (error) {
|
||
console.error("获取设备二维码失败", error);
|
||
qrImageUrl.value = "";
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
const saveQrCode = async () => {
|
||
if (!qrImageUrl.value) return;
|
||
|
||
let filePath = qrImageUrl.value;
|
||
try {
|
||
if (/^https?:\/\//.test(filePath)) {
|
||
filePath = await new Promise((resolve, reject) => {
|
||
uni.downloadFile({
|
||
url: filePath,
|
||
success: (result) =>
|
||
result.statusCode === 200
|
||
? resolve(result.tempFilePath)
|
||
: reject(new Error("二维码下载失败")),
|
||
fail: reject,
|
||
});
|
||
});
|
||
}
|
||
|
||
await new Promise((resolve, reject) => {
|
||
uni.saveImageToPhotosAlbum({ success: resolve, fail: reject, filePath });
|
||
});
|
||
qrSaved.value = true;
|
||
uni.showToast({ title: "已保存至相册", icon: "success" });
|
||
} catch (error) {
|
||
uni.showToast({ title: "请长按二维码保存", icon: "none" });
|
||
}
|
||
};
|
||
|
||
onLoad((options = {}) => {
|
||
try {
|
||
deviceId.value = decodeURIComponent(options.deviceId || "") || device.value.deviceId || "";
|
||
} catch (error) {
|
||
deviceId.value = device.value.deviceId || "";
|
||
}
|
||
void loadQrCode();
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<Container :bgType="12" :scroll="false">
|
||
<view class="qr-page">
|
||
<view class="qr-corner qr-corner--top"></view>
|
||
<view class="qr-corner qr-corner--bottom"></view>
|
||
<view class="qr-canvas">
|
||
<text v-if="loading" class="qr-empty">二维码加载中...</text>
|
||
<template v-else-if="qrImageUrl">
|
||
<image class="qr-image" :src="qrImageUrl" mode="aspectFit" show-menu-by-longpress />
|
||
<text v-if="qrSaved" class="qr-device-id">设备ID:{{ deviceId }}</text>
|
||
<view v-else class="qr-save-button" @click="saveQrCode">
|
||
<text>保存至相册</text>
|
||
</view>
|
||
<text class="qr-description">
|
||
该二维码为当前绑定弓箭的二维码,你可以截图保存到相册,以便当二维码丢失或不在身边时,可以扫描二维码进行设备绑定。
|
||
</text>
|
||
<text class="qr-note">注:解除绑定后将无法查看该二维码。</text>
|
||
</template>
|
||
<text v-else class="qr-empty">暂无设备二维码</text>
|
||
</view>
|
||
</view>
|
||
</Container>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.qr-page {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 100%;
|
||
min-height: 0;
|
||
box-sizing: border-box;
|
||
overflow: hidden;
|
||
background: transparent;
|
||
}
|
||
|
||
.qr-corner {
|
||
position: absolute;
|
||
width: 300rpx;
|
||
height: 300rpx;
|
||
background: #ffeb00;
|
||
}
|
||
|
||
.qr-corner--top {
|
||
top: -220rpx;
|
||
right: -170rpx;
|
||
transform: rotate(42deg);
|
||
}
|
||
|
||
.qr-corner--bottom {
|
||
bottom: -220rpx;
|
||
left: -170rpx;
|
||
transform: rotate(42deg);
|
||
}
|
||
|
||
.qr-canvas {
|
||
position: relative;
|
||
z-index: 1;
|
||
display: flex;
|
||
width: 100%;
|
||
height: 100%;
|
||
min-height: 0;
|
||
box-sizing: border-box;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 260rpx 62rpx 70rpx;
|
||
}
|
||
|
||
.qr-image {
|
||
width: 432rpx;
|
||
height: 432rpx;
|
||
box-sizing: border-box;
|
||
background: #ffffff;
|
||
}
|
||
|
||
.qr-save-button {
|
||
display: flex;
|
||
width: 360rpx;
|
||
height: 72rpx;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-top: 34rpx;
|
||
border: 1rpx solid #e8c840;
|
||
border-radius: 36rpx;
|
||
color: #ffe846;
|
||
font-size: 26rpx;
|
||
}
|
||
|
||
.qr-device-id,
|
||
.qr-empty {
|
||
color: rgba(255, 255, 255, 0.72);
|
||
font-size: 26rpx;
|
||
line-height: 40rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.qr-device-id {
|
||
margin-top: 24rpx;
|
||
}
|
||
|
||
.qr-empty {
|
||
margin-top: 140rpx;
|
||
}
|
||
|
||
.qr-description,
|
||
.qr-note {
|
||
width: 100%;
|
||
color: rgba(255, 255, 255, 0.6);
|
||
font-size: 22rpx;
|
||
line-height: 36rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.qr-description {
|
||
margin-top: 42rpx;
|
||
}
|
||
|
||
.qr-note {
|
||
margin-top: 12rpx;
|
||
color: rgba(255, 232, 70, 0.7);
|
||
}
|
||
</style>
|