feat(站内通知): 铃铛面板支持时间/内容搜索、按天分组与分页
- 列表接口加 keyword(标题/内容模糊)与 startDate/endDate(年月日闭区间)参数, 两端控制器透传,服务端补筛选日志 - 两端铃铛面板:搜索框(防抖 300ms)+ 日期区间 + 按年月日分组 + 翻页, 面板改 Teleport 到 body(挂在顶栏时会被页面 el-select 压住,提 z-index 无效) - 固化可见范围回归测试:超管全量/管理员只看本组/普通用户只看自己, 含读写两侧的 user_id+audience 裁剪断言与两端控制器身份来源断言
This commit is contained in:
@@ -3,10 +3,12 @@ import assert from 'node:assert/strict'
|
||||
import {
|
||||
formatNotificationTime,
|
||||
formatUnreadBadge,
|
||||
groupNotificationsByDay,
|
||||
hasNewNotification,
|
||||
readLastNotifiedId,
|
||||
writeLastNotifiedId,
|
||||
} from '../src/shared/utils/notification-bell.ts'
|
||||
import { buildNotificationListQuery } from '../src/shared/api/types/modules/notification.ts'
|
||||
|
||||
function createStorage() {
|
||||
const store = new Map<string, string>()
|
||||
@@ -84,3 +86,75 @@ test('formatNotificationTime 今天/昨天/更早展示', () => {
|
||||
assert.equal(formatNotificationTime(null, now), '')
|
||||
assert.equal(formatNotificationTime('not-a-date', now), '')
|
||||
})
|
||||
|
||||
test('groupNotificationsByDay 按年月日分组:今天/昨天/更早,组内保持原顺序', () => {
|
||||
const now = new Date(2026, 8, 13, 15, 30)
|
||||
const items = [
|
||||
{ id: 4, createdAt: new Date(2026, 8, 13, 15, 0).toISOString() },
|
||||
{ id: 3, createdAt: new Date(2026, 8, 13, 9, 0).toISOString() },
|
||||
{ id: 2, createdAt: new Date(2026, 8, 12, 23, 0).toISOString() },
|
||||
{ id: 1, createdAt: new Date(2026, 8, 1, 8, 0).toISOString() },
|
||||
]
|
||||
|
||||
const groups = groupNotificationsByDay(items, now)
|
||||
|
||||
assert.equal(groups.length, 3)
|
||||
assert.deepEqual(
|
||||
groups.map((group) => [group.day, group.label]),
|
||||
[
|
||||
['2026-09-13', '今天'],
|
||||
['2026-09-12', '昨天'],
|
||||
['2026-09-01', '2026年9月1日'],
|
||||
],
|
||||
)
|
||||
assert.deepEqual(
|
||||
groups[0].items.map((item) => item.id),
|
||||
[4, 3],
|
||||
'同一天的多条合为一组且保持倒序',
|
||||
)
|
||||
})
|
||||
|
||||
test('groupNotificationsByDay 时间缺失/非法归入未知时间组', () => {
|
||||
const now = new Date(2026, 8, 13, 15, 30)
|
||||
const groups = groupNotificationsByDay(
|
||||
[
|
||||
{ id: 2, createdAt: null },
|
||||
{ id: 1, createdAt: 'not-a-date' },
|
||||
],
|
||||
now,
|
||||
)
|
||||
|
||||
assert.equal(groups.length, 1)
|
||||
assert.equal(groups[0].day, '')
|
||||
assert.equal(groups[0].label, '未知时间')
|
||||
assert.deepEqual(
|
||||
groups[0].items.map((item) => item.id),
|
||||
[2, 1],
|
||||
)
|
||||
})
|
||||
|
||||
test('buildNotificationListQuery:关键字去空白、空条件不下发、日期原样透传', () => {
|
||||
assert.deepEqual(buildNotificationListQuery(), { page: 1, pageSize: 20, onlyUnread: 'false' })
|
||||
|
||||
const query = buildNotificationListQuery({
|
||||
page: 2,
|
||||
pageSize: 10,
|
||||
keyword: ' 余额不足 ',
|
||||
startDate: '2026-09-10',
|
||||
endDate: '2026-09-13',
|
||||
})
|
||||
assert.deepEqual(query, {
|
||||
page: 2,
|
||||
pageSize: 10,
|
||||
onlyUnread: 'false',
|
||||
keyword: '余额不足',
|
||||
startDate: '2026-09-10',
|
||||
endDate: '2026-09-13',
|
||||
})
|
||||
|
||||
// 面板清空筛选后不能带空串日期(后端日期绑定会 400)
|
||||
const cleared = buildNotificationListQuery({ keyword: ' ', startDate: '', endDate: '' })
|
||||
assert.equal('keyword' in cleared, false)
|
||||
assert.equal('startDate' in cleared, false)
|
||||
assert.equal('endDate' in cleared, false)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user