+ {/* 紧凑的搜索和过滤区 */}
+
+
-
- {/* 步骤 1: 选择会议 */}
- {createStep === 1 && (
-
-
- {/* 紧凑的搜索和过滤区 */}
-
-
-
- {availableTags.length > 0 && (
-
-
- {availableTags.map(tag => (
-
- ))}
-
-
- )}
-
- {(searchQuery || selectedTags.length > 0) && (
+ {availableTags.length > 0 && (
+
+
+ {availableTags.map(tag => (
- )}
+ ))}
+
+ )}
-
- {loadingMeetings ? (
-
- ) : meetings.length === 0 ? (
-
- ) : (
- meetings.map(meeting => (
-
toggleMeetingSelection(meeting.meeting_id)}
- >
-
{
- e.stopPropagation();
- toggleMeetingSelection(meeting.meeting_id);
- }}
- onClick={(e) => e.stopPropagation()}
- />
-
-
{meeting.title}
-
- {meeting.creator_username && (
- 创建人: {meeting.creator_username}
- )}
- {meeting.created_at && (
- 创建时间: {formatMeetingDate(meeting.created_at)}
- )}
-
-
-
- ))
- )}
-
+ {(searchQuery || selectedTags.length > 0) && (
+
+ )}
+
- {/* 分页按钮 */}
- {!loadingMeetings && meetings.length > 0 && (
-
-
-
- 第 {meetingsPagination.page} 页 · 共 {meetingsPagination.total} 条
-
-
+
+ {loadingMeetings ? (
+
+ ) : meetings.length === 0 ? (
+
+ ) : (
+ meetings.map(meeting => (
+
toggleMeetingSelection(meeting.meeting_id)}
+ >
+
{
+ e.stopPropagation();
+ toggleMeetingSelection(meeting.meeting_id);
+ }}
+ onClick={(e) => e.stopPropagation()}
+ />
+
+
{meeting.title}
+
+ {meeting.creator_username && (
+ 创建人: {meeting.creator_username}
+ )}
+ {meeting.created_at && (
+ 创建时间: {formatMeetingDate(meeting.created_at)}
+ )}
+
- )}
-
-
- )}
-
- {/* 步骤 2: 输入提示词 */}
- {createStep === 2 && (
-
-
-
- 已选择会议:
- {selectedMeetings.length} 个
-
-
-
-
您可以添加额外的要求来定制知识库生成内容,例如重点关注某个主题、提取特定信息等。如不填写,系统将使用默认提示词。
-
-
- )}
-
+ ))
+ )}
+
-
- {createStep === 1 ? (
- <>
-
+ {/* 分页按钮 */}
+ {!loadingMeetings && meetings.length > 0 && (
+
- >
- ) : (
- <>
-
+
+ 第 {meetingsPagination.page} 页 · 共 {meetingsPagination.total} 条
+
- >
+
)}
-
- )}
+ )}
+
+ {/* 步骤 2: 输入提示词 */}
+ {createStep === 2 && (
+
+
+
+ 已选择会议:
+ {selectedMeetings.length} 个
+
+
+
+
+
您可以添加额外的要求来定制知识库生成内容,例如重点关注某个主题、提取特定信息等。如不填写,系统将使用默认提示词。
+
+
+ )}
+
{/* 删除确认对话框 */}
{
const [prompts, setPrompts] = useState([]);
@@ -16,10 +18,21 @@ const PromptManagement = () => {
const [showModal, setShowModal] = useState(false);
const [isEditing, setIsEditing] = useState(false);
const [currentPrompt, setCurrentPrompt] = useState(null);
- const [activeMenu, setActiveMenu] = useState(null); // For dropdown menu
+ const [activeMenu, setActiveMenu] = useState(null);
const [deleteConfirmInfo, setDeleteConfirmInfo] = useState(null);
+ const [toasts, setToasts] = useState([]);
const menuRef = useRef(null);
+ // Toast helper functions
+ const showToast = (message, type = 'info') => {
+ const id = Date.now();
+ setToasts(prev => [...prev, { id, message, type }]);
+ };
+
+ const removeToast = (id) => {
+ setToasts(prev => prev.filter(toast => toast.id !== id));
+ };
+
useEffect(() => {
fetchPrompts();
}, [page, pageSize]);
@@ -72,11 +85,13 @@ const PromptManagement = () => {
try {
if (isEditing) {
await apiClient.put(buildApiUrl(API_ENDPOINTS.PROMPTS.UPDATE(currentPrompt.id)), currentPrompt);
+ showToast('提示词更新成功', 'success');
} else {
await apiClient.post(buildApiUrl(API_ENDPOINTS.PROMPTS.CREATE), currentPrompt);
+ showToast('提示词创建成功', 'success');
}
handleCloseModal();
- fetchPrompts(); // Refresh list
+ fetchPrompts();
} catch (err) {
setError(err.response?.data?.message || '保存失败');
}
@@ -93,11 +108,14 @@ const PromptManagement = () => {
const handleConfirmDelete = async () => {
try {
await apiClient.delete(buildApiUrl(API_ENDPOINTS.PROMPTS.DELETE(deleteConfirmInfo.id)));
- fetchPrompts(); // Refresh list
+ setDeleteConfirmInfo(null);
+ fetchPrompts();
+ showToast('提示词删除成功', 'success');
} catch (err) {
setError(err.response?.data?.message || '删除失败');
+ showToast('删除失败,请重试', 'error');
+ setDeleteConfirmInfo(null);
}
- setDeleteConfirmInfo(null);
};
const handleInputChange = (field, value) => {
@@ -153,30 +171,53 @@ const PromptManagement = () => {
>
)}
- {showModal && (
-
-
-
{isEditing ? '编辑提示词' : '新增提示词'}
- {error &&
{error}
}
+
+
+
+ >
+ }
+ >
+ {error && {error}
}
+ {currentPrompt && (
+ <>
- handleInputChange('name', e.target.value)} />
+ handleInputChange('name', e.target.value)}
+ placeholder="请输入提示词名称"
+ />
- handleInputChange('tags', value)} />
+ handleInputChange('tags', value)}
+ />
-
-
-
-
-
-
-
- )}
+ >
+ )}
+
{/* 删除提示词确认对话框 */}
{
cancelText="取消"
type="danger"
/>
+
+ {/* Toast notifications */}
+ {toasts.map(toast => (
+ removeToast(toast.id)}
+ />
+ ))}
);
};
diff --git a/src/pages/admin/UserManagement.jsx b/src/pages/admin/UserManagement.jsx
index e683553..8e520d4 100644
--- a/src/pages/admin/UserManagement.jsx
+++ b/src/pages/admin/UserManagement.jsx
@@ -1,8 +1,9 @@
import React, { useState, useEffect } from 'react';
import apiClient from '../../utils/apiClient';
import { buildApiUrl, API_ENDPOINTS } from '../../config/api';
-import { Plus, Edit, Trash2, KeyRound } from 'lucide-react';
+import { Plus, Edit, Trash2, KeyRound, User, Mail, Shield } from 'lucide-react';
import ConfirmDialog from '../../components/ConfirmDialog';
+import FormModal from '../../components/FormModal';
import Toast from '../../components/Toast';
import './UserManagement.css';
@@ -13,12 +14,11 @@ const UserManagement = () => {
const [pageSize, setPageSize] = useState(10);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
- const [showAddUserModal, setShowAddUserModal] = useState(false);
- const [showEditUserModal, setShowEditUserModal] = useState(false);
+ const [showUserModal, setShowUserModal] = useState(false);
+ const [isEditing, setIsEditing] = useState(false);
+ const [currentUser, setCurrentUser] = useState(null);
const [deleteConfirmInfo, setDeleteConfirmInfo] = useState(null);
const [resetConfirmInfo, setResetConfirmInfo] = useState(null);
- const [newUser, setNewUser] = useState({ username: '', caption: '', email: '', role_id: 2 });
- const [editingUser, setEditingUser] = useState(null);
const [roles, setRoles] = useState([]);
const [toasts, setToasts] = useState([]);
@@ -67,11 +67,11 @@ const UserManagement = () => {
const handleAddUser = async (e) => {
e.preventDefault();
try {
- await apiClient.post(buildApiUrl(API_ENDPOINTS.USERS.CREATE), newUser);
- setShowAddUserModal(false);
- setNewUser({ username: '', caption: '', email: '', role_id: 2 });
- setError(''); // Clear any previous errors
- fetchUsers(); // Refresh user list
+ await apiClient.post(buildApiUrl(API_ENDPOINTS.USERS.CREATE), currentUser);
+ handleCloseModal();
+ setError('');
+ fetchUsers();
+ showToast('用户添加成功', 'success');
} catch (err) {
console.error('Error adding user:', err);
setError(err.response?.data?.message || '新增用户失败');
@@ -81,27 +81,23 @@ const UserManagement = () => {
const handleUpdateUser = async (e) => {
e.preventDefault();
try {
- // 只发送模型期望的字段
const updateData = {
- caption: editingUser.caption,
- email: editingUser.email,
- role_id: editingUser.role_id
+ caption: currentUser.caption,
+ email: currentUser.email,
+ role_id: currentUser.role_id
};
-
- // 只有当用户名被修改时才发送
- if (editingUser.username && editingUser.username.trim()) {
- updateData.username = editingUser.username;
+
+ if (currentUser.username && currentUser.username.trim()) {
+ updateData.username = currentUser.username;
}
-
- console.log('Sending update data:', updateData); // 调试用
-
- await apiClient.put(buildApiUrl(API_ENDPOINTS.USERS.UPDATE(editingUser.user_id)), updateData);
- setShowEditUserModal(false);
- setError(''); // Clear any previous errors
- fetchUsers(); // Refresh user list
+
+ await apiClient.put(buildApiUrl(API_ENDPOINTS.USERS.UPDATE(currentUser.user_id)), updateData);
+ handleCloseModal();
+ setError('');
+ fetchUsers();
+ showToast('用户修改成功', 'success');
} catch (err) {
console.error('Error updating user:', err);
- console.error('Error response:', err.response?.data); // 调试用
setError(err.response?.data?.message || '修改用户失败');
}
};
@@ -111,7 +107,7 @@ const UserManagement = () => {
await apiClient.delete(buildApiUrl(API_ENDPOINTS.USERS.DELETE(deleteConfirmInfo.user_id)));
setDeleteConfirmInfo(null);
showToast('用户删除成功', 'success');
- fetchUsers(); // Refresh user list
+ fetchUsers();
} catch (err) {
console.error('Error deleting user:', err);
showToast('删除用户失败,请重试', 'error');
@@ -131,9 +127,34 @@ const UserManagement = () => {
}
};
- const openEditModal = (user) => {
- setEditingUser({ ...user });
- setShowEditUserModal(true);
+ const handleOpenModal = (user = null) => {
+ if (user) {
+ setIsEditing(true);
+ setCurrentUser({ ...user });
+ } else {
+ setIsEditing(false);
+ setCurrentUser({ username: '', caption: '', email: '', role_id: 2 });
+ }
+ setError('');
+ setShowUserModal(true);
+ };
+
+ const handleCloseModal = () => {
+ setShowUserModal(false);
+ setCurrentUser(null);
+ setError('');
+ };
+
+ const handleSave = async () => {
+ if (isEditing) {
+ await handleUpdateUser({ preventDefault: () => {} });
+ } else {
+ await handleAddUser({ preventDefault: () => {} });
+ }
+ };
+
+ const handleInputChange = (field, value) => {
+ setCurrentUser(prev => ({ ...prev, [field]: value }));
};
const openDeleteConfirm = (user) => {
@@ -148,7 +169,7 @@ const UserManagement = () => {
用户列表
-
+
{loading &&
加载中...
}
{error &&
{error}
}
@@ -176,7 +197,7 @@ const UserManagement = () => {
{user.role_name} |
{new Date(user.created_at).toLocaleString()} |
-
+
|
@@ -195,78 +216,75 @@ const UserManagement = () => {
>
)}
- {showAddUserModal && (
-
- )}
-
- {showEditUserModal && editingUser && (
-
- )}
+ )}
+ >
+ )}
+
{/* 删除用户确认对话框 */}