feat(tasks): 切换页加「获取最新任务中」刷新状态 + 旋转动画,1.2s 后切换
- TaskDisplay.jsx:displayedPage 与 page 分离,页切换先置 switching 展示加载遮罩,SWITCH_MS(1200ms) 后再切到新页;task_refresh 亦播放一次。 - task-display.css:tasks-screen position:relative;+ tasks-switch-overlay / tasks-spinner(旋转) / tasks-switch-text。 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -43,6 +43,9 @@ export default function TaskDisplay() {
|
||||
const pageSize = cols * ROWS; // 2×2=4 或 2×3=6
|
||||
const pageCount = Math.max(1, Math.ceil(tasks.length / pageSize));
|
||||
const [countdown, setCountdown] = useState(Math.round(ROTATE_MS / 1000));
|
||||
// 切换:page 为目标页,displayedPage 为当前展示页;切换时先显示「获取最新任务中」动画,1-2 秒后再切
|
||||
const [displayedPage, setDisplayedPage] = useState(0);
|
||||
const [switching, setSwitching] = useState(false);
|
||||
useEffect(() => {
|
||||
if (pageCount <= 1) { setPage(0); return; }
|
||||
const t = setInterval(() => setPage((p) => (p + 1) % pageCount), ROTATE_MS);
|
||||
@@ -56,13 +59,30 @@ export default function TaskDisplay() {
|
||||
return () => clearInterval(t);
|
||||
}, []);
|
||||
|
||||
// 页切换 → 显示加载动画,SWITCH_MS 后再切到新页
|
||||
const SWITCH_MS = 1200;
|
||||
useEffect(() => {
|
||||
if (page === displayedPage) return;
|
||||
setSwitching(true);
|
||||
const t = setTimeout(() => { setDisplayedPage(page); setSwitching(false); }, SWITCH_MS);
|
||||
return () => clearTimeout(t);
|
||||
}, [page, displayedPage]);
|
||||
|
||||
// 手动/任务刷新 → 同样播放一次「获取最新任务中」
|
||||
useEffect(() => {
|
||||
if (refreshTick === 0) return;
|
||||
setSwitching(true);
|
||||
const t = setTimeout(() => setSwitching(false), SWITCH_MS);
|
||||
return () => clearTimeout(t);
|
||||
}, [refreshTick]);
|
||||
|
||||
const visible = useMemo(() => {
|
||||
if (tasks.length === 0) return [];
|
||||
const start = page * pageSize;
|
||||
const start = displayedPage * pageSize;
|
||||
// 不足一页时按行补位(循环取),保证 2 行填满
|
||||
const items = tasks.slice(start, start + pageSize);
|
||||
return items.length ? items : Array.from({ length: pageSize }, (_, i) => tasks[i % tasks.length]);
|
||||
}, [tasks, page, pageSize]);
|
||||
}, [tasks, displayedPage, pageSize]);
|
||||
|
||||
return (
|
||||
<div className="tasks-screen">
|
||||
@@ -76,7 +96,7 @@ export default function TaskDisplay() {
|
||||
<span className="tasks-info-sep">·</span>
|
||||
<span className="tasks-info">翻页 <b>{pageCount > 1 ? `${countdown}s` : '—'}</b></span>
|
||||
<span className="tasks-info-sep">·</span>
|
||||
<span className="tasks-info">页码 <b>{pageCount > 1 ? `${page + 1}/${pageCount}` : '1/1'}</b></span>
|
||||
<span className="tasks-info">页码 <b>{pageCount > 1 ? `${displayedPage + 1}/${pageCount}` : '1/1'}</b></span>
|
||||
<span className="tasks-info-sep">·</span>
|
||||
<span className="tasks-info hint">接单:抢单·竞标·指派·推荐</span>
|
||||
</div>
|
||||
@@ -99,10 +119,17 @@ export default function TaskDisplay() {
|
||||
{pageCount > 1 && (
|
||||
<div className="tasks-dots">
|
||||
{Array.from({ length: pageCount }).map((_, i) => (
|
||||
<span key={i} className={i === page ? 'tasks-dot on' : 'tasks-dot'} />
|
||||
<span key={i} className={i === displayedPage ? 'tasks-dot on' : 'tasks-dot'} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{/* 切换/刷新加载遮罩 */}
|
||||
{switching && (
|
||||
<div className="tasks-switch-overlay">
|
||||
<span className="tasks-spinner" />
|
||||
<span className="tasks-switch-text">获取最新任务中…</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: relative; /* 供切换加载遮罩定位于此 */
|
||||
background: radial-gradient(ellipse at 20% 0%, rgba(79, 135, 255, 0.08), transparent 55%),
|
||||
radial-gradient(ellipse at 80% 100%, rgba(23, 178, 106, 0.06), transparent 55%);
|
||||
}
|
||||
@@ -115,3 +116,35 @@
|
||||
.task-dots { display: flex; justify-content: center; gap: 8px; padding-bottom: 6px; }
|
||||
.task-dot { width: 8px; height: 8px; border-radius: 50%; background: rgba(29, 44, 68, 0.15); transition: all 0.25s; }
|
||||
.task-dot.on { background: var(--bd-blue, #2f6bff); width: 20px; border-radius: 999px; }
|
||||
|
||||
/* ---- 切换/刷新加载遮罩:文字(获取最新任务中) + 旋转动画 ---- */
|
||||
.tasks-switch-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 14px;
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
backdrop-filter: blur(4px);
|
||||
-webkit-backdrop-filter: blur(4px);
|
||||
}
|
||||
.tasks-spinner {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 50%;
|
||||
border: 4px solid rgba(47, 107, 255, 0.18);
|
||||
border-top-color: var(--bd-blue, #2f6bff);
|
||||
animation: tasks-spin 0.8s linear infinite;
|
||||
}
|
||||
.tasks-switch-text {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--bd-blue, #2f6bff);
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
@keyframes tasks-spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user