From 944ba177bb6f0219943357b13cf54bd552b5059d Mon Sep 17 00:00:00 2001 From: selfrelease Date: Tue, 1 Sep 2026 10:00:03 +0800 Subject: [PATCH] =?UTF-8?q?ux:=20=E7=83=AD=E7=82=B9=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E6=94=B9=E4=B8=BA=E5=88=97=E8=A1=A8=E5=BC=8F?= =?UTF-8?q?=E7=BC=96=E8=BE=91,=E6=94=AF=E6=8C=81=E9=80=90=E6=9D=A1?= =?UTF-8?q?=E5=A2=9E=E5=88=A0=E6=94=B9+=E6=89=B9=E9=87=8F=E7=B2=98?= =?UTF-8?q?=E8=B4=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web2/src/pages/admin/AdminDailyTopics.tsx | 93 ++++++++++++++++------- 1 file changed, 67 insertions(+), 26 deletions(-) diff --git a/web2/src/pages/admin/AdminDailyTopics.tsx b/web2/src/pages/admin/AdminDailyTopics.tsx index 879f04b..4a7f7f8 100644 --- a/web2/src/pages/admin/AdminDailyTopics.tsx +++ b/web2/src/pages/admin/AdminDailyTopics.tsx @@ -1,6 +1,6 @@ import { useEffect, useState, useCallback } from 'react' import { toast } from 'sonner' -import { Sparkles, Loader2, RefreshCw, Pencil, Calendar } from 'lucide-react' +import { Sparkles, Loader2, RefreshCw, Pencil, Calendar, Plus, X } from 'lucide-react' import { PageLayout } from '@/components/common/PageLayout' import { EmptyState } from '@/components/common/EmptyState' import { LoadingState } from '@/components/common/LoadingState' @@ -8,7 +8,7 @@ import { Card, CardContent } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' import { Label } from '@/components/ui/label' -import { Textarea } from '@/components/ui/textarea' +import { Input } from '@/components/ui/input' import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from '@/components/ui/dialog' @@ -160,7 +160,7 @@ export function AdminDailyTopics() { ) } -/** 编辑/创建热点问题弹窗 */ +/** 编辑/创建热点问题弹窗:列表式编辑,每条可单独修改/删除 */ function EditTopicsDialog({ topic, onClose, @@ -172,23 +172,43 @@ function EditTopicsDialog({ }) { const isCreate = !topic const [scene, setScene] = useState(topic?.scene || 'legal') - const [questionsText, setQuestionsText] = useState( - topic?.questions.join('\n') || '', - ) + const [questions, setQuestions] = useState(topic?.questions || ['']) const [saving, setSaving] = useState(false) + /** 更新某行问题 */ + const handleUpdate = (index: number, value: string) => { + setQuestions(prev => prev.map((q, i) => i === index ? value : q)) + } + + /** 删除某行问题 */ + const handleDelete = (index: number) => { + setQuestions(prev => prev.filter((_, i) => i !== index)) + } + + /** 添加空行 */ + const handleAdd = () => { + setQuestions(prev => [...prev, '']) + } + + /** 批量粘贴:从剪贴板按行解析 */ + const handlePaste = (e: React.ClipboardEvent) => { + const text = e.clipboardData.getData('text') + if (text.includes('\n') && text.trim().length > 50) { + e.preventDefault() + const lines = text.split('\n').map(s => s.trim()).filter(Boolean) + setQuestions(prev => [...prev.filter(s => s.trim()), ...lines]) + } + } + const handleSave = async () => { - const questions = questionsText - .split('\n') - .map((s) => s.trim()) - .filter(Boolean) - if (questions.length === 0) { + const valid = questions.map(s => s.trim()).filter(Boolean) + if (valid.length === 0) { toast.error('至少输入一个问题') return } setSaving(true) try { - await api.adminUpdateDailyTopics({ scene, questions }) + await api.adminUpdateDailyTopics({ scene, questions: valid }) toast.success(isCreate ? '热点问题已添加' : '热点问题已更新') onSuccess() } catch (e) { @@ -200,17 +220,17 @@ function EditTopicsDialog({ return ( !o && onClose()}> - + {isCreate ? '添加热点问题' : `编辑 - ${SCENE_LABELS[topic!.scene]}`} - 每行一个问题,保存后用户端实时生效 + 保存后用户端实时生效。可逐条编辑,支持批量粘贴。
{isCreate && (
-
+
{Object.entries(SCENE_LABELS).map(([value, label]) => (