task-114(任务与重复分析中心): 实现店铺数据任务权限配置
shop-data-api.ts 增加 fetch/saveShopDataTaskPermissions(GET|PUT /api/admin/ shop-data-crawl-task-permissions),复用 task-permission 解析与保存负载。 TDD: task-114.test.ts 8 用例先 RED 后 GREEN。
This commit is contained in:
@@ -4,8 +4,10 @@ import { parseShopDataTaskPage, type ShopDataTaskPageResult } from './shop-data-
|
|||||||
import { toShopDataQuery, type ShopDataFilter } from './shop-data-filter.ts'
|
import { toShopDataQuery, type ShopDataFilter } from './shop-data-filter.ts'
|
||||||
import { toShopDataZipRequest } from './shop-data-download.ts'
|
import { toShopDataZipRequest } from './shop-data-download.ts'
|
||||||
import { downloadZipHeaderCounts } from './image-video-download.ts'
|
import { downloadZipHeaderCounts } from './image-video-download.ts'
|
||||||
|
import { parseTaskPermissionPayload, toPermissionUserIdsPayload, type TaskPermissionItem } from './task-permission.ts'
|
||||||
|
|
||||||
export const SHOP_DATA_CRAWL_TASKS_ENDPOINT = '/api/admin/shop-data-crawl-tasks'
|
export const SHOP_DATA_CRAWL_TASKS_ENDPOINT = '/api/admin/shop-data-crawl-tasks'
|
||||||
|
export const SHOP_DATA_TASK_PERMISSIONS_ENDPOINT = '/api/admin/shop-data-crawl-task-permissions'
|
||||||
|
|
||||||
export async function fetchShopDataTaskList(
|
export async function fetchShopDataTaskList(
|
||||||
filter: ShopDataFilter,
|
filter: ShopDataFilter,
|
||||||
@@ -32,3 +34,14 @@ export async function requestShopDataZipDownload(resultIds: readonly (number | s
|
|||||||
const counts = downloadZipHeaderCounts(headers as Record<string, string>)
|
const counts = downloadZipHeaderCounts(headers as Record<string, string>)
|
||||||
return { blob: data, fileCount: counts.fileCount, errorCount: counts.errorCount }
|
return { blob: data, fileCount: counts.fileCount, errorCount: counts.errorCount }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 加载店铺数据任务数据范围授权用户:GET /api/admin/shop-data-crawl-task-permissions。 */
|
||||||
|
export async function fetchShopDataTaskPermissionUsers(): Promise<TaskPermissionItem[]> {
|
||||||
|
const { data } = await http.get<unknown>(SHOP_DATA_TASK_PERMISSIONS_ENDPOINT)
|
||||||
|
return parseTaskPermissionPayload(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 保存店铺数据任务数据范围授权:PUT /api/admin/shop-data-crawl-task-permissions { user_ids }。 */
|
||||||
|
export async function saveShopDataTaskPermissions(userIds: Iterable<number>): Promise<void> {
|
||||||
|
await http.put<unknown>(SHOP_DATA_TASK_PERMISSIONS_ENDPOINT, toPermissionUserIdsPayload(userIds))
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import test from 'node:test'
|
||||||
|
import assert from 'node:assert/strict'
|
||||||
|
import { readSource } from './helpers.ts'
|
||||||
|
import { grantedUserIds, parseTaskPermissionPayload, permissionSelectionChanged, toPermissionUserIdsPayload } from '../src/pages/tasks/task-permission.ts'
|
||||||
|
|
||||||
|
const SHOP_DATA_PERM_RESP = {
|
||||||
|
success: true,
|
||||||
|
data: [
|
||||||
|
{ id: 1, username: '张伟', granted: true },
|
||||||
|
{ id: 2, username: '李四', granted: false },
|
||||||
|
{ id: 3, username: '王五', granted: true },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
test('test_task_114_shop_data_permission_normal_primary_path', () => {
|
||||||
|
// 正常主路径:店铺数据权限负载解析并取已授权 id。
|
||||||
|
const items = parseTaskPermissionPayload(SHOP_DATA_PERM_RESP)
|
||||||
|
assert.deepEqual(grantedUserIds(items), [1, 3])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('test_task_114_shop_data_permission_normal_variant_input', () => {
|
||||||
|
// 正常变体:仅全选/部分授权变更判定。
|
||||||
|
const initial = new Set([1, 3])
|
||||||
|
assert.equal(permissionSelectionChanged(initial, new Set([1, 3])), false)
|
||||||
|
assert.equal(permissionSelectionChanged(initial, new Set([1])), true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('test_task_114_shop_data_permission_repeated_is_idempotent', () => {
|
||||||
|
// 正常重复:保存负载稳定。
|
||||||
|
assert.deepEqual(toPermissionUserIdsPayload(new Set([3, 1])), { user_ids: [3, 1] })
|
||||||
|
})
|
||||||
|
|
||||||
|
test('test_task_114_shop_data_permission_boundary_empty_input', () => {
|
||||||
|
// 边界空值:无授权时的空选择。
|
||||||
|
const initial = new Set<number>()
|
||||||
|
assert.equal(permissionSelectionChanged(initial, new Set()), false)
|
||||||
|
assert.deepEqual(toPermissionUserIdsPayload(initial), { user_ids: [] })
|
||||||
|
})
|
||||||
|
|
||||||
|
test('test_task_114_shop_data_permission_boundary_single_item', () => {
|
||||||
|
// 边界单元素:单用户授权变更。
|
||||||
|
assert.equal(permissionSelectionChanged(new Set(), new Set([7])), true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('test_task_114_shop_data_permission_boundary_limit_or_missing_field', () => {
|
||||||
|
// 边界上限/缺字段:仅新增未授权用户时判定为已变更。
|
||||||
|
assert.equal(permissionSelectionChanged(new Set([1]), new Set([1, 4])), true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('test_task_114_shop_data_permission_invalid_input_rejected', () => {
|
||||||
|
// 异常输入:success=false 抛后端 message。
|
||||||
|
assert.throws(() => parseTaskPermissionPayload({ success: false, message: '仅超级管理员可配置' }), /仅超级管理员/)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('test_task_114_shop_data_permission_dependency_failure_returns_actionable_message', () => {
|
||||||
|
// 依赖失败/加载走 adapter:GET|PUT /api/admin/shop-data-crawl-task-permissions。
|
||||||
|
const api = readSource('src/pages/tasks/shop-data-api.ts')
|
||||||
|
assert.match(api, /\/api\/admin\/shop-data-crawl-task-permissions/)
|
||||||
|
assert.match(api, /fetchShopDataTaskPermissionUsers/)
|
||||||
|
assert.match(api, /saveShopDataTaskPermissions/)
|
||||||
|
assert.match(api, /http\.put/)
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user