163 lines
4.9 KiB
Vue
163 lines
4.9 KiB
Vue
<template>
|
|
<full-page :customScroll="true">
|
|
<view class="qrcode-container">
|
|
<view class="qrcode-content">
|
|
<canvas id="auth-qrcode" canvas-id="auth-qrcode" class="qrcode-canvas"
|
|
:style="{ width: `${qrcodeSize}px`, height: `${qrcodeSize}px` }" />
|
|
<view class="tip">请使用就诊人本人的支付宝</view>
|
|
<view class="tip">扫描上方二维码授权</view>
|
|
</view>
|
|
</view>
|
|
<template #footer>
|
|
<footer-button :text="checking ? '查询中...' : '已授权'" @onClick="hasAuthed" />
|
|
</template>
|
|
</full-page>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed, ref } from "vue";
|
|
import { onLoad, onReady } from "@dcloudio/uni-app";
|
|
import UQRCode from "@/uni_modules/Sansnn-uQRCode/js_sdk/uqrcode/uqrcode.js";
|
|
import { get, remove, set } from "@/utils/cache";
|
|
import { getSelfAuthResult } from "@/utils/api";
|
|
import { toast } from "@/utils/widget";
|
|
|
|
import fullPage from "@/components/full-page.vue";
|
|
import footerButton from "@/components/footer-button.vue";
|
|
|
|
const baseQrcode = process.env.YB_AUTH_QRCODE;
|
|
const AUTH_ID_PATTERN = /^[a-f\d]{24}$/i;
|
|
|
|
const id = ref("");
|
|
const patient = ref(null);
|
|
const checking = ref(false);
|
|
const qrcodeValue = computed(() => id.value && patient.value ? `${baseQrcode}${id.value}` : "");
|
|
const qrcodeSize = Math.round(uni.upx2px(640));
|
|
|
|
function drawQrcode() {
|
|
const value = qrcodeValue.value;
|
|
if (!value) return;
|
|
try {
|
|
const qr = new UQRCode();
|
|
qr.data = value;
|
|
qr.size = qrcodeSize;
|
|
qr.make();
|
|
|
|
const context = uni.createCanvasContext("auth-qrcode");
|
|
const moduleCount = qr.moduleCount;
|
|
// 二维码四周至少保留 4 个模块的静区,并使用整数像素避免模块间出现白线。
|
|
const moduleSize = Math.max(1, Math.floor(qrcodeSize / (moduleCount + 8)));
|
|
const contentSize = moduleSize * moduleCount;
|
|
const offset = Math.floor((qrcodeSize - contentSize) / 2);
|
|
|
|
context.setFillStyle("#fff");
|
|
context.fillRect(0, 0, qrcodeSize, qrcodeSize);
|
|
context.setFillStyle("#000");
|
|
|
|
// 将每行相邻的黑色模块合并成一个矩形,避免支付宝 canvas
|
|
// 一次提交数千条绘制指令导致页面主线程阻塞。
|
|
for (let row = 0; row < moduleCount; row += 1) {
|
|
let runStart = -1;
|
|
for (let col = 0; col <= moduleCount; col += 1) {
|
|
const isBlack = col < moduleCount && qr.isBlack(row, col);
|
|
if (isBlack && runStart < 0) {
|
|
runStart = col;
|
|
} else if (!isBlack && runStart >= 0) {
|
|
context.fillRect(
|
|
offset + runStart * moduleSize,
|
|
offset + row * moduleSize,
|
|
(col - runStart) * moduleSize,
|
|
moduleSize
|
|
);
|
|
runStart = -1;
|
|
}
|
|
}
|
|
}
|
|
context.draw(false);
|
|
} catch (error) {
|
|
console.error("生成授权二维码失败", error);
|
|
toast("生成授权二维码失败,请重新进入页面");
|
|
}
|
|
}
|
|
|
|
async function hasAuthed() {
|
|
if (checking.value || !id.value || !patient.value) return;
|
|
checking.value = true;
|
|
try {
|
|
const { success, data, message } = await getSelfAuthResult(id.value);
|
|
if (!success || !data) {
|
|
toast(message || "查询授权结果失败");
|
|
return;
|
|
}
|
|
if (data.status === "success" && data.hisArchive) {
|
|
set("current-his-archive", data.hisArchive);
|
|
remove("auth-hlw-patient");
|
|
uni.redirectTo({
|
|
url: `/pages/consult/disease-description?socialno=${patient.value.certNo}&feeType=YB`,
|
|
});
|
|
return;
|
|
}
|
|
if (data.status === "failed") {
|
|
toast(data.errorMessage || message || "医保授权失败,请让就诊人重新授权");
|
|
return;
|
|
}
|
|
if (data.status === "expired") {
|
|
remove("auth-hlw-patient");
|
|
toast("授权链接已过期,请重新发起授权").then(() => uni.navigateBack());
|
|
return;
|
|
}
|
|
toast(data.status === "processing" ? "授权正在处理中,请稍后再试" : "尚未完成授权");
|
|
} catch (error) {
|
|
toast(error.message || error || "查询授权结果失败");
|
|
} finally {
|
|
checking.value = false;
|
|
}
|
|
}
|
|
|
|
onLoad((options) => {
|
|
id.value = options && typeof options.id === "string" ? options.id.trim() : "";
|
|
patient.value = get("auth-hlw-patient");
|
|
if (!AUTH_ID_PATTERN.test(id.value) || !patient.value || !patient.value.certNo) {
|
|
toast("就诊人无效,请重新选择").then(() => uni.navigateBack());
|
|
}
|
|
});
|
|
|
|
onReady(() => {
|
|
// 等待支付宝小程序完成 canvas 节点挂载后再绘制一次。
|
|
setTimeout(drawQrcode, 50);
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.qrcode-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 100%;
|
|
height: 100%;
|
|
text-align: center;
|
|
}
|
|
|
|
.qrcode-content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
transform: translateY(-60rpx);
|
|
}
|
|
|
|
.qrcode-canvas {
|
|
display: block;
|
|
background: #fff;
|
|
}
|
|
|
|
.tip {
|
|
font-size: 32rpx;
|
|
line-height: 52rpx;
|
|
color: #333;
|
|
font-weight: bold;
|
|
}
|
|
|
|
|
|
</style>
|