284 lines
8.8 KiB
Vue
284 lines
8.8 KiB
Vue
|
|
<template>
|
|||
|
|
<full-page pageStyle="background:#f5f5f5" @reachBottom="loadMore()">
|
|||
|
|
<template #header>
|
|||
|
|
<view class="header-tabs" :style="elderVarStyle">
|
|||
|
|
<view v-for="tab in tabs" :key="tab.value" :class="['tab', { active: activeTab === tab.value }]"
|
|||
|
|
@click="switchTab(tab.value)">
|
|||
|
|
{{ tab.label }}
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<view class="p-15" :style="elderVarStyle">
|
|||
|
|
<view v-for="(item, index) in list" :key="item._id" class="px-15 bg-white shadow-lg rounded"
|
|||
|
|
:class="index > 0 ? 'mt-15' : ''" @click="viewOrder(item)">
|
|||
|
|
<view class="flex items-center py-12 border-b">
|
|||
|
|
<view class="flex-grow mr-10 w-0 truncate text-base text-dark font-semibold">
|
|||
|
|
{{ item.time }}
|
|||
|
|
</view>
|
|||
|
|
<view v-if="item.statusText" class="flex-shrink-0 text-base font-semibold" :class="item.statusClass">
|
|||
|
|
{{ item.statusText }}
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view v-for="(med, idx) in item.drugs" :key="`${idx}_${med.id}`" class="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-dark">¥{{ 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="py-12">
|
|||
|
|
<view class="flex justify-end pb-10">
|
|||
|
|
<view v-if="item.hasShippingFee" class="text-sm text-gray">
|
|||
|
|
(含互联网诊查费¥{{ item.regFee }}、{{ item.shippingFee > 0 ? '运费¥' + item.shippingFee : '免运费' }})
|
|||
|
|
</view>
|
|||
|
|
<view v-else class="text-sm text-gray">(含互联网诊查费¥{{ item.regFee }})</view>
|
|||
|
|
<view class="flex-shrink-0 text-sm text-dark">合计:</view>
|
|||
|
|
<view class="flex-shrink-0 text-sm text-dark">¥{{ item.totalFee }}</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="flex justify-end flex-wrap">
|
|||
|
|
<view v-if="item.canViewInvoice"
|
|||
|
|
class="flex-shrink-0 border-primary text-base text-primary px-15 py-5 rounded"
|
|||
|
|
@click.stop="viewInvoice(item.patientId, item.orderNo)">电子发票</view>
|
|||
|
|
<view v-if="item.canViewDelivery"
|
|||
|
|
class="flex-shrink-0 ml-10 bg-primary border-primary text-base text-white px-15 py-5 rounded"
|
|||
|
|
@click.stop="viewShippingInfo(item._id)">查看物流</view>
|
|||
|
|
<view v-else-if="item.status === 'ybPaid'"
|
|||
|
|
class="flex-shrink-0 bg-primary border-primary text-base text-white px-15 py-5 rounded"
|
|||
|
|
@click.stop="toPay(item)">
|
|||
|
|
去支付</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<empty-data v-if="list.length === 0" />
|
|||
|
|
</view>
|
|||
|
|
</full-page>
|
|||
|
|
<confirm-popup
|
|||
|
|
:title="invoicePopup.title"
|
|||
|
|
:content="invoicePopup.content"
|
|||
|
|
:showCancel="false"
|
|||
|
|
confirmText="知道了"
|
|||
|
|
:visible="invoicePopup.visible"
|
|||
|
|
@confirm="invoicePopup.visible = false"
|
|||
|
|
@close="invoicePopup.visible = false" />
|
|||
|
|
</template>
|
|||
|
|
<script setup>
|
|||
|
|
import { computed, ref } from 'vue';
|
|||
|
|
import { onShow } from '@dcloudio/uni-app';
|
|||
|
|
import dayjs from 'dayjs';
|
|||
|
|
import BigNumber from 'bignumber.js';
|
|||
|
|
import useElder from '@/hooks/useElder';
|
|||
|
|
import usePageList from '@/hooks/usePageList';
|
|||
|
|
import useUser from '@/hooks/useUser';
|
|||
|
|
import { getMedicinePurchaseList, getMedicineOrderTradeNo, getHisInvoice } from '@/utils/api';
|
|||
|
|
import { pay } from '@/utils/pay';
|
|||
|
|
import { loading as showLoading, hideLoading, toast } from '@/utils/widget';
|
|||
|
|
import { viewShippingInfo } from './util';
|
|||
|
|
|
|||
|
|
import emptyData from '@/components/empty.vue';
|
|||
|
|
import fullPage from '@/components/full-page.vue';
|
|||
|
|
import confirmPopup from '@/components/confirm-popup.vue';
|
|||
|
|
|
|||
|
|
const statusSet = {
|
|||
|
|
ybPaid: { text: '待支付运费', className: 'text-danger' },
|
|||
|
|
shipped: { text: '已配送', className: 'text-success' },
|
|||
|
|
refunded: { text: '已退费', className: 'text-gray' },
|
|||
|
|
ybFeeRefunded: { text: '药诊费已退', className: 'text-gray' },
|
|||
|
|
}
|
|||
|
|
const tabs = [
|
|||
|
|
{ label: '全部', value: 'all', statusList: [] },
|
|||
|
|
{ label: '待支付', value: 'ybPaid', statusList: ['ybPaid'] },
|
|||
|
|
{ label: '已配送', value: 'shipped', statusList: ['shipped'] },
|
|||
|
|
{ label: '退费', value: 'refunded', statusList: ['refunded', 'ybFeeRefunded'] }
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
const activeTab = ref('all');
|
|||
|
|
const { page, pageSize, list, pages, changePage, loading, hasMore } = usePageList(getList);
|
|||
|
|
const { elderVarStyle } = useElder();
|
|||
|
|
const { userInfo } = useUser();
|
|||
|
|
const statusList = computed(() => {
|
|||
|
|
if (activeTab.value === 'all') {
|
|||
|
|
return tabs.reduce((list, item) => [...list, ...item.statusList], []);
|
|||
|
|
}
|
|||
|
|
const tab = tabs.find(item => item.value === activeTab.value);
|
|||
|
|
return tab ? tab.statusList : [];
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
const invoicePopup = ref({
|
|||
|
|
visible: false,
|
|||
|
|
title: '提示',
|
|||
|
|
content: ''
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
function switchTab(value) {
|
|||
|
|
activeTab.value = value;
|
|||
|
|
changePage(1)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function loadMore() {
|
|||
|
|
if (hasMore.value && !loading.value) {
|
|||
|
|
changePage(page.value + 1)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function viewOrder(item) {
|
|||
|
|
uni.navigateTo({
|
|||
|
|
url: `/pages/consult/drug-purchase-list/detail?id=${item._id}`
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function getList() {
|
|||
|
|
if (loading.value || !userInfo.value?.userId) return;
|
|||
|
|
loading.value = true;
|
|||
|
|
const params = {
|
|||
|
|
accountId: userInfo.value.userId,
|
|||
|
|
page: page.value,
|
|||
|
|
pageSize: pageSize.value,
|
|||
|
|
statusList: statusList.value
|
|||
|
|
}
|
|||
|
|
showLoading();
|
|||
|
|
const res = await getMedicinePurchaseList(params);
|
|||
|
|
hideLoading()
|
|||
|
|
const arr = res && Array.isArray(res.list) ? res.list.map(i => {
|
|||
|
|
const item = { ...i };
|
|||
|
|
const status = statusSet[i.status];
|
|||
|
|
if (status) {
|
|||
|
|
item.statusText = status.text;
|
|||
|
|
item.statusClass = status.className;
|
|||
|
|
}
|
|||
|
|
item.hasShippingFee = 'shippingFee' in item;
|
|||
|
|
let totalFee = new BigNumber(0);
|
|||
|
|
item.drugs.forEach(med => {
|
|||
|
|
totalFee = totalFee.plus(med.totalPrice > 0 ? med.totalPrice : 0);
|
|||
|
|
});
|
|||
|
|
totalFee = totalFee.plus(item.regFee > 0 ? item.regFee : 0);
|
|||
|
|
totalFee = totalFee.plus(item.shippingFee > 0 ? item.shippingFee : 0);
|
|||
|
|
item.totalFee = totalFee.toNumber();
|
|||
|
|
item.time = dayjs(item.createTime).format('YYYY-MM-DD HH:mm');
|
|||
|
|
item.canViewInvoice = 'shipped' === item.status;
|
|||
|
|
item.canViewDelivery = ['shipped', 'ybFeeRefunded'].includes(item.status);
|
|||
|
|
return item;
|
|||
|
|
}) : [];
|
|||
|
|
list.value = page.value === 1 ? arr : [...list.value, ...arr];
|
|||
|
|
pages.value = res && res.pages > 0 ? res.pages : 0;
|
|||
|
|
if (!res || !res.success) {
|
|||
|
|
toast(res && res.message ? res.message : '获取列表失败');
|
|||
|
|
};
|
|||
|
|
loading.value = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function toPay(item) {
|
|||
|
|
showLoading();
|
|||
|
|
const res = await getMedicineOrderTradeNo({
|
|||
|
|
accountId: userInfo.value.userId,
|
|||
|
|
id: item._id
|
|||
|
|
});
|
|||
|
|
hideLoading();
|
|||
|
|
if (res && res.success) {
|
|||
|
|
if (res.statusChanged) {
|
|||
|
|
await toast('订单状态已更新')
|
|||
|
|
getList()
|
|||
|
|
}
|
|||
|
|
if (res.tradeNo && res.payType === 'alipay') {
|
|||
|
|
payTrade(res.tradeNo, item);
|
|||
|
|
}
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
toast(res.message || '获取交易订单号失败')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function payTrade(tradeNo, item) {
|
|||
|
|
try {
|
|||
|
|
await pay(tradeNo);
|
|||
|
|
viewOrder(item);
|
|||
|
|
} catch (e) {
|
|||
|
|
if (e === 'cancel') {
|
|||
|
|
toast('支付已取消')
|
|||
|
|
} else {
|
|||
|
|
toast(e)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onShow(() => {
|
|||
|
|
changePage(1);
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// 本地版本的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: '发票正在开具中,请稍后再试!'
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
</script>
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
.header-tabs {
|
|||
|
|
display: flex;
|
|||
|
|
background: #fff;
|
|||
|
|
text-align: center;
|
|||
|
|
|
|||
|
|
.tab {
|
|||
|
|
position: relative;
|
|||
|
|
flex-grow: 1;
|
|||
|
|
padding: 24rpx 30rpx;
|
|||
|
|
font-size: var(--text-base);
|
|||
|
|
color: #333;
|
|||
|
|
|
|||
|
|
&.active {
|
|||
|
|
color: $theme-brown-primary;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&.active::after {
|
|||
|
|
position: absolute;
|
|||
|
|
left: 50%;
|
|||
|
|
transform: translateX(-50%);
|
|||
|
|
bottom: 0;
|
|||
|
|
content: "";
|
|||
|
|
width: 80rpx;
|
|||
|
|
height: 8rpx;
|
|||
|
|
border-radius: 4rpx;
|
|||
|
|
background: $theme-brown-primary;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.ml-10 {
|
|||
|
|
margin-left: 20rpx;
|
|||
|
|
}
|
|||
|
|
</style>
|