fix(ui): 自动刷新时静默更新卡片,不再重播进入动画导致闪烁 - renderAccounts/renderPlatforms 增加 animate 参数 - refresh 自动轮询传 false(无动画),首次渲染与用户操作保留 stagger 动画

This commit is contained in:
2026-08-05 07:41:23 +08:00
parent 86ef5aa412
commit fc52caddfd
+12 -8
View File
@@ -13,6 +13,7 @@
let filterPlatform = 0;
const checkingIds = new Set();
let historyCache = {};
let hasRendered = false; // 首次渲染保留进入动画,自动刷新静默更新
const accountWindows = {}; // {accountId: 'all'|'1h'|'1d'|'1w'|'1mo'|'1yr'}
const windowCache = {}; // {'aid:win': [...]}
@@ -149,8 +150,9 @@
platforms = plat;
historyCache = hist || {};
providersList = provs || [];
renderAccounts();
if (!document.getElementById("view-platforms").classList.contains("hidden")) renderPlatforms();
renderAccounts(!hasRendered);
if (!document.getElementById("view-platforms").classList.contains("hidden")) renderPlatforms(!hasRendered);
hasRendered = true;
const d = new Date();
document.getElementById("refresh-time").textContent =
d.toLocaleTimeString("zh-CN", { hour12: false });
@@ -174,7 +176,7 @@
return { cls: "pending", text: "待检查" };
}
function accountCard(a, idx) {
function accountCard(a, idx, animate = true) {
const st = statusInfo(a);
const plat = platforms.find((p) => p.id === a.platform_id) || {};
const b = brandStyle(plat.icon || "");
@@ -188,6 +190,7 @@
st.cls === "disabled" ? "disabled" : "",
st.cls === "pending" ? "pending" : "",
].join(" ").trim();
const animStyle = animate ? `animation-delay:${Math.min(idx, 12) * 40}ms` : "animation:none";
const win = accountWindows[a.id] || "all";
let hist;
if (win === "all") {
@@ -203,7 +206,7 @@
? `<button class="btn sm check-btn loading" disabled><span class="spinner"></span>检查中</button>`
: `<button class="btn sm check-btn" data-act="check" data-id="${a.id}" ${!a.enabled ? "disabled title=启用后可用" : ""}>${ICONS.refresh}立即检查</button>`;
return `
<div class="${cardCls}" style="animation-delay:${Math.min(idx, 12) * 40}ms">
<div class="${cardCls}" style="${animStyle}">
<div class="card-head">
<div class="badge" style="background:${b.color}">${escapeHtml(b.abbr)}</div>
<div class="card-title">
@@ -290,7 +293,7 @@
return `<svg class="sparkline" viewBox="0 0 ${W} ${H}" preserveAspectRatio="none">${thLine}<polyline points="${pts.join(" ")}" fill="none" stroke="${lineColor}" stroke-width="1.5" stroke-linejoin="round" stroke-linecap="round" vector-effect="non-scaling-stroke"/></svg>`;
}
function renderAccounts() {
function renderAccounts(animate = true) {
const grid = document.getElementById("account-grid");
const stats = { total: accounts.length, ok: 0, below: 0, error: 0, disabled: 0, pending: 0 };
accounts.forEach((a) => {
@@ -326,7 +329,7 @@
});
list = [...list].sort((x, y) => STATUS_ORDER[statusInfo(x).cls] - STATUS_ORDER[statusInfo(y).cls]);
grid.innerHTML = list.map(accountCard).join("");
grid.innerHTML = list.map((a, i) => accountCard(a, i, animate)).join("");
const hint = document.getElementById("empty-hint");
if (accounts.length > 0) {
hint.classList.add("hidden");
@@ -343,7 +346,7 @@
/* ---------- 渲染:平台 ---------- */
function renderPlatforms() {
function renderPlatforms(animate = true) {
const list = document.getElementById("platform-list");
if (platforms.length === 0) {
list.innerHTML = `<div class="empty-hint">暂无平台(代码内置平台会在启动时自动同步)。</div>`;
@@ -352,8 +355,9 @@
list.innerHTML = platforms.map((p, i) => {
const b = brandStyle(p.icon || "");
const prov = providersList.find((x) => x.id === p.provider_id);
const animStyle = animate ? `animation-delay:${Math.min(i, 10) * 35}ms` : "animation:none";
return `
<div class="platform-row ${p.enabled ? "" : "platform-off"}" style="animation-delay:${Math.min(i, 10) * 35}ms">
<div class="platform-row ${p.enabled ? "" : "platform-off"}" style="${animStyle}">
<div class="badge" style="background:${b.color}">${escapeHtml(b.abbr)}</div>
<div class="platform-info">
<div class="platform-name">${escapeHtml(p.name)}