fix(announcements): 公告分类中文化并修正筛选
This commit is contained in:
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user