fix(announcements): 公告分类中文化并修正筛选

This commit is contained in:
2026-11-13 11:28:58 +08:00
parent d65b8d8089
commit b11c77e47f
6 changed files with 85 additions and 22 deletions
+4 -10
View File
@@ -223,21 +223,15 @@ export const announcementStatusMap: Record<string, StatusMeta> = {
archived: { label: '已归档', tone: 'default' },
}
export const announcementCategoryMap: Record<string, string> = {
notice: '通知',
tutorial: '教程',
rule: '规则',
faq: '常见问题',
}
export {
announcementCategoryMap,
announcementCategoryOptions,
} from '@/features/announcements/labels'
export const announcementStatusOptions = Object.entries(announcementStatusMap).map(
([value, meta]) => ({ value, label: meta.label })
)
export const announcementCategoryOptions = Object.entries(announcementCategoryMap).map(
([value, label]) => ({ value, label })
)
export const auditActorTypeMap: Record<string, string> = {
admin: '管理员',
user: '用户',
@@ -3,7 +3,8 @@ import { ArrowLeftOutlined } from '@ant-design/icons'
import { useNavigate, useParams } from 'react-router-dom'
import { useAnnouncement } from '@/features/announcements/api'
import { formatDateTime, formatText } from '@/shared/utils/format'
import { announcementCategoryLabel } from '@/features/announcements/labels'
import { formatDateTime } from '@/shared/utils/format'
export function AnnouncementDetailPage() {
const { id } = useParams()
@@ -39,7 +40,7 @@ export function AnnouncementDetailPage() {
<Space size={8} wrap style={{ marginBottom: 16 }}>
{item.is_pinned ? <Tag color="red">置顶</Tag> : null}
{item.is_important ? <Tag color="orange">重要</Tag> : null}
<Tag bordered={false}>{formatText(item.category)}</Tag>
<Tag bordered={false}>{announcementCategoryLabel(item.category)}</Tag>
<Typography.Text type="secondary">
{formatDateTime(item.published_at || item.created_at)} · 阅读 {item.view_count}
</Typography.Text>
@@ -3,15 +3,14 @@ import { Alert, Card, Pagination, Segmented, Space, Tag, Typography } from 'antd
import { Link } from 'react-router-dom'
import { useAnnouncements } from '@/features/announcements/api'
import {
announcementCategoryLabel,
announcementCategoryOptions,
} from '@/features/announcements/labels'
import type { Announcement } from '@/features/announcements/types'
import { formatDateTime, formatText } from '@/shared/utils/format'
import { formatDateTime } from '@/shared/utils/format'
const categoryOptions = [
{ value: '', label: '全部' },
{ value: 'system', label: '系统公告' },
{ value: 'order', label: '订单规则' },
{ value: 'activity', label: '活动' },
]
const categoryOptions = [{ value: '', label: '全部' }, ...announcementCategoryOptions]
export function AnnouncementsPage() {
const [category, setCategory] = useState('')
@@ -62,7 +61,7 @@ export function AnnouncementsPage() {
<Space size={8} wrap style={{ marginBottom: 6 }}>
{item.is_pinned ? <Tag color="red">置顶</Tag> : null}
{item.is_important ? <Tag color="orange">重要</Tag> : null}
<Tag bordered={false}>{formatText(item.category)}</Tag>
<Tag bordered={false}>{announcementCategoryLabel(item.category)}</Tag>
<Typography.Text strong style={{ fontSize: 16 }}>
{item.title}
</Typography.Text>
@@ -0,0 +1,43 @@
import { describe, expect, it } from 'vitest'
import {
announcementCategoryLabel,
announcementCategoryMap,
announcementCategoryOptions,
} from './labels'
describe('announcementCategoryLabel', () => {
it('映射四个公告分类', () => {
expect(announcementCategoryLabel('notice')).toBe('通知公告')
expect(announcementCategoryLabel('tutorial')).toBe('使用教程')
expect(announcementCategoryLabel('rule')).toBe('规则说明')
expect(announcementCategoryLabel('faq')).toBe('常见问题')
})
it('未知分类保留原始值', () => {
expect(announcementCategoryLabel('activity')).toBe('activity')
expect(announcementCategoryLabel(' system ')).toBe('system')
})
it('空值显示破折号', () => {
expect(announcementCategoryLabel('')).toBe('—')
expect(announcementCategoryLabel(' ')).toBe('—')
expect(announcementCategoryLabel(null)).toBe('—')
expect(announcementCategoryLabel(undefined)).toBe('—')
})
})
describe('announcementCategoryOptions', () => {
it('按固定顺序输出四个分类选项', () => {
expect(announcementCategoryOptions).toEqual([
{ value: 'notice', label: '通知公告' },
{ value: 'tutorial', label: '使用教程' },
{ value: 'rule', label: '规则说明' },
{ value: 'faq', label: '常见问题' },
])
})
it('映射表与选项数量一致', () => {
expect(announcementCategoryOptions).toHaveLength(Object.keys(announcementCategoryMap).length)
})
})
@@ -0,0 +1,25 @@
/**
* 公告分类中文映射:与后台「公告分类」下拉保持一致。
* 后端 category 取值固定为 notice / tutorial / rule / faq。
*/
export const announcementCategoryMap: Record<string, string> = {
notice: '通知公告',
tutorial: '使用教程',
rule: '规则说明',
faq: '常见问题',
}
export const announcementCategoryOptions = Object.entries(announcementCategoryMap).map(
([value, label]) => ({ value, label })
)
/**
* 公告分类展示文案:
* - 未知分类保留原始值,避免历史数据被吞掉
* - 空值统一显示破折号
*/
export function announcementCategoryLabel(code?: string | null): string {
const key = (code ?? '').trim()
if (!key) return '—'
return announcementCategoryMap[key] ?? key
}
@@ -2,7 +2,8 @@ import { Card, ErrorBlock, NavBar, Skeleton, Tag } from 'antd-mobile'
import { useNavigate, useParams } from 'react-router-dom'
import { useAnnouncement } from '@/features/announcements/api'
import { formatDateTime, formatText } from '@/shared/utils/format'
import { announcementCategoryLabel } from '@/features/announcements/labels'
import { formatDateTime } from '@/shared/utils/format'
export function MobileAnnouncementDetailPage() {
const { id } = useParams()
@@ -33,7 +34,7 @@ export function MobileAnnouncementDetailPage() {
<div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
{item.is_pinned ? <Tag color="danger">置顶</Tag> : null}
{item.is_important ? <Tag color="warning">重要</Tag> : null}
<Tag>{formatText(item.category)}</Tag>
<Tag>{announcementCategoryLabel(item.category)}</Tag>
</div>
<span className="mobile-wallet__sub">
{formatDateTime(item.published_at || item.created_at)} · 阅读 {item.view_count}