import { useState, useEffect } from 'react' import { Plus, Edit, Crown, Sprout, X, Search, Trophy, Star, Sparkles } from 'lucide-react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table' import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { getLevelConfList, addLevelConf, updateLevelConf, type LevelConf } from '@/api/config' import { cn } from '@/lib/utils' interface LevelFormData { id?: string level: number title: string minSunlight: number perks: string } const defaultFormData: LevelFormData = { level: 1, title: '', minSunlight: 0, perks: '', } export default function LevelConfigPage() { const [levels, setLevels] = useState([]) const [loading, setLoading] = useState(true) const [dialogOpen, setDialogOpen] = useState(false) const [formData, setFormData] = useState(defaultFormData) const [isEdit, setIsEdit] = useState(false) const [submitting, setSubmitting] = useState(false) const [searchTerm, setSearchTerm] = useState('') // 获取列表 const fetchLevels = async () => { setLoading(true) try { const res = await getLevelConfList() let list: LevelConf[] = [] if (res && res.data && Array.isArray(res.data.list)) { list = res.data.list } // Sort by level list.sort((a, b) => a.level - b.level) setLevels(list) } catch (error) { console.error('获取等级配置失败:', error) setLevels([]) } finally { setLoading(false) } } useEffect(() => { fetchLevels() }, []) // 打开新增对话框 const handleAdd = () => { setIsEdit(false) // Auto increment level suggestion const maxLevel = levels.length > 0 ? Math.max(...levels.map(l => l.level)) : 0 setFormData({ ...defaultFormData, level: maxLevel + 1 }) setDialogOpen(true) } // 打开编辑对话框 const handleEdit = (level: LevelConf) => { setIsEdit(true) setFormData({ id: level.id, level: level.level, title: level.title, minSunlight: level.minSunlight, perks: level.perks, }) setDialogOpen(true) } // 提交表单 const handleSubmit = async () => { if (!formData.title) return setSubmitting(true) try { if (isEdit && formData.id) { await updateLevelConf({ ...formData, id: formData.id }) } else { await addLevelConf(formData) } setDialogOpen(false) fetchLevels() } catch (error) { console.error('保存等级配置失败:', error) } finally { setSubmitting(false) } } const filteredLevels = levels.filter(l => l.title.toLowerCase().includes(searchTerm.toLowerCase()) || l.perks?.toLowerCase().includes(searchTerm.toLowerCase()) ) // Calculate stats const maxSunlight = Math.max(...levels.map(l => l.minSunlight), 0) const totalPerks = levels.reduce((acc, curr) => acc + (curr.perks ? 1 : 0), 0) return (
{/* Header & Stats */}
总等级数
{levels.length}

当前配置的等级总数

最高阳光门槛
{maxSunlight.toLocaleString()}

解锁最高等级所需阳光

权益覆盖率
{levels.length > 0 ? Math.round((totalPerks / levels.length) * 100) : 0}%

已配置权益的等级占比

快速添加
New

点击创建新等级配置

{/* Main Content */}
等级列表 {levels.length} 管理用户成长的等级体系,定义每个阶段的阳光值要求与专属特权。
setSearchTerm(e.target.value)} />
{loading ? (

正在加载配置数据...

) : (
等级 称号 & 标识 阳光值门槛 权益说明 操作 {filteredLevels.length === 0 ? (

未找到匹配数据

尝试调整搜索关键词或添加新等级

{searchTerm && ( )}
) : ( filteredLevels.map((item, index) => (
{item.level}
{item.title} {item.level === levels.length && levels.length > 5 && ( MAX )}
{item.minSunlight.toLocaleString()}
{item.perks ? (

{item.perks}

) : ( 暂无权益 )}
)) )}
)}
{isEdit ? : }
{isEdit ? '编辑等级' : '新增等级'}
配置等级数值、称号及对应的权益。这些设置将直接影响用户成长体验。
setFormData({ ...formData, level: parseInt(e.target.value) || 0 })} className="pr-8 font-mono bg-muted/30 focus:bg-background h-10 transition-all" /> {formData.level > 0 && ( )}
setFormData({ ...formData, minSunlight: parseInt(e.target.value) || 0 })} className="pr-8 font-mono bg-muted/30 focus:bg-background h-10 transition-all" /> {formData.minSunlight > 0 && ( )}
setFormData({ ...formData, title: e.target.value })} placeholder="例如:萌芽园丁" className="pr-8 bg-muted/30 focus:bg-background h-10 transition-all" /> {formData.title && ( )}
支持换行