'use client'; import { useState, useEffect, useMemo } from 'react'; import api from '@/lib/api'; import { Loader2, Save, RefreshCw, Settings2, Plus, Trash2, AlertCircle } from 'lucide-react'; import { toast } from 'react-hot-toast'; // 假设你项目中使用了 react-hot-toast,如果没有可以用 alert 替代 export default function TroovBookLimitManager() { const [limits, setLimits] = useState>({}); const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(false); // 新增时间点的表单状态 const [newTime, setNewTime] = useState(''); const [newValue, setNewValue] = useState(1); useEffect(() => { fetchConfig(); }, []); // 获取配置 const fetchConfig = async () => { setLoading(true); try { const res = await api.get('/api/dynamic-configurations/key/troov.book.limit'); let val = res.data?.data?.config_value; // 兼容后端可能返回 JSON 字符串或直接返回对象的情况 if (typeof val === 'string') { try { val = JSON.parse(val); } catch (e) { val = {}; } } setLimits(val || {}); } catch (error) { console.error('获取配置失败:', error); toast.error('加载名额配置失败'); } finally { setLoading(false); } }; // 保存配置 const handleSave = async () => { setSaving(true); try { // 按照你提供的 curl 示例,PUT 接口需要将 config_value 作为序列化后的 JSON 字符串传入 await api.put('/api/dynamic-configurations/key/troov.book.limit', { config_value: JSON.stringify(limits) }); toast.success('配置保存成功!'); fetchConfig(); } catch (error) { console.error('保存配置失败:', error); toast.error('保存配置失败,请重试'); } finally { setSaving(false); } }; // 更新某个时间点的值 const handleUpdateLimit = (time: string, value: string) => { const num = parseInt(value, 10); setLimits(prev => ({ ...prev, [time]: isNaN(num) ? 0 : Math.max(0, num) // 保证不小于0 })); }; // 删除某个时间点 const handleDeleteTime = (time: string) => { if (!confirm(`确定要删除 ${time} 的配置吗?`)) return; const newLimits = { ...limits }; delete newLimits[time]; setLimits(newLimits); }; // 新增时间点 const handleAddTime = (e: React.FormEvent) => { e.preventDefault(); if (!newTime) return; // 简单校验格式 HH:mm if (!/^\d{2}:\d{2}$/.test(newTime)) { return toast.error('时间格式需为 HH:mm,如 09:30'); } if (limits[newTime] !== undefined) { return toast.error('该时间点已存在!'); } setLimits(prev => ({ ...prev, [newTime]: newValue })); setNewTime(''); setNewValue(1); }; // 对时间键进行排序 (09:00, 09:15, 10:00...) 方便展示 const sortedTimes = useMemo(() => { return Object.keys(limits).sort((a, b) => { const [hA, mA] = a.split(':').map(Number); const [hB, mB] = b.split(':').map(Number); return (hA * 60 + mA) - (hB * 60 + mB); }); }, [limits]); return (
{/* 头部 */}

Troov 预约名额限制配置

{/* 主体内容 */}
{loading && Object.keys(limits).length === 0 ? (
) : (
{/* 警告提示 */}

修改此配置将实时影响 Troov 法签机器人对应时间点的单日最大预约数。点击右上角“保存配置”后生效。

{/* 配置网格 */}
{sortedTimes.map((time) => (
{time}
handleUpdateLimit(time, e.target.value)} />
))}
{/* 快速添加时间点 */}
新增时段: setNewTime(e.target.value)} /> 数量: setNewValue(parseInt(e.target.value) || 1)} />
)}
); }