@@ -26,13 +46,15 @@ export default function KnowledgeCard({ id, title, description, documents, date,
-
{description}
+
+ {description}
+
{documents} 文档
diff --git a/src/router/router.jsx b/src/router/router.jsx
index 2fcf7e3..8279f97 100644
--- a/src/router/router.jsx
+++ b/src/router/router.jsx
@@ -2,7 +2,7 @@ import React, { Suspense } from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import Mainlayout from '../layouts/Mainlayout';
import KnowledgeBase from '../pages/KnowledgeBase/KnowledgeBase';
-import KnowledgeBaseDetail from '../pages/KnowledgeBase/KnowledgeBaseDetail';
+import KnowledgeBaseDetail from '../pages/KnowledgeBase/Detail/KnowledgeBaseDetail';
import Chat from '../pages/Chat/Chat';
import Loading from '../components/Loading';
import Login from '../pages/Auth/Login';
diff --git a/src/services/api.js b/src/services/api.js
index 80e61ea..894c2ba 100644
--- a/src/services/api.js
+++ b/src/services/api.js
@@ -1,8 +1,12 @@
import axios from 'axios';
import CryptoJS from 'crypto-js';
+import { mockGet, mockPost, mockPut, mockDel } from './mockApi';
const secretKey = import.meta.env.VITE_SECRETKEY;
+// Flag to enable/disable mock API
+const USE_MOCK_API = true; // Set to false to use real API
+
// Create Axios instance with base URL
const api = axios.create({
baseURL: '/api',
@@ -58,12 +62,30 @@ api.interceptors.response.use(
// Define common HTTP methods
const get = async (url, params = {}) => {
+ if (USE_MOCK_API) {
+ try {
+ const response = await mockGet(url, params);
+ return { data: response };
+ } catch (error) {
+ return Promise.reject(error);
+ }
+ }
+
const res = await api.get(url, { params });
return res.data;
};
// Handle POST requests for JSON data
const post = async (url, data, isMultipart = false) => {
+ if (USE_MOCK_API) {
+ try {
+ const response = await mockPost(url, data);
+ return { data: response };
+ } catch (error) {
+ return Promise.reject(error);
+ }
+ }
+
const headers = isMultipart
? { 'Content-Type': 'multipart/form-data' } // For file uploads
: { 'Content-Type': 'application/json' }; // For JSON data
@@ -74,6 +96,15 @@ const post = async (url, data, isMultipart = false) => {
// Handle PUT requests
const put = async (url, data) => {
+ if (USE_MOCK_API) {
+ try {
+ const response = await mockPut(url, data);
+ return { data: response };
+ } catch (error) {
+ return Promise.reject(error);
+ }
+ }
+
const res = await api.put(url, data, {
headers: { 'Content-Type': 'application/json' },
});
@@ -82,11 +113,25 @@ const put = async (url, data) => {
// Handle DELETE requests
const del = async (url) => {
+ if (USE_MOCK_API) {
+ try {
+ const response = await mockDel(url);
+ return { data: response };
+ } catch (error) {
+ return Promise.reject(error);
+ }
+ }
+
const res = await api.delete(url);
return res.data;
};
const upload = async (url, data) => {
+ if (USE_MOCK_API) {
+ console.warn('[MOCK API] Upload functionality is not mocked');
+ return { success: true, message: 'Mock upload successful' };
+ }
+
const axiosInstance = await axios.create({
baseURL: '/api',
headers: {
@@ -96,4 +141,5 @@ const upload = async (url, data) => {
const res = await axiosInstance.post(url, data);
return res.data;
};
+
export { get, post, put, del, upload };
diff --git a/src/services/mockApi.js b/src/services/mockApi.js
new file mode 100644
index 0000000..ddbacd8
--- /dev/null
+++ b/src/services/mockApi.js
@@ -0,0 +1,352 @@
+// Mock API service for development without backend
+import { v4 as uuidv4 } from 'uuid';
+
+// Mock data for knowledge bases
+const mockKnowledgeBases = [
+ {
+ id: 'kb-001',
+ name: 'Frontend Development',
+ description: 'Resources and guides for frontend development including React, Vue, and Angular',
+ created_at: '2023-10-15T08:30:00Z',
+ updated_at: '2023-12-20T14:45:00Z',
+ create_time: '2023-10-15T08:30:00Z',
+ update_time: '2023-12-20T14:45:00Z',
+ type: 'private',
+ owner: {
+ id: 'user-001',
+ username: 'johndoe',
+ email: 'john@example.com',
+ },
+ document_count: 15,
+ tags: ['react', 'javascript', 'frontend'],
+ permissions: {
+ can_edit: true,
+ can_read: true,
+ },
+ documents: [
+ {
+ id: 'doc-001',
+ name: 'React Best Practices.pdf',
+ description: 'A guide to React best practices and patterns',
+ size: '1.2MB',
+ create_time: '2023-10-20T09:15:00Z',
+ update_time: '2023-10-20T09:15:00Z',
+ },
+ {
+ id: 'doc-002',
+ name: 'Vue.js Tutorial.docx',
+ description: 'Step-by-step tutorial for Vue.js beginners',
+ size: '850KB',
+ create_time: '2023-11-05T14:30:00Z',
+ update_time: '2023-11-05T14:30:00Z',
+ },
+ {
+ id: 'doc-003',
+ name: 'JavaScript ES6 Features.pdf',
+ description: 'Overview of ES6 features and examples',
+ size: '1.5MB',
+ create_time: '2023-11-15T11:45:00Z',
+ update_time: '2023-11-15T11:45:00Z',
+ },
+ ],
+ },
+ {
+ id: 'kb-002',
+ name: 'Backend Technologies',
+ description: 'Information about backend frameworks, databases, and server configurations',
+ created_at: '2023-09-05T10:15:00Z',
+ updated_at: '2024-01-10T09:20:00Z',
+ create_time: '2023-09-05T10:15:00Z',
+ update_time: '2024-01-10T09:20:00Z',
+ type: 'private',
+ owner: {
+ id: 'user-001',
+ username: 'johndoe',
+ email: 'john@example.com',
+ },
+ document_count: 23,
+ tags: ['nodejs', 'python', 'databases'],
+ permissions: {
+ can_edit: true,
+ can_read: true,
+ },
+ },
+ {
+ id: 'kb-003',
+ name: 'DevOps Practices',
+ description: 'Best practices for CI/CD, containerization, and cloud deployment',
+ created_at: '2023-11-12T15:45:00Z',
+ updated_at: '2024-02-05T11:30:00Z',
+ create_time: '2023-11-12T15:45:00Z',
+ update_time: '2024-02-05T11:30:00Z',
+ type: 'public',
+ owner: {
+ id: 'user-002',
+ username: 'janedoe',
+ email: 'jane@example.com',
+ },
+ document_count: 18,
+ tags: ['docker', 'kubernetes', 'aws'],
+ permissions: {
+ can_edit: false,
+ can_read: true,
+ },
+ },
+ {
+ id: 'kb-004',
+ name: 'Machine Learning Fundamentals',
+ description: 'Introduction to machine learning concepts, algorithms, and frameworks',
+ created_at: '2023-08-20T09:00:00Z',
+ updated_at: '2024-01-25T16:15:00Z',
+ create_time: '2023-08-20T09:00:00Z',
+ update_time: '2024-01-25T16:15:00Z',
+ type: 'public',
+ owner: {
+ id: 'user-003',
+ username: 'alexsmith',
+ email: 'alex@example.com',
+ },
+ document_count: 30,
+ tags: ['ml', 'python', 'tensorflow'],
+ permissions: {
+ can_edit: false,
+ can_read: true,
+ },
+ },
+ {
+ id: 'kb-005',
+ name: 'UI/UX Design Principles',
+ description: 'Guidelines for creating effective and user-friendly interfaces',
+ created_at: '2023-12-01T13:20:00Z',
+ updated_at: '2024-02-15T10:45:00Z',
+ create_time: '2023-12-01T13:20:00Z',
+ update_time: '2024-02-15T10:45:00Z',
+ type: 'private',
+ owner: {
+ id: 'user-002',
+ username: 'janedoe',
+ email: 'jane@example.com',
+ },
+ document_count: 12,
+ tags: ['design', 'ui', 'ux'],
+ permissions: {
+ can_edit: true,
+ can_read: true,
+ },
+ },
+ {
+ id: 'kb-006',
+ name: 'Mobile App Development',
+ description: 'Resources for iOS, Android, and cross-platform mobile development',
+ created_at: '2023-10-25T11:10:00Z',
+ updated_at: '2024-01-30T14:00:00Z',
+ create_time: '2023-10-25T11:10:00Z',
+ update_time: '2024-01-30T14:00:00Z',
+ type: 'private',
+ owner: {
+ id: 'user-001',
+ username: 'johndoe',
+ email: 'john@example.com',
+ },
+ document_count: 20,
+ tags: ['mobile', 'react-native', 'flutter'],
+ permissions: {
+ can_edit: true,
+ can_read: true,
+ },
+ },
+ {
+ id: 'kb-007',
+ name: 'Cybersecurity Best Practices',
+ description: 'Guidelines for securing applications, networks, and data',
+ created_at: '2023-09-18T14:30:00Z',
+ updated_at: '2024-02-10T09:15:00Z',
+ create_time: '2023-09-18T14:30:00Z',
+ update_time: '2024-02-10T09:15:00Z',
+ type: 'private',
+ owner: {
+ id: 'user-004',
+ username: 'sarahwilson',
+ email: 'sarah@example.com',
+ },
+ document_count: 25,
+ tags: ['security', 'encryption', 'authentication'],
+ permissions: {
+ can_edit: false,
+ can_read: false,
+ },
+ },
+ {
+ id: 'kb-008',
+ name: 'Data Science Toolkit',
+ description: 'Tools and techniques for data analysis, visualization, and modeling',
+ created_at: '2023-11-05T10:00:00Z',
+ updated_at: '2024-01-20T15:30:00Z',
+ create_time: '2023-11-05T10:00:00Z',
+ update_time: '2024-01-20T15:30:00Z',
+ type: 'public',
+ owner: {
+ id: 'user-003',
+ username: 'alexsmith',
+ email: 'alex@example.com',
+ },
+ document_count: 28,
+ tags: ['data-science', 'python', 'visualization'],
+ permissions: {
+ can_edit: false,
+ can_read: true,
+ },
+ },
+];
+
+// In-memory store for CRUD operations
+let knowledgeBases = [...mockKnowledgeBases];
+
+// Helper function for pagination
+const paginate = (array, page_size, page) => {
+ const startIndex = (page - 1) * page_size;
+ const endIndex = startIndex + page_size;
+ const items = array.slice(startIndex, endIndex);
+
+ return {
+ items,
+ total: array.length,
+ page,
+ page_size,
+ };
+};
+
+// Mock API functions
+export const mockGet = async (url, params = {}) => {
+ console.log(`[MOCK API] GET ${url}`, params);
+
+ // Simulate network delay
+ await new Promise((resolve) => setTimeout(resolve, 500));
+
+ // Knowledge bases list with pagination
+ if (url === '/knowledge-bases/') {
+ const { page = 1, page_size = 10 } = params;
+ return paginate(knowledgeBases, page_size, page);
+ }
+
+ // Knowledge base search
+ if (url === '/knowledge-bases/search/') {
+ const { keyword = '', page = 1, page_size = 10 } = params;
+ const filtered = knowledgeBases.filter(
+ (kb) =>
+ kb.name.toLowerCase().includes(keyword.toLowerCase()) ||
+ kb.description.toLowerCase().includes(keyword.toLowerCase()) ||
+ kb.tags.some((tag) => tag.toLowerCase().includes(keyword.toLowerCase()))
+ );
+ return paginate(filtered, page_size, page);
+ }
+
+ // Knowledge base details
+ if (url.match(/^\/knowledge-bases\/[^/]+\/$/)) {
+ const id = url.split('/')[2];
+ const knowledgeBase = knowledgeBases.find((kb) => kb.id === id);
+
+ if (!knowledgeBase) {
+ throw { response: { status: 404, data: { message: 'Knowledge base not found' } } };
+ }
+
+ return knowledgeBase;
+ }
+
+ throw { response: { status: 404, data: { message: 'Not found' } } };
+};
+
+export const mockPost = async (url, data) => {
+ console.log(`[MOCK API] POST ${url}`, data);
+
+ // Simulate network delay
+ await new Promise((resolve) => setTimeout(resolve, 700));
+
+ // Create knowledge base
+ if (url === '/knowledge-bases/') {
+ const newKnowledgeBase = {
+ id: `kb-${uuidv4().slice(0, 8)}`,
+ name: data.name,
+ description: data.description || '',
+ desc: data.desc || data.description || '',
+ created_at: new Date().toISOString(),
+ updated_at: new Date().toISOString(),
+ create_time: new Date().toISOString(),
+ update_time: new Date().toISOString(),
+ type: data.type || 'private',
+ owner: {
+ id: 'user-001',
+ username: 'johndoe',
+ email: 'john@example.com',
+ },
+ document_count: 0,
+ tags: data.tags || [],
+ permissions: {
+ can_edit: true,
+ can_read: true,
+ },
+ documents: [],
+ };
+
+ knowledgeBases.push(newKnowledgeBase);
+ return newKnowledgeBase;
+ }
+
+ throw { response: { status: 404, data: { message: 'Not found' } } };
+};
+
+export const mockPut = async (url, data) => {
+ console.log(`[MOCK API] PUT ${url}`, data);
+
+ // Simulate network delay
+ await new Promise((resolve) => setTimeout(resolve, 600));
+
+ // Update knowledge base
+ if (url.match(/^\/knowledge-bases\/[^/]+\/$/)) {
+ const id = url.split('/')[2];
+ const index = knowledgeBases.findIndex((kb) => kb.id === id);
+
+ if (index === -1) {
+ throw { response: { status: 404, data: { message: 'Knowledge base not found' } } };
+ }
+
+ const updatedKnowledgeBase = {
+ ...knowledgeBases[index],
+ ...data,
+ updated_at: new Date().toISOString(),
+ update_time: new Date().toISOString(),
+ };
+
+ knowledgeBases[index] = updatedKnowledgeBase;
+ return updatedKnowledgeBase;
+ }
+
+ throw { response: { status: 404, data: { message: 'Not found' } } };
+};
+
+export const mockDel = async (url) => {
+ console.log(`[MOCK API] DELETE ${url}`);
+
+ // Simulate network delay
+ await new Promise((resolve) => setTimeout(resolve, 800));
+
+ // Delete knowledge base
+ if (url.match(/^\/knowledge-bases\/[^/]+\/$/)) {
+ const id = url.split('/')[2];
+ const index = knowledgeBases.findIndex((kb) => kb.id === id);
+
+ if (index === -1) {
+ throw { response: { status: 404, data: { message: 'Knowledge base not found' } } };
+ }
+
+ knowledgeBases.splice(index, 1);
+ return { success: true };
+ }
+
+ throw { response: { status: 404, data: { message: 'Not found' } } };
+};
+
+// Reset mock data to initial state (useful for testing)
+export const resetMockData = () => {
+ knowledgeBases = [...mockKnowledgeBases];
+};