blob: 35ae4283e6ccfbecfeae35a30d5fb6a686d4fcea [file] [log] [blame]
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import './Administer.css';
import {
getAllUsers,
searchUsers,
updateUserAuthority,
getAllDiscounts,
getCurrentDiscount,
addDiscount,
deleteDiscount
} from '../api/administer';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
const Administer = () => {
const navigate = useNavigate();
const [users, setUsers] = useState([]);
const [discounts, setDiscounts] = useState([]);
const [currentDiscount, setCurrentDiscount] = useState(null);
const [searchKey, setSearchKey] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [newDiscount, setNewDiscount] = useState({
name: '',
discountType: 'FREE'
});
const [startDate, setStartDate] = useState(new Date());
const [endDate, setEndDate] = useState(new Date());
const [activeTab, setActiveTab] = useState('users'); // 'users' 或 'discounts'
const fetchAllUsers = async () => {
setLoading(true);
setError(null);
try {
const users = await getAllUsers();
console.log("API Data:", users); // 现在应该直接是用户数组
const formattedUsers = users.map(user => ({
username: user.username || '未知用户',
authority: user.authority || 'USER',
registTime: user.registTime || null,
lastLogin: user.lastLogin || null,
upload: Number(user.upload) || 0,
download: Number(user.download) || 0,
magicPoints: Number(user.magicPoints) || 0,
shareRate: Number(user.shareRate) || 0
}));
console.log("Formatted Users:", formattedUsers);
setUsers(formattedUsers);
} catch (err) {
console.error("Error details:", err);
setError(`获取用户列表失败: ${err.message}`);
} finally {
setLoading(false);
}
};
const handleSearch = async () => {
if (!searchKey.trim()) {
fetchAllUsers();
return;
}
setLoading(true);
setError(null);
try {
const users = await searchUsers(searchKey);
console.log("Search Results:", users); // 打印搜索结果
// 格式化数据(确保数值字段正确解析)
const formattedUsers = users.map(user => ({
username: user.username || '未知用户',
authority: user.authority || 'USER',
registTime: user.registTime || null,
lastLogin: user.lastLogin || null,
upload: Number(user.upload) || 0, // 确保解析为数字
download: Number(user.download) || 0,
magicPoints: Number(user.magicPoints) || 0,
shareRate: Number(user.shareRate) || 0
}));
setUsers(formattedUsers);
} catch (err) {
setError('搜索用户失败,请重试');
console.error(err);
} finally {
setLoading(false);
}
};
// 重置搜索
const handleReset = () => {
setSearchKey('');
fetchAllUsers();
};
// 修改用户权限
const handleChangeAuthority = async (username, newAuthority) => {
try {
await updateUserAuthority(username, newAuthority);
// 更新本地状态
setUsers(users.map(user =>
user.username === username ? { ...user, authority: newAuthority } : user
));
} catch (err) {
setError('修改权限失败,请重试');
console.error(err);
}
};
// 获取所有折扣
const fetchAllDiscounts = async () => {
setLoading(true);
setError(null);
try {
const data = await getAllDiscounts();
setDiscounts(data);
} catch (err) {
setError('获取折扣列表失败: ' + err.message);
console.error(err);
} finally {
setLoading(false);
}
};
// 获取当前折扣
const fetchCurrentDiscount = async () => {
try {
const data = await getCurrentDiscount();
setCurrentDiscount(data);
} catch (err) {
console.error('获取当前折扣失败:', err);
}
};
const handleAddDiscount = async () => {
if (!newDiscount.name || !startDate || !endDate) {
setError('请填写所有必填字段');
return;
}
try {
// 验证时间
if (startDate >= endDate) {
setError('结束时间必须晚于开始时间');
return;
}
const payload = {
name: newDiscount.name,
startTime: formatDateToISO(startDate), // 例如: "2025-06-01T14:30:00"
endTime: formatDateToISO(endDate, true), // 例如: "2025-06-01T18:45:59"
discountType: newDiscount.discountType
};
console.log('提交数据:', payload); // 调试用
await addDiscount(payload);
// 重置表单
setNewDiscount({
name: '',
discountType: 'FREE'
});
setStartDate(new Date());
setEndDate(new Date());
fetchAllDiscounts();
setError(null);
} catch (err) {
setError('添加折扣失败: ' + err.message);
console.error(err);
}
};
const formatDateToISO = (date, isEndTime = false) => {
if (!date) return '';
const pad = (num) => num.toString().padStart(2, '0');
const year = date.getFullYear();
const month = pad(date.getMonth() + 1);
const day = pad(date.getDate());
const hours = pad(date.getHours());
const minutes = pad(date.getMinutes());
if (isEndTime) {
// 结束时间精确到用户选择的时间+59秒
return `${year}-${month}-${day}T${hours}:${minutes}:59`;
} else {
// 开始时间精确到用户选择的时间+00秒
return `${year}-${month}-${day}T${hours}:${minutes}:00`;
}
};
// 删除折扣
const handleDeleteDiscount = async (id) => {
try {
await deleteDiscount(id);
fetchAllDiscounts();
} catch (err) {
setError('删除折扣失败: ' + err.message);
console.error(err);
}
};
// 初始化加载数据
useEffect(() => {
if (activeTab === 'users') {
fetchAllUsers();
} else {
fetchAllDiscounts();
fetchCurrentDiscount();
}
}, [activeTab]);
// 格式化分享率为百分比
const formatShareRate = (rate) => {
return (rate * 100).toFixed(2) + '%';
};
// 格式化日期
const formatDate = (date) => {
if (!date) return '-';
return new Date(date).toLocaleDateString();
};
// 格式化日期
const formatDateTime = (dateTime) => {
if (!dateTime) return '-';
return new Date(dateTime).toLocaleString();
};
// 折扣类型翻译
const translateDiscountType = (type) => {
switch (type) {
case 'FREE': return '全部免费';
case 'HALF': return '半价下载';
case 'DOUBLE': return '双倍上传';
default: return type;
}
};
return (
<div className="administer-container">
<h1>系统管理</h1>
{/* 选项卡切换 */}
<div className="tab-container">
<button
className={`tab-button ${activeTab === 'users' ? 'active' : ''}`}
onClick={() => setActiveTab('users')}
>
用户管理
</button>
<button
className={`tab-button ${activeTab === 'discounts' ? 'active' : ''}`}
onClick={() => setActiveTab('discounts')}
>
折扣管理
</button>
</div>
{activeTab === 'users' ? (
<>
{/* 搜索框 */}
<div className="search-container">
<input
type="text"
value={searchKey}
onChange={(e) => setSearchKey(e.target.value)}
placeholder="输入用户名搜索"
className="search-input"
/>
<button onClick={handleSearch} className="search-button">
搜索
</button>
<button onClick={handleReset} className="reset-button">
重置
</button>
</div>
{/* 错误提示 */}
{error && <div className="error-message">{error}</div>}
{/* 加载状态 */}
{loading && <div className="loading-message">加载中...</div>}
{/* 用户列表 */}
<div className="user-list-container">
<table className="user-table">
<thead>
<tr>
<th>用户名</th>
<th>注册时间</th>
<th>最后登录</th>
<th>上传量</th>
<th>下载量</th>
<th>分享率</th>
<th>魔力值</th>
<th>权限</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{Array.isArray(users) && users.map((user) => (
<tr key={user.username}>
<td>{user.username}</td>
<td>{formatDate(user.registTime)}</td>
<td>{formatDate(user.lastLogin)}</td>
<td>{user.upload}</td>
<td>{user.download}</td>
<td>{formatShareRate(user.shareRate)}</td>
<td>{user.magicPoints}</td>
<td>{user.authority}</td>
<td>
<select
value={user.authority}
onChange={(e) => handleChangeAuthority(user.username, e.target.value)}
className="authority-select"
>
<option value="USER">普通用户</option>
<option value="ADMIN">管理员</option>
<option value="LIMIT">受限用户</option>
<option value="BAN">封禁用户</option>
</select>
</td>
</tr>
))}
</tbody>
</table>
</div>
</>
) : (
/* 新增的折扣管理部分 */
<>
{/* 当前活动折扣 */}
<div className="current-discount-section">
<h3>当前活动折扣</h3>
{currentDiscount ? (
<div className="current-discount-card">
<p><strong>名称:</strong> {currentDiscount.name}</p>
<p><strong>类型:</strong> {translateDiscountType(currentDiscount.discountType)}</p>
<p><strong>时间:</strong> {formatDateTime(currentDiscount.startTime)} 至 {formatDateTime(currentDiscount.endTime)}</p>
<p><strong>状态:</strong> {currentDiscount.status}</p>
</div>
) : (
<p>当前没有进行中的折扣</p>
)}
</div>
{/* 添加新折扣表单 */}
<div className="add-discount-form">
<h3>添加新折扣</h3>
<div className="form-group">
<label>折扣名称:</label>
<input
type="text"
value={newDiscount.name}
onChange={(e) => setNewDiscount({...newDiscount, name: e.target.value})}
/>
</div>
<div className="form-group">
<label>开始时间:</label>
<DatePicker
selected={startDate}
onChange={(date) => setStartDate(date)}
showTimeSelect
timeFormat="HH:mm"
timeIntervals={1} // 1分钟间隔
dateFormat="yyyy-MM-dd HH:mm"
minDate={new Date()}
placeholderText="选择开始日期和时间"
/>
</div>
<div className="form-group">
<label>结束时间:</label>
<DatePicker
selected={endDate}
onChange={(date) => setEndDate(date)}
showTimeSelect
timeFormat="HH:mm"
timeIntervals={1} // 1分钟间隔
dateFormat="yyyy-MM-dd HH:mm"
minDate={startDate}
placeholderText="选择结束日期和时间"
/>
</div>
<div className="form-group">
<label>折扣类型:</label>
<select
value={newDiscount.discountType}
onChange={(e) => setNewDiscount({...newDiscount, discountType: e.target.value})}
>
<option value="FREE">全部免费</option>
<option value="HALF">半价下载</option>
<option value="DOUBLE">双倍上传</option>
</select>
</div>
<button
onClick={(e) => {
e.preventDefault(); // 确保没有阻止默认行为
handleAddDiscount();
}}
>
添加折扣
</button>
</div>
{/* 所有折扣列表 */}
<div className="discount-list-container">
<h3>所有折扣计划</h3>
<table className="discount-table">
<thead>
<tr>
<th>ID</th>
<th>名称</th>
<th>开始时间</th>
<th>结束时间</th>
<th>类型</th>
<th>创建时间</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{discounts.map(discount => (
<tr key={discount.id}>
<td>{discount.id}</td>
<td>{discount.name}</td>
<td>{formatDateTime(discount.startTime)}</td>
<td>{formatDateTime(discount.endTime)}</td>
<td>{translateDiscountType(discount.discountType)}</td>
<td>{formatDateTime(discount.createTime)}</td>
<td>{discount.status || '未知'}</td>
<td>
<button
onClick={() => handleDeleteDiscount(discount.id)}
className="delete-button"
>
删除
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</>
)}
</div>
);
};
export default Administer;