@xbongbong/xbbcli 2.4.5 → 2.4.6

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.
Files changed (258) hide show
  1. package/README.md +15 -4
  2. package/business-info-detail.js +126 -0
  3. package/business-info-search.js +95 -0
  4. package/buyer-inquiry-detail.js +16 -47
  5. package/buyer-inquiry-list.js +18 -56
  6. package/clue-add-couser.js +14 -39
  7. package/clue-add.js +15 -41
  8. package/clue-back.js +14 -39
  9. package/clue-del.js +14 -39
  10. package/clue-delete-couser.js +14 -39
  11. package/clue-delete-mainuser.js +14 -39
  12. package/clue-detail.js +15 -40
  13. package/clue-distribution.js +14 -43
  14. package/clue-edit.js +15 -41
  15. package/clue-handover.js +15 -45
  16. package/clue-list.js +18 -61
  17. package/clue-thorough-delete.js +14 -39
  18. package/communicate-add.js +15 -56
  19. package/communicate-del.js +17 -59
  20. package/communicate-detail.js +15 -56
  21. package/communicate-edit.js +15 -56
  22. package/communicate-list.js +17 -62
  23. package/communicate-plan-add.js +16 -42
  24. package/communicate-plan-cancel.js +14 -40
  25. package/communicate-plan-del.js +14 -40
  26. package/communicate-plan-detail.js +15 -41
  27. package/communicate-plan-list.js +18 -46
  28. package/communicate-plan-single-operate.js +14 -39
  29. package/contact-add-couser.js +14 -39
  30. package/contact-add-mainuser.js +14 -39
  31. package/contact-add.js +15 -51
  32. package/contact-del.js +15 -38
  33. package/contact-delete-couser.js +14 -39
  34. package/contact-delete-mainuser.js +14 -39
  35. package/contact-detail.js +15 -38
  36. package/contact-edit.js +14 -47
  37. package/contact-handover.js +14 -39
  38. package/contact-list.js +37 -61
  39. package/contract-add-couser.js +16 -58
  40. package/contract-add-mainuser.js +16 -58
  41. package/contract-add.js +15 -57
  42. package/contract-del.js +17 -58
  43. package/contract-delete-couser.js +16 -57
  44. package/contract-delete-mainuser.js +16 -58
  45. package/contract-detail.js +15 -57
  46. package/contract-edit.js +15 -57
  47. package/contract-handover.js +15 -56
  48. package/contract-list.js +18 -61
  49. package/contract-outstock-add.js +15 -46
  50. package/contract-outstock-del.js +15 -41
  51. package/contract-outstock-detail.js +15 -41
  52. package/contract-outstock-edit.js +15 -46
  53. package/contract-outstock-list.js +18 -46
  54. package/customer-add-couser.js +13 -54
  55. package/customer-add.js +15 -58
  56. package/customer-back.js +15 -57
  57. package/customer-del.js +17 -58
  58. package/customer-delete-couser.js +16 -57
  59. package/customer-delete-mainuser.js +16 -58
  60. package/customer-detail.js +13 -54
  61. package/customer-distribution.js +15 -57
  62. package/customer-edit.js +13 -53
  63. package/customer-handover.js +15 -56
  64. package/customer-invoice-address-add.js +15 -41
  65. package/customer-invoice-address-edit.js +15 -40
  66. package/customer-invoice-address.js +17 -42
  67. package/customer-invoice-info-add.js +15 -41
  68. package/customer-invoice-info-edit.js +15 -40
  69. package/customer-invoice-info.js +17 -42
  70. package/customer-list.js +18 -61
  71. package/department-add.js +14 -39
  72. package/department-del.js +14 -40
  73. package/department-edit.js +14 -39
  74. package/department-list.js +17 -59
  75. package/form-data-add-couser.js +14 -39
  76. package/form-data-add-mainuser.js +14 -39
  77. package/form-data-add.js +13 -54
  78. package/form-data-del.js +13 -53
  79. package/form-data-delete-couser.js +14 -40
  80. package/form-data-delete-mainuser.js +14 -39
  81. package/form-data-detail.js +13 -54
  82. package/form-data-edit.js +13 -54
  83. package/form-data-handover.js +14 -39
  84. package/form-data-list.js +37 -63
  85. package/form-get.js +13 -53
  86. package/form-list.js +19 -66
  87. package/hkh-call-add-task.js +14 -44
  88. package/hkh-word-list.js +16 -44
  89. package/invoice-add.js +15 -45
  90. package/invoice-cancel.js +14 -44
  91. package/invoice-del.js +15 -45
  92. package/invoice-detail.js +15 -45
  93. package/invoice-edit.js +15 -45
  94. package/invoice-get-amount-detail.js +14 -44
  95. package/invoice-list.js +18 -50
  96. package/invoice-red.js +15 -45
  97. package/label-add.js +14 -44
  98. package/label-all-list.js +16 -44
  99. package/label-batch-add.js +14 -44
  100. package/label-batch-remove.js +14 -44
  101. package/label-del-completely.js +14 -44
  102. package/label-del.js +15 -45
  103. package/label-edit.js +14 -44
  104. package/label-group-add.js +15 -45
  105. package/label-group-del.js +15 -45
  106. package/label-group-list.js +16 -44
  107. package/label-group-update.js +15 -45
  108. package/label-list.js +16 -44
  109. package/label-reduction.js +15 -45
  110. package/label-repeat.js +15 -45
  111. package/market-activity-add.js +14 -49
  112. package/market-activity-del.js +15 -46
  113. package/market-activity-detail.js +15 -45
  114. package/market-activity-edit.js +15 -46
  115. package/market-activity-handover.js +14 -40
  116. package/market-activity-list.js +18 -46
  117. package/opportunity-add-couser.js +16 -58
  118. package/opportunity-add-mainuser.js +16 -58
  119. package/opportunity-add.js +15 -56
  120. package/opportunity-del.js +17 -59
  121. package/opportunity-delete-couser.js +16 -58
  122. package/opportunity-delete-mainuser.js +16 -57
  123. package/opportunity-detail.js +15 -58
  124. package/opportunity-edit.js +15 -56
  125. package/opportunity-handover.js +15 -57
  126. package/opportunity-list.js +40 -65
  127. package/orginal-text-list.js +16 -61
  128. package/package.json +8 -1
  129. package/pay-plan-add-couser.js +14 -41
  130. package/pay-plan-add-mainuser.js +14 -41
  131. package/pay-plan-add.js +15 -46
  132. package/pay-plan-delete-couser.js +14 -40
  133. package/pay-plan-delete-mainuser.js +14 -40
  134. package/pay-plan-handover.js +14 -40
  135. package/pay-sheet-add-bad.js +15 -46
  136. package/pay-sheet-add-couser.js +14 -40
  137. package/pay-sheet-add-mainuser.js +14 -41
  138. package/pay-sheet-add-red.js +15 -46
  139. package/pay-sheet-add-write-off.js +15 -46
  140. package/pay-sheet-del.js +14 -48
  141. package/pay-sheet-delete-couser.js +14 -40
  142. package/pay-sheet-delete-mainuser.js +14 -41
  143. package/pay-sheet-detail.js +15 -46
  144. package/pay-sheet-edit-bad.js +14 -49
  145. package/pay-sheet-edit-red.js +14 -49
  146. package/pay-sheet-edit-write-off.js +15 -46
  147. package/pay-sheet-get-amount-detail.js +14 -44
  148. package/pay-sheet-list.js +18 -46
  149. package/payment-add-couser.js +16 -58
  150. package/payment-add-mainuser.js +16 -58
  151. package/payment-add.js +15 -56
  152. package/payment-del.js +17 -58
  153. package/payment-delete-couser.js +16 -57
  154. package/payment-delete-mainuser.js +16 -57
  155. package/payment-detail.js +15 -56
  156. package/payment-edit.js +15 -56
  157. package/payment-handover.js +15 -57
  158. package/payment-list.js +37 -61
  159. package/payment-sheet-add-bad-debt.js +15 -57
  160. package/payment-sheet-add-pre.js +15 -46
  161. package/payment-sheet-add-red.js +15 -57
  162. package/payment-sheet-add-write-off.js +15 -52
  163. package/payment-sheet-del.js +17 -53
  164. package/payment-sheet-detail.js +15 -52
  165. package/payment-sheet-edit-bad-debt.js +15 -51
  166. package/payment-sheet-edit-red.js +15 -56
  167. package/payment-sheet-edit-write-off.js +15 -56
  168. package/payment-sheet-get-amount-detail.js +14 -45
  169. package/payment-sheet-handover.js +14 -40
  170. package/payment-sheet-list.js +37 -60
  171. package/product-add.js +15 -51
  172. package/product-category-add.js +13 -48
  173. package/product-category-del.js +13 -53
  174. package/product-category-list.js +17 -60
  175. package/product-category-update.js +13 -54
  176. package/product-del.js +17 -53
  177. package/product-detail.js +13 -54
  178. package/product-edit.js +15 -51
  179. package/product-list.js +37 -63
  180. package/product-online.js +14 -44
  181. package/quotation-add-couser.js +15 -45
  182. package/quotation-add-mainuser.js +15 -45
  183. package/quotation-add.js +15 -45
  184. package/quotation-del.js +15 -45
  185. package/quotation-delete-couser.js +15 -45
  186. package/quotation-delete-mainuser.js +15 -45
  187. package/quotation-detail.js +15 -45
  188. package/quotation-edit.js +15 -45
  189. package/quotation-handover.js +14 -39
  190. package/quotation-list.js +18 -50
  191. package/refund-add.js +15 -39
  192. package/refund-del.js +15 -38
  193. package/refund-detail.js +15 -39
  194. package/refund-edit.js +15 -39
  195. package/refund-list.js +37 -61
  196. package/role-list.js +18 -46
  197. package/sign-in-list.js +21 -49
  198. package/stage-get.js +16 -42
  199. package/stage-jump.js +15 -49
  200. package/supplier-add.js +15 -57
  201. package/token-del.js +1 -1
  202. package/token-list.js +20 -1
  203. package/token-set.js +1 -1
  204. package/token-use.js +2 -35
  205. package/user-add.js +14 -39
  206. package/user-del.js +14 -40
  207. package/user-edit.js +14 -40
  208. package/user-handover.js +14 -40
  209. package/user-list.js +16 -62
  210. package/work-order-add.js +13 -54
  211. package/work-order-asset-add-couser.js +15 -45
  212. package/work-order-asset-add-mainuser.js +15 -45
  213. package/work-order-asset-add.js +15 -45
  214. package/work-order-asset-del-couser.js +15 -45
  215. package/work-order-asset-del-mainuser.js +15 -45
  216. package/work-order-asset-del.js +15 -45
  217. package/work-order-asset-detail.js +15 -45
  218. package/work-order-asset-edit.js +15 -45
  219. package/work-order-asset-handover.js +15 -45
  220. package/work-order-asset-list.js +18 -50
  221. package/work-order-del.js +13 -54
  222. package/work-order-detail.js +13 -53
  223. package/work-order-dynamic-list.js +18 -56
  224. package/work-order-edit.js +13 -54
  225. package/work-order-list.js +17 -59
  226. package/work-order-operate.js +13 -54
  227. package/work-order-template-detail.js +13 -54
  228. package/work-order-template-list.js +17 -60
  229. package/work-report-daily-add.js +14 -39
  230. package/work-report-daily-del.js +14 -39
  231. package/work-report-daily-detail.js +15 -40
  232. package/work-report-daily-edit.js +17 -52
  233. package/work-report-daily-get-work-plan.js +14 -40
  234. package/work-report-daily-list.js +18 -45
  235. package/work-report-monthly-add.js +14 -40
  236. package/work-report-monthly-del.js +14 -43
  237. package/work-report-monthly-detail.js +15 -40
  238. package/work-report-monthly-edit.js +15 -40
  239. package/work-report-monthly-list.js +18 -45
  240. package/work-report-weekly-add.js +14 -40
  241. package/work-report-weekly-del.js +14 -40
  242. package/work-report-weekly-detail.js +15 -41
  243. package/work-report-weekly-edit.js +15 -41
  244. package/work-report-weekly-list.js +18 -45
  245. package/work-task-add-couser.js +14 -43
  246. package/work-task-add.js +15 -41
  247. package/work-task-delete-couser.js +14 -40
  248. package/work-task-detail.js +15 -40
  249. package/work-task-edit.js +14 -39
  250. package/work-task-handover.js +14 -40
  251. package/workorder-add-couser.js +16 -57
  252. package/workorder-delete-couser.js +16 -58
  253. package/workorder-handover.js +17 -58
  254. package/workorderlist.js +38 -60
  255. package/workorderproductlist.js +18 -59
  256. package/worktimerecorddetail.js +13 -54
  257. package/worktimerecordlist.js +18 -59
  258. package/xbb-http.js +71 -0
