fix: 需求开发

This commit is contained in:
huxuejian 2026-07-31 16:21:41 +08:00
parent 875eccc803
commit 5e84eae788
9 changed files with 239 additions and 50 deletions

View File

@ -5,10 +5,10 @@ export default function useUser() {
const store = userStore(); const store = userStore();
const { drugStore, familyProfile, logined, myProfile, patientList, storeId, userInfo } = storeToRefs(store); const { drugStore, familyProfile, logined, myProfile, patientList, storeId, userInfo } = storeToRefs(store);
const { getAuthCode, getFamilyProfile, getStore, loadPatientList, login, loginout, getProfileData } = store; const { getAuthCode, getFamilyProfile, getStore, loadPatientList, login, loginout, getProfileData, setTemporaryPatient } = store;
return { return {
drugStore, familyProfile, logined, myProfile, patientList, storeId, userInfo, drugStore, familyProfile, logined, myProfile, patientList, storeId, userInfo,
getAuthCode, getFamilyProfile, getStore, loadPatientList, login, loginout, getProfileData getAuthCode, getFamilyProfile, getStore, loadPatientList, login, loginout, getProfileData, setTemporaryPatient
}; };
// const { userInfo, logined, maskName, maskMobile, maskCertNo, cards, card, idCardInfo, storeId, drugStore, getFamilyProfile, familyProfile } = storeToRefs(store); // const { userInfo, logined, maskName, maskMobile, maskCertNo, cards, card, idCardInfo, storeId, drugStore, getFamilyProfile, familyProfile } = storeToRefs(store);
// const { login, loginout, getAuthCode, getStore } = store; // const { login, loginout, getAuthCode, getStore } = store;

View File

@ -22,7 +22,7 @@
"title": "【开发】支付宝", "title": "【开发】支付宝",
"env": { "env": {
"UNI_PLATFORM": "mp-alipay", "UNI_PLATFORM": "mp-alipay",
"API_BASE_URL": "http://192.168.170.62:8080", "API_BASE_URL": "http://192.168.31.146:8080",
"CORP_ID": "4G7H8J2K9L0M1N3P5Q6R7S8T9U", "CORP_ID": "4G7H8J2K9L0M1N3P5Q6R7S8T9U",
"APP_ID": "2021004129669493", "APP_ID": "2021004129669493",
"ORDER_SOURCE": "ALIPAY_MINI", "ORDER_SOURCE": "ALIPAY_MINI",

View File

@ -3,7 +3,8 @@
<view v-if="logined" class="container" :class="{ 'container--elder': elderMode }"> <view v-if="logined" class="container" :class="{ 'container--elder': elderMode }">
<view class="header" :class="{ 'header--elder': elderMode }"> <view class="header" :class="{ 'header--elder': elderMode }">
<text class="title" :class="{ 'title--elder': elderMode }">选择就诊人</text> <text class="title" :class="{ 'title--elder': elderMode }">选择就诊人</text>
<button class="scan-button" :class="{ 'scan-button--elder': elderMode }">扫医保码</button> <button class="scan-button" :class="{ 'scan-button--elder': elderMode }" :disabled="scanning"
@click="scanInsuranceCode">{{ scanning ? "读取中..." : "扫医保码" }}</button>
</view> </view>
<view class="patient-list"> <view class="patient-list">
@ -49,7 +50,7 @@ import { computed, ref, watch } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app"; import { onLoad, onShow } from "@dcloudio/uni-app";
import useElder from "@/hooks/useElder"; import useElder from "@/hooks/useElder";
import useUser from "@/hooks/useUser"; import useUser from "@/hooks/useUser";
import { bindHisPatient, getHisCustomer } from "@/utils/api"; import { bindHisPatient, getHisCustomer, getScannedCard } from "@/utils/api";
import { set } from "@/utils/cache"; import { set } from "@/utils/cache";
import { toast } from "@/utils/widget"; import { toast } from "@/utils/widget";
@ -64,6 +65,7 @@ const {
myProfile, myProfile,
familyProfile, familyProfile,
getProfileData, getProfileData,
storeId,
patientList: storePatientList, patientList: storePatientList,
loadPatientList, loadPatientList,
} = useUser(); } = useUser();
@ -76,9 +78,12 @@ const titleMap = {
const selectedPatientId = ref(""); const selectedPatientId = ref("");
const preferredCertNo = ref(""); const preferredCertNo = ref("");
const feeType = ref(""); const feeType = ref("");
const scanning = ref(false);
const patientList = computed(() => { const patientList = computed(() => {
const list = [...storePatientList.value].sort((a, b) => { const list = storePatientList.value
.filter(patient => !patient.isTemporary)
.sort((a, b) => {
return new Date(a.createTime).getTime() - new Date(b.createTime).getTime(); return new Date(a.createTime).getTime() - new Date(b.createTime).getTime();
}); });
return feeType.value === "YB" ? list.filter(patient => patient.isSelf) : list; return feeType.value === "YB" ? list.filter(patient => patient.isSelf) : list;
@ -128,6 +133,49 @@ function selectDefaultPatient() {
watch(patientList, selectDefaultPatient, { immediate: true }); watch(patientList, selectDefaultPatient, { immediate: true });
function scanCode() {
return new Promise((resolve, reject) => {
uni.scanCode({
onlyFromCamera: true,
scanType: ["qrCode"],
success: resolve,
fail: reject,
});
});
}
async function scanInsuranceCode() {
if (scanning.value) return;
scanning.value = true;
try {
const scanResult = await scanCode();
const id = typeof scanResult.result === "string" ? scanResult.result.trim() : "";
if (!/^[a-f\d]{24}$/i.test(id)) {
toast("医保二维码无效");
return;
}
const res = await getScannedCard({ id, storeId: storeId.value });
if (!res || !res.success || !res.data) {
toast((res && res.message) || "获取医保信息失败");
return;
}
if (!res.data.Name || !res.data.IDNum || !res.data.CardNum || !res.data.CardIDCode) {
toast("医保信息不完整,请重新读卡");
return;
}
set("current-scanned-card", res.data, 300);
uni.navigateTo({
url: `/pages/member/detail?type=ybQrcode&feeType=${feeType.value}`,
});
} catch (error) {
if (!error || !/cancel/i.test(error.errMsg || error.message || "")) {
toast(error.message || error.errMsg || error || "扫码失败");
}
} finally {
scanning.value = false;
}
}
async function nextStep() { async function nextStep() {
if (!currentProfile.value) { if (!currentProfile.value) {
toast("请选择就诊人"); toast("请选择就诊人");

View File

@ -56,6 +56,8 @@
</view> </view>
</full-page> </full-page>
<store-popup :drugStore="drugStore" :visible="visible" :elderMode="elderMode" @confirm="confirmStoreInfo()"
@close="visible = false" />
<confirm-popup title="提示" content="您是否半年内在医院就诊过?" cancelText="否" confirmText="是" :visible="confirmVisible" <confirm-popup title="提示" content="您是否半年内在医院就诊过?" cancelText="否" confirmText="是" :visible="confirmVisible"
@confirm="handleConfirmYes" @cancel="handleConfirmNo" @close="confirmVisible = false" /> @confirm="handleConfirmYes" @cancel="handleConfirmNo" @close="confirmVisible = false" />
</template> </template>
@ -69,6 +71,7 @@ import ybPlugin from "@/utils/insurance-plugin";
import fullPage from "@/components/full-page.vue"; import fullPage from "@/components/full-page.vue";
import confirmPopup from "./confirm-popup.vue"; import confirmPopup from "./confirm-popup.vue";
import storePopup from "./store-popup.vue";
const mainMenuList = [ const mainMenuList = [
{ {
@ -106,13 +109,14 @@ const menuList = [
}, },
]; ];
const { userInfo, logined, login, loginout, getAuthCode } = useUser(); const { userInfo, logined, login, loginout, getAuthCode, drugStore, getStore } = useUser();
const statusBarHeight = ref(20); const statusBarHeight = ref(20);
const count = ref({ rxUnpay: 0 }); const count = ref({ rxUnpay: 0 });
const confirmVisible = ref(false); const confirmVisible = ref(false);
const confirmResolve = ref(null); const confirmResolve = ref(null);
const confirmReject = ref(null); const confirmReject = ref(null);
const feeType = ref(""); const feeType = ref("");
const visible = ref(false)
function goBack() { function goBack() {
uni.navigateBack(); uni.navigateBack();
@ -137,14 +141,19 @@ async function handleMainMenuClick(item) {
confirmVisible.value = true; confirmVisible.value = true;
} }
function handleConfirmYes() { async function handleConfirmYes() {
confirmVisible.value = false; confirmVisible.value = false;
confirmAuth(); await getStore();
visible.value = true
if (confirmResolve.value) { if (confirmResolve.value) {
confirmResolve.value(); confirmResolve.value();
cleanupConfirmPromise(); cleanupConfirmPromise();
} }
} }
function confirmStoreInfo() {
visible.value = false
confirmAuth();
}
function handleConfirmNo() { function handleConfirmNo() {
confirmVisible.value = false; confirmVisible.value = false;

View File

@ -9,8 +9,7 @@
<template v-slot:body> <template v-slot:body>
<view class="info-item"> <view class="info-item">
<text class="item-label">姓名</text> <text class="item-label">姓名</text>
<input v-model="form.name" :maxlength="20" class="item-value" type="text" <input v-model="form.name" :maxlength="20" class="item-value" type="text" placeholder="请输入姓名" />
placeholder="请输入姓名" />
</view> </view>
<view class="info-item"> <view class="info-item">
<text class="item-label">证件类型</text> <text class="item-label">证件类型</text>
@ -57,15 +56,25 @@
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from '@dcloudio/uni-app';
import useUser from '@/hooks/useUser'; import useUser from '@/hooks/useUser';
import { addHlwPatient, getHlwPatient, updateHlwPatient } from '@/utils/api'; import {
addHisCustomer,
addHlwPatient,
getHisCustomer,
getHlwPatient,
updateHlwPatient,
} from '@/utils/api';
import { get, remove, set } from '@/utils/cache';
import { isChinaId } from '@/utils/validator'; import { isChinaId } from '@/utils/validator';
import { toast } from '@/utils/widget'; import { toast } from '@/utils/widget';
import reLogin from '@/components/re-login.vue'; import reLogin from '@/components/re-login.vue';
const id = ref(''); const id = ref('');
const type = ref('');
const feeType = ref('');
const loading = ref(false); const loading = ref(false);
const elderMode = ref(false); const elderMode = ref(false);
const loadedPatientKey = ref(''); const loadedPatientKey = ref('');
const scannedCard = ref(null);
const form = ref({ const form = ref({
name: '', name: '',
certNo: '', certNo: '',
@ -73,8 +82,9 @@ const form = ref({
address: '', address: '',
}); });
const { userInfo, logined } = useUser(); const { userInfo, logined, setTemporaryPatient } = useUser();
const accountId = computed(() => userInfo.value && userInfo.value.userId ? userInfo.value.userId : ''); const accountId = computed(() => userInfo.value && userInfo.value.userId ? userInfo.value.userId : '');
const isYbQrcode = computed(() => type.value === 'ybQrcode');
function validateForm() { function validateForm() {
if (!form.value.name.trim()) { if (!form.value.name.trim()) {
@ -122,6 +132,11 @@ async function confirm() {
loading.value = true; loading.value = true;
try { try {
if (isYbQrcode.value) {
await saveYbQrcodePatient();
return;
}
const payload = { const payload = {
accountId: accountId.value, accountId: accountId.value,
name: form.value.name.trim(), name: form.value.name.trim(),
@ -150,6 +165,72 @@ async function confirm() {
} }
} }
async function saveYbQrcodePatient() {
if (!scannedCard.value) {
toast('医保扫码信息已失效,请重新扫码');
return;
}
const idCard = form.value.certNo.trim();
const res = await addHisCustomer({
idCard,
name: form.value.name.trim(),
mobile: form.value.mobile.trim(),
address: form.value.address.trim(),
mdtrt_cert_type: '03',
mdtrt_cert_no: scannedCard.value.CardNum,
card_sn: scannedCard.value.CardIDCode,
});
const patients = Array.isArray(res && res.list) ? res.list : [];
const hisArchive = patients.find(patient => patient.socialno === idCard) || patients[0] || null;
if (!res || !res.success || !hisArchive) {
toast((res && res.message) || '医保建档失败');
return;
}
hisArchive.socialno = hisArchive.socialno || idCard;
hisArchive.tmbxx = Array.isArray(res.tmbxx) ? res.tmbxx : [];
set('current-his-archive', hisArchive);
setTemporaryPatient({
name: form.value.name.trim(),
certNo: idCard,
mobile: form.value.mobile.trim(),
address: form.value.address.trim(),
});
uni.redirectTo({
url: `/pages/consult/disease-description?socialno=${idCard}&feeType=${feeType.value}`,
});
}
async function loadScannedCard() {
const card = get('current-scanned-card');
remove('current-scanned-card');
if (!card || !card.Name || !card.IDNum) {
toast('医保扫码信息已失效,请重新扫码');
uni.navigateBack();
return;
}
scannedCard.value = card;
form.value.name = card.Name;
form.value.certNo = card.IDNum;
loading.value = true;
try {
const res = await getHisCustomer(card.IDNum);
const patients = Array.isArray(res.list) ? res.list : [];
const patient = patients.find(item => item.socialno === card.IDNum);
if (patient) {
form.value.mobile = patient.tel || patient.mobile || '';
form.value.address = patient.address || '';
}
} catch (error) {
toast(error.message || error || '查询已有档案失败');
}
loading.value = false;
}
async function loadPatient() { async function loadPatient() {
if (!id.value || !accountId.value) return; if (!id.value || !accountId.value) return;
const patientKey = `${accountId.value}:${id.value}`; const patientKey = `${accountId.value}:${id.value}`;
@ -178,12 +259,20 @@ async function loadPatient() {
onLoad(options => { onLoad(options => {
id.value = options.id || ''; id.value = options.id || '';
uni.setNavigationBarTitle({ title: id.value ? '编辑就诊人' : '新增就诊人' }); type.value = options.type || '';
feeType.value = options.feeType || '';
uni.setNavigationBarTitle({
title: isYbQrcode.value ? '医保建档' : (id.value ? '编辑就诊人' : '新增就诊人'),
});
const savedElderMode = uni.getStorageSync('elderMode'); const savedElderMode = uni.getStorageSync('elderMode');
if (savedElderMode !== null && savedElderMode !== undefined) { if (savedElderMode !== null && savedElderMode !== undefined) {
elderMode.value = savedElderMode; elderMode.value = savedElderMode;
} }
if (isYbQrcode.value) {
loadScannedCard();
}
}); });
watch([id, accountId], loadPatient, { immediate: true }); watch([id, accountId], loadPatient, { immediate: true });

View File

@ -72,8 +72,8 @@ import emptyData from "@/components/empty.vue";
const { elderVarStyle } = useElder(); const { elderVarStyle } = useElder();
const PrescriptionType = { const PrescriptionType = {
onlineMedicinePurchase: '在线配药', // 线 (线 ) ZF: '自费处方', // 线 (线 )
storeMedicinePurchase: '在线复诊' YB: '医保处方'
} }
const { userInfo } = useUser(); const { userInfo } = useUser();
@ -120,7 +120,7 @@ async function getList() {
return { return {
...i, ...i,
time: dayjs(i.createTime).format('YYYY-MM-DD HH:mm'), time: dayjs(i.createTime).format('YYYY-MM-DD HH:mm'),
typeText: PrescriptionType[i.prescriptionType] || PrescriptionType.ONLINE_CONSULT, typeText: PrescriptionType[i.feeType] || '',
name: i.name, name: i.name,
sex: i.sex, sex: i.sex,
age: i.age, age: i.age,

View File

@ -60,7 +60,7 @@
<view class="signatures"> <view class="signatures">
<view class="signature-item" style="width: 33%"> <view class="signature-item" style="width: 33%">
<view>医生 <view>医生
<image v-if="data.doctorSignImg" class="signImage" :src="data.data"></image> <image v-if="data.doctorSignImg" class="signImage" :src="data.doctorSignImg"></image>
<text v-else>{{ data.doctorName }}</text> <text v-else>{{ data.doctorName }}</text>
</view> </view>
<view class="stamp"> <view class="stamp">

View File

@ -26,7 +26,15 @@ export default defineStore("userStore", () => {
const userInfo = ref({}); // { avatar, certNo, mobile, userName, userId } const userInfo = ref({}); // { avatar, certNo, mobile, userName, userId }
// his档案信息 // his档案信息
const patients = ref([]); // 就诊人档案 const patients = ref([]); // 就诊人档案
const patientList = computed(() => patients.value.map(i => { const temporaryPatient = ref(null);
const patientList = computed(() => {
const source = temporaryPatient.value && temporaryPatient.value.certNo
? [
...patients.value.filter(i => i.certNo !== temporaryPatient.value.certNo),
temporaryPatient.value,
]
: patients.value;
return source.map(i => {
const { birthday, age, sex } = getInfoFromIdNo({ socialno: i.certNo }); const { birthday, age, sex } = getInfoFromIdNo({ socialno: i.certNo });
const maskInfo = getMaskInfo({ const maskInfo = getMaskInfo({
name: i.name, name: i.name,
@ -44,7 +52,8 @@ export default defineStore("userStore", () => {
tel: i.mobile, tel: i.mobile,
isSelf: i.certNo === userInfo.value.certNo, isSelf: i.certNo === userInfo.value.certNo,
} }
})) })
})
async function login() { async function login() {
if (!userInfo.value.certNo) { if (!userInfo.value.certNo) {
@ -100,6 +109,7 @@ export default defineStore("userStore", () => {
logined.value = false; logined.value = false;
userInfo.value = {}; userInfo.value = {};
patients.value = []; patients.value = [];
temporaryPatient.value = null;
uni.removeStorageSync("hasAuthed"); uni.removeStorageSync("hasAuthed");
} }
@ -224,6 +234,19 @@ export default defineStore("userStore", () => {
} }
} }
function setTemporaryPatient(patient) {
if (!patient || !patient.certNo) {
temporaryPatient.value = null;
return;
}
temporaryPatient.value = {
id: patient.id || `yb-qrcode-${patient.certNo}`,
createTime: patient.createTime || new Date().toISOString(),
...patient,
isTemporary: true,
};
}
watch(storeId, (n) => { watch(storeId, (n) => {
uni.setStorageSync("storeId", n); uni.setStorageSync("storeId", n);
}); });
@ -234,6 +257,7 @@ export default defineStore("userStore", () => {
storeId, storeId,
userInfo, userInfo,
patients, patients,
temporaryPatient,
launchOptions, launchOptions,
patientList, patientList,
@ -241,6 +265,7 @@ export default defineStore("userStore", () => {
getStore, getStore,
login, login,
loginout, loginout,
loadPatientList loadPatientList,
setTemporaryPatient
}; };
}); });

View File

@ -31,6 +31,28 @@ export async function getHisCustomer(idCard) {
}); });
} }
export async function getScannedCard({ id, storeId }) {
return await request({
url: "/getYoucanData/hlw",
data: {
type: "getScannedCard",
id,
storeId,
corpId: process.env.CORP_ID,
},
});
}
export async function addHisCustomer(data) {
return await request({
url: "/getYoucanData/hlw",
data: {
type: "addHisCustomer",
...data,
},
});
}
export async function bindHisPatient({ export async function bindHisPatient({
idCard, idCard,
name, name,
@ -38,16 +60,12 @@ export async function bindHisPatient({
address, address,
psnToken, psnToken,
}) { }) {
return await request({ return await addHisCustomer({
url: "/getYoucanData/hlw",
data: {
type: "addHisCustomer",
idCard, idCard,
name, name,
mobile, mobile,
address, address,
psnToken, psnToken,
},
}); });
} }