blob: 834ad739c62685c4b3762b8e7eef364025a6268c [file] [log] [blame]
import React, { useState, useEffect } from 'react';
import './PromotionsPage.css';
function PromotionsPage() {
const [promotions, setPromotions] = useState([]);
const [currentPromotion, setCurrentPromotion] = useState(null);
const [isAdmin, setIsAdmin] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const [formData, setFormData] = useState({
name: '',
uploadCoeff: 1,
downloadCoeff: 1,
timeRange: 0,
criteria: 1,
pStartTime: '',
pEndTime: ''
});
const [isCreating, setIsCreating] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
const [perPage] = useState(10);
const [totalPromotions, setTotalPromotions] = useState(0);
const getAuthHeaders = () => {
const token = localStorage.getItem('token');
return {
'Authorization': token ? `Bearer ${token}` : '',
'Content-Type': 'application/json'
};
};
const fetchPromotions = async (page = 1) => {
setIsLoading(true);
try {
const response = await fetch(`/promotions/list?page=${page}&per_page=${perPage}`, {
headers: getAuthHeaders()
});
if (!response.ok) {
throw new Error('获取促销活动失败');
}
const data = await response.json();
if (data.code === 0 && data.result) {
setPromotions(data.rows || []);
setTotalPromotions(data.total || 0);
} else {
throw new Error(data.msg || '获取促销活动失败');
}
} catch (err) {
console.error('获取促销活动错误:', err);
setError(err.message);
} finally {
setIsLoading(false);
}
};
const fetchPromotionDetails = async (promoId) => {
setIsLoading(true);
try {
const response = await fetch(`/promotions/${promoId}`, {
headers: getAuthHeaders()
});
if (!response.ok) {
throw new Error('获取促销详情失败');
}
const data = await response.json();
if (data.code === 0 && data.result) {
setCurrentPromotion(data.rows);
} else {
throw new Error(data.msg || '获取促销详情失败');
}
} catch (err) {
console.error('获取促销详情错误:', err);
setError(err.message);
} finally {
setIsLoading(false);
}
};
const createPromotion = async () => {
if (!formData.name || !formData.pStartTime || !formData.pEndTime) {
alert('请填写完整活动信息');
return;
}
if (new Date(formData.pStartTime) >= new Date(formData.pEndTime)) {
alert('活动时间设置不正确,请重新设定');
return;
}
setIsLoading(true);
try {
const response = await fetch('/promotions/add', {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(formData)
});
if (!response.ok) {
throw new Error('创建促销活动失败');
}
const data = await response.json();
if (data.code === 0 && data.result) {
alert(`活动创建成功!活动ID: ${data.msg}`);
setIsCreating(false);
setFormData({
name: '',
uploadCoeff: 1,
downloadCoeff: 1,
timeRange: 0,
criteria: 1,
pStartTime: '',
pEndTime: ''
});
fetchPromotions();
} else {
throw new Error(data.msg || '创建促销活动失败');
}
} catch (err) {
console.error('创建促销活动错误:', err);
alert(err.message);
} finally {
setIsLoading(false);
}
};
const deletePromotion = async (promoId) => {
if (!window.confirm('确定要删除这个促销活动吗?')) {
return;
}
setIsLoading(true);
try {
const response = await fetch(`/promotions/delete/${promoId}`, {
method: 'DELETE',
headers: getAuthHeaders()
});
if (!response.ok) {
throw new Error('删除促销活动失败');
}
const data = await response.json();
if (data.code === 0 && data.result) {
alert('促销活动删除成功');
fetchPromotions();
if (currentPromotion && currentPromotion.promoId === promoId) {
setCurrentPromotion(null);
}
} else {
throw new Error(data.msg || '删除促销活动失败');
}
} catch (err) {
console.error('删除促销活动错误:', err);
alert(err.message);
} finally {
setIsLoading(false);
}
};
const checkAdminStatus = () => {
const role = localStorage.getItem('role');
setIsAdmin(role === 'admin');
};
useEffect(() => {
checkAdminStatus();
fetchPromotions();
}, []);
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: name === 'uploadCoeff' || name === 'downloadCoeff' || name === 'timeRange' || name === 'criteria'
? parseFloat(value)
: value
}));
};
const handlePageChange = (newPage) => {
setCurrentPage(newPage);
fetchPromotions(newPage);
};
const getPromotionType = (promo) => {
if (promo.downloadCoeff === 0 && promo.uploadCoeff > 1) {
return '免费';
} else if (promo.downloadCoeff < 1 && promo.uploadCoeff > 1) {
return '折扣+上传奖励';
} else if (promo.downloadCoeff < 1) {
return '折扣';
} else if (promo.uploadCoeff > 1) {
return '上传奖励';
}
return '普通';
};
return (
<div className="promotions-page">
<div className="promotions-container">
<h1>促销活动</h1>
{isAdmin && (
<div className="admin-actions">
<button
className="create-button"
onClick={() => setIsCreating(!isCreating)}
>
{isCreating ? '取消创建' : '创建新活动'}
</button>
</div>
)}
{isCreating && isAdmin && (
<div className="create-promotion-form">
<h2>创建新促销活动</h2>
<div className="form-group">
<label>活动名称</label>
<input
type="text"
name="name"
value={formData.name}
onChange={handleInputChange}
placeholder="例如: 春节特惠"
/>
</div>
<div className="form-row">
<div className="form-group">
<label>上传量系数</label>
<input
type="number"
name="uploadCoeff"
min="0"
step="0.1"
value={formData.uploadCoeff}
onChange={handleInputChange}
/>
</div>
<div className="form-group">
<label>下载量系数</label>
<input
type="number"
name="downloadCoeff"
min="0"
step="0.1"
value={formData.downloadCoeff}
onChange={handleInputChange}
/>
</div>
</div>
<div className="form-row">
<div className="form-group">
<label>资源时间范围</label>
<select
name="timeRange"
value={formData.timeRange}
onChange={handleInputChange}
>
<option value="0">全站资源</option>
<option value="1">当天上传</option>
<option value="2">最近两天</option>
<option value="7">最近一周</option>
<option value="30">最近一个月</option>
</select>
</div>
<div className="form-group">
<label>最低用户等级</label>
<input
type="number"
name="criteria"
min="1"
value={formData.criteria}
onChange={handleInputChange}
/>
</div>
</div>
<div className="form-row">
<div className="form-group">
<label>开始时间</label>
<input
type="datetime-local"
name="pStartTime"
value={formData.pStartTime}
onChange={handleInputChange}
/>
</div>
<div className="form-group">
<label>结束时间</label>
<input
type="datetime-local"
name="pEndTime"
value={formData.pEndTime}
onChange={handleInputChange}
/>
</div>
</div>
<button
className="submit-button"
onClick={createPromotion}
disabled={isLoading}
>
{isLoading ? '创建中...' : '提交创建'}
</button>
</div>
)}
{error && <div className="error-message">{error}</div>}
<div className="promotions-grid">
{/* 促销活动列表 */}
<div className="promotions-list">
<h2>当前促销活动</h2>
{isLoading && promotions.length === 0 ? (
<div className="loading">加载中...</div>
) : promotions.length === 0 ? (
<div className="no-promotions">暂无促销活动</div>
) : (
<div className="promotion-items">
{promotions.map(promo => (
<div
key={promo.promoId}
className={`promotion-item ${currentPromotion && currentPromotion.promoId === promo.promoId ? 'active' : ''}`}
onClick={() => fetchPromotionDetails(promo.promoId)}
>
<div className="promotion-header">
<h3>{promo.name}</h3>
<span className="promotion-type">{getPromotionType(promo)}</span>
</div>
<div className="promotion-dates">
{new Date(promo.pStartTime).toLocaleString()} - {new Date(promo.pEndTime).toLocaleString()}
</div>
<div className="promotion-coeffs">
<span>上传: {promo.uploadCoeff}x</span>
<span>下载: {promo.downloadCoeff}x</span>
</div>
{isAdmin && (
<button
className="delete-button"
onClick={(e) => {
e.stopPropagation();
deletePromotion(promo.promoId);
}}
disabled={isLoading}
>
删除
</button>
)}
</div>
))}
</div>
)}
{totalPromotions > perPage && (
<div className="pagination">
<button
disabled={currentPage === 1}
onClick={() => handlePageChange(currentPage - 1)}
>
上一页
</button>
<span> {currentPage} 页</span>
<button
disabled={currentPage * perPage >= totalPromotions}
onClick={() => handlePageChange(currentPage + 1)}
>
下一页
</button>
</div>
)}
</div>
{/* 促销活动详情 */}
<div className="promotion-details">
{currentPromotion ? (
<>
<h2>{currentPromotion.name}</h2>
<div className="detail-item">
<label>活动ID:</label>
<span>{currentPromotion.promoId}</span>
</div>
<div className="detail-item">
<label>活动时间:</label>
<span>
{new Date(currentPromotion.pStartTime).toLocaleString()} - {new Date(currentPromotion.pEndTime).toLocaleString()}
</span>
</div>
<div className="detail-item">
<label>促销类型:</label>
<span>{getPromotionType(currentPromotion)}</span>
</div>
<div className="detail-item">
<label>上传量系数:</label>
<span>{currentPromotion.uploadCoeff}x</span>
</div>
<div className="detail-item">
<label>下载量系数:</label>
<span>{currentPromotion.downloadCoeff}x</span>
</div>
<div className="detail-item">
<label>适用资源:</label>
<span>
{currentPromotion.timeRange === 0
? '全站资源'
: `最近${currentPromotion.timeRange}天内上传的资源`}
</span>
</div>
<div className="detail-item">
<label>参与条件:</label>
<span>用户等级 {currentPromotion.criteria}</span>
</div>
</>
) : (
<div className="no-selection">请从左侧选择一个促销活动查看详情</div>
)}
</div>
</div>
</div>
</div>
);
}
export default PromotionsPage;