package/README.md CHANGED
@@ -203,7 +203,7 @@ note config.env 中存在 2 个 enable=true,仅第一条生效,请用 x
203
203
  - Windows:用 `setx` 写入用户级环境变量,**只对新开的终端生效**
204
204
  - macOS/Linux:写入 `~/.xbbcli/env.sh`(`export` 形式,权限 600),需要 `source ~/.xbbcli/env.sh` 才在当前 shell 生效
205
205
 
206
- `token-list` 会把环境变量行(`source=env`)与 `config.env` 中的公司行(`source=config`)一起列出:环境变量行在 `msg` 列标注「XBB_* 环境变量存在(仅供外部系统,业务命令不再读取)」,`config.env` 的启用行固定标注「来源为 config.env,当前生效」;`token-use` 在切换 `config.env` 启用公司的同时,若检测到 `XBB_*` 有值,会把该公司凭证同步写回环境变量(目标公司缺 `token` 时拒绝切换,避免残留旧 `XBB_TOKEN`),便于外部系统跟随切换;`token-del` 默认在删除公司的同时一并删除 `XBB_*` 环境变量(`--env 0` 可保留),并在 `message` 说明删除后的实际生效来源。
206
+ `token-list` 会把环境变量行(`source=env`)与 `config.env` 中的公司行(`source=config`)一起列出:环境变量行在 `msg` 列标注「XBB_* 环境变量存在(仅供外部系统,业务命令不再读取)」,`config.env` 的启用行固定标注「来源为 config.env,当前生效」;`token-use` 只切换 `config.env` 中的启用公司,不读写 `XBB_*` 环境变量;`token-del` 默认在删除公司的同时一并删除 `XBB_*` 环境变量(`--env 0` 可保留),并在 `message` 说明删除后的实际生效来源。
207
207
 
