import React, { useEffect, useMemo, useState } from "react"; import { Badge, Button, Card, Col, Form, Input, InputNumber, message, Modal, Popconfirm, Radio, Row, Select, Space, Table, Tag, Tooltip, Typography, } from "antd"; import { DeleteOutlined, EditOutlined, GlobalOutlined, PlusOutlined, SearchOutlined, UserOutlined, } from "@ant-design/icons"; import { useTranslation } from "react-i18next"; import { useDict } from "../../hooks/useDict"; import { deleteHotWord, getHotWordPage, getPinyinSuggestion, saveHotWord, updateHotWord, type HotWordVO, } from "../../api/business/hotword"; const { Option } = Select; const { Text } = Typography; type HotWordFormValues = { word: string; pinyin?: string; category?: string; weight: number; status: number; isPublic: number; remark?: string; }; const HotWords: React.FC = () => { const { t } = useTranslation(); const [form] = Form.useForm(); const { items: categories } = useDict("biz_hotword_category"); const [loading, setLoading] = useState(false); const [data, setData] = useState([]); const [total, setTotal] = useState(0); const [current, setCurrent] = useState(1); const [size, setSize] = useState(10); const [searchWord, setSearchWord] = useState(""); const [searchCategory, setSearchCategory] = useState(undefined); const [searchType, setSearchType] = useState(undefined); const [modalVisible, setModalVisible] = useState(false); const [editingId, setEditingId] = useState(null); const [submitLoading, setSubmitLoading] = useState(false); const userProfile = useMemo(() => { const profileStr = sessionStorage.getItem("userProfile"); return profileStr ? JSON.parse(profileStr) : {}; }, []); const isAdmin = useMemo(() => { return userProfile.isPlatformAdmin === true || userProfile.isTenantAdmin === true; }, [userProfile]); useEffect(() => { void fetchData(); }, [current, searchCategory, searchType, searchWord, size]); const fetchData = async () => { setLoading(true); try { const res = await getHotWordPage({ current, size, word: searchWord, category: searchCategory, isPublic: searchType, }); if (res.data?.data) { setData(res.data.data.records); setTotal(res.data.data.total); } } finally { setLoading(false); } }; const handleOpenModal = (record?: HotWordVO) => { if (record?.isPublic === 1 && !isAdmin) { message.error("公开热词仅限管理员修改"); return; } if (record) { setEditingId(record.id); form.setFieldsValue({ word: record.word, pinyin: record.pinyinList?.[0] || "", category: record.category, weight: record.weight, status: record.status, isPublic: record.isPublic, remark: record.remark, }); } else { setEditingId(null); form.resetFields(); form.setFieldsValue({ weight: 2, status: 1, isPublic: 0 }); } setModalVisible(true); }; const handleDelete = async (id: number) => { try { await deleteHotWord(id); message.success("删除成功"); await fetchData(); } catch { // handled by interceptor } }; const handleSubmit = async () => { try { const values = await form.validateFields(); setSubmitLoading(true); const payload = { ...values, matchStrategy: 1, pinyinList: values.pinyin ? [values.pinyin.trim()] : [], }; if (editingId) { await updateHotWord({ ...payload, id: editingId }); message.success("更新成功"); } else { await saveHotWord(payload); message.success("新增成功"); } setModalVisible(false); await fetchData(); } finally { setSubmitLoading(false); } }; const handleWordBlur = async (e: React.FocusEvent) => { const word = e.target.value?.trim(); if (!word || form.getFieldValue("pinyin")) { return; } try { const res = await getPinyinSuggestion(word); const firstPinyin = res.data?.data?.[0]; if (firstPinyin) { form.setFieldValue("pinyin", firstPinyin); } } catch { // handled by interceptor } }; const columns = [ { title: "热词原文", dataIndex: "word", key: "word", render: (text: string, record: HotWordVO) => ( {text} {record.isPublic === 1 ? ( ) : ( )} ), }, { title: "拼音", dataIndex: "pinyinList", key: "pinyinList", render: (list: string[]) => list?.[0] ? {list[0]} : -, }, { title: "类别", dataIndex: "category", key: "category", render: (value: string) => categories.find((item) => item.itemValue === value)?.itemLabel || value || "-", }, { title: "范围", dataIndex: "isPublic", key: "isPublic", render: (value: number) => (value === 1 ? 公开 : 私有), }, { title: "权重", dataIndex: "weight", key: "weight", render: (value: number) => {value}, }, { title: "状态", dataIndex: "status", key: "status", render: (value: number) => value === 1 ? : , }, { title: "操作", key: "action", render: (_: unknown, record: HotWordVO) => { const isMine = record.creatorId === userProfile.userId; const canEdit = record.isPublic === 1 ? isAdmin : isMine || isAdmin; if (!canEdit) { return 无权操作; } return ( handleDelete(record.id)} okText={t("common.confirm")} cancelText={t("common.cancel")} > ); }, }, ]; return (
} allowClear onPressEnter={(e) => { setSearchWord((e.target as HTMLInputElement).value); setCurrent(1); }} style={{ width: 200 }} /> } >
`共 ${value} 条`, onChange: (page, pageSize) => { setCurrent(page); setSize(pageSize); }, }} /> setModalVisible(false)} confirmLoading={submitLoading} width={560} destroyOnHidden >
{/**/} {/* */} {/**/}
{isAdmin ? ( ) : null} ); }; export default HotWords;