feat(hjc-web): 订单页展示并下载电子发票
发票由一站式平台开具后推给后端(官方网不开票,见工作区根目录 docs/adr/0006), 订单响应里新增 invoices;文件是本平台副本,下载走与附件同一条链路(点击时取票)。 - 抽出 composable useAttachmentDownload:把「先换票据、再取文件」的逻辑从 HjcTenderFiles 里提出来,附件与发票共用(各写一份必然分叉);同时把资源标识解析 扩到 orderNo/projectNo/invoiceId 三种。 - 新增 HjcInvoiceFiles.vue:发票号/类型/开票日期/金额 + 下载;作废(红冲)的也列出来 且仍可下载——它是留档凭证。 - HjcTenderFiles.vue 改用 composable,行为不变。 - 订单详情加发票区块,订单列表加「已开票」标记与发票列表。 - 不判"是否已支付":有没有发票取决于甲方开没开票,与订单当前状态无关。 校验:npm run build 通过。
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<ul v-if="files.length" class="space-y-2">
|
||||
<li
|
||||
v-for="(file, idx) in files"
|
||||
:key="file.url + idx"
|
||||
class="flex items-center gap-3 rounded-lg border border-gray-200 px-4 py-2.5"
|
||||
>
|
||||
<span class="shrink-0" :class="file.status === 'CANCELLED' ? 'text-gray-400' : 'text-blue-600'" aria-hidden="true">
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.8"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M4 3h16v18l-8-4-8 4z" />
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<div class="min-w-0 flex-1">
|
||||
<p class="truncate text-sm text-gray-900">
|
||||
发票号 {{ file.invoiceNo || '-' }}
|
||||
<span v-if="file.status === 'CANCELLED'" class="ml-2 text-xs text-gray-500">已作废</span>
|
||||
</p>
|
||||
<p class="mt-0.5 truncate text-xs text-gray-500">
|
||||
{{ typeLabel(file.invoiceType) }}
|
||||
<template v-if="file.invoiceDate"> · {{ file.invoiceDate }}</template>
|
||||
<template v-if="file.amount !== undefined && file.amount !== null">
|
||||
· ¥{{ Number(file.amount).toFixed(2) }}
|
||||
</template>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="shrink-0 text-sm text-blue-600 hover:underline disabled:opacity-60"
|
||||
:disabled="busyKey === file.url"
|
||||
@click="download(file, file.url)"
|
||||
>
|
||||
{{ busyKey === file.url ? '正在准备…' : '下载' }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p v-if="errorText" class="mt-2 text-sm text-red-500">{{ errorText }}</p>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { HjcInvoiceFile } from '~/types/tender'
|
||||
|
||||
/**
|
||||
* 电子发票列表(订单详情页用)。
|
||||
*
|
||||
* 发票是**一站式平台开具后推给我们的**(官方网不开票,见工作区根目录
|
||||
* `docs/adr/0006-invoice-issued-by-one-stop-platform.md`),文件留的是**本平台副本**,
|
||||
* 所以下载链路与标书附件一致:点击时先换一次性票据(`useAttachmentDownload`)。
|
||||
*
|
||||
* 作废(红冲)的发票**照样列出来**且仍可下载:它是留档凭证,用户与客服都要能看到原件。
|
||||
*/
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
files?: HjcInvoiceFile[] | null
|
||||
}>(),
|
||||
{
|
||||
files: () => []
|
||||
}
|
||||
)
|
||||
|
||||
const files = computed<HjcInvoiceFile[]>(() =>
|
||||
(props.files || []).filter((f) => !!f && typeof f.url === 'string' && f.url.length > 0)
|
||||
)
|
||||
|
||||
const { busyKey, errorText, download } = useAttachmentDownload()
|
||||
|
||||
/** 发票类型:后端给的是 VAT_NORMAL / VAT_SPECIAL,界面上说人话 */
|
||||
function typeLabel(type?: string) {
|
||||
if (type === 'VAT_SPECIAL') return '电子专用发票'
|
||||
if (type === 'VAT_NORMAL') return '电子普通发票'
|
||||
return '电子发票'
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user