diff --git a/README.md b/README.md
index cf398446..53784b01 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,12 @@
## 📝 项目概述
+DEV 更新待办:
+
+- 智能体的消息加载有问题
+- 智能体的管理员的配置无法更新到用户层面
+
+
语析是一个强大的问答平台,结合了大模型 RAG 知识库与知识图谱技术,基于 Llamaindex + VueJS + FastAPI + Neo4j 构建。
**核心特点:**
diff --git a/server/utils/auth_middleware.py b/server/utils/auth_middleware.py
index 692f872f..f78aa1d2 100644
--- a/server/utils/auth_middleware.py
+++ b/server/utils/auth_middleware.py
@@ -59,6 +59,14 @@ async def get_current_user(token: Optional[str] = Depends(oauth2_scheme), db: Se
raise credentials_exception
except JWTError:
raise credentials_exception
+ except ValueError as e:
+ # 捕获AuthUtils.verify_access_token可能抛出的ValueError
+ # 例如令牌过期或无效
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail=str(e), # 将错误信息直接传递给客户端
+ headers={"WWW-Authenticate": "Bearer"},
+ )
# 查找用户
user = db.query(User).filter(User.id == user_id).first()
@@ -108,7 +116,15 @@ ADMIN_PATHS = [
r"^/admin/.*$", # 管理员接口
r"^/data/.*$", # 数据操作接口,所有数据操作都需要管理员权限
r"^/chat/set_default_agent$", # 设置默认智能体
- r"^/chat/models/update$" # 更新模型列表
+ r"^/chat/models/update$", # 更新模型列表
+ r"^/auth/users.*$", # 用户管理相关API
+ r"^/config$" # 系统配置API
+]
+
+# 路径是否需要超级管理员权限
+SUPERADMIN_PATHS = [
+ r"^/restart$", # 系统重启
+ r"^/auth/users/\d+/role$" # 修改用户角色(仅超级管理员可操作)
]
# 检查路径是否需要管理员权限
@@ -117,4 +133,12 @@ def is_admin_path(path: str) -> bool:
for pattern in ADMIN_PATHS:
if re.match(pattern, path):
return True
+ return False
+
+# 检查路径是否需要超级管理员权限
+def is_superadmin_path(path: str) -> bool:
+ path = path.rstrip('/') # 去除尾部斜杠以便于匹配
+ for pattern in SUPERADMIN_PATHS:
+ if re.match(pattern, path):
+ return True
return False
\ No newline at end of file
diff --git a/web/src/apis/admin_api.js b/web/src/apis/admin_api.js
index 5b4177ce..9e298524 100644
--- a/web/src/apis/admin_api.js
+++ b/web/src/apis/admin_api.js
@@ -5,7 +5,7 @@ import { useUserStore } from '@/stores/user'
* 管理员API模块
* 只有管理员和超级管理员可以访问的API
* 权限要求: admin 或 superadmin
- *
+ *
* 注意: 请确保在使用这些API之前检查用户是否具有管理员权限
*/
@@ -50,7 +50,7 @@ export const userManagementApi = {
/**
* 更新用户
- * @param {number} userId - 用户ID
+ * @param {number} userId - 用户ID
* @param {Object} userData - 用户数据
* @returns {Promise} - 更新结果
*/
@@ -137,7 +137,7 @@ export const knowledgeBaseApi = {
/**
* 删除知识库
- * @param {string} dbId - 知识库ID
+ * @param {string} dbId - 知识库ID
* @returns {Promise} - 删除结果
*/
deleteDatabase: async (dbId) => {
@@ -165,7 +165,7 @@ export const knowledgeBaseApi = {
/**
* 删除文件
* @param {string} dbId - 知识库ID
- * @param {string} fileId - 文件ID
+ * @param {string} fileId - 文件ID
* @returns {Promise} - 删除结果
*/
deleteFile: async (dbId, fileId) => {
@@ -204,6 +204,17 @@ export const knowledgeBaseApi = {
checkAdminPermission()
return apiPost('/api/data/query-test', data, {}, true)
},
+
+ /**
+ * 获取文档详情
+ * @param {string} dbId - 知识库ID
+ * @param {string} fileId - 文件ID
+ * @returns {Promise} - 文档详情
+ */
+ getDocumentDetail: async (dbId, fileId) => {
+ checkAdminPermission()
+ return apiGet(`/api/data/document?db_id=${dbId}&file_id=${fileId}`, {}, true)
+ }
}
// 图数据库管理API
@@ -309,6 +320,6 @@ export const logApi = {
*/
getLogs: async (params = {}) => {
checkAdminPermission()
- return apiGet('/api/admin/logs', { params }, true)
+ return apiGet('/api/log', { params }, true)
},
-}
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/web/src/apis/auth_api.js b/web/src/apis/auth_api.js
index f971d5c7..92010820 100644
--- a/web/src/apis/auth_api.js
+++ b/web/src/apis/auth_api.js
@@ -1,4 +1,5 @@
import { apiGet, apiPost, apiDelete } from './base'
+import { useUserStore } from '@/stores/user'
/**
* 需要用户认证的API模块
@@ -10,7 +11,7 @@ import { apiGet, apiPost, apiDelete } from './base'
export const chatApi = {
/**
* 发送聊天消息
- * @param {Object} params - 聊天参数
+ * @param {Object} params - 聊天参数
* @returns {Promise} - 聊天响应流
*/
sendMessage: (params) => {
@@ -18,11 +19,47 @@ export const chatApi = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
+ ...useUserStore().getAuthHeaders()
},
body: JSON.stringify(params),
})
},
+ /**
+ * 发送可中断的聊天消息
+ * @param {Object} params - 聊天参数
+ * @param {AbortSignal} signal - 用于中断请求的信号控制器
+ * @returns {Promise} - 聊天响应流
+ */
+ sendMessageWithAbort: (params, signal) => {
+ return fetch('/api/chat/', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ ...useUserStore().getAuthHeaders()
+ },
+ body: JSON.stringify(params),
+ signal // 添加 signal 用于中断请求
+ })
+ },
+
+ /**
+ * 发送聊天消息到指定智能体(流式响应)
+ * @param {string} agentId - 智能体ID
+ * @param {Object} data - 聊天数据
+ * @returns {Promise} - 聊天响应流
+ */
+ sendAgentMessage: (agentId, data) => {
+ return fetch(`/api/chat/agent/${agentId}`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ ...useUserStore().getAuthHeaders()
+ },
+ body: JSON.stringify(data)
+ })
+ },
+
/**
* 简单聊天调用(非流式)
* @param {string} query - 查询内容
@@ -66,7 +103,7 @@ export const chatApi = {
* @param {string} conversationId - 对话ID
* @returns {Promise} - 对话详情
*/
- getConversation: (conversationId) =>
+ getConversation: (conversationId) =>
apiGet(`/api/chat/conversations/${conversationId}`, {}, true),
/**
@@ -74,7 +111,7 @@ export const chatApi = {
* @param {string} conversationId - 对话ID
* @returns {Promise} - 删除结果
*/
- deleteConversation: (conversationId) =>
+ deleteConversation: (conversationId) =>
apiDelete(`/api/chat/conversations/${conversationId}`, {}, true),
/**
@@ -83,7 +120,7 @@ export const chatApi = {
* @param {string} title - 新标题
* @returns {Promise} - 更新结果
*/
- updateConversationTitle: (conversationId, title) =>
+ updateConversationTitle: (conversationId, title) =>
apiPost(`/api/chat/conversations/${conversationId}/title`, { title }, {}, true),
}
@@ -94,7 +131,7 @@ export const userSettingsApi = {
* @returns {Promise} - 用户设置
*/
getSettings: () => apiGet('/api/user/settings', {}, true),
-
+
/**
* 更新用户设置
* @param {Object} settings - 新设置
@@ -103,4 +140,4 @@ export const userSettingsApi = {
updateSettings: (settings) => apiPost('/api/user/settings', settings, {}, true),
}
-// 其他需要用户认证的API可以继续添加到这里
\ No newline at end of file
+// 其他需要用户认证的API可以继续添加到这里
\ No newline at end of file
diff --git a/web/src/apis/base.js b/web/src/apis/base.js
index 78e4bdf8..5b403d8a 100644
--- a/web/src/apis/base.js
+++ b/web/src/apis/base.js
@@ -30,19 +30,21 @@ export async function apiRequest(url, options = {}, requiresAuth = false) {
if (!userStore.isLoggedIn) {
throw new Error('用户未登录')
}
-
+
Object.assign(requestOptions.headers, userStore.getAuthHeaders())
}
// 发送请求
const response = await fetch(url, requestOptions)
-
+
// 处理API返回的错误
if (!response.ok) {
// 尝试解析错误信息
let errorMessage = `请求失败: ${response.status}`
+ let errorData = null
+
try {
- const errorData = await response.json()
+ errorData = await response.json()
errorMessage = errorData.detail || errorData.message || errorMessage
} catch (e) {
// 如果无法解析JSON,使用默认错误信息
@@ -54,9 +56,19 @@ export async function apiRequest(url, options = {}, requiresAuth = false) {
const userStore = useUserStore()
if (userStore.isLoggedIn) {
// 如果用户认为自己已登录,但收到401,则可能是令牌过期
- message.error('登录已过期,请重新登录')
+ const isTokenExpired = errorData &&
+ (errorData.detail?.includes('令牌已过期') ||
+ errorData.detail?.includes('token expired') ||
+ errorMessage?.includes('令牌已过期') ||
+ errorMessage?.includes('token expired'))
+
+ message.error(isTokenExpired ? '登录已过期,请重新登录' : '认证失败,请重新登录')
userStore.logout()
- window.location.href = '/login'
+
+ // 使用setTimeout确保消息显示后再跳转
+ setTimeout(() => {
+ window.location.href = '/login'
+ }, 1500)
}
throw new Error('未授权,请先登录')
} else if (response.status === 403) {
@@ -81,7 +93,7 @@ export async function apiRequest(url, options = {}, requiresAuth = false) {
/**
* 发送GET请求
- * @param {string} url - API端点
+ * @param {string} url - API端点
* @param {Object} options - 请求选项
* @param {boolean} requiresAuth - 是否需要认证
* @returns {Promise} - 请求结果
@@ -100,12 +112,12 @@ export function apiGet(url, options = {}, requiresAuth = false) {
*/
export function apiPost(url, data = {}, options = {}, requiresAuth = false) {
return apiRequest(
- url,
- {
- method: 'POST',
+ url,
+ {
+ method: 'POST',
body: JSON.stringify(data),
- ...options
- },
+ ...options
+ },
requiresAuth
)
}
@@ -120,12 +132,12 @@ export function apiPost(url, data = {}, options = {}, requiresAuth = false) {
*/
export function apiPut(url, data = {}, options = {}, requiresAuth = false) {
return apiRequest(
- url,
- {
- method: 'PUT',
+ url,
+ {
+ method: 'PUT',
body: JSON.stringify(data),
- ...options
- },
+ ...options
+ },
requiresAuth
)
}
@@ -139,4 +151,4 @@ export function apiPut(url, data = {}, options = {}, requiresAuth = false) {
*/
export function apiDelete(url, options = {}, requiresAuth = false) {
return apiRequest(url, { method: 'DELETE', ...options }, requiresAuth)
-}
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/web/src/apis/index.js b/web/src/apis/index.js
index ffa124cc..6acfb3fc 100644
--- a/web/src/apis/index.js
+++ b/web/src/apis/index.js
@@ -17,17 +17,17 @@ export { apiRequest, apiGet, apiPost, apiPut, apiDelete } from './base'
/**
* 权限说明:
- *
+ *
* 1. public_api.js: 不需要认证就可以访问的API
* - 登录、初始化管理员、获取公共配置等
- *
+ *
* 2. auth_api.js: 需要用户认证才能访问的API
* - 权限要求: 任何已登录用户(普通用户、管理员、超级管理员)
* - 聊天功能、个人设置等
- *
+ *
* 3. admin_api.js: 需要管理员权限才能访问的API
* - 权限要求: admin 或 superadmin
* - 用户管理、知识库管理、系统配置等
- *
+ *
* 注意:本模块已处理权限验证和请求头,使用时无需再手动添加认证头
- */
\ No newline at end of file
+ */
\ No newline at end of file
diff --git a/web/src/apis/public_api.js b/web/src/apis/public_api.js
index 88d759de..66cb0412 100644
--- a/web/src/apis/public_api.js
+++ b/web/src/apis/public_api.js
@@ -16,7 +16,7 @@ export const authApi = {
const formData = new FormData()
formData.append('username', credentials.username)
formData.append('password', credentials.password)
-
+
return apiRequest('/api/auth/token', {
method: 'POST',
body: formData
@@ -56,4 +56,4 @@ export const healthApi = {
}
// 从base.js导入apiRequest以支持FormData
-import { apiRequest } from './base'
\ No newline at end of file
+import { apiRequest } from './base'
\ No newline at end of file
diff --git a/web/src/components/AgentChatComponent.vue b/web/src/components/AgentChatComponent.vue
index 6ca3c1b0..df496bd2 100644
--- a/web/src/components/AgentChatComponent.vue
+++ b/web/src/components/AgentChatComponent.vue
@@ -12,11 +12,11 @@
@@ -359,14 +359,7 @@ const sendMessageWithText = async (text) => {
};
// 发送请求
- const response = await fetch(`/api/chat/agent/${currentAgent.value.name}`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- ...userStore.getAuthHeaders()
- },
- body: JSON.stringify(requestData)
- });
+ const response = await chatApi.sendAgentMessage(currentAgent.value.name, requestData);
// console.log("requestData", requestData);
if (!response.ok) {
diff --git a/web/src/components/ChatComponent.vue b/web/src/components/ChatComponent.vue
index b314cfc4..546ce5dd 100644
--- a/web/src/components/ChatComponent.vue
+++ b/web/src/components/ChatComponent.vue
@@ -190,6 +190,7 @@ import MessageInputComponent from '@/components/MessageInputComponent.vue'
import MessageComponent from '@/components/MessageComponent.vue'
import RefsSidebar from '@/components/RefsSidebar.vue'
import { chatApi } from '@/apis/auth_api'
+import { knowledgeBaseApi } from '@/apis/admin_api'
const props = defineProps({
conv: Object,
@@ -479,18 +480,24 @@ const groupRefs = (id) => {
}
const loadDatabases = () => {
- fetch('/api/data/', {
- method: "GET",
- headers: userStore.getAuthHeaders()
- })
- .then(response => response.json())
- .then(data => {
- console.log(data)
- opts.databases = data.databases
- })
- .catch(error => {
- console.error('加载数据库列表失败:', error)
- })
+ // 由于这是管理功能,需要检查用户是否有管理权限
+ if (!userStore.isAdmin) {
+ console.log('非管理员用户,跳过加载数据库列表');
+ return;
+ }
+
+ try {
+ knowledgeBaseApi.getDatabases()
+ .then(data => {
+ console.log(data)
+ opts.databases = data.databases
+ })
+ .catch(error => {
+ console.error('加载数据库列表失败:', error)
+ })
+ } catch (error) {
+ console.error('获取数据库列表失败:', error);
+ }
}
const simpleCall = (msg) => {
@@ -514,20 +521,27 @@ const fetchChatResponse = (user_input, cur_res_id) => {
}
console.log(params)
- // 使用fetch带上认证头和信号控制
- fetch('/api/chat/', {
- method: 'POST',
- body: JSON.stringify(params),
- headers: {
- 'Content-Type': 'application/json',
- ...userStore.getAuthHeaders()
- },
- signal // 添加 signal 用于中断请求
- })
+ // 使用API函数发送请求
+ chatApi.sendMessageWithAbort(params, signal)
.then((response) => {
if (!response.ok) {
- throw new Error(`请求失败: ${response.status} ${response.statusText}`)
+ // 检查是否是401错误(令牌过期)
+ if (response.status === 401) {
+ const userStore = useUserStore();
+ if (userStore.isLoggedIn) {
+ message.error('登录已过期,请重新登录');
+ userStore.logout();
+
+ // 使用setTimeout确保消息显示后再跳转
+ setTimeout(() => {
+ window.location.href = '/login';
+ }, 1500);
+ }
+ throw new Error('未授权,请先登录');
+ }
+ throw new Error(`请求失败: ${response.status} ${response.statusText}`);
}
+
if (!response.body) throw new Error("ReadableStream not supported.");
const reader = response.body.getReader();
const decoder = new TextDecoder("utf-8");
@@ -568,8 +582,6 @@ const fetchChatResponse = (user_input, cur_res_id) => {
meta: data.meta,
...data,
});
- // console.log("Last message", conv.value.messages[conv.value.messages.length - 1].content)
- // console.log("Last message", conv.value.messages[conv.value.messages.length - 1].status)
if (data.history) {
conv.value.history = data.history;
@@ -592,12 +604,18 @@ const fetchChatResponse = (user_input, cur_res_id) => {
if (error.name === 'AbortError') {
console.log('Fetch aborted');
} else {
- console.error(error);
- updateMessage({
- id: cur_res_id,
- status: "error",
- message: error.message || '请求失败',
- });
+ console.error('聊天请求错误:', error);
+
+ // 检查是否是认证错误
+ if (error.message.includes('未授权') || error.message.includes('令牌已过期')) {
+ // 已在上面处理,这里不需要重复处理
+ } else {
+ updateMessage({
+ id: cur_res_id,
+ status: "error",
+ message: error.message || '请求失败',
+ });
+ }
}
isStreaming.value = false;
});
diff --git a/web/src/components/DebugComponent.vue b/web/src/components/DebugComponent.vue
index 07b0d9ee..d7bb3640 100644
--- a/web/src/components/DebugComponent.vue
+++ b/web/src/components/DebugComponent.vue
@@ -22,7 +22,7 @@
{{ state.isFullscreen ? '退出全屏' : '全屏' }}
-
@@ -72,9 +72,11 @@
diff --git a/web/src/components/UserInfoComponent.vue b/web/src/components/UserInfoComponent.vue
index 9afe0d94..5f556589 100644
--- a/web/src/components/UserInfoComponent.vue
+++ b/web/src/components/UserInfoComponent.vue
@@ -1,12 +1,15 @@
-
-
{{ userInitial }}
-
+
+
+
{{ userStore.username }}
-
+
@@ -36,6 +39,13 @@ import { message } from 'ant-design-vue';
const router = useRouter();
const userStore = useUserStore();
+const props = defineProps({
+ showRole: {
+ type: Boolean,
+ default: false
+ }
+})
+
// 用户名首字母(用于显示在头像中)
const userInitial = computed(() => {
if (!userStore.username) return '?';
@@ -84,7 +94,22 @@ const goToLogin = () => {
display: flex;
align-items: center;
justify-content: center;
- margin-bottom: 16px;
+ // margin-bottom: 16px;
+}
+
+.user-info-dropdown {
+ width: 100%;
+ display: flex;
+ align-items: center;
+ gap: 12px;
+
+ &[data-align="center"] {
+ justify-content: center;
+ }
+
+ &[data-align="left"] {
+ justify-content: flex-start;
+ }
}
.user-avatar {
diff --git a/web/src/components/tools/ConvertToTxtComponent.vue b/web/src/components/tools/ConvertToTxtComponent.vue
deleted file mode 100644
index a95ce38c..00000000
--- a/web/src/components/tools/ConvertToTxtComponent.vue
+++ /dev/null
@@ -1,183 +0,0 @@
-
-
-
-
-
-
-
-
- 字符数: {{ charCount }}
- Token 数:{{ estimatedTokenCount }}
-
-
-
-
-
-
-
-
-
diff --git a/web/src/components/tools/TextChunkingComponent.vue b/web/src/components/tools/TextChunkingComponent.vue
deleted file mode 100644
index d06c5dfd..00000000
--- a/web/src/components/tools/TextChunkingComponent.vue
+++ /dev/null
@@ -1,276 +0,0 @@
-
-
-
-
-
-
-
-
-
#{{ index + 1 }} {{ chunk.text }}
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/web/src/layouts/AppLayout.vue b/web/src/layouts/AppLayout.vue
index 86a68f08..23705db2 100644
--- a/web/src/layouts/AppLayout.vue
+++ b/web/src/layouts/AppLayout.vue
@@ -92,6 +92,11 @@ const mainList = [{
path: '/chat',
icon: MessageOutlined,
activeIcon: MessageFilled,
+ }, {
+ name: '智能体',
+ path: '/agent',
+ icon: ToolOutlined,
+ activeIcon: ToolFilled,
}, {
name: '图谱',
path: '/graph',
@@ -104,11 +109,6 @@ const mainList = [{
icon: BookOutlined,
activeIcon: BookFilled,
// hidden: !configStore.config.enable_knowledge_base,
- }, {
- name: '智能体',
- path: '/agent',
- icon: ToolOutlined,
- activeIcon: ToolFilled,
}
]
@@ -168,7 +168,9 @@ const mainList = [{
-
+
+
+
-
+
设置
@@ -365,8 +367,7 @@ div.header, #app-router-view {
width: auto;
font-size: 20px;
color: #333;
- margin-bottom: 20px;
- margin-top: 10px;
+ margin-bottom: 8px;
padding: 16px 12px;
&:hover {
diff --git a/web/src/router/index.js b/web/src/router/index.js
index 2f6a8b3c..5c095dd5 100644
--- a/web/src/router/index.js
+++ b/web/src/router/index.js
@@ -41,8 +41,15 @@ const router = createRouter({
{
path: '/agent',
name: 'AgentMain',
- component: () => import('../views/AgentView.vue'),
- meta: { keepAlive: true, requiresAuth: true, requiresAdmin: true }
+ component: AppLayout,
+ children: [
+ {
+ path: '',
+ name: 'AgentComp',
+ component: () => import('../views/AgentView.vue'),
+ meta: { keepAlive: true, requiresAuth: true, requiresAdmin: true }
+ }
+ ]
},
{
path: '/agent/:agent_id',
diff --git a/web/src/views/AgentSingleView.vue b/web/src/views/AgentSingleView.vue
index d0d6c8d7..093b0446 100644
--- a/web/src/views/AgentSingleView.vue
+++ b/web/src/views/AgentSingleView.vue
@@ -1,26 +1,23 @@
-
-
-
-
-
+ -->
-
+
+
+
+
+
@@ -56,6 +53,8 @@ const toggleUserInfo = () => {
height: 100vh;
overflow: hidden;
position: relative;
+ display: flex;
+ flex-direction: row;
}
.user-info-wrapper {
@@ -67,7 +66,7 @@ const toggleUserInfo = () => {
// 侧边栏样式
.sidebar {
- position: absolute;
+ // position: absolute;
left: 0;
top: 0;
height: 100%;
@@ -90,6 +89,7 @@ const toggleUserInfo = () => {
.user-icon {
cursor: pointer;
margin-bottom: 20px;
+ padding-left: 4px 8px;
img {
width: 32px;
diff --git a/web/src/views/AgentView.vue b/web/src/views/AgentView.vue
index b7328fd4..2f5149cb 100644
--- a/web/src/views/AgentView.vue
+++ b/web/src/views/AgentView.vue
@@ -30,7 +30,7 @@
{{ agents[selectedAgentId]?.description }}
-
+
diff --git a/web/src/views/DataBaseInfoView.vue b/web/src/views/DataBaseInfoView.vue
index 39ec9c67..a4f74bc8 100644
--- a/web/src/views/DataBaseInfoView.vue
+++ b/web/src/views/DataBaseInfoView.vue
@@ -397,29 +397,29 @@ const onQuery = () => {
return
}
meta.db_id = database.value.db_id
- fetch('/api/data/query-test', {
- method: "POST",
- headers: {
- "Content-Type": "application/json" // 添加 Content-Type 头
- },
- body: JSON.stringify({
+
+ try {
+ knowledgeBaseApi.queryTest({
query: queryText.value.trim(),
meta: meta
- }),
- })
- .then(response => response.json())
- .then(data => {
- console.log(data)
- queryResult.value = data
- filterQueryResults()
- })
- .catch(error => {
+ })
+ .then(data => {
+ console.log(data)
+ queryResult.value = data
+ filterQueryResults()
+ })
+ .catch(error => {
+ console.error(error)
+ message.error(error.message)
+ })
+ .finally(() => {
+ state.searchLoading = false
+ })
+ } catch (error) {
console.error(error)
message.error(error.message)
- })
- .finally(() => {
state.searchLoading = false
- })
+ }
}
const handleFileUpload = (event) => {
@@ -480,27 +480,31 @@ const deleteDatabse = () => {
const openFileDetail = (record) => {
state.lock = true
- fetch(`/api/data/document?db_id=${databaseId.value}&file_id=${record.file_id}`, {
- method: "GET",
- })
- .then(response => response.json())
- .then(data => {
- console.log(data)
- if (data.status == "failed") {
- message.error(data.message)
- return
- }
- state.lock = false
- selectedFile.value = {
- ...record,
- lines: data.lines || []
- }
- state.drawer = true
- })
- .catch(error => {
- console.error(error)
- message.error(error.message)
- })
+
+ try {
+ knowledgeBaseApi.getDocumentDetail(databaseId.value, record.file_id)
+ .then(data => {
+ console.log(data)
+ if (data.status == "failed") {
+ message.error(data.message)
+ return
+ }
+ state.lock = false
+ selectedFile.value = {
+ ...record,
+ lines: data.lines || []
+ }
+ state.drawer = true
+ })
+ .catch(error => {
+ console.error(error)
+ message.error(error.message)
+ })
+ } catch (error) {
+ console.error(error)
+ message.error('获取文件详情失败')
+ state.lock = false
+ }
}
const formatRelativeTime = (timestamp) => {
@@ -603,17 +607,10 @@ const chunkFiles = () => {
state.loading = true
// 调用file-to-chunk接口获取分块信息
- fetch('/api/data/file-to-chunk', {
- method: "POST",
- headers: {
- "Content-Type": "application/json"
- },
- body: JSON.stringify({
- files: files,
- params: chunkParams.value
- }),
+ knowledgeBaseApi.fileToChunk({
+ files: files,
+ params: chunkParams.value
})
- .then(response => response.json())
.then(data => {
console.log('文件分块信息:', data)
chunkResults.value = Object.values(data);
@@ -645,17 +642,10 @@ const addToDatabase = () => {
});
// 调用add-by-chunks接口将分块添加到数据库
- fetch('/api/data/add-by-chunks', {
- method: "POST",
- headers: {
- "Content-Type": "application/json"
- },
- body: JSON.stringify({
- db_id: databaseId.value,
- file_chunks: fileChunks
- }),
+ knowledgeBaseApi.addByChunks({
+ db_id: databaseId.value,
+ file_chunks: fileChunks
})
- .then(response => response.json())
.then(data => {
console.log(data)
diff --git a/web/src/views/DataBaseView.vue b/web/src/views/DataBaseView.vue
index 8489f131..1a9526b7 100644
--- a/web/src/views/DataBaseView.vue
+++ b/web/src/views/DataBaseView.vue
@@ -121,7 +121,7 @@ const loadDatabases = () => {
console.error('加载数据库列表失败:', error);
if (error.message.includes('权限')) {
message.error('需要管理员权限访问知识库')
- }
+ }
})
}
@@ -135,10 +135,10 @@ const createDatabase = () => {
}
knowledgeBaseApi.createDatabase({
- database_name: newDatabase.name,
- description: newDatabase.description,
- dimension: newDatabase.dimension ? parseInt(newDatabase.dimension) : null,
- })
+ database_name: newDatabase.name,
+ description: newDatabase.description,
+ dimension: newDatabase.dimension ? parseInt(newDatabase.dimension) : null,
+ })
.then(data => {
console.log(data)
loadDatabases()
diff --git a/web/src/views/HomeView.vue b/web/src/views/HomeView.vue
index ac116398..58b66861 100644
--- a/web/src/views/HomeView.vue
+++ b/web/src/views/HomeView.vue
@@ -91,7 +91,7 @@ const goToChat = async () => {
} else {
// 没有可用智能体,回退到chat页面
router.push("/chat");
- }
+}
}
} catch (error) {
console.error('跳转到智能体页面失败:', error);
diff --git a/web/src/views/SettingView.vue b/web/src/views/SettingView.vue
index 488e6b45..0a0fd6ae 100644
--- a/web/src/views/SettingView.vue
+++ b/web/src/views/SettingView.vue
@@ -379,6 +379,7 @@ import HeaderComponent from '@/components/HeaderComponent.vue';
import TableConfigComponent from '@/components/TableConfigComponent.vue';
import { notification, Button } from 'ant-design-vue';
import { modelIcons } from '@/utils/modelIcon'
+import { systemConfigApi } from '@/apis/admin_api'
const configStore = useConfigStore()
@@ -584,15 +585,19 @@ onUnmounted(() => {
const sendRestart = () => {
console.log('Restarting...')
message.loading({ content: '重新加载模型中', key: "restart", duration: 0 });
- fetch('/api/restart', {
- method: 'POST',
- }).then(() => {
- console.log('Restarted')
- message.success({ content: '重新加载完成!', key: "restart", duration: 2 });
- setTimeout(() => {
- window.location.reload()
- }, 200)
- })
+
+ systemConfigApi.restartServer()
+ .then(() => {
+ console.log('Restarted')
+ message.success({ content: '重新加载完成!', key: "restart", duration: 2 });
+ setTimeout(() => {
+ window.location.reload()
+ }, 200)
+ })
+ .catch(error => {
+ console.error('重启服务失败:', error)
+ message.error({ content: `重启失败: ${error.message}`, key: "restart", duration: 2 });
+ });
}
// 获取模型提供商的模型列表
diff --git a/web/src/views/ToolsView.vue b/web/src/views/ToolsView.vue
deleted file mode 100644
index bee5f4b3..00000000
--- a/web/src/views/ToolsView.vue
+++ /dev/null
@@ -1,111 +0,0 @@
-
-
-
-
-
-
-