公开页补齐自引用 Canonical 与按类型的结构化数据,图片补上说明文字。

后台设置和内容编辑改成可导航布局;部署用访客 origin 生成 Canonical,避免落到容器地址。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-20 00:11:24 +08:00
parent 2b3d122e56
commit 40bbad2c82
51 changed files with 3042 additions and 1318 deletions

View File

@@ -45,18 +45,18 @@ export default function BrandLockup({
{src ? (
both ? (
<>
<Logo src={logoLight} fit={fit} extra="j13-brand-logo-light" />
<Logo src={logoDark} fit={fit} extra="j13-brand-logo-dark" />
<Logo src={logoLight} fit={fit} alt={label} decorative={showText} extra="j13-brand-logo-light" />
<Logo src={logoDark} fit={fit} alt={label} decorative={showText} extra="j13-brand-logo-dark" />
</>
) : (
<Logo src={src} fit={fit} />
<Logo src={src} fit={fit} alt={label} decorative={showText} />
)
) : (
<Bubble h={box.h} />
<Bubble h={box.h} label={showText ? undefined : label} />
)}
</span>
) : (
<Bubble h={36} />
<Bubble h={36} label={showText ? undefined : label} />
)
) : null}
{showText ? (
@@ -75,10 +75,26 @@ export default function BrandLockup({
);
}
function Logo({ src, fit, extra = "" }: { src: string; fit: BrandLogoFit; extra?: string }) {
function Logo({
src,
fit,
alt,
decorative = false,
extra = "",
}: {
src: string;
fit: BrandLogoFit;
alt: string;
/** 旁边已有站名时,读屏跳过,HTML 仍保留 alt 供检索 */
decorative?: boolean;
extra?: string;
}) {
if (fit === "repeat") {
return (
<span
role={decorative ? undefined : "img"}
aria-hidden={decorative || undefined}
aria-label={decorative ? undefined : alt}
className={`j13-brand-logo j13-brand-logo-tile ${extra}`}
style={{ backgroundImage: `url("${src.replace(/["\\\n\r]/g, "")}")` }}
/>
@@ -86,17 +102,20 @@ function Logo({ src, fit, extra = "" }: { src: string; fit: BrandLogoFit; extra?
}
return (
/* eslint-disable-next-line @next/next/no-img-element */
<img src={src} alt="" className={`j13-brand-logo ${extra}`} />
<img src={src} alt={alt} aria-hidden={decorative || undefined} className={`j13-brand-logo ${extra}`} />
);
}
function Bubble({ h }: { h: number }) {
function Bubble({ h, label }: { h: number; label?: string }) {
return (
<span
role={label ? "img" : undefined}
aria-label={label}
aria-hidden={label ? undefined : true}
className="j13-brand-bubble rounded-2xl flex items-center justify-center shrink-0 transition-transform duration-300 group-hover:rotate-[-6deg]"
style={{ width: h, height: h, background: "var(--accent)", color: "var(--accent-on)" }}
>
<svg width="50%" height="50%" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
<svg aria-hidden="true" focusable="false" width="50%" height="50%" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" />
</svg>
</span>