Files
hjc-web/server/api/tender/detail.get.ts
T
weicw1996 9299485899 feat(hjc-web): 标书详情加「收藏」按钮,「我的收藏」页与顶栏入口
后端接口是端无关的,本轮 **mp-java 零改动**,纯前端 + Nitro 代理。

- 新增 favorites.get/post/delete 三个站内代理,原样透传 ApiResult
  (HTTP 恒 200,按 body.code 判登录态与业务失败)。delete 用查询串传 projectId。
- detail.get.ts 补发 Authorization:详情接口内联了 favorited,而它此前是匿名调用,
  已收藏的项目会显示成「未收藏」。未登录时不带这个头,行为与改动前完全一致
  (返回体仍整体返回 data,favorited 正是靠这一点透传的)。
- 「我的收藏」做成**模板无关的公共路由** app/pages/tender/favorites.vue(10 套模板共用),
  顶栏 HjcUserBar 在「我的订单」后加入口。列表按收藏时间倒序 + 加载更多;
  只渲染后端算好的 saleState/purchased(前端不再判一遍);失效项目**保留条目**、
  点击只提示不进详情、仍可取消;取消收藏弹二次确认(复用 HjcConfirmDialog)。
  取数用 useRequestFetch —— 裸 $fetch 在 SSR 不转发 cookie,会被代理当成匿名调用,
  拿到 401 后 handleAuthCode 会清凭据跳登录,等于刷新页面把自己登出。
- template-07 详情页加收藏按钮(heart SVG 两态,不引图标库),未登录点它跳登录、
  回跳带 favorite=1 后自动补一次收藏(只在客户端 onMounted 做,不改写 URL——
  详情壳是 :key="route.fullPath",改 query 会重挂载并与收藏请求赛跑)。
  取数同样改用 useRequestFetch,否则首屏 favorited 恒为 false。
- 只改 template-07:10 套模板里只有它有 TenderDetail.vue,其余按需再补。
2026-09-17 17:37:10 +08:00

56 lines
2.1 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, getRouterParam, getHeader, getCookie } from 'h3'
import { useRuntimeConfig } from '#imports'
import { getTenantFromContext } from '../../utils/tenant'
/**
* 标书项目详情
* GET /api/tender/detail?id=1 (或 /api/tender/{id}
* 代理到 mp-apimp-java) hjc 标书项目详情,返回扁平化项目对象;不存在则 404。
*
* 返回体**整体**返回后端 data(不逐字段挑选):后端新增的 `favorited`(是否已收藏)
* 正是靠这一点透传过来的,改成字段白名单就会把它丢掉。
*/
export default defineEventHandler(async (event) => {
const config = useRuntimeConfig()
const ctx = getTenantFromContext(event, config)
const id = getRouterParam(event, 'id') || (getQuery(event) as any)?.id
const modulesApiBase = config.public.modulesApiBase as string
/**
* 转发登录态。详情接口本身是**公开**的(匿名也返回 code=0),但它的返回体里内联了一个
* `favorited`:匿名调用时后端按契约返回 `false`,页面就会把已收藏的项目显示成「未收藏」。
*
* 未登录时没有 cookie → 不带这个头 → 行为与改动前**完全一致**(向后兼容)。
*/
const cookieToken = getCookie(event, 'hjc_token')
const auth = getHeader(event, 'authorization') || (cookieToken ? `Bearer ${cookieToken}` : null)
if (!id) {
throw createError({ statusCode: 400, statusMessage: '缺少 id' })
}
try {
const res = await $fetch(`/hjc/bid-project/${id}`, {
baseURL: modulesApiBase,
headers: {
TenantId: ctx.tenantId,
...(auth ? { Authorization: auth } : {})
}
}) as any
const data = res && res.data !== undefined ? res.data : res
if (!data) {
throw createError({ statusCode: 404, statusMessage: '标书项目不存在' })
}
return data
} catch (error: any) {
if (error?.statusCode === 404) {
throw error
}
throw createError({
statusCode: error?.statusCode || error?.response?.status || 502,
statusMessage: error?.statusMessage || 'Failed to fetch tender detail'
})
}
})