/* Copyright (c) 2025 Tethys Plex This file is part of Veloera. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ import React, { useState, useEffect } from 'react'; import { API, isMobile, showError, showSuccess } from '../../helpers'; import Title from '@douyinfe/semi-ui/lib/es/typography/title'; import { Button, Input, SideSheet, Space, Spin, TextArea, RadioGroup, Radio, Table, Tag, Descriptions } from '@douyinfe/semi-ui'; import { useTranslation } from 'react-i18next'; const EditMessage = (props) => { const { t } = useTranslation(); const [inputs, setInputs] = useState({ title: '', content: '', format: 'markdown', }); const [loading, setLoading] = useState(false); const [messageDetails, setMessageDetails] = useState(null); const [recipients, setRecipients] = useState([]); const [recipientLoading, setRecipientLoading] = useState(false); const { title, content, format } = inputs; const handleInputChange = (name, value) => { setInputs((inputs) => ({ ...inputs, [name]: value })); }; const loadMessageDetails = async (messageId) => { if (!messageId) return; setLoading(true); try { const res = await API.get(`/api/admin/messages/${messageId}`); const { success, message, data } = res.data; if (success) { setMessageDetails(data); setInputs({ title: data.title || '', content: data.content || '', format: data.format || 'markdown', }); loadRecipients(messageId); } else { showError(message); } } catch (error) { showError(error.message); } setLoading(false); }; const loadRecipients = async (messageId) => { setRecipientLoading(true); try { const res = await API.get(`/api/admin/messages/${messageId}/recipients`); const { success, message, data } = res.data; if (success) { setRecipients(data || []); } else { showError(message); } } catch (error) { showError(error.message); } setRecipientLoading(false); }; useEffect(() => { if (props.visible && props.editingMessage?.id) { loadMessageDetails(props.editingMessage.id); } }, [props.visible, props.editingMessage?.id]); const recipientColumns = [ { title: 'ID', dataIndex: 'user_id', width: 80, }, { title: t('用户名'), dataIndex: 'username', }, { title: t('显示名称'), dataIndex: 'display_name', render: (text) => text || '-', }, { title: t('阅读状态'), dataIndex: 'read_at', width: 120, render: (text) => ( {text ? t('已读') : t('未读')} ), }, { title: t('阅读时间'), dataIndex: 'read_at', width: 180, render: (text) => { return text ? new Date(text).toLocaleString() : '-'; }, }, ]; const submit = async () => { setLoading(true); if (!inputs.title.trim()) { showError(t('请输入消息标题')); setLoading(false); return; } if (!inputs.content.trim()) { showError(t('请输入消息内容')); setLoading(false); return; } const messageData = { title: inputs.title.trim(), content: inputs.content.trim(), format: inputs.format, }; try { const res = await API.put(`/api/admin/messages/${props.editingMessage.id}`, messageData); const { success, message } = res.data; if (success) { showSuccess(t('消息更新成功')); props.refresh(); props.handleClose(); } else { showError(message); } } catch (error) { showError(error.message); } setLoading(false); }; const handleCancel = () => { setInputs({ title: '', content: '', format: 'markdown', }); setMessageDetails(null); setRecipients([]); props.handleClose(); }; return ( <> {t('编辑消息')}} headerStyle={{ borderBottom: '1px solid var(--semi-color-border)' }} bodyStyle={{ borderBottom: '1px solid var(--semi-color-border)' }} visible={props.visible} footer={
} closeIcon={null} onCancel={() => handleCancel()} width={isMobile() ? '100%' : 900} >
{messageDetails && (
r.read_at).length }, ]} row size="small" />
)} handleInputChange('title', value)} style={{ marginBottom: 20 }} />
handleInputChange('format', e.target.value)} > Markdown HTML