📝 feat(SettingsAnnouncements/SettingsFAQ): update placeholders & success texts, add Markdown/HTML hint

• SettingsAnnouncements.js
  – Placeholder now states “Supports Markdown/HTML” for both small & expanded editors
  – Success/alert messages unified to use Chinese quotation marks

• SettingsFAQ.js
  – Answer textarea placeholder updated with Markdown/HTML support note
  – Unified success/alert messages punctuation

These tweaks clarify rich-text support and keep UI copy consistent.
This commit is contained in:
t0ng7u
2025-06-21 22:31:19 +08:00
parent b842baf21f
commit ea379e1d0e
5 changed files with 55 additions and 27 deletions

View File

@@ -113,25 +113,31 @@ const NoticeModal = ({ visible, onClose, isMobile, defaultTab = 'inApp', unreadK
return ( return (
<div className="max-h-[55vh] overflow-y-auto pr-2 card-content-scroll"> <div className="max-h-[55vh] overflow-y-auto pr-2 card-content-scroll">
<Timeline mode="alternate"> <Timeline mode="alternate">
{processedAnnouncements.map((item, idx) => ( {processedAnnouncements.map((item, idx) => {
<Timeline.Item const htmlContent = marked.parse(item.content || '');
key={idx} const htmlExtra = item.extra ? marked.parse(item.extra) : '';
type={item.type} return (
time={item.time} <Timeline.Item
className={item.isUnread ? '' : ''} key={idx}
> type={item.type}
<div> time={item.time}
{item.isUnread ? ( className={item.isUnread ? '' : ''}
<span className="shine-text"> >
{item.content} <div>
</span> <div
) : ( className={item.isUnread ? 'shine-text' : ''}
item.content dangerouslySetInnerHTML={{ __html: htmlContent }}
)} />
{item.extra && <div className="text-xs text-gray-500">{item.extra}</div>} {item.extra && (
</div> <div
</Timeline.Item> className="text-xs text-gray-500"
))} dangerouslySetInnerHTML={{ __html: htmlExtra }}
/>
)}
</div>
</Timeline.Item>
);
})}
</Timeline> </Timeline>
</div> </div>
); );

View File

@@ -1615,6 +1615,7 @@
"编辑公告": "Edit Notice", "编辑公告": "Edit Notice",
"公告内容": "Notice Content", "公告内容": "Notice Content",
"请输入公告内容": "Please enter the notice content", "请输入公告内容": "Please enter the notice content",
"请输入公告内容(支持 Markdown/HTML": "Please enter the notice content (supports Markdown/HTML)",
"发布日期": "Publish Date", "发布日期": "Publish Date",
"请选择发布日期": "Please select the publish date", "请选择发布日期": "Please select the publish date",
"发布时间": "Publish Time", "发布时间": "Publish Time",
@@ -1630,6 +1631,7 @@
"请输入问题标题": "Please enter the question title", "请输入问题标题": "Please enter the question title",
"回答内容": "Answer Content", "回答内容": "Answer Content",
"请输入回答内容": "Please enter the answer content", "请输入回答内容": "Please enter the answer content",
"请输入回答内容(支持 Markdown/HTML": "Please enter the answer content (supports Markdown/HTML)",
"确定要删除此问答吗?": "Are you sure you want to delete this FAQ?", "确定要删除此问答吗?": "Are you sure you want to delete this FAQ?",
"系统公告管理可以发布系统通知和重要消息最多100个前端显示最新20条": "System notice management, you can publish system notices and important messages (maximum 100, display latest 20 on the front end)", "系统公告管理可以发布系统通知和重要消息最多100个前端显示最新20条": "System notice management, you can publish system notices and important messages (maximum 100, display latest 20 on the front end)",
"常见问答管理为用户提供常见问题的答案最多50个前端显示最新20条": "FAQ management, providing answers to common questions for users (maximum 50, display latest 20 on the front end)", "常见问答管理为用户提供常见问题的答案最多50个前端显示最新20条": "FAQ management, providing answers to common questions for users (maximum 50, display latest 20 on the front end)",

View File

@@ -2,6 +2,7 @@ import React, { useContext, useEffect, useRef, useState, useMemo, useCallback }
import { initVChartSemiTheme } from '@visactor/vchart-semi-theme'; import { initVChartSemiTheme } from '@visactor/vchart-semi-theme';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { Wallet, Activity, Zap, Gauge, PieChart, Server, Bell, HelpCircle } from 'lucide-react'; import { Wallet, Activity, Zap, Gauge, PieChart, Server, Bell, HelpCircle } from 'lucide-react';
import { marked } from 'marked';
import { import {
Card, Card,
@@ -1267,10 +1268,27 @@ const Detail = (props) => {
onScroll={() => handleCardScroll(announcementScrollRef, setShowAnnouncementScrollHint)} onScroll={() => handleCardScroll(announcementScrollRef, setShowAnnouncementScrollHint)}
> >
{announcementData.length > 0 ? ( {announcementData.length > 0 ? (
<Timeline <Timeline mode="alternate">
mode="alternate" {announcementData.map((item, idx) => (
dataSource={announcementData} <Timeline.Item
/> key={idx}
type={item.type || 'default'}
time={item.time}
>
<div>
<div
dangerouslySetInnerHTML={{ __html: marked.parse(item.content || '') }}
/>
{item.extra && (
<div
className="text-xs text-gray-500"
dangerouslySetInnerHTML={{ __html: marked.parse(item.extra) }}
/>
)}
</div>
</Timeline.Item>
))}
</Timeline>
) : ( ) : (
<div className="flex justify-center items-center py-8"> <div className="flex justify-center items-center py-8">
<Empty <Empty
@@ -1321,7 +1339,9 @@ const Detail = (props) => {
header={item.question} header={item.question}
itemKey={index.toString()} itemKey={index.toString()}
> >
<p>{item.answer}</p> <div
dangerouslySetInnerHTML={{ __html: marked.parse(item.answer || '') }}
/>
</Collapse.Panel> </Collapse.Panel>
))} ))}
</Collapse> </Collapse>

View File

@@ -494,7 +494,7 @@ const SettingsAnnouncements = ({ options, refresh }) => {
<Form.TextArea <Form.TextArea
field='content' field='content'
label={t('公告内容')} label={t('公告内容')}
placeholder={t('请输入公告内容')} placeholder={t('请输入公告内容(支持 Markdown/HTML')}
maxCount={500} maxCount={500}
rows={3} rows={3}
rules={[{ required: true, message: t('请输入公告内容') }]} rules={[{ required: true, message: t('请输入公告内容') }]}
@@ -571,7 +571,7 @@ const SettingsAnnouncements = ({ options, refresh }) => {
> >
<TextArea <TextArea
value={announcementForm.content} value={announcementForm.content}
placeholder={t('请输入公告内容')} placeholder={t('请输入公告内容(支持 Markdown/HTML')}
maxCount={500} maxCount={500}
rows={15} rows={15}
style={{ width: '100%' }} style={{ width: '100%' }}

View File

@@ -424,7 +424,7 @@ const SettingsFAQ = ({ options, refresh }) => {
<Form.TextArea <Form.TextArea
field='answer' field='answer'
label={t('回答内容')} label={t('回答内容')}
placeholder={t('请输入回答内容')} placeholder={t('请输入回答内容(支持 Markdown/HTML')}
maxCount={1000} maxCount={1000}
rows={6} rows={6}
rules={[{ required: true, message: t('请输入回答内容') }]} rules={[{ required: true, message: t('请输入回答内容') }]}