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('获取权限申请列表失败');