This commit is contained in:
toom1996
2026-10-19 00:33:53 +08:00
parent 335e264e45
commit 549d025afe
8 changed files with 80 additions and 209 deletions

View File

@ -1,13 +1,22 @@
// src/lib/config/env.prod.ts — 生产环境配置(astro build / MODE=production)
import type { AppConfig } from "./types"
// SSR 取数地址:容器里 127.0.0.1/localhost 指的是容器自己,不是后端。
// docker-compose 会注入 BASE_API_SSR=http://backend:8090(服务名解析);
// 非容器部署不注入时回落到本机回环,行为与之前一致。
// 用 globalThis 取 process,避免把 Node 专有的 process 直接写进浏览器 bundle。
const ssrBaseApi: string =
(globalThis as any)?.process?.env?.BASE_API_SSR || "http://localhost:8090"
const config: AppConfig = {
// 空串 = 同源相对:生产由 nginx 把 /api 反代到后端,浏览器直接打同源 /api/v1/...
baseApi: "",
// 按需渲染 SSR 在 Node 里 fetch,必须是绝对 URL(后端在本机/Docker 内部)。
baseApiSsr: "http://localhost:8090",
baseApiSsr: ssrBaseApi,
// 构建期 SSG 内部端口:绑定回环,绝不对公网暴露。
baseApiSsg: "http://127.0.0.1:8091",
// Docker 构建时由 build-arg BASE_API_SSG 注入(配合 build.network=host 访问宿主回环)。
baseApiSsg:
(globalThis as any)?.process?.env?.BASE_API_SSG || "http://127.0.0.1:8091",
idleLogoutDays: 7, // 超过 7 天没访问则登出(0 = 关闭空闲登出)
siteName: "Xisoa", // 站点名(TDK 的 title 后缀 / description 前缀统一来源)
}

View File

@ -40,27 +40,32 @@ export function toAbs(url: string): string {
// 响应式 srcset:基于同一图片 URL 生成多档宽度的候选集,交给浏览器按设备 DPR/视口挑选,
// 避免「一张大图在所有屏幕都下载」造成的带宽浪费(图片站性能关键项)。
//
// 适配本站两类远程图 URL:
// - 缤纷云 S4 CoreIX 样式串:key!style:high → key!w:480 / !w:768 ...(替换 style 段为宽度段)
// - 带查询串:?w=1080&q=80 → 改写 w= 参数
// 本地 /uploads 没有缩放服务,返回空(不生成 srcset,退回单图)。
// 仅对「带查询串」的远程图 URL 生效(?w=1080&q=80 → 改写 w= 参数);
// 其余一律返回空(不生成 srcset,退回单图):
// - 本地 /uploads:没有缩放服务;
// - 缤纷云 S4:**桶上没有开启动态缩放**,只有命名样式(!style:thumb / !style:high),
// 任何 !w:480 这类宽度变体都会 404。
//
// ⚠️ 历史坑(2026-10-15):曾把列表图的 !style:thumb 改写成 !w:480/768/1080/1600 四档,
// 而桶上并未配置动态缩放 → 四档全部 404。关键点是 `<img srcset>` 一旦有候选集,浏览器
// 只从候选里挑、**不会回退到 src**,于是列表整片裂图(封面与缩略图都裂)。
// 故带 !xxx: 样式段的 URL 一律不产出 srcset,直接用后端给的单图。
const SRCSET_WIDTHS = [480, 768, 1080, 1600]
export function toSrcset(url: string): string {
if (!url) return ""
const abs = toAbs(url)
if (!/^https?:\/\//i.test(abs)) return ""
const at = (u: string, w: number): string => {
if (/\!style:/.test(u)) return u.replace(/\!style:[^!]+/, `!w:${w}`)
if (/\!w:\d+/.test(u)) return u.replace(/\!w:\d+/, `!w:${w}`)
// 缤纷云样式串(!style:…)与历史宽度串(!w:…)都不支持按宽度改写,退回单图。
if (/![a-z]+:/i.test(abs)) return ""
return SRCSET_WIDTHS.map((w) => {
try {
const u2 = new URL(u)
const u2 = new URL(abs)
u2.searchParams.set("w", String(w))
return u2.toString()
return `${u2.toString()} ${w}w`
} catch {
return u + (u.includes("?") ? "&" : "?") + "w=" + w
return `${abs + (abs.includes("?") ? "&" : "?") + "w=" + w} ${w}w`
}
}
return SRCSET_WIDTHS.map((w) => `${at(abs, w)} ${w}w`).join(", ")
}).join(", ")
}
// 按需渲染(on-demand SSR)详情 base:必须是绝对 URL(Node fetch 不吃相对路径)。