[Ai] feat(page): 品牌改为 91fans 并切回 A 版落地页

- 品牌名:黄果短剧 / 黄果 / HUANGGUO 全量替换为 91fans,涉及 index.html
  的 title / description / keywords / og / twitter,以及 landing-b 与
  mobile 引导组件的展示文案;APK 文件名改为 91fans.apk
- 域名:hgaidj.app -> 91fans01.com(canonical、iOS 引导页、部署脚本注释)
- 图标:新增 app-icon.webp,favicon.ico、logo-h、logo-m 均按新 App 图标
  重制;删除无引用的旧品牌资源 logo-icon-activity / logo-icon-brick /
  mark-white / qr-huangguo
- 接口:APP_ID 与 iOS H5 描述文件 appId 由 2 改为 3;
  getLandingVersion 固定返回 A
- 落地页:恢复 A 版组件(PcDeck / PcLanding / PcLandingB / MobileLanding
  / share.vue),index.vue 按版本分流,PC 走 PcDeck、手机走 MobileLanding,
  /b 路由保留 B 版
- 移除分享页与手机版的 Telegram / X / Instagram / TikTok 入口及对应样式

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
谢宇宁
2026-09-17 11:04:06 +07:00
co-authored by Claude Opus 5
parent cb90ccb2de
commit 35a856b6f2
29 changed files with 1507 additions and 93 deletions
+10 -10
View File
@@ -11,32 +11,32 @@
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700;900&display=swap" rel="stylesheet" />
<title>黄果短剧|成人短剧APP|每日更新|海量高清</title>
<meta name="description" content="黄果短剧每日更新,海量高清成人短剧、成人影集在线观看,禁忌、诱惑、霸总、逆袭、穿越,精彩黄剧尽在黄果。" />
<meta name="keywords" content="黄果,huangguo,黄果短剧 官网,黄果落地页,黄果短剧 落地页,黄果APP下载,黄果短剧 APP下载,黄果短剧 APP,黄果 下载,黄果短剧 下载,黄果短剧 安卓版,黄果短剧 安卓下载,黄果短剧 APK,黄果短剧 苹果版,黄果短剧 iOS下载,黄果短剧 App Store,黄果 观看,黄果短剧 怎么看,黄果短剧 在哪看,黄果短剧 在线看,黄果短剧 免费看,黄果短剧 全集,黄果短剧 注册,黄果短剧 登录,黄果短剧 会员,黄果短剧 VIP,黄果短剧 客服,黄果短剧 官方,黄果短剧 是什么,黄果短剧 好看吗,黄果短剧 评价,黄果短剧 心得,黄果短剧 安全吗,黄果短剧 收费,黄果短剧 上线时间,黄果短剧 预订,黄果短剧 预约,黄果短剧 通知,短剧,竖屏短剧,直屏短剧,微短剧,迷你剧,短剧集,追剧,在线短剧,短剧平台,短剧 APP,短剧网站,在线看短剧,免费短剧,短剧推荐,热门短剧,短剧下载,逆袭爽剧,小人物逆袭,爽剧,都市情感剧,都市爱情剧,悬疑反转剧,悬疑短剧,甜宠恋爱剧,甜宠剧,古装传奇,古装爽剧,奇幻脑洞,穿越短剧,重生短剧,霸道总裁,通勤看剧,碎片时间追剧,一集十分钟 短剧,上瘾短剧,睡前看剧,短剧 上瘾,什么是短剧,什么是竖屏短剧,红果短剧,ReelShort,DramaBox,番茄短剧,抖音短剧,快手短剧,手机 看短剧,短剧 排行榜,2026 短剧推荐,台湾 短剧,繁体中文 短剧,日本 短剧,短剧 上线通知,黄果 上线时间" />
<title>91fans|成人短剧APP|每日更新|海量高清</title>
<meta name="description" content="91fans 每日更新,海量高清成人短剧、成人影集在线观看,禁忌、诱惑、霸总、逆袭、穿越,精彩短剧尽在 91fans。" />
<meta name="keywords" content="91fans,91fans 官网,91fans 落地页,91fans APP下载,91fans APP下载,91fans APP,91fans 下载,91fans 安卓版,91fans 安卓下载,91fans APK,91fans 苹果版,91fans iOS下载,91fans App Store,91fans 观看,91fans 怎么看,91fans 在哪看,91fans 在线看,91fans 免费看,91fans 全集,91fans 注册,91fans 登录,91fans 会员,91fans VIP,91fans 客服,91fans 官方,91fans 是什么,91fans 好看吗,91fans 评价,91fans 心得,91fans 安全吗,91fans 收费,91fans 上线时间,91fans 预订,91fans 预约,91fans 通知,短剧,竖屏短剧,直屏短剧,微短剧,迷你剧,短剧集,追剧,在线短剧,短剧平台,短剧 APP,短剧网站,在线看短剧,免费短剧,短剧推荐,热门短剧,短剧下载,逆袭爽剧,小人物逆袭,爽剧,都市情感剧,都市爱情剧,悬疑反转剧,悬疑短剧,甜宠恋爱剧,甜宠剧,古装传奇,古装爽剧,奇幻脑洞,穿越短剧,重生短剧,霸道总裁,通勤看剧,碎片时间追剧,一集十分钟 短剧,上瘾短剧,睡前看剧,短剧 上瘾,什么是短剧,什么是竖屏短剧,红果短剧,ReelShort,DramaBox,番茄短剧,抖音短剧,快手短剧,手机 看短剧,短剧 排行榜,2026 短剧推荐,台湾 短剧,繁体中文 短剧,日本 短剧,短剧 上线通知" />
<meta name="robots" content="index, follow" />
<!-- Bing Webmaster Tools -->
<meta name="msvalidate.01" content="__BING_VERIFICATION_TOKEN__" />
<meta property="og:title" content="黄果短剧 | 竖屏短剧APP下载官方入口" />
<meta property="og:site_name" content="黄果短剧" />
<meta property="og:title" content="91fans | 竖屏短剧APP下载官方入口" />
<meta property="og:site_name" content="91fans" />
<meta property="og:type" content="article" />
<meta property="og:image" content="/favicon.ico" />
<meta property="og:description" content="黄果短剧每日更新,海量高清成人短剧、成人影集在线观看,禁忌、诱惑、霸总、逆袭、穿越,精彩黄剧尽在黄果。" />
<meta property="og:description" content="91fans 每日更新,海量高清成人短剧、成人影集在线观看,禁忌、诱惑、霸总、逆袭、穿越,精彩短剧尽在 91fans。" />
<meta name="twitter:title" content="黄果短剧 | 竖屏短剧APP下载官方入口" />
<meta name="twitter:description" content="黄果短剧每日更新,海量高清成人短剧、成人影集在线观看,禁忌、诱惑、霸总、逆袭、穿越,精彩黄剧尽在黄果。" />
<meta name="twitter:title" content="91fans | 竖屏短剧APP下载官方入口" />
<meta name="twitter:description" content="91fans 每日更新,海量高清成人短剧、成人影集在线观看,禁忌、诱惑、霸总、逆袭、穿越,精彩短剧尽在 91fans。" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:image" content="/favicon.ico" />
<meta name="twitter:site" content="黄果短剧" />
<meta name="twitter:site" content="91fans" />
<meta name="theme-color" content="#000000" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="#000000" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="canonical" href="https://hgaidj.app" />
<link rel="canonical" href="https://91fans01.com" />
</head>
+1 -1
View File
@@ -2,6 +2,6 @@
set -e
pnpm run build
zip -q -r dist.zip dist
#黄果落地页地址 :https://hgaidj.app
#91fans 落地页地址 :https://91fans01.com
scp dist.zip root@172.104.166.87:/tmp/dist.zip
ssh root@172.104.166.87 "set -e && rm -rf /tmp/extract && unzip -q /tmp/dist.zip -d /tmp/extract && cd /server/huangguo/landpage/dist/ && rm -rf ./* && mv /tmp/extract/dist/* . && rm -rf /tmp/extract /tmp/dist.zip && echo DEPLOY_OK"
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 43 KiB

