feat: 添加知识库配置管理功能

新增地区-知识库绑定管理功能,支持增删改查操作
- 添加 V3 API 路由层:area-datasets 相关接口
- 添加 API 客户端:area-datasets.ts
- 添加自定义 Hook:use-area-dataset-config.ts
- 添加管理组件:area-dataset-config.tsx
- 修复路由冲突问题,删除重复的 .ts 路由文件
- 更新 dataset-manager 页面,添加 Tabs 导航

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-07 23:12:21 +08:00
parent 21bcb1310b
commit 27aff59152
13 changed files with 3740 additions and 21 deletions
+21 -3
View File
@@ -21,6 +21,24 @@ declare global {
}
}
interface ChatTheme {
colorBgContainer: string;
borderRadiusLG: number;
}
/**
* 获取主题token - 避免在SSR环境中调用
*/
function useChatTheme(): ChatTheme {
// Ant Design的theme.useToken()必须在组件顶层调用,不能放在useEffect中
const antdToken = typeof window !== 'undefined' ? theme.useToken().token : null;
return {
colorBgContainer: antdToken?.colorBgContainer || '#ffffff',
borderRadiusLG: antdToken?.borderRadiusLG || 8,
};
}
/**
* 主聊天组件
* 实现单页面应用模式,参考webapp-conversation的初始化逻辑
@@ -29,9 +47,9 @@ export default function Chat() {
// 侧边栏状态
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
const [isMobile, setIsMobile] = useState(false);
const {
token: { colorBgContainer, borderRadiusLG },
} = theme.useToken();
// 获取主题配置,避免SSR错误
const { colorBgContainer, borderRadiusLG } = useChatTheme();
// 会话管理
const {
+30 -1
View File
@@ -9,8 +9,9 @@ import {
PlusOutlined,
SearchOutlined,
} from '@ant-design/icons';
import { Button, Dropdown, Input, Layout, Menu, Modal, Tooltip, message, theme } from 'antd';
import { Button, Dropdown, Input, Layout, Menu, Modal, Tooltip, message, theme, Select } from 'antd';
import { forwardRef, useImperativeHandle, useState } from 'react';
import type { ChatApp } from '~/api/dify-chat-apps/types';
import type { ConversationItem } from '~/api/dify-chat';
import { deleteConversation, renameConversation } from '~/api/dify-chat';
import '../../styles/components/chat-with-llm/sidebar.css';
@@ -25,6 +26,11 @@ interface ChatSidebarProps {
onConversationSelect: (conversationId: string) => void;
onNewConversation: () => void;
onConversationDeleted?: (conversationId: string) => void;
// 对话应用相关属性
chatApps: ChatApp[];
loadingChatApps: boolean;
currentChatApp: ChatApp | null;
onChatAppChange: (appId: string) => void;
onConversationRenamed?: (conversationId: string, newName: string) => void;
}
@@ -39,6 +45,10 @@ export interface ChatSidebarRef {
const ChatSidebar = forwardRef<ChatSidebarRef, ChatSidebarProps>(({
collapsed,
onToggle,
chatApps,
loadingChatApps,
currentChatApp,
onChatAppChange,
conversations,
currentConversationId,
onConversationSelect,
@@ -281,6 +291,25 @@ const ChatSidebar = forwardRef<ChatSidebarRef, ChatSidebarProps>(({
</div>
{/* 搜索框 */}
{/* 对话应用选择器 */}
{!collapsed && (
<div className="mb-3">
<Select
value={currentChatApp?.app_id}
onChange={onChatAppChange}
loading={loadingChatApps}
className="w-full"
placeholder="选择对话应用"
size="small"
>
{(chatApps || []).map(app => (
<Select.Option key={app.app_id} value={app.app_id}>
{app.app_name}
</Select.Option>
))}
</Select>
</div>
)}
{!collapsed && (
<Input
placeholder="搜索对话..."