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

289 lines
11 KiB
Vue
Raw 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 v-if="order" pageStyle="background:#f5f5f5">
<view :style="elderVarStyle">
<confirm-popup
:title="invoicePopup.title"
:content="invoicePopup.content"
:showCancel="false"
confirmText="知道了"
:visible="invoicePopup.visible"
@confirm="invoicePopup.visible = false"
@close="invoicePopup.visible = false" />
<view v-if="headText[order.status]" class="bg-white p-15 shadow-lg">
<view class="pb-10 text-drak text-lg font-semibold ">{{ headText[order.status].title }}</view>
<view v-if="headText[order.status].dynicDesc" class="text-base text-dark leading-normal">{{ dynicDesc }}</view>
<view v-else class="text-base text-dark leading-normal">{{ headText[order.status].desc }}</view>
</view>
<view class="mt-15 bg-white shadow-lg">
<view class="flex border-b py-12 px-15">
<view class="flex-shrink-0 mr-10 text-base text-gray">收货地址</view>
<view class="flex-grow text-dark text-right">
<view class="text-base">{{ order.receiveName }} {{ order.receivePhone }}</view>
<view>
<text v-if="order.receiveRegion && order.receiveRegion.length > 0" class="text-base">
{{ order.receiveRegion.join('') }}
</text>
<text class="text-base">{{ order.receiveAddress }}</text>
</view>
</view>
</view>
<view class="flex justify-between py-12 px-15">
<view class="flex-shrink-0 mr-10 text-base text-gray">配送方式</view>
<view class="text-base">{{ shippingType[order.shippingType] }}</view>
</view>
</view>
<view class="mt-15 bg-white shadow-lg">
<view v-for="(med, idx) in order.drugs" class="px-15" :class="idx === order.drugs.length - 1 ? 'border-b' : ''">
<view class="flex justify-between py-10">
<view class="mr-15 text-base font-semibold">{{ med.drugName }}</view>
<view class="flex-shrink-0 text-base text-danger">¥{{ med.price }}</view>
</view>
<view class="flex pb-10">
<view class="flex-grow mr-10 w-0 truncate text-sm text-gray">规格:{{ med.spec }}</view>
<view class="flex-shrink-0 text-sm text-gray">x{{ med.quantity }}</view>
</view>
</view>
<view class="flex justify-between py-10 px-15">
<view>
<text class="text-base text-dark">药品费</text>
<text class="text-sm text-gray">(医保结算)</text>
</view>
<view class="text-base text-danger">¥{{ countDetails.drugFee }}</view>
</view>
<view class="flex justify-between pb-10 px-15">
<view>
<text class="text-base text-dark">互联网诊查费</text>
<text v-if="order.regFee > 0" class="text-sm text-gray">(医保结算)</text>
</view>
<view class="text-base text-danger">¥{{ countDetails.regFee }}</view>
</view>
<view class="flex justify-between pb-10 px-15">
<view>
<text class="text-base text-dark">运费</text>
<text v-if="order.shippingFee > 0 && order.payTime" class="text-sm text-gray">(支付宝支付)</text>
</view>
<view class="text-base text-danger">¥{{ countDetails.shippingFee }}</view>
</view>
<view class="text-right pb-10 px-15">
<text class="text-base text-dark">总计:</text>
<text class="text-base text-danger">¥{{ countDetails.totalFee }}</text>
</view>
</view>
<view class="mt-15 px-15 bg-white shadwo-lg">
<view class="flex justify-between py-10 border-b">
<view class="text-sm text-gray">订单号</view>
<view class="text-sm text-dark">{{ order.orderNo }}</view>
</view>
<view class="flex justify-between py-10 border-b">
<view class="text-sm text-gray">下单时间</view>
<view class="text-sm text-dark">{{ order.createTime }}</view>
</view>
<view v-if="order.tradeNo" class="flex justify-between py-10" :class="order.payTime ? 'border-b' : ''">
<view class="text-sm text-gray">交易订单号</view>
<view class="text-sm text-dark">{{ order.tradeNo }}</view>
</view>
<view v-if="order.payTime" class="flex justify-between py-10" :class="refundRecords.length ? 'border-b' : ''">
<view class="text-sm text-gray">支付时间</view>
<view class="text-sm text-dark">{{ order.payTime }}</view>
</view>
<view v-for="(i, idx) in refundRecords" :key="idx" class="flex justify-between py-10"
:class="idx === refundRecords.length - 1 ? '' : 'border-b'">
<view class="text-sm text-gray">退费时间 ({{ i.fee }})</view>
<view class="text-sm text-dark">{{ i.time }}</view>
</view>
</view>
</view>
<template #footer>
<view class="flex justify-end bg-white px-15 py-10" :style="elderVarStyle">
<view v-if="order.status === 'ybPaid'"
class="flex-shrink-0 bg-primary border-primary text-base text-white px-15 py-5 rounded" @click="toPay">
去支付
</view>
<view v-if="order.status === 'shipped'"
class="flex-shrink-0 border-primary text-base text-primary px-15 py-5 rounded mr-10"
@click="viewInvoice(order.patientId, order.orderNo)">电子发票</view>
<view v-if="order.status === 'shipped' || order.status === 'ybFeeRefunded'"
class="flex-shrink-0 bg-primary border-primary text-base text-white px-15 py-5 rounded"
@click="viewShippingInfo(order._id)">
查看物流
</view>
</view>
</template>
</full-page>
</template>
<script setup>
import { computed, ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import BigNumber from 'bignumber.js';
import dayjs from 'dayjs';
import useElder from '@/hooks/useElder';
import useUser from '@/hooks/useUser';
import { getMedicinePurchaseOrder, getMedicineOrderTradeNo, getHisInvoice } from '@/utils/api';
import { toast, loading as showLoading, hideLoading } from '@/utils/widget';
import { pay } from '@/utils/pay';
import { viewShippingInfo } from './util';
import fullPage from '@/components/full-page.vue';
import confirmPopup from '@/components/confirm-popup.vue';
const shippingType = {
ems: '快递邮寄',
fengniao: '蜂鸟配送',
}
const headText = {
ybPaid: { title: '待支付运费', desc: '为确保药品尽快发出,请及时支付运费。' },
shipped: { title: '已配送', desc: '您可点击查看物流跟踪配送进度。' },
refunded: { title: '已退费', dynicDesc: true },
ybFeeRefunded: { title: '药诊费已退', dynicDesc: true },
}
const { elderVarStyle } = useElder();
const { userInfo } = useUser();
const id = ref('');
const order = ref(null);
const autoCallPay = ref(false)
const invoicePopup = ref({
visible: false,
title: '提示',
content: ''
})
const countDetails = computed(() => {
const drugFee = order.value && typeof order.value.drugFee === 'number' ? order.value.drugFee : undefined;
const shippingFee = order.value && typeof order.value.shippingFee === 'number' ? order.value.shippingFee : undefined;
const regFee = order.value && typeof order.value.regFee === 'number' ? order.value.regFee : undefined;
const total = new BigNumber(drugFee || 0).plus(regFee || 0).plus(shippingFee || 0);
const ybFee = new BigNumber(regFee || 0).plus(drugFee || 0).toNumber();
return {
drugFee: typeof drugFee === 'number' ? drugFee.toFixed(2) : '',
regFee: typeof regFee === 'number' ? regFee.toFixed(2) : '',
shippingFee: typeof shippingFee === 'number' ? shippingFee.toFixed(2) : '',
totalFee: total.toFixed(2),
ybFee: ybFee.toFixed(2),
}
})
const dynicDesc = computed(() => {
if (order.value && order.value.status === 'refunded' && order.value.payTime && order.value.shippingFee > 0) {
return `已退回药费+问诊费(¥${countDetails.value.ybFee}${order.value.shippingFee > 0 ? `,运费(¥${countDetails.value.shippingFee}` : ''}`
}
if (order.value && ['ybFeeRefunded', 'refunded'].includes(order.value.status)) {
return `已退回药费+问诊费(¥${countDetails.value.ybFee})。`
}
return '';
})
const refundRecords = computed(() => {
return order.value && Array.isArray(order.value.refundRecords) ? order.value.refundRecords.filter(i => i.result === 'refunded').map(i => ({
fee: `¥${i.amount.toFixed(2)}`,
time: dayjs(i.refundTime || i.applyTime).format('YYYY-MM-DD HH:mm'),
})) : [];
})
async function getDetail() {
showLoading()
const res = await getMedicinePurchaseOrder({ accountId: userInfo.value.userId, id: id.value });
hideLoading();
if (res && res.success) {
order.value = res.data;
if (order.value.status === 'unpay') {
uni.redirectTo({
url: `/pages/consult/drug-purchase-order/drug-purchase-order?&orderId=${order.value.id}`
});
return
}
if (order.value.status === 'expired') {
await toast('订单已过期')
uni.navigateBack();
return
}
order.value.createTime = dayjs(order.value.createTime).format('YYYY-MM-DD HH:mm:ss');
order.value.payTime = order.value.payTime ? dayjs(order.value.payTime).format('YYYY-MM-DD HH:mm:ss') : '';
if (order.value.status === 'ybPaid' && autoCallPay.value) {
autoCallPay.value = false;
toPay()
}
} else {
await toast(res.message || '获取在线配药订单详情失败');
uni.navigateBack();
}
}
async function toPay() {
showLoading();
const res = await getMedicineOrderTradeNo({
accountId: userInfo.value.userId,
id: id.value
});
hideLoading();
if (res && res.success) {
if (res.statusChanged) {
await toast('订单状态已更新')
getDetail()
}
if (res.tradeNo && res.payType === 'alipay') {
payTrade(res.tradeNo);
}
return
}
toast(res.message || '获取交易订单号失败')
}
async function payTrade(tradeNo) {
try {
await pay(tradeNo);
getDetail()
} catch (e) {
if (e === 'cancel') {
toast('支付已取消')
} else {
toast(e)
}
}
}
// 本地版本的viewInvoice使用自定义弹窗
async function viewInvoice(patientId, orderNo) {
showLoading()
const res = await getHisInvoice({
patientId,
orderNo
});
hideLoading()
if (res && res.success) {
const url = typeof res.data === 'string' ? res.data : ''
if (url) {
uni.setClipboardData({
data: url,
success: () => {
invoicePopup.value = {
visible: true,
title: '提示',
content: '已复制发票地址,请在浏览器中打开'
}
}
})
} else {
invoicePopup.value = {
visible: true,
title: '提示',
content: '发票正在开具中,请稍后再试!'
}
}
} else {
invoicePopup.value = {
visible: true,
title: '提示',
content: '发票正在开具中,请稍后再试!'
}
}
}
onLoad(options => {
id.value = options.id || '';
autoCallPay.value = options.autoCallPay === 'YES';
getDetail()
})
</script>
<style lang="scss" scoped></style>