+1 -1
View File
@@ -15,7 +15,7 @@ export const bottonclick = (param: donwloadParam) => {
}
// iOS H5 描述文件的 appId 写死
const H5_CONFIG_APP_ID = 2
const H5_CONFIG_APP_ID = 3
// iOS H5 描述文件:返回 .mobileconfig 原文(非 JSON),不走 useHttp
export const downloadH5 = async (data: H5param): Promise<string> => {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

+32 -32
View File
@@ -109,8 +109,8 @@ const {
<header class="nav" :class="{ scrolled: isScrolled }">
<div class="wrap">
<a class="logo" href="#" @click.prevent="switchView('landing')">
<img class="ico" :src="assetUrl('logo-icon-activity.png')" alt="黄果短剧" />
<img class="wm" :src="assetUrl('wordmark-white-1line.png')" alt="黄果短剧" />
<img class="ico" :src="assetUrl('app-icon.webp')" alt="91fans" />
<img class="wm" :src="assetUrl('wordmark-white-1line.png')" alt="91fans" />
</a>
<div class="right">
<button class="btn glass xs" @click="handleDownload()">
@@ -163,7 +163,7 @@ const {
{{ (currentHero?.tags || []).join(' ') }}&nbsp;&nbsp;{{ currentHero?.eps ? `全 ${currentHero.eps} 集 更新至第 ${currentHero.eps} 集` : '连载中' }}&nbsp;&nbsp;2026
</div>
<p class="syn">
{{ currentHero?.syn || '精彩短剧,黄果独家呈现。高清画质与震撼剧情,畅享视听盛宴。' }}
{{ currentHero?.syn || '精彩短剧,91fans独家呈现。高清画质与震撼剧情,畅享视听盛宴。' }}
</p>
<div class="dlhero">
<div class="dlbtns">
@@ -214,7 +214,7 @@ const {
下载 Android 版
</button>
<a class="link brand open-app" href="#" @click.prevent="handleOpenAppDeepLink">
已安装?打开黄果短剧 App
已安装?打开91fans App
<svg class="ic"><use href="#i-arrow-right" /></svg>
</a>
</template>
@@ -353,18 +353,18 @@ const {
<div class="col">
<span class="kicker">关于我们</span>
<h2 class="h2">不是所有短剧,<br />都能被称作作品。</h2>
<p class="sub">黄果短剧,因为专业,所以领先。</p>
<p class="sub">91fans,因为专业,所以领先。</p>
<p>
别人拼命追赶风口,我们定义创造标准。每一支作品都经过精心制作,分镜反复推敲,为一句台词的语气重新生成十次,字幕与剪辑的表情调整到满意为止。这就是我们的匠人精神,也是黄果品质唯一的定义。
别人拼命追赶风口,我们定义创造标准。每一支作品都经过精心制作,分镜反复推敲,为一句台词的语气重新生成十次,字幕与剪辑的表情调整到满意为止。这就是我们的匠人精神,也是91fans品质唯一的定义。
</p>
<p>
我们用 AI 帮助提升作品的品质,把不可能的画面化为可能。题材多元,都会、悬疑、古装、奇幻同步推进;每日更新,精彩不断。短剧与影集双轨并行,仿真与动画齐发。我们只做一件事:把每一支作品,做到值得被记得。
</p>
<p class="slogan">黄果一开,全射出来,每一帧都能解你的色。</p>
<p class="slogan">91fans一开,全射出来,每一帧都能解你的色。</p>
</div>
<div>
<div class="vis">
<img :src="assetUrl('about-visual.png')" alt="黄果短剧 作品视觉" />
<img :src="assetUrl('about-visual.png')" alt="91fans 作品视觉" />
</div>
<div class="tags">
<span class="chip">短剧与影集双轨并行</span>
@@ -376,12 +376,12 @@ const {
</div>
</section>
<!-- ④ 黄果特色 -->
<!-- ④ 91fans特色 -->
<section class="sec" style="padding-top: 0">
<div class="wrap">
<div class="secHead" data-reveal>
<div class="left">
<span class="kicker">黄果特色</span>
<span class="kicker">91fans特色</span>
<h2 class="h2">把最好看的留给你</h2>
</div>
</div>
@@ -415,7 +415,7 @@ const {
<div class="wscrim"></div>
<div class="wrap in">
<div data-reveal>
<h2>现在下载,海量短剧尽在黄果</h2>
<h2>现在下载,海量短剧尽在91fans</h2>
<p class="sub">
支援 iOS / Android&nbsp;&nbsp;双版本 APP,即刻下载,追剧不断档
</p>
@@ -467,7 +467,7 @@ const {
<div class="wrap faq">
<div class="left" data-reveal>
<span class="kicker">常见问题</span>
<h2 class="h2">关于黄果,<br />你想知道的</h2>
<h2 class="h2">关于91fans,<br />你想知道的</h2>
</div>
<div class="acc" data-reveal>
<div
@@ -559,12 +559,12 @@ const {
<footer>
<div class="wrap in">
<div class="lockup">
<img class="ico" :src="assetUrl('logo-icon-activity.png')" alt="黄果短剧" />
<img class="wm" :src="assetUrl('wordmark-white-2line.png')" alt="黄果短剧 hgaidj.app" />
<img class="ico" :src="assetUrl('app-icon.webp')" alt="91fans" />
<img class="wm" :src="assetUrl('wordmark-white-2line.png')" alt="91fans 91fans01.com" />
</div>
<div class="fl">
<a href="#works" @click.prevent="switchView('landing', '#works')">作品精选</a>
<a href="#about" @click.prevent="switchView('landing', '#about')">关于黄果</a>
<a href="#about" @click.prevent="switchView('landing', '#about')">关于91fans</a>
<a href="#faq" @click.prevent="switchView('landing', '#faq')">常见问题</a>
<a href="#" @click.prevent="handleDownload()">下载 APP</a>
</div>
@@ -573,16 +573,16 @@ const {
<p>本网站所呈现之所有人员,于拍摄当时均已年满 18 岁,符合 18 U.S.C. 第 2257 章规定。</p>
</div>
<div class="bot">
<span>© 2026 黄果短剧 HUANGGUO&nbsp;&nbsp;All rights reserved.</span>
<span>© 2026 91fans&nbsp;&nbsp;All rights reserved.</span>
<span>仅限 18 岁以上成年人</span>
</div>
</div>
</footer>
<!-- ============ H5 底部常驻下载条 ============ -->
<div class="mdl" :class="{ show: showMobileStickyBar }">
<img :src="assetUrl('logo-icon-activity.png')" alt="黄果短剧" />
<img :src="assetUrl('app-icon.webp')" alt="91fans" />
<div class="c">
<b>黄果短剧 App</b>
<b>91fans App</b>
<span>免费下载&nbsp;&nbsp;海量短剧每日更新</span>
</div>
<button class="btn primary" @click="handleDownload()">
@@ -597,10 +597,10 @@ const {
<div class="bd"></div>
<div class="dlg">
<div class="grab" aria-hidden="true"></div>
<img class="age-ico" :src="assetUrl('logo-icon-activity.png')" alt="黄果短剧" width="72" height="72" />
<img class="age-ico" :src="assetUrl('app-icon.webp')" alt="91fans" width="72" height="72" />
<h3 id="agegate-title">本站含成人内容</h3>
<p>
黄果短剧仅限 18 岁以上成年人访问。进入即表示您已年满 18 岁、所在地区法律允许浏览成人内容,并同意<a class="privacy" href="#" @click.prevent>《隐私政策》</a>。
91fans仅限 18 岁以上成年人访问。进入即表示您已年满 18 岁、所在地区法律允许浏览成人内容,并同意<a class="privacy" href="#" @click.prevent>《隐私政策》</a>。
</p>
<button class="btn primary md block enter" type="button" @click="confirmAge">
我已年满 18 岁,进入
@@ -616,13 +616,13 @@ const {
:class="{ open: showInstallGuideModal, in: showInstallGuideModal }"
role="dialog"
aria-modal="true"
aria-label="下载黄果短剧 App"
aria-label="下载91fans App"
>
<div class="dlg">
<header class="install-nav">
<button class="back" type="button" aria-label="返回" @click="showInstallGuideModal = false">
<svg class="ic"><use href="#i-chevron-left" /></svg>
<span>下载黄果短剧 App</span>
<span>下载91fans App</span>
</button>
</header>
@@ -630,7 +630,7 @@ const {
<template v-if="installGuideTab === 'ios'">
<div class="install-scroll">
<div class="hd">
<img :src="assetUrl('logo-icon-activity.png')" alt="黄果短剧" width="72" height="72" />
<img :src="assetUrl('app-icon.webp')" alt="91fans" width="72" height="72" />
<h3>安装 iOS 版</h3>
<p>
{{
@@ -670,7 +670,7 @@ const {
<svg class="ic"><use href="#i-si-apple" /></svg>
</div>
<div class="store-title">
<b>黄果短剧&nbsp;&nbsp;App Store 版</b>
<b>91fans&nbsp;&nbsp;App Store 版</b>
<span class="tag-rec">推荐</span>
</div>
<p>
@@ -711,7 +711,7 @@ const {
<span class="n">STEP.3</span>
<div class="c">
<b>返回桌面打开</b>
<span>桌面出现「黄果短剧」图标,点击即可观看。建议同时保存账号凭证。</span>
<span>桌面出现「91fans」图标,点击即可观看。建议同时保存账号凭证。</span>
</div>
</div>
<div class="tip">
@@ -738,7 +738,7 @@ const {
</template>
</button>
<a class="link brand open-app" href="#" @click.prevent="handleOpenAppDeepLink">
已安装?打开黄果短剧 App
已安装?打开91fans App
<svg class="ic"><use href="#i-arrow-right" /></svg>
</a>
</div>
@@ -748,7 +748,7 @@ const {
<template v-else>
<div class="install-scroll">
<div class="hd">
<img :src="assetUrl('logo-icon-activity.png')" alt="黄果短剧" width="72" height="72" />
<img :src="assetUrl('app-icon.webp')" alt="91fans" width="72" height="72" />
<h3>安装 Android 版</h3>
<p>已识别为 Android 设备,下载 APK 直接安装。</p>
</div>
@@ -758,7 +758,7 @@ const {
<span class="n">STEP.1</span>
<div class="c">
<b>下载 APK 安装包</b>
<span>点击「下载 Android 版」,浏览器开始下载 huangguo.apk,下载完成后在通知栏或下载列表点击打开。</span>
<span>点击「下载 Android 版」,浏览器开始下载 91fans.apk,下载完成后在通知栏或下载列表点击打开。</span>
</div>
</div>
<div class="step">
@@ -771,8 +771,8 @@ const {
<div class="step">
<span class="n">STEP.3</span>
<div class="c">
<b>打开黄果短剧</b>
<span>安装完成后点击「打开」,或在桌面找到「黄果短剧」图标即可观看。</span>
<b>打开91fans</b>
<span>安装完成后点击「打开」,或在桌面找到「91fans」图标即可观看。</span>
</div>
</div>
<div class="tip">
@@ -792,7 +792,7 @@ const {
下载 Android 版
</button>
<a class="link brand open-app" href="#" @click.prevent="handleOpenAppDeepLink">
已安装?打开黄果短剧 App
已安装?打开91fans App
<svg class="ic"><use href="#i-arrow-right" /></svg>
</a>
</div>
@@ -1905,7 +1905,7 @@ section.sec {
margin-top: 20px;
}
/* ============ 黄果特色 ============ */
/* ============ 91fans特色 ============ */
.feat {
margin-top: 40px;
display: flex;
+30 -30
View File
@@ -112,8 +112,8 @@ const {
<header class="nav" :class="{ scrolled: isScrolled }">
<div class="wrap">
<a class="logo" href="#" @click.prevent="switchView('landing')">
<img class="ico" :src="assetUrl('logo-icon-activity.png')" alt="黄果短剧" />
<img class="wm" :src="assetUrl('wordmark-white-1line.png')" alt="黄果短剧" />
<img class="ico" :src="assetUrl('app-icon.webp')" alt="91fans" />
<img class="wm" :src="assetUrl('wordmark-white-1line.png')" alt="91fans" />
</a>
<nav class="links">
<a
@@ -128,7 +128,7 @@ const {
:class="{ on: activeAnchor === '#about' && currentView === 'landing' }"
@click.prevent="switchView('landing', '#about')"
>
关于黄果
关于91fans
</a>
<a
href="#faq"
@@ -191,7 +191,7 @@ const {
{{ (currentHero?.tags || []).join(' ') }}&nbsp;&nbsp;{{ currentHero?.eps ? `全 ${currentHero.eps} 集 更新至第 ${currentHero.eps} 集` : '连载中' }}&nbsp;&nbsp;2026
</div>
<p class="syn">
{{ currentHero?.syn || '精彩短剧,黄果独家呈现。高清画质与震撼剧情,畅享视听盛宴。' }}
{{ currentHero?.syn || '精彩短剧,91fans独家呈现。高清画质与震撼剧情,畅享视听盛宴。' }}
</p>
<div class="dlhero">
<div class="qrbox">
@@ -389,18 +389,18 @@ const {
<div class="col">
<span class="kicker">关于我们</span>
<h2 class="h2">不是所有短剧,<br />都能被称作作品。</h2>
<p class="sub">黄果短剧,因为专业,所以领先。</p>
<p class="sub">91fans,因为专业,所以领先。</p>
<p>
别人拼命追赶风口,我们定义创造标准。每一支作品都经过精心制作,分镜反复推敲,为一句台词的语气重新生成十次,字幕与剪辑的表情调整到满意为止。这就是我们的匠人精神,也是黄果品质唯一的定义。
别人拼命追赶风口,我们定义创造标准。每一支作品都经过精心制作,分镜反复推敲,为一句台词的语气重新生成十次,字幕与剪辑的表情调整到满意为止。这就是我们的匠人精神,也是91fans品质唯一的定义。
</p>
<p>
我们用 AI 帮助提升作品的品质,把不可能的画面化为可能。题材多元,都会、悬疑、古装、奇幻同步推进;每日更新,精彩不断。短剧与影集双轨并行,仿真与动画齐发。我们只做一件事:把每一支作品,做到值得被记得。
</p>
<p class="slogan">黄果一开,全射出来,每一帧都能解你的色。</p>
<p class="slogan">91fans一开,全射出来,每一帧都能解你的色。</p>
</div>
<div>
<div class="vis">
<img :src="assetUrl('about-visual.png')" alt="黄果短剧 作品视觉" />
<img :src="assetUrl('about-visual.png')" alt="91fans 作品视觉" />
</div>
<div class="tags">
<span class="chip">短剧与影集双轨并行</span>
@@ -412,12 +412,12 @@ const {
</div>
</section>
<!-- ④ 黄果特色 -->
<!-- ④ 91fans特色 -->
<section class="sec" style="padding-top: 0">
<div class="wrap">
<div class="secHead" data-reveal>
<div class="left">
<span class="kicker">黄果特色</span>
<span class="kicker">91fans特色</span>
<h2 class="h2">把最好看的留给你</h2>
</div>
</div>
@@ -451,7 +451,7 @@ const {
<div class="wscrim"></div>
<div class="wrap in">
<div data-reveal>
<h2>现在下载,海量短剧尽在黄果</h2>
<h2>现在下载,海量短剧尽在91fans</h2>
<p class="sub">
支援 iOS / Android&nbsp;&nbsp;双版本 APP,即刻下载,追剧不断档
</p>
@@ -471,7 +471,7 @@ const {
<span class="qr-lab">扫码下载 App</span>
</div>
<div class="col">
<h4>扫码安装 黄果短剧 App</h4>
<h4>扫码安装 91fans App</h4>
<div class="btns">
<template v-if="hasIosShopPackage">
<button
@@ -532,7 +532,7 @@ const {
<div class="wrap faq">
<div class="left" data-reveal>
<span class="kicker">常见问题</span>
<h2 class="h2">关于黄果,<br />你想知道的</h2>
<h2 class="h2">关于91fans,<br />你想知道的</h2>
</div>
<div class="acc" data-reveal>
<div
@@ -624,12 +624,12 @@ const {
<footer>
<div class="wrap in">
<div class="lockup">
<img class="ico" :src="assetUrl('logo-icon-activity.png')" alt="黄果短剧" />
<img class="wm" :src="assetUrl('wordmark-white-2line.png')" alt="黄果短剧 hgaidj.app" />
<img class="ico" :src="assetUrl('app-icon.webp')" alt="91fans" />
<img class="wm" :src="assetUrl('wordmark-white-2line.png')" alt="91fans 91fans01.com" />
</div>
<div class="fl">
<a href="#works" @click.prevent="switchView('landing', '#works')">作品精选</a>
<a href="#about" @click.prevent="switchView('landing', '#about')">关于黄果</a>
<a href="#about" @click.prevent="switchView('landing', '#about')">关于91fans</a>
<a href="#faq" @click.prevent="switchView('landing', '#faq')">常见问题</a>
<a href="#" @click.prevent="handleDownload()">下载 APP</a>
</div>
@@ -638,7 +638,7 @@ const {
<p>本网站所呈现之所有人员,于拍摄当时均已年满 18 岁,符合 18 U.S.C. 第 2257 章规定。</p>
</div>
<div class="bot">
<span>© 2026 黄果短剧 HUANGGUO&nbsp;&nbsp;All rights reserved.</span>
<span>© 2026 91fans&nbsp;&nbsp;All rights reserved.</span>
<span>仅限 18 岁以上成年人</span>
</div>
</div>
@@ -657,7 +657,7 @@ const {
/>
</span>
<div class="c">
<b>扫码下载黄果短剧 App</b>
<b>扫码下载91fans App</b>
<span>支援 iOS / Android</span>
<button class="btn primary" @click="handleDownload()">
<svg class="ic"><use href="#i-download" /></svg>
@@ -676,10 +676,10 @@ const {
<div class="modal agegate" :class="{ open: showAgeGate, in: showAgeGate }" role="dialog" aria-modal="true" aria-labelledby="agegate-title-pc">
<div class="bd"></div>
<div class="dlg">
<img class="age-ico" :src="assetUrl('logo-icon-activity.png')" alt="黄果短剧" width="72" height="72" />
<img class="age-ico" :src="assetUrl('app-icon.webp')" alt="91fans" width="72" height="72" />
<h3 id="agegate-title-pc">本站含成人内容</h3>
<p>
黄果短剧仅限 18 岁以上成年人访问。进入即表示您已年满 18 岁、所在地区法律允许浏览成人内容,并同意<a class="privacy" href="#" @click.prevent>《隐私政策》</a>。
91fans仅限 18 岁以上成年人访问。进入即表示您已年满 18 岁、所在地区法律允许浏览成人内容,并同意<a class="privacy" href="#" @click.prevent>《隐私政策》</a>。
</p>
<button class="btn primary lg block enter" type="button" @click="confirmAge">
我已年满 18 岁,进入
@@ -697,7 +697,7 @@ const {
<svg class="ic"><use href="#i-x" /></svg>
</button>
<div class="hd">
<h3>下载黄果短剧 App</h3>
<h3>下载91fans App</h3>
<p>
<template v-if="targetDramaForDownload">
下载后即可观看<b>《{{ targetDramaForDownload.t }}》</b>全 {{ targetDramaForDownload.eps || '' }} 集及更多原创作品&nbsp;&nbsp;支援 iOS / Android
@@ -761,7 +761,7 @@ const {
<div class="bot">
<span>
已安装?
<a class="link brand" href="#" @click.prevent="handleOpenAppDeepLink">打开黄果短剧 App</a>
<a class="link brand" href="#" @click.prevent="handleOpenAppDeepLink">打开91fans App</a>
</span>
<a
class="link guide"
@@ -783,8 +783,8 @@ const {
<svg class="ic"><use href="#i-x" /></svg>
</button>
<div class="hd">
<img :src="assetUrl('logo-icon-activity.png')" alt="黄果短剧" />
<h3>安装黄果短剧 App</h3>
<img :src="assetUrl('app-icon.webp')" alt="91fans" />
<h3>安装91fans App</h3>
<p>三步完成,约 1 分钟。安装后可在桌面直接打开。</p>
</div>
<div class="seg">
@@ -810,7 +810,7 @@ const {
<span class="n">STEP.3</span>
<div class="c">
<b>返回桌面打开</b>
<span>桌面出现「黄果短剧」图标,点击即可观看。建议同时保存账号凭证。</span>
<span>桌面出现「91fans」图标,点击即可观看。建议同时保存账号凭证。</span>
</div>
</div>
</div>
@@ -819,7 +819,7 @@ const {
<span class="n">STEP.1</span>
<div class="c">
<b>下载 APK 安装包</b>
<span>点击「下载 Android 版」,浏览器开始下载 huangguo.apk,下载完成后在通知栏或下载列表点击打开。</span>
<span>点击「下载 Android 版」,浏览器开始下载 91fans.apk,下载完成后在通知栏或下载列表点击打开。</span>
</div>
</div>
<div class="step">
@@ -832,8 +832,8 @@ const {
<div class="step">
<span class="n">STEP.3</span>
<div class="c">
<b>打开黄果短剧</b>
<span>安装完成后点击「打开」,或在桌面找到「黄果短剧」图标即可观看。</span>
<b>打开91fans</b>
<span>安装完成后点击「打开」,或在桌面找到「91fans」图标即可观看。</span>
</div>
</div>
</div>
@@ -851,7 +851,7 @@ const {
{{ installGuideTab === 'ios' ? '下载 iOS 版' : '下载 Android 版' }}
</button>
<a class="link brand open-app" href="#" @click.prevent="handleOpenAppDeepLink">
已安装?打开黄果短剧 App
已安装?打开91fans App
<svg class="ic"><use href="#i-arrow-right" /></svg>
</a>
</div>
@@ -1960,7 +1960,7 @@ section.sec {
margin-top: 20px;
}
/* ============ 黄果特色 ============ */
/* ============ 91fans特色 ============ */
.feat {
margin-top: 40px;
display: flex;
+2 -2
View File
@@ -70,11 +70,11 @@ const GENRES = ['都市', '悬疑', '古装', '奇幻', '穿越', '重生', '武
const FAQS = [
{
q: '黄果短剧 App 需要付费吗?',
q: '91fans App 需要付费吗?',
a: 'App 免费下载。海量短剧与影集每日更新,开通会员可解锁全站作品、免广告与高清画质,随时可取消。',
},
{
q: 'iOS 如何安装黄果短剧 App?',
q: 'iOS 如何安装91fans App?',
a: '用 Safari 打开本页,点击「下载 iOS 版」,允许下载描述文件后,前往 设置 › 已下载描述文件 › 安装,输入锁屏密码即可;桌面出现图标即安装完成。',
},
{
+604
View File
@@ -0,0 +1,604 @@
<template>
<div class="m-page">
<!-- 整页背景(背景-4:hero 紫光 + WHO 人物列 + STAY 剧照,一整张) -->
<div class="page-bg">
<picture>
<source type="image/webp" :srcset="pageBgW" />
<img :src="pageBg" alt="" />
</picture>
</div>
<!-- ① Hero -->
<section class="hero">
<swiper
class="hero-bg"
:modules="modules"
:speed="500"
:loop="true"
:grab-cursor="true"
:allow-touch-move="true"
:autoplay="{ delay: 4000, disableOnInteraction: false }"
@slide-change="onSlide"
>
<swiper-slide v-for="(item, i) in PERSONS" :key="i">
<picture>
<source type="image/webp" :srcset="item.w" />
<img :src="item.p" alt="" />
</picture>
</swiper-slide>
</swiper>
<!-- 顶部 logo -->
<div class="top">
<picture class="logo">
<source type="image/webp" :srcset="logoMW" />
<img :src="logoM" alt="91fans" />
</picture>
</div>
<!-- 底部文案 + 圆点 + CTA -->
<div class="hero-bottom">
<div class="theme">
<h1 class="theme-title">每一帧<br /><span>都能</span><span class="hl">解你的色</span></h1>
<p class="theme-desc">91fans每日更新,海量高清成人短剧、成人影集在线观看,禁忌、诱惑、霸总、逆袭、穿越,精彩黄剧尽在91fans。</p>
</div>
<div class="dots">
<i v-for="i in PERSONS.length" :key="i" class="dot" :class="{ active: i - 1 === activeIndex }" />
</div>
<!-- Figma 743:561:正式发布胶囊 + 下载按钮(间距 25) -->
<div class="download-block">
<p class="launch-pill" role="status">
<span class="launch-dot" aria-hidden="true" />
<span>正式发布 · Officially launched</span>
</p>
<template v-if="isIos">
<div v-if="buttonList.shopIosDownUrl" class="cta-row">
<a class="cta cta-lite" data-track="download" role="button" @click="download(0)">轻量版下载</a>
<a class="cta cta-recommend" data-track="download" role="button" @click="download(1)">
商店包下载
<img class="cta-badge" :src="badgeRecommend" alt="推荐" width="56" height="56" />
</a>
</div>
<a v-else class="cta" data-track="download" role="button" @click="download(0)">轻量版下载</a>
</template>
<a v-else class="cta" data-track="download" role="button" @click="download()">{{ downloadLabel }}</a>
</div>
<div class="ctas">
<p class="install-tip">*下载后开启飞行模式安装*安装包报毒解决方案</p>
</div>
</div>
</section>
<!-- ② WHO WE ARE -->
<section class="who">
<div class="who-inner">
<p class="eyebrow">WHO WE ARE</p>
<h2 class="who-title">91fans一开,全射出来<br />这是我们对每一位用户的承诺。</h2>
<div class="paras">
<p>上千部精彩作品任你挑选,热门主题一应俱全。</p>
<p>从暧昧拉扯到禁忌反转,从碎片时间到深夜独处,随时打开,都能快速沉浸、越看越停不下来。</p>
<p>现在就打开这颗「91fans」,尝尝里面究竟藏着什么让人上瘾的滋味。</p>
</div>
<div class="cards">
<div class="card">
<h3>多元齐全</h3>
<p>多元的题材、海量的短剧与影集,我们把最好看的留给你。</p>
</div>
<div class="card">
<h3>天天上新</h3>
<p>持续更新的内容节奏,每天打开都有新惊喜,追剧永不断档。</p>
</div>
<div class="card">
<h3>沉浸体验</h3>
<p>高清画质、震撼音效,每个动作、每个画面,全心投入剧情。</p>
</div>
</div>
</div>
</section>
<!-- ③ STAY TUNED -->
<section class="stay">
<div class="stay-inner">
<p class="eyebrow">STAY TUNED</p>
<h2 class="stay-title">第一时间 不错过上新</h2>
<div class="foot">
<picture class="logo">
<source type="image/webp" :srcset="logoMW" />
<img :src="logoM" alt="91fans" />
</picture>
<p>© 2026 91fans. All rights reserved.</p>
</div>
</div>
</section>
<!-- 下载后的安装引导:Twitter/IG/TikTok → 复制到 Safari;其它 → Figma 三步轻量版安装引导 -->
<IosSafariOpenGuide v-if="isSocialInApp" :show="guide === 'ios'" :url="iosInstallUrl" @close="guide = null" />
<IosInstallGuide v-else :show="guide === 'ios'" @close="guide = null" />
<AndroidInstallTip :show="guide === 'android'" @close="guide = null" />
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import { Swiper, SwiperSlide } from 'swiper/vue'
import { Autoplay } from 'swiper/modules'
import type { Swiper as SwiperClass } from 'swiper/types'
import 'swiper/css'
import { useAppDownload } from '~/utils/useAppDownload'
import IosInstallGuide from '~/components/mobile/IosInstallGuide.vue'
import IosSafariOpenGuide from '~/components/mobile/IosSafariOpenGuide.vue'
import AndroidInstallTip from '~/components/mobile/AndroidInstallTip.vue'
import logoM from '~/assets/image/hg/common/logo-m.png'
import logoMW from '~/assets/image/hg/common/logo-m.webp'
import person1 from '~/assets/image/hg/mobile/person1.png'
import person1W from '~/assets/image/hg/mobile/person1.webp'
import person2 from '~/assets/image/hg/mobile/person2.png'
import person2W from '~/assets/image/hg/mobile/person2.webp'
import person3 from '~/assets/image/hg/mobile/person3.png'
import person3W from '~/assets/image/hg/mobile/person3.webp'
import person4 from '~/assets/image/hg/mobile/person4.png'
import person4W from '~/assets/image/hg/mobile/person4.webp'
import person5 from '~/assets/image/hg/mobile/person5.png'
import person5W from '~/assets/image/hg/mobile/person5.webp'
import pageBg from '~/assets/image/hg/mobile/pagebg.jpg'
import pageBgW from '~/assets/image/hg/mobile/pagebg.webp'
import badgeRecommend from '~/assets/image/hg/mobile/cta/badge-recommend.png'
const modules = [Autoplay]
const activeIndex = ref(0)
// Hero 五张人物图(透明羽化边,叠在固定颜色层上轮播)
const PERSONS = [
{ p: person1, w: person1W },
{ p: person2, w: person2W },
{ p: person3, w: person3W },
{ p: person4, w: person4W },
{ p: person5, w: person5W },
]
function onSlide(sw: SwiperClass) {
activeIndex.value = sw.realIndex
}
// 下载:进页面即拉取下载地址(appId=209,整包 query 作为渠道交后端),点击按平台分流
const { isIos, isSocialInApp, guide, iosInstallUrl, buttonList, init: initDownload, download } = useAppDownload()
const downloadLabel = isIos ? '立即下载 iOS 版' : '立即下载 Android 版'
onMounted(() => {
initDownload()
})
</script>
<style lang="scss" scoped>
@use 'sass:math';
// 设计稿 375 宽,main.js 设 1rem = 屏宽/7.5(375 屏 = 50px);故设计 px → rem 为 /50
@function r($px) {
@return math.div($px, 50) * 1rem;
}
img {
-webkit-user-drag: none;
}
.m-page {
user-select: none;
position: fixed;
inset: 0;
overflow-y: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
background: #1a0d1f;
.eyebrow {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 400;
font-size: 18px;
line-height: 1;
color: #ffb92b;
}
.paras {
display: flex;
flex-direction: column;
gap: r(12);
p {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 400;
font-size: r(14);
line-height: 1.6;
color: #fff;
}
&.center p {
text-align: center;
}
}
}
// 整页背景:一整张 背景-4,按 375 宽自然高度铺满、随内容滚动,三段透明叠在上面
.page-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
z-index: 0;
img {
width: 100%;
height: auto;
display: block;
}
}
// ① Hero
.hero {
position: relative;
width: 100%;
height: 100vh;
height: 100dvh;
overflow: hidden;
// 人物轮播(前景,顶部对齐;紫光由整页背景 .page-bg 提供)
.hero-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
height: r(560);
z-index: 1;
}
:deep(.swiper-slide) {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center top;
}
}
.top {
position: absolute;
top: 0;
left: 0;
right: 0;
height: r(70);
padding: 0 r(24);
display: flex;
align-items: center;
z-index: 3;
pointer-events: none;
}
// 文案层整块盖在轮播上,默认不接触摸(透给下面的 swiper 横滑),只给按钮恢复
.hero-bottom {
position: absolute;
left: 0;
right: 0;
bottom: r(35);
z-index: 3;
display: flex;
flex-direction: column;
align-items: center;
pointer-events: none;
.cta,
.cta-row,
.download-block {
pointer-events: auto;
}
.theme {
align-self: flex-start;
margin: 0 r(40);
width: r(295);
display: flex;
flex-direction: column;
gap: r(16);
.theme-title {
color: #FFF;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-size: 36px;
font-style: normal;
font-weight: 900;
line-height: normal;
.hl {
background: linear-gradient(90deg, #F9D742 -40%, #FF3276 100%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-size: 36px;
font-style: normal;
font-weight: 900;
line-height: normal;
}
}
.theme-desc {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 400;
font-size: r(15);
line-height: 1.6;
color: #fff;
}
}
.dots {
// 标题底 y518 → 圆点 y546 ≈ 28
margin-top: r(28);
display: flex;
align-items: center;
gap: r(10);
.dot {
width: r(8);
height: r(8);
border-radius: 50%;
background: rgba(255, 255, 255, 0.35);
transition: all 0.3s ease;
&.active {
width: r(20);
border-radius: r(4);
background: #fff;
}
}
}
// Figma 743:561:胶囊(29) + 间距25 + 按钮(39) = 93
.download-block {
position: relative;
// 圆点底 y554 → 按钮组 y573 ≈ 19
margin-top: r(19);
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
gap: r(25);
overflow: visible;
}
// Figma 743:562「正式发布 · Officially launched」
.launch-pill {
display: inline-flex;
align-items: center;
gap: r(6);
margin: 0;
padding: r(6) r(10);
box-sizing: border-box;
border-radius: r(999);
border: 1px solid #ffbb2c;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(2px);
-webkit-backdrop-filter: blur(2px);
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 700;
font-size: r(12);
line-height: normal;
color: #ffba2b;
white-space: nowrap;
pointer-events: none;
.launch-dot {
width: r(5);
height: r(5);
border-radius: 50%;
background: #ffba2b;
flex-shrink: 0;
}
}
.ctas {
margin-top: r(12);
display: flex;
flex-direction: column;
align-items: center;
gap: r(12);
overflow: visible;
}
// 下载按钮下的安装提示(文案与参考版一致)
.install-tip {
margin: 0;
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
font-size: r(12);
line-height: 1.4;
color: rgba(255, 255, 255, 0.72);
white-space: nowrap;
}
// iOS 双下载:左白「轻量版」右黄「商店包」(Figma 743:565,宽243 / 左右66)
.cta-row {
display: flex;
align-items: stretch;
gap: r(18);
width: r(243);
margin: 0;
overflow: visible;
.cta {
flex: 1 1 0;
min-width: 0;
display: flex;
align-items: center;
justify-content: center;
height: r(39);
padding: r(8) r(12);
box-sizing: border-box;
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
font-weight: 500;
font-size: r(16);
white-space: nowrap;
}
}
.cta-recommend {
position: relative;
// Figma 777:794:相对按钮组 top17 / 按钮 top54 → 相对按钮 top -37
.cta-badge {
position: absolute;
top: r(-37);
right: r(-32);
width: r(56);
height: r(56);
display: block;
pointer-events: none;
z-index: 2;
}
}
.cta {
padding: r(10) r(28);
border-radius: r(999);
background: #ffb92b;
box-shadow: 0 r(8) r(16) rgba(255, 187, 43, 0.25);
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 525;
font-size: r(14);
line-height: normal;
color: #2a0a2e;
cursor: pointer;
}
.cta-lite {
background: #fff;
box-shadow: none;
}
}
}
// logo 图(hero 顶部 + footer 共用):参考站手机版横图(图标 + 91fans短劇 + 副标),原图 252×60,按 30px 高 = 2x 整数缩放
.logo {
display: block;
img {
height: r(30);
width: auto;
display: block;
}
}
// WHO / STAY:本身透明,整页背景 .page-bg 在底层透出,内容叠在上面
.who,
.stay {
position: relative;
width: 100%;
z-index: 1;
}
// ② WHO WE ARE
.who-inner {
position: relative;
z-index: 1;
padding: r(36) r(30);
display: flex;
flex-direction: column;
gap: r(20);
.who-title {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 900;
font-size: r(30);
line-height: 1.4;
color: #fff;
}
.cards {
margin-top: r(4);
display: flex;
flex-direction: column;
gap: r(14);
.card {
display: flex;
flex-direction: column;
gap: r(5);
padding: r(18) r(12);
align-self: stretch;
border-radius: r(24);
border: 1px solid rgba(255, 210, 63, 0.3);
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
h3 {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 700;
font-size: r(20);
line-height: 1.2;
color: #ffb92b;
margin-bottom: 12px;
}
p {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 400;
font-size: 12px;
line-height: 1.5;
color: rgba(255, 255, 255, 0.85);
}
}
}
}
// ③ STAY TUNED
.stay-inner {
position: relative;
z-index: 1;
padding: r(36) r(30);
display: flex;
flex-direction: column;
align-items: center;
gap: r(24);
.eyebrow {
text-align: center;
}
.stay-title {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 900;
font-size: r(28);
line-height: 1.2;
color: #fff;
text-align: center;
}
.foot {
margin-top: r(8);
display: flex;
flex-direction: column;
align-items: center;
gap: r(12);
.logo {
justify-content: center;
}
p {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 400;
font-size: 12px;
line-height: 1.5;
color: #fff;
text-align: center;
}
}
}
</style>
+51
View File
@@ -0,0 +1,51 @@
<template>
<div class="pc-deck">
<!-- ① A 版(hero 轮播) -->
<section class="deck-page">
<PcLanding />
</section>
<!-- ② 原 B 版(WHO WE ARE) -->
<section class="deck-page">
<PcLandingB />
</section>
<!-- ③ 分享页 -->
<section class="deck-page">
<Share />
</section>
</div>
</template>
<script lang="ts" setup>
import PcLanding from '~/components/landing/PcLanding.vue'
import PcLandingB from '~/components/landing/PcLandingB.vue'
import Share from '~/pages/share.vue'
</script>
<style lang="scss" scoped>
.pc-deck {
width: 100%;
height: 100vh;
overflow-y: scroll;
overflow-x: hidden;
// 整屏强制翻页:每屏吸附、一次滚动只切一屏
scroll-snap-type: y mandatory;
scroll-behavior: smooth;
// 隐藏滚动条
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
}
.deck-page {
width: 100%;
height: 100vh;
overflow: hidden;
scroll-snap-align: start;
scroll-snap-stop: always;
}
</style>
+358
View File
@@ -0,0 +1,358 @@
<template>
<div class="fit" ref="fitEl">
<div class="hg-pc">
<!-- 五页轮播:只切换背景大图 -->
<swiper
class="hero"
:modules="modules"
effect="fade"
:speed="800"
:loop="true"
:allow-touch-move="false"
:autoplay="{ delay: 4000, disableOnInteraction: false }"
@swiper="onSwiper"
>
<swiper-slide v-for="(item, i) in PC_VARIANTS" :key="i">
<div class="slide-bg">
<!-- 首张是首屏第一眼,提优先级;其余保持默认,避免轮播切过去时还没下完 -->
<picture>
<source type="image/webp" :srcset="item.bgW" />
<img :src="item.bg" alt="" :fetchpriority="i === 0 ? 'high' : 'auto'" />
</picture>
</div>
</swiper-slide>
</swiper>
<!-- 固定 chrome 覆盖层(5 页共用):居中 1920 舞台 -->
<div class="stage">
<!-- 顶部 LOGO(白色横版) -->
<div class="top">
<picture>
<source type="image/webp" :srcset="logoHW" />
<img class="logo-h" :src="logoH" alt="91fans" />
</picture>
</div>
<!-- 主文案 -->
<div class="theme">
<h1 class="theme-title">
<span class="line">每一帧</span>
<span class="line"><span>都能</span><span class="hl">解你的色</span></span>
</h1>
<p class="theme-desc">91fans每日更新,海量高清成人短剧、成人影集在线观看,禁忌、诱惑、霸总、逆袭、穿越,精彩黄剧尽在91fans。</p>
</div>
<!-- 行动区:左 = 二维码框;右 = 扫码说明(Figma 659:2 二维码部分) -->
<div class="cta">
<div class="qr-frame">
<div class="qr-inner">
<DesktopQrcode :size="164" />
</div>
</div>
<div class="qr-copy">
<p class="qr-title">使用相机或者浏览器扫码下载</p>
<p class="qr-tip">
安装提示:下载好安装包以后,请断开网络,由于行业原因,本
APP会被某些杀毒软件视为病毒,请放心下载使用,本APP有广告和会员收益,安装本APP不会对您的手机造成任何损害。
</p>
</div>
</div>
<!-- 右下角封面条:整条图固定不换,5 张封面各盖一个热区,点击切到对应轮播页 -->
<div class="covers">
<picture>
<source type="image/webp" :srcset="PC_COVERS.srcW" />
<img :src="PC_COVERS.src" alt="" fetchpriority="high" />
</picture>
<button
v-for="(item, i) in PC_VARIANTS"
:key="i"
class="cover-hit"
:style="{ left: `${i * COVER_STEP}px` }"
type="button"
:aria-label="`查看第 ${i + 1} 部作品`"
@click="goSlide(i)"
/>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, shallowRef, onMounted, onBeforeUnmount } from 'vue'
import { Swiper, SwiperSlide } from 'swiper/vue'
import { Autoplay, EffectFade } from 'swiper/modules'
import type { Swiper as SwiperClass } from 'swiper'
import 'swiper/css'
import 'swiper/css/effect-fade'
import { PC_VARIANTS, PC_COVERS } from '~/config/variants'
import DesktopQrcode from '~/components/desktop/qrcode.vue'
import logoH from '~/assets/image/hg/common/logo-h.png'
import logoHW from '~/assets/image/hg/common/logo-h.webp'
const modules = [Autoplay, EffectFade]
// 封面条几何(同 Figma「轮动」:封面 110 宽、间距 14),热区据此逐张定位
const COVER_STEP = 124
const swiperRef = shallowRef<SwiperClass | null>(null)
function onSwiper(swiper: SwiperClass) {
swiperRef.value = swiper
}
// loop 模式下按真实索引跳转,跳完 autoplay 继续(disableOnInteraction: false)
function goSlide(i: number) {
swiperRef.value?.slideToLoop(i)
}
// 1920×1080 画布按视口 cover 缩放(不再用 body.zoom,避免和翻页滚动冲突)
const fitEl = ref<HTMLElement | null>(null)
function fit() {
const s = Math.min(window.innerWidth / 1920, window.innerHeight / 1080)
fitEl.value?.style.setProperty('--fit', String(s))
}
onMounted(() => {
fit()
window.addEventListener('resize', fit)
})
onBeforeUnmount(() => window.removeEventListener('resize', fit))
</script>
<style lang="scss" scoped>
img {
-webkit-user-drag: none;
}
.fit {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
background: #000;
}
.hg-pc {
user-select: none;
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
// 轮播铺满整屏(背景全幅,cover 独立铺满,不随舞台缩放)
.hero {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
z-index: 0;
}
:deep(.swiper-slide) {
width: 100%;
height: 100%;
}
.slide-bg {
position: absolute;
inset: 0;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
// 固定 chrome:居中 1920 舞台,超过 1920 不左偏
.stage {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(var(--fit, 1));
width: 1920px;
height: 1080px;
z-index: 2;
pointer-events: none;
}
// 顶部 LOGO
.top {
position: absolute;
left: 220px;
top: 38px;
.logo-h {
width: 220px;
height: 77px;
object-fit: contain;
display: block;
}
}
.theme {
position: absolute;
left: 244px;
top: 323px;
width: 630px;
display: flex;
flex-direction: column;
gap: 24px;
.theme-title {
margin: 0;
display: flex;
flex-direction: column;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 900;
font-size: 105px;
line-height: 1.44;
white-space: nowrap;
color: #fff;
.line {
display: flex;
gap: 10px;
}
.hl {
background: linear-gradient(90deg, #f9d742, #ff3276);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
}
.theme-desc {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 400;
font-size: 24px;
line-height: 1.42;
color: #fff;
}
}
// 行动区:二维码 + 文案(Figma 659:2)
.cta {
position: absolute;
left: 244px;
top: 777px;
display: flex;
align-items: center;
gap: 31px;
pointer-events: auto;
// 220 圆角框:渐变描边(稿面自上而下橙 → 玫红)
.qr-frame {
flex-shrink: 0;
width: 220px;
height: 220px;
border-radius: 24px;
padding: 2px;
box-sizing: border-box;
background: linear-gradient(180deg, #f9d742 0%, #cb865f 45%, #f75562 100%);
}
.qr-inner {
width: 100%;
height: 100%;
border-radius: 22px;
background: #000;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
:deep(.qrContent) {
height: 188px;
.left {
width: 188px;
height: 188px;
margin-right: 0;
border-radius: 12px;
overflow: hidden;
.qr {
width: 188px;
height: 188px;
padding: 12px;
box-sizing: border-box;
background-color: #fff;
display: flex;
align-items: center;
justify-content: center;
.qrcode {
padding: 0;
}
}
}
}
}
.qr-copy {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 20px;
font-family: 'PingFang SC', 'Noto Serif SC', 'Songti SC', sans-serif;
font-style: normal;
line-height: 1.6;
}
.qr-title {
margin: 0;
font-weight: 500;
font-size: 24px;
color: #f75562;
white-space: nowrap;
}
.qr-tip {
margin: 0;
width: 505px;
font-weight: 500;
font-size: 18px;
color: #fff;
}
}
// 右下角封面条(5 页共用同一张)
.covers {
position: absolute;
left: 1184px;
top: 778px;
width: 606px;
height: 152px;
pointer-events: auto;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
// 盖在整条图上的 5 个点击热区,与图内封面一一对齐
.cover-hit {
position: absolute;
top: 0;
width: 110px;
height: 152px;
padding: 0;
border: 1px solid transparent;
border-radius: 12px;
background: transparent;
cursor: pointer;
transition: background 0.2s, border-color 0.2s;
&:hover {
border-color: rgba(255, 255, 255, 0.75);
background: rgba(255, 255, 255, 0.16);
}
}
}
}
</style>
+223
View File
@@ -0,0 +1,223 @@
<template>
<div class="fit" ref="fitEl">
<div class="hg-pc-b">
<!-- 整页背景(倾斜剧照拼贴 + 暗化遮罩,已在设计中烘焙为一张图) -->
<div class="bg">
<!-- 第二屏资源:滚到才加载,不占首屏带宽(视口内时 lazy 会立即加载,单独访问不受影响) -->
<picture>
<source type="image/webp" :srcset="bgW" />
<img :src="bg" alt="" loading="lazy" fetchpriority="low" />
</picture>
</div>
<!-- 居中内容:左侧介绍 + 右侧三卡 -->
<div class="stage">
<div class="content">
<div class="intro">
<div class="head">
<p class="eyebrow">WHO WE ARE</p>
<h2 class="title">91fans一开,全射出来<br />这是我们对每一位用户的承诺。</h2>
</div>
<div class="paras">
<p>上千部精彩作品任你挑选,热门主题一应俱全。</p>
<p>从暧昧拉扯到禁忌反转,从碎片时间到深夜独处,随时打开,都能快速沉浸、越看越停不下来。</p>
<p>现在就打开这颗「91fans」,尝尝里面究竟藏着什么让人上瘾的滋味。</p>
</div>
</div>
<div class="cards">
<div class="card">
<h3>多元齐全</h3>
<p>多元的题材、海量的短剧与影集,我们把最好看的留给你。</p>
</div>
<div class="card">
<h3>天天上新</h3>
<p>持续更新的内容节奏,每天打开都有新惊喜,追剧永不断档。</p>
</div>
<div class="card">
<h3>沉浸体验</h3>
<p>高清画质、震撼音效,每个动作、每个画面,全心投入剧情。</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import bg from '~/assets/image/hg/pc/b-bg.jpg'
import bgW from '~/assets/image/hg/pc/b-bg.webp'
// 1920×1080 画布按视口 cover 缩放(不再用 body.zoom)
const fitEl = ref<HTMLElement | null>(null)
function fit() {
const s = Math.min(window.innerWidth / 1920, window.innerHeight / 1080)
fitEl.value?.style.setProperty('--fit', String(s))
}
onMounted(() => {
fit()
window.addEventListener('resize', fit)
})
onBeforeUnmount(() => window.removeEventListener('resize', fit))
</script>
<style lang="scss" scoped>
img {
-webkit-user-drag: none;
}
.fit {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
background: #000;
}
.hg-pc-b {
user-select: none;
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
background: #000;
.bg {
position: absolute;
inset: 0;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.stage {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(var(--fit, 1));
width: 1920px;
height: 1080px;
z-index: 2;
}
.content {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: flex;
align-items: center;
gap: 52px;
}
.intro {
width: 840px;
display: flex;
flex-direction: column;
gap: 60px;
.head {
display: flex;
flex-direction: column;
gap: 24px;
}
.eyebrow {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 400;
font-size: 36px;
line-height: 1;
color: #ffb92b;
}
.title {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 900;
font-size: 60px;
line-height: 1.4;
color: #fff;
}
.paras {
display: flex;
flex-direction: column;
gap: 18px;
p {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 400;
font-size: 20px;
line-height: 1.6;
color: #fff;
}
}
}
.cards {
display: flex;
align-items: center;
gap: 20px;
.card {
position: relative;
width: 230px;
box-sizing: border-box;
padding: 70px 35px;
border-radius: 30px;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 15px;
// 外框渐变描边:只画 2px 边框一圈(顶部亮金 → 底部渐隐),内部仍是透明玻璃
&::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
padding: 2px;
background: linear-gradient(180deg, #ffd23f 0%, rgba(255, 210, 63, 0.5) 40%, rgba(255, 210, 63, 0.08) 100%);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
}
h3 {
margin: 0;
width: 160px;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 700;
font-size: 36px;
line-height: 1.2;
color: #ffb92b;
}
p {
margin: 0;
width: 160px;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 400;
font-size: 22px;
line-height: 1.5;
text-align: justify;
color: #fff;
opacity: 0.6;
}
}
}
}
</style>
+8 -8
View File
@@ -1,6 +1,6 @@
<template>
<!-- Safari 轻量版安装引导:三步(Figma 63:89569 / 63:89572) -->
<div v-if="show" class="ios-guide" role="dialog" aria-label="黄果短剧轻量版安装引导">
<div v-if="show" class="ios-guide" role="dialog" aria-label="91fans轻量版安装引导">
<header class="guide-head">
<button class="nav-back" type="button" @click="emit('close')">
<img class="nav-back-ico" :src="iconBack" alt="" width="24" height="24" />
@@ -9,16 +9,16 @@
<div class="top">
<picture class="logo">
<source type="image/webp" :srcset="logoHW" />
<img :src="logoH" alt="黄果短剧" width="79" height="28" />
<img :src="logoH" alt="91fans" width="79" height="28" />
</picture>
<span class="domain">hgaidj.app</span>
<span class="domain">91fans01.com</span>
</div>
</header>
<div class="content">
<div class="head">
<p class="kicker">轻量版安装</p>
<h2 class="title">黄果短剧 轻量版安装引导</h2>
<h2 class="title">91fans 轻量版安装引导</h2>
<p class="desc">三步完成,约 1 分钟。安装后可在桌面直接打开。</p>
</div>
@@ -31,7 +31,7 @@
<div class="card">
<div class="ios-alert">
<div class="alert-body">
<p>“hgaidj.app”正尝试下载配置描述文件。要允许吗?</p>
<p>“91fans01.com”正尝试下载配置描述文件。要允许吗?</p>
</div>
<div class="alert-btns">
<div class="alert-btn muted">忽略</div>
@@ -56,7 +56,7 @@
<span class="path-brand">已下载描述文件</span>
</div>
<div class="path-row">
<span class="path-text">黄果短剧</span>
<span class="path-text">91fans</span>
<img class="ico-film" :src="iconFilm" alt="" width="12" height="12" />
<img class="ico-chevron" :src="iconChevron" alt="" width="14" height="14" />
<span class="path-brand">安装</span>
@@ -78,13 +78,13 @@
<span class="step-name">返回桌面打开</span>
</div>
<div class="card">
<p class="card-body">桌面出现「黄果短剧」图标,点击即可观看。建议同时保存账号凭证。</p>
<p class="card-body">桌面出现「91fans」图标,点击即可观看。建议同时保存账号凭证。</p>
</div>
</section>
<button class="cta" type="button" @click="emit('close')">
<img class="cta-ico" :src="iconPlay" alt="" width="16" height="16" />
<span>已安装,打开黄果短剧</span>
<span>已安装,打开91fans</span>
</button>
</div>
</div>
+3 -3
View File
@@ -9,9 +9,9 @@
<div class="top">
<picture class="logo">
<source type="image/webp" :srcset="logoHW" />
<img :src="logoH" alt="黄果短剧" width="79" height="28" />
<img :src="logoH" alt="91fans" width="79" height="28" />
</picture>
<span class="domain">hgaidj.app</span>
<span class="domain">91fans01.com</span>
</div>
</header>
@@ -46,7 +46,7 @@
</div>
</div>
<p class="foot">官方备用地址&nbsp;&nbsp;hgaidj.app</p>
<p class="foot">官方备用地址&nbsp;&nbsp;91fans01.com</p>
</div>
</div>
</template>
+2 -2
View File
@@ -1,2 +1,2 @@
// 黄果 App 在下载接口(blsp01.com /api/stat/version)的 appId
export const APP_ID = 2
// 91fans App 在下载接口(blsp01.com /api/stat/version)的 appId
export const APP_ID = 3
+20 -1
View File
@@ -1,9 +1,28 @@
<script setup>
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import PcDeck from '~/components/landing/PcDeck.vue'
import MobileLanding from '~/components/landing/MobileLanding.vue'
import LandingB from '~/components/landing-b/LandingB.vue'
import { getLandingVersion } from '~/utils/landingVersion'
const route = useRoute()
const isMobile = computed(() =>
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
)
// A/B 分流:与 getButtonList 共用同一份版本(见 landingVersion.ts),当前固定 A
const isVersionB = getLandingVersion(route.query, route.path) === 'B'
const landingComponent = computed(() => {
if (isVersionB) return LandingB
return isMobile.value ? MobileLanding : PcDeck
})
</script>
<template>
<LandingB />
<component :is="landingComponent" />
</template>
<style scoped></style>
+159
View File
@@ -0,0 +1,159 @@
<template>
<div class="fit" ref="fitEl">
<div class="hg-share">
<!-- 背景:剧照网格拼贴 + 暗化遮罩(Figma 导出整图) -->
<div class="bg">
<!-- 作为落地页第三屏时滚到才加载;单独访问 /share 时它在视口内,lazy 会立即加载 -->
<picture>
<source type="image/webp" :srcset="bgW" />
<img :src="bg" alt="" loading="lazy" fetchpriority="low" />
</picture>
</div>
<!-- 居中内容 -->
<div class="stage">
<div class="content">
<div class="head">
<p class="eyebrow">STAY TUNED</p>
<h1 class="title">第一时间 不错过上新</h1>
</div>
<div class="footer">
<picture>
<source type="image/webp" :srcset="logoHW" />
<img class="logo-h" :src="logoH" alt="91fans" />
</picture>
<p>© 2026 91fans. All rights reserved.</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import bg from '~/assets/image/hg/pc/share-bg.jpg'
import bgW from '~/assets/image/hg/pc/share-bg.webp'
import logoH from '~/assets/image/hg/common/logo-h.png'
import logoHW from '~/assets/image/hg/common/logo-h.webp'
// 1920×1080 画布按视口 cover 缩放(不再用 body.zoom)
const fitEl = ref<HTMLElement | null>(null)
function fit() {
const s = Math.min(window.innerWidth / 1920, window.innerHeight / 1080)
fitEl.value?.style.setProperty('--fit', String(s))
}
onMounted(() => {
fit()
window.addEventListener('resize', fit)
})
onBeforeUnmount(() => window.removeEventListener('resize', fit))
</script>
<style lang="scss" scoped>
img {
-webkit-user-drag: none;
}
.fit {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
background: #000;
}
.hg-share {
user-select: none;
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
background: #000;
.bg {
position: absolute;
inset: 0;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.stage {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(var(--fit, 1));
width: 1920px;
height: 1080px;
z-index: 2;
}
.content {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 60px;
}
.head {
display: flex;
flex-direction: column;
align-items: center;
gap: 24px;
.eyebrow {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 400;
font-size: 36px;
line-height: 1;
color: #ffb92b;
}
.title {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 900;
font-size: 60px;
line-height: 1.2;
color: #fff;
text-align: center;
}
}
.footer {
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
.logo-h {
width: 220px;
height: 77px;
object-fit: contain;
display: block;
}
p {
margin: 0;
font-family: 'Noto Serif SC', 'PingFang SC', 'Songti SC', serif;
font-weight: 400;
font-size: 16px;
line-height: 1.4;
color: #fff;
text-align: center;
}
}
}
</style>
+2 -2
View File
@@ -1,5 +1,5 @@
/**
* 落地页版本:已下线 A 版,固定 B(getButtonList 等接口带 version=B)
* 落地页版本:固定 A(getButtonList 等接口带 version=A)
*/
export type LandingAbVersion = 'A' | 'B'
@@ -7,5 +7,5 @@ export function getLandingVersion(
_query?: Record<string, unknown>,
_path?: string,
): LandingAbVersion {
return 'B'
return 'A'
}
+1 -1
View File
@@ -158,7 +158,7 @@ export function useAppDownload() {
*/
async function download(index = 0, terminal: Terminal = isIos ? 'ios' : 'android') {
const trace_id = renewSessionTraceId()
// 写剪贴板供 App 首次启动读取做安装归因:整包 URL 参数 + tid(黄果 App 按 tid 读)
// 写剪贴板供 App 首次启动读取做安装归因:整包 URL 参数 + tid(91fans App 按 tid 读)
copyToClipboard(JSON.stringify({ ...route.query, tid: trace_id }))
if (terminal === 'ios' && index !== 1) {