2026-07-27 11:26:39 +08:00

388 lines
8.8 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<full-page pageStyle="background: #f5f6f7;">
<view v-if="logined" class="container" :class="{ 'container--elder': elderMode }">
<view class="header" :class="{ 'header--elder': elderMode }">
<text class="title" :class="{ 'title--elder': elderMode }">选择就诊人</text>
<button class="scan-button" :class="{ 'scan-button--elder': elderMode }">扫医保码</button>
</view>
<view class="patient-list">
<view v-for="patient in patientList" :key="patient.id" class="patient-card"
:class="{ 'patient-card--elder': elderMode }" @click="toggle(patient.id)">
<view class="patient-info">
<view class="name" :class="{ 'name--elder': elderMode }">
{{ patient.name }}
<text v-if="patient.isSelf" class="self-tag">本人</text>
</view>
<view class="details" :class="{ 'details--elder': elderMode }">
<text v-if="patient.sex">{{ patient.sex }}</text>
<text v-if="patient.age" class="age">{{ patient.age }}</text>
</view>
</view>
<uni-icons v-if="selectedPatientId === patient.id" type="checkbox-filled" color="#3375f6"
:size="elderMode ? 34 : 22" />
</view>
<view v-if="!patientList.length" class="empty-text">暂无就诊人</view>
</view>
</view>
<re-login v-else height="80vh" />
<template v-if="logined" #footer>
<view class="footer">
<view class="button-group" :class="{ 'button-group--elder': elderMode }">
<button class="action-button add-button" @click="toAddPatient">+ 新增就诊人</button>
<button class="action-button next-button" @click="nextStep">下一步</button>
</view>
<view class="manage-link" :class="{ 'manage-link--elder': elderMode }" @click="toPatientManagement">
<text>最多添加10位就诊人点击就诊人管理</text>
<uni-icons type="right" color="#8b8b8b" :size="elderMode ? 24 : 16" />
</view>
</view>
</template>
</full-page>
</template>
<script setup>
import { computed, ref, watch } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import useElder from "@/hooks/useElder";
import useUser from "@/hooks/useUser";
import { bindHisPatient, sm4Encrypt } from "@/utils/api";
import { toast } from "@/utils/widget";
import reLogin from "@/components/re-login.vue";
import ybPlugin from "@/utils/insurance-plugin";
import fullPage from "@/components/full-page.vue";
const { elderMode } = useElder();
const {
logined,
getAuthCode,
myProfile,
familyProfile,
getProfileData,
patientList: storePatientList,
loadPatientList,
} = useUser();
const titleMap = {
YB: "医保处方",
ZF: "自费处方",
};
const selectedPatientId = ref("");
const preferredCertNo = ref("");
const feeType = ref("");
const patientList = computed(() => {
const list = [...storePatientList.value].sort((a, b) => {
return new Date(a.createTime).getTime() - new Date(b.createTime).getTime();
});
return feeType.value === "YB" ? list.filter(patient => patient.isSelf) : list;
});
const currentProfile = computed(() => {
return patientList.value.find(patient => patient.id === selectedPatientId.value);
});
onLoad(options => {
feeType.value = options.feeType;
preferredCertNo.value = options.socialno || "";
uni.setNavigationBarTitle({
title: titleMap[options.feeType] || "",
});
ybPlugin.init({
archiveTokenCallback: () => {
const certNo = currentProfile.value ? currentProfile.value.certNo : "";
uni.redirectTo({
url: `/pages/consult/index?socialno=${certNo}&feeType=${feeType.value}`,
});
},
});
});
onShow(async () => {
if (logined.value) {
await loadPatientList();
selectDefaultPatient();
}
});
watch(logined, value => {
if (value) loadPatientList();
});
function selectDefaultPatient() {
const selectedExists = patientList.value.some(patient => patient.id === selectedPatientId.value);
if (selectedExists) return;
const preferred = patientList.value.find(patient => patient.certNo === preferredCertNo.value);
const self = patientList.value.find(patient => patient.isSelf);
selectedPatientId.value = (preferred || self || patientList.value[0] || {}).id || "";
}
watch(patientList, selectDefaultPatient, { immediate: true });
async function nextStep() {
if (!currentProfile.value) {
toast("请选择就诊人");
return;
}
if (feeType.value === 'YB' && false) {
// 医保暂只支持支本人, 进行医保授权操作
const self = currentProfile.value.isSelf;
const authCode = await getAuthCode("nhsamp");
let archiveParams = [authCode];
if (!self) {
const encrypted = await getEncryptedPatientInfo(currentProfile.value);
archiveParams = [authCode, encrypted.anotherIdNo, encrypted.anotherName];
}
const psnToken = await ybPlugin.getArchiveToken(...archiveParams);
if (!psnToken) return;
try {
await bindInsurance(
psnToken,
currentProfile.value.certNo,
currentProfile.value.name,
currentProfile.value.mobile,
);
uni.navigateTo({
url: `/pages/consult/disease-description?socialno=${currentProfile.value.certNo}&type=${type.value}&authDrugRecord=${authDrugRecord.value}`,
});
} catch (error) {
toast(error.message || error);
}
}
uni.navigateTo({
url: `/pages/consult/disease-description?socialno=${currentProfile.value.certNo}&feeType=${feeType.value}`,
});
}
async function getEncryptedPatientInfo(patient) {
const res = await sm4Encrypt({ textGroup: [patient.certNo, patient.name] });
if (!res || !res.success || !Array.isArray(res.textGroup) || res.textGroup.length < 2) {
return Promise.reject((res && res.message) || "获取就诊人加密信息失败");
}
return {
anotherIdNo: res.textGroup[0],
anotherName: res.textGroup[1],
};
}
async function bindInsurance(psnToken, idCard, name, mobile) {
const { success, list, message } = await bindHisPatient({ idCard, name, mobile, psnToken });
const patients = Array.isArray(list) ? list : [];
const patient = patients.find(item => item.socialno === idCard) || patients[0] || null;
if (!success || !patient) {
return Promise.reject(message || "医保建档失败");
}
if (patient.isyb !== "1") {
return Promise.reject("当前用户为非医保用户");
}
if (myProfile.value && myProfile.value.socialno === patient.socialno) {
myProfile.value = getProfileData(patient);
return;
}
const index = familyProfile.value.findIndex(item => item.socialno === patient.socialno);
if (index >= 0) familyProfile.value[index] = getProfileData(patient);
}
function toggle(patientId) {
selectedPatientId.value = patientId;
}
function toAddPatient() {
uni.navigateTo({
url: `/pages/member/detail`,
});
}
function toPatientManagement() {
uni.navigateTo({ url: "/pages/member/list" });
}
</script>
<style lang="scss" scoped>
.container {
min-height: 100%;
box-sizing: border-box;
padding: 0 16rpx 24rpx;
}
.header {
height: 104rpx;
padding: 0 34rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.title {
font-size: 28rpx;
color: #222;
}
.scan-button {
width: 164rpx;
height: 64rpx;
margin: 0;
padding: 0;
border-radius: 4rpx;
background: #3375f6;
color: #fff;
font-size: 26rpx;
line-height: 64rpx;
}
.scan-button::after,
.action-button::after {
border: none;
}
.patient-list {
background: #eceeef;
}
.patient-card {
min-height: 118rpx;
box-sizing: border-box;
padding: 18rpx 34rpx;
background: #fff;
display: flex;
align-items: center;
justify-content: space-between;
}
.patient-card+.patient-card {
margin-top: 8rpx;
}
.patient-info {
display: flex;
flex-direction: column;
}
.name {
font-size: 28rpx;
line-height: 40rpx;
color: #333;
}
.self-tag {
color: #116f38;
}
.details {
margin-top: 4rpx;
font-size: 24rpx;
line-height: 34rpx;
color: #9a9a9a;
}
.age {
margin-left: 10rpx;
}
.empty-text {
padding: 80rpx 0;
background: #fff;
text-align: center;
font-size: 26rpx;
color: #999;
}
.footer {
padding: 18rpx 24rpx 12rpx;
background: #fff;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.06);
}
.button-group {
display: flex;
gap: 22rpx;
}
.action-button {
height: 72rpx;
margin: 0;
padding: 0;
border-radius: 4rpx;
font-size: 28rpx;
line-height: 70rpx;
}
.add-button {
width: 244rpx;
border: 2rpx solid #3375f6;
background: #fff;
color: #3375f6;
}
.next-button {
flex: 1;
background: #3375f6;
color: #fff;
}
.manage-link {
min-height: 50rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 23rpx;
color: #8b8b8b;
}
.container--elder {
padding: 0 24rpx 32rpx;
}
.header--elder {
height: 128rpx;
}
.title--elder {
font-size: 38rpx;
}
.scan-button--elder {
width: 196rpx;
height: 80rpx;
font-size: 34rpx;
line-height: 80rpx;
}
.patient-card--elder {
min-height: 156rpx;
padding: 24rpx 40rpx;
}
.name--elder {
font-size: 38rpx;
line-height: 52rpx;
}
.details--elder {
font-size: 32rpx;
line-height: 44rpx;
}
.button-group--elder .action-button {
height: 92rpx;
font-size: 36rpx;
line-height: 90rpx;
}
.manage-link--elder {
min-height: 68rpx;
font-size: 30rpx;
}
</style>