From 523c4740014e426b70922c281ba549a1f1f641da Mon Sep 17 00:00:00 2001 From: susie-laptop Date: Wed, 19 Mar 2025 20:22:02 -0400 Subject: [PATCH] [dev]add mock data --- src/layouts/HeaderWithNav.jsx | 3 +- src/pages/Chat/ChatWindow.jsx | 11 +- src/pages/Chat/NewChat.jsx | 113 ++--- .../Detail/KnowledgeBaseDetail.jsx | 21 +- .../components/KnowledgeBaseList.jsx | 13 +- .../components/KnowledgeCard.jsx | 12 +- .../components/PendingRequests.jsx | 170 +------- src/services/mockApi.js | 407 +++++++++--------- src/store/auth/auth.thunk.js | 2 + .../knowledgeBase/knowledgeBase.slice.js | 53 +-- .../knowledgeBase/knowledgeBase.thunks.js | 13 +- src/store/permissions/permissions.thunks.js | 7 +- 12 files changed, 363 insertions(+), 462 deletions(-) diff --git a/src/layouts/HeaderWithNav.jsx b/src/layouts/HeaderWithNav.jsx index 4e31724..a7eb64d 100644 --- a/src/layouts/HeaderWithNav.jsx +++ b/src/layouts/HeaderWithNav.jsx @@ -21,7 +21,8 @@ export default function HeaderWithNav() { const isActive = (path) => { return location.pathname.startsWith(path); }; - + console.log('user', user); + // 检查用户是否有管理权限(leader 或 admin) const hasManagePermission = user && (user.role === 'leader' || user.role === 'admin'); diff --git a/src/pages/Chat/ChatWindow.jsx b/src/pages/Chat/ChatWindow.jsx index b8cf4c4..8c106ee 100644 --- a/src/pages/Chat/ChatWindow.jsx +++ b/src/pages/Chat/ChatWindow.jsx @@ -4,6 +4,7 @@ import { fetchMessages, sendMessage } from '../../store/chat/chat.messages.thunk import { resetMessages, resetSendMessageStatus } from '../../store/chat/chat.slice'; import { showNotification } from '../../store/notification.slice'; import SvgIcon from '../../components/SvgIcon'; +import { fetchKnowledgeBases } from '../../store/knowledgeBase/knowledgeBase.thunks'; export default function ChatWindow({ chatId, knowledgeBaseId }) { const dispatch = useDispatch(); @@ -18,8 +19,9 @@ export default function ChatWindow({ chatId, knowledgeBaseId }) { } = useSelector((state) => state.chat.messages); const { status: sendStatus, error: sendError } = useSelector((state) => state.chat.sendMessage); const knowledgeBase = useSelector((state) => - state.knowledgeBase.list.items.find((kb) => kb.id === knowledgeBaseId) + state.knowledgeBase.list.data?.items?.find((kb) => kb.id === knowledgeBaseId) ); + const isLoadingKnowledgeBases = useSelector((state) => state.knowledgeBase.list.isLoading); // 获取聊天消息 useEffect(() => { @@ -51,6 +53,13 @@ export default function ChatWindow({ chatId, knowledgeBaseId }) { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages]); + // 从 Redux store 获取知识库信息 + useEffect(() => { + if (!knowledgeBase && !isLoadingKnowledgeBases) { + dispatch(fetchKnowledgeBases()); + } + }, [dispatch, knowledgeBase, isLoadingKnowledgeBases]); + const handleSendMessage = (e) => { e.preventDefault(); diff --git a/src/pages/Chat/NewChat.jsx b/src/pages/Chat/NewChat.jsx index 873fe50..313df22 100644 --- a/src/pages/Chat/NewChat.jsx +++ b/src/pages/Chat/NewChat.jsx @@ -1,87 +1,92 @@ import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { showNotification } from '../../store/notification.slice'; -import { get } from '../../services/api'; +import { fetchKnowledgeBases } from '../../store/knowledgeBase/knowledgeBase.thunks'; import SvgIcon from '../../components/SvgIcon'; export default function NewChat() { const navigate = useNavigate(); const dispatch = useDispatch(); - const [knowledgeBases, setKnowledgeBases] = useState([]); const [loading, setLoading] = useState(true); + // 从 Redux store 获取知识库数据 + const { data, status, error } = useSelector((state) => state.knowledgeBase.list); + const knowledgeBases = data?.items || []; + const isLoading = status === 'loading'; + // 获取知识库列表 useEffect(() => { - const fetchKnowledgeBases = async () => { - try { - setLoading(true); - const response = await get('/knowledge-bases/'); + if (!data?.items?.length && status !== 'loading') { + dispatch(fetchKnowledgeBases()); + } + }, [dispatch, data, status]); - // 过滤出有 can_read 权限的知识库 - const readableKnowledgeBases = response.data.items.filter( - (kb) => kb.permissions && kb.permissions.can_read === true - ); + // 监听错误状态 + useEffect(() => { + if (status === 'failed' && error) { + dispatch( + showNotification({ + message: `获取知识库列表失败: ${error.message || error}`, + type: 'danger', + }) + ); + } + }, [status, error, dispatch]); - setKnowledgeBases(readableKnowledgeBases); - } catch (error) { - console.error('获取知识库列表失败:', error); - dispatch( - showNotification({ - message: '获取知识库列表失败,请稍后重试', - type: 'danger', - }) - ); - } finally { - setLoading(false); - } - }; - - fetchKnowledgeBases(); - }, [dispatch]); + // 过滤出有 can_read 权限的知识库 + const readableKnowledgeBases = knowledgeBases.filter((kb) => kb.permissions && kb.permissions.can_read === true); const handleSelectKnowledgeBase = (knowledgeBaseId) => { // 创建新聊天并导航到聊天页面 navigate(`/chat/${knowledgeBaseId}`); }; - return ( -
-
-

选择知识库开始聊天

+ // 渲染加载状态 + if (isLoading) { + return ( +
+
+ 加载中... +
+ ); + } - {loading ? ( -
-
- 加载中... -
-
- ) : knowledgeBases.length === 0 ? ( -
-

没有可用的知识库,请联系管理员获取权限

-
- ) : ( -
- {knowledgeBases.map((kb) => ( + return ( +
+

选择知识库开始聊天

+
+ {readableKnowledgeBases.length > 0 ? ( + readableKnowledgeBases.map((kb) => (
handleSelectKnowledgeBase(kb.id)} - style={{ cursor: 'pointer' }} > -
-

{kb.name}

-

{kb.description}

-
- 文档数: {kb.document_count || 0} +
+
{kb.name}
+

{kb.desc || kb.description || ''}

+
+ + + {kb.document_count} 文档 + + + + {new Date(kb.create_time).toLocaleDateString()} +
- ))} -
- )} + )) + ) : ( +
+
暂无可访问的知识库,请先申请知识库访问权限
+
+ )} +
); } diff --git a/src/pages/KnowledgeBase/Detail/KnowledgeBaseDetail.jsx b/src/pages/KnowledgeBase/Detail/KnowledgeBaseDetail.jsx index 6e35482..8e42a14 100644 --- a/src/pages/KnowledgeBase/Detail/KnowledgeBaseDetail.jsx +++ b/src/pages/KnowledgeBase/Detail/KnowledgeBaseDetail.jsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { useSelector, useDispatch } from 'react-redux'; import { showNotification } from '../../../store/notification.slice'; +import { fetchKnowledgeBases } from '../../../store/knowledgeBase/knowledgeBase.thunks'; import SvgIcon from '../../../components/SvgIcon'; import DatasetTab from './DatasetTab'; import SettingsTab from './SettingsTab'; @@ -13,8 +14,16 @@ export default function KnowledgeBaseDetail() { const [activeTab, setActiveTab] = useState(tab === 'settings' ? 'settings' : 'datasets'); // Get knowledge base details from Redux store - const { items: knowledgeBases } = useSelector((state) => state.knowledgeBase.list); - const knowledgeBase = knowledgeBases.find((kb) => kb.id === id); + const { data, status } = useSelector((state) => state.knowledgeBase.list); + const knowledgeBase = data?.items?.find((kb) => kb.id === id); + const isLoading = status === 'loading'; + + // Fetch knowledge bases if not available + useEffect(() => { + if (!data?.items?.length && status !== 'loading') { + dispatch(fetchKnowledgeBases()); + } + }, [dispatch, data, status]); // Update active tab when URL changes useEffect(() => { @@ -25,7 +34,7 @@ export default function KnowledgeBaseDetail() { // If knowledge base not found in Redux store, show notification and redirect useEffect(() => { - if (!knowledgeBase && knowledgeBases.length > 0) { + if (!knowledgeBase && data?.items?.length > 0 && !isLoading) { dispatch( showNotification({ message: '未找到知识库,请返回知识库列表', @@ -34,7 +43,7 @@ export default function KnowledgeBaseDetail() { ); navigate('/knowledge-base'); } - }, [knowledgeBase, knowledgeBases, dispatch, navigate]); + }, [knowledgeBase, data, isLoading, dispatch, navigate]); // Handle tab change const handleTabChange = (tab) => { @@ -43,7 +52,7 @@ export default function KnowledgeBaseDetail() { }; // Show loading state if knowledge base not loaded yet - if (!knowledgeBase) { + if (isLoading || !knowledgeBase) { return (
@@ -61,7 +70,7 @@ export default function KnowledgeBaseDetail() {
{knowledgeBase.name}

- {knowledgeBase.desc || knowledgeBase.description || ''} + {knowledgeBase.desc || ''}


diff --git a/src/pages/KnowledgeBase/components/KnowledgeBaseList.jsx b/src/pages/KnowledgeBase/components/KnowledgeBaseList.jsx index 9aea72e..4b51caf 100644 --- a/src/pages/KnowledgeBase/components/KnowledgeBaseList.jsx +++ b/src/pages/KnowledgeBase/components/KnowledgeBaseList.jsx @@ -5,7 +5,7 @@ import KnowledgeCard from './KnowledgeCard'; * 知识库列表组件 */ const KnowledgeBaseList = ({ knowledgeBases, isSearching, onCardClick, onRequestAccess, onDelete }) => { - if (knowledgeBases.length === 0) { + if (!knowledgeBases?.length) { return (
{isSearching ? '没有找到匹配的知识库' : '暂无知识库,请创建新的知识库'} @@ -19,15 +19,18 @@ const KnowledgeBaseList = ({ knowledgeBases, isSearching, onCardClick, onRequest onCardClick(item.id, item.permissions)} onRequestAccess={onRequestAccess} onDelete={(e) => onDelete(e, item.id)} + type={item.type} + department={item.department} + group={item.group} /> ))} diff --git a/src/pages/KnowledgeBase/components/KnowledgeCard.jsx b/src/pages/KnowledgeBase/components/KnowledgeCard.jsx index 0930673..022f478 100644 --- a/src/pages/KnowledgeBase/components/KnowledgeCard.jsx +++ b/src/pages/KnowledgeBase/components/KnowledgeCard.jsx @@ -13,6 +13,9 @@ export default function KnowledgeCard({ onClick, onRequestAccess, onDelete, + type, + department, + group, }) { const navigate = useNavigate(); @@ -41,7 +44,7 @@ export default function KnowledgeCard({ return (
-
{title}
+
{permissions && permissions.can_delete && (
+ {/*
+ + {type === 'private' ? '私有' : '公开'} + + {department && {department}} + {group && {group}} +
*/}
{access === 'full' ? ( diff --git a/src/pages/Permissions/components/PendingRequests.jsx b/src/pages/Permissions/components/PendingRequests.jsx index 5025dd2..ab16175 100644 --- a/src/pages/Permissions/components/PendingRequests.jsx +++ b/src/pages/Permissions/components/PendingRequests.jsx @@ -10,136 +10,6 @@ import { resetApproveRejectStatus } from '../../../store/permissions/permissions import './PendingRequests.css'; // 引入外部CSS文件 import SvgIcon from '../../../components/SvgIcon'; -// 模拟数据 -const mockPendingRequests = [ - { - id: 1, - applicant: { - name: '王五', - department: '达人组', - }, - knowledge_base: { - name: '达人直播数据报告', - }, - permissions: { - can_read: true, - can_edit: true, - can_delete: false, - }, - reason: '需要查看和编辑直播数据报告', - created_at: '2024-01-07T10:30:00Z', - expires_at: null, - }, - { - id: 2, - applicant: { - name: '赵六', - department: '直播组', - }, - knowledge_base: { - name: '人力资源政策文件', - }, - permissions: { - can_read: true, - can_edit: false, - can_delete: false, - }, - reason: '需要了解最新的人力资源政策', - created_at: '2024-01-06T14:20:00Z', - expires_at: '2025-01-06T14:20:00Z', - }, - { - id: 3, - applicant: { - name: '钱七', - department: '市场部', - }, - knowledge_base: { - name: '市场分析报告', - }, - permissions: { - can_read: true, - can_edit: false, - can_delete: false, - }, - reason: '需要了解市场趋势', - created_at: '2024-01-05T09:15:00Z', - expires_at: '2024-07-05T09:15:00Z', - }, - { - id: 4, - applicant: { - name: '孙八', - department: '技术部', - }, - knowledge_base: { - name: '技术架构文档', - }, - permissions: { - can_read: true, - can_edit: true, - can_delete: true, - }, - reason: '需要进行技术架构更新', - created_at: '2024-01-04T16:45:00Z', - expires_at: null, - }, - { - id: 5, - applicant: { - name: '周九', - department: '产品部', - }, - knowledge_base: { - name: '产品规划文档', - }, - permissions: { - can_read: true, - can_edit: true, - can_delete: false, - }, - reason: '需要参与产品规划讨论', - created_at: '2024-01-03T11:30:00Z', - expires_at: '2024-12-31T23:59:59Z', - }, - { - id: 6, - applicant: { - name: '吴十', - department: '设计部', - }, - knowledge_base: { - name: '设计规范文档', - }, - permissions: { - can_read: true, - can_edit: false, - can_delete: false, - }, - reason: '需要参考设计规范', - created_at: '2024-01-02T14:20:00Z', - expires_at: '2024-06-30T23:59:59Z', - }, - { - id: 7, - applicant: { - name: '郑十一', - department: '财务部', - }, - knowledge_base: { - name: '财务报表', - }, - permissions: { - can_read: true, - can_edit: false, - can_delete: false, - }, - reason: '需要查看财务数据', - created_at: '2024-01-01T09:00:00Z', - expires_at: null, - }, -]; - // 每页显示的申请数量 const PAGE_SIZE = 5; @@ -173,31 +43,16 @@ export default function PendingRequests() { const fetchData = async () => { try { setFetchStatus('loading'); - // 尝试从API获取数据 const result = await dispatch(fetchPermissionsThunk()); - - // 检查API返回的数据 - if (result && result.payload && result.payload.length > 0) { - // 使用API返回的数据 + if (result.payload) { setPendingRequests(result.payload); setTotalPages(Math.ceil(result.payload.length / PAGE_SIZE)); - console.log('使用API返回的待处理申请数据'); - } else { - // API返回的数据为空,使用模拟数据 - console.log('API返回的待处理申请数据为空,使用模拟数据'); - setPendingRequests(mockPendingRequests); - setTotalPages(Math.ceil(mockPendingRequests.length / PAGE_SIZE)); } setFetchStatus('succeeded'); } catch (error) { - console.error('获取待处理申请失败:', error); - setFetchError('获取待处理申请失败'); + console.error('获取待处理申请列表失败:', error); + setFetchError(error.message || '获取待处理申请列表失败'); setFetchStatus('failed'); - - // API请求失败,使用模拟数据作为后备 - console.log('API请求失败,使用模拟数据作为后备'); - setPendingRequests(mockPendingRequests); - setTotalPages(Math.ceil(mockPendingRequests.length / PAGE_SIZE)); } }; @@ -318,7 +173,7 @@ export default function PendingRequests() { const getCurrentPageData = () => { const startIndex = (currentPage - 1) * PAGE_SIZE; const endIndex = startIndex + PAGE_SIZE; - return pendingRequests.slice(startIndex, endIndex); + return Array.isArray(pendingRequests) ? pendingRequests.slice(startIndex, endIndex) : []; }; // 处理页码变化 @@ -401,14 +256,13 @@ export default function PendingRequests() {
handleRowClick(request)}>
-
{request.applicant.name}
-

{request.applicant.department}

+
{request.applicant}
{new Date(request.created_at).toLocaleDateString()}
-

申请访问:{request.knowledge_base.name}

+

申请访问:{request.knowledge_base}

{request.permissions.can_edit ? ( 申请人信息
- {(selectedRequest.applicant.name || selectedRequest.applicant).charAt(0)} + {selectedRequest.applicant.charAt(0)}
-
- {selectedRequest.applicant.name || selectedRequest.applicant} -
-

- {selectedRequest.applicant.department || '无归属部门'} -

+
{selectedRequest.applicant}
@@ -493,8 +342,7 @@ export default function PendingRequests() {
知识库信息

- 名称:{' '} - {selectedRequest.knowledge_base.name || selectedRequest.knowledge_base} + ID: {selectedRequest.knowledge_base}

diff --git a/src/services/mockApi.js b/src/services/mockApi.js index c2afe2f..ad97585 100644 --- a/src/services/mockApi.js +++ b/src/services/mockApi.js @@ -295,235 +295,230 @@ const mockDeleteChat = (id) => { // 模拟聊天消息数据 const chatMessages = {}; -// 模拟待处理权限申请 +// 权限申请列表的 mock 数据 const mockPendingRequests = [ { id: 1, - applicant: { - name: '王五', - department: '达人组', - }, - knowledge_base: { - name: '达人直播数据报告', - }, + knowledge_base: 'f13c4bdb-eb03-4ce2-b83c-30917351fb72', + applicant: 'f2799611-7a3d-436d-b3fa-3789bdd877e2', permissions: { + can_edit: false, can_read: true, - can_edit: true, can_delete: false, }, - reason: '需要查看和编辑直播数据报告', - created_at: '2024-01-07T10:30:00Z', - expires_at: null, + status: 'pending', + reason: '需要访问知识库进行学习', + response_message: null, + expires_at: '2025-03-19T00:17:43.781000Z', + created_at: '2025-03-12T00:17:44.044351Z', + updated_at: '2025-03-12T00:17:44.044369Z', }, { id: 2, - applicant: { - name: '赵六', - department: '直播组', - }, - knowledge_base: { - name: '人力资源政策文件', - }, + knowledge_base: 'f13c4bdb-eb03-4ce2-b83c-30917351fb73', + applicant: 'f2799611-7a3d-436d-b3fa-3789bdd877e3', permissions: { + can_edit: true, can_read: true, - can_edit: false, can_delete: false, }, - reason: '需要了解最新的人力资源政策', - created_at: '2024-01-06T14:20:00Z', - expires_at: '2025-01-06T14:20:00Z', + status: 'pending', + reason: '需要编辑和更新文档', + response_message: null, + expires_at: '2025-03-20T00:17:43.781000Z', + created_at: '2025-03-12T00:17:44.044351Z', + updated_at: '2025-03-12T00:17:44.044369Z', }, +]; + +// 用户权限列表的 mock 数据 +const mockUserPermissions = [ { - id: 3, - applicant: { - name: '钱七', - department: '市场部', + id: 'perm-001', + user: { + id: 'user-001', + username: 'johndoe', + name: 'John Doe', + email: 'john@example.com', + department: '研发部', + group: '前端开发组', }, knowledge_base: { - name: '市场分析报告', - }, - permissions: { - can_read: true, - can_edit: false, - can_delete: false, - }, - reason: '需要了解市场趋势', - created_at: '2024-01-05T09:15:00Z', - expires_at: '2024-07-05T09:15:00Z', - }, - { - id: 4, - applicant: { - name: '孙八', - department: '技术部', - }, - knowledge_base: { - name: '技术架构文档', + id: 'kb-001', + name: 'Frontend Development Guide', }, permissions: { can_read: true, can_edit: true, can_delete: true, + can_manage: true, + }, + granted_at: '2024-01-15T10:00:00Z', + granted_by: { + id: 'user-admin', + username: 'admin', + name: 'System Admin', }, - reason: '需要进行技术架构更新', - created_at: '2024-01-04T16:45:00Z', - expires_at: null, }, { - id: 5, - applicant: { - name: '周九', - department: '产品部', + id: 'perm-002', + user: { + id: 'user-002', + username: 'janedoe', + name: 'Jane Doe', + email: 'jane@example.com', + department: '研发部', + group: '前端开发组', }, knowledge_base: { - name: '产品规划文档', + id: 'kb-001', + name: 'Frontend Development Guide', }, permissions: { can_read: true, can_edit: true, can_delete: false, + can_manage: false, + }, + granted_at: '2024-01-20T14:30:00Z', + granted_by: { + id: 'user-001', + username: 'johndoe', + name: 'John Doe', }, - reason: '需要参与产品规划讨论', - created_at: '2024-01-03T11:30:00Z', - expires_at: '2024-12-31T23:59:59Z', }, { - id: 6, - applicant: { - name: '吴十', - department: '设计部', + id: 'perm-003', + user: { + id: 'user-003', + username: 'alexsmith', + name: 'Alex Smith', + email: 'alex@example.com', + department: '研发部', + group: '后端开发组', }, knowledge_base: { - name: '设计规范文档', + id: 'kb-001', + name: 'Frontend Development Guide', }, permissions: { can_read: true, can_edit: false, can_delete: false, + can_manage: false, }, - reason: '需要参考设计规范', - created_at: '2024-01-02T14:20:00Z', - expires_at: '2024-06-30T23:59:59Z', - }, - { - id: 7, - applicant: { - name: '郑十一', - department: '财务部', + granted_at: '2024-02-01T09:15:00Z', + granted_by: { + id: 'user-001', + username: 'johndoe', + name: 'John Doe', }, - knowledge_base: { - name: '财务报表', - }, - permissions: { - can_read: true, - can_edit: false, - can_delete: false, - }, - reason: '需要查看财务数据', - created_at: '2024-01-01T09:00:00Z', - expires_at: null, }, ]; -// 模拟用户权限详情 -const mockUserPermissions = { - 'user-001': [ - { - knowledge_base: { - id: 'kb-001', - name: '达人直播数据报告', - department: '达人组', +// Mock API handlers for permissions +const mockPermissionApi = { + // 获取待处理的权限申请列表 + getPendingRequests: () => { + return { + code: 200, + message: 'success', + data: { + items: mockPendingRequests, + total: mockPendingRequests.length, }, - permission: { - can_read: true, - can_edit: true, - can_admin: false, + }; + }, + + // 获取用户权限列表 + getUserPermissions: (knowledgeBaseId) => { + const permissions = mockUserPermissions.filter((perm) => perm.knowledge_base.id === knowledgeBaseId); + return { + code: 200, + message: 'success', + data: { + items: permissions, + total: permissions.length, }, - last_access_time: '2024-03-10T14:30:00Z', - }, - { - knowledge_base: { - id: 'kb-002', - name: '人力资源政策文件', - department: '人力资源组', - }, - permission: { - can_read: true, - can_edit: false, - can_admin: false, - }, - last_access_time: '2024-03-08T09:15:00Z', - }, - { - knowledge_base: { - id: 'kb-003', - name: '市场分析报告', - department: '市场部', - }, - permission: { - can_read: true, - can_edit: false, - can_admin: false, - }, - last_access_time: null, - }, - ], - 'user-002': [ - { - knowledge_base: { - id: 'kb-001', - name: '达人直播数据报告', - department: '达人组', - }, - permission: { - can_read: true, - can_edit: false, - can_admin: false, - }, - last_access_time: '2024-03-05T10:20:00Z', - }, - { - knowledge_base: { - id: 'kb-004', - name: '产品规划文档', - department: '产品部', - }, - permission: { - can_read: true, - can_edit: true, - can_admin: true, - }, - last_access_time: '2024-03-15T11:20:00Z', - }, - ], - 'user-003': [ - { - knowledge_base: { - id: 'kb-003', - name: '市场分析报告', - department: '市场部', - }, - permission: { - can_read: true, - can_edit: true, - can_admin: false, - }, - last_access_time: '2024-03-12T15:40:00Z', - }, - { - knowledge_base: { - id: 'kb-005', - name: 'UI/UX设计指南', - department: '设计部', - }, - permission: { - can_read: true, - can_edit: false, - can_admin: false, - }, - last_access_time: '2024-03-01T09:10:00Z', - }, - ], + }; + }, + + // 处理权限申请 + handlePermissionRequest: (requestId, action) => { + const request = mockPendingRequests.find((req) => req.id === requestId); + if (!request) { + return { + code: 404, + message: 'Permission request not found', + }; + } + + request.status = action === 'approve' ? 'approved' : 'rejected'; + + if (action === 'approve') { + // 如果批准,添加新的权限记录 + const newPermission = { + id: `perm-${Date.now()}`, + user: request.user, + knowledge_base: request.knowledge_base, + permissions: { + can_read: true, + can_edit: request.request_type === 'edit', + can_delete: false, + can_manage: false, + }, + granted_at: new Date().toISOString(), + granted_by: mockCurrentUser, + }; + mockUserPermissions.push(newPermission); + } + + return { + code: 200, + message: 'success', + data: request, + }; + }, + + // 更新用户权限 + updateUserPermission: (permissionId, permissions) => { + const permission = mockUserPermissions.find((perm) => perm.id === permissionId); + if (!permission) { + return { + code: 404, + message: 'Permission not found', + }; + } + + permission.permissions = { + ...permission.permissions, + ...permissions, + }; + + return { + code: 200, + message: 'success', + data: permission, + }; + }, + + // 删除用户权限 + deleteUserPermission: (permissionId) => { + const index = mockUserPermissions.findIndex((perm) => perm.id === permissionId); + if (index === -1) { + return { + code: 404, + message: 'Permission not found', + }; + } + + mockUserPermissions.splice(index, 1); + + return { + code: 200, + message: 'success', + }; + }, }; // Mock API functions @@ -536,13 +531,7 @@ export const mockGet = async (url, config = {}) => { // Get current user if (url === '/users/me/') { return { - data: { - code: 200, - message: 'success', - data: { - user: mockUsers[0], // 默认返回第一个用户 - }, - }, + user: mockUsers[0], // 默认返回第一个用户 }; } @@ -550,7 +539,7 @@ export const mockGet = async (url, config = {}) => { if (url === '/knowledge-bases/') { const params = config.params || { page: 1, page_size: 10 }; const result = paginate(knowledgeBases, params.page_size, params.page); - + return { data: { code: 200, @@ -670,7 +659,8 @@ export const mockGet = async (url, config = {}) => { code: 200, message: 'success', data: { - pending_requests: mockPendingRequests, + items: mockPendingRequests, + total: mockPendingRequests.length, }, }, }; @@ -721,22 +711,18 @@ export const mockPost = async (url, data) => { const token = `mock-jwt-token-${uuidv4()}`; return { + code: 200, + message: '登录成功', data: { - code: 200, - message: '登录成功', - data: { - token, - user: { - id: user.id, - username: user.username, - email: user.email, - name: user.name, - department: user.department, - group: user.group, - role: user.role, - avatar: user.avatar, - }, - }, + token, + id: user.id, + username: user.username, + email: user.email, + name: user.name, + department: user.department, + group: user.group, + role: user.role, + avatar: user.avatar, }, }; } @@ -1003,3 +989,18 @@ export const mockDelete = async (url) => { export const resetMockData = () => { knowledgeBases = [...mockKnowledgeBases]; }; + +// 添加权限相关的 API 处理 +export const mockApi = { + // ... existing api handlers ... + + // 权限管理相关的 API + 'GET /api/permissions/pending': () => mockPermissionApi.getPendingRequests(), + 'GET /api/permissions/users/:knowledgeBaseId': (params) => + mockPermissionApi.getUserPermissions(params.knowledgeBaseId), + 'POST /api/permissions/handle/:requestId': (params, body) => + mockPermissionApi.handlePermissionRequest(params.requestId, body.action), + 'PUT /api/permissions/:permissionId': (params, body) => + mockPermissionApi.updateUserPermission(params.permissionId, body.permissions), + 'DELETE /api/permissions/:permissionId': (params) => mockPermissionApi.deleteUserPermission(params.permissionId), +}; diff --git a/src/store/auth/auth.thunk.js b/src/store/auth/auth.thunk.js index 5894af4..71fbd8d 100644 --- a/src/store/auth/auth.thunk.js +++ b/src/store/auth/auth.thunk.js @@ -11,6 +11,8 @@ export const loginThunk = createAsyncThunk( async ({ username, password }, { rejectWithValue, dispatch }) => { try { const { message, data } = await post('/auth/login/', { username, password }); + console.log('data', data); + if (!data) { throw new Error(message || 'Something went wrong'); } diff --git a/src/store/knowledgeBase/knowledgeBase.slice.js b/src/store/knowledgeBase/knowledgeBase.slice.js index 9b7ed7c..5ea1f99 100644 --- a/src/store/knowledgeBase/knowledgeBase.slice.js +++ b/src/store/knowledgeBase/knowledgeBase.slice.js @@ -11,20 +11,24 @@ import { const initialState = { // List state list: { - items: [], - total: 0, - page: 1, - page_size: 10, + data: { + items: [], + total: 0, + page: 1, + page_size: 10, + }, status: 'idle', // 'idle' | 'loading' | 'succeeded' | 'failed' error: null, }, // Search state search: { - items: [], - total: 0, - page: 1, - page_size: 10, - keyword: '', + data: { + items: [], + total: 0, + page: 1, + page_size: 10, + keyword: '', + }, status: 'idle', // 'idle' | 'loading' | 'succeeded' | 'failed' error: null, }, @@ -62,11 +66,13 @@ const knowledgeBaseSlice = createSlice({ }, resetSearchState: (state) => { state.search = { - items: [], - total: 0, - page: 1, - page_size: 10, - keyword: '', + data: { + items: [], + total: 0, + page: 1, + page_size: 10, + keyword: '', + }, status: 'idle', error: null, }; @@ -93,15 +99,12 @@ const knowledgeBaseSlice = createSlice({ state.search.status = 'loading'; // Store the keyword for reference if (action.meta.arg.keyword) { - state.search.keyword = action.meta.arg.keyword; + state.search.data.keyword = action.meta.arg.keyword; } }) .addCase(searchKnowledgeBases.fulfilled, (state, action) => { state.search.status = 'succeeded'; - state.search.items = action.payload.items; - state.search.total = action.payload.total; - state.search.page = action.payload.page; - state.search.page_size = action.payload.page_size; + state.search.data = action.payload; state.search.error = null; }) .addCase(searchKnowledgeBases.rejected, (state, action) => { @@ -146,14 +149,14 @@ const knowledgeBaseSlice = createSlice({ .addCase(updateKnowledgeBase.fulfilled, (state, action) => { state.operations.status = 'succeeded'; // Update in list if present - const index = state.list.items.findIndex((item) => item.id === action.payload.id); + const index = state.list.data.items.findIndex((item) => item.id === action.payload.id); if (index !== -1) { - state.list.items[index] = action.payload; + state.list.data.items[index] = action.payload; } // Update in search results if present - const searchIndex = state.search.items.findIndex((item) => item.id === action.payload.id); + const searchIndex = state.search.data.items.findIndex((item) => item.id === action.payload.id); if (searchIndex !== -1) { - state.search.items[searchIndex] = action.payload; + state.search.data.items[searchIndex] = action.payload; } // Update current if it's the same knowledge base if (state.current.data && state.current.data.id === action.payload.id) { @@ -174,9 +177,9 @@ const knowledgeBaseSlice = createSlice({ .addCase(deleteKnowledgeBase.fulfilled, (state, action) => { state.operations.status = 'succeeded'; // Remove from list if present - state.list.items = state.list.items.filter((item) => item.id !== action.payload); + state.list.data.items = state.list.data.items.filter((item) => item.id !== action.payload); // Remove from search results if present - state.search.items = state.search.items.filter((item) => item.id !== action.payload); + state.search.data.items = state.search.data.items.filter((item) => item.id !== action.payload); // Reset current if it's the same knowledge base if (state.current.data && state.current.data.id === action.payload) { state.current.data = null; diff --git a/src/store/knowledgeBase/knowledgeBase.thunks.js b/src/store/knowledgeBase/knowledgeBase.thunks.js index 757ba04..06baa1a 100644 --- a/src/store/knowledgeBase/knowledgeBase.thunks.js +++ b/src/store/knowledgeBase/knowledgeBase.thunks.js @@ -35,10 +35,13 @@ export const searchKnowledgeBases = createAsyncThunk( async ({ keyword, page = 1, page_size = 10 }, { rejectWithValue }) => { try { const response = await get('/knowledge-bases/search/', { - keyword, - page, - page_size, + params: { keyword, page, page_size }, }); + + // 处理新的返回格式 + if (response.data && response.data.code === 200) { + return response.data.data; + } return response.data; } catch (error) { return rejectWithValue(error.response?.data || 'Failed to search knowledge bases'); @@ -75,6 +78,10 @@ export const getKnowledgeBaseById = createAsyncThunk( async (id, { rejectWithValue }) => { try { const response = await get(`/knowledge-bases/${id}/`); + // 处理新的返回格式 + if (response.data && response.data.code === 200) { + return response.data.data.knowledge_base; + } return response.data; } catch (error) { return rejectWithValue(error.response?.data || 'Failed to get knowledge base details'); diff --git a/src/store/permissions/permissions.thunks.js b/src/store/permissions/permissions.thunks.js index a512d0b..8cacafe 100644 --- a/src/store/permissions/permissions.thunks.js +++ b/src/store/permissions/permissions.thunks.js @@ -6,8 +6,11 @@ export const fetchPermissionsThunk = createAsyncThunk( 'permissions/fetchPermissions', async (_, { rejectWithValue }) => { try { - const response = await get('/permissions/'); - return response || []; + const response = await get('/permissions/pending/'); + if (response?.data?.code === 200) { + return response.data.data.items || []; + } + return rejectWithValue('获取权限申请列表失败'); } catch (error) { console.error('获取权限申请列表失败:', error); return rejectWithValue('获取权限申请列表失败');