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:
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 { Button } from "@/components/ui/button";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { getStoredAuth } from "@/core/auth";
|
import { getStoredAuth } from "@/core/auth";
|
||||||
|
import { queryClient } from "@/components/query-client-provider";
|
||||||
import Empty from "./empty";
|
import Empty from "./empty";
|
||||||
import { NetworkActor } from "./network-actor";
|
import { NetworkActor } from "./network-actor";
|
||||||
|
|
||||||
// ── 适配层 ─────────────────────────────────────────────────
|
// ── 适配层 ─────────────────────────────────────────────────
|
||||||
|
|
||||||
function authenticatedFetch(url: string, init?: RequestInit) {
|
// 本组件只对接「我的笔记/空间」后端,用不到本系统(DeerFlow)token。
|
||||||
const token = getStoredAuth()?.access_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, {
|
return fetch(url, {
|
||||||
...init,
|
...init,
|
||||||
headers: {
|
headers: {
|
||||||
@@ -334,7 +345,7 @@ const DocumentUploadPopupContent: FC<{
|
|||||||
if (!files.length) return;
|
if (!files.length) return;
|
||||||
setUploading(true);
|
setUploading(true);
|
||||||
try {
|
try {
|
||||||
const token = getStoredAuth()?.access_token ?? "";
|
const token = getNotebookToken() ?? "";
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("search_space_id", searchSpaceId);
|
formData.append("search_space_id", searchSpaceId);
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
@@ -389,7 +400,7 @@ const DocumentUploadPopupContent: FC<{
|
|||||||
search_space_id: Number(searchSpaceId),
|
search_space_id: Number(searchSpaceId),
|
||||||
source_list: dataList,
|
source_list: dataList,
|
||||||
}),
|
}),
|
||||||
});
|
}, true);
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const data = await response.json() as { imported_count?: number };
|
const data = await response.json() as { imported_count?: number };
|
||||||
toast.success(`成功导入 ${data.imported_count || dataList.length} 个来源`);
|
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 { Button } from "@/components/ui/button";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { getStoredAuth } from "@/core/auth";
|
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 {
|
interface NetworkActorProps {
|
||||||
inputValue: string;
|
inputValue: string;
|
||||||
@@ -195,7 +186,7 @@ export function NetworkActor({ inputValue, searchSpaceId, onSuccess }: NetworkAc
|
|||||||
const [actorCount, setActorCount] = useState<number>(0);
|
const [actorCount, setActorCount] = useState<number>(0);
|
||||||
const [directionType, setDirectionType] = useState<string>('TW');
|
const [directionType, setDirectionType] = useState<string>('TW');
|
||||||
const directionValue = useRef<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'
|
const backendUrl = typeof window !== 'undefined'
|
||||||
? (import.meta.env.VITE_BACKEND_BASE_URL || 'http://localhost:8001')
|
? (import.meta.env.VITE_BACKEND_BASE_URL || 'http://localhost:8001')
|
||||||
: 'http://localhost:8001';
|
: 'http://localhost:8001';
|
||||||
@@ -395,7 +386,7 @@ export function NetworkActor({ inputValue, searchSpaceId, onSuccess }: NetworkAc
|
|||||||
search_space_id: Number(searchSpaceId),
|
search_space_id: Number(searchSpaceId),
|
||||||
source_list: dataList,
|
source_list: dataList,
|
||||||
}),
|
}),
|
||||||
});
|
}, true);
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
toast.success(`成功导入 ${data.imported_count || dataList.length} 个来源`);
|
toast.success(`成功导入 ${data.imported_count || dataList.length} 个来源`);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
QueryClientProvider as TanStackQueryClientProvider,
|
QueryClientProvider as TanStackQueryClientProvider,
|
||||||
} from "@tanstack/react-query";
|
} from "@tanstack/react-query";
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
export const queryClient = new QueryClient();
|
||||||
|
|
||||||
export function QueryClientProvider({
|
export function QueryClientProvider({
|
||||||
children,
|
children,
|
||||||
|
|||||||
@@ -455,6 +455,11 @@ export default function StudioNotebookDetailPage() {
|
|||||||
return (
|
return (
|
||||||
<DocumentUploadDialogProvider
|
<DocumentUploadDialogProvider
|
||||||
searchSpace={{ id: notebook.id }}
|
searchSpace={{ id: notebook.id }}
|
||||||
|
onClose={() => {
|
||||||
|
// 关闭上传弹窗时刷新来源列表与 source_count(覆盖文件上传 / A·B·Y 导入等所有路径)
|
||||||
|
void queryClient.invalidateQueries({ queryKey: ["studio", "sources"] });
|
||||||
|
void queryClient.invalidateQueries({ queryKey: ["studio", "notebooks", studioToken] });
|
||||||
|
}}
|
||||||
onUploadSuccess={() => {
|
onUploadSuccess={() => {
|
||||||
void queryClient.invalidateQueries({ queryKey: ["studio", "sources"] });
|
void queryClient.invalidateQueries({ queryKey: ["studio", "sources"] });
|
||||||
void queryClient.invalidateQueries({ queryKey: ["studio", "notebooks", studioToken] });
|
void queryClient.invalidateQueries({ queryKey: ["studio", "notebooks", studioToken] });
|
||||||
|
|||||||
Reference in new issue
Block a user