ea0c563680
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
430 lines
32 KiB
HTML
430 lines
32 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<link rel="stylesheet" href="../shared/fonts.css">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||
<title>赚钱中心 · 傻瓜比价</title>
|
||
<style>
|
||
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
|
||
html, body { height: 100%; overflow: hidden; }
|
||
body { font-family: 'PuHuiTi', -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; background: #F5F5F5; color: #1A1A1A; }
|
||
|
||
:root {
|
||
--orange: #FF5722; --bg: #F5F5F5; --card: #FFFFFF; --aux: #999999; --text: #1A1A1A;
|
||
--cta-grad: linear-gradient(180deg, #FFE066 0%, #FFC400 100%);
|
||
--cta-shadow: inset 0 1px 0 rgba(255,255,255,.7), 0 2px 6px rgba(255,179,0,.35);
|
||
}
|
||
.num { font-family: "DIN Alternate", "Helvetica Neue", sans-serif; font-variant-numeric: tabular-nums; }
|
||
|
||
.device { position: relative; width: 100%; height: 100%; background: var(--bg); overflow: hidden; }
|
||
.screen { position: absolute; inset: 0; display: flex; flex-direction: column; }
|
||
/* 底部留出原生底部 tab 栏高度(内容区铺满、tab 栏盖其上)+ 手势条安全区 */
|
||
.scroll { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 0 12px calc(80px + env(safe-area-inset-bottom, 0px)); }
|
||
.scroll::-webkit-scrollbar { display: none; }
|
||
|
||
.page-header { height: 50px; display: flex; align-items: center; justify-content: center; padding: 4px 4px 8px; }
|
||
.page-title { font-size: 20px; font-weight: 700; color: var(--text); line-height: 1; }
|
||
|
||
/* ===== 资产卡(与收益明细汇总卡同一套 UI:黄渐变) ===== */
|
||
.asset-card { position: relative; border-radius: 18px; padding: 16px; margin: 0 4px; overflow: hidden;
|
||
background: linear-gradient(180deg, #FFE86A 0%, #FFD600 100%); box-shadow: 0 6px 18px rgba(255,179,0,.22); }
|
||
.asset-cols { display: flex; gap: 22px; }
|
||
.asset-col { flex: 1; min-width: 0; cursor: pointer; }
|
||
.asset-label { display: inline-flex; align-items: center; gap: 2px; font-size: 15px; font-weight: 600; color: #1A1A1A; line-height: 20px; }
|
||
.asset-arrow { width: 13px; height: 13px; flex-shrink: 0; }
|
||
.asset-valrow { display: flex; align-items: center; gap: 8px; min-height: 31px; margin-top: 8px; }
|
||
.asset-val { font-size: 28px; font-weight: 700; color: #FF5A1F; line-height: 30px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
.chip { flex-shrink: 0; display: inline-flex; align-items: center; gap: 2px; height: 26px; padding: 0 10px; border-radius: 999px; background: #FFFFFF; border: none; box-shadow: 0 2px 6px rgba(139,94,0,.13); font-size: 12px; font-weight: 700; color: #1A1A1A; white-space: nowrap; cursor: pointer; }
|
||
.chip:active { transform: translateY(1px) scale(.98); }
|
||
.chip svg, .chip img { width: 16px; height: 16px; display: block; border-radius: 50%; }
|
||
.asset-note { font-size: 11px; font-weight: 400; color: rgba(26,26,26,.58); line-height: 15.4px; margin-top: 8px; }
|
||
|
||
/* 未登录卡:暖白 + 钱包插画 */
|
||
.asset-card.unlogged { background: radial-gradient(120% 90% at 100% 0%, rgba(255,214,0,.28) 0%, rgba(255,214,0,0) 55%), #FFFDF5; box-shadow: 0 4px 14px rgba(204,153,0,.08); min-height: 132px; display: flex; align-items: center; padding: 0 16px; }
|
||
.asset-illustration { position: absolute; right: 6px; bottom: 17px; width: 96px; z-index: 2; pointer-events: none; }
|
||
.asset-unlogged-body { display: flex; flex-direction: column; gap: 16px; padding-right: 112px; position: relative; z-index: 3; }
|
||
.asset-unlogged-title { font-size: 17px; font-weight: 700; color: var(--text); }
|
||
.login-btn { align-self: flex-start; height: 40px; padding: 0 28px; border-radius: 20px; border: none; background: var(--cta-grad); box-shadow: var(--cta-shadow); color: var(--text); font-size: 14px; font-weight: 700; letter-spacing: .04em; cursor: pointer; }
|
||
.login-btn:active { transform: translateY(1px) scale(.99); }
|
||
|
||
/* ===== 任务卡 ===== */
|
||
.task-card { background: var(--card); border-radius: 14px; padding: 20px 16px 16px; box-shadow: 0 4px 12px rgba(0,0,0,.04); margin-top: 16px; }
|
||
.section-title { font-size: 16px; font-weight: 600; color: var(--text); margin: 0 0 14px; }
|
||
|
||
/* 通用黄色 CTA + 红点 */
|
||
.cta { flex-shrink: 0; position: relative; border: none; border-radius: 32px; background: var(--cta-grad); box-shadow: var(--cta-shadow); color: var(--text); font-size: 12px; font-weight: 600; line-height: 29px; height: 29px; cursor: pointer; white-space: nowrap; }
|
||
.cta:active { transform: translateY(1px) scale(.98); }
|
||
.cta.gray { background: #F5F5F5; border: 1px solid #E5E5E5; box-shadow: none; color: var(--aux); }
|
||
.dot { position: absolute; top: -1px; right: -1px; width: 11px; height: 11px; border-radius: 50%; background: #FF3B30; box-shadow: 0 1px 4px rgba(255,59,48,.35); pointer-events: none; }
|
||
|
||
/* 签到行 + 时间线 */
|
||
.checkin-row { padding: 2px 0 24px; border-bottom: 1px solid #F0F0F0; }
|
||
.checkin-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
|
||
.checkin-copy { min-width: 0; }
|
||
.checkin-title { font-size: 15px; font-weight: 500; color: var(--text); white-space: nowrap; }
|
||
.checkin-sub { font-size: 11px; font-weight: 400; color: var(--aux); margin-top: 6px; white-space: nowrap; }
|
||
.checkin-cta { width: 60px; min-width: 60px; padding: 0 12px; }
|
||
.timeline { position: relative; display: grid; grid-template-columns: repeat(5, minmax(0,1fr)); column-gap: 2px; margin-top: 20px; }
|
||
.step { position: relative; display: grid; grid-template-rows: 18px 22px 15px; row-gap: 2px; justify-items: center; }
|
||
.step-label { font-size: 11px; font-weight: 650; color: var(--aux); line-height: 18px; white-space: nowrap; }
|
||
.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; }
|
||
.step-icon { box-sizing: border-box; width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center; justify-content: center; }
|
||
.step-icon img { display: block; width: 22px; height: 22px; object-fit: contain; }
|
||
.step.done .step-icon { background: #FFF3E0; border: 1px solid #FFE066; box-shadow: inset 0 1px 0 rgba(255,255,255,.72); }
|
||
.step.done .step-icon::before { content: '✓'; color: #FFA000; font-size: 13px; line-height: 1; font-weight: 900; }
|
||
.step-amt { color: var(--aux); font-size: 11px; line-height: 1; font-weight: 650; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
||
.step.current .step-amt { color: #FF6A00; font-weight: 800; }
|
||
/* 连线:节点内容 z-index:1 盖住线,线 z-index:0(勿用 -1,会沉到卡片背景下看不见) */
|
||
.step > * { position: relative; z-index: 1; }
|
||
.step:not(:last-child)::after { content: ''; position: absolute; top: 30px; left: 50%; width: calc(100% + 2px); height: 2px; border-radius: 32px; background: #E5E5E5; z-index: 0; }
|
||
.step.gap-next::after { border-radius: 0; background: repeating-linear-gradient(90deg,#E5E5E5 0 3px, transparent 3px 8px); background-size: 8px 2px; background-repeat: repeat-x; }
|
||
|
||
/* 任务行 */
|
||
.task-row { display: flex; align-items: center; margin-top: 30px; }
|
||
.task-info { flex: 1; min-width: 0; }
|
||
.task-titlerow { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
|
||
.task-title { font-size: 15px; font-weight: 500; color: var(--text); line-height: 1.3; }
|
||
.task-coin { display: inline-flex; align-items: center; gap: 0; font-size: 12px; font-weight: 600; color: var(--orange); }
|
||
.task-coin .ci { width: 18px; height: 18px; flex-shrink: 0; margin-right: -2px; transform: scale(1.12); }
|
||
.task-sub { font-size: 11px; color: var(--aux); margin-top: 6px; font-weight: 400; line-height: 1.4; display: flex; align-items: center; gap: 6px; }
|
||
.task-tag { padding: 2px 5px 1px; border-radius: 4px; background: #FFF3E0; color: #E65100; font-size: 10px; font-weight: 700; }
|
||
.task-cta { min-width: 60px; padding: 0 12px; }
|
||
.task-row[hidden] { display: none; }
|
||
|
||
/* 规则入口(在任务卡外) */
|
||
.rule-entry { margin: 16px auto 8px; border: none; background: transparent; color: #999999; font-size: 12px; font-weight: 500; line-height: 18px; display: flex; align-items: center; justify-content: center; gap: 2px; width: 100%; cursor: pointer; }
|
||
.rule-entry span { font-size: 13px; }
|
||
|
||
/* 调试预览(检查签到 1-7 天图案) */
|
||
.dbg { margin: 8px auto 0; display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; opacity: .85; }
|
||
.dbg button { font-size: 11px; padding: 5px 10px; border-radius: 8px; border: 1px solid #E5E5E5; background: #fff; color: #666; cursor: pointer; }
|
||
.dbg .lbl { font-size: 11px; color: #999; }
|
||
|
||
/* ===== 签到弹窗(1:1 对齐原型 #checkinPopup) ===== */
|
||
.ck-layer { position: fixed; inset: 0; z-index: 200; background: rgba(0,0,0,.55); -webkit-backdrop-filter: blur(1px); backdrop-filter: blur(1px); display: none; align-items: center; justify-content: center; padding: 0 16px; }
|
||
.ck-layer.show { display: flex; }
|
||
.ck-card { position: relative; width: 100%; max-width: 340px; 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); }
|
||
.ck-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; }
|
||
.ck-banner { 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: 700; white-space: nowrap; }
|
||
.ck-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; }
|
||
.ck-title { margin: 0; text-align: center; color: #1A1A1A; font-size: 20px; line-height: 1.1; font-weight: 900; }
|
||
.ck-sub { margin-top: 8px; text-align: center; color: #666; font-size: 11px; line-height: 1.2; font-weight: 500; white-space: nowrap; }
|
||
.ck-sub b { color: #FF6A00; font-weight: 800; }
|
||
.ck-rewards { margin-top: 12px; display: grid; grid-template-columns: repeat(5,1fr); gap: 6px; }
|
||
.ck-rcard { 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; box-shadow: inset 0 1px 0 rgba(255,255,255,.75); }
|
||
.ck-rcard.claimed { background: rgba(247,247,247,.96); border-color: #E5E5E5; box-shadow: none; }
|
||
.ck-rcard.current { border-color: #FFB300; box-shadow: 0 8px 15px rgba(255,184,0,.14); background: rgba(255,255,255,.96); }
|
||
.ck-ricon { min-height: 26px; display: flex; align-items: center; justify-content: center; color: #999; font-size: 10px; line-height: 1; font-weight: 800; white-space: nowrap; }
|
||
.ck-ricon img { width: 29px; height: 29px; object-fit: contain; display: block; }
|
||
.ck-ricon img.chest { width: 36px; height: 33px; }
|
||
.ck-ramt { color: #1A1A1A; font-size: 12px; line-height: 1; font-weight: 800; }
|
||
.ck-rcard.claimed .ck-ramt { color: #999; }
|
||
.ck-progress { margin: 12px 0 0; position: relative; display: grid; grid-template-columns: repeat(5,1fr); gap: 6px; align-items: start; }
|
||
.ck-lines { position: absolute; top: 4.5px; left: 0; right: 0; height: 3px; pointer-events: none; z-index: 0; }
|
||
.ck-seg { position: absolute; top: 0; height: 3px; border-radius: 32px; }
|
||
.ck-seg.solid { background: var(--lc,#FFB800); }
|
||
.ck-seg.dashed { background: repeating-linear-gradient(90deg,var(--lc,#D9D9D9) 0 3px, transparent 3px 8px); background-size: 8px 3px; background-repeat: repeat-x; }
|
||
.ck-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; }
|
||
.ck-dot { box-sizing: border-box; width: 12px; height: 12px; border-radius: 50%; background: #fff; border: 2px solid #DDD; }
|
||
.ck-node.done .ck-dot { background: #FFB300; border-color: #FFB300; }
|
||
.ck-node.current .ck-dot { background: #fff; border: 2.5px solid #FFB300; }
|
||
.ck-cta { position: relative; margin: 12px auto 0; width: fit-content; min-width: 252px; max-width: calc(100% - 24px); height: 40px; padding: 0 22px; border: none; border-radius: 24px; background: linear-gradient(180deg,#FFE066 0%,#FFB300 100%); color: #1A1A1A; font-size: 16px; font-weight: 900; line-height: 1; white-space: nowrap; box-shadow: 0 14px 28px rgba(255,184,0,.22); display: flex; align-items: center; justify-content: center; gap: 4px; cursor: pointer; }
|
||
.ck-cta:active { transform: translateY(1px) scale(.99); }
|
||
.ck-cta img { width: 18px; height: 18px; object-fit: contain; display: block; }
|
||
.ck-cta b { color: #FF6A00; font-size: 22px; line-height: 1; }
|
||
|
||
/* Toast */
|
||
.toast { position: fixed; left: 50%; top: 45%; transform: translate(-50%,-50%); background: rgba(56,56,68,.94); color: #fff; font-size: 14px; padding: 12px 20px; border-radius: 12px; z-index: 60; opacity: 0; transition: opacity .2s; pointer-events: none; max-width: 78vw; text-align: center; }
|
||
.toast.show { opacity: 1; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div class="device">
|
||
<div class="screen">
|
||
<div class="scroll">
|
||
<div class="page-header"><span class="page-title">赚钱中心</span></div>
|
||
<div id="assetSlot"></div>
|
||
<div class="task-card">
|
||
<div class="section-title">赚金币</div>
|
||
<div id="checkinSlot"></div>
|
||
<div id="tasksSlot"></div>
|
||
</div>
|
||
<button class="rule-entry" onclick="onRules()">查看活动规则<span>›</span></button>
|
||
<div class="dbg" id="dbgSlot">
|
||
<button onclick="dbgStep(-1)">◀ 天</button>
|
||
<span class="lbl" id="dbgLabel">预览签到:关</span>
|
||
<button onclick="dbgStep(1)">天 ▶</button>
|
||
<button onclick="dbgToggleSigned()">切已签</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="ck-layer" id="ckMask" onclick="if(event.target===this)closeCheckin()">
|
||
<div class="ck-card" onclick="event.stopPropagation()">
|
||
<button class="ck-close" onclick="closeCheckin()" aria-label="关闭">×</button>
|
||
<div class="ck-banner"><span class="star"></span><span id="ckBanner">连续签到7天,必得2500金币</span></div>
|
||
<h2 class="ck-title" id="ckTitle">签到领取今日金币</h2>
|
||
<div class="ck-sub" id="ckSub">—</div>
|
||
<div class="ck-rewards" id="ckRewards"></div>
|
||
<div class="ck-progress" id="ckProgress"></div>
|
||
<button class="ck-cta" id="ckBtn" onclick="doCheckin()"></button>
|
||
<button class="ck-cta" id="ckBoostBtn" onclick="onSigninBoost()" style="display:none">看广告最高膨胀至 3000 金币</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="toast" id="toast"></div>
|
||
|
||
<script src="../shared/bridge.js"></script>
|
||
<script src="../shared/api.js"></script>
|
||
<script>
|
||
(function () {
|
||
'use strict';
|
||
var A = 'assets/';
|
||
var state = { logged: false, coin: 0, cashCents: 0, signin: null, notif: null, ad: null, couponDone: false };
|
||
var dbg = { day: 0, signed: false }; // day 0 = 关(用真实数据)
|
||
var SIGN_AMT = [200, 200, 300, 200, 400, 400, 800];
|
||
|
||
function el(id) { return document.getElementById(id); }
|
||
function esc(s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"' }[c]; }); }
|
||
function thousands(n) { return Number(n || 0).toLocaleString('zh-CN'); }
|
||
function yuan(cents) { return (Number(cents || 0) / 100).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); }
|
||
var toastTimer;
|
||
function toast(msg) { var t = el('toast'); t.textContent = msg; t.classList.add('show'); clearTimeout(toastTimer); toastTimer = setTimeout(function () { t.classList.remove('show'); }, 1800); }
|
||
|
||
function loggedIn() {
|
||
try { if (window.SGBridge) { var t = SGBridge.getToken && SGBridge.getToken(); if (t) return true; var a = SGBridge.getAuthState && SGBridge.getAuthState(); return !!(a && (a.loggedIn || a.logged_in)); } } catch (e) {}
|
||
return false;
|
||
}
|
||
function requestLogin() { if (window.SGBridge && SGBridge.requestLogin) SGBridge.requestLogin(); }
|
||
function nav(route) { if (window.SGBridge && SGBridge.navigate) SGBridge.navigate(route); else console.log('[nav]', route); }
|
||
function guard(fn) { if (!state.logged) { requestLogin(); return; } fn(); }
|
||
|
||
// ---------- CTA ----------
|
||
window.onRules = function () { if (state.logged) nav('welfareRules'); else requestLogin(); };
|
||
window.onWithdraw = function () { nav('withdrawal'); };
|
||
window.onCoinHistory = function () { nav('coinHistory'); };
|
||
window.onCashHistory = function () { nav('cashHistory'); };
|
||
window.onLogin = function () { requestLogin(); };
|
||
window.onCoupon = function () { guard(function () { nav('welfareTask:coupon'); }); };
|
||
window.onCompare = function () { guard(function () { nav('welfareTask:compare'); }); };
|
||
window.onNotif = function () { guard(function () { nav('welfareTask:notification'); }); };
|
||
window.onReport = function () { guard(function () { nav('reportFlow'); }); };
|
||
window.onInvite = function () { guard(function () { nav('invite'); }); };
|
||
window.onVideo = function () {
|
||
guard(function () {
|
||
if (state.ad && state.ad.remaining <= 0) { toast('今日看视频奖励已达上限,明天再来'); return; }
|
||
if (cooldownLeft() > 0) return;
|
||
nav('welfareTask:rewardVideo');
|
||
});
|
||
};
|
||
|
||
// ---------- 资产卡 ----------
|
||
function renderAsset() {
|
||
var slot = el('assetSlot');
|
||
if (!state.logged) {
|
||
slot.innerHTML =
|
||
'<div class="asset-card unlogged"><img class="asset-illustration" src="' + A + 'asset-illustration.png" alt="">' +
|
||
'<div class="asset-unlogged-body"><div class="asset-unlogged-title">登录就能赚金币</div>' +
|
||
'<button class="login-btn" onclick="onLogin()">一键登录</button></div></div>';
|
||
return;
|
||
}
|
||
var wx = '<img src="' + A + 'wechat-pay-check-icon.png" alt="">';
|
||
var arw = '<svg class="asset-arrow" viewBox="0 0 24 24" fill="none"><path d="M9 6L15 12L9 18" stroke="rgba(26,26,26,.4)" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg>';
|
||
slot.innerHTML =
|
||
'<div class="asset-card"><div class="asset-cols">' +
|
||
'<div class="asset-col" onclick="onCoinHistory()"><div class="asset-label">我的金币' + arw + '</div>' +
|
||
'<div class="asset-valrow"><span class="asset-val num" id="coinVal">' + String(state.coin) + '</span></div></div>' +
|
||
'<div class="asset-col" onclick="onCashHistory()"><div class="asset-label">我的现金' + arw + '</div>' +
|
||
'<div class="asset-valrow"><span class="asset-val num" id="cashVal">' + yuan(state.cashCents) + '</span>' +
|
||
'<button class="chip" onclick="event.stopPropagation();onWithdraw()">' + wx + '去提现</button></div></div>' +
|
||
'</div><div class="asset-note">0点自动兑现金(可能存在延迟)</div></div>';
|
||
}
|
||
function refreshAssetNumbers() { var c = el('coinVal'), k = el('cashVal'); if (c) c.textContent = String(state.coin); if (k) k.textContent = yuan(state.cashCents); }
|
||
|
||
// ---------- 签到时间线 ----------
|
||
function effSignin() {
|
||
if (dbg.day > 0) {
|
||
return {
|
||
steps: SIGN_AMT.map(function (c, i) { return { day: i + 1, coin: c }; }),
|
||
today_signed: dbg.signed, today_cycle_day: dbg.day,
|
||
consecutive_days: dbg.day, today_coin: SIGN_AMT[dbg.day - 1],
|
||
};
|
||
}
|
||
return state.signin;
|
||
}
|
||
// 签到视图态(对齐原型 buildCheckin7Steps):5 格滑窗跟随 focus(未签=今天/已签=明天),
|
||
// done=已领✓;current=「今天领」(未签在今天)或「明天领」(已签移到明天);已签的今天节点标签变「今天」。
|
||
// ⚠️不依赖后端 step.status——签到后后端把今天标 claimed、不再有 today 节点,badge 会整个消失(bug)。
|
||
function ckSteps(s, preview) {
|
||
var steps = (s && s.steps && s.steps.length) ? s.steps : SIGN_AMT.map(function (c, i) { return { day: i + 1, coin: c }; });
|
||
var maxDay = steps.length;
|
||
var today = preview ? 0 : Math.min(Math.max((s && s.today_cycle_day) || 1, 1), maxDay);
|
||
var signed = !preview && !!(s && s.today_signed);
|
||
var focus = preview ? 1 : (signed ? Math.min(today + 1, maxDay) : today);
|
||
var start = Math.min(3, Math.max(1, focus - 2));
|
||
var days = [start, start + 1, start + 2, start + 3, maxDay];
|
||
return days.map(function (d) {
|
||
var st = steps[d - 1] || { day: d, coin: 0 };
|
||
var isToday = d === today, isTomorrow = d === today + 1;
|
||
var isDone = signed ? d <= today : d < today;
|
||
var isCurrent = (!signed && isToday) || (signed && isTomorrow);
|
||
return {
|
||
day: d, coin: st.coin, done: isDone, current: isCurrent, isLastDay: d === maxDay,
|
||
badge: isCurrent ? (isTomorrow ? '明天领' : '今天领') : null,
|
||
label: (isToday && signed) ? '今天' : ('第' + d + '天'),
|
||
};
|
||
});
|
||
}
|
||
function stepIconImg(v) {
|
||
var src = (v.isLastDay || v.coin >= 800) ? 'checkin-chest-8888.png' : (v.coin >= 300 ? 'checkin-coins-600.png' : 'checkin-coin-single.png');
|
||
return '<img src="' + A + src + '" alt="">';
|
||
}
|
||
function stepNode(v, gapNext) {
|
||
var cls = 'step' + (v.done ? ' done' : '') + (v.current ? ' current' : '') + (gapNext ? ' gap-next' : '');
|
||
var top = v.badge ? '<span class="step-badge">' + v.badge + '</span>' : '<span class="step-label">' + v.label + '</span>';
|
||
var icon = v.done ? '<span class="step-icon"></span>' : '<span class="step-icon">' + stepIconImg(v) + '</span>';
|
||
return '<div class="' + cls + '">' + top + icon + '<span class="step-amt num">' + v.coin + '</span></div>';
|
||
}
|
||
function renderCheckin() {
|
||
var slot = el('checkinSlot'), s = effSignin(), logged = state.logged;
|
||
var signed = !!(s && s.today_signed);
|
||
var sub = logged ? (s ? '连续签到7天必得2500金币' : '连续签到领金币') : '登录后每日签到,连续7天最高领800金币';
|
||
var ctaText = (logged && signed) ? '去查看' : '去签到';
|
||
var ctaDot = (!signed) ? '<span class="dot"></span>' : '';
|
||
var view = ckSteps(s, !(logged && s));
|
||
var html = view.map(function (v, i) {
|
||
return stepNode(v, view[i + 1] ? (view[i + 1].day - v.day > 1) : false);
|
||
}).join('');
|
||
slot.innerHTML =
|
||
'<div class="checkin-row"><div class="checkin-head"><div class="checkin-copy">' +
|
||
'<div class="checkin-title">新人签到领金币</div><div class="checkin-sub">' + esc(sub) + '</div></div>' +
|
||
'<button class="cta checkin-cta" onclick="onCheckinEntry()">' + ctaText + ctaDot + '</button></div>' +
|
||
'<div class="timeline">' + html + '</div></div>';
|
||
}
|
||
window.onCheckinEntry = function () { if (!state.logged) { requestLogin(); return; } openCheckin(); };
|
||
|
||
// ---------- 任务行 ----------
|
||
function cooldownLeft() { if (!state.ad || !state.ad.cooldown_until) return 0; var u = Date.parse(state.ad.cooldown_until); return isNaN(u) ? 0 : Math.max(0, u - Date.now()); }
|
||
function videoCta() {
|
||
if (!state.logged) return { cls: '', label: '去观看', click: 'onVideo()' };
|
||
if (state.ad && state.ad.remaining <= 0) return { cls: 'gray', label: '已领完', click: 'onVideo()' };
|
||
var left = cooldownLeft();
|
||
if (left > 0) { var s = Math.ceil(left / 1000), mm = Math.floor(s / 60), ss = s % 60; return { cls: 'gray', label: (mm < 10 ? '0' + mm : mm) + ':' + (ss < 10 ? '0' + ss : ss), click: '' }; }
|
||
return { cls: '', label: '去赚取', click: 'onVideo()' };
|
||
}
|
||
function coinTag(t) { return '<span class="task-coin"><img class="ci" src="' + A + 'coin-icon.png" alt="">' + esc(t) + '</span>'; }
|
||
function row(o) {
|
||
var sub = o.subHtml ? '<div class="task-sub">' + o.subHtml + '</div>' : '';
|
||
var coin = o.coin ? coinTag(o.coin) : '';
|
||
var dot = o.dot ? '<span class="dot"></span>' : '';
|
||
return '<div class="task-row" id="' + o.id + '"><div class="task-info"><div class="task-titlerow"><span class="task-title">' + esc(o.title) + '</span>' + coin + '</div>' + sub +
|
||
'</div><button class="cta task-cta ' + (o.cls || '') + '" ' + (o.click ? 'onclick="' + o.click + '"' : '') + '>' + esc(o.cta) + dot + '</button></div>';
|
||
}
|
||
function renderTasks() {
|
||
var logged = state.logged, vs = videoCta(), notifCoin = state.notif ? state.notif.coin : 750;
|
||
el('tasksSlot').innerHTML = [
|
||
row({ id: 'tCoupon', title: '大额优惠券免费领', coin: '最高500/次', subHtml: '全网神券 AI 帮你一键领齐', cta: '去领券', click: 'onCoupon()', dot: !state.couponDone }),
|
||
row({ id: 'tCompare', title: '天天比价赚金币', coin: '最高500/次', subHtml: '同款菜品全网比,自动找底价', cta: '去比价', click: 'onCompare()' }),
|
||
row({ id: 'tVideo', title: '看视频赚海量金币', coin: '最高1000000', subHtml: logged ? '单日最高赚 100 万金币' : '登录后立得海量金币', cta: vs.label, cls: vs.cls, click: vs.click }),
|
||
row({ id: 'tNotif', title: '打开消息提醒', coin: String(notifCoin), subHtml: '开启推送即得金币', cta: '去开启', click: 'onNotif()' }),
|
||
row({ id: 'tReport', title: '上报更低价赚金币', coin: '1000/次', subHtml: '每次审核通过得 1000 金币', cta: '去上报', click: 'onReport()' }),
|
||
row({ id: 'tInvite', title: '邀请好友赚现金', subHtml: '<span class="task-tag">限时大额福利</span>每邀1人必得2元现金', cta: '去邀请', click: 'onInvite()' }),
|
||
].join('');
|
||
}
|
||
setInterval(function () { if (cooldownLeft() > 0 || (state.ad && state.ad.remaining > 0)) { var vs = videoCta(); var b = document.querySelector('#tVideo .task-cta'); if (b) { b.innerHTML = esc(vs.label); b.className = 'cta task-cta ' + vs.cls; b.setAttribute('onclick', vs.click); } } }, 1000);
|
||
|
||
// ---------- 签到弹窗(1:1 对齐原型 #checkinPopup) ----------
|
||
function ckRewardImg(st, isLast) {
|
||
var src = (isLast || st.coin >= 800) ? 'checkin-chest-8888.png' : (st.coin >= 300 ? 'checkin-coins-600.png' : 'checkin-coin-single.png');
|
||
var chest = src.indexOf('chest') >= 0 ? ' class="chest"' : '';
|
||
return '<img' + chest + ' src="' + A + src + '" alt="">';
|
||
}
|
||
function roundTotal(s) {
|
||
if (s && s.steps && s.steps.length) { var t = 0; for (var i = 0; i < Math.min(7, s.steps.length); i++) t += (s.steps[i].coin || 0); return t; }
|
||
return 2500;
|
||
}
|
||
function nextReward(s) {
|
||
// 明天那档的金币(today_cycle_day 的下一档);第 7 天签完无"明天"档,返回 0(文案走特殊分支)。
|
||
var steps = (s && s.steps) || [];
|
||
var today = (s && s.today_cycle_day) || 1;
|
||
return (steps[today] && steps[today].coin) || 0;
|
||
}
|
||
function renderCkLines(view) {
|
||
var c = el('ckLines'); if (!c) return;
|
||
var centers = [10, 30, 50, 70, 90], html = '';
|
||
for (var i = 0; i < view.length - 1; i++) {
|
||
var jump = (view[i + 1].day - view[i].day) > 1;
|
||
var reached = view[i + 1].done || view[i + 1].current; // 连到"已达/当前"节点的线段亮黄
|
||
var lc = (reached && !jump) ? '#FFB800' : '#D9D9D9';
|
||
html += '<span class="ck-seg ' + (jump ? 'dashed' : 'solid') + '" style="left:' + centers[i] + '%;width:' + (centers[i + 1] - centers[i]) + '%;--lc:' + lc + '"></span>';
|
||
}
|
||
c.innerHTML = html;
|
||
}
|
||
function renderCkPopup(s) {
|
||
var view = ckSteps(s, false);
|
||
var maxDay = (s.steps && s.steps.length) || 7;
|
||
var lastDaySigned = s.today_signed && (s.today_cycle_day >= maxDay);
|
||
el('ckBanner').textContent = '连续签到7天,必得' + roundTotal(s) + '金币';
|
||
el('ckTitle').textContent = s.today_signed ? '今日金币已领取' : '签到领取今日金币';
|
||
el('ckSub').innerHTML = lastDaySigned
|
||
? '本轮大额奖励已入账,明日领新一轮大奖'
|
||
: (s.today_signed
|
||
? '已连续签到 <b>' + (s.consecutive_days || 0) + '</b> 天,明天可领 <b>' + nextReward(s) + '</b> 金币'
|
||
: '已连续签到 <b>' + (s.consecutive_days || 0) + '</b> 天,今天可领 <b>' + (s.today_coin || 0) + '</b> 金币');
|
||
el('ckRewards').innerHTML = view.map(function (v) {
|
||
if (v.done) return '<div class="ck-rcard claimed"><div class="ck-ricon">已领取</div><div class="ck-ramt">' + v.coin + '</div></div>';
|
||
return '<div class="ck-rcard' + (v.current ? ' current' : '') + '"><div class="ck-ricon">' + ckRewardImg(v, v.isLastDay) + '</div><div class="ck-ramt">' + v.coin + '</div></div>';
|
||
}).join('');
|
||
el('ckProgress').innerHTML = '<div class="ck-lines" id="ckLines"></div>' + view.map(function (v) {
|
||
var cls = (v.done ? ' done' : '') + (v.current ? ' current' : '');
|
||
return '<div class="ck-node' + cls + '"><span class="ck-dot"></span><span>' + (v.badge || v.label) + '</span></div>';
|
||
}).join('');
|
||
renderCkLines(view);
|
||
var btn = el('ckBtn'), boost = el('ckBoostBtn');
|
||
if (s.today_signed) { btn.style.display = 'none'; boost.style.display = 'flex'; }
|
||
else { btn.style.display = 'flex'; boost.style.display = 'none'; btn.innerHTML = '签到领 <img src="' + A + 'checkin-coin-single.png" alt=""><b>' + (s.today_coin || 0) + '</b>'; }
|
||
}
|
||
window.openCheckin = function () {
|
||
var s = effSignin(); if (!s) { toast('签到信息加载中…'); return; }
|
||
renderCkPopup(s); el('ckMask').classList.add('show');
|
||
};
|
||
window.closeCheckin = function () { el('ckMask').classList.remove('show'); };
|
||
window.doCheckin = function () {
|
||
if (dbg.day > 0) { toast('预览模式不发真金币'); return; }
|
||
var s = state.signin; if (!s || s.today_signed) return;
|
||
SGApi.post('/signin', {}).then(function (r) {
|
||
if (r && r.coin_balance != null) { state.coin = r.coin_balance; refreshAssetNumbers(); }
|
||
toast('签到成功 +' + ((r && r.coin_awarded) || s.today_coin || 0) + ' 金币');
|
||
// 重拉签到态,弹窗刷成已签(显示膨胀 CTA),不关弹窗(对齐原型)
|
||
SGApi.get('/signin/status').then(function (ns) { state.signin = ns; renderCheckin(); if (el('ckMask').classList.contains('show')) renderCkPopup(ns); }).catch(function () {});
|
||
}).catch(function (e) {
|
||
if (String(e).indexOf('409') >= 0) { toast('今天已签到'); loadSignin(); } else { toast('签到失败,请稍后再试'); }
|
||
});
|
||
};
|
||
window.onSigninBoost = function () { closeCheckin(); guard(function () { nav('welfareTask:signinBoost'); }); };
|
||
|
||
// ---------- 调试预览 ----------
|
||
window.dbgStep = function (d) { dbg.day += d; if (dbg.day > 7) dbg.day = 0; if (dbg.day < 0) dbg.day = 7; el('dbgLabel').textContent = dbg.day ? ('预览签到:第' + dbg.day + '天') : '预览签到:关'; renderCheckin(); };
|
||
window.dbgToggleSigned = function () { dbg.signed = !dbg.signed; renderCheckin(); };
|
||
|
||
// ---------- 数据 ----------
|
||
function loadAccount() { return SGApi.get('/wallet/account').then(function (a) { if (!a) return; state.coin = a.coin_balance || 0; state.cashCents = a.cash_balance_cents || 0; refreshAssetNumbers(); }).catch(function () {}); }
|
||
function loadSignin() { return SGApi.get('/signin/status').then(function (s) { state.signin = s; if (dbg.day === 0) renderCheckin(); }).catch(function () {}); }
|
||
function loadTasks() { return SGApi.get('/tasks').then(function (t) { if (t && t.items) for (var i = 0; i < t.items.length; i++) if (t.items[i].task_key === 'enable_notification') { state.notif = t.items[i]; break; } renderTasks(); }).catch(function () {}); }
|
||
function loadAd() { return SGApi.get('/ad/reward-status').then(function (a) { state.ad = a; renderTasks(); }).catch(function () {}); }
|
||
function loadAll() { state.logged = loggedIn(); renderAsset(); renderCheckin(); renderTasks(); if (!state.logged) return; loadAccount(); loadSignin(); loadTasks(); loadAd(); }
|
||
|
||
loadAll();
|
||
setInterval(function () { if (state.logged && !document.hidden) { loadAccount(); loadAd(); } }, 12000);
|
||
if (window.SGBridge && SGBridge.on) {
|
||
SGBridge.on('onResume', function () { var was = state.logged; state.logged = loggedIn(); if (state.logged !== was) loadAll(); else if (state.logged) { loadAccount(); loadSignin(); loadTasks(); loadAd(); } });
|
||
SGBridge.on('onAuthChange', function () { loadAll(); });
|
||
}
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|