调用以下所有接口需在请求头加上 Authorization: Bearer <Token>,请点右上角登录后在「Token 管理」页面创建。

API及SKILL

产品数据 API 接口文档与 Qoder CLI Skill 管理

接口目录

产品管理
货盘管理
供应商管理
导入导出
图片管理

基本信息

Base URL: http://localhost:5000/api
Content-Type: application/json

产品管理接口

GET /api/products 获取所有产品

返回所有主产品列表,包含关联的样品状态信息。支持 ?pallet_id=X 按货盘过滤。服装类产品 (fu_zhuang) 自动嵌入 variants[] 数组。

响应示例
[
  {
    "id": "prod_1",
    "name": "蔚蓝男士淡香水",
    "sku": "LF-zi",
    "sku_wn": "2026_P1",
    "product_no": "#P1",
    "product_type": "xiang_shui",
    "price": "35",
    "sample_status": "existing"
  },
  {
    "id": "prod_570",
    "name": "FOG卫衣",
    "sku": "FOG01",
    "product_type": "fu_zhuang",
    "variants": [
      {"id": "prod_571", "variant_size": "S", "variant_supplier": "供货商A", "price": "120", "sku": "FOG01-S-A"},
      {"id": "prod_572", "variant_size": "L", "variant_supplier": "供货商B", "price": "135", "sku": "FOG01-L-B"}
    ]
  }
]
POST /api/products 新增产品

创建一个新产品,系统自动生成 idproduct_nosku_wn。服装类产品 (fu_zhuang) 可通过 variants 数组同时创建变体。

请求参数
{
  "name": "蔚蓝男士淡香水",       // 必填 - 产品名称
  "sku": "LF-zi",               // 必填 - 原始SKU
  "pallet_id": 1,               // 选填 - 所属货盘ID(默认1)
  "prefix": "P",                // 选填 - 编号前缀(默认P, 服装用F)
  "category": "男士香水",         // 选填 - 分类
  "product_type": "xiang_shui", // 选填 - 产品类型(name_en)
  "price": "35",                // 选填 - 价格
  "stock": "10",                // 选填 - 库存
  "spec": "100ml",              // 选填 - 规格
  "description": "木质调",         // 选填 - 描述
  "warehouse": "SH-01",         // 选填 - 仓库
  "image_path": "/i/abc123def....jpg", // 选填 - NGS 图片路径(需先调 /api/ngs/upload 获取)
  "variants": [                 // 选填 - 服装变体数组
    {"size": "S", "supplier": "供货商A", "price": "120", "stock": "5"},
    {"size": "L", "supplier": "供货商B", "price": "135", "stock": "8"}
  ]
}
成功响应
{
  "success": true,
  "id": "prod_569",
  "product_no": "#P463",
  "sku_wn": "2026_P463",
  "variants_created": 0   // 服装产品时返回变体创建数
}
PUT /api/products/{product_id} 修改产品

更新指定产品的字段,仅传入需要修改的字段即可。

请求参数
// PUT /api/products/prod_1
{
  "name": "新名称",     // 可选 - 产品名称
  "price": "42",       // 可选 - 价格
  "stock": "20",       // 可选 - 库存
  "category": "女士香水" // 可选 - 分类
  // 可更新字段: name, sku, category, product_type,
  //   price, stock, spec, description, warehouse,
  //   image_path, product_no, sku_wn,
  //   parent_id, variant_size, variant_supplier
}
成功响应
{"success": true}
DELETE /api/products/{product_id} 删除产品

删除指定产品(不会删除关联的样品数据)。服装主产品会级联删除所有变体子行。

成功响应
{"success": true}
POST /api/products/{product_id}/variants 追加变体

为已存在的服装主产品追加一个变体。变体继承主产品的 product_type、category、pallet_id 等公共字段。

请求参数
// POST /api/products/prod_570/variants
{
  "size": "XL",           // 必填 - 尺寸
  "supplier": "供货商A",   // 必填 - 供货商
  "price": "125",         // 选填 - 价格
  "stock": "4"            // 选填 - 库存
}
成功响应
{
  "success": true,
  "id": "prod_573",
  "sku": "FOG01-XL-A",
  "sku_wn": "2026_F1-XL"
}
POST /api/clear_data 清空数据

清空指定数据表的所有数据。此操作不可逆!

请求参数
{
  "target": "products",  // 可选值: products, samples, all
  "pallet_id": 1         // 选填 - 指定货盘
}
成功响应
{"success": true, "message": "products 数据已清除"}
GET /api/products/{product_id}/perfume_details 获取香水详情

获取指定产品的香水详细信息,包括品牌、系列、适用性别、前中后调、产品简介和相关链接。如果该产品从未填写过详情,返回所有字段为空字符串的默认值。

