feat(category): 类目树、属性、属性字典维护,新增系统管理员管理类目数据
This commit is contained in:
@@ -87,18 +87,85 @@ export async function fetchOzonDictionaryValues(
|
||||
},
|
||||
) {
|
||||
const query = input.query?.trim() ?? '';
|
||||
const path = query
|
||||
? '/v1/description-category/attribute/values/search'
|
||||
: '/v1/description-category/attribute/values';
|
||||
const body = await requestOzon(clientId, apiKey, path, {
|
||||
const request = {
|
||||
attribute_id: numberOrText(input.attributeId),
|
||||
description_category_id: numberOrText(input.categoryId),
|
||||
type_id: numberOrText(input.typeId),
|
||||
language: 'ZH_HANS',
|
||||
limit: query ? 100 : 1_000,
|
||||
...(query ? { value: query } : { last_value_id: 0 }),
|
||||
});
|
||||
return readResultArray<OzonDictionaryValue>(body, '属性字典');
|
||||
};
|
||||
if (query) {
|
||||
const body = await requestOzon(
|
||||
clientId, apiKey, '/v1/description-category/attribute/values/search',
|
||||
{ ...request, limit: 100, value: query },
|
||||
);
|
||||
return readResultArray<OzonDictionaryValue>(body, '属性字典');
|
||||
}
|
||||
const values: OzonDictionaryValue[] = [];
|
||||
const seen = new Set<string>();
|
||||
let lastValueId: number | string = 0;
|
||||
// 大字典仅预取首批 1000 项;后续值由关键词搜索补充,重复游标不得造成无限循环。
|
||||
for (let pageIndex = 0; pageIndex < 20 && values.length < 1_000; pageIndex += 1) {
|
||||
const body = await requestOzon(
|
||||
clientId, apiKey, '/v1/description-category/attribute/values',
|
||||
{ ...request, limit: 1_000 - values.length, last_value_id: lastValueId },
|
||||
);
|
||||
const page = readResultArray<OzonDictionaryValue>(body, '属性字典');
|
||||
let added = 0;
|
||||
for (const value of page) {
|
||||
const id = String(value.id ?? '');
|
||||
if (!id || seen.has(id)) continue;
|
||||
seen.add(id);
|
||||
values.push(value);
|
||||
added += 1;
|
||||
}
|
||||
const nextId = page.at(-1)?.id;
|
||||
if (
|
||||
(body as { has_next?: unknown }).has_next !== true || !page.length ||
|
||||
!added || nextId == null || String(nextId) === String(lastValueId)
|
||||
) break;
|
||||
lastValueId = typeof nextId === 'string' ? numberOrText(nextId) : nextId;
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
/** 平台级字典按页获取,明确返回完整性;大字典不会伪装成已全量同步。 */
|
||||
export async function fetchOzonDictionaryBatch(
|
||||
clientId: string,
|
||||
apiKey: string,
|
||||
input: { attributeId: string; categoryId: string; typeId: string },
|
||||
): Promise<{ values: OzonDictionaryValue[]; isComplete: boolean }> {
|
||||
const values: OzonDictionaryValue[] = [];
|
||||
const seen = new Set<string>();
|
||||
let lastValueId: number | string = 0;
|
||||
for (let pageIndex = 0; pageIndex < 5; pageIndex += 1) {
|
||||
const body = await requestOzon(
|
||||
clientId, apiKey, '/v1/description-category/attribute/values',
|
||||
{
|
||||
attribute_id: numberOrText(input.attributeId),
|
||||
description_category_id: numberOrText(input.categoryId),
|
||||
type_id: numberOrText(input.typeId),
|
||||
language: 'ZH_HANS',
|
||||
limit: 2000,
|
||||
last_value_id: lastValueId,
|
||||
},
|
||||
);
|
||||
const page = readResultArray<OzonDictionaryValue>(body, '属性字典');
|
||||
for (const value of page) {
|
||||
const id = String(value.id ?? '').trim();
|
||||
if (id && !seen.has(id)) {
|
||||
seen.add(id);
|
||||
values.push(value);
|
||||
}
|
||||
}
|
||||
const hasNext = (body as { has_next?: unknown }).has_next === true;
|
||||
if (!hasNext) return { values, isComplete: true };
|
||||
const nextId = page.at(-1)?.id;
|
||||
if (!page.length || nextId == null || String(nextId) === String(lastValueId)) {
|
||||
throw new OzonRetryableError('Ozon 字典分页游标没有前进');
|
||||
}
|
||||
lastValueId = nextId;
|
||||
}
|
||||
return { values, isComplete: false };
|
||||
}
|
||||
|
||||
async function requestOzon(
|
||||
|
||||
Reference in New Issue
Block a user