Files
hjc-web/server/api/tender/attachment-ticket.get.ts
T
weicw-dshsa fb5a8ce4a2 fix(attachment): 官网电子发票下载报「发票ID不能为空」
取票中转 route 的转发 query 是手写白名单,只带 kind/orderNo/projectNo/index,漏了 invoiceId。官网点发票下载时后端因此只收到 kind=invoice、没有发票 id,命中 HjcAttachmentController 的入参校验,原样回 code=1「发票ID不能为空」。补上解构与转发,并在注释里写清三种资源标识都要转发(tender 按订单号、bulletin 按项目编号、invoice 按发票 id)。
2026-09-30 10:13:10 +08:00

61 lines
2.8 KiB
TypeScript
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.
import { $fetch } from 'ofetch'
import { createError, defineEventHandler, getHeader, getCookie, getQuery } from 'h3'
import { useRuntimeConfig } from '#imports'
import { getTenantFromContext } from '../../utils/tenant'
/**
* 取附件下载票据(一次性、短时)。
* GET /api/tender/attachment-ticket?kind=tender&orderNo=xxx&index=0
* GET /api/tender/attachment-ticket?kind=bulletin&projectNo=xxx&index=0
* GET /api/tender/attachment-ticket?kind=invoice&invoiceId=xxx&index=0
*
* **三种资源标识都要转发**:`kind=invoice`(电子发票)的标识是 `invoiceId`,
* 漏了它后端只会看到「kind=invoice 但没有发票 id」,直接回
* `{"code":1,"message":"发票ID不能为空"}`——本路由曾漏过这一个字段。
*
* 为什么要它:一站式的静态文件服务加了鉴权,附件不再直连,改由后端反代
* (工作区根目录 `docs/adr/0007-attachment-download-via-platform-proxy.md`)。
* 下发给前端的附件地址是**本平台的资源地址**(只有 kind/订单号或项目编号或发票 id/序号,
* 没有路径、也没有票据);**点击下载时**才来这里换一张票据,再用票据去
* `{modulesApiBase}/api/hjc/attachment?ticket=…` 取文件。
*
* 为什么票据要现取而不能直接放进列表里的地址:票据很短命,"页面开着放一会儿再点"
* 会撞过期;现取则永远新鲜(ADR 0007 补记)。
*
* 约定:原样透传 ApiResult{code,message,data},HTTP 状态码恒为 200。
* `code=401`(未登录)与 `code=403`(未支付/无权/已下架)都是**业务码**,
* 前端必须按 code 判定——401 要清凭据跳登录,403 只提示。
*/
export default defineEventHandler(async (event) => {
const config = useRuntimeConfig()
const ctx = getTenantFromContext(event, config)
const { kind, orderNo, projectNo, invoiceId, index } = getQuery(event)
const cookieToken = getCookie(event, 'hjc_token')
const auth = getHeader(event, 'authorization') || (cookieToken ? `Bearer ${cookieToken}` : null)
try {
return await $fetch('/hjc/attachment/ticket', {
baseURL: config.public.modulesApiBase,
method: 'GET',
headers: {
TenantId: ctx.tenantId,
...(auth ? { Authorization: auth } : {})
},
query: {
TenantId: ctx.tenantId,
kind,
index,
...(orderNo ? { orderNo } : {}),
...(projectNo ? { projectNo } : {}),
// 电子发票按发票 id 取件;漏掉这一行,发票下载必报「发票ID不能为空」
...(invoiceId ? { invoiceId } : {})
}
})
} catch (error: any) {
throw createError({
statusCode: error?.statusCode || error?.response?.status || 502,
statusMessage: error?.statusMessage || 'Failed to fetch attachment ticket'
})
}
})