388 lines
8.8 KiB
Vue
388 lines
8.8 KiB
Vue
<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>
|