继续更新
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
.background-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(180deg, #f0f9f2 0%, #f7fff8 55%, #eef7f1 100%);
|
||||
}
|
||||
|
||||
.floating-blob {
|
||||
position: absolute;
|
||||
width: 420px;
|
||||
height: 420px;
|
||||
border-radius: 55% 45% 60% 40% / 50% 50% 45% 55%;
|
||||
filter: blur(0px);
|
||||
opacity: 0.28;
|
||||
background: radial-gradient(circle at 30% 30%, rgba(129, 199, 132, 0.6), rgba(129, 199, 132, 0));
|
||||
animation: drift 36s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.blob-1 {
|
||||
top: -120px;
|
||||
left: -160px;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.blob-2 {
|
||||
right: -120px;
|
||||
bottom: -160px;
|
||||
animation-delay: 8s;
|
||||
background: radial-gradient(circle at 70% 70%, rgba(76, 175, 80, 0.5), rgba(76, 175, 80, 0));
|
||||
}
|
||||
|
||||
.blob-3 {
|
||||
top: 45%;
|
||||
left: 55%;
|
||||
animation-delay: 16s;
|
||||
background: radial-gradient(circle at 40% 60%, rgba(165, 214, 167, 0.5), rgba(165, 214, 167, 0));
|
||||
}
|
||||
|
||||
@keyframes drift {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
}
|
||||
33% {
|
||||
transform: translate3d(30px, -40px, 0) scale(1.05);
|
||||
}
|
||||
66% {
|
||||
transform: translate3d(-25px, 30px, 0) scale(0.95);
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.floating-blob {
|
||||
width: 260px;
|
||||
height: 260px;
|
||||
opacity: 0.22;
|
||||
}
|
||||
|
||||
.blob-1 {
|
||||
top: -80px;
|
||||
left: -120px;
|
||||
}
|
||||
|
||||
.blob-2 {
|
||||
right: -140px;
|
||||
bottom: -140px;
|
||||
}
|
||||
|
||||
.blob-3 {
|
||||
top: 55%;
|
||||
left: 48%;
|
||||
}
|
||||
}
|
||||
432
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/css/style.css
Normal file
432
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/css/style.css
Normal file
@@ -0,0 +1,432 @@
|
||||
:root {
|
||||
--primary-50: #f0f9f2;
|
||||
--primary-100: #d8f3d8;
|
||||
--primary-200: #bce5c1;
|
||||
--primary-300: #a0d8a8;
|
||||
--primary-400: #7fcf8e;
|
||||
--primary-500: #66bb6a;
|
||||
--primary-600: #5aa75f;
|
||||
--primary-700: #4a8c50;
|
||||
--primary-text: #103a2b;
|
||||
--muted-text: #49705d;
|
||||
--card-bg: rgba(255, 255, 255, 0.85);
|
||||
--border-soft: rgba(102, 187, 106, 0.18);
|
||||
--shadow-soft: 0 12px 40px rgba(48, 94, 60, 0.12);
|
||||
--shadow-hover: 0 18px 50px rgba(48, 94, 60, 0.16);
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
|
||||
background: transparent;
|
||||
color: var(--primary-text);
|
||||
line-height: 1.6;
|
||||
min-height: 100vh;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.page {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
width: min(100%, 960px);
|
||||
padding: 20px 16px 72px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
padding: 20px 18px;
|
||||
border-radius: 18px;
|
||||
background: var(--card-bg);
|
||||
box-shadow: var(--shadow-soft);
|
||||
border: 1px solid var(--border-soft);
|
||||
backdrop-filter: blur(18px);
|
||||
}
|
||||
|
||||
.title-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.label-pill {
|
||||
align-self: flex-start;
|
||||
padding: 4px 12px;
|
||||
font-size: 0.82rem;
|
||||
font-weight: 600;
|
||||
color: var(--primary-700);
|
||||
background: rgba(102, 187, 106, 0.15);
|
||||
border-radius: 999px;
|
||||
letter-spacing: 0.06em;
|
||||
}
|
||||
|
||||
.page-header h1 {
|
||||
font-size: 1.6rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.meta-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.update-time {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 12px;
|
||||
font-size: 0.9rem;
|
||||
color: var(--muted-text);
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(102, 187, 106, 0.22);
|
||||
}
|
||||
|
||||
.refresh-button {
|
||||
align-self: flex-start;
|
||||
padding: 10px 18px;
|
||||
font-size: 0.92rem;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, var(--primary-500), var(--primary-600));
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 10px 24px rgba(102, 187, 106, 0.35);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.refresh-button:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
|
||||
.summary-section {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 14px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
padding: 18px 16px;
|
||||
background: var(--card-bg);
|
||||
border-radius: 16px;
|
||||
border: 1px solid var(--border-soft);
|
||||
box-shadow: var(--shadow-soft);
|
||||
backdrop-filter: blur(12px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.card-label {
|
||||
font-size: 0.92rem;
|
||||
color: var(--muted-text);
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.card-value {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 6px;
|
||||
color: var(--primary-700);
|
||||
}
|
||||
|
||||
.card-value .unit {
|
||||
font-size: 0.88rem;
|
||||
font-weight: 500;
|
||||
color: var(--muted-text);
|
||||
}
|
||||
|
||||
.list-section {
|
||||
margin-top: 28px;
|
||||
padding: 22px 18px 26px;
|
||||
background: var(--card-bg);
|
||||
border-radius: 20px;
|
||||
border: 1px solid var(--border-soft);
|
||||
box-shadow: var(--shadow-soft);
|
||||
backdrop-filter: blur(16px);
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.section-header h2 {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
font-size: 0.88rem;
|
||||
color: var(--muted-text);
|
||||
}
|
||||
|
||||
.movie-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.loading,
|
||||
.error-message {
|
||||
padding: 18px 16px;
|
||||
text-align: center;
|
||||
color: var(--muted-text);
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
border-radius: 14px;
|
||||
border: 1px dashed rgba(102, 187, 106, 0.35);
|
||||
}
|
||||
|
||||
.movie-item {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 14px;
|
||||
padding: 16px;
|
||||
border-radius: 18px;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border: 1px solid rgba(102, 187, 106, 0.18);
|
||||
box-shadow: 0 12px 28px rgba(48, 94, 60, 0.08);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.movie-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-hover);
|
||||
}
|
||||
|
||||
.movie-rank {
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
border-radius: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 700;
|
||||
font-size: 1.1rem;
|
||||
color: #fff;
|
||||
background: var(--primary-500);
|
||||
}
|
||||
|
||||
.movie-rank.top-1 {
|
||||
background: linear-gradient(135deg, #4caf50, #43a047);
|
||||
}
|
||||
|
||||
.movie-rank.top-2 {
|
||||
background: linear-gradient(135deg, #66bb6a, #5aa75f);
|
||||
}
|
||||
|
||||
.movie-rank.top-3 {
|
||||
background: linear-gradient(135deg, #81c784, #66bb6a);
|
||||
}
|
||||
|
||||
.movie-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.movie-heading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.movie-title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
color: var(--primary-text);
|
||||
}
|
||||
|
||||
.release-info {
|
||||
font-size: 0.9rem;
|
||||
color: var(--muted-text);
|
||||
}
|
||||
|
||||
.movie-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px 14px;
|
||||
}
|
||||
|
||||
.stat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.83rem;
|
||||
color: var(--muted-text);
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
color: var(--primary-700);
|
||||
}
|
||||
|
||||
.progress-metrics {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.progress-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.progress-label {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.8rem;
|
||||
color: var(--muted-text);
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
border-radius: 6px;
|
||||
background: rgba(102, 187, 106, 0.16);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-bar span {
|
||||
display: block;
|
||||
height: 100%;
|
||||
border-radius: inherit;
|
||||
background: linear-gradient(135deg, rgba(102, 187, 106, 0.9), rgba(76, 175, 80, 0.85));
|
||||
width: 0;
|
||||
transition: width 0.5s ease;
|
||||
}
|
||||
|
||||
/* Tablet */
|
||||
@media (min-width: 600px) {
|
||||
.page {
|
||||
padding: 28px 20px 84px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.title-block h1 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.meta-block {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.summary-section {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.movie-item {
|
||||
grid-template-columns: 80px 1fr;
|
||||
padding: 18px 20px;
|
||||
}
|
||||
|
||||
.movie-rank {
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.movie-heading {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.release-info {
|
||||
font-size: 0.88rem;
|
||||
}
|
||||
|
||||
.movie-stats {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.progress-metrics {
|
||||
flex-direction: row;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.progress-group {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktop */
|
||||
@media (min-width: 1024px) {
|
||||
.page {
|
||||
padding: 36px 24px 96px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
padding: 26px 30px;
|
||||
}
|
||||
|
||||
.page-header h1 {
|
||||
font-size: 2.1rem;
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
padding: 20px 22px;
|
||||
}
|
||||
|
||||
.card-value {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.list-section {
|
||||
padding: 28px 30px 34px;
|
||||
}
|
||||
|
||||
.movie-item {
|
||||
grid-template-columns: 96px 1fr;
|
||||
padding: 22px 26px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.movie-title {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.movie-stats {
|
||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.progress-metrics {
|
||||
gap: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
67
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/index.html
Normal file
67
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/index.html
Normal file
@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>猫眼电影实时票房</title>
|
||||
<link rel="stylesheet" href="./css/background.css">
|
||||
<link rel="stylesheet" href="./css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="background-container">
|
||||
<div class="floating-blob blob-1"></div>
|
||||
<div class="floating-blob blob-2"></div>
|
||||
<div class="floating-blob blob-3"></div>
|
||||
</div>
|
||||
|
||||
<div class="page">
|
||||
<header class="page-header">
|
||||
<div class="title-block">
|
||||
<span class="label-pill">实时票房</span>
|
||||
<h1>猫眼电影实时票房</h1>
|
||||
</div>
|
||||
<div class="meta-block">
|
||||
<span id="updateTime" class="update-time">正在获取最新更新...</span>
|
||||
<button type="button" id="refreshButton" class="refresh-button">手动刷新</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="summary-section" id="summarySection">
|
||||
<div class="summary-card">
|
||||
<p class="card-label" id="summaryTitle">实时大盘</p>
|
||||
<p class="card-value">
|
||||
<span id="totalBoxOffice">--</span>
|
||||
<span class="unit" id="totalBoxOfficeUnit"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="summary-card">
|
||||
<p class="card-label">综合票房</p>
|
||||
<p class="card-value">
|
||||
<span id="combinedBoxOffice">--</span>
|
||||
<span class="unit" id="combinedBoxOfficeUnit"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="summary-card">
|
||||
<p class="card-label">排片场次</p>
|
||||
<p class="card-value" id="showCount">--</p>
|
||||
</div>
|
||||
<div class="summary-card">
|
||||
<p class="card-label">观影人次</p>
|
||||
<p class="card-value" id="viewCount">--</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="list-section">
|
||||
<div class="section-header">
|
||||
<h2>影片实时表现</h2>
|
||||
<span class="section-subtitle">数据每 5 秒同步一次</span>
|
||||
</div>
|
||||
<div id="movieList" class="movie-list">
|
||||
<div class="loading">正在加载实时票房...</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script src="./js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
297
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/js/main.js
Normal file
297
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/js/main.js
Normal file
@@ -0,0 +1,297 @@
|
||||
const API_ENDPOINTS = [
|
||||
"https://60s.api.shumengya.top/v2/maoyan/realtime/movie"
|
||||
];
|
||||
|
||||
const FALLBACK_ENDPOINT = "./返回接口.json";
|
||||
const REFRESH_INTERVAL = 5000;
|
||||
const MAX_MOVIES_TO_RENDER = 40;
|
||||
|
||||
const updateTimeEl = document.getElementById("updateTime");
|
||||
const refreshButton = document.getElementById("refreshButton");
|
||||
const summaryTitleEl = document.getElementById("summaryTitle");
|
||||
const totalBoxOfficeEl = document.getElementById("totalBoxOffice");
|
||||
const totalBoxOfficeUnitEl = document.getElementById("totalBoxOfficeUnit");
|
||||
const combinedBoxOfficeEl = document.getElementById("combinedBoxOffice");
|
||||
const combinedBoxOfficeUnitEl = document.getElementById("combinedBoxOfficeUnit");
|
||||
const showCountEl = document.getElementById("showCount");
|
||||
const viewCountEl = document.getElementById("viewCount");
|
||||
const movieListEl = document.getElementById("movieList");
|
||||
|
||||
let autoRefreshTimer = null;
|
||||
let isLoading = false;
|
||||
|
||||
function escapeHtml(value) {
|
||||
if (value === undefined || value === null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return String(value)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
function safeText(value) {
|
||||
if (value === undefined || value === null || value === "") {
|
||||
return "--";
|
||||
}
|
||||
return escapeHtml(value);
|
||||
}
|
||||
|
||||
function parseRate(rateText) {
|
||||
if (!rateText || typeof rateText !== "string") {
|
||||
return { text: "--", ratio: 0 };
|
||||
}
|
||||
|
||||
const trimmed = rateText.trim();
|
||||
const numeric = parseFloat(trimmed.replace(/[^0-9.]/g, ""));
|
||||
let ratio = Number.isFinite(numeric) ? Math.max(0, Math.min(numeric, 100)) : 0;
|
||||
|
||||
if (trimmed.startsWith("<")) {
|
||||
ratio = Math.max(3, ratio);
|
||||
}
|
||||
|
||||
return { text: escapeHtml(trimmed), ratio };
|
||||
}
|
||||
|
||||
function formatUpdateTime(data) {
|
||||
if (data && typeof data.updated === "string" && data.updated.trim().length > 0) {
|
||||
return data.updated.trim();
|
||||
}
|
||||
|
||||
if (data && typeof data.updated_at === "number" && !Number.isNaN(data.updated_at)) {
|
||||
return new Date(data.updated_at).toLocaleString("zh-CN", {
|
||||
hour12: false
|
||||
});
|
||||
}
|
||||
|
||||
return new Date().toLocaleString("zh-CN", { hour12: false });
|
||||
}
|
||||
|
||||
function renderSummary(data) {
|
||||
summaryTitleEl.textContent = data?.title ? data.title : "实时大盘";
|
||||
totalBoxOfficeEl.textContent = data?.split_box_office ? data.split_box_office : "--";
|
||||
totalBoxOfficeUnitEl.textContent = data?.split_box_office_unit ? data.split_box_office_unit : "";
|
||||
combinedBoxOfficeEl.textContent = data?.box_office ? data.box_office : "--";
|
||||
combinedBoxOfficeUnitEl.textContent = data?.box_office_unit ? data.box_office_unit : "";
|
||||
showCountEl.textContent = data?.show_count_desc ? data.show_count_desc : "--";
|
||||
viewCountEl.textContent = data?.view_count_desc ? data.view_count_desc : "--";
|
||||
}
|
||||
|
||||
function createStat(label, value) {
|
||||
return `
|
||||
<div class="stat">
|
||||
<span class="stat-label">${label}</span>
|
||||
<span class="stat-value">${safeText(value)}</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function createMovieItem(movie, index) {
|
||||
const item = document.createElement("article");
|
||||
item.className = "movie-item";
|
||||
|
||||
const topClass = index < 3 ? ` top-${index + 1}` : "";
|
||||
const name = safeText(movie?.movie_name || "未命名影片");
|
||||
const releaseInfo = movie?.release_info ? `<div class="release-info">${safeText(movie.release_info)}</div>` : "";
|
||||
|
||||
const boxOfficeDesc = movie?.box_office_desc || (movie?.box_office ? `${movie.box_office}${movie.box_office_unit || ""}` : "--");
|
||||
const splitBoxOfficeDesc = movie?.split_box_office_desc || (movie?.split_box_office ? `${movie.split_box_office}${movie.split_box_office_unit || ""}` : "--");
|
||||
const totalBoxOfficeDesc = movie?.sum_box_desc ?? "--";
|
||||
const totalSplitBoxOfficeDesc = movie?.sum_split_box_desc ?? "--";
|
||||
|
||||
let showCountText = "--";
|
||||
if (movie?.show_count !== undefined && movie.show_count !== null && movie.show_count !== "") {
|
||||
const numericShowCount = Number(movie.show_count);
|
||||
showCountText = Number.isFinite(numericShowCount)
|
||||
? `${numericShowCount.toLocaleString("zh-CN")} 场`
|
||||
: movie.show_count;
|
||||
}
|
||||
|
||||
const avgShowView = movie?.avg_show_view ?? "--";
|
||||
const avgSeatView = movie?.avg_seat_view ?? "--";
|
||||
|
||||
const boxRate = parseRate(movie?.box_office_rate);
|
||||
const showRate = parseRate(movie?.show_count_rate);
|
||||
|
||||
item.innerHTML = `
|
||||
<div class="movie-rank${topClass}">${index + 1}</div>
|
||||
<div class="movie-body">
|
||||
<div class="movie-heading">
|
||||
<div>
|
||||
<div class="movie-title">${name}</div>
|
||||
${releaseInfo}
|
||||
</div>
|
||||
</div>
|
||||
<div class="movie-stats">
|
||||
${createStat("单日综合票房", boxOfficeDesc)}
|
||||
${createStat("单日分账票房", splitBoxOfficeDesc)}
|
||||
${createStat("累计综合票房", totalBoxOfficeDesc)}
|
||||
${createStat("累计分账票房", totalSplitBoxOfficeDesc)}
|
||||
${createStat("排片场次", showCountText)}
|
||||
${createStat("场均人次", avgShowView)}
|
||||
${createStat("上座率", avgSeatView)}
|
||||
</div>
|
||||
<div class="progress-metrics">
|
||||
<div class="progress-group">
|
||||
<div class="progress-label">
|
||||
<span>综合票房占比</span>
|
||||
<span>${boxRate.text}</span>
|
||||
</div>
|
||||
<div class="progress-bar"><span></span></div>
|
||||
</div>
|
||||
<div class="progress-group">
|
||||
<div class="progress-label">
|
||||
<span>排片占比</span>
|
||||
<span>${showRate.text}</span>
|
||||
</div>
|
||||
<div class="progress-bar"><span></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const progressBars = item.querySelectorAll(".progress-bar span");
|
||||
if (progressBars[0]) {
|
||||
progressBars[0].style.width = `${boxRate.ratio}%`;
|
||||
}
|
||||
if (progressBars[1]) {
|
||||
progressBars[1].style.width = `${showRate.ratio}%`;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
function renderMovieList(list) {
|
||||
movieListEl.innerHTML = "";
|
||||
|
||||
if (!Array.isArray(list) || list.length === 0) {
|
||||
const empty = document.createElement("div");
|
||||
empty.className = "error-message";
|
||||
empty.textContent = "暂时没有可展示的实时票房数据";
|
||||
movieListEl.appendChild(empty);
|
||||
return;
|
||||
}
|
||||
|
||||
const sliced = list.slice(0, MAX_MOVIES_TO_RENDER);
|
||||
sliced.forEach((movie, index) => {
|
||||
movieListEl.appendChild(createMovieItem(movie, index));
|
||||
});
|
||||
}
|
||||
|
||||
async function requestJson(url) {
|
||||
const response = await fetch(url, {
|
||||
cache: "no-store"
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`请求失败: ${response.status}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async function retrieveData() {
|
||||
for (const endpoint of API_ENDPOINTS) {
|
||||
try {
|
||||
const result = await requestJson(endpoint);
|
||||
if (result?.code === 200 && result?.data) {
|
||||
return result.data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("主接口请求失败", error);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const fallbackResult = await requestJson(FALLBACK_ENDPOINT);
|
||||
if (fallbackResult?.data) {
|
||||
return fallbackResult.data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("本地示例数据读取失败", error);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function loadData(isManual = false) {
|
||||
if (isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading = true;
|
||||
|
||||
if (isManual) {
|
||||
refreshButton.disabled = true;
|
||||
refreshButton.textContent = "刷新中...";
|
||||
}
|
||||
|
||||
if (!movieListEl.children.length) {
|
||||
movieListEl.innerHTML = '<div class="loading">正在加载实时票房...</div>';
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await retrieveData();
|
||||
if (!data) {
|
||||
throw new Error("无法获取数据");
|
||||
}
|
||||
|
||||
renderSummary(data);
|
||||
renderMovieList(Array.isArray(data.list) ? data.list : []);
|
||||
updateTimeEl.textContent = `最近更新 ${formatUpdateTime(data)}`;
|
||||
} catch (error) {
|
||||
console.error("加载数据失败", error);
|
||||
movieListEl.innerHTML = "";
|
||||
const err = document.createElement("div");
|
||||
err.className = "error-message";
|
||||
err.textContent = "数据获取暂时遇到问题,系统会稍后自动重试";
|
||||
movieListEl.appendChild(err);
|
||||
updateTimeEl.textContent = "最近更新 --";
|
||||
renderSummary(null);
|
||||
} finally {
|
||||
if (isManual) {
|
||||
refreshButton.disabled = false;
|
||||
refreshButton.textContent = "手动刷新";
|
||||
}
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
function startAutoRefresh() {
|
||||
if (autoRefreshTimer) {
|
||||
clearInterval(autoRefreshTimer);
|
||||
}
|
||||
autoRefreshTimer = setInterval(() => {
|
||||
loadData(false);
|
||||
}, REFRESH_INTERVAL);
|
||||
}
|
||||
|
||||
refreshButton.addEventListener("click", () => {
|
||||
loadData(true);
|
||||
});
|
||||
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
if (document.hidden) {
|
||||
if (autoRefreshTimer) {
|
||||
clearInterval(autoRefreshTimer);
|
||||
autoRefreshTimer = null;
|
||||
}
|
||||
} else {
|
||||
startAutoRefresh();
|
||||
loadData(false);
|
||||
}
|
||||
});
|
||||
|
||||
function init() {
|
||||
loadData(false);
|
||||
startAutoRefresh();
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
1861
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/返回接口.json
Normal file
1861
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/返回接口.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user