feat: Add console announcements and FAQ management system

- Add SettingsAnnouncements component with full CRUD operations for system announcements
  * Support multiple announcement types (default, ongoing, success, warning, error)
  * Include publish date, content, type classification and additional notes
  * Implement batch operations and pagination for better data management
  * Add real-time preview with relative time display and date formatting

- Add SettingsFAQ component for comprehensive FAQ management
  * Support question-answer pairs with rich text content
  * Include full editing, deletion and creation capabilities
  * Implement batch delete operations and paginated display
  * Add validation for complete Q&A information

- Integrate announcement and FAQ modules into DashboardSetting
  * Add unified configuration interface in admin console
  * Implement auto-refresh functionality for real-time updates
  * Add loading states and error handling for better UX

- Enhance backend API support in controller and setting modules
  * Add validation functions for console settings
  * Include time and sorting utilities for announcement management
  * Extend API endpoints for announcement and FAQ data persistence

- Improve frontend infrastructure
  * Add new translation keys for internationalization support
  * Update utility functions for date/time formatting
  * Enhance CSS styles for better component presentation
  * Add icons and visual improvements for announcements and FAQ sections

This implementation provides administrators with comprehensive tools to manage
system-wide announcements and user FAQ content through an intuitive console interface.
This commit is contained in:
Apple\Apple
2025-06-10 20:10:07 +08:00
parent 26521f42d9
commit 0f3696eef3
11 changed files with 1487 additions and 36 deletions

View File

@@ -44,6 +44,9 @@ const SettingsAPIInfo = ({ options, refresh }) => {
route: '',
color: 'blue'
});
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const colorOptions = [
{ value: 'blue', label: 'blue' },
@@ -237,6 +240,7 @@ const SettingsAPIInfo = ({ options, refresh }) => {
{
title: t('操作'),
fixed: 'right',
width: 150,
render: (_, record) => (
<Space>
<Button
@@ -264,12 +268,25 @@ const SettingsAPIInfo = ({ options, refresh }) => {
},
];
const handleBatchDelete = () => {
if (selectedRowKeys.length === 0) {
showError('请先选择要删除的API信息');
return;
}
const newList = apiInfoList.filter(api => !selectedRowKeys.includes(api.id));
setApiInfoList(newList);
setSelectedRowKeys([]);
setHasChanges(true);
showSuccess(`已删除 ${selectedRowKeys.length} 个API信息请及时点击“保存配置”进行保存`);
};
const renderHeader = () => (
<div className="flex flex-col w-full">
<div className="mb-2">
<div className="flex items-center text-blue-500">
<Settings size={16} className="mr-2" />
<Text>{t('API信息管理可以配置多个API地址用于状态展示和负载均衡')}</Text>
<Text>{t('API信息管理可以配置多个API地址用于状态展示和负载均衡最多50个')}</Text>
</div>
</div>
@@ -286,6 +303,16 @@ const SettingsAPIInfo = ({ options, refresh }) => {
>
{t('添加API')}
</Button>
<Button
icon={<Trash2 size={14} />}
type='danger'
theme='light'
onClick={handleBatchDelete}
disabled={selectedRowKeys.length === 0}
className="!rounded-full w-full md:w-auto"
>
{t('批量删除')} {selectedRowKeys.length > 0 && `(${selectedRowKeys.length})`}
</Button>
<Button
icon={<Save size={14} />}
onClick={submitApiInfo}
@@ -301,14 +328,56 @@ const SettingsAPIInfo = ({ options, refresh }) => {
</div>
);
// 计算当前页显示的数据
const getCurrentPageData = () => {
const startIndex = (currentPage - 1) * pageSize;
const endIndex = startIndex + pageSize;
return apiInfoList.slice(startIndex, endIndex);
};
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys, selectedRows) => {
setSelectedRowKeys(selectedRowKeys);
},
onSelect: (record, selected, selectedRows) => {
console.log(`选择行: ${selected}`, record);
},
onSelectAll: (selected, selectedRows) => {
console.log(`全选: ${selected}`, selectedRows);
},
getCheckboxProps: (record) => ({
disabled: false,
name: record.id,
}),
};
return (
<>
<Form.Section text={renderHeader()}>
<Table
columns={columns}
dataSource={apiInfoList}
dataSource={getCurrentPageData()}
rowSelection={rowSelection}
rowKey="id"
scroll={{ x: 'max-content' }}
pagination={false}
pagination={{
currentPage: currentPage,
pageSize: pageSize,
total: apiInfoList.length,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (total, range) => t(`${total} 条记录,显示第 ${range[0]}-${range[1]}`),
pageSizeOptions: ['5', '10', '20', '50'],
onChange: (page, size) => {
setCurrentPage(page);
setPageSize(size);
},
onShowSizeChange: (current, size) => {
setCurrentPage(1);
setPageSize(size);
}
}}
size='middle'
loading={loading}
empty={