208
208
  > 注意:`token-del --env 0` 保留环境变量时,`XBB_*` 仍会存在(仅供外部系统使用;业务命令不再读取),`message` 会给出提示;要连环境变量一起清理,用 `token-del` 默认行为(不传 `--env`)或执行 `xbbcli auth-logout`(默认就会清除 `XBB_*`);也可以手工执行 `setx XBB_TOKEN ""`(其余 `XBB_*` 同理,Windows 需重开终端)或删除 `~/.xbbcli/env.sh` 并 `unset` 当前 shell 中已导出的变量。
209
209
 
@@ -216,8 +216,8 @@ note config.env 中存在 2 个 enable=true,仅第一条生效,请用 x
216
216
  - `auth-logout`:删除 `config.env` 中 `enable=true` 的那一条配置,删除前整份备份为 `~/.xbbcli/config.env.bak`;不自动把其他公司提升为启用;默认同时清除 `XBB_*` 环境变量(`--env 0` 跳过,返回 `envStored` / `envFile`);既无启用公司又无环境变量时返回 `NO_ACTIVE_CONFIG` 且不改动文件
217
217
  - `auth-refresh-cache`:对当前启用公司重新拉取表单缓存、命令映射与部门/员工缓存,并回填 `corpName` / `userName`;失败时返回 `code=CACHE_REFRESH_FAILED`,`message` 注明中断步骤(`formlist` / `command-map` / `department-user` / `profile`),已完成的部分照常输出;支持 `--userId`、`--debug`
218
218
  - `token-set`:保存个人 token、`corpid`、`userId`、`baseurl`,并刷新本地表单缓存、命令映射文件与部门/员工缓存;传入的 token 不以 `user_` 开头时,会先为该 `userId` 刷新并保存个人 token;`--env` 控制存储方式:`0`(默认)仅写入本地文件,`1` 仅写入 `XBB_*` 环境变量(供外部系统使用,本 CLI 不读取;Windows 用 `setx`,其他平台写 `~/.xbbcli/env.sh`)且不写任何本地文件;返回 `envStored` / `envFile` 两列
219
- - `token-list`:同时列出环境变量行(`source=env`,仅 `XBB_CORPID` / `XBB_TOKEN` 有值时出现,`msg` 标注「仅供外部系统,业务命令不再读取」)与 `config.env` 中保存的全部公司(`source=config`,含 `corpName` 公司名称与 `userName` 操作人姓名),config 启用行在 `msg` 列标注「来源为 config.env,当前生效」;`--showToken` 显示完整 token(默认脱敏)
220
- - `token-use`:切换当前启用的公司(`xbbcli token-use --corpid <CORPID>`),保证仅且只有一个公司被启用;若环境变量 `XBB_*` 有值,同时把该公司凭证(`corpid`/`token`/`baseurl`/`userId`/`corpName`/`userName`,缺 `baseurl` 时按 `corpid` 推导)同步写回环境变量(供外部系统使用,本 CLI 不读取)——Windows 用 `setx`(需重开终端)、macOS/Linux 写 `~/.xbbcli/env.sh`(需重新 `source`);同步失败时返回 `status=partial`,目标公司缺 `token` 时返回错误且不改动任何配置
219
+ - `token-list`:同时列出环境变量行(`source=env`,仅 `XBB_CORPID` / `XBB_TOKEN` 有值时出现,`msg` 标注「仅供外部系统,业务命令不再读取」)与 `config.env` 中保存的全部公司(`source=config`,含 `corpName` 公司名称与 `userName` 操作人姓名),config 启用行在 `msg` 列标注「来源为 config.env,当前生效」;`--showToken` 显示完整 token(默认脱敏);`--raw` 输出本地配置原文(token 仍按 `--showToken` 决定是否掩码)
220
+ - `token-use`:切换当前启用的公司(`xbbcli token-use --corpid <CORPID>`),保证仅且只有一个公司被启用;只改动 `config.env`,不读写 `XBB_*` 环境变量
221
221
  - `token-del`:删除指定公司的本地配置(`xbbcli token-del --corpid <CORPID>`),并保证剩余配置中仅且只有一个公司被启用;默认同时删除 `XBB_*` 环境变量(`--env 0` 保留,返回 `envStored` / `envFile` 两列)
