Files
xk-client-wx/subPackages/my/my-drug/invoice-detail.vue
2026-07-28 12:45:56 +08:00

251 lines
6.3 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>
<view class="page safe-area-inset-bottom">
<view class="card" v-if="info">
<view class="status-row">
<text class="status">{{ info.status_text || '' }}</text>
<text class="amount">{{ info.amount || '' }}</text>
</view>
<view class="row"><text class="label">订单号</text><text class="value">{{ info.order_no }}</text></view>
<view class="row"><text class="label">抬头类型</text><text class="value">{{ info.title_type_text }}</text></view>
<view class="row"><text class="label">抬头名称</text><text class="value">{{ info.title_name }}</text></view>
<view class="row" v-if="info.title_type == 2">
<text class="label">税号</text><text class="value">{{ info.tax_no }}</text>
</view>
<view class="row"><text class="label">接收方式</text><text class="value">{{ info.receive_type_text }}</text></view>
<view class="row" v-if="info.receive_type == 2">
<text class="label">邮箱</text><text class="value">{{ info.email }}</text>
</view>
<view class="row" v-if="info.invoice_code">
<text class="label">票据代码</text><text class="value">{{ info.invoice_code }}</text>
</view>
<view class="row" v-if="info.reject_reason">
<text class="label">拒绝原因</text><text class="value warn">{{ info.reject_reason }}</text>
</view>
<view class="tip" v-if="info.status == 2 && info.receive_type == 2">
发票已发送至邮箱{{ info.email_sent == 1 ? '' : '如未收到可联系客服' }}
</view>
</view>
<view class="card" v-if="info && info.status == 2 && fileList.length">
<view class="section-title">发票文件</view>
<view
class="file-item"
v-for="(url, index) in fileList"
:key="index"
@tap="openFile(url)"
>
<image
v-if="isImage(url)"
class="thumb"
:src="url"
mode="aspectFill"
/>
<view v-else class="file-icon">PDF</view>
<text class="file-name">{{ fileName(url, index) }}</text>
<text class="link">{{ isImage(url) ? '预览' : '打开文档预览' }}</text>
</view>
</view>
<view class="empty" v-if="!loading && !info">暂无开票信息</view>
</view>
</template>
<script>
import { getInvoiceDetailApi } from '@/request/api/invoice.js'
/**
* 开票详情/下载页:订阅消息落地页,支持预览图片与打开 PDF
*/
export default {
data() {
return {
id: 0,
orderId: 0,
info: null,
loading: false
}
},
computed: {
fileList() {
if (!this.info || !this.info.invoice_files) return []
return this.info.invoice_files
}
},
onLoad(query) {
this.id = Number(query.id || 0)
this.orderId = Number(query.order_id || 0)
this.loadDetail()
},
methods: {
/**
* 拉取开票详情
*/
loadDetail() {
if (!this.id && !this.orderId) return
this.loading = true
const params = this.id ? { id: this.id } : { order_id: this.orderId }
getInvoiceDetailApi(params).then((res) => {
if (res.data && res.data.errcode == 0) {
this.info = res.data.data || null
} else {
uni.showToast({
title: (res.data && (res.data.errmsg || res.data.message)) || '加载失败',
icon: 'none'
})
}
}).finally(() => {
this.loading = false
})
},
isImage(url) {
return /\.(jpg|jpeg|png|gif|webp)(\?|$)/i.test(url || '')
},
fileName(url, index) {
const name = (url || '').split('/').pop() || ''
return name || ('发票文件' + (index + 1))
},
/**
* 预览图片PDF 通过微信文档能力打开(小程序无法页内嵌 PDF
*/
openFile(url) {
if (!url) return
if (this.isImage(url)) {
uni.previewImage({
urls: this.fileList.filter((u) => this.isImage(u)),
current: url
})
return
}
uni.showLoading({ title: '打开文档预览' })
uni.downloadFile({
url: url,
success: (res) => {
if (res.statusCode === 200) {
uni.openDocument({
filePath: res.tempFilePath,
fileType: 'pdf',
showMenu: true,
fail: () => {
uni.showToast({ title: '无法打开文档,请稍后重试或联系客服', icon: 'none' })
}
})
} else {
uni.showToast({ title: '下载失败', icon: 'none' })
}
},
fail: () => {
uni.showToast({ title: '下载失败,请稍后重试', icon: 'none' })
},
complete: () => {
uni.hideLoading()
}
})
}
}
}
</script>
<style lang="scss" scoped>
.page {
min-height: 100vh;
background: #f5f6f8;
padding: 24rpx;
box-sizing: border-box;
}
.card {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 24rpx;
}
.status-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16rpx;
padding-bottom: 16rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.status {
font-size: 32rpx;
font-weight: 600;
color: #1777ff;
}
.amount {
color: #e54d42;
font-size: 32rpx;
font-weight: 600;
}
.row {
display: flex;
padding: 12rpx 0;
font-size: 28rpx;
}
.label {
width: 160rpx;
color: #999;
flex-shrink: 0;
}
.value {
flex: 1;
color: #333;
word-break: break-all;
}
.warn {
color: #e54d42;
}
.tip {
margin-top: 16rpx;
font-size: 24rpx;
color: #999;
}
.section-title {
font-size: 30rpx;
font-weight: 600;
margin-bottom: 16rpx;
}
.file-item {
display: flex;
align-items: center;
padding: 16rpx 0;
border-top: 1rpx solid #f0f0f0;
}
.thumb {
width: 80rpx;
height: 80rpx;
border-radius: 8rpx;
margin-right: 16rpx;
background: #f5f5f5;
}
.file-icon {
width: 80rpx;
height: 80rpx;
border-radius: 8rpx;
margin-right: 16rpx;
background: #fff1f0;
color: #e54d42;
font-size: 24rpx;
display: flex;
align-items: center;
justify-content: center;
}
.file-name {
flex: 1;
font-size: 26rpx;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.link {
color: #1777ff;
font-size: 26rpx;
margin-left: 12rpx;
}
.empty {
text-align: center;
color: #999;
padding: 80rpx 0;
}
</style>