响应示例
{
  "product_id": "prod_0",
  "brand": "Raffa",
  "series": "Classic",
  "gender": "男女都适用",
  "note_top": "柑橘 佛手柑",
  "note_middle": "茉莉 玫瑰",
  "note_base": "麝香 琥珀",
  "intro": "经典清新香型",
  "link1_title": "官方",
  "link1_url": "https://example.com",
  "link2_title": "",
  "link2_url": "",
  "updated_at": "2026-05-02 14:40:32"
}
PUT /api/products/{product_id}/perfume_details 更新香水详情

新建或更新指定产品的香水详情(UPSERT)。所有字段均为可选,未传入的字段将保存为空字符串。

请求参数
// PUT /api/products/prod_0/perfume_details
{
  "brand": "Raffa",            // 可选 - 品牌名称
  "series": "Classic",         // 可选 - 系列或型号
  "gender": "男女都适用",        // 可选 - 男性/女性/男女都适用
  "note_top": "柑橘 佛手柑",    // 可选 - 前调
  "note_middle": "茉莉 玫瑰",   // 可选 - 中调
  "note_base": "麝香 琥珀",     // 可选 - 后调
  "intro": "经典清新香型",       // 可选 - 产品简介
  "link1_title": "官方",        // 可选 - 链接1标题
  "link1_url": "https://...",  // 可选 - 链接1 URL
  "link2_title": "",           // 可选 - 链接2标题
  "link2_url": ""              // 可选 - 链接2 URL
}
成功响应 / 错误响应
// 成功
{"success": true}

// 失败 - 产品不存在
{"error": "产品不存在"}  // HTTP 404

货盘管理接口

GET /api/pallets 获取所有货盘

返回所有货盘列表,包含每个货盘下的产品数量。

响应示例
[
  {
    "id": 1,
    "name": "香水",
    "description": "常规业务管理",
    "created_at": "2026-04-29 16:15:59",
    "product_count": 463
  }
]
POST /api/pallets 创建货盘

创建一个新货盘。可选在创建时直接指定编号前缀配置,避免创建后再调用 /sku-config 接口。

请求参数
{
  "name": "新货盘名称",          // 必填 - 货盘名称
  "description": "货盘说明",     // 选填 - 货盘描述
  "product_no_prefix": "#P",    // 选填 - 编号前缀, 1-12 ASCII字符, 如 '#A' / '#M' / 'P'
  "sku_wn_year_prefix": "2026_" // 选填 - SKU_WN年份前缀, 0-16字符; 留空=当年
}
成功响应
{"success": true, "id": 5}
PUT /api/pallets/{pallet_id} 修改货盘

更新指定货盘的名称和描述。

请求参数
// PUT /api/pallets/1
{
  "name": "新名称",          // 必填 - 货盘名称
  "description": "新说明"    // 选填 - 货盘描述
}
成功响应
{"success": true}
DELETE /api/pallets/{pallet_id} 删除货盘

删除指定货盘。货盘下有产品时拒绝删除。

成功响应 / 错误响应
// 成功
{"success": true}

// 失败 - 货盘下有产品
{"error": "该货盘下还有 463 个产品,请先清空产品后再删除"}
PUT /api/pallets/{pallet_id}/default-image 更新货盘默认图

更新货盘的默认图片(通用/男/女/中性)。只更新请求体中出现的字段,不会清空未传入的字段。图片路径需先通过 /api/ngs/upload 上传获取。

请求参数
// PUT /api/pallets/1/default-image
{
  "default_image": "/i/abc123....jpg",        // 选填 - 通用默认图
  "default_image_male": "/i/def456....jpg",    // 选填 - 男性默认图
  "default_image_female": "/i/ghi789....jpg",  // 选填 - 女性默认图
  "default_image_unisex": "/i/jkl012....jpg"   // 选填 - 中性默认图
}
成功响应
{"success": true}
PUT /api/pallets/{pallet_id}/sku-config 更新SKU前缀配置

更新货盘的 product_no 和 sku_wn 前缀配置,同时批量重命名该货盘下所有产品的编号和SKU。仅允许 ASCII 可见字符。

请求参数
// PUT /api/pallets/1/sku-config
{
  "product_no_prefix": "#P",     // 必填 - 编号前缀, 1-12字符, 如 '#P' / 'P' / '001'
  "sku_wn_year_prefix": "2026_"  // 选填 - SKU_WN年份前缀, 0-16字符; 留空=当年
}
成功响应
{
  "success": true,
  "product_no_prefix": "#P",
  "sku_wn_year_prefix": "2026_",
  "updated_product_no": 12,    // 被重命名的 product_no 数量
  "updated_sku_wn": 12,        // 被重命名的 sku_wn 数量
  "updated_sku": 8             // 被重命名的 sku 数量
}