222
222
  - `token-generate`:生成/获取个人 token,`--resetToken 0` 获取(默认)、`1` 刷新;`--checkUserId` 未传则用配置中的 `userId`
223
223
 
@@ -234,6 +234,11 @@ note config.env 中存在 2 个 enable=true,仅第一条生效,请用 x
234
234
  - `department-del`:删除部门
235
235
  - `role-list`:角色列表
236
236
 
237
+ ### 企业工商信息
238
+
239
+ - `business-info-search`:按关键词搜索企业,返回企业准确全称与 `pid`(供 `business-info-detail` 使用)
240
+ - `business-info-detail`:按 `pid` 查询企业工商登记信息,key/value 逐字段回显;`dateOfEstablishment` / `approvalDate` / `cancellationDate` 等时间戳转为 `YYYY-MM-DD`(UTC+8),`registeredAddress` / `shareholder` 为 JSON 字符串
241
+
237
242
  ### CRM 主数据
238
243
 
239
244
  - `customer-list`:客户列表
@@ -472,7 +477,6 @@ note config.env 中存在 2 个 enable=true,仅第一条生效,请用 x
472
477
  - 当前公司名称存在 `~/.xbbcli/config.env` 的 `corpName` 字段(取部门 `id` 为 `1` 的部门名称),操作人姓名存在 `userName` 字段(按 `userId` 匹配员工列表)
473
478
  - 未传入的可选参数不会进入请求体
474
479
  - `--attr` 和 `--value` 只有同时提供时才会拼入查询条件
475
- - `--limit` 是在响应映射之后截断结果
476
480
  - 失败时返回的是带 `code` / `msg` 的结果行,不抛异常
477
481
  - 加 `--debug` 可以输出 `requestBody` 和 `responseBody`
478
482
  - 加 `--raw` 可以输出接口返回的原始 JSON 字符串(所有 list 命令均支持)
@@ -520,6 +524,13 @@ xbbcli customer-detail --dataId 310992
520
524
  xbbcli customer-add-couser --dataId 310995 --businessUserIdList '["xbbTest002"]'
521
525
  ```
522
526
 
527
+ ### 企业工商信息
528
+
529
+ ```bash
530
+ xbbcli business-info-search --keyword 杭州逍邦网络科技有限公司
531
+ xbbcli business-info-detail --pid 5bb73e72a9ae9a0318fd95ce
532
+ ```
533
+
523
534
  ### 表单模型/业务数据
524
535
 
525
536
  ```bash
