- 349→ 349→ {/* ===== 周挑战卡片(fuchsia 主题) ===== */}
- 350→ 350→
- 358→ 358→ {/* 头部:标题 + weekKey + 倒计时 */}
- 359→ 359→
- 360→ 360→
- 361→ 361→
- 362→ 362→
- 363→ 363→ 周挑战 · WEEKLY
- 364→ 364→
- 365→ 365→
- 366→ 366→
- 367→ 367→
- 368→ 368→ {weeklyChallenge.weekKey}
- 369→ 369→
- 370→ 370→
- 371→ 371→ {weekCountdown}
- 372→ 372→
- 373→ 373→
- 374→ 374→
- 375→ 375→ {/* 难度 + 类型 标签 */}
- 376→ 376→
- 377→ 377→
- 381→ 381→ {wDiffMeta.icon}
- 382→ 382→ {wDiffMeta.label}
- 383→ 383→
- 384→ 384→
- 385→ 385→ {wTypeMeta.icon} {wTypeMeta.label}
- 386→ 386→
- 387→ 387→ {wCompleted && (
- 388→ 388→
- 389→ 389→ 已完成
- 390→ 390→
- 391→ 391→ )}
- 392→ 392→
- 393→ 393→
- 394→ 394→ {/* 标题 */}
- 395→ 395→
- 399→ 399→ {weeklyChallenge.title}
- 400→ 400→
- 401→ 401→
- 402→ 402→ {weeklyChallenge.desc}
- 403→ 403→
- 404→ 404→
- 405→ 405→ {/* 进度条 */}
- 406→ 406→
- 407→ 407→
- 408→ 408→ 进度
- 409→ 409→
- 410→ 410→ {Math.min(weeklyProgress.progress, weeklyChallenge.goal)} / {weeklyChallenge.goal} {wTypeMeta.unit}
- 411→ 411→
- 412→ 412→
- 413→ 413→
- 420→ 420→
- 421→ 421→
- 422→ 422→ {/* 奖励 + 领取按钮 */}
- 423→ 423→
- 424→ 424→
- 425→ 425→ 奖励:
- 426→ 426→ {weeklyChallenge.rewardInsight > 0 && (
- 427→ 427→
- 428→ 428→ +{formatNum(weeklyChallenge.rewardInsight)}洞见
- 429→ 429→
- 430→ 430→ )}
- 431→ 431→
- 432→ 432→ +{weeklyChallenge.rewardContact.toFixed(1)}接触
- 433→ 433→
- 434→ 434→
- 435→ 435→
- 457→ 457→
- 458→ 458→
- 459→ 459→ {wCompleted && weeklyProgress.durationSec > 0 && (
- 460→ 460→
- 461→ 461→ 完成用时 {Math.floor(weeklyProgress.durationSec / 60)}分{weeklyProgress.durationSec % 60}秒
- 462→ 462→
- 463→ 463→ )}
- 464→ 464→
- 465→ 465→
- 466→ 466→ {/* ===== 信标链卡片(amber→rose 渐变) ===== */}
- 467→ 467→
- 474→ 474→ {/* 头部:标题 + 当前连续天数 */}
- 475→ 475→
- 476→ 476→
- 477→ 477→
- 478→ 478→
- 479→ 479→ 信标链 · CHAIN
- 480→ 480→
- 481→ 481→
- 482→ 482→
- 483→ 483→
- 484→ 484→ 连续
- 485→ 485→
- 486→ 486→ {chainState.currentStreak}
- 487→ 487→
- 488→ 488→ 天
- 489→ 489→
- 490→ 490→
- 491→ 491→
- 492→ 492→ {/* 今日完成状态 */}
- 493→ 493→
- 494→ 494→
- 495→ 495→ {completedToday
- 496→ 496→ ? "今日已贡献"
- 497→ 497→ : "今日尚未完成日挑战"}
- 498→ 498→
- 499→ 499→
- 506→ 506→ {completedToday ? "✓ 已记录" : "○ 待完成"}
- 507→ 507→
- 508→ 508→
- 509→ 509→
- 510→ 510→ {/* 4 个里程碑节点横向排列 */}
- 511→ 511→
- 512→ 512→ {/* 节点之间的连线(背景灰) */}
- 513→ 513→
- 514→ 514→ {/* 已达成部分高亮(基于 prev→next 插值) */}
- 515→ 515→ {(() => {
- 516→ 516→ // 节点圆心水平位置(百分比)
- 517→ 517→ const MILESTONE_POS: Record
= {
- 518→ 518→ 0: 12.5,
- 519→ 519→ 3: 12.5,
- 520→ 520→ 7: 37.5,
- 521→ 521→ 14: 62.5,
- 522→ 522→ 30: 87.5,
- 523→ 523→ };
- 524→ 524→ const prevPos =
- 525→ 525→ MILESTONE_POS[chainProgress.prev] ?? 12.5;
- 526→ 526→ const nextPos =
- 527→ 527→ chainProgress.next !== null
- 528→ 528→ ? MILESTONE_POS[chainProgress.next] ?? 87.5
- 529→ 529→ : 87.5;
- 530→ 530→ const pct = chainProgress.progressPct / 100;
- 531→ 531→ const activeEndPos = prevPos + (nextPos - prevPos) * pct;
- 532→ 532→ const widthPct = Math.max(0, activeEndPos - 12.5);
- 533→ 533→ if (widthPct <= 0) return null;
- 534→ 534→ return (
- 535→ 535→
- 545→ 545→ );
- 546→ 546→ })()}
- 547→ 547→
- 548→ 548→ {BEACON_CHAIN_MILESTONES.map((m) => {
- 549→ 549→ const reward = BEACON_CHAIN_REWARDS.find((r) => r.milestone === m);
- 550→ 550→ const claimed = chainState.milestonesClaimed.includes(m);
- 551→ 551→ const reachable =
- 552→ 552→ chainState.currentStreak >= m && !claimed;
- 553→ 553→ const inProgress = chainState.currentStreak > 0 && nextMilestone === m;
- 554→ 554→ // 节点配色
- 555→ 555→ let nodeBg = "rgba(255,255,255,0.05)";
- 556→ 556→ let nodeBorder = "rgba(255,255,255,0.15)";
- 557→ 557→ let textColor = "rgba(255,255,255,0.4)";
- 558→ 558→ if (claimed) {
- 559→ 559→ nodeBg = "rgba(52,211,153,0.25)";
- 560→ 560→ nodeBorder = "#34d399";
- 561→ 561→ textColor = "#34d399";
- 562→ 562→ } else if (reachable) {
- 563→ 563→ nodeBg = "rgba(251,113,133,0.20)";
- 564→ 564→ nodeBorder = "#fb7185";
- 565→ 565→ textColor = "#fb7185";
- 566→ 566→ } else if (inProgress) {
- 567→ 567→ nodeBg = "rgba(251,191,36,0.20)";
- 568→ 568→ nodeBorder = "#fbbf24";
- 569→ 569→ textColor = "#fbbf24";
- 570→ 570→ }
- 571→ 571→
- 572→ 572→ return (
- 573→ 573→
- 577→ 577→
- 587→ 587→ {claimed ? (
- 588→ 588→
- 589→ 589→ ) : (
- 590→ 590→ m
- 591→ 591→ )}
- 592→ 592→
- 593→ 593→
- 597→ 597→ {reward?.label}
- 598→ 598→
- 599→ 599→ {claimed ? (
- 600→ 600→
- 601→ 601→ 已领
- 602→ 602→
- 603→ 603→ ) : reachable ? (
- 604→ 604→
- 616→ 616→ ) : (
- 617→ 617→
- 618→ 618→ +{reward?.rewardInsight}洞
- 619→ 619→
- 620→ 620→ )}
- 621→ 621→
- 622→ 622→ );
- 623→ 623→ })}
- 624→ 624→
- 625→ 625→
- 626→ 626→ {/* 进度条 */}
- 627→ 627→
- 628→ 628→
- 629→ 629→
- 630→ 630→ {chainProgress.next === null
- 631→ 631→ ? "已通关全部里程碑"
- 632→ 632→ : `下一目标:${chainProgress.next} 天`}
- 633→ 633→
- 634→ 634→
- 635→ 635→ {chainProgress.current}
- 636→ 636→ {chainProgress.next !== null && ` / ${chainProgress.next}`} 天
- 637→ 637→
- 638→ 638→
- 639→ 639→
- 646→ 646→
- 647→ 647→
- 648→ 648→ {/* 底部统计 */}
- 649→ 649→
- 650→ 650→
- 651→ 651→ 最长
- 652→ 652→
- 653→ 653→ {chainState.longestStreak}天
- 654→ 654→
- 655→ 655→
- 656→ 656→
- 657→ 657→ 累计
- 658→ 658→
- 659→ 659→ {chainState.totalCompletions}次
- 660→ 660→
- 661→ 661→
- 662→ 662→
- 663→ 663→ 续命
- 664→ 664→ {chainState.graceUsed >= 1 ? (
- 665→ 665→ 已用
- 666→ 666→ ) : (
- 667→ 667→ 可用
- 668→ 668→ )}
- 669→ 669→
- 670→ 670→
- 671→ 671→