供应商管理接口

GET /api/suppliers 获取所有供应商

返回所有供应商列表,包含每个供应商的产品引用数和关联货盘信息。支持 ?pallet_id=X 过滤为对该货盘可见的供应商(未关联任何货盘的供应商全局可见)。

响应示例
[
  {
    "id": 1,
    "name": "广州香水批发",
    "phone": "13800138000",
    "wechat": "gz_perfume",
    "note": "主营大牌香水",
    "created_at": "2026-05-01 10:00:00",
    "updated_at": "2026-05-01 10:00:00",
    "product_count": 42,           // 引用该供应商的产品数
    "pallet_ids": [1, 3],          // 关联的货盘ID
    "pallet_names": ["香水", "服装"] // 关联的货盘名称(与pallet_ids同序)
  }
]
GET /api/suppliers/{supplier_id} 获取单个供应商

根据 ID 获取单个供应商的详细信息。

成功响应 / 错误响应
// 成功 - 返回完整供应商对象(同列表中的单条)
{"id": 1, "name": "广州香水批发", ...}

// 失败 - 供应商不存在
{"error": "供应商不存在"}  // HTTP 404
POST /api/suppliers 创建供应商

创建一个新供应商。name 不可重复。pallet_ids 控制供应商对哪些货盘可见;为空数组表示全局可见。

注意:导入产品时 Excel 中的「供应商」列按名称匹配,供应商必须已存在才能匹配成功。请先创建供应商再导入产品。

请求参数
{
  "name": "广州香水批发",       // 必填 - 供应商名称(不可重复)
  "phone": "13800138000",     // 选填 - 电话
  "wechat": "gz_perfume",     // 选填 - 微信号
  "note": "主营大牌香水",       // 选填 - 备注
  "pallet_ids": [1, 3]        // 选填 - 关联货盘ID; []=全局可见
}
成功响应 / 错误响应
// 成功 - 返回创建的供应商对象
{"id": 5, "name": "广州香水批发", "phone": "...", ...}

// 失败 - 名称为空
{"error": "供应商名称不能为空"}  // HTTP 400

// 失败 - 名称重复
{"error": "供应商 \"广州香水批发\" 已存在"}  // HTTP 400
PUT /api/suppliers/{supplier_id} 修改供应商

更新指定供应商的信息。pallet_ids 传入时会全量替换原有的关联关系。

请求参数
// PUT /api/suppliers/1
{
  "name": "广州香水批发(新)",   // 必填
  "phone": "13900139000",     // 选填
  "wechat": "gz_perfume_v2",  // 选填
  "note": "已升级",            // 选填
  "pallet_ids": [1]           // 选填 - 全量替换关联
}
成功响应
// 返回更新后的完整供应商对象(含 product_count, pallet_ids, pallet_names)
{"id": 1, "name": "广州香水批发(新)", "product_count": 42, ...}
DELETE /api/suppliers/{supplier_id} 删除供应商

删除指定供应商。如有产品引用该供应商,默认拒绝删除;加 ?force=1 可强制删除(产品的 supplier_id 会被置为 NULL)。

请求示例 / 响应
// 普通删除(有产品引用时失败)
DELETE /api/suppliers/1
// 失败:
{"error": "该供应商已被 42 个商品引用,无法直接删除", "product_count": 42}

// 强制删除(产品引用被解除)
DELETE /api/suppliers/1?force=1
// 成功:
{"success": true, "unlinked_products": 42}

导入导出接口

POST /api/upload_products Excel导入产品

通过 Excel 文件批量导入产品到指定货盘。按 SKU 匹配:已有产品则更新(仅更新非空字段),不存在则新建。

注意事项:

  • 供应商必须先创建:Excel 中「供应商」列按名称匹配,不存在的供应商会导致该行被跳过并报错
  • 产品分类必须是字典值:「产品分类」列使用中文名(如"香水"、"服装"),必须在系统字典 chan_pin_fen_lei 中已配置
  • SKU 必填:每行必须有 SKU,空 SKU 的行会被跳过
  • 新建需产品名称:新增产品时「产品名称」必填,否则跳过
  • 图片路径格式:「图片路径」列填 /i/sha256.ext(通过 /api/ngs/upload 上传获取)或 http(s):// URL
请求格式
Content-Type: multipart/form-data

