452d7fef8f
删写死 mock(DEFAULT_LAST_COMPARE_RECORD + localStorage 读),改带 Bearer token 拉真实比价记录;取最近一条 status=success 且 created_at 在 4 分钟内才显示(对齐原生 HomeViewModel.loadLastCompare),否则/未登录/401 隐藏横幅;进页 + 回前台 visibilitychange 各拉一次;点击仍走 SGBridge.navigate('compareResult')。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
10398 lines
434 KiB
HTML
10398 lines
434 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
|
||
|
||
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>比价APP 高保真原型 (外卖版)</title>
|
||
<style>
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
html { background: #000; }
|
||
body { font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; background: #000; display: flex; justify-content: center; align-items: center; min-height: 100vh; }
|
||
:root {
|
||
--primary: #FFD600; --primary-dark: #F5C500; --primary-light: #FFEB3B; --primary-bg: #FFFDE7;
|
||
--primary-pale: #FFFAEC;
|
||
--primary-gradient: linear-gradient(180deg, #FFE066 0%, #FFD600 100%);
|
||
--primary-gradient-soft: linear-gradient(180deg, #FFFAEC 0%, #FFEEB0 100%);
|
||
--accent-orange: #FF5722; --accent-red: #E53935;
|
||
--success: #4CAF50; --success-bg: #E8F5E9; --warning: #FFC107; --error: #F44336; --info: #2196F3;
|
||
--coin: #FFB300; --coin-bg: #FFF8E1;
|
||
--gray-900: #1A1A1A; --gray-800: #333; --gray-700: #4D4D4D; --gray-600: #666; --gray-500: #999; --gray-400: #B3B3B3; --gray-300: #CCC; --gray-200: #E5E5E5; --gray-100: #F5F5F5; --gray-50: #FAFAFA; --bg: #F5F5F5;
|
||
/* Onboarding 统一 token(B 方案) */
|
||
--cta-radius: 25px;
|
||
--cta-height: 50px;
|
||
--cta-font-size: 17px;
|
||
--cta-font-weight: 700;
|
||
--cta-letter-spacing: 1.5px;
|
||
--cta-shadow: 0 6px 18px rgba(255,179,0,.38), inset 0 1px 0 rgba(255,255,255,.55);
|
||
--cta-shadow-active: 0 3px 10px rgba(255,179,0,.30), inset 0 1px 0 rgba(255,255,255,.55);
|
||
--shadow-card-sm: 0 2px 8px rgba(0,0,0,.06);
|
||
--shadow-card-md: 0 6px 18px rgba(0,0,0,.08);
|
||
}
|
||
.device { width: 375px; height: 812px; background: #fff; border-radius: 32px; overflow: hidden; position: relative; box-shadow: 0 20px 60px rgba(0,0,0,0.5); }
|
||
.screen { position: absolute; inset: 0; display: none; flex-direction: column; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; }
|
||
.screen.active { display: flex; }
|
||
.screen.noscroll { overflow-y: hidden; }
|
||
.screen::-webkit-scrollbar { display: none; }
|
||
/* 通用样式 */
|
||
.header { display: flex; align-items: center; justify-content: space-between; padding: 40px 16px 12px; background: #fff; flex-shrink: 0; }
|
||
.header-title { font-size: 17px; font-weight: 600; color: var(--gray-900); }
|
||
.back-btn { font-size: 15px; font-weight: 600; color: var(--gray-800); cursor: pointer; background: none; border: none; }
|
||
.btn { display: flex; align-items: center; justify-content: center; border: none; border-radius: 14px; font-weight: 600; cursor: pointer; transition: opacity .15s; }
|
||
.btn:active { opacity: .7; }
|
||
.btn-primary { background: var(--primary); color: #1a1a1a; }
|
||
.btn-outline { background: transparent; border: 1.5px solid var(--primary); color: #1a1a1a; }
|
||
.btn-secondary { background: var(--primary-bg); color: var(--primary); }
|
||
.btn-lg { padding: 12px 24px; font-size: 17px; width: 100%; }
|
||
.btn-md { padding: 8px 16px; font-size: 15px; }
|
||
.btn-sm { padding: 8px 16px; font-size: 13px; }
|
||
/* ===== Onboarding 统一 CTA(B 方案)===== */
|
||
.btn-cta {
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
border: none; cursor: pointer;
|
||
background: var(--primary-gradient);
|
||
color: var(--gray-900);
|
||
font-family: inherit;
|
||
font-size: var(--cta-font-size);
|
||
font-weight: var(--cta-font-weight);
|
||
letter-spacing: var(--cta-letter-spacing);
|
||
border-radius: var(--cta-radius);
|
||
height: var(--cta-height);
|
||
box-shadow: var(--cta-shadow);
|
||
transition: transform .12s ease, box-shadow .2s ease, opacity .15s ease;
|
||
}
|
||
.btn-cta:active { transform: translateY(1px); box-shadow: var(--cta-shadow-active); }
|
||
.btn-cta.size-lg { width: 100%; padding: 0 24px; }
|
||
.btn-cta.size-md { padding: 0 24px; height: 44px; font-size: 15px; letter-spacing: 1px; border-radius: 24px; }
|
||
.btn-cta.size-pill { padding: 0 16px; height: 36px; font-size: 13px; letter-spacing: .5px; border-radius: 18px; }
|
||
/* 文字辅助按钮(取消、放弃等) */
|
||
.btn-text {
|
||
background: none; border: none; cursor: pointer;
|
||
color: var(--gray-500); font-size: 14px; font-weight: 500;
|
||
font-family: inherit; transition: opacity .15s;
|
||
}
|
||
.btn-text:active { opacity: .6; }
|
||
/* ===== Splash CTA Variants ===== */
|
||
.splash-cta { width: 100%; border: none; padding: 16px 0; border-radius: 14px; font-size: 17px; font-weight: 700; cursor: pointer; transition: transform .15s, box-shadow .25s; position: relative; overflow: hidden; }
|
||
.splash-cta:active { transform: scale(.97); }
|
||
/* V1 红橙渐变(当前) */
|
||
.splash-cta-v1 { background: linear-gradient(135deg, #FE2C55, #FF6B3D); color: #fff; box-shadow: 0 6px 16px rgba(255,68,68,.30); }
|
||
/* V2 黄底黑字(品牌主色) */
|
||
.splash-cta-v2 { background: #FFD600; color: #1a1a1a; box-shadow: 0 6px 16px rgba(255,214,0,.45); }
|
||
/* V3 黑底黄字(高对比) */
|
||
.splash-cta-v3 { background: #1a1a1a; color: #FFD600; box-shadow: 0 6px 16px rgba(0,0,0,.25); }
|
||
/* V4 黄→金渐变 + 光泽扫过 */
|
||
.splash-cta-v4 { background: linear-gradient(135deg, #FFEB3B 0%, #FFD600 50%, #FFA000 100%); color: #1a1a1a; box-shadow: 0 6px 20px rgba(249,168,37,.45); }
|
||
.splash-cta-v4::after { content: ""; position: absolute; top: 0; left: -75%; width: 50%; height: 100%; background: linear-gradient(120deg, transparent, rgba(255,255,255,.6), transparent); transform: skewX(-25deg); animation: ctaShine 2.6s infinite; }
|
||
@keyframes ctaShine { 0% { left: -75%; } 60%, 100% { left: 125%; } }
|
||
/* V5 玻璃质感 黄+白光 */
|
||
.splash-cta-v5 { background: linear-gradient(180deg, #FFEB3B, #FFC400); color: #1a1a1a; box-shadow: inset 0 1px 0 rgba(255,255,255,.7), inset 0 -2px 0 rgba(0,0,0,.08), 0 8px 20px rgba(255,193,7,.35); }
|
||
/* V6 描边款(克制风) */
|
||
.splash-cta-v6 { background: #fff; color: #1a1a1a; border: 2px solid #1a1a1a; box-shadow: 4px 4px 0 #FFD600; }
|
||
.splash-cta-v6:active { box-shadow: 2px 2px 0 #FFD600; transform: translate(2px, 2px); }
|
||
/* V7 红包红(喜庆款) */
|
||
.splash-cta-v7 { background: linear-gradient(135deg, #E53935 0%, #E02E24 100%); color: #FFD600; box-shadow: 0 6px 18px rgba(198,40,40,.40); text-shadow: 0 1px 2px rgba(0,0,0,.2); }
|
||
/* V8 跳动呼吸款(黄底) */
|
||
.splash-cta-v8 { background: #FFD600; color: #1a1a1a; box-shadow: 0 6px 16px rgba(255,214,0,.45); animation: ctaPulse 1.6s ease-in-out infinite; }
|
||
@keyframes ctaPulse { 0%,100% { transform: scale(1); box-shadow: 0 6px 16px rgba(255,214,0,.45);} 50% { transform: scale(1.03); box-shadow: 0 10px 24px rgba(255,214,0,.65);} }
|
||
/* V9 蜜糖渐变(黄→琥珀,温暖软渐变,无扫光)*/
|
||
.splash-cta-v9 { background: linear-gradient(180deg, #FFE066 0%, #FFB300 100%); color: #1a1a1a; box-shadow: 0 8px 22px rgba(255,140,0,.4); }
|
||
/* V10 金币描边(品牌黄 + 深金细边 + 内嵌高光,模拟铸币感)*/
|
||
.splash-cta-v10 { background: linear-gradient(180deg, #FFE066 0%, #FFD600 100%); color: #1a1a1a; border: 1.5px solid #8B6914; box-shadow: inset 0 1px 0 rgba(255,255,255,.7), 0 6px 18px rgba(184,134,11,.35); }
|
||
/* ===== Coupon Subtitle Variants ===== */
|
||
.cps { font-family: inherit; }
|
||
/* V1 当前灰色基线 */
|
||
.cps-v1 { font-size: 13px;font-weight: 500;color: var(--gray-500);line-height: 1.5; }
|
||
/* V2 系列:金币胶囊家族 */
|
||
.cps-v2 { display: inline-flex;align-items: center;gap: 6px;padding: 6px 12px;border-radius: 999px;background: linear-gradient(180deg,#FFE066,#FFC400);color: #5A3A00;font-size: 12px;font-weight: 600;letter-spacing: .2px;box-shadow: inset 0 1px 0 rgba(255,255,255,.7),0 2px 6px rgba(255,179,0,.35); }
|
||
.cps-v2 .cps-coin { width: 14px;height: 14px;border-radius: 50%;background: radial-gradient(circle at 35% 30%,#FFE0B2,#FFA000);box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);display: inline-flex;align-items: center;justify-content: center;font-size: 10px;font-weight: 900;color: #7A4F00; }
|
||
/* V2b 金币翻转动效 */
|
||
.cps-v2b { display: inline-flex;align-items: center;gap: 6px;padding: 6px 12px;border-radius: 999px;background: linear-gradient(180deg,#FFE066,#FFC400);color: #5A3A00;font-size: 12px;font-weight: 600;letter-spacing: .2px;box-shadow: inset 0 1px 0 rgba(255,255,255,.7),0 2px 6px rgba(255,179,0,.35); }
|
||
.cps-v2b .cps-coin { width: 14px;height: 14px;border-radius: 50%;background: radial-gradient(circle at 35% 30%,#FFE0B2,#FFA000);box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);display: inline-flex;align-items: center;justify-content: center;font-size: 10px;font-weight: 900;color: #7A4F00;animation: coinFlip 2.4s ease-in-out infinite; }
|
||
@keyframes coinFlip { 0%,70%,100% { transform: rotateY(0); } 80% { transform: rotateY(180deg); } 90% { transform: rotateY(360deg); } }
|
||
/* V2c 双色分段 */
|
||
.cps-v2c { display: inline-flex;align-items: center;padding: 0;border-radius: 999px;background: linear-gradient(180deg,#FFE066,#FFC400);font-size: 12px;font-weight: 600;letter-spacing: .2px;box-shadow: inset 0 1px 0 rgba(255,255,255,.7),0 2px 6px rgba(255,179,0,.35);overflow: hidden; }
|
||
.cps-v2c .cps-tag { background: #1a1a1a;color: #FFD600;padding: 6px 8px;font-weight: 900;letter-spacing: .5px;display: inline-flex;align-items: center;gap: 2px; }
|
||
.cps-v2c .cps-text { padding: 6px 12px 6px 8px;color: #5A3A00; }
|
||
/* V2d 闪光描边(轻盈款) */
|
||
.cps-v2d { position: relative;display: inline-flex;align-items: center;gap: 6px;padding: 6px 12px;border-radius: 999px;background: #FFFDF5;color: #1a1a1a;font-size: 12px;font-weight: 600;letter-spacing: .2px;border: 1.5px solid transparent;background-image: linear-gradient(#FFFDF5,#FFFDF5),linear-gradient(135deg,#FFD600,#F9A825,#FFD600);background-origin: border-box;background-clip: padding-box,border-box;box-shadow: 0 2px 8px rgba(255,179,0,.2); }
|
||
.cps-v2d .cps-coin { width: 14px;height: 14px;border-radius: 50%;background: radial-gradient(circle at 35% 30%,#FFE0B2,#FFA000);box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);display: inline-flex;align-items: center;justify-content: center;font-size: 10px;font-weight: 900;color: #7A4F00; }
|
||
/* V2e 数字嵌入款 */
|
||
.cps-v2e { display: inline-flex;align-items: center;gap: 6px;padding: 4px 12px 4px 8px;border-radius: 999px;background: linear-gradient(180deg,#FFE066,#FFC400);color: #5A3A00;font-size: 12px;font-weight: 600;letter-spacing: .2px;box-shadow: inset 0 1px 0 rgba(255,255,255,.7),0 2px 6px rgba(255,179,0,.35); }
|
||
.cps-v2e .cps-amount { display: inline-flex;align-items: baseline;background: #1a1a1a;color: #FFD600;padding: 2px 8px;border-radius: 999px;font-weight: 900;font-size: 12px;letter-spacing: .3px; }
|
||
.cps-v2e .cps-amount small { font-size: 10px;font-weight: 700;opacity: .85;margin-left: 2px; }
|
||
/* V2f 双图标夹击 */
|
||
.cps-v2f { display: inline-flex;align-items: center;gap: 4px;padding: 6px 12px;border-radius: 999px;background: linear-gradient(180deg,#FFE066,#FFC400);color: #5A3A00;font-size: 12px;font-weight: 600;letter-spacing: .2px;box-shadow: inset 0 1px 0 rgba(255,255,255,.7),0 2px 6px rgba(255,179,0,.35); }
|
||
.cps-v2f .cps-coin { width: 14px;height: 14px;border-radius: 50%;background: radial-gradient(circle at 35% 30%,#FFE0B2,#FFA000);box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);display: inline-flex;align-items: center;justify-content: center;font-size: 10px;font-weight: 900;color: #7A4F00; }
|
||
.cps-v2f .cps-bolt { width: 12px;height: 12px;display: inline-flex;align-items: center;justify-content: center; }
|
||
.cps-v2f .cps-bolt svg { display: block; }
|
||
/* V2g 立体浮起 */
|
||
.cps-v2g { display: inline-flex;align-items: center;gap: 6px;padding: 6px 12px;border-radius: 999px;background: linear-gradient(180deg,#FFE066 0%,#FFD600 50%,#FFA000 100%);color: #5A3A00;font-size: 12px;font-weight: 900;letter-spacing: .2px;box-shadow: inset 0 1.5px 0 rgba(255,255,255,.85),inset 0 -1.5px 0 rgba(184,134,11,.3),0 6px 14px rgba(249,168,37,.45),0 1px 2px rgba(0,0,0,.1);text-shadow: 0 1px 0 rgba(255,255,255,.4); }
|
||
.cps-v2g .cps-coin { width: 15px;height: 15px;border-radius: 50%;background: radial-gradient(circle at 35% 30%,#FFE0B2,#FFA000);box-shadow: inset 0 -1.5px 0 rgba(0,0,0,.2),0 1px 1px rgba(0,0,0,.15);display: inline-flex;align-items: center;justify-content: center;font-size: 10px;font-weight: 900;color: #7A4F00; }
|
||
.cps-v3f { display: inline-flex;align-items: center;gap: 6px;padding: 4px 12px;border-radius: 999px;background: rgba(255,179,0,.18);color: #8B6914;font-size: 12px;font-weight: 600;letter-spacing: .2px; }
|
||
.cps-v3f .cps-coin { display: inline-flex;align-items: center;justify-content: center;font-size: 15px;line-height: 1; }
|
||
/* V3 关键词高亮 */
|
||
.cps-v3 { font-size: 13px;font-weight: 500;color: var(--gray-700);line-height: 1.5; }
|
||
.cps-v3 em { font-style: normal;font-weight: 900;color: #1a1a1a;background: linear-gradient(to top,#FFD600 45%,transparent 45%);padding: 0 2px; }
|
||
/* V4 优惠券齿边小票 */
|
||
.cps-v4 { position: relative;display: inline-flex;align-items: stretch;background: #fff;border: 1.5px dashed #FFB300;border-radius: 8px;padding: 4px 12px;font-size: 12px;font-weight: 600;color: #E02E24;letter-spacing: .3px;box-shadow: 0 1px 4px rgba(255,179,0,.25); }
|
||
.cps-v4::before, .cps-v4::after { content: "";position: absolute;top: 50%;width: 8px;height: 8px;border-radius: 50%;background: #FFF3C4;transform: translateY(-50%); }
|
||
.cps-v4::before { left: -5px; }
|
||
.cps-v4::after { right: -5px; }
|
||
.cps-v4 .cps-amt { color: #1a1a1a;background: #FFD600;padding: 2px 6px;border-radius: 4px;margin: 0 4px;font-weight: 900; }
|
||
/* V5 数字驱动徽章 */
|
||
.cps-v5 { display: inline-flex;align-items: center;gap: 8px;padding: 4px 6px 4px 12px;border-radius: 999px;background: rgba(26,26,26,.06);font-size: 12px;font-weight: 600;color: var(--gray-800); }
|
||
.cps-v5 .cps-pill { display: inline-flex;align-items: baseline;gap: 2px;padding: 2px 8px;border-radius: 999px;background: #1a1a1a;color: #FFD600;font-weight: 900;font-size: 12px;letter-spacing: .3px; }
|
||
.cps-v5 .cps-pill small { font-size: 10px;font-weight: 700;opacity: .85; }
|
||
/* V6 双行节奏 */
|
||
.cps-v6 { display: flex;flex-direction: column;align-items: center;gap: 2px;line-height: 1.3; }
|
||
.cps-v6 .cps-top { font-size: 11px;font-weight: 600;color: var(--gray-500);letter-spacing: .5px;text-transform: uppercase; }
|
||
.cps-v6 .cps-bot { font-size: 13px;font-weight: 600;color: #E02E24; }
|
||
.cps-v6 .cps-bot em { font-style: normal;color: #1a1a1a;background: linear-gradient(to top,#FFD600 45%,transparent 45%);padding: 0 2px;font-weight: 900; }
|
||
|
||
/* ===== Tweaks Panel ===== */
|
||
.tweaks-panel { position: fixed; right: 20px; bottom: 20px; width: 280px; background: #fff; border-radius: 14px; box-shadow: 0 8px 32px rgba(0,0,0,.18); padding: 16px; z-index: 9998; font-family: -apple-system, sans-serif; display: none; }
|
||
.tweaks-panel.open { display: block; }
|
||
.tweaks-panel h3 { font-size: 14px; font-weight: 700; color: #1a1a1a; margin-bottom: 4px; }
|
||
.tweaks-panel .tweaks-sub { font-size: 11px; color: #999; margin-bottom: 12px; }
|
||
.tweaks-panel .tweaks-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
|
||
.tweaks-opt { padding: 8px 8px; border-radius: 8px; border: 1.5px solid #e5e5e5; cursor: pointer; font-size: 12px; font-weight: 600; color: #333; background: #fff; text-align: center; transition: all .15s; }
|
||
.tweaks-opt:hover { border-color: #999; }
|
||
.tweaks-opt.active { background: #FFD600; border-color: #FFD600; color: #1a1a1a; }
|
||
.tweaks-opt small { display: block; font-size: 10px; font-weight: 500; color: #999999; margin-top: 2px; }
|
||
.tweaks-opt.active small { color: #5A3A00; }
|
||
.tweaks-close { position: absolute; top: 10px; right: 10px; width: 22px; height: 22px; border-radius: 12px; background: #f0f0f0; border: none; cursor: pointer; font-size: 13px; line-height: 1; color: #666; }
|
||
.card { background: #fff; border-radius: 14px; padding: 16px; box-shadow: 0 2px 8px rgba(0,0,0,.06); }
|
||
.section-title { font-size: 17px; font-weight: 600; color: var(--gray-900); margin-bottom: 12px; }
|
||
.badge { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
|
||
/* Tab bar — 4 tab + 中央 AI 领券 FAB(平 tab bar + FAB 站在上面,下半部分被白底视觉包住) */
|
||
.tab-bar { display: flex; height: 60px; background: #fff; border-top: .5px solid var(--gray-200); flex-shrink: 0; position: relative; overflow: visible; }
|
||
.tab-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; cursor: pointer; position: relative; z-index: 1; }
|
||
.tab-icon { width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; }
|
||
.tab-label { font-size: 11px; color: var(--gray-800); font-weight: 400; }
|
||
.tab-item.active .tab-label { color: var(--gray-900); font-weight: 700; }
|
||
.tab-icon .i-outline { display: block; }
|
||
.tab-icon .i-filled { display: none; }
|
||
.tab-item.active .tab-icon .i-outline { display: none; }
|
||
.tab-item.active .tab-icon .i-filled { display: block; }
|
||
.welfare-tab-dot {
|
||
position: absolute;
|
||
left: 50%;
|
||
top: 9px;
|
||
width: 10px;
|
||
height: 10px;
|
||
border-radius: 50%;
|
||
background: #FF3B30;
|
||
border: 1px solid #FFFFFF;
|
||
box-shadow: 0 2px 5px rgba(255, 59, 48, .32);
|
||
transform: translateX(7px);
|
||
display: none;
|
||
pointer-events: none;
|
||
z-index: 3;
|
||
}
|
||
.tab-item.has-welfare-dot .welfare-tab-dot { display: block; }
|
||
/* 横幅轮播 */
|
||
@keyframes marqueeScroll { 0%{transform: translateX(0);} 100%{transform: translateX(-50%);} }
|
||
.marquee-wrap { overflow: hidden;border-radius: 8px;background: #FFF3E0;margin-bottom: 8px;height: 32px;display: flex;align-items: center; }
|
||
/* 用户案例翻页横幅 */
|
||
.flip-banner { height: 36px;border-radius: 18px;background: linear-gradient(90deg,#FFF3E0,#FFE0B2);margin-bottom: 12px;perspective: 800px;padding: 0 6px 0 4px; }
|
||
.flip-banner-stage { width: 100%;height: 100%;position: relative;transform-style: preserve-3d;transition: transform .55s cubic-bezier(.5,0,.4,1); }
|
||
.flip-banner.flipping .flip-banner-stage { transform: rotateX(-180deg); }
|
||
.flip-banner-face { position: absolute;inset: 0;display: flex;align-items: center;gap: 8px;backface-visibility: hidden;-webkit-backface-visibility: hidden;padding: 0 8px 0 4px;overflow: hidden; }
|
||
.flip-banner-face.back { transform: rotateX(180deg); }
|
||
.flip-banner-avatar { width: 28px;height: 28px;border-radius: 14px;display: flex;align-items: center;justify-content: center;font-size: 16px;flex-shrink: 0;box-shadow: 0 1px 3px rgba(0,0,0,.08); }
|
||
.flip-banner-text { flex: 1;font-size: 12px;font-weight: 500;color: var(--gray-700);white-space: nowrap;overflow: hidden;text-overflow: ellipsis; }
|
||
.flip-banner-text .flip-name { color: var(--gray-900);font-weight: 700;margin-right: 4px; }
|
||
.flip-banner-text em { font-style: normal;color: #FF5722;font-weight: 600;margin-left: 2px; }
|
||
.marquee-track { display: flex;white-space: nowrap;animation: marqueeScroll 20s linear infinite; }
|
||
.marquee-item { display: inline-flex;align-items: center;padding: 0 24px;font-size: 12px;font-weight: 600;color: var(--gray-700); }
|
||
/* 浮窗 */
|
||
.floating-btn { position: absolute; right: 16px; bottom: 80px; width: 56px; height: 56px; border-radius: 24px; background: var(--primary); color: #1a1a1a; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 600; box-shadow: 0 4px 12px rgba(255,87,34,.4); cursor: pointer; z-index: 100; animation: pulse 2s infinite; }
|
||
@keyframes pulse { 0%,100% { box-shadow: 0 4px 12px rgba(255,87,34,.4); } 50% { box-shadow: 0 4px 24px rgba(255,87,34,.6); } }
|
||
@keyframes spin { to { transform: rotate(360deg); } }
|
||
@keyframes cardHint { 0%,100% { box-shadow: 0 2px 8px rgba(255,87,34,.1); } 50% { box-shadow: 0 2px 16px rgba(255,87,34,.3); } }
|
||
@keyframes splashTickerScroll { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); } }
|
||
@keyframes splashFadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||
|
||
/* ===== Splash · 全图方案:splash-full-bg 含印章+tagline,HTML 仅放按钮 ===== */
|
||
.splash-illustration {
|
||
position: absolute;
|
||
top: 80px; left: 0; right: 0;
|
||
height: 575px;
|
||
background-image: url('assets/onboarding/index/full-bg.png');
|
||
background-size: 375px auto;
|
||
background-position: top center;
|
||
background-repeat: no-repeat;
|
||
background-color: transparent;
|
||
overflow: hidden;
|
||
z-index: 1;
|
||
}
|
||
.splash-illustration::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0; left: 0; right: 0;
|
||
height: 90px;
|
||
background: linear-gradient(to top, rgba(253,250,249,0) 0%, rgba(253,250,249,.55) 55%, rgba(253,250,249,1) 100%);
|
||
pointer-events: none;
|
||
z-index: 1;
|
||
}
|
||
/* 底部渐变:仅最末端消接缝,远离"下单前先比价"避免糊字 */
|
||
.splash-illustration::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: 0; left: 0; right: 0;
|
||
height: 14px;
|
||
background: linear-gradient(to bottom, rgba(253,250,249,0) 0%, rgba(253,250,249,1) 100%);
|
||
pointer-events: none;
|
||
}
|
||
.splash-start-btn {
|
||
position: absolute;
|
||
bottom: 60px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 220px;
|
||
height: 52px;
|
||
border-radius: 24px;
|
||
background: linear-gradient(180deg, #FFEB3B 0%, #FFD600 50%, #FFC400 100%);
|
||
color: #1A1A1A;
|
||
font-size: 17px;
|
||
font-weight: 700;
|
||
letter-spacing: 4px;
|
||
text-indent: 4px;
|
||
border: none;
|
||
cursor: pointer;
|
||
z-index: 10;
|
||
box-shadow: 0 8px 22px rgba(255,193,0,.45), inset 0 1px 0 rgba(255,255,255,.55), inset 0 -2px 0 rgba(180,110,0,.10);
|
||
transition: transform .12s ease, box-shadow .2s ease, opacity .15s ease;
|
||
}
|
||
.splash-start-btn:active {
|
||
transform: translateX(-50%) scale(0.97);
|
||
opacity: 0.92;
|
||
box-shadow: 0 4px 12px rgba(255,193,0,.35), inset 0 1px 0 rgba(255,255,255,.55);
|
||
}
|
||
@keyframes safetySlideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
|
||
@keyframes safetyPopIn { from { transform: scale(.92); opacity: 0; } to { transform: scale(1); opacity: 1; } }
|
||
@keyframes confettiDrop {
|
||
0% { transform: translateY(0) translateX(0) rotate(0deg) rotateY(0deg); opacity: 1; }
|
||
25% { translateX(var(--sway)); }
|
||
50% { transform: translateY(400px) translateX(calc(var(--sway) * -1)) rotate(360deg) rotateY(540deg); opacity: 1; }
|
||
75% { translateX(var(--sway)); }
|
||
100% { transform: translateY(850px) translateX(var(--sway)) rotate(720deg) rotateY(1080deg); opacity: 0; }
|
||
}
|
||
@keyframes confettiFloat {
|
||
0% { transform: translateY(0) translateX(0) rotate(0deg) rotateX(0deg) scale(1); opacity: 1; }
|
||
100% { transform: translateY(var(--dy)) translateX(var(--dx)) rotate(var(--spin)) rotateX(1080deg) scale(0.5); opacity: 0; }
|
||
}
|
||
/* 导航指示 */
|
||
.nav-hint { position: absolute; bottom: 8px; left: 50%; transform: translateX(-50%); font-size: 11px; color: var(--gray-400); background: rgba(255,255,255,.8); padding: 4px 12px; border-radius: 12px; z-index: 50; }
|
||
/* 方案切换控制面板 */
|
||
.variant-toggle { position: fixed; top: 16px; left: 16px; z-index: 9999; }
|
||
.variant-btn { width: 36px; height: 36px; border-radius: 18px; background: #333; color: #fff; border: none; font-size: 16px; cursor: pointer; box-shadow: 0 2px 8px rgba(0,0,0,.3); display: flex; align-items: center; justify-content: center; }
|
||
.variant-btn:hover { background: #666666; }
|
||
.variant-panel { display: none; position: absolute; top: 44px; left: 0; background: #fff; border-radius: 14px; box-shadow: 0 4px 24px rgba(0,0,0,.15); padding: 16px; min-width: 260px; max-height: 70vh; overflow-y: auto; }
|
||
.variant-panel.open { display: block; }
|
||
.variant-panel h3 { font-size: 14px; font-weight: 700; color: #333; margin-bottom: 12px; }
|
||
.variant-module { margin-bottom: 12px; }
|
||
.variant-module:last-child { margin-bottom: 0; }
|
||
.variant-module-label { font-size: 12px; font-weight: 600; color: #666; margin-bottom: 6px; }
|
||
.variant-options { display: flex; gap: 6px; flex-wrap: wrap; }
|
||
.variant-opt { padding: 4px 12px; border-radius: 32px; border: 1.5px solid #e5e5e5; font-size: 12px; font-weight: 600; cursor: pointer; background: #fff; color: #666; transition: all .15s; }
|
||
.variant-opt:hover { border-color: #999; }
|
||
.variant-opt.active { background: #FFD600; border-color: #FFD600; color: #1a1a1a; }
|
||
.variant-empty { font-size: 12px; color: #999; text-align: center; padding: 16px 0; }
|
||
/* 平台icon浮动动画 */
|
||
@keyframes float1 { 0%,100%{transform: translateY(0)} 50%{transform: translateY(-6px)} }
|
||
@keyframes float2 { 0%,100%{transform: translateY(0)} 50%{transform: translateY(-8px)} }
|
||
@keyframes float3 { 0%,100%{transform: translateY(0)} 50%{transform: translateY(-5px)} }
|
||
.fly-icon.fly1 { animation: float1 3s ease-in-out infinite; }
|
||
.fly-icon.fly2 { animation: float2 2.5s ease-in-out infinite .3s; }
|
||
.fly-icon.fly3 { animation: float3 3.2s ease-in-out infinite .6s; }
|
||
/* 下滑手势动画:底部开始→往上滑→底部消失 */
|
||
@keyframes swipeDown { 0%{transform: translateY(30px) rotate(-15deg);opacity: 0} 50%{transform: translateY(-30px) rotate(-15deg);opacity: 1} 100%{transform: translateY(30px) rotate(-15deg);opacity: 0} }
|
||
.swipe-hand { animation: swipeDown 2s ease-in-out infinite; }
|
||
/* 首个卡片呼吸光效 */
|
||
@keyframes breathGlow { 0%,100%{box-shadow: 0 2px 8px rgba(255,87,34,.06)} 50%{box-shadow: 0 2px 16px rgba(255,87,34,.18)} }
|
||
.platform-card-first { animation: breathGlow 2s ease-in-out infinite; border-color: #FFD600 !important; }
|
||
/* 点击手势提示 */
|
||
@keyframes tapHint { 0%,100%{transform: translate(0,0) scale(1)} 50%{transform: translate(-2px,2px) scale(.92)} }
|
||
.tap-hand { animation: tapHint 1.2s ease-in-out infinite; }
|
||
.gesture-hand-img { display: block; width: 100%; height: 100%; object-fit: contain; }
|
||
/* 加号二级高亮:贴近原按钮的双层呼吸圈 */
|
||
.demo-plus-focus {
|
||
display: none;
|
||
position: absolute;
|
||
z-index: 14;
|
||
width: 46px;
|
||
height: 46px;
|
||
border-radius: 50%;
|
||
transform: translate(-50%, -50%);
|
||
pointer-events: none;
|
||
}
|
||
.demo-plus-focus.circle { border-radius: 50%; }
|
||
.demo-plus-focus.pill { border-radius: 999px; }
|
||
.demo-plus-focus.rect { border-radius: 12px; }
|
||
.demo-plus-focus.confirm { border-radius: 4px 24px 24px 4px; }
|
||
.demo-plus-focus.clickable {
|
||
cursor: pointer;
|
||
pointer-events: auto;
|
||
}
|
||
.demo-plus-focus::before,
|
||
.demo-plus-focus::after {
|
||
content: "";
|
||
position: absolute;
|
||
inset: 5px;
|
||
border-radius: inherit;
|
||
border: 2px solid rgba(255,214,0,.62);
|
||
box-shadow: 0 0 8px rgba(255,214,0,.28);
|
||
transform-origin: 50% 50%;
|
||
animation: plusGuidePulse 1.45s ease-out infinite;
|
||
}
|
||
.demo-plus-focus::after {
|
||
inset: 3px;
|
||
border-color: rgba(255,255,255,.54);
|
||
animation-delay: .48s;
|
||
}
|
||
.demo-plus-core {
|
||
position: absolute;
|
||
left: 50%;
|
||
top: 50%;
|
||
width: calc(100% - 12px);
|
||
height: calc(100% - 12px);
|
||
transform: translate(-50%, -50%);
|
||
border-radius: inherit;
|
||
border: 2px solid #fff;
|
||
outline: 2px solid #FFD600;
|
||
box-shadow: 0 0 0 3px rgba(255,214,0,.10), 0 0 8px rgba(255,214,0,.30);
|
||
}
|
||
@keyframes plusGuidePulse {
|
||
0% { transform: scale(.76); opacity: .72; }
|
||
100% { transform: scale(1.38); opacity: 0; }
|
||
}
|
||
@keyframes plusGuideTap {
|
||
0%,100% { transform: translate(0,0) scale(1); }
|
||
50% { transform: translate(3px,-3px) scale(.93); }
|
||
}
|
||
#demoFinger.demo-plus-finger {
|
||
z-index: 14;
|
||
animation: plusGuideTap 1.18s ease-in-out infinite;
|
||
}
|
||
#demoFinger .gesture-hand-img {
|
||
filter: brightness(.94) saturate(.88);
|
||
}
|
||
#demoFinger.demo-plus-finger .gesture-hand-img {
|
||
transform: scaleX(-1) rotate(-14deg);
|
||
}
|
||
/* 平台选择卡片 hover 效果 */
|
||
.platform-card:hover { border-color: #FF5722 !important; box-shadow: 0 0 0 1px #FF5722, 0 4px 14px rgba(255,87,34,.12); }
|
||
.platform-card:active { transform: scale(.98); }
|
||
/* 开始比价按钮光晕 */
|
||
@keyframes btnGlow {
|
||
0%,100% { box-shadow: 0 0 12px 4px rgba(218,165,0,.45), 0 0 28px 8px rgba(218,165,0,.15); }
|
||
50% { box-shadow: 0 0 22px 10px rgba(218,165,0,.6), 0 0 45px 16px rgba(218,165,0,.25); }
|
||
}
|
||
@keyframes btnGlowRing {
|
||
0% { transform: translate(-50%,-50%) scale(.85); opacity: .7; }
|
||
100% { transform: translate(-50%,-50%) scale(1.5); opacity: 0; }
|
||
}
|
||
@keyframes fadeInUp {
|
||
0% { opacity: 0; transform: translateY(20px); }
|
||
100% { opacity: 1; transform: translateY(0); }
|
||
}
|
||
@keyframes welcomeRing {
|
||
0% { transform: scale(1); opacity: .6; }
|
||
100% { transform: scale(1.4); opacity: 0; }
|
||
}
|
||
/* ===== Agent toast 数字暴涨动效 ===== */
|
||
@keyframes couponNumPop {
|
||
0% { transform: scale(1); }
|
||
30% { transform: scale(1.32); }
|
||
65% { transform: scale(.92); }
|
||
100% { transform: scale(1); }
|
||
}
|
||
.coupon-num-pop { animation: couponNumPop .28s ease-out; }
|
||
@keyframes couponPlusFly {
|
||
0% { opacity: 0; transform: translate(-50%, 0) scale(.6); }
|
||
20% { opacity: 1; transform: translate(calc(-50% + var(--dx, 0px) * .25), calc(var(--dy, -8px) * .25)) scale(1.1); }
|
||
100% { opacity: 0; transform: translate(calc(-50% + var(--dx, 0px)), var(--dy, -34px)) scale(.7); }
|
||
}
|
||
.coupon-plus-particle {
|
||
position: absolute; left: 50%; top: 6px;
|
||
font-size: 13px; font-weight: 900; color: #FF3D00;
|
||
text-shadow: 0 1px 4px rgba(255,107,0,.4);
|
||
pointer-events: none;
|
||
z-index: 3;
|
||
animation: couponPlusFly .85s ease-out forwards;
|
||
}
|
||
@keyframes couponBarFlow {
|
||
0% { width: 8%; }
|
||
100% { width: 92%; }
|
||
}
|
||
@keyframes couponBarShine {
|
||
0% { transform: translateX(-100%); }
|
||
100% { transform: translateX(400%); }
|
||
}
|
||
@keyframes giftAwait {
|
||
0%, 100% {
|
||
transform: translateY(-50%) scale(1) rotate(-8deg);
|
||
filter: drop-shadow(0 2px 4px rgba(255,180,0,.55));
|
||
}
|
||
50% {
|
||
transform: translateY(-72%) scale(1.18) rotate(8deg);
|
||
filter: drop-shadow(0 4px 10px rgba(255,180,0,.95));
|
||
}
|
||
}
|
||
/* ===== 比价副文案红包动效(摇摆 + 光晕 + sparkle)===== */
|
||
@keyframes redpacketBob {
|
||
0%, 100% { transform: translateY(0) rotate(-3deg); }
|
||
50% { transform: translateY(-3px) rotate(3deg); }
|
||
}
|
||
@keyframes redpacketGlow {
|
||
0%, 100% { opacity: .35; transform: scale(.85); }
|
||
50% { opacity: 1; transform: scale(1.18); }
|
||
}
|
||
@keyframes redpacketSparkleA {
|
||
0%, 100% { opacity: 0; transform: scale(.4); }
|
||
30%, 65% { opacity: 1; transform: scale(1); }
|
||
}
|
||
@keyframes redpacketSparkleB {
|
||
0%, 100% { opacity: 0; transform: scale(.4); }
|
||
20%, 55% { opacity: 1; transform: scale(1); }
|
||
}
|
||
.redpacket-bob { animation: redpacketBob 2.4s ease-in-out infinite; }
|
||
/* ===== AI 接管橘黄色流动光晕 ===== */
|
||
@property --aiGlowAngle {
|
||
syntax: '<angle>';
|
||
initial-value: 0deg;
|
||
inherits: false;
|
||
}
|
||
@keyframes aiGlowRotate { to { --aiGlowAngle: 360deg; } }
|
||
@keyframes aiGlowPulse {
|
||
0% { opacity: .7; }
|
||
50% { opacity: 1; }
|
||
100% { opacity: .7; }
|
||
}
|
||
@keyframes aiGlowBreathe {
|
||
0% { transform: scale(1); opacity: .85; }
|
||
50% { transform: scale(1.015); opacity: 1; }
|
||
100% { transform: scale(1); opacity: .85; }
|
||
}
|
||
.ai-takeover-glow {
|
||
display: none;
|
||
position: absolute;
|
||
inset: 0;
|
||
pointer-events: none;
|
||
z-index: 14;
|
||
border-radius: 32px;
|
||
}
|
||
.ai-takeover-glow.active { display: block; }
|
||
/* 外层流动光带:粗一圈 + 大模糊,形成柔和橘黄光晕 */
|
||
.ai-takeover-glow::before {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
padding: 8px;
|
||
border-radius: 32px;
|
||
background: conic-gradient(
|
||
from var(--aiGlowAngle, 0deg),
|
||
#FFE082 0%,
|
||
#FFC107 12%,
|
||
#FF8F00 24%,
|
||
#FF6B00 36%,
|
||
#FFB300 50%,
|
||
#FFD54F 62%,
|
||
#FF9800 75%,
|
||
#FF6B00 87%,
|
||
#FFE082 100%
|
||
);
|
||
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
|
||
-webkit-mask-composite: xor;
|
||
mask-composite: exclude;
|
||
filter: blur(7px);
|
||
animation: aiGlowRotate 5s linear infinite, aiGlowBreathe 3.2s ease-in-out infinite;
|
||
}
|
||
/* 内层柔光:从边缘向内渗透的橘色辉光,强化"光晕"感 */
|
||
.ai-takeover-glow::after {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
border-radius: 32px;
|
||
box-shadow: inset 0 0 36px rgba(255, 152, 0, .55),
|
||
inset 0 0 80px rgba(255, 107, 0, .28),
|
||
inset 0 0 140px rgba(255, 87, 34, .12);
|
||
animation: aiGlowPulse 2.6s ease-in-out infinite;
|
||
}
|
||
/* ===== 新手礼包弹窗 ===== */
|
||
.gift-overlay { position: absolute; inset: 0; background: rgba(0,0,0,.6); display: none; align-items: center; justify-content: center; z-index: 200; backdrop-filter: blur(2px); }
|
||
.gift-overlay.show { display: flex; animation: fadeIn .25s ease-out; }
|
||
.gift-card { width: 304px; background: #fff; border-radius: 24px; padding: 24px 16px; position: relative; box-shadow: 0 24px 60px rgba(0,0,0,.4); animation: giftPop .4s cubic-bezier(.34,1.56,.64,1); overflow: hidden; }
|
||
.gift-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 120px; background: linear-gradient(180deg, #FFE066 0%, #FFD600 50%, transparent 100%); opacity: .6; pointer-events: none; }
|
||
.gift-close { position: absolute; top: 12px; right: 12px; width: 28px; height: 28px; border-radius: 14px; background: rgba(0,0,0,.08); display: flex; align-items: center; justify-content: center; font-size: 14px; color: #666; cursor: pointer; border: none; z-index: 2; }
|
||
.gift-confetti { font-size: 22px; text-align: center; letter-spacing: 4px; margin-bottom: 8px; position: relative; z-index: 1; }
|
||
.gift-title { font-size: 24px; font-weight: 600; color: #1a1a1a; text-align: center; margin-bottom: 4px; position: relative; z-index: 1; }
|
||
.gift-subtitle { font-size: 13px; color: var(--gray-700); text-align: center; margin-bottom: 16px; position: relative; z-index: 1; }
|
||
.gift-chest-wrap { position: relative; width: 160px; height: 160px; margin: 8px auto 16px; display: flex; align-items: center; justify-content: center; }
|
||
.gift-chest-glow { position: absolute; inset: 0; border-radius: 32px; background: radial-gradient(circle, rgba(255,214,0,.7) 0%, rgba(255,214,0,0) 65%); animation: chestGlow 2s ease-in-out infinite; }
|
||
.gift-chest-emoji { font-size: 48px; position: relative; z-index: 2; animation: chestBob 2s ease-in-out infinite; transition: transform .3s; }
|
||
.gift-card.opening .gift-chest-emoji { animation: chestShake .3s ease-out; }
|
||
/* 光线 burst */
|
||
.gift-burst { position: absolute; inset: 0; pointer-events: none; opacity: 0; }
|
||
.gift-card.opened .gift-burst { animation: burstFlash .6s ease-out; }
|
||
.gift-burst-ray { position: absolute; top: 50%; left: 50%; width: 6px; height: 80px; background: linear-gradient(180deg, rgba(255,214,0,1) 0%, rgba(255,214,0,0) 100%); transform-origin: 3px 0; }
|
||
.gift-burst-ray:nth-child(1) { transform: translate(-50%, 0) rotate(0deg); }
|
||
.gift-burst-ray:nth-child(2) { transform: translate(-50%, 0) rotate(60deg); }
|
||
.gift-burst-ray:nth-child(3) { transform: translate(-50%, 0) rotate(120deg); }
|
||
.gift-burst-ray:nth-child(4) { transform: translate(-50%, 0) rotate(180deg); }
|
||
.gift-burst-ray:nth-child(5) { transform: translate(-50%, 0) rotate(240deg); }
|
||
.gift-burst-ray:nth-child(6) { transform: translate(-50%, 0) rotate(300deg); }
|
||
.gift-amount { font-size: 48px; font-weight: 900; color: #FF5722; text-align: center; line-height: 1.1; display: none; }
|
||
.gift-amount-suffix { font-size: 18px; font-weight: 700; color: var(--gray-800); margin-left: 4px; }
|
||
.gift-amount-hint { font-size: 13px; color: var(--gray-700); text-align: center; margin: 6px 0 16px; display: none; }
|
||
.gift-card.opened .gift-stage-a { display: none; }
|
||
.gift-card.opened .gift-amount,
|
||
.gift-card.opened .gift-amount-hint { display: block; }
|
||
.gift-btn { width: 100%; height: 48px; border: none; border-radius: 24px; background: linear-gradient(180deg, #FFEB3B 0%, #FFD600 100%); color: #1a1a1a; font-size: 17px; font-weight: 700; cursor: pointer; box-shadow: 0 4px 16px rgba(255,214,0,.5); position: relative; z-index: 1; }
|
||
.gift-btn:active { opacity: .85; transform: translateY(1px); }
|
||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||
@keyframes giftPop { 0% { opacity: 0; transform: scale(.7) translateY(20px); } 100% { opacity: 1; transform: scale(1) translateY(0); } }
|
||
@keyframes chestBob { 0%,100% { transform: translateY(0) rotate(-2deg); } 50% { transform: translateY(-8px) rotate(2deg); } }
|
||
@keyframes chestGlow { 0%,100% { transform: scale(1); opacity: .6; } 50% { transform: scale(1.15); opacity: .9; } }
|
||
@keyframes chestShake { 0%,100% { transform: scale(1); } 25% { transform: scale(1.15) rotate(-8deg); } 75% { transform: scale(1.15) rotate(8deg); } }
|
||
@keyframes burstFlash { 0% { opacity: 0; transform: scale(.4); } 30% { opacity: 1; transform: scale(1.1); } 100% { opacity: 0; transform: scale(1.6); } }
|
||
/* 飞行金币 */
|
||
.fly-coin { position: absolute; left: 50%; top: 50%; font-size: 28px; line-height: 1; pointer-events: none; z-index: 250;
|
||
transform: translate(-50%, -50%);
|
||
animation: coinFly 1100ms cubic-bezier(.55,.05,.7,.4) forwards;
|
||
animation-delay: var(--d, 0ms);
|
||
--tx: 0px; --ty: 0px; --bx: 0px; --by: 0px;
|
||
filter: drop-shadow(0 2px 4px rgba(255,179,0,.6));
|
||
}
|
||
@keyframes coinFly {
|
||
0% { opacity: 0; transform: translate(-50%, -50%) scale(.4); }
|
||
15% { opacity: 1; transform: translate(calc(-50% + var(--bx)*.2), calc(-50% + var(--by)*.2)) scale(1.4); }
|
||
35% { opacity: 1; transform: translate(calc(-50% + var(--bx)), calc(-50% + var(--by))) scale(1.2); }
|
||
100% { opacity: 0; transform: translate(calc(-50% + var(--tx)), calc(-50% + var(--ty))) scale(.5); }
|
||
}
|
||
/* 福利 tab pulse + +5000 飘字 */
|
||
.tab-pulse { animation: tabPulse .6s ease-out; }
|
||
@keyframes tabPulse { 0% { transform: scale(1); } 40% { transform: scale(1.3); filter: drop-shadow(0 0 12px rgba(255,214,0,.9)); } 100% { transform: scale(1); } }
|
||
.tab-coin-badge { position: absolute; bottom: 50px; left: 50%; transform: translateX(-50%); background: linear-gradient(180deg,#FFEB3B,#FFD600); color: #1a1a1a; font-size: 13px; font-weight: 600; padding: 4px 8px; border-radius: 32px; box-shadow: 0 4px 12px rgba(255,179,0,.6); pointer-events: none; opacity: 0; z-index: 150; white-space: nowrap; }
|
||
.tab-coin-badge.show { animation: floatUp 1.2s ease-out forwards; }
|
||
@keyframes floatUp { 0% { opacity: 0; transform: translate(-50%, 0) scale(.7); } 20% { opacity: 1; transform: translate(-50%, -8px) scale(1.1); } 100% { opacity: 0; transform: translate(-50%, -32px) scale(1); } }
|
||
/* === 登录页 · E1 方案:PNG 背景 + 纯白渐变蒙版(分界 ~62%,红包区不糊) === */
|
||
/* 背景层:PNG 满屏 + 横向渐变兜底色(PNG 加载失败时不会露白) */
|
||
#login {
|
||
background: url("assets/login/index/redpacket-bg.png") center top / cover no-repeat,
|
||
linear-gradient(90deg, #FEE7B7 0%, #FDEFD0 50%, #FEE7B7 100%);
|
||
}
|
||
/* E1 渐变蒙版:28% 起、52.5% 之前完全透明(保红包+优惠券不糊),57% 处 .95,64% 处完全不透明 */
|
||
#login::before {
|
||
content: '';
|
||
position: absolute;
|
||
left: 0; right: 0; top: 28%; bottom: 0;
|
||
background: linear-gradient(180deg,
|
||
rgba(255, 255, 255, 0) 0%,
|
||
rgba(255, 255, 255, 0) 34%,
|
||
rgba(255, 255, 255, .55) 38%,
|
||
rgba(255, 255, 255, .95) 40.5%,
|
||
rgba(255, 255, 255, 1) 50%);
|
||
pointer-events: none;
|
||
z-index: 1;
|
||
}
|
||
/* 登录按钮去掉黄色光晕(全局 --cta-shadow 是黄底配黄阴影,登录页是白底要换中性阴影) */
|
||
#login .btn-cta {
|
||
box-shadow: 0 4px 14px rgba(0, 0, 0, .08), inset 0 1px 0 rgba(255, 255, 255, .55);
|
||
}
|
||
#login .btn-cta:active {
|
||
box-shadow: 0 2px 6px rgba(0, 0, 0, .06), inset 0 1px 0 rgba(255, 255, 255, .55);
|
||
}
|
||
/* 登录控件区:按钮位置沿用上一版,协议固定到底部 */
|
||
.lg-bottom { position: absolute; inset: 0; z-index: 5; }
|
||
.login-quick { position: absolute; inset: 0; display: block; }
|
||
.login-masked-phone { position: absolute; left: 0; right: 0; top: 64%; text-align: center; font-size: 28px; font-weight: 600; color: var(--gray-900); letter-spacing: .02em; line-height: 1; font-variant-numeric: tabular-nums; }
|
||
.login-main-btn { position: absolute; left: 7.5%; right: 7.5%; top: 71%; width: auto !important; height: 7.8%; min-height: 50px; font-size: 18px; }
|
||
.login-other-link { position: absolute; left: 0; right: 0; top: 81.5%; display: flex; align-items: center; justify-content: center; gap: 2px; border: 0; background: transparent; color: #999999; font-size: 13px; font-weight: 600; letter-spacing: .02em; cursor: pointer; font-family: inherit; }
|
||
.login-other-link .arrow { font-size: 15px; line-height: 1; color: inherit; transform: translateY(-.5px); }
|
||
.login-agreement { position: absolute; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 6; display: inline-flex; align-items: center; gap: 8px; border: 0; background: transparent; color: #999999; font-size: 12px; line-height: 1; white-space: nowrap; cursor: pointer; font-family: inherit; padding: 0; }
|
||
.login-agreement .check { width: 16px; height: 16px; margin-top: 2px; border-radius: 50%; border: 1.5px solid #CCCCCC; background: #fff; flex: 0 0 auto; position: relative; }
|
||
.login-agreement.checked .check { border-color: transparent; background: transparent url("data:image/svg+xml;utf8,<svg xmlns='http: //www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16' stroke='%23D85A1F' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><circle cx='8' cy='8' r='7'/><path d='M5 8.25 7 10 11 6'/></svg>") center/100% 100% no-repeat; background-origin: border-box; }
|
||
.login-agreement .link, .login-agreement-sheet-copy .link { color: #E65100; font-weight: 700; }
|
||
.login-phone-panel { position: absolute; left: 40px; right: 40px; top: 61%; z-index: 6; }
|
||
/* 祝贺页底部登录面板(方案 A:完整 banner + 白底简洁登录,celebration 屏内嵌一键登录) */
|
||
.celeb-login {
|
||
flex-shrink: 0; padding: 16px 24px 24px;
|
||
background: #fff; border-top: 1px solid var(--gray-200);
|
||
position: relative; z-index: 11; /* 高于 confettiCanvas(z-index: 10) */
|
||
display: flex; flex-direction: column; align-items: stretch;
|
||
}
|
||
.celeb-login-phone {
|
||
text-align: center; font-size: 24px; font-weight: 600;
|
||
color: var(--gray-900); letter-spacing: .02em; margin-bottom: 12px;
|
||
font-variant-numeric: tabular-nums; line-height: 1;
|
||
}
|
||
.celeb-login > .btn-cta { width: 100%; }
|
||
.celeb-login-other {
|
||
display: block; width: 100%; margin-top: 12px;
|
||
border: 0; background: transparent; cursor: pointer; font-family: inherit;
|
||
text-align: center; color: #999999; font-size: 13px; font-weight: 600; letter-spacing: .02em;
|
||
}
|
||
.celeb-login-other .arrow { font-size: 14px; vertical-align: -1px; color: inherit; }
|
||
.celeb-login-agreement {
|
||
position: static !important; transform: none !important;
|
||
margin: 12px auto 0; display: inline-flex; left: auto; right: auto; bottom: auto;
|
||
align-self: center;
|
||
}
|
||
/* 入口页协议 · 底部抽屉(一键登录场景) */
|
||
.login-agreement-sheet-layer { display: none; position: absolute; inset: 0; z-index: 30; align-items: flex-end; background: rgba(0,0,0,.48); }
|
||
.login-agreement-sheet { width: 100%; padding: 24px 24px 32px; border-radius: 24px 24px 0 0; background: #FFFDF5; color: #1A1A1A; text-align: center; box-shadow: 0 -12px 30px rgba(0,0,0,.16); animation: loginSheetIn .24s cubic-bezier(.22,1,.36,1); }
|
||
@keyframes loginSheetIn { from { transform: translateY(24px); opacity: .75; } to { transform: translateY(0); opacity: 1; } }
|
||
.login-agreement-sheet-title { font-size: 17px; font-weight: 600; letter-spacing: .01em; margin-bottom: 12px; }
|
||
.login-agreement-sheet-copy { font-size: 13px; line-height: 1.6; color: #666666; margin-bottom: 16px; }
|
||
.login-agreement-sheet-primary { width: 100%; height: 50px; border: 0; border-radius: 999px; background: linear-gradient(180deg, #FFE066 0%, #FFD600 55%, #FFC400 100%); color: #5A3A00; font-size: 16px; font-weight: 700; letter-spacing: .04em; box-shadow: 0 12px 24px rgba(255, 200, 0, .28), inset 0 1px 0 rgba(255, 255, 255, .65); cursor: pointer; font-family: inherit; }
|
||
.login-agreement-sheet-secondary { margin-top: 12px; border: 0; background: transparent; color: #999999; font-size: 13px; cursor: pointer; font-family: inherit; padding: 8px 16px; }
|
||
/* 独立手机号登录页 */
|
||
#loginPhone { background: #fff; }
|
||
.lp-topbar { position: absolute; top: 44px; left: 0; right: 0; height: 44px; display: flex; align-items: center; padding: 0 8px; z-index: 10; }
|
||
.lp-back { width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; font-size: 24px; color: var(--gray-900); background: none; border: none; cursor: pointer; font-family: inherit; }
|
||
.lp-title { position: absolute; left: 0; right: 0; top: 132px; text-align: center; font-size: 24px; font-weight: 600; color: var(--gray-900); letter-spacing: .04em; }
|
||
.lp-form { position: absolute; left: 32px; right: 32px; top: 220px; }
|
||
.lp-input-row { display: flex; align-items: center; height: 50px; border-bottom: 1px solid var(--gray-200); }
|
||
.lp-input-row.focused { border-bottom-color: var(--gray-900); }
|
||
.lp-cc { font-size: 17px; font-weight: 600; color: var(--gray-900); letter-spacing: .02em; display: inline-flex; align-items: center; gap: 4px; margin-right: 12px; flex-shrink: 0; }
|
||
.lp-cc .chev { font-size: 10px; color: var(--gray-700); margin-left: 2px; }
|
||
.lp-divider { width: 1px; height: 18px; background: var(--gray-200); margin-right: 16px; flex-shrink: 0; }
|
||
.lp-input { flex: 1; height: 100%; border: none; padding: 0; font-size: 17px; font-weight: 500; color: var(--gray-900); letter-spacing: .04em; font-variant-numeric: tabular-nums; outline: none; background: transparent; }
|
||
.lp-input::placeholder { color: var(--gray-400); font-weight: 400; }
|
||
.lp-cta { width: 100%; margin-top: 40px; margin-bottom: 16px; }
|
||
.lp-cta.disabled { background: linear-gradient(180deg, #FFE0B2 0%, #FFE066 100%); color: rgba(26,26,26,.45); box-shadow: none; pointer-events: none; }
|
||
.lp-agreement { display: flex; align-items: flex-start; gap: 8px; color: #999999; font-size: 12px; line-height: 1.55; padding-right: 8px; cursor: pointer; border: 0; background: transparent; text-align: left; font-family: inherit; width: 100%; }
|
||
.lp-agreement .check { width: 16px; height: 16px; border-radius: 50%; border: 1.5px solid #CCCCCC; background: #fff; flex: 0 0 auto; margin-top: 2px; position: relative; }
|
||
.lp-agreement.checked .check { border-color: transparent; background: transparent url("data:image/svg+xml;utf8,<svg xmlns='http: //www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16' stroke='%23D85A1F' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><circle cx='8' cy='8' r='7'/><path d='M5 8.25 7 10 11 6'/></svg>") center/100% 100% no-repeat; background-origin: border-box; }
|
||
.lp-agreement .link { color: #E65100; font-weight: 600; }
|
||
/* 验证码步骤(沿用原 step2 视觉,放在新页内) */
|
||
.lp-sms-hint { font-size: 13px; color: var(--gray-500); margin-bottom: 16px; }
|
||
.lp-sms-boxes { display: flex; gap: 8px; justify-content: center; margin-bottom: 16px; }
|
||
.lp-sms-boxes input { width: 40px; height: 48px; border-radius: 12px; border: 1.5px solid var(--gray-200); text-align: center; font-size: 20px; font-weight: 700; outline: none; }
|
||
.lp-sms-actions { display: flex; justify-content: center; gap: 16px; }
|
||
.lp-sms-actions span { font-size: 13px; cursor: pointer; }
|
||
/* 手机号页协议 · 居中弹窗 */
|
||
.lp-modal-layer { display: none; position: absolute; inset: 0; z-index: 30; align-items: center; justify-content: center; padding: 0 32px; background: rgba(0,0,0,.5); }
|
||
.lp-modal-card { width: 100%; padding: 24px 24px 16px; border-radius: 18px; background: #fff; color: #1A1A1A; text-align: center; box-shadow: 0 20px 60px rgba(0,0,0,.3); animation: lpModalIn .24s cubic-bezier(.22,1,.36,1); }
|
||
@keyframes lpModalIn { from { transform: scale(.94); opacity: 0; } to { transform: scale(1); opacity: 1; } }
|
||
.lp-modal-title { font-size: 17px; font-weight: 600; letter-spacing: .01em; margin-bottom: 12px; color: var(--gray-900); }
|
||
.lp-modal-copy { font-size: 13px; line-height: 1.7; color: var(--gray-700); margin-bottom: 24px; text-align: left; }
|
||
.lp-modal-copy .link { color: #E65100; font-weight: 600; }
|
||
.lp-modal-primary { width: 100%; height: 44px; border: 0; border-radius: 24px; background: linear-gradient(180deg, #FFE066 0%, #FFD600 100%); color: var(--gray-900); font-size: 15px; font-weight: 700; letter-spacing: .04em; box-shadow: 0 4px 14px rgba(0, 0, 0, .08), inset 0 1px 0 rgba(255, 255, 255, .55); cursor: pointer; font-family: inherit; }
|
||
.lp-modal-secondary { margin-top: 4px; height: 40px; border: 0; background: transparent; color: var(--gray-500); font-size: 13px; cursor: pointer; font-family: inherit; padding: 8px 16px; }
|
||
/* 新人礼包 · 优惠券样式 */
|
||
.gift-coupon { position: relative; background: linear-gradient(90deg,#FF6B6B 0%,#FF5722 100%); border-radius: 24px; padding: 16px 16px 16px 24px; display: flex; align-items: center; gap: 12px; box-shadow: 0 6px 18px rgba(255,87,34,.35); color: #fff; overflow: visible; }
|
||
.gift-coupon::before { content: ''; position: absolute; top: 50%; left: -6px; transform: translateY(-50%); width: 12px; height: 12px; background: #FFF8E1; border-radius: 50%; }
|
||
.gift-coupon::after { content: ''; position: absolute; left: 16px; top: 12px; bottom: 12px; width: 1px; background-image: linear-gradient(180deg, rgba(255,255,255,.5) 50%, transparent 50%); background-size: 1px 6px; }
|
||
.gift-coupon .gc-icon { flex-shrink: 0; font-size: 48px; line-height: 1; filter: drop-shadow(0 2px 6px rgba(0,0,0,.2)); }
|
||
.gift-coupon .gc-title { font-size: 18px; font-weight: 900; color: #fff; margin-bottom: 4px; }
|
||
.gift-coupon .gc-sub { font-size: 12px; color: rgba(255,255,255,.9); }
|
||
/* 新人礼包 · 7 方案样式(用于 ?giftvariant= 切换) */
|
||
.gv-base { position: relative; border-radius: 24px; display: flex; align-items: center; gap: 12px; }
|
||
.gv-a { background: linear-gradient(135deg,#FFF3E0,#FFE0B2); padding: 16px; box-shadow: 0 4px 16px rgba(255,179,0,.18); }
|
||
.gv-a .gv-icon { flex-shrink: 0; font-size: 48px; line-height: 1; }
|
||
.gv-a .gv-title { font-size: 18px; font-weight: 600; color: #1a1a1a; margin-bottom: 4px; }
|
||
.gv-a .gv-sub { font-size: 12px; color: var(--gray-700); }
|
||
.gv-b { background: linear-gradient(135deg,#FFF3E0,#FFE0B2); padding: 16px; box-shadow: 0 4px 16px rgba(255,179,0,.18); }
|
||
.gv-b .gv-icon { flex-shrink: 0; font-size: 48px; line-height: 1; }
|
||
.gv-b .gv-title { font-size: 18px; font-weight: 600; color: #1a1a1a; margin-bottom: 4px; }
|
||
.gv-b .gv-sub { font-size: 12px; color: var(--gray-700); }
|
||
.gv-b .gv-stamp { position: absolute; top: -10px; right: 14px; background: linear-gradient(135deg,#FF5722,#E65100); color: #fff; font-size: 11px; font-weight: 600; padding: 6px 12px; border-radius: 12px 12px 12px 4px; box-shadow: 0 4px 10px rgba(255,87,34,.4); transform: rotate(8deg); }
|
||
.gv-c { background: linear-gradient(135deg,#FFF3E0,#FFE0B2); padding: 16px; box-shadow: 0 4px 16px rgba(255,179,0,.18); }
|
||
.gv-c .gv-icon { flex-shrink: 0; font-size: 48px; line-height: 1; }
|
||
.gv-c .gv-title { font-size: 18px; font-weight: 600; color: #1a1a1a; margin-bottom: 6px; }
|
||
.gv-c .gv-cd { display: inline-flex; align-items: center; gap: 4px; background: #1a1a1a; color: #FFD600; font-size: 11px; font-weight: 600; padding: 4px 8px; border-radius: 8px; font-variant-numeric: tabular-nums; }
|
||
.gv-c .gv-blink { animation: gvBlink 1s infinite; }
|
||
@keyframes gvBlink { 50% { opacity: .3; } }
|
||
.gv-d { background: linear-gradient(135deg,#FFE0B2 0%,#FFE066 50%,#FFE066 100%); padding: 24px 16px; box-shadow: 0 8px 24px rgba(255,87,34,.25), inset 0 1px 0 rgba(255,255,255,.6); overflow: hidden; }
|
||
.gv-d .gv-iconwrap { position: relative; flex-shrink: 0; width: 70px; height: 70px; display: flex; align-items: center; justify-content: center; }
|
||
.gv-d .gv-icon { position: relative; font-size: 48px; line-height: 1; filter: drop-shadow(0 4px 8px rgba(255,87,34,.3)); }
|
||
.gv-d .gv-text { position: relative; z-index: 1; }
|
||
.gv-d .gv-title { font-size: 20px; font-weight: 900; color: #1a1a1a; margin-bottom: 4px; letter-spacing: -.3px; }
|
||
.gv-d .gv-sub { font-size: 13px; color: #5A3A00; font-weight: 600; }
|
||
.gv-f { background: radial-gradient(circle at 50% 20%, rgba(255,255,255,.8), transparent 50%), linear-gradient(135deg,#FFF3E0,#FFE0B2); padding: 24px 16px 24px; box-shadow: 0 8px 24px rgba(255,179,0,.25); flex-direction: column; text-align: center; overflow: hidden; }
|
||
.gv-f .gv-rays { position: absolute; top: -20px; left: 50%; transform: translateX(-50%); width: 200px; height: 200px; pointer-events: none; background: conic-gradient(from 0deg, rgba(255,213,79,.3) 0deg, transparent 30deg, rgba(255,213,79,.3) 60deg, transparent 90deg, rgba(255,213,79,.3) 120deg, transparent 150deg, rgba(255,213,79,.3) 180deg, transparent 210deg, rgba(255,213,79,.3) 240deg, transparent 270deg, rgba(255,213,79,.3) 300deg, transparent 330deg); border-radius: 50%; animation: gvSpin 12s linear infinite; opacity: .6; }
|
||
@keyframes gvSpin { to { transform: translateX(-50%) rotate(360deg); } }
|
||
.gv-f .gv-iconwrap { position: relative; z-index: 1; margin-bottom: 8px; }
|
||
.gv-f .gv-icon { font-size: 48px; line-height: 1; display: inline-block; animation: gvBob 2.5s infinite ease-in-out; filter: drop-shadow(0 6px 12px rgba(255,87,34,.3)); }
|
||
@keyframes gvBob { 50% { transform: translateY(-4px); } }
|
||
@keyframes gvPop { 0% { transform: scale(.4); opacity: 0; } 60% { transform: scale(1.08); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
|
||
.gv-f .gv-title { position: relative; z-index: 1; font-size: 22px; font-weight: 900; color: #1a1a1a; margin-bottom: 4px; letter-spacing: -.3px; }
|
||
.gv-f .gv-sub { position: relative; z-index: 1; font-size: 12px; color: #5A3A00; font-weight: 600; }
|
||
.gv-g { background: linear-gradient(135deg,#FFF3E0,#FFE0B2); padding: 16px; box-shadow: 0 4px 16px rgba(255,179,0,.18); overflow: hidden; }
|
||
.gv-g .gv-iconwrap { position: relative; flex-shrink: 0; width: 56px; height: 56px; display: flex; align-items: center; justify-content: center; }
|
||
.gv-g .gv-icon { font-size: 48px; line-height: 1; }
|
||
.gv-g .gv-spark { position: absolute; width: 6px; height: 6px; background: #FFD600; border-radius: 50%; box-shadow: 0 0 8px #FFD600; }
|
||
.gv-g .gv-s1 { top: 0; right: 4px; animation: gvSparkle 1.8s infinite; }
|
||
.gv-g .gv-s2 { bottom: 4px; left: 0; animation: gvSparkle 1.8s infinite .6s; }
|
||
.gv-g .gv-s3 { top: 50%; right: -4px; animation: gvSparkle 1.8s infinite 1.2s; }
|
||
@keyframes gvSparkle { 0%,100% { transform: scale(0); opacity: 0; } 50% { transform: scale(1); opacity: 1; } }
|
||
.gv-g .gv-title { font-size: 18px; font-weight: 900; color: #1a1a1a; margin-bottom: 4px; }
|
||
.gv-g .gv-title em { font-style: normal; background: linear-gradient(90deg, #FF5722, #FFB300); -webkit-background-clip: text; background-clip: text; color: transparent; margin-left: 4px; font-weight: 900; }
|
||
.gv-g .gv-sub { font-size: 12px; color: var(--gray-700); }
|
||
body.gv-embed .variant-toggle { display: none !important; }
|
||
|
||
/* ===== Coupon prompt 变体 · 平台选择卡通用样式 ===== */
|
||
.cp-card { transition: all .2s; cursor: pointer; }
|
||
.cp-card[data-checked="false"] { opacity: .5; }
|
||
.cp-card[data-checked="false"] .cp-check { background: var(--gray-300) !important; }
|
||
.cp-card[data-checked="false"] .cp-check svg { opacity: 0; }
|
||
/* 选中态边框色按主题分 */
|
||
.cp-card-pink[data-checked="false"] { border-color: var(--gray-200) !important; }
|
||
.cp-card-red[data-checked="false"] { border-color: var(--gray-200) !important; }
|
||
.cp-card-yellow[data-checked="false"] { border-color: var(--gray-200) !important; }
|
||
.cp-card-yellow[data-checked="false"] .cp-toggle { background: var(--gray-200) !important; }
|
||
.cp-card-yellow[data-checked="false"] .cp-toggle::after { transform: translateX(0) !important; }
|
||
|
||
/* ============================================
|
||
一键领券完成 · 迭代 6 配色 B(朱红卡包风)
|
||
============================================ */
|
||
.coupon-done-k-mask {
|
||
position: absolute; inset: 0;
|
||
background: rgba(0,0,0,.55);
|
||
z-index: 28;
|
||
animation: kFadeIn .3s ease-out;
|
||
}
|
||
@keyframes kFadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||
|
||
.coupon-done-k {
|
||
/* 配色 B · 朱红 */
|
||
--v6-bg-top: #FF1744;
|
||
--v6-bg-bottom: #C62828;
|
||
--v6-pocket-top: #FF5252;
|
||
--v6-pocket-bottom: #E53935;
|
||
--v6-notch: #C62828;
|
||
|
||
position: absolute; left: 50%; top: 50%;
|
||
transform: translate(-50%, -50%);
|
||
z-index: 30;
|
||
width: 296px;
|
||
background: linear-gradient(180deg, var(--v6-bg-top) 0%, var(--v6-bg-bottom) 65%, var(--v6-bg-bottom) 100%);
|
||
border-radius: 24px;
|
||
box-shadow: 0 20px 50px rgba(0,0,0,.4);
|
||
overflow: visible;
|
||
animation: kPopIn .5s cubic-bezier(.34,1.56,.64,1);
|
||
}
|
||
@keyframes kPopIn {
|
||
0% { opacity: 0; transform: translate(-50%, -50%) scale(.85); }
|
||
100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
|
||
}
|
||
|
||
/* 顶部居中品牌 logo(与 splash / 浮窗一致:黄色圆角方块 + 机器人 SVG + 文字) */
|
||
.coupon-done-k .coupon-done-logo {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 8px;
|
||
padding: 16px 0 2px;
|
||
position: relative;
|
||
z-index: 3;
|
||
}
|
||
.coupon-done-k .coupon-done-logo .logo-mark {
|
||
width: 32px; height: 32px;
|
||
border-radius: 8px;
|
||
background: linear-gradient(135deg, #FFD600, #FFB300);
|
||
display: flex; align-items: center; justify-content: center;
|
||
flex-shrink: 0;
|
||
box-shadow: 0 4px 10px rgba(0,0,0,.22);
|
||
}
|
||
.coupon-done-k .coupon-done-logo .logo-text {
|
||
font-size: 15px; font-weight: 900;
|
||
color: #fff;
|
||
letter-spacing: 0.8px;
|
||
text-shadow: 0 1px 2px rgba(0,0,0,.22);
|
||
}
|
||
|
||
/* sparkle 黄色星光 */
|
||
.coupon-done-k .v6-sparkle {
|
||
position: absolute;
|
||
width: 7px; height: 7px;
|
||
background: #FFE066; border-radius: 50%;
|
||
box-shadow: 0 0 8px #FFE082;
|
||
animation: kSparkleTwinkle 1.5s infinite ease-in-out;
|
||
z-index: 2;
|
||
}
|
||
.coupon-done-k .v6-sparkle.s1 { top: 14px; left: 22px; }
|
||
.coupon-done-k .v6-sparkle.s2 { top: 22px; right: 28px; animation-delay: .3s; }
|
||
.coupon-done-k .v6-sparkle.s3 { top: 60px; left: 28px; animation-delay: .6s; width: 5px; height: 5px; }
|
||
.coupon-done-k .v6-sparkle.s4 { top: 50px; right: 32px; animation-delay: .9s; width: 5px; height: 5px; }
|
||
.coupon-done-k .v6-sparkle.s5 { top: 38px; left: 50%; animation-delay: 1.1s; width: 4px; height: 4px; }
|
||
@keyframes kSparkleTwinkle {
|
||
0%, 100% { opacity: .3; transform: scale(.6); }
|
||
50% { opacity: 1; transform: scale(1.2); }
|
||
}
|
||
|
||
/* 头部双行渐变文案(票卡删除后改为页面中心展示) */
|
||
.coupon-done-k .v6-head {
|
||
text-align: center;
|
||
padding: 24px 16px 24px;
|
||
color: #fff; position: relative; z-index: 1;
|
||
}
|
||
.coupon-done-k .v6-head .lead-line {
|
||
font-size: 20px; font-weight: 600;
|
||
margin-bottom: 12px;
|
||
background: linear-gradient(180deg, #fff 30%, #FFE0B2 100%);
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
letter-spacing: 1px;
|
||
}
|
||
.coupon-done-k .v6-head .num-line {
|
||
font-size: 28px; font-weight: 900;
|
||
line-height: 1.1;
|
||
text-shadow: 0 2px 10px rgba(0,0,0,.28);
|
||
letter-spacing: 0.5px;
|
||
}
|
||
.coupon-done-k .v6-head .num-line .num {
|
||
color: #FFE066;
|
||
font-family: -apple-system, "DIN Alternate", sans-serif;
|
||
font-size: 36px;
|
||
margin-right: 2px;
|
||
}
|
||
.coupon-done-k .v6-head .num-line .rest {
|
||
background: linear-gradient(180deg, #fff 30%, #FFE066 100%);
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
}
|
||
/* 平台来源:"来自 + 两个 logo",不写平台名 */
|
||
.coupon-done-k .v6-from {
|
||
display: flex; align-items: center; justify-content: center;
|
||
gap: 8px;
|
||
padding: 6px 16px 12px;
|
||
position: relative; z-index: 1;
|
||
}
|
||
.coupon-done-k .v6-from .label {
|
||
font-size: 12px; font-weight: 600;
|
||
color: rgba(255,255,255,.85);
|
||
letter-spacing: 0.04em;
|
||
}
|
||
.coupon-done-k .v6-from .lgs { display: flex; align-items: center; gap: 6px; }
|
||
.coupon-done-k .v6-from .lg {
|
||
width: 28px; height: 28px;
|
||
border-radius: 8px; overflow: hidden;
|
||
border: 2px solid #fff;
|
||
box-shadow: 0 2px 6px rgba(0,0,0,.25);
|
||
background: #fff;
|
||
}
|
||
.coupon-done-k .v6-from .lg img { width: 100%; height: 100%; object-fit: cover; }
|
||
|
||
/* v3:标题内联式 — 把"领取自 + 平台 logo"嵌入第一行文案,密度最高 */
|
||
.coupon-done-k .v6-head .lead-line-inline {
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
flex-wrap: wrap; gap: 4px;
|
||
/* 取消渐变文字,避免与内联图片混搭显得别扭 */
|
||
background: none;
|
||
-webkit-text-fill-color: #fff;
|
||
color: #fff;
|
||
font-size: 16px; font-weight: 700;
|
||
letter-spacing: .3px;
|
||
}
|
||
.coupon-done-k .v6-head .lead-line-inline .lg-inline {
|
||
display: inline-block;
|
||
width: 28px; height: 28px;
|
||
border-radius: 8px; overflow: hidden;
|
||
box-shadow: 0 1px 4px rgba(0,0,0,.25);
|
||
vertical-align: middle;
|
||
}
|
||
.coupon-done-k .v6-head .lead-line-inline .lg-inline img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||
|
||
/* v2:领取自上提(顶部胶囊;与领取数量绑定为同一信息块) */
|
||
.coupon-done-k .v6-from-top {
|
||
display: inline-flex; align-items: center; gap: 6px;
|
||
margin: 0 auto 12px;
|
||
padding: 4px 12px 4px 8px;
|
||
background: rgba(255,255,255,.16);
|
||
border: 1px solid rgba(255,255,255,.22);
|
||
border-radius: 999px;
|
||
backdrop-filter: blur(6px);
|
||
-webkit-backdrop-filter: blur(6px);
|
||
}
|
||
.coupon-done-k .v6-from-top .label {
|
||
font-size: 11px; font-weight: 700;
|
||
color: rgba(255,255,255,.92);
|
||
letter-spacing: 0.04em;
|
||
}
|
||
.coupon-done-k .v6-from-top .lgs { gap: 4px; }
|
||
.coupon-done-k .v6-from-top .lg {
|
||
width: 18px; height: 18px;
|
||
border-width: 1.5px;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,.2);
|
||
}
|
||
/* 整体 head 容器在使用 v6-from-top 时改 flex column 居中(让胶囊上居中) */
|
||
.coupon-done-k .v6-head:has(> .v6-from-top) {
|
||
display: flex; flex-direction: column; align-items: center;
|
||
padding-top: 12px;
|
||
}
|
||
.coupon-done-k .v6-head:has(> .v6-from-top) .lead-line {
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
/* 白色票卡 */
|
||
.coupon-done-k .v6-tickets {
|
||
display: flex; gap: 12px;
|
||
padding: 6px 16px 16px;
|
||
position: relative; z-index: 1;
|
||
}
|
||
.coupon-done-k .v6-tickets .pl {
|
||
flex: 1;
|
||
background: #fff;
|
||
border-radius: 8px;
|
||
padding: 12px 6px;
|
||
text-align: center;
|
||
position: relative;
|
||
box-shadow: 0 4px 12px rgba(0,0,0,.15);
|
||
}
|
||
/* 票卡左右切角 */
|
||
.coupon-done-k .v6-tickets .pl::before,
|
||
.coupon-done-k .v6-tickets .pl::after {
|
||
content: '';
|
||
position: absolute;
|
||
width: 12px; height: 12px;
|
||
background: var(--v6-bg-top);
|
||
border-radius: 50%;
|
||
top: 50%; transform: translateY(-50%);
|
||
}
|
||
.coupon-done-k .v6-tickets .pl::before { left: -6px; clip-path: inset(0 0 0 50%); }
|
||
.coupon-done-k .v6-tickets .pl::after { right: -6px; clip-path: inset(0 50% 0 0); }
|
||
.coupon-done-k .v6-tickets .pl .num {
|
||
font-size: 24px; font-weight: 900; color: #E02E24;
|
||
font-family: -apple-system, "DIN Alternate", sans-serif;
|
||
line-height: 1; letter-spacing: -0.5px;
|
||
}
|
||
.coupon-done-k .v6-tickets .pl .num small {
|
||
font-size: 11px; color: #E02E24; font-weight: 700; margin-left: 2px;
|
||
}
|
||
.coupon-done-k .v6-tickets .pl .dash {
|
||
margin: 8px 4px;
|
||
border-top: 1px dashed #FFCDD2;
|
||
}
|
||
.coupon-done-k .v6-tickets .pl .lg {
|
||
width: 32px; height: 32px;
|
||
border-radius: 8px; overflow: hidden;
|
||
background: #FFF8E1; margin: 0 auto;
|
||
box-shadow: 0 2px 5px rgba(0,0,0,.06);
|
||
}
|
||
.coupon-done-k .v6-tickets .pl .lg img { width: 100%; height: 100%; object-fit: cover; }
|
||
|
||
/* pocket 上层(浅)+ U 形凹口 */
|
||
.coupon-done-k .v6-pocket {
|
||
background: linear-gradient(180deg, var(--v6-pocket-top) 0%, var(--v6-pocket-bottom) 100%);
|
||
padding: 24px 16px 12px;
|
||
position: relative;
|
||
z-index: 1;
|
||
border-radius: 24px;
|
||
box-shadow: 0 -6px 14px rgba(0,0,0,.18);
|
||
}
|
||
.coupon-done-k .v6-pocket-notch {
|
||
position: absolute;
|
||
top: 0; left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 44px; height: 16px;
|
||
background: var(--v6-notch);
|
||
border-radius: 0 0 32px 32px;
|
||
z-index: 2;
|
||
}
|
||
.coupon-done-k .v6-expiry {
|
||
text-align: center;
|
||
color: #fff;
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
margin-bottom: 12px;
|
||
margin-top: 4px;
|
||
letter-spacing: 0.3px;
|
||
position: relative; z-index: 2;
|
||
}
|
||
.coupon-done-k .v6-expiry .time-box {
|
||
display: inline-block;
|
||
background: #fff;
|
||
color: #E02E24;
|
||
padding: 2px 4px;
|
||
border-radius: 4px;
|
||
font-weight: 600;
|
||
font-size: 13px;
|
||
font-family: -apple-system, "DIN Alternate", sans-serif;
|
||
margin: 0 2px;
|
||
letter-spacing: -0.5px;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,.15);
|
||
}
|
||
.coupon-done-k .v6-cta {
|
||
width: 100%;
|
||
background: linear-gradient(135deg, #FFEB3B 0%, #FFD600 50%, #FFC400 100%);
|
||
color: #1a1a1a;
|
||
border: none;
|
||
padding: 12px;
|
||
border-radius: 24px;
|
||
font-size: 15px;
|
||
font-weight: 900;
|
||
cursor: pointer;
|
||
box-shadow: inset 0 -2px 0 rgba(184,134,11,.18);
|
||
position: relative; z-index: 2;
|
||
letter-spacing: 1px;
|
||
}
|
||
|
||
.ad-reward-toast {
|
||
position: absolute;
|
||
left: 50%;
|
||
top: 46%;
|
||
z-index: 240;
|
||
width: 158px;
|
||
min-height: 140px;
|
||
padding: 20px 14px 18px;
|
||
border-radius: 18px;
|
||
background: linear-gradient(165deg, rgba(40,28,4,.94), rgba(0,0,0,.86));
|
||
color: #fff;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
pointer-events: none;
|
||
opacity: 0;
|
||
transform: translate(-50%, -50%) scale(.7);
|
||
overflow: visible;
|
||
backdrop-filter: blur(8px);
|
||
-webkit-backdrop-filter: blur(8px);
|
||
box-shadow: 0 14px 34px rgba(120,80,0,.32), inset 0 1px 0 rgba(255,230,120,.18);
|
||
}
|
||
.ad-reward-toast.visible {
|
||
opacity: 1;
|
||
animation: adRewardPop .32s cubic-bezier(.18,.9,.25,1.15) both;
|
||
}
|
||
@keyframes adRewardPop {
|
||
0% { opacity: 0; transform: translate(-50%, -50%) scale(.7); }
|
||
60% { opacity: 1; transform: translate(-50%, -50%) scale(1.08); }
|
||
100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
|
||
}
|
||
.ad-reward-toast img {
|
||
width: 60px;
|
||
height: 60px;
|
||
object-fit: contain;
|
||
margin-bottom: 6px;
|
||
filter: drop-shadow(0 4px 8px rgba(255,179,0,.4));
|
||
}
|
||
.ad-reward-toast-amount {
|
||
color: var(--primary);
|
||
font-family: "DIN Alternate", "Helvetica Neue", sans-serif;
|
||
font-size: 30px;
|
||
font-weight: 800;
|
||
line-height: 1;
|
||
letter-spacing: 0;
|
||
text-shadow: 0 1px 3px rgba(0,0,0,.4);
|
||
}
|
||
.ad-reward-toast.visible .ad-reward-toast-amount {
|
||
animation: adRewardNumBounce .5s .08s cubic-bezier(.18,.9,.25,1.4) both;
|
||
}
|
||
@keyframes adRewardNumBounce {
|
||
0% { transform: scale(.4); }
|
||
55% { transform: scale(1.25); }
|
||
100% { transform: scale(1); }
|
||
}
|
||
.ad-reward-toast-text {
|
||
margin-top: 8px;
|
||
color: #fff;
|
||
font-size: 14px;
|
||
font-weight: 700;
|
||
line-height: 1.2;
|
||
letter-spacing: 0;
|
||
white-space: nowrap;
|
||
}
|
||
.ad-reward-toast .spark {
|
||
position: absolute;
|
||
top: 38%;
|
||
left: 50%;
|
||
width: 8px;
|
||
height: 8px;
|
||
border-radius: 50%;
|
||
background: radial-gradient(circle at 35% 30%, #FFE680, #FFB300);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
}
|
||
.ad-reward-toast.visible .spark {
|
||
animation: adSparkBurst .6s ease-out forwards;
|
||
}
|
||
.ad-reward-toast .spark.s1 { --dx: -46px; --dy: -40px; animation-delay: .05s; }
|
||
.ad-reward-toast .spark.s2 { --dx: 48px; --dy: -34px; animation-delay: .08s; }
|
||
.ad-reward-toast .spark.s3 { --dx: -52px; --dy: 18px; animation-delay: .04s; }
|
||
.ad-reward-toast .spark.s4 { --dx: 50px; --dy: 24px; animation-delay: .1s; }
|
||
.ad-reward-toast .spark.s5 { --dx: 0px; --dy: -56px; animation-delay: .12s; width: 6px; height: 6px; }
|
||
.ad-reward-toast .spark.s6 { --dx: -30px; --dy: 46px; animation-delay: .07s; width: 6px; height: 6px; }
|
||
@keyframes adSparkBurst {
|
||
0% { opacity: 0; transform: translate(-50%, -50%) scale(.3); }
|
||
25% { opacity: 1; }
|
||
100% { opacity: 0; transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(1); }
|
||
}
|
||
|
||
/* ===== 比价结果页:全网最低价徽章(图片) + N2 chip ===== */
|
||
.card.with-ribbon { overflow: visible; }
|
||
.ribbon-vi {
|
||
position: absolute;
|
||
top: -16px; right: -6px;
|
||
width: 104px;
|
||
height: auto;
|
||
z-index: 3;
|
||
pointer-events: none;
|
||
filter: drop-shadow(0 4px 10px rgba(220,40,40,0.25));
|
||
}
|
||
|
||
/* 价格旁红 chip "比原选择省 ¥X" — 强调"省了多少",刻意放大 */
|
||
.save-chip-red {
|
||
background: linear-gradient(135deg, #FE2C55, #FF6B3D);
|
||
color: #fff;
|
||
border-radius: 8px;
|
||
padding: 4px 12px;
|
||
font-size: 15px;
|
||
font-weight: 600;
|
||
letter-spacing: 0.2px;
|
||
align-self: center;
|
||
display: inline-flex; align-items: baseline; gap: 2px;
|
||
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
|
||
white-space: nowrap;
|
||
-webkit-font-smoothing: antialiased;
|
||
-moz-osx-font-smoothing: grayscale;
|
||
}
|
||
.save-chip-red .small { font-size: 12px; opacity: 1; font-weight: 700; }
|
||
|
||
.result-cta {
|
||
flex-shrink: 0;
|
||
min-height: 34px;
|
||
padding: 6px 16px;
|
||
border: none;
|
||
border-radius: 999px;
|
||
font-size: 13px;
|
||
font-weight: 700;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
background: var(--gray-100);
|
||
color: var(--gray-800);
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 2px;
|
||
white-space: nowrap;
|
||
}
|
||
.result-cta .arrow {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--gray-500);
|
||
font-size: 15px;
|
||
line-height: 1;
|
||
transform: translateY(-.5px);
|
||
}
|
||
|
||
/* 用户原选 chip:店名旁描边方角 */
|
||
.badge-userorig {
|
||
flex-shrink: 0;
|
||
display: inline-flex; align-items: center;
|
||
background: transparent;
|
||
border: 1px solid #CCCCCC;
|
||
border-radius: 4px;
|
||
padding: 2px 8px;
|
||
font-size: 11px; font-weight: 600;
|
||
color: #666666; letter-spacing: .3px;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* ===== Kickoff 引导卡(首次进店)— L·I 升级版:黄 header + 米黄 body ===== */
|
||
.kickoff-card {
|
||
position: relative;
|
||
border-radius: 14px;
|
||
box-shadow: 0 14px 30px rgba(0,0,0,.32), 0 4px 14px rgba(255,179,0,.22);
|
||
}
|
||
/* 气泡上方的 journey 排版字(无卡片背景,闲鱼式:白字 + 关键词黄字 + 弧线下划) */
|
||
.kickoff-promo {
|
||
position: absolute;
|
||
bottom: 100%;
|
||
left: 0; right: 0;
|
||
margin-bottom: 24px;
|
||
text-align: center;
|
||
pointer-events: none;
|
||
}
|
||
.kickoff-promo .promo-line {
|
||
font-size: 22px;
|
||
font-weight: 900;
|
||
color: #fff;
|
||
line-height: 1.35;
|
||
letter-spacing: .5px;
|
||
-webkit-text-stroke: 0.4px currentColor; /* 在 900 之上再加描边,视觉更粗 */
|
||
text-stroke: 0.4px currentColor;
|
||
text-shadow: 0 2px 12px rgba(0,0,0,.7), 0 1px 3px rgba(0,0,0,.55), 0 0 2px rgba(0,0,0,.35);
|
||
}
|
||
.kickoff-promo .promo-accent {
|
||
position: relative;
|
||
display: inline-block;
|
||
padding: 0 2px;
|
||
color: #FFEB3B;
|
||
}
|
||
/* SVG 手绘风弧线下划,仿闲鱼那种"标注"感(按字号同比例放大) */
|
||
.kickoff-promo .promo-accent::after {
|
||
content: '';
|
||
position: absolute;
|
||
left: -2px; right: -2px;
|
||
bottom: -7px;
|
||
height: 9px;
|
||
background: url("data:image/svg+xml;utf8,<svg xmlns='http: //www.w3.org/2000/svg' viewBox='0 0 100 9' preserveAspectRatio='none'><path d='M2 5 Q 25 1 50 4.5 T 98 4.5' stroke='%23FFE34D' stroke-width='2.8' fill='none' stroke-linecap='round'/></svg>") no-repeat center / 100% 100%;
|
||
}
|
||
.kickoff-head {
|
||
background: linear-gradient(135deg, #FFEB3B 0%, #FFD600 100%);
|
||
padding: 8px 12px 8px;
|
||
display: flex; align-items: center; gap: 8px;
|
||
border-radius: 14px 14px 0 0;
|
||
}
|
||
.kickoff-dot {
|
||
width: 6px; height: 6px; border-radius: 50%;
|
||
background: #1a1a1a;
|
||
flex-shrink: 0;
|
||
}
|
||
.kickoff-title {
|
||
font-size: 14px; font-weight: 900; color: #1a1a1a;
|
||
letter-spacing: .5px; line-height: 1.2;
|
||
}
|
||
.kickoff-body {
|
||
background: #FFF8E1;
|
||
padding: 12px 12px 12px;
|
||
font-size: 13px; font-weight: 700; color: #1a1a1a;
|
||
line-height: 1.5;
|
||
border-radius: 0 0 14px 14px;
|
||
}
|
||
.kickoff-leader {
|
||
position: absolute;
|
||
bottom: -36px; left: 50%; margin-left: -1px;
|
||
width: 2px; height: 36px;
|
||
background: linear-gradient(180deg, rgba(255,214,0,0) 0%, #FFD600 30%, #FFD600 100%);
|
||
border-radius: 4px;
|
||
pointer-events: none;
|
||
}
|
||
.kickoff-leader::before {
|
||
content: '';
|
||
position: absolute; bottom: -4px; left: -4px;
|
||
width: 10px; height: 10px; border-radius: 50%;
|
||
background: #fff;
|
||
border: 2px solid #1a1a1a;
|
||
box-sizing: border-box;
|
||
box-shadow: 0 0 0 3px rgba(255,214,0,.55), 0 1px 3px rgba(0,0,0,.25);
|
||
animation: kickoffLeaderDot 1.6s ease-in-out infinite;
|
||
}
|
||
@keyframes kickoffLeaderDot {
|
||
0%, 100% { box-shadow: 0 0 0 3px rgba(255,214,0,.55), 0 1px 3px rgba(0,0,0,.25); }
|
||
50% { box-shadow: 0 0 0 6px rgba(255,214,0,.2), 0 1px 3px rgba(0,0,0,.25); }
|
||
}
|
||
/* 比价流程内引导气泡的黄色连接线(动态长度+方向,dot 落点贴住 spotlight 边缘) */
|
||
#demoGuide .demo-guide-leader {
|
||
position: absolute;
|
||
left: 50%; margin-left: -1px;
|
||
width: 2px;
|
||
border-radius: 4px;
|
||
pointer-events: none;
|
||
}
|
||
#demoGuide .demo-guide-leader.dir-down {
|
||
top: 100%;
|
||
background: linear-gradient(180deg, rgba(255,214,0,0) 0%, #FFD600 30%, #FFD600 100%);
|
||
}
|
||
#demoGuide .demo-guide-leader.dir-down::before {
|
||
content: '';
|
||
position: absolute; bottom: -4px; left: -4px;
|
||
width: 10px; height: 10px; border-radius: 50%;
|
||
background: #fff;
|
||
border: 2px solid #1a1a1a;
|
||
box-sizing: border-box;
|
||
box-shadow: 0 0 0 3px rgba(255,214,0,.55), 0 1px 3px rgba(0,0,0,.25);
|
||
animation: kickoffLeaderDot 1.6s ease-in-out infinite;
|
||
}
|
||
#demoGuide .demo-guide-leader.dir-up {
|
||
bottom: 100%;
|
||
background: linear-gradient(0deg, rgba(255,214,0,0) 0%, #FFD600 30%, #FFD600 100%);
|
||
}
|
||
#demoGuide .demo-guide-leader.dir-up::before {
|
||
content: '';
|
||
position: absolute; top: -4px; left: -4px;
|
||
width: 10px; height: 10px; border-radius: 50%;
|
||
background: #fff;
|
||
border: 2px solid #1a1a1a;
|
||
box-sizing: border-box;
|
||
box-shadow: 0 0 0 3px rgba(255,214,0,.55), 0 1px 3px rgba(0,0,0,.25);
|
||
animation: kickoffLeaderDot 1.6s ease-in-out infinite;
|
||
}
|
||
/* 一键比价入口 · 右下角 kickoff 卡(leader 偏右对齐侧贴按钮中心)*/
|
||
.start-compare-kickoff {
|
||
position: absolute;
|
||
right: 14px;
|
||
width: 310px;
|
||
bottom: 246px;
|
||
z-index: 16;
|
||
pointer-events: none;
|
||
}
|
||
.start-compare-kickoff .kickoff-leader {
|
||
left: auto;
|
||
right: 50px;
|
||
margin-left: 0;
|
||
}
|
||
/* 比价中浮窗 · 三平台并行 mini icons */
|
||
.cmp-platform-mini { position: relative; width: 24px; height: 24px; }
|
||
.cmp-platform-mini > img { width: 100%; height: 100%; border-radius: 4px; object-fit: cover; display: block; }
|
||
.cmp-platform-mini.done::after {
|
||
content: ''; position: absolute; bottom: -3px; right: -3px;
|
||
width: 12px; height: 12px; border-radius: 50%; background: #22C55E;
|
||
border: 1.5px solid #fff;
|
||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M2 5l2 2 4-5' stroke='%23fff' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
||
background-size: 8px; background-repeat: no-repeat; background-position: center;
|
||
}
|
||
.cmp-platform-mini.active::after {
|
||
content: ''; position: absolute; inset: -4px;
|
||
border: 2px solid #FFD600; border-top-color: transparent;
|
||
border-radius: 50%; animation: spin 0.8s linear infinite;
|
||
}
|
||
.cmp-platform-mini.pending { opacity: 0.4; filter: grayscale(0.6); }
|
||
/* ============ 2. VIDEO 教程页 (vt-) ============ */
|
||
#video .vt-video-player {
|
||
flex-shrink: 0; height: 667px; background: #000;
|
||
position: relative; overflow: hidden;
|
||
}
|
||
#video .vt-poster {
|
||
position: absolute; inset: 0;
|
||
background: radial-gradient(ellipse at 25% 15%, rgba(255,255,255,.45) 0%, transparent 55%),
|
||
radial-gradient(ellipse at 80% 90%, rgba(255,87,34,.18) 0%, transparent 60%),
|
||
linear-gradient(160deg, #FFE57F 0%, #FFD54F 35%, #FFB300 75%, #F57F17 100%);
|
||
display: flex; align-items: center; justify-content: center;
|
||
cursor: pointer; overflow: hidden;
|
||
}
|
||
#video .vt-poster::before {
|
||
content: ''; position: absolute; inset: 0;
|
||
background: radial-gradient(circle at 18% 88%, rgba(255,255,255,.15) 0%, transparent 8%),
|
||
radial-gradient(circle at 88% 22%, rgba(255,255,255,.18) 0%, transparent 6%);
|
||
pointer-events: none;
|
||
}
|
||
#video .vt-video-player.paused .vt-poster::after,
|
||
#video .vt-video-player.initial .vt-poster::after {
|
||
content: ''; position: absolute; inset: 0;
|
||
background: rgba(0,0,0,.18); z-index: 2; pointer-events: none;
|
||
}
|
||
/* 商品对比卡 */
|
||
#video .vt-poster-compare {
|
||
display: flex; align-items: center; gap: 8px;
|
||
background: rgba(255,255,255,.95); border-radius: 18px;
|
||
padding: 12px 16px;
|
||
box-shadow: 0 14px 36px rgba(140,70,0,.22), 0 2px 6px rgba(0,0,0,.08);
|
||
z-index: 2; position: relative;
|
||
}
|
||
#video .vt-pc-card {
|
||
display: flex; flex-direction: column; align-items: center;
|
||
gap: 4px; padding: 4px 8px; min-width: 70px; position: relative;
|
||
}
|
||
#video .vt-pc-label { font-size: 10px; color: #999; font-weight: 600; letter-spacing: .3px; }
|
||
#video .vt-pc-card.win .vt-pc-label {
|
||
color: #fff; background: linear-gradient(135deg, #FF6B6B, #E53935);
|
||
padding: 2px 8px; border-radius: 4px;
|
||
box-shadow: 0 2px 4px rgba(229,57,53,.3);
|
||
}
|
||
#video .vt-pc-price {
|
||
font-size: 22px; font-weight: 800; color: #1a1a1a;
|
||
font-variant-numeric: tabular-nums; letter-spacing: -.5px;
|
||
}
|
||
#video .vt-pc-price.strike { color: #CCCCCC; text-decoration: line-through; font-size: 18px; font-weight: 600; }
|
||
#video .vt-pc-price.now { color: #E53935; font-size: 24px; }
|
||
#video .vt-pc-arrow { color: #E65100; font-size: 22px; font-weight: 600; text-shadow: 0 2px 4px rgba(255,111,0,.3); }
|
||
#video .vt-pc-save-tag {
|
||
position: absolute; top: -10px; right: -8px;
|
||
font-size: 10px; font-weight: 600; color: #fff;
|
||
background: linear-gradient(135deg, #FF6B6B, #E53935);
|
||
padding: 2px 6px; border-radius: 8px 8px 8px 4px;
|
||
box-shadow: 0 2px 6px rgba(229,57,53,.45);
|
||
transform: rotate(8deg); white-space: nowrap;
|
||
}
|
||
/* 装饰金币 */
|
||
#video .vt-coin {
|
||
position: absolute; z-index: 1; border-radius: 50%;
|
||
background: linear-gradient(135deg, #FFE066 0%, #FFC300 50%, #FFA000 100%);
|
||
display: flex; align-items: center; justify-content: center;
|
||
font-weight: 800; color: #5A3A00;
|
||
box-shadow: 0 4px 10px rgba(120,60,0,.25),
|
||
inset 0 1px 2px rgba(255,255,255,.7),
|
||
inset 0 -1px 2px rgba(139,69,19,.3);
|
||
border: 1.5px solid rgba(180,100,30,.25);
|
||
}
|
||
#video .vt-coin-tl { top: 14%; left: 10%; width: 36px; height: 36px; font-size: 17px; transform: rotate(-12deg); animation: vtFloatA 3.2s ease-in-out infinite; }
|
||
#video .vt-coin-tr { top: 22%; right: 9%; width: 28px; height: 28px; font-size: 13px; transform: rotate(18deg); animation: vtFloatB 3.6s ease-in-out infinite .3s; }
|
||
#video .vt-coin-bl { bottom: 28%; left: 14%; width: 24px; height: 24px; font-size: 12px; transform: rotate(8deg); animation: vtFloatA 3.8s ease-in-out infinite .6s; }
|
||
#video .vt-coin-br { bottom: 18%; right: 12%; width: 32px; height: 32px; font-size: 15px; transform: rotate(-15deg); animation: vtFloatB 3.4s ease-in-out infinite .9s; }
|
||
@keyframes vtFloatA { 0%,100% { transform: rotate(-12deg) translateY(0); } 50% { transform: rotate(-12deg) translateY(-8px); } }
|
||
@keyframes vtFloatB { 0%,100% { transform: rotate(18deg) translateY(0); } 50% { transform: rotate(18deg) translateY(-10px); } }
|
||
/* 闪光 */
|
||
#video .vt-sparkle {
|
||
position: absolute; z-index: 1; width: 8px; height: 8px;
|
||
background: linear-gradient(to bottom, transparent 45%, rgba(255,255,255,.9) 50%, transparent 55%),
|
||
linear-gradient(to right, transparent 45%, rgba(255,255,255,.9) 50%, transparent 55%);
|
||
transform: rotate(45deg);
|
||
animation: vtSparkle 2.4s ease-in-out infinite;
|
||
}
|
||
#video .vt-sparkle-1 { top: 38%; left: 22%; }
|
||
#video .vt-sparkle-2 { top: 56%; right: 24%; animation-delay: .6s; }
|
||
#video .vt-sparkle-3 { top: 70%; left: 38%; width: 6px; height: 6px; animation-delay: 1.2s; }
|
||
@keyframes vtSparkle { 0%,100% { opacity: 0; transform: rotate(45deg) scale(.5); } 50% { opacity: 1; transform: rotate(45deg) scale(1); } }
|
||
/* dim overlay */
|
||
#video .vt-dim-overlay {
|
||
position: absolute; inset: 0; z-index: 4;
|
||
background: rgba(0,0,0,.5); pointer-events: none;
|
||
opacity: 0; transition: opacity .35s;
|
||
}
|
||
#video .vt-video-player.ended .vt-dim-overlay { opacity: 1; }
|
||
/* center play */
|
||
#video .vt-center-play {
|
||
position: absolute; left: 50%; top: 50%;
|
||
width: 72px; height: 72px;
|
||
background: rgba(0,0,0,.5); border-radius: 50%;
|
||
display: flex; align-items: center; justify-content: center;
|
||
transform: translate(-50%, -50%); cursor: pointer;
|
||
box-shadow: 0 8px 24px rgba(0,0,0,.3);
|
||
transition: opacity .2s, background .15s; z-index: 6;
|
||
}
|
||
#video .vt-center-play svg { width: 30px; height: 30px; fill: #fff; margin-left: 2px; }
|
||
#video .vt-video-player.playing .vt-center-play { opacity: 0; pointer-events: none; }
|
||
#video .vt-video-player.paused .vt-center-play,
|
||
#video .vt-video-player.initial .vt-center-play {
|
||
opacity: 1; visibility: visible; pointer-events: auto;
|
||
}
|
||
#video .vt-video-player.ended .vt-center-play {
|
||
width: 80px; height: 80px;
|
||
background: rgba(255,255,255,.18);
|
||
border: 2px solid rgba(255,255,255,.45);
|
||
backdrop-filter: blur(8px);
|
||
}
|
||
#video .vt-video-player.ended .vt-center-play svg { width: 32px; height: 32px; margin-left: 0; }
|
||
/* controls */
|
||
#video .vt-controls {
|
||
position: absolute; left: 0; right: 0; bottom: 0;
|
||
padding: 12px 12px 16px;
|
||
background: linear-gradient(180deg, transparent, rgba(0,0,0,.7) 55%);
|
||
z-index: 3;
|
||
}
|
||
#video .vt-progress-row { display: flex; align-items: center; gap: 8px; }
|
||
#video .vt-time {
|
||
font-size: 11px; font-weight: 600; color: #fff;
|
||
min-width: 32px; text-align: center; font-variant-numeric: tabular-nums;
|
||
}
|
||
#video .vt-ctrl-pill {
|
||
width: 36px; height: 36px; border-radius: 50%;
|
||
background: rgba(255,255,255,.18);
|
||
display: flex; align-items: center; justify-content: center;
|
||
cursor: pointer; flex-shrink: 0;
|
||
transition: background .15s, transform .12s;
|
||
backdrop-filter: blur(4px);
|
||
}
|
||
#video .vt-ctrl-pill:active { transform: scale(.92); }
|
||
#video .vt-ctrl-pill svg { width: 16px; height: 16px; fill: #fff; }
|
||
/* track 24px 大命中区 */
|
||
#video .vt-progress-track {
|
||
flex: 1; height: 24px; background: transparent;
|
||
display: flex; align-items: center; position: relative; cursor: pointer;
|
||
}
|
||
#video .vt-progress-track::before {
|
||
content: ''; position: absolute; left: 0; right: 0; top: 50%;
|
||
transform: translateY(-50%); height: 4px;
|
||
background: rgba(255,255,255,.3); border-radius: 4px;
|
||
pointer-events: none;
|
||
}
|
||
#video .vt-progress-fill {
|
||
position: absolute; left: 0; top: 50%;
|
||
transform: translateY(-50%); height: 4px;
|
||
background: linear-gradient(90deg, #FFE066, #FFD600);
|
||
border-radius: 4px; pointer-events: none;
|
||
transition: width .08s linear; width: 0%;
|
||
}
|
||
#video .vt-progress-fill::after {
|
||
content: ''; position: absolute; right: -5px; top: 50%;
|
||
width: 11px; height: 11px; background: #FFD600;
|
||
border-radius: 50%; transform: translateY(-50%);
|
||
box-shadow: 0 0 0 3px rgba(255,214,0,.25);
|
||
}
|
||
/* desc */
|
||
#video .vt-desc-body {
|
||
flex: 1; display: flex; align-items: center; justify-content: center;
|
||
text-align: center; padding: 16px 24px;
|
||
}
|
||
#video .vt-desc {
|
||
font-size: 22px; font-weight: 600; color: var(--gray-700);
|
||
letter-spacing: .5px; line-height: 1.4;
|
||
}
|
||
/* CTA */
|
||
#video .vt-cta-bar { padding: 12px 16px 32px; flex-shrink: 0; }
|
||
#video .vt-cta-btn {
|
||
width: 100%; padding: 16px 0; border: none;
|
||
background: linear-gradient(135deg, #FFE066 0%, #FFD600 50%, #FFB300 100%);
|
||
color: #1a1a1a; border-radius: 14px;
|
||
font-size: 17px; font-weight: 700; cursor: pointer;
|
||
box-shadow: 0 6px 18px rgba(255,179,0,.45),
|
||
inset 0 1px 0 rgba(255,255,255,.6);
|
||
position: relative; overflow: hidden;
|
||
letter-spacing: .5px; transition: transform .15s;
|
||
}
|
||
#video .vt-cta-btn:active { transform: scale(.98); }
|
||
#video .vt-cta-btn.disabled {
|
||
background: #E5E5E5 !important;
|
||
background-image: none !important;
|
||
color: #CCCCCC !important;
|
||
box-shadow: none !important;
|
||
cursor: not-allowed; font-weight: 600; letter-spacing: 0;
|
||
}
|
||
|
||
/* ============ Home v2026-05-10 (image-asset driven) ============ */
|
||
/* 原来是 padding: 40px 0 16px,但 padding-top 会推高 sticky 的 scrollport 起点,
|
||
让 brand-strip 贴顶时在 y=84 而非 y=44,上方 40px padding 区域露出滚动卡片。
|
||
改为把 40px 挪到 .brand-strip 的 margin-top,sticky 才能真正贴到 scrollport 顶部 y=44 */
|
||
#home .home-scroll { padding: 0; }
|
||
|
||
/* 顶部品牌带 wordmark —— 38px 极薄 strip;sticky 贴顶(与 .feed-sort 接力,两层共同形成 header)*/
|
||
#home .brand-strip {
|
||
height: 38px;
|
||
margin-top: 40px; /* 替代原 home-scroll 的 padding-top:40px */
|
||
padding: 0 16px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
background: #F5F5F5; /* 同 page bg,未贴顶时无视觉变化;贴顶后挡住下方滚动内容 */
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 5;
|
||
}
|
||
#home .brand-strip-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 7px;
|
||
}
|
||
#home .brand-strip-logo {
|
||
width: 26px;
|
||
height: 26px;
|
||
display: block;
|
||
flex-shrink: 0;
|
||
border-radius: 6px;
|
||
}
|
||
#home .brand-strip-name {
|
||
font-size: 19px;
|
||
font-weight: 800;
|
||
color: #1a1a1a;
|
||
letter-spacing: .8px;
|
||
line-height: 1;
|
||
}
|
||
#home .brand-strip-tagline {
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
color: #666666;
|
||
letter-spacing: .2px;
|
||
}
|
||
|
||
/* 顶部 Banner —— 可滑动轮播(3 个点位) */
|
||
#home .home-banner {
|
||
position: relative;
|
||
margin: 8px 12px 8px;
|
||
border-radius: 18px;
|
||
overflow: hidden;
|
||
box-shadow: 0 6px 20px rgba(255,179,0,.18);
|
||
touch-action: pan-y;
|
||
}
|
||
#home .home-banner-track {
|
||
display: flex;
|
||
width: 200%;
|
||
transition: transform .35s cubic-bezier(.4,0,.2,1);
|
||
will-change: transform;
|
||
}
|
||
#home .home-banner-track.dragging { transition: none; }
|
||
#home .home-banner-slide {
|
||
width: 50%;
|
||
flex-shrink: 0;
|
||
cursor: pointer;
|
||
-webkit-user-select: none;
|
||
user-select: none;
|
||
}
|
||
#home .home-banner-slide img {
|
||
width: 100%;
|
||
display: block;
|
||
pointer-events: none;
|
||
-webkit-user-drag: none;
|
||
}
|
||
#home .home-banner-slide-fill {
|
||
width: 100%;
|
||
aspect-ratio: 1793 / 677;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
justify-content: center;
|
||
padding: 0 28px;
|
||
color: #fff;
|
||
box-sizing: border-box;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
#home .home-banner-slide-fill.bf-orange {
|
||
background: linear-gradient(135deg, #FF9A56 0%, #FF6B35 60%, #F4511E 100%);
|
||
}
|
||
#home .home-banner-slide-fill.bf-blue {
|
||
background: linear-gradient(135deg, #5EC9F5 0%, #2196F3 60%, #1565C0 100%);
|
||
}
|
||
#home .home-banner-slide-fill .bf-title {
|
||
font-size: 24px;
|
||
font-weight: 800;
|
||
line-height: 1.2;
|
||
letter-spacing: -.2px;
|
||
text-shadow: 0 1px 2px rgba(0,0,0,.12);
|
||
}
|
||
#home .home-banner-slide-fill .bf-pill {
|
||
margin-top: 12px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
padding: 6px 12px;
|
||
border-radius: 999px;
|
||
background: rgba(255,255,255,.92);
|
||
color: #1A1A1A;
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
}
|
||
#home .home-banner-slide-fill .bf-deco {
|
||
position: absolute;
|
||
right: -10px;
|
||
bottom: -10px;
|
||
font-size: 110px;
|
||
line-height: 1;
|
||
opacity: .85;
|
||
filter: drop-shadow(0 4px 12px rgba(0,0,0,.18));
|
||
pointer-events: none;
|
||
}
|
||
#home .home-banner-dots {
|
||
position: absolute;
|
||
right: 12px;
|
||
bottom: 10px;
|
||
display: flex;
|
||
gap: 5px;
|
||
z-index: 2;
|
||
}
|
||
#home .home-banner-dot {
|
||
width: 5px;
|
||
height: 5px;
|
||
border-radius: 50%;
|
||
background: rgba(255,255,255,.45);
|
||
transition: background .2s ease;
|
||
}
|
||
#home .home-banner-dot.active {
|
||
background: #fff;
|
||
}
|
||
|
||
/* ============ Home v2026-06-01: 节省日志横条(banner ↔ 双卡之间,左侧脉冲点 + 滚动 feed) ============ */
|
||
#home .home-marquee {
|
||
margin: 0 12px;
|
||
height: 32px;
|
||
border-radius: 16px;
|
||
background: linear-gradient(135deg, #FFF8E1 0%, #FFECB3 100%);
|
||
border: 1px solid #FFE082;
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 0 12px 0 40px;
|
||
gap: 10px;
|
||
overflow: hidden;
|
||
box-shadow: 0 2px 6px rgba(255, 140, 60, .08);
|
||
-webkit-tap-highlight-color: transparent;
|
||
}
|
||
#home .home-mq-dot {
|
||
flex-shrink: 0;
|
||
width: 16px; height: 16px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #FF5722;
|
||
}
|
||
#home .home-mq-dot svg { display: block; width: 100%; height: 100%; }
|
||
#home .home-mq-viewport {
|
||
flex: 1;
|
||
height: 22px;
|
||
overflow: hidden;
|
||
position: relative;
|
||
}
|
||
#home .home-mq-track {
|
||
position: absolute; left: 0; top: 0; right: 0;
|
||
display: block;
|
||
will-change: transform;
|
||
}
|
||
#home .home-mq-item {
|
||
height: 22px;
|
||
display: grid;
|
||
grid-template-columns: 16px max-content;
|
||
column-gap: 9px;
|
||
align-items: center;
|
||
justify-content: start;
|
||
font-size: 12px; color: #1a1a1a;
|
||
letter-spacing: .1px;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
}
|
||
#home .home-mq-copy {
|
||
--home-mq-letter-gap: .1px;
|
||
--home-mq-time-user-gap: 7px;
|
||
display: grid;
|
||
grid-template-columns:
|
||
max-content
|
||
var(--home-mq-time-user-gap)
|
||
var(--home-mq-user-slot, 41px)
|
||
var(--home-mq-letter-gap)
|
||
max-content
|
||
var(--home-mq-letter-gap)
|
||
var(--home-mq-amount-slot, 48px)
|
||
var(--home-mq-letter-gap)
|
||
max-content;
|
||
align-items: baseline;
|
||
white-space: nowrap;
|
||
letter-spacing: .1px;
|
||
}
|
||
#home .home-mq-item .mq-time {
|
||
grid-column: 1;
|
||
color: #8B7355; font-weight: 700; font-size: 13px;
|
||
font-family: -apple-system, "DIN Alternate", sans-serif;
|
||
letter-spacing: .2px;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
#home .home-mq-item .mq-user {
|
||
grid-column: 3;
|
||
justify-self: center;
|
||
text-align: center;
|
||
color: #4D4D4D;
|
||
overflow: visible;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
#home .home-mq-item .mq-act {
|
||
grid-column: 5;
|
||
color: #4D4D4D;
|
||
overflow: visible;
|
||
text-overflow: clip;
|
||
}
|
||
#home .home-mq-item .mq-amt {
|
||
grid-column: 7;
|
||
justify-self: center;
|
||
color: #FF5722; font-weight: 800;
|
||
font-family: -apple-system, "DIN Alternate", sans-serif;
|
||
font-size: 13px;
|
||
letter-spacing: .1px;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
#home .home-mq-item .mq-unit {
|
||
grid-column: 9;
|
||
color: #4D4D4D;
|
||
}
|
||
#home .home-mq-measure {
|
||
position: absolute;
|
||
left: -9999px;
|
||
top: -9999px;
|
||
visibility: hidden;
|
||
white-space: nowrap;
|
||
font-size: 12px;
|
||
letter-spacing: .1px;
|
||
pointer-events: none;
|
||
}
|
||
#home .home-mq-measure .mq-user {
|
||
color: #4D4D4D;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
#home .home-mq-measure .mq-amt {
|
||
color: #FF5722;
|
||
font-weight: 800;
|
||
font-family: -apple-system, "DIN Alternate", sans-serif;
|
||
font-size: 13px;
|
||
letter-spacing: .1px;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
|
||
/* ============ Home v2026-06-03: 平台 3 数据板块(纯色 + 深字 + 竖线分隔,无阴影) ============ */
|
||
#home .home-3stat {
|
||
margin: 8px 12px 0;
|
||
background: #FFD600;
|
||
border-radius: 12px;
|
||
padding: 9px 6px;
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr 1fr;
|
||
box-sizing: border-box;
|
||
}
|
||
#home .h3s-card {
|
||
background: transparent;
|
||
text-align: center;
|
||
position: relative;
|
||
padding: 0 4px;
|
||
box-sizing: border-box;
|
||
}
|
||
#home .h3s-card + .h3s-card::before {
|
||
content: '';
|
||
position: absolute;
|
||
left: 0; top: 14%;
|
||
width: 1px; height: 72%;
|
||
background: linear-gradient(180deg, transparent, rgba(0,0,0,.18) 30%, rgba(0,0,0,.18) 70%, transparent);
|
||
}
|
||
#home .h3s-label {
|
||
font-size: 10px; font-weight: 700;
|
||
color: #1A1A1A; opacity: .75;
|
||
letter-spacing: .3px;
|
||
margin-bottom: 3px;
|
||
line-height: 1;
|
||
}
|
||
#home .h3s-num {
|
||
font-family: -apple-system, "DIN Alternate", sans-serif;
|
||
font-size: 20px; font-weight: 900; color: #1A1A1A;
|
||
line-height: 1; letter-spacing: -.3px;
|
||
display: block;
|
||
text-align: center;
|
||
white-space: nowrap;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
#home .h3s-value {
|
||
position: relative;
|
||
display: inline-block;
|
||
}
|
||
#home .h3s-num .h3s-yuan { font-size: 13px; font-weight: 800; margin-right: 1px; color: #1A1A1A; }
|
||
#home .h3s-num .h3s-unit {
|
||
position: absolute;
|
||
left: 100%;
|
||
bottom: 1px;
|
||
font-size: 11px;
|
||
font-weight: 800;
|
||
margin-left: 1px;
|
||
color: #1A1A1A;
|
||
opacity: .8;
|
||
}
|
||
|
||
/* 最近一次比价记录:结果摘要入口 */
|
||
#home .last-compare-banner {
|
||
margin: 8px 12px 0;
|
||
padding: 10px;
|
||
border-radius: 12px;
|
||
background: #FFFDF5;
|
||
border: 1px solid rgba(255,214,0,.72);
|
||
box-shadow: 0 4px 12px rgba(255,179,0,.12);
|
||
cursor: pointer;
|
||
opacity: 1;
|
||
transform: none;
|
||
transition: transform .12s ease, opacity .12s ease;
|
||
-webkit-tap-highlight-color: transparent;
|
||
}
|
||
#home .last-compare-banner:active {
|
||
transform: scale(.985);
|
||
opacity: .92;
|
||
}
|
||
#home .last-compare-banner .lcb-foot { display: none !important; }
|
||
#home .last-compare-banner .lcb-platform { display: none !important; }
|
||
#home .last-compare-banner::after {
|
||
content: '';
|
||
position: absolute;
|
||
right: 4px;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
width: 18px; height: 22px;
|
||
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'><path d='M9 6l6 6-6 6' stroke='%231A1A1A' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
|
||
background-size: contain;
|
||
background-repeat: no-repeat;
|
||
background-position: center;
|
||
pointer-events: none;
|
||
}
|
||
#home .last-compare-banner.visible {
|
||
display: block;
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
#home .lcb-head,
|
||
#home .lcb-body,
|
||
#home .lcb-foot,
|
||
#home .lcb-top,
|
||
#home .lcb-platform {
|
||
display: flex;
|
||
align-items: center;
|
||
min-width: 0;
|
||
}
|
||
#home .lcb-head {
|
||
justify-content: flex-start;
|
||
gap: 8px;
|
||
margin-bottom: 7px;
|
||
}
|
||
#home .lcb-body { gap: 10px; }
|
||
#home .lcb-main {
|
||
min-width: 0;
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 5px;
|
||
}
|
||
#home .lcb-top { gap: 6px; }
|
||
#home .lcb-kicker {
|
||
flex-shrink: 0;
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
color: #8B6914;
|
||
padding: 2px 7px;
|
||
border-radius: 999px;
|
||
background: rgba(255,214,0,.26);
|
||
line-height: 1.1;
|
||
}
|
||
#home .lcb-status {
|
||
display: none;
|
||
}
|
||
#home .lcb-shop {
|
||
min-width: 0;
|
||
flex: 1;
|
||
font-size: 14px;
|
||
font-weight: 800;
|
||
color: #1A1A1A;
|
||
line-height: 1.2;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
#home .lcb-meta {
|
||
min-width: 0;
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
color: #666;
|
||
line-height: 1.25;
|
||
}
|
||
#home .lcb-dish {
|
||
display: block;
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
#home .lcb-pricebox {
|
||
width: 90px;
|
||
min-height: 56px;
|
||
flex-shrink: 0;
|
||
border-radius: 10px;
|
||
background: linear-gradient(180deg,#FFE066 0%,#FFD600 100%);
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 3px;
|
||
box-shadow: inset 0 1px 0 rgba(255,255,255,.58);
|
||
}
|
||
#home .lcb-price-label {
|
||
color: #8B6914;
|
||
font-size: 10px;
|
||
font-weight: 700;
|
||
line-height: 1;
|
||
}
|
||
#home .lcb-price {
|
||
color: #FF5722;
|
||
font-size: 20px;
|
||
font-weight: 900;
|
||
line-height: 1;
|
||
white-space: nowrap;
|
||
}
|
||
#home .lcb-platform {
|
||
gap: 4px;
|
||
min-width: 0;
|
||
color: #5A3A00;
|
||
font-size: 10px;
|
||
font-weight: 700;
|
||
line-height: 1;
|
||
max-width: 82px;
|
||
}
|
||
#home .lcb-platform img {
|
||
width: 14px;
|
||
height: 14px;
|
||
border-radius: 4px;
|
||
object-fit: cover;
|
||
flex-shrink: 0;
|
||
background: #fff;
|
||
}
|
||
#home .lcb-platform-name {
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
#home .lcb-foot {
|
||
justify-content: flex-end;
|
||
gap: 4px;
|
||
margin-top: 7px;
|
||
}
|
||
#home .lcb-note {
|
||
color: #8B6914;
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
white-space: nowrap;
|
||
}
|
||
#home .lcb-arrow {
|
||
flex-shrink: 0;
|
||
color: #8B6914;
|
||
width: 16px;
|
||
height: 16px;
|
||
border-radius: 8px;
|
||
background: rgba(255,214,0,.22);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
#home .lcb-arrow svg { width: 11px; height: 11px; display: block; }
|
||
|
||
#home .last-compare-banner.lcb-v-summary .lcb-pricebox {
|
||
background: #FFF3C4;
|
||
box-shadow: none;
|
||
}
|
||
|
||
#home .last-compare-banner.lcb-v-price {
|
||
background: #FFFFFF;
|
||
border-color: rgba(26,26,26,.08);
|
||
box-shadow: 0 4px 12px rgba(0,0,0,.06);
|
||
}
|
||
#home .last-compare-banner.lcb-v-price .lcb-pricebox {
|
||
background: #1A1A1A;
|
||
color: #FFD600;
|
||
}
|
||
#home .last-compare-banner.lcb-v-price .lcb-price-label,
|
||
#home .last-compare-banner.lcb-v-price .lcb-platform {
|
||
color: #FFD600;
|
||
}
|
||
#home .last-compare-banner.lcb-v-price .lcb-price { color: #FFD600; }
|
||
#home .last-compare-banner.lcb-v-price .lcb-platform img { border: 1px solid rgba(255,255,255,.7); }
|
||
|
||
#home .last-compare-banner.lcb-v-ticket {
|
||
background: linear-gradient(180deg,#FFFDF5 0%,#FFF8E6 100%);
|
||
}
|
||
#home .last-compare-banner.lcb-v-ticket .lcb-body {
|
||
display: block;
|
||
}
|
||
#home .last-compare-banner.lcb-v-ticket .lcb-main {
|
||
gap: 6px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-ticket .lcb-pricebox {
|
||
width: auto;
|
||
min-height: 30px;
|
||
margin-top: 7px;
|
||
padding: 0 9px;
|
||
flex-direction: row;
|
||
justify-content: space-between;
|
||
background: #fff;
|
||
border: 1px dashed rgba(255,179,0,.72);
|
||
box-shadow: none;
|
||
}
|
||
#home .last-compare-banner.lcb-v-ticket .lcb-price {
|
||
font-size: 17px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-ticket .lcb-platform {
|
||
max-width: 120px;
|
||
color: #666;
|
||
}
|
||
|
||
#home .last-compare-banner.lcb-v-split {
|
||
min-height: 88px;
|
||
padding: 0;
|
||
overflow: hidden;
|
||
background: #fff;
|
||
border-color: #FFD600;
|
||
display: grid;
|
||
grid-template-columns: minmax(0,1fr) 98px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-split .lcb-head,
|
||
#home .last-compare-banner.lcb-v-split .lcb-main,
|
||
#home .last-compare-banner.lcb-v-split .lcb-foot {
|
||
padding-left: 10px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-split .lcb-head {
|
||
grid-column: 1;
|
||
margin: 9px 0 6px;
|
||
padding-right: 0;
|
||
}
|
||
#home .last-compare-banner.lcb-v-split .lcb-body {
|
||
display: contents;
|
||
}
|
||
#home .last-compare-banner.lcb-v-split .lcb-main {
|
||
grid-column: 1;
|
||
padding-right: 8px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-split .lcb-pricebox {
|
||
grid-column: 2;
|
||
grid-row: 1 / span 3;
|
||
width: 98px;
|
||
min-height: 88px;
|
||
border-radius: 0;
|
||
background: linear-gradient(180deg,#FFE066 0%,#FFD600 100%);
|
||
}
|
||
#home .last-compare-banner.lcb-v-split .lcb-foot {
|
||
grid-column: 1;
|
||
justify-content: flex-start;
|
||
margin: 5px 0 9px;
|
||
}
|
||
|
||
#home .last-compare-banner.lcb-v-leftprice {
|
||
min-height: 92px;
|
||
padding: 8px;
|
||
display: grid;
|
||
grid-template-columns: 90px minmax(0,1fr);
|
||
column-gap: 10px;
|
||
align-items: stretch;
|
||
background: #FFFFFF;
|
||
border-color: #FFD600;
|
||
box-shadow: 0 5px 14px rgba(255,179,0,.16);
|
||
}
|
||
#home .last-compare-banner.lcb-v-leftprice .lcb-body {
|
||
display: contents;
|
||
}
|
||
#home .last-compare-banner.lcb-v-leftprice .lcb-pricebox {
|
||
grid-column: 1;
|
||
grid-row: 1 / span 3;
|
||
width: 90px;
|
||
min-height: 76px;
|
||
border-radius: 10px;
|
||
background: linear-gradient(180deg,#FFE066 0%,#FFD600 100%);
|
||
}
|
||
#home .last-compare-banner.lcb-v-leftprice .lcb-price-label {
|
||
color: #8B6914;
|
||
}
|
||
#home .last-compare-banner.lcb-v-leftprice .lcb-price {
|
||
color: #FF5722;
|
||
font-size: 19px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-leftprice .lcb-platform {
|
||
max-width: 78px;
|
||
color: #5A3A00;
|
||
}
|
||
#home .last-compare-banner.lcb-v-leftprice .lcb-head {
|
||
grid-column: 2;
|
||
margin: 2px 0 5px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-leftprice .lcb-kicker {
|
||
padding: 0;
|
||
background: transparent;
|
||
color: #8B6914;
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
}
|
||
#home .last-compare-banner.lcb-v-leftprice .lcb-main {
|
||
grid-column: 2;
|
||
justify-content: center;
|
||
gap: 4px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-leftprice .lcb-shop {
|
||
font-size: 14px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-leftprice .lcb-meta {
|
||
font-size: 12px;
|
||
color: #666;
|
||
}
|
||
#home .last-compare-banner.lcb-v-leftprice .lcb-foot {
|
||
grid-column: 2;
|
||
justify-content: flex-start;
|
||
margin: 5px 0 2px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-leftprice .lcb-note {
|
||
height: 20px;
|
||
padding: 0 7px;
|
||
border-radius: 999px;
|
||
background: rgba(255,214,0,.22);
|
||
color: #8B6914;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
}
|
||
#home .last-compare-banner.lcb-v-leftprice .lcb-arrow {
|
||
width: 18px;
|
||
height: 18px;
|
||
border-radius: 9px;
|
||
}
|
||
|
||
/* lcb-v-reference (= B6 final): 顶角红 chip + 左栈店名菜名 + 右栈最低价/¥57.9/查看详情 pill */
|
||
#home .last-compare-banner.lcb-v-reference {
|
||
display: grid;
|
||
grid-template-columns: 1fr auto;
|
||
grid-template-rows: auto auto;
|
||
align-items: center;
|
||
column-gap: 12px;
|
||
row-gap: 1px;
|
||
min-height: auto;
|
||
padding: 24px 12px 8px 12px;
|
||
position: relative;
|
||
background: linear-gradient(90deg,#FFF7D8 0%,#FFFDF8 58%,#FFF2C8 100%);
|
||
border: 0;
|
||
border-radius: 14px;
|
||
box-shadow: inset 0 0 0 1px rgba(255,214,0,.50), 0 4px 12px rgba(255,179,0,.10);
|
||
overflow: hidden;
|
||
}
|
||
/* 隐藏 base banner 的右箭头 ::after */
|
||
#home .last-compare-banner.lcb-v-reference::after {
|
||
display: none !important;
|
||
}
|
||
/* body / main / pricebox 用 display: contents(左栈)或 grid 项(右栈) */
|
||
#home .last-compare-banner.lcb-v-reference .lcb-body { display: contents; }
|
||
#home .last-compare-banner.lcb-v-reference .lcb-main { display: contents; }
|
||
#home .last-compare-banner.lcb-v-reference .lcb-foot { display: none !important; }
|
||
#home .last-compare-banner.lcb-v-reference .lcb-arrow { display: none; }
|
||
#home .last-compare-banner.lcb-v-reference .lcb-platform { display: none !important; }
|
||
|
||
/* chip 「最近比价」 顶角红块带阴影 */
|
||
#home .last-compare-banner.lcb-v-reference .lcb-head {
|
||
position: absolute;
|
||
left: 12px;
|
||
top: 0;
|
||
margin: 0;
|
||
padding: 0;
|
||
z-index: 2;
|
||
display: inline-flex;
|
||
}
|
||
#home .last-compare-banner.lcb-v-reference .lcb-kicker {
|
||
height: 22px;
|
||
padding: 0 10px;
|
||
border-radius: 0 0 6px 6px;
|
||
background: #FF5722;
|
||
color: #FFFFFF;
|
||
font-size: 0;
|
||
line-height: 1;
|
||
box-shadow: 0 2px 5px rgba(255,87,34,.16);
|
||
display: inline-flex;
|
||
align-items: center;
|
||
}
|
||
#home .last-compare-banner.lcb-v-reference .lcb-kicker::before {
|
||
content: '最近比价';
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
color: #FFFFFF;
|
||
line-height: 1;
|
||
letter-spacing: .3px;
|
||
}
|
||
|
||
/* 行 1 左:店名 */
|
||
#home .last-compare-banner.lcb-v-reference .lcb-top {
|
||
grid-row: 1;
|
||
grid-column: 1;
|
||
justify-self: start;
|
||
align-self: center;
|
||
display: flex;
|
||
align-items: center;
|
||
min-width: 0;
|
||
max-width: 100%;
|
||
}
|
||
#home .last-compare-banner.lcb-v-reference .lcb-shop {
|
||
font-size: 15px;
|
||
font-weight: 800;
|
||
line-height: 1.2;
|
||
color: #1A1A1A;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
max-width: 100%;
|
||
letter-spacing: 0;
|
||
}
|
||
|
||
/* 行 2 左:菜名 — 对齐首页 .tc-sub 视觉权重 */
|
||
#home .last-compare-banner.lcb-v-reference .lcb-meta {
|
||
grid-row: 2;
|
||
grid-column: 1;
|
||
justify-self: start;
|
||
align-self: start;
|
||
font-size: 10px;
|
||
font-weight: 400;
|
||
color: #666;
|
||
line-height: 1.2;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
min-width: 0;
|
||
max-width: 100%;
|
||
}
|
||
|
||
/* 右栈:透明 column,最低价 + ¥57.9 + pill — 收紧版(方案 A 微调 + 上移 4px) */
|
||
#home .last-compare-banner.lcb-v-reference .lcb-pricebox {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
justify-content: center;
|
||
gap: 2px;
|
||
grid-row: 1 / 3;
|
||
grid-column: 2;
|
||
justify-self: end;
|
||
align-self: center;
|
||
position: static;
|
||
width: 92px;
|
||
min-height: 0;
|
||
height: auto;
|
||
background: transparent;
|
||
border-radius: 0;
|
||
padding: 0;
|
||
box-shadow: none;
|
||
flex-shrink: 0;
|
||
line-height: 1;
|
||
transform: translateY(-4px);
|
||
}
|
||
#home .last-compare-banner.lcb-v-reference .lcb-pricebox::before {
|
||
display: none;
|
||
}
|
||
#home .last-compare-banner.lcb-v-reference .lcb-price-label {
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
color: #8B6914;
|
||
letter-spacing: .2px;
|
||
line-height: 1;
|
||
padding: 0;
|
||
background: transparent;
|
||
align-self: center;
|
||
border-radius: 0;
|
||
height: auto;
|
||
min-width: 0;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
#home .last-compare-banner.lcb-v-reference .lcb-price {
|
||
color: #FF5722;
|
||
font-family: "DIN Alternate", "Helvetica Neue", sans-serif;
|
||
font-size: 22px;
|
||
font-weight: 800;
|
||
line-height: 1;
|
||
letter-spacing: 0;
|
||
font-variant-numeric: tabular-nums;
|
||
display: inline-flex;
|
||
align-items: baseline;
|
||
gap: 0;
|
||
align-self: center;
|
||
}
|
||
#home .last-compare-banner.lcb-v-reference .lcb-price-currency {
|
||
font-size: 15px;
|
||
font-weight: 800;
|
||
line-height: 1;
|
||
}
|
||
#home .last-compare-banner.lcb-v-reference .lcb-price-int {
|
||
font-size: 22px;
|
||
font-weight: 800;
|
||
line-height: 1;
|
||
}
|
||
#home .last-compare-banner.lcb-v-reference .lcb-price-dec {
|
||
font-size: 12px;
|
||
font-weight: 800;
|
||
line-height: 1;
|
||
}
|
||
|
||
/* 右栈底 满宽 CTA pill「查看详情 ›」— 校准到 DESIGN.md cta-primary 标准 */
|
||
#home .last-compare-banner.lcb-v-reference .lcb-detail-cta {
|
||
align-self: stretch;
|
||
width: 100%;
|
||
height: 22px;
|
||
padding: 0 8px;
|
||
border-radius: 999px;
|
||
background: linear-gradient(180deg,#FFE066 0%,#FFC400 100%);
|
||
color: #5A3A00;
|
||
font-size: 11px;
|
||
font-weight: 800;
|
||
line-height: 1;
|
||
letter-spacing: .3px;
|
||
border: none;
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 4px;
|
||
box-shadow: inset 0 1px 0 rgba(255,255,255,.7), 0 2px 6px rgba(255,179,0,.35);
|
||
pointer-events: none;
|
||
}
|
||
#home .last-compare-banner.lcb-v-reference .lcb-detail-cta::after {
|
||
content: '';
|
||
display: inline-block;
|
||
width: 4px; height: 4px;
|
||
border-top: 1.7px solid currentColor;
|
||
border-right: 1.7px solid currentColor;
|
||
transform: rotate(45deg) translate(-1px, 1px);
|
||
}
|
||
|
||
#home .last-compare-banner.lcb-v-tagright .lcb-head {
|
||
left: auto;
|
||
right: 104px;
|
||
top: 8px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-tagright .lcb-kicker {
|
||
height: 18px;
|
||
padding: 0 8px;
|
||
border-radius: 999px;
|
||
background: rgba(255,214,0,.32);
|
||
color: #7A5600;
|
||
box-shadow: none;
|
||
}
|
||
#home .last-compare-banner.lcb-v-tagright .lcb-main {
|
||
padding-top: 8px;
|
||
}
|
||
|
||
#home .last-compare-banner.lcb-v-topbar .lcb-head {
|
||
left: 0;
|
||
right: 96px;
|
||
top: 0;
|
||
height: 23px;
|
||
margin: 0;
|
||
justify-content: center;
|
||
background: linear-gradient(90deg, rgba(255,214,0,.18), rgba(255,214,0,.04));
|
||
border-bottom: 1px solid rgba(255,214,0,.18);
|
||
}
|
||
#home .last-compare-banner.lcb-v-topbar .lcb-kicker {
|
||
height: auto;
|
||
padding: 0;
|
||
border-radius: 0;
|
||
background: transparent;
|
||
color: #8B6914;
|
||
box-shadow: none;
|
||
font-size: 10px;
|
||
letter-spacing: .4px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-topbar .lcb-main {
|
||
padding-top: 17px;
|
||
}
|
||
|
||
#home .last-compare-banner.lcb-v-pricebadge .lcb-head {
|
||
left: auto;
|
||
right: 15px;
|
||
top: 7px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-pricebadge .lcb-kicker {
|
||
height: 16px;
|
||
padding: 0 6px;
|
||
border-radius: 999px;
|
||
background: rgba(255,255,255,.78);
|
||
color: #8B6914;
|
||
box-shadow: inset 0 0 0 1px rgba(255,214,0,.36);
|
||
font-size: 9px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-pricebadge .lcb-price-label {
|
||
margin-top: 10px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-pricebadge .lcb-main {
|
||
padding-top: 7px;
|
||
}
|
||
|
||
#home .last-compare-banner.lcb-v-mutedright .lcb-head {
|
||
left: auto;
|
||
right: 108px;
|
||
top: 11px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-mutedright .lcb-kicker {
|
||
height: auto;
|
||
padding: 0;
|
||
border-radius: 0;
|
||
background: transparent;
|
||
color: #9B8C6A;
|
||
box-shadow: none;
|
||
font-size: 10px;
|
||
font-weight: 600;
|
||
letter-spacing: .2px;
|
||
}
|
||
#home .last-compare-banner.lcb-v-mutedright .lcb-main {
|
||
padding-top: 8px;
|
||
}
|
||
|
||
/* 5 类别快捷入口(无白底卡片,直接贴页面背景) */
|
||
#home .home-cats {
|
||
display: grid; grid-template-columns: repeat(5, 1fr);
|
||
margin: 0 12px;
|
||
padding: 6px 4px 4px;
|
||
background: transparent;
|
||
border-radius: 0;
|
||
box-shadow: none;
|
||
}
|
||
#home .home-cat {
|
||
display: flex; flex-direction: column; align-items: center;
|
||
cursor: pointer; transition: transform .12s;
|
||
padding: 0 2px;
|
||
}
|
||
#home .home-cat:active { transform: scale(.94); }
|
||
#home .home-cat img {
|
||
width: 48px; height: 48px; display: block; margin-bottom: 4px;
|
||
border-radius: 12px;
|
||
}
|
||
#home .home-cat-label {
|
||
font-size: 12px; font-weight: 600; color: #1a1a1a; letter-spacing: .2px;
|
||
}
|
||
|
||
/* 三联:左 双数据卡(HTML+CSS)+ 右 一键领优惠(橙色整卡) */
|
||
#home .home-tri {
|
||
display: grid; grid-template-columns: minmax(0, 1fr) 32px minmax(0, 1fr); gap: 4px;
|
||
padding: 8px 12px 8px;
|
||
align-items: stretch;
|
||
}
|
||
#home .home-tri-arrow {
|
||
align-self: center;
|
||
justify-self: center;
|
||
width: 28.8px;
|
||
height: 19.8px;
|
||
pointer-events: none;
|
||
z-index: 4;
|
||
background-image: url('assets/home/index/chevron-double-fade.png');
|
||
background-size: contain;
|
||
background-repeat: no-repeat;
|
||
background-position: center;
|
||
}
|
||
#home .home-tri-arrow svg { display: none; }
|
||
#home .tri-stats {
|
||
display: flex; flex-direction: column; gap: 8px;
|
||
height: 100%;
|
||
}
|
||
#home .tri-stat {
|
||
position: relative;
|
||
flex: 1; min-height: 84px;
|
||
border-radius: 14px;
|
||
background: linear-gradient(135deg,#FFF3E0 0%,#FFE0B2 100%);
|
||
padding: 12px 12px;
|
||
cursor: pointer; transition: transform .12s;
|
||
box-shadow: 0 4px 14px rgba(255,140,60,.10);
|
||
overflow: hidden;
|
||
}
|
||
#home .tri-stat:active { transform: translateY(1px); }
|
||
#home .tri-stat-label {
|
||
font-size: 13px; font-weight: 700; color: #1a1a1a; letter-spacing: .2px;
|
||
line-height: 1;
|
||
}
|
||
#home .tri-stat-amount {
|
||
margin-top: 8px;
|
||
color: #FF5722; font-weight: 900;
|
||
display: inline-flex; align-items: baseline; gap: 0;
|
||
letter-spacing: -.5px; line-height: 1;
|
||
}
|
||
/* Price Golden Ratio: 整数 28 → ¥ 20 (×0.7), dec 15 (×0.55) + tabular-nums */
|
||
#home .tri-stat-amount { font-variant-numeric: tabular-nums; }
|
||
#home .tri-stat-amount .yuan { font-size: 20px; font-weight: 900; margin-right: 2px; }
|
||
#home .tri-stat-amount .num { font-size: 28px; line-height: 1; }
|
||
#home .tri-stat-amount .dec { font-size: 15px; font-weight: 900; margin-left: 2px; }
|
||
#home .tri-stat-art {
|
||
position: absolute; right: 6px; bottom: 4px;
|
||
width: 70px; height: 64px;
|
||
pointer-events: none;
|
||
user-select: none;
|
||
filter: drop-shadow(0 4px 6px rgba(180,80,20,.12));
|
||
}
|
||
#home .tri-stat-art img {
|
||
width: 100%; height: 100%; object-fit: contain; object-position: right bottom; display: block;
|
||
}
|
||
#home .tri-claim {
|
||
position: relative; overflow: hidden;
|
||
border-radius: 14px;
|
||
cursor: pointer; transition: transform .12s;
|
||
box-shadow: 0 8px 22px rgba(255,87,34,.22);
|
||
background: linear-gradient(140deg,#FFE066 0%,#FF5722 55%,#FF5722 100%);
|
||
padding: 12px 12px 8px;
|
||
display: flex; flex-direction: column;
|
||
color: #fff;
|
||
}
|
||
#home .tri-claim:active { transform: translateY(1px); }
|
||
#home .tri-claim-bg {
|
||
position: absolute; inset: -2px;
|
||
background-image: url('assets/home/index/coupon-claim-bg.png');
|
||
background-size: cover; background-position: center bottom;
|
||
background-repeat: no-repeat;
|
||
pointer-events: none;
|
||
}
|
||
#home .tri-claim-inner {
|
||
position: relative; z-index: 1;
|
||
display: flex; flex-direction: column; height: 100%;
|
||
}
|
||
#home .tri-claim-title {
|
||
font-size: 22px; font-weight: 900; color: #fff;
|
||
letter-spacing: .5px; line-height: 1;
|
||
text-shadow: 0 2px 6px rgba(180,50,0,.22);
|
||
}
|
||
#home .tri-claim-sub {
|
||
margin-top: 8px;
|
||
font-size: 12px; font-weight: 600; color: #fff;
|
||
opacity: .95; letter-spacing: .3px;
|
||
text-shadow: 0 1px 3px rgba(180,50,0,.18);
|
||
}
|
||
#home .tri-claim-spacer { flex: 1; min-height: 56px; }
|
||
#home .tri-claim-cta {
|
||
align-self: stretch;
|
||
background: #fff; color: #FF5722;
|
||
border-radius: 999px;
|
||
padding: 8px 12px;
|
||
font-size: 14px; font-weight: 600; letter-spacing: .3px;
|
||
display: inline-flex; align-items: center; justify-content: center; gap: 4px;
|
||
box-shadow: 0 4px 10px rgba(180,60,0,.18);
|
||
}
|
||
#home .tri-claim-cta .arrow { font-size: 14px; font-weight: 900; margin-left: 2px; }
|
||
|
||
/* "已领"态:领券完成后回到首页时替换 .tri-claim 默认态 */
|
||
#home .tri-claim-done {
|
||
background: linear-gradient(140deg,#FF6B3D 0%,#FF5722 55%,#E65100 100%);
|
||
padding: 12px 12px 8px;
|
||
}
|
||
#home .tri-claim-bg-done {
|
||
background-image: none;
|
||
background: radial-gradient(circle at 80% 18%, rgba(255,224,160,.45) 0%, rgba(255,160,80,0) 55%);
|
||
}
|
||
#home .tcd-head {
|
||
font-size: 12px; font-weight: 600; color: #fff;
|
||
display: inline-flex; align-items: center; gap: 4px;
|
||
opacity: .98; letter-spacing: .2px;
|
||
text-shadow: 0 1px 2px rgba(180,50,0,.18);
|
||
}
|
||
#home .tcd-check {
|
||
width: 14px; height: 14px; border-radius: 50%;
|
||
background: rgba(255,255,255,.95); color: #FF5722;
|
||
font-size: 10px; font-weight: 900; line-height: 14px;
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
}
|
||
#home .tcd-num {
|
||
margin-top: 6px;
|
||
display: inline-flex; align-items: baseline; gap: 4px;
|
||
text-shadow: 0 2px 6px rgba(180,50,0,.25);
|
||
}
|
||
#home .tcd-num .num {
|
||
font-size: 28px; font-weight: 900; color: #fff;
|
||
line-height: 1; letter-spacing: -1px;
|
||
font-family: -apple-system, "DIN Alternate", sans-serif;
|
||
}
|
||
#home .tcd-num .unit {
|
||
font-size: 12px; font-weight: 600; color: #FFF3E0;
|
||
letter-spacing: .2px;
|
||
}
|
||
#home .tcd-from {
|
||
align-self: stretch;
|
||
background: rgba(255,255,255,.18);
|
||
border-radius: 999px;
|
||
padding: 4px 8px 4px 8px;
|
||
font-size: 11px; font-weight: 600;
|
||
display: inline-flex; align-items: center; gap: 6px; justify-content: center;
|
||
color: #fff; letter-spacing: .2px;
|
||
backdrop-filter: blur(2px);
|
||
}
|
||
#home .tcd-from-label { opacity: .9; }
|
||
#home .tcd-logos { display: inline-flex; align-items: center; gap: 2px; }
|
||
#home .tcd-logos img {
|
||
width: 16px; height: 16px; border-radius: 4px;
|
||
border: 1.5px solid rgba(255,255,255,.95);
|
||
background: #fff; object-fit: cover;
|
||
box-shadow: 0 1px 3px rgba(120,40,0,.25);
|
||
}
|
||
|
||
/* ============ Home v2026-06-03: 今日领券 + 点外卖赚金币 双卡(结构 1:1 镜像)============ */
|
||
/* 左:今日领券(与右卡 .cta-g6 同 padding / shadow / 字号 / CTA 规格) */
|
||
#home .today-coupon {
|
||
position: relative;
|
||
height: 92px;
|
||
border-radius: 14px;
|
||
padding: 10px 12px;
|
||
background: url('assets/home/index/card-stats-bg.png') center/cover no-repeat;
|
||
box-shadow: 0 4px 14px rgba(255,140,60,.10);
|
||
display: flex;
|
||
flex-direction: column;
|
||
overflow: visible;
|
||
cursor: pointer;
|
||
-webkit-tap-highlight-color: transparent;
|
||
}
|
||
#home .tc-title {
|
||
font-size: 13px;
|
||
font-weight: 700;
|
||
color: #1a1a1a;
|
||
line-height: 1.28;
|
||
letter-spacing: 0;
|
||
white-space: nowrap;
|
||
}
|
||
#home .tc-title .hl { color: #FF5722; }
|
||
#home .tc-sub {
|
||
font-size: 11px;
|
||
font-weight: 400;
|
||
color: #666;
|
||
letter-spacing: 0;
|
||
line-height: 1.3;
|
||
margin-top: 3px;
|
||
white-space: nowrap;
|
||
}
|
||
#home .tc-bottom {
|
||
margin-top: auto;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
#home .tc-cta {
|
||
height: 26px;
|
||
padding: 0 9px 0 11px;
|
||
border-radius: 999px;
|
||
background: linear-gradient(180deg, #FFE066 0%, #FFD600 100%);
|
||
color: #1a1a1a;
|
||
font-size: 11px;
|
||
font-weight: 800;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
box-shadow: inset 0 1px 0 rgba(255,255,255,.55), 0 3px 8px rgba(255,179,0,.35);
|
||
letter-spacing: .3px;
|
||
border: none;
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
}
|
||
#home .tc-cta::after {
|
||
content: '';
|
||
display: inline-block;
|
||
width: 4px; height: 4px;
|
||
border-top: 1.5px solid currentColor;
|
||
border-right: 1.5px solid currentColor;
|
||
transform: rotate(45deg) translate(-1px, 1px);
|
||
}
|
||
#home .tc-coupon-symbols {
|
||
position: absolute;
|
||
right: 8px;
|
||
bottom: 4px;
|
||
width: 46.2px;
|
||
height: auto;
|
||
pointer-events: none;
|
||
z-index: 2;
|
||
}
|
||
#home .tc-coupon-symbols img {
|
||
display: block;
|
||
width: 100%;
|
||
height: auto;
|
||
}
|
||
#home .tc-red-dot {
|
||
position: absolute;
|
||
top: 8px; right: 10px;
|
||
width: 8px; height: 8px;
|
||
background: #FF3D00;
|
||
border-radius: 50%;
|
||
border: 1.5px solid #fff;
|
||
box-shadow: 0 0 0 1.5px rgba(255,61,0,.18);
|
||
animation: tcDotPulse 1.6s ease-in-out infinite;
|
||
z-index: 2;
|
||
}
|
||
@keyframes tcDotPulse {
|
||
0%, 100% { box-shadow: 0 0 0 1.5px rgba(255,61,0,.18); }
|
||
50% { box-shadow: 0 0 0 5px rgba(255,61,0,0); }
|
||
}
|
||
/* 已领状态:其他视觉保持不变,仅隐藏手势提示 */
|
||
#home .today-coupon.claimed .tc-red-dot { display: none; }
|
||
/* 引导手势:未领时手指点击 CTA 的呼吸动画(与 onboarding 的 tapHint 同一套节奏) */
|
||
#home .tc-tap-hand {
|
||
position: absolute;
|
||
left: 60px;
|
||
bottom: -12px;
|
||
width: 46px;
|
||
height: 46px;
|
||
pointer-events: none;
|
||
z-index: 3;
|
||
filter:
|
||
drop-shadow(0 1px 0 #fff)
|
||
drop-shadow(1px 0 0 #fff)
|
||
drop-shadow(0 -1px 0 #fff)
|
||
drop-shadow(-1px 0 0 #fff);
|
||
animation: tcTapHint 1.2s ease-in-out infinite;
|
||
}
|
||
#home .tc-tap-hand img {
|
||
display: block;
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: contain;
|
||
}
|
||
@keyframes tcTapHint {
|
||
0%, 100% { transform: translate(0, 0) scale(1); }
|
||
50% { transform: translate(-2px, 2px) scale(.92); }
|
||
}
|
||
#home .today-coupon.claimed .tc-tap-hand { display: none; }
|
||
|
||
/* 右:比价入口 G-6c(货比三家·不踩坑 + 平台 logo 右下叠加 + CTA pill) */
|
||
#home .cta-g6 {
|
||
position: relative;
|
||
height: 92px;
|
||
border-radius: 14px;
|
||
padding: 10px 12px;
|
||
background: url('assets/home/index/card-waimai-bg.png') center/cover no-repeat;
|
||
box-shadow: 0 4px 14px rgba(255,140,60,.10);
|
||
display: flex;
|
||
flex-direction: column;
|
||
overflow: visible;
|
||
cursor: pointer;
|
||
-webkit-tap-highlight-color: transparent;
|
||
}
|
||
#home .g6-title {
|
||
font-size: 13px;
|
||
font-weight: 700;
|
||
color: #1a1a1a;
|
||
line-height: 1.28;
|
||
letter-spacing: 0;
|
||
white-space: nowrap;
|
||
}
|
||
#home .g6-title .hl { color: #FF5722; }
|
||
#home .g6-sub {
|
||
font-size: 11px;
|
||
font-weight: 400;
|
||
color: #666;
|
||
letter-spacing: 0;
|
||
line-height: 1.3;
|
||
margin-top: 3px;
|
||
white-space: nowrap;
|
||
}
|
||
#home .g6-bottom {
|
||
margin-top: auto;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
#home .g6-cta {
|
||
height: 26px;
|
||
padding: 0 9px 0 11px;
|
||
border-radius: 999px;
|
||
background: linear-gradient(180deg, #FFE066 0%, #FFD600 100%);
|
||
color: #1a1a1a;
|
||
font-size: 11px;
|
||
font-weight: 800;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
box-shadow: inset 0 1px 0 rgba(255,255,255,.55), 0 3px 8px rgba(255,179,0,.35);
|
||
letter-spacing: .3px;
|
||
border: none;
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
}
|
||
#home .g6-cta::after {
|
||
content: '';
|
||
display: inline-block;
|
||
width: 4px;
|
||
height: 4px;
|
||
border-top: 1.5px solid currentColor;
|
||
border-right: 1.5px solid currentColor;
|
||
transform: rotate(45deg) translate(-1px, 1px);
|
||
}
|
||
#home .g6-logos {
|
||
position: absolute;
|
||
bottom: 8px;
|
||
right: 8px;
|
||
display: flex;
|
||
align-items: center;
|
||
flex-shrink: 0;
|
||
}
|
||
#home .g6-logos img {
|
||
width: 24px; height: 24px;
|
||
border-radius: 6px;
|
||
border: 1.5px solid #fff;
|
||
box-shadow: 0 2px 5px rgba(0,0,0,.10);
|
||
margin-left: -6px;
|
||
}
|
||
#home .g6-logos img:first-child { margin-left: 0; }
|
||
#home .g6-logos img:nth-child(1) { z-index: 1; transform: rotate(-14deg); }
|
||
#home .g6-logos img:nth-child(2) { z-index: 3; transform: translateY(-6px) rotate(5deg); }
|
||
#home .g6-logos img:nth-child(3) { z-index: 2; transform: rotate(16deg); }
|
||
/* 右卡引导手势:已领券后,手从左卡转移到「去点餐」CTA 上(与左卡 .tc-tap-hand 同一套呼吸节奏) */
|
||
#home .g6-tap-hand {
|
||
position: absolute;
|
||
left: 60px;
|
||
bottom: -12px;
|
||
width: 46px;
|
||
height: 46px;
|
||
pointer-events: none;
|
||
z-index: 3;
|
||
display: none;
|
||
filter:
|
||
drop-shadow(0 1px 0 #fff)
|
||
drop-shadow(1px 0 0 #fff)
|
||
drop-shadow(0 -1px 0 #fff)
|
||
drop-shadow(-1px 0 0 #fff);
|
||
animation: tcTapHint 1.2s ease-in-out infinite;
|
||
}
|
||
#home .g6-tap-hand img {
|
||
display: block;
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: contain;
|
||
}
|
||
/* 仅在已领券状态下显示右卡的手 */
|
||
#home .cta-g6.coupon-claimed .g6-tap-hand { display: block; }
|
||
|
||
/* 引导卡呼吸描边框(橙红 #FF5722 = cta-warm,与高亮字同色):跟随引导手——
|
||
未领券 → 高亮左卡「今日大额优惠券」;已领券 → 高亮右卡「点外卖赚金币」 */
|
||
#home .today-coupon:not(.claimed),
|
||
#home .cta-g6.coupon-claimed {
|
||
animation: homeGuideBreath 2s ease-in-out infinite;
|
||
}
|
||
@keyframes homeGuideBreath {
|
||
0%, 100% { box-shadow: 0 0 0 1.5px rgba(255,87,34,.5), 0 4px 14px rgba(255,140,60,.10); }
|
||
50% { box-shadow: 0 0 0 2.5px rgba(255,87,34,1), 0 0 11px 1px rgba(255,87,34,.45), 0 4px 14px rgba(255,140,60,.10); }
|
||
}
|
||
|
||
/* 比价平台选择 · 中央模态 */
|
||
.home-picker-mask {
|
||
display: none;
|
||
position: absolute;
|
||
inset: 0;
|
||
z-index: 250;
|
||
background: rgba(20, 12, 4, .5);
|
||
backdrop-filter: blur(2px);
|
||
-webkit-backdrop-filter: blur(2px);
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 24px;
|
||
}
|
||
.home-picker-mask.show { display: flex; animation: homePickerFade .22s ease-out; }
|
||
@keyframes homePickerFade { from { opacity: 0; } to { opacity: 1; } }
|
||
.home-picker-modal {
|
||
width: 100%;
|
||
max-width: 304px;
|
||
background: linear-gradient(180deg, #FFFAF0 0%, #FFFFFF 70%);
|
||
border-radius: 24px;
|
||
padding: 22px 18px 20px;
|
||
box-shadow: 0 24px 60px rgba(120, 80, 30, .28), 0 2px 8px rgba(0,0,0,.06), inset 0 1px 0 rgba(255,255,255,.85);
|
||
border: 1px solid rgba(255, 220, 120, .4);
|
||
animation: homePickerIn .35s cubic-bezier(.22,1,.36,1);
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
.home-picker-modal::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: -60px; left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 220px; height: 120px;
|
||
background: radial-gradient(ellipse at center, rgba(255, 214, 0, .25), transparent 65%);
|
||
pointer-events: none;
|
||
}
|
||
@keyframes homePickerIn {
|
||
from { opacity: 0; transform: scale(.86) translateY(-6px); }
|
||
to { opacity: 1; transform: scale(1) translateY(0); }
|
||
}
|
||
.home-picker-close {
|
||
position: absolute;
|
||
top: 12px; right: 12px;
|
||
width: 28px; height: 28px;
|
||
border-radius: 14px;
|
||
background: rgba(0,0,0,.06);
|
||
display: flex; align-items: center; justify-content: center;
|
||
font-size: 13px; color: #4D4D4D;
|
||
cursor: pointer; font-weight: 700;
|
||
z-index: 2;
|
||
}
|
||
.home-picker-emoji {
|
||
width: 38px; height: 38px;
|
||
margin: 0 auto 6px;
|
||
border-radius: 12px;
|
||
background: linear-gradient(135deg, #FFE066 0%, #FFB300 100%);
|
||
box-shadow: 0 4px 10px rgba(255, 160, 0, .35), inset 0 1px 0 rgba(255,255,255,.6);
|
||
display: flex; align-items: center; justify-content: center;
|
||
font-size: 20px;
|
||
position: relative;
|
||
}
|
||
.home-picker-title {
|
||
font-size: 18px; font-weight: 900; color: #1a1a1a;
|
||
text-align: center; letter-spacing: .3px;
|
||
margin-bottom: 4px;
|
||
position: relative;
|
||
}
|
||
.home-picker-sub {
|
||
font-size: 12px; color: #4D4D4D;
|
||
text-align: center; margin-bottom: 18px;
|
||
line-height: 1.5; position: relative;
|
||
}
|
||
.home-picker-sub strong { color: #FF5722; font-weight: 800; }
|
||
.home-picker-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 8px;
|
||
position: relative;
|
||
}
|
||
.home-picker-item {
|
||
position: relative;
|
||
background: linear-gradient(180deg, #FFFFFF 0%, #FFFDF5 100%);
|
||
border: 1.5px solid #F2EBD8;
|
||
border-radius: 14px;
|
||
padding: 14px 6px 12px;
|
||
text-align: center;
|
||
cursor: pointer;
|
||
transition: transform .15s, border-color .15s, box-shadow .15s;
|
||
-webkit-tap-highlight-color: transparent;
|
||
box-shadow: 0 2px 6px rgba(120, 80, 20, .05);
|
||
}
|
||
.home-picker-item:active {
|
||
transform: scale(.94);
|
||
border-color: #FFD600;
|
||
box-shadow: 0 4px 14px rgba(255, 179, 0, .25);
|
||
}
|
||
.home-picker-item .home-picker-logo {
|
||
width: 46px; height: 46px;
|
||
border-radius: 12px;
|
||
margin: 0 auto 8px;
|
||
overflow: hidden;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,.08);
|
||
}
|
||
.home-picker-item .home-picker-logo img { width: 100%; height: 100%; object-fit: cover; }
|
||
.home-picker-item .home-picker-name {
|
||
font-size: 12px; font-weight: 700; color: #1a1a1a;
|
||
line-height: 1.2; letter-spacing: .2px;
|
||
}
|
||
/* 未安装态:置灰 + 黄色 ↓ 引导安装 chip */
|
||
.home-picker-item.uninstalled {
|
||
background: #FAFAFA;
|
||
border-color: #ECECEC;
|
||
box-shadow: none;
|
||
}
|
||
.home-picker-item.uninstalled .home-picker-logo {
|
||
box-shadow: 0 1px 3px rgba(0,0,0,.04);
|
||
}
|
||
.home-picker-item.uninstalled .home-picker-logo img {
|
||
filter: grayscale(.7);
|
||
opacity: .55;
|
||
}
|
||
.home-picker-item.uninstalled .home-picker-name { color: #BBB; }
|
||
.home-picker-install-chip {
|
||
position: absolute;
|
||
top: 6px; right: 6px;
|
||
width: 18px; height: 18px;
|
||
border-radius: 50%;
|
||
background: #FFD600;
|
||
box-shadow: 0 0 0 1.5px rgba(255,179,0,.35);
|
||
display: flex; align-items: center; justify-content: center;
|
||
}
|
||
|
||
/* 推荐信息流 */
|
||
#home .home-feed-wrap {
|
||
background: #fff;
|
||
border-radius: 14px 14px 0 0;
|
||
margin: 0;
|
||
padding-bottom: 0;
|
||
overflow: clip; /* 用 clip 而非 hidden:clip 只做视觉裁剪不创建 BFC,sticky 才能继续找到 .home-scroll 作为参考 */
|
||
}
|
||
#home .home-feed-head {
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
padding: 12px 16px 4px;
|
||
}
|
||
|
||
/* feed 排序 tab —— 文字 + 下划线(黑字全部一致,激活态加粗 + 黄下划线 + 略大字号)
|
||
左对齐:tab 全部贴左侧,gap 28px 分隔
|
||
方向:data-dir="desc|asc" 仅作内部状态,feed 卡片重排即反馈
|
||
交互:点 tab 时若 sort 已贴顶就不再 scrollIntoView,避免 0 距离平滑滚动造成的微位移 */
|
||
#home .feed-sort {
|
||
display: flex; align-items: center; justify-content: flex-start;
|
||
gap: 28px;
|
||
background: #fff;
|
||
padding: 14px 16px 12px;
|
||
position: sticky;
|
||
top: 38px; /* 紧贴 .brand-strip 底部(38px) */
|
||
z-index: 5;
|
||
}
|
||
#home .feed-sort .fs-item {
|
||
display: inline-flex; align-items: center;
|
||
cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
|
||
white-space: nowrap;
|
||
flex: 0 0 auto;
|
||
font-size: 14px; font-weight: 400;
|
||
color: #1A1A1A;
|
||
}
|
||
#home .feed-sort .fs-item .lbl { display: inline-block; position: relative; }
|
||
#home .feed-sort .fs-item.active { font-weight: 700; font-size: 15px; }
|
||
#home .feed-sort .fs-item.active .lbl::after {
|
||
content: ''; position: absolute;
|
||
left: 20%; right: 20%; bottom: -7px; /* 内缩 20%/20% = 下划线为文字宽度的 60%,居中 */
|
||
height: 3px; border-radius: 2px;
|
||
background: #FFD600;
|
||
}
|
||
|
||
/* 首页商品流多方案:用于 ?feedvariant=frame|tabs|combo|border|accent|cap|lift 对比 */
|
||
body.feed-v-frame #home .home-feed-wrap,
|
||
body.feed-v-combo #home .home-feed-wrap {
|
||
margin: 12px 10px 0;
|
||
border: 1px solid rgba(0,0,0,.10);
|
||
border-top-color: rgba(0,0,0,.14);
|
||
border-radius: 16px 16px 0 0;
|
||
box-shadow: 0 -1px 0 rgba(255,255,255,.85) inset, 0 5px 16px rgba(0,0,0,.05);
|
||
}
|
||
body.feed-v-frame #home .feed-sort,
|
||
body.feed-v-combo #home .feed-sort {
|
||
padding: 13px 14px 12px;
|
||
border-bottom: 1px solid rgba(0,0,0,.06);
|
||
}
|
||
body.feed-v-tabs #home .feed-sort,
|
||
body.feed-v-combo #home .feed-sort {
|
||
gap: 8px;
|
||
padding: 10px 12px;
|
||
background: #fff;
|
||
}
|
||
body.feed-v-tabs #home .feed-sort .fs-item,
|
||
body.feed-v-combo #home .feed-sort .fs-item {
|
||
height: 30px;
|
||
padding: 0 12px;
|
||
border-radius: 999px;
|
||
background: #F4F5F7;
|
||
color: #5F6368;
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
letter-spacing: .1px;
|
||
}
|
||
body.feed-v-tabs #home .feed-sort .fs-item.active,
|
||
body.feed-v-combo #home .feed-sort .fs-item.active {
|
||
background: linear-gradient(180deg, #FFE45C 0%, #FFD600 100%);
|
||
color: #1A1A1A;
|
||
font-size: 13px;
|
||
font-weight: 800;
|
||
box-shadow: inset 0 0 0 1px rgba(0,0,0,.06), 0 3px 8px rgba(255,214,0,.24);
|
||
}
|
||
body.feed-v-tabs #home .feed-sort .fs-item.active .lbl::after,
|
||
body.feed-v-combo #home .feed-sort .fs-item.active .lbl::after {
|
||
display: none;
|
||
}
|
||
body.feed-v-border #home .home-feed-wrap {
|
||
border: 1px solid rgba(0,0,0,.13);
|
||
border-top-width: 2px;
|
||
border-top-color: rgba(0,0,0,.20);
|
||
box-shadow: 0 -1px 0 rgba(255,255,255,.90) inset;
|
||
}
|
||
body.feed-v-accent #home .home-feed-wrap {
|
||
border-top: 3px solid #FFD600;
|
||
box-shadow: 0 -1px 0 rgba(255,255,255,.75) inset;
|
||
}
|
||
body.feed-v-cap #home .home-feed-wrap {
|
||
border: 1px solid rgba(255,193,7,.46);
|
||
border-top-color: rgba(255,179,0,.62);
|
||
background: #fff;
|
||
box-shadow: inset 0 1px 0 rgba(255,255,255,.92);
|
||
}
|
||
body.feed-v-cap #home .feed-sort {
|
||
background: linear-gradient(180deg, #FFF0A8 0%, #FFF8D8 58%, #fff 100%);
|
||
border-bottom: 0;
|
||
}
|
||
body.feed-v-lift #home .home-feed-wrap {
|
||
margin: 10px 8px 0;
|
||
border: 1px solid rgba(0,0,0,.12);
|
||
border-top-color: rgba(0,0,0,.20);
|
||
box-shadow: 0 -2px 0 rgba(255,255,255,.95), 0 -10px 22px rgba(0,0,0,.09);
|
||
}
|
||
#home .home-feed-title {
|
||
font-size: 17px; font-weight: 600; color: #1a1a1a; letter-spacing: -.2px;
|
||
display: inline-flex; align-items: center; gap: 4px;
|
||
}
|
||
#home .home-feed-title .feed-fire { font-size: 18px; line-height: 1; }
|
||
#home .feed-promo-tag {
|
||
background: linear-gradient(90deg, #FF5722, #FF8A4C);
|
||
color: #fff;
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
padding: 3px 8px;
|
||
border-radius: 8px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
letter-spacing: 0;
|
||
white-space: nowrap;
|
||
box-shadow: 0 1px 2px rgba(255,87,34,.22);
|
||
}
|
||
#home .feed-promo-tag .dot {
|
||
opacity: .8;
|
||
margin: 0 3px;
|
||
}
|
||
#home .home-feed {
|
||
display: flex; flex-direction: column;
|
||
padding: 0;
|
||
background: #fff;
|
||
}
|
||
#home .feed-card {
|
||
background: transparent;
|
||
border-radius: 0;
|
||
box-shadow: none;
|
||
cursor: pointer;
|
||
display: flex; flex-direction: row; align-items: stretch;
|
||
position: relative;
|
||
padding: 12px 16px;
|
||
}
|
||
#home .feed-card:active { background: #fafafa; }
|
||
#home .feed-img {
|
||
flex: 0 0 124px; width: 124px; height: 124px; aspect-ratio: 1/1;
|
||
border-radius: 10px;
|
||
overflow: hidden;
|
||
background: #fafafa;
|
||
position: relative;
|
||
}
|
||
#home .feed-img img {
|
||
width: 100%; height: 100%;
|
||
object-fit: cover;
|
||
display: block;
|
||
}
|
||
/* 品类徽章:左下角,外卖黄 #FFC300 / 团购橙 #FF5722 */
|
||
#home .feed-cat-badge {
|
||
position: absolute;
|
||
left: 5px; bottom: 5px;
|
||
padding: 1px 5px 2px;
|
||
border-radius: 3px;
|
||
font-size: 9px; font-weight: 700;
|
||
line-height: 1.3;
|
||
letter-spacing: .2px;
|
||
box-shadow: 0 1px 2px rgba(0,0,0,.18);
|
||
}
|
||
#home .feed-cat-badge.cat-waimai { background: #FFC300; color: #1A1A1A; }
|
||
#home .feed-cat-badge.cat-tuangou { background: #FF5722; color: #fff; }
|
||
#home .feed-body {
|
||
flex: 1; min-width: 0;
|
||
padding: 0 0 0 12px;
|
||
display: flex; flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
#home .feed-title {
|
||
font-size: 13px; font-weight: 500; color: #1a1a1a; line-height: 1.35;
|
||
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
padding-right: 4px;
|
||
}
|
||
#home .feed-title .shop-name { color: #FF5722; font-weight: 600; }
|
||
#home .feed-title .title-sep { color: #CCCCCC; margin: 0 2px; font-weight: 400; }
|
||
#home .feed-meta {
|
||
display: flex; align-items: center; gap: 8px;
|
||
font-size: 11px; color: #999;
|
||
padding-right: 0;
|
||
}
|
||
#home .feed-meta .meta-left {
|
||
color: #999; font-weight: 400;
|
||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||
flex: 1 1 auto; min-width: 0;
|
||
}
|
||
#home .feed-meta .meta-right {
|
||
color: #999; font-weight: 400;
|
||
white-space: nowrap; flex-shrink: 0;
|
||
}
|
||
#home .feed-pricerow {
|
||
display: flex; align-items: baseline; gap: 4px;
|
||
margin-top: auto;
|
||
padding-right: 60px;
|
||
}
|
||
/* Price Golden Ratio: 整数 22 → ¥ 15 (×0.7), dec 12 (×0.55) + tabular-nums */
|
||
#home .feed-price {
|
||
display: inline-flex; align-items: baseline; gap: 0;
|
||
color: #FF5722; font-weight: 600;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
#home .feed-price .yuan { font-size: 18px; font-weight: 600; margin-right: 2px; }
|
||
#home .feed-price .num { font-size: 26px; letter-spacing: -.3px; line-height: 1; font-weight: 600; }
|
||
#home .feed-price .num small { font-size: 14px; font-weight: 600; }
|
||
#home .feed-original {
|
||
font-size: 12px; color: #B0B0B0; text-decoration: line-through;
|
||
font-weight: 400;
|
||
}
|
||
#home .feed-tag {
|
||
font-size: 11px;
|
||
font-weight: 400;
|
||
line-height: 1.4;
|
||
color: #FF6B3D;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
padding-right: 60px;
|
||
}
|
||
#home .feed-grab {
|
||
position: absolute; right: 16px; bottom: 12px;
|
||
background: linear-gradient(135deg,#FFE066,#FFD600); color: #1A1A1A;
|
||
font-size: 15px; font-weight: 800;
|
||
width: 46px; height: 46px;
|
||
border-radius: 16px 16px 16px 4px;
|
||
display: flex; align-items: center; justify-content: center;
|
||
box-shadow: inset 0 1px 0 rgba(255,255,255,.7);
|
||
letter-spacing: 1px;
|
||
z-index: 2;
|
||
}
|
||
|
||
/* feed 末尾「已经到底了」—— 12px/400 #999,左右各一条 24×0.5px 浅灰短线 */
|
||
#home .feed-end {
|
||
display: flex; align-items: center; justify-content: center;
|
||
gap: 12px;
|
||
padding: 24px 16px 20px;
|
||
font-size: 12px; font-weight: 400;
|
||
color: #999;
|
||
letter-spacing: 1px;
|
||
}
|
||
#home .feed-end::before,
|
||
#home .feed-end::after {
|
||
content: '';
|
||
width: 24px; height: 0.5px;
|
||
background: #E5E5E5;
|
||
}
|
||
|
||
/* ===== R8 福利页设计规范(仅作用在 .scheme-r8 节点内) ===== */
|
||
.scheme-r8 {
|
||
--r8-yellow: #FFD600;
|
||
--r8-yellow-deep: #FFC107;
|
||
--r8-orange: #FF6A1A;
|
||
--r8-green: #21C45A;
|
||
--r8-bg: #FBFAF6;
|
||
--r8-card: #FFFFFF;
|
||
--r8-divider: #EEE8D7;
|
||
--r8-aux: #8A8A8A;
|
||
--r8-text: #1F1F1F;
|
||
background: var(--r8-bg) !important;
|
||
padding: 0 12px 16px !important;
|
||
}
|
||
.r8-status-bar {
|
||
height: 40px;
|
||
padding: 12px 8px 0;
|
||
display: flex;
|
||
align-items: flex-start;
|
||
justify-content: space-between;
|
||
color: #1A1A1A;
|
||
font-size: 14px;
|
||
font-weight: 700;
|
||
letter-spacing: 0;
|
||
}
|
||
.r8-status-icons {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
height: 18px;
|
||
}
|
||
.r8-signal {
|
||
display: inline-flex;
|
||
align-items: flex-end;
|
||
gap: 2px;
|
||
height: 13px;
|
||
}
|
||
.r8-signal span {
|
||
width: 3px;
|
||
border-radius: 4px;
|
||
background: #1A1A1A;
|
||
}
|
||
.r8-signal span:nth-child(1) { height: 5px; }
|
||
.r8-signal span:nth-child(2) { height: 8px; }
|
||
.r8-signal span:nth-child(3) { height: 11px; }
|
||
.r8-signal span:nth-child(4) { height: 13px; }
|
||
.r8-wifi {
|
||
position: relative;
|
||
width: 16px;
|
||
height: 12px;
|
||
}
|
||
.r8-wifi::before,
|
||
.r8-wifi::after {
|
||
content: "";
|
||
position: absolute;
|
||
left: 50%;
|
||
border: 2px solid #1A1A1A;
|
||
border-left-color: transparent;
|
||
border-right-color: transparent;
|
||
border-bottom: none;
|
||
transform: translateX(-50%);
|
||
}
|
||
.r8-wifi::before {
|
||
top: 0;
|
||
width: 16px;
|
||
height: 9px;
|
||
border-radius: 14px 14px 0 0;
|
||
}
|
||
.r8-wifi::after {
|
||
top: 5px;
|
||
width: 9px;
|
||
height: 5px;
|
||
border-radius: 8px 8px 0 0;
|
||
}
|
||
.r8-wifi span {
|
||
position: absolute;
|
||
left: 50%;
|
||
bottom: 0;
|
||
width: 3px;
|
||
height: 3px;
|
||
transform: translateX(-50%);
|
||
border-radius: 50%;
|
||
background: #1A1A1A;
|
||
}
|
||
.r8-battery {
|
||
position: relative;
|
||
width: 24px;
|
||
height: 12px;
|
||
border: 1.8px solid #1A1A1A;
|
||
border-radius: 4px;
|
||
}
|
||
.r8-battery::before {
|
||
content: "";
|
||
position: absolute;
|
||
right: -4px;
|
||
top: 3px;
|
||
width: 2px;
|
||
height: 5px;
|
||
border-radius: 0 4px 4px 0;
|
||
background: #1A1A1A;
|
||
}
|
||
.r8-battery::after {
|
||
content: "";
|
||
position: absolute;
|
||
left: 2px;
|
||
top: 2px;
|
||
width: 17px;
|
||
height: 6px;
|
||
border-radius: 4px;
|
||
background: #1A1A1A;
|
||
}
|
||
.r8-page-header {
|
||
height: 50px;
|
||
padding: 4px 0 8px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
.r8-page-title {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 8px;
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
.r8-page-title strong {
|
||
font-size: 24px;
|
||
line-height: 1;
|
||
font-weight: 900;
|
||
color: #1A1A1A;
|
||
letter-spacing: 0;
|
||
flex-shrink: 0;
|
||
white-space: nowrap;
|
||
}
|
||
.r8-page-title .sub {
|
||
font-size: 11px;
|
||
line-height: 1;
|
||
color: #666666;
|
||
font-weight: 500;
|
||
white-space: nowrap;
|
||
flex-shrink: 0;
|
||
}
|
||
.r8-page-title .star {
|
||
color: var(--r8-yellow);
|
||
font-size: 12px;
|
||
font-weight: 900;
|
||
transform: translateY(-10px);
|
||
flex-shrink: 0;
|
||
}
|
||
.r8-reward-btn {
|
||
height: 32px;
|
||
padding: 0 8px 0 8px;
|
||
border: none;
|
||
border-radius: 18px;
|
||
background: rgba(255,255,255,.92);
|
||
color: #1A1A1A;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
box-shadow: 0 5px 14px rgba(173,128,18,.12);
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
margin-left: 8px;
|
||
}
|
||
.r8-reward-btn svg {
|
||
width: 18px;
|
||
height: 18px;
|
||
flex-shrink: 0;
|
||
}
|
||
.r8-asset-card {
|
||
position: relative;
|
||
border-radius: 18px;
|
||
background: radial-gradient(ellipse 125% 86% at 4% 8%, rgba(255,255,255,.98) 0%, rgba(255,255,255,.56) 38%, rgba(255,255,255,0) 68%),
|
||
linear-gradient(155deg, #FFF5BF 0%, #FFE982 46%, #FFF9E4 100%);
|
||
min-height: 132px;
|
||
padding: 12px 16px 8px;
|
||
overflow: hidden;
|
||
border: 1px solid rgba(255,255,255,.78);
|
||
box-shadow: 0 8px 22px rgba(185,137,18,.10), inset 0 1px 0 rgba(255,255,255,.9);
|
||
}
|
||
.r8-asset-illustration {
|
||
position: absolute;
|
||
right: 6px; bottom: 17px;
|
||
width: 96px;
|
||
z-index: 2;
|
||
pointer-events: none; user-select: none;
|
||
}
|
||
.r8-corner-cut {
|
||
position: absolute; right: 0; top: 0;
|
||
width: 148px; height: 70px;
|
||
z-index: 1; pointer-events: none;
|
||
}
|
||
.r8-stars {
|
||
position: absolute; right: 98px; top: 42px;
|
||
width: 106px; height: 50px;
|
||
z-index: 1; pointer-events: none;
|
||
}
|
||
.r8-asset-header {
|
||
display: flex; align-items: baseline; gap: 8px;
|
||
position: relative; z-index: 3;
|
||
}
|
||
.r8-asset-title {
|
||
font-size: 18px; font-weight: 900; color: var(--r8-text);
|
||
letter-spacing: 0;
|
||
line-height: 1.08;
|
||
}
|
||
.r8-asset-withdraw {
|
||
font-size: 12px; color: #8B6914;
|
||
font-weight: 800; cursor: pointer;
|
||
}
|
||
.r8-asset-grid {
|
||
display: flex; align-items: flex-start; gap: 8px; margin-top: 16px;
|
||
position: relative; z-index: 3;
|
||
}
|
||
.r8-asset-col {
|
||
display: flex; flex-direction: column; gap: 6px;
|
||
flex: 0 1 auto; cursor: pointer;
|
||
}
|
||
.r8-asset-col:first-child {
|
||
width: 110px;
|
||
}
|
||
.r8-asset-col + .r8-asset-col {
|
||
min-width: 94px;
|
||
padding-left: 6px;
|
||
border-left: none;
|
||
}
|
||
.r8-asset-label-row {
|
||
display: flex; align-items: center; gap: 4px;
|
||
white-space: nowrap;
|
||
transform: translateX(-1px);
|
||
}
|
||
.r8-asset-coin-icon, .r8-asset-cash-icon-svg {
|
||
width: 17px; height: 17px; flex-shrink: 0; object-fit: contain;
|
||
margin-left: -3px;
|
||
}
|
||
.r8-asset-coin-label, .r8-asset-cash-label {
|
||
font-size: 13px; color: var(--r8-text); font-weight: 800;
|
||
display: inline-flex; align-items: center; gap: 2px;
|
||
}
|
||
.r8-asset-arrow {
|
||
font-size: 11px; color: #999999; font-weight: 600;
|
||
margin-left: 2px;
|
||
}
|
||
.r8-asset-coin-val, .r8-asset-cash-val {
|
||
font-size: 22px; font-weight: 800; color: #1A1A1A;
|
||
line-height: 1; letter-spacing: -.2px;
|
||
white-space: nowrap;
|
||
}
|
||
.r8-asset-coin-val, .r8-asset-cash-val {
|
||
color: var(--r8-orange);
|
||
}
|
||
.r8-asset-cash-val .unit {
|
||
font-size: 11px; font-weight: 800; margin-left: 2px;
|
||
}
|
||
.r8-asset-tip {
|
||
font-size: 10px; color: #999999;
|
||
margin-top: 12px;
|
||
position: relative; z-index: 3;
|
||
display: flex; align-items: center; gap: 4px;
|
||
line-height: 1.25;
|
||
white-space: nowrap;
|
||
}
|
||
.r8-info-icon {
|
||
width: 12px; height: 12px; border-radius: 50%;
|
||
background: rgba(138,138,138,.25); color: var(--r8-aux);
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
font-size: 10px; font-weight: 700; font-style: italic;
|
||
flex-shrink: 0;
|
||
}
|
||
.r8-checkin-card {
|
||
margin-top: 12px;
|
||
min-height: 58px;
|
||
background: linear-gradient(90deg, #FFE0B2 0%, #FFE066 100%);
|
||
border-radius: 18px;
|
||
padding: 6px 12px 6px 16px;
|
||
display: flex; align-items: center; gap: 8px;
|
||
box-shadow: 0 8px 18px rgba(185,137,18,.08);
|
||
cursor: pointer;
|
||
}
|
||
.r8-checkin-calendar {
|
||
width: 44px; height: 44px;
|
||
flex-shrink: 0; object-fit: contain;
|
||
}
|
||
.r8-checkin-text { flex: 1; min-width: 0; }
|
||
.r8-checkin-headline {
|
||
font-size: 16px; font-weight: 900; color: var(--r8-text);
|
||
display: flex; align-items: baseline; gap: 2px;
|
||
white-space: nowrap;
|
||
line-height: 1.08;
|
||
}
|
||
.r8-checkin-headline .num {
|
||
font-size: 22px; font-weight: 900; color: #FF5722;
|
||
margin: 0 4px;
|
||
}
|
||
.r8-checkin-sub {
|
||
font-size: 11px; color: #999999;
|
||
margin-top: 2px;
|
||
font-weight: 600;
|
||
white-space: nowrap;
|
||
display: none;
|
||
}
|
||
.r8-checkin-cta {
|
||
height: 32px;
|
||
background: #FFFFFF; border-radius: 32px;
|
||
padding: 0 12px 0 8px;
|
||
font-size: 12px; font-weight: 800; color: var(--r8-text);
|
||
border: none; cursor: pointer;
|
||
display: inline-flex; align-items: center; gap: 4px;
|
||
flex-shrink: 0; white-space: nowrap;
|
||
box-shadow: 0 4px 12px rgba(185,137,18,.08);
|
||
}
|
||
.r8-checkin-cta .check-tick {
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
width: 16px; height: 16px; border-radius: 4px;
|
||
background: var(--r8-green); color: #fff;
|
||
font-size: 11px; font-weight: 900;
|
||
}
|
||
.r8-section-title {
|
||
font-size: 17px; font-weight: 800; color: var(--r8-text);
|
||
margin: 0 0 8px;
|
||
}
|
||
.r8-task-card {
|
||
background: var(--r8-card);
|
||
border-radius: 14px;
|
||
padding: 12px 16px 12px;
|
||
box-shadow: 0 4px 12px rgba(0,0,0,0.04);
|
||
margin-top: 16px;
|
||
}
|
||
.r8-task-row {
|
||
display: flex; align-items: center; padding: 0;
|
||
border-bottom: none;
|
||
margin-top: 12px;
|
||
}
|
||
.r8-task-row:first-of-type { margin-top: 0; }
|
||
.r8-task-icon {
|
||
display: none;
|
||
}
|
||
.r8-task-info { flex: 1; min-width: 0; }
|
||
.r8-task-titlerow {
|
||
display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
|
||
}
|
||
.r8-task-title {
|
||
font-size: 15px; font-weight: 800; color: var(--r8-text);
|
||
}
|
||
.r8-task-coin {
|
||
display: inline-flex; align-items: center; gap: 0;
|
||
font-size: 12px; font-weight: 700; color: var(--r8-orange);
|
||
}
|
||
.r8-task-coin .ci {
|
||
width: 18px; height: 18px; flex-shrink: 0;
|
||
margin-right: -2px;
|
||
transform: scale(1.12);
|
||
transform-origin: center;
|
||
}
|
||
.r8-task-sub {
|
||
font-size: 12px; color: var(--r8-aux); margin-top: 2px; font-weight: 500;
|
||
}
|
||
.r8-task-cta {
|
||
background: var(--r8-yellow); color: var(--r8-text);
|
||
border: none; border-radius: 32px;
|
||
padding: 6px 12px;
|
||
font-size: 12px; font-weight: 800;
|
||
cursor: pointer; flex-shrink: 0;
|
||
}
|
||
.r8-checkin-task-row {
|
||
display: block;
|
||
margin-top: 8px;
|
||
padding: 2px 0 16px;
|
||
border-bottom: 1px solid #F0F0F0;
|
||
cursor: pointer;
|
||
transition: margin .18s ease;
|
||
}
|
||
.r8-checkin-task-main {
|
||
min-width: 0;
|
||
}
|
||
.r8-checkin-task-head {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 8px;
|
||
}
|
||
.r8-checkin-task-copy {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
.r8-checkin-task-title {
|
||
color: var(--r8-text);
|
||
font-size: 15px;
|
||
line-height: 1.18;
|
||
font-weight: 800;
|
||
white-space: nowrap;
|
||
}
|
||
.r8-checkin-task-sub {
|
||
margin-top: 2px;
|
||
color: var(--r8-aux);
|
||
font-size: 12px;
|
||
line-height: 1.25;
|
||
font-weight: 500;
|
||
white-space: nowrap;
|
||
}
|
||
.r8-checkin-task-cta {
|
||
flex: 0 0 auto;
|
||
min-width: 54px;
|
||
height: auto;
|
||
border: none;
|
||
border-radius: 999px;
|
||
background: var(--r8-yellow);
|
||
color: var(--r8-text);
|
||
font-family: inherit;
|
||
padding: 6px 12px;
|
||
font-size: 12px;
|
||
font-weight: 800;
|
||
box-shadow: none;
|
||
cursor: pointer;
|
||
}
|
||
.r8-checkin-timeline {
|
||
position: relative;
|
||
display: grid;
|
||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||
column-gap: 2px;
|
||
margin-top: 16px;
|
||
}
|
||
.r8-checkin-timeline::before {
|
||
content: '';
|
||
position: absolute;
|
||
left: 20px;
|
||
right: 20px;
|
||
top: 32px;
|
||
height: 2px;
|
||
border-radius: 32px;
|
||
background: #E5E5E5;
|
||
}
|
||
.r8-checkin-step {
|
||
position: relative;
|
||
z-index: 1;
|
||
min-width: 0;
|
||
display: grid;
|
||
grid-template-rows: 18px 22px 15px;
|
||
justify-items: center;
|
||
align-items: center;
|
||
row-gap: 2px;
|
||
}
|
||
.r8-checkin-step-label {
|
||
min-height: 18px;
|
||
color: #999999;
|
||
font-size: 11px;
|
||
line-height: 18px;
|
||
font-weight: 650;
|
||
white-space: nowrap;
|
||
}
|
||
.r8-checkin-step-badge {
|
||
padding: 0 8px;
|
||
border-radius: 999px;
|
||
background: #fff;
|
||
color: #FFA000;
|
||
font-size: 11px;
|
||
line-height: 18px;
|
||
font-weight: 900;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,.08);
|
||
white-space: nowrap;
|
||
}
|
||
.r8-checkin-step-icon {
|
||
box-sizing: border-box;
|
||
width: 22px;
|
||
height: 22px;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.r8-checkin-step-icon img {
|
||
display: block;
|
||
width: 22px;
|
||
height: 22px;
|
||
object-fit: contain;
|
||
}
|
||
.r8-checkin-step.done .r8-checkin-step-icon {
|
||
background: #FFF3E0;
|
||
border: 1px solid #FFE066;
|
||
box-shadow: inset 0 1px 0 rgba(255,255,255,.72);
|
||
}
|
||
.r8-checkin-step.done .r8-checkin-step-icon img {
|
||
display: none;
|
||
}
|
||
.r8-checkin-step.done .r8-checkin-step-icon::before {
|
||
content: '✓';
|
||
color: #FFA000;
|
||
font-size: 13px;
|
||
line-height: 1;
|
||
font-weight: 900;
|
||
}
|
||
.r8-checkin-step.just-done .r8-checkin-step-icon {
|
||
animation: r8CheckDonePop .38s cubic-bezier(.22, 1.4, .36, 1);
|
||
}
|
||
.r8-checkin-step.current .r8-checkin-step-icon {
|
||
animation: r8CheckCoinPulse .42s ease-out;
|
||
}
|
||
@keyframes r8CheckDonePop {
|
||
0% { transform: scale(.68); opacity: .55; }
|
||
64% { transform: scale(1.12); opacity: 1; }
|
||
100% { transform: scale(1); opacity: 1; }
|
||
}
|
||
@keyframes r8CheckCoinPulse {
|
||
0% { transform: scale(.86); }
|
||
64% { transform: scale(1.1); }
|
||
100% { transform: scale(1); }
|
||
}
|
||
.r8-checkin-step.most .r8-checkin-step-icon img {
|
||
width: 22px;
|
||
height: 22px;
|
||
}
|
||
.r8-checkin-step-amount {
|
||
color: #999999;
|
||
font-size: 11px;
|
||
line-height: 1;
|
||
font-weight: 650;
|
||
font-variant-numeric: tabular-nums;
|
||
white-space: nowrap;
|
||
}
|
||
.r8-badge-update {
|
||
background: rgba(255,106,26,0.10); color: var(--r8-orange);
|
||
border: 1px solid rgba(255,106,26,0.35);
|
||
font-size: 10px; padding: 2px 4px; border-radius: 4px; font-weight: 700;
|
||
}
|
||
.r8-rule-entry {
|
||
margin: 16px auto 8px;
|
||
border: none;
|
||
background: transparent;
|
||
color: #999999;
|
||
font-family: inherit;
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
line-height: 18px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 2px;
|
||
cursor: pointer;
|
||
}
|
||
.r8-rule-entry span {
|
||
font-size: 13px;
|
||
transform: translateY(-.5px);
|
||
}
|
||
.welfare-rules-screen {
|
||
background: #FAFAFA !important;
|
||
color: #1A1A1A;
|
||
}
|
||
.welfare-rules-body {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
padding: 12px 16px 24px;
|
||
}
|
||
.welfare-rules-card {
|
||
background: #fff;
|
||
border-radius: 14px;
|
||
padding: 16px 16px 16px;
|
||
box-shadow: 0 4px 14px rgba(0,0,0,.04);
|
||
}
|
||
.welfare-rules-title {
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
color: #1A1A1A;
|
||
margin-bottom: 12px;
|
||
}
|
||
.welfare-rules-list {
|
||
display: grid;
|
||
gap: 12px;
|
||
}
|
||
.welfare-rules-item {
|
||
display: grid;
|
||
grid-template-columns: 20px 1fr;
|
||
gap: 8px;
|
||
align-items: start;
|
||
}
|
||
.welfare-rules-index {
|
||
width: 20px;
|
||
height: 20px;
|
||
border-radius: 50%;
|
||
background: #FFF3C4;
|
||
color: #8B6914;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
}
|
||
.welfare-rules-text {
|
||
font-size: 13px;
|
||
line-height: 20px;
|
||
font-weight: 400;
|
||
color: #666666;
|
||
}
|
||
.welfare-rules-text strong {
|
||
display: block;
|
||
margin-bottom: 2px;
|
||
font-size: 14px;
|
||
line-height: 20px;
|
||
font-weight: 700;
|
||
color: #1A1A1A;
|
||
}
|
||
.r8-record-task-block {
|
||
margin-top: 12px;
|
||
}
|
||
.r8-record-task-row {
|
||
margin-top: 0;
|
||
}
|
||
.r8-record-rewards {
|
||
position: relative;
|
||
margin-top: 8px;
|
||
display: grid;
|
||
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||
gap: 2px;
|
||
}
|
||
.r8-record-milestone {
|
||
position: relative;
|
||
z-index: 1;
|
||
min-width: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
.r8-record-reward-box {
|
||
-webkit-appearance: none;
|
||
appearance: none;
|
||
width: 42px;
|
||
height: 50px;
|
||
border-radius: 8px;
|
||
background: #F0F0F0;
|
||
border: none;
|
||
font-family: inherit;
|
||
box-shadow: inset 0 1px 0 rgba(255,255,255,.75);
|
||
display: grid;
|
||
grid-template-rows: 10px 18px 13px;
|
||
align-content: center;
|
||
justify-items: center;
|
||
row-gap: 2px;
|
||
padding: 2px 2px;
|
||
position: relative;
|
||
transition: transform .12s ease, box-shadow .12s ease, background .12s ease;
|
||
}
|
||
button.r8-record-reward-box {
|
||
cursor: pointer;
|
||
-webkit-tap-highlight-color: transparent;
|
||
}
|
||
button.r8-record-reward-box:active {
|
||
transform: translateY(1px);
|
||
}
|
||
button.r8-record-reward-box:focus-visible {
|
||
outline: 2px solid rgba(255, 184, 0, .5);
|
||
outline-offset: 2px;
|
||
}
|
||
button.r8-record-reward-box.done,
|
||
button.r8-record-reward-box:disabled {
|
||
cursor: default;
|
||
pointer-events: none;
|
||
}
|
||
.r8-record-reward-box.done {
|
||
background: #FAFAFA;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
row-gap: 2px;
|
||
}
|
||
.r8-record-reward-box.active {
|
||
background: #FFF3E0;
|
||
box-shadow: inset 0 0 0 1px #FFD979;
|
||
}
|
||
.r8-record-status {
|
||
position: static;
|
||
text-align: center;
|
||
font-size: 10px;
|
||
line-height: 1;
|
||
font-weight: 800;
|
||
color: var(--r8-orange);
|
||
white-space: nowrap;
|
||
}
|
||
.r8-record-reward-box.done .r8-record-status {
|
||
font-size: 10px;
|
||
color: #999999;
|
||
}
|
||
.r8-record-reward-box.active .r8-record-status {
|
||
color: #FFA000;
|
||
}
|
||
.r8-record-reward-box.locked .r8-record-status {
|
||
color: #999999;
|
||
}
|
||
.r8-record-coin {
|
||
width: 18px;
|
||
height: 18px;
|
||
object-fit: contain;
|
||
flex-shrink: 0;
|
||
transform: scale(1.12);
|
||
transform-origin: center;
|
||
}
|
||
.r8-record-num {
|
||
font-size: 12px;
|
||
line-height: 1;
|
||
font-weight: 800;
|
||
color: var(--r8-orange);
|
||
letter-spacing: 0;
|
||
white-space: nowrap;
|
||
}
|
||
.r8-record-reward-box.done .r8-record-num {
|
||
font-size: 10px;
|
||
color: #999999;
|
||
font-weight: 750;
|
||
}
|
||
.r8-record-reward-box.active .r8-record-num {
|
||
font-size: 13px;
|
||
color: var(--r8-orange);
|
||
}
|
||
.r8-record-label {
|
||
margin-top: 4px;
|
||
font-size: 10px;
|
||
line-height: 1;
|
||
font-weight: 750;
|
||
color: #666666;
|
||
white-space: nowrap;
|
||
}
|
||
.r8-task-cta.is-done {
|
||
background: #F0F0F0;
|
||
color: #999999;
|
||
cursor: default;
|
||
}
|
||
@keyframes rewardToastIn {
|
||
0% { opacity: 0; transform: translate(-50%, -48%) scale(.86); }
|
||
68% { opacity: 1; transform: translate(-50%, -50%) scale(1.04); }
|
||
100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
|
||
}
|
||
@keyframes rewardToastOut {
|
||
from { opacity: 1; transform: translate(-50%, -50%) scale(1); }
|
||
to { opacity: 0; transform: translate(-50%, -54%) scale(.96); }
|
||
}
|
||
.reward-toast {
|
||
position: absolute;
|
||
left: 50%;
|
||
top: 48%;
|
||
width: 176px;
|
||
min-height: 164px;
|
||
border-radius: 18px;
|
||
background: rgba(56, 56, 68, .98);
|
||
box-shadow: 0 18px 42px rgba(0,0,0,.24);
|
||
z-index: 10020;
|
||
pointer-events: none;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 16px 12px 16px;
|
||
color: #FFFFFF;
|
||
text-align: center;
|
||
animation: rewardToastIn .26s cubic-bezier(.18, .9, .25, 1.15) both;
|
||
}
|
||
.reward-toast.is-leaving {
|
||
animation: rewardToastOut .22s ease both;
|
||
}
|
||
.reward-toast-icon {
|
||
width: 72px;
|
||
height: 54px;
|
||
object-fit: contain;
|
||
display: block;
|
||
margin-bottom: 8px;
|
||
filter: drop-shadow(0 7px 10px rgba(255, 169, 27, .18));
|
||
}
|
||
.reward-toast-amount {
|
||
font-size: 28px;
|
||
line-height: 1;
|
||
font-weight: 900;
|
||
letter-spacing: 0;
|
||
color: #FFFFFF;
|
||
}
|
||
.reward-toast-title {
|
||
margin-top: 16px;
|
||
font-size: 20px;
|
||
line-height: 1;
|
||
font-weight: 700;
|
||
color: rgba(255,255,255,.9);
|
||
white-space: nowrap;
|
||
}
|
||
/* ===== 收益明细 / 提现 ===== */
|
||
.income-nav {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 40px 16px 16px;
|
||
background: #fff;
|
||
flex-shrink: 0;
|
||
}
|
||
.income-nav-title {
|
||
position: absolute;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
font-size: 18px;
|
||
font-weight: 500;
|
||
color: var(--gray-900);
|
||
letter-spacing: 0;
|
||
}
|
||
.income-nav-back,
|
||
.income-nav-link {
|
||
position: relative;
|
||
z-index: 1;
|
||
border: none;
|
||
background: none;
|
||
cursor: pointer;
|
||
font-family: inherit;
|
||
}
|
||
.income-nav-back {
|
||
width: 44px;
|
||
min-width: 44px;
|
||
height: 32px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: flex-start;
|
||
padding: 0;
|
||
text-align: left;
|
||
font-size: 24px;
|
||
line-height: 1;
|
||
font-weight: 400;
|
||
color: var(--gray-800);
|
||
}
|
||
.income-nav-link {
|
||
min-width: 72px;
|
||
text-align: right;
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
color: var(--gray-500);
|
||
}
|
||
.income-rate {
|
||
padding: 0 16px 8px;
|
||
font-size: 12px;
|
||
line-height: 18px;
|
||
font-weight: 400;
|
||
color: var(--gray-500);
|
||
flex-shrink: 0;
|
||
}
|
||
.income-summary-card {
|
||
margin: 0 16px 16px;
|
||
padding: 24px 16px;
|
||
border-radius: 18px;
|
||
background: linear-gradient(135deg, #FFF3E0 0%, #FFFDE7 100%);
|
||
flex-shrink: 0;
|
||
}
|
||
.income-summary-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 24px;
|
||
}
|
||
.income-summary-label {
|
||
font-size: 13px;
|
||
font-weight: 400;
|
||
color: var(--gray-600);
|
||
margin-bottom: 6px;
|
||
}
|
||
.income-summary-value {
|
||
font-size: 28px;
|
||
line-height: 1;
|
||
font-weight: 700;
|
||
color: #FF5722;
|
||
letter-spacing: .2px;
|
||
}
|
||
.income-chip-btn {
|
||
margin-top: 8px;
|
||
height: 28px;
|
||
padding: 0 12px;
|
||
border-radius: 999px;
|
||
border: 1.5px solid #FF5722;
|
||
background: transparent;
|
||
color: #FF5722;
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
font-family: inherit;
|
||
}
|
||
.income-chip-btn.filled {
|
||
background: #FF5722;
|
||
color: #fff;
|
||
}
|
||
.income-tabs {
|
||
position: relative;
|
||
display: flex;
|
||
padding: 0 16px;
|
||
border-bottom: 2px solid var(--gray-200);
|
||
flex-shrink: 0;
|
||
}
|
||
.income-tab {
|
||
flex: 1;
|
||
border: none;
|
||
background: none;
|
||
padding: 16px 0 12px;
|
||
text-align: center;
|
||
font-family: inherit;
|
||
font-size: 15px;
|
||
font-weight: 400;
|
||
color: var(--gray-500);
|
||
cursor: pointer;
|
||
}
|
||
.income-tab.active {
|
||
color: #000;
|
||
font-weight: 400;
|
||
}
|
||
.income-tab-indicator {
|
||
position: absolute;
|
||
left: 16px;
|
||
bottom: -2px;
|
||
width: calc((100% - 32px) / 2);
|
||
height: 2px;
|
||
background: #1a1a1a;
|
||
transition: transform .24s ease;
|
||
}
|
||
.income-tabs[data-active="cash"] .income-tab-indicator {
|
||
transform: translateX(100%);
|
||
}
|
||
.income-record-shell {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
background: #fff;
|
||
touch-action: pan-y;
|
||
user-select: none;
|
||
-webkit-user-select: none;
|
||
}
|
||
.income-record-track {
|
||
height: 100%;
|
||
display: flex;
|
||
width: 200%;
|
||
transition: transform .24s ease;
|
||
}
|
||
.income-record-track.cash-active {
|
||
transform: translateX(-50%);
|
||
}
|
||
.income-record-panel {
|
||
width: 50%;
|
||
min-width: 50%;
|
||
overflow-y: auto;
|
||
-webkit-overflow-scrolling: touch;
|
||
padding: 0 16px 16px;
|
||
}
|
||
.income-record-row {
|
||
min-height: 72px;
|
||
display: flex;
|
||
align-items: center;
|
||
border-bottom: .5px solid var(--gray-100);
|
||
}
|
||
.income-record-main {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
.income-record-title {
|
||
font-size: 15px;
|
||
font-weight: 400;
|
||
color: #1A1A1A;
|
||
line-height: 1.3;
|
||
}
|
||
.income-record-date {
|
||
margin-top: 4px;
|
||
font-size: 13px;
|
||
font-weight: 400;
|
||
color: var(--gray-400);
|
||
}
|
||
.income-record-amount {
|
||
margin-left: 8px;
|
||
font-size: 16px;
|
||
font-weight: 400;
|
||
color: #FF5722;
|
||
white-space: nowrap;
|
||
}
|
||
.income-record-amount.cash {
|
||
color: #FE2C55;
|
||
}
|
||
.income-footer {
|
||
padding: 12px 16px 24px;
|
||
border-top: .5px solid var(--gray-200);
|
||
text-align: center;
|
||
flex-shrink: 0;
|
||
background: #fff;
|
||
}
|
||
.income-footer-note {
|
||
margin-bottom: 8px;
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
color: var(--gray-500);
|
||
}
|
||
.income-footer-note strong {
|
||
color: #FF5722;
|
||
font-weight: 500;
|
||
}
|
||
.income-footer .btn {
|
||
font-weight: 400;
|
||
}
|
||
.withdraw-screen {
|
||
background: #fff !important;
|
||
color: var(--gray-900);
|
||
}
|
||
#withdrawal .income-nav-title {
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
}
|
||
#withdrawal .income-nav {
|
||
background: transparent;
|
||
}
|
||
#withdrawal .income-nav-back {
|
||
font-size: 22px;
|
||
font-weight: 400;
|
||
}
|
||
.withdraw-nav-links {
|
||
min-width: 104px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
gap: 6px;
|
||
font-size: 12px;
|
||
font-weight: 400;
|
||
color: var(--gray-700);
|
||
}
|
||
.withdraw-nav-links button {
|
||
border: none;
|
||
background: none;
|
||
padding: 0;
|
||
font: inherit;
|
||
color: inherit;
|
||
cursor: pointer;
|
||
}
|
||
.withdraw-nav-sep {
|
||
width: 1px;
|
||
height: 12px;
|
||
background: var(--gray-300);
|
||
}
|
||
.withdraw-top {
|
||
flex-shrink: 0;
|
||
background: linear-gradient(126deg, #FFF3C4 0%, #FFFFFF 52%, #E8F5E9 100%);
|
||
border-bottom: .5px solid rgba(0,0,0,.04);
|
||
}
|
||
.withdraw-notice {
|
||
min-height: 40px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
padding: 0 16px;
|
||
border-top: .5px solid rgba(0,0,0,.04);
|
||
border-bottom: .5px solid rgba(0,0,0,.05);
|
||
background: rgba(255,255,255,.50);
|
||
color: var(--gray-700);
|
||
font-size: 11px;
|
||
font-weight: 400;
|
||
}
|
||
.withdraw-notice-icon {
|
||
width: 14px;
|
||
height: 14px;
|
||
border-radius: 50%;
|
||
border: 1.3px solid currentColor;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
font-size: 10px;
|
||
line-height: 1;
|
||
}
|
||
.withdraw-notice-text {
|
||
flex: 1;
|
||
min-width: 0;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.withdraw-notice-close {
|
||
border: none;
|
||
background: none;
|
||
color: var(--gray-700);
|
||
font-size: 18px;
|
||
font-weight: 400;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
}
|
||
.withdraw-content {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
-webkit-overflow-scrolling: touch;
|
||
padding: 24px 16px 24px;
|
||
background: #fff;
|
||
}
|
||
.withdraw-balance-card {
|
||
display: block;
|
||
text-align: center;
|
||
padding: 12px 0 32px;
|
||
margin-bottom: 0;
|
||
}
|
||
.withdraw-balance-amount {
|
||
font-size: 48px;
|
||
line-height: 1;
|
||
font-weight: 800;
|
||
color: #FFA000;
|
||
letter-spacing: 0;
|
||
}
|
||
.withdraw-balance-amount span {
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
margin-left: 4px;
|
||
}
|
||
.withdraw-balance-sub {
|
||
display: none;
|
||
}
|
||
.withdraw-method {
|
||
margin-bottom: 24px;
|
||
}
|
||
.withdraw-method-head {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
min-height: 26px;
|
||
margin-bottom: 12px;
|
||
}
|
||
.withdraw-method-title {
|
||
flex: 1;
|
||
font-size: 15px;
|
||
font-weight: 600;
|
||
color: var(--gray-900);
|
||
}
|
||
.withdraw-wechat-logo {
|
||
width: 22px;
|
||
height: 22px;
|
||
border-radius: 50%;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
background: #22C55E;
|
||
}
|
||
.withdraw-wechat-logo svg {
|
||
width: 16px;
|
||
height: 16px;
|
||
display: block;
|
||
}
|
||
.withdraw-amount-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 8px;
|
||
}
|
||
.withdraw-amount {
|
||
min-height: 66px;
|
||
border: 1px solid #F0F0F0;
|
||
border-radius: 12px;
|
||
background: #FAFAFA;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
text-align: center;
|
||
cursor: pointer;
|
||
font-family: inherit;
|
||
font-size: 18px;
|
||
font-weight: 700;
|
||
color: #1A1A1A;
|
||
box-shadow: 0 5px 14px rgba(0,0,0,.032);
|
||
}
|
||
.withdraw-amount small {
|
||
font-size: 12px;
|
||
font-weight: 400;
|
||
margin-left: 2px;
|
||
}
|
||
.withdraw-amount.active {
|
||
border-color: #FFD600;
|
||
background: #FFFDE7;
|
||
color: #1A1A1A;
|
||
box-shadow: inset 0 0 0 1px #FFD600, 0 7px 16px rgba(255,214,0,.13);
|
||
}
|
||
.wechat-bind-layer {
|
||
display: none;
|
||
position: absolute;
|
||
inset: 0;
|
||
z-index: 285;
|
||
overflow: hidden;
|
||
}
|
||
.wechat-bind-layer.open {
|
||
display: block;
|
||
}
|
||
.wechat-bind-mask {
|
||
position: absolute;
|
||
inset: 0;
|
||
background: rgba(0,0,0,.56);
|
||
}
|
||
.wechat-bind-sheet {
|
||
position: absolute;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
min-height: 520px;
|
||
border-radius: 24px 24px 0 0;
|
||
background: #FAFAFA;
|
||
padding: 24px 16px 24px;
|
||
animation: exchangeSheetUp .24s ease-out;
|
||
}
|
||
.wechat-bind-close {
|
||
width: 38px;
|
||
height: 38px;
|
||
border-radius: 18px;
|
||
border: none;
|
||
background: #F0F0F0;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #1A1A1A;
|
||
font-size: 28px;
|
||
font-weight: 400;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
font-family: inherit;
|
||
}
|
||
.wechat-bind-amount-label {
|
||
margin-top: 4px;
|
||
text-align: center;
|
||
font-size: 17px;
|
||
font-weight: 400;
|
||
color: var(--gray-600);
|
||
}
|
||
.wechat-bind-amount {
|
||
margin-top: 8px;
|
||
text-align: center;
|
||
font-size: 48px;
|
||
line-height: 1;
|
||
font-weight: 700;
|
||
color: #1A1A1A;
|
||
}
|
||
.wechat-bind-amount small {
|
||
font-size: 18px;
|
||
font-weight: 400;
|
||
margin-left: 4px;
|
||
}
|
||
.wechat-bind-card {
|
||
margin-top: 64px;
|
||
min-height: 92px;
|
||
border-radius: 14px;
|
||
background: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
padding: 0 16px;
|
||
box-shadow: 0 6px 20px rgba(0,0,0,.03);
|
||
}
|
||
.wechat-bind-card-logo {
|
||
width: 34px;
|
||
height: 34px;
|
||
border-radius: 18px;
|
||
background: #22C55E;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
}
|
||
.wechat-bind-card-logo svg {
|
||
width: 24px;
|
||
height: 24px;
|
||
}
|
||
.wechat-bind-card-title {
|
||
font-size: 17px;
|
||
font-weight: 600;
|
||
color: #1A1A1A;
|
||
}
|
||
.wechat-bind-card-sub {
|
||
margin-top: 6px;
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
color: var(--gray-500);
|
||
}
|
||
.wechat-bind-cta {
|
||
position: absolute;
|
||
left: 20px;
|
||
right: 20px;
|
||
bottom: 28px;
|
||
height: 56px;
|
||
border: none;
|
||
border-radius: 14px;
|
||
background: linear-gradient(90deg, #FFE066 0%, #FFD600 52%, #FFE066 100%);
|
||
color: #1A1A1A;
|
||
font-family: inherit;
|
||
font-size: 17px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
}
|
||
.exchange-layer {
|
||
display: none;
|
||
position: absolute;
|
||
inset: 0;
|
||
z-index: 280;
|
||
overflow: hidden;
|
||
}
|
||
.exchange-layer.open {
|
||
display: block;
|
||
}
|
||
.exchange-mask {
|
||
position: absolute;
|
||
inset: 0;
|
||
background: rgba(0,0,0,.72);
|
||
}
|
||
.exchange-sheet {
|
||
position: absolute;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: #fff;
|
||
border-radius: 24px 24px 0 0;
|
||
padding: 24px 16px 24px;
|
||
animation: exchangeSheetUp .24s ease-out;
|
||
}
|
||
@keyframes exchangeSheetUp {
|
||
from { transform: translateY(100%); }
|
||
to { transform: translateY(0); }
|
||
}
|
||
.exchange-close {
|
||
position: absolute;
|
||
top: 18px;
|
||
right: 18px;
|
||
width: 38px;
|
||
height: 38px;
|
||
border-radius: 18px;
|
||
border: none;
|
||
background: #F0F0F0;
|
||
color: #1A1A1A;
|
||
font-size: 24px;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
font-family: inherit;
|
||
}
|
||
.exchange-title {
|
||
font-size: 20px;
|
||
font-weight: 900;
|
||
color: #1A1A1A;
|
||
margin-bottom: 8px;
|
||
}
|
||
.exchange-balance {
|
||
font-size: 15px;
|
||
font-weight: 600;
|
||
color: var(--gray-500);
|
||
margin-bottom: 24px;
|
||
}
|
||
.exchange-balance strong {
|
||
color: var(--gray-700);
|
||
font-weight: 800;
|
||
}
|
||
.exchange-convert-card {
|
||
height: 64px;
|
||
border-radius: 8px;
|
||
background: #FAFAFA;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0 16px 0 16px;
|
||
margin-bottom: 24px;
|
||
}
|
||
.exchange-coin-side {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.exchange-coin-icon {
|
||
width: 30px;
|
||
height: 30px;
|
||
border-radius: 14px;
|
||
background: radial-gradient(circle at 35% 30%, #FFE0B2, #FFB300);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #8B6914;
|
||
font-weight: 900;
|
||
font-size: 16px;
|
||
}
|
||
.exchange-coin-num {
|
||
font-size: 24px;
|
||
font-weight: 900;
|
||
color: #000;
|
||
}
|
||
.exchange-cash-num {
|
||
font-size: 28px;
|
||
font-weight: 900;
|
||
color: #FE2C55;
|
||
}
|
||
.exchange-cash-num small {
|
||
font-size: 17px;
|
||
margin-left: 2px;
|
||
}
|
||
.exchange-presets {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 8px;
|
||
margin-bottom: 12px;
|
||
}
|
||
.exchange-preset {
|
||
height: 48px;
|
||
border-radius: 8px;
|
||
border: 1px solid #F0F0F0;
|
||
background: #fff;
|
||
color: var(--gray-400);
|
||
font-family: inherit;
|
||
font-size: 16px;
|
||
font-weight: 700;
|
||
cursor: pointer;
|
||
}
|
||
.exchange-preset.active {
|
||
border-color: #FF6B6B;
|
||
color: #FE2C55;
|
||
background: #FAFAFA;
|
||
}
|
||
.exchange-error {
|
||
min-height: 22px;
|
||
color: #FE2C55;
|
||
font-size: 14px;
|
||
font-weight: 700;
|
||
margin-bottom: 24px;
|
||
}
|
||
.exchange-rule {
|
||
text-align: center;
|
||
font-size: 15px;
|
||
font-weight: 600;
|
||
color: var(--gray-500);
|
||
margin-bottom: 24px;
|
||
}
|
||
.exchange-submit {
|
||
width: 100%;
|
||
height: 56px;
|
||
border: none;
|
||
border-radius: 8px;
|
||
background: #FE2C55;
|
||
color: #fff;
|
||
font-family: inherit;
|
||
font-size: 18px;
|
||
font-weight: 700;
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* === 标准返回按钮 (统一 design.md - icons.back-chevron) === */
|
||
.btn-back {
|
||
width: 44px; height: 44px;
|
||
display: flex; align-items: center; justify-content: center;
|
||
background: transparent; border: none; padding: 0;
|
||
cursor: pointer; -webkit-tap-highlight-color: transparent;
|
||
flex-shrink: 0;
|
||
}
|
||
.btn-back:active { opacity: 0.5; }
|
||
.btn-back svg { width: 24px; height: 24px; display: block; }
|
||
|
||
</style>
|
||
|
||
<style>
|
||
/* === 跳转动画(原 shared/transitions.css 内嵌) === */
|
||
/* tokens.css 是空文件已废弃,未内嵌;token 由各 HTML 的 :root 单独定义 */
|
||
/**
|
||
* 7 种跳转动画
|
||
* 用法:JS 给 body 加 .transitioning-{词} class,触发对应动画
|
||
*/
|
||
|
||
/* push: 右进左出(进入下一层级) */
|
||
@keyframes nav-push-out {
|
||
from { transform: translateX(0); opacity: 1; }
|
||
to { transform: translateX(-30%); opacity: 0.6; }
|
||
}
|
||
body.transitioning-push { animation: nav-push-out 280ms ease-in forwards; }
|
||
|
||
/* pop: 左进右出(返回) */
|
||
@keyframes nav-pop-out {
|
||
from { transform: translateX(0); opacity: 1; }
|
||
to { transform: translateX(100%); opacity: 0.8; }
|
||
}
|
||
body.transitioning-pop { animation: nav-pop-out 280ms ease-in forwards; }
|
||
|
||
/* modal: 从底弹起(即将离开页面,向上让位) */
|
||
@keyframes nav-modal-out {
|
||
from { transform: translateY(0); opacity: 1; }
|
||
to { transform: translateY(-8%); opacity: 0.6; }
|
||
}
|
||
body.transitioning-modal { animation: nav-modal-out 280ms ease-in forwards; }
|
||
|
||
/* dismiss: 向下收起 */
|
||
@keyframes nav-dismiss-out {
|
||
from { transform: translateY(0); opacity: 1; }
|
||
to { transform: translateY(100%); opacity: 0.4; }
|
||
}
|
||
body.transitioning-dismiss { animation: nav-dismiss-out 280ms ease-in forwards; }
|
||
|
||
/* replace: 直接替换(淡出) */
|
||
@keyframes nav-replace-out {
|
||
from { opacity: 1; }
|
||
to { opacity: 0; }
|
||
}
|
||
body.transitioning-replace { animation: nav-replace-out 200ms ease-out forwards; }
|
||
|
||
/* fade: 淡入淡出(splash 类过渡) */
|
||
@keyframes nav-fade-out {
|
||
from { opacity: 1; }
|
||
to { opacity: 0; }
|
||
}
|
||
body.transitioning-fade { animation: nav-fade-out 400ms ease-in-out forwards; }
|
||
|
||
/* tab: 无动画(瞬切) */
|
||
body.transitioning-tab { /* no animation */ }
|
||
|
||
/* 进入动画(DOMContentLoaded 前的初始状态由 body.preanim 控制,可选) */
|
||
@keyframes nav-fade-in {
|
||
from { opacity: 0; }
|
||
to { opacity: 1; }
|
||
}
|
||
body { /* nav-fade-in disabled — tab 切换闪烁源头 */ }
|
||
</style>
|
||
<style>
|
||
html,body{background:#fff;display:block;height:100%;margin:0;cursor:auto;overflow:hidden;overscroll-behavior:none}
|
||
.device{width:100%;height:100%;border-radius:0;box-shadow:none}
|
||
.screen,.home-scroll{overscroll-behavior:none;-webkit-overflow-scrolling:touch}
|
||
#variantToggle,#debugBack{display:none!important}
|
||
.tab-bar{display:none!important} /* 底栏归原生壳:隐藏 H5 原型自带 tabbar,修双底栏 */
|
||
/* 顶部品牌带吸顶(去框后).第一版用 flex 固定头(#home overflow:hidden + .home-scroll min-height:0)
|
||
在本机 WebView 上把页面整个卡死、无法滚动,放弃。改用与已验证可用的 records 页同款「绝对定位」法:
|
||
.screen(position:absolute 定位容器)内,品牌带绝对贴顶、home-scroll 绝对占满其下并自身滚动——
|
||
不依赖 flex 高度链或 position:sticky,在本机 WebView 上最稳(对齐 records .hist-scroll 的 top/bottom 定位)。
|
||
margin-top:0 去框后无假状态栏,贴系统状态栏下(原生壳已 statusBarsPadding);feed-sort top:0 紧贴品牌带下。 */
|
||
#home{overflow:hidden}
|
||
#home .brand-strip{position:absolute; top:0; left:0; right:0; margin-top:0; z-index:5}
|
||
#home .home-scroll{position:absolute; top:38px; left:0; right:0; bottom:0}
|
||
#home .feed-sort{top:0}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<!--
|
||
@page: home
|
||
@path: app/home
|
||
@source: 2026-05-18.html
|
||
TODO: 补充 @owner / @from / @to / @notes(参照 FLOW.md)
|
||
-->
|
||
|
||
<!-- 方案切换控制面板 -->
|
||
<div class="variant-toggle" id="variantToggle">
|
||
<button class="variant-btn" onclick="toggleVariantPanel()" title="方案切换">⚙</button>
|
||
<div class="variant-panel" id="variantPanel">
|
||
<h3>方案切换</h3>
|
||
<div id="variantList"><div class="variant-empty">暂无多方案模块<br><span style="font-size: 11px;">在 variants 配置中添加模块即可</span></div></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="device" id="app">
|
||
<!-- 调试返回按钮 -->
|
||
<div id="debugBack" onclick="debugGoBack()" style="position: absolute; left: 0px; bottom: 0px; z-index: 99999; background: rgb(0, 0, 0); color: rgb(255, 255, 255); font-size: 11px; font-weight: 700; padding: 8px 8px; border-radius: 0px 4px 0px 0px; cursor: pointer; opacity: 0.7; line-height: 1; letter-spacing: 1px;">返回</div>
|
||
<!-- ===== 11. LOGIN ===== -->
|
||
<!-- screen #login removed for split -->
|
||
|
||
<!-- 入口页协议 · 底部抽屉(device 级 overlay,可跨屏触发:login / celebration 都用) -->
|
||
<div id="agreeModal" class="login-agreement-sheet-layer">
|
||
<div class="login-agreement-sheet">
|
||
<div class="login-agreement-sheet-title">用户协议及隐私保护</div>
|
||
<div class="login-agreement-sheet-copy">我已阅读并同意<span class="link">用户协议</span>、<span class="link">基本功能隐私政策</span></div>
|
||
<button class="login-agreement-sheet-primary" type="button" onclick="agreeAndLogin()">同意并登录</button>
|
||
<button class="login-agreement-sheet-secondary" type="button" onclick="closeAgreeModal()">不同意</button>
|
||
</div>
|
||
</div>
|
||
<!-- 通用 Toast(device 级,跨屏可见) -->
|
||
<div id="loginToast" style="display: none;position: absolute;left: 50%;bottom: 120px;transform: translateX(-50%);background: rgba(0,0,0,.75);color: #fff;font-size: 13px;font-weight: 500;padding: 8px 16px;border-radius: 8px;white-space: nowrap;z-index: 40;"></div>
|
||
|
||
<!-- ===== 11b. LOGIN PHONE(独立手机号登录页) ===== -->
|
||
<!-- screen #loginPhone removed for split -->
|
||
|
||
<!-- ===== HOME TAB ===== -->
|
||
<div class="screen active" id="home" style="background: var(--bg);">
|
||
<!-- 顶部品牌带 wordmark(吸顶:移出滚动区,作 .screen 固定头,不随内容滚动) -->
|
||
<div class="brand-strip">
|
||
<div class="brand-strip-left">
|
||
<img class="brand-strip-logo" src="assets/shared/logos/sb-brand.png" alt="">
|
||
<span class="brand-strip-name">傻瓜比价</span>
|
||
</div>
|
||
<span class="brand-strip-tagline">跨平台比价,用傻瓜</span>
|
||
</div>
|
||
<div class="home-scroll" style="flex: 1;overflow-y: auto;">
|
||
<!-- 顶部 Banner —— 3 个点位的可滑动轮播 -->
|
||
<div class="home-banner" id="homeBanner">
|
||
<div class="home-banner-track" id="homeBannerTrack">
|
||
<div class="home-banner-slide" data-banner-idx="0" data-nav-target="guideVideo" style="cursor: pointer;">
|
||
<img src="assets/home/index/banner-top-cropped.png" alt="如何使用傻瓜比价 · 新手指南">
|
||
</div>
|
||
<div class="home-banner-slide" data-banner-idx="1" data-nav-target="invite" style="cursor: pointer;">
|
||
<div class="home-banner-slide-fill bf-orange">
|
||
<div class="bf-title">邀好友 赚金币</div>
|
||
<div class="bf-pill">立即邀请 ›</div>
|
||
<div class="bf-deco">🎁</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="home-banner-dots" id="homeBannerDots">
|
||
<span class="home-banner-dot active" data-dot-idx="0"></span>
|
||
<span class="home-banner-dot" data-dot-idx="1"></span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- v2026-06-01:节省日志横条(喇叭 + 时间戳 feed,整体居中) -->
|
||
<div class="home-marquee" id="homeMarquee">
|
||
<div class="home-mq-viewport">
|
||
<div class="home-mq-track" id="homeMarqueeTrack">
|
||
<div class="home-mq-item">
|
||
<span class="home-mq-dot" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none"><path d="M3 9.5h3l8-5v15l-8-5H3v-5z" fill="currentColor"/><path d="M17 9.5c1 .9 1 4.1 0 5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/><path d="M19.5 7c2 1.8 2 8.2 0 10" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/></svg></span>
|
||
<span class="home-mq-copy"><span class="mq-time">14:23:18</span><span class="mq-user" data-nick="省钱小能手">省***手</span><span class="mq-act">比价后节省</span><span class="mq-amt">88888.88</span><span class="mq-unit">元</span></span>
|
||
</div>
|
||
<div class="home-mq-item">
|
||
<span class="home-mq-dot" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none"><path d="M3 9.5h3l8-5v15l-8-5H3v-5z" fill="currentColor"/><path d="M17 9.5c1 .9 1 4.1 0 5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/><path d="M19.5 7c2 1.8 2 8.2 0 10" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/></svg></span>
|
||
<span class="home-mq-copy"><span class="mq-time">14:22:45</span><span class="mq-user" data-uid="12902">1***2</span><span class="mq-act">比价后节省</span><span class="mq-amt">42.40</span><span class="mq-unit">元</span></span>
|
||
</div>
|
||
<div class="home-mq-item">
|
||
<span class="home-mq-dot" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none"><path d="M3 9.5h3l8-5v15l-8-5H3v-5z" fill="currentColor"/><path d="M17 9.5c1 .9 1 4.1 0 5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/><path d="M19.5 7c2 1.8 2 8.2 0 10" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/></svg></span>
|
||
<span class="home-mq-copy"><span class="mq-time">14:20:31</span><span class="mq-user" data-nick="小确呀">小**</span><span class="mq-act">比价后节省</span><span class="mq-amt">7.90</span><span class="mq-unit">元</span></span>
|
||
</div>
|
||
<div class="home-mq-item">
|
||
<span class="home-mq-dot" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none"><path d="M3 9.5h3l8-5v15l-8-5H3v-5z" fill="currentColor"/><path d="M17 9.5c1 .9 1 4.1 0 5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/><path d="M19.5 7c2 1.8 2 8.2 0 10" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/></svg></span>
|
||
<span class="home-mq-copy"><span class="mq-time">14:18:07</span><span class="mq-user" data-uid="77150">7***0</span><span class="mq-act">比价后节省</span><span class="mq-amt">156.30</span><span class="mq-unit">元</span></span>
|
||
</div>
|
||
<div class="home-mq-item">
|
||
<span class="home-mq-dot" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none"><path d="M3 9.5h3l8-5v15l-8-5H3v-5z" fill="currentColor"/><path d="M17 9.5c1 .9 1 4.1 0 5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/><path d="M19.5 7c2 1.8 2 8.2 0 10" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/></svg></span>
|
||
<span class="home-mq-copy"><span class="mq-time">14:15:42</span><span class="mq-user" data-nick="团团">团**</span><span class="mq-act">比价后节省</span><span class="mq-amt">23.50</span><span class="mq-unit">元</span></span>
|
||
</div>
|
||
<div class="home-mq-item">
|
||
<span class="home-mq-dot" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none"><path d="M3 9.5h3l8-5v15l-8-5H3v-5z" fill="currentColor"/><path d="M17 9.5c1 .9 1 4.1 0 5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/><path d="M19.5 7c2 1.8 2 8.2 0 10" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/></svg></span>
|
||
<span class="home-mq-copy"><span class="mq-time">14:11:29</span><span class="mq-user" data-uid="66180">6***0</span><span class="mq-act">比价后节省</span><span class="mq-amt">89.40</span><span class="mq-unit">元</span></span>
|
||
</div>
|
||
<!-- 末尾复制首条,保证循环切回顶部无视觉跳变 -->
|
||
<div class="home-mq-item">
|
||
<span class="home-mq-dot" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none"><path d="M3 9.5h3l8-5v15l-8-5H3v-5z" fill="currentColor"/><path d="M17 9.5c1 .9 1 4.1 0 5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/><path d="M19.5 7c2 1.8 2 8.2 0 10" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/></svg></span>
|
||
<span class="home-mq-copy"><span class="mq-time">14:23:18</span><span class="mq-user" data-nick="省钱小能手">省***手</span><span class="mq-act">比价后节省</span><span class="mq-amt">88888.88</span><span class="mq-unit">元</span></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- v2026-06-03 新增:平台 3 数据板块(单卡 3 列竖线) -->
|
||
<div class="home-3stat">
|
||
<div class="h3s-card">
|
||
<div class="h3s-label">帮助用户</div>
|
||
<div class="h3s-num"><span class="h3s-value">12847<span class="h3s-unit">人</span></span></div>
|
||
</div>
|
||
<div class="h3s-card">
|
||
<div class="h3s-label">完成比价</div>
|
||
<div class="h3s-num"><span class="h3s-value">86532<span class="h3s-unit">次</span></span></div>
|
||
</div>
|
||
<div class="h3s-card">
|
||
<div class="h3s-label">累计节省</div>
|
||
<div class="h3s-num"><span class="h3s-value">37621.4<span class="h3s-unit">元</span></span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="last-compare-banner" id="lastCompareBanner" onclick="go('compresult')" aria-live="polite" style="display:none">
|
||
<div class="lcb-head">
|
||
<span class="lcb-kicker" id="lastCompareAge">上次比价</span>
|
||
<span class="lcb-status"></span>
|
||
</div>
|
||
<div class="lcb-body">
|
||
<div class="lcb-main">
|
||
<div class="lcb-top">
|
||
<span class="lcb-shop" id="lastCompareShop">窑鸡王(康营店)</span>
|
||
</div>
|
||
<div class="lcb-meta">
|
||
<span class="lcb-dish" id="lastCompareDish">招牌窑鸡整只-原味</span>
|
||
</div>
|
||
</div>
|
||
<div class="lcb-pricebox" id="lastComparePriceBox">
|
||
<div class="lcb-price-label">最低价</div>
|
||
<div class="lcb-price" id="lastComparePrice">¥57.9</div>
|
||
<div class="lcb-platform" id="lastComparePlatformWrap">
|
||
<img id="lastComparePlatformLogo" src="assets/shared/logos/taobao.png" alt="">
|
||
<span class="lcb-platform-name" id="lastComparePlatform">淘宝</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="lcb-foot">
|
||
<span class="lcb-note" id="lastCompareNote">去查看</span>
|
||
<div class="lcb-arrow" aria-hidden="true">
|
||
<svg viewBox="0 0 24 24" fill="none">
|
||
<path d="M9 5l7 7-7 7" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- v2026-06-01 改版:左 平台累计省下 + 右 点外卖赚金币 -->
|
||
<div class="home-tri">
|
||
<!-- 左:今日领券(结构 1:1 镜像右卡 .cta-g6:title + sub + bottom CTA) -->
|
||
<div class="today-coupon" id="homeStatsCard" onclick="onTriClaimClick()">
|
||
<div class="tc-title">今日<span class="hl">大额优惠券</span></div>
|
||
<div class="tc-sub">AI 一键自动领</div>
|
||
<div class="tc-bottom">
|
||
<button class="tc-cta">去领取</button>
|
||
</div>
|
||
<div class="tc-coupon-symbols" aria-hidden="true">
|
||
<img src="assets/home/index/coupon-ticket-cluster.png" alt="">
|
||
</div>
|
||
<div class="tc-tap-hand" aria-hidden="true"><img src="assets/home/index/tap-hand-generated.png" alt=""></div>
|
||
</div>
|
||
<div class="home-tri-arrow" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none"><path d="M4 12h13M12 6l7 6-7 6" stroke="currentColor" stroke-width="3.4" stroke-linecap="round" stroke-linejoin="round"/></svg></div>
|
||
<!-- 右:点外卖赚金币(原货比三家文案改) → 点击弹平台选择 -->
|
||
<div class="cta-g6" id="homeCompareEntry" onclick="onHomeCompareClick()">
|
||
<div class="g6-title">点外卖,<span class="hl">赚金币</span></div>
|
||
<div class="g6-sub">快去解锁全网底价</div>
|
||
<div class="g6-bottom">
|
||
<button class="g6-cta">去点餐</button>
|
||
</div>
|
||
<div class="g6-logos">
|
||
<img src="assets/shared/logos/meituan.png" alt="">
|
||
<img src="assets/shared/logos/taobao.png" alt="">
|
||
<img src="assets/shared/logos/jd.png" alt="">
|
||
</div>
|
||
<div class="g6-tap-hand" aria-hidden="true"><img src="assets/home/index/tap-hand-generated.png" alt=""></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 5 类别快捷入口(暂时隐藏,元素保留,以后会加回来) -->
|
||
<div class="home-cats" style="display:none;">
|
||
<div class="home-cat">
|
||
<img src="assets/home/index/categories/hotel.png" alt="">
|
||
<span class="home-cat-label">特惠酒店</span>
|
||
</div>
|
||
<div class="home-cat">
|
||
<img src="assets/home/index/categories/movie.png" alt="">
|
||
<span class="home-cat-label">折扣电影票</span>
|
||
</div>
|
||
<div class="home-cat">
|
||
<img src="assets/home/index/categories/taxi.png" alt="">
|
||
<span class="home-cat-label">打车券</span>
|
||
</div>
|
||
<div class="home-cat">
|
||
<img src="assets/home/index/categories/express.png" alt="">
|
||
<span class="home-cat-label">寄快递</span>
|
||
</div>
|
||
<div class="home-cat" onclick="go('invite')">
|
||
<img src="assets/home/index/categories/invite-earn.png" alt="">
|
||
<span class="home-cat-label">分享赚钱</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 推荐信息流 -->
|
||
<div class="home-feed-wrap">
|
||
<div class="feed-sort" data-sort>
|
||
<div class="fs-item active" data-key="rec"><span class="lbl">智能推荐</span></div>
|
||
<div class="fs-item" data-key="distance"><span class="lbl">距离最近</span></div>
|
||
<div class="fs-item" data-key="sales"><span class="lbl">销量最高</span></div>
|
||
</div>
|
||
<!-- 位置权限未授权·feed 空态(未授权时替换 feed + 排序 tab;授权后由 applyLocationState 切回 feed) -->
|
||
<div class="home-feed-empty" id="homeFeedEmpty" style="display: none;flex-direction: column;align-items: center;justify-content: flex-start;background: #fff;padding: 18px 24px 24px;text-align: center;">
|
||
<div style="width: 48px;height: 48px;border-radius: 50%;background: #F5F5F5;display: flex;align-items: center;justify-content: center;margin-bottom: 10px;">
|
||
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||
<path d="M12 21.5s6.5-5.4 6.5-10.5a6.5 6.5 0 1 0-13 0c0 5.1 6.5 10.5 6.5 10.5z" stroke="#CCCCCC" stroke-width="1.6" fill="#fff"/>
|
||
<circle cx="12" cy="10.8" r="2.4" stroke="#CCCCCC" stroke-width="1.6" fill="none"/>
|
||
</svg>
|
||
</div>
|
||
<div style="font-size: 14px;color: #999;line-height: 1.5;">授权地理位置,附近美食优惠马上看~</div>
|
||
<button onclick="goAuthLocation()" style="margin-top: 12px;height: 32px;padding: 0 20px;border: none;border-radius: 18px;font-size: 13px;font-weight: 600;background: linear-gradient(180deg,#FFE066 0%,#FFC400 100%);color: #1A1A1A;box-shadow: inset 0 1px 0 rgba(255,255,255,.7), 0 2px 6px rgba(255,179,0,.35);cursor: pointer;display: inline-flex;align-items: center;justify-content: center;">去授权</button>
|
||
</div>
|
||
<!-- 已授权但附近暂无推荐·feed 空态(推荐列表为空时替换 feed;点击去比价复用首页「去点餐」逻辑) -->
|
||
<div class="home-feed-empty" id="homeFeedNoDealEmpty" style="display: none;flex-direction: column;align-items: center;justify-content: flex-start;background: #fff;padding: 18px 24px 24px;text-align: center;">
|
||
<img src="assets/home/index/no-deal-search.png" alt="" style="width: 48px;height: 48px;object-fit: contain;display: block;margin-bottom: 10px;" aria-hidden="true">
|
||
<div style="font-size: 14px;color: #999;line-height: 1.5;">附近暂无优惠商品~去外卖平台解锁底价</div>
|
||
<button onclick="onHomeCompareClick()" style="margin-top: 12px;height: 32px;padding: 0 20px;border: none;border-radius: 18px;font-size: 13px;font-weight: 600;background: linear-gradient(180deg,#FFE066 0%,#FFC400 100%);color: #1A1A1A;box-shadow: inset 0 1px 0 rgba(255,255,255,.7), 0 2px 6px rgba(255,179,0,.35);cursor: pointer;display: inline-flex;align-items: center;justify-content: center;">去比价</button>
|
||
</div>
|
||
<!-- feed 首次加载中(转圈占位) -->
|
||
<div class="home-feed-empty" id="homeFeedLoading" style="display: none;flex-direction: column;align-items: center;justify-content: flex-start;background: #fff;padding: 32px 24px;text-align: center;">
|
||
<div style="font-size: 14px;color: #999;">加载中…</div>
|
||
</div>
|
||
<!-- feed 服务繁忙(degraded:上游/库失败已降级,可重试) -->
|
||
<div class="home-feed-empty" id="homeFeedDegraded" style="display: none;flex-direction: column;align-items: center;justify-content: flex-start;background: #fff;padding: 18px 24px 24px;text-align: center;">
|
||
<div style="font-size: 14px;color: #999;line-height: 1.5;">服务繁忙,下拉重试~</div>
|
||
<button onclick="HomeFeed.loadFirst()" style="margin-top: 12px;height: 32px;padding: 0 20px;border: none;border-radius: 18px;font-size: 13px;font-weight: 600;background: linear-gradient(180deg,#FFE066 0%,#FFC400 100%);color: #1A1A1A;cursor: pointer;">重试</button>
|
||
</div>
|
||
<!-- H2b: feed 卡片由 JS 按 /api/v1/meituan/feed|top-sales 动态渲染(原 mock 静态卡已移除) -->
|
||
<div class="home-feed"></div>
|
||
<div class="feed-end" style="display:none">已经到底了</div>
|
||
</div>
|
||
</div>
|
||
<div class="tab-bar">
|
||
<div class="tab-item active" onclick="go('home')"><span class="tab-icon"><svg class="i-outline" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12l9-8 9 8"></path><path d="M5 10v9a1 1 0 001 1h3v-5h6v5h3a1 1 0 001-1v-9"></path></svg><svg class="i-filled" width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M3 12l9-8 9 8" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M5 10v9a1 1 0 001 1h3v-5h6v5h3a1 1 0 001-1v-9" fill="#FFD600" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></span><span class="tab-label">首页</span></div>
|
||
<div class="tab-item" id="homeTabWelfare" onclick="go('welfare')"><span class="welfare-tab-dot" aria-hidden="true"></span><span class="tab-icon" id="homeTabWelfareIcon"><svg class="i-outline" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="8" width="18" height="4" rx="1"></rect><path d="M12 8v12"></path><path d="M5 12v7a1 1 0 001 1h12a1 1 0 001-1v-7"></path><path d="M7.5 8C6 8 5 6.5 6 5.5S9 4 9.5 5.5c.4 1.2 2.5 2.5 2.5 2.5s2.1-1.3 2.5-2.5C15 4 17 4.5 18 5.5s-1 2.5-2.5 2.5"></path></svg><svg class="i-filled" width="24" height="24" viewBox="0 0 24 24" fill="none"><rect x="3" y="8" width="18" height="4" rx="1" fill="#FFD600" stroke="#1a1a1a" stroke-width="2"></rect><path d="M5 12v7a1 1 0 001 1h12a1 1 0 001-1v-7" fill="#FFD600" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 8v12" stroke="#1a1a1a" stroke-width="2"></path><path d="M7.5 8C6 8 5 6.5 6 5.5S9 4 9.5 5.5c.4 1.2 2.5 2.5 2.5 2.5s2.1-1.3 2.5-2.5C15 4 17 4.5 18 5.5s-1 2.5-2.5 2.5" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></span><span class="tab-label">赚钱</span></div>
|
||
<div class="tab-item" onclick="go('history')"><span class="tab-icon"><svg class="i-outline" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="2.5"></rect><path d="M8 9h8"></path><path d="M8 13h8"></path><path d="M8 17h5"></path></svg><svg class="i-filled" width="24" height="24" viewBox="0 0 24 24" fill="none"><rect x="4" y="4" width="16" height="16" rx="2.5" fill="#FFD600" stroke="#1a1a1a" stroke-width="2"></rect><path d="M8 9h8" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round"></path><path d="M8 13h8" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round"></path><path d="M8 17h5" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round"></path></svg></span><span class="tab-label">记录</span></div>
|
||
<div class="tab-item" onclick="go('profile')"><span class="tab-icon"><svg class="i-outline" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"></circle><path d="M4 20c0-4 4-6 8-6s8 2 8 6"></path></svg><svg class="i-filled" width="24" height="24" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="8" r="4" fill="#FFD600" stroke="#1a1a1a" stroke-width="2"></circle><path d="M4 20c0-4 4-6 8-6s8 2 8 6" fill="#FFD600" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></span><span class="tab-label">我的</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- [ECOM-ONLY] BLIND BOX screen removed for waimai V1 -->
|
||
<!-- Original: 150+ lines of blind box full-page screen with card slider -->
|
||
|
||
|
||
<!-- ===== WELFARE TAB (红果风格) ===== -->
|
||
<!-- screen #welfare removed for split -->
|
||
|
||
<!-- ===== WELFARE RULES / 活动规则 ===== -->
|
||
<!-- screen #welfareRules removed for split -->
|
||
|
||
<!-- ===== PROFILE TAB ===== -->
|
||
<style>
|
||
/* —— 我的页 (profile) —— */
|
||
#profile {
|
||
background: radial-gradient(circle at 84% 17%, rgba(255,255,255,.82) 0 36px, transparent 37px),
|
||
radial-gradient(circle at 98% 20%, rgba(255,255,255,.66) 0 42px, transparent 43px),
|
||
linear-gradient(180deg, #FFF1D9 0%, #FFF6E8 28%, #FFF8EF 48%, #F8F8F8 70%, #F7F7F7 100%);
|
||
}
|
||
.prof-statusbar { position: absolute; left: 0; right: 0; top: 0; height: 42px; z-index: 20; display: flex; align-items: center; justify-content: space-between; padding: 8px 32px 0 32px; pointer-events: none; color: #000; }
|
||
.prof-status-time { font-size: 15px; font-weight: 600; letter-spacing: .1px; line-height: 1; font-variant-numeric: tabular-nums; }
|
||
.prof-status-icons { display: flex; align-items: center; gap: 8px; }
|
||
.prof-cell { display: flex; align-items: flex-end; gap: 2px; height: 14px; }
|
||
.prof-cell i { display: block; width: 3px; border-radius: 4px; background: #000; }
|
||
.prof-cell i:nth-child(1) { height: 5px; }
|
||
.prof-cell i:nth-child(2) { height: 8px; }
|
||
.prof-cell i:nth-child(3) { height: 11px; }
|
||
.prof-cell i:nth-child(4) { height: 14px; }
|
||
.prof-wifi { position: relative; width: 17px; height: 13px; overflow: hidden; }
|
||
.prof-wifi::before, .prof-wifi::after { content: ''; position: absolute; left: 50%; border: 3px solid #000; border-color: #000 transparent transparent transparent; border-radius: 50%; transform: translateX(-50%); }
|
||
.prof-wifi::before { width: 21px; height: 21px; top: 1px; }
|
||
.prof-wifi::after { width: 11px; height: 11px; top: 6px; }
|
||
.prof-wifi i { position: absolute; left: 50%; bottom: 0; width: 5px; height: 5px; margin-left: -2.5px; border-radius: 50%; background: #000; }
|
||
.prof-battery { position: relative; width: 23px; height: 12px; border: 1.7px solid #000; border-radius: 4px; padding: 2px; }
|
||
.prof-battery::before { content: ''; position: absolute; right: -3.7px; top: 3.1px; width: 2px; height: 5px; border-radius: 0 4px 4px 0; background: #000; }
|
||
.prof-battery i { display: block; width: 100%; height: 100%; border-radius: 4px; background: #000; }
|
||
.prof-scroll { flex: 1; overflow-y: auto; overflow-x: hidden; }
|
||
.prof-hero { position: relative; padding: 64px 16px 0; min-height: 154px; overflow: visible; }
|
||
.prof-clouds { position: absolute; left: 0; right: 0; top: 0; width: 100%; height: 174px; object-fit: cover; opacity: .72; pointer-events: none; }
|
||
.prof-piggy { position: absolute; top: 36px; right: -12px; width: 160px; height: auto; pointer-events: none; z-index: 1; filter: drop-shadow(0 10px 18px rgba(255,125,50,.16)); }
|
||
.prof-hero::after { content: ''; position: absolute; right: 160px; top: 114px; width: 9px; height: 9px; background: #FFB300; transform: rotate(45deg); box-shadow: 7px 0 0 -3px rgba(255,179,0,.75), 0 7px 0 -3px rgba(255,179,0,.75); z-index: 2; }
|
||
.prof-id { position: relative; z-index: 2; display: flex; align-items: center; gap: 12px; }
|
||
.prof-avatar { width: 74px; height: 74px; border-radius: 50%; flex-shrink: 0; background: radial-gradient(circle at 42% 32%, #FFE0B2 0%, #FFE066 43%, #FFEB3B 100%); border: 3px solid #fff; box-shadow: 0 6px 16px rgba(255,137,32,.20); display: flex; align-items: center; justify-content: center; overflow: hidden; }
|
||
.prof-avatar svg { width: 70px; height: 70px; display: block; }
|
||
.prof-meta { flex: 1; min-width: 0; padding-top: 2px; }
|
||
.prof-name { font-size: 18px; font-weight: 600; color: #000000; line-height: 1.16; letter-spacing: 0; }
|
||
.prof-phone { font-size: 13px; color: rgba(0,0,0,.58); margin-top: 6px; letter-spacing: .1px; font-variant-numeric: tabular-nums; }
|
||
.prof-badge { display: inline-flex; align-items: center; gap: 4px; margin-top: 8px; padding: 4px 8px 4px 6px; background: rgba(255,255,255,.58); border: 1px solid rgba(255,255,255,.95); border-radius: 999px; font-size: 12px; line-height: 1; font-weight: 700; color: #FF5722; box-shadow: 0 2px 8px rgba(143,84,25,.08); backdrop-filter: blur(4px); }
|
||
.prof-badge svg { width: 15px; height: 15px; }
|
||
.prof-badge svg path:first-child { fill: #FFA000; }
|
||
.prof-badge svg path:last-child { stroke: #fff; }
|
||
.prof-body-inner { position: relative; z-index: 3; padding: 12px 16px 16px; }
|
||
/* —— 累计帮省卡片 —— */
|
||
.prof-savings-card { position: relative; min-height: 244px; border-radius: 24px; padding: 24px 24px 16px; background: linear-gradient(180deg, #FF6A00 0%, #FF5722 52%, #FFA000 100%); box-shadow: 0 12px 24px rgba(255,117,31,.22), inset 0 1px 0 rgba(255,255,255,.30); overflow: hidden; color: #fff; border: 1px solid rgba(255,172,63,.55); }
|
||
.prof-savings-card::before { content: ''; position: absolute; inset: 0; background: radial-gradient(circle at 18% 26%, rgba(255,255,255,.10), transparent 18%), radial-gradient(circle at 75% 35%, rgba(255,255,255,.08), transparent 24%); pointer-events: none; }
|
||
.prof-savings-deco { position: absolute; left: -14px; bottom: -12px; width: 160px; height: 128px; object-fit: contain; object-position: left bottom; opacity: .30; pointer-events: none; }
|
||
.prof-savings-coin { position: absolute; top: auto; bottom: 112px; right: 18px; width: 44px; height: 44px; opacity: .82; pointer-events: none; transform: rotate(-22deg); }
|
||
.prof-savings-label { position: relative; z-index: 1; font-size: 15px; line-height: 1.1; font-weight: 700; color: rgba(255,255,255,.96); text-align: center; letter-spacing: .2px; }
|
||
.prof-amount-row { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; gap: 8px; height: 64px; margin: 6px 0 6px; }
|
||
.prof-amount-row::before { content: none; }
|
||
.prof-wheat { width: 46px; height: 64px; flex: 0 0 auto; opacity: .58; background-image: url('assets/profile/index/laurel.png'); background-repeat: no-repeat; background-size: 230px 77px; pointer-events: none; }
|
||
.prof-wheat.left { background-position: 17% center; }
|
||
.prof-wheat.right { background-position: 83% center; }
|
||
.prof-laurel { display: none; }
|
||
.prof-laurel.left { object-position: left center; }
|
||
.prof-laurel.right { object-position: right center; transform: scaleX(-1); }
|
||
.prof-amount { position: relative; z-index: 1; display: inline-flex; align-items: baseline; font-size: 36px; font-weight: 900; color: #fff; line-height: 1; letter-spacing: .1px; text-shadow: 0 2px 6px rgba(160,50,0,.16); font-variant-numeric: tabular-nums; }
|
||
.prof-currency { font-size: 28px; margin-right: 4px; vertical-align: 4px; }
|
||
.prof-stats-row { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; gap: 0; margin: 6px 0 12px; padding-top: 12px; border-top: 1px solid rgba(255,255,255,.35); }
|
||
.prof-stats-row > div:not(.prof-stats-div) { flex: 1; text-align: center; }
|
||
.prof-stat-num { font-size: 18px; font-weight: 900; color: #fff; line-height: 1; font-variant-numeric: tabular-nums; }
|
||
.prof-stat-key { font-size: 12px; font-weight: 600; color: rgba(255,255,255,.88); margin-top: 4px; }
|
||
.prof-stats-div { width: 1px; height: 38px; background: rgba(255,255,255,.33); }
|
||
.prof-savings-btn { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; gap: 6px; width: 142px; height: 34px; margin: 0 auto; padding: 0 16px; background: #fff; border: none; border-radius: 999px; font-size: 14px; font-weight: 600; color: #FF5722; cursor: pointer; box-shadow: 0 6px 12px rgba(214,82,0,.14); }
|
||
.prof-savings-btn span { font-size: 18px; line-height: 1; margin-left: 0; display: inline-block; transform: translateY(-1px); }
|
||
/* —— 省钱战绩卡 —— */
|
||
.prof-card { background: rgba(255,255,255,.96); border-radius: 18px; padding: 12px 12px; margin-top: 12px; box-shadow: 0 6px 18px rgba(151,93,35,.08); border: 1px solid rgba(255,255,255,.82); }
|
||
.prof-achv-title { display: flex; align-items: center; gap: 6px; font-size: 16px; font-weight: 600; color: #1A1A1A; margin-bottom: 12px; letter-spacing: 0; }
|
||
.prof-achv-title .prof-trophy { width: 23px; height: 23px; display: inline-flex; align-items: center; justify-content: center; background: transparent; border-radius: 0; font-size: 20px; filter: drop-shadow(0 3px 5px rgba(255,133,0,.22)); }
|
||
.prof-achv-title .prof-spark { color: #FFEB3B; font-size: 14px; margin-left: 2px; }
|
||
.prof-achv-row { display: flex; align-items: stretch; gap: 0; }
|
||
.prof-achv-item { position: relative; flex: 1; display: flex; align-items: flex-start; justify-content: center; gap: 0; min-width: 0; padding: 0 8px; text-align: center; }
|
||
.prof-achv-item > div { display: grid; grid-template-rows: 17px 23px 14px; justify-items: center; align-items: center; }
|
||
.prof-achv-item::after { content: ''; position: absolute; right: 0; top: 3px; bottom: 3px; width: 1px; background: #F0F0F0; }
|
||
.prof-achv-item:last-child::after { display: none; }
|
||
.prof-achv-ico { width: 34px; height: 34px; border-radius: 18px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
|
||
.prof-achv-ico.ico-orange { background: linear-gradient(180deg,#FFF3C4 0%,#FFE066 100%); }
|
||
.prof-achv-ico.ico-green { background: linear-gradient(180deg,#E8F5E9 0%,#CCCCCC 100%); }
|
||
.prof-achv-ico.ico-blue { background: linear-gradient(180deg,#E3F2FD 0%,#DDDDDD 100%); }
|
||
.prof-achv-ico svg { width: 19px; height: 19px; }
|
||
.prof-achv-item .prof-achv-key { font-size: 12px; color: #1A1A1A; font-weight: 500; line-height: 1.15; white-space: nowrap; }
|
||
.prof-achv-item .prof-achv-val { font-size: 18px; font-weight: 900; color: #FF5722; line-height: 1; margin-top: 0; font-variant-numeric: tabular-nums; }
|
||
.prof-achv-item .prof-achv-val span { font-size: 12px; font-weight: 500; color: #1A1A1A; margin-left: 2px; }
|
||
/* —— 菜单卡 —— */
|
||
.prof-menu-card { padding: 8px 12px; }
|
||
.prof-menu-item { display: flex; align-items: center; gap: 12px; padding: 6px 0; cursor: pointer; border-bottom: .5px solid #F0F0F0; }
|
||
.prof-menu-item:last-child { border-bottom: none; }
|
||
.prof-menu-ico { width: 34px; height: 34px; flex-shrink: 0; filter: drop-shadow(0 4px 6px rgba(49,99,180,.10)); }
|
||
.prof-menu-text { flex: 1; min-width: 0; }
|
||
.prof-menu-title { font-size: 14px; font-weight: 600; color: #1A1A1A; line-height: 1.2; }
|
||
.prof-menu-sub { font-size: 12px; color: #666666; margin-top: 2px; }
|
||
.prof-menu-arrow { font-size: 24px; line-height: 1; color: #999999; font-weight: 400; transform: translateY(-1px); }
|
||
/* —— 未登录 —— */
|
||
.prof-unlogged-hero { position: relative; padding: 64px 16px 24px; text-align: center; }
|
||
.prof-unlogged-hero .prof-avatar { margin: 0 auto 12px; background: linear-gradient(180deg,#F0F0F0 0%,#DDDDDD 100%); }
|
||
.prof-unlogged-cta { margin-top: 6px; background: linear-gradient(180deg,#FFD600 0%,#FFB300 100%); border: none; padding: 8px 24px; border-radius: 999px; font-size: 14px; font-weight: 700; color: #1a1a1a; cursor: pointer; box-shadow: 0 4px 12px rgba(255,180,52,.35); }
|
||
</style>
|
||
<!-- screen #profile removed for split -->
|
||
|
||
<!-- ===== INVITE FRIENDS ===== -->
|
||
<!-- screen #invite removed for split -->
|
||
|
||
<!-- ===== COMPARISON RESULT ===== -->
|
||
<!-- screen #compresult removed for split -->
|
||
|
||
<!-- ===== WITHDRAWAL / 提现(参考图二) ===== -->
|
||
<!-- screen #withdrawal removed for split -->
|
||
|
||
<div id="wechatBindSheet" class="wechat-bind-layer" aria-hidden="true">
|
||
<div class="wechat-bind-mask" onclick="closeWechatBindSheet()"></div>
|
||
<div class="wechat-bind-sheet" onclick="event.stopPropagation()">
|
||
<button class="wechat-bind-close" onclick="closeWechatBindSheet()" aria-label="关闭">×</button>
|
||
<div class="wechat-bind-amount-label">提现金额</div>
|
||
<div class="wechat-bind-amount"><span id="wechatBindAmount">0.3</span><small>元</small></div>
|
||
<div class="wechat-bind-card">
|
||
<span class="wechat-bind-card-logo" aria-hidden="true">
|
||
<svg viewBox="0 0 32 32" fill="none" aria-hidden="true">
|
||
<path d="M13.7 7.2C8 7.2 3.5 10.8 3.5 15.3c0 2.6 1.5 4.9 3.8 6.4l-.9 2.9 3.3-1.7c1.2.3 2.5.5 4 .5 5.6 0 10.2-3.6 10.2-8.1S19.3 7.2 13.7 7.2Z" fill="#fff"/>
|
||
<path d="M21 13.2c4.3.5 7.5 3.4 7.5 7 0 2.2-1.2 4.1-3.2 5.4l.7 2.4-2.8-1.5c-.9.2-1.9.4-3 .4-3.9 0-7.2-2.1-8.2-5.1.6.1 1.2.2 1.8.2 6.2 0 11.2-4 11.2-8.9v-.2Z" fill="#fff" opacity=".86"/>
|
||
<circle cx="10.1" cy="13.8" r="1" fill="#07C160"/>
|
||
<circle cx="16.7" cy="13.8" r="1" fill="#07C160"/>
|
||
</svg>
|
||
</span>
|
||
<div>
|
||
<div class="wechat-bind-card-title">暂未绑定微信账户</div>
|
||
<div class="wechat-bind-card-sub">绑定后才可提现,可以更换和解绑</div>
|
||
</div>
|
||
</div>
|
||
<button class="wechat-bind-cta" onclick="showPrototypeToast('原型演示:跳转微信授权绑定')">去微信绑定并提现</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== COIN HISTORY / 收益明细 ===== -->
|
||
<!-- screen #coinhistory removed for split -->
|
||
|
||
<div id="exchangeSheet" class="exchange-layer" aria-hidden="true">
|
||
<div class="exchange-mask" onclick="closeExchangeSheet()"></div>
|
||
<div class="exchange-sheet" onclick="event.stopPropagation()">
|
||
<button class="exchange-close" onclick="closeExchangeSheet()" aria-label="关闭">×</button>
|
||
<div class="exchange-title">金币兑换现金</div>
|
||
<div class="exchange-balance">金币余额:<strong id="exchangeBalanceText">28,967</strong></div>
|
||
<div class="exchange-convert-card">
|
||
<div class="exchange-coin-side">
|
||
<span class="exchange-coin-icon">¥</span>
|
||
<span class="exchange-coin-num" id="exchangeCoinAmount">28,967</span>
|
||
</div>
|
||
<div class="exchange-cash-num">= <span id="exchangeCashAmount">2.89</span><small>元</small></div>
|
||
</div>
|
||
<div class="exchange-presets">
|
||
<button class="exchange-preset" onclick="selectExchangeAmount(1000, this)">1000</button>
|
||
<button class="exchange-preset" onclick="selectExchangeAmount(2000, this)">2000</button>
|
||
<button class="exchange-preset" onclick="selectExchangeAmount(3000, this)">3000</button>
|
||
<button class="exchange-preset active" id="exchangePresetAll" onclick="selectExchangeAmount('all', this)">全部兑换</button>
|
||
</div>
|
||
<div class="exchange-error" id="exchangeError"></div>
|
||
<div class="exchange-rule">最低 100 金币,不足 100 的金币将原路返回</div>
|
||
<button class="exchange-submit" onclick="confirmExchange()">立即兑换</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== PURCHASE RECORDS ===== -->
|
||
<!-- screen #records removed for split -->
|
||
|
||
<!-- ===== SETTINGS ===== -->
|
||
<!-- screen #settings removed for split -->
|
||
|
||
<!-- 退出登录确认弹窗 -->
|
||
<div id="logoutConfirm" style="display: none;position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 260;background: rgba(0,0,0,.45);align-items: center;justify-content: center;padding: 40px 32px;overflow: hidden;">
|
||
<div style="background: #fff;border-radius: 18px;max-width: 295px;width: 100%;padding: 24px 24px 16px;text-align: center;">
|
||
<div style="font-size: 18px;font-weight: 700;color: var(--gray-900);margin-bottom: 8px;">退出登录</div>
|
||
<div style="font-size: 14px;color: var(--gray-500);line-height: 22px;margin-bottom: 24px;">退出后将无法继续累积金币收益</div>
|
||
<div style="display: flex;gap: 12px;">
|
||
<button onclick="closeLogoutConfirm()" style="flex: 1;padding: 12px;border-radius: 12px;border: 1px solid var(--gray-300);background: #fff;font-size: 15px;font-weight: 600;color: var(--gray-700);cursor: pointer;">取消</button>
|
||
<button onclick="doLogout()" style="flex: 1;padding: 12px;border-radius: 12px;border: none;background: var(--error);font-size: 15px;font-weight: 600;color: #fff;cursor: pointer;">确认退出</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 注销账号确认弹窗 -->
|
||
<div id="deleteConfirm" style="display: none;position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 260;background: rgba(0,0,0,.45);align-items: center;justify-content: center;padding: 40px 32px;overflow: hidden;">
|
||
<div style="background: #fff;border-radius: 18px;max-width: 295px;width: 100%;padding: 24px 24px 16px;text-align: center;">
|
||
<div style="font-size: 48px;margin-bottom: 12px;">⚠️</div>
|
||
<div style="font-size: 18px;font-weight: 700;color: var(--error);margin-bottom: 8px;">确认注销账号?</div>
|
||
<div style="font-size: 14px;color: var(--gray-500);line-height: 22px;margin-bottom: 8px;">注销后以下数据将<span style="color: var(--error);font-weight: 600;">永久删除且无法恢复</span>:</div>
|
||
<div style="text-align: left;background: var(--gray-50);border-radius: 8px;padding: 12px 16px;margin-bottom: 24px;font-size: 13px;color: var(--gray-600);line-height: 22px;">
|
||
· 全部金币余额和现金收益<br>
|
||
· 比价记录和购买战绩<br>
|
||
· 邀请好友关系和返佣收益
|
||
</div>
|
||
<div style="display: flex;gap: 12px;">
|
||
<button onclick="closeDeleteConfirm()" style="flex: 1;padding: 12px;border-radius: 12px;border: 1px solid var(--gray-300);background: #fff;font-size: 15px;font-weight: 600;color: var(--gray-700);cursor: pointer;">我再想想</button>
|
||
<button onclick="doDeleteAccount()" style="flex: 1;padding: 12px;border-radius: 12px;border: none;background: var(--error);font-size: 15px;font-weight: 600;color: #fff;cursor: pointer;">确认注销</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== FEEDBACK ===== -->
|
||
<!-- screen #feedback removed for split -->
|
||
|
||
<!-- ===== 领券流程屏(与新手引导同款,复用 demoSteps 的前 6 步:弹窗 → agentFlow → 完成 toast) ===== -->
|
||
<!-- screen #comparing removed for split -->
|
||
|
||
<!-- ===== 一键领券 · 完成 toast(提到 device 级别,让结算弹窗显示在首页背景上而非 agent 流的截图上) ===== -->
|
||
<!-- ⚠️ SYNC: 与 prototypes/app/coupon/index.html 的 #phase-done 同步维护,改这里前先看那边 -->
|
||
<!-- 同步对象:本 toast 的 DOM 结构 + .coupon-done-k 系列 class 的 CSS -->
|
||
<!-- 不同步:onclick="onHomeCouponClaimDone()" 本地回调(首页特有) -->
|
||
<div id="demoCouponDoneToast" style="display: none;position: absolute;inset: 0;z-index: 200;">
|
||
<div class="coupon-done-k-mask"></div>
|
||
<div class="coupon-done-k">
|
||
<div class="coupon-done-logo">
|
||
<span class="logo-mark">
|
||
<span style="font-size: 12px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span>
|
||
</span>
|
||
</div>
|
||
<div class="v6-sparkle s1"></div>
|
||
<div class="v6-sparkle s2"></div>
|
||
<div class="v6-sparkle s3"></div>
|
||
<div class="v6-sparkle s4"></div>
|
||
<div class="v6-head">
|
||
<div class="lead-line lead-line-inline">今日已从<span id="couponDoneFromLogos" style="display:contents;"></span>帮您领取</div>
|
||
<div class="num-line"><span class="rest" style="margin-right: 6px;">共</span><span class="num" id="demoCouponDoneCount">0</span><span class="rest">张优惠券</span></div>
|
||
</div>
|
||
<div class="v6-pocket">
|
||
<div class="v6-pocket-notch"></div>
|
||
<div class="v6-expiry">
|
||
<span class="time-box" id="cdH">23</span>:<span class="time-box" id="cdM">58</span>:<span class="time-box" id="cdS">27</span> 后失效
|
||
</div>
|
||
<button class="v6-cta" onclick="onHomeCouponClaimDone()">开心收下,立即使用</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== 一键领券 · 平台选择弹窗(device 级 overlay,显示在首页之上) ===== -->
|
||
<!-- ⚠️ SYNC: 与 prototypes/app/coupon/index.html 的 #phase-prompt 同步维护,改这里前先看那边 -->
|
||
<!-- 同步对象:本弹窗的 DOM 结构 + #couponPlatformGrid 渲染逻辑 -->
|
||
<!-- 不同步:本弹窗外层有 mask 关闭与 X 按钮(首页可关闭);标准模块 fade 进入无 mask 关闭 -->
|
||
<div id="demoCouponPrompt" style="display: none;position: absolute;inset: 0;z-index: 18;background: rgba(0,0,0,.55);align-items: center;justify-content: center;padding: 24px;" onclick="onCouponPromptMaskClick(event)">
|
||
<div id="demoCouponPromptCard" style="width: 100%;max-width: 330px;animation: fadeInUp .45s cubic-bezier(.34,1.56,.64,1);position: relative;">
|
||
<div style="background: linear-gradient(180deg,#FF7567 0%,#F44C43 56%,#ED3F36 100%);border-radius: 24px;padding: 32px 16px 24px;width: 100%;box-shadow: 0 16px 48px rgba(220,60,50,.36);border: 1px solid rgba(255,255,255,.2);text-align: center;position: relative;">
|
||
<div onclick="closeHomeCouponClaim()" style="position: absolute;top: 12px;right: 12px;width: 28px;height: 28px;border-radius: 14px;background: rgba(255,255,255,.2);display: flex;align-items: center;justify-content: center;cursor: pointer;font-size: 14px;color: #fff;font-weight: 600;line-height: 1;z-index: 2;">✕</div>
|
||
<img src="assets/welfare/index/coin-icon.png" alt="" style="position: absolute;top: 12px;right: 48px;width: 34px;height: 34px;z-index: 2;filter: drop-shadow(0 2px 4px rgba(150,40,0,.3));">
|
||
<span style="position:absolute;width:7px;height:7px;background:#FFE066;border-radius:50%;box-shadow:0 0 8px #FFE082;animation:kSparkleTwinkle 1.5s infinite ease-in-out;z-index:2;top:16px;left:22px;"></span>
|
||
<span style="position:absolute;width:5px;height:5px;background:#FFE066;border-radius:50%;box-shadow:0 0 7px #FFE082;animation:kSparkleTwinkle 1.5s infinite ease-in-out;animation-delay:.5s;z-index:2;top:58px;left:16px;"></span>
|
||
<span style="position:absolute;width:4px;height:4px;background:#FFE066;border-radius:50%;box-shadow:0 0 6px #FFE082;animation:kSparkleTwinkle 1.5s infinite ease-in-out;animation-delay:.9s;z-index:2;top:100px;left:30px;"></span>
|
||
<span style="position:absolute;width:6px;height:6px;background:#FFE066;border-radius:50%;box-shadow:0 0 8px #FFE082;animation:kSparkleTwinkle 1.5s infinite ease-in-out;animation-delay:.3s;z-index:2;top:60px;right:24px;"></span>
|
||
<span style="position:absolute;width:4px;height:4px;background:#FFE066;border-radius:50%;box-shadow:0 0 6px #FFE082;animation:kSparkleTwinkle 1.5s infinite ease-in-out;animation-delay:.7s;z-index:2;top:104px;right:30px;"></span>
|
||
<img src="assets/shared/logos/sb-brand.png" alt="傻瓜比价" style="width: 52px;height: 52px;border-radius: 12px;display: block;margin: 0 auto 16px;box-shadow: 0 4px 14px rgba(0,0,0,.25);">
|
||
<div style="font-size: 18px;font-weight: 900;color: #fff;line-height: 1.4;margin-bottom: 8px;text-shadow: 0 1px 2px rgba(120,10,5,.3);">您仍未领取今日大额优惠券</div>
|
||
<div style="display: inline-flex;align-items: center;gap: 6px;background: #fff;color: #ED3F36;font-size: 12px;font-weight: 800;padding: 4px 12px;border-radius: 32px;margin-bottom: 12px;box-shadow: 0 2px 8px rgba(120,10,5,.25);">
|
||
<svg width="14" height="12" viewBox="0 0 22 18" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M2 7.2 V10.8 A1.4 1.4 0 0 0 3.4 12.2 H5.4 L11.2 16.4 A0.8 0.8 0 0 0 12.5 15.7 V2.3 A0.8 0.8 0 0 0 11.2 1.6 L5.4 5.8 H3.4 A1.4 1.4 0 0 0 2 7.2 Z" fill="#ED3F36"/><path d="M14.6 4.4 C16 6 16 12 14.6 13.6" stroke="#ED3F36" stroke-width="1.4" stroke-linecap="round" fill="none"/><path d="M16.8 2.6 C19.2 5.2 19.2 12.8 16.8 15.4" stroke="#ED3F36" stroke-width="1.4" stroke-linecap="round" fill="none"/><circle cx="6.2" cy="14.4" r="1.5" fill="#ED3F36"/></svg>
|
||
先领券,再比价
|
||
</div>
|
||
<div style="background: #fff;border-radius: 18px;padding: 12px 8px 12px;margin-bottom: 8px;box-shadow: 0 4px 12px rgba(120,10,5,.2);">
|
||
<div id="couponPlatformGrid" style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;"></div>
|
||
</div>
|
||
<div style="font-size: 11px;color: #FFE2D8;font-weight: 500;letter-spacing: .1px;line-height: 1.2;margin: 0 4px 12px 0;text-align: right;">将在以上平台领取</div>
|
||
<div style="position: relative;">
|
||
<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFE27A 0%,#FFC400 100%);color: #1a1a1a;font-weight: 900;box-shadow: inset 0 1px 0 rgba(255,255,255,.75), 0 8px 20px rgba(0,0,0,.28);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- F-2 改版:比价平台选择 · 中央模态(device 级 overlay) -->
|
||
<div class="home-picker-mask" id="homePickerMask">
|
||
<div class="home-picker-modal">
|
||
<div class="home-picker-close" onclick="closeHomePicker()">✕</div>
|
||
<div class="home-picker-emoji">🍱</div>
|
||
<div class="home-picker-title">请选择您常用的平台</div>
|
||
<div class="home-picker-sub">进入平台选好商品后,<strong>AI 一键替你比多家</strong></div>
|
||
<div class="home-picker-grid" id="homePickerGrid"><!-- 内容由 renderHomePickerPlatforms() 动态渲染 --></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== 签到弹窗 ===== -->
|
||
<style>
|
||
@keyframes checkinPopIn { 0%{transform: translateY(18px) scale(.96);opacity: 0;} 100%{transform: translateY(0) scale(1);opacity: 1;} }
|
||
.checkin-popup-layer {
|
||
display: none;
|
||
position: absolute;
|
||
inset: 0;
|
||
z-index: 200;
|
||
background: rgba(0,0,0,.55);
|
||
backdrop-filter: blur(1px);
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0 16px;
|
||
overflow: hidden;
|
||
}
|
||
.checkin-popup-card {
|
||
width: 100%;
|
||
border-radius: 18px;
|
||
padding: 16px 12px 12px;
|
||
background: linear-gradient(180deg, #FFE0B2 0%, #FFFDE7 30%, #FFFFFF 72%);
|
||
box-shadow: 0 20px 40px rgba(0,0,0,.12);
|
||
position: relative;
|
||
overflow: visible;
|
||
animation: checkinPopIn .26s cubic-bezier(.22,1,.36,1);
|
||
}
|
||
.checkin-close {
|
||
position: absolute;
|
||
left: 50%;
|
||
bottom: -52px;
|
||
width: 34px;
|
||
height: 34px;
|
||
transform: translateX(-50%);
|
||
border: none;
|
||
border-radius: 50%;
|
||
background: rgba(255,255,255,.58);
|
||
color: rgba(0,0,0,.46);
|
||
box-shadow: 0 6px 18px rgba(0,0,0,.08);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 22px;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
z-index: 4;
|
||
}
|
||
.checkin-banner {
|
||
position: relative;
|
||
z-index: 2;
|
||
width: 206px;
|
||
height: 16px;
|
||
margin: -4px auto 8px;
|
||
border-radius: 999px;
|
||
background: rgba(255,255,255,.92);
|
||
box-shadow: 0 4px 14px rgba(255,174,0,.14);
|
||
border: 1px solid rgba(255,184,0,.24);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 4px;
|
||
color: #7A4F00;
|
||
font-size: 10px;
|
||
font-weight: 600;
|
||
white-space: nowrap;
|
||
}
|
||
.checkin-banner .star {
|
||
width: 9px;
|
||
height: 9px;
|
||
background: #FFB300;
|
||
clip-path: polygon(50% 0%, 62% 37%, 100% 50%, 62% 63%, 50% 100%, 38% 63%, 0% 50%, 38% 37%);
|
||
flex-shrink: 0;
|
||
}
|
||
.checkin-title {
|
||
position: relative;
|
||
z-index: 2;
|
||
margin: 0;
|
||
text-align: center;
|
||
color: #1A1A1A;
|
||
font-size: 20px;
|
||
line-height: 1.1;
|
||
font-weight: 900;
|
||
letter-spacing: 0;
|
||
}
|
||
.checkin-sub {
|
||
position: relative;
|
||
z-index: 2;
|
||
margin-top: 8px;
|
||
text-align: center;
|
||
color: #666;
|
||
font-size: 11px;
|
||
line-height: 1.2;
|
||
font-weight: 500;
|
||
white-space: nowrap;
|
||
}
|
||
.checkin-sub b {
|
||
color: #FF6A00;
|
||
font-weight: 600;
|
||
}
|
||
.checkin-rewards {
|
||
position: relative;
|
||
z-index: 2;
|
||
margin-top: 12px;
|
||
display: grid;
|
||
grid-template-columns: repeat(5, 1fr);
|
||
gap: 6px;
|
||
}
|
||
.checkin-reward-card {
|
||
position: relative;
|
||
min-height: 64px;
|
||
border-radius: 8px;
|
||
background: rgba(255,255,255,.88);
|
||
border: 1px solid #F0F0F0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 6px;
|
||
padding: 8px 2px 6px;
|
||
color: #1A1A1A;
|
||
font-weight: 600;
|
||
box-shadow: inset 0 1px 0 rgba(255,255,255,.75);
|
||
}
|
||
.checkin-reward-card.claimed {
|
||
background: rgba(247,247,247,.96);
|
||
border-color: #E5E5E5;
|
||
box-shadow: none;
|
||
color: #999999;
|
||
}
|
||
.checkin-reward-card.current {
|
||
border-color: #FFB300;
|
||
box-shadow: 0 8px 15px rgba(255,184,0,.14);
|
||
background: rgba(255,255,255,.96);
|
||
}
|
||
.checkin-reward-icon {
|
||
min-height: 26px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #999999;
|
||
font-size: 10px;
|
||
line-height: 1;
|
||
font-weight: 850;
|
||
white-space: nowrap;
|
||
}
|
||
.checkin-reward-card img {
|
||
width: 29px;
|
||
height: 29px;
|
||
object-fit: contain;
|
||
display: block;
|
||
}
|
||
.checkin-reward-card .icon-chest {
|
||
width: 36px;
|
||
height: 33px;
|
||
}
|
||
.checkin-reward-amount {
|
||
color: #1A1A1A;
|
||
font-size: 12px;
|
||
line-height: 1;
|
||
font-weight: 850;
|
||
}
|
||
.checkin-reward-card.claimed .checkin-reward-amount {
|
||
color: #999999;
|
||
}
|
||
.checkin-progress {
|
||
margin: 12px 0 0;
|
||
position: relative;
|
||
height: 42px;
|
||
display: grid;
|
||
grid-template-columns: repeat(5, 1fr);
|
||
gap: 6px;
|
||
align-items: start;
|
||
}
|
||
.checkin-progress-lines {
|
||
position: absolute;
|
||
top: 4.5px;
|
||
left: 0;
|
||
right: 0;
|
||
height: 3px;
|
||
pointer-events: none;
|
||
z-index: 0;
|
||
}
|
||
.checkin-segment {
|
||
position: absolute;
|
||
top: 0;
|
||
height: 3px;
|
||
border-radius: 32px;
|
||
}
|
||
.checkin-segment.solid {
|
||
background: var(--line-color);
|
||
}
|
||
.checkin-segment.dashed {
|
||
background-repeat: no-repeat;
|
||
}
|
||
.checkin-node {
|
||
position: relative;
|
||
z-index: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 8px;
|
||
color: #666;
|
||
font-size: 10px;
|
||
line-height: 1;
|
||
white-space: nowrap;
|
||
}
|
||
.checkin-dot {
|
||
box-sizing: border-box;
|
||
width: 12px;
|
||
height: 12px;
|
||
border-radius: 50%;
|
||
background: #FFFFFF;
|
||
border: 2px solid #DDDDDD;
|
||
}
|
||
.checkin-node.done .checkin-dot {
|
||
background: #FFB300;
|
||
border-color: #FFB300;
|
||
}
|
||
.checkin-node.current .checkin-dot {
|
||
background: #FFFFFF;
|
||
border: 2.5px solid #FFB300;
|
||
}
|
||
.checkin-popup-cta {
|
||
position: relative;
|
||
z-index: 2;
|
||
margin: 8px auto 0;
|
||
width: 252px;
|
||
height: 40px;
|
||
border: none;
|
||
border-radius: 24px;
|
||
background: linear-gradient(180deg, #FFE066 0%, #FFB300 100%);
|
||
color: #1A1A1A;
|
||
font-size: 17px;
|
||
font-weight: 900;
|
||
box-shadow: 0 14px 28px rgba(255,184,0,.22);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 4px;
|
||
cursor: pointer;
|
||
font-family: inherit;
|
||
}
|
||
.checkin-popup-cta img {
|
||
width: 18px;
|
||
height: 18px;
|
||
object-fit: contain;
|
||
display: block;
|
||
}
|
||
.checkin-popup-cta b {
|
||
color: #FF6A00;
|
||
font-size: 22px;
|
||
line-height: 1;
|
||
}
|
||
</style>
|
||
<div id="checkinPopup" class="checkin-popup-layer">
|
||
<div class="checkin-popup-card" onclick="event.stopPropagation()">
|
||
<button class="checkin-close" onclick="closeCheckinPopup()" aria-label="关闭">×</button>
|
||
<div class="checkin-banner" id="checkinBanner"><span class="star"></span>连续签到14天 最高可领2888金币</div>
|
||
<h2 class="checkin-title" id="checkinPopupTitle">签到领取今日金币</h2>
|
||
<div class="checkin-sub" id="checkinPopupSub">已连续签到 <b>2</b> 天,今天可领 <b>220</b> 金币</div>
|
||
|
||
<div class="checkin-rewards" id="checkinRewards" aria-label="连续签到奖励">
|
||
<div class="checkin-reward-card claimed">
|
||
<div class="checkin-reward-icon">已领取</div>
|
||
<div class="checkin-reward-amount">180</div>
|
||
</div>
|
||
<div class="checkin-reward-card claimed">
|
||
<div class="checkin-reward-icon">已领取</div>
|
||
<div class="checkin-reward-amount">380</div>
|
||
</div>
|
||
<div class="checkin-reward-card current">
|
||
<div class="checkin-reward-icon"><img src="assets/welfare/index/checkin-coin-single.png" alt=""></div>
|
||
<div class="checkin-reward-amount">220</div>
|
||
</div>
|
||
<div class="checkin-reward-card">
|
||
<div class="checkin-reward-icon"><img src="assets/welfare/index/checkin-coin-single.png" alt=""></div>
|
||
<div class="checkin-reward-amount">260</div>
|
||
</div>
|
||
<div class="checkin-reward-card">
|
||
<div class="checkin-reward-icon"><img src="assets/welfare/index/checkin-coins-600.png" alt=""></div>
|
||
<div class="checkin-reward-amount">888</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="checkin-progress" id="checkinProgress" aria-label="签到进度">
|
||
<div class="checkin-progress-lines" id="checkinProgressLines"></div>
|
||
<div class="checkin-node done" data-day="1"><span class="checkin-dot"></span><span>第1天</span></div>
|
||
<div class="checkin-node done" data-day="2"><span class="checkin-dot"></span><span>第2天</span></div>
|
||
<div class="checkin-node current" data-day="3"><span class="checkin-dot"></span><span>今天</span></div>
|
||
<div class="checkin-node" data-day="4"><span class="checkin-dot"></span><span>明天</span></div>
|
||
<div class="checkin-node" data-day="7"><span class="checkin-dot"></span><span>第7天</span></div>
|
||
</div>
|
||
|
||
<button id="checkinBtn" class="checkin-popup-cta" onclick="doCheckin()">签到领 <img src="assets/welfare/index/checkin-coin-single.png" alt=""><b>220</b></button>
|
||
<button id="checkinReminderBtn" class="checkin-popup-cta" onclick="doCheckinReminder()" style="display: none;">打开签到提醒</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== 签到提醒权限弹窗 ===== -->
|
||
<div id="calendarPermPopup" style="display: none;position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 250;background: rgba(0,0,0,.55);align-items: center;justify-content: center;padding: 40px 24px;overflow: hidden;">
|
||
<div style="background: #fff;border-radius: 18px;max-width: 327px;width: 100%;padding: 24px 24px;position: relative;">
|
||
<div onclick="closeCalendarPerm()" style="position: absolute;top: 14px;right: 14px;width: 28px;height: 28px;border-radius: 14px;background: var(--gray-100);display: flex;align-items: center;justify-content: center;cursor: pointer;font-size: 14px;color: var(--gray-500);">✕</div>
|
||
<div style="text-align: center;">
|
||
<div style="font-size: 20px;font-weight: 700;color: var(--gray-900);margin-bottom: 8px;">日历权限未开启</div>
|
||
<div style="font-size: 14px;color: var(--gray-500);line-height: 1.6;">开启提醒失败,请前往设置-傻瓜比价打开日历权限后重试</div>
|
||
</div>
|
||
<button onclick="closeCalendarPerm()" style="width: 100%;margin-top: 16px;background: linear-gradient(180deg,#FFE066 0%,#FFC400 100%);color: #1A1A1A;border: none;padding: 12px;border-radius: 24px;font-size: 17px;font-weight: 700;cursor: pointer;box-shadow: inset 0 1px 0 rgba(255,255,255,.7), 0 2px 6px rgba(255,179,0,.35);">去开启</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 页面导航提示 -->
|
||
|
||
<!-- ===== 全部权限开启完成 · 祝贺弹窗(A/B/C 内容动态注入) ===== -->
|
||
<div id="celebrationModal" onclick="closeCelebrationModal()" style="display: none;position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 260;background: rgba(0,0,0,.55);align-items: center;justify-content: center;padding: 0 24px;overflow: hidden;">
|
||
<div onclick="event.stopPropagation()" id="celebrationModalCard" style="background: #fff;border-radius: 24px;width: 100%;max-width: 327px;padding: 24px 24px 24px;position: relative;animation: safetyPopIn .3s cubic-bezier(.22,1,.36,1);"></div>
|
||
</div>
|
||
|
||
<!-- ===== 权限未开启提示弹窗(居中卡片式,复用于无障碍/悬浮窗) ===== -->
|
||
<div id="safetyModal" onclick="closeSafetyModal()" style="display: none;position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 250;background: rgba(0,0,0,.55);align-items: center;justify-content: center;padding: 0 24px;overflow: hidden;">
|
||
<div onclick="event.stopPropagation()" style="background: #fff;border-radius: 24px;width: 100%;max-width: 327px;padding: 24px 24px 24px;position: relative;animation: safetyPopIn .3s cubic-bezier(.22,1,.36,1);">
|
||
<!-- 关闭按钮 -->
|
||
<button onclick="closeSafetyModal()" aria-label="关闭" style="position: absolute;top: 14px;right: 14px;width: 28px;height: 28px;border-radius: 14px;background: #f0f0f0;border: none;cursor: pointer;font-size: 16px;line-height: 1;color: #666;display: flex;align-items: center;justify-content: center;padding: 0;z-index: 2;">×</button>
|
||
<!-- 警示图标 -->
|
||
<div style="width: 60px;height: 60px;border-radius: 32px;background: #FFF3E0;display: flex;align-items: center;justify-content: center;margin: 0 auto 12px;font-size: 28px;">⚠️</div>
|
||
<!-- 标题 -->
|
||
<div id="safetyModalTitle" style="font-size: 20px;font-weight: 800;color: var(--gray-900);text-align: center;margin-bottom: 8px;">比价功能未开启</div>
|
||
<div style="font-size: 13px; color: rgb(0, 0, 0); line-height: 20px; text-align: center; margin-bottom: 16px; white-space: nowrap;">
|
||
<span id="safetyModalBody">在「已安装的应用」中找到「傻瓜比价」并开启</span><span id="safetyModalPermName" style="display: none;">无障碍</span>
|
||
</div>
|
||
<!-- 安全承诺区(压缩版) -->
|
||
<div id="safetyPromiseBlock" style="background: var(--gray-100);border-radius: 14px;padding: 12px 12px 12px;margin-bottom: 16px;">
|
||
<div style="font-size: 14px;font-weight: 700;color: var(--gray-700);margin-bottom: 8px;">我们的安全承诺</div>
|
||
<ul style="list-style: disc;padding-left: 16px;margin: 0;font-size: 12px;color: var(--gray-500);line-height: 19px;">
|
||
<li style="margin-bottom: 6px;">仅在您开启比价时启用,用完即停</li>
|
||
<li style="margin-bottom: 6px;">全程端侧加密,全方位守护您的隐私</li>
|
||
<li>您随时可在设置中关闭</li>
|
||
</ul>
|
||
</div>
|
||
<!-- 底部按钮 -->
|
||
<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;" onclick="goToPermFromSafetyModal()">去开启</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== 系统询问弹窗:位置权限(Android 系统弹窗风格,对齐 onboarding-v2 permLocationPopup) ===== -->
|
||
<div id="locSysPopup" onclick="closeLocSysPopup('dismiss')" style="display: none;position: absolute;inset: 0px;z-index: 280;background: rgba(0,0,0,.45);align-items: flex-end;justify-content: center;padding: 40px 12px 16px;overflow: hidden;">
|
||
<div onclick="event.stopPropagation()" style="background: #fff;border-radius: 24px;max-width: 460px;width: 100%;padding: 24px 24px 8px;text-align: left;">
|
||
<div style="font-size: 16px;font-weight: 600;color: #1A1A1A;margin-bottom: 12px;">允许"傻瓜比价"获取此设备的位置信息?</div>
|
||
<div style="font-size: 14px;color: #666666;line-height: 20px;margin-bottom: 16px;">用于获取附近美食优惠和配送范围,为你推荐更精准的比价结果。</div>
|
||
<div style="display: flex;flex-direction: column;gap: 0;padding-top: 4px;border-top: 1px solid #F5F5F5;">
|
||
<button onclick="closeLocSysPopup('whileUsing')" style="background: none;border: none;border-bottom: 1px solid #F5F5F5;padding: 12px 0;font-size: 14px;font-weight: 600;color: #1a73e8;cursor: pointer;text-align: left;">仅使用期间允许</button>
|
||
<button onclick="closeLocSysPopup('once')" style="background: none;border: none;border-bottom: 1px solid #F5F5F5;padding: 12px 0;font-size: 14px;font-weight: 600;color: #1a73e8;cursor: pointer;text-align: left;">允许本次使用</button>
|
||
<button onclick="closeLocSysPopup('denied')" style="background: none;border: none;padding: 12px 0;font-size: 14px;font-weight: 600;color: #1a73e8;cursor: pointer;text-align: left;">禁止</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- ===== 反馈底部半屏面板 ===== -->
|
||
<style>
|
||
@keyframes sheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
|
||
.feedback-sheet { animation: sheetUp .3s ease-out; }
|
||
.fb-platform.selected { border-color: #FF5722 !important; background: #FFF3E0; color: #FF5722; }
|
||
</style>
|
||
<div id="feedbackSheet" style="display: none;position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 260;overflow: hidden;">
|
||
<!-- 遮罩 -->
|
||
<div onclick="closeFeedbackSheet()" style="position: absolute;inset: 0;background: rgba(0,0,0,.4);"></div>
|
||
<!-- 面板 -->
|
||
<div class="feedback-sheet" style="position: absolute;bottom: 0;left: 0;right: 0;background: #fff;border-radius: 18px 18px 0 0;max-height: 75%;overflow-y: auto;">
|
||
<!-- 拖动条 -->
|
||
<div style="padding: 12px 0 0;text-align: center;"><div style="width: 40px;height: 4px;border-radius: 4px;background: var(--gray-300);margin: 0 auto;"></div></div>
|
||
<!-- 标题 -->
|
||
<div style="padding: 16px 16px 12px;">
|
||
<div style="font-size: 18px;font-weight: 700;">比价结果反馈</div>
|
||
<div style="font-size: 13px;color: var(--gray-500);margin-top: 4px;">审核通过可获得 <span style="color: #FF5722;font-weight: 600;">2,000 金币</span> 奖励</div>
|
||
</div>
|
||
<!-- 步骤1:选择反馈类型 -->
|
||
<div id="fbStep1" style="padding: 0 16px 16px;">
|
||
<div style="font-size: 14px;font-weight: 600;color: var(--gray-700);margin-bottom: 12px;">选择反馈类型</div>
|
||
<div onclick="selectFbType('lower_price')" style="display: flex;align-items: center;gap: 12px;padding: 16px;border: 1.5px solid var(--gray-200);border-radius: 14px;cursor: pointer;margin-bottom: 8px;transition: all .15s;" id="fbTypeLower">
|
||
<div style="width: 44px;height: 44px;border-radius: 12px;background: linear-gradient(135deg,#FFF3E0,#FFE0B2);display: flex;align-items: center;justify-content: center;font-size: 22px;flex-shrink: 0;">💰</div>
|
||
<div><div style="font-size: 15px;font-weight: 600;">我发现了更低价格</div><div style="font-size: 12px;color: var(--gray-500);margin-top: 2px;">在其他平台找到了同款更便宜的</div></div>
|
||
<span style="margin-left: auto;font-size: 18px;color: var(--gray-400);">›</span>
|
||
</div>
|
||
<div onclick="selectFbType('wrong_match')" style="display: flex;align-items: center;gap: 12px;padding: 16px;border: 1.5px solid var(--gray-200);border-radius: 14px;cursor: pointer;transition: all .15s;" id="fbTypeWrong">
|
||
<div style="width: 44px;height: 44px;border-radius: 12px;background: linear-gradient(135deg,#E3F2FD,#E3F2FD);display: flex;align-items: center;justify-content: center;font-size: 22px;flex-shrink: 0;">❌</div>
|
||
<div><div style="font-size: 15px;font-weight: 600;">外卖不是同一家</div><div style="font-size: 12px;color: var(--gray-500);margin-top: 2px;">比价结果中有外卖匹配错误</div></div>
|
||
<span style="margin-left: auto;font-size: 18px;color: var(--gray-400);">›</span>
|
||
</div>
|
||
</div>
|
||
<!-- 步骤2A:更低价格表单 -->
|
||
<div id="fbFormLower" style="display: none;padding: 0 16px 24px;">
|
||
<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 16px;">
|
||
<button class="btn-back" onclick="backToFbStep1()" aria-label="返回上一步"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15 6L9 12L15 18" stroke="#1A1A1A" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg></button>
|
||
<div style="font-size: 15px;font-weight: 600;">我发现了更低价格</div>
|
||
</div>
|
||
<div style="font-size: 14px;font-weight: 600;color: var(--gray-700);margin-bottom: 8px;">粘贴外卖链接</div>
|
||
<input type="text" placeholder="粘贴更低价外卖的链接" style="width: 100%;border: 1.5px solid var(--gray-200);border-radius: 12px;padding: 12px;font-size: 14px;outline: none;margin-bottom: 16px;">
|
||
<div style="font-size: 14px;font-weight: 600;color: var(--gray-700);margin-bottom: 8px;">上传截图 <span style="font-weight: 400;color: var(--gray-400);">(含价格信息)</span></div>
|
||
<div style="display: flex;gap: 8px;margin-bottom: 16px;">
|
||
<div style="width: 80px;height: 80px;border: 1.5px dashed var(--gray-300);border-radius: 12px;display: flex;align-items: center;justify-content: center;font-size: 24px;color: var(--gray-400);cursor: pointer;">+</div>
|
||
<div style="width: 80px;height: 80px;border: 1.5px dashed var(--gray-300);border-radius: 12px;display: flex;align-items: center;justify-content: center;font-size: 24px;color: var(--gray-400);cursor: pointer;">+</div>
|
||
</div>
|
||
<button onclick="submitFeedback()" style="width: 100%;background: var(--primary);border: none;padding: 12px;border-radius: 14px;font-size: 16px;font-weight: 700;color: #1a1a1a;cursor: pointer;">提交反馈</button>
|
||
</div>
|
||
<!-- 步骤2B:非同款表单 -->
|
||
<div id="fbFormWrong" style="display: none;padding: 0 16px 24px;">
|
||
<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 16px;">
|
||
<button class="btn-back" onclick="backToFbStep1()" aria-label="返回上一步"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15 6L9 12L15 18" stroke="#1A1A1A" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg></button>
|
||
<div style="font-size: 15px;font-weight: 600;">外卖不是同一家</div>
|
||
</div>
|
||
<div style="font-size: 14px;font-weight: 600;color: var(--gray-700);margin-bottom: 8px;">哪个平台的结果有误?</div>
|
||
<div id="fbPlatformList" style="display: flex;flex-wrap: wrap;gap: 8px;margin-bottom: 16px;"></div>
|
||
<div style="font-size: 14px;font-weight: 600;color: var(--gray-700);margin-bottom: 8px;">上传截图或描述问题</div>
|
||
<div style="display: flex;gap: 8px;margin-bottom: 12px;">
|
||
<div style="width: 80px;height: 80px;border: 1.5px dashed var(--gray-300);border-radius: 12px;display: flex;align-items: center;justify-content: center;font-size: 24px;color: var(--gray-400);cursor: pointer;">+</div>
|
||
</div>
|
||
<textarea placeholder="描述哪里不同(可选)" style="width: 100%;border: 1.5px solid var(--gray-200);border-radius: 12px;padding: 12px;font-size: 14px;outline: none;height: 60px;resize: none;font-family: inherit;margin-bottom: 16px;"></textarea>
|
||
<button onclick="submitFeedback()" style="width: 100%;background: var(--primary);border: none;padding: 12px;border-radius: 14px;font-size: 16px;font-weight: 700;color: #1a1a1a;cursor: pointer;">提交反馈</button>
|
||
</div>
|
||
<!-- 提交成功 -->
|
||
<div id="fbSuccess" style="display: none;padding: 24px 16px 32px;text-align: center;">
|
||
<div style="font-size: 48px;margin-bottom: 12px;">✅</div>
|
||
<div style="font-size: 18px;font-weight: 700;margin-bottom: 4px;">反馈已提交</div>
|
||
<div style="font-size: 14px;color: var(--gray-500);line-height: 22px;">系统正在验证,审核通过后<br><span style="color: #FF5722;font-weight: 600;">2,000 金币</span> 将自动到账</div>
|
||
<div style="font-size: 12px;color: var(--gray-400);margin-top: 12px;">审核结果将通过推送通知告知您</div>
|
||
<button onclick="closeFeedbackSheet()" style="margin-top: 16px;width: 100%;background: var(--primary);border: none;padding: 12px;border-radius: 14px;font-size: 16px;font-weight: 700;color: #1a1a1a;cursor: pointer;">知道了</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="nav-hint" id="navHint" style="display: none;"></div>
|
||
|
||
<!-- 结果页预览浮层 -->
|
||
<div id="resultPreviewOverlay" onclick="hideResultPreview()" style="display: none;position: absolute;inset: 0;z-index: 300;background: #fff;cursor: pointer;">
|
||
<img id="resultPreviewImg" src="" style="width: 100%;height: 100%;object-fit: cover;object-position: top;">
|
||
</div>
|
||
|
||
<!-- ===== 新手礼包弹窗 ===== -->
|
||
<div class="gift-overlay" id="welcomeGiftPopup">
|
||
<div class="gift-card" id="welcomeGiftCard">
|
||
<button class="gift-close" onclick="closeWelcomeGift(true)">✕</button>
|
||
<div class="gift-stage-a">
|
||
<div class="gift-confetti">🎉🎊✨🎊🎉</div>
|
||
<div class="gift-title">新手大礼包</div>
|
||
<div class="gift-subtitle">专享新客福利,开启领取</div>
|
||
</div>
|
||
<div class="gift-chest-wrap">
|
||
<div class="gift-chest-glow"></div>
|
||
<div class="gift-burst">
|
||
<div class="gift-burst-ray"></div>
|
||
<div class="gift-burst-ray"></div>
|
||
<div class="gift-burst-ray"></div>
|
||
<div class="gift-burst-ray"></div>
|
||
<div class="gift-burst-ray"></div>
|
||
<div class="gift-burst-ray"></div>
|
||
</div>
|
||
<div class="gift-chest-emoji" id="giftChestEmoji">🎁</div>
|
||
</div>
|
||
<div class="gift-amount" id="giftAmount">+5,000<span class="gift-amount-suffix">金币</span></div>
|
||
<div class="gift-amount-hint">已存入「福利」,随时可提现</div>
|
||
<button class="gift-btn" id="giftMainBtn" onclick="openGiftBox()">✨ 开启礼包</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 福利 tab 上方 +5000 飘字(device 级,z-index 高于 overlay) -->
|
||
<div class="tab-coin-badge" id="welfareTabBadge" style="z-index: 260;">+5,000 金币</div>
|
||
|
||
</div>
|
||
|
||
|
||
<script>
|
||
function showResultPreview(imgSrc) {
|
||
if (!imgSrc) return;
|
||
document.getElementById('resultPreviewImg').src = imgSrc;
|
||
document.getElementById('resultPreviewOverlay').style.display = 'block';
|
||
}
|
||
function hideResultPreview() {
|
||
document.getElementById('resultPreviewOverlay').style.display = 'none';
|
||
}
|
||
// 结果数据
|
||
// [WAIMAI-ONLY] 外卖比价结果数据 — 真实窑鸡王订单
|
||
const results = [
|
||
{
|
||
status: 'found',
|
||
platform: '淘宝',
|
||
platformIcon: 'assets/shared/logos/taobao.png',
|
||
shop: '窑鸡王(康营店)',
|
||
delivery: '商家自配',
|
||
lowest: true,
|
||
items: [
|
||
{ name: '招牌窑鸡★★ 整只-原味', spec: '原味 × 1', price: 69.9, original: 99.9 }
|
||
],
|
||
fees: [
|
||
{ label: '打包费', amount: 5 },
|
||
{ label: '配送费', amount: 5, original: 12, note: '惊喜减7元' }
|
||
],
|
||
discounts: [
|
||
{ label: '店铺活动/券', amount: 1 },
|
||
{ label: '平台红包(超级吃货卡)', amount: 21 }
|
||
],
|
||
totalPrice: 57.9,
|
||
totalSaved: 59,
|
||
bonuses: [{ label: '下单返豆', detail: '返110吃货豆' }],
|
||
resultImage: 'assets/onboarding/index/platform-flows/taobao/result.jpg'
|
||
},
|
||
{
|
||
status: 'found',
|
||
platform: '美团',
|
||
platformIcon: 'assets/shared/logos/meituan.png',
|
||
shop: '窑鸡王(康营店)',
|
||
delivery: '商家自配',
|
||
lowest: false,
|
||
items: [
|
||
{ name: '招牌窑鸡(整只)', spec: '1只, 招牌整只原味 × 1', price: 69.9 }
|
||
],
|
||
fees: [
|
||
{ label: '打包费', amount: 5 },
|
||
{ label: '配送费', amount: 5.8, original: 12, note: '活动减6.2元' }
|
||
],
|
||
discounts: [
|
||
{ label: '美团红包(神券包)', amount: 18 }
|
||
],
|
||
totalPrice: 62.7,
|
||
totalSaved: 24.2,
|
||
bonuses: [],
|
||
resultImage: 'assets/onboarding/index/platform-flows/meituan/result.jpg'
|
||
},
|
||
{
|
||
status: 'not-found',
|
||
platform: '京东',
|
||
platformIcon: 'assets/shared/logos/jd.png',
|
||
reason: '未找到店铺'
|
||
},
|
||
{
|
||
status: 'not-installed',
|
||
platform: '拼多多',
|
||
platformIcon: '', chipText: '拼', chipColor: '#E02E24'
|
||
}
|
||
];
|
||
|
||
// --- 同价 corner case 备用数据(取消注释可切换演示)---
|
||
// results[1].status = 'same-price';
|
||
// results[1].totalPrice = 57.9;
|
||
|
||
function renderFoundCard(r, idx, ctx) {
|
||
const isLowest = r.lowest;
|
||
const isUserOrig = ctx && ctx.userOrigId && r._id === ctx.userOrigId;
|
||
const borderColor = isLowest ? 'var(--primary)' : 'var(--gray-200)';
|
||
const cardBorder = isLowest ? '2px' : '1.5px';
|
||
const cardClass = isLowest ? 'card with-ribbon lowest' : 'card';
|
||
|
||
// 标识:最低价 → M2 斜挂红 ribbon(右上角);用户原选 → 描边方角 chip(店名旁 inline)
|
||
const lowestRibbon = isLowest ? '<img class="ribbon-vi" src="assets/shared/badges/lowest-price.png" alt="全网最低">' : '';
|
||
const userOrigChip = isUserOrig ? '<span class="badge-userorig">原选择</span>' : '';
|
||
|
||
// 收集所有 AI 帮领的优惠(配送费减免 + 优惠券 + 店铺活动)
|
||
const aiDiscountItems = [];
|
||
r.fees.forEach(f => {
|
||
if (f.note) aiDiscountItems.push({ label: f.note, amount: f.original - f.amount });
|
||
});
|
||
r.discounts.forEach(d => {
|
||
aiDiscountItems.push({ label: d.label, amount: d.amount });
|
||
});
|
||
|
||
// AI 优惠标签
|
||
const aiTagsHtml = aiDiscountItems.map(d =>
|
||
`<span style="display: inline-flex;align-items: center;gap: 2px;background: #E8F5E9;border-radius: 4px;padding: 2px 8px;font-size: 11px;color: #2E7D32;white-space: nowrap;">${d.label} <b>-¥${d.amount}</b></span>`
|
||
).join('');
|
||
|
||
// N2 chip:仅最低价 + 有正向价差时显示
|
||
let chipHtml = '';
|
||
if (isLowest && ctx && ctx.savings > 0) {
|
||
chipHtml = `<span class="save-chip-red"><span class="small">比原选择省</span>¥${ctx.savings}</span>`;
|
||
}
|
||
|
||
// CTA:新手引导里弱化购买入口,所有卡片统一使用"查看"浅灰次级胶囊
|
||
const ctaHtml = `<button class="result-cta" onclick="event.stopPropagation();showResultPreview('${r.resultImage || ''}')">查看<span class="arrow">›</span></button>`;
|
||
|
||
return `
|
||
<div class="${cardClass}" style="background: #fff;border-radius: 14px;padding: 12px 16px;border:${cardBorder} solid ${borderColor};position: relative;">
|
||
${lowestRibbon}
|
||
<!-- 头部:平台 logo + 店铺名 + 原选择 chip -->
|
||
<div style="display: flex;align-items: center;gap: 6px;${isLowest?'padding-right: 92px;':''}">
|
||
<img src="${r.platformIcon}" style="width: 28px;height: 28px;border-radius: 8px;flex-shrink: 0;" onerror="this.style.display='none'">
|
||
<span style="font-size: 14px;font-weight: 600;color: var(--gray-800);min-width: 0;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">${r.shop}</span>
|
||
${userOrigChip}
|
||
</div>
|
||
<!-- 傻瓜比价 AI 优惠 -->
|
||
<div style="margin-top: 8px;">
|
||
<div style="font-size: 12px;color: var(--gray-500);margin-bottom: 6px;">🤖 傻瓜比价已帮您领取以下优惠:</div>
|
||
<div style="display: flex;flex-wrap: wrap;gap: 4px;">
|
||
${aiTagsHtml}
|
||
</div>
|
||
</div>
|
||
<!-- 价格 + chip + CTA -->
|
||
<div style="display: flex;justify-content: space-between;align-items: center;margin-top: 12px;gap: 8px;">
|
||
<div style="display: flex;align-items: baseline;gap: 6px;flex-wrap: wrap;">
|
||
<span style="font-size: 13px;font-weight: 700;color: #FF5722;">¥</span>
|
||
<span style="font-size: 24px;font-weight: 800;color: #FF5722;line-height: 1;">${r.totalPrice}</span>
|
||
${chipHtml}
|
||
</div>
|
||
${ctaHtml}
|
||
</div>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
function renderNotFoundCard(r) {
|
||
// 从其他 found 结果中取店铺名
|
||
const shopName = (results.find(x => x.status === 'found') || {}).shop || '';
|
||
return `
|
||
<div style="background: #fff;border-radius: 14px;padding: 12px 16px;border: 1.5px solid var(--gray-200);position: relative;">
|
||
<!-- 头部:平台 -->
|
||
<div style="display: flex;align-items: center;gap: 8px;">
|
||
<img src="${r.platformIcon}" style="width: 28px;height: 28px;border-radius: 8px;" onerror="this.style.display='none'">
|
||
<span style="font-size: 14px;font-weight: 600;color: var(--gray-800);">${r.platform}</span>
|
||
</div>
|
||
<!-- 未找到提示 -->
|
||
<div style="margin-top: 12px;padding: 16px;background: var(--gray-50);border-radius: 8px;text-align: center;">
|
||
<div style="font-size: 13px;color: var(--gray-500);line-height: 20px;">该平台未找到「${shopName}」</div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
/* 未安装平台卡(方案A 轻量问号):橙色双问号占位 + 未安装标 + 灰色"去安装"按钮 */
|
||
function renderNotInstalledCard(r) {
|
||
const logoHtml = r.platformIcon
|
||
? `<img src="${r.platformIcon}" style="width: 28px;height: 28px;border-radius: 8px;flex-shrink: 0;" onerror="this.style.display='none'">`
|
||
: `<span style="width: 28px;height: 28px;border-radius: 8px;flex-shrink: 0;display: inline-flex;align-items: center;justify-content: center;background: ${r.chipColor || 'var(--gray-500)'};color: #fff;font-size: 15px;font-weight: 800;">${r.chipText || ''}</span>`;
|
||
return `
|
||
<div style="background: #fff;border-radius: 14px;padding: 12px 16px;border: 1.5px solid var(--gray-200);position: relative;">
|
||
<div style="display: flex;align-items: center;gap: 6px;">
|
||
${logoHtml}
|
||
<span style="font-size: 14px;font-weight: 600;color: var(--gray-800);min-width: 0;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">${r.platform}</span>
|
||
<span style="flex-shrink: 0;display: inline-flex;align-items: center;background: #FFF1EC;border: 1px solid rgba(255,87,34,.3);border-radius: 4px;padding: 2px 8px;font-size: 11px;font-weight: 600;color: #E0521F;white-space: nowrap;">未安装</span>
|
||
</div>
|
||
<div style="font-size: 12px;color: var(--gray-500);margin: 8px 0 6px;">🤖 就差这家没比,装上说不定更便宜</div>
|
||
<div style="display: flex;justify-content: space-between;align-items: center;margin-top: 12px;gap: 8px;">
|
||
<div style="display: flex;align-items: baseline;font-variant-numeric: tabular-nums;">
|
||
<span style="display: inline-flex;align-items: baseline;"><span style="font-size: 17px;font-weight: 800;color: #FF5722;line-height: 1;">¥</span><span style="font-size: 24px;font-weight: 800;color: #FF5722;line-height: 1;letter-spacing: -0.3px;">??</span></span>
|
||
</div>
|
||
<button class="result-cta">去安装<span class="arrow">›</span></button>
|
||
</div>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
function renderResults(containerId) {
|
||
const c = document.getElementById(containerId);
|
||
// 给每条结果赋稳定 id,便于 ctx 引用
|
||
results.forEach((r, i) => { if (r._id == null) r._id = '_r' + i; });
|
||
|
||
// 计算"用户原选"= 找到的非最低里最贵那条;savings = userOrig 价 - lowest 价
|
||
const foundResults = results.filter(r => r.status === 'found' || r.status === 'same-price');
|
||
const lowestResult = results.find(r => r.lowest);
|
||
const otherFound = foundResults.filter(r => !r.lowest);
|
||
const userResult = otherFound.length ? otherFound.reduce((a, b) => a.totalPrice >= b.totalPrice ? a : b) : null;
|
||
const savings = (lowestResult && userResult && userResult.totalPrice > lowestResult.totalPrice)
|
||
? (userResult.totalPrice - lowestResult.totalPrice).toFixed(1)
|
||
: 0;
|
||
const ctx = {
|
||
userOrigId: userResult ? userResult._id : null,
|
||
savings: Number(savings),
|
||
};
|
||
|
||
// 排序:lowest → found 按价格升序 → same-price → not-found
|
||
const order = { 'found': 1, 'same-price': 2, 'not-installed': 3, 'not-found': 4 };
|
||
const sorted = [...results].sort((a, b) => {
|
||
if (a.lowest && !b.lowest) return -1;
|
||
if (!a.lowest && b.lowest) return 1;
|
||
const oa = order[a.status] || 9, ob = order[b.status] || 9;
|
||
if (oa !== ob) return oa - ob;
|
||
if (a.totalPrice && b.totalPrice) return a.totalPrice - b.totalPrice;
|
||
return 0;
|
||
});
|
||
c.innerHTML = sorted.map((r, i) => {
|
||
if (r.status === 'not-found') return renderNotFoundCard(r);
|
||
if (r.status === 'not-installed') return renderNotInstalledCard(r);
|
||
return renderFoundCard(r, i, ctx);
|
||
}).join('');
|
||
}
|
||
|
||
function renderCelebrationSavings() {
|
||
const card = document.getElementById('celebSavingsCard');
|
||
if (!card) return;
|
||
card.innerHTML = `
|
||
<img src="assets/onboarding/index/first-banner.png" alt="恭喜您完成首次比价" style="display: block;width: 100%;height: auto;">
|
||
`;
|
||
}
|
||
|
||
// 无障碍全屏引导流程
|
||
const accessibilityImages = ['assets/onboarding/index/guide-1.jpg', 'assets/onboarding/index/guide-2.jpg', 'assets/onboarding/index/guide-3.jpg', 'assets/onboarding/index/guide-4.jpg'];
|
||
let accessibilityIdx = 0;
|
||
|
||
function startAccessibilityFlow() {
|
||
accessibilityIdx = 0;
|
||
document.getElementById('accessFlowImg').src = accessibilityImages[0];
|
||
document.getElementById('accessStep4Overlay').style.display = 'none';
|
||
go('accessibility-flow');
|
||
}
|
||
|
||
function nextAccessibilityStep() {
|
||
accessibilityIdx++;
|
||
if (accessibilityIdx < accessibilityImages.length) {
|
||
document.getElementById('accessFlowImg').src = accessibilityImages[accessibilityIdx];
|
||
// 无障碍4(index=3)显示允许/拒绝覆盖层,禁用全屏点击
|
||
if (accessibilityIdx === 3) {
|
||
document.getElementById('accessStep4Overlay').style.display = 'block';
|
||
}
|
||
}
|
||
}
|
||
|
||
function onAllowClick(e) {
|
||
e.stopPropagation();
|
||
document.getElementById('accessStep4Overlay').style.display = 'none';
|
||
go('permission-step2');
|
||
}
|
||
|
||
function onRejectClick(e) {
|
||
e.stopPropagation();
|
||
document.getElementById('accessStep4Overlay').style.display = 'none';
|
||
go('permission-step1');
|
||
// 权限未开启 → 弹出提示弹窗
|
||
setTimeout(function() { openSafetyModal('无障碍'); }, 300);
|
||
}
|
||
|
||
function openSafetyModal(permName) {
|
||
document.getElementById('safetyModalPermName').textContent = permName;
|
||
document.getElementById('safetyModalTitle').textContent =
|
||
permName === '悬浮窗' ? '比价按钮未开启' : '比价功能未开启';
|
||
// 文案随权限上下文切换:无障碍 → 在「已安装的应用」中找;悬浮窗 → 直接在列表中找
|
||
var bodyEl = document.getElementById('safetyModalBody');
|
||
if (bodyEl) {
|
||
bodyEl.textContent = permName === '悬浮窗'
|
||
? '在列表中找到「傻瓜比价」并开启'
|
||
: '在「已安装的应用」中找到「傻瓜比价」并开启';
|
||
}
|
||
// 仅无障碍弹窗显示安全承诺,悬浮窗弹窗隐藏
|
||
var promise = document.getElementById('safetyPromiseBlock');
|
||
if (promise) promise.style.display = (permName === '悬浮窗') ? 'none' : 'block';
|
||
document.getElementById('safetyModal').style.display = 'flex';
|
||
}
|
||
|
||
function closeSafetyModal() {
|
||
document.getElementById('safetyModal').style.display = 'none';
|
||
}
|
||
|
||
// 「继续开启」按钮:关弹窗 + 直接进入对应权限设置页
|
||
function goToPermFromSafetyModal() {
|
||
const permName = document.getElementById('safetyModalPermName').textContent;
|
||
closeSafetyModal();
|
||
if (permName === '悬浮窗') {
|
||
startOverlayFlow();
|
||
} else {
|
||
startAccessibilityFlow();
|
||
}
|
||
}
|
||
|
||
// 悬浮窗引导流程
|
||
function startOverlayFlow() {
|
||
go('overlay-flow');
|
||
}
|
||
|
||
function onOverlayAllowClick(e) {
|
||
e.stopPropagation();
|
||
go('productselect');
|
||
openCelebrationModal();
|
||
}
|
||
|
||
// ===== 祝贺弹窗(多版本) =====
|
||
var celebrationVariants = {
|
||
// V1 「轻收尾·重期待」:承上小灰,起下大黑,行为按钮含次要引导
|
||
v1: '' +
|
||
'<div style="display: flex;align-items: center;justify-content: center;gap: 6px;font-size: 12px;color: var(--gray-500);margin-bottom: 8px;"><span style="display: inline-flex;align-items: center;justify-content: center;width: 16px;height: 16px;border-radius: 8px;background: #22C55E;color: #fff;font-size: 11px;font-weight: 700;">✓</span>全部设置已完成</div>' +
|
||
'<div style="font-size: 24px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.3;margin-bottom: 8px;">下一步,体验<br>傻瓜式一键比价</div>' +
|
||
'<div style="font-size: 14px;color: var(--gray-600);text-align: center;margin-bottom: 24px;">先选一个你常用的外卖平台</div>' +
|
||
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;" onclick="closeCelebrationModal()">选个常用平台开始体验</button>',
|
||
|
||
// V2 「分割式」:顶部承上小条 + 中部起下标题 + 底部行为引导,节奏分明
|
||
v2: '' +
|
||
'<div style="text-align: center;margin-bottom: 12px;"><span style="display: inline-flex;align-items: center;gap: 6px;padding: 4px 12px;border-radius: 32px;background: #E8F5E9;color: #2E7D32;font-size: 12px;font-weight: 600;">✓ 已完成全部设置</span></div>' +
|
||
'<div style="font-size: 22px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.35;margin-bottom: 16px;">来体验傻瓜式<br>一键比价</div>' +
|
||
'<div style="height: 1px;background: var(--gray-200);margin-bottom: 16px;"></div>' +
|
||
'<div style="font-size: 13px;color: var(--gray-500);text-align: center;margin-bottom: 8px;">第一步</div>' +
|
||
'<div style="font-size: 15px;font-weight: 700;color: var(--gray-900);text-align: center;margin-bottom: 16px;">选择一个常用的外卖平台</div>' +
|
||
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;" onclick="closeCelebrationModal()">选个常用平台开始体验</button>',
|
||
|
||
// V3 「叙事流」:递进式三行,承上→起下→行为,逐级加重(采用 V5 的绿圆勾徽章)
|
||
v3: '' +
|
||
'<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 16px;">' +
|
||
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 20px;height: 20px;border-radius: 50%;background: #22C55E;box-shadow: 0 0 0 3px rgba(34,197,94,.18);flex-shrink: 0;"><svg width="11" height="11" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
|
||
'<span style="font-size: 13px;color: var(--gray-700);font-weight: 600;">设置已完成</span>' +
|
||
'</div>' +
|
||
'<div style="background: linear-gradient(135deg,#FFFDE7,#FFF8E1);border-radius: 14px;padding: 16px 16px;margin-bottom: 16px;text-align: center;">' +
|
||
'<div style="font-size: 12px;color: #F9A825;font-weight: 600;margin-bottom: 6px;">下一步</div>' +
|
||
'<div style="font-size: 18px;font-weight: 800;color: var(--gray-900);">用傻瓜比价,找全网底价</div>' +
|
||
'</div>' +
|
||
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;width: 100%;" onclick="closeCelebrationModal()">选外卖平台开始体验</button>',
|
||
|
||
// V4 「行为优先」:承上完全收为一行小提示,起下并入按钮上方副文,主舞台让给行为
|
||
v4: '' +
|
||
'<div style="font-size: 11px;color: var(--gray-500);letter-spacing: 1px;text-align: center;margin-bottom: 8px;text-transform: uppercase;">SETUP COMPLETE</div>' +
|
||
'<div style="font-size: 24px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.25;margin-bottom: 8px;">选一个常用<br>外卖平台</div>' +
|
||
'<div style="font-size: 13px;color: var(--gray-600);text-align: center;margin-bottom: 24px;">即可开启傻瓜式一键比价</div>' +
|
||
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;" onclick="closeCelebrationModal()">现在选择</button>',
|
||
|
||
// V5 「徽章+行动卡」:左对齐绿圆勾徽章承上,黄色行动卡承载"下一步 + 体验傻瓜式一键比价"
|
||
v5: '' +
|
||
'<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 16px;">' +
|
||
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 20px;height: 20px;border-radius: 50%;background: #22C55E;box-shadow: 0 0 0 3px rgba(34,197,94,.18);flex-shrink: 0;"><svg width="11" height="11" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
|
||
'<span style="font-size: 13px;color: var(--gray-700);font-weight: 600;">设置已完成</span>' +
|
||
'</div>' +
|
||
'<div style="position: relative;background: linear-gradient(135deg,#FFFDE7,#FFF3C4);border-radius: 14px;padding: 24px 16px 16px;margin: 12px 0 16px;border: 1.5px solid #FFE082;text-align: center;">' +
|
||
'<div style="position: absolute;top: -12px;left: 50%;transform: translateX(-50%);font-size: 11px;color: #F57F17;font-weight: 800;background: #fff;padding: 4px 12px;border-radius: 32px;letter-spacing: .6px;border: 1.5px solid #FFE082;white-space: nowrap;">下一步</div>' +
|
||
'<div style="font-size: 20px;font-weight: 800;color: var(--gray-900);line-height: 1.3;">用傻瓜比价,找全网底价</div>' +
|
||
'</div>' +
|
||
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;width: 100%;" onclick="closeCelebrationModal()">选外卖平台开始体验</button>',
|
||
|
||
// V6 「进度条」:完成段绿+待办段黄色脉动,强化推进感
|
||
v6: '' +
|
||
'<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 12px;">' +
|
||
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 20px;height: 20px;border-radius: 50%;background: #22C55E;box-shadow: 0 0 0 3px rgba(34,197,94,.18);flex-shrink: 0;"><svg width="11" height="11" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
|
||
'<span style="font-size: 13px;color: var(--gray-700);font-weight: 600;">设置已完成</span>' +
|
||
'</div>' +
|
||
'<div style="display: flex;align-items: center;gap: 6px;margin-bottom: 24px;">' +
|
||
'<div style="flex: 1;height: 6px;border-radius: 4px;background: #22C55E;"></div>' +
|
||
'<div style="flex: 1;height: 6px;border-radius: 4px;background: linear-gradient(90deg,#FFD600,#FFB300);box-shadow: 0 0 10px rgba(255,214,0,.55);animation: gvBob 1.6s ease-in-out infinite;"></div>' +
|
||
'</div>' +
|
||
'<div style="font-size: 13px;color: #F57F17;font-weight: 800;text-align: center;margin-bottom: 6px;letter-spacing: .5px;">最后一步</div>' +
|
||
'<div style="font-size: 22px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.3;margin-bottom: 24px;">选个常用平台</div>' +
|
||
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;width: 100%;" onclick="closeCelebrationModal()">立即选择</button>',
|
||
|
||
// V7 「数字步骤」:① 已完成 → ② 当前 双步骤连线,明确流程位置
|
||
v7: '' +
|
||
'<div style="display: flex;align-items: center;justify-content: center;gap: 8px;margin-bottom: 24px;">' +
|
||
'<div style="display: flex;align-items: center;gap: 6px;opacity: .85;">' +
|
||
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 20px;height: 20px;border-radius: 50%;background: #22C55E;flex-shrink: 0;"><svg width="11" height="11" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
|
||
'<span style="font-size: 12px;color: var(--gray-500);font-weight: 600;">设置完成</span>' +
|
||
'</div>' +
|
||
'<div style="width: 20px;height: 2px;background: var(--gray-200);border-radius: 4px;"></div>' +
|
||
'<div style="display: flex;align-items: center;gap: 6px;">' +
|
||
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 20px;height: 20px;border-radius: 50%;background: var(--primary);color: #1a1a1a;font-size: 12px;font-weight: 800;flex-shrink: 0;box-shadow: 0 0 0 3px rgba(255,214,0,.25);">2</span>' +
|
||
'<span style="font-size: 12px;color: var(--gray-900);font-weight: 700;">选平台</span>' +
|
||
'</div>' +
|
||
'</div>' +
|
||
'<div style="font-size: 22px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.3;margin-bottom: 8px;">选个常用外卖平台</div>' +
|
||
'<div style="font-size: 13px;color: var(--gray-600);text-align: center;margin-bottom: 24px;">即可开启傻瓜式一键比价</div>' +
|
||
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;display: flex;align-items: center;justify-content: center;gap: 6px;width: 100%;" onclick="closeCelebrationModal()">选择平台<span style="font-size: 18px;line-height: 1;">→</span></button>',
|
||
|
||
// V8 「极简专注」:单行小绿勾承上,舞台全部让给主标题
|
||
v8: '' +
|
||
'<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 24px;">' +
|
||
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 20px;height: 20px;border-radius: 50%;background: #22C55E;box-shadow: 0 0 0 3px rgba(34,197,94,.18);flex-shrink: 0;"><svg width="11" height="11" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
|
||
'<span style="font-size: 13px;color: var(--gray-600);font-weight: 500;">设置已完成</span>' +
|
||
'</div>' +
|
||
'<div style="font-size: 24px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.25;margin-bottom: 8px;letter-spacing: -.3px;">选个常用平台</div>' +
|
||
'<div style="font-size: 14px;color: var(--gray-600);text-align: center;margin-bottom: 24px;line-height: 1.5;">现在体验<span style="font-weight: 700;color: var(--gray-900);background: linear-gradient(to top,var(--primary) 40%,transparent 40%);padding: 0 2px;">傻瓜式一键比价</span></div>' +
|
||
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;width: 100%;" onclick="closeCelebrationModal()">开始体验</button>',
|
||
|
||
// V9 「iOS 极简·一图一字一按钮」:80px 大圆勾 + 大字标题 + 单按钮,零嵌套盒子
|
||
v9: '' +
|
||
'<div style="display: flex;justify-content: center;margin: 6px 0 16px;">' +
|
||
'<div style="width: 80px;height: 80px;border-radius: 50%;background: linear-gradient(135deg,#34D399,#10B981);display: flex;align-items: center;justify-content: center;box-shadow: 0 10px 28px rgba(16,185,129,.35), 0 0 0 8px rgba(16,185,129,.10);animation: gvPop .5s cubic-bezier(.34,1.56,.64,1) both;">' +
|
||
'<svg width="42" height="42" viewBox="0 0 42 42" fill="none">' +
|
||
'<path d="M11 21.5 L18 28.5 L31.5 14.5" stroke="#fff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>' +
|
||
'</svg>' +
|
||
'</div>' +
|
||
'</div>' +
|
||
'<div style="font-size: 24px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.3;margin-bottom: 8px;letter-spacing: -.3px;">就差最后一步</div>' +
|
||
'<div style="font-size: 14px;color: var(--gray-600);text-align: center;line-height: 1.55;margin-bottom: 24px;">选个常用平台 · 立刻体验傻瓜式一键比价</div>' +
|
||
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;font-weight: 700;" onclick="closeCelebrationModal()">选外卖平台开始体验</button>',
|
||
|
||
// V10 「Stripe / Linear 风」:左对齐、小绿勾 + 大字 + 黑底按钮,冷峻 SaaS 调性
|
||
v10: '' +
|
||
'<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 24px;">' +
|
||
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 18px;height: 18px;border-radius: 50%;background: #10B981;flex-shrink: 0;"><svg width="10" height="10" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
|
||
'<span style="font-size: 12px;color: var(--gray-500);font-weight: 500;letter-spacing: .3px;">Setup complete</span>' +
|
||
'</div>' +
|
||
'<div style="font-size: 28px;font-weight: 800;color: var(--gray-900);line-height: 1.2;margin-bottom: 8px;letter-spacing: -.6px;">选个常用<br>外卖平台</div>' +
|
||
'<div style="font-size: 14px;color: var(--gray-600);line-height: 1.55;margin-bottom: 24px;">即可开启傻瓜式一键比价 — AI 会自动跨平台比价、领券、下单。</div>' +
|
||
'<button style="background: #1A1A1A;color: #fff;border: none;border-radius: 14px;font-size: 15px;height: 50px;width: 100%;font-weight: 600;display: flex;align-items: center;justify-content: center;gap: 8px;cursor: pointer;" onclick="closeCelebrationModal()">' +
|
||
'<span>开始体验</span>' +
|
||
'<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 7h8m0 0l-3.5-3.5M11 7l-3.5 3.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
|
||
'</button>',
|
||
|
||
// V11 「沉浸彩屏 hero」:负 margin 把顶部 bleed 成黄色渐变 hero,礼包大图标占主舞台,电商喜庆调性
|
||
v11: '' +
|
||
'<div style="margin: -28px -22px 16px;border-radius: 24px 24px 0 0;background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 55%,#fff 100%);padding: 32px 24px 16px;text-align: center;position: relative;overflow: hidden;">' +
|
||
'<div style="position: absolute;top: -30px;left: -30px;width: 120px;height: 120px;border-radius: 50%;background: radial-gradient(circle,rgba(255,255,255,.6),transparent 70%);"></div>' +
|
||
'<div style="position: absolute;bottom: -40px;right: -30px;width: 140px;height: 140px;border-radius: 50%;background: radial-gradient(circle,rgba(255,179,0,.25),transparent 70%);"></div>' +
|
||
'<div style="width: 96px;height: 96px;margin: 0 auto 12px;position: relative;animation: gvPop .55s cubic-bezier(.34,1.56,.64,1) both;">' +
|
||
'<div style="position: absolute;inset: 0;border-radius: 50%;background: radial-gradient(circle,rgba(255,255,255,.85) 0%,rgba(255,255,255,0) 70%);"></div>' +
|
||
'<div style="position: absolute;inset: 6px;border-radius: 50%;background: linear-gradient(135deg,#FFD600 0%,#FF9800 100%);display: flex;align-items: center;justify-content: center;box-shadow: 0 14px 32px rgba(255,152,0,.45), inset 0 -6px 14px rgba(0,0,0,.08);">' +
|
||
'<span style="font-size: 46px;line-height: 1;filter: drop-shadow(0 2px 4px rgba(0,0,0,.15));">🎁</span>' +
|
||
'</div>' +
|
||
'</div>' +
|
||
'<div style="display: inline-block;font-size: 11px;font-weight: 800;color: #D84315;letter-spacing: 1.2px;background: #fff;padding: 4px 12px;border-radius: 32px;margin-bottom: 8px;box-shadow: 0 2px 6px rgba(216,67,21,.18);">SETUP COMPLETE</div>' +
|
||
'<div style="font-size: 24px;font-weight: 900;color: var(--gray-900);line-height: 1.25;letter-spacing: -.3px;">傻瓜比价 · 准备就绪</div>' +
|
||
'</div>' +
|
||
'<div style="font-size: 14px;color: var(--gray-600);text-align: center;line-height: 1.55;margin-bottom: 16px;">选个常用平台 · 立刻领券一键比价</div>' +
|
||
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 52px;width: 100%;font-weight: 700;box-shadow: 0 8px 22px rgba(255,179,0,.42);display: flex;align-items: center;justify-content: center;gap: 6px;" onclick="closeCelebrationModal()">' +
|
||
'<span>选外卖平台开始体验</span><span style="font-size: 18px;line-height: 1;">→</span>' +
|
||
'</button>',
|
||
|
||
// V12 「步骤推进 2/2」:顶部细进度条 100% + 双步骤指示,强化"最后一步"流程感
|
||
v12: '' +
|
||
'<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 8px;">' +
|
||
'<div style="font-size: 11px;font-weight: 700;color: var(--gray-500);letter-spacing: .4px;">2 / 2</div>' +
|
||
'<div style="flex: 1;height: 5px;border-radius: 4px;background: var(--gray-200);overflow: hidden;display: flex;">' +
|
||
'<div style="flex: 1;background: #10B981;border-radius: 4px 0 0 4px;"></div>' +
|
||
'<div style="flex: 1;background: linear-gradient(90deg,var(--primary),#FFB300);border-radius: 0 4px 4px 0;box-shadow: 0 0 8px rgba(255,179,0,.5);animation: gvBob 1.6s ease-in-out infinite;"></div>' +
|
||
'</div>' +
|
||
'</div>' +
|
||
'<div style="display: flex;align-items: center;gap: 6px;margin-bottom: 24px;font-size: 11px;">' +
|
||
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 13px;height: 13px;border-radius: 50%;background: #10B981;flex-shrink: 0;"><svg width="8" height="8" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
|
||
'<span style="color: var(--gray-500);font-weight: 500;">设置完成</span>' +
|
||
'<span style="color: var(--gray-300);margin: 0 2px;">›</span>' +
|
||
'<span style="color: var(--coin);font-weight: 800;letter-spacing: .2px;">现在选平台</span>' +
|
||
'</div>' +
|
||
'<div style="font-size: 24px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.25;margin-bottom: 8px;letter-spacing: -.3px;">就差最后一步</div>' +
|
||
'<div style="font-size: 14px;color: var(--gray-600);text-align: center;line-height: 1.55;margin-bottom: 24px;">选个常用平台开启<span style="font-weight: 700;color: var(--gray-900);">傻瓜式一键比价</span></div>' +
|
||
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;font-weight: 700;display: flex;align-items: center;justify-content: center;gap: 6px;" onclick="closeCelebrationModal()">' +
|
||
'<span>立即选择</span><span style="font-size: 18px;line-height: 1;">→</span>' +
|
||
'</button>'
|
||
};
|
||
var currentCelebrationVariant = 'v1';
|
||
var celebrationModalHTML = celebrationVariants[currentCelebrationVariant];
|
||
|
||
function openCelebrationModal() {
|
||
document.getElementById('celebrationModalCard').innerHTML = celebrationVariants[currentCelebrationVariant] || celebrationVariants.v1;
|
||
document.getElementById('celebrationModal').style.display = 'flex';
|
||
if (typeof fireConfetti === 'function') {
|
||
fireConfetti();
|
||
}
|
||
}
|
||
|
||
function closeCelebrationModal() {
|
||
document.getElementById('celebrationModal').style.display = 'none';
|
||
}
|
||
|
||
function onOverlayRejectClick(e) {
|
||
e.stopPropagation();
|
||
go('permission-step2');
|
||
// 权限未开启 → 弹出提示弹窗
|
||
setTimeout(function() { openSafetyModal('悬浮窗'); }, 300);
|
||
}
|
||
|
||
// 礼花彩纸特效 — 从顶部散落的彩色纸片
|
||
function fireConfetti() {
|
||
var container = document.getElementById('app');
|
||
var colors = ['#FFD600', '#FF5722', '#4CAF50', '#2196F3', '#E91E63', '#FF9800', '#9C27B0', '#00BCD4'];
|
||
for (var i = 0; i < 60; i++) {
|
||
var particle = document.createElement('div');
|
||
var color = colors[Math.floor(Math.random() * colors.length)];
|
||
var w = Math.random() * 6 + 4;
|
||
var h = Math.random() * 14 + 8;
|
||
var left = Math.random() * 100;
|
||
var dx = (Math.random() - 0.5) * 100;
|
||
var dy = 700 + Math.random() * 200;
|
||
var spin = (Math.random() - 0.5) * 1440;
|
||
var delay = Math.random() * 0.6;
|
||
var duration = Math.random() * 1.5 + 1.5;
|
||
particle.style.cssText = 'position:absolute;width:' + w + 'px;height:' + h + 'px;background:' + color + ';border-radius:1px;left:' + left + '%;top:-20px;z-index:9999;pointer-events:none;opacity:1;animation:confettiFloat ' + duration + 's ease-in ' + delay + 's forwards;--dx:' + dx + 'px;--dy:' + dy + 'px;--spin:' + spin + 'deg;';
|
||
container.appendChild(particle);
|
||
(function(p, t) { setTimeout(function() { p.remove(); }, t); })(particle, (duration + delay) * 1000 + 100);
|
||
}
|
||
}
|
||
|
||
// 权限检测 → 两个都开启才能进入下一步
|
||
function checkPermAndGo() {
|
||
var accDone = document.getElementById('accessibilityBtn').disabled;
|
||
var ovlDone = document.getElementById('overlayBtn').disabled;
|
||
if (accDone && ovlDone) {
|
||
go('productselect');
|
||
} else {
|
||
showToast('请先完成前置步骤再继续');
|
||
}
|
||
}
|
||
|
||
// Toast 提示
|
||
function showToast(msg) {
|
||
var existing = document.getElementById('globalToast');
|
||
if (existing) existing.remove();
|
||
var toast = document.createElement('div');
|
||
toast.id = 'globalToast';
|
||
toast.textContent = msg;
|
||
toast.style.cssText = 'position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background:rgba(0,0,0,0.75);color:#fff;padding:10px 20px;border-radius:20px;font-size:14px;z-index:9999;pointer-events:none;opacity:1;transition:opacity 0.3s;white-space:nowrap;';
|
||
document.getElementById('app').appendChild(toast);
|
||
setTimeout(function() { toast.style.opacity = '0'; }, 1500);
|
||
setTimeout(function() { toast.remove(); }, 1800);
|
||
}
|
||
|
||
// 登录状态
|
||
let isLoggedIn = (typeof localStorage !== 'undefined' && localStorage.getItem('proto_isLoggedIn') !== 'false');
|
||
let loginFrom = (typeof localStorage !== 'undefined' && localStorage.getItem('proto_loginFrom')) || 'home';
|
||
let welfareVisited = (typeof localStorage !== 'undefined' && localStorage.getItem('proto_welfareVisited') === 'true');
|
||
let profileVisited = (typeof localStorage !== 'undefined' && localStorage.getItem('proto_profileVisited') === 'true');
|
||
|
||
// 新手礼包流程
|
||
let welcomeGiftShown = (typeof localStorage !== 'undefined' && localStorage.getItem('proto_welcomeGiftShown') === 'true');
|
||
let welcomeGiftClaimed = false;
|
||
let welfareCoinBalance = 28967;
|
||
let welfareCashBalance = 2.89;
|
||
let recordComparisonRewardClaimed = false;
|
||
let messageReminderRewardClaimed = false;
|
||
let videoRewardClaimed = false;
|
||
|
||
// 导航
|
||
// ===== 方案切换系统 =====
|
||
// 配置:在这里注册需要多方案对比的模块
|
||
// 格式:screenId: { current: 'a', options: { a: '方案名', b: '方案名' } }
|
||
// 方案A的screen id = 原id(如 productselect)
|
||
// 方案B的screen id = 原id--b(如 productselect--b)
|
||
// 方案C的screen id = 原id--c(如 productselect--c)
|
||
const variants = {
|
||
'home-feed': {
|
||
current: 'cap',
|
||
inPlace: true,
|
||
options: {
|
||
base: '默认',
|
||
frame: '方案1 外框',
|
||
tabs: '方案2 Tab',
|
||
combo: '方案3 组合',
|
||
border: '边框1 描边',
|
||
accent: '边框2 黄线',
|
||
cap: '边框3 帽檐',
|
||
lift: '边框4 阴影'
|
||
},
|
||
onChange: applyHomeFeedVariant
|
||
},
|
||
'last-compare': {
|
||
current: 'reference',
|
||
inPlace: true,
|
||
options: {
|
||
reference: '默认左标',
|
||
tagright: '方案1 右上',
|
||
topbar: '方案2 顶栏',
|
||
pricebadge: '方案3 价格区',
|
||
mutedright: '方案4 弱化右侧'
|
||
},
|
||
onChange: applyLastCompareVariant
|
||
}
|
||
};
|
||
|
||
function applyHomeFeedVariant(variant) {
|
||
const key = variants['home-feed'].options[variant] ? variant : 'base';
|
||
document.body.classList.remove('feed-v-frame', 'feed-v-tabs', 'feed-v-combo', 'feed-v-border', 'feed-v-accent', 'feed-v-cap', 'feed-v-lift');
|
||
if (key !== 'base') document.body.classList.add('feed-v-' + key);
|
||
variants['home-feed'].current = key;
|
||
}
|
||
|
||
function applyLastCompareVariant(variant) {
|
||
const key = variants['last-compare'].options[variant] ? variant : 'reference';
|
||
const banner = document.getElementById('lastCompareBanner');
|
||
if (banner) {
|
||
banner.classList.remove('lcb-v-reference', 'lcb-v-tagright', 'lcb-v-topbar', 'lcb-v-pricebadge', 'lcb-v-mutedright');
|
||
banner.classList.add('lcb-v-reference');
|
||
if (key !== 'reference') banner.classList.add('lcb-v-' + key);
|
||
}
|
||
variants['last-compare'].current = key;
|
||
}
|
||
|
||
function resolveScreenId(id) {
|
||
if (variants[id] && !variants[id].inPlace) {
|
||
const v = variants[id].current;
|
||
return v === 'a' ? id : id + '--' + v;
|
||
}
|
||
return id;
|
||
}
|
||
|
||
function switchVariant(moduleId, variant) {
|
||
if (!variants[moduleId]) return;
|
||
variants[moduleId].current = variant;
|
||
renderVariantPanel();
|
||
if (typeof variants[moduleId].onChange === 'function') {
|
||
variants[moduleId].onChange(variant);
|
||
}
|
||
if (variants[moduleId].inPlace) return;
|
||
// 如果当前正在看这个模块的某个方案,立即切换
|
||
const allScreens = document.querySelectorAll('.screen');
|
||
let isViewing = false;
|
||
allScreens.forEach(s => {
|
||
if (s.classList.contains('active') && (s.id === moduleId || s.id.startsWith(moduleId + '--'))) {
|
||
isViewing = true;
|
||
}
|
||
});
|
||
if (isViewing) go(moduleId);
|
||
}
|
||
|
||
function toggleVariantPanel() {
|
||
const p = document.getElementById('variantPanel');
|
||
p.classList.toggle('open');
|
||
if (p.classList.contains('open')) renderVariantPanel();
|
||
}
|
||
|
||
function renderVariantPanel() {
|
||
const list = document.getElementById('variantList');
|
||
const keys = Object.keys(variants);
|
||
if (keys.length === 0) {
|
||
list.innerHTML = '<div class="variant-empty">暂无多方案模块<br><span style="font-size: 11px;">在 variants 配置中添加模块即可</span></div>';
|
||
return;
|
||
}
|
||
list.innerHTML = keys.map(id => {
|
||
const v = variants[id];
|
||
const opts = Object.entries(v.options).map(([key, label]) =>
|
||
`<div class="variant-opt ${v.current===key?'active':''}" onclick="switchVariant('${id}','${key}')">${label}</div>`
|
||
).join('');
|
||
return `<div class="variant-module"><div class="variant-module-label">${id}</div><div class="variant-options">${opts}</div></div>`;
|
||
}).join('');
|
||
}
|
||
|
||
// 页面加载时初始化面板
|
||
document.addEventListener('DOMContentLoaded', renderVariantPanel);
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
try {
|
||
const feedVariant = new URLSearchParams(location.search).get('feedvariant') || variants['home-feed'].current;
|
||
applyHomeFeedVariant(feedVariant);
|
||
const lastCompareVariant = new URLSearchParams(location.search).get('lastcompare') || variants['last-compare'].current;
|
||
applyLastCompareVariant(lastCompareVariant);
|
||
renderVariantPanel();
|
||
} catch (e) {}
|
||
});
|
||
|
||
// 调试:URL hash 直跳(如 #home / #welfare / #profile)
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
var h = (location.hash || '').replace(/^#/, '');
|
||
if (h && document.getElementById(h)) {
|
||
setTimeout(function(){ try { go(h); } catch(e){} }, 80);
|
||
}
|
||
});
|
||
|
||
// ===== 用户案例翻页横幅 =====
|
||
var FLIP_AVATARS = ['🦊','🐱','🐶','🐻','🐼','🐨','🐯','🦁','🐮','🐷','🐸','🐵','🐔','🐧','🦆','🦅','🦉','🐺','🐗','🦄','🐝','🦋','🐞','🦜','🦩','🐢','🐙','🦀','🐠','🐬','🐳','🦈','🌸','🌻','🌺','🌷','🍎','🍑','🍓','🍉','🍊','🥭','🍇','🥝','🌶','🌮','🍔','🍕','🍜','🥟'];
|
||
var FLIP_BG = ['#FFE0B2','#FFCCBC','#FFAB91','#F8BBD0','#E1BEE7','#C5CAE9','#B3E5FC','#B2EBF2','#B2DFDB','#C8E6C9','#DCEDC8','#F0F4C3','#FFF59D','#FFE082','#FFCC80','#FFAB91','#BCAAA4','#CFD8DC','#FFCDD2','#D1C4E9'];
|
||
var FLIP_NAMES = [
|
||
'省钱小达人','抠门大魔王','优惠券猎人','比价老司机','折扣专家',
|
||
'拼单狂魔','薅羊毛达人','一只小鹿','花猫不喝酒','天天吃辣条',
|
||
'想变有钱人','哈哈哈是我','安静的咸鱼','奶茶续命中','干饭人本人',
|
||
'云上漫步者','向日葵不晒','糖醋排骨饭','北漂十年','打工累了',
|
||
'不熬夜星人','早睡早起队','宇宙小行星','深夜放毒','贪吃的橘子',
|
||
'永远不胖派','减肥进行时','咖啡因爱好者','下班想躺平','键盘侠本侠',
|
||
'佛系青年','努力上进鸡','摸鱼小能手','加班狗一只','周一不想动',
|
||
'周五最快乐','双十一战神','凑单小能手','满减狂魔','省一块是一块',
|
||
'外卖红包党','比价才下单','看完三家再买','不冲动消费','理智剁手党',
|
||
'存钱罐已满','月光警告','钱包瘦身中','大脑买买买','手刹车住'
|
||
];
|
||
var FLIP_VERBS = [
|
||
'通过比价省了','点外卖省了','刚省了','单笔省了','下单时省了',
|
||
'比价后省了','用券省了','薅到了','这单省了'
|
||
];
|
||
|
||
function buildFlipCases() {
|
||
var cases = [];
|
||
for (var i = 0; i < FLIP_NAMES.length; i++) {
|
||
var amount = (Math.random() * 27 + 3).toFixed(1); // 3.0 - 30.0
|
||
cases.push({
|
||
avatar: FLIP_AVATARS[i % FLIP_AVATARS.length],
|
||
bg: FLIP_BG[i % FLIP_BG.length],
|
||
name: FLIP_NAMES[i],
|
||
verb: FLIP_VERBS[i % FLIP_VERBS.length],
|
||
amount: amount,
|
||
});
|
||
}
|
||
// 洗牌一下避免按顺序露馅
|
||
for (var j = cases.length - 1; j > 0; j--) {
|
||
var k = Math.floor(Math.random() * (j + 1));
|
||
var t = cases[j]; cases[j] = cases[k]; cases[k] = t;
|
||
}
|
||
return cases;
|
||
}
|
||
|
||
function flipCaseHTML(c) {
|
||
return '<span class="flip-banner-avatar" style="background: ' + c.bg + '">' + c.avatar + '</span>'
|
||
+ '<span class="flip-banner-text"><span class="flip-name">' + c.name + '</span>' + c.verb + '<em>¥' + c.amount + '</em></span>';
|
||
}
|
||
|
||
var flipCases = [];
|
||
var flipIdx = 0;
|
||
var flipping = false;
|
||
function startFlipBanner() {
|
||
var banner = document.getElementById('flipBanner');
|
||
var front = document.getElementById('flipBannerFront');
|
||
var back = document.getElementById('flipBannerBack');
|
||
if (!banner || !front || !back) return;
|
||
flipCases = buildFlipCases();
|
||
front.innerHTML = flipCaseHTML(flipCases[0]);
|
||
back.innerHTML = flipCaseHTML(flipCases[1 % flipCases.length]);
|
||
setInterval(function() {
|
||
if (flipping) return;
|
||
flipping = true;
|
||
banner.classList.add('flipping');
|
||
setTimeout(function() {
|
||
flipIdx = (flipIdx + 1) % flipCases.length;
|
||
// 翻转完成后,把当前 back 内容搬到 front,瞬时复位(无 transition)
|
||
front.innerHTML = flipCaseHTML(flipCases[flipIdx]);
|
||
var stage = document.getElementById('flipBannerStage');
|
||
stage.style.transition = 'none';
|
||
banner.classList.remove('flipping');
|
||
void stage.offsetWidth; // 强制重排
|
||
stage.style.transition = '';
|
||
back.innerHTML = flipCaseHTML(flipCases[(flipIdx + 1) % flipCases.length]);
|
||
flipping = false;
|
||
}, 560);
|
||
}, 2800);
|
||
}
|
||
document.addEventListener('DOMContentLoaded', startFlipBanner);
|
||
|
||
// ===== feed 排序 tab(智能推荐/距离最近/销量最高)→ 接真实数据(H2b) =====
|
||
// 点未激活 tab → 切高亮 + 拉真实数据(原 asc/desc 方向翻转是 mock 残留、后端不支持方向, 已删)
|
||
document.addEventListener('click', function (e) {
|
||
var item = e.target.closest('#home .feed-sort .fs-item');
|
||
if (!item || item.classList.contains('active')) return;
|
||
var group = item.closest('.feed-sort');
|
||
group.querySelectorAll('.fs-item').forEach(function (o) { o.classList.remove('active'); });
|
||
item.classList.add('active');
|
||
// 未授权定位:只切高亮、不打接口(对齐原生 selectTabWithoutLoad);授权后由 applyLocationState 拉
|
||
if (window.HomeFeed) {
|
||
if (HomeFeed.locationGranted()) HomeFeed.switchTab(item.dataset.key);
|
||
else HomeFeed.selectTabWithoutLoad(item.dataset.key);
|
||
}
|
||
// 自动滚到顶部:仅当 sort 还未贴顶时才滚(贴顶位置 device y=44 + sticky top=38 = 82)
|
||
var stickY = 82;
|
||
if (group.getBoundingClientRect().top > stickY + 2) {
|
||
group.scrollIntoView({ block: 'start', behavior: 'smooth' });
|
||
}
|
||
});
|
||
|
||
// ===== 顶部 Banner 轮播(3 个点位,左右滑动 + 自动播放) =====
|
||
function initHomeBannerSwiper() {
|
||
var banner = document.getElementById('homeBanner');
|
||
var track = document.getElementById('homeBannerTrack');
|
||
var dotsWrap = document.getElementById('homeBannerDots');
|
||
if (!banner || !track || !dotsWrap) return;
|
||
var total = 2;
|
||
var idx = 0;
|
||
var autoTimer = null;
|
||
var startX = 0, startY = 0, deltaX = 0, dragging = false, locked = false, abandoned = false;
|
||
var width = 0;
|
||
var pointerId = null;
|
||
var moved = false; // 本次按下是否发生了拖动(用于区分「点击」与「滑动」)
|
||
|
||
function go(i) {
|
||
idx = (i + total) % total;
|
||
width = banner.clientWidth;
|
||
track.style.transform = 'translateX(' + (-idx * width) + 'px)';
|
||
var dots = dotsWrap.querySelectorAll('.home-banner-dot');
|
||
for (var k = 0; k < dots.length; k++) {
|
||
dots[k].classList.toggle('active', k === idx);
|
||
}
|
||
}
|
||
function next() { go(idx + 1); }
|
||
function startAuto() {
|
||
stopAuto();
|
||
autoTimer = setInterval(next, 4000);
|
||
}
|
||
function stopAuto() {
|
||
if (autoTimer) { clearInterval(autoTimer); autoTimer = null; }
|
||
}
|
||
|
||
// Pointer Events 同时覆盖触摸 + 鼠标拖拽
|
||
banner.addEventListener('pointerdown', function(e) {
|
||
if (e.pointerType === 'mouse' && e.button !== 0) return;
|
||
stopAuto();
|
||
width = banner.clientWidth;
|
||
startX = e.clientX;
|
||
startY = e.clientY;
|
||
deltaX = 0;
|
||
dragging = true;
|
||
locked = false;
|
||
abandoned = false;
|
||
moved = false;
|
||
pointerId = e.pointerId;
|
||
track.classList.add('dragging');
|
||
try { banner.setPointerCapture(e.pointerId); } catch (err) {}
|
||
});
|
||
banner.addEventListener('pointermove', function(e) {
|
||
if (!dragging || e.pointerId !== pointerId) return;
|
||
var dx = e.clientX - startX;
|
||
var dy = e.clientY - startY;
|
||
if (!locked) {
|
||
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 6) {
|
||
locked = true;
|
||
} else if (Math.abs(dy) > 6) {
|
||
// 纵向滚动:放弃这次拖拽
|
||
abandoned = true;
|
||
dragging = false;
|
||
track.classList.remove('dragging');
|
||
track.style.transform = 'translateX(' + (-idx * width) + 'px)';
|
||
try { banner.releasePointerCapture(e.pointerId); } catch (err) {}
|
||
startAuto();
|
||
return;
|
||
}
|
||
}
|
||
if (locked) {
|
||
// 阻止页面纵向滚动(pointermove 默认 passive: false 可 preventDefault)
|
||
if (e.cancelable) e.preventDefault();
|
||
if (Math.abs(dx) > 6) moved = true;
|
||
deltaX = dx;
|
||
if ((idx === 0 && dx > 0) || (idx === total - 1 && dx < 0)) {
|
||
deltaX = dx * 0.35;
|
||
}
|
||
track.style.transform = 'translateX(' + (-idx * width + deltaX) + 'px)';
|
||
}
|
||
});
|
||
function endDrag(e) {
|
||
if (e && e.pointerId !== pointerId && pointerId !== null) return;
|
||
if (abandoned) { pointerId = null; return; }
|
||
if (!dragging) { startAuto(); return; }
|
||
dragging = false;
|
||
track.classList.remove('dragging');
|
||
var threshold = Math.max(30, width * 0.15);
|
||
if (deltaX < -threshold && idx < total - 1) go(idx + 1);
|
||
else if (deltaX > threshold && idx > 0) go(idx - 1);
|
||
else go(idx);
|
||
try { if (e) banner.releasePointerCapture(e.pointerId); } catch (err) {}
|
||
pointerId = null;
|
||
startAuto();
|
||
}
|
||
banner.addEventListener('pointerup', endDrag);
|
||
banner.addEventListener('pointercancel', endDrag);
|
||
|
||
// 点击 banner 跳转(监听挂在 banner 上:setPointerCapture 会让 click 派发到
|
||
// #homeBanner 而非具体 slide,所以按当前 idx 取目标。
|
||
// 区分「点击」与「滑动」:发生过拖动则不跳;点圆点也不跳)
|
||
var slides = track.querySelectorAll('.home-banner-slide');
|
||
banner.addEventListener('click', function(e) {
|
||
if (moved) return;
|
||
if (e.target.closest && e.target.closest('.home-banner-dots')) return;
|
||
var active = slides[idx];
|
||
if (!active) return;
|
||
var target = active.getAttribute('data-nav-target');
|
||
if (target) window.go(target);
|
||
});
|
||
|
||
// 点击点位跳转
|
||
dotsWrap.addEventListener('click', function(e) {
|
||
var t = e.target;
|
||
if (!t || !t.getAttribute) return;
|
||
var i = t.getAttribute('data-dot-idx');
|
||
if (i === null) return;
|
||
stopAuto();
|
||
go(parseInt(i, 10));
|
||
startAuto();
|
||
});
|
||
|
||
window.addEventListener('resize', function() { go(idx); });
|
||
|
||
go(0);
|
||
startAuto();
|
||
}
|
||
document.addEventListener('DOMContentLoaded', initHomeBannerSwiper);
|
||
|
||
// 页面历史栈(同时驱动左下角调试按钮和页面内的「← 返回」按钮)
|
||
var screenHistory = ['splash'];
|
||
|
||
// 统一返回:pop 一格回到上一步,不再 push
|
||
function goBack() {
|
||
if (screenHistory.length <= 1) return; // 已经在起点,无效
|
||
screenHistory.pop();
|
||
var prev = screenHistory[screenHistory.length - 1];
|
||
_activateScreen(prev, /*pushHistory=*/false);
|
||
}
|
||
|
||
// 调试按钮(左下角)走同一逻辑
|
||
function debugGoBack() { goBack(); }
|
||
|
||
// 仅切换 DOM active 态(不触发登录拦截、不入栈),供 goBack 复用
|
||
function _activateScreen(resolvedId, pushHistory) {
|
||
document.querySelectorAll('.screen').forEach(function(s) { s.classList.remove('active'); });
|
||
document.getElementById(resolvedId).classList.add('active');
|
||
if (pushHistory && screenHistory[screenHistory.length - 1] !== resolvedId) {
|
||
screenHistory.push(resolvedId);
|
||
}
|
||
}
|
||
|
||
function go(id) {
|
||
// 未登录 + 首次进入福利/我的 → 先跳登录页
|
||
if (!isLoggedIn && id === 'welfare' && !welfareVisited) {
|
||
welfareVisited = true; try{localStorage.setItem('proto_welfareVisited','true');}catch(e){}
|
||
loginFrom='welfare'; try{localStorage.setItem('proto_loginFrom','welfare');}catch(e){}
|
||
id = 'login';
|
||
}
|
||
if (!isLoggedIn && id === 'profile' && !profileVisited) {
|
||
profileVisited = true; try{localStorage.setItem('proto_profileVisited','true');}catch(e){}
|
||
loginFrom='profile'; try{localStorage.setItem('proto_loginFrom','profile');}catch(e){}
|
||
id = 'login';
|
||
}
|
||
|
||
// 方案切换:解析实际 screen id
|
||
var resolvedId = resolveScreenId(id);
|
||
|
||
_activateScreen(resolvedId, /*pushHistory=*/true);
|
||
|
||
// 切换福利页登录态
|
||
if (id === 'welfare') {
|
||
document.getElementById('welfareUnlogged').style.display = isLoggedIn ? 'none' : 'block';
|
||
document.getElementById('welfareLogged').style.display = isLoggedIn ? 'block' : 'none';
|
||
updateWelfareCheckinTask();
|
||
if (isLoggedIn) {
|
||
animateWelfareAssetIntro();
|
||
}
|
||
if (isLoggedIn && !checkinDone && !checkinShown && !checkinPending) {
|
||
checkinPending = true;
|
||
setTimeout(function() {
|
||
checkinPending = false;
|
||
var active = document.querySelector('.screen.active');
|
||
if (isLoggedIn && !checkinDone && !checkinShown && active && active.id === 'welfare') {
|
||
checkinShown = true; try{localStorage.setItem('proto_checkinShown','true');}catch(e){}
|
||
showCheckinPopup();
|
||
}
|
||
}, 500);
|
||
}
|
||
}
|
||
// 切换我的页登录态
|
||
if (id === 'profile') {
|
||
document.getElementById('profileUnlogged').style.display = isLoggedIn ? 'none' : 'block';
|
||
document.getElementById('profileLogged').style.display = isLoggedIn ? 'block' : 'none';
|
||
}
|
||
|
||
if (id === 'productselect') { startPlatformScan(); }
|
||
if (id === 'celebResults' || id === 'celebration') { renderCelebrationSavings(); renderResults('celebResults'); startConfetti(); }
|
||
if (id === 'compresult') { renderResults('compResultList'); }
|
||
if (id === 'comparing') { startComparison(); }
|
||
if (id === 'home') {
|
||
if (typeof renderTriClaim === 'function') renderTriClaim();
|
||
if (typeof renderLastCompareBanner === 'function') renderLastCompareBanner();
|
||
}
|
||
}
|
||
|
||
// 登录页返回 → 走统一的 goBack(pop 历史栈)
|
||
function loginGoBack() { goBack(); }
|
||
|
||
// ===== 签到弹窗 =====
|
||
const CHECKIN_MAX_DAY = 14;
|
||
const CHECKIN_REWARD_RULES = [
|
||
{ day: 1, amount: 180 },
|
||
{ day: 2, amount: 380 },
|
||
{ day: 3, amount: 220 },
|
||
{ day: 4, amount: 260 },
|
||
{ day: 5, amount: 320 },
|
||
{ day: 6, amount: 420 },
|
||
{ day: 7, amount: 888 },
|
||
{ day: 8, amount: 360 },
|
||
{ day: 9, amount: 460 },
|
||
{ day: 10, amount: 520 },
|
||
{ day: 11, amount: 680 },
|
||
{ day: 12, amount: 1088 },
|
||
{ day: 13, amount: 1688 },
|
||
{ day: 14, amount: 2888 },
|
||
];
|
||
const CHECKIN_REWARD_ASSETS = {
|
||
coin: 'assets/welfare/index/checkin-coin-single.png',
|
||
coins: 'assets/welfare/index/checkin-coins-600.png',
|
||
bigCoins: 'assets/welfare/index/checkin-coins-3888.png',
|
||
chest: 'assets/welfare/index/checkin-chest-8888.png'
|
||
};
|
||
let checkinShown = (typeof localStorage !== 'undefined' && localStorage.getItem('proto_checkinShown') === 'true');
|
||
let checkinPending = false;
|
||
let checkinDone = false;
|
||
let checkinCompletedBeforeToday = 2;
|
||
|
||
function getCheckinTodayDay() {
|
||
return Math.min(checkinCompletedBeforeToday + 1, CHECKIN_MAX_DAY);
|
||
}
|
||
|
||
function getCheckinCurrentStreak() {
|
||
return Math.min(checkinCompletedBeforeToday + (checkinDone ? 1 : 0), CHECKIN_MAX_DAY);
|
||
}
|
||
|
||
function getCheckinReward(day) {
|
||
var found = CHECKIN_REWARD_RULES.find(function(item) { return item.day === day; });
|
||
return found ? found.amount : 0;
|
||
}
|
||
|
||
function getCheckinMaxReward() {
|
||
return CHECKIN_REWARD_RULES.reduce(function(max, item) {
|
||
return Math.max(max, item.amount);
|
||
}, 0);
|
||
}
|
||
|
||
function getCheckinRewardAsset(day) {
|
||
var amount = getCheckinReward(day);
|
||
if (day === CHECKIN_MAX_DAY) return CHECKIN_REWARD_ASSETS.chest;
|
||
if (amount >= 1000) return CHECKIN_REWARD_ASSETS.bigCoins;
|
||
if (amount >= 680) return CHECKIN_REWARD_ASSETS.coins;
|
||
return CHECKIN_REWARD_ASSETS.coin;
|
||
}
|
||
|
||
function getCheckinLabel(day) {
|
||
var today = getCheckinTodayDay();
|
||
if (day === today) return '今天';
|
||
if (day === today + 1) return '明天';
|
||
return '第' + day + '天';
|
||
}
|
||
|
||
function getCheckinVisibleDays() {
|
||
var today = getCheckinTodayDay();
|
||
var days = [];
|
||
var start = Math.max(1, today - 2);
|
||
for (var day = start; day <= today; day++) days.push(day);
|
||
if (today < CHECKIN_MAX_DAY) days.push(today + 1);
|
||
|
||
[7, 14].some(function(milestone) {
|
||
if (milestone > today + 1) {
|
||
days.push(milestone);
|
||
return true;
|
||
}
|
||
return false;
|
||
});
|
||
|
||
for (var next = today + 2; next <= CHECKIN_MAX_DAY && days.length < 5; next++) {
|
||
days.push(next);
|
||
}
|
||
days = Array.from(new Set(days)).sort(function(a, b) { return a - b; });
|
||
while (days.length < 5 && days[0] > 1) {
|
||
days.unshift(days[0] - 1);
|
||
}
|
||
return days.slice(-5);
|
||
}
|
||
|
||
function getCheckinStep(day) {
|
||
var today = getCheckinTodayDay();
|
||
var completed = getCheckinCurrentStreak();
|
||
var isToday = day === today;
|
||
var isTomorrow = day === today + 1;
|
||
var isDone = day <= completed;
|
||
var isNextTarget = (!checkinDone && isToday) || (checkinDone && isTomorrow);
|
||
return {
|
||
day: day,
|
||
amount: getCheckinReward(day),
|
||
label: getCheckinLabel(day),
|
||
isDone: isDone,
|
||
isToday: isToday,
|
||
isTomorrow: isTomorrow,
|
||
isCurrent: isNextTarget,
|
||
isJustDone: checkinDone && isToday,
|
||
isMilestone: day === 7 || day === CHECKIN_MAX_DAY,
|
||
img: getCheckinRewardAsset(day)
|
||
};
|
||
}
|
||
|
||
function getCheckinSteps() {
|
||
return getCheckinVisibleDays().map(getCheckinStep);
|
||
}
|
||
|
||
function renderWelfareCheckinTimeline() {
|
||
var timeline = document.getElementById('r8CheckinTimeline');
|
||
if (!timeline) return;
|
||
|
||
timeline.innerHTML = getCheckinSteps().map(function(step) {
|
||
var classes = ['r8-checkin-step'];
|
||
if (step.isDone) classes.push('done');
|
||
if (step.isCurrent) classes.push('current');
|
||
if (step.isJustDone) classes.push('just-done');
|
||
if (step.day === CHECKIN_MAX_DAY) classes.push('most');
|
||
|
||
var top = step.isCurrent
|
||
? '<div class="r8-checkin-step-badge">' + (step.isTomorrow ? '明天' : '今天领') + '</div>'
|
||
: '<div class="r8-checkin-step-label">' + step.label + '</div>';
|
||
var icon = step.isDone
|
||
? '<div class="r8-checkin-step-icon"></div>'
|
||
: '<div class="r8-checkin-step-icon"><img src="' + step.img + '" alt=""></div>';
|
||
|
||
return '<div class="' + classes.join(' ') + '">' + top + icon + '<div class="r8-checkin-step-amount">' + step.amount + '</div></div>';
|
||
}).join('');
|
||
}
|
||
|
||
function renderCheckinPopupRewards() {
|
||
var rewards = document.getElementById('checkinRewards');
|
||
if (!rewards) return;
|
||
|
||
rewards.innerHTML = getCheckinSteps().map(function(step) {
|
||
var classes = ['checkin-reward-card'];
|
||
if (step.isDone) classes.push('claimed');
|
||
if (!step.isDone && step.isToday && !checkinDone) classes.push('current');
|
||
var icon = step.isDone
|
||
? '<div class="checkin-reward-icon">已领取</div>'
|
||
: '<div class="checkin-reward-icon"><img' + (step.day === CHECKIN_MAX_DAY ? ' class="icon-chest"' : '') + ' src="' + step.img + '" alt=""></div>';
|
||
|
||
return '<div class="' + classes.join(' ') + '">' + icon + '<div class="checkin-reward-amount">' + step.amount + '</div></div>';
|
||
}).join('');
|
||
}
|
||
|
||
function renderCheckinPopupProgress() {
|
||
var progress = document.getElementById('checkinProgress');
|
||
if (!progress) return;
|
||
|
||
progress.innerHTML = '<div class="checkin-progress-lines" id="checkinProgressLines"></div>' + getCheckinSteps().map(function(step) {
|
||
var classes = ['checkin-node'];
|
||
if (step.isDone) classes.push('done');
|
||
if (step.isCurrent) classes.push('current');
|
||
return '<div class="' + classes.join(' ') + '" data-day="' + step.day + '"><span class="checkin-dot"></span><span>' + step.label + '</span></div>';
|
||
}).join('');
|
||
}
|
||
|
||
function updateCheckinPopupCopy() {
|
||
var banner = document.getElementById('checkinBanner');
|
||
var title = document.getElementById('checkinPopupTitle');
|
||
var sub = document.getElementById('checkinPopupSub');
|
||
var btn = document.getElementById('checkinBtn');
|
||
var reminderBtn = document.getElementById('checkinReminderBtn');
|
||
var today = getCheckinTodayDay();
|
||
var streak = getCheckinCurrentStreak();
|
||
var todayReward = getCheckinReward(today);
|
||
var nextDay = Math.min(today + 1, CHECKIN_MAX_DAY);
|
||
var nextReward = getCheckinReward(nextDay);
|
||
|
||
if (banner) banner.innerHTML = '<span class="star"></span>连续签到14天 最高可领' + getCheckinMaxReward() + '金币';
|
||
if (title) title.textContent = checkinDone ? '今日金币已领取' : '签到领取今日金币';
|
||
if (sub) {
|
||
if (checkinDone && today >= CHECKIN_MAX_DAY) {
|
||
sub.innerHTML = '已完成 <b>14</b> 天签到,今日大奖已领取';
|
||
} else if (checkinDone) {
|
||
sub.innerHTML = '已连续签到 <b>' + streak + '</b> 天,明天可领 <b>' + nextReward + '</b> 金币';
|
||
} else {
|
||
sub.innerHTML = '已连续签到 <b>' + streak + '</b> 天,今天可领 <b>' + todayReward + '</b> 金币';
|
||
}
|
||
}
|
||
if (btn) {
|
||
btn.innerHTML = '签到领 <img src="' + CHECKIN_REWARD_ASSETS.coin + '" alt=""><b>' + todayReward + '</b>';
|
||
btn.style.display = checkinDone ? 'none' : 'flex';
|
||
}
|
||
if (reminderBtn) reminderBtn.style.display = checkinDone ? 'flex' : 'none';
|
||
}
|
||
|
||
function renderCheckinPopup() {
|
||
updateCheckinPopupCopy();
|
||
renderCheckinPopupRewards();
|
||
renderCheckinPopupProgress();
|
||
requestAnimationFrame(renderCheckinProgressLines);
|
||
}
|
||
|
||
function updateWelfareCheckinTask() {
|
||
var taskCard = document.getElementById('r8TaskCard');
|
||
var row = document.getElementById('r8CheckinTaskRow');
|
||
var recordBlock = document.getElementById('r8RecordTaskBlock');
|
||
var title = document.getElementById('r8CheckinTaskTitle');
|
||
var sub = document.getElementById('r8CheckinTaskSub');
|
||
var cta = document.getElementById('r8CheckinTaskCta');
|
||
var headline = document.getElementById('r8CheckinHeadline');
|
||
var cardCta = document.getElementById('r8CheckinCardCta');
|
||
if (!taskCard || !row || !recordBlock) return;
|
||
|
||
var today = getCheckinTodayDay();
|
||
var streak = getCheckinCurrentStreak();
|
||
var todayReward = getCheckinReward(today);
|
||
var nextDay = Math.min(today + 1, CHECKIN_MAX_DAY);
|
||
var nextReward = getCheckinReward(nextDay);
|
||
|
||
row.classList.toggle('is-done', checkinDone);
|
||
taskCard.insertBefore(row, recordBlock);
|
||
if (title) title.textContent = '新人签到领金币';
|
||
if (sub) {
|
||
sub.textContent = checkinDone
|
||
? (today >= CHECKIN_MAX_DAY ? '已完成14天签到,今日大奖已领取' : '已连续签到 ' + streak + ' 天,明天可领 ' + nextReward + ' 金币')
|
||
: '已连续签到 ' + streak + ' 天,今日可领 ' + todayReward + ' 金币';
|
||
}
|
||
if (cta) cta.textContent = checkinDone ? '去查看' : '去签到';
|
||
renderWelfareCheckinTimeline();
|
||
if (checkinDone) {
|
||
if (headline) headline.innerHTML = '已连续签到<span class="num">' + streak + '</span>天';
|
||
if (cardCta) cardCta.innerHTML = '<span class="check-tick">✓</span>今日已签';
|
||
} else {
|
||
if (headline) headline.textContent = '今日签到领金币';
|
||
if (cardCta) cardCta.textContent = '去签到';
|
||
}
|
||
}
|
||
|
||
function openCheckinTask() {
|
||
showCheckinPopup();
|
||
}
|
||
|
||
function renderCheckinProgressLines() {
|
||
var progress = document.getElementById('checkinProgress');
|
||
var lines = document.getElementById('checkinProgressLines');
|
||
if (!progress || !lines) return;
|
||
var nodes = Array.prototype.slice.call(progress.querySelectorAll('.checkin-node'));
|
||
if (nodes.length < 2) return;
|
||
lines.innerHTML = '';
|
||
var progressRect = progress.getBoundingClientRect();
|
||
var completed = getCheckinCurrentStreak();
|
||
var targetDay = checkinDone ? Math.min(getCheckinTodayDay() + 1, CHECKIN_MAX_DAY) : getCheckinTodayDay();
|
||
|
||
nodes.forEach(function(node, index) {
|
||
var next = nodes[index + 1];
|
||
if (!next) return;
|
||
var dot = node.querySelector('.checkin-dot');
|
||
var nextDot = next.querySelector('.checkin-dot');
|
||
if (!dot || !nextDot) return;
|
||
|
||
var dotRect = dot.getBoundingClientRect();
|
||
var nextDotRect = nextDot.getBoundingClientRect();
|
||
var x1Center = dotRect.left + dotRect.width / 2 - progressRect.left;
|
||
var x2Center = nextDotRect.left + nextDotRect.width / 2 - progressRect.left;
|
||
var dotRadius = dotRect.width / 2;
|
||
var nextDotRadius = nextDotRect.width / 2;
|
||
var day = Number(node.dataset.day || 0);
|
||
var nextDay = Number(next.dataset.day || 0);
|
||
var isDashed = nextDay - day > 1;
|
||
var x1 = isDashed ? x1Center + dotRadius : x1Center;
|
||
var x2 = isDashed ? x2Center - nextDotRadius : x2Center;
|
||
var width = Math.max(0, x2 - x1);
|
||
var color = (nextDay <= completed || nextDay === targetDay) ? '#FFB800' : '#D9D9D9';
|
||
|
||
var segment = document.createElement('span');
|
||
segment.className = 'checkin-segment ' + (isDashed ? 'dashed' : 'solid');
|
||
segment.style.left = x1 + 'px';
|
||
segment.style.width = width + 'px';
|
||
segment.style.setProperty('--line-color', color);
|
||
if (isDashed) {
|
||
var dashCount = 4;
|
||
var gap = Math.max(4, Math.min(5, width / 10));
|
||
var dash = Math.max(4, (width - gap * (dashCount + 1)) / dashCount);
|
||
for (var i = 0; i < dashCount; i++) {
|
||
var dashEl = document.createElement('i');
|
||
dashEl.style.cssText = 'position:absolute;top:0;height:3px;border-radius:99px;background:' + color + ';left:' + (gap + i * (dash + gap)) + 'px;width:' + dash + 'px;';
|
||
segment.appendChild(dashEl);
|
||
}
|
||
}
|
||
lines.appendChild(segment);
|
||
});
|
||
}
|
||
|
||
window.addEventListener('resize', function() {
|
||
var popup = document.getElementById('checkinPopup');
|
||
if (popup && getComputedStyle(popup).display !== 'none') renderCheckinProgressLines();
|
||
});
|
||
|
||
function showCheckinPopup() {
|
||
var popup = document.getElementById('checkinPopup');
|
||
if (!popup) return;
|
||
popup.style.display = 'flex';
|
||
renderCheckinPopup();
|
||
}
|
||
|
||
function closeCheckinPopup() {
|
||
document.getElementById('checkinPopup').style.display = 'none';
|
||
}
|
||
|
||
function doCheckin() {
|
||
if (checkinDone) return;
|
||
var todayReward = getCheckinReward(getCheckinTodayDay());
|
||
checkinDone = true;
|
||
updateWelfareCheckinTask();
|
||
renderCheckinPopup();
|
||
claimTaskReward('签到奖励', todayReward);
|
||
}
|
||
|
||
function doCheckinReminder() {
|
||
// 模拟权限弹窗
|
||
document.getElementById('calendarPermPopup').style.display = 'flex';
|
||
}
|
||
|
||
function closeCalendarPerm() {
|
||
document.getElementById('calendarPermPopup').style.display = 'none';
|
||
closeCheckinPopup();
|
||
}
|
||
|
||
|
||
// ===== 新手礼包 + 优惠券流程 =====
|
||
function showWelcomeGiftPopup() {
|
||
document.getElementById('welcomeGiftPopup').classList.add('show');
|
||
}
|
||
|
||
function openGiftBox() {
|
||
if (welcomeGiftClaimed) return;
|
||
var card = document.getElementById('welcomeGiftCard');
|
||
var chest = document.getElementById('giftChestEmoji');
|
||
var btn = document.getElementById('giftMainBtn');
|
||
|
||
// 阶段 A → B:宝箱开盖
|
||
card.classList.add('opening');
|
||
setTimeout(function() {
|
||
chest.textContent = '📦';
|
||
card.classList.remove('opening');
|
||
card.classList.add('opened');
|
||
flyCoinsToWelfareTab();
|
||
// 福利 tab 数字滚动 + badge + pulse
|
||
setTimeout(function() {
|
||
var tabItem = document.getElementById('homeTabWelfare');
|
||
var tabIcon = document.getElementById('homeTabWelfareIcon');
|
||
if (tabItem) {
|
||
// 临时提升 z-index 让 tab 浮在 overlay 之上
|
||
tabItem.style.position = 'relative';
|
||
tabItem.style.zIndex = '260';
|
||
}
|
||
if (tabIcon) {
|
||
tabIcon.classList.remove('tab-pulse');
|
||
// 触发重排以重启动画
|
||
void tabIcon.offsetWidth;
|
||
tabIcon.classList.add('tab-pulse');
|
||
}
|
||
var badge = document.getElementById('welfareTabBadge');
|
||
badge.classList.remove('show');
|
||
void badge.offsetWidth;
|
||
badge.classList.add('show');
|
||
// 余额在当前 mock 基数上累加新手礼包。
|
||
var coinStart = welfareCoinBalance;
|
||
var coinEnd = coinStart + 5000;
|
||
var cashEl = document.getElementById('welfareCashBalance');
|
||
var cashStart = parseFloat((cashEl && cashEl.textContent || '0').replace(/,/g, '')) || 0;
|
||
var cashEnd = cashStart + 0.5;
|
||
welfareCoinBalance = coinEnd;
|
||
welfareCashBalance = cashEnd;
|
||
animateNumber(document.getElementById('welfareCoinBalance'), coinStart, coinEnd, 1200, function(v) {
|
||
return v.toLocaleString();
|
||
});
|
||
animateNumber(cashEl, cashStart, cashEnd, 1200, function(v) {
|
||
return v.toFixed(2);
|
||
});
|
||
}, 600);
|
||
// 主按钮切换
|
||
btn.textContent = '开心收下,立即使用';
|
||
btn.onclick = claimGift;
|
||
}, 300);
|
||
}
|
||
|
||
function flyCoinsToWelfareTab() {
|
||
var card = document.getElementById('welcomeGiftCard');
|
||
var device = document.getElementById('app');
|
||
var tabIcon = document.getElementById('homeTabWelfareIcon');
|
||
if (!card || !device || !tabIcon) return;
|
||
|
||
var deviceRect = device.getBoundingClientRect();
|
||
var cardRect = card.getBoundingClientRect();
|
||
var tabRect = tabIcon.getBoundingClientRect();
|
||
|
||
// 宝箱中心相对于 device 的坐标
|
||
var startX = (cardRect.left + cardRect.width / 2) - deviceRect.left;
|
||
var startY = (cardRect.top + cardRect.height / 2) - deviceRect.top;
|
||
// 福利 tab 图标中心
|
||
var endX = (tabRect.left + tabRect.width / 2) - deviceRect.left;
|
||
var endY = (tabRect.top + tabRect.height / 2) - deviceRect.top;
|
||
|
||
var COIN_COUNT = 16;
|
||
for (var i = 0; i < COIN_COUNT; i++) {
|
||
var coin = document.createElement('div');
|
||
coin.className = 'fly-coin';
|
||
coin.textContent = '🪙';
|
||
// 起点定位(绝对定位 in device)
|
||
coin.style.left = startX + 'px';
|
||
coin.style.top = startY + 'px';
|
||
// burst 散射点(爆开瞬间)
|
||
var angle = (Math.PI * 2 * i) / COIN_COUNT + Math.random() * 0.4;
|
||
var burstDist = 60 + Math.random() * 60;
|
||
var bx = Math.cos(angle) * burstDist;
|
||
var by = Math.sin(angle) * burstDist - 30; // 略偏上
|
||
// 终点偏移(相对起点)
|
||
var tx = endX - startX + (Math.random() - 0.5) * 16;
|
||
var ty = endY - startY + (Math.random() - 0.5) * 8;
|
||
coin.style.setProperty('--bx', bx + 'px');
|
||
coin.style.setProperty('--by', by + 'px');
|
||
coin.style.setProperty('--tx', tx + 'px');
|
||
coin.style.setProperty('--ty', ty + 'px');
|
||
coin.style.setProperty('--d', (i * 18) + 'ms');
|
||
device.appendChild(coin);
|
||
// 动画结束后移除
|
||
coin.addEventListener('animationend', function() {
|
||
this.remove();
|
||
});
|
||
}
|
||
}
|
||
|
||
function animateWelfareAssetIntro() {
|
||
animateNumber(document.getElementById('welfareCoinBalance'), 0, welfareCoinBalance, 760, function(v) {
|
||
return Math.round(v).toLocaleString();
|
||
});
|
||
animateNumber(document.getElementById('welfareCashBalance'), 0, welfareCashBalance, 760, function(v) {
|
||
return v.toFixed(2);
|
||
});
|
||
}
|
||
|
||
function claimTaskReward(title, amount) {
|
||
var start = welfareCoinBalance;
|
||
welfareCoinBalance += amount;
|
||
animateNumber(document.getElementById('welfareCoinBalance'), start, welfareCoinBalance, amount >= 1000 ? 860 : 680, function(v) {
|
||
return Math.round(v).toLocaleString();
|
||
});
|
||
showRewardToast(title, amount);
|
||
}
|
||
|
||
function showRewardToast(title, amount) {
|
||
var existing = document.getElementById('rewardToast');
|
||
if (existing) existing.remove();
|
||
|
||
var toast = document.createElement('div');
|
||
toast.id = 'rewardToast';
|
||
toast.className = 'reward-toast';
|
||
|
||
var icon = document.createElement('img');
|
||
icon.className = 'reward-toast-icon';
|
||
icon.src = 'assets/welfare/index/checkin-coins-600.png';
|
||
icon.alt = '';
|
||
|
||
var amountEl = document.createElement('div');
|
||
amountEl.className = 'reward-toast-amount';
|
||
amountEl.textContent = '+' + Math.round(amount).toLocaleString();
|
||
|
||
var titleEl = document.createElement('div');
|
||
titleEl.className = 'reward-toast-title';
|
||
titleEl.textContent = title;
|
||
|
||
toast.appendChild(icon);
|
||
toast.appendChild(amountEl);
|
||
toast.appendChild(titleEl);
|
||
document.getElementById('app').appendChild(toast);
|
||
|
||
setTimeout(function() {
|
||
toast.classList.add('is-leaving');
|
||
}, 1450);
|
||
setTimeout(function() {
|
||
if (toast.parentNode) toast.remove();
|
||
}, 1700);
|
||
}
|
||
|
||
function claimVideoReward() {
|
||
if (videoRewardClaimed) return;
|
||
videoRewardClaimed = true;
|
||
claimTaskReward('任务奖励', 1859);
|
||
var cta = document.getElementById('r8VideoTaskCta');
|
||
if (cta) {
|
||
cta.textContent = '已领取';
|
||
cta.classList.add('is-done');
|
||
cta.disabled = true;
|
||
}
|
||
}
|
||
|
||
function claimMessageReminderReward() {
|
||
if (messageReminderRewardClaimed) return;
|
||
messageReminderRewardClaimed = true;
|
||
claimTaskReward('任务奖励', 10000);
|
||
var cta = document.getElementById('r8MessageTaskCta');
|
||
var sub = document.getElementById('r8MessageTaskSub');
|
||
if (sub) sub.textContent = '消息提醒已开启';
|
||
if (cta) {
|
||
cta.textContent = '已开启';
|
||
cta.classList.add('is-done');
|
||
cta.disabled = true;
|
||
}
|
||
}
|
||
|
||
function claimRecordComparisonReward() {
|
||
if (recordComparisonRewardClaimed) return;
|
||
recordComparisonRewardClaimed = true;
|
||
|
||
var activeBox = document.querySelector('#r8RecordTaskBlock .r8-record-reward-box.active');
|
||
if (activeBox) {
|
||
activeBox.classList.remove('active');
|
||
activeBox.classList.add('done');
|
||
var status = activeBox.querySelector('.r8-record-status');
|
||
if (status) status.textContent = '已领取';
|
||
var coin = activeBox.querySelector('.r8-record-coin');
|
||
if (coin) coin.remove();
|
||
if (activeBox.tagName === 'BUTTON') {
|
||
activeBox.disabled = true;
|
||
activeBox.setAttribute('aria-label', '第2次记录比价奖励已领取180金币');
|
||
}
|
||
}
|
||
|
||
claimTaskReward('比价奖励', 180);
|
||
}
|
||
|
||
function animateNumber(el, from, to, duration, formatter) {
|
||
if (!el) return;
|
||
el.__animateNumberToken = (el.__animateNumberToken || 0) + 1;
|
||
var token = el.__animateNumberToken;
|
||
var start = performance.now();
|
||
function frame(now) {
|
||
if (token !== el.__animateNumberToken) return;
|
||
var t = Math.min(1, (now - start) / duration);
|
||
var eased = 1 - Math.pow(1 - t, 3); // ease-out cubic
|
||
var v = from + (to - from) * eased;
|
||
el.textContent = formatter ? formatter(v) : Math.round(v).toString();
|
||
if (t < 1) requestAnimationFrame(frame);
|
||
else el.textContent = formatter ? formatter(to) : to.toString();
|
||
}
|
||
requestAnimationFrame(frame);
|
||
}
|
||
|
||
function claimGift() {
|
||
welcomeGiftClaimed = true;
|
||
closeWelcomeGift(false);
|
||
}
|
||
|
||
function closeWelcomeGift(skipped) {
|
||
document.getElementById('welcomeGiftPopup').classList.remove('show');
|
||
// 还原 tab 的 z-index
|
||
var tabItem = document.getElementById('homeTabWelfare');
|
||
if (tabItem) {
|
||
tabItem.style.position = '';
|
||
tabItem.style.zIndex = '';
|
||
}
|
||
if (skipped) {
|
||
// 重置卡片为初始状态以备重弹(但目前 welcomeGiftShown 已 true,不会重弹)
|
||
var card = document.getElementById('welcomeGiftCard');
|
||
card.classList.remove('opened');
|
||
document.getElementById('giftChestEmoji').textContent = '🎁';
|
||
var btn = document.getElementById('giftMainBtn');
|
||
btn.textContent = '✨ 开启礼包';
|
||
btn.onclick = openGiftBox;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
// ===== 登录流程 =====
|
||
let pendingLoginAction = null; // 记录待执行的登录动作
|
||
|
||
function showToast(msg) {
|
||
var t = document.getElementById('loginToast');
|
||
t.textContent = msg;
|
||
t.style.display = 'block';
|
||
setTimeout(function(){ t.style.display = 'none'; }, 2000);
|
||
}
|
||
|
||
function toggleAgreeCheck() {
|
||
var chk = document.getElementById('agreeCheck');
|
||
chk.classList.toggle('checked');
|
||
var hint = document.getElementById('agreeHint');
|
||
if (hint) hint.style.display = chk.classList.contains('checked') ? 'none' : 'block';
|
||
}
|
||
|
||
function toggleAgreeCheckCeleb() {
|
||
var chk = document.getElementById('agreeCheckCeleb');
|
||
chk.classList.toggle('checked');
|
||
}
|
||
function isAgreedCeleb() {
|
||
return document.getElementById('agreeCheckCeleb').classList.contains('checked');
|
||
}
|
||
function celebOnboardingLogin() {
|
||
if (!isAgreedCeleb()) { showAgreeModal('celeb-quick'); return; }
|
||
doLogin();
|
||
}
|
||
|
||
function togglePhoneAgree() {
|
||
var chk = document.getElementById('agreeCheckPhone');
|
||
chk.classList.toggle('checked');
|
||
}
|
||
|
||
function isAgreed() {
|
||
return document.getElementById('agreeCheck').classList.contains('checked');
|
||
}
|
||
|
||
function isPhoneAgreed() {
|
||
return document.getElementById('agreeCheckPhone').classList.contains('checked');
|
||
}
|
||
|
||
function showAgreeModal(action) {
|
||
pendingLoginAction = action;
|
||
document.getElementById('agreeModal').style.display = 'flex';
|
||
}
|
||
|
||
function closeAgreeModal() {
|
||
document.getElementById('agreeModal').style.display = 'none';
|
||
pendingLoginAction = null;
|
||
}
|
||
|
||
function agreeAndLogin() {
|
||
// 入口页(一键登录):勾选入口页协议并继续
|
||
var chk = document.getElementById('agreeCheck');
|
||
if (chk && !chk.classList.contains('checked')) chk.classList.add('checked');
|
||
// 祝贺页内嵌登录的协议同步勾选
|
||
var chkCeleb = document.getElementById('agreeCheckCeleb');
|
||
if (chkCeleb && !chkCeleb.classList.contains('checked')) chkCeleb.classList.add('checked');
|
||
document.getElementById('agreeModal').style.display = 'none';
|
||
if (pendingLoginAction === 'quick' || pendingLoginAction === 'celeb-quick') {
|
||
doLogin();
|
||
} else if (pendingLoginAction === 'phone') {
|
||
doPhoneLogin();
|
||
}
|
||
pendingLoginAction = null;
|
||
}
|
||
|
||
function showAgreePhoneModal() {
|
||
document.getElementById('agreePhoneModal').style.display = 'flex';
|
||
}
|
||
function closeAgreePhoneModal() {
|
||
document.getElementById('agreePhoneModal').style.display = 'none';
|
||
}
|
||
function agreeAndContinuePhone() {
|
||
var chkP = document.getElementById('agreeCheckPhone');
|
||
if (chkP && !chkP.classList.contains('checked')) chkP.classList.add('checked');
|
||
document.getElementById('agreePhoneModal').style.display = 'none';
|
||
doSendSms();
|
||
}
|
||
|
||
function doLogin() {
|
||
isLoggedIn = true; try{localStorage.setItem('proto_isLoggedIn','true');}catch(e){}
|
||
var target = loginFrom || 'home';
|
||
go(target);
|
||
// 主路径登录(不是从福利/我的回流的) + 首次 → 弹新手礼包
|
||
if (!welcomeGiftShown && target === 'home') {
|
||
welcomeGiftShown = true; try{localStorage.setItem('proto_welcomeGiftShown','true');}catch(e){}
|
||
setTimeout(showWelcomeGiftPopup, 400);
|
||
}
|
||
}
|
||
|
||
function onboardingLogin() {
|
||
if (!isAgreed()) { showAgreeModal('quick'); return; }
|
||
doLogin();
|
||
}
|
||
|
||
function showPhoneLogin() {
|
||
// 进入独立手机号登录页(Step1)
|
||
document.getElementById('lpStep1').style.display = 'block';
|
||
document.getElementById('lpStep2').style.display = 'none';
|
||
go('loginPhone');
|
||
setTimeout(function(){
|
||
var inp = document.getElementById('phoneInput');
|
||
if (inp) inp.focus();
|
||
}, 80);
|
||
}
|
||
|
||
function showQuickLogin() {
|
||
// 用于其他位置返回入口页(保留兼容)
|
||
if (smsTimer) { clearInterval(smsTimer); smsTimer = null; }
|
||
go('login');
|
||
}
|
||
|
||
function updatePhoneCta() {
|
||
var inp = document.getElementById('phoneInput');
|
||
var cta = document.getElementById('lpCta');
|
||
if (!inp || !cta) return;
|
||
if (inp.value.length >= 11) cta.classList.remove('disabled');
|
||
else cta.classList.add('disabled');
|
||
}
|
||
|
||
function backToPhoneStep1() {
|
||
document.getElementById('lpStep2').style.display = 'none';
|
||
document.getElementById('lpStep1').style.display = 'block';
|
||
if (smsTimer) { clearInterval(smsTimer); smsTimer = null; }
|
||
}
|
||
|
||
let smsTimer = null;
|
||
function doSendSms() {
|
||
var phone = document.getElementById('phoneInput').value;
|
||
if (phone.length < 11) { showToast('请输入正确的手机号'); return; }
|
||
// 显示手机号提示(脱敏)
|
||
var masked = phone.substring(0,3) + '****' + phone.substring(7);
|
||
document.getElementById('smsPhoneHint').textContent = '验证码已发送至 ' + masked;
|
||
// 切换到 Step2
|
||
document.getElementById('lpStep1').style.display = 'none';
|
||
document.getElementById('lpStep2').style.display = 'block';
|
||
// 清空验证码输入框
|
||
var boxes = document.getElementById('smsCodeBoxes').querySelectorAll('input');
|
||
boxes.forEach(function(b){ b.value = ''; });
|
||
boxes[0].focus();
|
||
// 倒计时
|
||
var btn = document.getElementById('smsBtn');
|
||
var sec = 60;
|
||
btn.style.color = 'var(--gray-400)';
|
||
btn.style.cursor = 'default';
|
||
btn.onclick = null;
|
||
btn.textContent = sec + 's 后重发';
|
||
smsTimer = setInterval(function(){
|
||
sec--;
|
||
if (sec <= 0) {
|
||
clearInterval(smsTimer);
|
||
smsTimer = null;
|
||
btn.style.color = '#FFD600';
|
||
btn.style.cursor = 'pointer';
|
||
btn.textContent = '重新发送';
|
||
btn.onclick = function(){ doSendSms(); };
|
||
} else {
|
||
btn.textContent = sec + 's 后重发';
|
||
}
|
||
}, 1000);
|
||
}
|
||
|
||
function sendSmsCode() {
|
||
// 手机号页有独立的协议勾选状态 + 独立居中弹窗
|
||
if (!isPhoneAgreed()) { showAgreePhoneModal(); return; }
|
||
doSendSms();
|
||
}
|
||
|
||
function smsCodeComplete() {
|
||
// 6位验证码全部填完,自动登录
|
||
var boxes = document.getElementById('smsCodeBoxes').querySelectorAll('input');
|
||
var code = '';
|
||
boxes.forEach(function(b){ code += b.value; });
|
||
if (code.length === 6) {
|
||
isLoggedIn = true; try{localStorage.setItem('proto_isLoggedIn','true');}catch(e){}
|
||
go(loginFrom || 'home');
|
||
}
|
||
}
|
||
|
||
// ===== 平台选择流程 =====
|
||
// 全量平台列表,外卖版优先;同系优先外卖版,有外卖版则隐藏主站版
|
||
const allApps = [
|
||
{ id: 'meituan-waimai', name: '美团', icon: 'assets/shared/logos/meituan.png', color: '#FF6B00', bg: '#FFF3E0', desc: '外卖·美食·买菜', installed: true, replaces: 'meituan' },
|
||
{ id: 'taobao-shanguang', name: '淘宝', icon: 'assets/shared/logos/taobao.png', color: '#FF6A00', bg: '#FFF3E0', desc: '外卖·超市·买药', installed: true, replaces: 'taobao' },
|
||
{ id: 'jd-waimai', name: '京东', icon: 'assets/shared/logos/jd.png', color: '#E1251B', bg: '#FFEBEE', desc: '品质外卖·新人立减', installed: false, replaces: 'jd' },
|
||
{ id: 'meituan', name: '美团', icon: 'assets/shared/logos/meituan.png', color: '#FFD600', bg: '#FFFDE7', desc: '团购·到店·买菜', installed: true },
|
||
{ id: 'taobao', name: '淘宝', icon: 'assets/shared/logos/taobao.png', color: '#FF5000', bg: '#FFF3E0', desc: '网购·百亿补贴', installed: true },
|
||
{ id: 'jd', name: '京东', icon: 'assets/shared/logos/jd.png', color: '#E1251B', bg: '#FFEBEE', desc: '又好又便宜', installed: true },
|
||
];
|
||
|
||
// 外卖版是这个产品的画布:只要 allApps 里有外卖版条目,就隐藏对应主站版(不论主站是否安装)。
|
||
// 未安装的外卖版仍然在列表里以 disabled 形态展示,强调"我们能比 3 个平台,但你少了 1 个"。
|
||
function getVisibleApps() {
|
||
const replacedIds = new Set(allApps.filter(a => a.replaces).map(a => a.replaces));
|
||
return allApps.filter(a => !replacedIds.has(a.id));
|
||
}
|
||
|
||
// 进入 productselect 时渲染平台列表
|
||
let platformScanDone = false;
|
||
function startPlatformScan() {
|
||
if (platformScanDone) return;
|
||
platformScanDone = true;
|
||
renderPlatformList();
|
||
startRewardCountdown();
|
||
}
|
||
|
||
function renderPlatformList() {
|
||
const visible = getVisibleApps();
|
||
|
||
// 已装 + 未装合并到同一列表,外形对齐,用样式区分 disabled 态
|
||
document.getElementById('installedApps').innerHTML = visible.map((app, i) => {
|
||
if (app.installed) {
|
||
return '' +
|
||
'<div onclick="selectPlatform(\'' + app.id + '\')" data-pcard="' + i + '" class="platform-card" style="background: #fff;border-radius: 14px;padding: 16px 16px;cursor: pointer;display: flex;align-items: center;gap: 12px;border: 1.5px solid var(--gray-200);margin-bottom: 8px;position: relative;transition: border-color .25s,box-shadow .25s,transform .15s;">' +
|
||
'<img src="' + app.icon + '" style="width: 48px;height: 48px;border-radius: 12px;flex-shrink: 0;object-fit: cover;" />' +
|
||
'<div style="flex: 1;min-width: 0;">' +
|
||
'<div style="font-size: 20px;font-weight: 700;color: var(--gray-900);letter-spacing: -.2px;">' + app.name + '</div>' +
|
||
'</div>' +
|
||
'<svg width="20" height="20" viewBox="0 0 20 20" fill="none" style="flex-shrink: 0;color: var(--gray-300);"><path d="M7.5 4.5l5.5 5.5-5.5 5.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
|
||
'</div>';
|
||
}
|
||
return '' +
|
||
'<div class="platform-card-disabled" aria-disabled="true" onclick="onPlatformInstallClick(\'' + app.id + '\')" style="background: #FAFAFA;border-radius: 14px;padding: 16px 16px;cursor: pointer;display: flex;align-items: center;gap: 12px;border: 1.5px solid #ECECEC;margin-bottom: 8px;position: relative;">' +
|
||
'<img src="' + app.icon + '" style="width: 48px;height: 48px;border-radius: 12px;flex-shrink: 0;object-fit: cover;filter: grayscale(.7);opacity: .55;" />' +
|
||
'<div style="flex: 1;min-width: 0;">' +
|
||
'<div style="font-size: 20px;font-weight: 700;color: var(--gray-400);letter-spacing: -.2px;">' + app.name + '</div>' +
|
||
'</div>' +
|
||
'<span style="flex-shrink: 0;display: inline-flex;align-items: center;gap: 8px;">' +
|
||
'<span style="font-size: 15px;font-weight: 700;color: var(--gray-900);line-height: 1;">去安装</span>' +
|
||
'<svg width="20" height="20" viewBox="0 0 20 20" fill="none" style="color: var(--gray-300);"><path d="M7.5 4.5l5.5 5.5-5.5 5.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
|
||
'</span>' +
|
||
'</div>';
|
||
}).join('');
|
||
|
||
// 旧的次级"未安装"分区不再使用
|
||
document.getElementById('notInstalledSection').style.display = 'none';
|
||
}
|
||
|
||
// 领券浮窗 / 比价浮窗顶部的平台进度 mini icons —— 只渲染已安装的平台
|
||
// states: { 'platform-id': 'done' | 'active' | 'pending' }
|
||
function renderFloatPlatforms(containerId, states) {
|
||
const container = document.getElementById(containerId);
|
||
if (!container) return;
|
||
const installed = getVisibleApps().filter(a => a.installed);
|
||
container.innerHTML = installed.map(app => {
|
||
const state = (states && states[app.id]) || 'pending';
|
||
return '<div class="cmp-platform-mini ' + state + '"><img src="' + app.icon + '" alt="' + app.name + '"/></div>';
|
||
}).join('');
|
||
}
|
||
|
||
// 一键领券弹窗 · 3 平台卡片渲染。已装:黄边 + ✓;未装(方案 C):灰底 + 黄圆 ↓ 角标
|
||
function couponChipShortName(name) {
|
||
return name.replace(/外卖$|闪购$/, '');
|
||
}
|
||
function renderCouponPromptPlatforms() {
|
||
const grid = document.getElementById('couponPlatformGrid');
|
||
if (!grid) return;
|
||
const installedList = getInstalledPkgSet(); // 真装机态(同去点餐,替换写死的 mock app.installed)
|
||
const platforms = getVisibleApps(); // 3 张外卖版卡片
|
||
grid.innerHTML = platforms.map(app => {
|
||
const shortName = couponChipShortName(app.name);
|
||
const installed = (PICKER_PACKAGES[app.name] || []).some(function(p){ return installedList.indexOf(p) !== -1; });
|
||
if (installed) {
|
||
return '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FF5630;border-radius: 14px;padding: 12px 4px 8px;position: relative;">' +
|
||
'<img src="' + app.icon + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/>' +
|
||
'<div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + shortName + '</div>' +
|
||
'<span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FF5630;display: flex;align-items: center;justify-content: center;">' +
|
||
'<svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg>' +
|
||
'</span>' +
|
||
'</div>';
|
||
}
|
||
return '<div class="cp-card-uninstalled" aria-disabled="true" style="background: #FAFAFA;border: 1.5px solid #ECECEC;border-radius: 14px;padding: 12px 4px 8px;position: relative;">' +
|
||
'<img src="' + app.icon + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;filter: grayscale(.7);opacity: .55;"/>' +
|
||
'<div style="font-size: 12px;font-weight: 700;color: #BBB;margin-top: 8px;">' + shortName + '</div>' +
|
||
'<span style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFD600;box-shadow: 0 0 0 1.5px rgba(255,179,0,.35);display: flex;align-items: center;justify-content: center;">' +
|
||
'<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M5 1.5v5.5m0 0L2.5 4.5M5 7l2.5-2.5M2 9h6" stroke="#1a1a1a" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
|
||
'</span>' +
|
||
'</div>';
|
||
}).join('');
|
||
}
|
||
|
||
let selectedAppForBubble = null;
|
||
function selectPlatform(platformId) {
|
||
const app = allApps.find(a => a.id === platformId);
|
||
if (!app) return;
|
||
selectedAppForBubble = app;
|
||
go('comparing');
|
||
}
|
||
|
||
// 未安装平台 → 跳应用市场(原型 stub)
|
||
function onPlatformInstallClick(platformId) {
|
||
const app = allApps.find(a => a.id === platformId);
|
||
if (!app) return;
|
||
console.log('[install] 跳应用市场下载:', app.name);
|
||
}
|
||
|
||
function showWelcomeBubble() {
|
||
const mask = document.getElementById('welcomeMask');
|
||
const bubble = document.getElementById('welcomeBubble');
|
||
const title = document.getElementById('welcomeTitle');
|
||
const app = selectedAppForBubble || { name: '美团' };
|
||
|
||
title.textContent = '已为您唤起' + app.name;
|
||
|
||
mask.style.display = 'block';
|
||
bubble.style.display = 'block';
|
||
// 强制重排,让初始 opacity:0 / scale .92 生效
|
||
void bubble.offsetWidth;
|
||
|
||
requestAnimationFrame(() => {
|
||
mask.style.opacity = '1';
|
||
bubble.style.opacity = '1';
|
||
bubble.style.transform = 'translate(-50%,-50%) scale(1)';
|
||
});
|
||
|
||
setTimeout(() => {
|
||
mask.style.opacity = '0';
|
||
bubble.style.opacity = '0';
|
||
setTimeout(() => {
|
||
mask.style.display = 'none';
|
||
bubble.style.display = 'none';
|
||
}, 450);
|
||
}, 2000);
|
||
}
|
||
|
||
// 红包倒计时
|
||
let countdownInterval;
|
||
let rewardPhase = 0; // 0=首次, 1=已过期, 2=二次机会
|
||
|
||
function startRewardCountdown() {
|
||
let total = 300; // 5分钟
|
||
rewardPhase = 0;
|
||
updateRewardCard('active');
|
||
runCountdown(total);
|
||
}
|
||
|
||
function runCountdown(totalSeconds) {
|
||
let remaining = totalSeconds * 10; // 1/10秒为单位
|
||
const el = document.getElementById('rewardCountdown');
|
||
if (!el) return;
|
||
clearInterval(countdownInterval);
|
||
countdownInterval = setInterval(() => {
|
||
remaining--;
|
||
if (remaining <= 0) {
|
||
clearInterval(countdownInterval);
|
||
remaining = 0;
|
||
onCountdownEnd();
|
||
}
|
||
const totalSec = Math.floor(remaining / 10);
|
||
const tenths = remaining % 10;
|
||
const m = String(Math.floor(totalSec / 60)).padStart(2, '0');
|
||
const s = String(totalSec % 60).padStart(2, '0');
|
||
el.textContent = m + ':' + s + '.' + tenths;
|
||
}, 100);
|
||
}
|
||
|
||
function onCountdownEnd() {
|
||
if (rewardPhase === 0) {
|
||
// 首次过期 → 显示过期状态
|
||
rewardPhase = 1;
|
||
updateRewardCard('expired');
|
||
// 2秒后给二次机会
|
||
setTimeout(() => {
|
||
rewardPhase = 2;
|
||
updateRewardCard('second-chance');
|
||
runCountdown(180); // 二次机会 3分钟
|
||
}, 2000);
|
||
} else {
|
||
// 二次也过期 → 最终过期
|
||
updateRewardCard('final-expired');
|
||
}
|
||
}
|
||
|
||
function updateRewardCard(state) {
|
||
const card = document.getElementById('rewardCard');
|
||
if (!card) return;
|
||
if (state === 'active') {
|
||
card.style.background = 'linear-gradient(135deg,#FFF8E1,#FFECB3)';
|
||
card.style.opacity = '1';
|
||
card.innerHTML = `
|
||
<div style="flex-shrink: 0;font-size: 36px;line-height: 1;">🧧</div>
|
||
<div style="flex: 1;">
|
||
<div style="font-size: 14px;font-weight: 700;color: var(--gray-900);">完成首次比价领红包奖励</div>
|
||
</div>`;
|
||
} else if (state === 'expired') {
|
||
card.style.background = 'var(--gray-100)';
|
||
card.style.opacity = '.6';
|
||
card.innerHTML = `
|
||
<div style="flex-shrink: 0;font-size: 36px;line-height: 1;filter: grayscale(1);">🧧</div>
|
||
<div style="flex: 1;">
|
||
<div style="font-size: 14px;font-weight: 700;color: var(--gray-500);">红包已过期</div>
|
||
<div style="font-size: 12px;color: var(--gray-400);margin-top: 2px;">很遗憾,活动已结束</div>
|
||
</div>`;
|
||
} else if (state === 'second-chance') {
|
||
card.style.background = 'linear-gradient(135deg,#FFEBEE,#FFCDD2)';
|
||
card.style.opacity = '1';
|
||
card.innerHTML = `
|
||
<div style="flex-shrink: 0;font-size: 36px;line-height: 1;">🎁</div>
|
||
<div style="flex: 1;">
|
||
<div style="font-size: 14px;font-weight: 700;color: #E53935;">再给你一次机会!</div>
|
||
<div style="font-size: 12px;color: #FF5722;font-weight: 600;margin-top: 2px;">最后 <span id="rewardCountdown">03:00.0</span></div>
|
||
</div>`;
|
||
} else if (state === 'final-expired') {
|
||
card.style.background = 'var(--gray-100)';
|
||
card.style.opacity = '.5';
|
||
card.innerHTML = `
|
||
<div style="flex-shrink: 0;font-size: 36px;line-height: 1;filter: grayscale(1);">🧧</div>
|
||
<div style="flex: 1;">
|
||
<div style="font-size: 14px;font-weight: 600;color: var(--gray-400);">新人红包奖励已过期</div>
|
||
</div>`;
|
||
}
|
||
}
|
||
|
||
// 卡片轮流高亮
|
||
let cardRotationInterval;
|
||
function startCardRotation(count) {
|
||
let active = 0;
|
||
function highlight() {
|
||
document.querySelectorAll('[data-pcard]').forEach((el, i) => {
|
||
if (i === active) {
|
||
el.style.borderColor = '#FF5722';
|
||
el.style.boxShadow = '0 0 0 1px #FF5722';
|
||
el.querySelector('.tap-hand-icon').style.opacity = '1';
|
||
el.querySelector('.tap-hand-icon').classList.add('tap-hand');
|
||
} else {
|
||
el.style.borderColor = 'var(--gray-200)';
|
||
el.style.boxShadow = 'none';
|
||
el.querySelector('.tap-hand-icon').style.opacity = '0';
|
||
el.querySelector('.tap-hand-icon').classList.remove('tap-hand');
|
||
}
|
||
});
|
||
active = (active + 1) % count;
|
||
}
|
||
highlight();
|
||
clearInterval(cardRotationInterval);
|
||
cardRotationInterval = setInterval(highlight, 2100);
|
||
}
|
||
|
||
// 省钱数字滚动动画(已弃用但保留兼容)
|
||
function animateSavingCounter() {
|
||
const el = document.getElementById('savingCounter');
|
||
const target = 12847;
|
||
const duration = 1500;
|
||
const start = performance.now();
|
||
function tick(now) {
|
||
const p = Math.min((now - start) / duration, 1);
|
||
const ease = 1 - Math.pow(1 - p, 3);
|
||
el.textContent = Math.floor(target * ease).toLocaleString();
|
||
if (p < 1) requestAnimationFrame(tick);
|
||
}
|
||
requestAnimationFrame(tick);
|
||
}
|
||
|
||
// 商品点击 → 过渡提示 → 进入比价(兼容旧调用)
|
||
function startProductCompare() {
|
||
selectPlatform('meituan-waimai');
|
||
}
|
||
|
||
// ===== 反馈面板 =====
|
||
function openFeedbackSheet() {
|
||
const sheet = document.getElementById('feedbackSheet');
|
||
// 重置到步骤1
|
||
document.getElementById('fbStep1').style.display = 'block';
|
||
document.getElementById('fbFormLower').style.display = 'none';
|
||
document.getElementById('fbFormWrong').style.display = 'none';
|
||
document.getElementById('fbSuccess').style.display = 'none';
|
||
// 动态生成平台选项(仅显示 found/same-price 的平台)
|
||
const pl = document.getElementById('fbPlatformList');
|
||
if (pl) {
|
||
pl.innerHTML = results.filter(r => r.status !== 'not-found').map(r =>
|
||
`<div class="fb-platform" onclick="this.classList.toggle('selected')" style="padding: 8px 16px;border: 1.5px solid var(--gray-200);border-radius: 32px;font-size: 13px;font-weight: 600;cursor: pointer;display: flex;align-items: center;gap: 4px;"><img src="${r.platformIcon}" style="width: 16px;height: 16px;border-radius: 4px;"> ${r.platform}</div>`
|
||
).join('');
|
||
}
|
||
sheet.style.display = 'block';
|
||
}
|
||
|
||
function closeFeedbackSheet() {
|
||
document.getElementById('feedbackSheet').style.display = 'none';
|
||
}
|
||
|
||
function selectFbType(type) {
|
||
document.getElementById('fbStep1').style.display = 'none';
|
||
if (type === 'lower_price') {
|
||
document.getElementById('fbFormLower').style.display = 'block';
|
||
} else {
|
||
document.getElementById('fbFormWrong').style.display = 'block';
|
||
}
|
||
}
|
||
|
||
function backToFbStep1() {
|
||
document.getElementById('fbFormLower').style.display = 'none';
|
||
document.getElementById('fbFormWrong').style.display = 'none';
|
||
document.getElementById('fbStep1').style.display = 'block';
|
||
}
|
||
|
||
function submitFeedback() {
|
||
document.getElementById('fbFormLower').style.display = 'none';
|
||
document.getElementById('fbFormWrong').style.display = 'none';
|
||
document.getElementById('fbSuccess').style.display = 'block';
|
||
}
|
||
|
||
// 提现金额选择
|
||
function selectWd(el) {
|
||
document.querySelectorAll('.wd-opt').forEach(e => { e.style.borderColor='var(--gray-200)'; e.style.background='#fff'; });
|
||
el.style.borderColor='#FF5722'; el.style.background='#FFF3E0';
|
||
}
|
||
|
||
function showPrototypeToast(msg) {
|
||
var existing = document.getElementById('prototypeToast');
|
||
if (existing) existing.remove();
|
||
var toast = document.createElement('div');
|
||
toast.id = 'prototypeToast';
|
||
toast.textContent = msg;
|
||
toast.style.cssText = 'position:absolute;left:50%;bottom:118px;transform:translateX(-50%);max-width:310px;background:rgba(0,0,0,.78);color:#fff;font-size:13px;font-weight:600;line-height:18px;padding:10px 16px;border-radius:12px;z-index:9999;text-align:center;pointer-events:none;opacity:1;transition:opacity .25s;white-space:nowrap;';
|
||
document.getElementById('app').appendChild(toast);
|
||
setTimeout(function() { toast.style.opacity = '0'; }, 1500);
|
||
setTimeout(function() { if (toast.parentNode) toast.remove(); }, 1800);
|
||
}
|
||
|
||
function selectWithdrawAmount(el) {
|
||
document.querySelectorAll('.withdraw-amount').forEach(function(item) {
|
||
item.classList.remove('active');
|
||
});
|
||
el.classList.add('active');
|
||
openWechatBindSheet(el.dataset.amount || el.textContent.replace('元', '').trim());
|
||
}
|
||
|
||
function openWechatBindSheet(amount) {
|
||
var layer = document.getElementById('wechatBindSheet');
|
||
var amountEl = document.getElementById('wechatBindAmount');
|
||
if (amountEl) amountEl.textContent = amount || '0.3';
|
||
if (!layer) return;
|
||
layer.classList.add('open');
|
||
layer.setAttribute('aria-hidden', 'false');
|
||
}
|
||
|
||
function closeWechatBindSheet() {
|
||
var layer = document.getElementById('wechatBindSheet');
|
||
if (!layer) return;
|
||
layer.classList.remove('open');
|
||
layer.setAttribute('aria-hidden', 'true');
|
||
}
|
||
|
||
var incomeCurrentTab = 'coin';
|
||
|
||
function openIncomeHistory(tab) {
|
||
go('coinhistory');
|
||
setIncomeTab(tab);
|
||
}
|
||
|
||
function setIncomeTab(tab) {
|
||
incomeCurrentTab = tab === 'cash' ? 'cash' : 'coin';
|
||
var tabs = document.getElementById('incomeTabs');
|
||
var coinTab = document.getElementById('incomeTabCoin');
|
||
var cashTab = document.getElementById('incomeTabCash');
|
||
var track = document.getElementById('incomeRecordTrack');
|
||
var note = document.getElementById('incomeFooterNote');
|
||
var btn = document.getElementById('incomeFooterBtn');
|
||
if (tabs) tabs.dataset.active = incomeCurrentTab;
|
||
if (coinTab) coinTab.classList.toggle('active', incomeCurrentTab === 'coin');
|
||
if (cashTab) cashTab.classList.toggle('active', incomeCurrentTab === 'cash');
|
||
if (track) track.classList.toggle('cash-active', incomeCurrentTab === 'cash');
|
||
if (note) {
|
||
note.innerHTML = incomeCurrentTab === 'coin'
|
||
? '累计收益 <strong>2.18 元</strong>'
|
||
: '累计到账 <strong>2.36 元</strong>';
|
||
}
|
||
if (btn) btn.textContent = incomeCurrentTab === 'coin' ? '立即提现' : '去提现';
|
||
}
|
||
|
||
function initIncomeSwipe() {
|
||
var shell = document.getElementById('incomeRecordShell');
|
||
if (!shell) return;
|
||
var startX = 0;
|
||
var startY = 0;
|
||
var tracking = false;
|
||
|
||
function begin(x, y) {
|
||
startX = x;
|
||
startY = y;
|
||
tracking = true;
|
||
}
|
||
|
||
function finish(x, y) {
|
||
if (!tracking) return;
|
||
tracking = false;
|
||
var dx = x - startX;
|
||
var dy = y - startY;
|
||
if (Math.abs(dx) < 46 || Math.abs(dx) < Math.abs(dy) * 1.1) return;
|
||
if (dx < 0 && incomeCurrentTab === 'coin') setIncomeTab('cash');
|
||
if (dx > 0 && incomeCurrentTab === 'cash') setIncomeTab('coin');
|
||
}
|
||
|
||
shell.addEventListener('touchstart', function(e) {
|
||
if (!e.touches || !e.touches[0]) return;
|
||
begin(e.touches[0].clientX, e.touches[0].clientY);
|
||
}, { passive: true });
|
||
shell.addEventListener('touchend', function(e) {
|
||
var touch = e.changedTouches && e.changedTouches[0];
|
||
if (!touch) return;
|
||
finish(touch.clientX, touch.clientY);
|
||
}, { passive: true });
|
||
shell.addEventListener('mousedown', function(e) {
|
||
begin(e.clientX, e.clientY);
|
||
});
|
||
shell.addEventListener('mouseup', function(e) {
|
||
finish(e.clientX, e.clientY);
|
||
});
|
||
}
|
||
|
||
var EXCHANGE_COIN_BALANCE = 28967;
|
||
var currentExchangeAmount = EXCHANGE_COIN_BALANCE;
|
||
|
||
function exchangeCashText(coins) {
|
||
return (Math.floor(coins / 100) / 100).toFixed(2);
|
||
}
|
||
|
||
function selectExchangeAmount(amount, el) {
|
||
currentExchangeAmount = amount === 'all' ? EXCHANGE_COIN_BALANCE : Number(amount);
|
||
document.querySelectorAll('.exchange-preset').forEach(function(item) {
|
||
item.classList.remove('active');
|
||
});
|
||
if (el) el.classList.add('active');
|
||
var coinAmount = document.getElementById('exchangeCoinAmount');
|
||
var cashAmount = document.getElementById('exchangeCashAmount');
|
||
var error = document.getElementById('exchangeError');
|
||
if (coinAmount) coinAmount.textContent = currentExchangeAmount.toLocaleString('zh-CN');
|
||
if (cashAmount) cashAmount.textContent = exchangeCashText(currentExchangeAmount);
|
||
if (error) {
|
||
if (currentExchangeAmount > EXCHANGE_COIN_BALANCE) {
|
||
error.textContent = '超过已拥有金币数';
|
||
} else if (currentExchangeAmount < 100) {
|
||
error.textContent = '最低 100 金币起兑';
|
||
} else {
|
||
error.textContent = '';
|
||
}
|
||
}
|
||
}
|
||
|
||
function openExchangeSheet() {
|
||
var layer = document.getElementById('exchangeSheet');
|
||
if (!layer) return;
|
||
layer.classList.add('open');
|
||
layer.setAttribute('aria-hidden', 'false');
|
||
selectExchangeAmount('all', document.getElementById('exchangePresetAll'));
|
||
}
|
||
|
||
function closeExchangeSheet() {
|
||
var layer = document.getElementById('exchangeSheet');
|
||
if (!layer) return;
|
||
layer.classList.remove('open');
|
||
layer.setAttribute('aria-hidden', 'true');
|
||
}
|
||
|
||
function confirmExchange() {
|
||
if (currentExchangeAmount > EXCHANGE_COIN_BALANCE || currentExchangeAmount < 100) return;
|
||
closeExchangeSheet();
|
||
showPrototypeToast('兑换申请已提交,现金到账可能会有延迟');
|
||
}
|
||
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
initIncomeSwipe();
|
||
setIncomeTab('coin');
|
||
updateWelfareCheckinTask();
|
||
});
|
||
|
||
// ===== 退出登录 / 注销账号 =====
|
||
function showLogoutConfirm() {
|
||
document.getElementById('logoutConfirm').style.display = 'flex';
|
||
}
|
||
function closeLogoutConfirm() {
|
||
document.getElementById('logoutConfirm').style.display = 'none';
|
||
}
|
||
function doLogout() {
|
||
closeLogoutConfirm();
|
||
isLoggedIn = false; try{localStorage.setItem('proto_isLoggedIn','false');}catch(e){}
|
||
welfareVisited = false; try{localStorage.setItem('proto_welfareVisited','false');}catch(e){}
|
||
profileVisited = false; try{localStorage.setItem('proto_profileVisited','false');}catch(e){}
|
||
checkinShown = false; try{localStorage.setItem('proto_checkinShown','false');}catch(e){}
|
||
go('home');
|
||
}
|
||
function showDeleteConfirm() {
|
||
document.getElementById('deleteConfirm').style.display = 'flex';
|
||
}
|
||
function closeDeleteConfirm() {
|
||
document.getElementById('deleteConfirm').style.display = 'none';
|
||
}
|
||
function doDeleteAccount() {
|
||
closeDeleteConfirm();
|
||
isLoggedIn = false; try{localStorage.setItem('proto_isLoggedIn','false');}catch(e){}
|
||
welfareVisited = false; try{localStorage.setItem('proto_welfareVisited','false');}catch(e){}
|
||
profileVisited = false; try{localStorage.setItem('proto_profileVisited','false');}catch(e){}
|
||
checkinShown = false; try{localStorage.setItem('proto_checkinShown','false');}catch(e){}
|
||
go('home');
|
||
}
|
||
|
||
// Splash 不再自动跳转,等用户点击 CTA "开始体验"
|
||
// (旧的 splashCounter 累计数字动画已移除 — Option C 设计无大数字)
|
||
|
||
// Video 模拟
|
||
// ============ Video tutorial 状态机 (vt-) ============
|
||
const vt = {
|
||
status: 'initial', // initial | playing | paused | ended
|
||
elapsed: 0, // 已播毫秒
|
||
duration: 5000, // 5s 模拟一分钟,真实视频接入后改成视频时长
|
||
intervalId: null,
|
||
hasFinished: false,
|
||
isDragging: false,
|
||
};
|
||
const VT_PLAY = '<path d="M8 5v14l11-7z"/>';
|
||
const VT_PAUSE = '<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/>';
|
||
const VT_REPLAY = '<path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/>';
|
||
|
||
function vtRender() {
|
||
const player = document.getElementById('vt-video');
|
||
if (!player) return;
|
||
const fill = document.getElementById('vt-fill');
|
||
const cur = document.getElementById('vt-current');
|
||
const cta = document.getElementById('vt-cta');
|
||
const cIco = document.getElementById('vt-center-icon');
|
||
const bIco = document.getElementById('vt-bottom-icon');
|
||
|
||
player.className = 'vt-video-player ' + vt.status;
|
||
|
||
const progress = Math.min(vt.elapsed / vt.duration, 1);
|
||
fill.style.width = (progress * 100) + '%';
|
||
|
||
// 5s 真时长 → 显示成 1 分钟视频
|
||
const totalSec = Math.floor(progress * 60);
|
||
const min = Math.floor(totalSec / 60);
|
||
const sec = totalSec % 60;
|
||
cur.textContent = min + ':' + (sec < 10 ? '0' : '') + sec;
|
||
|
||
cIco.innerHTML = (vt.status === 'ended') ? VT_REPLAY : VT_PLAY;
|
||
bIco.innerHTML = (vt.status === 'playing') ? VT_PAUSE : VT_PLAY;
|
||
|
||
if (vt.hasFinished) {
|
||
cta.classList.remove('disabled');
|
||
cta.textContent = '进入快速设置';
|
||
} else {
|
||
cta.classList.add('disabled');
|
||
cta.textContent = '看完后继续';
|
||
}
|
||
}
|
||
|
||
function vtStopTimer() {
|
||
if (vt.intervalId !== null) { clearInterval(vt.intervalId); vt.intervalId = null; }
|
||
}
|
||
function vtStartTimer() {
|
||
vtStopTimer();
|
||
vt.intervalId = setInterval(() => {
|
||
vt.elapsed += 50;
|
||
if (vt.elapsed >= vt.duration) {
|
||
vt.elapsed = vt.duration;
|
||
vt.status = 'ended';
|
||
vt.hasFinished = true;
|
||
vtStopTimer();
|
||
}
|
||
vtRender();
|
||
}, 50);
|
||
}
|
||
function vtToggle() {
|
||
if (vt.status === 'playing') {
|
||
vtStopTimer();
|
||
vt.status = 'paused';
|
||
} else if (vt.status === 'ended') {
|
||
vt.elapsed = 0;
|
||
vt.status = 'playing';
|
||
vtStartTimer();
|
||
} else {
|
||
vt.status = 'playing';
|
||
vtStartTimer();
|
||
}
|
||
vtRender();
|
||
}
|
||
function vtNext() {
|
||
if (!vt.hasFinished) return;
|
||
vtStopTimer();
|
||
go('permission-step1');
|
||
}
|
||
|
||
let vtInited = false;
|
||
function vtInit() {
|
||
if (vtInited) return;
|
||
const player = document.getElementById('vt-video');
|
||
if (!player) return;
|
||
const track = document.getElementById('vt-track');
|
||
vtInited = true;
|
||
|
||
// 1. 点视频本身切换播放/暂停(排除 controls 与 center-play 的内联 onclick)
|
||
player.addEventListener('click', (e) => {
|
||
if (e.target.closest('.vt-controls')) return;
|
||
if (e.target.closest('.vt-center-play')) return;
|
||
vtToggle();
|
||
});
|
||
|
||
// 2. 进度条拖动(playing / paused 都支持)
|
||
function vtSeekFromX(clientX) {
|
||
const rect = track.getBoundingClientRect();
|
||
const ratio = Math.max(0, Math.min((clientX - rect.left) / rect.width, 1));
|
||
vt.elapsed = ratio * vt.duration;
|
||
if (ratio >= 1) {
|
||
vt.status = 'ended';
|
||
vt.hasFinished = true;
|
||
vtStopTimer();
|
||
} else if (vt.status === 'ended') {
|
||
vt.status = 'paused';
|
||
}
|
||
vtRender();
|
||
}
|
||
track.addEventListener('mousedown', (e) => {
|
||
e.preventDefault(); e.stopPropagation();
|
||
vt.isDragging = true; vtSeekFromX(e.clientX);
|
||
});
|
||
document.addEventListener('mousemove', (e) => { if (vt.isDragging) vtSeekFromX(e.clientX); });
|
||
document.addEventListener('mouseup', () => { vt.isDragging = false; });
|
||
track.addEventListener('touchstart', (e) => {
|
||
e.stopPropagation();
|
||
vt.isDragging = true; vtSeekFromX(e.touches[0].clientX);
|
||
}, {passive: true});
|
||
document.addEventListener('touchmove', (e) => { if (vt.isDragging) vtSeekFromX(e.touches[0].clientX); }, {passive: true});
|
||
document.addEventListener('touchend', () => { vt.isDragging = false; });
|
||
}
|
||
|
||
// startVideo 由"进入教程"触发:进入即自动播放
|
||
function startVideo() {
|
||
vtInit();
|
||
vt.elapsed = 0;
|
||
vt.hasFinished = false;
|
||
vtStopTimer();
|
||
vt.status = 'playing';
|
||
vtStartTimer();
|
||
vtRender();
|
||
}
|
||
// startVideo 由用户点击"进入教程"触发
|
||
|
||
// 商品选择
|
||
function selectProduct(el) {
|
||
document.querySelectorAll('.product-option').forEach(e => { e.style.borderColor='transparent'; e.style.background='var(--gray-50)'; });
|
||
el.style.borderColor='var(--primary)'; el.style.background='var(--primary-bg)';
|
||
document.getElementById('selectBtn').style.display='block';
|
||
}
|
||
|
||
// 比价模拟
|
||
// ===== 截图演示比价流程 =====
|
||
// spotlight: { top, left, width, height } 相对于375x812设备
|
||
// finger: { top, left } 手指位置
|
||
// guidePos: { top, left } 文案位置, 'above' = 聚光灯上方居中
|
||
const demoSteps = [
|
||
// ===== 一键领券前置流程 =====
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/meituan/1-home.jpg',
|
||
mode: 'couponPrompt',
|
||
},
|
||
// TODO: 替换为真实的美团神券中心 / 饿了么神券中心截图
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/meituan/1-home.jpg',
|
||
mode: 'agentFlow',
|
||
agentText: '正在打开美团神券中心...',
|
||
platforms: { 'meituan-waimai': 'active' },
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/meituan/1-home.jpg',
|
||
mode: 'agentFlow',
|
||
agentText: '已领取美团红包',
|
||
couponDelta: 8,
|
||
platforms: { 'meituan-waimai': 'done' },
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/taobao/2-coupon-center.jpg',
|
||
mode: 'agentFlow',
|
||
agentText: '正在领取淘宝神券...',
|
||
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/taobao/3-coupon-claimed.jpg',
|
||
mode: 'agentFlow',
|
||
agentText: '已领取淘宝神券',
|
||
couponDelta: 12,
|
||
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'done' },
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/meituan/1-home.jpg',
|
||
mode: 'couponDone',
|
||
},
|
||
// ===== 比价引导流程 =====
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/meituan/1-home.jpg',
|
||
guide: '• 点击下方店铺,并找到商品准备比价',
|
||
guideTitle: '找到待比价的商品',
|
||
kickoff: true,
|
||
spotlight: { top: 517, left: 7, width: 361, height: 125 },
|
||
finger: { top: 590, left: 312 },
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/meituan/2-shop-top.jpg',
|
||
guide: '下滑找到待比价的商品',
|
||
mode: 'swipe',
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/waimai-guide/add-to-cart.png',
|
||
guide: '点击「+」加入购物车',
|
||
spotlight: { top: 174, left: 70, width: 301, height: 152 },
|
||
plusFocus: { top: 295, left: 352 },
|
||
finger: { top: 306, left: 274, size: 60, plusGuide: true },
|
||
guideTop: 344,
|
||
guideLeft: 187.5,
|
||
clickTarget: 'plus',
|
||
spotlightRadius: 8,
|
||
spotlightOpacity: .62,
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/waimai-guide/missing-required.png',
|
||
guide: '点击添加必选品',
|
||
spotlight: { top: 719, left: 0, width: 375, height: 93 },
|
||
plusFocus: { top: 755, left: 311, width: 128, height: 54, shape: 'rect' },
|
||
finger: { top: 771, left: 236, size: 60, plusGuide: true },
|
||
guideTop: 664,
|
||
guideLeft: 187.5,
|
||
clickTarget: 'plus',
|
||
spotlightRadius: 0,
|
||
spotlightOpacity: .62,
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/waimai-guide/add-required-item.png',
|
||
guide: '点击「+」添加',
|
||
spotlight: { top: 306, left: 76, width: 296, height: 134 },
|
||
plusFocus: { top: 403, left: 352, width: 46, height: 46, shape: 'circle' },
|
||
finger: { top: 414, left: 274, size: 60, plusGuide: true },
|
||
guideTop: 458,
|
||
guideLeft: 187.5,
|
||
clickTarget: 'plus',
|
||
spotlightRadius: 8,
|
||
spotlightOpacity: .62,
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/meituan/5-shop-cart.jpg',
|
||
guide: '点击去结算',
|
||
spotlight: { top: 719, left: 0, width: 375, height: 93 },
|
||
plusFocus: { top: 790, left: 315, width: 112, height: 46, shape: 'pill' },
|
||
finger: { top: 735, left: 320, size: 60, imgTransform: 'rotate(-90deg)' },
|
||
guideTop: 660,
|
||
guideLeft: 187.5,
|
||
clickTarget: 'plus',
|
||
spotlightRadius: 0,
|
||
spotlightOpacity: .62,
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/meituan/6-checkout.jpg',
|
||
guide: '请选择待使用的红包',
|
||
spotlight: { top: 636, left: 14, width: 347, height: 48 },
|
||
finger: { top: 660, left: 315, size: 60, imgTransform: 'rotate(6deg)' },
|
||
guideTop: 580,
|
||
guideLeft: 187.5,
|
||
spotlightRadius: 20,
|
||
spotlightOpacity: .62,
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/meituan/7-coupon-select.jpg',
|
||
guide: '点击确认',
|
||
spotlight: { top: 752, left: 9, width: 354, height: 55 },
|
||
plusFocus: { top: 780, left: 312, width: 104, height: 52, shape: 'confirm' },
|
||
finger: { top: 729, left: 313, size: 60, imgTransform: 'rotate(-90deg)' },
|
||
guideTop: 696,
|
||
guideLeft: 187.5,
|
||
clickTarget: 'plus',
|
||
spotlightRadius: 24,
|
||
spotlightOpacity: .62,
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/meituan/8-checkout-coupon.jpg',
|
||
mode: 'startCompare',
|
||
},
|
||
// ===== 淘宝 Agent 自动比价流程 =====
|
||
// 比价阶段:美团已用作起点(done),淘宝为当前 active 平台
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/taobao/1-home.jpg',
|
||
mode: 'agentFlow',
|
||
agentText: '正在打开淘宝...',
|
||
retentionPercent: 11,
|
||
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/taobao/4-search.jpg',
|
||
mode: 'agentFlow',
|
||
agentText: '正在搜索「窑鸡王」...',
|
||
retentionPercent: 26,
|
||
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/taobao/5-shop-top.jpg',
|
||
mode: 'agentFlow',
|
||
agentText: '正在浏览菜单...',
|
||
retentionPercent: 40,
|
||
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/taobao/6-shop-item.jpg',
|
||
mode: 'agentFlow',
|
||
agentText: '搜索同款商品中...',
|
||
retentionPercent: 55,
|
||
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/taobao/7-spec.jpg',
|
||
mode: 'agentFlow',
|
||
agentText: '正在确认商品规格...',
|
||
retentionPercent: 70,
|
||
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/taobao/8-checkout.jpg',
|
||
mode: 'agentFlow',
|
||
agentText: '正在应用所有优惠...',
|
||
retentionPercent: 85,
|
||
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
|
||
},
|
||
{
|
||
img: 'assets/onboarding/index/platform-flows/taobao/result.jpg',
|
||
mode: 'agentFlow',
|
||
agentText: '正在获取淘宝最终价格',
|
||
retentionPercent: 100,
|
||
last: true,
|
||
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
|
||
},
|
||
];
|
||
let demoStep = 0;
|
||
let couponTotal = 0;
|
||
let pendingDemoStartStep = null;
|
||
|
||
function startComparison() {
|
||
demoStep = pendingDemoStartStep != null ? pendingDemoStartStep : 0;
|
||
pendingDemoStartStep = null;
|
||
couponTotal = 0;
|
||
const numEl = document.getElementById('demoCouponNum');
|
||
if (numEl) numEl.textContent = '0';
|
||
renderDemoStep();
|
||
}
|
||
|
||
// 距下一个 0 点倒计时(每秒更新 v6-expiry 三个 time-box)
|
||
let __midnightTimer = null;
|
||
function startMidnightCountdown() {
|
||
function pad(n) { return n < 10 ? '0' + n : '' + n; }
|
||
function tick() {
|
||
var hEl = document.getElementById('cdH');
|
||
var mEl = document.getElementById('cdM');
|
||
var sEl = document.getElementById('cdS');
|
||
if (!hEl || !mEl || !sEl) { stopMidnightCountdown(); return; }
|
||
var now = new Date();
|
||
var midnight = new Date(now);
|
||
midnight.setHours(24, 0, 0, 0);
|
||
var diff = Math.max(0, Math.floor((midnight - now) / 1000));
|
||
var h = Math.floor(diff / 3600);
|
||
var m = Math.floor((diff % 3600) / 60);
|
||
var s = diff % 60;
|
||
hEl.textContent = pad(h);
|
||
mEl.textContent = pad(m);
|
||
sEl.textContent = pad(s);
|
||
}
|
||
stopMidnightCountdown();
|
||
tick();
|
||
__midnightTimer = setInterval(tick, 1000);
|
||
}
|
||
function stopMidnightCountdown() {
|
||
if (__midnightTimer) { clearInterval(__midnightTimer); __midnightTimer = null; }
|
||
}
|
||
|
||
// 高频弹跳:N 次连续 +1,每次都触发数字弹跳 + 多向粒子喷射(F2 样式)
|
||
// K 方案:从 0 缓出到目标值(用于"领券完成"弹窗的总数和分平台数)
|
||
function runKCountUp(elId, target, duration, delay) {
|
||
const el = document.getElementById(elId);
|
||
if (!el) return;
|
||
el.textContent = '0';
|
||
setTimeout(() => {
|
||
let start = null;
|
||
const step = ts => {
|
||
if (!start) start = ts;
|
||
const p = Math.min((ts - start) / duration, 1);
|
||
const eased = 1 - Math.pow(1 - p, 3);
|
||
el.textContent = Math.round(target * eased);
|
||
if (p < 1) requestAnimationFrame(step);
|
||
};
|
||
requestAnimationFrame(step);
|
||
}, delay || 0);
|
||
}
|
||
|
||
function playCouponDelta(delta) {
|
||
const numEl = document.getElementById('demoCouponNum');
|
||
const numBlock = document.getElementById('demoCouponNumBlock');
|
||
if (!numEl || !numBlock) return;
|
||
const tickInterval = 130;
|
||
for (let i = 0; i < delta; i++) {
|
||
setTimeout(() => {
|
||
couponTotal += 1;
|
||
numEl.textContent = couponTotal;
|
||
numEl.classList.remove('coupon-num-pop');
|
||
void numEl.offsetWidth;
|
||
numEl.classList.add('coupon-num-pop');
|
||
const particleCount = 1 + Math.floor(Math.random() * 2);
|
||
for (let k = 0; k < particleCount; k++) {
|
||
const angle = -Math.PI / 2 + (Math.random() - 0.5) * 1.6;
|
||
const dist = 26 + Math.random() * 18;
|
||
const p = document.createElement('div');
|
||
p.className = 'coupon-plus-particle';
|
||
p.textContent = '+1';
|
||
p.style.setProperty('--dx', Math.cos(angle) * dist + 'px');
|
||
p.style.setProperty('--dy', Math.sin(angle) * dist + 'px');
|
||
numBlock.appendChild(p);
|
||
setTimeout(() => p.remove(), 900);
|
||
}
|
||
}, i * tickInterval);
|
||
}
|
||
}
|
||
|
||
function renderDemoStep() {
|
||
const s = demoSteps[demoStep];
|
||
document.getElementById('demoScreenshot').src = s.img;
|
||
// AI 接管橘黄光晕:仅在 agentFlow 阶段(块 1 一键领券 + 块 3 自动比价)开启
|
||
const aiGlow = document.getElementById('aiTakeoverGlow');
|
||
if (aiGlow) aiGlow.classList.toggle('active', s.mode === 'agentFlow');
|
||
// 进度条已移除(原 demoProgressBar),不再做按 step 计算宽度的逻辑
|
||
|
||
const spot = document.getElementById('demoSpotlight');
|
||
const plusFocus = document.getElementById('demoPlusFocus');
|
||
const finger = document.getElementById('demoFinger');
|
||
const guide = document.getElementById('demoGuide');
|
||
const guideText = document.getElementById('demoGuideText');
|
||
const kickoff = document.getElementById('demoKickoff');
|
||
const swipeOverlay = document.getElementById('demoSwipeOverlay');
|
||
const startOverlay = document.getElementById('demoStartOverlay');
|
||
|
||
const agentOverlay = document.getElementById('demoAgentOverlay');
|
||
const couponPrompt = document.getElementById('demoCouponPrompt');
|
||
const couponDoneToast = document.getElementById('demoCouponDoneToast');
|
||
|
||
// 先全部隐藏
|
||
swipeOverlay.style.display = 'none';
|
||
startOverlay.style.display = 'none';
|
||
agentOverlay.style.display = 'none';
|
||
couponPrompt.style.display = 'none';
|
||
couponDoneToast.style.display = 'none';
|
||
kickoff.style.display = 'none';
|
||
plusFocus.style.display = 'none';
|
||
plusFocus.className = 'demo-plus-focus';
|
||
plusFocus.style.width = '46px';
|
||
plusFocus.style.height = '46px';
|
||
finger.classList.remove('demo-plus-finger');
|
||
finger.style.width = '58px';
|
||
finger.style.height = '58px';
|
||
finger.style.zIndex = '15';
|
||
const fingerImg = finger.querySelector('.gesture-hand-img');
|
||
fingerImg.style.transform = '';
|
||
|
||
// ===== 一键领券弹窗 =====
|
||
if (s.mode === 'couponPrompt') {
|
||
spot.style.display = 'none';
|
||
finger.style.display = 'none';
|
||
guide.style.display = 'none';
|
||
renderCouponPromptPlatforms();
|
||
couponPrompt.style.display = 'flex';
|
||
return;
|
||
}
|
||
|
||
// ===== 一键领券完成 toast =====
|
||
if (s.mode === 'couponDone') {
|
||
spot.style.display = 'none';
|
||
finger.style.display = 'none';
|
||
guide.style.display = 'none';
|
||
// home 模式:toast 应展示在首页背景之上,先切回 home 再弹
|
||
if (homeClaimMode) {
|
||
go('home');
|
||
}
|
||
couponDoneToast.style.display = 'block';
|
||
// 0 → N 计数动画;不自动消失,等用户点击 CTA 才推进
|
||
runKCountUp('demoCouponDoneCount', couponTotal || 20, 1500, 200);
|
||
// 启动距 0 点倒计时(每秒滴答)
|
||
startMidnightCountdown();
|
||
return;
|
||
}
|
||
|
||
if (s.mode === 'swipe') {
|
||
spot.style.display = 'none';
|
||
finger.style.display = 'none';
|
||
guide.style.display = 'none';
|
||
swipeOverlay.style.display = 'flex';
|
||
swipeOverlay.querySelector('.swipe-text').textContent = s.guide;
|
||
return;
|
||
}
|
||
|
||
if (s.mode === 'startCompare') {
|
||
spot.style.display = 'none';
|
||
finger.style.display = 'none';
|
||
guide.style.display = 'none';
|
||
startOverlay.style.display = 'block';
|
||
return;
|
||
}
|
||
|
||
if (s.mode === 'agentFlow') {
|
||
spot.style.display = 'none';
|
||
finger.style.display = 'none';
|
||
guide.style.display = 'none';
|
||
agentOverlay.style.display = 'block';
|
||
// 块 1(领券) vs 块 3(比价)切换浮窗形态
|
||
const firstSpotlightIdx = demoSteps.findIndex(d => d.spotlight || d.mode === 'swipe' || d.mode === 'startCompare');
|
||
const inCouponPhase = firstSpotlightIdx > 0 && demoStep < firstSpotlightIdx;
|
||
const agentFloat = document.getElementById('demoAgentFloat');
|
||
const comparingFloat = document.getElementById('demoComparingFloat');
|
||
if (inCouponPhase) {
|
||
// 块 1:领券阶段 → 显示已领券计数浮窗(显式 flex,避免清掉 inline display:flex)
|
||
if (agentFloat) agentFloat.style.display = 'flex';
|
||
if (comparingFloat) comparingFloat.style.display = 'none';
|
||
document.getElementById('demoAgentText').textContent = s.agentText;
|
||
if (s.couponDelta) playCouponDelta(s.couponDelta);
|
||
renderFloatPlatforms('demoAgentPlatforms', s.platforms);
|
||
} else {
|
||
// 块 3:比价阶段 → 显示合并比价浮窗(无已领券计数,红包激励融入副文案动效)
|
||
if (agentFloat) agentFloat.style.display = 'none';
|
||
if (comparingFloat) comparingFloat.style.display = 'block';
|
||
document.getElementById('demoComparingText').textContent = s.agentText;
|
||
if (s.retentionPercent != null) {
|
||
const fill = document.getElementById('demoComparingFill');
|
||
if (fill) fill.style.width = s.retentionPercent + '%';
|
||
}
|
||
renderFloatPlatforms('demoComparingPlatforms', s.platforms);
|
||
}
|
||
return;
|
||
}
|
||
|
||
// 默认:聚光灯模式
|
||
spot.style.display = 'block';
|
||
spot.style.top = s.spotlight.top + 'px';
|
||
spot.style.left = s.spotlight.left + 'px';
|
||
spot.style.width = s.spotlight.width + 'px';
|
||
spot.style.height = s.spotlight.height + 'px';
|
||
spot.style.borderRadius = (s.spotlightRadius ? s.spotlightRadius + 'px' : '12px');
|
||
spot.style.boxShadow = '0 0 0 9999px rgba(0,0,0,' + (s.spotlightOpacity != null ? s.spotlightOpacity : .5) + ')';
|
||
spot.style.pointerEvents = s.clickTarget === 'plus' ? 'none' : 'auto';
|
||
spot.style.cursor = s.clickTarget === 'plus' ? 'default' : 'pointer';
|
||
|
||
if (s.plusFocus) {
|
||
plusFocus.style.display = 'block';
|
||
plusFocus.style.top = s.plusFocus.top + 'px';
|
||
plusFocus.style.left = s.plusFocus.left + 'px';
|
||
plusFocus.style.width = (s.plusFocus.width || 46) + 'px';
|
||
plusFocus.style.height = (s.plusFocus.height || 46) + 'px';
|
||
plusFocus.classList.add(s.plusFocus.shape || 'circle');
|
||
if (s.clickTarget === 'plus') plusFocus.classList.add('clickable');
|
||
}
|
||
|
||
if (s.finger) {
|
||
finger.style.display = 'block';
|
||
finger.style.top = s.finger.top + 'px';
|
||
finger.style.left = s.finger.left + 'px';
|
||
finger.style.width = (s.finger.size || 58) + 'px';
|
||
finger.style.height = (s.finger.size || 58) + 'px';
|
||
if (s.finger.plusGuide) {
|
||
finger.classList.add('demo-plus-finger');
|
||
finger.style.transform = 'none';
|
||
} else {
|
||
finger.style.transform = s.finger.mirror ? 'scaleX(-1)' : 'none';
|
||
if (s.finger.imgTransform) {
|
||
fingerImg.style.transform = s.finger.imgTransform;
|
||
}
|
||
}
|
||
} else {
|
||
finger.style.display = 'none';
|
||
}
|
||
|
||
if (s.kickoff && s.guide) {
|
||
// Kickoff 黄卡:标题 + 虚线 + 圆形箭头 + 引线
|
||
guide.style.display = 'none';
|
||
document.getElementById('demoKickoffTitle').textContent = s.guideTitle || '下一步,比出全网最低价';
|
||
document.getElementById('demoKickoffText').textContent = s.guide;
|
||
kickoff.style.display = 'block';
|
||
// 让卡片底部到引线落点正好对齐 spotlight 顶部
|
||
const cardEl = kickoff.querySelector('.kickoff-card');
|
||
const leaderH = 36;
|
||
const cardH = cardEl.offsetHeight;
|
||
kickoff.style.top = (s.spotlight.top - leaderH - cardH) + 'px';
|
||
} else if (s.guide) {
|
||
guide.style.display = 'block';
|
||
guideText.textContent = s.guide;
|
||
var bubbleTopY = null;
|
||
if (s.guideTop != null) {
|
||
guide.style.top = s.guideTop + 'px';
|
||
guide.style.left = (s.guideLeft != null ? s.guideLeft + 'px' : '50%');
|
||
guide.style.right = 'auto';
|
||
guide.style.transform = 'translateX(-50%)';
|
||
bubbleTopY = s.guideTop;
|
||
} else if (s.guidePos === 'above') {
|
||
const offset = s.guideOffset || -50;
|
||
guide.style.top = (s.spotlight.top + offset) + 'px';
|
||
bubbleTopY = s.spotlight.top + offset;
|
||
if (s.guideAlign === 'spotlight') {
|
||
var cx = s.spotlight.left + s.spotlight.width / 2;
|
||
// 渲染后检查是否超出屏幕,先设置位置
|
||
guide.style.left = cx + 'px';
|
||
guide.style.transform = 'translateX(-50%)';
|
||
// 延迟检查边界并修正
|
||
setTimeout(function() {
|
||
var rect = guide.getBoundingClientRect();
|
||
var device = document.getElementById('app').getBoundingClientRect();
|
||
if (rect.right > device.right - 8) {
|
||
guide.style.left = 'auto';
|
||
guide.style.right = '8px';
|
||
guide.style.transform = 'none';
|
||
}
|
||
}, 10);
|
||
} else {
|
||
guide.style.left = '50%';
|
||
guide.style.right = 'auto';
|
||
guide.style.transform = 'translateX(-50%)';
|
||
}
|
||
}
|
||
// 动态定位 leader:dot 中心贴在 spotlight 最近的边缘上
|
||
var leader = guide.querySelector('.demo-guide-leader');
|
||
if (leader) {
|
||
leader.classList.remove('dir-down', 'dir-up');
|
||
leader.style.height = '';
|
||
leader.style.display = '';
|
||
if (bubbleTopY != null && s.spotlight) {
|
||
var bubbleH = guideText.offsetHeight;
|
||
var bubbleBottomY = bubbleTopY + bubbleH;
|
||
var targetTop = s.spotlight.top;
|
||
var targetBottom = s.spotlight.top + s.spotlight.height;
|
||
if (bubbleBottomY <= targetTop) {
|
||
leader.classList.add('dir-down');
|
||
leader.style.height = Math.max(0, targetTop - bubbleBottomY + 1) + 'px';
|
||
} else if (bubbleTopY >= targetBottom) {
|
||
leader.classList.add('dir-up');
|
||
leader.style.height = Math.max(0, bubbleTopY - targetBottom + 1) + 'px';
|
||
} else {
|
||
leader.style.display = 'none';
|
||
}
|
||
} else {
|
||
leader.style.display = 'none';
|
||
}
|
||
}
|
||
} else {
|
||
guide.style.display = 'none';
|
||
}
|
||
}
|
||
|
||
function demoPlusHit(event) {
|
||
event.stopPropagation();
|
||
const el = event.currentTarget;
|
||
const rect = el.getBoundingClientRect();
|
||
const x = event.clientX - rect.left;
|
||
const y = event.clientY - rect.top;
|
||
if (el.classList.contains('circle')) {
|
||
const radius = Math.min(rect.width, rect.height) / 2;
|
||
const dx = x - rect.width / 2;
|
||
const dy = y - rect.height / 2;
|
||
if ((dx * dx + dy * dy) > radius * radius) {
|
||
return;
|
||
}
|
||
}
|
||
if (el.classList.contains('pill')) {
|
||
const radius = rect.height / 2;
|
||
const leftCap = radius;
|
||
const rightCap = rect.width - radius;
|
||
const inCenter = x >= leftCap && x <= rightCap && y >= 0 && y <= rect.height;
|
||
const dx = x < leftCap ? x - leftCap : x - rightCap;
|
||
const dy = y - radius;
|
||
if (!inCenter && (dx * dx + dy * dy) > radius * radius) {
|
||
return;
|
||
}
|
||
}
|
||
if (el.classList.contains('confirm')) {
|
||
const leftRadius = 4;
|
||
const rightRadius = rect.height / 2;
|
||
const inMiddle = y >= 0 && y <= rect.height && x >= leftRadius && x <= rect.width - rightRadius;
|
||
const inLeft = x >= 0 && x < leftRadius && y >= leftRadius && y <= rect.height - leftRadius;
|
||
const inRight = x > rect.width - rightRadius && x <= rect.width && y >= 0 && y <= rect.height;
|
||
const dx = x - (rect.width - rightRadius);
|
||
const dy = y - rightRadius;
|
||
if (!inMiddle && !inLeft && (!inRight || (dx * dx + dy * dy) > rightRadius * rightRadius)) {
|
||
return;
|
||
}
|
||
}
|
||
demoNext();
|
||
}
|
||
|
||
function demoNext() {
|
||
// 离开 couponDone 弹窗时关掉倒计时
|
||
stopMidnightCountdown();
|
||
const s = demoSteps[demoStep];
|
||
// home 一键领券模式:couponDone toast CTA → 回首页并切换"已领"态
|
||
if (homeClaimMode && s && s.mode === 'couponDone') {
|
||
onHomeCouponClaimDone();
|
||
return;
|
||
}
|
||
if (s.last) {
|
||
renderCelebrationSavings();
|
||
renderResults('celebResults');
|
||
go('celebration');
|
||
return;
|
||
}
|
||
if (demoStep < demoSteps.length - 1) {
|
||
demoStep++;
|
||
renderDemoStep();
|
||
}
|
||
}
|
||
|
||
// ===== 一键领券弹窗按钮 =====
|
||
function onClaimCouponConfirm() {
|
||
// H4:确认 → 触发原生领券(权限校验→缺则 OEM 引导→前台服务领券)。[] = 全领(对齐原生 platformSelectable=false);
|
||
// 领券时用户在外卖 App,进度由原生悬浮窗展示(D2),H5 不接事件流、也不再跳原型 coupon 页。
|
||
const prompt = document.getElementById('demoCouponPrompt');
|
||
if (prompt) prompt.style.display = 'none';
|
||
if (window.SGBridge && typeof SGBridge.startCouponClaim === 'function') SGBridge.startCouponClaim([]);
|
||
}
|
||
|
||
// ===== 首页"一键领优惠"卡片:去领取 → 弹窗 → agent 领券 → 完成 → 回首页 =====
|
||
let homeClaimMode = false;
|
||
let homeCouponClaimed = false;
|
||
let homeCouponClaimSummary = null; // { total, platforms: [{ id, name, icon }] }
|
||
|
||
// 领券完成弹窗:内嵌平台 logo —— 从几个平台领的就显示几个(来源 homeCouponClaimSummary.platforms)
|
||
function renderCouponDoneFromLogos() {
|
||
const el = document.getElementById('couponDoneFromLogos');
|
||
if (!el) return;
|
||
const platforms = (homeCouponClaimSummary && Array.isArray(homeCouponClaimSummary.platforms)) ? homeCouponClaimSummary.platforms : [];
|
||
el.innerHTML = platforms.map(function(p) {
|
||
return '<span class="lg-inline"><img src="' + p.icon + '" alt="' + (p.name || '') + '"></span>';
|
||
}).join('');
|
||
}
|
||
|
||
function onTriClaimClick() {
|
||
// H4:登录门槛(领券要归属用户)→ 未登录拉极光一键登录
|
||
if (window.SGBridge && typeof SGBridge.getToken === 'function' && !SGBridge.getToken()) { SGBridge.requestLogin(); return; }
|
||
// 今日已领 → 提示,不重复触发(完整「上次结算卡」回显留后续)
|
||
if (window.SGBridge && typeof SGBridge.getCouponClaimedToday === 'function' && SGBridge.getCouponClaimedToday()) {
|
||
if (typeof showToast === 'function') showToast('今日已领取~');
|
||
return;
|
||
}
|
||
// 弹领券确认弹窗:「一键自动领取」→ onClaimCouponConfirm → SGBridge.startCouponClaim
|
||
homeClaimMode = true;
|
||
couponTotal = 0;
|
||
renderCouponPromptPlatforms();
|
||
const prompt = document.getElementById('demoCouponPrompt');
|
||
if (prompt) prompt.style.display = 'flex';
|
||
}
|
||
|
||
function closeHomeCouponClaim() {
|
||
// 关闭弹窗 → 留在首页(保持未领状态)
|
||
const prompt = document.getElementById('demoCouponPrompt');
|
||
if (prompt) prompt.style.display = 'none';
|
||
homeClaimMode = false;
|
||
stopMidnightCountdown();
|
||
}
|
||
|
||
function onCouponPromptMaskClick(e) {
|
||
// 点击弹窗外侧蒙层关闭(home 模式才生效;点中卡片不关)
|
||
if (!homeClaimMode) return;
|
||
if (e.target && e.target.id === 'demoCouponPrompt') closeHomeCouponClaim();
|
||
}
|
||
|
||
function getStoredCouponAdRewardCoins() {
|
||
var reward = 0;
|
||
try {
|
||
reward = parseInt(localStorage.getItem('proto_couponAdRewardCoins') || '0', 10) || 0;
|
||
} catch(e) {}
|
||
return reward;
|
||
}
|
||
|
||
function showCouponAdRewardToast(amount) {
|
||
if (!amount || amount <= 0) return;
|
||
var existing = document.getElementById('adRewardToast');
|
||
if (existing) existing.remove();
|
||
|
||
var toast = document.createElement('div');
|
||
toast.id = 'adRewardToast';
|
||
toast.className = 'ad-reward-toast';
|
||
toast.setAttribute('aria-live', 'polite');
|
||
toast.setAttribute('aria-hidden', 'false');
|
||
|
||
for (var si = 1; si <= 6; si++) {
|
||
var spark = document.createElement('span');
|
||
spark.className = 'spark s' + si;
|
||
toast.appendChild(spark);
|
||
}
|
||
|
||
var icon = document.createElement('img');
|
||
icon.src = 'assets/welfare/index/checkin-coins-600.png';
|
||
icon.alt = '';
|
||
|
||
var amountEl = document.createElement('div');
|
||
amountEl.className = 'ad-reward-toast-amount';
|
||
amountEl.textContent = '+' + Math.round(amount);
|
||
|
||
var textEl = document.createElement('div');
|
||
textEl.className = 'ad-reward-toast-text';
|
||
textEl.textContent = '领券奖励已到账';
|
||
|
||
toast.appendChild(icon);
|
||
toast.appendChild(amountEl);
|
||
toast.appendChild(textEl);
|
||
document.getElementById('app').appendChild(toast);
|
||
requestAnimationFrame(function() { toast.classList.add('visible'); });
|
||
setTimeout(function() {
|
||
toast.classList.remove('visible');
|
||
toast.setAttribute('aria-hidden', 'true');
|
||
}, 1900);
|
||
setTimeout(function() {
|
||
if (toast.parentNode) toast.remove();
|
||
}, 2150);
|
||
}
|
||
|
||
function onHomeCouponClaimDone() {
|
||
// 用户点击结果 toast 的 CTA → 关 toast、持久化"已领"态、切首页卡片到"已领"展示
|
||
homeClaimMode = false;
|
||
homeCouponClaimed = true;
|
||
stopMidnightCountdown();
|
||
var couponAdRewardCoins = getStoredCouponAdRewardCoins();
|
||
const toast = document.getElementById('demoCouponDoneToast');
|
||
if (toast) toast.style.display = 'none';
|
||
// 如果是从 compare 跳回来的,summary 已经在 init 阶段从 localStorage 还原;否则现拼一个兜底值
|
||
if (!homeCouponClaimSummary) {
|
||
const platforms = (typeof getVisibleApps === 'function' ? getVisibleApps() : [])
|
||
.filter(a => a.installed)
|
||
.map(a => ({ id: a.id, name: a.name, icon: a.icon }));
|
||
homeCouponClaimSummary = {
|
||
total: couponTotal || 20,
|
||
platforms: platforms,
|
||
};
|
||
}
|
||
try {
|
||
localStorage.setItem('proto_homeCouponClaimed', 'true');
|
||
localStorage.setItem('proto_homeCouponClaimSummary', JSON.stringify(homeCouponClaimSummary));
|
||
localStorage.setItem('proto_home_coupon_claim_date', getTodayStr_home());
|
||
localStorage.removeItem('proto_showCouponDoneToast');
|
||
localStorage.removeItem('proto_couponAdRewardCoins');
|
||
} catch(e) {}
|
||
renderTriClaim();
|
||
showCouponAdRewardToast(couponAdRewardCoins);
|
||
// 收券后直接弹"选择常用平台"弹窗(图2),引导用户进入比价
|
||
if (typeof renderHomePickerPlatforms === 'function') renderHomePickerPlatforms();
|
||
var pickerMask = document.getElementById('homePickerMask');
|
||
if (pickerMask) pickerMask.classList.add('show');
|
||
}
|
||
|
||
// ===== 首页每日检查:权限提醒 + 领券提醒(每条每天最多 1 次)=====
|
||
function getTodayStr_home() {
|
||
var d = new Date();
|
||
return d.getFullYear() + '-' + String(d.getMonth()+1).padStart(2,'0') + '-' + String(d.getDate()).padStart(2,'0');
|
||
}
|
||
|
||
function runHomeDailyChecks() {
|
||
var today = getTodayStr_home();
|
||
|
||
// ① 权限提醒:任一权限关闭 → 弹一次 safetyModal
|
||
// 默认两个权限均为"开";只有用户/调试主动写 'off' 才视为关闭,模拟真实场景
|
||
var permRemindedToday = false;
|
||
try { permRemindedToday = localStorage.getItem('proto_home_perm_reminder_date') === today; } catch(e) {}
|
||
if (!permRemindedToday) {
|
||
var accOn = true, overlayOn = true;
|
||
try {
|
||
accOn = localStorage.getItem('proto_perm_accessibility') !== 'off';
|
||
overlayOn = localStorage.getItem('proto_perm_overlay') !== 'off';
|
||
} catch(e) {}
|
||
if (!accOn || !overlayOn) {
|
||
try { localStorage.setItem('proto_home_perm_reminder_date', today); } catch(e) {}
|
||
// 两个都关时优先提示无障碍(核心功能依赖项),让用户一次一个开
|
||
var permToShow = !accOn ? '无障碍' : '悬浮窗';
|
||
setTimeout(function() {
|
||
if (typeof openSafetyModal === 'function') openSafetyModal(permToShow);
|
||
}, 450);
|
||
return; // 权限弹窗优先,避免与领券弹窗叠层;领券推迟到明天
|
||
}
|
||
}
|
||
|
||
// ② 领券提醒:今日未领且今日未弹过 → 自动弹 onTriClaimClick 多平台领券窗
|
||
var couponRemindedToday = false;
|
||
var couponClaimedToday = false;
|
||
try {
|
||
couponRemindedToday = localStorage.getItem('proto_home_coupon_reminder_date') === today;
|
||
couponClaimedToday = localStorage.getItem('proto_home_coupon_claim_date') === today;
|
||
} catch(e) {}
|
||
if (!couponRemindedToday && !couponClaimedToday && !homeCouponClaimed) {
|
||
try { localStorage.setItem('proto_home_coupon_reminder_date', today); } catch(e) {}
|
||
setTimeout(function() {
|
||
if (typeof onTriClaimClick === 'function') onTriClaimClick();
|
||
}, 500);
|
||
}
|
||
}
|
||
|
||
// ===== LBS:仅手动点击 home「去授权」后弹系统询问 =====
|
||
const HOME_LOC_AUTH_MODE_KEY = 'proto_locationAuthMode'; // whileUsing / once / denied
|
||
const HOME_LOC_LEGACY_GRANTED_KEY = 'proto_locationGranted';
|
||
const HOME_LOC_ONCE_DATE_KEY = 'proto_location_once_date';
|
||
const HOME_LOC_SESSION_GRANTED_KEY = 'proto_location_session_granted';
|
||
const HOME_NEARBY_EMPTY_KEY = 'proto_home_nearby_empty';
|
||
function getHomeLocationMode() {
|
||
try {
|
||
var mode = localStorage.getItem(HOME_LOC_AUTH_MODE_KEY);
|
||
if (mode) return mode;
|
||
if (localStorage.getItem(HOME_LOC_LEGACY_GRANTED_KEY) === '1') return 'whileUsing';
|
||
} catch(e) {}
|
||
return '';
|
||
}
|
||
function isHomeLocationGranted() {
|
||
// H2a:优先读真·系统定位权限;无桥(浏览器无 bridge)兜底原 localStorage 模式。
|
||
try { if (window.SGBridge && typeof SGBridge.isLocationGranted === 'function') return !!SGBridge.isLocationGranted(); } catch(e) {}
|
||
var mode = getHomeLocationMode();
|
||
if (mode === 'whileUsing') return true;
|
||
if (mode === 'once') {
|
||
try {
|
||
return localStorage.getItem(HOME_LOC_ONCE_DATE_KEY) === getTodayStr_home() &&
|
||
sessionStorage.getItem(HOME_LOC_SESSION_GRANTED_KEY) === '1';
|
||
} catch(e) { return false; }
|
||
}
|
||
return false;
|
||
}
|
||
function setHomeLocationMode(mode) {
|
||
try {
|
||
if (mode === 'whileUsing') {
|
||
localStorage.setItem(HOME_LOC_AUTH_MODE_KEY, 'whileUsing');
|
||
localStorage.setItem(HOME_LOC_LEGACY_GRANTED_KEY, '1');
|
||
sessionStorage.setItem(HOME_LOC_SESSION_GRANTED_KEY, '1');
|
||
} else if (mode === 'once') {
|
||
localStorage.setItem(HOME_LOC_AUTH_MODE_KEY, 'once');
|
||
localStorage.setItem(HOME_LOC_ONCE_DATE_KEY, getTodayStr_home());
|
||
localStorage.removeItem(HOME_LOC_LEGACY_GRANTED_KEY);
|
||
sessionStorage.setItem(HOME_LOC_SESSION_GRANTED_KEY, '1');
|
||
} else if (mode === 'denied') {
|
||
localStorage.setItem(HOME_LOC_AUTH_MODE_KEY, 'denied');
|
||
localStorage.removeItem(HOME_LOC_LEGACY_GRANTED_KEY);
|
||
localStorage.removeItem(HOME_LOC_ONCE_DATE_KEY);
|
||
sessionStorage.removeItem(HOME_LOC_SESSION_GRANTED_KEY);
|
||
}
|
||
} catch(e) {}
|
||
}
|
||
function openLocSysPopup() {
|
||
var s = document.getElementById('locSysPopup');
|
||
if (s) s.style.display = 'flex';
|
||
}
|
||
function goAuthLocation() {
|
||
// H2a:接真·系统定位权限窗(永久拒绝由原生跳设置);无桥兜底原型假弹窗。
|
||
if (window.SGBridge && typeof SGBridge.requestLocationPermission === 'function') { SGBridge.requestLocationPermission(); return; }
|
||
openLocSysPopup();
|
||
}
|
||
// 回前台(定位授权窗 / 设置返回)重核授权态并刷新 feed 区(纯 H5,不依赖原生事件)。
|
||
document.addEventListener('visibilitychange', function(){ if (document.visibilityState === 'visible') { try { applyLocationState(); } catch(e){} try { renderLastCompareBanner(); } catch(e){} } });
|
||
// 「上次比价」横幅:进页拉一次 + 回前台(上面 visibilitychange)再拉(4 分钟窗口随时间过期;在外卖 App 比完价回来即出)
|
||
document.addEventListener('DOMContentLoaded', function(){ try { renderLastCompareBanner(); } catch(e){} });
|
||
function isHomeNearbyEmpty(feed) {
|
||
try {
|
||
var params = new URLSearchParams(location.search);
|
||
if (params.get('nearbyEmpty') === '1') return true;
|
||
if (params.get('nearbyEmpty') === '0') return false;
|
||
if (localStorage.getItem(HOME_NEARBY_EMPTY_KEY) === '1') return true;
|
||
} catch(e) {}
|
||
if (!feed) return false;
|
||
if (feed.dataset && feed.dataset.empty === 'true') return true;
|
||
return !feed.querySelector('.feed-card:not([hidden])');
|
||
}
|
||
function syncHomeFeedEmptyHeight(activeEmpty) {
|
||
if (!activeEmpty) return;
|
||
activeEmpty.style.minHeight = '';
|
||
requestAnimationFrame(function() {
|
||
var tab = document.querySelector('#home .tab-bar');
|
||
var need = (tab ? tab.getBoundingClientRect().top : window.innerHeight) - activeEmpty.getBoundingClientRect().top;
|
||
if (need > activeEmpty.offsetHeight) activeEmpty.style.minHeight = need + 'px';
|
||
});
|
||
}
|
||
// feed 区定位空态:未授权显示授权空态;已授权但无附近推荐显示比价空态;有推荐时切回 feed
|
||
// 默认值沿用项目 localStorage 约定:未显式授权即视为未授权 → 首屏即空态(点右下角「重置」清空 localStorage 可回到空态重看)
|
||
let locationGranted = (typeof localStorage !== 'undefined' && localStorage.getItem('proto_locationGranted') === '1');
|
||
function applyLocationState() {
|
||
locationGranted = isHomeLocationGranted();
|
||
var empty = document.getElementById('homeFeedEmpty');
|
||
var noDealEmpty = document.getElementById('homeFeedNoDealEmpty');
|
||
var feed = document.querySelector('#home .home-feed');
|
||
var sort = document.querySelector('#home .feed-sort');
|
||
if (!empty || !feed) return;
|
||
var nearbyEmpty = locationGranted && isHomeNearbyEmpty(feed);
|
||
empty.style.display = locationGranted ? 'none' : 'flex';
|
||
if (noDealEmpty) noDealEmpty.style.display = nearbyEmpty ? 'flex' : 'none';
|
||
feed.style.display = (locationGranted && !nearbyEmpty) ? '' : 'none';
|
||
if (sort) sort.style.display = ''; // 排序三按键(智能推荐/距离最近/销量最高)始终保留,不被空态替换
|
||
// 空态时去掉 feed 卡框(cap 帽檐变体)的金色描边,避免露出横/竖线
|
||
var wrap = document.querySelector('#home .home-feed-wrap');
|
||
if (wrap) wrap.style.borderColor = (locationGranted && !nearbyEmpty) ? '' : 'transparent';
|
||
// 空态时让白色 feed 区撑满到底栏,下方不留灰
|
||
if (!locationGranted) {
|
||
var fl0 = document.getElementById('homeFeedLoading'); if (fl0) fl0.style.display = 'none';
|
||
var fd0 = document.getElementById('homeFeedDegraded'); if (fd0) fd0.style.display = 'none';
|
||
syncHomeFeedEmptyHeight(empty); return;
|
||
}
|
||
empty.style.minHeight = '';
|
||
if (nearbyEmpty && noDealEmpty) syncHomeFeedEmptyHeight(noDealEmpty);
|
||
else if (noDealEmpty) noDealEmpty.style.minHeight = '';
|
||
// H2b: 已授权(未授权上面已 return)→ 首次拉 feed / 坐标变化刷新;loading/empty/degraded 由 HomeFeedStates 接管
|
||
if (window.HomeFeed) {
|
||
if (!HomeFeed.state.loadedOnce && !HomeFeed.state.loading) HomeFeed.loadFirst();
|
||
else HomeFeed.refreshIfCoordsChanged();
|
||
}
|
||
}
|
||
document.addEventListener('DOMContentLoaded', applyLocationState);
|
||
window.addEventListener('load', applyLocationState);
|
||
|
||
// 系统弹窗:仅由手动点击「去授权」呼出;遮罩只关闭;允许期间写入长期授权;允许本次只给当前会话;禁止保持未授权空态。
|
||
function closeLocSysPopup(action) {
|
||
var s = document.getElementById('locSysPopup');
|
||
if (s) s.style.display = 'none';
|
||
if (action === 'whileUsing') {
|
||
setHomeLocationMode('whileUsing');
|
||
applyLocationState();
|
||
} else if (action === 'once') {
|
||
setHomeLocationMode('once');
|
||
applyLocationState();
|
||
} else if (action === 'denied') {
|
||
setHomeLocationMode('denied');
|
||
applyLocationState();
|
||
}
|
||
}
|
||
|
||
function renderTriClaim() {
|
||
const card = document.getElementById('homeStatsCard');
|
||
if (!card) return;
|
||
const cta = card.querySelector('.tc-cta');
|
||
const sub = card.querySelector('.tc-sub');
|
||
if (homeCouponClaimed) {
|
||
card.classList.add('claimed');
|
||
if (cta) cta.textContent = '去查看';
|
||
if (sub) sub.textContent = 'AI 一键自动领';
|
||
} else {
|
||
card.classList.remove('claimed');
|
||
if (cta) cta.textContent = '去领取';
|
||
if (sub) sub.textContent = 'AI 一键自动领';
|
||
}
|
||
// 引导手势在两卡间转移:未领券 → 手在左卡「去领取」;已领券 → 手转到右卡「去点餐」
|
||
const entry = document.getElementById('homeCompareEntry');
|
||
if (entry) entry.classList.toggle('coupon-claimed', homeCouponClaimed);
|
||
}
|
||
|
||
// 「上次比价」数据改由后端 /api/v1/compare/records 实拉(见 renderLastCompareBanner);原写死 mock 已移除。
|
||
const LAST_COMPARE_VARIANTS = ['reference', 'tagright', 'topbar', 'pricebadge', 'mutedright'];
|
||
const LAST_COMPARE_PLATFORM_LOGOS = {
|
||
'淘宝': 'assets/shared/logos/taobao.png',
|
||
'美团': 'assets/shared/logos/meituan.png',
|
||
'京东': 'assets/shared/logos/jd.png',
|
||
'淘宝': 'assets/shared/logos/taobao.png',
|
||
'美团': 'assets/shared/logos/meituan.png',
|
||
'京东': 'assets/shared/logos/jd.png'
|
||
};
|
||
|
||
function getLastCompareVariant() {
|
||
const params = new URLSearchParams(location.search);
|
||
const value = params.get('lastcompare') || (variants['last-compare'] && variants['last-compare'].current) || 'reference';
|
||
return LAST_COMPARE_VARIANTS.includes(value) ? value : 'reference';
|
||
}
|
||
|
||
function renderLastCompareBanner() {
|
||
const banner = document.getElementById('lastCompareBanner');
|
||
if (!banner) return;
|
||
const token = (window.SGBridge && SGBridge.getToken && SGBridge.getToken()) || '';
|
||
if (!token) { banner.style.display = 'none'; return; } // 未登录 → 隐藏
|
||
fetch('/api/v1/compare/records?limit=5', { headers: { 'Authorization': 'Bearer ' + token } })
|
||
.then(function (r) { return r.ok ? r.json() : null; })
|
||
.then(function (d) {
|
||
const rec = pickFreshLastCompare(d && d.items);
|
||
if (!rec) { banner.style.display = 'none'; return; } // 无成功 / 超 4 分钟窗口 / 401 → 隐藏
|
||
banner.style.display = '';
|
||
fillLastCompareBanner(lastCompareToSummary(rec));
|
||
})
|
||
.catch(function () { banner.style.display = 'none'; });
|
||
}
|
||
|
||
// 取最近一条成功比价并卡 4 分钟新鲜窗口(records 按 created_at 倒序,首条成功即最新成功)。
|
||
function pickFreshLastCompare(items) {
|
||
if (!Array.isArray(items)) return null;
|
||
for (let i = 0; i < items.length; i++) {
|
||
const it = items[i];
|
||
if (it && it.status === 'success') {
|
||
const t = Date.parse(it.created_at);
|
||
if (isNaN(t)) return null;
|
||
const age = Date.now() - t; // 容 1 分钟时钟偏差(同原生 toFreshSummary)
|
||
return (age >= -60000 && age <= 4 * 60 * 1000) ? it : null;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
// 后端 ComparisonRecordOut → 横幅摘要(对齐原生 LastCompareSummary)。
|
||
function lastCompareToSummary(rec) {
|
||
return {
|
||
shop: rec.store_name || '',
|
||
items: (rec.items || []).map(function (it) { return it && it.name; }).filter(Boolean),
|
||
bestPlatform: rec.best_platform_name || '',
|
||
bestPrice: rec.best_price_cents != null ? rec.best_price_cents / 100 : 0,
|
||
};
|
||
}
|
||
|
||
function fillLastCompareBanner(record) {
|
||
const banner = document.getElementById('lastCompareBanner');
|
||
if (!banner) return;
|
||
const shopEl = document.getElementById('lastCompareShop');
|
||
const dishEl = document.getElementById('lastCompareDish');
|
||
const ageEl = document.getElementById('lastCompareAge');
|
||
const platformWrap = document.getElementById('lastComparePlatformWrap');
|
||
const platformEl = document.getElementById('lastComparePlatform');
|
||
const platformLogo = document.getElementById('lastComparePlatformLogo');
|
||
const priceEl = document.getElementById('lastComparePrice');
|
||
const noteEl = document.getElementById('lastCompareNote');
|
||
const statusEl = banner.querySelector('.lcb-status');
|
||
|
||
const dishes = Array.isArray(record.items) && record.items.length
|
||
? record.items
|
||
: (record.item ? [record.item] : []);
|
||
const dishText = dishes.slice(0, 2).filter(Boolean).join('、');
|
||
const variant = getLastCompareVariant();
|
||
const platform = record.bestPlatform || record.sourcePlatform || '淘宝';
|
||
const price = Number(record.bestPrice || record.sourcePrice || 0);
|
||
const priceText = price ? price.toFixed(1) : '';
|
||
const priceParts = priceText ? priceText.split('.') : [];
|
||
|
||
if (shopEl) shopEl.textContent = record.shop || '上次比价店铺';
|
||
if (dishEl) dishEl.textContent = dishText || '查看比价结果';
|
||
if (ageEl) ageEl.textContent = '上次比价';
|
||
if (statusEl) statusEl.textContent = '';
|
||
if (platformEl) platformEl.textContent = platform;
|
||
if (platformLogo) platformLogo.src = LAST_COMPARE_PLATFORM_LOGOS[platform] || LAST_COMPARE_PLATFORM_LOGOS['淘宝'];
|
||
if (priceEl) {
|
||
priceEl.innerHTML = price
|
||
? '<span class="lcb-price-currency">¥</span><span class="lcb-price-int">' + priceParts[0] + '</span><span class="lcb-price-dec">.' + (priceParts[1] || '0') + '</span>'
|
||
: '';
|
||
}
|
||
if (platformWrap) platformWrap.style.display = price ? '' : 'none';
|
||
if (noteEl) noteEl.textContent = '去查看';
|
||
|
||
banner.classList.remove('lcb-v-card', 'lcb-v-platform', 'lcb-v-dish', 'lcb-v-strong', 'lcb-v-summary', 'lcb-v-price', 'lcb-v-ticket', 'lcb-v-split', 'lcb-v-leftprice', 'lcb-v-reference', 'lcb-v-tagright', 'lcb-v-topbar', 'lcb-v-pricebadge', 'lcb-v-mutedright');
|
||
banner.classList.add('lcb-v-reference');
|
||
if (variant !== 'reference') banner.classList.add('lcb-v-' + variant);
|
||
banner.classList.add('visible');
|
||
banner.setAttribute('aria-hidden', 'false');
|
||
|
||
// B6: 注入「查看详情」满宽 pill 到 pricebox 底部
|
||
const pricebox = document.getElementById('lastComparePriceBox');
|
||
if (pricebox && !pricebox.querySelector('.lcb-detail-cta')) {
|
||
const cta = document.createElement('button');
|
||
cta.className = 'lcb-detail-cta';
|
||
cta.type = 'button';
|
||
cta.tabIndex = -1;
|
||
cta.setAttribute('aria-hidden', 'true');
|
||
cta.textContent = '查看详情';
|
||
pricebox.appendChild(cta);
|
||
}
|
||
}
|
||
|
||
// ===== 一键领券弹窗 · 多版本(平台选择中部 + 视觉风格切换)=====
|
||
function toggleCouponPlatform(el) {
|
||
if (!el) return;
|
||
el.dataset.checked = el.dataset.checked === 'true' ? 'false' : 'true';
|
||
}
|
||
|
||
const couponPromptVariants = {
|
||
// V2 「快手糖果风」粉橙渐变外卡 + 白色内卡 3 列网格
|
||
v2: '' +
|
||
'<div style="background: linear-gradient(180deg,#FF6B9E 0%,#FF8FAB 55%,#FFAA8C 100%);border-radius: 24px;padding: 16px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,80,120,.45);text-align: center;">' +
|
||
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
|
||
'<div style="font-size: 17px;font-weight: 900;color: #fff;line-height: 1.4;margin-bottom: 12px;text-shadow: 0 1px 2px rgba(0,0,0,.08);">您今日还有大额优惠券可领</div>' +
|
||
'<div style="background: linear-gradient(180deg,#fff 70%,#FFF1F4 100%);border-radius: 18px;padding: 12px 12px;margin-bottom: 16px;">' +
|
||
'<div style="font-size: 11px;color: var(--gray-600);font-weight: 600;margin-bottom: 12px;">已为您发现 <span style="color: #FF4081;font-weight: 800;">3</span> 个平台都有大额优惠</div>' +
|
||
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
|
||
['美团', 'assets/shared/logos/meituan.png', '淘宝', 'assets/shared/logos/taobao.png', '京东', 'assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-pink" style="background: #fff;border: 2px solid #FF6B9E;border-radius: 12px;padding: 8px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 36px;height: 36px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 11px;font-weight: 700;color: var(--gray-900);margin-top: 6px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 4px;right: 4px;width: 16px;height: 16px;border-radius: 50%;background: #FF4081;display: flex;align-items: center;justify-content: center;"><svg width="9" height="9" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
|
||
'</div>' +
|
||
'</div>' +
|
||
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;width: 100%;background: linear-gradient(180deg,#FFE066,#FFD600);color: #1a1a1a;font-weight: 900;box-shadow: 0 6px 16px rgba(255,179,0,.5);" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
|
||
'</div>',
|
||
|
||
// V3 「品牌黄横向选择卡」黄→白渐变外卡 + 3 张并排选择卡(琥珀边框态)+ 黄色品牌按钮(加深收尾保对比)
|
||
v3: '' +
|
||
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
|
||
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
|
||
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 12px;">您今日还有大额优惠券可领</div>' +
|
||
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
|
||
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
|
||
['美团', 'assets/shared/logos/meituan.png', '淘宝', 'assets/shared/logos/taobao.png', '京东', 'assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
|
||
'</div>' +
|
||
'</div>' +
|
||
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
|
||
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
|
||
'</div>',
|
||
|
||
// V4 「黄色品牌风」白底外卡 + 纵向 3 行平台列表 + 黄色 toggle 开关
|
||
v4: '' +
|
||
'<div style="background: #fff;border-radius: 24px;padding: 24px 16px 16px;width: 100%;text-align: center;box-shadow: 0 16px 48px rgba(0,0,0,.3);border-top: 6px solid #FFD600;">' +
|
||
'<div style="width: 56px;height: 56px;border-radius: 14px;margin: 0 auto 12px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 18px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
|
||
'<div style="font-size: 18px;font-weight: 800;color: var(--gray-900);line-height: 1.4;margin-bottom: 12px;">您今日还有大额优惠券可领</div>' +
|
||
'<div style="background: var(--gray-100);border-radius: 14px;padding: 8px;margin-bottom: 16px;display: flex;flex-direction: column;gap: 6px;">' +
|
||
['美团', 'assets/shared/logos/meituan.png', '淘宝', 'assets/shared/logos/taobao.png', '京东', 'assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 1.5px solid #FFD600;border-radius: 12px;padding: 8px 12px;display: flex;align-items: center;gap: 8px;text-align: left;"><img src="' + arr[i+1] + '" style="width: 36px;height: 36px;border-radius: 8px;flex-shrink: 0;"/><div style="flex: 1;font-size: 14px;font-weight: 700;color: var(--gray-900);">' + arr[i] + '</div><span class="cp-toggle" style="position: relative;width: 36px;height: 20px;border-radius: 8px;background: #FFD600;flex-shrink: 0;transition: background .2s;"><span style="position: absolute;top: 2px;left: 2px;width: 16px;height: 16px;border-radius: 50%;background: #fff;box-shadow: 0 1px 3px rgba(0,0,0,.2);transform: translateX(16px);transition: transform .2s;"></span></span></div>'; }, '') +
|
||
'</div>' +
|
||
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;width: 100%;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
|
||
'</div>',
|
||
|
||
// ===== V3 副标题处理方案 a~e(仅副标题区域不同,其他与 V3 一致)=====
|
||
// V3a 「机制副标题」副标题改讲"AI 自动 · 跨平台"机制,13px / 600 / 暗金
|
||
v3a: '' +
|
||
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
|
||
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
|
||
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 6px;">您今日还有大额优惠券可领</div>' +
|
||
'<div style="font-size: 13px;font-weight: 600;color: #8B6914;line-height: 1.5;margin-bottom: 12px;">AI 跨平台一键领取,无需手动切换 APP</div>' +
|
||
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
|
||
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
|
||
['美团', 'assets/shared/logos/meituan.png', '淘宝', 'assets/shared/logos/taobao.png', '京东', 'assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
|
||
'</div>' +
|
||
'</div>' +
|
||
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
|
||
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
|
||
'</div>',
|
||
|
||
// V3b 「黄色胶囊标签」副标题文案不变,但用黄色 pill 包裹 + 🎁 emoji
|
||
v3b: '' +
|
||
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
|
||
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
|
||
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 8px;">您今日还有大额优惠券可领</div>' +
|
||
'<div style="display: inline-block;background: rgba(255,179,0,.18);color: #8B6914;font-size: 12px;font-weight: 700;padding: 4px 12px;border-radius: 32px;margin-bottom: 12px;">🎁 领取后立享更低好价</div>' +
|
||
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
|
||
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
|
||
['美团', 'assets/shared/logos/meituan.png', '淘宝', 'assets/shared/logos/taobao.png', '京东', 'assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
|
||
'</div>' +
|
||
'</div>' +
|
||
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
|
||
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
|
||
'</div>',
|
||
|
||
// V3c 「特性 chip 行」三枚迷你 pill:AI 自动 · 30 秒 · 安全
|
||
v3c: '' +
|
||
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
|
||
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
|
||
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 8px;">您今日还有大额优惠券可领</div>' +
|
||
'<div style="display: flex;justify-content: center;gap: 6px;flex-wrap: wrap;margin-bottom: 12px;">' +
|
||
'<span style="background: rgba(255,179,0,.18);color: #8B6914;font-size: 11px;font-weight: 700;padding: 4px 8px;border-radius: 32px;">🤖 AI 自动</span>' +
|
||
'<span style="background: rgba(255,179,0,.18);color: #8B6914;font-size: 11px;font-weight: 700;padding: 4px 8px;border-radius: 32px;">⚡ 30 秒完成</span>' +
|
||
'<span style="background: rgba(255,179,0,.18);color: #8B6914;font-size: 11px;font-weight: 700;padding: 4px 8px;border-radius: 32px;">🛡️ 安全无感</span>' +
|
||
'</div>' +
|
||
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
|
||
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
|
||
['美团', 'assets/shared/logos/meituan.png', '淘宝', 'assets/shared/logos/taobao.png', '京东', 'assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
|
||
'</div>' +
|
||
'</div>' +
|
||
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
|
||
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
|
||
'</div>',
|
||
|
||
// V3d 「顶部小标签 + 单标题」副标题取消,logo 下方加「今日福利」黄色小 pill
|
||
v3d: '' +
|
||
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
|
||
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
|
||
'<div style="display: inline-block;background: #FFD600;color: #1a1a1a;font-size: 11px;font-weight: 800;letter-spacing: .5px;padding: 2px 8px;border-radius: 32px;margin-bottom: 8px;">今日福利</div>' +
|
||
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 12px;">发现您有未领取的大额优惠券</div>' +
|
||
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
|
||
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
|
||
['美团', 'assets/shared/logos/meituan.png', '淘宝', 'assets/shared/logos/taobao.png', '京东', 'assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
|
||
'</div>' +
|
||
'</div>' +
|
||
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
|
||
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
|
||
'</div>',
|
||
|
||
// V3e 「紧迫感副标题」副标题强调时效,⏰ + 暖红色,13px / 700
|
||
v3e: '' +
|
||
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
|
||
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
|
||
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 6px;">您今日还有大额优惠券可领</div>' +
|
||
'<div style="font-size: 13px;font-weight: 700;color: #D9534F;line-height: 1.5;margin-bottom: 12px;">⏰ 仅今日有效,错过自动失效</div>' +
|
||
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
|
||
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
|
||
['美团', 'assets/shared/logos/meituan.png', '淘宝', 'assets/shared/logos/taobao.png', '京东', 'assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
|
||
'</div>' +
|
||
'</div>' +
|
||
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
|
||
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
|
||
'</div>',
|
||
|
||
// V3f 「流程植入副标题」副标题植入产品流程:先领券 → AI 比价 → 找底价
|
||
v3f: '' +
|
||
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
|
||
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
|
||
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 8px;">您今日还有大额优惠券可领</div>' +
|
||
'<div style="display: inline-flex;align-items: center;gap: 6px;background: rgba(255,179,0,.18);color: #8B6914;font-size: 12px;font-weight: 700;padding: 4px 12px;border-radius: 32px;margin-bottom: 12px;"><svg width="14" height="12" viewBox="0 0 22 18" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M2 7.2 V10.8 A1.4 1.4 0 0 0 3.4 12.2 H5.4 L11.2 16.4 A0.8 0.8 0 0 0 12.5 15.7 V2.3 A0.8 0.8 0 0 0 11.2 1.6 L5.4 5.8 H3.4 A1.4 1.4 0 0 0 2 7.2 Z" fill="#8B6914"/><path d="M14.6 4.4 C16 6 16 12 14.6 13.6" stroke="#8B6914" stroke-width="1.4" stroke-linecap="round" fill="none"/><path d="M16.8 2.6 C19.2 5.2 19.2 12.8 16.8 15.4" stroke="#8B6914" stroke-width="1.4" stroke-linecap="round" fill="none"/><circle cx="6.2" cy="14.4" r="1.5" fill="#8B6914"/></svg>先领券再比价</div>' +
|
||
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
|
||
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
|
||
['美团', 'assets/shared/logos/meituan.png', '淘宝', 'assets/shared/logos/taobao.png', '京东', 'assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width=\"10\" height=\"10\" viewBox=\"0 0 9 9\"><path d=\"M2 4.5l1.5 1.5 3-4\" stroke=\"#fff\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\"/></svg></span></div>'; }, '') +
|
||
'</div>' +
|
||
'</div>' +
|
||
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
|
||
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
|
||
'</div>'
|
||
};
|
||
|
||
function applyCouponPromptVariant(v) {
|
||
const card = document.getElementById('demoCouponPromptCard');
|
||
if (!card || !couponPromptVariants[v]) return;
|
||
card.style.cssText = 'width:100%;max-width:330px;animation:fadeInUp .45s cubic-bezier(.34,1.56,.64,1);';
|
||
card.innerHTML = couponPromptVariants[v];
|
||
}
|
||
|
||
function showCouponPromptForPreview() {
|
||
// 预览模式:直接强制显示弹窗,不走 demo flow
|
||
document.querySelectorAll('.screen').forEach(function(s){ s.classList.remove('active'); s.style.display = ''; });
|
||
const cmp = document.getElementById('comparing');
|
||
if (cmp) { cmp.classList.add('active'); cmp.style.display = 'flex'; }
|
||
const prompt = document.getElementById('demoCouponPrompt');
|
||
if (prompt) prompt.style.display = 'flex';
|
||
}
|
||
|
||
function onClaimCouponDecline() {
|
||
// 残忍放弃:跳过领券,直接进入比价引导第一步
|
||
document.getElementById('demoCouponPrompt').style.display = 'none';
|
||
const firstSpotlightIdx = demoSteps.findIndex(d => d.spotlight || d.mode === 'swipe' || d.mode === 'startCompare');
|
||
if (firstSpotlightIdx > 0) {
|
||
demoStep = firstSpotlightIdx;
|
||
renderDemoStep();
|
||
} else {
|
||
demoNext();
|
||
}
|
||
}
|
||
|
||
// 跳过新人体验流程 → 召回弹窗(居中卡片式)
|
||
function onSkipExperienceRequest() {
|
||
const modal = document.getElementById('skipConfirmModal');
|
||
if (modal) modal.style.display = 'flex';
|
||
}
|
||
function closeSkipConfirmModal() {
|
||
const modal = document.getElementById('skipConfirmModal');
|
||
if (modal) modal.style.display = 'none';
|
||
}
|
||
function confirmSkipExperience() {
|
||
closeSkipConfirmModal();
|
||
// 真的跳过 → 直接进入 login(不走 demo 比价 + celebration)
|
||
go('login');
|
||
}
|
||
|
||
// [ECOM-ONLY] 盲盒解锁 + 滑动引擎 removed for waimai V1
|
||
|
||
// ===== 礼花爆炸特效 =====
|
||
function startConfetti() {
|
||
const canvas = document.getElementById('confettiCanvas');
|
||
if (!canvas) return;
|
||
const ctx = canvas.getContext('2d');
|
||
canvas.width = 375;
|
||
canvas.height = 812;
|
||
const colors = ['#FF5722','#FFD600','#4CAF50','#2196F3','#E91E63','#FF9800','#9C27B0','#00BCD4','#FF4081'];
|
||
const pieces = [];
|
||
const shapes = ['rect','circle','strip'];
|
||
|
||
// 从两侧底部发射两簇礼花
|
||
function burst(originX, originY, count) {
|
||
for (let i = 0; i < count; i++) {
|
||
const angle = -Math.PI/2 + (Math.random() - 0.5) * 1.2; // 向上扇形
|
||
const speed = Math.random() * 8 + 5;
|
||
pieces.push({
|
||
x: originX,
|
||
y: originY,
|
||
vx: Math.cos(angle) * speed * (originX < 187 ? 1 : -1) * (0.3 + Math.random() * 0.7),
|
||
vy: Math.sin(angle) * speed - Math.random() * 3,
|
||
w: Math.random() * 10 + 4,
|
||
h: Math.random() * 6 + 2,
|
||
color: colors[Math.floor(Math.random() * colors.length)],
|
||
rot: Math.random() * 360,
|
||
vr: (Math.random() - 0.5) * 12,
|
||
gravity: 0.12 + Math.random() * 0.06,
|
||
friction: 0.98,
|
||
opacity: 1,
|
||
shape: shapes[Math.floor(Math.random() * shapes.length)],
|
||
wobble: Math.random() * 10,
|
||
wobbleSpeed: 0.05 + Math.random() * 0.1,
|
||
});
|
||
}
|
||
}
|
||
|
||
// 左右两侧各爆一簇
|
||
burst(60, 350, 50);
|
||
burst(315, 350, 50);
|
||
// 稍后中间再爆一簇
|
||
setTimeout(() => burst(187, 300, 40), 300);
|
||
|
||
let frame = 0;
|
||
function draw() {
|
||
ctx.clearRect(0, 0, 375, 812);
|
||
let alive = 0;
|
||
pieces.forEach(p => {
|
||
if (p.opacity <= 0) return;
|
||
alive++;
|
||
p.vx *= p.friction;
|
||
p.vy *= p.friction;
|
||
p.vy += p.gravity;
|
||
p.vx += Math.sin(p.wobble) * 0.3;
|
||
p.wobble += p.wobbleSpeed;
|
||
p.x += p.vx;
|
||
p.y += p.vy;
|
||
p.rot += p.vr;
|
||
p.vr *= 0.99;
|
||
// 慢慢淡出
|
||
if (frame > 80) p.opacity = Math.max(0, p.opacity - 0.006);
|
||
|
||
ctx.save();
|
||
ctx.translate(p.x, p.y);
|
||
ctx.rotate(p.rot * Math.PI / 180);
|
||
ctx.globalAlpha = p.opacity;
|
||
ctx.fillStyle = p.color;
|
||
if (p.shape === 'circle') {
|
||
ctx.beginPath();
|
||
ctx.arc(0, 0, p.w/2, 0, Math.PI*2);
|
||
ctx.fill();
|
||
} else if (p.shape === 'strip') {
|
||
ctx.fillRect(-p.w/2, -1, p.w, 2.5);
|
||
} else {
|
||
ctx.fillRect(-p.w/2, -p.h/2, p.w, p.h);
|
||
}
|
||
ctx.restore();
|
||
});
|
||
frame++;
|
||
if (alive > 0 && frame < 400) requestAnimationFrame(draw);
|
||
else ctx.clearRect(0, 0, 375, 812);
|
||
}
|
||
draw();
|
||
}
|
||
|
||
// ===== 新人礼包方案切换(URL 参数驱动,用于 gift-variants 对比页) =====
|
||
const giftVariantTemplates = {
|
||
A: '<div class="gv-base gv-a"><div class="gv-icon">🎁</div><div><div class="gv-title">新人专享礼包</div><div class="gv-sub">完成体验立即到账</div></div></div>',
|
||
B: '<div class="gv-base gv-b"><div class="gv-stamp">价值 ¥88</div><div class="gv-icon">🎁</div><div><div class="gv-title">新人专享礼包</div><div class="gv-sub">完成体验立即到账</div></div></div>',
|
||
C: '<div class="gv-base gv-c"><div class="gv-icon">🎁</div><div><div class="gv-title">新人专享礼包</div><div class="gv-cd"><span>⏱</span><span id="gvCd">23:45<span class="gv-blink">:</span>12</span><span>后失效</span></div></div></div>',
|
||
D: '<div class="gv-base gv-d"><div class="gv-iconwrap"><div class="gv-icon">🎁</div></div><div class="gv-text"><div class="gv-title">新人专享礼包</div><div class="gv-sub">完成体验立即到账</div></div></div>',
|
||
E: '<div class="gift-coupon"><div class="gc-icon">🎁</div><div style="flex: 1;min-width: 0;"><div class="gc-title">新人专享礼包</div><div class="gc-sub">完成体验立即到账</div></div></div>',
|
||
F: '<div class="gv-base gv-f"><div class="gv-rays"></div><div class="gv-iconwrap"><div class="gv-icon">🎁</div></div><div class="gv-title">新人专享礼包</div><div class="gv-sub">完成体验立即到账</div></div>',
|
||
G: '<div class="gv-base gv-g"><div class="gv-iconwrap"><span class="gv-spark gv-s1"></span><span class="gv-spark gv-s2"></span><span class="gv-spark gv-s3"></span><div class="gv-icon">🎁</div></div><div><div class="gv-title">新人专享<em>大礼包</em></div><div class="gv-sub">完成体验立即到账</div></div></div>'
|
||
};
|
||
let __gvCdTimer = null;
|
||
function __gvStartCountdown() {
|
||
let total = 23 * 3600 + 45 * 60 + 12;
|
||
if (__gvCdTimer) clearInterval(__gvCdTimer);
|
||
const tick = () => {
|
||
total = Math.max(0, total - 1);
|
||
const h = String(Math.floor(total / 3600)).padStart(2, '0');
|
||
const m = String(Math.floor((total % 3600) / 60)).padStart(2, '0');
|
||
const s = String(total % 60).padStart(2, '0');
|
||
const el = document.getElementById('gvCd');
|
||
if (el) el.innerHTML = h + ':' + m + '<span class="gv-blink">:</span>' + s;
|
||
};
|
||
tick();
|
||
__gvCdTimer = setInterval(tick, 1000);
|
||
}
|
||
function applyGiftVariant(letter) {
|
||
const container = document.getElementById('giftCardContainer');
|
||
if (!container) return;
|
||
const key = (letter || 'E').toUpperCase();
|
||
const tpl = giftVariantTemplates[key] || giftVariantTemplates.E;
|
||
container.innerHTML = tpl;
|
||
if (key === 'C') __gvStartCountdown();
|
||
}
|
||
(function applyGiftVariantURLParams() {
|
||
try {
|
||
const params = new URLSearchParams(location.search);
|
||
const variant = params.get('giftvariant');
|
||
const celebVariant = params.get('celebrationvariant');
|
||
const celebrate = params.get('celebrate') === '1';
|
||
const couponVariant = params.get('couponvariant');
|
||
const showCoupon = params.get('showcoupon') === '1';
|
||
const ctaVariantParam = params.get('ctavariant');
|
||
const screen = params.get('screen');
|
||
const embed = params.get('embed') === '1';
|
||
const run = function() {
|
||
if (embed) document.body.classList.add('gv-embed');
|
||
if (variant) applyGiftVariant(variant);
|
||
if (celebVariant && celebrationVariants[celebVariant]) {
|
||
currentCelebrationVariant = celebVariant;
|
||
}
|
||
if (screen) { try { go(screen); } catch (e) {} }
|
||
if (celebrate) {
|
||
try { openCelebrationModal(); } catch (e) {}
|
||
}
|
||
if (couponVariant && typeof applyCouponPromptVariant === 'function') {
|
||
try { applyCouponPromptVariant(couponVariant); } catch (e) {}
|
||
}
|
||
if (showCoupon && typeof showCouponPromptForPreview === 'function') {
|
||
try { showCouponPromptForPreview(); } catch (e) {}
|
||
}
|
||
if (ctaVariantParam && typeof applyCtaVariant === 'function') {
|
||
try { applyCtaVariant(parseInt(ctaVariantParam, 10)); } catch (e) {}
|
||
}
|
||
};
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', run);
|
||
} else {
|
||
run();
|
||
}
|
||
} catch (e) {}
|
||
})();
|
||
</script>
|
||
|
||
|
||
<!-- ===== Tweaks Panel ===== -->
|
||
<div id="tweaksPanel" class="tweaks-panel">
|
||
<button class="tweaks-close" onclick="closeTweaks()">×</button>
|
||
<h3>「开启省钱之旅」按钮样式</h3>
|
||
<div class="tweaks-sub">点击切换,预览不同方案</div>
|
||
<div class="tweaks-grid">
|
||
<div class="tweaks-opt" data-v="1">红橙渐变<small>当前</small></div>
|
||
<div class="tweaks-opt" data-v="2">黄底黑字<small>品牌主色</small></div>
|
||
<div class="tweaks-opt" data-v="3">黑底黄字<small>高对比</small></div>
|
||
<div class="tweaks-opt" data-v="4">金色光泽<small>动态扫光</small></div>
|
||
<div class="tweaks-opt" data-v="5">玻璃质感<small>立体黄</small></div>
|
||
<div class="tweaks-opt" data-v="6">描边偏移<small>克制款</small></div>
|
||
<div class="tweaks-opt" data-v="7">红包喜庆<small>红+金</small></div>
|
||
<div class="tweaks-opt" data-v="8">呼吸跳动<small>动效款</small></div>
|
||
<div class="tweaks-opt" data-v="9">蜜糖渐变<small>黄→琥珀</small></div>
|
||
<div class="tweaks-opt" data-v="10">金币描边<small>深金细边</small></div>
|
||
</div>
|
||
|
||
<div style="height: 1px;background: #E5E5E5;margin: 16px 0 12px;"></div>
|
||
<h3>领券弹窗副标题样式</h3>
|
||
<div class="tweaks-sub">主标题下那行小字,强化"收益"信号</div>
|
||
<div class="tweaks-grid">
|
||
<div class="tweaks-opt sub-opt" data-sv="1">基线灰<small>当前最弱</small></div>
|
||
<div class="tweaks-opt sub-opt" data-sv="2">金币胶囊<small>品牌黄徽章</small></div>
|
||
<div class="tweaks-opt sub-opt" data-sv="3">关键词高亮<small>黄色荧光笔</small></div>
|
||
<div class="tweaks-opt sub-opt" data-sv="4">优惠券小票<small>齿边+朱红</small></div>
|
||
<div class="tweaks-opt sub-opt" data-sv="5">数字徽章<small>预计立省¥</small></div>
|
||
<div class="tweaks-opt sub-opt" data-sv="6">双行节奏<small>预告+承诺</small></div>
|
||
<div class="tweaks-opt sub-opt" data-sv="7">V2b 金币翻转<small>动效活力</small></div>
|
||
<div class="tweaks-opt sub-opt" data-sv="8">V2c 双色分段<small>黑黄拼接</small></div>
|
||
<div class="tweaks-opt sub-opt" data-sv="9">V2d 闪光描边<small>轻盈款</small></div>
|
||
<div class="tweaks-opt sub-opt" data-sv="10">V2e 数字嵌入<small>¥18+ 内嵌</small></div>
|
||
<div class="tweaks-opt sub-opt" data-sv="11">V2f 双图标<small>金币+闪电</small></div>
|
||
<div class="tweaks-opt sub-opt" data-sv="12">V2g 立体浮起<small>金属高光</small></div>
|
||
<div class="tweaks-opt sub-opt" data-sv="13">流程植入<small>领券→比价→底价</small></div>
|
||
</div>
|
||
|
||
<div style="height: 1px;background: #E5E5E5;margin: 16px 0 12px;"></div>
|
||
<h3>「完成设置」弹窗版式</h3>
|
||
<div class="tweaks-sub">点击切换,下次进入弹窗即生效</div>
|
||
<div class="tweaks-grid">
|
||
<div class="tweaks-opt celeb-opt" data-cv="v1">轻收尾·重期待<small>承上小,起下大</small></div>
|
||
<div class="tweaks-opt celeb-opt" data-cv="v2">分割式<small>三段节奏</small></div>
|
||
<div class="tweaks-opt celeb-opt" data-cv="v3">叙事流<small>递进式</small></div>
|
||
<div class="tweaks-opt celeb-opt" data-cv="v4">行为优先<small>主舞台让给行为</small></div>
|
||
<div class="tweaks-opt celeb-opt" data-cv="v5">徽章+行动卡<small>chip 强调最后一步</small></div>
|
||
<div class="tweaks-opt celeb-opt" data-cv="v6">进度条推进<small>脉动黄推进感</small></div>
|
||
<div class="tweaks-opt celeb-opt" data-cv="v7">数字步骤<small>① ✓ → ② 当前</small></div>
|
||
<div class="tweaks-opt celeb-opt" data-cv="v8">极简专注<small>大字承担引导</small></div>
|
||
</div>
|
||
<button onclick="previewCelebration()" style="margin-top: 12px;width: 100%;padding: 8px;border-radius: 8px;border: 1px solid #ddd;background: #fff;font-size: 13px;font-weight: 600;cursor: pointer;">▶ 预览当前版式</button>
|
||
</div>
|
||
<script>
|
||
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
|
||
"ctaVariant": 5,
|
||
"celebVariant": "v3",
|
||
"couponSubVariant": 13
|
||
}/*EDITMODE-END*/;
|
||
let currentCtaVariant = TWEAK_DEFAULTS.ctaVariant || 1;
|
||
let currentCouponSubVariant = TWEAK_DEFAULTS.couponSubVariant || 1;
|
||
currentCelebrationVariant = TWEAK_DEFAULTS.celebVariant || 'v1';
|
||
const couponSubMarkup = {
|
||
1: '<div class="cps cps-v1">领取后将为您解锁更低好价</div>',
|
||
2: '<div class="cps cps-v2"><span class="cps-coin">¥</span>领取后解锁今日最低价</div>',
|
||
3: '<div class="cps cps-v3">领取后将为您解锁<em>全网最低价</em></div>',
|
||
4: '<div class="cps cps-v4">已为您锁定 <span class="cps-amt">¥18+</span> 神券</div>',
|
||
5: '<div class="cps cps-v5">领取后预计立省<span class="cps-pill">¥8<small>~</small>25</span></div>',
|
||
6: '<div class="cps cps-v6"><span class="cps-top">· 预计 3 秒完成 ·</span><span class="cps-bot">领券解锁<em>今日最低价</em></span></div>',
|
||
7: '<div class="cps cps-v2b"><span class="cps-coin">¥</span>领取后解锁今日最低价</div>',
|
||
8: '<div class="cps cps-v2c"><span class="cps-tag">立省</span><span class="cps-text">解锁今日最低价</span></div>',
|
||
9: '<div class="cps cps-v2d"><span class="cps-coin">¥</span>领取后解锁今日最低价</div>',
|
||
10: '<div class="cps cps-v2e"><span class="cps-amount">¥18<small>+</small></span>解锁今日最低价</div>',
|
||
11: '<div class="cps cps-v2f"><span class="cps-coin">¥</span>领取后解锁<span class="cps-bolt"><svg width="10" height="11" viewBox="0 0 10 11"><path d="M6 0L0 6h3l-1 5 6-6H5z" fill="#1a1a1a"/></svg></span>今日最低价</div>',
|
||
12: '<div class="cps cps-v2g"><span class="cps-coin">¥</span>领取后解锁今日最低价</div>',
|
||
13: '<div class="cps cps-v3f"><span class="cps-coin"><svg width="15" height="13" viewBox="0 0 22 18" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M2 7.2 V10.8 A1.4 1.4 0 0 0 3.4 12.2 H5.4 L11.2 16.4 A0.8 0.8 0 0 0 12.5 15.7 V2.3 A0.8 0.8 0 0 0 11.2 1.6 L5.4 5.8 H3.4 A1.4 1.4 0 0 0 2 7.2 Z" fill="#8B6914"/><path d="M14.6 4.4 C16 6 16 12 14.6 13.6" stroke="#8B6914" stroke-width="1.4" stroke-linecap="round" fill="none"/><path d="M16.8 2.6 C19.2 5.2 19.2 12.8 16.8 15.4" stroke="#8B6914" stroke-width="1.4" stroke-linecap="round" fill="none"/><circle cx="6.2" cy="14.4" r="1.5" fill="#8B6914"/></svg></span>先领券,再比价</div>'
|
||
};
|
||
function applyCouponSubVariant(v) {
|
||
currentCouponSubVariant = v;
|
||
const slot = document.getElementById('demoCouponSubtitleSlot');
|
||
if (slot) slot.innerHTML = couponSubMarkup[v] || couponSubMarkup[1];
|
||
document.querySelectorAll('#tweaksPanel .sub-opt').forEach(el => {
|
||
el.classList.toggle('active', String(el.dataset.sv) === String(v));
|
||
});
|
||
}
|
||
function applyCelebVariant(cv) {
|
||
currentCelebrationVariant = cv;
|
||
document.querySelectorAll('#tweaksPanel .celeb-opt').forEach(el => {
|
||
el.classList.toggle('active', el.dataset.cv === cv);
|
||
});
|
||
}
|
||
function previewCelebration() {
|
||
if (typeof openCelebrationModal === 'function') openCelebrationModal();
|
||
}
|
||
function applyCtaVariant(v) {
|
||
currentCtaVariant = v;
|
||
const btn = document.getElementById('splashCTA');
|
||
if (!btn) return;
|
||
btn.className = 'splash-cta splash-cta-v' + v;
|
||
document.querySelectorAll('#tweaksPanel .tweaks-opt').forEach(el => {
|
||
el.classList.toggle('active', String(el.dataset.v) === String(v));
|
||
});
|
||
}
|
||
function closeTweaks() {
|
||
document.getElementById('tweaksPanel').classList.remove('open');
|
||
try { window.parent.postMessage({type:'__edit_mode_dismissed'},'*'); } catch(e){}
|
||
}
|
||
window.addEventListener('message', (e) => {
|
||
const d = e.data || {};
|
||
if (d.type === '__activate_edit_mode') document.getElementById('tweaksPanel').classList.add('open');
|
||
if (d.type === '__deactivate_edit_mode') document.getElementById('tweaksPanel').classList.remove('open');
|
||
});
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
document.querySelectorAll('#tweaksPanel .tweaks-opt:not(.celeb-opt):not(.sub-opt)').forEach(el => {
|
||
el.addEventListener('click', () => {
|
||
const v = parseInt(el.dataset.v, 10);
|
||
applyCtaVariant(v);
|
||
try { window.parent.postMessage({type:'__edit_mode_set_keys', edits:{ctaVariant: v}}, '*'); } catch(e){}
|
||
});
|
||
});
|
||
document.querySelectorAll('#tweaksPanel .sub-opt').forEach(el => {
|
||
el.addEventListener('click', () => {
|
||
const v = parseInt(el.dataset.sv, 10);
|
||
applyCouponSubVariant(v);
|
||
try { window.parent.postMessage({type:'__edit_mode_set_keys', edits:{couponSubVariant: v}}, '*'); } catch(e){}
|
||
});
|
||
});
|
||
document.querySelectorAll('#tweaksPanel .celeb-opt').forEach(el => {
|
||
el.addEventListener('click', () => {
|
||
const cv = el.dataset.cv;
|
||
applyCelebVariant(cv);
|
||
try { window.parent.postMessage({type:'__edit_mode_set_keys', edits:{celebVariant: cv}}, '*'); } catch(e){}
|
||
});
|
||
});
|
||
applyCtaVariant(currentCtaVariant);
|
||
applyCouponSubVariant(currentCouponSubVariant);
|
||
applyCelebVariant(currentCelebrationVariant);
|
||
try { window.parent.postMessage({type:'__edit_mode_available'},'*'); } catch(e){}
|
||
});
|
||
</script>
|
||
|
||
|
||
<script>
|
||
(function() {
|
||
var ID_TO_PATH = {
|
||
"login": "app/login/inapp.html",
|
||
"loginPhone": "app/login/phone.html",
|
||
"home": "app/home",
|
||
"guideVideo": "app/home/guide-video.html",
|
||
"welfare": "app/welfare",
|
||
"welfareRules": "app/welfare/rules.html",
|
||
"profile": "app/profile",
|
||
"invite": "app/welfare/invite.html",
|
||
"compresult": "app/compare/index.html?screen=result",
|
||
"withdrawal": "app/welfare/withdrawal.html",
|
||
"coinhistory": "app/welfare/coinhistory.html",
|
||
"records": "app/profile/records.html",
|
||
"settings": "app/profile/settings.html",
|
||
"feedback": "app/profile/feedback.html",
|
||
"comparing": "app/compare",
|
||
"history": "app/history"
|
||
};
|
||
var PREFIX = '../../';
|
||
function navigate(id) {
|
||
// 抢救 inline onclick 设置的 window.loginFrom(隐式 global,不会进 let 绑定)
|
||
if (window.loginFrom && typeof window.loginFrom === 'string') {
|
||
try { localStorage.setItem('proto_loginFrom', window.loginFrom); } catch(e) {}
|
||
}
|
||
var p = ID_TO_PATH[id];
|
||
if (!p) { console.warn('[nav] unknown id:', id); return; }
|
||
location.href = PREFIX + p + (p.indexOf('.html') !== -1 ? '' : '/index.html');
|
||
}
|
||
window.go = navigate;
|
||
window._activateScreen = function(id) { navigate(id); };
|
||
window.goBack = function() { if (history.length > 1) history.back(); else navigate('home'); };
|
||
window.debugGoBack = window.goBack;
|
||
})();
|
||
</script>
|
||
|
||
<script>
|
||
// ============================================
|
||
// V3: 页面级初始化
|
||
// 替代原 go(id) 切到本屏时跑的逻辑
|
||
// ============================================
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
var isLogged = false;
|
||
try { isLogged = localStorage.getItem('proto_isLoggedIn') !== 'false'; } catch(e) {}
|
||
|
||
var activeScreen = document.querySelector('.screen.active');
|
||
if (!activeScreen) return;
|
||
var id = activeScreen.id;
|
||
|
||
// welfare 登录态切换
|
||
if (id === 'welfare') {
|
||
var wu = document.getElementById('welfareUnlogged');
|
||
var wl = document.getElementById('welfareLogged');
|
||
if (wu) wu.style.display = isLogged ? 'none' : 'block';
|
||
if (wl) wl.style.display = isLogged ? 'block' : 'none';
|
||
// 已登录 + 没显示过签到弹窗 → 弹一次
|
||
if (isLogged && typeof showCheckinPopup === 'function') {
|
||
var checkinShown = false;
|
||
try { checkinShown = localStorage.getItem('proto_checkinShown') === 'true'; } catch(e) {}
|
||
if (!checkinShown) setTimeout(showCheckinPopup, 500);
|
||
}
|
||
}
|
||
|
||
// profile 登录态切换
|
||
if (id === 'profile') {
|
||
var pu = document.getElementById('profileUnlogged');
|
||
var pl = document.getElementById('profileLogged');
|
||
if (pu) pu.style.display = isLogged ? 'none' : 'block';
|
||
if (pl) pl.style.display = isLogged ? 'block' : 'none';
|
||
}
|
||
|
||
// productselect 自动开始平台扫描
|
||
if (id === 'productselect') {
|
||
if (typeof startPlatformScan === 'function') {
|
||
try { startPlatformScan(); } catch(e) { console.warn(e); }
|
||
}
|
||
}
|
||
|
||
// celebration 动画 + 数据
|
||
if (id === 'celebration') {
|
||
if (typeof renderCelebrationSavings === 'function') try { renderCelebrationSavings(); } catch(e){}
|
||
if (typeof renderResults === 'function') try { renderResults('celebResults'); } catch(e){}
|
||
if (typeof startConfetti === 'function') try { startConfetti(); } catch(e){}
|
||
}
|
||
|
||
// comparing 自动开始比价动画
|
||
if (id === 'comparing') {
|
||
if (typeof startCompareAnimation === 'function') try { startCompareAnimation(); } catch(e){}
|
||
if (typeof startComparing === 'function') try { startComparing(); } catch(e){}
|
||
}
|
||
|
||
// 首页:从 compare 跑完领券流程跳回来时,还原"已领"态 + 弹结果 toast
|
||
if (id === 'home') {
|
||
try {
|
||
if (typeof renderLastCompareBanner === 'function') renderLastCompareBanner();
|
||
var summaryStr = localStorage.getItem('proto_homeCouponClaimSummary');
|
||
var claimedFlag = localStorage.getItem('proto_homeCouponClaimed');
|
||
var claimDate = localStorage.getItem('proto_home_coupon_claim_date');
|
||
var today_home = (typeof getTodayStr_home === 'function') ? getTodayStr_home() : '';
|
||
// 跨日重置:上次领的不是今天 → 已领态作废,让今天重新走一遍领券流程
|
||
if (claimedFlag === 'true' && claimDate && claimDate !== today_home) {
|
||
localStorage.removeItem('proto_homeCouponClaimed');
|
||
localStorage.removeItem('proto_homeCouponClaimSummary');
|
||
claimedFlag = null;
|
||
summaryStr = null;
|
||
}
|
||
if (claimedFlag === 'true' && summaryStr) {
|
||
homeCouponClaimed = true;
|
||
homeCouponClaimSummary = JSON.parse(summaryStr);
|
||
if (typeof renderTriClaim === 'function') renderTriClaim();
|
||
}
|
||
var showToast = localStorage.getItem('proto_showCouponDoneToast');
|
||
if (showToast === 'true' && summaryStr) {
|
||
localStorage.removeItem('proto_showCouponDoneToast');
|
||
var summary = JSON.parse(summaryStr);
|
||
couponTotal = summary.total || 0;
|
||
homeCouponClaimSummary = summary;
|
||
var toast = document.getElementById('demoCouponDoneToast');
|
||
if (toast) {
|
||
toast.style.display = 'block';
|
||
renderCouponDoneFromLogos();
|
||
if (typeof runKCountUp === 'function') runKCountUp('demoCouponDoneCount', couponTotal, 1500, 200);
|
||
if (typeof startMidnightCountdown === 'function') startMidnightCountdown();
|
||
}
|
||
}
|
||
if (showToast !== 'true') {
|
||
// LBS 系统弹窗只由首页「去授权」手动触发;进入 home 只跑每日检查(领券/权限提醒)
|
||
if (typeof runHomeDailyChecks === 'function') runHomeDailyChecks();
|
||
}
|
||
} catch(e) { console.warn('[home init] claim state restore failed:', e); }
|
||
}
|
||
});
|
||
</script>
|
||
|
||
|
||
<script>
|
||
// === 调试用:右下角"重置"按钮,仅 file:// 本地预览可见 ===
|
||
(function() {
|
||
if (location.protocol !== 'file:') return;
|
||
if (document.getElementById('debugReset')) return;
|
||
function mount() {
|
||
var btn = document.createElement('div');
|
||
btn.id = 'debugReset';
|
||
btn.textContent = '↻ 重置'; // ↻ 重置
|
||
btn.title = '清空 localStorage 并刷新(仅本地预览可见)';
|
||
btn.style.cssText = 'position:fixed;right:0;bottom:0;z-index:99999;background:#000;color:#fff;font-size:11px;font-weight:700;padding:8px;border-radius:4px 0 0 0;cursor:pointer;opacity:.7;line-height:1;letter-spacing:1px;font-family:inherit;';
|
||
btn.onclick = function() {
|
||
try { localStorage.clear(); } catch(e) {}
|
||
location.reload();
|
||
};
|
||
document.body.appendChild(btn);
|
||
}
|
||
if (document.body) mount();
|
||
else document.addEventListener('DOMContentLoaded', mount);
|
||
})();
|
||
|
||
// === 调试用:首页"每日检查"控制面板(权限开关 + 清今日态),仅 file:// 可见 ===
|
||
(function() {
|
||
if (location.protocol !== 'file:') return;
|
||
if (document.getElementById('debugDaily')) return;
|
||
function mount() {
|
||
var wrap = document.createElement('div');
|
||
wrap.id = 'debugDaily';
|
||
wrap.style.cssText = 'position:fixed;right:0;bottom:34px;z-index:99999;display:flex;flex-direction:column;gap:3px;align-items:flex-end;font-family:inherit;';
|
||
function permChip(label, key) {
|
||
var c = document.createElement('div');
|
||
var off = false;
|
||
try { off = localStorage.getItem(key) === 'off'; } catch(e) {}
|
||
c.textContent = label + (off ? ' ✕' : ' ✓');
|
||
c.title = '点击切换'+label+'权限状态(仅本地预览)';
|
||
c.style.cssText = 'background:'+(off ? '#c0392b' : '#222')+';color:#fff;font-size:10px;font-weight:700;padding:5px 8px;border-radius:4px 0 0 4px;cursor:pointer;opacity:.78;line-height:1;letter-spacing:.5px;';
|
||
c.onclick = function() {
|
||
try {
|
||
if (localStorage.getItem(key) === 'off') localStorage.removeItem(key);
|
||
else localStorage.setItem(key, 'off');
|
||
// 切换权限即清掉今日提醒记忆,下一次刷新可重新弹
|
||
localStorage.removeItem('proto_home_perm_reminder_date');
|
||
} catch(e) {}
|
||
location.reload();
|
||
};
|
||
return c;
|
||
}
|
||
function clearTodayChip() {
|
||
var c = document.createElement('div');
|
||
c.textContent = '清今日态';
|
||
c.title = '清空今日权限/领券弹窗记忆 + 已领卡片,模拟新一天进入首页';
|
||
c.style.cssText = 'background:#555;color:#fff;font-size:10px;font-weight:700;padding:5px 8px;border-radius:4px 0 0 4px;cursor:pointer;opacity:.78;line-height:1;letter-spacing:.5px;';
|
||
c.onclick = function() {
|
||
try {
|
||
localStorage.removeItem('proto_home_perm_reminder_date');
|
||
localStorage.removeItem('proto_home_coupon_reminder_date');
|
||
localStorage.removeItem('proto_home_coupon_claim_date');
|
||
localStorage.removeItem('proto_homeCouponClaimed');
|
||
localStorage.removeItem('proto_homeCouponClaimSummary');
|
||
} catch(e) {}
|
||
location.reload();
|
||
};
|
||
return c;
|
||
}
|
||
function nearbyEmptyChip() {
|
||
var c = document.createElement('div');
|
||
var on = false;
|
||
try { on = localStorage.getItem('proto_home_nearby_empty') === '1'; } catch(e) {}
|
||
c.textContent = '无推荐' + (on ? ' ✓' : ' ✕');
|
||
c.title = '模拟已开启位置权限但附近没有推荐商品,空态由首页状态判断出现(仅本地预览)';
|
||
c.style.cssText = 'background:'+(on ? '#222' : '#555')+';color:#fff;font-size:10px;font-weight:700;padding:5px 8px;border-radius:4px 0 0 4px;cursor:pointer;opacity:.78;line-height:1;letter-spacing:.5px;';
|
||
c.onclick = function() {
|
||
try {
|
||
if (localStorage.getItem('proto_home_nearby_empty') === '1') {
|
||
localStorage.removeItem('proto_home_nearby_empty');
|
||
} else {
|
||
// 调试态只模拟“已授权但附近无推荐”,空态仍由 applyLocationState 统一判断展示。
|
||
localStorage.setItem('proto_home_nearby_empty', '1');
|
||
localStorage.setItem('proto_locationAuthMode', 'whileUsing');
|
||
localStorage.setItem('proto_locationGranted', '1');
|
||
}
|
||
} catch(e) {}
|
||
location.reload();
|
||
};
|
||
return c;
|
||
}
|
||
wrap.appendChild(permChip('无障碍', 'proto_perm_accessibility'));
|
||
wrap.appendChild(permChip('悬浮窗', 'proto_perm_overlay'));
|
||
wrap.appendChild(nearbyEmptyChip());
|
||
wrap.appendChild(clearTodayChip());
|
||
document.body.appendChild(wrap);
|
||
}
|
||
if (document.body) mount();
|
||
else document.addEventListener('DOMContentLoaded', mount);
|
||
})();
|
||
</script>
|
||
|
||
<script>
|
||
// ===== v2026-06-01:实时节省日志横条 + 平台累计省下入口 + AI 领券 FAB =====
|
||
|
||
// 昵称脱敏:4 字保留首尾;3 字及以下保留首字;5 字及以上固定 3 星。
|
||
function maskNickname(name) {
|
||
var chars = Array.from(name || '');
|
||
var len = chars.length;
|
||
if (len === 0) return '用户**';
|
||
if (len >= 5) return chars[0] + '***' + chars[len - 1];
|
||
if (len === 4) return chars[0] + '**' + chars[len - 1];
|
||
return chars[0] + '**';
|
||
}
|
||
|
||
// 无昵称用户:固定 id 前 1 位 + 3 个星号 + id 后 1 位,例如 a***8。
|
||
function maskUserId(id) {
|
||
var normalized = String(id || '').replace(/\s/g, '');
|
||
if (!normalized) return '0***0';
|
||
return normalized.slice(0, 1) + '***' + normalized.slice(-1);
|
||
}
|
||
|
||
function formatSavingsAmount(value) {
|
||
var num = Number(String(value || '').replace(/[^\d.]/g, ''));
|
||
if (!Number.isFinite(num)) num = 0;
|
||
return num.toFixed(2);
|
||
}
|
||
|
||
function setHomeMqFixedSlots(track) {
|
||
var home = document.getElementById('home');
|
||
var host = track && track.closest ? track.closest('.home-marquee') : null;
|
||
if (!home || !host) return;
|
||
var measure = document.createElement('span');
|
||
measure.className = 'home-mq-measure';
|
||
home.appendChild(measure);
|
||
|
||
function measureText(className, text) {
|
||
var span = document.createElement('span');
|
||
span.className = className;
|
||
span.textContent = text;
|
||
measure.innerHTML = '';
|
||
measure.appendChild(span);
|
||
return (Math.ceil(span.getBoundingClientRect().width * 100) / 100) + 'px';
|
||
}
|
||
|
||
host.style.setProperty('--home-mq-user-slot', measureText('mq-user', '省***手'));
|
||
host.style.setProperty('--home-mq-amount-slot', measureText('mq-amt', '88888.88'));
|
||
measure.remove();
|
||
}
|
||
|
||
// 实时节省日志横条 —— 每 2.4s 自动上滚一条,到末尾(首条副本)后无动画归零
|
||
(function() {
|
||
var track = document.getElementById('homeMarqueeTrack');
|
||
if (!track) return;
|
||
setHomeMqFixedSlots(track);
|
||
// 两种打码混着渲染:有昵称(data-nick)走昵称脱敏,无昵称(data-uid)走 id 前后位脱敏。
|
||
Array.prototype.forEach.call(track.querySelectorAll('.mq-user'), function(el) {
|
||
if (el.dataset.nick) el.textContent = maskNickname(el.dataset.nick);
|
||
else if (el.dataset.uid) el.textContent = maskUserId(el.dataset.uid);
|
||
});
|
||
Array.prototype.forEach.call(track.querySelectorAll('.mq-amt'), function(el) {
|
||
el.textContent = formatSavingsAmount(el.textContent);
|
||
});
|
||
var items = track.children;
|
||
var n = items.length;
|
||
if (n < 2) return;
|
||
var itemH = 22;
|
||
var idx = 0;
|
||
var maxIdx = n - 1; // 末尾是首条副本,到这里要无动画归零
|
||
setInterval(function() {
|
||
idx++;
|
||
track.style.transition = 'transform .42s cubic-bezier(.22,1,.36,1)';
|
||
track.style.transform = 'translateY(' + (-idx * itemH) + 'px)';
|
||
if (idx >= maxIdx) {
|
||
setTimeout(function() {
|
||
track.style.transition = 'none';
|
||
track.style.transform = 'translateY(0)';
|
||
idx = 0;
|
||
}, 460);
|
||
}
|
||
}, 2400);
|
||
})();
|
||
|
||
// 平台累计省下入口 → 跳转占位(暂复用 profile,后续替换为战报页)
|
||
function onPlatformStatsClick() {
|
||
if (typeof go === 'function') go('profile');
|
||
}
|
||
|
||
// 平台候选包(对齐原生 HOME_PICKER_APPS):任一已装即「已装」;点击拉起把整组候选包交原生取首个已装。
|
||
var PICKER_PACKAGES = {
|
||
'美团': ['com.sankuai.meituan', 'com.sankuai.meituan.takeoutnew'],
|
||
'淘宝': ['com.taobao.taobao', 'me.ele'],
|
||
'京东': ['com.jingdong.app.mall'],
|
||
};
|
||
function getInstalledPkgSet() {
|
||
try { if (window.SGBridge && typeof SGBridge.getInstalledApps === 'function') return SGBridge.getInstalledApps() || []; } catch(e) {}
|
||
return [];
|
||
}
|
||
// 比价入口 picker:动态渲染 3 平台(真装机态:getInstalledApps 判候选包是否已装)
|
||
function renderHomePickerPlatforms() {
|
||
var grid = document.getElementById('homePickerGrid');
|
||
if (!grid || typeof getVisibleApps !== 'function') return;
|
||
var installedList = getInstalledPkgSet();
|
||
var platforms = getVisibleApps();
|
||
grid.innerHTML = platforms.map(function(app) {
|
||
var pkgs = PICKER_PACKAGES[app.name] || [];
|
||
var installed = pkgs.some(function(p){ return installedList.indexOf(p) !== -1; });
|
||
if (installed) {
|
||
return '<div class="home-picker-item" data-platform="' + app.name + '">' +
|
||
'<div class="home-picker-logo"><img src="' + app.icon + '" alt=""></div>' +
|
||
'<div class="home-picker-name">' + app.name + '</div>' +
|
||
'</div>';
|
||
}
|
||
return '<div class="home-picker-item uninstalled" data-platform="' + app.name + '" data-uninstalled="true">' +
|
||
'<div class="home-picker-logo"><img src="' + app.icon + '" alt=""></div>' +
|
||
'<div class="home-picker-name">' + app.name + '</div>' +
|
||
'<span class="home-picker-install-chip">' +
|
||
'<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M5 1.5v5.5m0 0L2.5 4.5M5 7l2.5-2.5M2 9h6" stroke="#1a1a1a" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
|
||
'</span>' +
|
||
'</div>';
|
||
}).join('');
|
||
}
|
||
|
||
// 比价入口 onclick → 渲染平台 + 弹 picker
|
||
function onHomeCompareClick() {
|
||
// H3:拉起外卖不需登录态;「未登录引导」连同 getAuthState 留后续登录态子项。直接渲染 + 弹平台选择。
|
||
renderHomePickerPlatforms();
|
||
var mask = document.getElementById('homePickerMask');
|
||
if (mask) mask.classList.add('show');
|
||
}
|
||
function closeHomePicker() {
|
||
var mask = document.getElementById('homePickerMask');
|
||
if (mask) mask.classList.remove('show');
|
||
}
|
||
(function() {
|
||
var mask = document.getElementById('homePickerMask');
|
||
if (!mask) return;
|
||
// 事件委托:点蒙层关闭 / 点平台触发跳转或安装引导
|
||
mask.addEventListener('click', function(e) {
|
||
if (e.target === mask) { closeHomePicker(); return; }
|
||
var item = e.target.closest('.home-picker-item');
|
||
if (!item) return;
|
||
var nameEl = item.querySelector('.home-picker-name');
|
||
var name = nameEl ? nameEl.textContent : '';
|
||
closeHomePicker();
|
||
if (item.dataset.uninstalled === 'true') {
|
||
// 未装:跳应用市场引导(原型 stub)
|
||
if (typeof showToast === 'function') showToast('请先安装「' + name + '」APP');
|
||
if (typeof onPlatformInstallClick === 'function') {
|
||
var app = (typeof allApps !== 'undefined') ? allApps.find(function(a){return a.name === name;}) : null;
|
||
if (app) onPlatformInstallClick(app.id);
|
||
}
|
||
} else {
|
||
// 已装:拉起对应平台 App(整组候选包交原生取首个已装,NEW_TASK|CLEAR_TASK 冷启首页)
|
||
var pkgs = PICKER_PACKAGES[name] || [];
|
||
if (pkgs.length && window.SGBridge && typeof SGBridge.launchApp === 'function') SGBridge.launchApp(pkgs);
|
||
}
|
||
});
|
||
})();
|
||
|
||
</script>
|
||
<script>
|
||
(function() {
|
||
function getTodayKey() {
|
||
var d = new Date();
|
||
return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
|
||
}
|
||
function updateWelfareCheckinTabDot() {
|
||
var tab = document.getElementById('homeTabWelfare');
|
||
if (!tab) return;
|
||
var done = false;
|
||
try { done = localStorage.getItem('proto_checkinDoneDate') === getTodayKey(); } catch(e) {}
|
||
tab.classList.toggle('has-welfare-dot', !done);
|
||
}
|
||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateWelfareCheckinTabDot);
|
||
else updateWelfareCheckinTabDot();
|
||
})();
|
||
</script>
|
||
<script src="../shared/bridge.js"></script>
|
||
<script>
|
||
/* H2b 首页 feed:rec/distance→/meituan/feed,sales→/meituan/top-sales;触底翻页 + 每 tab 5min 缓存
|
||
+ loading/empty/degraded 三态 + 去重 + 切 tab 防竞态 + 未授权不打接口。对齐原生 HomeViewModel。 */
|
||
(function (global) {
|
||
'use strict';
|
||
var BEIJING = { longitude: 116.404, latitude: 39.928 };
|
||
var ENDPOINT = { rec: '/api/v1/meituan/feed', distance: '/api/v1/meituan/feed', sales: '/api/v1/meituan/top-sales' };
|
||
var CACHE_TTL = 5 * 60 * 1000;
|
||
var SCROLL_THRESHOLD = 400; // 距底 px 触发翻页
|
||
|
||
var st = { tab: 'rec', page: 0, hasNext: true, loading: false, loadedOnce: false,
|
||
items: [], seq: 0, coords: null, cache: {} };
|
||
|
||
function $feed() { return document.querySelector('#home .home-feed'); }
|
||
function $end() { return document.querySelector('#home .feed-end'); }
|
||
function $scroll() { return document.querySelector('#home .home-scroll'); }
|
||
|
||
function locationGranted() {
|
||
try { if (global.SGBridge && SGBridge.isLocationGranted) return !!SGBridge.isLocationGranted(); } catch (e) {}
|
||
return false;
|
||
}
|
||
function getCoords() {
|
||
try {
|
||
if (global.SGBridge && SGBridge.getLocation) {
|
||
var c = SGBridge.getLocation();
|
||
if (c && typeof c.longitude === 'number' && typeof c.latitude === 'number') return c;
|
||
}
|
||
} catch (e) {}
|
||
return BEIJING;
|
||
}
|
||
function esc(s) {
|
||
return String(s == null ? '' : s).replace(/[&<>"']/g, function (m) {
|
||
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[m];
|
||
});
|
||
}
|
||
function splitPrice(p) {
|
||
var s = String(p == null ? '' : p), i = s.indexOf('.');
|
||
return i < 0 ? [s, ''] : [s.slice(0, i), s.slice(i)];
|
||
}
|
||
|
||
// CouponCard → .feed-card(1:1 照原生 FeedCard;feed-tag 只用 price_label/rank_label,不显示「比团购省」)
|
||
function renderCard(card) {
|
||
var isWaimai = card.platform === 1;
|
||
var shop = card.brand_name
|
||
? '<span class="shop-name">' + esc(card.brand_name) + '</span><span class="title-sep">|</span>' : '';
|
||
var title = esc(card.name || '');
|
||
if (card.available_poi_num) title += '|' + card.available_poi_num + '店通用';
|
||
var metaLeft = '';
|
||
if (card.distance_text) metaLeft += esc(card.distance_text);
|
||
if (card.poi_name) metaLeft += (metaLeft ? ' ' : '') + esc(card.poi_name);
|
||
var saleVol = card.sale_volume ? '<span class="meta-right">' + esc(card.sale_volume) + '</span>' : '';
|
||
var labels = [];
|
||
if (card.price_label && card.price_label.trim()) labels.push(card.price_label.trim());
|
||
if (card.rank_label && card.rank_label.trim()) labels.push(card.rank_label.trim());
|
||
var tag = labels.length
|
||
? '<div class="feed-tag">' + esc(labels[Math.floor(Math.random() * labels.length)]) + '</div>' : '';
|
||
var pr = splitPrice(card.sell_price);
|
||
|
||
var el = document.createElement('div');
|
||
el.className = 'feed-card';
|
||
el.dataset.sign = card.product_view_sign || '';
|
||
el.dataset.platform = card.platform;
|
||
if (card.biz_line != null) el.dataset.bizLine = card.biz_line;
|
||
el.innerHTML =
|
||
'<div class="feed-img"><img src="' + esc(card.head_image_url || '') + '" alt="">' +
|
||
'<span class="feed-cat-badge ' + (isWaimai ? 'cat-waimai">外卖' : 'cat-tuangou">团购') + '</span></div>' +
|
||
'<div class="feed-body">' +
|
||
'<div class="feed-title">' + shop + title + '</div>' +
|
||
'<div class="feed-meta"><span class="meta-left">' + metaLeft + '</span>' + saleVol + '</div>' +
|
||
tag +
|
||
'<div class="feed-pricerow">' +
|
||
'<div class="feed-price"><span class="yuan">¥</span><span class="num">' + esc(pr[0]) +
|
||
(pr[1] ? '<small>' + esc(pr[1]) + '</small>' : '') + '</span></div>' +
|
||
'<span class="feed-original">¥' + esc(card.original_price || '') + '</span>' +
|
||
'</div>' +
|
||
'</div>' +
|
||
'<div class="feed-grab">抢</div>';
|
||
return el;
|
||
}
|
||
|
||
function renderList(newItems, append) {
|
||
var feed = $feed(); if (!feed) return;
|
||
if (!append) feed.innerHTML = '';
|
||
newItems.forEach(function (c) { feed.appendChild(renderCard(c)); });
|
||
var end = $end();
|
||
if (end) end.style.display = (!st.hasNext && st.items.length) ? '' : 'none';
|
||
}
|
||
|
||
function reqBody(tab, page, coords) {
|
||
return tab === 'sales'
|
||
? { page: page }
|
||
: { longitude: coords.longitude, latitude: coords.latitude, page: page, tab: tab };
|
||
}
|
||
|
||
function loadPage(page, append) {
|
||
var tab = st.tab, coords = getCoords(), mySeq = ++st.seq;
|
||
st.coords = coords; st.loading = true;
|
||
if (global.HomeFeedStates) HomeFeedStates(append ? 'loadingMore' : 'loading');
|
||
fetch(ENDPOINT[tab], {
|
||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify(reqBody(tab, page, coords)),
|
||
}).then(function (r) { return r.ok ? r.json() : null; }).then(function (d) {
|
||
if (mySeq !== st.seq) return; // 竞态:已切 tab/重载 → 丢弃旧响应
|
||
st.loading = false; st.loadedOnce = true;
|
||
if (!d) { if (global.HomeFeedStates) HomeFeedStates('degraded'); return; }
|
||
var items = d.items || [];
|
||
if (append) {
|
||
var seen = {}; st.items.forEach(function (c) { seen[c.product_view_sign] = 1; });
|
||
items = items.filter(function (c) { return c.product_view_sign && !seen[c.product_view_sign]; });
|
||
st.items = st.items.concat(items);
|
||
} else { st.items = items; }
|
||
st.page = page; st.hasNext = !!d.has_next;
|
||
st.cache[tab] = { items: st.items.slice(), page: st.page, hasNext: st.hasNext,
|
||
loadedAt: (append && st.cache[tab]) ? st.cache[tab].loadedAt : Date.now() };
|
||
renderList(append ? items : st.items, append);
|
||
if (global.HomeFeedStates) HomeFeedStates(d.status === 'degraded' ? 'degraded' : (st.items.length ? 'ok' : 'empty'));
|
||
}).catch(function () {
|
||
if (mySeq !== st.seq) return;
|
||
st.loading = false; st.loadedOnce = true;
|
||
if (global.HomeFeedStates) HomeFeedStates('degraded');
|
||
});
|
||
}
|
||
|
||
function loadFirst() { st.page = 0; st.hasNext = true; st.items = []; renderList([], false); loadPage(1, false); }
|
||
function loadNext() { if (!st.hasNext || st.loading) return; loadPage(st.page + 1, true); }
|
||
|
||
function switchTab(tab) {
|
||
if (tab === st.tab) return;
|
||
st.seq++; // 作废旧 tab 在飞的请求
|
||
st.tab = tab;
|
||
var c = st.cache[tab];
|
||
if (c && Date.now() - c.loadedAt < CACHE_TTL) { // 命中新鲜缓存 → 直接恢复,不转圈
|
||
st.items = c.items.slice(); st.page = c.page; st.hasNext = c.hasNext; st.loading = false;
|
||
renderList(st.items, false);
|
||
if (global.HomeFeedStates) HomeFeedStates(st.items.length ? 'ok' : 'empty');
|
||
} else { loadFirst(); }
|
||
}
|
||
function selectTabWithoutLoad(tab) { // 未授权:只切状态,不打接口
|
||
if (tab === st.tab) return;
|
||
st.seq++; st.tab = tab; st.page = 0; st.hasNext = true; st.items = []; renderList([], false);
|
||
}
|
||
|
||
// 坐标变化(rec/distance 依赖坐标)→ 清全部缓存并重拉当前 tab
|
||
function refreshIfCoordsChanged() {
|
||
var c = getCoords();
|
||
if (st.coords && (st.coords.longitude !== c.longitude || st.coords.latitude !== c.latitude)) {
|
||
st.cache = {};
|
||
if (locationGranted()) loadFirst();
|
||
}
|
||
}
|
||
|
||
function bindScroll() { // 触底翻页
|
||
var sc = $scroll(); if (!sc || sc._feedBound) return; sc._feedBound = true;
|
||
sc.addEventListener('scroll', function () {
|
||
if (sc.scrollTop + sc.clientHeight >= sc.scrollHeight - SCROLL_THRESHOLD) loadNext();
|
||
});
|
||
}
|
||
|
||
global.HomeFeed = {
|
||
loadFirst: loadFirst, switchTab: switchTab, selectTabWithoutLoad: selectTabWithoutLoad,
|
||
refreshIfCoordsChanged: refreshIfCoordsChanged, bindScroll: bindScroll,
|
||
locationGranted: locationGranted, state: st,
|
||
};
|
||
document.addEventListener('DOMContentLoaded', bindScroll);
|
||
})(window);
|
||
</script>
|
||
<script>
|
||
/* H2b feed 三态 + 抢:loading 首次转圈 / empty 复用「附近暂无…去比价」/ degraded 服务繁忙;
|
||
抢 → referral-link([1,3]) → openMeituan(deeplink||h5)。与 H2a applyLocationState 协作切态。 */
|
||
(function (global) {
|
||
'use strict';
|
||
function el(id) { return document.getElementById(id); }
|
||
function hide(n) { if (n) n.style.display = 'none'; }
|
||
|
||
// feed 子态机:loading/degraded 本函数管;ok/empty 交回 applyLocationState 按卡片数切 feed/附近暂无空态。
|
||
global.HomeFeedStates = function (kind) {
|
||
var feed = document.querySelector('#home .home-feed');
|
||
var loading = el('homeFeedLoading');
|
||
var degraded = el('homeFeedDegraded');
|
||
var noDeal = el('homeFeedNoDealEmpty');
|
||
var hasItems = !!(global.HomeFeed && HomeFeed.state.items.length);
|
||
if (kind === 'loading' && !hasItems) { // 首次加载中:转圈,压住空态/feed
|
||
if (loading) loading.style.display = 'flex';
|
||
hide(degraded); hide(noDeal); if (feed) feed.style.display = 'none';
|
||
return;
|
||
}
|
||
if (kind === 'degraded' && !hasItems) { // 上游失败且无数据:服务繁忙
|
||
if (degraded) degraded.style.display = 'flex';
|
||
hide(loading); hide(noDeal); if (feed) feed.style.display = 'none';
|
||
return;
|
||
}
|
||
// ok / empty / loadingMore / 有数据时的 degraded:收起 loading+degraded,交 H2a 按卡片数定 feed/附近暂无
|
||
hide(loading); hide(degraded);
|
||
try { applyLocationState(); } catch (e) {}
|
||
};
|
||
|
||
// 抢:换链(linkTypeList=[1,3])→ deeplink 优先, 退 h5 → SGBridge.openMeituan(事件委托,适配动态卡)
|
||
document.addEventListener('click', function (e) {
|
||
var grab = e.target.closest('#home .feed-card .feed-grab');
|
||
if (!grab) return;
|
||
var card = grab.closest('.feed-card');
|
||
if (!card || card._grabbing) return;
|
||
card._grabbing = true;
|
||
var prev = grab.textContent; grab.textContent = '…';
|
||
fetch('/api/v1/meituan/referral-link', {
|
||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
product_view_sign: card.dataset.sign,
|
||
platform: Number(card.dataset.platform) || 1,
|
||
biz_line: card.dataset.bizLine != null ? Number(card.dataset.bizLine) : null,
|
||
link_type_list: [1, 3],
|
||
}),
|
||
}).then(function (r) { return r.ok ? r.json() : null; }).then(function (d) {
|
||
var map = (d && d.link_map) || {};
|
||
var uri = map['3'] || map['1'] || (d && d.link) || '';
|
||
if (uri && global.SGBridge && SGBridge.openMeituan) SGBridge.openMeituan(uri);
|
||
else if (global.SGBridge && SGBridge.toast) SGBridge.toast('暂时无法跳转,请稍后再试');
|
||
else console.log('[抢] openMeituan →', uri);
|
||
}).catch(function () {
|
||
if (global.SGBridge && SGBridge.toast) SGBridge.toast('暂时无法跳转,请稍后再试');
|
||
}).then(function () { grab.textContent = prev; card._grabbing = false; });
|
||
});
|
||
})(window);
|
||
</script>
|
||
<script>
|
||
/* H1→收尾:导航类 go() 已接 SGBridge.navigate(原生壳跳 教程/邀请/比价结果);去领取/去点餐/去授权仍占位(H3/H4)。
|
||
占位 = 轻量 toast + console,不触发原型多屏切换(其它 .screen 已删,原型切屏会 JS 报错)。
|
||
仅真实点击才弹 toast:pointerdown 记最近手势,过滤加载时的自动调用(如领券提醒 setTimeout(onTriClaimClick))。 */
|
||
(function(){
|
||
var lastGesture = 0;
|
||
document.addEventListener('pointerdown', function(){ lastGesture = Date.now(); }, true);
|
||
var hideTimer;
|
||
function placeholderToast(){
|
||
var el = document.getElementById('h1PlaceholderToast');
|
||
if (!el){
|
||
el = document.createElement('div');
|
||
el.id = 'h1PlaceholderToast';
|
||
el.style.cssText = 'position:fixed;left:50%;bottom:96px;transform:translateX(-50%);max-width:78%;'
|
||
+ 'background:rgba(0,0,0,.8);color:#fff;font-size:13px;font-weight:500;line-height:1.4;text-align:center;'
|
||
+ 'padding:9px 16px;border-radius:10px;z-index:9999;opacity:0;transition:opacity .18s;pointer-events:none;';
|
||
document.body.appendChild(el);
|
||
}
|
||
el.textContent = '功能开发中,敬请期待';
|
||
el.style.opacity = '1';
|
||
clearTimeout(hideTimer);
|
||
hideTimer = setTimeout(function(){ el.style.opacity = '0'; }, 1400);
|
||
}
|
||
function placeholder(label){
|
||
return function(){
|
||
try { console.log('[H1 占位] ' + label + ' — H2-H4 接桥'); } catch(e){}
|
||
if (Date.now() - lastGesture < 1200) placeholderToast(); // 仅手势触发才弹,滤掉加载时自动调用
|
||
};
|
||
}
|
||
// 导航类按钮 → SGBridge.navigate(原生壳跳真实页);其余目标本轮未接,维持占位
|
||
var NAV_ROUTES = { guideVideo: 'guideVideo', invite: 'invite', compresult: 'compareResult' };
|
||
window.go = function(target){
|
||
var route = NAV_ROUTES[target];
|
||
if (route && window.SGBridge && typeof SGBridge.navigate === 'function') { SGBridge.navigate(route); return; }
|
||
try { console.log('[H1 占位] go(' + (target == null ? '' : target) + ') — 未接线/无桥,占位'); } catch(e){}
|
||
if (Date.now() - lastGesture < 1200) placeholderToast();
|
||
};
|
||
// onTriClaimClick(去领取)已接真实领券(见上方定义),从占位移除
|
||
// onHomeCompareClick(去点餐)已接真实 picker + launchApp(见上方定义),从占位移除;去领取/去授权仍占位
|
||
// goAuthLocation(去授权)已接真·定位权限(见上方定义),从占位移除;去领取仍占位
|
||
})();
|
||
|
||
/* H1:三数据卡 + 跑马灯接同源 /api/v1/platform/*(均不鉴权;失败回落原型 mock) */
|
||
(function(){
|
||
// 三数据卡:替换静态数字(顺序 帮助用户/完成比价/累计节省)
|
||
fetch('/api/v1/platform/stats').then(function(r){return r.ok?r.json():null;}).then(function(s){
|
||
if(!s) return;
|
||
var v=document.querySelectorAll('.home-3stat .h3s-value');
|
||
if(v.length<3) return;
|
||
v[0].innerHTML=s.help_users+'<span class="h3s-unit">人</span>';
|
||
v[1].innerHTML=s.total_compares+'<span class="h3s-unit">次</span>';
|
||
v[2].innerHTML=(s.total_saved_cents/100).toFixed(1)+'<span class="h3s-unit">元</span>';
|
||
}).catch(function(){});
|
||
// 跑马灯:原地更新现有行文本(不重建 DOM→保住滚动);末行是首条副本,用 data[0] 保无缝循环
|
||
fetch('/api/v1/platform/savings-feed?limit=8').then(function(r){return r.ok?r.json():null;}).then(function(d){
|
||
if(!d||!d.items||!d.items.length) return;
|
||
var rows=document.querySelectorAll('#homeMarqueeTrack .home-mq-item');
|
||
if(!rows.length) return;
|
||
var data=d.items;
|
||
rows.forEach(function(el,i){
|
||
var src=(i===rows.length-1)?data[0]:data[i%data.length];
|
||
var t=el.querySelector('.mq-time'); if(t)t.textContent=src.time;
|
||
var u=el.querySelector('.mq-user'); if(u)u.textContent=src.masked_user;
|
||
var a=el.querySelector('.mq-amt'); if(a)a.textContent=(src.saved_amount_cents/100).toFixed(2);
|
||
});
|
||
}).catch(function(){});
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|