358 lines
13 KiB
Vue
358 lines
13 KiB
Vue
|
|
<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>
|