1ff4dfffb9
发票由一站式平台开具后推给后端(官方网不开票,见工作区根目录 docs/adr/0006), 订单响应里新增 invoices;文件是本平台副本,下载走与附件同一条链路(点击时取票)。 - 抽出 composable useAttachmentDownload:把「先换票据、再取文件」的逻辑从 HjcTenderFiles 里提出来,附件与发票共用(各写一份必然分叉);同时把资源标识解析 扩到 orderNo/projectNo/invoiceId 三种。 - 新增 HjcInvoiceFiles.vue:发票号/类型/开票日期/金额 + 下载;作废(红冲)的也列出来 且仍可下载——它是留档凭证。 - HjcTenderFiles.vue 改用 composable,行为不变。 - 订单详情加发票区块,订单列表加「已开票」标记与发票列表。 - 不判"是否已支付":有没有发票取决于甲方开没开票,与订单当前状态无关。 校验:npm run build 通过。
82 lines
2.6 KiB
Vue
82 lines
2.6 KiB
Vue
<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"
|
||
>
|
||
<!-- 用内联 SVG,避免为一个小图标引入图标库依赖(同 PageAttachments.vue) -->
|
||
<span class="shrink-0 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="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||
<path d="M14 2v6h6" />
|
||
</svg>
|
||
</span>
|
||
|
||
<button
|
||
type="button"
|
||
class="min-w-0 flex-1 truncate text-left text-sm text-blue-600 hover:underline disabled:opacity-60"
|
||
:title="nameOf(file)"
|
||
:disabled="busyKey === file.url"
|
||
@click="download(file, file.url)"
|
||
>
|
||
{{ nameOf(file) }}
|
||
</button>
|
||
|
||
<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 { HjcTenderFile } from '~/types/tender'
|
||
|
||
/**
|
||
* 附件列表(订单列表页、订单详情页、项目详情的公告附件共用)。
|
||
*
|
||
* 只渲染后端下发的 `tenderFiles` / `bulletinFiles`:**发不发由后端定**
|
||
* (标书附件仅 `payStatus === 1` 的订单下发、公告附件随项目上下架),
|
||
* 所以这里不做任何权限判断,也不从项目字段里自己拼地址。
|
||
*
|
||
* 「点击下载」走 `useAttachmentDownload`:先换一张一次性票据、再取文件
|
||
* (为什么要绕这一圈见该 composable 的注释)。
|
||
*/
|
||
const props = withDefaults(
|
||
defineProps<{
|
||
files?: HjcTenderFile[] | null
|
||
}>(),
|
||
{
|
||
files: () => []
|
||
}
|
||
)
|
||
|
||
/** 过滤掉没有地址的脏数据(后端已保证,前端再兜一层,避免渲染出死链) */
|
||
const files = computed<HjcTenderFile[]>(() =>
|
||
(props.files || []).filter((f) => !!f && typeof f.url === 'string' && f.url.length > 0)
|
||
)
|
||
|
||
const { busyKey, errorText, download } = useAttachmentDownload()
|
||
|
||
function nameOf(file: HjcTenderFile) {
|
||
return file.name || '标书附件'
|
||
}
|
||
</script>
|