hn-hlw-app/pages/consult/self-auth/auth-action.vue

224 lines
5.7 KiB
Vue
Raw Normal View History

2026-08-12 15:20:15 +08:00
<template>
<full-page :customScroll="true" pageStyle="background: #f5f5f5;">
<view class="auth-page">
<view class="title">医保本人授权</view>
<view class="description">请核对就诊人信息并由就诊人本人完成医保授权</view>
<view v-if="patient" class="patient-card">
<view class="info-row">
<text class="label">姓名</text>
<text class="value">{{ patient.name || '--' }}</text>
</view>
<view class="info-row">
<text class="label">证件号</text>
<text class="value">{{ patient.certNo || '--' }}</text>
</view>
<view class="info-row">
<text class="label">年龄</text>
<text class="value">{{ patient.age === '' ? '--' : `${patient.age}` }}</text>
</view>
<view class="info-row">
<text class="label">性别</text>
<text class="value">{{ patient.sex || '--' }}</text>
</view>
</view>
<view v-else-if="errorMessage" class="state-card state-card--error">
<view>{{ errorMessage }}</view>
<view class="retry" @click="loadPatient">重新加载</view>
</view>
<view v-else class="state-card">正在加载就诊人信息...</view>
<view v-if="completed" class="success-card">
<view class="success-title">授权成功</view>
<view>医保建档已完成请返回原手机继续操作</view>
</view>
</view>
<template v-if="patient && !completed" #footer>
<footer-button :text="submitting ? '授权处理中...' : '确认授权'" @onClick="authorize" />
</template>
</full-page>
</template>
<script setup>
import { ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import useUser from "@/hooks/useUser";
import ybPlugin from "@/utils/insurance-plugin";
import { getSelfAuthPatient, submitSelfAuth } from "@/utils/api";
import { get, remove, set } from "@/utils/cache";
import { toast } from "@/utils/widget";
import fullPage from "@/components/full-page.vue";
import footerButton from "@/components/footer-button.vue";
const AUTH_ID_PATTERN = /^[a-f\d]{24}$/i;
const { getAuthCode, login, logined } = useUser();
const authId = ref("");
const patient = ref(null);
const errorMessage = ref("");
const submitting = ref(false);
const completed = ref(false);
function parseId(value) {
const id = typeof value === "string" ? value.trim() : "";
if (!AUTH_ID_PATTERN.test(id)) return false;
authId.value = id;
return true;
}
async function ensureLogin() {
if (!logined.value) await login();
if (!logined.value) throw new Error("登录失败,请重新进入授权页面");
}
async function loadPatient(autoAuth = false) {
errorMessage.value = "";
patient.value = null;
if (!authId.value) {
errorMessage.value = "授权链接无效";
return;
}
try {
await ensureLogin();
const { success, data, message } = await getSelfAuthPatient(authId.value);
if (!success || !data) throw new Error(message || "获取就诊人信息失败");
patient.value = data;
completed.value = data.status === "success";
if (autoAuth) {
authorize()
}
} catch (error) {
errorMessage.value = error.message || error || "获取就诊人信息失败";
}
}
async function completeAuthorization(psnToken) {
if (completed.value || submitting.value) return;
if (typeof psnToken !== "string" || !psnToken.trim()) {
toast("获取医保授权信息失败");
return;
}
submitting.value = true;
try {
const { success, message } = await submitSelfAuth(authId.value, psnToken.trim());
if (!success) throw new Error(message || "医保建档失败");
completed.value = true;
remove("self-auth-action-id");
toast("授权并建档成功");
} catch (error) {
toast(error.message || error || "医保建档失败");
} finally {
submitting.value = false;
}
}
async function authorize() {
if (!patient.value || submitting.value || completed.value) return;
try {
const authCode = await getAuthCode("nhsamp");
const psnToken = await ybPlugin.getArchiveToken(authCode);
if (psnToken) await completeAuthorization(psnToken);
} catch (error) {
toast(error.message || error || "获取医保授权失败");
}
}
onLoad(async (options) => {
const optionId = options && typeof options.id === "string" ? options.id : "";
const targetId = optionId || get("self-auth-action-id", "");
if (!parseId(targetId)) {
errorMessage.value = "授权链接无效";
return;
}
set("self-auth-action-id", authId.value, 10 * 60);
ybPlugin.init({
archiveTokenCallback: () => {
uni.redirectTo({
url: `/pages/consult/self-auth/auth-action?id=${optionId}&type=afterAuth`,
})
},
});
await loadPatient(options.type === 'afterAuth');
});
</script>
<style lang="scss" scoped>
.auth-page {
padding: 48rpx 30rpx;
}
.title {
color: #333;
font-size: 40rpx;
font-weight: 600;
text-align: center;
}
.description {
margin: 20rpx 0 40rpx;
color: #888;
font-size: 28rpx;
text-align: center;
}
.patient-card,
.state-card,
.success-card {
padding: 12rpx 30rpx;
background: #fff;
border-radius: 16rpx;
}
.info-row {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 92rpx;
border-bottom: 1rpx solid #eee;
}
.info-row:last-child {
border-bottom: 0;
}
.label {
color: #888;
}
.value {
color: #333;
}
.state-card {
padding: 50rpx 30rpx;
color: #888;
text-align: center;
}
.state-card--error {
color: #d9534f;
}
.retry {
margin-top: 28rpx;
color: #8b6538;
}
.success-card {
margin-top: 30rpx;
padding: 40rpx 30rpx;
color: #666;
text-align: center;
}
.success-title {
margin-bottom: 16rpx;
color: #2e9b58;
font-size: 36rpx;
font-weight: 600;
}
</style>