forked from EduCraft/curriculum-project-hub
feat(filelib): 老师端左栏导航:回收站 + 最近打开(ADR-0031)
- 回收站:listBin(祖先全活跃的已删顶点;管理员/直连 MANAGE 可见)、 restore(与 D15 对称只清本节点,落审计)、purge(仅管理员,pathIds 枚举 子树按深度降序分批硬删,绕过 self-FK RESTRICT) - 最近打开:FileLibRecentVisit 表(filePath='' 兜底 PG 唯一索引),客户端 成功打开后上报(VIEW 门禁,upsert 刷新),列表 20 条,D8/D15 可见性过滤 - 前端:/app 左栏(文件库/最近打开/回收站);RecentView/BinView; GridLibraryView 埋点 + navTarget 跳转(breadcrumb 建栈,role 已捎带) - 测试:filelib-nav 集成 4 例;全套 79 例绿
This commit is contained in:
@@ -1,12 +1,30 @@
|
||||
<script lang="ts">
|
||||
/** 老师端。未登录显示登录卡片;登录后是网盘式文件库浏览器。 */
|
||||
/** 老师端。未登录显示登录卡片;登录后是带左栏导航的文件库(ADR-0031)。 */
|
||||
import { onMount } from "svelte";
|
||||
import { me, authChecked } from "$lib/stores.js";
|
||||
import { loadSession } from "$lib/session.js";
|
||||
import LoginView from "$lib/LoginView.svelte";
|
||||
import GridLibraryView from "$lib/GridLibraryView.svelte";
|
||||
import GridLibraryView, { type NavTarget } from "$lib/GridLibraryView.svelte";
|
||||
import RecentView from "$lib/RecentView.svelte";
|
||||
import BinView from "$lib/BinView.svelte";
|
||||
import Icon from "$lib/Icon.svelte";
|
||||
|
||||
onMount(loadSession);
|
||||
|
||||
type View = "library" | "recent" | "bin";
|
||||
let view = $state<View>("library");
|
||||
let navTarget = $state<NavTarget | null>(null);
|
||||
|
||||
function openFromRecent(target: NavTarget): void {
|
||||
navTarget = target;
|
||||
view = "library";
|
||||
}
|
||||
|
||||
const tabs: ReadonlyArray<readonly [View, string, "layers" | "clock" | "trash"]> = [
|
||||
["library", "文件库", "layers"],
|
||||
["recent", "最近打开", "clock"],
|
||||
["bin", "回收站", "trash"],
|
||||
];
|
||||
</script>
|
||||
|
||||
<svelte:head><title>文件库</title></svelte:head>
|
||||
@@ -14,8 +32,29 @@
|
||||
{#if !$authChecked}
|
||||
<div class="flex h-full items-center justify-center text-ink-3">加载中…</div>
|
||||
{:else if $me}
|
||||
<div class="flex h-full flex-col">
|
||||
<GridLibraryView />
|
||||
<div class="flex h-full">
|
||||
<!-- 左栏导航(ADR-0031) -->
|
||||
<nav class="flex w-[168px] shrink-0 flex-col gap-0.5 border-r border-line-soft bg-sidebar px-2.5 py-3.5">
|
||||
{#each tabs as [id, label, icon] (id)}
|
||||
<button
|
||||
class="flex items-center gap-2.5 rounded-lg px-3 py-2 text-left text-[13px] transition {view === id
|
||||
? 'bg-selected font-semibold text-ink'
|
||||
: 'text-ink-2 hover:bg-hover'}"
|
||||
onclick={() => (view = id)}
|
||||
>
|
||||
<span class="text-ink-3"><Icon name={icon} size={15} /></span>
|
||||
{label}
|
||||
</button>
|
||||
{/each}
|
||||
</nav>
|
||||
|
||||
{#if view === "library"}
|
||||
<GridLibraryView {navTarget} onnavigated={() => (navTarget = null)} />
|
||||
{:else if view === "recent"}
|
||||
<RecentView onopen={openFromRecent} />
|
||||
{:else}
|
||||
<BinView />
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<LoginView />
|
||||
|
||||
Reference in New Issue
Block a user