@@ -0,0 +1,126 @@
1
+ import { cli, Strategy } from './xbb-registry.js';
2
+ import { getRuntimeConfig, requestGateway } from './xbb-http.js';
3
+
4
+ const BUSINESS_INFO_GET_API_PATH = '/pro/v2/api/businessInfo/getInfo';
5
+ const MISSING_TOKEN_MESSAGE = '缺少 token;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>';
6
+
7
+ // 回显固定为 key/value 两列,逐字段列出工商登记信息;kind 决定取值与格式化方式
8
+ const FIELDS = [
9
+ ['enterpriseName', 'text'],
10
+ ['pid', 'pid'],
11
+ ['operatingState', 'text'],
12
+ ['legalRepresentative', 'text'],
13
+ ['registeredCapital', 'text'],
14
+ ['unifySocialCreditCode', 'text'],
15
+ ['registrationNumber', 'text'],
16
+ ['organizationCode', 'text'],
17
+ ['enterpriseType', 'text'],
18
+ ['companySize', 'text'],
19
+ ['securitySize', 'text'],
20
+ ['dateOfEstablishment', 'date'],
21
+ ['approvalDate', 'date'],
22
+ ['operatingPeriod', 'text'],
23
+ ['cancellationDate', 'date'],
24
+ ['registrationAuthority', 'text'],
25
+ ['provinceCity', 'text'],
26
+ ['registeredAddress', 'json'],
27
+ ['mailingAddress', 'text'],
28
+ ['business', 'text'],
29
+ ['scopeOfBusiness', 'text'],
30
+ ['annualTurnover', 'text'],
31
+ ['shareholder', 'json'],
32
+ ['historyName', 'text'],
33
+ ];
34
+
35
+ function buildPayload(kwargs, corpid) {
36
+ return {
37
+ pid: String(kwargs.pid || '').trim(),
38
+ corpid,
39
+ };
40
+ }
41
+
42
+ function getValidationError(payload, token) {
43
+ if (!payload.pid) {
44
+ return { code: 'NO_PID', msg: '缺少 --pid' };
45
+ }
46
+
47
+ if (!payload.corpid) {
48
+ return { code: 'NO_CORPID', msg: '缺少本地 corpid;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>' };
49
+ }
50
+
51
+ if (!token) {
52
+ return { code: 'NO_TOKEN', msg: MISSING_TOKEN_MESSAGE };
53
+ }
54
+
55
+ return null;
56
+ }
57
+
58
+ // 接口按 UTC+8 零点存储秒级时间戳(如 1426435200 → 2015-03-16),0/空表示无值
59
+ function fmtDate(value) {
60
+ const seconds = Number(value || 0);
61
+ if (!seconds) return '';
62
+ return new Date((seconds + 8 * 3600) * 1000).toISOString().slice(0, 10);
63
+ }
64
+
65
+ function fieldValue(data, field, kind) {
66
+ if (kind === 'pid') {
67
+ return data.id == null ? '' : String(data.id);
68
+ }
69
+ const value = data[field];
70
+ if (kind === 'date') return fmtDate(value);
71
+ if (kind === 'json') return value == null ? '' : JSON.stringify(value);
72
+ return value == null ? '' : String(value);
73
+ }
74
+
75
+ function makeErrorRow(code, msg) {
76
+ return [{ key: code, value: msg }];
77
+ }
78
+
79
+ function makeSuccessRows(data) {
80
+ return FIELDS.map(([field, kind]) => ({ key: field, value: fieldValue(data, field, kind) }));
81
+ }
82
+
83
+ cli({
84
+ site: 'xbb',
85
+ name: 'business-info-detail',
86
+ description: '按 pid 查询企业工商登记信息(需购买工商查询服务方可调用)',
87
+ strategy: Strategy.PUBLIC,
88
+ access: 'read',
89
+ browser: false,
90
+ domain: 'proapi.xbongbong.com',
91
+ args: [
92
+ { name: 'pid', type: 'str', help: '企业 pid(必填,由 business-info-search 获取)' },
93
+ { name: 'debug', type: 'bool', default: false, help: '输出请求体和返回体调试信息' },
94
+ ],
95
+ columns: ['key', 'value'],
96
+ func: async function (kwargs) {
97
+ const debug = Boolean(kwargs.debug);
98
+ const { corpid, token, baseUrl, userId } = getRuntimeConfig();
99
+ const payload = buildPayload(kwargs, corpid);
100
+
101
+ const validationError = getValidationError(payload, token);
102
+ if (validationError) {
103
+ return makeErrorRow(validationError.code, validationError.msg);
104
+ }
105
+
106
+ const gateway = await requestGateway({
107
+ baseUrl,
108
+ apiPath: BUSINESS_INFO_GET_API_PATH,
109
+ payload,
110
+ token,
111
+ userId,
112
+ debug,
113
+ });
114
+ if (!gateway.ok) return makeErrorRow(gateway.code, gateway.msg);
115
+ if (gateway.data.code !== 1) {
116
+ return makeErrorRow(gateway.data.code ?? '', gateway.data.msg ?? '未知错误');
117
+ }
118
+
119
+ const result = gateway.data.result?.data;
120
+ if (!result || typeof result !== 'object') {
121
+ return makeErrorRow('NO_DATA', '接口成功,但工商信息为空');
122
+ }
123
+
124
+ return makeSuccessRows(result);
125
+ },
126
+ });
@@ -0,0 +1,95 @@
1
+ import { cli, Strategy } from './xbb-registry.js';
2
+ import { getRuntimeConfig, requestGateway } from './xbb-http.js';
3
+
4
+ const BUSINESS_INFO_LIST_API_PATH = '/pro/v2/api/businessInfo/getList';
5
+ const MISSING_TOKEN_MESSAGE = '缺少 token;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>';
6
+
7
+ function buildPayload(kwargs, corpid) {
8
+ return {
9
+ keyword: String(kwargs.keyword || '').trim(),
10
+ corpid,
11
+ };
12
+ }
13
+
14
+ function getValidationError(payload, token) {
15
+ if (!payload.keyword) {
16
+ return { code: 'NO_KEYWORD', msg: '缺少 --keyword' };
17
+ }
18
+
19
+ if (!payload.corpid) {
20
+ return { code: 'NO_CORPID', msg: '缺少本地 corpid;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>' };
21
+ }
22
+
23
+ if (!token) {
24
+ return { code: 'NO_TOKEN', msg: MISSING_TOKEN_MESSAGE };
25
+ }
26
+
27
+ return null;
28
+ }
29
+
30
+ function makeErrorRow(code, msg) {
31
+ return [{
32
+ rank: '',
33
+ pid: '',
34
+ enterpriseName: '',
35
+ code,
36
+ msg,
37
+ }];
38
+ }
39
+
40
+ function makeSuccessRows(items) {
41
+ return items.map((item, index) => ({
42
+ rank: index + 1,
43
+ pid: item.pid || '',
44
+ enterpriseName: item.enterpriseName || '',
45
+ code: '',
46
+ msg: '',
47
+ }));
48
+ }
49
+
50
+ cli({
51
+ site: 'xbb',
52
+ name: 'business-info-search',
53
+ description: '按关键词搜索企业,返回企业准确全称与 pid(需购买工商查询服务方可调用)',
54
+ strategy: Strategy.PUBLIC,
55
+ access: 'read',
56
+ browser: false,
57
+ domain: 'proapi.xbongbong.com',
58
+ args: [
59
+ { name: 'keyword', type: 'str', help: '企业名称关键词(必填,支持模糊匹配)' },
60
+ { name: 'debug', type: 'bool', default: false, help: '输出请求体和返回体调试信息' },
61
+ { name: 'raw', type: 'bool', default: false, help: '输出接口返回的原文' },
62
+ ],
63
+ columns: ['rank', 'pid', 'enterpriseName', 'code', 'msg'],
64
+ func: async function (kwargs) {
65
+ const debug = Boolean(kwargs.debug);
66
+ const { corpid, token, baseUrl, userId } = getRuntimeConfig();
67
+ const payload = buildPayload(kwargs, corpid);
68
+
69
+ const validationError = getValidationError(payload, token);
70
+ if (validationError) {
71
+ return makeErrorRow(validationError.code, validationError.msg);
72
+ }
73
+
74
+ const gateway = await requestGateway({
75
+ baseUrl,
76
+ apiPath: BUSINESS_INFO_LIST_API_PATH,
77
+ payload,
78
+ token,
79
+ userId,
80
+ debug,
81
+ });
82
+ if (!gateway.ok) return makeErrorRow(gateway.code, gateway.msg);
83
+ if (kwargs.raw) return [{ raw: gateway.responseBody }];
84
+ if (gateway.data.code !== 1) {
85
+ return makeErrorRow(gateway.data.code ?? '', gateway.data.msg ?? '未知错误');
86
+ }
87
+
88
+ const items = Array.isArray(gateway.data.result?.data?.items) ? gateway.data.result.data.items : [];
89
+ if (!items.length) {
90
+ return makeErrorRow('NO_DATA', '接口成功,但企业列表为空');
91
+ }
92
+
93
+ return makeSuccessRows(items);
94
+ },
95
+ });
@@ -1,34 +1,9 @@
1
- import crypto from 'node:crypto';
2
- import fs from 'node:fs';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
1
  import { cli, Strategy } from './xbb-registry.js';
6
- import { readActiveConfig } from './xbb-config.js';
2
+ import { getRuntimeConfig, requestGateway } from './xbb-http.js';
7
3
 
