hn-hlw-app/pages/consult/drug-purchase-order/drug-purchase-order.vue

358 lines
13 KiB
Vue
Raw Normal View History

2026-07-27 11:26:39 +08:00
<template>
<full-page v-if="order" pageStyle="background:#f5f5f5">
<view :style="elderVarStyle">
<view class="bg-white flex items-center p-15 shadow-lg" @click="showAddressPopup()">
<view class="w-0 flex-grow flex mr-10">
<uni-icons class="flex-shrink-0 mr-10" type="location" size="32" :color="themeColor"></uni-icons>
<view v-if="address">
<view class="text-base text-dark leading-normal">{{ address.region.join(' ') }} {{ address.address }}</view>
<view class="text-base text-dark">{{ address.name }} {{ address.phone }}</view>
</view>
<view v-else class="text-base text-gray">请选择收货地址</view>
</view>
<uni-icons v-if="enableChangeAddress" class="flex-shrinl-0" type="arrowright" size="20"
color="#999"></uni-icons>
</view>
<view class="mt-15 bg-white shadow-lg">
<view class="flex justify-between items-center py-10 px-15 border-b">
<view class="flex-shrink-0 mr-10 text-base text-gray">配送方式</view>
<view v-if="address" class="flex items-center">
<view v-if="fengNiaoAvailable" class="flex items-center mr-10" @click="toggleShippingType('fengniao')">
<uni-icons :type="shippingType === 'fengniao' ? 'circle-filled' : 'circle'" size="20"
:color="themeColor"></uni-icons>
<view class="radio-text text-base text-dark">骑手配送</view>
</view>
<view class="flex items-center mr-10" @click="toggleShippingType('ems')">
<uni-icons :type="shippingType === 'ems' ? 'circle-filled' : 'circle'" size="20"
:color="themeColor"></uni-icons>
<view class="radio-text text-base text-dark">快递邮寄</view>
</view>
</view>
<view v-else class="text-base text-gray">请选择收货地址</view>
</view>
<view v-if="address" class="flex justify-between items-center py-10 px-15 border-b">
<view>
<text class="text-base text-gray">运费</text>
<text v-if="shippingInfo.shippingDiscount > 0" class="text-base text-gray">
立减¥{{ countDetails.shippingDiscount }}
</text>
</view>
<view class="text-base text-danger">¥{{ countDetails.shippingFee }}</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 class="text-base text-dark">药费合计</view>
<view class="text-base text-danger">¥{{ countDetails.drugFee }}</view>
</view>
</view>
<view class="mt-12 bg-white shadow-lg flex justify-between py-10 px-15">
<view class="text-base text-dark">互联网诊查费</view>
<view class="text-base text-danger">¥{{ countDetails.regFee }}</view>
</view>
<view style="height: 160rpx;"></view>
</view>
<template #footer>
<view class="relative px-15 bg-white leading-normal shadow-up" :style="elderVarStyle">
<view v-if="shippingInfo.shippingFee > 0 && address" class="pt-12">
<view>
<text class="mr-5 text-base text-dark">您将会分</text>
<text class="mr-5 text-base text-danger"> 2 </text>
<text class="text-base text-dark">次进行支付</text>
</view>
<view class="pt-5">
<text class="mr-5 text-base text-dark">第一笔: 药费+互联网诊查费</text>
<text class="mr-5 text-base text-danger"> ¥{{ countDetails.ybFee }} </text>
<text class="text-base text-dark">(医保结算)</text>
</view>
<view class="pt-5">
<text class="mr-5 text-base text-dark">第二笔: 运费</text>
<text class="mr-5 text-base text-danger"> ¥{{ countDetails.shippingFee }} </text>
<text class="text-base text-dark">(支付宝支付)</text>
</view>
</view>
<view class="py-12">
<view class="bg-primary border-primary text-base text-white text-center py-10 rounded"
@click="showConfirmPopup()">
立即支付 (¥{{ countDetails.ybFee }})
</view>
</view>
</view>
</template>
</full-page>
<address-popup :accountId="userInfo.userId" :visible="visible" @close="visible = false" @confirm="onSelect($event)" />
<comfirm-popup :elderMode="elderMode" :elderVarStyle="elderVarStyle" :visible="comfirmVisible"
@close="comfirmVisible = false" @confirm="toPay()" />
</template>
<script setup>
import { computed, ref, watch } from 'vue';
import { onLoad, onHide, onShow } from '@dcloudio/uni-app';
import BigNumber from 'bignumber.js';
import useElder from '@/hooks/useElder';
import useUser from '@/hooks/useUser';
import { getDefaultAddress, getMedicinePurchaseOrder, testFengniaoAvailable, getMedicineOrderTradeNo } from '@/utils/api';
import { toast, loading as showLoading, hideLoading, confirm } from '@/utils/widget';
import ybPlugin from "@/utils/insurance-plugin";
import { pay } from '@/utils/pay';
import { themeColor } from '@/utils/theme-config';
import fullPage from '@/components/full-page.vue';
import AddressPopup from './address-popup.vue';
import ComfirmPopup from './comfirm-popup.vue';
const { elderVarStyle, elderMode } = useElder();
const { userInfo, getAuthCode, myProfile } = useUser();
const address = ref(null)
const shippingType = ref('ems');
const visible = ref(false);
const comfirmVisible = ref(false);
const id = ref('')
const order = ref(null)
const fengNiaoAvailable = ref(false);
const enableChangeAddress = ref(false);
const disabledShippingTypeChange = ref(false);
const autoBack = ref(false);
const exprssFee = ref({});
const shippingInfo = computed(() => exprssFee.value[shippingType.value] || {})
let waitingYbPay = false;
const isFamilyPay = computed(() => myProfile.value && myProfile.value.patientid !== order.value.patientId);
const drugFee = computed(() => {
const drugs = order.value && Array.isArray(order.value.drugs) ? order.value.drugs : [];
const total = drugs.reduce((total, med) => {
return total.plus(med.totalPrice > 0 ? med.totalPrice : 0);
}, new BigNumber(0));
return total.toNumber();
})
const countDetails = computed(() => {
const shippingFee = shippingInfo.value && typeof shippingInfo.value.shippingFee === 'number' ? shippingInfo.value.shippingFee : undefined;
const shippingDiscount = shippingInfo.value && typeof shippingInfo.value.shippingDiscount === 'number' ? shippingInfo.value.shippingDiscount : undefined;
const regFee = order.value && typeof order.value.regFee === 'number' ? order.value.regFee : undefined;
const total = new BigNumber(drugFee.value).plus(regFee || 0).plus(shippingFee || 0);
const ybFee = new BigNumber(drugFee.value).plus(regFee || 0).toNumber();
return {
drugFee: drugFee.value.toFixed(2),
shippingFee: typeof shippingFee === 'number' ? shippingFee.toFixed(2) : '',
shippingDiscount: typeof shippingDiscount === 'number' ? shippingDiscount.toFixed(2) : '',
regFee: typeof regFee === 'number' ? regFee.toFixed(2) : '',
shippingFee: typeof shippingFee === 'number' ? shippingFee.toFixed(2) : '',
totalFee: total.toFixed(2),
ybFee: ybFee.toFixed(2),
}
})
function onSelect(item) {
visible.value = false
address.value = item
}
function showAddressPopup() {
if (enableChangeAddress.value) {
visible.value = true;
}
}
function toggleShippingType(type) {
if (disabledShippingTypeChange.value) return;
shippingType.value = type;
}
async function getAddress() {
const res = await getDefaultAddress(userInfo.value.userId);
address.value = res && res.data && res.data.id ? res.data : null;
}
async function getDetail(showYbPaidTip) {
showLoading()
const res = await getMedicinePurchaseOrder({ accountId: userInfo.value.userId, id: id.value, withExpressInfo: true });
hideLoading();
if (res && res.success) {
order.value = res.data;
exprssFee.value = res.exprssFee || {};
enableChangeAddress.value = order.value.status === 'unpay';
if (order.value.status === 'shipped' || order.value.status === 'ybPaid') {
// 支付宝医保支付回调提示用户继续完成剩下 自费部分费用支付
if (showYbPaidTip && order.value.status === 'ybPaid' && order.value.shippingFee > 0) {
await confirm(`您已完成第一笔药费+诊查费支付, 请继续支付第二笔运费(¥${order.value.shippingFee})支付`, { showCancel: false, confirmText: '继续支付' })
}
uni.redirectTo({
url: `/pages/consult/drug-purchase-list/detail?id=${id.value}&autoCallPay=YES`,
success: () => {
autoBack.value = true
}
});
return
}
if (order.value.status === 'expired') {
await toast('订单已过期')
uni.navigateBack();
return
}
if (order.value.status !== 'unpay') {
await toast('订单状态异常')
uni.navigateBack();
return
}
disabledShippingTypeChange.value = Boolean(order.value.shippingType);
initOrderAddress()
} else {
await toast(res.message || '获取在线配药订单详情失败');
uni.navigateBack();
}
}
async function initOrderAddress() {
// if (order.value.receivePhone) {
// address.value = {
// name: order.value.receiveName,
// phone: order.value.receivePhone,
// region: [...order.value.receiveRegion],
// address: order.value.receiveAddress,
// longitude: order.value.receiveLongitude,
// latitude: order.value.receiveLatitude,
// }
// } else {
getAddress();
// }
}
async function checkFengNiaoAvailable() {
if (address.value) {
const fullAddress = address.value.region.join('') + address.value.address;
const res = await testFengniaoAvailable({ orderNo: order.value.orderNo, address: fullAddress, longitude: address.value.longitude, latitude: address.value.latitude });
fengNiaoAvailable.value = res && res.data && typeof res.data.canDelivery === 'boolean' ? res.data.canDelivery : false;
if (fengNiaoAvailable.value) {
shippingType.value = 'fengniao';
} else {
shippingType.value = 'ems';
}
} else {
shippingType.value = 'ems';
fengNiaoAvailable.value = false
}
}
function showConfirmPopup() {
if (!address.value) {
return toast('请选择收货地址')
}
comfirmVisible.value = true;
}
async function toPay() {
const payload = {
accountId: userInfo.value.userId,
id: id.value,
shippingType: shippingType.value,
receiveName: address.value.name,
receivePhone: address.value.phone,
receiveRegion: address.value.region,
receiveAddress: address.value.address,
receiveLongitude: address.value.longitude,
receiveLatitude: address.value.latitude,
}
showLoading();
const res = await getMedicineOrderTradeNo(payload);
hideLoading();
if (res && res.success) {
if (res.statusChanged) {
await toast('订单状态已更新')
getDetail()
}
if (res.tradeNo && res.payType === 'ybPay') {
pluginPay(res.tradeNo);
} else 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)
}
}
}
async function pluginPay(medOrgOrd) {
try {
const authCode = await getAuthCode("nhsamp");
const params = {
authCode,
cardNo: order.value.blhno,
medOrgOrd
}
if (isFamilyPay.value) {
params.anotherIdNo = order.value.anotherIdNo;
params.anotherName = order.value.anotherName;
}
showLoading('请稍等,正在为您接入医保支付...')
waitingYbPay = true;
ybPlugin.toAuthAndPay(params);
} catch (e) {
toast(e);
}
}
onLoad(options => {
id.value = options.id || '';
getDetail()
ybPlugin.init({
payCallback: () => {
getDetail(true)
},
tokenCallback: () => {
uni.redirectTo({
url: `/pages/consult/drug-purchase-order/drug-purchase-order?id=${id.value}`,
});
},
});
})
onHide(() => {
if (waitingYbPay) {
hideLoading();
}
})
onShow(() => {
if (autoBack.value) {
uni.navigateBack();
}
})
watch(address, n => checkFengNiaoAvailable())
</script>
<style lang="scss" scoped>
.radio-text {
line-height: 20px;
}
.pt-12 {
padding-top: 24rpx;
}
</style>