feat(core): 列表数据在途显示骨架屏(加载态),不再先显示空状态

渐进渲染后,列表在接口返回前会短暂显示「0 SKU / 显示 0」的空状态,易被误读为「没数据」。
新增 SkeletonGrid/SkeletonRows(components/loading),区分「加载中(请求在途且无数据)」与
「加载完确实为空」:

- 全局态页(商品库/视频项目/工作台最近项目):App 传 loading={!dataLoaded},未加载完显示骨架。
- 自取页(资产库/商品详情AI素材/图片生成任务/账单流水):各自 loading 标志,首次拉取时显示骨架/加载行。
- 团队成员有 owner 兜底行(非空)不改。

闸:9 页全绿、功能正常;实测 /products 加载期显示骨架→数据到后渲染真实卡片。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
zyc
2026-06-17 21:37:07 +08:00
co-authored by Claude Opus 4.8
parent 6e73fb53dd
commit 7c6d4477da
9 changed files with 228 additions and 78 deletions
+7 -3
View File
@@ -5,6 +5,7 @@ import type { Page } from "./route-config";
import { ConfirmModal, EmptyPanel } from "../components/overlays";
import { ProductCreateDrawer } from "../components/product-create-drawer";
import { Pager } from "../components/pager";
import { SkeletonRows } from "../components/loading";
import "../project-wizard-page.css";
const PROJ_PAGE_SIZE = 10; // 项目列表/网格每页条数
@@ -388,9 +389,10 @@ const PROJ_TABS: Array<{ filter: "all" | "wip" | "done" | "fail"; label: string
{ filter: "all", label: "全部" }, { filter: "wip", label: "进行中" }, { filter: "done", label: "已完成" }, { filter: "fail", label: "失败" }
];
export function ProjectsPage({ products, projects, navigate, openPipeline, onDelete }: {
export function ProjectsPage({ products, projects, loading = false, navigate, openPipeline, onDelete }: {
products: Product[];
projects: Project[];
loading?: boolean;
navigate: (page: Page) => void;
onCreate: (payload: { name: string; product: string }) => Promise<unknown> | void;
openPipeline: (projectId: string) => void;
@@ -564,9 +566,11 @@ export function ProjectsPage({ products, projects, navigate, openPipeline, onDel
</div>
</div>
<div className="result-meta" id="result-meta">// 显示 <span className="count">{pageItems.length}</span> / {filtered.length} 个项目</div>
<div className="result-meta" id="result-meta">// {loading && projects.length === 0 ? "加载中…" : <>显示 <span className="count">{pageItems.length}</span> / {filtered.length} 个项目</>}</div>
{view === "list" ? (
{loading && projects.length === 0 ? (
<SkeletonRows count={6} />
) : view === "list" ? (
<div id="list-view">
<table className="t">
<thead>