file:       产品Excel文件 (.xlsx / .xls)  — 必填
pallet_id:  目标货盘ID (默认=1)           — 选填
Excel 列说明
┌─────────────┬────────┬──────────────────────────────────────────────┐
│ 列名         │ 必填   │ 说明                                          │
├─────────────┼────────┼──────────────────────────────────────────────┤
│ SKU          │ ✅ 必填 │ 每行唯一标识,用于匹配已有产品                    │
│ 编号          │ 选填   │ product_no, 如不填系统自动生成                   │
│ SKU_WN       │ 选填   │ 内部SKU, 如不填系统自动生成                      │
│ 产品名称       │ 新建必填│ 新增产品时必须填写                                │
│ 产品分类       │ 选填   │ 中文分类名, 如"香水""服装", 需在字典中已配置       │
│ 价格          │ 选填   │                                              │
│ 库存          │ 选填   │                                              │
│ 规格          │ 选填   │                                              │
│ 描述          │ 选填   │                                              │
│ 仓库地址       │ 选填   │                                              │
│ 图片路径       │ 选填   │ /i/sha.ext 或 http(s)://URL                   │
│ 市场价USD     │ 选填   │ 数值                                          │
│ 市场参考链接    │ 选填   │                                              │
│ 建议售价USD    │ 选填   │ 数值                                          │
│ 供应商         │ 选填   │ 供应商名称(需已存在于系统)                       │
├─────────────┼────────┼──────────────────────────────────────────────┤
│ 以下为香水专属  │       │ product_type 以 xiang_shui 开头时生效            │
├─────────────┼────────┼──────────────────────────────────────────────┤
│ 品牌          │ 选填   │                                              │
│ 系列          │ 选填   │                                              │
│ 性别          │ 选填   │                                              │
│ 前调          │ 选填   │                                              │
│ 中调          │ 选填   │                                              │
│ 后调          │ 选填   │                                              │
│ 介绍          │ 选填   │                                              │
│ 推荐链接1标题   │ 选填   │                                              │
│ 推荐链接1      │ 选填   │                                              │
│ 推荐链接2标题   │ 选填   │                                              │
│ 推荐链接2      │ 选填   │                                              │
└─────────────┴────────┴──────────────────────────────────────────────┘
成功响应
{
  "success": true,
  "inserted": 15,       // 新创建的产品数
  "updated": 8,         // 更新的已有产品数
  "skipped": 2,         // 跳过的行数(SKU为空/供应商不存在/分类未知等)
  "errors": [           // 最多返回20条错误信息
    "第 5 行:未知供应商\"不存在的供应商\"(请先在系统字典中创建)",
    "第 12 行:未知产品分类\"错误分类\""
  ]
}
GET /api/export_products 导出产品Excel

将产品导出为 Excel 文件,列格式与导入模板一致,可直接修改后重新导入。支持 GET 和 POST 两种方式调用。

请求参数
// GET 方式
GET /api/export_products?pallet_id=1

// POST 方式(可指定导出特定产品)
POST /api/export_products
{
  "pallet_id": 1,        // 选填 - 按货盘过滤
  "ids": [101, 102, 103] // 选填 - 仅导出这些产品ID
}
响应
// 返回 Excel 文件下载
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Content-Disposition: attachment; filename="货盘清单_20260602_143025.xlsx"

// Excel 包含所有列: 编号, SKU, SKU_WN, 产品名称, 产品分类,
//   价格, 库存, 规格, 描述, 仓库地址, 图片路径,
//   市场价USD, 市场参考链接, 建议售价USD, 供应商,
//   品牌, 系列, 性别, 前调, 中调, 后调, 介绍,
//   推荐链接1标题, 推荐链接1, 推荐链接2标题, 推荐链接2

图片管理接口

POST /api/ngs/upload 上传图片

上传图片文件到服务器,返回稳定的图片路径 /i/<sha256>.<ext>。该路径可用于产品 image_path 字段和货盘默认图字段。系统按 SHA256 去重,相同文件不会重复存储。

请求格式
Content-Type: multipart/form-data

file:  图片文件 — 必填
       支持格式: jpg, jpeg, png, gif, webp
成功响应 / 错误响应
// 成功
{
  "success": true,
  "image_path": "/i/a1b2c3d4e5f6...abc.jpg"
}
// → 将 image_path 填入产品创建/更新请求, 或 Excel 的「图片路径」列

// 失败 - 缺少文件
{"error": "缺少文件"}  // HTTP 400

推荐调用流程

批量导入产品(含图片)的标准流程:

1
POST /api/suppliers

创建供应商(导入时按名称匹配,必须先创建)

2
POST /api/pallets

创建货盘,获取 pallet_id

3
POST /api/ngs/upload

上传产品图片,获取 image_path(每张图一次)

4
POST /api/upload_products

导入 Excel(pallet_id + Excel 文件),「图片路径」列填步骤3返回的 image_path

加载中...

v2026.06.21.009