[Ai] feat: 花魁短剧 Next.js 站点初始提交

- 原生 Next.js App Router + 严格 TypeScript 实现花魁短剧 PC/H5 页面,按 src/features/{catalog,content,playback} 组织,保留完整 SEO(metadata、JSON-LD、canonical、robots、llms、sitemap、IndexNow)。
- 主域名通过 SITE_URL=https://huakuidj.com 强制覆盖后端 foreverUrlAddr(config/*.env、src/server/config.ts、src/server/seo/shared.ts、src/server/services/shared.ts),支持邮箱改为 support@huakuidj.com。
- 移除登录与账户体系:删除 /account 全部页面、登录/注册/充值弹窗、收藏点赞、评论、金币解锁及对应 BFF 接口;旧账户地址 GET/HEAD 统一 301 到首页(src/lib/routes.ts REMOVED_ACCOUNT_PATHS),保留游客会话、反馈、图片上传、观看上报与搜索联想。
- 播放页:评论位改为同类推荐 + 热播榜单,锁定集改为 App 观看遮罩与底部弹层,新增简介标签、分集图例与独立视觉皮肤(src/features/playback、src/styles/pages/playback.css)。
- 卡片:短剧/视频卡状态与时长移至信息行胶囊标签,封面角标移至左上角(src/components/catalog/Cards.tsx、src/styles/foundations/base.css)。
- 同步更新单元测试、浏览器冒烟脚本、路由清单与 README。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
谢宇宁
2026-10-16 11:33:31 +07:00
co-authored by Claude Opus 5.5
commit d2ddb1c321
423 changed files with 52152 additions and 0 deletions
+155
View File
@@ -0,0 +1,155 @@
"use client";
import type { Data } from "@/server/services/model";
import { Icon } from "@/components/ui/Icon";
import { QRCode } from "@/components/ui/QRCode";
import { appDownloadURL } from "@/lib/app-download";
import { useSite } from "@/components/providers/SiteProvider";
import { NavigationLink } from "./SiteHeader";
export function SiteFooter({ data }: { data: Data }) {
const site = useSite(),
config = data.config || {},
qrValue = appDownloadURL(data.appConfig) || appDownloadURL(config),
appAddr = qrValue || "/app/download/";
const download = (event: React.MouseEvent) => {
event.preventDefault();
site.openDownload();
};
const nav = (label: string, items: [string, string, string][]) => (
<nav className="hk-footer-col" aria-label={label}>
<h3>{label}</h3>
{items.map(([href, title, key]) => (
<a
key={key}
href={href}
{...(/^https?:/.test(href)
? { target: "_blank", rel: "sponsored nofollow noopener" }
: {})}
data-navigation-key={"footer_" + key}
data-navigation-name={title}
>
{title}
</a>
))}
</nav>
);
const social = [
["brand-x", config.twitterAddr, "X"],
[
"brand-telegram",
config.tgGroup || config.telegram || config.telegramAdd,
"Telegram",
],
].filter(([, url]) => url);
return (
<footer className="hk-site-footer">
<div className="hk-site-footer__inner">
<div className="hk-site-footer__top">
<div className="hk-site-footer__brand">
<div className="hk-brand">
<picture>
<source
media="(max-width:768px)"
srcSet="/static/brand/header.svg"
/>
<img
className="hk-brand__logo hk-brand__logo--lg"
src="/static/brand/footer.svg"
width="124"
height="44"
alt="花魁短剧"
/>
</picture>
</div>
<p className="hk-content-section__subtitle">每一帧都值得细看</p>
<div className="hk-social">
{social.map(([icon, url, label]) => (
<a
className="hk-social__item"
href={url}
key={icon}
target="_blank"
rel="sponsored nofollow noopener"
aria-label={label}
data-navigation-key={"footer_" + label.toLowerCase()}
data-navigation-name={label}
>
<Icon name={icon} />
</a>
))}
</div>
</div>
<div className="hk-site-footer__links">
<nav className="hk-footer-col" aria-label="浏览">
<h3>浏览</h3>
{(data.categoryList || []).map((item: Data, index: number) => (
<NavigationLink key={index} item={item} data={data} />
))}
</nav>
{nav("帮助", [
["/about/", "关于我们", "about"],
["/help/", "常见问题", "help"],
["/return-home/", "回家的路", "home_road"],
["/feedback/", "意见反馈", "feedback"],
[
config.customerServiceHost || "/feedback/",
"联系我们",
"contact",
],
])}
{nav("条款", [
["/terms/", "用户条款", "terms"],
["/privacy/", "隐私政策", "privacy"],
["/2257/", "2257 合规声明", "2257"],
["/dmca/", "DMCA 版权声明", "dmca"],
])}
<a
className="hk-footer-download-mobile"
data-download-open=""
href={appAddr}
onClick={download}
data-navigation-key="footer_download_mobile"
data-navigation-name="下载 App"
>
下载 App
</a>
<div className="hk-footer-download">
<div className="hk-app-download-qr" aria-label="扫码下载">
<QRCode value={qrValue} />
</div>
<div className="hk-footer-download__copy">
<strong>扫码下载 App</strong>
<p>iOS / Android 海量短剧每日更新</p>
<a
className="hk-button hk-button--primary hk-button--sm"
data-download-open=""
href={appAddr}
onClick={download}
data-navigation-key="footer_download"
data-navigation-name="下载 APP"
>
<Icon name="download" className="hk-icon hk-icon--sm" />
下载 App
</a>
</div>
</div>
</div>
</div>
<hr className="hk-site-footer__rule" />
<div className="hk-site-footer__legal">
<p>
© 2026 花魁短剧 HUAKUI 
<span className="hk-site-footer__rights">All rights reserved.</span>
<span className="hk-site-footer__mobile-adult">
仅限 18 岁以上成年人
</span>
</p>
<p>
<span className="hk-site-footer__adult">仅限 18 岁以上成年人 </span>
本网站所呈现之所有人员,于拍摄当时均已年满 18 岁,符合 18 U.S.C. 第
2257 条规定。
</p>
</div>
</div>
</footer>
);
}