feat(ai-writing): 课题研究笔记本内嵌打开 + 新建/所有空间入口(0616 #5)
- 左栏点笔记本/所有空间 → 右侧内嵌打开(不跳路由),写作布局保持挂载(display:none,不丢 setup 线程),顶部「返回写作」 - ResearchSidebar 加「新建空间」(弹窗 createSearchSpace) 与「所有空间」入口 - StudioNotebookDetailPage 加可选 notebookId prop;StudioNotebooksPage 加可选 onOpenNotebook(内嵌时卡片走回调而非 Link),列表内点空间内嵌打开详情 - 内嵌笔记本详情用 ChatRuntime 包裹(修复 useArtifacts must be used within an ArtifactsProvider) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
f39cffcb9a
commit
0e4caa5a66
4 files changed
+243
-47
No files matched your search
@@ -209,8 +209,15 @@ function SourcesDialog({
|
||||
}
|
||||
|
||||
// ── 主页面 ──────────────────────────────────────────────
|
||||
export default function StudioNotebookDetailPage() {
|
||||
const { notebookId } = useParams<{ notebookId: string }>();
|
||||
export default function StudioNotebookDetailPage({
|
||||
notebookId: notebookIdProp,
|
||||
}: {
|
||||
/** 内嵌使用(如课题研究右侧)时直接传入;缺省则从路由参数取。 */
|
||||
notebookId?: number;
|
||||
} = {}) {
|
||||
const params = useParams<{ notebookId: string }>();
|
||||
const notebookId =
|
||||
notebookIdProp != null ? String(notebookIdProp) : params.notebookId;
|
||||
const { notebooks, isLoading, token: studioToken } = useStudioNotebooks(); // token 用于跳转 callback
|
||||
const { models } = useModels();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
@@ -39,17 +39,16 @@ function NotebookCard({
|
||||
nb,
|
||||
onRename,
|
||||
onDelete,
|
||||
onOpen,
|
||||
}: {
|
||||
nb: StudioNotebook;
|
||||
onRename: (nb: StudioNotebook) => void;
|
||||
onDelete: (nb: StudioNotebook) => void;
|
||||
/** 传入则点击卡片回调(内嵌打开),不再路由跳转。 */
|
||||
onOpen?: (id: number) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="group relative flex flex-col rounded-[20px] bg-[#f2f2f2] transition-colors hover:bg-[#e8e8e8]" style={{ minHeight: 180 }}>
|
||||
<Link
|
||||
to={`/page/workspace/studio/notebooks/${nb.id}`}
|
||||
className="flex flex-1 flex-col p-5"
|
||||
>
|
||||
const inner = (
|
||||
<>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex size-11 items-center justify-center text-3xl leading-none select-none">
|
||||
{nb.avatar_url ? (
|
||||
@@ -67,7 +66,27 @@ function NotebookCard({
|
||||
</span>
|
||||
<span className="text-[13px] text-[#666]">{nb.source_count} 个来源</span>
|
||||
</div>
|
||||
</Link>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="group relative flex flex-col rounded-[20px] bg-[#f2f2f2] transition-colors hover:bg-[#e8e8e8]" style={{ minHeight: 180 }}>
|
||||
{onOpen ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onOpen(nb.id)}
|
||||
className="flex flex-1 flex-col p-5 text-left"
|
||||
>
|
||||
{inner}
|
||||
</button>
|
||||
) : (
|
||||
<Link
|
||||
to={`/page/workspace/studio/notebooks/${nb.id}`}
|
||||
className="flex flex-1 flex-col p-5"
|
||||
>
|
||||
{inner}
|
||||
</Link>
|
||||
)}
|
||||
|
||||
{/* three-dot menu — absolute so it doesn't shift layout */}
|
||||
<div className="absolute right-4 top-4">
|
||||
@@ -99,7 +118,12 @@ function NotebookCard({
|
||||
);
|
||||
}
|
||||
|
||||
export default function StudioNotebooksPage() {
|
||||
export default function StudioNotebooksPage({
|
||||
onOpenNotebook,
|
||||
}: {
|
||||
/** 内嵌使用(课题研究右侧)时传入:点击空间卡片回调,不跳路由。 */
|
||||
onOpenNotebook?: (id: number) => void;
|
||||
} = {}) {
|
||||
const { notebooks, isLoading, isError } = useStudioNotebooks();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
@@ -204,6 +228,7 @@ export default function StudioNotebooksPage() {
|
||||
nb={nb}
|
||||
onRename={(nb) => { setRenameTarget(nb); setRenameName(nb.name); setRenameError(""); }}
|
||||
onDelete={(nb) => { setDeleteTarget(nb); setDeleteError(""); }}
|
||||
onOpen={onOpenNotebook}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user