import { useEffect, useState } from 'react'; import { Database, Shield, Server, SlidersHorizontal } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; import { Spinner } from '@/components/ui/spinner'; import { notify } from '@/lib/notify'; import { api } from '../../api/client'; import { useAdminGuard } from '../../layouts/AdminLayout'; import { invalidateForumLimitsCache } from '../../hooks/useForumLimits'; import type { AdminSettings, ForumLimits } from '../../api/types'; type TabId = 'limits' | 'filter' | 'system'; type SettingRow = { key: keyof ForumLimits; label: string; unit?: string; hint?: string; min?: number; }; type SettingSection = { id: string; title: string; summary: string; rows: SettingRow[]; }; const SETTING_SECTIONS: SettingSection[] = [ { id: 'rule', title: '编辑规则', summary: '控制普通用户修改自己帖子的时限', rows: [ { key: 'post_edit_window_hours', label: '可编辑时限', unit: '小时', hint: '0 = 不限', min: 0 }, ], }, { id: 'rate', title: '操作限流', summary: '同一用户或 IP 在窗口期内的最大请求次数', rows: [ { key: 'rate_limit_window_sec', label: '限流窗口', unit: '秒', min: 10 }, { key: 'rate_limit_post', label: '发帖', unit: '次', min: 1 }, { key: 'rate_limit_comment', label: '评论', unit: '次', min: 1 }, { key: 'rate_limit_register', label: '注册', unit: '次', min: 1 }, { key: 'rate_limit_login', label: '登录', unit: '次', min: 1 }, ], }, { id: 'content', title: '内容长度', summary: '发帖与评论的字数上限,服务端强制校验', rows: [ { key: 'post_title_max', label: '帖子标题', unit: '字', min: 1 }, { key: 'post_tags_max', label: '帖子标签', unit: '字', hint: '0 = 不限', min: 0 }, { key: 'post_content_max', label: '帖子正文', unit: '字', hint: '0 = 不限', min: 0 }, { key: 'comment_max', label: '评论内容', unit: '字', min: 1 }, ], }, { id: 'search', title: '搜索与列表', summary: '关键词长度与帖子列表分页', rows: [ { key: 'search_keyword_min', label: '关键词最短', unit: '字', min: 0 }, { key: 'search_keyword_max', label: '关键词最长', unit: '字', min: 1 }, { key: 'page_size_default', label: '默认每页', unit: '条', min: 1 }, { key: 'page_size_max', label: '最大每页', unit: '条', min: 1 }, { key: 'feed_max_pages', label: '首页自动加载页数', unit: '页', hint: '超出后需手动加载', min: 1 }, { key: 'feed_max_items', label: '首页自动加载条数', unit: '条', hint: '与页数取先到上限', min: 1 }, ], }, { id: 'user', title: '用户账号', summary: '注册、改密与头像上传限制', rows: [ { key: 'password_min_len', label: '密码最短', unit: '位', min: 4 }, { key: 'avatar_max_mb', label: '头像上限', unit: 'MB', min: 1 }, ], }, ]; const TABS: { id: TabId; label: string; icon: typeof SlidersHorizontal }[] = [ { id: 'limits', label: '论坛限制', icon: SlidersHorizontal }, { id: 'filter', label: '敏感词', icon: Shield }, { id: 'system', label: '系统维护', icon: Server }, ]; function SettingTable({ sections, limits, onChange, }: { sections: SettingSection[]; limits: ForumLimits; onChange: (key: keyof ForumLimits, value: string) => void; }) { return (
{section.summary}
管理论坛运行规则、敏感词过滤与数据维护
修改后请点击保存,新规则立即对全部用户生效
每行一个词,# 开头为注释。保存后写入 filter_words.txt 并立即生效。
敏感词会在发帖、评论、昵称等文本中自动替换为 *
{settings.data_dir}{settings.db_path}{settings.filter_path}导出当前 SQLite 数据库副本,便于迁移或灾难恢复。
文件名:jiang13_backup_YYYYMMDD_HHMMSS.db