feat(studio): 上传组件用我的笔记 token + 关闭上传弹窗刷新来源列表

- document-upload-popup: 新增 getNotebookToken(),上传/导入到笔记后端
  (source/import、documents/fileupload)改用「我的笔记」token;
  其余请求由调用方在 init.headers 自带 Authorization,不再注入本系统 token
- query-client-provider: 导出 queryClient 单例,便于非 hook 处读取缓存的 token
- network-actor: consumerUrl 改为读 VITE_AIPI_CONSUMER_URL;修复 source/import
  headers 语法并去掉重复 token
- StudioNotebookDetailPage: DocumentUploadDialogProvider 增加 onClose,
  关闭上传弹窗时刷新来源列表与 source_count

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
xuhdandClaude Opus 4.8 committed 2026-06-12 10:14:49 +08:00
1 parent bd0d922737
commit c268348e29
4 files changed
+24 -17

No files matched your search

@@ -26,13 +26,24 @@ import {
import { Button } from "@/components/ui/button";
import { toast } from "sonner";
import { getStoredAuth } from "@/core/auth";
import { queryClient } from "@/components/query-client-provider";
import Empty from "./empty";
import { NetworkActor } from "./network-actor";
// ── 适配层 ─────────────────────────────────────────────────
function authenticatedFetch(url: string, init?: RequestInit) {
const token = getStoredAuth()?.access_token;
// 本组件只对接「我的笔记/空间」后端,用不到本系统(DeerFlow)token。
// notebook token 由 fetchStudioToken(getTokenByEmail) 获取,缓存在 react-query
// 的 ["studio","token",email] 下(见 core/studio/hooks)。
function getNotebookToken(): string | undefined {
const email = getStoredAuth()?.email ?? "";
return queryClient.getQueryData<string>(["studio", "token", email]);
}
// 上传到笔记后端时传 useNotebookToken=true 注入我的笔记 token;
// 其余请求不注入本系统 token,调用方自行在 init.headers 里带 Authorization。
export function authenticatedFetch(url: string, init?: RequestInit, useNotebookToken = false): Promise<Response> {
const token = useNotebookToken ? getNotebookToken() : undefined;
return fetch(url, {
...init,
headers: {
@@ -334,7 +345,7 @@ const DocumentUploadPopupContent: FC<{
if (!files.length) return;
setUploading(true);
try {
const token = getStoredAuth()?.access_token ?? "";
const token = getNotebookToken() ?? "";
const formData = new FormData();
formData.append("search_space_id", searchSpaceId);
for (const file of files) {
@@ -389,7 +400,7 @@ const DocumentUploadPopupContent: FC<{
search_space_id: Number(searchSpaceId),
source_list: dataList,
}),
});
}, true);
if (response.ok) {
const data = await response.json() as { imported_count?: number };
toast.success(`成功导入 ${data.imported_count || dataList.length} 个来源`);
@@ -10,17 +10,8 @@ import { Loader2, Plus, Search, Trash2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { toast } from "sonner";
import { getStoredAuth } from "@/core/auth";
import { authenticatedFetch } from "@/components/assistant-ui/document-upload-popup";
function authenticatedFetch(url: string, init?: RequestInit) {
const token = getStoredAuth()?.access_token;
return fetch(url, {
...init,
headers: {
...(init?.headers ?? {}),
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
});
}
interface NetworkActorProps {
inputValue: string;
@@ -195,7 +186,7 @@ export function NetworkActor({ inputValue, searchSpaceId, onSuccess }: NetworkAc
const [actorCount, setActorCount] = useState<number>(0);
const [directionType, setDirectionType] = useState<string>('TW');
const directionValue = useRef<string>('TW');
const consumerUrl = 'http://ch1.b.uat.4.cn/consumer';
const consumerUrl = import.meta.env.VITE_AIPI_CONSUMER_URL || 'https://ch1.b.uat.4.cn/consumer';
const backendUrl = typeof window !== 'undefined'
? (import.meta.env.VITE_BACKEND_BASE_URL || 'http://localhost:8001')
: 'http://localhost:8001';
@@ -395,7 +386,7 @@ export function NetworkActor({ inputValue, searchSpaceId, onSuccess }: NetworkAc
search_space_id: Number(searchSpaceId),
source_list: dataList,
}),
});
}, true);
if (response.ok) {
const data = await response.json();
toast.success(`成功导入 ${data.imported_count || dataList.length} 个来源`);
@@ -5,7 +5,7 @@ import {
QueryClientProvider as TanStackQueryClientProvider,
} from "@tanstack/react-query";
const queryClient = new QueryClient();
export const queryClient = new QueryClient();
export function QueryClientProvider({
children,
@@ -455,6 +455,11 @@ export default function StudioNotebookDetailPage() {
return (
<DocumentUploadDialogProvider
searchSpace={{ id: notebook.id }}
onClose={() => {
// 关闭上传弹窗时刷新来源列表与 source_count(覆盖文件上传 / A·B·Y 导入等所有路径)
void queryClient.invalidateQueries({ queryKey: ["studio", "sources"] });
void queryClient.invalidateQueries({ queryKey: ["studio", "notebooks", studioToken] });
}}
onUploadSuccess={() => {
void queryClient.invalidateQueries({ queryKey: ["studio", "sources"] });
void queryClient.invalidateQueries({ queryKey: ["studio", "notebooks", studioToken] });