import React, { useCallback, useEffect, useState } from 'react'; import Grid from '@mui/material/Grid'; import Card from '@mui/material/Card'; import CardContent from '@mui/material/CardContent'; import Typography from '@mui/material/Typography'; import Button from '@mui/material/Button'; import Box from '@mui/material/Box'; import Chip from '@mui/material/Chip'; import IconButton from '@mui/material/IconButton'; import EditIcon from '@mui/icons-material/Edit'; import DeleteIcon from '@mui/icons-material/Delete'; import AddIcon from '@mui/icons-material/Add'; import Dialog from '@mui/material/Dialog'; import DialogTitle from '@mui/material/DialogTitle'; import DialogContent from '@mui/material/DialogContent'; import DialogActions from '@mui/material/DialogActions'; import TextField from '@mui/material/TextField'; import { listCategories, createCategory, updateCategory, deleteCategory, listPosts } from '../../api/forum.js'; import { showSnack } from '../snack.jsx'; import ConfirmDialog from '../ConfirmDialog.jsx'; const EMPTY = { name: '', description: '', announcement: '', sub_categories: '', sort_order: '0' }; /** 论坛管理:板块卡片(帖子数)+ 添加/编辑弹窗 + 删除(MUI 版,同前台 ForumManage API) */ export default function ForumManage() { const [cats, setCats] = useState([]); const [counts, setCounts] = useState({}); const [dialog, setDialog] = useState(false); const [editingId, setEditingId] = useState(null); const [form, setForm] = useState(EMPTY); const [confirm, setConfirm] = useState(null); const [saving, setSaving] = useState(false); const load = useCallback(() => { listCategories() .then((cs) => setCats(cs || [])) .catch((e) => showSnack(e.message, 'error')); listPosts() .then((ps) => { const c = {}; (ps || []).forEach((p) => { c[p.category_id] = (c[p.category_id] || 0) + 1; }); setCounts(c); }) .catch(() => {}); }, []); useEffect(() => { load(); }, [load]); const openAdd = () => { setEditingId(null); setForm(EMPTY); setDialog(true); }; const openEdit = (c) => { setEditingId(c.id); setForm({ name: c.name, description: c.description || '', announcement: c.announcement || '', sub_categories: c.sub_categories || '', sort_order: String(c.sort_order || 0), }); setDialog(true); }; const save = async () => { if (!form.name.trim()) { showSnack('名称不能为空', 'error'); return; } setSaving(true); const data = { name: form.name.trim(), description: form.description.trim(), announcement: form.announcement.trim(), sub_categories: form.sub_categories.trim(), sort_order: parseInt(form.sort_order, 10) || 0, }; try { if (editingId) await updateCategory(editingId, data); else await createCategory(data); showSnack('保存成功'); setDialog(false); load(); } catch (e) { showSnack(e.message, 'error'); } setSaving(false); }; const doDelete = async () => { if (!confirm) return; try { await deleteCategory(confirm.id); showSnack('已删除'); setConfirm(null); load(); } catch (e) { showSnack(e.message, 'error'); } }; return ( 论坛管理 {cats.length === 0 ? ( 暂无板块,点击"添加板块"创建 ) : ( {cats.map((c) => ( {c.name} {c.description || '无描述'} {c.announcement && ( 📢 {c.announcement} )} {counts[c.id] || 0} 个帖子 openEdit(c)} title="编辑"> setConfirm({ id: c.id, name: c.name })}> ))} )} setDialog(false)} fullWidth maxWidth="sm"> {editingId ? '编辑板块' : '添加板块'} setForm((p) => ({ ...p, name: e.target.value }))} margin="normal" /> setForm((p) => ({ ...p, description: e.target.value }))} margin="normal" /> setForm((p) => ({ ...p, announcement: e.target.value }))} margin="normal" /> setForm((p) => ({ ...p, sub_categories: e.target.value }))} margin="normal" placeholder="例: 求助,分享,讨论,建议" /> setForm((p) => ({ ...p, sort_order: e.target.value }))} margin="normal" sx={{ maxWidth: 160 }} /> setConfirm(null)} onConfirm={doDelete} confirmText="确认删除" /> ); }