diff --git a/src/components/AccessRequestModal.jsx b/src/components/AccessRequestModal.jsx index 5dc4da6..6a8654c 100644 --- a/src/components/AccessRequestModal.jsx +++ b/src/components/AccessRequestModal.jsx @@ -20,18 +20,29 @@ export default function AccessRequestModal({ isSubmitting = false, }) { const [accessRequestData, setAccessRequestData] = useState({ - accessType: '只读访问', - duration: '一周', + permissions: { + can_read: true, + can_edit: false, + can_delete: false, + }, + duration: '30', // 默认30天 reason: '', }); const [accessRequestErrors, setAccessRequestErrors] = useState({}); const handleAccessRequestInputChange = (e) => { const { name, value } = e.target; - setAccessRequestData((prev) => ({ - ...prev, - [name]: value, - })); + if (name === 'duration') { + setAccessRequestData((prev) => ({ + ...prev, + [name]: value, + })); + } else if (name === 'reason') { + setAccessRequestData((prev) => ({ + ...prev, + [name]: value, + })); + } // Clear error when user types if (accessRequestErrors[name]) { @@ -42,6 +53,17 @@ export default function AccessRequestModal({ } }; + const handlePermissionChange = (permissionType) => { + setAccessRequestData((prev) => ({ + ...prev, + permissions: { + can_read: true, // 只读权限始终为true + can_edit: permissionType === '编辑权限', + can_delete: false, // 管理权限暂时不开放 + }, + })); + }; + const validateAccessRequestForm = () => { const errors = {}; @@ -59,17 +81,27 @@ export default function AccessRequestModal({ return; } + // 计算过期日期 + const expirationDate = new Date(); + expirationDate.setDate(expirationDate.getDate() + parseInt(accessRequestData.duration)); + const expiresAt = expirationDate.toISOString(); + // 调用父组件的提交函数 onSubmit({ - id: knowledgeBaseId, - title: knowledgeBaseTitle, - ...accessRequestData, + knowledge_base: knowledgeBaseId, + permissions: accessRequestData.permissions, + reason: accessRequestData.reason, + expires_at: expiresAt, }); // 重置表单 setAccessRequestData({ - accessType: '只读访问', - duration: '一周', + permissions: { + can_read: true, + can_edit: false, + can_delete: false, + }, + duration: '30', reason: '', }); setAccessRequestErrors({}); @@ -123,9 +155,8 @@ export default function AccessRequestModal({
diff --git a/src/layouts/HeaderWithNav.jsx b/src/layouts/HeaderWithNav.jsx index 8013793..a843cf0 100644 --- a/src/layouts/HeaderWithNav.jsx +++ b/src/layouts/HeaderWithNav.jsx @@ -127,7 +127,7 @@ export default function HeaderWithNav() { setShowSettings(true)} + // onClick={() => setShowSettings(true)} > 个人设置 diff --git a/src/pages/Chat/ChatWindow.jsx b/src/pages/Chat/ChatWindow.jsx index f36fe4e..e80659c 100644 --- a/src/pages/Chat/ChatWindow.jsx +++ b/src/pages/Chat/ChatWindow.jsx @@ -235,8 +235,8 @@ export default function ChatWindow({ chatId, knowledgeBaseId }) {
{message.content}
-
- {message.created_at && new Date(message.created_at).toLocaleTimeString()} -
+
+
+ {message.created_at && new Date(message.created_at).toLocaleTimeString()}
))} diff --git a/src/pages/KnowledgeBase/Detail/SettingsTab.jsx b/src/pages/KnowledgeBase/Detail/SettingsTab.jsx index 056fb4f..ae5014b 100644 --- a/src/pages/KnowledgeBase/Detail/SettingsTab.jsx +++ b/src/pages/KnowledgeBase/Detail/SettingsTab.jsx @@ -333,7 +333,7 @@ export default function SettingsTab({ knowledgeBase }) { /> {/* User Permissions Manager */} - + {/* */} {/* Delete confirmation modal */} -
diff --git a/src/pages/KnowledgeBase/KnowledgeBase.jsx b/src/pages/KnowledgeBase/KnowledgeBase.jsx index acf91e7..723d5aa 100644 --- a/src/pages/KnowledgeBase/KnowledgeBase.jsx +++ b/src/pages/KnowledgeBase/KnowledgeBase.jsx @@ -381,17 +381,10 @@ export default function KnowledgeBase() { setIsSubmittingRequest(true); try { - // 使用权限服务发送请求 - await requestKnowledgeBaseAccess(requestData); + // 使用权限服务发送请求 - 通过dispatch调用thunk + await dispatch(requestKnowledgeBaseAccess(requestData)).unwrap(); - dispatch( - showNotification({ - message: '权限申请已提交', - type: 'success', - }) - ); - - // Close modal + // Close modal after success setShowAccessRequestModal(false); } catch (error) { dispatch( diff --git a/src/pages/Permissions/PermissionsPage.jsx b/src/pages/Permissions/PermissionsPage.jsx index 37198cb..afb8466 100644 --- a/src/pages/Permissions/PermissionsPage.jsx +++ b/src/pages/Permissions/PermissionsPage.jsx @@ -18,11 +18,11 @@ export default function PermissionsPage() { return (
-
+
{user && user.role === 'admin' && ( -
+
)} diff --git a/src/pages/Permissions/components/PendingRequests.jsx b/src/pages/Permissions/components/PendingRequests.jsx index 47d5347..af9377f 100644 --- a/src/pages/Permissions/components/PendingRequests.jsx +++ b/src/pages/Permissions/components/PendingRequests.jsx @@ -24,7 +24,7 @@ export default function PendingRequests() { // 从Redux store获取权限申请列表状态 const { - results: pendingRequests, + results: permissionRequests, status: fetchStatus, error: fetchError, page: currentPage, @@ -185,32 +185,69 @@ export default function PendingRequests() { ); }; + // 根据状态渲染不同的状态标签 + const renderStatusBadge = (status) => { + switch (status) { + case 'approved': + return ( + + + 已批准 + + ); + case 'rejected': + return ( + + + 已拒绝 + + ); + case 'pending': + return ( + + 待处理 + + ); + default: + return null; + } + }; + // 渲染加载状态 - if (fetchStatus === 'loading' && pendingRequests.length === 0) { + if (fetchStatus === 'loading' && permissionRequests.length === 0) { return (
加载中...
-

加载待处理申请...

+

加载权限申请...

); } // 渲染错误状态 - if (fetchStatus === 'failed' && pendingRequests.length === 0) { + if (fetchStatus === 'failed' && permissionRequests.length === 0) { return (
- {fetchError || '获取待处理申请失败'} + {fetchError || '获取权限申请失败'}
); } // 渲染空状态 - if (pendingRequests.length === 0) { + if (permissionRequests.length === 0) { return (
- 暂无待处理的权限申请 + 暂无权限申请记录
); } @@ -219,12 +256,14 @@ export default function PendingRequests() { return ( <>
-
待处理申请
-
{total}个待处理
+
权限申请列表
+
+ {permissionRequests.filter((req) => req.status === 'pending').length}个待处理 +
- {pendingRequests.map((request) => ( + {permissionRequests.map((request) => (
handleRowClick(request)}>
@@ -235,7 +274,10 @@ export default function PendingRequests() {
-

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

+
+

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

+ {renderStatusBadge(request.status)} +
{request.permissions.can_edit ? (
)} + + {request.response_message && ( +
+ 审批意见: {request.response_message} +
+ )}
- - + {request.status === 'pending' ? ( + <> + + + + ) : ( +
+ {request.status === 'approved' ? '已批准' : '已拒绝'} + {request.updated_at && ( + + {new Date(request.updated_at).toLocaleDateString()} + + )} +
+ )}
))} diff --git a/src/pages/Permissions/components/UserPermissions.jsx b/src/pages/Permissions/components/UserPermissions.jsx index 801226c..42dad52 100644 --- a/src/pages/Permissions/components/UserPermissions.jsx +++ b/src/pages/Permissions/components/UserPermissions.jsx @@ -13,6 +13,7 @@ export default function UserPermissions() { const [selectedUser, setSelectedUser] = useState(null); const [showDetailsModal, setShowDetailsModal] = useState(false); const [searchTerm, setSearchTerm] = useState(''); + const [statusFilter, setStatusFilter] = useState('all'); // 'all', 'pending', 'approved', 'rejected' // 分页状态 const [currentPage, setCurrentPage] = useState(1); @@ -62,6 +63,11 @@ export default function UserPermissions() { setCurrentPage(1); // 重置到第一页 }; + const handleStatusFilterChange = (e) => { + setStatusFilter(e.target.value); + setCurrentPage(1); // 重置到第一页 + }; + const handlePageChange = (page) => { if (page > 0 && page <= totalPages) { setCurrentPage(page); @@ -76,17 +82,27 @@ export default function UserPermissions() { // 过滤用户列表 const getFilteredUsers = () => { - if (!searchTerm.trim()) { - return users; + let filtered = users; + + // 应用状态过滤 + if (statusFilter !== 'all') { + filtered = filtered.filter((user) => + user.permissions.some((permission) => permission.status === statusFilter) + ); } - return users.filter( - (user) => - user.user_info?.username.toLowerCase().includes(searchTerm.toLowerCase()) || - user.user_info?.name.toLowerCase().includes(searchTerm.toLowerCase()) || - user.user_info?.department.toLowerCase().includes(searchTerm.toLowerCase()) || - user.user_info?.role.toLowerCase().includes(searchTerm.toLowerCase()) - ); + // 应用搜索过滤 + if (searchTerm.trim()) { + filtered = filtered.filter( + (user) => + user.user_info?.username.toLowerCase().includes(searchTerm.toLowerCase()) || + user.user_info?.name.toLowerCase().includes(searchTerm.toLowerCase()) || + user.user_info?.department.toLowerCase().includes(searchTerm.toLowerCase()) || + user.user_info?.role.toLowerCase().includes(searchTerm.toLowerCase()) + ); + } + + return filtered; }; const filteredUsers = getFilteredUsers(); @@ -196,22 +212,35 @@ export default function UserPermissions() {
<> - {/*
-
-
- - - - +
+
+
+
+ + + + +
+
-
*/} +
{loading === 'loading' ? (
diff --git a/src/services/api.js b/src/services/api.js index 200e69d..13a9291 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -214,4 +214,21 @@ export const switchToRealApi = async () => { return isServerUp; }; +// 权限相关API +export const applyPermission = (data) => { + return post('/permissions/', data); +}; + +export const updatePermission = (data) => { + return post('/permissions/update_permission/', data); +}; + +export const approvePermission = (permissionId) => { + return post(`/permissions/approve_permission/${permissionId}`); +}; + +export const rejectPermission = (permissionId) => { + return post(`/permissions/reject_permission/${permissionId}`); +}; + export { get, post, put, del, upload }; diff --git a/src/services/permissionService.js b/src/services/permissionService.js index c4141ac..a77532e 100644 --- a/src/services/permissionService.js +++ b/src/services/permissionService.js @@ -31,7 +31,8 @@ export const calculateExpiresAt = (duration) => { }; /** - * 申请知识库访问权限 + * 申请知识库访问权限(已废弃,请使用store/knowledgeBase/knowledgeBase.thunks中的requestKnowledgeBaseAccess) + * @deprecated 请使用Redux thunk版本 * @param {Object} requestData - 请求数据 * @param {string} requestData.id - 知识库ID * @param {string} requestData.accessType - 访问类型,如 '只读访问', '编辑权限' @@ -39,7 +40,7 @@ export const calculateExpiresAt = (duration) => { * @param {string} requestData.reason - 申请原因 * @returns {Promise} - API 请求的 Promise */ -export const requestKnowledgeBaseAccess = async (requestData) => { +export const legacyRequestKnowledgeBaseAccess = async (requestData) => { const apiRequestData = { knowledge_base: requestData.id, permissions: { diff --git a/src/store/knowledgeBase/knowledgeBase.thunks.js b/src/store/knowledgeBase/knowledgeBase.thunks.js index 97621d9..00cb565 100644 --- a/src/store/knowledgeBase/knowledgeBase.thunks.js +++ b/src/store/knowledgeBase/knowledgeBase.thunks.js @@ -165,15 +165,17 @@ export const changeKnowledgeBaseType = createAsyncThunk( /** * 申请知识库访问权限 * @param {Object} params - 参数 - * @param {string} params.knowledgeBaseId - 知识库ID + * @param {string} params.knowledge_base - 知识库ID + * @param {Object} params.permissions - 权限对象 + * @param {string} params.reason - 申请原因 + * @param {string} params.expires_at - 过期时间 * @returns {Promise} - Promise对象 */ export const requestKnowledgeBaseAccess = createAsyncThunk( 'knowledgeBase/requestAccess', async (params, { rejectWithValue, dispatch }) => { try { - const { knowledgeBaseId } = params; - const response = await post(`/knowledge-bases/${knowledgeBaseId}/request_access/`); + const response = await post('/permissions/', params); dispatch( showNotification({ type: 'success',