Files

102 lines
6.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import test from 'node:test'
import assert from 'node:assert/strict'
import { readSource } from './helpers.ts'
import { aggregateDrawerRows, drawerSummaryOf } from '../src/pages/tasks/duplicate-console-logic.ts'
// 验收反馈:店铺重复检测对齐 reference —— 本轮补齐 P0 缺口:
// 分组筛选生效、抽屉聚合+汇总徽章、台账计数打开即显示、撞款计数走后端 total_dup、矩阵表头吸顶。
test('align_dup_console_group_filter_wired', () => {
const api = readSource('src/pages/tasks/duplicate-console-api.ts')
assert.match(api, /query\.group = group/, 'console 查询携带 group 参数')
const page = readSource('src/pages/tasks/DuplicateCheckPage.vue')
assert.match(page, /group: filter\.group\.trim\(\)/, '页面筛选把 group 传给查询')
})
test('align_dup_console_group_filter_backend', () => {
const ctrl = readSource('../backend-java/src/main/java/com/nanri/aiimage/modules/shopduplicatecheck/controller/AdminShopDataDuplicateCheckController.java')
assert.match(ctrl, /@RequestParam\(name = "group"/, '后端 console/ledger 接收 group 参数')
assert.match(ctrl, /withGroupFilter\(visibleKeys, scan, group\)/, '端点按分组裁剪可见店铺')
const service = readSource('../backend-java/src/main/java/com/nanri/aiimage/modules/shopduplicatecheck/service/ShopDataDuplicateCheckQueryService.java')
assert.match(service, /withGroupFilter/, 'service 提供分组裁剪方法')
assert.match(service, /分组筛选/, '分组筛选留中文排查日志')
})
test('align_dup_console_drawer_aggregation', () => {
const rows = aggregateDrawerRows([
{ asin: 'A', date: '2026-09-02 10:00', price: '1', brand: 'B', shopName: '店1', groupName: '组1', countryCodes: [], country: 'DE' },
{ asin: 'A', date: '2026-09-01 10:00', price: '1', brand: 'B', shopName: '店1', groupName: '组1', countryCodes: [], country: 'DE' },
{ asin: 'A', date: '2026-09-03 10:00', price: '1', brand: 'B', shopName: '店2', groupName: '组1', countryCodes: [], country: 'UK' },
])
assert.equal(rows.length, 2, '按店铺×站点聚合')
assert.equal(rows[0].count, 2, '同店同站次数累加')
assert.deepEqual(rows[0].times, ['2026-09-01 10:00', '2026-09-02 10:00'], '时间升序')
const summary = drawerSummaryOf(rows.flatMap((row) => row.times.map((time) => ({ asin: 'A', date: time, price: '1', brand: 'B', shopName: row.shopName, groupName: '组1', countryCodes: [], country: row.country }))))
assert.equal(summary.shopCount, 2)
assert.equal(summary.totalRecords, 3)
assert.equal(summary.earliest, '2026-09-01 10:00')
})
test('align_dup_console_drawer_template', () => {
const page = readSource('src/pages/tasks/DuplicateCheckPage.vue')
assert.match(page, /drawerAggRows/, '抽屉渲染聚合行')
assert.match(page, /drawerSummary/, '抽屉渲染汇总徽章')
assert.match(page, /次上架/, '汇总含 N 次上架')
assert.match(page, /<th[^>]*>次数<\/th>/, '聚合表含次数列')
assert.match(page, /v-for="row in drawerRows"/, '抽屉聚合表绑定分页切片')
assert.match(page, /:total="drawerAggRows\.length"/, '抽屉聚合表有分页器')
})
test('align_dup_console_pagination_all_lists', () => {
// 全站统一收官:撞款页四处列表(分布/矩阵/撞款详情卡片/抽屉明细)均挂共享 OldPagination
// 且分布/矩阵/详情常显(不足一页也显示分页器,反馈:数据少时看不到分页)。
const page = readSource('src/pages/tasks/DuplicateCheckPage.vue')
assert.match(page, /:total="distCount"/, '店铺上架分布有分页器(常显)')
assert.match(page, /:total="dupRows\.length"/, '撞款覆盖矩阵有分页器(常显)')
assert.match(page, /v-for="item in dupCardRows"/, '撞款详情卡片绑定分页切片')
assert.match(page, /:total="dupRows\.length"[\s\S]*dupCardPageSize/, '撞款详情卡片有分页器(常显)')
assert.match(page, /<OldPagination[^>]*:total="distCount"/, '分布分页器无 v-if 条件')
assert.match(page, /<OldPagination[^>]*:total="dupRows\.length"/, '矩阵/详情分页器无 v-if 条件')
assert.match(page, /v-for="group in pagedGroupStats"/, '分组说明抽屉表绑定分页切片')
assert.match(page, /:total="groupStats\.length"/, '分组说明抽屉表有分页器')
})
test('align_dup_console_ledger_total_preload', () => {
const page = readSource('src/pages/tasks/DuplicateCheckPage.vue')
assert.match(page, /onMounted\(\(\) => \{\s*loadConsole\(\).*loadLedger\(1\)/s, '挂载即预取台账计数')
assert.match(page, /totalDup/, '撞款计数走后端 total_dup 字段')
})
test('align_dup_console_matrix_sticky', () => {
const page = readSource('src/pages/tasks/DuplicateCheckPage.vue')
assert.match(page, /table\.matrix th\s*\{[^}]*position:\s*sticky/, '矩阵表头吸顶')
assert.match(page, /\.matrix-wrap\s*\{[^}]*max-height/, '矩阵容器限高滚动')
})
test('align_dup_console_role_scope_group_filter_only_super', () => {
// 角色范围:分组筛选下拉仅超管需要;管理员数据由后端裁到本组。
const page = readSource('src/pages/tasks/DuplicateCheckPage.vue')
assert.match(page, /useAdminSessionStore/, '页面读取登录会话取角色')
assert.match(page, /const isSuper = computed\(\(\) => session\.isSuperAdmin\)/, 'isSuper 由会话角色推导')
assert.match(page, /<div v-if="isSuper" class="f-group">\s*<label>分组<\/label>/s, '分组筛选仅超管可见')
assert.match(page, /group: filter\.group\.trim\(\)/, '分组筛选仍参与查询参数')
})
test('align_dup_console_role_scope_group_controls_only_super', () => {
// 分组撞款/分组说明为超管专属交互;后端超管全量、普通管理员所管分组店铺。
const page = readSource('src/pages/tasks/DuplicateCheckPage.vue')
assert.match(page, /<div v-if="isSuper" class="scope-bar">/, '分组撞款分段仅超管可见')
assert.match(page, /v-if="isSuper" class="btn btn-ghost btn-sm" type="button" @click="groupInfoVisible = true"/, '分组说明按钮仅超管可见')
const service = readSource('../backend-java/src/main/java/com/nanri/aiimage/modules/shopduplicatecheck/service/ShopDataDuplicateCheckQueryService.java')
assert.match(service, /if \(superAdmin\) \{\s*return null;/, '超管可见范围=全量(null)')
assert.match(service, /selectManagedShopNames\(operatorId\)/, '普通管理员可见范围=所管分组店铺')
})
test('align_dup_console_country_labels_chinese', () => {
// 反馈:国家显示一定要用中文——站点/国家一律经 asinCountryLabel 映射,禁止裸国家码直出。
const page = readSource('src/pages/tasks/DuplicateCheckPage.vue')
assert.match(page, /asinCountryLabel\(/, '站点显示走中文映射函数')
assert.doesNotMatch(page, /\{\{\s*(row|item)\.country\s*\}\}/, '表格/抽屉无裸国家码直出')
assert.match(page, /asinCountryLabel\(code\)/, '筛选下拉站点显示中文')
})