feat(foreshadow): 写作台本章伏笔主动提醒(前端)
- 新增 chapterForeshadow 纯分类:按当前章分 可回收/待回收/已逾期(启用闲置的 isWindowApproaching) - useChapterForeshadow hook(复用 GET /foreshadow,切章仅重分类不重拉) - 右栏「本章参考」+ ContextDrawer 伏笔页新增「本章伏笔」实时清单, 分色展示 + 跳看板链接 + 空态;标注『按已验收进度』
This commit is contained in:
@@ -22,12 +22,17 @@ import {
|
||||
useContextDrawerData,
|
||||
type ContextResource,
|
||||
} from "@/lib/workbench/useContextDrawer";
|
||||
import { chapterForeshadowTotal } from "@/lib/foreshadow/chapterForeshadow";
|
||||
import { useChapterForeshadow } from "@/lib/foreshadow/useChapterForeshadow";
|
||||
import { ChapterForeshadowList } from "./ChapterForeshadowList";
|
||||
|
||||
// 速查抽屉总开关:一键关闭即回滚(触发按钮据此隐藏,旧侧栏/全宽页路由不受影响)。
|
||||
export const CONTEXT_DRAWER_ENABLED = true;
|
||||
|
||||
interface ContextDrawerProps {
|
||||
projectId: string;
|
||||
// 当前章号:伏笔速查按此分「可回收 / 待回收 / 已逾期」。
|
||||
chapterNo: number;
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
// 关闭时把焦点还给触发按钮(a11y)。
|
||||
@@ -39,6 +44,7 @@ interface ContextDrawerProps {
|
||||
// a11y 复用命令面板/Drawer 范式:role=dialog + aria-modal + Esc 关闭 + focus trap + body scroll lock + 还原焦点。
|
||||
export function ContextDrawer({
|
||||
projectId,
|
||||
chapterNo,
|
||||
open,
|
||||
onClose,
|
||||
triggerRef,
|
||||
@@ -98,7 +104,12 @@ export function ContextDrawer({
|
||||
<TabBar activeTab={activeTab} onSelect={setActiveTab} />
|
||||
|
||||
<div className="flex-1 overflow-auto overscroll-contain px-4 py-4">
|
||||
<TabPanel projectId={projectId} activeTab={activeTab} data={data} />
|
||||
<TabPanel
|
||||
projectId={projectId}
|
||||
chapterNo={chapterNo}
|
||||
activeTab={activeTab}
|
||||
data={data}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -144,12 +155,13 @@ function TabBar({ activeTab, onSelect }: TabBarProps) {
|
||||
|
||||
interface TabPanelProps {
|
||||
projectId: string;
|
||||
chapterNo: number;
|
||||
activeTab: ContextTabKey;
|
||||
data: ReturnType<typeof useContextDrawerData>;
|
||||
}
|
||||
|
||||
// 按当前 Tab 渲染对应速查面板;每个面板都带一个「去完整页编辑 →」链接。
|
||||
function TabPanel({ projectId, activeTab, data }: TabPanelProps) {
|
||||
function TabPanel({ projectId, chapterNo, activeTab, data }: TabPanelProps) {
|
||||
const href = contextTabHref(projectId, activeTab);
|
||||
return (
|
||||
<div role="tabpanel" className="space-y-3">
|
||||
@@ -160,7 +172,7 @@ function TabPanel({ projectId, activeTab, data }: TabPanelProps) {
|
||||
<OutlinePanel resource={data.outline} onRetry={data.reloadOutline} />
|
||||
) : null}
|
||||
{activeTab === "foreshadow" ? (
|
||||
<PlaceholderPanel summary="伏笔账本:埋设/回收窗口与逾期告警在完整看板逐条管理。" />
|
||||
<ForeshadowPanel projectId={projectId} chapterNo={chapterNo} />
|
||||
) : null}
|
||||
{activeTab === "rules" ? (
|
||||
<PlaceholderPanel summary="世界硬规则:分级约束正文一致性,在规则页增删改。" />
|
||||
@@ -307,7 +319,32 @@ function OutlinePanel({ resource, onRetry }: OutlinePanelProps) {
|
||||
);
|
||||
}
|
||||
|
||||
// 占位面板(伏笔/规则/文风):抽屉内一句话摘要,完整编辑走下方跳链。
|
||||
interface ForeshadowPanelProps {
|
||||
projectId: string;
|
||||
chapterNo: number;
|
||||
}
|
||||
|
||||
// 伏笔速查(只读):按当前章号分「可回收 / 待回收 / 已逾期」,与右栏本章伏笔同数据源、同分类函数。
|
||||
function ForeshadowPanel({ projectId, chapterNo }: ForeshadowPanelProps) {
|
||||
const { groups, status, reload } = useChapterForeshadow(projectId, chapterNo);
|
||||
if (status === "loading") return <LoadingNote />;
|
||||
if (status === "error") {
|
||||
return <ErrorNote message="伏笔暂不可用。" onRetry={reload} />;
|
||||
}
|
||||
if (chapterForeshadowTotal(groups) === 0) {
|
||||
return <EmptyNote text="这一章暂无待回收或已逾期的伏笔(按已验收进度)。" />;
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<p className="mb-2 text-2xs uppercase tracking-wide text-muted-soft">
|
||||
本章伏笔 · 按已验收进度
|
||||
</p>
|
||||
<ChapterForeshadowList groups={groups} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 占位面板(规则/文风):抽屉内一句话摘要,完整编辑走下方跳链。
|
||||
function PlaceholderPanel({ summary }: { summary: string }) {
|
||||
return (
|
||||
<StatusNote variant="info">
|
||||
|
||||
Reference in New Issue
Block a user