8
- const CONFIG_FILE = path.join(os.homedir(), '.xbbcli', 'config.env');
9
- const BUYER_INQUIRY_DETAIL_API_URL = 'https://proapi.xbongbong.com/pro/v2/api/buyerInquiry/detail';
10
- const DEFAULT_BASE_URL = 'https://proapi.xbongbong.com';
4
+ const BUYER_INQUIRY_DETAIL_API_PATH = '/pro/v2/api/buyerInquiry/detail';
11
5
  const MISSING_TOKEN_MESSAGE = '缺少 token;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>';
12
6
 
13
- function readConfig() {
14
- return readActiveConfig();
15
- }
16
-
17
- function getRuntimeConfig() {
18
- const config = readConfig();
19
- return {
20
- corpid: String(config.corpid || '').trim(),
21
- token: String(config.token || '').trim(),
22
- baseUrl: String(config.baseurl || DEFAULT_BASE_URL).trim(),
23
- userId: String(config.userId || '').trim(),
24
- };
25
- }
26
-
27
- function buildApiUrl(baseUrl, defaultUrl) {
28
- const apiPath = new URL(defaultUrl).pathname;
29
- return `${baseUrl.replace(/\/+$/, '')}${apiPath}`;
30
- }
31
-
32
7
  function buildPayload(kwargs, corpid) {
33
8
  const payload = { corpid, dataId: Number(kwargs.dataId || 0) };
34
9
  if (kwargs.userId) payload.userId = String(kwargs.userId);
@@ -72,38 +47,32 @@ cli({
72
47
  const debug = Boolean(kwargs.debug);
73
48
  const { corpid, token, baseUrl, userId } = getRuntimeConfig();
74
49
  const payload = buildPayload(kwargs, corpid);
75
- const body = JSON.stringify(payload);
76
50
 
77
51
  const validationError = getValidationError(payload, token);
78
52
  if (validationError) return makeErrorRow(validationError.code, validationError.msg);
79
53
 
80
- const sign = crypto.createHash('sha256').update(body + token).digest('hex');
81
- const headers = Object.assign({ 'Content-Type': 'application/json;charset=UTF-8', sign }, userId ? { userId } : {});
82
- const apiUrl = buildApiUrl(baseUrl, BUYER_INQUIRY_DETAIL_API_URL);
83
- if (debug) {
84
- process.stderr.write(`[debug] URL: ${apiUrl}\n[debug] Headers: ${JSON.stringify(headers)}\n[debug] RequestBody: ${body}\n`);
54
+ const gateway = await requestGateway({
55
+ baseUrl,
56
+ apiPath: BUYER_INQUIRY_DETAIL_API_PATH,
57
+ payload,
58
+ token,
59
+ userId,
60
+ debug,
61
+ });
62
+ if (!gateway.ok) return makeErrorRow(gateway.code, gateway.msg);
63
+ if (gateway.data.code !== 1) {
64
+ return makeErrorRow(gateway.data.code ?? '', gateway.data.msg ?? '未知错误');
85
65
  }
86
- const resp = await fetch(apiUrl, { method: 'POST', headers, body });
87
- if (!resp.ok) {
88
- const responseText = await resp.text();
89
- if (debug) process.stderr.write(`[debug] ResponseBody: ${responseText}\n`);
90
- return makeErrorRow(resp.status, `HTTP ${resp.status} ${resp.statusText}`);
91
- }
92
-
93
- const data = await resp.json();
94
- const responseBody = JSON.stringify(data);
95
- if (debug) process.stderr.write(`[debug] ResponseBody: ${responseBody}\n`);
96
- if (data.code !== 1) return makeErrorRow(data.code ?? '', data.msg ?? '未知错误');
97
66
 
98
- const result = data.result || {};
67
+ const result = gateway.data.result || {};
99
68
  return [{
100
69
  dataId: result.dataId ?? result.id ?? payload.dataId,
101
70
  formId: result.formId ?? '',
102
71
  addTime: result.addTime ?? result.createTime ?? '',
103
72
  updateTime: result.updateTime ?? '',
104
73
  data: JSON.stringify(result.data ?? result),
105
- code: data.code ?? '',
106
- msg: data.msg ?? '',
74
+ code: gateway.data.code ?? '',
75
+ msg: gateway.data.msg ?? '',
107
76
  }];
108
77
  },
109
78
  });
@@ -1,34 +1,9 @@
1
- import crypto from 'node:crypto';
2
- import fs from 'node:fs';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
1
  import { cli, Strategy } from './xbb-registry.js';
6
- import { readActiveConfig } from './xbb-config.js';
2
+ import { getRuntimeConfig, requestGateway, createPagination } from './xbb-http.js';
7
3
 
8
- const CONFIG_FILE = path.join(os.homedir(), '.xbbcli', 'config.env');
9
- const BUYER_INQUIRY_LIST_API_URL = 'https://proapi.xbongbong.com/pro/v2/api/buyerInquiry/list';
10
- const DEFAULT_BASE_URL = 'https://proapi.xbongbong.com';
4
+ const BUYER_INQUIRY_LIST_API_PATH = '/pro/v2/api/buyerInquiry/list';
11
5
  const MISSING_TOKEN_MESSAGE = '缺少 token;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>';
12
- let lastPagination = null;
13
-
14
- function readConfig() {
15
- return readActiveConfig();
16
- }
17
-
18
- function getRuntimeConfig() {
19
- const config = readConfig();
20
- return {
21
- corpid: String(config.corpid || '').trim(),
22
- token: String(config.token || '').trim(),
23
- baseUrl: String(config.baseurl || DEFAULT_BASE_URL).trim(),
24
- userId: String(config.userId || '').trim(),
25
- };
26
- }
27
-
28
- function buildApiUrl(baseUrl, defaultUrl) {
29
- const apiPath = new URL(defaultUrl).pathname;
30
- return `${baseUrl.replace(/\/+$/, '')}${apiPath}`;
31
- }
6
+ const pagination = createPagination();
32
7
 
33
8
  function buildPayload(kwargs, corpid) {
34
9
  return {
@@ -91,46 +66,33 @@ cli({
91
66
  { name: 'raw', type: 'bool', default: false, help: '输出接口返回的原文' },
92
67
  ],
93
68
  columns: ['rank', 'inquiryId', 'inquiryNo', 'buyerName', 'status', 'createTime', 'data', 'code', 'msg'],
94
- footerExtra: () => (lastPagination ? `totalCount ${lastPagination.totalCount} / totalPage ${lastPagination.totalPage}` : undefined),
69
+ footerExtra: pagination.footerExtra,
95
70
  func: async function (kwargs) {
96
71
  const debug = Boolean(kwargs.debug);
97
72
  const { corpid, token, baseUrl, userId } = getRuntimeConfig();
98
73
  const payload = buildPayload(kwargs, corpid);
99
- const body = JSON.stringify(payload);
100
74
 
101
75
  const validationError = getValidationError(payload, token);
102
76
  if (validationError) {
103
77
  return makeErrorRow(validationError.code, validationError.msg);
104
78
  }
105
79
 
106
- const sign = crypto.createHash('sha256').update(body + token).digest('hex');
107
- const headers = Object.assign({
108
- 'Content-Type': 'application/json;charset=UTF-8',
109
- sign,
110
- }, userId ? { userId } : {});
111
- const apiUrl = buildApiUrl(baseUrl, BUYER_INQUIRY_LIST_API_URL);
112
- if (debug) {
113
- process.stderr.write(`[debug] URL: ${apiUrl}\n[debug] Headers: ${JSON.stringify(headers)}\n[debug] RequestBody: ${body}\n`);
114
- }
115
- const resp = await fetch(apiUrl, { method: 'POST', headers, body });
116
- if (!resp.ok) {
117
- const responseText = await resp.text();
118
- if (debug) process.stderr.write(`[debug] ResponseBody: ${responseText}\n`);
119
- return makeErrorRow(resp.status, `HTTP ${resp.status} ${resp.statusText}`);
120
- }
121
-
122
- const data = await resp.json();
123
- lastPagination = data?.code === 1 && data?.result?.totalCount != null && data?.result?.totalPage != null
124
- ? { totalCount: data.result.totalCount, totalPage: data.result.totalPage }
125
- : null;
126
- const responseBody = JSON.stringify(data);
127
- if (debug) process.stderr.write(`[debug] ResponseBody: ${responseBody}\n`);
128
- if (kwargs.raw) return [{ raw: responseBody }];
129
- if (data.code !== 1) {
130
- return makeErrorRow(data.code ?? '', data.msg ?? '未知错误');
80
+ const gateway = await requestGateway({
81
+ baseUrl,
82
+ apiPath: BUYER_INQUIRY_LIST_API_PATH,
83
+ payload,
84
+ token,
85
+ userId,
86
+ debug,
87
+ });
88
+ if (!gateway.ok) return makeErrorRow(gateway.code, gateway.msg);
89
+ pagination.update(gateway.data);
90
+ if (kwargs.raw) return [{ raw: gateway.responseBody }];
91
+ if (gateway.data.code !== 1) {
92
+ return makeErrorRow(gateway.data.code ?? '', gateway.data.msg ?? '未知错误');
131
93
  }
132
94
 
133
- const list = Array.isArray(data.result?.list) ? data.result.list : [];
95
+ const list = Array.isArray(gateway.data.result?.list) ? gateway.data.result.list : [];
134
96
  if (!list.length) {
135
97
  return makeErrorRow('NO_DATA', '接口成功,但 list 为空');
136
98
  }
@@ -1,34 +1,9 @@
1
- import fs from 'node:fs';
2
- import os from 'node:os';
3
- import path from 'node:path';
4
- import crypto from 'node:crypto';
5
1
  import { cli, Strategy } from './xbb-registry.js';
6
- import { readActiveConfig } from './xbb-config.js';
2
+ import { getRuntimeConfig, requestGateway } from './xbb-http.js';
7
3
 
8
- const CONFIG_FILE = path.join(os.homedir(), '.xbbcli', 'config.env');
9
- const API_URL = 'https://proapi.xbongbong.com/pro/v2/api/clue/addCoUser';
10
- const DEFAULT_BASE_URL = 'https://proapi.xbongbong.com';
4
+ const API_PATH = '/pro/v2/api/clue/addCoUser';
11
5
  const MISSING_TOKEN_MESSAGE = '缺少 token;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>';
12
6
 
13
- function readConfig() {
14
- return readActiveConfig();
15
- }
16
-
17
- function getRuntimeConfig() {
18
- const config = readConfig();
19
- return {
20
- corpid: String(config.corpid || '').trim(),
21
- token: String(config.token || '').trim(),
22
- baseUrl: String(config.baseurl || DEFAULT_BASE_URL).trim(),
23
- userId: String(config.userId || '').trim(),
24
- };
25
- }
26
-
27
- function buildApiUrl(baseUrl, apiUrl) {
28
- const apiPath = new URL(apiUrl).pathname;
29
- return `${baseUrl.replace(/\/+$/, '')}${apiPath}`;
30
- }
31
-
32
7
  function makeErrorRow(code, msg) {
33
8
  return [{ resultCode: '', resultMsg: '', messageList: '', code, msg }];
34
9
  }
@@ -62,22 +37,22 @@ cli({
62
37
  businessUserIdList = null;
63
38
  }
64
39
  if (Array.isArray(businessUserIdList)) payload.businessUserIdList = businessUserIdList;
65
- const requestBody = JSON.stringify(payload);
66
40
  if (!payload.dataId) return makeErrorRow('NO_DATAID', '缺少 --dataId');
67
41
  if (!payload.corpid) return makeErrorRow('NO_CORPID', '缺少本地 corpid;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>');
68
42
  if (!Array.isArray(businessUserIdList) || !businessUserIdList.length) return makeErrorRow('NO_USERIDLIST', '缺少 --businessUserIdList 或格式不正确,需为JSON数组');
69
43
  if (!token) return makeErrorRow('NO_TOKEN', MISSING_TOKEN_MESSAGE);
70
- const sign = crypto.createHash('sha256').update(requestBody + token).digest('hex');
71
- const headers = Object.assign({ 'Content-Type': 'application/json;charset=UTF-8', sign }, userId ? { userId } : {});
72
- if (debug) {
73
- process.stderr.write(`[debug] URL: ${buildApiUrl(baseUrl, API_URL)}\n[debug] Headers: ${JSON.stringify(headers)}\n[debug] RequestBody: ${requestBody}\n`);
44
+ const gateway = await requestGateway({
45
+ baseUrl,
46
+ apiPath: API_PATH,
47
+ payload,
48
+ token,
49
+ userId,
50
+ debug,
51
+ });
52
+ if (!gateway.ok) return makeErrorRow(gateway.code, gateway.msg);
53
+ if (gateway.data.code !== 1) {
54
+ return makeErrorRow(gateway.data.code ?? '', gateway.data.msg ?? '未知错误');
74
55
  }
75
- const resp = await fetch(buildApiUrl(baseUrl, API_URL), { method: 'POST', headers, body: requestBody });
76
- if (!resp.ok) return makeErrorRow(resp.status, `HTTP ${resp.status} ${resp.statusText}`);
77
- const data = await resp.json();
78
- const responseBody = JSON.stringify(data);
79
- if (debug) process.stderr.write(`[debug] ResponseBody: ${responseBody}\n`);
80
- if (data.code !== 1) return makeErrorRow(data.code ?? '', data.msg ?? '未知错误');
81
- return [{ resultCode: data.code ?? '', resultMsg: data.msg || '', messageList: JSON.stringify(data.result?.messageList || []), code: data.code ?? '', msg: data.msg || '' }];
56
+ return [{ resultCode: gateway.data.code ?? '', resultMsg: gateway.data.msg || '', messageList: JSON.stringify(gateway.data.result?.messageList || []), code: gateway.data.code ?? '', msg: gateway.data.msg || '' }];
82
57
  },
83
58
  });
package/clue-add.js CHANGED
@@ -1,34 +1,9 @@
1
- import crypto from 'node:crypto';
2
- import fs from 'node:fs';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
1
  import { cli, Strategy } from './xbb-registry.js';
6
- import { readActiveConfig } from './xbb-config.js';
2
+ import { getRuntimeConfig, requestGateway } from './xbb-http.js';
7
3
 
8
- const CONFIG_FILE = path.join(os.homedir(), '.xbbcli', 'config.env');
9
- const API_URL = 'https://proapi.xbongbong.com/pro/v2/api/clue/add';
10
- const DEFAULT_BASE_URL = 'https://proapi.xbongbong.com';
4
+ const API_PATH = '/pro/v2/api/clue/add';
11
5
  const MISSING_TOKEN_MESSAGE = '缺少 token;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>';
12
6
 
13
- function readConfig() {
14
- return readActiveConfig();
15
- }
16
-
17
- function getRuntimeConfig() {
18
- const config = readConfig();
19
- return {
20
- corpid: String(config.corpid || '').trim(),
21
- token: String(config.token || '').trim(),
22
- baseUrl: String(config.baseurl || DEFAULT_BASE_URL).trim(),
23
- userId: String(config.userId || '').trim(),
24
- };
25
- }
26
-
27
- function buildApiUrl(baseUrl, apiUrl) {
28
- const apiPath = new URL(apiUrl).pathname;
29
- return `${baseUrl.replace(/\/+$/, '')}${apiPath}`;
30
- }
31
-
32
7
  function parseDataList(raw) {
33
8
  if (raw && typeof raw === 'object' && !Array.isArray(raw)) {
34
9
  return raw;
@@ -75,25 +50,24 @@ cli({
75
50
  const runtimeUserId = String(kwargs.userId || userId || '').trim();
76
51
  if (runtimeUserId) payload.userId = runtimeUserId;
77
52
  if (parsedDataList) payload.dataList = parsedDataList;
78
- const requestBody = JSON.stringify(payload);
79
53
  if (!payload.corpid) return makeErrorRow('NO_CORPID', '缺少本地 corpid;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>');
80
54
  if (!payload.formId) return makeErrorRow('NO_FORMID', '缺少 --formId');
81
55
  if (!token) return makeErrorRow('NO_TOKEN', MISSING_TOKEN_MESSAGE);
82
56
  if (parsedDataList === null) return makeErrorRow('NO_DATALIST', '缺少 --dataList');
83
57
  if (parsedDataList === undefined) return makeErrorRow('INVALID_DATALIST', '--dataList 必须是 JSON 对象字符串');
84
- const sign = crypto.createHash('sha256').update(requestBody + token).digest('hex');
85
- const headers = Object.assign({ 'Content-Type': 'application/json;charset=UTF-8', sign }, runtimeUserId ? { userId: runtimeUserId } : {});
86
- const apiUrl = buildApiUrl(baseUrl, API_URL);
87
- if (debug) {
88
- process.stderr.write(`[debug] URL: ${apiUrl}\n[debug] Headers: ${JSON.stringify(headers)}\n[debug] RequestBody: ${requestBody}\n`);
58
+ const gateway = await requestGateway({
59
+ baseUrl,
60
+ apiPath: API_PATH,
61
+ payload,
62
+ token,
63
+ userId: runtimeUserId,
64
+ debug,
65
+ });
66
+ if (!gateway.ok) return makeErrorRow(gateway.code, gateway.msg);
67
+ if (gateway.data.code !== 1) {
68
+ return makeErrorRow(gateway.data.code ?? '', gateway.data.msg ?? '未知错误');
89
69
  }
90
- const resp = await fetch(apiUrl, { method: 'POST', headers, body: requestBody });
91
- if (!resp.ok) return makeErrorRow(resp.status, `HTTP ${resp.status} ${resp.statusText}`);
92
- const data = await resp.json();
93
- const responseBody = JSON.stringify(data);
94
- if (debug) process.stderr.write(`[debug] ResponseBody: ${responseBody}\n`);
95
- if (data.code !== 1) return makeErrorRow(data.code ?? '', data.msg ?? '未知错误');
96
- const result = data.result || {};
97
- return [{ dataId: result.dataId || '', resultCode: result.code ?? '', resultMsg: result.msg || '', code: data.code ?? '', msg: data.msg || '' }];
70
+ const result = gateway.data.result || {};
71
+ return [{ dataId: result.dataId || '', resultCode: result.code ?? '', resultMsg: result.msg || '', code: gateway.data.code ?? '', msg: gateway.data.msg || '' }];
98
72
  },
99
73
  });