hn-hlw-app/pages/record/rx-paper.vue

393 lines
10 KiB
Vue
Raw Permalink Normal View History

2026-07-27 11:26:39 +08:00
<template>
<full-page>
<view v-if="data" class="relative prescription-container">
<view class="header">
<view class="row">
<view class="company">绍兴市同源健康管理有限公司越城</view>
<view class="prescription-type">
<view>普通</view>
<view>处方</view>
</view>
</view>
<view class="hospital">震元堂中医院互联网医院处方笺</view>
<view class="sub-header">
<span class="no">NO:{{ data.medOrgOrderNo }}</span>
</view>
</view>
<view class="patient-info">
<view class="info-row">
<view class="info-item" style="width: 28%">姓名{{ data.name }}</view>
<view class="info-item" style="width: 20%">性别{{ data.sex }}</view>
<view class="info-item" style="width: 28%">费别</view>
<view class="info-item" style="width: 24%">年龄{{ data.age }}</view>
</view>
<view class="info-row">
<view class="info-item" style="width: 60%">门诊病历号{{ data.blhno }}</view>
<view class="info-item" style="width: 40%">科别{{ data.deptName }}</view>
</view>
<view class="info-row">
<view class="info-item full-width">地址 {{ data.address }}</view>
</view>
<view class="info-row">
<view class="info-item full-width">电话号{{ data.mobile }}</view>
</view>
</view>
<!-- 诊断信息 -->
<view class="diagnosis-section">
<view class="diagnosis-header">
<span>诊断</span>
<span class="date">开方日期{{ data.time }}</span>
</view>
<view class="diagnosis-items">
<view v-for="(i, idx) in diagnosis" :key="i.code">{{ idx + 1 }}. {{ i.name }}</view>
</view>
</view>
<!-- 药品处方区域 -->
<view class="medicine-section">
<view class="rp-symbol">Rp</view>
<view class="medicine-list">
<view v-for="i in drugList" :key="i.insurance_code" class="medicine-item">
<view class="medicine-name">{{ i.drugName }} x {{ i.quantity }} {{ i.unit }}</view>
<view class="medicine-spec">规格{{ i.specification }}</view>
<view class="medicine-usage">用法{{ i.memo }}</view>
</view>
</view>
</view>
<!-- 底部签章区域 -->
<view class="footer">
<view class="stamp-area">
<view class="signatures">
<view class="signature-item" style="width: 33%">
<view>医生
<image v-if="doctorImg" class="signImage" :src="doctorImg"></image>
<text v-else>{{ data.doctorName }}</text>
</view>
<view class="stamp">
<!-- <image class="stamp-img" src="/static/stamp.png"></image> -->
</view>
</view>
<view class="signature-item" style="width: 33%">
<view>审方<image v-if="yaoshiImg" class="signImage" :src="yaoshiImg"></image>
<text v-else>{{ data.pharmacist }}</text>
</view>
<view>发药</view>
</view>
<view class="signature-item" style="width: 34%">
<view class="stamp">收费盖章
<!-- <image class="stamp-img" src="/static/stamp.png"></image> -->
</view>
<view>配方</view>
<view>复核</view>
</view>
</view>
</view>
<view class="notice">注意请勿丢失处方当日有效因特殊情况该处方有效为天签名</view>
</view>
<image v-if="isExpired" class="expired-icon" src="/static/icons/expired.svg" />
</view>
<template #footer>
<footer-button v-if="canPay" text="医保结算" @onClick="handleInsurancePayment" />
<footer-button v-else-if="canViewOrder" text="查看订单" @onClick="viewOrder" />
</template>
</full-page>
</template>
<script setup>
import { computed, ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import dayjs from 'dayjs';
import useUser from '@/hooks/useUser';
import { getRxDetail, getSealImage, getRxMedicinePurchaseOrderId } from '@/utils/api'
import fullPage from "@/components/full-page.vue";
import footerButton from "@/components/footer-button.vue";
import { loading as showLoading, hideLoading, toast } from "@/utils/widget";
const { userInfo } = useUser();
const data = ref(null);
const doctorImg = ref('')
const yaoshiImg = ref('')
const id = ref('');
const serviceTime = ref(0);
const isExpired = computed(() => {
if (data.value && data.value.prescriptionType === 'onlineMedicinePurchase') {
console.log(data.value.expireTime < serviceTime.value)
console.log(!data.value.purchaseOrder, data.value.purchaseOrder?.status === 'expired')
return data.value.expireTime < serviceTime.value && (!data.value.purchaseOrder || data.value.purchaseOrder.status === 'expired');
}
return false
})
const canPay = computed(() => {
if (data.value && data.value.prescriptionType === 'onlineMedicinePurchase') {
return !isExpired.value && (!data.value.purchaseOrder || ['unpay', 'ybPaid'].includes(data.value.purchaseOrder.status));
}
return false
})
const canViewOrder = computed(() => {
if (data.value && data.value.prescriptionType === 'onlineMedicinePurchase') {
return data.value.purchaseOrder && data.value.purchaseOrder.status === 'shipped';
}
return false
})
onLoad((options) => {
id.value = options.id;
getRx();
})
const diagnosis = computed(() => data.value && Array.isArray(data.value.diagnosisList) ? data.value.diagnosisList : [])
const drugList = computed(() => {
const drugs = data.value && Array.isArray(data.value.drugs) ? data.value.drugs : [];
return drugs.map((item) => {
const arr = [item.usageName, item.frequencyName, item.dosage ? `每次${item.dosage}${item.dosage_unit || ''}` : ''].filter(Boolean);
return { ...item, memo: arr.join(' ') }
})
})
async function getRx() {
showLoading();
const res = await getRxDetail(id.value, userInfo.value?.userId);
const { success, data: rx, message } = res || {};
hideLoading();
if (success) {
data.value = rx;
serviceTime.value = typeof res.now === 'number' ? res.now : 0;
data.value.time = rx.createTime ? dayjs(rx.createTime).format('YYYY-MM-DD HH:mm') : '';
getDoctorSign()
} else {
toast(message || '获取处方详情失败');
}
}
function getDoctorSign() {
if (data.value.doctorCode && !doctorImg.value) {
getSealImage(data.value.doctorCode).then(res => {
if (res.success && res.data) {
doctorImg.value = `data:image/png;base64,${res.data}`
}
})
}
if (data.value.pharmacistNo && !yaoshiImg.value) {
getSealImage(data.value.pharmacistNo).then(res => {
if (res.success && res.data) {
yaoshiImg.value = `data:image/png;base64,${res.data}`
}
})
}
}
async function handleInsurancePayment() {
showLoading();
const res = await getRxMedicinePurchaseOrderId({
accountId: userInfo.value.userId,
rpNo: id.value
});
hideLoading()
if (res && res.success) {
if (res.status === 'unpay') {
uni.navigateTo({
url: `/pages/consult/drug-purchase-order/drug-purchase-order?id=${res.id}`
})
}
else if (res.status === 'expired') {
await toast('订单已过期');
getRx();
}
else {
uni.navigateTo({
url: `/pages/consult/drug-purchase-list/detail?id=${res.id}`
})
}
} else {
toast(res.message || '获取在线配药订单失败');
}
}
function viewOrder() {
uni.navigateTo({
url: `/pages/consult/drug-purchase-list/detail?id=${data.value.purchaseOrder._id}`
})
}
</script>
<style scoped>
.prescription-container {
max-width: 750rpx;
margin: 0 auto;
font-family: "SimSun", serif;
background: #fff;
box-shadow: 0 4rpx 30rpx rgba(0, 0, 0, 0.1);
line-height: 1.5;
padding: 24rpx 24rpx 240rpx;
font-size: 28rpx;
}
/* 头部样式 */
.header {
border-bottom: 1px solid #000;
padding-bottom: 32rpx;
margin-bottom: 24rpx;
}
.row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12rpx;
}
.company {
font-size: 30rpx;
font-weight: bold;
}
.prescription-type {
font-size: 28rpx;
color: #666;
border: 1px solid #333;
width: 80rpx;
text-align: center;
}
.hospital {
font-size: 32rpx;
font-weight: bold;
text-align: center;
margin: 16rpx 0;
}
.sub-header {
display: flex;
justify-content: space-between;
font-size: 28rpx;
margin-top: 20rpx;
flex-direction: column;
}
/* 患者信息表格 */
.patient-info {
margin: 24rpx 0;
}
.info-row {
display: flex;
padding: 12rpx 8rpx;
}
.info-row:last-child {
border-bottom: none;
}
.info-item {
padding: 0 8rpx;
white-space: normal;
}
.full-width {
width: 100% !important;
}
/* 诊断区域 */
.diagnosis-section {
margin: 30rpx 0;
}
.diagnosis-header {
display: flex;
justify-content: space-between;
margin-bottom: 16rpx;
}
.date {
font-size: 26rpx;
color: #666;
}
/* 药品处方 */
.medicine-section {
position: relative;
padding-left: 60rpx;
margin: 36rpx 0;
}
.rp-symbol {
position: absolute;
left: 0;
top: 0;
font-weight: bold;
}
.medicine-item {
margin-bottom: 30rpx;
}
.medicine-name {
font-weight: bold;
}
.medicine-spec {
color: #666;
margin: 6rpx 0;
}
/* 底部签章 */
.footer {
border-top: 1px dashed #999;
padding-top: 30rpx;
margin-top: 40rpx;
}
.stamp-area {
margin-bottom: 30rpx;
}
.signatures {
display: flex;
margin-top: 30rpx;
}
.signature-item {
padding: 0 16rpx;
}
.stamp {
position: relative;
/* margin-top: 50rpx; */
}
.signImage {
display: inline-block;
width: 100rpx;
height: 40rpx;
}
.stamp-img {
position: absolute;
left: 0;
top: -150rpx;
width: 280rpx;
height: 280rpx;
}
.notice {
color: #d32f2f;
font-size: 24rpx;
margin-top: 30rpx;
}
.no {
margin-top: 10rpx;
}
.expired-icon {
position: absolute;
right: 80rpx;
top: 30%;
width: 240rpx;
height: 240rpx;
}
</style>