From cf65e36d24284ba6416cef4c47827f68286cd4d6 Mon Sep 17 00:00:00 2001 From: tikkhun Date: Thu, 8 Jan 2026 18:46:13 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E7=BB=9F=E4=B8=80=E4=B8=AD=E6=96=87?= =?UTF-8?q?=E6=8B=AC=E5=8F=B7=E6=A0=BC=E5=BC=8F=E4=B8=BA=E5=85=A8=E8=A7=92?= =?UTF-8?q?=E6=8B=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将代码中的中文括号格式从半角"()"统一修改为全角"()",并删除测试文档文件test-site-sku-methods.md chore: config.local 还原 docs(dto): 修正注释中的中文括号格式 docs(dto): 修正注释中的括号格式 docs: 修正中文标点符号和注释格式 统一将中文注释和文档中的全角括号和冒号改为半角格式 修正部分TODO注释的标点符号 统一接口文档中的描述符号格式 --- permutation_fix.md | 184 -------------------------- src/adapter/shopyy.adapter.ts | 20 +-- src/adapter/woocommerce.adapter.ts | 6 +- src/config/config.local.ts | 5 +- src/configuration.ts | 2 +- src/controller/site-api.controller.ts | 6 +- src/db/seeds/dict.seeder.ts | 44 +++--- src/dto/api.dto.ts | 12 +- src/dto/batch.dto.ts | 14 +- src/dto/customer.dto.ts | 16 +-- src/dto/shopyy.dto.ts | 28 ++-- src/dto/site-api.dto.ts | 2 +- src/dto/site.dto.ts | 2 +- src/dto/woocommerce.dto.ts | 14 +- src/enums/base.enum.ts | 2 +- src/interface/platform.interface.ts | 2 +- src/service/customer.service.ts | 18 +-- src/service/dict.service.ts | 4 +- src/service/order.service.ts | 8 +- src/service/product.service.ts | 10 +- src/service/shopyy.service.ts | 2 +- src/service/site-api.service.ts | 2 +- src/service/wp.service.ts | 2 +- test-site-sku-methods.md | 105 --------------- 24 files changed, 112 insertions(+), 398 deletions(-) delete mode 100644 permutation_fix.md delete mode 100644 test-site-sku-methods.md diff --git a/permutation_fix.md b/permutation_fix.md deleted file mode 100644 index de227d0..0000000 --- a/permutation_fix.md +++ /dev/null @@ -1,184 +0,0 @@ -# Permutation页面列表显示问题分析和修复方案 - -## 问题分析 - -经过代码分析,发现了以下几个可能导致列表不显示的问题: - -### 1. API路径不匹配 -前端代码中引用的API函数名与后端控制器中的路径不一致: -- 前端:`productcontrollerGetcategoriesall`、`productcontrollerGetcategoryattributes`、`productcontrollerGetproductlist` -- 后端实际的API路径:`/product/categories/all`、`/product/category/:id/attributes`、`/product/list` - -### 2. 数据格式问题 -- `getCategoryAttributes`返回的数据结构与前端期望的不匹配 -- 属性值获取逻辑可能存在问题 - -### 3. 组合生成逻辑问题 -- 在生成排列组合时,数据结构和键值对应可能不正确 - -## 修复方案 - -### 后端修复 - -1. **修改getCategoryAttributes方法** - 在`/Users/zksu/Developer/work/workcode/API/src/service/product.service.ts`中: - -```typescript -// 获取分类下的属性配置 -async getCategoryAttributes(categoryId: number): Promise { - const category = await this.categoryModel.findOne({ - where: { id: categoryId }, - relations: ['attributes', 'attributes.attributeDict', 'attributes.attributeDict.items'], - }); - - if (!category) { - return []; - } - - // 格式化返回,匹配前端期望的数据结构 - return category.attributes.map(attr => ({ - id: attr.id, - dictId: attr.attributeDict.id, - name: attr.attributeDict.name, // 用于generateKeyFromPermutation - title: attr.attributeDict.title, // 用于列标题 - dict: { - id: attr.attributeDict.id, - name: attr.attributeDict.name, - title: attr.attributeDict.title, - items: attr.attributeDict.items || [] - } - })); -} -``` - -2. **确保dict/items接口可用** - 检查字典项获取接口: - -在`/Users/zksu/Developer/work/workcode/API/src/controller/dict.controller.ts`中添加或确认: - -```typescript -@Get('/items') -async getDictItems(@Query('dictId') dictId: number) { - try { - const dict = await this.dictModel.findOne({ - where: { id: dictId }, - relations: ['items'] - }); - - if (!dict) { - return []; - } - - return dict.items || []; - } catch (error) { - return errorResponse(error?.message || error); - } -} -``` - -### 前端修复建议 - -1. **添加错误处理和调试信息**: - -```typescript -// 在获取属性值的地方添加错误处理 -const fetchData = async () => { - setLoading(true); - try { - // 1. Fetch Attributes - const attrRes = await productcontrollerGetcategoryattributes({ - id: categoryId, - }); - console.log('Attributes response:', attrRes); // 调试用 - const attrs = Array.isArray(attrRes) ? attrRes : attrRes?.data || []; - setAttributes(attrs); - - // 2. Fetch Attribute Values (Dict Items) - const valuesMap: Record = {}; - for (const attr of attrs) { - const dictId = attr.dict?.id || attr.dictId; - if (dictId) { - try { - const itemsRes = await request('/dict/items', { - params: { dictId }, - }); - console.log(`Dict items for ${attr.name}:`, itemsRes); // 调试用 - valuesMap[attr.name] = itemsRes || []; - } catch (error) { - console.error(`Failed to fetch items for dict ${dictId}:`, error); - valuesMap[attr.name] = []; - } - } - } - setAttributeValues(valuesMap); - - // 3. Fetch Existing Products - await fetchProducts(categoryId); - } catch (error) { - console.error('Error in fetchData:', error); - message.error('获取数据失败'); - } finally { - setLoading(false); - } -}; -``` - -2. **修复组合生成逻辑**: - -```typescript -// 修改generateKeyFromPermutation函数 -const generateKeyFromPermutation = (perm: any) => { - const parts = Object.keys(perm).map((attrName) => { - const valItem = perm[attrName]; - const val = valItem.name || valItem.value; // 兼容不同的数据格式 - return `${attrName}:${val}`; - }); - return parts.sort().join('|'); -}; - -// 修改generateAttributeKey函数 -const generateAttributeKey = (attrs: any[]) => { - const parts = attrs.map((a) => { - const key = a.dict?.name || a.dictName || a.name; - const val = a.name || a.value; - return `${key}:${val}`; - }); - return parts.sort().join('|'); -}; -``` - -3. **添加空状态处理**: - -```typescript -// 在ProTable中添加空状态提示 - -``` - -## 调试步骤 - -1. **检查网络请求**: - - 打开浏览器开发者工具 - - 检查 `/product/categories/all` 请求是否成功 - - 检查 `/product/category/:id/attributes` 请求返回的数据格式 - - 检查 `/dict/items?dictId=:id` 请求是否成功 - - 检查 `/product/list` 请求是否成功 - -2. **检查控制台日志**: - - 查看属性数据是否正确加载 - - 查看属性值是否正确获取 - - 查看排列组合是否正确生成 - -3. **检查数据结构**: - - 确认 `attributes` 数组是否正确 - - 确认 `attributeValues` 对象是否正确填充 - - 确认 `permutations` 数组是否正确生成 - -## 测试验证 - -1. 选择一个有属性配置的分类 -2. 确认属性有对应的字典项 -3. 检查排列组合是否正确显示 -4. 验证现有产品匹配是否正确 \ No newline at end of file diff --git a/src/adapter/shopyy.adapter.ts b/src/adapter/shopyy.adapter.ts index cba2c5a..d9215bb 100644 --- a/src/adapter/shopyy.adapter.ts +++ b/src/adapter/shopyy.adapter.ts @@ -405,7 +405,7 @@ export class ShopyyAdapter implements ISiteAdapter { } mapUpdateOrderParams(data: Partial): any { - // 构建 ShopYY 订单更新参数(仅包含传入的字段) + // 构建 ShopYY 订单更新参数(仅包含传入的字段) const params: any = {}; // 仅当字段存在时才添加到更新参数中 @@ -665,7 +665,7 @@ export class ShopyyAdapter implements ISiteAdapter { const statusMap = { 'pending': '100', // 100 未完成 'processing': '110', // 110 待处理 - 'completed': "180", // 180 已完成(确认收货) + 'completed': "180", // 180 已完成(确认收货) 'cancelled': '190', // 190 取消 }; @@ -797,7 +797,7 @@ export class ShopyyAdapter implements ISiteAdapter { return status === 'publish' ? 1 : 0; }; - // 构建 ShopYY 产品更新参数(仅包含传入的字段) + // 构建 ShopYY 产品更新参数(仅包含传入的字段) const params: any = {}; // 仅当字段存在时才添加到更新参数中 @@ -816,7 +816,7 @@ export class ShopyyAdapter implements ISiteAdapter { params.inventory_quantity = data.stock_status === 'instock' ? (data.stock_quantity || 1) : 0; } - // 添加变体信息(如果存在) + // 添加变体信息(如果存在) if (data.variations && data.variations.length > 0) { params.variants = data.variations.map((variation: UnifiedProductVariationDTO) => { const variationParams: any = {}; @@ -836,7 +836,7 @@ export class ShopyyAdapter implements ISiteAdapter { }); } - // 添加图片信息(如果存在) + // 添加图片信息(如果存在) if (data.images && data.images.length > 0) { params.images = data.images.map((image: any) => ({ id: image.id, @@ -846,12 +846,12 @@ export class ShopyyAdapter implements ISiteAdapter { })); } - // 添加标签信息(如果存在) + // 添加标签信息(如果存在) if (data.tags && data.tags.length > 0) { params.tags = data.tags.map((tag: any) => tag.name || ''); } - // 添加分类信息(如果存在) + // 添加分类信息(如果存在) if (data.categories && data.categories.length > 0) { params.collections = data.categories.map((category: any) => ({ id: category.id, @@ -1121,7 +1121,7 @@ export class ShopyyAdapter implements ISiteAdapter { } mapUpdateVariationParams(data: Partial): any { - // 构建 ShopYY 变体更新参数(仅包含传入的字段) + // 构建 ShopYY 变体更新参数(仅包含传入的字段) const params: any = {}; // 仅当字段存在时才添加到更新参数中 @@ -1292,12 +1292,12 @@ export class ShopyyAdapter implements ISiteAdapter { return stockStatus === 'instock' ? 1 : 0; }; - shopyyOrderStatusMap = {//订单状态 100 未完成;110 待处理;180 已完成(确认收货); 190 取消; + shopyyOrderStatusMap = {//订单状态 100 未完成;110 待处理;180 已完成(确认收货); 190 取消; [100]: OrderStatus.PENDING, // 100 未完成 转为 pending [110]: OrderStatus.PROCESSING, // 110 待处理 转为 processing // 已发货 - [180]: OrderStatus.COMPLETED, // 180 已完成(确认收货) 转为 completed + [180]: OrderStatus.COMPLETED, // 180 已完成(确认收货) 转为 completed [190]: OrderStatus.CANCEL // 190 取消 转为 cancelled } diff --git a/src/adapter/woocommerce.adapter.ts b/src/adapter/woocommerce.adapter.ts index 3627c22..0849358 100644 --- a/src/adapter/woocommerce.adapter.ts +++ b/src/adapter/woocommerce.adapter.ts @@ -609,7 +609,7 @@ export class WooCommerceAdapter implements ISiteAdapter { // await api.put(`orders/${orderId}`, { status: 'processing' }); // // 添加取消履行的备注 - // const note = `订单履行已取消${data.reason ? `,原因:${data.reason}` : ''}`; + // const note = `订单履行已取消${data.reason ? `,原因:${data.reason}` : ''}`; // await api.post(`orders/${orderId}/notes`, { note, customer_note: true }); // return { @@ -698,14 +698,14 @@ export class WooCommerceAdapter implements ISiteAdapter { })); } - // 映射变体数据(注意:WooCommerce API 中变体通常通过单独的端点处理) + // 映射变体数据(注意:WooCommerce API 中变体通常通过单独的端点处理) // 这里只映射变体的基本信息,具体创建/更新变体需要额外处理 if (data.variations && Array.isArray(data.variations)) { // 对于WooProduct类型,variations字段只存储变体ID mapped.variations = data.variations.map(variation => variation.id as number); } - // 映射下载数据(如果产品是可下载的) + // 映射下载数据(如果产品是可下载的) // if (data.downloads && Array.isArray(data.downloads)) { // mapped.downloads = data.downloads.map(download => ({ // id: download.id as number, diff --git a/src/config/config.local.ts b/src/config/config.local.ts index 6d381aa..a8326f6 100644 --- a/src/config/config.local.ts +++ b/src/config/config.local.ts @@ -7,8 +7,11 @@ export default { // dataSource: { // default: { // host: '13.212.62.127', + // port: "3306", // username: 'root', // password: 'Yoone!@.2025', + // database: 'inventory_v2', + // synchronize: true, // }, // }, // }, @@ -19,7 +22,7 @@ export default { port: "3306", username: 'root', password: 'root', - database: 'inventory', + database: 'inventory' }, }, }, diff --git a/src/configuration.ts b/src/configuration.ts index 16a5716..9711264 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -99,7 +99,7 @@ export class MainConfiguration { } /** - * 初始化数据库(如果不存在则创建) + * 初始化数据库(如果不存在则创建) */ private async initializeDatabase(): Promise { // 使用注入的数据库配置 diff --git a/src/controller/site-api.controller.ts b/src/controller/site-api.controller.ts index 00d8285..8eb45e1 100644 --- a/src/controller/site-api.controller.ts +++ b/src/controller/site-api.controller.ts @@ -299,7 +299,7 @@ export class SiteApiController { } } - // 平台特性:产品导出(特殊CSV,走平台服务) + // 平台特性:产品导出(特殊CSV,走平台服务) @Get('/:siteId/links') async getLinks( @Param('siteId') siteId: number @@ -429,7 +429,7 @@ export class SiteApiController { } } - // 平台特性:产品导入(特殊CSV,走平台服务) + // 平台特性:产品导入(特殊CSV,走平台服务) @Post('/:siteId/products/import-special') @ApiOkResponse({ type: Object }) async importProductsSpecial( @@ -443,7 +443,7 @@ export class SiteApiController { const created: any[] = []; const failed: any[] = []; if (site.type === 'woocommerce') { - // 解析 CSV 为对象数组(若传入 items 则优先 items) + // 解析 CSV 为对象数组(若传入 items 则优先 items) let payloads = items; if (!payloads.length && csvText) { const lines = csvText.split(/\r?\n/).filter(Boolean); diff --git a/src/db/seeds/dict.seeder.ts b/src/db/seeds/dict.seeder.ts index d015a05..37ef843 100644 --- a/src/db/seeds/dict.seeder.ts +++ b/src/db/seeds/dict.seeder.ts @@ -126,7 +126,7 @@ const flavorsData = [ { name: 'arctic-mint', title: 'arctic mint', titleCn: '北极薄荷', shortName: 'AR' }, { name: 'baddie-blueberries', title: 'baddie blueberries', titleCn: '时髦蓝莓', shortName: 'BA' }, { name: 'banana', title: 'banana', titleCn: '香蕉', shortName: 'BA' }, - { name: 'banana-(solid)', title: 'banana (solid)', titleCn: '香蕉(固体)', shortName: 'BA' }, + { name: 'banana-(solid)', title: 'banana (solid)', titleCn: '香蕉(固体)', shortName: 'BA' }, { name: 'banana-berry', title: 'banana berry', titleCn: '香蕉莓果', shortName: 'BA' }, { name: 'banana-berry-melon-ice', title: 'banana berry melon ice', titleCn: '香蕉莓果瓜冰', shortName: 'BA' }, { name: 'banana-blackberry', title: 'banana blackberry', titleCn: '香蕉黑莓', shortName: 'BA' }, @@ -137,7 +137,7 @@ const flavorsData = [ { name: 'bangin-blood-orange-iced', title: 'bangin blood orange iced', titleCn: '爆炸血橙冰', shortName: 'BA' }, { name: 'berries-in-the-6ix', title: 'berries in the 6ix', titleCn: '多伦多莓果', shortName: 'BE' }, { name: 'berry-burst', title: 'berry burst', titleCn: '浆果爆发', shortName: 'BE' }, - { name: 'berry-burst-(thermal)', title: 'berry burst (thermal)', titleCn: '浆果爆发(热感)', shortName: 'BE' }, + { name: 'berry-burst-(thermal)', title: 'berry burst (thermal)', titleCn: '浆果爆发(热感)', shortName: 'BE' }, { name: 'berry-ice', title: 'berry ice', titleCn: '浆果冰', shortName: 'BE' }, { name: 'berry-lime-ice', title: 'berry lime ice', titleCn: '浆果青柠冰', shortName: 'BE' }, { name: 'berry-trio-ice', title: 'berry trio ice', titleCn: '三重浆果冰', shortName: 'BE' }, @@ -145,7 +145,7 @@ const flavorsData = [ { name: 'black-cherry', title: 'black cherry', titleCn: '黑樱桃', shortName: 'BL' }, { name: 'blackcherry', title: 'blackcherry', titleCn: '黑樱桃混合', shortName: 'BL' }, { name: 'blackcurrant-ice', title: 'blackcurrant ice', titleCn: '黑加仑冰', shortName: 'BL' }, - { name: 'black-currant-ice', title: 'black currant ice', titleCn: '黑加仑冰(空格版)', shortName: 'BL' }, + { name: 'black-currant-ice', title: 'black currant ice', titleCn: '黑加仑冰(空格版)', shortName: 'BL' }, { name: 'black-licorice', title: 'black licorice', titleCn: '黑甘草', shortName: 'BL' }, { name: 'black-tea', title: 'black tea', titleCn: '红茶', shortName: 'BL' }, { name: 'blackberry-ice', title: 'blackberry ice', titleCn: '黑莓冰', shortName: 'BL' }, @@ -168,7 +168,7 @@ const flavorsData = [ { name: 'blue-razz', title: 'blue razz', titleCn: '蓝覆盆子', shortName: 'BL' }, { name: 'blue-razz-hype', title: 'blue razz hype', titleCn: '蓝覆盆子热情', shortName: 'BL' }, { name: 'blue-razz-ice', title: 'blue razz ice', titleCn: '蓝覆盆子冰', shortName: 'BL' }, - { name: 'blue-razz-ice-(solid)', title: 'blue razz ice (solid)', titleCn: '蓝覆盆子冰(固体)', shortName: 'BL' }, + { name: 'blue-razz-ice-(solid)', title: 'blue razz ice (solid)', titleCn: '蓝覆盆子冰(固体)', shortName: 'BL' }, { name: 'blue-razz-ice-glace', title: 'blue razz ice glace', titleCn: '蓝覆盆子冰格', shortName: 'BL' }, { name: 'blue-razz-lemon-ice', title: 'blue razz lemon ice', titleCn: '蓝覆盆子柠檬冰', shortName: 'BL' }, { name: 'blue-razz-lemonade', title: 'blue razz lemonade', titleCn: '蓝覆盆子柠檬水', shortName: 'BL' }, @@ -196,7 +196,7 @@ const flavorsData = [ { name: 'bumpin-blackcurrant-iced', title: 'bumpin blackcurrant iced', titleCn: '黑加仑热烈冰', shortName: 'BU' }, { name: 'burst-ice', title: 'burst ice', titleCn: '爆炸冰', shortName: 'BU' }, { name: 'bussin-banana-iced', title: 'bussin banana iced', titleCn: '香蕉热烈冰', shortName: 'BU' }, - { name: 'bussin-banana-iced', title: 'bussin banana iced', titleCn: '香蕉热烈冰(重复)', shortName: 'BU' }, + { name: 'bussin-banana-iced', title: 'bussin banana iced', titleCn: '香蕉热烈冰(重复)', shortName: 'BU' }, { name: 'california-cherry', title: 'california cherry', titleCn: '加州樱桃', shortName: 'CA' }, { name: 'cantaloupe-mango-banana', title: 'cantaloupe mango banana', titleCn: '香瓜芒果香蕉', shortName: 'CA' }, { name: 'caramel', title: 'caramel', titleCn: '焦糖', shortName: 'CA' }, @@ -230,7 +230,7 @@ const flavorsData = [ { name: 'citrus-chill', title: 'citrus chill', titleCn: '柑橘清凉', shortName: 'CI' }, { name: 'citrus-smash-ice', title: 'citrus smash ice', titleCn: '柑橘冲击冰', shortName: 'CI' }, { name: 'citrus-sunrise', title: 'citrus sunrise', titleCn: '柑橘日出', shortName: 'CI' }, - { name: 'citrus-sunrise-(thermal)', title: 'citrus sunrise (thermal)', titleCn: '柑橘日出(热感)', shortName: 'CI' }, + { name: 'citrus-sunrise-(thermal)', title: 'citrus sunrise (thermal)', titleCn: '柑橘日出(热感)', shortName: 'CI' }, { name: 'classic', title: 'classic', titleCn: '经典', shortName: 'CL' }, { name: 'classic-ice', title: 'classic ice', titleCn: '经典冰', shortName: 'CL' }, { name: 'classic-mint-ice', title: 'classic mint ice', titleCn: '经典薄荷冰', shortName: 'CL' }, @@ -310,7 +310,7 @@ const flavorsData = [ { name: 'fizzy', title: 'fizzy', titleCn: '汽水', shortName: 'FI' }, { name: 'flavourless', title: 'flavourless', titleCn: '无味', shortName: 'FL' }, { name: 'flippin-fruit-flash', title: 'flippin fruit flash', titleCn: '翻转水果闪电', shortName: 'FL' }, - { name: 'flippin-fruit-flash-(rainbow-burst)', title: 'flippin fruit flash (rainbow burst)', titleCn: '翻转水果闪电(彩虹爆发)', shortName: 'FL' }, + { name: 'flippin-fruit-flash-(rainbow-burst)', title: 'flippin fruit flash (rainbow burst)', titleCn: '翻转水果闪电(彩虹爆发)', shortName: 'FL' }, { name: 'forest-fruits', title: 'forest fruits', titleCn: '森林水果', shortName: 'FO' }, { name: 'fragrant-grapefruit', title: 'fragrant grapefruit', titleCn: '香气葡萄柚', shortName: 'FR' }, { name: 'freeze', title: 'freeze', titleCn: '冰冻', shortName: 'FR' }, @@ -340,14 +340,14 @@ const flavorsData = [ { name: 'fuji-melon-ice', title: 'fuji melon ice', titleCn: '富士瓜冰', shortName: 'FU' }, { name: 'full-charge', title: 'full charge', titleCn: '满电', shortName: 'FU' }, { name: 'gb', title: 'gb', titleCn: '软糖', shortName: 'GB' }, - { name: 'gb(gummy-bear)', title: 'gb(gummy bear)', titleCn: '软糖(Gummy Bear)', shortName: 'GB' }, + { name: 'gb(gummy-bear)', title: 'gb(gummy bear)', titleCn: '软糖(Gummy Bear)', shortName: 'GB' }, { name: 'gentle-mint', title: 'gentle mint', titleCn: '温和薄荷', shortName: 'GE' }, { name: 'ghost-cola-&-vanilla', title: 'ghost cola & vanilla', titleCn: '幽灵可乐香草', shortName: 'GH' }, { name: 'ghost-cola-ice', title: 'ghost cola ice', titleCn: '幽灵可乐冰', shortName: 'GH' }, { name: 'ghost-mango', title: 'ghost mango', titleCn: '幽灵芒果', shortName: 'GH' }, { name: 'ghost-original', title: 'ghost original', titleCn: '幽灵原味', shortName: 'GH' }, { name: 'ghost-watermelon-ice', title: 'ghost watermelon ice', titleCn: '幽灵西瓜冰', shortName: 'GH' }, - { name: 'gnarly-green-d-(green-dew)', title: 'gnarly green d (green dew)', titleCn: '狂野绿 D(绿色露水)', shortName: 'GN' }, + { name: 'gnarly-green-d-(green-dew)', title: 'gnarly green d (green dew)', titleCn: '狂野绿 D(绿色露水)', shortName: 'GN' }, { name: 'gold-edition', title: 'gold edition', titleCn: '金版', shortName: 'GO' }, { name: 'grape', title: 'grape', titleCn: '葡萄', shortName: 'GR' }, { name: 'grape-cherry', title: 'grape cherry', titleCn: '葡萄樱桃', shortName: 'GR' }, @@ -492,13 +492,13 @@ const flavorsData = [ { name: 'mixed-fruit', title: 'mixed fruit', titleCn: '混合水果', shortName: 'MI' }, { name: 'mocha-ice', title: 'mocha ice', titleCn: '摩卡冰', shortName: 'MO' }, { name: 'morocco-mint', title: 'morocco mint', titleCn: '摩洛哥薄荷', shortName: 'MO' }, - { name: 'morocco-mint-(thermal)', title: 'morocco mint (thermal)', titleCn: '摩洛哥薄荷(热感)', shortName: 'MO' }, + { name: 'morocco-mint-(thermal)', title: 'morocco mint (thermal)', titleCn: '摩洛哥薄荷(热感)', shortName: 'MO' }, { name: 'mung-beans', title: 'mung beans', titleCn: '绿豆', shortName: 'MU' }, { name: 'nasty-tropic', title: 'nasty tropic', titleCn: '恶搞热带', shortName: 'NA' }, { name: 'nectarine-ice', title: 'nectarine ice', titleCn: '油桃冰', shortName: 'NE' }, { name: 'night-rider', title: 'night rider', titleCn: '夜骑', shortName: 'NI' }, { name: 'nirvana', title: 'nirvana', titleCn: '宁静蓝莓', shortName: 'NI' }, - { name: 'north-american-style(root-beer)', title: 'north american style(root beer)', titleCn: '北美风格(根啤)', shortName: 'NO' }, + { name: 'north-american-style(root-beer)', title: 'north american style(root beer)', titleCn: '北美风格(根啤)', shortName: 'NO' }, { name: 'northern-blue-razz', title: 'northern blue razz', titleCn: '北方蓝覆盆子', shortName: 'NO' }, { name: 'nutty-virginia', title: 'nutty virginia', titleCn: '坚果弗吉尼亚', shortName: 'NU' }, { name: 'orange', title: 'orange', titleCn: '橙子', shortName: 'OR' }, @@ -508,12 +508,12 @@ const flavorsData = [ { name: 'orange-mango-guava', title: 'orange mango guava', titleCn: '橙子芒果番石榴', shortName: 'OR' }, { name: 'orange-mango-pineapple-ice', title: 'orange mango pineapple ice', titleCn: '橙子芒果菠萝冰', shortName: 'OR' }, { name: 'orange-p', title: 'orange p', titleCn: '橙子 P', shortName: 'OR' }, - { name: 'orange-p(fanta)', title: 'orange p(fanta)', titleCn: '橙子 P(芬达)', shortName: 'OR' }, + { name: 'orange-p(fanta)', title: 'orange p(fanta)', titleCn: '橙子 P(芬达)', shortName: 'OR' }, { name: 'orange-spark', title: 'orange spark', titleCn: '橙色火花', shortName: 'OR' }, { name: 'orange-tangerine', title: 'orange tangerine', titleCn: '橙子柑橘', shortName: 'OR' }, { name: 'original', title: 'original', titleCn: '原味', shortName: 'OR' }, { name: 'packin-peach-berry', title: 'packin peach berry', titleCn: '装满桃浆果', shortName: 'PA' }, - { name: 'packin-peach-berry-(popn-peach-berry)', title: 'packin peach berry (popn peach berry)', titleCn: '装满桃浆果(Pop’n 桃浆果)', shortName: 'PA' }, + { name: 'packin-peach-berry-(popn-peach-berry)', title: 'packin peach berry (popn peach berry)', titleCn: '装满桃浆果(Pop’n 桃浆果)', shortName: 'PA' }, { name: 'papio', title: 'papio', titleCn: 'Papio', shortName: 'PA' }, { name: 'paradise', title: 'paradise', titleCn: '天堂', shortName: 'PA' }, { name: 'paradise-iced', title: 'paradise iced', titleCn: '天堂冰', shortName: 'PA' }, @@ -603,7 +603,7 @@ const flavorsData = [ { name: 'red-fruits', title: 'red fruits', titleCn: '红色水果', shortName: 'RE' }, { name: 'red-lightning', title: 'red lightning', titleCn: '红色闪电', shortName: 'RE' }, { name: 'red-line', title: 'red line', titleCn: '红线', shortName: 'RE' }, - { name: 'red-line-(energy-drink)', title: 'red line (energy drink)', titleCn: '红线(能量饮料)', shortName: 'RE' }, + { name: 'red-line-(energy-drink)', title: 'red line (energy drink)', titleCn: '红线(能量饮料)', shortName: 'RE' }, { name: 'red-magic', title: 'red magic', titleCn: '红魔', shortName: 'RE' }, { name: 'rich-tobacco', title: 'rich tobacco', titleCn: '浓烈烟草', shortName: 'RI' }, { name: 'root-beer', title: 'root beer', titleCn: '根啤', shortName: 'RO' }, @@ -625,8 +625,8 @@ const flavorsData = [ { name: 'sic-strawberry-iced', title: 'sic strawberry iced', titleCn: '意大利草莓冰', shortName: 'SI' }, { name: 'simply-spearmint', title: 'simply spearmint', titleCn: '清爽留兰香', shortName: 'SI' }, { name: 'skc', title: 'skc', titleCn: 'SKC', shortName: 'SK' }, - { name: 'skc(skittles-candy)', title: 'skc(skittles candy)', titleCn: 'SKC(彩虹糖)', shortName: 'SK' }, - { name: 'slammin-sts-(sour-snap)', title: 'slammin sts (sour snap)', titleCn: '热烈 STS(酸糖)', shortName: 'SL' }, + { name: 'skc(skittles-candy)', title: 'skc(skittles candy)', titleCn: 'SKC(彩虹糖)', shortName: 'SK' }, + { name: 'slammin-sts-(sour-snap)', title: 'slammin sts (sour snap)', titleCn: '热烈 STS(酸糖)', shortName: 'SL' }, { name: 'slammin-sts-iced', title: 'slammin sts iced', titleCn: '热烈 STS 冰', shortName: 'SL' }, { name: 'smooth', title: 'smooth', titleCn: '顺滑', shortName: 'SM' }, { name: 'smooth-mint', title: 'smooth mint', titleCn: '顺滑薄荷', shortName: 'SM' }, @@ -664,7 +664,7 @@ const flavorsData = [ { name: 'strawberry-jasmine-t', title: 'strawberry jasmine t', titleCn: '草莓茉莉茶', shortName: 'ST' }, { name: 'strawberry-jasmine-tea', title: 'strawberry jasmine tea', titleCn: '草莓茉莉茶', shortName: 'ST' }, { name: 'strawberry-kiwi', title: 'strawberry kiwi', titleCn: '草莓奇异果', shortName: 'ST' }, - { name: 'strawberry-kiwi-(solid)', title: 'strawberry kiwi (solid)', titleCn: '草莓奇异果(固体)', shortName: 'ST' }, + { name: 'strawberry-kiwi-(solid)', title: 'strawberry kiwi (solid)', titleCn: '草莓奇异果(固体)', shortName: 'ST' }, { name: 'strawberry-kiwi-banana-ice', title: 'strawberry kiwi banana ice', titleCn: '草莓奇异果香蕉冰', shortName: 'ST' }, { name: 'strawberry-kiwi-guava-ice', title: 'strawberry kiwi guava ice', titleCn: '草莓奇异果番石榴冰', shortName: 'ST' }, { name: 'strawberry-kiwi-ice', title: 'strawberry kiwi ice', titleCn: '草莓奇异果冰', shortName: 'ST' }, @@ -680,10 +680,10 @@ const flavorsData = [ { name: 'strawberry-watermelon', title: 'strawberry watermelon', titleCn: '草莓西瓜', shortName: 'ST' }, { name: 'strawberry-watermelon-ice', title: 'strawberry watermelon ice', titleCn: '草莓西瓜冰', shortName: 'ST' }, { name: 'strawmelon-peach', title: 'strawmelon peach', titleCn: '草莓桃', shortName: 'ST' }, - { name: 'strawmelon-peach-(solid)', title: 'strawmelon peach (solid)', titleCn: '草莓桃(固体)', shortName: 'ST' }, + { name: 'strawmelon-peach-(solid)', title: 'strawmelon peach (solid)', titleCn: '草莓桃(固体)', shortName: 'ST' }, { name: 'strawnana-orange', title: 'strawnana orange', titleCn: '草莓香蕉橙', shortName: 'ST' }, { name: 'summer-grape', title: 'summer grape', titleCn: '夏日葡萄', shortName: 'SU' }, - { name: 'summer-grape-(thermal)', title: 'summer grape (thermal)', titleCn: '夏日葡萄(热感)', shortName: 'SU' }, + { name: 'summer-grape-(thermal)', title: 'summer grape (thermal)', titleCn: '夏日葡萄(热感)', shortName: 'SU' }, { name: 'super-sour-blueberry-iced', title: 'super sour blueberry iced', titleCn: '超级酸蓝莓冰', shortName: 'SU' }, { name: 'super-spearmint', title: 'super spearmint', titleCn: '超级留兰香', shortName: 'SU' }, { name: 'super-spearmint-iced', title: 'super spearmint iced', titleCn: '超级留兰香冰', shortName: 'SU' }, @@ -704,7 +704,7 @@ const flavorsData = [ { name: 'tropical-orang-ice', title: 'tropical orang ice', titleCn: '热带橙冰', shortName: 'TR' }, { name: 'tropical-prism-blast', title: 'tropical prism blast', titleCn: '热带棱镜爆炸', shortName: 'TR' }, { name: 'tropical-splash', title: 'tropical splash', titleCn: '热带飞溅', shortName: 'TR' }, - { name: 'tropical-splash-(solid)', title: 'tropical splash (solid)', titleCn: '热带飞溅(固体)', shortName: 'TR' }, + { name: 'tropical-splash-(solid)', title: 'tropical splash (solid)', titleCn: '热带飞溅(固体)', shortName: 'TR' }, { name: 'tropical-storm-ice', title: 'tropical storm ice', titleCn: '热带风暴冰', shortName: 'TR' }, { name: 'tropical-summer', title: 'tropical summer', titleCn: '热带夏日', shortName: 'TR' }, { name: 'tropika', title: 'tropika', titleCn: '热带果', shortName: 'TR' }, @@ -728,7 +728,7 @@ const flavorsData = [ { name: 'watermelon-cantaloupe-honeydew-ice', title: 'watermelon cantaloupe honeydew ice', titleCn: '西瓜香瓜蜜瓜冰', shortName: 'WA' }, { name: 'watermelon-g', title: 'watermelon g', titleCn: '西瓜 G', shortName: 'WA' }, { name: 'watermelon-ice', title: 'watermelon ice', titleCn: '西瓜冰', shortName: 'WA' }, - { name: 'watermelon-ice-(solid)', title: 'watermelon ice (solid)', titleCn: '西瓜冰(固体)', shortName: 'WA' }, + { name: 'watermelon-ice-(solid)', title: 'watermelon ice (solid)', titleCn: '西瓜冰(固体)', shortName: 'WA' }, { name: 'watermelon-lime-ice', title: 'watermelon lime ice', titleCn: '西瓜青柠冰', shortName: 'WA' }, { name: 'watermelon-mango-tango', title: 'watermelon mango tango', titleCn: '西瓜芒果探戈', shortName: 'WA' }, { name: 'watermelona-cg', title: 'watermelona cg', titleCn: '西瓜 CG', shortName: 'WA' }, @@ -750,7 +750,7 @@ const flavorsData = [ { name: 'wild-strawberry-watermelon', title: 'wild strawberry watermelon', titleCn: '野生草莓西瓜', shortName: 'WI' }, { name: 'wild-white-grape', title: 'wild white grape', titleCn: '野生白葡萄', shortName: 'WI' }, { name: 'wild-white-grape-ice', title: 'wild white grape ice', titleCn: '野生白葡萄冰', shortName: 'WI' }, - { name: 'wild-white-grape-iced', title: 'wild white grape iced', titleCn: '野生白葡萄冰(冷饮)', shortName: 'WI' }, + { name: 'wild-white-grape-iced', title: 'wild white grape iced', titleCn: '野生白葡萄冰(冷饮)', shortName: 'WI' }, { name: 'winter-berry-ice', title: 'winter berry ice', titleCn: '冬季浆果冰', shortName: 'WI' }, { name: 'winter-green', title: 'winter green', titleCn: '冬青', shortName: 'WI' }, { name: 'wintergreen', title: 'wintergreen', titleCn: '冬青薄荷', shortName: 'WI' }, diff --git a/src/dto/api.dto.ts b/src/dto/api.dto.ts index 1388a4e..6cd4c41 100644 --- a/src/dto/api.dto.ts +++ b/src/dto/api.dto.ts @@ -56,7 +56,7 @@ export class UnifiedSearchParamsDTO> { * 批量操作错误项 */ export interface BatchErrorItem { - // 错误项标识(可以是ID、邮箱等) + // 错误项标识(可以是ID、邮箱等) identifier: string; // 错误信息 error: string; @@ -76,7 +76,7 @@ export interface BatchOperationResult { updated?: number; // 删除数量 deleted?: number; - // 跳过的数量(如数据已存在或无需处理) + // 跳过的数量(如数据已存在或无需处理) skipped?: number; // 错误列表 errors: BatchErrorItem[]; @@ -101,7 +101,7 @@ export class SyncOperationResult implements BatchOperationResult { * 批量操作错误项DTO */ export class BatchErrorItemDTO { - @ApiProperty({ description: '错误项标识(如ID、邮箱等)', type: String }) + @ApiProperty({ description: '错误项标识(如ID、邮箱等)', type: String }) @Rule(RuleType.string().required()) identifier: string; @@ -164,7 +164,7 @@ export class SyncParamsDTO { @Rule(RuleType.string().optional()) endDate?: string; - @ApiProperty({ description: '强制同步(忽略缓存)', type: Boolean, required: false, default: false }) + @ApiProperty({ description: '强制同步(忽略缓存)', type: Boolean, required: false, default: false }) @Rule(RuleType.boolean().optional()) force?: boolean = false; } @@ -183,7 +183,7 @@ export class BatchQueryDTO { } /** - * 批量操作结果类(泛型支持) + * 批量操作结果类(泛型支持) */ export class BatchOperationResultDTOGeneric extends BatchOperationResultDTO { @ApiProperty({ description: '操作成功的数据列表', type: Array }) @@ -191,7 +191,7 @@ export class BatchOperationResultDTOGeneric extends BatchOperationResultDTO { } /** - * 同步操作结果类(泛型支持) + * 同步操作结果类(泛型支持) */ export class SyncOperationResultDTOGeneric extends SyncOperationResultDTO { @ApiProperty({ description: '同步成功的数据列表', type: Array }) diff --git a/src/dto/batch.dto.ts b/src/dto/batch.dto.ts index 67b11cd..4551a3e 100644 --- a/src/dto/batch.dto.ts +++ b/src/dto/batch.dto.ts @@ -5,7 +5,7 @@ import { Rule, RuleType } from '@midwayjs/validate'; * 批量操作错误项 */ export interface BatchErrorItem { - // 错误项标识(可以是ID、邮箱等) + // 错误项标识(可以是ID、邮箱等) identifier: string; // 错误信息 error: string; @@ -25,7 +25,7 @@ export interface BatchOperationResult { updated?: number; // 删除数量 deleted?: number; - // 跳过的数量(如数据已存在或无需处理) + // 跳过的数量(如数据已存在或无需处理) skipped?: number; // 错误列表 errors: BatchErrorItem[]; @@ -43,7 +43,7 @@ export interface SyncOperationResult extends BatchOperationResult { * 批量操作错误项DTO */ export class BatchErrorItemDTO { - @ApiProperty({ description: '错误项标识(如ID、邮箱等)', type: String }) + @ApiProperty({ description: '错误项标识(如ID、邮箱等)', type: String }) @Rule(RuleType.string().required()) identifier: string; @@ -114,7 +114,7 @@ export class BatchDeleteDTO { } /** - * 批量操作请求DTO(包含增删改) + * 批量操作请求DTO(包含增删改) */ export class BatchOperationDTO { @ApiProperty({ description: '要创建的数据列表', type: Array, required: false }) @@ -175,7 +175,7 @@ export class SyncParamsDTO { @Rule(RuleType.string().optional()) endDate?: string; - @ApiProperty({ description: '强制同步(忽略缓存)', type: Boolean, required: false, default: false }) + @ApiProperty({ description: '强制同步(忽略缓存)', type: Boolean, required: false, default: false }) @Rule(RuleType.boolean().optional()) force?: boolean = false; } @@ -194,7 +194,7 @@ export class BatchQueryDTO { } /** - * 批量操作结果类(泛型支持) + * 批量操作结果类(泛型支持) */ export class BatchOperationResultDTOGeneric extends BatchOperationResultDTO { @ApiProperty({ description: '操作成功的数据列表', type: Array }) @@ -202,7 +202,7 @@ export class BatchOperationResultDTOGeneric extends BatchOperationResultDTO { } /** - * 同步操作结果类(泛型支持) + * 同步操作结果类(泛型支持) */ export class SyncOperationResultDTOGeneric extends SyncOperationResultDTO { @ApiProperty({ description: '同步成功的数据列表', type: Array }) diff --git a/src/dto/customer.dto.ts b/src/dto/customer.dto.ts index 99a343d..74e78b8 100644 --- a/src/dto/customer.dto.ts +++ b/src/dto/customer.dto.ts @@ -2,7 +2,7 @@ import { ApiProperty } from '@midwayjs/swagger'; import { UnifiedSearchParamsDTO } from './api.dto'; import { Customer } from '../entity/customer.entity'; -// 客户基本信息DTO(用于响应) +// 客户基本信息DTO(用于响应) export class CustomerDTO extends Customer{ @ApiProperty({ description: '客户ID' }) id: number; @@ -163,11 +163,11 @@ export class UpdateCustomerDTO { tags?: string[]; } -// 查询单个客户响应DTO(继承基本信息) +// 查询单个客户响应DTO(继承基本信息) export class GetCustomerDTO extends CustomerDTO { // 可以添加额外的详细信息字段 } -// 客户统计信息DTO(包含订单统计) +// 客户统计信息DTO(包含订单统计) export class CustomerStatisticDTO extends CustomerDTO { @ApiProperty({ description: '创建日期' }) date_created: Date; @@ -209,7 +209,7 @@ export class CustomerStatisticWhereDTO { customerId?: number; } -// 客户统计查询参数DTO(继承通用查询参数) +// 客户统计查询参数DTO(继承通用查询参数) export type CustomerStatisticQueryParamsDTO = UnifiedSearchParamsDTO; // 客户统计列表响应DTO @@ -259,7 +259,7 @@ export class BatchDeleteCustomerDTO { // ====================== 查询操作 ====================== -// 客户查询条件DTO(用于UnifiedSearchParamsDTO的where参数) +// 客户查询条件DTO(用于UnifiedSearchParamsDTO的where参数) export class CustomerWhereDTO { @ApiProperty({ description: '邮箱筛选', required: false }) email?: string; @@ -284,10 +284,10 @@ export class CustomerWhereDTO { role?: string; } -// 客户查询参数DTO(继承通用查询参数) +// 客户查询参数DTO(继承通用查询参数) export type CustomerQueryParamsDTO = UnifiedSearchParamsDTO; -// 客户列表响应DTO(参考site-api.dto.ts中的分页格式) +// 客户列表响应DTO(参考site-api.dto.ts中的分页格式) export class CustomerListResponseDTO { @ApiProperty({ description: '客户列表', type: [CustomerDTO] }) items: CustomerDTO[]; @@ -359,6 +359,6 @@ export class SyncCustomersDTO { @ApiProperty({ description: '站点ID' }) siteId: number; - @ApiProperty({ description: '查询参数(支持where和orderBy)', type: UnifiedSearchParamsDTO, required: false }) + @ApiProperty({ description: '查询参数(支持where和orderBy)', type: UnifiedSearchParamsDTO, required: false }) params?: UnifiedSearchParamsDTO; } \ No newline at end of file diff --git a/src/dto/shopyy.dto.ts b/src/dto/shopyy.dto.ts index 009d6ce..e775bdd 100644 --- a/src/dto/shopyy.dto.ts +++ b/src/dto/shopyy.dto.ts @@ -22,7 +22,7 @@ export class ShopyyAllProductQuery { id?: string; /** 商品标题,支持模糊查询 */ title?: string; - /** 商品状态,例如:上架、下架、删除等(具体值参考 Shopyy 接口文档) */ + /** 商品状态,例如:上架、下架、删除等(具体值参考 Shopyy 接口文档) */ status?: string; /** 商品SKU编码,库存保有单位,精确或模糊匹配 */ sku?: string; @@ -34,21 +34,21 @@ export class ShopyyAllProductQuery { variant_price_min?: string; /** 变体价格最大值,筛选变体价格小于等于该值的商品 */ variant_price_max?: string; - /** 变体划线价(原价)最小值,筛选变体划线价大于等于该值的商品 */ + /** 变体划线价(原价)最小值,筛选变体划线价大于等于该值的商品 */ variant_compare_at_price_min?: string; - /** 变体划线价(原价)最大值,筛选变体划线价小于等于该值的商品 */ + /** 变体划线价(原价)最大值,筛选变体划线价小于等于该值的商品 */ variant_compare_at_price_max?: string; - /** 变体重量最小值,筛选变体重量大于等于该值的商品(单位参考接口文档) */ + /** 变体重量最小值,筛选变体重量大于等于该值的商品(单位参考接口文档) */ variant_weight_min?: string; - /** 变体重量最大值,筛选变体重量小于等于该值的商品(单位参考接口文档) */ + /** 变体重量最大值,筛选变体重量小于等于该值的商品(单位参考接口文档) */ variant_weight_max?: string; - /** 商品创建时间最小值,格式参考接口文档(如:YYYY-MM-DD HH:mm:ss) */ + /** 商品创建时间最小值,格式参考接口文档(如:YYYY-MM-DD HH:mm:ss) */ created_at_min?: string; - /** 商品创建时间最大值,格式参考接口文档(如:YYYY-MM-DD HH:mm:ss) */ + /** 商品创建时间最大值,格式参考接口文档(如:YYYY-MM-DD HH:mm:ss) */ created_at_max?: string; - /** 商品更新时间最小值,格式参考接口文档(如:YYYY-MM-DD HH:mm:ss) */ + /** 商品更新时间最小值,格式参考接口文档(如:YYYY-MM-DD HH:mm:ss) */ updated_at_min?: string; - /** 商品更新时间最大值,格式参考接口文档(如:YYYY-MM-DD HH:mm:ss) */ + /** 商品更新时间最大值,格式参考接口文档(如:YYYY-MM-DD HH:mm:ss) */ updated_at_max?: string; } // 产品类型 @@ -133,9 +133,9 @@ export interface ShopyyVariant { // // 订单查询参数类型 export interface ShopyyOrderQuery { - // 订单ID集合 多个ID用','联接 例:1,2,3 + // 订单ID集合 多个ID用','联接 例:1,2,3 ids?: string; - // 订单状态 100 未完成;110 待处理;180 已完成(确认收货); 190 取消; + // 订单状态 100 未完成;110 待处理;180 已完成(确认收货); 190 取消; status?: string; // 物流状态 300 未发货;310 部分发货;320 已发货;330(确认收货) fulfillment_status?: string; @@ -159,9 +159,9 @@ export interface ShopyyOrderQuery { page?: string; // 每页条数 limit?: string; - // 排序字段(默认id) id=订单ID updated_at=最后更新时间 pay_at=支付时间 + // 排序字段(默认id) id=订单ID updated_at=最后更新时间 pay_at=支付时间 order_field?: string; - // 排序方式(默认desc) desc=降序 asc=升序 + // 排序方式(默认desc) desc=降序 asc=升序 order_by?: string; // 订单列表类型 group?: string; @@ -513,7 +513,7 @@ export class ShopyyFulfillmentDTO { "tracking_number": string; "courier_code": number; "note": string; - "mode": "replace" | 'cover' | null// 模式 replace(替换) cover (覆盖) 空(新增) + "mode": "replace" | 'cover' | null// 模式 replace(替换) cover (覆盖) 空(新增) } // https://www.apizza.net/project/e114fb8e628e0f604379f5b26f0d8330/browse export class ShopyPartFulfillmentDTO { diff --git a/src/dto/site-api.dto.ts b/src/dto/site-api.dto.ts index faee539..5c8e1d2 100644 --- a/src/dto/site-api.dto.ts +++ b/src/dto/site-api.dto.ts @@ -141,7 +141,7 @@ export class UnifiedProductAttributeDTO { @ApiProperty({ description: '属性选项', type: [String] }) options: string[]; - @ApiProperty({ description: '变体属性值(单个值)', required: false }) + @ApiProperty({ description: '变体属性值(单个值)', required: false }) option?: string; // 这个是属性的父级字典项 dict?: Dict; diff --git a/src/dto/site.dto.ts b/src/dto/site.dto.ts index 27d8bde..7c0267d 100644 --- a/src/dto/site.dto.ts +++ b/src/dto/site.dto.ts @@ -152,7 +152,7 @@ export class QuerySiteDTO { @Rule(RuleType.boolean().optional()) isDisabled?: boolean; - @ApiProperty({ description: '站点ID列表(逗号分隔)', required: false }) + @ApiProperty({ description: '站点ID列表(逗号分隔)', required: false }) @Rule(RuleType.string().optional()) ids?: string; } diff --git a/src/dto/woocommerce.dto.ts b/src/dto/woocommerce.dto.ts index f562d64..5077450 100644 --- a/src/dto/woocommerce.dto.ts +++ b/src/dto/woocommerce.dto.ts @@ -8,11 +8,11 @@ export interface WooProduct { id: number; // 创建时间 date_created: string; - // 创建时间(GMT) + // 创建时间(GMT) date_created_gmt: string; // 更新时间 date_modified: string; - // 更新时间(GMT) + // 更新时间(GMT) date_modified_gmt: string; // 产品类型 simple grouped external variable type: string; @@ -20,7 +20,7 @@ export interface WooProduct { status: string; // 是否为特色产品 featured: boolean; - // 目录可见性选项:visible, catalog, search and hidden. Default is visible. + // 目录可见性选项:visible, catalog, search and hidden. Default is visible. catalog_visibility: string; // 常规价格 @@ -130,11 +130,11 @@ export interface WooVariation { id: number; // 创建时间 date_created: string; - // 创建时间(GMT) + // 创建时间(GMT) date_created_gmt: string; // 更新时间 date_modified: string; - // 更新时间(GMT) + // 更新时间(GMT) date_modified_gmt: string; // 变体描述 description: string; @@ -150,11 +150,11 @@ export interface WooVariation { price_html?: string; // 促销开始日期 date_on_sale_from?: string; - // 促销开始日期(GMT) + // 促销开始日期(GMT) date_on_sale_from_gmt?: string; // 促销结束日期 date_on_sale_to?: string; - // 促销结束日期(GMT) + // 促销结束日期(GMT) date_on_sale_to_gmt?: string; // 是否在促销中 on_sale: boolean; diff --git a/src/enums/base.enum.ts b/src/enums/base.enum.ts index 3b87088..c79c4c9 100644 --- a/src/enums/base.enum.ts +++ b/src/enums/base.enum.ts @@ -42,7 +42,7 @@ export enum OrderStatus { REFUNDED = 'refunded', // 已退款 FAILED = 'failed', // 失败订单 DRAFT = 'draft', // 草稿 - AUTO_DRAFT = 'auto-draft', // 自动草稿(TODO:不知道为什么出现) + AUTO_DRAFT = 'auto-draft', // 自动草稿(TODO:不知道为什么出现) // TRASH = 'trash', // refund 也就是退款相关的状态 diff --git a/src/interface/platform.interface.ts b/src/interface/platform.interface.ts index f1681ed..1fd066e 100644 --- a/src/interface/platform.interface.ts +++ b/src/interface/platform.interface.ts @@ -53,7 +53,7 @@ export interface IPlatformService { getOrder(siteId: number, orderId: string): Promise; /** - * 获取订阅列表(如果平台支持) + * 获取订阅列表(如果平台支持) * @param siteId 站点ID * @returns 订阅列表数据 */ diff --git a/src/service/customer.service.ts b/src/service/customer.service.ts index 02ecb44..47f430f 100644 --- a/src/service/customer.service.ts +++ b/src/service/customer.service.ts @@ -66,7 +66,7 @@ export class CustomerService { } if (typeof dateValue === 'number') { - // 处理Unix时间戳(秒或毫秒) + // 处理Unix时间戳(秒或毫秒) return new Date(dateValue > 9999999999 ? dateValue : dateValue * 1000); } @@ -95,7 +95,7 @@ export class CustomerService { } /** - * 创建或更新客户(upsert) + * 创建或更新客户(upsert) * 如果客户存在则更新,不存在则创建 */ async upsertCustomer( @@ -157,24 +157,24 @@ export class CustomerService { /** * 从站点同步客户数据 - * 第一步:调用adapter获取站点客户数据 - * 第二步:通过upsertManyCustomers保存这些客户 + * 第一步:调用adapter获取站点客户数据 + * 第二步:通过upsertManyCustomers保存这些客户 */ async syncCustomersFromSite( siteId: number, params?: UnifiedSearchParamsDTO ): Promise { try { - // 第一步:获取适配器并从站点获取客户数据 + // 第一步:获取适配器并从站点获取客户数据 const adapter = await this.siteApiService.getAdapter(siteId); const siteCustomers = await adapter.getAllCustomers(params || {}); - // 第二步:将站点客户数据转换为客户实体数据 + // 第二步:将站点客户数据转换为客户实体数据 const customersData = siteCustomers.map(siteCustomer => { return this.mapSiteCustomerToCustomer(siteCustomer, siteId); }) - // 第三步:批量upsert客户数据 + // 第三步:批量upsert客户数据 const upsertResult = await this.upsertManyCustomers(customersData); return { total: siteCustomers.length, @@ -192,7 +192,7 @@ export class CustomerService { } /** - * 获取客户统计列表(包含订单统计信息) + * 获取客户统计列表(包含订单统计信息) * 支持分页、搜索和排序功能 * 使用原生SQL查询实现复杂的统计逻辑 */ @@ -363,7 +363,7 @@ export class CustomerService { } /** - * 获取纯粹的客户列表(不包含订单统计信息) + * 获取纯粹的客户列表(不包含订单统计信息) * 支持基本的分页、搜索和排序功能 * 使用TypeORM查询构建器实现 */ diff --git a/src/service/dict.service.ts b/src/service/dict.service.ts index 2f34a7c..6d683a6 100644 --- a/src/service/dict.service.ts +++ b/src/service/dict.service.ts @@ -239,7 +239,7 @@ export class DictService { } // 更新或创建字典项 (Upsert) - // 如果字典项已存在(根据 name 和 dictId 判断),则更新;否则创建新的 + // 如果字典项已存在(根据 name 和 dictId 判断),则更新;否则创建新的 async upsertDictItem(dictId: number, itemData: { name: string; title: string; @@ -252,7 +252,7 @@ export class DictService { // 格式化 name const formattedName = this.formatName(itemData.name); - // 查找是否已存在该字典项(根据 name 和 dictId) + // 查找是否已存在该字典项(根据 name 和 dictId) const existingItem = await this.dictItemModel.findOne({ where: { name: formattedName, diff --git a/src/service/order.service.ts b/src/service/order.service.ts index 1aa19bd..3dfd68b 100644 --- a/src/service/order.service.ts +++ b/src/service/order.service.ts @@ -479,7 +479,7 @@ export class OrderService { // 如果不能更新 ERP 状态,则保留原有的 orderStatus entity.orderStatus = existingOrder.orderStatus; } - // 更新订单数据(包括 shipping、billing 等字段) + // 更新订单数据(包括 shipping、billing 等字段) await this.orderModel.update(existingOrder.id, entity); entity.id = existingOrder.id; return entity; @@ -2567,8 +2567,8 @@ export class OrderService { * 导出数据为CSV格式 * @param {any[]} data 数据数组 * @param {Object} options 配置选项 - * @param {string} [options.type='string'] 输出类型:'string' | 'buffer' - * @param {string} [options.fileName] 文件名(仅当需要写入文件时使用) + * @param {string} [options.type='string'] 输出类型:'string' | 'buffer' + * @param {string} [options.fileName] 文件名(仅当需要写入文件时使用) * @param {boolean} [options.writeFile=false] 是否写入文件 * @returns {string|Buffer} 根据type返回字符串或Buffer */ @@ -2617,7 +2617,7 @@ async exportToCsv(data: any[], options: { type?: 'string' | 'buffer'; fileName?: // 获取当前用户目录 const userHomeDir = os.homedir(); - // 构建目标路径(下载目录) + // 构建目标路径(下载目录) const downloadsDir = path.join(userHomeDir, 'Downloads'); // 确保下载目录存在 diff --git a/src/service/product.service.ts b/src/service/product.service.ts index 384eca8..d518fca 100644 --- a/src/service/product.service.ts +++ b/src/service/product.service.ts @@ -235,7 +235,7 @@ export class ProductService { .leftJoinAndSelect('product.attributes', 'attribute') .leftJoinAndSelect('attribute.dict', 'dict') .leftJoinAndSelect('product.category', 'category'); - // 处理分页参数(支持新旧两种格式) + // 处理分页参数(支持新旧两种格式) const page = query.page || 1; const pageSize = query.per_page || 10; @@ -393,7 +393,7 @@ export class ProductService { qb.andWhere('product.updatedAt <= :whereUpdatedAtEnd', { whereUpdatedAtEnd: new Date(query.where.updatedAtEnd) }); } - // 品牌过滤(向后兼容) + // 品牌过滤(向后兼容) if (brandId) { qb.andWhere(qb => { const subQuery = qb @@ -423,7 +423,7 @@ export class ProductService { }); } - // 分类过滤(向后兼容) + // 分类过滤(向后兼容) if (categoryId) { qb.andWhere('product.categoryId = :categoryId', { categoryId }); } @@ -443,7 +443,7 @@ export class ProductService { qb.andWhere('product.categoryId IN (:...whereCategoryIds)', { whereCategoryIds: query.where.categoryIds }); } - // 处理排序(支持新旧两种格式) + // 处理排序(支持新旧两种格式) if (orderBy) { if (typeof orderBy === 'string') { // 如果orderBy是字符串,尝试解析JSON @@ -1765,7 +1765,7 @@ export class ProductService { } - // 根据ID获取产品详情(包含站点SKU) + // 根据ID获取产品详情(包含站点SKU) async getProductById(id: number): Promise { const product = await this.productModel.findOne({ where: { id }, diff --git a/src/service/shopyy.service.ts b/src/service/shopyy.service.ts index 0081f55..4a663cb 100644 --- a/src/service/shopyy.service.ts +++ b/src/service/shopyy.service.ts @@ -128,7 +128,7 @@ export class ShopyyService { * @returns 完整URL */ private buildURL(baseUrl: string, endpoint: string): string { - // ShopYY API URL格式:https://{shop}.shopyy.com/openapi/{version}/{endpoint} + // ShopYY API URL格式:https://{shop}.shopyy.com/openapi/{version}/{endpoint} const base = baseUrl.replace(/\/$/, ''); const end = endpoint.replace(/^\//, ''); return `${base}/${end}`; diff --git a/src/service/site-api.service.ts b/src/service/site-api.service.ts index 46d8ee4..22b17e4 100644 --- a/src/service/site-api.service.ts +++ b/src/service/site-api.service.ts @@ -152,7 +152,7 @@ export class SiteApiService { const result = await this.upsertProduct(siteId, product); // 判断是创建还是更新 if (result && result.id) { - // 简单判断:如果产品原本没有ID而现在有了,说明是创建的 + // 简单判断:如果产品原本没有ID而现在有了,说明是创建的 if (!product.id || !product.id.toString().trim()) { results.created.push(result); } else { diff --git a/src/service/wp.service.ts b/src/service/wp.service.ts index 14cf044..a4d66e5 100644 --- a/src/service/wp.service.ts +++ b/src/service/wp.service.ts @@ -254,7 +254,7 @@ export class WPService implements IPlatformService { } - // 导出 WooCommerce 产品为特殊CSV(平台特性) + // 导出 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']; diff --git a/test-site-sku-methods.md b/test-site-sku-methods.md deleted file mode 100644 index 18081a8..0000000 --- a/test-site-sku-methods.md +++ /dev/null @@ -1,105 +0,0 @@ -# 产品站点SKU查询方法测试文档 - -## 新增和更新的API接口 - -### 1. 根据产品ID获取站点SKU列表 -**接口**: `GET /product/:id/site-skus` -**功能**: 获取指定产品的所有站点SKU列表 -**返回**: 站点SKU对象数组,按创建时间升序排列 - -### 2. 根据站点SKU查询产品 -**接口**: `GET /product/site-sku/:siteSku` -**功能**: 根据站点SKU代码查询对应的产品信息 -**返回**: 完整的产品对象(包含站点SKU、分类、属性等关联数据) - -### 3. 根据产品ID获取产品详情 -**接口**: `GET /product/:id` -**功能**: 获取产品的完整详情信息 -**返回**: 完整的产品对象(包含站点SKU、分类、属性、组成等关联数据) - -### 4. 现有接口的增强 - -#### 4.1 根据SKU查询产品 -**接口**: `GET /product/sku/:sku` -**增强**: 现在返回的产品信息包含关联的站点SKU数据 - -#### 4.2 搜索产品 -**接口**: `GET /product/search?name=:name` -**增强**: 搜索结果现在包含每个产品的站点SKU数据 - -#### 4.3 获取产品列表 -**接口**: `GET /product/list` -**增强**: 产品列表中的每个产品现在都包含站点SKU数据 - -## 服务层新增方法 - -### ProductService新增方法 - -1. **getProductSiteSkus(productId: number)**: Promise - - 获取指定产品的所有站点SKU - - 包含产品关联信息 - - 按创建时间排序 - -2. **getProductById(id: number)**: Promise - - 根据产品ID获取完整产品信息 - - 包含站点SKU、分类、属性、组成等所有关联数据 - - 自动处理单品和混装商品的组成信息 - -3. **findProductBySiteSku(siteSku: string)**: Promise - - 根据站点SKU查询对应的产品 - - 返回完整的产品信息 - - 如果站点SKU不存在则抛出错误 - -### 现有方法增强 - -1. **findProductsByName(name: string)**: 现在包含站点SKU数据 -2. **findProductBySku(sku: string)**: 现在包含站点SKU数据 -3. **getProductList**: 已经包含站点SKU数据(无需更改) - -## 使用示例 - -### 获取产品的站点SKU列表 -```javascript -// GET /product/123/site-skus -// 返回: -[ - { - "id": 1, - "siteSku": "SITE-SKU-001", - "productId": 123, - "createdAt": "2024-01-01T00:00:00Z", - "updatedAt": "2024-01-01T00:00:00Z" - } -] -``` - -### 根据站点SKU查询产品 -```javascript -// GET /product/site-sku/SITE-SKU-001 -// 返回完整的产品对象,包含: -// - 基本信息(SKU、名称、价格等) -// - 分类信息 -// - 属性信息 -// - 站点SKU列表 -// - 组成信息 -``` - -### 获取产品详情 -```javascript -// GET /product/123 -// 返回完整的产品对象,与站点SKU查询类似 -``` - -## 数据库查询优化 - -所有新增和更新的方法都使用了TypeORM的关联查询,确保: -- 一次查询获取所有需要的数据 -- 避免N+1查询问题 -- 包含必要的关联关系(分类、属性、站点SKU、组成) - -## 错误处理 - -所有方法都包含适当的错误处理: -- 产品不存在时抛出明确的错误信息 -- 站点SKU不存在时抛出明确的错误信息 -- 控制器层统一处理错误并返回适当的HTTP响应 \ No newline at end of file