diff --git a/src/admin/pages/UserDetailPage.tsx b/src/admin/pages/UserDetailPage.tsx index 2802852..073b6a5 100644 --- a/src/admin/pages/UserDetailPage.tsx +++ b/src/admin/pages/UserDetailPage.tsx @@ -25,7 +25,8 @@ export function UserDetailPage() { const [spaceQuotaMb, setSpaceQuotaMb] = useState('5'); const [imageQuota, setImageQuota] = useState(null); const [imageQuotaLoading, setImageQuotaLoading] = useState(false); - const [imageGrant, setImageGrant] = useState({ delta: '', note: '' }); + const [imageTotal, setImageTotal] = useState(''); + const [imageGrantNote, setImageGrantNote] = useState(''); useEffect(() => { if (!user?.spaceQuotaBytes) return; @@ -82,6 +83,14 @@ export function UserDetailPage() { }; }, [user?.id, user?.role]); + useEffect(() => { + if (!imageQuota || imageQuota.unlimited || imageQuota.total == null) { + setImageTotal(''); + return; + } + setImageTotal(String(imageQuota.total)); + }, [imageQuota?.total, imageQuota?.unlimited]); + const handleRecharge = async (e: React.FormEvent) => { e.preventDefault(); if (!user) return; @@ -100,24 +109,42 @@ export function UserDetailPage() { } }; - const handleImageGrant = async (e: React.FormEvent) => { + const handleImageQuotaSave = async (e: React.FormEvent) => { e.preventDefault(); if (!user) return; setMessage(null); setLocalError(null); setError(null); - const delta = Math.floor(Number(imageGrant.delta)); - if (!Number.isFinite(delta) || delta === 0) { - setLocalError('请输入非零整数额度'); + if (!imageQuota) { + setLocalError('暂无额度信息,用户可能尚无有效订阅'); + return; + } + if (imageQuota.unlimited) { + setLocalError('当前为无限额度套餐,无法在此调整'); + return; + } + const targetTotal = Math.floor(Number(imageTotal)); + if (!Number.isFinite(targetTotal) || targetTotal < 0) { + setLocalError('请输入非负整数总额度'); + return; + } + if (targetTotal < imageQuota.used) { + setLocalError(`总额度不能低于已用量(${imageQuota.used} 张)`); + return; + } + const targetBonus = targetTotal - imageQuota.limit; + const delta = targetBonus - imageQuota.bonus; + if (delta === 0) { + setMessage('额度未变化'); return; } try { - const result = await grantUserImageQuota(user.id, delta, imageGrant.note.trim()); + const result = await grantUserImageQuota(user.id, delta, imageGrantNote.trim()); setImageQuota(result.quota); setMessage('图片额度已更新'); - setImageGrant({ delta: '', note: '' }); + setImageGrantNote(''); } catch (err) { - setLocalError(err instanceof Error ? err.message : '图片额度调整失败'); + setLocalError(err instanceof Error ? err.message : '图片额度设置失败'); } }; @@ -245,21 +272,31 @@ export function UserDetailPage() { ) : (

{imageQuotaSummary || '暂无额度信息(用户可能尚无订阅)'}

)} -
+

+ 直接设置本周期图片总额度(套餐额度 + 额外充值)。已用量不变,修改后会反映在「充值」部分。 +

+ setImageGrant((s) => ({ ...s, delta: e.target.value }))} + value={imageTotal} + onChange={(e) => setImageTotal(e.target.value)} + disabled={!imageQuota || imageQuota.unlimited} /> setImageGrant((s) => ({ ...s, note: e.target.value }))} + value={imageGrantNote} + onChange={(e) => setImageGrantNote(e.target.value)} + disabled={!imageQuota || imageQuota.unlimited} /> -