| import React, { useState, useEffect } from 'react'; |
| import { |
| Table, |
| Button, |
| Modal, |
| Image, |
| message, |
| Spin, |
| Input, |
| Select, |
| Pagination, |
| Space |
| } from 'antd'; |
| import { ExclamationCircleOutlined } from '@ant-design/icons'; |
| import axios from 'axios'; |
| |
| const { confirm } = Modal; |
| const { Option } = Select; |
| |
| const UserManagement = () => { |
| // 状态管理 |
| const [users, setUsers] = useState([]); |
| const [isLoading, setIsLoading] = useState(false); |
| const [error, setError] = useState(null); |
| const [currentUserId, setCurrentUserId] = useState(null); |
| const [applyExamLoading, setApplyExamLoading] = useState(false); |
| const [searchKeyword, setSearchKeyword] = useState(''); |
| const [currentPage, setCurrentPage] = useState(1); |
| const [pageSize, setPageSize] = useState(10); |
| |
| // 获取当前用户ID |
| useEffect(() => { |
| const userId = 1; // 示例,实际从认证系统获取 |
| setCurrentUserId(userId ? parseInt(userId) : null); |
| }, []); |
| |
| // 获取所有用户数据 |
| useEffect(() => { |
| fetchAllUsers(); |
| }, [searchKeyword]); |
| |
| // 获取所有用户的函数 |
| const fetchAllUsers = async () => { |
| setIsLoading(true); |
| setError(null); |
| try { |
| const res = await axios.get('http://localhost:8080/user/alluser'); |
| setUsers(res.data.data); |
| setCurrentPage(1); // 重置为第一页 |
| } catch (err) { |
| console.error('获取用户失败', err); |
| setError('获取用户列表失败,请稍后重试'); |
| message.error('获取用户列表失败'); |
| } finally { |
| setIsLoading(false); |
| } |
| }; |
| console.log('当前用户列表:', users); |
| |
| // 删除用户 |
| const handleDeleteUser = async (username) => { |
| confirm({ |
| title: '确认删除', |
| icon: <ExclamationCircleOutlined />, |
| content: '确定要删除这个用户吗?此操作不可恢复!', |
| onOk: async () => { |
| try { |
| await axios.delete(`http://localhost:8080/user/DeleteUser`, { |
| params: { username: username } |
| }); |
| setUsers(users.filter(user => user.username !== username)); |
| message.success('用户删除成功'); |
| } catch (err) { |
| console.error('用户删除失败', err); |
| if (err.response && err.response.status === 403) { |
| message.error('无权删除此用户'); |
| } else { |
| message.error('删除用户失败'); |
| } |
| } |
| } |
| }); |
| }; |
| |
| // 搜索种子 |
| const handleSearch = async () => { |
| if (!searchKeyword.trim()) { |
| fetchAllUsers(); |
| return; |
| } |
| |
| setIsLoading(true); |
| setError(null); |
| try { |
| const res = await axios.get(`http://localhost:8080/user/finduser`, { |
| params: { keyword: searchKeyword }, |
| }); |
| setUsers(res.data.data); |
| setCurrentPage(1); // 搜索后重置为第一页 |
| } catch (err) { |
| console.error('搜索失败', err); |
| setError('搜索失败,请稍后重试'); |
| message.error('搜索失败'); |
| } finally { |
| setIsLoading(false); |
| } |
| }; |
| |
| // 月度下载量考核 |
| const handleMonthExam = async () => { |
| if (!currentUserId) { |
| message.warning('请先登录'); |
| return; |
| } |
| |
| setApplyExamLoading(true); |
| try { |
| const now = new Date(); |
| const year = now.getFullYear(); |
| const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从0开始,补零 |
| const day = String(now.getDate()).padStart(2, '0'); // 日期补零 |
| const formattedDate = `${year}-${month}-${day}`; |
| |
| const currentDate = new Date(); |
| const lastMonthDate = new Date( |
| currentDate.getFullYear(), |
| currentDate.getMonth() - 1, // 月份减1 |
| currentDate.getDate() // 保持相同的日 |
| ); |
| |
| if (lastMonthDate.getDate() !== currentDate.getDate()) { |
| lastMonthDate.setDate(0); // 设置为上个月的最后一天 |
| } |
| const year1 = lastMonthDate.getFullYear(); |
| const month1 = String(lastMonthDate.getMonth() + 1).padStart(2, '0'); |
| const day1 = String(lastMonthDate.getDate()).padStart(2, '0'); |
| const formattedDate1 = `${year1}-${month1}-${day1}`; |
| |
| |
| |
| const res = await axios.post('http://localhost:8080/exam/MonthDownload', null, { |
| params: { startDate: formattedDate1,endDate: formattedDate } |
| }); |
| |
| if (res.data.success) { |
| message.success(res.data.message); |
| fetchAllUsers(); // 刷新种子列表 |
| } |
| } catch (err) { |
| console.error('月度考核失败', err); |
| if (err.response && err.response.status === 403) { |
| message.error('无权执行此操作'); |
| } else { |
| message.error('月度考核失败'); |
| } |
| } finally { |
| setApplyExamLoading(false); |
| } |
| }; |
| |
| // 季度上传量考核 |
| const handleQuarterExam = async () => { |
| if (!currentUserId) { |
| message.warning('请先登录'); |
| return; |
| } |
| |
| setApplyExamLoading(true); |
| try { |
| const now = new Date(); |
| const year = now.getFullYear(); |
| const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从0开始,补零 |
| const day = String(now.getDate()).padStart(2, '0'); // 日期补零 |
| const formattedDate = `${year}-${month}-${day}`; |
| |
| const currentDate = new Date(); |
| |
| const lastMonthDate = new Date( |
| currentDate.getFullYear(), |
| currentDate.getMonth() - 3, // 月份减1 |
| currentDate.getDate() // 保持相同的日 |
| ); |
| |
| if (lastMonthDate.getDate() !== currentDate.getDate()) { |
| lastMonthDate.setDate(0); // 设置为上个月的最后一天 |
| } |
| const year1 = lastMonthDate.getFullYear(); |
| const month1 = String(lastMonthDate.getMonth() + 1).padStart(2, '0'); |
| const day1 = String(lastMonthDate.getDate()).padStart(2, '0'); |
| const formattedDate1 = `${year1}-${month1}-${day1}`; |
| |
| |
| |
| const res = await axios.post('http://localhost:8080/exam/QuarterUpload', null, { |
| params: { startDate: formattedDate1,endDate: formattedDate } |
| }); |
| |
| if (res.data.success) { |
| message.success(res.data.message); |
| fetchAllUsers(); // 刷新种子列表 |
| } |
| } catch (err) { |
| console.error('季度考核失败', err); |
| if (err.response && err.response.status === 403) { |
| message.error('无权执行此操作'); |
| } else { |
| message.error('月度考核失败'); |
| } |
| } finally { |
| setApplyExamLoading(false); |
| } |
| }; |
| |
| // 分页数据计算 |
| const getCurrentPageData = () => { |
| const start = (currentPage - 1) * pageSize; |
| const end = start + pageSize; |
| return users;//.slice(start, end); |
| }; |
| |
| // 页码变化处理 |
| const handlePageChange = (page) => { |
| setCurrentPage(page); |
| }; |
| |
| // 每页条数变化处理 |
| const handlePageSizeChange = (current, size) => { |
| setPageSize(size); |
| setCurrentPage(1); // 重置为第一页 |
| }; |
| |
| // 格式化文件大小 |
| const formatFileSize = (bytes) => { |
| if (bytes === 0) return '0 Bytes'; |
| const k = 1024; |
| const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; |
| const i = Math.floor(Math.log(bytes) / Math.log(k)); |
| return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////////// |
| return ( |
| <div className="p-4 max-w-7xl mx-auto"> |
| <h1 className="text-2xl font-bold mb-6">用户管理</h1> |
| |
| {/* 搜索框 */} |
| <div className="mb-4 flex items-center"> |
| <Input |
| placeholder="搜索用户..." |
| value={searchKeyword} |
| onChange={(e) => setSearchKeyword(e.target.value)} |
| style={{ width: 300 }} |
| onPressEnter={handleSearch} |
| /> |
| <Button |
| type="primary" |
| onClick={handleSearch} |
| style={{ marginLeft: 8 }} |
| > |
| 搜索 |
| </Button> |
| </div> |
| |
| {/* 右上角按钮 */} |
| <Space> |
| <Button |
| type="primary" |
| loading={applyExamLoading} |
| onClick={handleMonthExam} |
| > |
| 月度下载量检查 |
| </Button> |
| <Button |
| type="primary" |
| loading={applyExamLoading} |
| onClick={handleQuarterExam} |
| > |
| 季度上传量检查 |
| </Button> |
| </Space> |
| |
| {/* 加载状态 */} |
| {isLoading && <Spin size="large" style={{ display: 'block', margin: '100px auto' }} />} |
| |
| {/* 错误提示 */} |
| {error && <div className="mb-4 p-3 bg-red-100 text-red-700 rounded border border-red-200">{error}</div>} |
| |
| {/* 种子列表表格 */} |
| {!isLoading && !error && ( |
| <> |
| <Table |
| columns={[ |
| { |
| title: '用户名', |
| dataIndex: 'username', |
| key: 'username' |
| }, |
| { |
| title: '密码', |
| dataIndex: 'password', |
| key: 'password' |
| }, |
| { |
| title: '上传量', |
| dataIndex: 'user_upload', |
| key: 'user_upload', |
| render: (size) => formatFileSize(size) |
| }, |
| { |
| title: '下载量', |
| dataIndex: 'user_download', |
| key: 'user_download', |
| render: (size) => formatFileSize(size) |
| }, |
| { |
| title: '保种积分', |
| dataIndex: 'credit', |
| key: 'credit', |
| }, |
| { |
| title: '头像', |
| dataIndex: 'image', |
| key: 'image', |
| render: (text) => text ? ( |
| <Image |
| src={text} |
| width={50} |
| height={50} |
| preview={{ maskClosable: true }} |
| /> |
| ) : ( |
| <div className="w-16 h-16 bg-gray-200 flex items-center justify-center">无头像</div> |
| ) |
| }, |
| { |
| title: '性别', |
| dataIndex: 'sex', |
| key: 'sex', |
| }, |
| { |
| title: '用户id', |
| dataIndex: 'userid', |
| key: 'userid' |
| }, |
| { |
| title: '用户等级', |
| dataIndex: 'grade_id', |
| key: 'grade_id' |
| }, |
| { |
| title: 'passkey', |
| dataIndex: 'passkey', |
| key: 'passkey' |
| }, |
| { |
| title: '分享率', |
| dataIndex: 'ratio', |
| key: 'ratio' |
| }, |
| { |
| title: '年龄', |
| dataIndex: 'age', |
| key: 'age' |
| }, |
| { |
| title: '邮箱', |
| dataIndex: 'email', |
| key: 'email' |
| }, |
| { |
| title: '用户权限', |
| dataIndex: 'permission', |
| key: 'permission' |
| }, |
| { |
| title: '操作', |
| key: 'action', |
| render: (_, record) => ( |
| <Space> |
| <Button |
| danger |
| onClick={() => handleDeleteUser(record.username)} |
| loading={isLoading} |
| > |
| 删除 |
| </Button> |
| </Space> |
| ) |
| } |
| ]} |
| dataSource={getCurrentPageData()} |
| rowKey="userid" |
| pagination={false} |
| loading={isLoading} |
| /> |
| |
| {/* 分页控件 */} |
| {users.length > 0 && ( |
| <div style={{ marginTop: 16, textAlign: 'center' }}> |
| <Pagination |
| current={currentPage} |
| pageSize={pageSize} |
| total={users.length} |
| onChange={handlePageChange} |
| onShowSizeChange={handlePageSizeChange} |
| showSizeChanger |
| showTotal={(total) => `共 ${total} 条记录`} |
| pageSizeOptions={['10', '20', '50']} |
| /> |
| </div> |
| )} |
| </> |
| )} |
| </div> |
| ); |
| }; |
| |
| export default UserManagement; |