@round2ai/r2-cli 1.0.13 → 1.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -6
- package/dist/README.md +11 -6
- package/dist/r2-cli.js +30 -29
- package/package.json +3 -2
- package/skills/r2-auth/SKILL.md +18 -12
- package/skills/r2-goods/SKILL.md +19 -4
- package/skills/r2-goods/references/r2-goods-hangup.md +44 -10
- package/skills/r2-goods/references/r2-goods-listing.md +32 -2
- package/skills/r2-goods/references/r2-goods-query.md +3 -2
- package/skills/r2-shared/SKILL.md +2 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
R2-CLI — 二手潮奢交易命令行工具,由 [Round2AI](https://github.com/Round2AI) 团队维护 — 让人类和 AI Agent 都能在终端中完成商品上架等交易操作。
|
|
7
7
|
|
|
8
|
-
覆盖商品上架、挂售、商品信息修改、认证登录等核心业务域,提供
|
|
8
|
+
覆盖商品上架、挂售、商品信息修改、认证登录等核心业务域,提供 19 个命令及 3 个 AI Agent [Skills](./skills/)。
|
|
9
9
|
|
|
10
10
|
[安装](#安装与快速开始) · [AI Agent 快速开始](#快速开始ai-agent) · [Agent Skills](#agent-skills) · [认证](#认证) · [命令](#命令参考) · [安全](#安全与风险提示)
|
|
11
11
|
|
|
@@ -22,7 +22,7 @@ R2-CLI — 二手潮奢交易命令行工具,由 [Round2AI](https://github.com
|
|
|
22
22
|
|------|------|
|
|
23
23
|
| 认证登录 | 扫码登录(第二回合 APP / 微信 / 支付宝)、闲鱼店铺授权、状态查询、登出(Agent 一步式流程) |
|
|
24
24
|
| 商品管理 | 商品上架(4 步流程:获取店铺 → 获取仓库 → 获取选品商品 → 提交上架 + 自动轮询上架结果)、商品信息修改(AI 读图识别 → 自动匹配类目/属性 → 提交修改)、店铺查看、仓库查看、选品商品查看、上架列表查询、下架、改价 |
|
|
25
|
-
| 闲鱼挂售 |
|
|
25
|
+
| 闲鱼挂售 | 图片上传(自动压缩大图、并行上传、失败重试)→ AI 读图识别商品信息 → 自动匹配类目/属性 → 提交挂售 |
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
@@ -146,8 +146,8 @@ Token 存储在 `~/.r2-cli/config.json`(原子写入防丢失),过期后
|
|
|
146
146
|
|------|------|
|
|
147
147
|
| `r2-cli goods shops [--json]` | 查看所有已授权店铺(跨平台) |
|
|
148
148
|
| `r2-cli goods stocks [--json]` | 查看所有仓库 |
|
|
149
|
-
| `r2-cli goods list [--stock-id <id>] [--stock-goods-id <id>] [--json]` | 查看选品商品(可按仓库或商品 ID 过滤,支持 `--page` 和 `--size
|
|
150
|
-
| `r2-cli goods listing [--json]` | 查询上架列表(支持 `--id` / `--shop-id` / `--stock-goods-id` / `--stock-id` / `--status
|
|
149
|
+
| `r2-cli goods list [--stock-id <id>] [--stock-goods-id <id>] [--json]` | 查看选品商品(可按仓库或商品 ID 过滤,支持 `--page` 和 `--size`,最大 50) |
|
|
150
|
+
| `r2-cli goods listing [--json]` | 查询上架列表(支持 `--id` / `--shop-id` / `--stock-goods-id` / `--stock-id` / `--status <init|up|down|fail|sold>` / `--platform` 过滤,支持 `--page` / `--size` 分页) |
|
|
151
151
|
|
|
152
152
|
### 商品上架/下架/改价
|
|
153
153
|
|
|
@@ -169,7 +169,12 @@ Token 存储在 `~/.r2-cli/config.json`(原子写入防丢失),过期后
|
|
|
169
169
|
|
|
170
170
|
**定位商品**:优先使用 `--id <goodsListingId>`(从上架列表 `id` 字段获取),也可用 `--stock-goods-id <id> --account <shopId>`。**必填参数**:定位参数(二选一)+ `--category-id` + `--channel-cat-id`(后端必填)
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
**关键约束**:
|
|
173
|
+
- **类目 ID 必须传**:即使不改类目也要传 `--category-id` 和 `--channel-cat-id`,后端复用挂售 DTO,缺少会报 `getCategoryId() is null`
|
|
174
|
+
- **`--item-attrs` 必须包含所有属性**:后端替换整个属性列表,漏传的属性会被清除。从 `goods hang-up props --channel-cat-id <id> --json` 获取全部属性后,修改目标值,其他保持原样一并传入
|
|
175
|
+
- **品牌必须双传**:`--brand-name`(文本字段)+ itemAttrs 中的品牌项(含 propId/valueId/valueName/propName/channelCatId 五个字段),缺一不可
|
|
176
|
+
|
|
177
|
+
**可选参数**:`--title`、`--desc`、`--image-ids`(需先通过 `hang-up upload-images` 上传)、`--item-attrs`(JSON,5 字段格式)、`--brand-name`、`--stuff-status`、`--goods-no`、`--original-price`、`--size`
|
|
173
178
|
|
|
174
179
|
### 闲鱼挂售(完整商品信息模式)
|
|
175
180
|
|
|
@@ -204,7 +209,7 @@ Token 存储在 `~/.r2-cli/config.json`(原子写入防丢失),过期后
|
|
|
204
209
|
|
|
205
210
|
建议:
|
|
206
211
|
- Agent 收到"上架"指令时,若用户未明确指定方式(选品上架/挂售上架),**必须询问用户**选择哪种上架方式
|
|
207
|
-
- Agent
|
|
212
|
+
- Agent 自动识别图片并填充商品信息,售价必问用户;商家编码优先让用户自定义,不填则自动生成推荐
|
|
208
213
|
- Token 存储在本地 `~/.r2-cli/config.json`(原子写入,防止中断导致配置丢失),注意保护
|
|
209
214
|
|
|
210
215
|
---
|
package/dist/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
R2-CLI — 二手潮奢交易命令行工具,由 [Round2AI](https://github.com/Round2AI) 团队维护 — 让人类和 AI Agent 都能在终端中完成商品上架等交易操作。
|
|
7
7
|
|
|
8
|
-
覆盖商品上架、挂售、商品信息修改、认证登录等核心业务域,提供
|
|
8
|
+
覆盖商品上架、挂售、商品信息修改、认证登录等核心业务域,提供 19 个命令及 3 个 AI Agent [Skills](./skills/)。
|
|
9
9
|
|
|
10
10
|
[安装](#安装与快速开始) · [AI Agent 快速开始](#快速开始ai-agent) · [Agent Skills](#agent-skills) · [认证](#认证) · [命令](#命令参考) · [安全](#安全与风险提示)
|
|
11
11
|
|
|
@@ -22,7 +22,7 @@ R2-CLI — 二手潮奢交易命令行工具,由 [Round2AI](https://github.com
|
|
|
22
22
|
|------|------|
|
|
23
23
|
| 认证登录 | 扫码登录(第二回合 APP / 微信 / 支付宝)、闲鱼店铺授权、状态查询、登出(Agent 一步式流程) |
|
|
24
24
|
| 商品管理 | 商品上架(4 步流程:获取店铺 → 获取仓库 → 获取选品商品 → 提交上架 + 自动轮询上架结果)、商品信息修改(AI 读图识别 → 自动匹配类目/属性 → 提交修改)、店铺查看、仓库查看、选品商品查看、上架列表查询、下架、改价 |
|
|
25
|
-
| 闲鱼挂售 |
|
|
25
|
+
| 闲鱼挂售 | 图片上传(自动压缩大图、并行上传、失败重试)→ AI 读图识别商品信息 → 自动匹配类目/属性 → 提交挂售 |
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
@@ -146,8 +146,8 @@ Token 存储在 `~/.r2-cli/config.json`(原子写入防丢失),过期后
|
|
|
146
146
|
|------|------|
|
|
147
147
|
| `r2-cli goods shops [--json]` | 查看所有已授权店铺(跨平台) |
|
|
148
148
|
| `r2-cli goods stocks [--json]` | 查看所有仓库 |
|
|
149
|
-
| `r2-cli goods list [--stock-id <id>] [--stock-goods-id <id>] [--json]` | 查看选品商品(可按仓库或商品 ID 过滤,支持 `--page` 和 `--size
|
|
150
|
-
| `r2-cli goods listing [--json]` | 查询上架列表(支持 `--id` / `--shop-id` / `--stock-goods-id` / `--stock-id` / `--status
|
|
149
|
+
| `r2-cli goods list [--stock-id <id>] [--stock-goods-id <id>] [--json]` | 查看选品商品(可按仓库或商品 ID 过滤,支持 `--page` 和 `--size`,最大 50) |
|
|
150
|
+
| `r2-cli goods listing [--json]` | 查询上架列表(支持 `--id` / `--shop-id` / `--stock-goods-id` / `--stock-id` / `--status <init|up|down|fail|sold>` / `--platform` 过滤,支持 `--page` / `--size` 分页) |
|
|
151
151
|
|
|
152
152
|
### 商品上架/下架/改价
|
|
153
153
|
|
|
@@ -169,7 +169,12 @@ Token 存储在 `~/.r2-cli/config.json`(原子写入防丢失),过期后
|
|
|
169
169
|
|
|
170
170
|
**定位商品**:优先使用 `--id <goodsListingId>`(从上架列表 `id` 字段获取),也可用 `--stock-goods-id <id> --account <shopId>`。**必填参数**:定位参数(二选一)+ `--category-id` + `--channel-cat-id`(后端必填)
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
**关键约束**:
|
|
173
|
+
- **类目 ID 必须传**:即使不改类目也要传 `--category-id` 和 `--channel-cat-id`,后端复用挂售 DTO,缺少会报 `getCategoryId() is null`
|
|
174
|
+
- **`--item-attrs` 必须包含所有属性**:后端替换整个属性列表,漏传的属性会被清除。从 `goods hang-up props --channel-cat-id <id> --json` 获取全部属性后,修改目标值,其他保持原样一并传入
|
|
175
|
+
- **品牌必须双传**:`--brand-name`(文本字段)+ itemAttrs 中的品牌项(含 propId/valueId/valueName/propName/channelCatId 五个字段),缺一不可
|
|
176
|
+
|
|
177
|
+
**可选参数**:`--title`、`--desc`、`--image-ids`(需先通过 `hang-up upload-images` 上传)、`--item-attrs`(JSON,5 字段格式)、`--brand-name`、`--stuff-status`、`--goods-no`、`--original-price`、`--size`
|
|
173
178
|
|
|
174
179
|
### 闲鱼挂售(完整商品信息模式)
|
|
175
180
|
|
|
@@ -204,7 +209,7 @@ Token 存储在 `~/.r2-cli/config.json`(原子写入防丢失),过期后
|
|
|
204
209
|
|
|
205
210
|
建议:
|
|
206
211
|
- Agent 收到"上架"指令时,若用户未明确指定方式(选品上架/挂售上架),**必须询问用户**选择哪种上架方式
|
|
207
|
-
- Agent
|
|
212
|
+
- Agent 自动识别图片并填充商品信息,售价必问用户;商家编码优先让用户自定义,不填则自动生成推荐
|
|
208
213
|
- Token 存储在本地 `~/.r2-cli/config.json`(原子写入,防止中断导致配置丢失),注意保护
|
|
209
214
|
|
|
210
215
|
---
|
package/dist/r2-cli.js
CHANGED
|
@@ -1,49 +1,50 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
`;process.stdout.write(a)}finally{$t.level=t}}function Bt(o,t){
|
|
3
|
+
var ge=Object.defineProperty;var ct=(o,t)=>()=>(o&&(t=o(o=0)),t);var lt=(o,t)=>{for(var e in t)ge(o,e,{get:t[e],enumerable:!0})};var fo={};lt(fo,{UserInfoCard:()=>Ne});import{Box as K,Text as G}from"ink";import{jsx as J,jsxs as Y}from"react/jsx-runtime";function Ne({userInfo:o,lastLogin:t,daysSinceLogin:e}){let r=o.mobile?o.mobile.replace(/(\d{3})\d{4}(\d{4})/,"$1****$2"):"-";return Y(K,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[J(G,{bold:!0,color:"cyan",children:"\u7528\u6237\u4FE1\u606F"}),Y(K,{flexDirection:"row",marginTop:1,children:[J(K,{width:10,children:J(G,{color:"gray",children:"\u6635\u79F0"})}),J(G,{color:"yellow",children:o.nickname})]}),Y(K,{flexDirection:"row",children:[J(K,{width:10,children:J(G,{color:"gray",children:"\u624B\u673A\u53F7"})}),J(G,{color:"yellow",children:r})]}),t&&Y(K,{flexDirection:"column",marginTop:1,children:[Y(G,{color:"gray",children:["\u6700\u540E\u767B\u5F55: ",t.toLocaleString()]}),e!==void 0&&Y(G,{color:"gray",children:[" \u8DDD\u4ECA: ",e," \u5929"]})]})]})}var ho=ct(()=>{"use strict"});var ft={};lt(ft,{renderComponent:()=>Bt,renderOnce:()=>yo});import De from"react";import $t from"chalk";import{render as Oe}from"ink";import{Writable as Ue}from"node:stream";function yo(o){let t=$t.level;process.env.NO_COLOR||($t.level=3);try{let e=[],r=new Ue({write(c,h,u){e.push(Buffer.from(c)),u()}});r.isTTY=!0,r.columns=process.stdout.columns||80,r.rows=process.stdout.rows||24,Oe(o,{stdout:r,patchConsole:!1}).unmount();let s=Buffer.concat(e).toString("utf8"),a=(s.split(/\x1B\[2J\x1B\[3J\x1B\[H/).at(-1)||s).replace(/\x1B\[\?[\d;]+[hl]/g,"").trimEnd()+`
|
|
4
|
+
`;process.stdout.write(a)}finally{$t.level=t}}function Bt(o,t){yo(De.createElement(o,t))}var st=ct(()=>{"use strict"});var Go={};lt(Go,{ShopsTable:()=>Ye});import{Box as A,Text as R}from"ink";import{jsx as f,jsxs as Z}from"react/jsx-runtime";function He(o){return o.map(t=>"shopName"in t?{id:t.shopId,name:t.shopName,platform:t.platform,expiresIn:t.expiresIn}:{id:t.id,name:t.name,platform:t.thirdUserId,expiresIn:t.expiresIn})}function Ve({hasPlatform:o,fillWidth:t}){return Z(A,{flexDirection:"row",paddingBottom:0,children:[o&&f(A,{width:Wt,children:f(R,{bold:!0,color:"white",children:"\u5E73\u53F0"})}),f(A,{width:t,children:f(R,{bold:!0,color:"white",children:"\u5E97\u94FA\u540D"})}),f(A,{width:Ht,children:f(R,{bold:!0,color:"white",children:"ID"})}),f(A,{width:Vt,children:f(R,{bold:!0,color:"white",children:"\u72B6\u6001"})})]})}function Ke({shop:o,hasPlatform:t,fillWidth:e}){let r=qo[o.platform]??o.platform;return Z(A,{flexDirection:"row",children:[t&&f(A,{width:Wt,children:f(R,{color:"cyan",children:r})}),f(A,{width:e,children:f(R,{bold:!0,children:o.name})}),f(A,{width:Ht,children:f(R,{color:"gray",children:o.id})}),f(A,{width:Vt,children:f(R,{color:"green",children:"\u25CF \u6388\u6743\u4E2D"})})]})}function Ye({shops:o,platform:t}){let e=He(o),r=t==="all",n=t==="all"?"\u6240\u6709\u6388\u6743\u5E97\u94FA":`${qo[t]??t}\u6388\u6743\u5E97\u94FA`,s=process.stdout.columns||80,i=4,a=Ht+Vt+(r?Wt:0),c=Math.max(s-i-a,20),h=a+c;return Z(A,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[Z(A,{flexDirection:"row",children:[f(R,{bold:!0,color:"cyan",children:n}),Z(R,{color:"gray",children:[" \xB7 ",e.length," \u5BB6"]})]}),Z(A,{flexDirection:"column",marginTop:1,children:[f(Ve,{hasPlatform:r,fillWidth:c}),f(R,{color:"gray",children:"\u2500".repeat(h)}),e.map(u=>f(Ke,{shop:u,hasPlatform:r,fillWidth:c},u.id))]})]})}var qo,Wt,Ht,Vt,Jo=ct(()=>{"use strict";qo={xianyu:"\u95F2\u9C7C",douyin:"\u6296\u97F3"},Wt=8,Ht=16,Vt=10});var _o={};lt(_o,{StocksTable:()=>er});import{Box as I,Text as v}from"ink";import{jsx as g,jsxs as tt}from"react/jsx-runtime";function tr({fillWidth:o}){return tt(I,{flexDirection:"row",paddingBottom:0,children:[g(I,{width:Kt,children:g(v,{bold:!0,color:"white",children:"ID"})}),g(I,{width:Yt,children:g(v,{bold:!0,color:"white",children:"\u7528\u6237ID"})}),g(I,{width:Zt,children:g(v,{bold:!0,color:"white",children:"\u4ED3\u5E93ID"})}),g(I,{width:o,children:g(v,{bold:!0,color:"white",children:"\u4ED3\u5E93\u540D\u79F0"})}),g(I,{width:to,children:g(v,{bold:!0,color:"white",children:"\u521B\u5EFA\u65F6\u95F4"})})]})}function or({stock:o,fillWidth:t}){let e=new Date(o.gmtCreate).toLocaleString("zh-CN");return tt(I,{flexDirection:"row",children:[g(I,{width:Kt,children:g(v,{color:"gray",children:o.id})}),g(I,{width:Yt,children:g(v,{color:"gray",children:o.userId})}),g(I,{width:Zt,children:g(v,{color:"gray",children:o.stockId})}),g(I,{width:t,children:g(v,{bold:!0,children:o.stockName})}),g(I,{width:to,children:g(v,{color:"gray",children:e})})]})}function er({stocks:o}){let t=process.stdout.columns||80,e=4,r=Kt+Yt+Zt+to,n=Math.max(t-e-r,20),s=r+n;return tt(I,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[tt(I,{flexDirection:"row",children:[g(v,{bold:!0,color:"cyan",children:"\u4ED3\u5E93\u5217\u8868"}),tt(v,{color:"gray",children:[" \xB7 ",o.length," \u4E2A"]})]}),tt(I,{flexDirection:"column",marginTop:1,children:[g(tr,{fillWidth:n}),g(v,{color:"gray",children:"\u2500".repeat(s)}),o.map(i=>g(or,{stock:i,fillWidth:n},i.id))]})]})}var Kt,Yt,Zt,to,Mo=ct(()=>{"use strict";Kt=6,Yt=10,Zt=10,to=22});import{Command as $r}from"commander";import rt from"chalk";import"commander";import{Command as To}from"commander";import x from"chalk";var F=class o extends Error{constructor(e,r,n){super(e);this.code=r;this.details=n;this.name="R2Error",Error.captureStackTrace&&Error.captureStackTrace(this,o)}code;details},b=class extends F{constructor(e,r,n){super(e,"API_ERROR",n);this.status=r;this.response=n;this.name="ApiError"}status;response},B=class extends F{constructor(e,r,n){super(e,"STORAGE_ERROR",{path:r,code:n});this.path=r;this.code=n;this.name="StorageError"}path;code},C=class extends F{constructor(t){super(t,"AUTH_ERROR"),this.name="AuthError"}},E=class extends F{constructor(e,r,n){super(e,"POLLING_ERROR",{attempts:r,timeout:n});this.attempts=r;this.timeout=n;this.name="PollingError"}attempts;timeout};async function pe(o,t,e){let r=new AbortController,n=()=>r.abort();e?.addEventListener("abort",n,{once:!0});let s=setTimeout(()=>r.abort(),t);try{return await o()}catch(i){throw r.signal.aborted&&!e?.aborted?new E("\u5355\u6B21\u8F6E\u8BE2\u8BF7\u6C42\u8D85\u65F6"):i}finally{clearTimeout(s),e?.removeEventListener("abort",n)}}async function W(o,t,e){let{interval:r,timeout:n,condition:s}=t,i=Date.now(),a=0;for(;Date.now()-i<n;){if(e?.aborted)throw new E("\u8F6E\u8BE2\u88AB\u4E2D\u6B62");a++;let c=n-(Date.now()-i),h=await pe(o,c,e);if(s(h,a))return h;await fe(r,e)}throw new E(`\u8F6E\u8BE2\u8D85\u65F6 (\u5DF2\u7B49\u5F85 ${Date.now()-i}ms, \u5171 ${a} \u6B21)`)}function fe(o,t){return new Promise((e,r)=>{if(t?.aborted){r(new E("\u8F6E\u8BE2\u88AB\u4E2D\u6B62"));return}let n=()=>{clearTimeout(s),r(new E("\u8F6E\u8BE2\u88AB\u4E2D\u6B62"))},s=setTimeout(()=>{t?.removeEventListener("abort",n),e()},o);t?.addEventListener("abort",n,{once:!0})})}import we from"node:fs";import{fileURLToPath as xe}from"node:url";import{createRequire as Ie}from"node:module";import co from"node:path";import{exec as Se}from"node:child_process";import he from"node:http";var kt=class o{server=null;pages=new Map;port=0;idleTimer=null;static IDLE_TIMEOUT_MS=1e4;async start(){return this.server?this.port:new Promise((t,e)=>{this.server=he.createServer((r,n)=>this.handleRequest(r,n)),this.server.listen(0,"127.0.0.1",()=>{let r=this.server.address();typeof r=="object"&&r?(this.port=r.port,t(this.port)):e(new Error("Failed to get server address"))}),this.server.on("error",e)})}registerPage(t,e,r,n){let s=this.pages.get(t);if(s){s.qrBuffer=r,s.status="waiting",s.config=n;let i=`data: ${JSON.stringify({status:"waiting"})}
|
|
5
5
|
|
|
6
6
|
`;for(let a of s.sseClients)a.write(i)}else this.pages.set(t,{html:e,qrBuffer:r,status:"waiting",sseClients:[],config:n});this.resetIdleTimer()}unregisterPage(t){let e=this.pages.get(t);if(e){for(let r of e.sseClients)r.end();e.sseClients.length=0,this.pages.delete(t),this.pages.size===0&&this.close()}}setStatus(t,e){let r=this.pages.get(t);if(!r)return;r.status=e;let n=`data: ${JSON.stringify({status:e})}
|
|
7
7
|
|
|
8
|
-
`;for(let s of r.sseClients)s.write(n)}close(){if(this.server){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null);for(let t of this.pages.values()){for(let e of t.sseClients)e.end();t.sseClients.length=0}this.pages.clear(),this.server.close(),this.server=null,this.port=0,
|
|
8
|
+
`;for(let s of r.sseClients)s.write(n)}close(){if(this.server){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null);for(let t of this.pages.values()){for(let e of t.sseClients)e.end();t.sseClients.length=0}this.pages.clear(),this.server.close(),this.server=null,this.port=0,H=null}}resetIdleTimer(){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>{[...this.pages.values()].some(e=>e.sseClients.length>0)||this.close()},o.IDLE_TIMEOUT_MS)}handleRequest(t,e){let r=t.url??"/";for(let[n,s]of this.pages){if(r===n){e.writeHead(302,{Location:n+"/"}),e.end();return}if(r===n+"/"){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(s.html);return}if(r===n+"/qr.png"){e.writeHead(200,{"Content-Type":"image/png","Content-Length":s.qrBuffer.length}),e.end(s.qrBuffer);return}if(r===n+"/events"){e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),e.write(`data: ${JSON.stringify({status:s.status})}
|
|
9
9
|
|
|
10
|
-
`),s.sseClients.push(e),t.on("close",()=>{let i=s.sseClients.indexOf(e);i>=0&&s.sseClients.splice(i,1)});return}if(r===n+"/config"){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(s.config??{}));return}}e.writeHead(404,{"Content-Type":"text/plain"}),e.end("Not Found")}},
|
|
11
|
-
\u{1F50D} \u5DF2\u626B\u7801: ${
|
|
10
|
+
`),s.sseClients.push(e),t.on("close",()=>{let i=s.sseClients.indexOf(e);i>=0&&s.sseClients.splice(i,1)});return}if(r===n+"/config"){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(s.config??{}));return}}e.writeHead(404,{"Content-Type":"text/plain"}),e.end("Not Found")}},H=null,io=!1;function dt(){H&&H.close()}function ye(){io||(io=!0,process.on("exit",dt),process.on("SIGINT",dt),process.on("SIGTERM",dt),setInterval(()=>{process.stdin?.destroyed&&dt()},3e3).unref())}function ao(){return H||(H=new kt,ye()),H}var Ce=co.dirname(xe(import.meta.url)),Te="/login",be="/login-xianyu",Rt=null;async function Pe(o){return we.promises.readFile(co.join(Ce,"pages",o),"utf-8")}async function Ae(o){return Rt||(Rt=Ie(import.meta.url)),Rt("qrcode").toBuffer(o,{width:300,margin:2})}function q(o){let t=process.platform==="win32"?`start "" "${o}"`:process.platform==="darwin"?`open "${o}"`:`xdg-open "${o}"`;Se(t)}async function lo(o,t,e,r){let[n,s]=await Promise.all([Pe(t),Ae(e)]),i=ao(),a=await i.start();i.registerPage(o,n,s,r);let c=`http://127.0.0.1:${a}${o}/`;return{url:e,qrUrl:c,setStatus:h=>i.setStatus(o,h),closeServer:()=>i.unregisterPage(o)}}function Lt(o){return lo(Te,"login.html",o)}function Nt(o,t){return lo(be,"xianyu-auth.html",o,{authUrl:t})}import{promises as V}from"node:fs";import Dt from"node:path";import ve from"node:os";var ke=".r2-cli",ut=class{configPath;config;configLoaded=!1;dirEnsured=!1;constructor(){let t=ve.homedir(),e=Dt.join(t,ke);this.configPath=Dt.join(e,"config.json"),this.config={credentials:null}}getConfigPath(){return this.configPath}async loadConfig(){if(this.configLoaded)return this.config;try{let t=await V.readFile(this.configPath,"utf-8");return this.config=JSON.parse(t),this.configLoaded=!0,this.config}catch{return this.config={credentials:null},this.configLoaded=!0,this.config}}async ensureDir(){if(this.dirEnsured)return;let t=Dt.dirname(this.configPath);try{await V.stat(t)}catch(e){if(e.code==="ENOENT")await V.mkdir(t,{recursive:!0});else throw new B("Failed to create directory",t,e.code)}this.dirEnsured=!0}async saveConfig(t){this.config=t,await this.ensureDir();let e=JSON.stringify(t,null,2),r=this.configPath+".tmp";try{await V.writeFile(r,e,"utf-8"),await V.rename(r,this.configPath),this.configLoaded=!0}catch(n){throw await V.unlink(r).catch(s=>{typeof process.env.DEBUG<"u"&&console.error("[config] cleanup tmp failed:",s)}),new B("Failed to save config",this.configPath,n.code)}}},Ot=null;function Ut(){return Ot||(Ot=new ut),Ot}var jt=300*1e3,mt=class{store=Ut();isTokenExpired(t){return t.expire?Date.now()>=t.expire-jt:!1}async saveCredentials(t,e){let r=Date.now(),n=e.expire?Number.parseInt(e.expire,10):0,s={token:t,userInfo:e,timestamp:r,...n>0&&{expire:r+n}},i=await this.store.loadConfig();i.credentials=s,await this.store.saveConfig(i)}async getCredentials(){let t=await this.store.loadConfig();return!t.credentials||this.isTokenExpired(t.credentials)?null:t.credentials}async clearCredentials(){let t=await this.store.loadConfig();t.credentials=null,await this.store.saveConfig(t)}async getToken(){return(await this.getCredentials())?.token??null}async getUserInfo(){return(await this.getCredentials())?.userInfo??null}async isLoggedIn(){return await this.getCredentials()!==null}},Et=null;function nt(){return Et||(Et=new mt),Et}var Re="https://api.puresnake.com",gt=class{config;authStorage=null;cachedToken=null;tokenExpiry=0;constructor(t={}){this.config={baseUrl:t.baseUrl??Re,version:t.version??"v3",debug:t.debug??!1},this.authStorage=t.auth===!1?null:nt()}buildUrl(t){let e=t.startsWith("/")?t.slice(1):t;return`${this.config.baseUrl}/${this.config.version}/${e}`}async getAuthToken(){if(!this.authStorage)return;if(this.cachedToken&&Date.now()<this.tokenExpiry)return this.cachedToken;let t=await this.authStorage.getCredentials();if(!t)throw new C("\u8BF7\u5148\u8FD0\u884C r2-cli auth login \u767B\u5F55");return this.cachedToken=t.token,this.tokenExpiry=t.expire?t.expire-jt:Date.now()+1800*1e3,t.token}async requestFull(t,e){let r=this.buildUrl(t),{method:n,headers:s,body:i,timeout:a=3e4}=e,c=await this.getAuthToken(),h={...s,...c?{token:c}:{}},u=new AbortController,w=setTimeout(()=>u.abort(),a),M={method:n,headers:{"Content-Type":"application/json",...h},signal:u.signal};i!==void 0&&(M.body=JSON.stringify(i)),this.config.debug&&console.error(`[API ${n}]`,r,i);try{let d=await fetch(r,M);if(!d.ok){if(d.status===401)throw this.authStorage&&(this.cachedToken=null,await this.authStorage.clearCredentials().catch(z=>{console.error("[API] \u6E05\u9664\u51ED\u8BC1\u5931\u8D25:",z instanceof Error?z.message:String(z))})),new C("\u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u8FD0\u884C r2-cli auth login \u91CD\u65B0\u767B\u5F55");let At=await d.text();throw new b(At||`${d.status} ${d.statusText}`,d.status)}let k=await d.json();if(this.config.debug&&console.error("[API Response]",k),!k.success||k.status!==0)throw new b(k.msg||"\u672A\u77E5\u9519\u8BEF",k.status,k);return k}catch(d){throw d instanceof DOMException&&d.name==="AbortError"?new b(`\u8BF7\u6C42\u8D85\u65F6 (${a}ms)`,408):d}finally{clearTimeout(w)}}async request(t,e){return(await this.requestFull(t,e)).data}async get(t,e,r){let n=e&&e.size>0?`${t}?${e.toString()}`:t;return this.request(n,{method:"GET",headers:r})}async post(t,e,r){return this.request(t,{method:"POST",body:e,headers:r})}async put(t,e,r){return this.request(t,{method:"PUT",body:e,headers:r})}async delete(t,e){return this.request(t,{method:"DELETE",headers:e})}async upload(t,e,r){let n=this.buildUrl(t),s=await this.getAuthToken(),i={...r,...s?{token:s}:{}},a=new AbortController,c=setTimeout(()=>a.abort(),6e4),h={method:"POST",headers:i,body:e,signal:a.signal};this.config.debug&&console.error("[API UPLOAD]",n);try{let u=await fetch(n,h);if(!u.ok){if(u.status===401)throw this.authStorage&&(this.cachedToken=null,await this.authStorage.clearCredentials().catch(()=>{})),new C("\u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u8FD0\u884C r2-cli auth login \u91CD\u65B0\u767B\u5F55");if(u.status===413)throw new b("\u56FE\u7247\u592A\u5927\uFF0C\u4E0A\u4F20\u5931\u8D25\uFF08\u670D\u52A1\u7AEF\u9650\u5236\u7EA6 2MB\uFF09",413);let M=await u.text();throw new b(M||`${u.status} ${u.statusText}`,u.status)}let w=await u.json();if(this.config.debug&&console.error("[API Response]",w),!w.success||w.status!==0)throw new b(w.msg||"\u672A\u77E5\u9519\u8BEF",w.status,w);return w.data}catch(u){throw u instanceof DOMException&&u.name==="AbortError"?new b("\u4E0A\u4F20\u8D85\u65F6 (60000ms)",408):u}finally{clearTimeout(c)}}},pt=new gt,uo=new gt({auth:!1});var mo=uo;async function go(){return mo.post("app/qrcode/generate")}async function po(o){let t=new URLSearchParams;t.append("qrToken",o);let e=`app/qrcode/status?${t.toString()}`,r=await mo.requestFull(e,{method:"GET"});return r.token&&typeof r.data=="object"&&r.data!==null&&(r.data.token=r.token),r.data}async function wo(o,t,e){let{UserInfoCard:r}=await Promise.resolve().then(()=>(ho(),fo)),{renderComponent:n}=await Promise.resolve().then(()=>(st(),ft)),s=t!=null?{userInfo:o,lastLogin:t,daysSinceLogin:e??0}:{userInfo:o};n(r,s)}var ht=class{storage;constructor(t){this.storage=t??nt()}async generateQR(){let t=await go(),e=`https://m.puresnake.com/r2/auth/login?qrToken=${t.qrContent}&from=wechat`,r=await Lt(e);return{qrData:t,...r}}async waitForLogin(t,e,r,n,s,i){let a=await W(()=>po(t),{interval:r,timeout:e,condition:c=>{switch(c.status){case"scanned":return i||(console.log(x.cyan(`
|
|
11
|
+
\u{1F50D} \u5DF2\u626B\u7801: ${c.userInfo?.nickname||"\u672A\u77E5\u7528\u6237"}`)),console.log(x.yellow("\u8BF7\u5728 APP \u4E0A\u786E\u8BA4\u767B\u5F55"))),s?.("scanning"),!1;case"confirmed":return i||console.log(x.green(`
|
|
12
12
|
\u2705 \u7528\u6237\u5DF2\u786E\u8BA4\u767B\u5F55`)),s?.("success"),!0;case"expired":return i||console.log(x.red(`
|
|
13
13
|
\u23F0 \u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F`)),s?.("expired"),!0;case"canceled":return i||console.log(x.red(`
|
|
14
|
-
\u{1F6AB} \u7528\u6237\u5DF2\u53D6\u6D88\u767B\u5F55`)),s?.("expired"),!0;default:return!1}}},n??void 0);if(a.status==="confirmed"&&a.token&&a.userInfo)return await this.storage.saveCredentials(a.token,a.userInfo),{userInfo:a.userInfo,token:a.token};throw a.status==="expired"?new
|
|
14
|
+
\u{1F6AB} \u7528\u6237\u5DF2\u53D6\u6D88\u767B\u5F55`)),s?.("expired"),!0;default:return!1}}},n??void 0);if(a.status==="confirmed"&&a.token&&a.userInfo)return await this.storage.saveCredentials(a.token,a.userInfo),{userInfo:a.userInfo,token:a.token};throw a.status==="expired"?new C("\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55"):a.status==="canceled"?new C("\u7528\u6237\u5DF2\u53D6\u6D88\u767B\u5F55"):new C("\u767B\u5F55\u5931\u8D25: \u672A\u83B7\u53D6\u5230\u51ED\u8BC1")}async login(t){console.log(x.cyan(`
|
|
15
15
|
\u{1F510} \u6B63\u5728\u542F\u52A8\u626B\u7801\u767B\u5F55...`));let{qrData:e,qrUrl:r,setStatus:n,closeServer:s}=await this.generateQR();console.log(x.green(`\u2705 \u4E8C\u7EF4\u7801\u5DF2\u751F\u6210
|
|
16
16
|
`)),console.log(x.cyan(` \u94FE\u63A5: ${r}
|
|
17
|
-
`)),
|
|
18
|
-
`));let i=Number.parseInt(e.expireTime,10),a=Number.parseInt(e.pollInterval,10);try{let
|
|
17
|
+
`)),q(r),console.log(x.yellow(`\u23F3 \u7B49\u5F85\u626B\u7801...
|
|
18
|
+
`));let i=Number.parseInt(e.expireTime,10),a=Number.parseInt(e.pollInterval,10);try{let c=await this.waitForLogin(e.qrToken,i,a,t,n);return console.log(x.green(`
|
|
19
19
|
\u2705 \u767B\u5F55\u6210\u529F\uFF01
|
|
20
|
-
`)),
|
|
20
|
+
`)),wo(c.userInfo),c}catch(c){throw console.log(x.red(`
|
|
21
21
|
\u274C \u767B\u5F55\u5931\u8D25
|
|
22
|
-
`)),
|
|
22
|
+
`)),c}finally{s()}}async logout(){console.log(x.cyan(`
|
|
23
23
|
\u{1F6AA} \u6B63\u5728\u9000\u51FA\u767B\u5F55...`)),await this.storage.clearCredentials(),console.log(x.green(`\u2705 \u5DF2\u9000\u51FA\u767B\u5F55
|
|
24
24
|
`))}async status(){if(!await this.storage.isLoggedIn()){console.log(x.yellow(`\u26A0\uFE0F \u5C1A\u672A\u767B\u5F55\u6216\u51ED\u8BC1\u5DF2\u8FC7\u671F
|
|
25
25
|
`));return}let e=await this.storage.getCredentials(),r=e.userInfo,n=new Date(e.timestamp),s=Math.floor((Date.now()-e.timestamp)/(1e3*60*60*24));console.log(x.green(`\u2705 \u5DF2\u767B\u5F55
|
|
26
|
-
`)),await
|
|
27
|
-
\u2705 \u6388\u6743\u6210\u529F\uFF01\u5E97\u94FA: ${s.shopName} (${s.shopId})`)),n?.("success"),!0):s.status==="expired"?(console.log(
|
|
28
|
-
\u23F0 \u6388\u6743\u94FE\u63A5\u5DF2\u8FC7\u671F`)),n?.("expired"),!0):!1},r)}async function
|
|
29
|
-
\u{1F517} \u6B63\u5728\u83B7\u53D6\u95F2\u9C7C\u6388\u6743\u5730\u5740...`));let{authData:t,qrUrl:e,setStatus:r,closeServer:n}=await
|
|
30
|
-
`)),console.log(
|
|
26
|
+
`)),await wo(r,n,s)}},qt=null;function L(){return qt||(qt=new ht),qt}import Q from"chalk";var xo=pt;async function Io(){return xo.get("mms/xianyu/auth/url")}async function So(o){let t=new URLSearchParams({state:o});return xo.get("mms/xianyu/auth/status",t)}async function yt(){let o=await Io(),t=await Nt(o.url,o.url);return{authData:o,...t}}async function it(o,t,e,r,n){return W(()=>So(o),{interval:e,timeout:t,condition:s=>s.status==="success"?(console.log(Q.green(`
|
|
27
|
+
\u2705 \u6388\u6743\u6210\u529F\uFF01\u5E97\u94FA: ${s.shopName} (${s.shopId})`)),n?.("success"),!0):s.status==="expired"?(console.log(Q.red(`
|
|
28
|
+
\u23F0 \u6388\u6743\u94FE\u63A5\u5DF2\u8FC7\u671F`)),n?.("expired"),!0):!1},r)}async function Gt(o){console.log(Q.cyan(`
|
|
29
|
+
\u{1F517} \u6B63\u5728\u83B7\u53D6\u95F2\u9C7C\u6388\u6743\u5730\u5740...`));let{authData:t,qrUrl:e,setStatus:r,closeServer:n}=await yt();console.log(Q.green(`\u2705 \u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210
|
|
30
|
+
`)),console.log(Q.cyan(` \u94FE\u63A5: ${e}`)),console.log(Q.gray(` \u6216\u590D\u5236\u94FE\u63A5\u6253\u5F00: ${t.url}`)),q(e),console.log(Q.yellow(`
|
|
31
31
|
\u23F3 \u7B49\u5F85\u6388\u6743...
|
|
32
|
-
`));let s=t.expireTime?Number.parseInt(t.expireTime,10):3e5,i=t.pollInterval?Number.parseInt(t.pollInterval,10):1e3;try{let a=await
|
|
33
|
-
\u25B2 ${o.message}`)),console.error(
|
|
34
|
-
`));else if(o instanceof
|
|
35
|
-
`));else{let t=o instanceof Error?o.message:String(o);console.error(j.red(`\u25B2 ${t}`))}process.exit(1)}function qt(o){console.log(JSON.stringify({success:!1,error:o})),process.exit(1)}function g(o){return async t=>{try{await o(t)}catch(e){if(t.json){let r=e instanceof Error?e.message:String(e),n=e instanceof A?e.status:void 0;console.log(JSON.stringify({success:!1,error:r,...n!=null&&{status:n}})),process.exit(1)}v(e)}}}function yt(o){return async(...t)=>{try{await o(...t)}catch(e){let r=e instanceof Error?e.message:String(e);qt(r)}}}var je=new Set(["accessToken","refreshExpireIn"]);function To(o){return o.map(t=>{let e={};for(let[r,n]of Object.entries(t))je.has(r)||(e[r]=n);return e})}async function wt(o){let{qrInfo:t,qrUrl:e,setStatus:r,closeServer:n,waitArgs:s}=await o.generate();console.log(JSON.stringify(t,null,2)),B(e);try{let i=await o.waitResult(s,r);console.log(JSON.stringify(o.formatSuccess(i)))}catch(i){let a=i instanceof Error?i.message:String(i);console.log(JSON.stringify({success:!1,error:a})),process.exit(1)}finally{setTimeout(n,1e3)}}function Xt(){let o=new bo("login");o.description("\u626B\u7801\u767B\u5F55 Round2AI \u8D26\u6237").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");let t=new bo("poll").description("\u8F6E\u8BE2\u767B\u5F55\u72B6\u6001\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").requiredOption("--token <qrToken>","\u4E8C\u7EF4\u7801 token").option("--expire <ms>","\u8FC7\u671F\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09","300000").option("--interval <ms>","\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09","1000").action(yt(async e=>{let n=await R().waitForLogin(e.token,Number.parseInt(e.expire,10),Number.parseInt(e.interval,10));console.log(JSON.stringify({success:!0,...n}))}));return o.addCommand(t),o.action(async e=>{try{e.json?await wt({generate:async()=>{let r=R(),{qrData:n,qrUrl:s,setStatus:i,closeServer:a}=await r.generateQR(),l=Number.parseInt(n.expireTime,10),w=Number.parseInt(n.pollInterval,10);return{qrInfo:{qrToken:n.qrToken,expireTimeMs:l,pollIntervalMs:w,url:`https://m.puresnake.com/r2/auth/login?qrToken=${n.qrContent}&from=wechat`,qrUrl:s},qrUrl:s,setStatus:i,closeServer:a,waitArgs:{qrToken:n.qrToken,expireMs:l,intervalMs:w}}},waitResult:({qrToken:r,expireMs:n,intervalMs:s},i)=>R().waitForLogin(r,n,s,void 0,i,!0),formatSuccess:r=>({success:!0,userInfo:r.userInfo})}):await R().login()}catch(r){if(e.json){let n=r instanceof Error?r.message:String(r);console.log(JSON.stringify({success:!1,error:n})),process.exit(1)}v(r)}}),o}import{Command as Ee}from"commander";function _t(){let o=new Ee("logout");return o.description("\u9000\u51FA\u767B\u5F55"),o.action(async()=>{try{await R().logout()}catch(t){v(t)}}),o}import{Command as $e}from"commander";function Qt(){let o=new $e("status");return o.description("\u67E5\u770B\u767B\u5F55\u72B6\u6001"),o.action(async()=>{try{await R().status()}catch(t){v(t)}}),o}import{Command as Po}from"commander";function Mt(){let o=new Po("xianyu");o.description("\u95F2\u9C7C\u5E97\u94FA\u6388\u6743").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");let t=new Po("poll").description("\u8F6E\u8BE2\u95F2\u9C7C\u6388\u6743\u72B6\u6001\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").requiredOption("--state <state>","\u6388\u6743\u8F6E\u8BE2 token").option("--expire <ms>","\u8FC7\u671F\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09","300000").option("--interval <ms>","\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09","1000").action(yt(async e=>{let r=await nt(e.state,Number.parseInt(e.expire,10),Number.parseInt(e.interval,10));r.status==="success"?console.log(JSON.stringify({success:!0,shopId:r.shopId,shopName:r.shopName})):qt(`\u6388\u6743\u72B6\u6001: ${r.status}`)}));return o.addCommand(t),o.action(async e=>{try{e.json?await wt({generate:async()=>{let{authData:r,qrUrl:n,setStatus:s,closeServer:i}=await ht(),a=r.expireTime?Number.parseInt(r.expireTime,10):3e5,l=r.pollInterval?Number.parseInt(r.pollInterval,10):1e3;return{qrInfo:{state:r.state,expireTimeMs:a,pollIntervalMs:l,qrUrl:n},qrUrl:n,setStatus:s,closeServer:i,waitArgs:{state:r.state,expireMs:a,intervalMs:l}}},waitResult:async({state:r,expireMs:n,intervalMs:s},i)=>{let a=await nt(r,n,s,void 0,i);if(a.status!=="success")throw new Error(`\u6388\u6743\u72B6\u6001: ${a.status}`);return a},formatSuccess:r=>({success:!0,shopId:r.shopId,shopName:r.shopName})}):await Jt()}catch(r){if(e.json){let n=r instanceof Error?r.message:String(r);console.log(JSON.stringify({success:!1,error:n})),process.exit(1)}v(r)}}),o}import{Command as gr}from"commander";import{Command as Je}from"commander";import L from"chalk";import{select as zt,input as qe,confirm as Xe}from"@inquirer/prompts";import{readFileSync as Be}from"node:fs";import{basename as Ge}from"node:path";function X(o){let t=new URLSearchParams;for(let[e,r]of Object.entries(o))r!=null&&r!==""&&t.append(e,String(r));return t}var C=gt;async function Ft(o){return C.post("mms/goods/listing/up/xianyu",o)}async function Ao(o){return C.get("mms/goods/listing/get",X({...o}))}async function ko(o){return C.post("mms/goods/listing/down/xianyu",o)}async function vo(o){return C.post("mms/goods/listing/update/xyPrice",o)}async function No(o){return C.post("mms/goods/listing/update/goodsInfo",o)}async function Ro(o){return C.get("mms/goods/listing/list",o?X({...o}):void 0)}async function xt(){return await C.get("mms/user/shop/list")??[]}async function It(){return await C.get("mms/user/stock/list")??[]}async function St(o){let t=o?X({...o}):void 0;return C.get("mms/seller/goods/select/list",t)}async function Lo(o,t){let e=[];for(let r of t){let n=Be(r),s=Ge(r),i=new FormData;i.append("file",new Blob([n]),s);let a=await C.upload(`platform/xy/media/upload?shopId=${encodeURIComponent(o)}`,i);e.push(a)}return e}async function Oo(o){return C.post("mms/goods/listing/hang/up/xianyu",o)}async function Do(o=16){return await C.get("platform/xy/cat",X({spBizType:o}))??[]}async function Uo(o){return await C.get("platform/xy/props",X({channelCatId:o}))??[]}async function jo(o,t,e){return await C.get("platform/xy/props/value",X({channelCatId:o,propId:t,key:e}))??[]}var _e=2e3,Qe=1e4;function Me(o){let t=o.status?.toLowerCase()??"";return t===""||t==="init"||t==="pending"||t==="processing"}async function Eo(o,t,e,r){r||process.stdout.write(L.cyan("\u23F3 \u6B63\u5728\u67E5\u8BE2\u4E0A\u67B6\u8FDB\u5EA6..."));let n=await F(()=>Ao({stockGoodsId:o,shopId:t,platform:e}),{interval:_e,timeout:Qe,condition:s=>!Me(s)});return r||process.stdout.write("\r"+" ".repeat(30)+"\r"),n}function $o(){let o=new Je("up");return o.description("\u4E0A\u67B6\u5546\u54C1\u5230\u95F2\u9C7C"),o.option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1ID\uFF08\u4ECE goods list \u83B7\u53D6\uFF09").option("--shop-id <id>","\u5E97\u94FAID\uFF08\u4ECE goods shops \u83B7\u53D6\uFF09").option("--price <amount>","\u4E0A\u67B6\u4EF7\u683C").option("-p, --platform <platform>","\u5E73\u53F0","xianyu").option("--json","\u8F93\u51FA JSON\uFF08Agent \u7528\uFF09").action(g(async t=>{if(t.json&&!(t.stockGoodsId&&t.shopId&&t.price)&&(console.log(JSON.stringify({success:!1,error:"Agent \u6A21\u5F0F\u9700\u8981 --stock-goods-id, --shop-id, --price"})),process.exit(1)),t.stockGoodsId&&t.shopId&&t.price){let d=Number(t.stockGoodsId),k=t.shopId,At=Number(t.price),Q=t.platform,de=await Ft({stockGoodsId:d,shopId:k,price:At,platform:Q}),kt=await Eo(d,k,Q,t.json);if(t.json)console.log(JSON.stringify({success:!0,data:{submit:de,listing:kt}},null,2));else{let ue=kt.status?.toLowerCase()!=="failed";console.log(ue?L.green("\u2713 \u4E0A\u67B6\u6210\u529F"):L.red("\u2717 \u4E0A\u67B6\u5931\u8D25")),console.log(JSON.stringify(kt,null,2))}return}let e=await xt();if(e.length===0){console.log(L.yellow("\u6CA1\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF0C\u8BF7\u5148\u8FD0\u884C r2-cli auth xianyu \u6388\u6743"));return}let r=await zt({message:"\u9009\u62E9\u5E97\u94FA",choices:e.map(d=>({name:`${d.shopName} (${d.platform})`,value:d.shopId}))}),n=await It();if(n.length===0){console.log(L.yellow("\u6CA1\u6709\u53EF\u7528\u7684\u4ED3\u5E93"));return}let s=await zt({message:"\u9009\u62E9\u4ED3\u5E93",choices:n.map(d=>({name:d.stockName,value:d.stockId}))}),i=await St({stockId:s,size:100});if(!i.items?.length){console.log(L.yellow("\u8BE5\u4ED3\u5E93\u6CA1\u6709\u53EF\u9009\u7684\u5546\u54C1"));return}let a=await zt({message:"\u9009\u62E9\u5546\u54C1",choices:i.items.map(d=>({name:`${d.goodsName} ${d.size?`| ${d.size}`:""} | \xA5${d.salePrice}`,value:d.stockGoodsId}))}),l=await qe({message:"\u8F93\u5165\u4E0A\u67B6\u4EF7\u683C",default:i.items.find(d=>d.stockGoodsId===a)?.salePrice?.toString()??"",validate:d=>Number(d)>0?!0:"\u4EF7\u683C\u5FC5\u987B\u4E3A\u6B63\u6570"});if(!await Xe({message:`\u786E\u8BA4\u4E0A\u67B6\uFF1F\u4EF7\u683C \xA5${l}`,default:!0})){console.log(L.gray("\u5DF2\u53D6\u6D88"));return}let m=Number(a);await Ft({stockGoodsId:m,shopId:r,price:Number(l),platform:"xianyu"}),console.log(L.green("\u2713 \u4E0A\u67B6\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u67E5\u8BE2\u8FDB\u5EA6..."));let P=await Eo(m,r,"xianyu"),_=P.status?.toLowerCase()!=="failed";console.log(_?L.green("\u2713 \u4E0A\u67B6\u6210\u529F"):L.red("\u2717 \u4E0A\u67B6\u5931\u8D25")),console.log(JSON.stringify(P,null,2))})),o}import{Command as Ve}from"commander";import qo from"chalk";function Xo(){let o=new Ve("shops");return o.description("\u67E5\u770B\u6240\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF08\u8DE8\u5E73\u53F0\uFF09"),o.option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(g(async t=>{let e=await xt();if(t.json){console.log(JSON.stringify(To(e),null,2));return}if(!e.length){console.log(qo.yellow("\u672A\u627E\u5230\u5DF2\u6388\u6743\u7684\u5E97\u94FA")),console.log(qo.gray(" \u63D0\u793A: \u8BF7\u5148\u5728\u7B2C\u4E8C\u56DE\u5408 APP \u4E2D\u6388\u6743\u5E97\u94FA"));return}let{ShopsTable:r}=await Promise.resolve().then(()=>(Jo(),Go)),{renderComponent:n}=await Promise.resolve().then(()=>(rt(),pt));n(r,{shops:e,platform:"all"})})),o}import{Command as tr}from"commander";import or from"chalk";function Mo(){let o=new tr("stocks");return o.description("\u67E5\u770B\u6240\u6709\u4ED3\u5E93"),o.option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(g(async t=>{let e=await It();if(t.json){console.log(JSON.stringify(e,null,2));return}if(!e.length){console.log(or.yellow("\u672A\u627E\u5230\u4ED3\u5E93\u4FE1\u606F"));return}let{StocksTable:r}=await Promise.resolve().then(()=>(Qo(),_o)),{renderComponent:n}=await Promise.resolve().then(()=>(rt(),pt));n(r,{stocks:e})})),o}import{Command as er}from"commander";import Z from"chalk";function Fo(){let o=new er("list");return o.description("\u67E5\u770B\u4ED3\u5E93\u4E2D\u7684\u9009\u54C1\u5546\u54C1"),o.option("--stock-id <id>","\u4ED3\u5E93 ID\uFF08\u4ECE goods stocks \u83B7\u53D6\uFF09").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--page <n>","\u9875\u7801","1").option("--size <n>","\u6BCF\u9875\u6570\u91CF","20").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(g(async t=>{let r=await St({stockId:t.stockId||void 0,stockGoodsId:t.stockGoodsId||void 0,page:Number(t.page)||1,size:Number(t.size)||20})??{items:[],total:0};if(t.json){r.items?.length?console.log(JSON.stringify(r,null,2)):console.log(JSON.stringify({...r,hint:"\u9009\u54C1\u5546\u54C1\u4E3A\u7A7A\uFF0C\u8BF7\u5148\u5728\u540E\u53F0\u751F\u6210\u9009\u54C1\u8868\u6570\u636E\u540E\u518D\u8BD5"},null,2));return}if(!r.items?.length){console.log(Z.yellow("\u6682\u65E0\u9009\u54C1\u5546\u54C1\uFF0C\u8BF7\u5148\u7ED1\u5B9A\u4ED3\u5E93\u6216\u5728\u540E\u53F0\u751F\u6210\u9009\u54C1\u8868\u6570\u636E"));return}console.log(Z.cyan(`
|
|
32
|
+
`));let s=t.expireTime?Number.parseInt(t.expireTime,10):3e5,i=t.pollInterval?Number.parseInt(t.pollInterval,10):1e3;try{let a=await it(t.state,s,i,o,r);if(a.status==="success")return a;throw new C("\u95F2\u9C7C\u6388\u6743\u5931\u8D25: "+(a.status==="expired"?"\u94FE\u63A5\u5DF2\u8FC7\u671F":"\u672A\u77E5\u72B6\u6001"))}finally{n()}}import N from"chalk";function X(o){if(o instanceof C)console.error(N.red(`
|
|
33
|
+
\u25B2 ${o.message}`)),console.error(N.gray(`\u2192 \u8BF7\u5148\u8FD0\u884C: r2-cli auth login
|
|
34
|
+
`));else if(o instanceof b)console.error(N.red(`\u25B2 \u64CD\u4F5C\u5931\u8D25: ${o.message}`)),o.status&&console.error(N.gray(` \u72B6\u6001\u7801: ${o.status}`));else if(o instanceof B)console.error(N.red(`\u25B2 \u914D\u7F6E\u6587\u4EF6\u5F02\u5E38: ${o.message}`)),o.path&&console.error(N.gray(` \u8DEF\u5F84: ${o.path}`)),console.error(N.gray(`\u2192 \u8BF7\u5C1D\u8BD5\u91CD\u65B0\u767B\u5F55: r2-cli auth login
|
|
35
|
+
`));else{let t=o instanceof Error?o.message:String(o);console.error(N.red(`\u25B2 ${t}`))}process.exit(1)}function Jt(o){console.log(JSON.stringify({success:!1,error:o})),process.exit(1)}function m(o){return async t=>{try{await o(t)}catch(e){if(t.json){let r=e instanceof Error?e.message:String(e),n=e instanceof b?e.status:void 0;console.log(JSON.stringify({success:!1,error:r,...n!=null&&{status:n}})),process.exit(1)}X(e)}}}function P(o,t){o.json&&(console.log(JSON.stringify({success:!1,error:t})),process.exit(1)),console.log(N.yellow(t))}function j(o,t,e){o.json?console.log(JSON.stringify({success:!0,data:t},null,2)):(e&&console.log(N.green(e)),console.log(JSON.stringify(t,null,2)))}function wt(o){return async(...t)=>{try{await o(...t)}catch(e){let r=e instanceof Error?e.message:String(e);Jt(r)}}}var je=new Set(["accessToken","refreshExpireIn"]);function Co(o){return o.map(t=>{let e={};for(let[r,n]of Object.entries(t))je.has(r)||(e[r]=n);return e})}async function xt(o){let{qrInfo:t,qrUrl:e,setStatus:r,closeServer:n,waitArgs:s}=await o.generate();console.log(JSON.stringify(t,null,2)),q(e);try{let i=await o.waitResult(s,r);console.log(JSON.stringify(o.formatSuccess(i)))}catch(i){let a=i instanceof Error?i.message:String(i);console.log(JSON.stringify({success:!1,error:a})),process.exit(1)}finally{setTimeout(n,1e3)}}function Qt(){let o=new To("login");o.description("\u626B\u7801\u767B\u5F55 Round2AI \u8D26\u6237").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");let t=new To("poll").description("\u8F6E\u8BE2\u767B\u5F55\u72B6\u6001\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").requiredOption("--token <qrToken>","\u4E8C\u7EF4\u7801 token").option("--expire <ms>","\u8FC7\u671F\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09","300000").option("--interval <ms>","\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09","1000").action(wt(async e=>{let n=await L().waitForLogin(e.token,Number.parseInt(e.expire,10),Number.parseInt(e.interval,10));console.log(JSON.stringify({success:!0,...n}))}));return o.addCommand(t),o.action(m(async e=>{e.json?await xt({generate:async()=>{let r=L(),{qrData:n,qrUrl:s,setStatus:i,closeServer:a}=await r.generateQR(),c=Number.parseInt(n.expireTime,10),h=Number.parseInt(n.pollInterval,10);return{qrInfo:{qrToken:n.qrToken,expireTimeMs:c,pollIntervalMs:h,qrUrl:s},qrUrl:s,setStatus:i,closeServer:a,waitArgs:{qrToken:n.qrToken,expireMs:c,intervalMs:h}}},waitResult:({qrToken:r,expireMs:n,intervalMs:s},i)=>L().waitForLogin(r,n,s,void 0,i,!0),formatSuccess:r=>({success:!0,userInfo:r.userInfo})}):await L().login()})),o}import{Command as $e}from"commander";function Xt(){let o=new $e("logout");return o.description("\u9000\u51FA\u767B\u5F55"),o.action(async()=>{try{await L().logout()}catch(t){X(t)}}),o}import{Command as Be}from"commander";function _t(){let o=new Be("status");return o.description("\u67E5\u770B\u767B\u5F55\u72B6\u6001"),o.action(async()=>{try{await L().status()}catch(t){X(t)}}),o}import{Command as bo}from"commander";function Mt(){let o=new bo("xianyu");o.description("\u95F2\u9C7C\u5E97\u94FA\u6388\u6743").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09");let t=new bo("poll").description("\u8F6E\u8BE2\u95F2\u9C7C\u6388\u6743\u72B6\u6001\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").requiredOption("--state <state>","\u6388\u6743\u8F6E\u8BE2 token").option("--expire <ms>","\u8FC7\u671F\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09","300000").option("--interval <ms>","\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09","1000").action(wt(async e=>{let r=await it(e.state,Number.parseInt(e.expire,10),Number.parseInt(e.interval,10));r.status==="success"?console.log(JSON.stringify({success:!0,shopId:r.shopId,shopName:r.shopName})):Jt(`\u6388\u6743\u72B6\u6001: ${r.status}`)}));return o.addCommand(t),o.action(m(async e=>{e.json?await xt({generate:async()=>{let{authData:r,qrUrl:n,setStatus:s,closeServer:i}=await yt(),a=r.expireTime?Number.parseInt(r.expireTime,10):3e5,c=r.pollInterval?Number.parseInt(r.pollInterval,10):1e3;return{qrInfo:{state:r.state,expireTimeMs:a,pollIntervalMs:c,qrUrl:n},qrUrl:n,setStatus:s,closeServer:i,waitArgs:{state:r.state,expireMs:a,intervalMs:c}}},waitResult:async({state:r,expireMs:n,intervalMs:s},i)=>{let a=await it(r,n,s,void 0,i);if(a.status!=="success")throw new Error(`\u6388\u6743\u72B6\u6001: ${a.status}`);return a},formatSuccess:r=>({success:!0,shopId:r.shopId,shopName:r.shopName})}):await Gt()})),o}import{Command as xr}from"commander";import{Command as Xe}from"commander";import D from"chalk";import{select as Ft,input as _e,confirm as Me}from"@inquirer/prompts";import{basename as Qe}from"node:path";function _(o){let t=new URLSearchParams;for(let[e,r]of Object.entries(o))r!=null&&r!==""&&t.append(e,String(r));return t}import{statSync as qe,readFileSync as Po}from"node:fs";import Ge from"sharp";var Je=2*1024*1024;async function Ao(o,t=Je){let{size:e}=qe(o);if(e<=t)return Po(o);let r=Ge(o);await r.metadata();let n=[100,90,80,70,60,50,40,30],s=null;for(let i of n){let a=await r.jpeg({quality:i,mozjpeg:!0}).toBuffer();if(a.length<=t)return a;s=a}return s??Po(o)}var T=pt;async function zt(o){return T.post("mms/goods/listing/up/xianyu",o)}async function vo(o){return T.get("mms/goods/listing/get",_({...o}))}async function ko(o){return T.post("mms/goods/listing/down/xianyu",o)}async function Ro(o){return T.post("mms/goods/listing/update/xyPrice",o)}async function Lo(o){return T.post("mms/goods/listing/update/goodsInfo",o)}async function No(o){return T.get("mms/goods/listing/list",o?_({...o}):void 0)}async function It(){return await T.get("mms/user/shop/list")??[]}async function St(){return await T.get("mms/user/stock/list")??[]}async function Ct(o){let t=o?_({...o}):void 0;return T.get("mms/seller/goods/select/list",t)}async function Do(o,t){let e=async(i,a=1)=>{for(let c=0;c<=a;c++)try{let h=await Ao(i),u=Qe(i),w=new FormData;return w.append("file",new Blob([new Uint8Array(h)]),u),await T.upload(`platform/xy/media/upload?shopId=${encodeURIComponent(o)}`,w)}catch(h){if(c<a){await new Promise(u=>setTimeout(u,1e3));continue}throw h}throw new Error("unreachable")},r=await Promise.allSettled(t.map(e)),n=[],s=[];for(let i=0;i<r.length;i++){let a=r[i];if(a.status==="fulfilled")n.push(a.value);else{let c=a.reason;s.push({file:t[i],error:c instanceof Error?c.message:`${c}`})}}return{images:n,failed:s}}async function Oo(o){return T.post("mms/goods/listing/hang/up/xianyu",o)}async function Uo(o=16){return await T.get("platform/xy/cat",_({spBizType:o}))??[]}async function Eo(o){return await T.get("platform/xy/props",_({channelCatId:o}))??[]}async function jo(o,t,e){return await T.get("platform/xy/props/value",_({channelCatId:o,propId:t,key:e}))??[]}var ze=2e3,Fe=1e4;function We(o){let t=o.status?.toLowerCase()??"";return t===""||t==="init"||t==="pending"||t==="processing"}async function $o(o,t,e,r){r||process.stdout.write(D.cyan("\u23F3 \u6B63\u5728\u67E5\u8BE2\u4E0A\u67B6\u8FDB\u5EA6..."));let n=await W(()=>vo({stockGoodsId:o,shopId:t,platform:e}),{interval:ze,timeout:Fe,condition:s=>!We(s)});return r||process.stdout.write("\r"+" ".repeat(30)+"\r"),n}function Bo(){let o=new Xe("up");return o.description("\u4E0A\u67B6\u5546\u54C1\u5230\u95F2\u9C7C"),o.option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1ID\uFF08\u4ECE goods list \u83B7\u53D6\uFF09").option("--shop-id <id>","\u5E97\u94FAID\uFF08\u4ECE goods shops \u83B7\u53D6\uFF09").option("--price <amount>","\u4E0A\u67B6\u4EF7\u683C").option("-p, --platform <platform>","\u5E73\u53F0","xianyu").option("--json","\u8F93\u51FA JSON\uFF08Agent \u7528\uFF09").action(m(async t=>{if(t.json&&!(t.stockGoodsId&&t.shopId&&t.price)){P(t,"Agent \u6A21\u5F0F\u9700\u8981 --stock-goods-id, --shop-id, --price");return}if(t.stockGoodsId&&t.shopId&&t.price){let d=Number(t.stockGoodsId),k=t.shopId,At=Number(t.price),z=t.platform,ue=await zt({stockGoodsId:d,shopId:k,price:At,platform:z}),vt=await $o(d,k,z,t.json);if(t.json)console.log(JSON.stringify({success:!0,data:{submit:ue,listing:vt}},null,2));else{let me=vt.status?.toLowerCase()!=="failed";console.log(me?D.green("\u2713 \u4E0A\u67B6\u6210\u529F"):D.red("\u2717 \u4E0A\u67B6\u5931\u8D25")),console.log(JSON.stringify(vt,null,2))}return}let e=await It();if(e.length===0){console.log(D.yellow("\u6CA1\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF0C\u8BF7\u5148\u8FD0\u884C r2-cli auth xianyu \u6388\u6743"));return}let r=await Ft({message:"\u9009\u62E9\u5E97\u94FA",choices:e.map(d=>({name:`${d.shopName} (${d.platform})`,value:d.shopId}))}),n=await St();if(n.length===0){console.log(D.yellow("\u6CA1\u6709\u53EF\u7528\u7684\u4ED3\u5E93"));return}let s=await Ft({message:"\u9009\u62E9\u4ED3\u5E93",choices:n.map(d=>({name:d.stockName,value:d.stockId}))}),i=await Ct({stockId:s,size:100});if(!i.items?.length){console.log(D.yellow("\u8BE5\u4ED3\u5E93\u6CA1\u6709\u53EF\u9009\u7684\u5546\u54C1"));return}let a=await Ft({message:"\u9009\u62E9\u5546\u54C1",choices:i.items.map(d=>({name:`${d.goodsName} ${d.size?`| ${d.size}`:""} | \xA5${d.salePrice}`,value:d.stockGoodsId}))}),c=await _e({message:"\u8F93\u5165\u4E0A\u67B6\u4EF7\u683C",default:i.items.find(d=>d.stockGoodsId===a)?.salePrice?.toString()??"",validate:d=>Number(d)>0?!0:"\u4EF7\u683C\u5FC5\u987B\u4E3A\u6B63\u6570"});if(!await Me({message:`\u786E\u8BA4\u4E0A\u67B6\uFF1F\u4EF7\u683C \xA5${c}`,default:!0})){console.log(D.gray("\u5DF2\u53D6\u6D88"));return}let u=Number(a);await zt({stockGoodsId:u,shopId:r,price:Number(c),platform:"xianyu"}),console.log(D.green("\u2713 \u4E0A\u67B6\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u67E5\u8BE2\u8FDB\u5EA6..."));let w=await $o(u,r,"xianyu"),M=w.status?.toLowerCase()!=="failed";console.log(M?D.green("\u2713 \u4E0A\u67B6\u6210\u529F"):D.red("\u2717 \u4E0A\u67B6\u5931\u8D25")),console.log(JSON.stringify(w,null,2))})),o}import{Command as Ze}from"commander";import Qo from"chalk";function Xo(){let o=new Ze("shops");return o.description("\u67E5\u770B\u6240\u6709\u5DF2\u6388\u6743\u5E97\u94FA\uFF08\u8DE8\u5E73\u53F0\uFF09"),o.option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(m(async t=>{let e=await It();if(t.json){console.log(JSON.stringify(Co(e),null,2));return}if(!e.length){console.log(Qo.yellow("\u672A\u627E\u5230\u5DF2\u6388\u6743\u7684\u5E97\u94FA")),console.log(Qo.gray(" \u63D0\u793A: \u8BF7\u5148\u5728\u7B2C\u4E8C\u56DE\u5408 APP \u4E2D\u6388\u6743\u5E97\u94FA"));return}let{ShopsTable:r}=await Promise.resolve().then(()=>(Jo(),Go)),{renderComponent:n}=await Promise.resolve().then(()=>(st(),ft));n(r,{shops:e,platform:"all"})})),o}import{Command as rr}from"commander";import nr from"chalk";function zo(){let o=new rr("stocks");return o.description("\u67E5\u770B\u6240\u6709\u4ED3\u5E93"),o.option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(m(async t=>{let e=await St();if(t.json){console.log(JSON.stringify(e,null,2));return}if(!e.length){console.log(nr.yellow("\u672A\u627E\u5230\u4ED3\u5E93\u4FE1\u606F"));return}let{StocksTable:r}=await Promise.resolve().then(()=>(Mo(),_o)),{renderComponent:n}=await Promise.resolve().then(()=>(st(),ft));n(r,{stocks:e})})),o}import{Command as sr}from"commander";import ot from"chalk";function Fo(){let o=new sr("list");return o.description("\u67E5\u770B\u4ED3\u5E93\u4E2D\u7684\u9009\u54C1\u5546\u54C1"),o.option("--stock-id <id>","\u4ED3\u5E93 ID\uFF08\u4ECE goods stocks \u83B7\u53D6\uFF09").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--page <n>","\u9875\u7801","1").option("--size <n>","\u6BCF\u9875\u6570\u91CF\uFF08\u6700\u5927 50\uFF09","20").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(m(async t=>{let r=await Ct({stockId:t.stockId||void 0,stockGoodsId:t.stockGoodsId||void 0,page:Number(t.page)||1,size:Math.min(Number(t.size)||20,50)})??{items:[],total:0};if(t.json){r.items?.length?console.log(JSON.stringify(r,null,2)):console.log(JSON.stringify({...r,hint:"\u9009\u54C1\u5546\u54C1\u4E3A\u7A7A\uFF0C\u8BF7\u5148\u5728\u540E\u53F0\u751F\u6210\u9009\u54C1\u8868\u6570\u636E\u540E\u518D\u8BD5"},null,2));return}if(!r.items?.length){console.log(ot.yellow("\u6682\u65E0\u9009\u54C1\u5546\u54C1\uFF0C\u8BF7\u5148\u7ED1\u5B9A\u4ED3\u5E93\u6216\u5728\u540E\u53F0\u751F\u6210\u9009\u54C1\u8868\u6570\u636E"));return}console.log(ot.cyan(`
|
|
36
36
|
\u9009\u54C1\u5546\u54C1\uFF08\u5171 ${r.total} \u4EF6\uFF0C\u7B2C ${r.page} \u9875\uFF09
|
|
37
|
-
`));for(let n of r.items)console.log(` ${Z.bold(n.goodsName)} ${n.size?Z.gray(`| ${n.size}`):""}`),console.log(` \u54C1\u724C: ${n.brand} \u5EFA\u8BAE\u552E\u4EF7: \xA5${n.salePrice} stockGoodsId: ${Z.green(n.stockGoodsId)}`),console.log(Z.gray(` \u5206\u7C7B: ${n.cate1Name} > ${n.cate2Name} > ${n.cate3Name}`)),console.log()})),o}import{Command as ar}from"commander";import cr from"chalk";rt();import{Box as p,Text as h}from"ink";import{jsx as c,jsxs as E}from"react/jsx-runtime";var rr={init:{label:"\u5F85\u4E0A\u67B6",color:"yellow"},up:{label:"\u5DF2\u4E0A\u67B6",color:"green"},down:{label:"\u5DF2\u4E0B\u67B6",color:"gray"},fail:{label:"\u5931\u8D25",color:"red"}},oo=4,eo=8,Ct=12,ro=10,no=6,so=8;function zo(o,t){return o.length>t?o.slice(0,t-1)+"\u2026":o}function Wo(o){if(!o)return"-";let t=new Date(o),e=r=>String(r).padStart(2,"0");return`${e(t.getMonth()+1)}/${e(t.getDate())} ${e(t.getHours())}:${e(t.getMinutes())}`}function nr({fillWidth:o}){return E(p,{flexDirection:"row",children:[c(p,{width:oo,children:c(h,{bold:!0,color:"white",children:"ID"})}),c(p,{width:eo,children:c(h,{bold:!0,color:"white",children:"\u72B6\u6001"})}),c(p,{width:Ct,children:c(h,{bold:!0,color:"white",children:"\u54C1\u724C"})}),c(p,{width:o,children:c(h,{bold:!0,color:"white",children:"\u5546\u54C1\u540D\u79F0"})}),c(p,{width:ro,children:c(h,{bold:!0,color:"white",children:"\u4EF7\u683C"})}),c(p,{width:no,children:c(h,{bold:!0,color:"white",children:"\u89C4\u683C"})}),c(p,{width:so,children:c(h,{bold:!0,color:"white",children:"\u5E93\u5B58ID"})})]})}function sr({item:o}){return c(p,{flexDirection:"column",children:c(h,{color:"gray",children:` shopId: ${o.shopId} thirdItemNo: ${o.thirdItemNo||"-"} outItemNo: ${o.outItemNo||"-"} \u8D27\u53F7: ${o.goodsNo||"-"} ${o.type||"-"} ${o.platform} \u521B\u5EFA: ${Wo(o.gmtCreate)} \u4FEE\u6539: ${Wo(o.gmtModified)}`})})}function ir({item:o,fillWidth:t}){let e=rr[o.status]??{label:o.status,color:"white"};return E(p,{flexDirection:"column",children:[E(p,{flexDirection:"row",children:[c(p,{width:oo,children:c(h,{color:"gray",children:o.id})}),c(p,{width:eo,children:c(h,{color:e.color,children:e.label})}),c(p,{width:Ct,children:c(h,{color:"cyan",children:zo(o.brandName||"-",Ct-1)})}),c(p,{width:t,children:c(h,{children:zo(o.goodsName,t-1)})}),c(p,{width:ro,children:E(h,{color:"yellow",children:["\xA5",o.price]})}),c(p,{width:no,children:c(h,{color:"gray",children:o.spec||"-"})}),c(p,{width:so,children:c(h,{color:"gray",children:o.stockGoodsId})})]}),c(sr,{item:o})]})}function Ho({items:o,total:t}){let e=process.stdout.columns||80,r=4,n=oo+eo+Ct+ro+no+so,s=Math.max(e-r-n,20),i=n+s;return E(p,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[E(p,{flexDirection:"row",children:[c(h,{bold:!0,color:"cyan",children:"\u4E0A\u67B6\u5217\u8868"}),E(h,{color:"gray",children:[" \xB7 \u5171 ",t," \u6761"]})]}),E(p,{flexDirection:"column",marginTop:1,children:[c(nr,{fillWidth:s}),c(h,{color:"gray",children:"\u2500".repeat(i)}),o.map(a=>c(ir,{item:a,fillWidth:s},a.id))]})]})}function Vo(){let o=new ar("listing");return o.description("\u67E5\u8BE2\u4E0A\u67B6\u5546\u54C1\u5217\u8868"),o.option("--id <id>","\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>","\u5E97\u94FA ID").option("--stock-id <id>","\u4ED3\u5E93 ID").option("-s, --status <status>","\u72B6\u6001\u8FC7\u6EE4\uFF08init/up/down/fail/sold\uFF09").option("-p, --platform <platform>","\u5E73\u53F0","xianyu").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(g(async t=>{let r=await Ro({id:t.id,stockGoodsId:t.stockGoodsId?Number(t.stockGoodsId):void 0,shopId:t.shopId,stockId:t.stockId,status:t.status,platform:t.platform})??{items:[],total:0};if(t.json){r.items?.length?console.log(JSON.stringify(r,null,2)):console.log(JSON.stringify({...r,hint:"\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55"},null,2));return}if(!r.items?.length){console.log(cr.yellow("\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55"));return}Bt(Ho,{items:r.items,total:r.total})})),o}import{Command as lr}from"commander";import io from"chalk";function Ko(){let o=new lr("down");return o.description("\u4E0B\u67B6\u95F2\u9C7C\u5546\u54C1"),o.option("--id <id>","\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>","\u5E97\u94FA ID").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(g(async t=>{if(!t.id&&!(t.stockGoodsId&&t.shopId)){t.json&&(console.log(JSON.stringify({success:!1,error:"\u8BF7\u6307\u5B9A\u4E0B\u67B6\u6761\u4EF6\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"})),process.exit(1)),console.log(io.yellow("\u8BF7\u6307\u5B9A\u4E0B\u67B6\u6761\u4EF6\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"));return}let e={};t.id&&(e.id=t.id),t.stockGoodsId&&(e.stockGoodsId=Number(t.stockGoodsId)),t.shopId&&(e.shopId=t.shopId),t.json||console.log(io.cyan("\u{1F4E6} \u6B63\u5728\u4E0B\u67B6\u5546\u54C1..."));let r=await ko(e);t.json?console.log(JSON.stringify({success:!0,data:r},null,2)):(console.log(io.green("\u2705 \u4E0B\u67B6\u6210\u529F")),console.log(JSON.stringify(r,null,2)))})),o}import{Command as dr}from"commander";import Tt from"chalk";function Yo(){let o=new dr("price");return o.description("\u4FEE\u6539\u95F2\u9C7C\u4E0A\u67B6\u5546\u54C1\u4EF7\u683C"),o.option("--id <id>","\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>","\u5E97\u94FA ID").option("--price <amount>","\u65B0\u4EF7\u683C\uFF08\u5FC5\u586B\uFF09").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(g(async t=>{if(!t.price){t.json&&(console.log(JSON.stringify({success:!1,error:"--price <amount> \u4E3A\u5FC5\u586B\u53C2\u6570"})),process.exit(1)),console.log(Tt.yellow("--price <amount> \u4E3A\u5FC5\u586B\u53C2\u6570"));return}if(!t.id&&!(t.stockGoodsId&&t.shopId)){t.json&&(console.log(JSON.stringify({success:!1,error:"\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"})),process.exit(1)),console.log(Tt.yellow("\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>"));return}let e={price:Number(t.price)};t.id&&(e.id=t.id),t.stockGoodsId&&(e.stockGoodsId=Number(t.stockGoodsId)),t.shopId&&(e.shopId=t.shopId),t.json||console.log(Tt.cyan(`\u{1F4B0} \u6B63\u5728\u4FEE\u6539\u4EF7\u683C\u4E3A ${t.price}...`));let r=await vo(e);t.json?console.log(JSON.stringify({success:!0,data:r},null,2)):(console.log(Tt.green("\u2705 \u4EF7\u683C\u4FEE\u6539\u6210\u529F")),console.log(JSON.stringify(r,null,2)))})),o}import{Command as ur}from"commander";import st from"chalk";function Zo(){let o=new ur("edit");return o.description("\u4FEE\u6539\u5DF2\u4E0A\u67B6\u5546\u54C1\u4FE1\u606F\uFF08\u6807\u9898\u3001\u63CF\u8FF0\u3001\u54C1\u724C\u3001\u7C7B\u76EE\u3001\u56FE\u7247\u3001\u5C5E\u6027\u7B49\uFF09"),o.option("--id <id>","\u5546\u54C1\u4E0A\u67B6 ID\uFF08goodsListingId\uFF0C\u63A8\u8350\uFF09").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID\uFF08\u4E0E --account \u914D\u5408\uFF09").option("--account <shopId>","\u95F2\u9C7C\u7528\u6237\u540D/\u5E97\u94FA ID\uFF08\u4E0E --stock-goods-id \u914D\u5408\uFF09").option("--title <title>","\u5546\u54C1\u6807\u9898").option("--desc <desc>","\u5546\u54C1\u63CF\u8FF0").option("--category-id <id>","\u5546\u54C1\u7C7B\u76EE ID\uFF08\u5927\u5206\u7C7B\uFF0C\u540E\u7AEF\u5FC5\u586B\uFF09").option("--channel-cat-id <id>","\u6E20\u9053\u7C7B\u76EE ID\uFF08\u5C0F\u5206\u7C7B\uFF0C\u540E\u7AEF\u5FC5\u586B\uFF09").option("--image-ids <ids>","\u56FE\u7247 ID \u5217\u8868\uFF08\u9017\u53F7\u5206\u9694\uFF09").option("--item-attrs <json>","\u5546\u54C1\u5C5E\u6027\u5217\u8868\uFF08JSON \u5B57\u7B26\u4E32\uFF09").option("--brand-name <name>","\u54C1\u724C\u540D\u79F0").option("--stuff-status <status>","\u6210\u8272\u7B49\u7EA7\uFF1A100=\u5168\u65B0 -1=\u51C6\u65B0 99=99\u65B0 95=95\u65B0 90=9\u65B0").option("--goods-no <no>","\u8D27\u53F7").option("--original-price <price>","\u539F\u4EF7\uFF08\u5355\u4F4D\uFF1A\u5143\uFF09").option("--size <size>","\u5C3A\u7801").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(g(async t=>{if(!t.id&&!(t.stockGoodsId&&t.account)){t.json&&(console.log(JSON.stringify({success:!1,status:400,error:"\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <goodsListingId> \u6216 --stock-goods-id <id> --account <shopId>"})),process.exit(1)),console.log(st.yellow("\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <goodsListingId> \u6216 --stock-goods-id <id> --account <shopId>"));return}let e={};if(t.id&&(e.goodsListingId=Number(t.id)),t.stockGoodsId&&(e.stockGoodsId=Number(t.stockGoodsId)),t.account&&(e.account=t.account),t.title&&(e.title=t.title),t.desc&&(e.desc=t.desc),t.categoryId&&(e.categoryId=Number(t.categoryId)),t.channelCatId&&(e.channelCatId=t.channelCatId),t.imageIds&&(e.imageIdList=t.imageIds.split(",").map(s=>s.trim())),t.brandName&&(e.brandName=t.brandName),t.stuffStatus&&(e.stuffStatus=Number(t.stuffStatus)),t.goodsNo&&(e.goodsNo=t.goodsNo),t.originalPrice&&(e.originalPrice=Number(t.originalPrice)),t.size&&(e.size=t.size),t.itemAttrs)try{e.itemAttrList=JSON.parse(t.itemAttrs)}catch{t.json&&(console.log(JSON.stringify({success:!1,status:400,error:"--item-attrs JSON \u89E3\u6790\u5931\u8D25"})),process.exit(1)),console.log(st.yellow("--item-attrs JSON \u89E3\u6790\u5931\u8D25"));return}if(!Object.keys(e).some(s=>!["goodsListingId","stockGoodsId","account"].includes(s))){t.json&&(console.log(JSON.stringify({success:!1,status:400,error:"\u672A\u6307\u5B9A\u9700\u8981\u4FEE\u6539\u7684\u5B57\u6BB5"})),process.exit(1)),console.log(st.yellow("\u672A\u6307\u5B9A\u9700\u8981\u4FEE\u6539\u7684\u5B57\u6BB5"));return}t.json||console.log(st.cyan("\u6B63\u5728\u4FEE\u6539\u5546\u54C1\u4FE1\u606F..."));let n=await No(e);t.json?console.log(JSON.stringify({success:!0,data:n},null,2)):(console.log(st.green("\u2705 \u5546\u54C1\u4FE1\u606F\u4FEE\u6539\u6210\u529F")),console.log(JSON.stringify(n,null,2)))})),o}import{Command as tt}from"commander";import y from"chalk";var mr={100:"\u5168\u65B0",[-1]:"\u51C6\u65B0",99:"99\u65B0",95:"95\u65B0",90:"9\u65B0"};function te(){let o=new tt("hang-up");return o.description("\u95F2\u9C7C\u6302\u552E\u4E0A\u67B6\uFF08\u5B8C\u6574\u5546\u54C1\u4FE1\u606F\u6A21\u5F0F\uFF09"),o.addCommand(new tt("categories").description("\u83B7\u53D6\u95F2\u9C7C\u7C7B\u76EE\u5217\u8868\uFF08\u5927\u5206\u7C7B \u2192 \u5C0F\u5206\u7C7B\uFF09").option("--sp-biz-type <n>","\u4E1A\u52A1\u5206\u7C7B\uFF0C16=\u5962\u54C1","16").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(g(async t=>{let e=await Do(Number(t.spBizType));if(t.json){console.log(JSON.stringify(e,null,2));return}let r=new Map;for(let n of e){let s=String(n.catId);r.has(s)||r.set(s,{catName:n.catName,children:[]}),r.get(s).children.push({channel:n.channel,channelCatId:n.channelCatId})}for(let[n,s]of r){console.log(y.bold(`${s.catName} (catId: ${y.green(n)})`));for(let i of s.children)console.log(` ${i.channel} (channelCatId: ${y.green(i.channelCatId)})`)}}))),o.addCommand(new tt("props").description("\u83B7\u53D6\u6307\u5B9A\u7C7B\u76EE\u4E0B\u7684\u5C5E\u6027\u5217\u8868\uFF08\u542B\u53EF\u9009\u503C\uFF09").requiredOption("--channel-cat-id <id>","\u5C0F\u5206\u7C7B ID\uFF08\u4ECE categories \u83B7\u53D6\uFF09").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(g(async t=>{let e=await Uo(t.channelCatId);if(t.json){console.log(JSON.stringify(e,null,2));return}for(let r of e)if(console.log(y.bold(`
|
|
38
|
-
${r.propName} (propId: ${r.propId})`)),r.propsValues?.length)for(let n of r.propsValues)console.log(` ${n.valueName} (valueId: ${n.valueId})`);else console.log(
|
|
37
|
+
`));for(let n of r.items)console.log(` ${ot.bold(n.goodsName)} ${n.size?ot.gray(`| ${n.size}`):""}`),console.log(` \u54C1\u724C: ${n.brand} \u5EFA\u8BAE\u552E\u4EF7: \xA5${n.salePrice} stockGoodsId: ${ot.green(n.stockGoodsId)}`),console.log(ot.gray(` \u5206\u7C7B: ${n.cate1Name} > ${n.cate2Name} > ${n.cate3Name}`)),console.log()})),o}import{Command as dr}from"commander";import ur from"chalk";st();import{Box as p,Text as y}from"ink";import{jsx as l,jsxs as $}from"react/jsx-runtime";var ir={init:{label:"\u5F85\u4E0A\u67B6",color:"yellow"},up:{label:"\u5DF2\u4E0A\u67B6",color:"green"},down:{label:"\u5DF2\u4E0B\u67B6",color:"gray"},fail:{label:"\u5931\u8D25",color:"red"},sold:{label:"\u5DF2\u552E\u51FA",color:"blue"}},oo=4,eo=8,Tt=12,ro=10,no=6,so=8;function Wo(o,t){return o.length>t?o.slice(0,t-1)+"\u2026":o}function Ho(o){if(!o)return"-";let t=new Date(o),e=r=>String(r).padStart(2,"0");return`${e(t.getMonth()+1)}/${e(t.getDate())} ${e(t.getHours())}:${e(t.getMinutes())}`}function ar({fillWidth:o}){return $(p,{flexDirection:"row",children:[l(p,{width:oo,children:l(y,{bold:!0,color:"white",children:"ID"})}),l(p,{width:eo,children:l(y,{bold:!0,color:"white",children:"\u72B6\u6001"})}),l(p,{width:Tt,children:l(y,{bold:!0,color:"white",children:"\u54C1\u724C"})}),l(p,{width:o,children:l(y,{bold:!0,color:"white",children:"\u5546\u54C1\u540D\u79F0"})}),l(p,{width:ro,children:l(y,{bold:!0,color:"white",children:"\u4EF7\u683C"})}),l(p,{width:no,children:l(y,{bold:!0,color:"white",children:"\u89C4\u683C"})}),l(p,{width:so,children:l(y,{bold:!0,color:"white",children:"\u5E93\u5B58ID"})})]})}function cr({item:o}){return l(p,{flexDirection:"column",children:l(y,{color:"gray",children:` shopId: ${o.shopId} thirdItemNo: ${o.thirdItemNo||"-"} outItemNo: ${o.outItemNo||"-"} \u8D27\u53F7: ${o.goodsNo||"-"} ${o.type||"-"} ${o.platform} \u521B\u5EFA: ${Ho(o.gmtCreate)} \u4FEE\u6539: ${Ho(o.gmtModified)}`})})}function lr({item:o,fillWidth:t}){let e=ir[o.status]??{label:o.status,color:"white"};return $(p,{flexDirection:"column",children:[$(p,{flexDirection:"row",children:[l(p,{width:oo,children:l(y,{color:"gray",children:o.id})}),l(p,{width:eo,children:l(y,{color:e.color,children:e.label})}),l(p,{width:Tt,children:l(y,{color:"cyan",children:Wo(o.brandName||"-",Tt-1)})}),l(p,{width:t,children:l(y,{children:Wo(o.goodsName,t-1)})}),l(p,{width:ro,children:$(y,{color:"yellow",children:["\xA5",o.price]})}),l(p,{width:no,children:l(y,{color:"gray",children:o.spec||"-"})}),l(p,{width:so,children:l(y,{color:"gray",children:o.stockGoodsId})})]}),l(cr,{item:o})]})}function Vo({items:o,total:t}){let e=process.stdout.columns||80,r=4,n=oo+eo+Tt+ro+no+so,s=Math.max(e-r-n,20),i=n+s;return $(p,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,children:[$(p,{flexDirection:"row",children:[l(y,{bold:!0,color:"cyan",children:"\u4E0A\u67B6\u5217\u8868"}),$(y,{color:"gray",children:[" \xB7 \u5171 ",t," \u6761"]})]}),$(p,{flexDirection:"column",marginTop:1,children:[l(ar,{fillWidth:s}),l(y,{color:"gray",children:"\u2500".repeat(i)}),o.map(a=>l(lr,{item:a,fillWidth:s},a.id))]})]})}function Ko(){let o=new dr("listing");return o.description("\u67E5\u8BE2\u4E0A\u67B6\u5546\u54C1\u5217\u8868"),o.option("--id <id>","\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>","\u5E97\u94FA ID").option("--stock-id <id>","\u4ED3\u5E93 ID").option("-s, --status <status>","\u72B6\u6001\u8FC7\u6EE4\uFF08init/up/down/fail/sold\uFF09").option("-p, --platform <platform>","\u5E73\u53F0","xianyu").option("--page <n>","\u9875\u7801","1").option("--size <n>","\u6BCF\u9875\u6570\u91CF\uFF08\u6700\u5927 50\uFF09","20").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(m(async t=>{let r=await No({id:t.id,stockGoodsId:t.stockGoodsId?Number(t.stockGoodsId):void 0,shopId:t.shopId,stockId:t.stockId,status:t.status,platform:t.platform,page:Number(t.page)||1,size:Math.min(Number(t.size)||20,50)})??{items:[],total:0};if(t.json){r.items?.length?console.log(JSON.stringify(r,null,2)):console.log(JSON.stringify({...r,hint:"\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55"},null,2));return}if(!r.items?.length){console.log(ur.yellow("\u6682\u65E0\u4E0A\u67B6\u8BB0\u5F55"));return}Bt(Vo,{items:r.items,total:Number(r.total)})})),o}import{Command as mr}from"commander";import gr from"chalk";function Yo(){let o=new mr("down");return o.description("\u4E0B\u67B6\u95F2\u9C7C\u5546\u54C1"),o.option("--id <id>","\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>","\u5E97\u94FA ID").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(m(async t=>{if(!t.id&&!(t.stockGoodsId&&t.shopId)){P(t,"\u8BF7\u6307\u5B9A\u4E0B\u67B6\u6761\u4EF6\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>");return}let e={};t.id&&(e.id=t.id),t.stockGoodsId&&(e.stockGoodsId=Number(t.stockGoodsId)),t.shopId&&(e.shopId=t.shopId),t.json||console.log(gr.cyan("\u{1F4E6} \u6B63\u5728\u4E0B\u67B6\u5546\u54C1..."));let r=await ko(e);j(t,r,"\u2705 \u4E0B\u67B6\u6210\u529F")})),o}import{Command as pr}from"commander";import fr from"chalk";function Zo(){let o=new pr("price");return o.description("\u4FEE\u6539\u95F2\u9C7C\u4E0A\u67B6\u5546\u54C1\u4EF7\u683C"),o.option("--id <id>","\u4E0A\u67B6\u8BB0\u5F55 ID").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID").option("--shop-id <id>","\u5E97\u94FA ID").option("--price <amount>","\u65B0\u4EF7\u683C\uFF08\u5FC5\u586B\uFF09").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(m(async t=>{if(!t.price){P(t,"--price <amount> \u4E3A\u5FC5\u586B\u53C2\u6570");return}if(!t.id&&!(t.stockGoodsId&&t.shopId)){P(t,"\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <id> \u6216 --stock-goods-id <id> --shop-id <id>");return}let e={price:Number(t.price)};t.id&&(e.id=t.id),t.stockGoodsId&&(e.stockGoodsId=Number(t.stockGoodsId)),t.shopId&&(e.shopId=t.shopId),t.json||console.log(fr.cyan(`\u{1F4B0} \u6B63\u5728\u4FEE\u6539\u4EF7\u683C\u4E3A ${t.price}...`));let r=await Ro(e);j(t,r,"\u2705 \u4EF7\u683C\u4FEE\u6539\u6210\u529F")})),o}import{Command as hr}from"commander";import yr from"chalk";function te(){let o=new hr("edit");return o.description("\u4FEE\u6539\u5DF2\u4E0A\u67B6\u5546\u54C1\u4FE1\u606F\uFF08\u6807\u9898\u3001\u63CF\u8FF0\u3001\u54C1\u724C\u3001\u7C7B\u76EE\u3001\u56FE\u7247\u3001\u5C5E\u6027\u7B49\uFF09"),o.option("--id <id>","\u5546\u54C1\u4E0A\u67B6 ID\uFF08goodsListingId\uFF0C\u63A8\u8350\uFF09").option("--stock-goods-id <id>","\u5E93\u5B58\u5546\u54C1 ID\uFF08\u4E0E --account \u914D\u5408\uFF09").option("--account <shopId>","\u95F2\u9C7C\u7528\u6237\u540D/\u5E97\u94FA ID\uFF08\u4E0E --stock-goods-id \u914D\u5408\uFF09").option("--title <title>","\u5546\u54C1\u6807\u9898").option("--desc <desc>","\u5546\u54C1\u63CF\u8FF0").requiredOption("--category-id <id>","\u5546\u54C1\u7C7B\u76EE ID\uFF08\u5927\u5206\u7C7B\uFF0C\u540E\u7AEF\u5FC5\u586B\uFF09").requiredOption("--channel-cat-id <id>","\u6E20\u9053\u7C7B\u76EE ID\uFF08\u5C0F\u5206\u7C7B\uFF0C\u540E\u7AEF\u5FC5\u586B\uFF09").option("--image-ids <ids>","\u56FE\u7247 ID \u5217\u8868\uFF08\u9017\u53F7\u5206\u9694\uFF09").option("--item-attrs <json>","\u5546\u54C1\u5C5E\u6027\u5217\u8868\uFF08JSON \u5B57\u7B26\u4E32\uFF09").option("--brand-name <name>","\u54C1\u724C\u540D\u79F0").option("--stuff-status <status>","\u6210\u8272\u7B49\u7EA7\uFF1A100=\u5168\u65B0 -1=\u51C6\u65B0 99=99\u65B0 95=95\u65B0 90=9\u65B0").option("--goods-no <no>","\u8D27\u53F7").option("--original-price <price>","\u539F\u4EF7\uFF08\u5355\u4F4D\uFF1A\u5143\uFF09").option("--size <size>","\u5C3A\u7801").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09"),o.action(m(async t=>{if(!t.id&&!(t.stockGoodsId&&t.account)){P(t,"\u8BF7\u6307\u5B9A\u5546\u54C1\uFF1A--id <goodsListingId> \u6216 --stock-goods-id <id> --account <shopId>");return}let e={categoryId:Number(t.categoryId),channelCatId:t.channelCatId};if(t.id&&(e.goodsListingId=Number(t.id)),t.stockGoodsId&&(e.stockGoodsId=Number(t.stockGoodsId)),t.account&&(e.account=t.account),t.title&&(e.title=t.title),t.desc&&(e.desc=t.desc),t.imageIds&&(e.imageIdList=t.imageIds.split(",").map(s=>s.trim())),t.brandName&&(e.brandName=t.brandName),t.stuffStatus&&(e.stuffStatus=Number(t.stuffStatus)),t.goodsNo&&(e.goodsNo=t.goodsNo),t.originalPrice&&(e.originalPrice=Number(t.originalPrice)),t.size&&(e.size=t.size),t.itemAttrs)try{e.itemAttrList=JSON.parse(t.itemAttrs)}catch{P(t,"--item-attrs JSON \u89E3\u6790\u5931\u8D25");return}if(!Object.keys(e).some(s=>!["goodsListingId","stockGoodsId","account"].includes(s))){P(t,"\u672A\u6307\u5B9A\u9700\u8981\u4FEE\u6539\u7684\u5B57\u6BB5");return}t.json||console.log(yr.cyan("\u6B63\u5728\u4FEE\u6539\u5546\u54C1\u4FE1\u606F..."));let n=await Lo(e);j(t,n,"\u2705 \u5546\u54C1\u4FE1\u606F\u4FEE\u6539\u6210\u529F")})),o}import{Command as et}from"commander";import S from"chalk";var wr={100:"\u5168\u65B0",[-1]:"\u51C6\u65B0",99:"99\u65B0",95:"95\u65B0",90:"9\u65B0"};function oe(){let o=new et("hang-up");return o.description("\u95F2\u9C7C\u6302\u552E\u4E0A\u67B6\uFF08\u5B8C\u6574\u5546\u54C1\u4FE1\u606F\u6A21\u5F0F\uFF09"),o.addCommand(new et("categories").description("\u83B7\u53D6\u95F2\u9C7C\u7C7B\u76EE\u5217\u8868\uFF08\u5927\u5206\u7C7B \u2192 \u5C0F\u5206\u7C7B\uFF09").option("--sp-biz-type <n>","\u4E1A\u52A1\u5206\u7C7B\uFF0C16=\u5962\u54C1","16").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(m(async t=>{let e=await Uo(Number(t.spBizType));if(t.json){console.log(JSON.stringify(e,null,2));return}let r=new Map;for(let n of e){let s=String(n.catId);r.has(s)||r.set(s,{catName:n.catName,children:[]}),r.get(s).children.push({channel:n.channel,channelCatId:n.channelCatId})}for(let[n,s]of r){console.log(S.bold(`${s.catName} (catId: ${S.green(n)})`));for(let i of s.children)console.log(` ${i.channel} (channelCatId: ${S.green(i.channelCatId)})`)}}))),o.addCommand(new et("props").description("\u83B7\u53D6\u6307\u5B9A\u7C7B\u76EE\u4E0B\u7684\u5C5E\u6027\u5217\u8868\uFF08\u542B\u53EF\u9009\u503C\uFF09").requiredOption("--channel-cat-id <id>","\u5C0F\u5206\u7C7B ID\uFF08\u4ECE categories \u83B7\u53D6\uFF09").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(m(async t=>{let e=await Eo(t.channelCatId);if(t.json){console.log(JSON.stringify(e,null,2));return}for(let r of e)if(console.log(S.bold(`
|
|
38
|
+
${r.propName} (propId: ${r.propId})`)),r.propsValues?.length)for(let n of r.propsValues)console.log(` ${n.valueName} (valueId: ${n.valueId})`);else console.log(S.gray(" \uFF08\u4F7F\u7528 brands \u5B50\u547D\u4EE4\u641C\u7D22\uFF09"))}))),o.addCommand(new et("brands").description("\u641C\u7D22\u95F2\u9C7C\u54C1\u724C\uFF08\u6309\u5173\u952E\u5B57\u8FC7\u6EE4\uFF09").requiredOption("--channel-cat-id <id>","\u5C0F\u5206\u7C7B ID").requiredOption("--prop-id <id>","\u5C5E\u6027 ID\uFF08\u54C1\u724C\u5C5E\u6027\u7684 propId\uFF09").requiredOption("--key <keyword>","\u641C\u7D22\u5173\u952E\u5B57").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(m(async t=>{let e=await jo(t.channelCatId,t.propId,t.key);if(t.json){console.log(JSON.stringify(e,null,2));return}if(!e.length){console.log(S.yellow("\u672A\u627E\u5230\u5339\u914D\u7684\u54C1\u724C"));return}for(let r of e)console.log(` ${r.valueName} (valueId: ${r.valueId})`)}))),o.addCommand(new et("upload-images").description("\u6279\u91CF\u4E0A\u4F20\u56FE\u7247\u5230\u95F2\u9C7C\uFF08\u6302\u552E\u524D\u5FC5\u987B\u5148\u4E0A\u4F20\u56FE\u7247\uFF09").requiredOption("--shop-id <id>","\u5E97\u94FA ID").requiredOption("--files <paths>","\u56FE\u7247\u6587\u4EF6\u8DEF\u5F84\uFF0C\u9017\u53F7\u5206\u9694").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(m(async t=>{let e=t.files.split(",").map(s=>s.trim()).filter(Boolean);if(e.length===0){P(t,"\u8BF7\u63D0\u4F9B\u81F3\u5C11\u4E00\u5F20\u56FE\u7247");return}t.json||console.log(S.cyan(`\u6B63\u5728\u4E0A\u4F20 ${e.length} \u5F20\u56FE\u7247...`));let{images:r,failed:n}=await Do(t.shopId,e);if(t.json){let s={success:!0,images:r};n.length&&(s.warning=`${n.length} \u5F20\u56FE\u7247\u4E0A\u4F20\u5931\u8D25`,s.failed=n),console.log(JSON.stringify(s,null,2))}else{if(r.length){console.log(S.green(`\u4E0A\u4F20\u6210\u529F\uFF0C\u5171 ${r.length} \u5F20`));for(let s of r)console.log(` \u56FE\u7247ID: ${s.value}`)}if(n.length){console.log(S.yellow(`
|
|
39
|
+
${n.length} \u5F20\u4E0A\u4F20\u5931\u8D25:`));for(let s of n)console.log(` ${s.file}: ${s.error}`)}}}))),o.addCommand(new et("submit").description("\u63D0\u4EA4\u6302\u552E\u4E0A\u67B6").requiredOption("--shop-id <id>","\u5E97\u94FA ID\uFF08\u5373\u95F2\u9C7C\u7528\u6237\u540D account\uFF09").requiredOption("--title <title>","\u5546\u54C1\u6807\u9898").requiredOption("--price <amount>","\u552E\u4EF7").requiredOption("--category-id <id>","\u5927\u5206\u7C7B ID\uFF08\u4ECE categories \u83B7\u53D6\uFF09").requiredOption("--channel-cat-id <id>","\u5C0F\u5206\u7C7B ID\uFF08\u4ECE categories \u83B7\u53D6\uFF09").requiredOption("--image-ids <ids>","\u56FE\u7247 ID \u5217\u8868\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u5148\u901A\u8FC7 upload-images \u83B7\u53D6\uFF09").requiredOption("--stuff-status <n>","\u6210\u8272\uFF1A100 \u5168\u65B0 / -1 \u51C6\u65B0 / 99 99\u65B0 / 95 95\u65B0 / 90 9\u65B0").option("--item-attrs <json>",'\u5546\u54C1\u5C5E\u6027\u5217\u8868 JSON\uFF0C\u683C\u5F0F: [{"valueName":"x","valueId":"y","propId":"z"}]').option("--brand-name <name>","\u54C1\u724C\u540D\u79F0").requiredOption("--desc <desc>","\u5546\u54C1\u63CF\u8FF0").option("--size <size>","\u5C3A\u7801").option("--goods-no <no>","\u8D27\u53F7").option("--original-price <amount>","\u539F\u4EF7").option("--trade-type <n>","\u4EA4\u6613\u65B9\u5F0F\uFF1A0 \u4EC5\u5728\u7EBF / 1 \u4EC5\u7EBF\u4E0B / 2 \u7EBF\u4E0A\u6216\u7EBF\u4E0B","0").option("--transport-fee <amount>","\u8FD0\u8D39\uFF08\u9ED8\u8BA4 0 \u5305\u90AE\uFF09","0").option("--yhb","\u662F\u5426\u5F00\u542F\u9A8C\u8D27\u5B9D").requiredOption("--out-item-no <no>","\u5546\u5BB6\u7F16\u7801\uFF08\u540C\u5E97\u94FA\u552F\u4E00\uFF0C\u7528\u6237\u81EA\u5B9A\u4E49\uFF09").option("--division-id <id>","\u884C\u653F\u533A\u5212 ID\uFF08\u5E02\u7EA7 ID\uFF0C\u9ED8\u8BA4\u676D\u5DDE 330100\uFF09","330100").option("--json","\u8F93\u51FA JSON\uFF08\u4F9B AI Agent \u4F7F\u7528\uFF09").action(m(async t=>{let e=t.imageIds.split(",").map(i=>i.trim()),r=t.itemAttrs?JSON.parse(t.itemAttrs):void 0,n={account:t.shopId,title:t.title,reservePrice:Number(t.price),categoryId:Number(t.categoryId),channelCatId:t.channelCatId,imageIdList:e,stuffStatus:Number(t.stuffStatus),itemBizType:2,spBizType:"16",tradeType:Number(t.tradeType)||0,transportFee:Number(t.transportFee)||0,yhb:t.yhb??!1,...t.brandName&&{brandName:t.brandName},desc:t.desc,...t.size&&{size:t.size},...t.goodsNo&&{goodsNo:t.goodsNo},...t.originalPrice&&{originalPrice:Number(t.originalPrice)},...r?.length&&{itemAttrList:r},outItemNo:t.outItemNo,divisionId:Number(t.divisionId)||330100,apiAfterSalesDo:{supportFd10msPolicy:!1,supportFd24hsPolicy:!1,supportNfrPolicy:!1,supportSdrPolicy:!1,supportVnrPolicy:!1,supportGpaPolicy:!1,supportFd48hsPolicy:!1}};t.json||(console.log(S.cyan("\u6B63\u5728\u63D0\u4EA4\u6302\u552E...")),console.log(S.gray(` \u6807\u9898: ${n.title}`)),console.log(S.gray(` \u552E\u4EF7: \xA5${n.reservePrice}`)),console.log(S.gray(` \u6210\u8272: ${wr[n.stuffStatus]??n.stuffStatus}`)),console.log(S.gray(` \u56FE\u7247: ${e.length} \u5F20`)),r?.length&&console.log(S.gray(` \u5C5E\u6027: ${r.length} \u9879`)));let s=await Oo(n);j(t,s,"\u6302\u552E\u63D0\u4EA4\u6210\u529F")}))),o}function ee(){let o=new xr("goods");return o.description("\u5546\u54C1\u7BA1\u7406"),o.addCommand(Xo()),o.addCommand(zo()),o.addCommand(Fo()),o.addCommand(Ko()),o.addCommand(Yo()),o.addCommand(Zo()),o.addCommand(te()),o.addCommand(Bo()),o.addCommand(oe()),o}import{Command as Ir}from"commander";import O from"chalk";import{promises as Sr}from"node:fs";import Cr from"node:path";import Tr from"node:os";import{spawn as br}from"node:child_process";var bt="@round2ai/r2-cli";function re(){let o=new Ir("uninstall");return o.description("\u5378\u8F7D R2-CLI \u5E76\u6E05\u9664\u6240\u6709\u914D\u7F6E"),o.action(async()=>{try{console.log(O.yellow(`
|
|
39
40
|
\u26A0\uFE0F \u5373\u5C06\u6267\u884C\u4EE5\u4E0B\u64CD\u4F5C\uFF1A`)),console.log(O.gray(" 1. \u5220\u9664\u914D\u7F6E\u76EE\u5F55 ~/.r2-cli/")),console.log(O.gray(` 2. \u5168\u5C40\u5378\u8F7D ${bt}
|
|
40
|
-
`));let{confirm:t}=await import("@inquirer/prompts");if(!await t({message:"\u786E\u8BA4\u5378\u8F7D\uFF1F",default:!1})){console.log(O.gray("\u5DF2\u53D6\u6D88\u5378\u8F7D"));return}let r=
|
|
41
|
+
`));let{confirm:t}=await import("@inquirer/prompts");if(!await t({message:"\u786E\u8BA4\u5378\u8F7D\uFF1F",default:!1})){console.log(O.gray("\u5DF2\u53D6\u6D88\u5378\u8F7D"));return}let r=Cr.join(Tr.homedir(),".r2-cli");try{await Sr.rm(r,{recursive:!0,force:!0}),console.log(O.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u6E05\u9664"))}catch{console.log(O.yellow("\u26A0\uFE0F \u914D\u7F6E\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u65E0\u6CD5\u5220\u9664\uFF08\u53EF\u5FFD\u7565\uFF09"))}console.log(O.cyan(`\u6B63\u5728\u5378\u8F7D ${bt}...`)),br("npm",["uninstall","-g",bt],{stdio:"inherit",shell:!0}).on("exit",s=>{s===0?console.log(O.green(`
|
|
41
42
|
\u2705 ${bt} \u5DF2\u5378\u8F7D`)):(console.log(O.yellow(`
|
|
42
|
-
\u26A0\uFE0F npm \u5378\u8F7D\u5931\u8D25 (exit code: ${s})`)),console.log(O.gray(" \u5982\u901A\u8FC7 yarn/pnpm \u5B89\u88C5\uFF0C\u8BF7\u624B\u52A8\u5378\u8F7D"))),process.exit(s??1)})}catch(t){
|
|
43
|
-
\u2717 update failed \xB7 Try: npm install -g ${
|
|
44
|
-
\u2713 \u66F4\u65B0\u5B8C\u6210: ${o} \u2192 ${e}`)),console.log(
|
|
45
|
-
Update available: ${o} \u2192 ${t}`)+
|
|
43
|
+
\u26A0\uFE0F npm \u5378\u8F7D\u5931\u8D25 (exit code: ${s})`)),console.log(O.gray(" \u5982\u901A\u8FC7 yarn/pnpm \u5B89\u88C5\uFF0C\u8BF7\u624B\u52A8\u5378\u8F7D"))),process.exit(s??1)})}catch(t){X(t)}}),o}import{Command as vr}from"commander";import at from"chalk";import{spawn as kr,execSync as Rr}from"node:child_process";import{readFileSync as Pr}from"node:fs";import{join as Ar}from"node:path";function Pt(){for(let o of["../package.json","../../package.json"])try{return JSON.parse(Pr(Ar(import.meta.dirname,o),"utf-8")).version}catch{}return"0.0.0"}var ne="@round2ai/r2-cli";function Lr(o,t){return new Promise(e=>{let r=kr(o,t,{stdio:"inherit"});r.on("close",n=>e(n??1)),r.on("error",()=>e(1))})}function se(){return new vr("update").description("\u4E00\u952E\u66F4\u65B0 CLI \u548C\u6280\u80FD").action(async()=>{let o=Pt();console.log(at.cyan(`\u5F53\u524D\u7248\u672C: ${o}`)),console.log(at.cyan("\u6B63\u5728\u66F4\u65B0 CLI...")),await Lr("npm",["install","-g",`${ne}@latest`])!==0&&(console.error(at.red(`
|
|
44
|
+
\u2717 update failed \xB7 Try: npm install -g ${ne}@latest`)),process.exit(1));let e=o;try{e=Rr("r2-cli --version",{encoding:"utf-8"}).trim()||o}catch{}console.log(at.green(`
|
|
45
|
+
\u2713 \u66F4\u65B0\u5B8C\u6210: ${o} \u2192 ${e}`)),console.log(at.green("\u2713 \u6280\u80FD\u5DF2\u540C\u6B65\u66F4\u65B0"))})}function ie(o){let t=o.command("auth").description("\u6388\u6743\u7BA1\u7406");t.addCommand(Qt()),t.addCommand(Xt()),t.addCommand(_t()),t.addCommand(Mt()),o.addCommand(ee()),o.addCommand(re()),o.addCommand(se())}import ae from"chalk";var ce="@round2ai/r2-cli",Nr=[`https://registry.npmmirror.com/${encodeURIComponent(ce)}/latest`,`https://registry.npmjs.org/${encodeURIComponent(ce)}/latest`],Dr=5e3;async function Or(o){let t=new AbortController,e=setTimeout(()=>t.abort(),Dr);try{let r=await fetch(o,{signal:t.signal});return r.ok?(await r.json()).version??null:null}catch{return null}finally{clearTimeout(e)}}async function Ur(){let o=await Promise.allSettled(Nr.map(Or));for(let t of o)if(t.status==="fulfilled"&&t.value)return t.value;return null}function Er(o,t){let e=o.split(".").map(Number),r=t.split(".").map(Number);for(let n=0;n<3;n++)if((e[n]??0)!==(r[n]??0))return(e[n]??0)>(r[n]??0);return!1}async function le(o){let t=await Ur();t&&Er(t,o)&&jr(o,t)}function jr(o,t){console.error(ae.yellow(`
|
|
46
|
+
Update available: ${o} \u2192 ${t}`)+ae.gray(`
|
|
46
47
|
Run: r2-cli update
|
|
47
|
-
`))}async function
|
|
48
|
-
`))}function
|
|
49
|
-
\u64CD\u4F5C\u5DF2\u53D6\u6D88`)),process.exit(130)}process.on("SIGINT",
|
|
48
|
+
`))}async function Br(){let{default:o}=await import("figlet");console.log(rt.cyan.bold(o.textSync("R2-CLI",{font:"Standard",horizontalLayout:"full"}))),console.log(rt.gray(` \u5411 AI \u5F00\u653E\u4E8C\u624B\u6F6E\u5962\u4EA4\u6613\u5168\u94FE\u8DEF\u80FD\u529B
|
|
49
|
+
`))}function qr(){let o=new $r;o.name("r2-cli").description("R2-CLI\uFF0C\u5411 AI \u5F00\u653E\u4E8C\u624B\u6F6E\u5962\u4EA4\u6613\u5168\u94FE\u8DEF\u80FD\u529B");let t=Pt();t==="0.0.0"&&console.error(rt.yellow("Warning: unable to read version from package.json")),o.version(t,"-v, --version");let e=le(t);return o.configureOutput({writeErr:r=>{console.error(rt.red(r.replace("error:","").trim()))}}),o.action(async()=>{await Br(),o.help()}),ie(o),{program:o,updateCheckPromise:e}}function de(){console.log(rt.gray(`
|
|
50
|
+
\u64CD\u4F5C\u5DF2\u53D6\u6D88`)),process.exit(130)}process.on("SIGINT",de);process.on("SIGTERM",de);var{program:Gr,updateCheckPromise:Jr}=qr();Gr.parse(process.argv);Jr.catch(o=>{console.error(rt.gray(`[update-check] ${o instanceof Error?o.message:String(o)}`))});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@round2ai/r2-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"description": "R2-CLI,向 AI 开放二手潮奢交易全链路能力",
|
|
5
5
|
"main": "dist/r2-cli.js",
|
|
6
6
|
"type": "module",
|
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
"ink": "^7.0.0",
|
|
50
50
|
"ora": "^9.3.0",
|
|
51
51
|
"qrcode": "^1.5.4",
|
|
52
|
-
"react": "^19.2.5"
|
|
52
|
+
"react": "^19.2.5",
|
|
53
|
+
"sharp": "^0.34.5"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
56
|
"@types/node": "^25.5.2",
|
package/skills/r2-auth/SKILL.md
CHANGED
|
@@ -33,6 +33,8 @@ r2-cli auth login --json
|
|
|
33
33
|
|
|
34
34
|
命令会依次输出两段 JSON:
|
|
35
35
|
|
|
36
|
+
> ⚠️ **命令会自动轮询,不需要(也不应该)手动调用 `auth login poll`。只需等待命令完成即可。**
|
|
37
|
+
|
|
36
38
|
**第 1 段:二维码信息(立即输出)**
|
|
37
39
|
|
|
38
40
|
```json
|
|
@@ -40,7 +42,6 @@ r2-cli auth login --json
|
|
|
40
42
|
"qrToken": "xxx",
|
|
41
43
|
"expireTimeMs": 300000,
|
|
42
44
|
"pollIntervalMs": 800,
|
|
43
|
-
"url": "https://m.puresnake.com/r2/auth/login?qrToken=xxx&from=wechat",
|
|
44
45
|
"qrUrl": "http://127.0.0.1:52173/login/"
|
|
45
46
|
}
|
|
46
47
|
```
|
|
@@ -49,8 +50,9 @@ r2-cli auth login --json
|
|
|
49
50
|
|------|------|
|
|
50
51
|
| `qrToken` | 二维码 token(轮询用,不需要手动使用) |
|
|
51
52
|
| `expireTimeMs` | 二维码过期时间(毫秒),默认 5 分钟 |
|
|
52
|
-
| `
|
|
53
|
-
|
|
53
|
+
| `qrUrl` | 本地扫码页面链接(**请在浏览器中打开此链接**,页面会显示二维码供手机扫描) |
|
|
54
|
+
|
|
55
|
+
> ⚠️ **浏览器可能无法自动打开**:请手动复制 `qrUrl` 在浏览器中打开。用户使用**第二回合 APP / 微信 / 支付宝**扫描页面上的二维码。
|
|
54
56
|
|
|
55
57
|
**第 2 段:登录结果(用户扫码确认后输出)**
|
|
56
58
|
|
|
@@ -60,19 +62,23 @@ r2-cli auth login --json
|
|
|
60
62
|
|
|
61
63
|
### Agent 操作步骤
|
|
62
64
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
> ⚠️ **不要手动轮询**:`auth login --json` 已内置自动轮询,不要用 `auth login poll` 单独轮询。
|
|
66
|
+
> ⚠️ **不要在命令末尾加 `&`**:如果工具已有后台执行选项,不要额外加 `&`,否则输出丢失。
|
|
67
|
+
|
|
68
|
+
1. 启动 `r2-cli auth login --json`(异步/后台执行,设置 5 分钟超时)
|
|
69
|
+
2. 读取命令输出,获取第 1 段 JSON(QR 信息)
|
|
70
|
+
3. **必须先**将 `qrUrl` 以醒目格式展示给用户:
|
|
66
71
|
|
|
67
72
|
```
|
|
68
|
-
|
|
73
|
+
请在浏览器中打开此链接扫码登录:http://127.0.0.1:PORT/login/
|
|
69
74
|
```
|
|
70
75
|
|
|
71
|
-
4.
|
|
72
|
-
5.
|
|
73
|
-
6.
|
|
76
|
+
4. **不要关闭/中断命令** — 命令正在自动轮询,等待用户扫码
|
|
77
|
+
5. 告知用户:用**第二回合 APP / 微信 / 支付宝**扫描页面上的二维码。浏览器会尝试自动打开扫码页面,**如未自动打开请手动复制上方链接在浏览器中打开**
|
|
78
|
+
6. 继续读取命令输出,等待第 2 段 JSON(登录结果,最长 5 分钟)
|
|
79
|
+
7. 检查第 2 段 JSON 的 `success` 字段判断登录是否成功
|
|
74
80
|
|
|
75
|
-
|
|
81
|
+
**为什么必须先展示链接**:浏览器自动打开在 Windows/远程服务器/SSH 环境下经常失败。`qrUrl` 是用户扫码的唯一保障,必须优先展示并提示手动打开。
|
|
76
82
|
|
|
77
83
|
---
|
|
78
84
|
|
|
@@ -107,7 +113,7 @@ r2-cli auth xianyu --json
|
|
|
107
113
|
{ "success": true, "shopId": "...", "shopName": "..." }
|
|
108
114
|
```
|
|
109
115
|
|
|
110
|
-
Agent
|
|
116
|
+
Agent 操作步骤与登录相同:启动命令 → 获取第 1 段 JSON → **先展示 `qrUrl`** → **不要中断命令,等待第 2 段 JSON**。同样不要手动轮询。
|
|
111
117
|
|
|
112
118
|
---
|
|
113
119
|
|
package/skills/r2-goods/SKILL.md
CHANGED
|
@@ -34,7 +34,7 @@ metadata:
|
|
|
34
34
|
|
|
35
35
|
**判断方法**:
|
|
36
36
|
1. 用户**明确指定**了上架方式 → 直接走对应流程
|
|
37
|
-
2. 用户提供了图片文件 → 直接走 `goods hang-up`,Agent 用 Read
|
|
37
|
+
2. 用户提供了图片文件 → 直接走 `goods hang-up`,Agent 用 Read 工具查看图片自动识别商品信息(如果 Read 工具返回 `[Unsupported Image]`,视为不能识别,走询问路径)
|
|
38
38
|
3. 用户只说"上架"未指定方式 → **必须询问用户**:"选品上架还是挂售上架?"
|
|
39
39
|
|
|
40
40
|
## 命令概览
|
|
@@ -46,7 +46,7 @@ metadata:
|
|
|
46
46
|
| `r2-cli goods shops [--json]` | 查看已授权店铺 | [r2-goods-query](references/r2-goods-query.md) |
|
|
47
47
|
| `r2-cli goods stocks [--json]` | 查看仓库 | [r2-goods-query](references/r2-goods-query.md) |
|
|
48
48
|
| `r2-cli goods list [--stock-id <id>] [--json]` | 查看选品商品 | [r2-goods-query](references/r2-goods-query.md) |
|
|
49
|
-
| `r2-cli goods listing [--json]` | 查询上架列表 | [r2-goods-query](references/r2-goods-query.md) |
|
|
49
|
+
| `r2-cli goods listing [--status <up/down/sold>] [--json]` | 查询上架列表 | [r2-goods-query](references/r2-goods-query.md) |
|
|
50
50
|
|
|
51
51
|
### 上架/下架/改价/修改
|
|
52
52
|
|
|
@@ -70,6 +70,8 @@ metadata:
|
|
|
70
70
|
|
|
71
71
|
修改已上架商品的标题、描述、品牌、类目、图片、属性等。
|
|
72
72
|
|
|
73
|
+
> **注意**:`goods edit` 不支持修改价格。改价需单独使用 `r2-cli goods price --id <id> --price <amount>`。
|
|
74
|
+
|
|
73
75
|
**路由决策**:
|
|
74
76
|
|
|
75
77
|
| 用户意图 | 流程 |
|
|
@@ -82,6 +84,7 @@ metadata:
|
|
|
82
84
|
|
|
83
85
|
**关键约束**:
|
|
84
86
|
- `--category-id` 和 `--channel-cat-id` 是**必填的**(后端复用挂售 DTO),即使不改类目也要传当前类目
|
|
87
|
+
- **`--item-attrs` 必须包含 props 中所有属性,不只是修改的那一个**:后端替换整个属性列表,漏传的属性会被清除。调 `goods hang-up props --channel-cat-id <id> --json` 获取全部属性后,改目标值,其他保持原样一并传入
|
|
85
88
|
- Agent 应自动查询类目并匹配,不需要用户手动提供
|
|
86
89
|
- AI 读图识别后填充的字段需展示给用户确认,不能静默覆盖已有信息
|
|
87
90
|
- `--image-ids` 接受已上传的图片 ID,用户给图片文件时需先调 `hang-up upload-images` 上传
|
|
@@ -115,17 +118,28 @@ metadata:
|
|
|
115
118
|
2. **识别商品**:Agent 用 Read 工具查看图片,自动识别品牌/成色/类目/描述。不支持读图的 Agent 走询问路径
|
|
116
119
|
3. **匹配类目**:`hang-up categories --json` → 自动匹配
|
|
117
120
|
4. **匹配属性**:`hang-up props --channel-cat-id <id> --json` → 自动填充。品牌需调 `hang-up brands` 搜索
|
|
118
|
-
5. **汇总展示**:自动填充的字段标 ✅,缺失字段标 ❓
|
|
121
|
+
5. **汇总展示**:自动填充的字段标 ✅,缺失字段标 ❓ 让用户补充。**运费默认包邮(`--transport-fee` 默认 0),需告知用户可修改**
|
|
119
122
|
6. **提交**:`hang-up submit` — 必填:`shop-id`、`title`、`price`、`category-id`、`channel-cat-id`、`image-ids`、`stuff-status`、`desc`、`out-item-no`
|
|
120
123
|
|
|
121
124
|
**核心原则**:**图片里能看到的,就别问用户**。只问价格和商家编码(优先用户自定义,不填则推荐自动生成),其他全部从图片自动提取。
|
|
122
125
|
|
|
123
126
|
**关键注意事项**:
|
|
124
|
-
- **品牌必须双传**:`--brand-name` + itemAttrs 中的一项(含 propId/valueId/valueName
|
|
127
|
+
- **品牌必须双传**:`--brand-name` + itemAttrs 中的一项(含 propId/valueId/valueName/propName/channelCatId),缺一不可。**只要涉及品牌修改,必须同时传 `--item-attrs`,`--item-attrs` 中必须包含 propName 和 channelCatId**
|
|
125
128
|
- **描述自动生成**:品牌+款式+颜色+材质+货号自动组合,不要标记为"需要补充"
|
|
126
129
|
- **季节自动推断**:夹克→春秋季,羽绒服→秋冬季,T恤→夏季等,不需要问用户
|
|
127
130
|
- **尺码/货号从标签读取**:图片中有标签时自动提取,读不到才问用户
|
|
128
131
|
- **标题自动组合**:品牌+款式+颜色+尺码+成色
|
|
132
|
+
- **stuff-status 与 itemAttrs 成色映射**:
|
|
133
|
+
|
|
134
|
+
| stuff-status | itemAttrs 成色 valueName |
|
|
135
|
+
|---|---|
|
|
136
|
+
| `100`(全新) | 全新 |
|
|
137
|
+
| `-1`(准新) | 几乎全新 |
|
|
138
|
+
| `99`(99新) | 几乎全新 |
|
|
139
|
+
| `95`(95新) | 轻微穿着痕迹 |
|
|
140
|
+
| `90`(9新) | 明显穿着痕迹 |
|
|
141
|
+
|
|
142
|
+
> 挂售提交时 `--item-attrs` 中的成色值需要从 props 中取对应 valueId,上面的映射告诉你取哪个 valueName。`--stuff-status` 参数单独传数字值。
|
|
129
143
|
|
|
130
144
|
> Agent 执行具体操作时,用 Read 工具读取对应的 reference 文件获取完整参数和流程说明。
|
|
131
145
|
|
|
@@ -143,5 +157,6 @@ metadata:
|
|
|
143
157
|
| `商品不存在` | edit 用了无效的 `--id` 或商品已被删除 | 确认 listing 列表中的 id 值 |
|
|
144
158
|
| `getCategoryId() is null` | edit 缺少 `--category-id` | 必须传 `--category-id` 和 `--channel-cat-id` |
|
|
145
159
|
| `商家编码重复` | out-item-no 同店铺已存在 | 更换唯一编码 |
|
|
160
|
+
| `该商品已上架` | 挂售已下架商品重新提交时 out-item-no 被占用 | 更换新的 out-item-no |
|
|
146
161
|
| `ITEM_CONDITION_NOT_SUPPORT_SIGN` | 售后服务未开通或品类不支持 | 默认关闭售后 |
|
|
147
162
|
| `轮询超时` | 上架结果查询超时 | 稍后用 `goods listing` 查看 |
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
- 商家编码(`out-item-no`)**优先让用户自定义**,用户不填则推荐自动生成编码(如 `GS20260512-0005`)
|
|
14
14
|
- **必须问用户的条件**:价格(永远无法从图片判断)。其他一切字段都应尝试从图片获取。商家编码优先用户自定义,不填则推荐自动生成
|
|
15
15
|
- **描述必须自动生成**:基于 AI 识别的品牌+款式+颜色+材质+货号自动组合,不要标记为"需要补充"
|
|
16
|
-
- **品牌必须双传**:`--brand-name`(文本字段)+ itemAttrs 中的一项(含 propId/valueId/valueName),缺一不可
|
|
16
|
+
- **品牌必须双传**:`--brand-name`(文本字段)+ itemAttrs 中的一项(含 propId/valueId/valueName/propName/channelCatId),缺一不可
|
|
17
17
|
- **季节自动推断**:根据商品类型推断适用季节(夹克/风衣→春秋季,羽绒服→秋冬季,T恤/短裤→夏季),不需要问用户
|
|
18
18
|
- **尺码/货号从标签读取**:如果图片中有标签/吊牌/水洗标,尝试读取尺码和货号,读不到时才问用户
|
|
19
19
|
- **标题自动组合**:品牌+款式+颜色+尺码+成色,自动组合为标题
|
|
@@ -50,7 +50,22 @@ r2-cli goods hang-up upload-images --shop-id <shopId> --files /path/img1.jpg,/pa
|
|
|
50
50
|
}
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
> 图片路径是用户本地文件路径。`--image-ids` 保持字符串,不要转数字(19 位 ID
|
|
53
|
+
> 图片路径是用户本地文件路径。`--image-ids` 保持字符串,不要转数字(19 位 ID 会精度丢失)。**CLI 自动压缩超过 2MB 的图片**(使用 sharp 渐进式降低 JPEG quality 直到 < 2MB,PNG 自动转 JPEG),原文件不会被修改。多张图片**并行上传**,单张失败自动重试 1 次。
|
|
54
|
+
|
|
55
|
+
返回(部分成功时带 `warning` 和 `failed` 字段):
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"success": true,
|
|
60
|
+
"images": [
|
|
61
|
+
{ "value": "1086608743767730915" }
|
|
62
|
+
],
|
|
63
|
+
"warning": "1 张图片上传失败",
|
|
64
|
+
"failed": [
|
|
65
|
+
{ "file": "d:/path/bad.jpg", "error": "413 Request Entity Too Large" }
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
```
|
|
54
69
|
|
|
55
70
|
**同时尝试识别图片**:如果 Agent 支持多模态(如 Claude Code、Gemini),用 Read 工具查看用户图片文件,识别以下信息。不支持则跳过,全部改为向用户询问。
|
|
56
71
|
|
|
@@ -123,22 +138,29 @@ Agent 遍历所有属性,尽量自动匹配:
|
|
|
123
138
|
|
|
124
139
|
**品牌精确匹配规则**:brands 搜索结果中必须选**完全匹配**的官方名称(如搜 Nike → 只选 `Nike/耐克`,忽略 BACHNIKE、NIKE 7 等)
|
|
125
140
|
|
|
141
|
+
**品牌搜索注意事项**:
|
|
142
|
+
- **支持大小写模糊搜索**:如搜索 `nike` 也能匹配到 `Nike/耐克`,搜索 `louis` 也能匹配到 `Louis Vuitton/路易威登`
|
|
143
|
+
- **搜索结果中选择精确匹配**:如搜 nike 返回多个结果,选官方名称 `Nike/耐克`,忽略 BACHNIKE、NIKE 7 等
|
|
144
|
+
|
|
126
145
|
```bash
|
|
127
146
|
r2-cli goods hang-up brands --channel-cat-id <id> --prop-id <品牌propId> --key "Nike" --json
|
|
128
147
|
```
|
|
129
148
|
|
|
130
|
-
最终构建 `--item-attrs
|
|
149
|
+
最终构建 `--item-attrs`(**5 个字段:valueName、valueId、propId、propName、channelCatId**):
|
|
131
150
|
|
|
132
|
-
**⚠️ 品牌必须同时出现在 itemAttrs 和 --brand-name 中**。只传 `--brand-name` 不会把品牌写入商品属性,品牌必须作为 itemAttrs 的一项传入(含
|
|
151
|
+
**⚠️ 品牌必须同时出现在 itemAttrs 和 --brand-name 中**。只传 `--brand-name` 不会把品牌写入商品属性,品牌必须作为 itemAttrs 的一项传入(含 propId、valueId、valueName、propName、channelCatId)。
|
|
133
152
|
|
|
134
153
|
```json
|
|
135
154
|
[
|
|
136
|
-
{ "
|
|
137
|
-
{ "
|
|
138
|
-
{ "
|
|
155
|
+
{ "valueName": "Nike/耐克", "valueId": "68af4e8f...", "propId": "83b8f62c...", "propName": "品牌", "channelCatId": "f4718bbb..." },
|
|
156
|
+
{ "valueName": "几乎全新", "valueId": "25317efe...", "propId": "3b9f06b2...", "propName": "成色", "channelCatId": "f4718bbb..." },
|
|
157
|
+
{ "valueName": "L", "valueId": "65f57139...", "propId": "6562df9f...", "propName": "尺码", "channelCatId": "f4718bbb..." },
|
|
158
|
+
{ "valueName": "春秋季", "valueId": "3162b94f...", "propId": "be925d4d...", "propName": "适用季节", "channelCatId": "f4718bbb..." }
|
|
139
159
|
]
|
|
140
160
|
```
|
|
141
161
|
|
|
162
|
+
> **注意**:每个属性项包含 `valueName`、`valueId`、`propId`、`propName`、`channelCatId` 五个字段,全部从 `props` 返回的 `propsValues` 中获取。
|
|
163
|
+
|
|
142
164
|
---
|
|
143
165
|
|
|
144
166
|
## 第 3 步:汇总展示 → 补充缺失 → 提交
|
|
@@ -155,8 +177,9 @@ Agent 将所有自动填充和识别结果汇总展示给用户,**一次确认
|
|
|
155
177
|
✅ 款式:运动鞋(图片识别)
|
|
156
178
|
✅ 鞋码:42(图片识别)
|
|
157
179
|
❓ 季节:?(无法识别,请选择:春季/夏季/秋季/冬季/四季)
|
|
180
|
+
📦 运费:默认包邮(如需收运费请告知金额)
|
|
158
181
|
💰 价格:?(必填)
|
|
159
|
-
📋
|
|
182
|
+
📋 商家编码:?(优先自定义,不填自动生成)
|
|
160
183
|
```
|
|
161
184
|
|
|
162
185
|
**处理顺序**:
|
|
@@ -164,7 +187,7 @@ Agent 将所有自动填充和识别结果汇总展示给用户,**一次确认
|
|
|
164
187
|
2. 让用户补充缺失字段(价格、商家编码、无法识别的属性)
|
|
165
188
|
3. 用户确认后直接提交
|
|
166
189
|
|
|
167
|
-
|
|
190
|
+
**所有参数就绪后提交**:
|
|
168
191
|
|
|
169
192
|
```bash
|
|
170
193
|
r2-cli goods hang-up submit \
|
|
@@ -179,7 +202,7 @@ r2-cli goods hang-up submit \
|
|
|
179
202
|
--out-item-no "商家编码" \
|
|
180
203
|
--brand-name "Nike/耐克" \
|
|
181
204
|
--size "42" \
|
|
182
|
-
--item-attrs '[{"
|
|
205
|
+
--item-attrs '[{"valueName":"Nike/耐克","valueId":"品牌valueId","propId":"83b8f62c...","propName":"品牌","channelCatId":"f4718bbb..."},{"valueName":"全新","valueId":"d114e6ab...","propId":"3b9f06b2...","propName":"成色","channelCatId":"f4718bbb..."},{"valueName":"42","valueId":"尺码valueId","propId":"6562df9f...","propName":"尺码","channelCatId":"f4718bbb..."}]' \
|
|
183
206
|
--json
|
|
184
207
|
```
|
|
185
208
|
|
|
@@ -215,6 +238,15 @@ r2-cli goods hang-up submit \
|
|
|
215
238
|
| `--title`(标题) | 图片识别无法生成时 | "商品标题用什么?" |
|
|
216
239
|
| `--desc`(描述) | 图片识别无法生成时 | "商品描述?" |
|
|
217
240
|
|
|
241
|
+
## Agent 常见错误预防
|
|
242
|
+
|
|
243
|
+
- **不要在命令末尾加 `&`**:如果用 `run_in_background: true` 启动命令,不要额外加 `&`,否则 shell 立即返回,无法捕获后续输出
|
|
244
|
+
- **`--image-ids` 保持字符串**:图片 ID 是 19 位数字(如 `"1086608743767730915"`),JavaScript `Number()` 会精度丢失。拼接时用字符串拼接,不要 `parseInt`/`Number`
|
|
245
|
+
- **`--stuff-status` 准新是数字 `-1`**:不是字符串 `"-1"`,直接传 `--stuff-status -1`
|
|
246
|
+
- **`--item-attrs` 传 JSON 字符串**:值必须是 `JSON.stringify()` 后的字符串,不能直接传对象。命令行示例:`--item-attrs '[{"propId":"x","valueId":"y"}]'`
|
|
247
|
+
- **`--files` 和 `--image-ids` 都是逗号分隔**:不要多次传 `--files`,用逗号拼成单个值:`--files a.jpg,b.jpg`
|
|
248
|
+
- **`--category-id` 取 `catId` 不是 `id`**:categories 返回的数据中 `catId`(如 50106003)是真正的类目 ID,`id`(如 865)是自增 ID,不要用错
|
|
249
|
+
|
|
218
250
|
## 必填参数
|
|
219
251
|
|
|
220
252
|
| 参数 | 说明 |
|
|
@@ -274,9 +306,11 @@ r2-cli goods hang-up submit \
|
|
|
274
306
|
| 错误信息 | 原因 | 解决方法 |
|
|
275
307
|
|----------|------|----------|
|
|
276
308
|
| `请提供至少一张图片` | upload-images 无图片 | 提供本地图片路径 |
|
|
309
|
+
| 413 / `图片太大` | 图片超过服务端大小限制 | CLI 自动压缩 > 2MB 的图片,如仍失败请手动压缩 |
|
|
277
310
|
| `请填写有效的商品叶子类目` | category-id 或 channel-cat-id 错误 | 重新查询 categories |
|
|
278
311
|
| `找不到传入的某些图片` | 图片 ID 无效或过期 | 重新上传图片 |
|
|
279
312
|
| `商家编码重复` | out-item-no 同店铺已存在 | 更换唯一编码 |
|
|
313
|
+
| `该商品已上架` | 挂售已下架商品重新提交使用了相同的 out-item-no | 更换新的 out-item-no,或检查 listing 确认该商品是否已在闲鱼端恢复上架 |
|
|
280
314
|
| `ITEM_CONDITION_NOT_SUPPORT_SIGN` | 售后服务未开通或品类不支持 | 默认关闭售后,或在闲鱼 APP 开通对应服务 |
|
|
281
315
|
|
|
282
316
|
## References
|
|
@@ -23,7 +23,24 @@
|
|
|
23
23
|
}
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
状态值:`init`(处理中)、`up`(已上架)、`down`(已下架)、`fail`(失败,查看 `errorMsg
|
|
26
|
+
状态值:`init`(处理中)、`up`(已上架)、`down`(已下架)、`fail`(失败,查看 `errorMsg`)、`sold`(已售出)、`sold`(已售出)
|
|
27
|
+
|
|
28
|
+
## 上架列表返回字段
|
|
29
|
+
|
|
30
|
+
| 字段 | 说明 |
|
|
31
|
+
|------|------|
|
|
32
|
+
| `id` | 上架记录 ID(edit/down/price 的 `--id` 取这个值) |
|
|
33
|
+
| `stockGoodsId` | 库存商品 ID(挂售商品可能为 0) |
|
|
34
|
+
| `shopId` | 店铺 ID |
|
|
35
|
+
| `goodsName` | 商品名称 |
|
|
36
|
+
| `brandName` | 品牌 |
|
|
37
|
+
| `price` | 上架价格 |
|
|
38
|
+
| `status` | 状态:`init`/`up`/`down`/`fail`/`sold`(已售出) |
|
|
39
|
+
| `thirdItemNo` | 平台商品 ID |
|
|
40
|
+
| `outItemNo` | 商家编码 |
|
|
41
|
+
| `spec` | 规格(尺码) |
|
|
42
|
+
| `platform` | 平台(xianyu) |
|
|
43
|
+
| `gmtCreate` / `gmtModified` | 创建/修改时间戳 |
|
|
27
44
|
|
|
28
45
|
## 上架参数
|
|
29
46
|
|
|
@@ -64,6 +81,8 @@ r2-cli goods price --stock-goods-id <id> --shop-id <id> --price <新价格> --js
|
|
|
64
81
|
|
|
65
82
|
修改已上架商品的标题、描述、品牌、类目、图片、属性等。
|
|
66
83
|
|
|
84
|
+
> **注意**:`goods edit` 不支持修改价格。改价需单独使用 `r2-cli goods price --id <id> --price <amount>`。
|
|
85
|
+
|
|
67
86
|
### 定位商品(二选一)
|
|
68
87
|
|
|
69
88
|
| 方式 | 参数 | 推荐度 |
|
|
@@ -71,6 +90,13 @@ r2-cli goods price --stock-goods-id <id> --shop-id <id> --price <新价格> --js
|
|
|
71
90
|
| 上架记录 ID | `--id <goodsListingId>` | 推荐,从 listing 的 id 字段取 |
|
|
72
91
|
| 库存商品 + 店铺 | `--stock-goods-id <id> --account <shopId>` | 备选,挂售商品 stockGoodsId 可能为 0 |
|
|
73
92
|
|
|
93
|
+
### Agent 注意事项
|
|
94
|
+
|
|
95
|
+
- **`--image-ids` 保持字符串**:图片 ID 是 19 位数字,`Number()` 会精度丢失
|
|
96
|
+
- **`--item-attrs` 传 JSON 字符串**:必须是 `JSON.stringify()` 后的结果,不能直接传对象
|
|
97
|
+
- **即使不改类目也要传 `--category-id` 和 `--channel-cat-id`**:后端必填,缺少会报 `getCategoryId() is null`
|
|
98
|
+
- **`--item-attrs` 必须包含 props 中所有属性,不只是修改的那一个**:后端替换整个属性列表,漏传的属性会被清除。从 `goods hang-up props --channel-cat-id <id> --json` 获取全部属性后,修改目标属性的值,其他属性保持原样一并传入
|
|
99
|
+
|
|
74
100
|
### 必填参数
|
|
75
101
|
|
|
76
102
|
| 参数 | 说明 |
|
|
@@ -124,9 +150,11 @@ r2-cli goods edit \
|
|
|
124
150
|
|
|
125
151
|
### 只改文字字段(无图片)
|
|
126
152
|
|
|
153
|
+
> 只改标题/描述等文字字段时,不需要传 `--item-attrs`。**但一旦传了 `--item-attrs`,必须包含 props 中所有属性**,不能只传修改的那一项。
|
|
154
|
+
|
|
127
155
|
```bash
|
|
128
156
|
# 改标题
|
|
129
|
-
r2-cli goods
|
|
157
|
+
r2-cli goods edit --id 5 \
|
|
130
158
|
--category-id 50106003 --channel-cat-id "f4718bbb04d7ed1facde29f76907b07f" \
|
|
131
159
|
--title "新标题" --json
|
|
132
160
|
|
|
@@ -135,3 +163,5 @@ r2-cli goods edit --id 5 \
|
|
|
135
163
|
--category-id 50106003 --channel-cat-id "f4718bbb04d7ed1facde29f76907b07f" \
|
|
136
164
|
--brand-name "Nike" --desc "全新描述" --json
|
|
137
165
|
```
|
|
166
|
+
|
|
167
|
+
> **注意**:改品牌时建议同时传 `--item-attrs`(含所有属性,品牌项用最新 valueId),因为只传 `--brand-name` 可能不会更新属性列表中的品牌值。
|
|
@@ -36,7 +36,7 @@ r2-cli goods list --stock-id <stockId> --json
|
|
|
36
36
|
r2-cli goods list --stock-goods-id <id> --json
|
|
37
37
|
|
|
38
38
|
# 翻页
|
|
39
|
-
r2-cli goods list --stock-id <stockId> --page 2 --size
|
|
39
|
+
r2-cli goods list --stock-id <stockId> --page 2 --size 50 --json
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
返回字段:
|
|
@@ -59,6 +59,7 @@ r2-cli goods listing --status sold --json # 只看已售出
|
|
|
59
59
|
r2-cli goods listing --shop-id <id> --json # 按店铺过滤
|
|
60
60
|
r2-cli goods listing --stock-goods-id <id> --json # 按商品过滤
|
|
61
61
|
r2-cli goods listing --id <id> --json # 精确查询
|
|
62
|
+
r2-cli goods listing --page 2 --size 50 --json # 翻页
|
|
62
63
|
```
|
|
63
64
|
|
|
64
|
-
过滤参数:`--id`、`--stock-goods-id`、`--shop-id`、`--stock-id`、`--status`(init/up/down/fail/sold)、`--platform
|
|
65
|
+
过滤参数:`--id`、`--stock-goods-id`、`--shop-id`、`--stock-id`、`--status`(init/up/down/fail/sold)、`--platform`、`--page`(默认 1)、`--size`(默认 20,最大 50)
|
|
@@ -28,6 +28,7 @@ metadata:
|
|
|
28
28
|
- 所有命令**必须**通过已安装的 `r2-cli` 二进制执行(`r2-cli goods ...`、`r2-cli auth ...`)
|
|
29
29
|
- **禁止**读取项目源码或用 `tsx`/`node` 直接运行源文件
|
|
30
30
|
- 如果 `r2-cli` 命令不可用,提示用户先安装:`npm install -g @round2ai/r2-cli@latest`
|
|
31
|
+
- **不要在命令末尾加 `&`**:如果用 Bash 工具的 `run_in_background: true`,不要额外加 `&`,否则 shell 立即返回导致输出丢失
|
|
31
32
|
|
|
32
33
|
**版本检查**:
|
|
33
34
|
- 首次使用时,Agent 应运行 `r2-cli --version` 检查当前版本
|
|
@@ -66,7 +67,7 @@ npm install -g @round2ai/r2-cli@latest
|
|
|
66
67
|
| 查询 | `r2-cli goods shops [--json]` | 查看已授权店铺 |
|
|
67
68
|
| | `r2-cli goods stocks [--json]` | 查看仓库 |
|
|
68
69
|
| | `r2-cli goods list [--stock-id <id>] [--json]` | 查看选品商品 |
|
|
69
|
-
| | `r2-cli goods listing [--json]` | 查询上架列表 |
|
|
70
|
+
| | `r2-cli goods listing [--status <up/down/sold>] [--json]` | 查询上架列表 |
|
|
70
71
|
| 上架 | `r2-cli goods up --stock-goods-id <> --shop-id <> --price <> --json` | 普通上架(选品商品) |
|
|
71
72
|
| | `r2-cli goods down --id <id> [--json]` | 下架商品 |
|
|
72
73
|
| | `r2-cli goods price --id <id> --price <amount> [--json]` | 修改价格 |
|