Merge "管理员端用户管理"
diff --git a/src/components/UserManagement.jsx b/src/components/UserManagement.jsx
new file mode 100644
index 0000000..c0ede42
--- /dev/null
+++ b/src/components/UserManagement.jsx
@@ -0,0 +1,418 @@
+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;
\ No newline at end of file