diff --git a/src/service/Wintopay.service.ts b/src/service/Wintopay.service.ts index eaef0c7..cf2491a 100644 --- a/src/service/Wintopay.service.ts +++ b/src/service/Wintopay.service.ts @@ -33,15 +33,15 @@ interface LogisticsUpdateResponse { @Provide() export class WintopayService { @Inject() logger; - - // 默认配置 - private config = { - //测试环境配置,在生产环境记得换掉 - apiBaseUrl: 'https://stage-merchant-api.wintopay.com', - Authorization: 'Bearer kV8w1er8dFw9p9g2kb0mer398hD8hfWk', - }; - // 发送请求 + // 默认配置 + private config = { + //测试环境配置,在生产环境记得换掉 + apiBaseUrl: 'https://stage-merchant-api.wintopay.com', + Authorization: 'Bearer kV8w1er8dFw9p9g2kb0mer398hD8hfWk', + }; + + // 发送请求 private async sendRequest(url: string, data: any): Promise { try { const headers = { @@ -77,19 +77,19 @@ export class WintopayService { async logisticsUpdate(params: LogisticsUpdateRequest): Promise { try { this.logger.info('开始更新物流信息:', params); - + const response = await this.sendRequest('/v1/logistics/update', params); - + this.logger.info('物流更新成功:', response); return response; } catch (error: any) { this.logger.error('物流更新失败:', error); - + // 处理API返回的错误 if (error.response?.data) { throw new Error(`物流更新失败: ${error.response.data.message || '未知错误'}`); } - + throw new Error(`物流更新请求失败: ${error.message || '网络错误'}`); } } diff --git a/src/service/order.service.ts b/src/service/order.service.ts index 752c1c5..2e5efe3 100644 --- a/src/service/order.service.ts +++ b/src/service/order.service.ts @@ -2873,7 +2873,7 @@ export class OrderService { const logisticsAliases = await this.logisticsAliasModel.find(); // 构建物流公司别名映射 - const logisticsAliasMap = new Map(logisticsAliases.map(alias => [ alias.logistics_alias,alias.logistics_company])); + const logisticsAliasMap = new Map(logisticsAliases.map(alias => [alias.logistics_alias, alias.logistics_company])); // 遍历数据行 for (let i = 0; i < dataRows.length; i++) { diff --git a/src/service/product.service.ts b/src/service/product.service.ts index 581485b..a32f487 100644 --- a/src/service/product.service.ts +++ b/src/service/product.service.ts @@ -1792,16 +1792,16 @@ export class ProductService { // 这里判断 second 是否是数字 return sku.includes('-MX-') || sku.includes('-Mixed-') || /^\d+$/.test(second) && /^\d+$/.test(last) } - async getComponentDetailFromSiteSku(siteProduct: { sku: string, name: string }, quantity: number = 1, site: Site): Promise<{ product: Product,parentProduct?: Product, quantity: number }[]> { + async getComponentDetailFromSiteSku(siteProduct: { sku: string, name: string }, quantity: number = 1, site: Site): Promise<{ product: Product, parentProduct?: Product, quantity: number }[]> { if (!siteProduct.sku) { throw new Error('siteSku 不能为空') } - const product = await this.getProductBySiteSku(siteProduct.sku, site) + const product = await this.getProductBySiteSku(siteProduct.sku, site) if (!product) return - if(!product?.components?.length){ + if (!product?.components?.length) { return [{ product, quantity @@ -1816,7 +1816,7 @@ export class ProductService { parentProduct: product, // 这里得记录一下他的爸爸用来记录 quantity: comp.quantity * quantity, } - })) + })) } // 准备创建产品的 DTO, 处理类型转换和默认值 diff --git a/src/service/wp.service.ts b/src/service/wp.service.ts index 3500bcb..8da7d40 100644 --- a/src/service/wp.service.ts +++ b/src/service/wp.service.ts @@ -16,7 +16,7 @@ import { WooProduct, WooVariation, WpMediaGetListParams } from '../dto/woocommer const MAX_PAGE_SIZE = 100; @Provide() export class WPService implements IPlatformService { - + @Inject() private readonly siteService: SiteService; @@ -75,7 +75,7 @@ export class WPService implements IPlatformService { } const data = res.data as T[]; const totalPages = Number(res.headers?.['x-wp-totalpages'] ?? 1); - const total = Number(res.headers?.['x-wp-total']?? 1) + const total = Number(res.headers?.['x-wp-total'] ?? 1) return { items: data, total, totalPages, page, per_page, page_size: per_page }; } @@ -94,9 +94,9 @@ export class WPService implements IPlatformService { * 默认按 date_created 倒序排列,确保获取最新的数据 */ private async sdkGetAllConcurrent( - api: WooCommerceRestApi, - resource: string, - params: Record = {}, + api: WooCommerceRestApi, + resource: string, + params: Record = {}, maxPages: number = MAX_PAGE_SIZE, concurrencyLimit: number = 5 ): Promise { @@ -118,7 +118,7 @@ export class WPService implements IPlatformService { // 限制最大页数,避免过多的并发请求 const actualMaxPages = Math.min(totalPages, maxPages); - + // 收集所有页面数据,从第二页开始 const allItems = [...firstPageItems]; let currentPage = 2; @@ -127,7 +127,7 @@ export class WPService implements IPlatformService { while (currentPage <= actualMaxPages) { const batchPromises: Promise[] = []; const batchSize = Math.min(concurrencyLimit, actualMaxPages - currentPage + 1); - + // 创建当前批次的并发请求 for (let i = 0; i < batchSize; i++) { const page = currentPage + i; @@ -137,18 +137,18 @@ export class WPService implements IPlatformService { console.error(`获取第 ${page} 页数据失败:`, error); return []; // 如果某页获取失败,返回空数组,不影响整体结果 }); - + batchPromises.push(pagePromise); } // 等待当前批次完成 const batchResults = await Promise.all(batchPromises); - + // 合并当前批次的数据 for (const pageItems of batchResults) { allItems.push(...pageItems); } - + // 移动到下一批次 currentPage += batchSize; } @@ -206,7 +206,7 @@ export class WPService implements IPlatformService { const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString( 'base64' ); - console.log(`!!!wpApiUrl, consumerKey, consumerSecret, auth`,site.apiUrl, consumerKey, consumerSecret, auth) + console.log(`!!!wpApiUrl, consumerKey, consumerSecret, auth`, site.apiUrl, consumerKey, consumerSecret, auth) let hasMore = true; while (hasMore) { const config: AxiosRequestConfig = { @@ -259,8 +259,8 @@ export class WPService implements IPlatformService { // 导出 WooCommerce 产品为特殊CSV(平台特性) async exportProductsCsvSpecial(site: any, page: number = 1, pageSize: number = 100): Promise { const list = await this.getProducts(site, { page, per_page: pageSize }); - const header = ['id','name','type','status','sku','regular_price','sale_price','stock_status','stock_quantity']; - const rows = (list.items || []).map((p: any) => [p.id,p.name,p.type,p.status,p.sku,p.regular_price,p.sale_price,p.stock_status,p.stock_quantity]); + const header = ['id', 'name', 'type', 'status', 'sku', 'regular_price', 'sale_price', 'stock_status', 'stock_quantity']; + const rows = (list.items || []).map((p: any) => [p.id, p.name, p.type, p.status, p.sku, p.regular_price, p.sale_price, p.stock_status, p.stock_quantity]); const csv = [header.join(','), ...rows.map(r => r.map(v => String(v ?? '')).join(','))].join('\n'); return csv; } @@ -289,7 +289,7 @@ export class WPService implements IPlatformService { const res = await api.get(`orders/${orderId}`); return res.data as Record; } - async getOrders(siteId: number,params: Record = {}): Promise[]> { + async getOrders(siteId: number, params: Record = {}): Promise[]> { const site = await this.siteService.get(siteId); const api = this.createApi(site, 'wc/v3'); return await this.sdkGetAll>(api, 'orders', params); @@ -367,10 +367,10 @@ export class WPService implements IPlatformService { const api = this.createApi(site, 'wc/v3'); // 确保价格为字符串 if (data.regular_price !== undefined && data.regular_price !== null) { - data.regular_price = String(data.regular_price); + data.regular_price = String(data.regular_price); } if (data.sale_price !== undefined && data.sale_price !== null) { - data.sale_price = String(data.sale_price); + data.sale_price = String(data.sale_price); } // 处理标签字段,如果为字符串数组则转换为 WooCommerce 所需的对象数组 if (Array.isArray((data as any).tags)) { @@ -696,7 +696,7 @@ export class WPService implements IPlatformService { Authorization: `Basic ${auth}`, }, }; - + try { const response = await axios.request(config); return response.data || []; @@ -740,19 +740,19 @@ export class WPService implements IPlatformService { ); const fulfillmentData: any = {}; - + if (data.shipping_provider !== undefined) { fulfillmentData.shipping_provider = data.shipping_provider; } - + if (data.tracking_number !== undefined) { fulfillmentData.tracking_number = data.tracking_number; } - + if (data.shipping_method !== undefined) { fulfillmentData.shipping_method = data.shipping_method; } - + if (data.status !== undefined) { fulfillmentData.status = data.status; } @@ -780,7 +780,7 @@ export class WPService implements IPlatformService { }, data: fulfillmentData, }; - + try { const response = await axios.request(config); return response.data; @@ -803,10 +803,10 @@ export class WPService implements IPlatformService { try { const response = await api.post('products/batch', data); const result = response.data; - + // 转换 WooCommerce 批量操作结果为统一格式 - const errors: Array<{identifier: string, error: string}> = []; - + const errors: Array<{ identifier: string, error: string }> = []; + // WooCommerce 返回格式: { create: [...], update: [...], delete: [...] } // 错误信息可能在每个项目的 error 字段中 const checkForErrors = (items: any[]) => { @@ -819,12 +819,12 @@ export class WPService implements IPlatformService { } }); }; - + // 检查每个操作类型的结果中的错误 if (result.create) checkForErrors(result.create); if (result.update) checkForErrors(result.update); if (result.delete) checkForErrors(result.delete); - + return { total: (data.create?.length || 0) + (data.update?.length || 0) + (data.delete?.length || 0), processed: (result.create?.length || 0) + (result.update?.length || 0) + (result.delete?.length || 0), @@ -1022,7 +1022,7 @@ export class WPService implements IPlatformService { async getMedia(siteId: number, page: number = 1, perPage: number = 20): Promise<{ items: any[], total: number, totalPages: number }> { const site = await this.siteService.get(siteId, true); if (!site) { - throw new Error('站点不存在'); + throw new Error('站点不存在'); } const endpoint = 'wp/v2/media'; const apiUrl = site.apiUrl; @@ -1030,15 +1030,15 @@ export class WPService implements IPlatformService { // 构建 URL,规避多/或少/问题 const url = this.buildURL(apiUrl, '/wp-json', endpoint); const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString('base64'); - + const response = await axios.get(url, { headers: { Authorization: `Basic ${auth}` }, params: { page, per_page: perPage } }); - + const total = Number(response.headers['x-wp-total'] || 0); const totalPages = Number(response.headers['x-wp-totalpages'] || 0); - + return { items: response.data, total, @@ -1046,7 +1046,7 @@ export class WPService implements IPlatformService { }; } -public async fetchMediaPaged(site: any, params: Partial = {}) { + public async fetchMediaPaged(site: any, params: Partial = {}) { const apiUrl = site.apiUrl; const { consumerKey, consumerSecret } = site as any; const endpoint = 'wp/v2/media'; @@ -1061,15 +1061,15 @@ public async fetchMediaPaged(site: any, params: Partial = } }); // 检查是否有错误信息 - if(response?.data?.message){ + if (response?.data?.message) { throw new Error(`获取${apiUrl}条媒体文件失败,原因为${response.data.message}`) } - if(!Array.isArray(response.data)) { + if (!Array.isArray(response.data)) { throw new Error(`获取${apiUrl}条媒体文件失败,原因为返回数据不是数组`); } const total = Number(response.headers['x-wp-total'] || 0); const totalPages = Number(response.headers['x-wp-totalpages'] || 0); - return { items: response.data, total, totalPages, page:params.page ?? 1, per_page: params.per_page ?? 20, page_size: params.per_page ?? 20 }; + return { items: response.data, total, totalPages, page: params.page ?? 1, per_page: params.per_page ?? 20, page_size: params.per_page ?? 20 }; } /** * 上传媒体文件 @@ -1091,15 +1091,15 @@ public async fetchMediaPaged(site: any, params: Partial = // 假设 file 是 MidwayJS 的 file 对象 // MidwayJS 上传文件通常在 tmp 目录,需要读取流 formData.append('file', fs.createReadStream(file.data), { - filename: file.filename, - contentType: file.mimeType, + filename: file.filename, + contentType: file.mimeType, }); // Axios headers for multipart const headers = { - Authorization: `Basic ${auth}`, - 'Content-Disposition': `attachment; filename=${file.filename}`, - ...formData.getHeaders(), + Authorization: `Basic ${auth}`, + 'Content-Disposition': `attachment; filename=${file.filename}`, + ...formData.getHeaders(), }; try { @@ -1205,10 +1205,12 @@ public async fetchMediaPaged(site: any, params: Partial = throw new Error('source_url 不存在'); } // 下载源文件为 Buffer - const resp = await axios.get(srcUrl, { responseType: 'arraybuffer', timeout: 30000, - headers: { - 'User-Agent': 'Mozilla/5.0 (compatible; Node.js Axios)', - } }); + const resp = await axios.get(srcUrl, { + responseType: 'arraybuffer', timeout: 30000, + headers: { + 'User-Agent': 'Mozilla/5.0 (compatible; Node.js Axios)', + } + }); const inputBuffer = Buffer.from(resp.data); // 条件判断 如果下载的 Buffer 为空则抛出错误 if (!inputBuffer || inputBuffer.length === 0) {