@gt6/sdk
Version:
GT6 SDK for articles management - A comprehensive JavaScript/TypeScript library for managing articles, categories, and tags in GT6 platform
1,409 lines (1,406 loc) • 117 kB
JavaScript
// 错误类型
class GT6Error extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
this.name = 'GT6Error';
}
}
class GT6Client {
constructor(config) {
this.config = {
timeout: 10000,
cache: {
enabled: true,
ttl: 300000 // 5分钟默认缓存
},
...config
};
this.cache = new Map();
}
/**
* 发起HTTP请求
*/
async request(endpoint, options = {}) {
const url = `${this.config.baseUrl}${endpoint}`;
const cacheKey = `${options.method || 'GET'}:${url}`;
// 检查缓存(只对GET请求缓存)
if (this.config.cache?.enabled && options.method !== 'POST' && options.method !== 'PUT' && options.method !== 'DELETE') {
const cached = this.cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < this.config.cache.ttl) {
return cached.data;
}
}
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
// 对于FormData,不设置Content-Type,让浏览器自动设置
const headers = new Headers(options.headers);
if (!(options.body instanceof FormData)) {
headers.set('Content-Type', 'application/json');
}
const response = await fetch(url, {
...options,
headers,
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
throw new GT6Error(`HTTP ${response.status}: ${response.statusText}`, response.status);
}
const data = await response.json();
// 更新缓存(只对GET请求缓存)
if (this.config.cache?.enabled && options.method !== 'POST' && options.method !== 'PUT' && options.method !== 'DELETE') {
this.cache.set(cacheKey, { data, timestamp: Date.now() });
}
return data;
}
catch (error) {
if (error instanceof GT6Error) {
throw error;
}
if (error.name === 'AbortError') {
throw new GT6Error('Request timeout', 408);
}
throw new GT6Error(`Network error: ${error.message}`);
}
}
/**
* 获取配置
*/
getConfig() {
return { ...this.config };
}
/**
* 清除缓存
*/
clearCache() {
this.cache.clear();
}
/**
* 获取缓存统计
*/
getCacheStats() {
const entries = Array.from(this.cache.entries()).map(([key, value]) => ({
key,
age: Date.now() - value.timestamp
}));
return {
size: this.cache.size,
entries
};
}
}
class ArticlesAPI {
constructor(client) {
this.client = client;
}
/**
* 1. 根据文章ID获取文章详情
*/
async getArticle(articleId) {
return this.client.request(`/articles/${articleId}.json`);
}
/**
* 1.1 根据文章ID获取文章详情(平台使用)
*/
async getArticle_p(articleId) {
return this.client.request(`/parentarticles/${articleId}.json`);
}
/**
* 2. 获取文章分类列表
*/
async getCategories(rootCategoryId) {
const config = this.client.getConfig();
const categoryId = rootCategoryId || config.rootCategoryId || '671920';
const response = await this.client.request(`/article-categories/platform-${config.platformId}-root-${categoryId}.json`);
return response.categories;
}
/**
* 2.1 获取文章分类列表(使用下级平台ID)
*/
async getCategories_p(rootCategoryId_p) {
const config = this.client.getConfig();
const categoryId = rootCategoryId_p || config.rootCategoryId_p || '671920';
const response = await this.client.request(`/article-categories/platform/platform-${config.platformId_p}-root-${categoryId}.json`);
return response.categories;
}
/**
* 2.2 获取文章分类列表(使用下级平台ID)
*/
async getCategories_a(rootCategoryId) {
const config = this.client.getConfig();
const categoryId = rootCategoryId || config.rootCategoryId;
const response = await this.client.request(`/big-article-categories/platform-${config.platformId}-root-${categoryId}.json`);
return response.categories;
}
/**
* 3. 获取文章标签列表
*/
async getTags(tagAlias) {
const config = this.client.getConfig();
const alias = tagAlias || config.tagAlias || '001';
const response = await this.client.request(`/article-tags/platform-${config.platformId}-${alias}.json`);
return response.tags;
}
/**
* 3.1 获取文章标签列表(使用下级平台ID)
*/
async getTags_p(tagAlias_p) {
const config = this.client.getConfig();
const alias = tagAlias_p || config.tagAlias_p || '001';
const response = await this.client.request(`/article-tags/platform-${config.platformId_p}-${alias}.json`);
return response.tags;
}
/**
* 3.2. 获取单个平台文章标签列表
*/
async getTags_p_single(tagId_p) {
const config = this.client.getConfig();
const tagId = tagId_p || config.tagId_p;
if (!tagId) {
throw new Error('Article tag ID is required');
}
const response = await this.client.request(`/article-tags/${tagId}.json`);
return response;
}
/**
* 3.3. 获取单个平台文章标签的文章ID列表
*/
async getTagArticleIds_p(tagId_p) {
const tagData = await this.getTags_p_single(tagId_p);
return tagData.articleIds;
}
/**
* 4. 根据分类ID获取文章列表
* 支持单个分类ID或分类ID数组
*/
async getArticlesByCategory(categoryId, options) {
// 获取分类数据
const categories = await this.getCategories();
// 将单个分类ID转换为数组
const categoryIds = Array.isArray(categoryId) ? categoryId : [categoryId];
// 收集所有指定分类下的文章ID
const allArticleIds = [];
categoryIds.forEach(id => {
const targetCategory = categories.find(cat => cat.categoryId === id);
if (targetCategory) {
allArticleIds.push(...targetCategory.articleIds);
}
});
// 去重
const uniqueArticleIds = [...new Set(allArticleIds)];
if (uniqueArticleIds.length === 0) {
return {
articles: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedArticleIds = uniqueArticleIds.slice(offset, offset + limit);
// 获取文章详情
const articles = await Promise.all(paginatedArticleIds.map(articleId => this.getArticle(articleId)));
// 应用状态过滤
let filteredArticles = articles;
if (options?.status) {
filteredArticles = articles.filter(article => article.status === options.status);
}
return {
articles: filteredArticles,
total: uniqueArticleIds.length,
page,
limit
};
}
/**
* 4.1 根据分类ID获取文章列表
* 支持单个分类ID或分类ID数组
*/
async getArticlesByCategory_p(categoryId, options) {
// 获取分类数据
const categories = await this.getCategories_p();
// 将单个分类ID转换为数组
const categoryIds = Array.isArray(categoryId) ? categoryId : [categoryId];
// 收集所有指定分类下的文章ID
const allArticleIds = [];
categoryIds.forEach(id => {
const targetCategory = categories.find(cat => cat.categoryId === id);
if (targetCategory) {
allArticleIds.push(...targetCategory.articleIds);
}
});
// 去重
const uniqueArticleIds = [...new Set(allArticleIds)];
if (uniqueArticleIds.length === 0) {
return {
articles: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedArticleIds = uniqueArticleIds.slice(offset, offset + limit);
// 获取文章详情
const articles = await Promise.all(paginatedArticleIds.map(articleId => this.getArticle_p(articleId)));
// 应用状态过滤
let filteredArticles = articles;
if (options?.status) {
filteredArticles = articles.filter(article => article.status === options.status);
}
return {
articles: filteredArticles,
total: uniqueArticleIds.length,
page,
limit
};
}
/**
* 4.2 根据分类ID获取文章列表
* 支持单个分类ID或分类ID数组
*/
async getArticlesByCategory_t(categoryId, options) {
// 获取分类数据
const categories = await this.getCategories();
// 将单个分类ID转换为数组
const categoryIds = Array.isArray(categoryId) ? categoryId : [categoryId];
// 收集所有指定分类下的文章ID
const allArticleIds = [];
categoryIds.forEach(id => {
const targetCategory = categories.find(cat => cat.categoryId === id);
if (targetCategory) {
allArticleIds.push(...targetCategory.articleIds);
}
});
// 去重
const uniqueArticleIds = [...new Set(allArticleIds)];
if (uniqueArticleIds.length === 0) {
return {
articles: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedArticleIds = uniqueArticleIds.slice(offset, offset + limit);
// 获取文章详情
const articles = await Promise.all(paginatedArticleIds.map(articleId => this.getArticle_p(articleId)));
// 应用状态过滤
let filteredArticles = articles;
if (options?.status) {
filteredArticles = articles.filter(article => article.status === options.status);
}
return {
articles: filteredArticles,
total: uniqueArticleIds.length,
page,
limit
};
}
/**
* 4.3 根据分类ID获取文章列表(使用大型分类静态文件)
* 只支持单个分类ID,从大型分类静态文件获取文章ID列表
*/
async getArticlesByCategory_a(categoryId, options) {
// 从大型分类静态文件获取该分类的文章ID列表
const categoryData = await this.client.request(`/big-article-categories/${categoryId}.json`);
if (!categoryData || !categoryData.articleIds || categoryData.articleIds.length === 0) {
return {
articles: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedArticleIds = categoryData.articleIds.slice(offset, offset + limit);
// 获取文章详情(使用上级平台数据)
const articles = await Promise.all(paginatedArticleIds.map(articleId => this.getArticle_p(articleId)));
// 应用状态过滤
let filteredArticles = articles;
if (options?.status) {
filteredArticles = articles.filter(article => article.status === options.status);
}
return {
articles: filteredArticles,
total: categoryData.articleIds.length,
page,
limit
};
}
/**
* 5. 根据标签ID获取文章列表
* 支持单个标签ID或标签ID数组
*/
async getArticlesByTag(tagId, options) {
// 获取标签数据,传递tagAlias参数
const tags = await this.getTags(options?.tagAlias);
// 将单个标签ID转换为数组
const tagIds = Array.isArray(tagId) ? tagId : [tagId];
// 收集所有指定标签下的文章ID
const allArticleIds = [];
tagIds.forEach(id => {
const targetTag = tags.find(tag => tag.tagId === id);
if (targetTag) {
allArticleIds.push(...targetTag.articleIds);
}
});
// 去重
const uniqueArticleIds = [...new Set(allArticleIds)];
if (uniqueArticleIds.length === 0) {
return {
articles: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedArticleIds = uniqueArticleIds.slice(offset, offset + limit);
// 获取文章详情
const articles = await Promise.all(paginatedArticleIds.map(articleId => this.getArticle(articleId)));
// 应用状态过滤
let filteredArticles = articles;
if (options?.status) {
filteredArticles = articles.filter(article => article.status === options.status);
}
return {
articles: filteredArticles,
total: uniqueArticleIds.length,
page,
limit
};
}
/**
* 5.1 根据标签ID获取文章列表
* 支持单个标签ID或标签ID数组
*/
async getArticlesByTag_p(tagId, options) {
// 获取标签数据,传递tagAlias参数
const tags = await this.getTags_p(options?.tagAlias);
// 将单个标签ID转换为数组
const tagIds = Array.isArray(tagId) ? tagId : [tagId];
// 收集所有指定标签下的文章ID
const allArticleIds = [];
tagIds.forEach(id => {
const targetTag = tags.find(tag => tag.tagId === id);
if (targetTag) {
allArticleIds.push(...targetTag.articleIds);
}
});
// 去重
const uniqueArticleIds = [...new Set(allArticleIds)];
if (uniqueArticleIds.length === 0) {
return {
articles: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedArticleIds = uniqueArticleIds.slice(offset, offset + limit);
// 获取文章详情
const articles = await Promise.all(paginatedArticleIds.map(articleId => this.getArticle_p(articleId)));
// 应用状态过滤
let filteredArticles = articles;
if (options?.status) {
filteredArticles = articles.filter(article => article.status === options.status);
}
return {
articles: filteredArticles,
total: uniqueArticleIds.length,
page,
limit
};
}
/**
* 5.2 根据标签ID获取文章列表
* 支持单个标签ID或标签ID数组
*/
async getArticlesByTag_t(tagId, options) {
// 获取标签数据,传递tagAlias参数
const tags = await this.getTags(options?.tagAlias);
// 将单个标签ID转换为数组
const tagIds = Array.isArray(tagId) ? tagId : [tagId];
// 收集所有指定标签下的文章ID
const allArticleIds = [];
tagIds.forEach(id => {
const targetTag = tags.find(tag => tag.tagId === id);
if (targetTag) {
allArticleIds.push(...targetTag.articleIds);
}
});
// 去重
const uniqueArticleIds = [...new Set(allArticleIds)];
if (uniqueArticleIds.length === 0) {
return {
articles: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedArticleIds = uniqueArticleIds.slice(offset, offset + limit);
// 获取文章详情
const articles = await Promise.all(paginatedArticleIds.map(articleId => this.getArticle_p(articleId)));
// 应用状态过滤
let filteredArticles = articles;
if (options?.status) {
filteredArticles = articles.filter(article => article.status === options.status);
}
return {
articles: filteredArticles,
total: uniqueArticleIds.length,
page,
limit
};
}
/**
* 5.3. 根据单个标签ID获取平台文章列表
* 使用getTags_p_single获取指定标签数据,然后获取文章详情
* @param tagId 单个标签ID
* @param options 查询选项
*/
async getArticlesByTag_single(tagId, options) {
// 获取指定标签的数据
const tagData = await this.getTags_p_single(tagId);
if (!tagData || !tagData.articleIds || tagData.articleIds.length === 0) {
// 剔除articleIds字段
const { articleIds, ...tagInfo } = tagData;
return {
articles: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10,
tag: tagInfo
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedArticleIds = tagData.articleIds.slice(offset, offset + limit);
// 获取文章详情
const articles = await Promise.all(paginatedArticleIds.map(articleId => this.getArticle_p(articleId)));
// 应用状态过滤
let filteredArticles = articles;
if (options?.status) {
filteredArticles = articles.filter(article => article.status === options.status);
}
// 剔除articleIds字段
const { articleIds, ...tagInfo } = tagData;
return {
articles: filteredArticles,
total: tagData.articleIds.length,
page,
limit,
tag: tagInfo
};
}
/**
* 6. 根据分类ID获取该分类的层级路径
* 用于前端面包屑导航
*/
async getCategoryPath(categoryId) {
// 获取所有分类数据
const categories = await this.getCategories();
// 查找目标分类
const targetCategory = categories.find(cat => cat.categoryId === categoryId);
if (!targetCategory) {
return {
path: [],
currentCategory: null,
breadcrumbs: []
};
}
// 构建分类路径
const path = [];
const breadcrumbs = [];
// 递归查找父分类
const buildPath = (currentCategory, level = 0) => {
// 将当前分类添加到路径开头(因为我们要从根到叶子构建)
path.unshift(currentCategory);
breadcrumbs.unshift({
categoryId: currentCategory.categoryId,
categoryName: currentCategory.categoryName,
level
});
// 如果有父分类,继续递归
if (currentCategory.parentId && currentCategory.parentId !== 0) {
const parentCategory = categories.find(cat => cat.categoryId === currentCategory.parentId);
if (parentCategory) {
buildPath(parentCategory, level + 1);
}
}
};
// 从目标分类开始构建路径
buildPath(targetCategory);
return {
path,
currentCategory: targetCategory,
breadcrumbs
};
}
/**
* 7. 获取指定分类ID下的子分类
* 支持递归获取所有层级的子分类
*/
async getSubCategories(categoryId, options) {
// 获取所有分类数据
const categories = await this.getCategories();
// 查找目标分类
const targetCategory = categories.find(cat => cat.categoryId === categoryId);
if (!targetCategory) {
return {
subCategories: [],
currentCategory: null,
total: 0,
depth: 0
};
}
const subCategories = [];
let maxDepth = options?.maxDepth || Infinity;
let actualDepth = 0;
// 递归获取子分类的函数
const collectSubCategories = (parentId, currentDepth = 0) => {
if (currentDepth >= maxDepth) {
return;
}
// 查找直接子分类
const children = categories.filter(cat => cat.parentId === parentId);
children.forEach(child => {
subCategories.push(child);
// 如果需要递归且未达到最大深度,继续查找子分类
if (options?.recursive && currentDepth < maxDepth - 1) {
collectSubCategories(child.categoryId, currentDepth + 1);
}
});
// 更新实际深度
actualDepth = Math.max(actualDepth, currentDepth);
};
// 开始收集子分类
collectSubCategories(categoryId);
// 如果需要包含当前分类,添加到结果中
if (options?.includeCurrent) {
subCategories.unshift(targetCategory);
}
return {
subCategories,
currentCategory: targetCategory,
total: subCategories.length,
depth: actualDepth
};
}
}
class ProductsAPI {
constructor(client) {
this.client = client;
}
/**
* 1. 根据产品ID获取产品详情
*/
async getProduct(productId) {
const product = await this.client.request(`/products/${productId}.json`);
// 检查产品是否有销售区域和税费模板
if (product.regions && product.regions.length > 0 &&
product.taxTemplates && product.taxTemplates.length > 0) {
try {
// 获取税费信息
const taxInfo = await this.getTaxInfo();
// 为每个税费模板添加规则
product.taxTemplates = product.taxTemplates.map(template => {
const matchingTemplate = taxInfo.templates.find(t => t.templateId === template.templateId);
if (matchingTemplate) {
// 过滤出产品可销售区域的规则
const productRegionIds = product.regions.map(r => r.regionId);
const applicableRules = matchingTemplate.rules.filter(rule => productRegionIds.includes(rule.regionId));
return {
...template,
rules: applicableRules
};
}
return template;
});
}
catch (error) {
// 如果获取税费信息失败,不影响产品详情返回
console.warn('Failed to fetch tax info:', error);
}
}
// 检查产品是否有销售区域和运费模板
if (product.regions && product.regions.length > 0 &&
product.shippingTemplates && product.shippingTemplates.length > 0) {
try {
// 获取运费信息
const shippingInfo = await this.getShippingInfo();
// 为每个运费模板添加规则
product.shippingTemplates = product.shippingTemplates.map(template => {
const matchingTemplate = shippingInfo.templates.find(t => t.templateId === template.templateId);
if (matchingTemplate) {
// 过滤出产品可销售区域的规则
const productRegionIds = product.regions.map(r => r.regionId);
const applicableRules = matchingTemplate.rules.filter(rule => productRegionIds.includes(rule.regionId));
return {
...template,
rules: applicableRules
};
}
return template;
});
}
catch (error) {
// 如果获取运费信息失败,不影响产品详情返回
console.warn('Failed to fetch shipping info:', error);
}
}
return product;
}
/**
* 1.1. 根据产品ID获取父平台产品详情
*/
async getProduct_p(productId) {
const product = await this.client.request(`/parentproducts/${productId}.json`);
// 检查产品是否有销售区域和税费模板
if (product.regions && product.regions.length > 0 &&
product.taxTemplates && product.taxTemplates.length > 0) {
try {
// 获取税费信息
const taxInfo = await this.getTaxInfo();
// 为每个税费模板添加规则
product.taxTemplates = product.taxTemplates.map(template => {
const matchingTemplate = taxInfo.templates.find(t => t.templateId === template.templateId);
if (matchingTemplate) {
// 过滤出产品可销售区域的规则
const productRegionIds = product.regions.map(r => r.regionId);
const applicableRules = matchingTemplate.rules.filter(rule => productRegionIds.includes(rule.regionId));
return {
...template,
rules: applicableRules
};
}
return template;
});
}
catch (error) {
// 如果获取税费信息失败,不影响产品详情返回
console.warn('Failed to fetch tax info:', error);
}
}
// 检查产品是否有销售区域和运费模板
if (product.regions && product.regions.length > 0 &&
product.shippingTemplates && product.shippingTemplates.length > 0) {
try {
// 获取运费信息
const shippingInfo = await this.getShippingInfo();
// 为每个运费模板添加规则
product.shippingTemplates = product.shippingTemplates.map(template => {
const matchingTemplate = shippingInfo.templates.find(t => t.templateId === template.templateId);
if (matchingTemplate) {
// 过滤出产品可销售区域的规则
const productRegionIds = product.regions.map(r => r.regionId);
const applicableRules = matchingTemplate.rules.filter(rule => productRegionIds.includes(rule.regionId));
return {
...template,
rules: applicableRules
};
}
return template;
});
}
catch (error) {
// 如果获取运费信息失败,不影响产品详情返回
console.warn('Failed to fetch shipping info:', error);
}
}
return product;
}
/**
* 2. 获取产品分类列表
*/
async getCategories(productRootCategoryId) {
const config = this.client.getConfig();
const categoryId = productRootCategoryId || config.productRootCategoryId || '277233';
const response = await this.client.request(`/product-categories/platform-${config.platformId}-root-${categoryId}.json`);
return response.categories;
}
/**
* 2.1. 获取平台产品分类列表
*/
async getCategories_p(productRootCategoryId_p) {
const config = this.client.getConfig();
const categoryId = productRootCategoryId_p || config.productRootCategoryId_p;
const response = await this.client.request(`/product-categories/platform/platform-${config.platformId_p}-root-${categoryId}.json`);
return response.categories;
}
/**
* 2.2. 获取平台产品分类列表
*/
async getCategories_b(productRootCategoryId) {
const config = this.client.getConfig();
const categoryId = productRootCategoryId || config.productRootCategoryId;
const response = await this.client.request(`/big-product-categories/platform-${config.platformId}-root-${categoryId}.json`);
return response.categories;
}
/**
* 3. 获取产品标签列表
*/
async getTags(productTagAlias) {
const config = this.client.getConfig();
const alias = productTagAlias || config.productTagAlias || '01';
const response = await this.client.request(`/product-tags/platform-${config.platformId}-${alias}.json`);
return response.tags;
}
/**
* 3.1. 获取平台产品标签列表
*/
async getTags_p(productTagAlias_p) {
const config = this.client.getConfig();
const alias = productTagAlias_p || config.productTagAlias_p;
const response = await this.client.request(`/product-tags/platform-${config.platformId_p}-${alias}.json`);
return response.tags;
}
/**
* 3.2. 获取单个平台产品标签列表
*/
async getTags_p_single(productTagId_p) {
const config = this.client.getConfig();
const productTagId = productTagId_p || config.productTagId_p;
if (!productTagId) {
throw new Error('Product tag ID is required');
}
const response = await this.client.request(`/product-tags/${productTagId}.json`);
return response;
}
/**
* 3.3. 获取单个平台产品标签的产品ID列表
*/
async getTagProductIds_p(productTagId_p) {
const tagData = await this.getTags_p_single(productTagId_p);
return tagData.productIds;
}
/**
* 4. 根据分类ID获取产品列表
* 支持单个分类ID或分类ID数组
*/
async getProductsByCategory(categoryId, options) {
// 获取分类数据
const categories = await this.getCategories();
// 递归查找分类的函数
const findCategoryById = (cats, targetId) => {
for (const cat of cats) {
if (cat.categoryId === targetId) {
return cat;
}
if (cat.children && cat.children.length > 0) {
const found = findCategoryById(cat.children, targetId);
if (found)
return found;
}
}
return null;
};
// 将单个分类ID转换为数组
const categoryIds = Array.isArray(categoryId) ? categoryId : [categoryId];
// 收集所有指定分类下的产品ID
const allProductIds = [];
categoryIds.forEach(id => {
const targetCategory = findCategoryById(categories, id);
if (targetCategory) {
allProductIds.push(...targetCategory.productIds);
}
});
// 去重
const uniqueProductIds = [...new Set(allProductIds)];
if (uniqueProductIds.length === 0) {
return {
products: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedProductIds = uniqueProductIds.slice(offset, offset + limit);
// 获取产品详情
const products = await Promise.all(paginatedProductIds.map(productId => this.getProduct(productId)));
// 应用状态过滤
let filteredProducts = products;
if (options?.status !== undefined) {
filteredProducts = products.filter(product => product.status === options.status);
}
return {
products: filteredProducts,
total: uniqueProductIds.length,
page,
limit
};
}
/**
* 4.1. 根据分类ID获取平台产品列表
*/
async getProductsByCategory_p(categoryId, options) {
// 获取分类数据
const categories = await this.getCategories_p();
// 递归查找分类的函数
const findCategoryById = (cats, targetId) => {
for (const cat of cats) {
if (cat.categoryId === targetId) {
return cat;
}
if (cat.children && cat.children.length > 0) {
const found = findCategoryById(cat.children, targetId);
if (found)
return found;
}
}
return null;
};
// 将单个分类ID转换为数组
const categoryIds = Array.isArray(categoryId) ? categoryId : [categoryId];
// 收集所有指定分类下的产品ID
const allProductIds = [];
categoryIds.forEach(id => {
const targetCategory = findCategoryById(categories, id);
if (targetCategory) {
allProductIds.push(...targetCategory.productIds);
}
});
// 去重
const uniqueProductIds = [...new Set(allProductIds)];
if (uniqueProductIds.length === 0) {
return {
products: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedProductIds = uniqueProductIds.slice(offset, offset + limit);
// 获取产品详情
const products = await Promise.all(paginatedProductIds.map(productId => this.getProduct_p(productId)));
// 应用状态过滤
let filteredProducts = products;
if (options?.status !== undefined) {
filteredProducts = products.filter(product => product.status === options.status);
}
return {
products: filteredProducts,
total: uniqueProductIds.length,
page,
limit
};
}
/**
* 4.2. 根据分类ID获取平台产品列表
*/
async getProductsByCategory_t(categoryId, options) {
// 获取分类数据
const categories = await this.getCategories();
// 递归查找分类的函数
const findCategoryById = (cats, targetId) => {
for (const cat of cats) {
if (cat.categoryId === targetId) {
return cat;
}
if (cat.children && cat.children.length > 0) {
const found = findCategoryById(cat.children, targetId);
if (found)
return found;
}
}
return null;
};
// 将单个分类ID转换为数组
const categoryIds = Array.isArray(categoryId) ? categoryId : [categoryId];
// 收集所有指定分类下的产品ID
const allProductIds = [];
categoryIds.forEach(id => {
const targetCategory = findCategoryById(categories, id);
if (targetCategory) {
allProductIds.push(...targetCategory.productIds);
}
});
// 去重
const uniqueProductIds = [...new Set(allProductIds)];
if (uniqueProductIds.length === 0) {
return {
products: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedProductIds = uniqueProductIds.slice(offset, offset + limit);
// 获取产品详情
const products = await Promise.all(paginatedProductIds.map(productId => this.getProduct_p(productId)));
// 应用状态过滤
let filteredProducts = products;
if (options?.status !== undefined) {
filteredProducts = products.filter(product => product.status === options.status);
}
return {
products: filteredProducts,
total: uniqueProductIds.length,
page,
limit
};
}
/**
* 4.3. 根据大分类ID获取平台产品列表
* 适配big-product-categories/${categoryId}.json新结构,支持排序和分页,直接返回数据
* @param categoryId 分类ID
* @param options { page, limit, sortBy }
* sortBy: 'createdAt-desc' | 'createdAt-asc' | 'price-desc' | 'price-asc'
*/
async getProductsByCategory_b(categoryId, options) {
// 从大型分类静态文件获取该分类的产品信息列表
const categoryData = await this.client.request(`/big-product-categories/${categoryId}.json`);
if (!categoryData || !categoryData.productInfos || categoryData.productInfos.length === 0) {
return {
products: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 排序
let sortedProducts = [...categoryData.productInfos];
const sortBy = options?.sortBy || 'createdAt-desc';
if (sortBy === 'createdAt-desc') {
sortedProducts.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
}
else if (sortBy === 'createdAt-asc') {
sortedProducts.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
}
else if (sortBy === 'price-desc') {
sortedProducts.sort((a, b) => parseFloat(b.price) - parseFloat(a.price));
}
else if (sortBy === 'price-asc') {
sortedProducts.sort((a, b) => parseFloat(a.price) - parseFloat(b.price));
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedProducts = sortedProducts.slice(offset, offset + limit);
// 应用状态过滤(如果有status字段)
let filteredProducts = paginatedProducts;
if (options?.status !== undefined) {
filteredProducts = paginatedProducts.filter(product => product.status === options.status);
}
return {
products: filteredProducts,
total: categoryData.productInfos.length,
page,
limit
};
}
/**
* 5. 根据标签ID获取产品列表
* 支持单个标签ID或标签ID数组
*/
async getProductsByTag(tagId, options) {
// 获取标签数据,传递productTagAlias参数
const tags = await this.getTags(options?.productTagAlias);
// 将单个标签ID转换为数组
const tagIds = Array.isArray(tagId) ? tagId : [tagId];
// 收集所有指定标签下的产品ID
const allProductIds = [];
tagIds.forEach(id => {
const targetTag = tags.find(tag => tag.tagId === id);
if (targetTag) {
allProductIds.push(...targetTag.productIds);
}
});
// 去重
const uniqueProductIds = [...new Set(allProductIds)];
if (uniqueProductIds.length === 0) {
return {
products: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedProductIds = uniqueProductIds.slice(offset, offset + limit);
// 获取产品详情
const products = await Promise.all(paginatedProductIds.map(productId => this.getProduct(productId)));
// 应用状态过滤
let filteredProducts = products;
if (options?.status !== undefined) {
filteredProducts = products.filter(product => product.status === options.status);
}
return {
products: filteredProducts,
total: uniqueProductIds.length,
page,
limit
};
}
/**
* 5.1. 根据标签ID获取平台产品列表
*/
async getProductsByTag_p(tagId, options) {
// 获取标签数据,传递productTagAlias参数
const tags = await this.getTags_p(options?.productTagAlias);
// 将单个标签ID转换为数组
const tagIds = Array.isArray(tagId) ? tagId : [tagId];
// 收集所有指定标签下的产品ID
const allProductIds = [];
tagIds.forEach(id => {
const targetTag = tags.find(tag => tag.tagId === id);
if (targetTag) {
allProductIds.push(...targetTag.productIds);
}
});
// 去重
const uniqueProductIds = [...new Set(allProductIds)];
if (uniqueProductIds.length === 0) {
return {
products: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedProductIds = uniqueProductIds.slice(offset, offset + limit);
// 获取产品详情
const products = await Promise.all(paginatedProductIds.map(productId => this.getProduct_p(productId)));
// 应用状态过滤
let filteredProducts = products;
if (options?.status !== undefined) {
filteredProducts = products.filter(product => product.status === options.status);
}
return {
products: filteredProducts,
total: uniqueProductIds.length,
page,
limit
};
}
/**
* 5.2. 根据标签ID获取平台产品列表
*/
async getProductsByTag_t(tagId, options) {
// 获取标签数据,传递productTagAlias参数
const tags = await this.getTags(options?.productTagAlias);
// 将单个标签ID转换为数组
const tagIds = Array.isArray(tagId) ? tagId : [tagId];
// 收集所有指定标签下的产品ID
const allProductIds = [];
tagIds.forEach(id => {
const targetTag = tags.find(tag => tag.tagId === id);
if (targetTag) {
allProductIds.push(...targetTag.productIds);
}
});
// 去重
const uniqueProductIds = [...new Set(allProductIds)];
if (uniqueProductIds.length === 0) {
return {
products: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedProductIds = uniqueProductIds.slice(offset, offset + limit);
// 获取产品详情
const products = await Promise.all(paginatedProductIds.map(productId => this.getProduct_p(productId)));
// 应用状态过滤
let filteredProducts = products;
if (options?.status !== undefined) {
filteredProducts = products.filter(product => product.status === options.status);
}
return {
products: filteredProducts,
total: uniqueProductIds.length,
page,
limit
};
}
/**
* 5.3. 根据单个标签ID获取平台产品列表
* 使用getTags_p_single获取指定标签数据,然后获取产品详情
* @param tagId 单个标签ID
* @param options 查询选项
*/
async getProductsByTag_single(tagId, options) {
// 获取指定标签的数据
const tagData = await this.getTags_p_single(tagId);
if (!tagData || !tagData.productIds || tagData.productIds.length === 0) {
// 剔除productIds字段
const { productIds, ...tagInfo } = tagData;
return {
products: [],
total: 0,
page: options?.page || 1,
limit: options?.limit || 10,
tag: tagInfo
};
}
// 应用分页
const page = options?.page || 1;
const limit = options?.limit || 10;
const offset = (page - 1) * limit;
const paginatedProductIds = tagData.productIds.slice(offset, offset + limit);
// 获取产品详情
const products = await Promise.all(paginatedProductIds.map(productId => this.getProduct_p(productId)));
// 应用状态过滤
let filteredProducts = products;
if (options?.status !== undefined) {
filteredProducts = products.filter(product => product.status === options.status);
}
// 剔除productIds字段
const { productIds, ...tagInfo } = tagData;
return {
products: filteredProducts,
total: tagData.productIds.length,
page,
limit,
tag: tagInfo
};
}
/**
* 6. 根据分类ID获取该分类的层级路径
* 用于前端面包屑导航
*/
async getCategoryPath(categoryId) {
// 获取所有分类数据
const categories = await this.getCategories();
// 递归查找目标分类的函数
const findCategoryById = (cats, targetId) => {
for (const cat of cats) {
if (cat.categoryId === targetId) {
return cat;
}
if (cat.children && cat.children.length > 0) {
const found = findCategoryById(cat.children, targetId);
if (found)
return found;
}
}
return null;
};
// 查找目标分类(包括子分类)
const targetCategory = findCategoryById(categories, categoryId);
if (!targetCategory) {
return {
path: [],
currentCategory: null,
breadcrumbs: []
};
}
// 构建分类路径
const path = [];
const breadcrumbs = [];
// 递归查找父分类的函数
const buildPath = (currentCategory, level = 0) => {
// 将当前分类添加到路径开头(因为我们要从根到叶子构建)
path.unshift(currentCategory);
breadcrumbs.unshift({
categoryId: currentCategory.categoryId,
categoryName: currentCategory.categoryName,
level
});
// 如果有父分类,继续递归
if (currentCategory.parentId && currentCategory.parentId !== 0) {
const parentCategory = findCategoryById(categories, currentCategory.parentId);
if (parentCategory) {
buildPath(parentCategory, level + 1);
}
}
};
// 从目标分类开始构建路径
buildPath(targetCategory);
return {
path,
currentCategory: targetCategory,
breadcrumbs
};
}
/**
* 7. 获取指定分类ID下的子分类
* 支持递归获取所有层级的子分类
*/
async getSubCategories(categoryId, options) {
// 获取所有分类数据
const categories = await this.getCategories();
// 递归查找分类的函数
const findCategoryById = (cats, targetId) => {
for (const cat of cats) {
if (cat.categoryId === targetId) {
return cat;
}
if (cat.children && cat.children.length > 0) {
const found = findCategoryById(cat.children, targetId);
if (found)
return found;
}
}
return null;
};
// 查找目标分类(包括子分类)
const targetCategory = findCategoryById(categories, categoryId);
if (!targetCategory) {
return {
subCategories: [],
currentCategory: null,
total: 0,
depth: 0
};
}
const subCategories = [];
let maxDepth = options?.maxDepth || Infinity;
let actualDepth = 0;
// 递归获取子分类的函数
const collectSubCategories = (parentId, currentDepth = 0) => {
if (currentDepth >= maxDepth) {
return;
}
// 递归查找直接子分类
const findChildren = (cats, parentId) => {
const children = [];
for (const cat of cats) {
if (cat.parentId === parentId) {
children.push(cat);
}
if (cat.children && cat.children.length > 0) {
children.push(...findChildren(cat.children, parentId));
}
}
return children;
};
const children = findChildren(categories, parentId);
children.forEach(child => {
subCategories.push(child);
// 如果需要递归且未达到最大深度,继续查找子分类
if (options?.recursive && currentDepth < maxDepth - 1) {
collectSubCategories(child.categoryId, currentDepth + 1);
}
});
// 更新实际深度
actualDepth = Math.max(actualDepth, currentDepth);
};
// 开始收集子分类
collectSubCategories(categoryId);
// 如果需要包含当前分类,添加到结果中
if (options?.includeCurrent) {
subCategories.unshift(targetCategory);
}
return {
subCategories,
currentCategory: targetCategory,
total: subCategories.length,
depth: actualDepth
};
}
/**
* 8. 获取税费信息
* 获取平台的所有税费模板和规则
*/
async getTaxInfo() {
const config = this.client.getConfig();
return this.client.request(`/tax/platform-${config.platformId}.json`);
}
/**
* 9. 获取运费信息
* 获取平台的所有运费模板和规则
*/
async getShippingInfo() {
const config = this.client.getConfig();
return this.client.request(`/shipping/platform-${config.platformId}.json`);
}
/**
* 10. 获取区域信息
* 获取平台的所有区域信息,包括层级结构
*/
async getRegions() {
const config = this.client.getConfig();
return this.client.request(`/regions/platform-${config.platformId}.json`);
}
/**
* 11. 获取支付方式信息
* 获取平台的所有支付方式,包括API支付和手动支付
* @param paymentAlias 支付方式别名,默认为'01'
*/
async getPaymentMethods(paymentAlias) {
const config = this.client.getConfig();
const alias = paymentAlias || '01';
return this.client.request(`/payment/platform-${config.platformId}-${alias}.json`);
}
/**
* 12. 根据支付方式类型获取支付方式列表
* @param type 支付方式类型:'Api' | 'Manual' | 'Gateway' | 'Crypto'
* @param paymentAlias 支付方式别名,默认为'01'
*/
async getPaymentMethodsByType(type, paymentAlias) {
const response = await this.getPaymentMethods(paymentAlias);
return response.methods.filter(method => method.type === type);
}
/**
* 13. 根据支付方式ID获取特定支付方式详情
* @param methodId 支付方式ID
* @param paymentAlias 支付方式别名,默认为'01'
*/
async getPaymentMethodById(methodId, paymentAlias) {
const response = await this.getPaymentMethods(paymentAlias);
return response.methods.find(method => method.id === methodId) || null;
}
/**
* 14. 获取支付方式属性值
* @param methodId 支付方式ID
* @param attrName 属性名称
* @param paymentAlias 支付方式别名,默认为'01'
*/
async getPaymentMethodAttribute(methodId, attrName, paymentAlias) {
const method = await this.ge