@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/sign-in-list.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, createPagination } 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/signIn/list';
10
- const DEFAULT_BASE_URL = 'https://proapi.xbongbong.com';
4
+ const API_PATH = '/pro/v2/api/signIn/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 parseArray(raw) {
34
9
  const text = String(raw ?? '').trim();
@@ -74,7 +49,7 @@ cli({
74
49
  { name: 'userId', type: 'str', default: '', help: '操作人id(可选)' },
75
50
  { name: 'signInUserId', type: 'str', default: '', help: '签到人userId(可选)' },
76
51
  { name: 'signInUserName', type: 'str', default: '', help: '签到人姓名精确匹配(可选)' },
77
- { name: 'signInCustomerId', type: 'int', default: '', help: '签到客户id(可选)' },
52
+ { name: 'signInCustomerId', type: 'str', default: '', help: '签到客户id(可选)' },
78
53
  { name: 'signInUserIdIn', type: 'str', default: '', help: '签到人userId集合,JSON数组字符串(可选)' },
79
54
  { name: 'signInCustomerIdIn', type: 'str', default: '', help: '签到客户id集合,JSON数组字符串(可选)' },
80
55
  { name: 'country', type: 'str', default: '', help: '签到国家(可选)' },
@@ -92,41 +67,38 @@ cli({
92
67
  { name: 'outCity', type: 'str', default: '', help: '签退城市(可选)' },
93
68
  { name: 'outDistrict', type: 'str', default: '', help: '签退区县(可选)' },
94
69
  { name: 'outAddress', type: 'str', default: '', help: '签退详情地址(可选)' },
95
- { name: 'status', type: 'int', default: '', help: '签到状态(可选)' },
96
- { name: 'linkBusinessType', type: 'int', default: '', help: '签到对象业务类型(可选)' },
70
+ { name: 'status', type: 'str', default: '', help: '签到状态(可选)' },
71
+ { name: 'linkBusinessType', type: 'str', default: '', help: '签到对象业务类型(可选)' },
97
72
  { name: 'startOutTime', type: 'str', default: '', help: '开始签退时间(可选)' },
98
73
  { name: 'endOutTime', type: 'str', default: '', help: '结束签退时间(可选)' },
99
74
  { name: 'debug', type: 'bool', default: false, help: '输出请求体和返回体调试信息' },
100
75
  { name: 'raw', type: 'bool', default: false, help: '输出接口返回的原文' },
101
76
  ],
102
77
  columns: ['rank', 'userId', 'userName', 'customerId', 'customerName', 'status', 'inTime', 'outTime', 'address', 'outAddress', 'data', 'code', 'msg'],
103
- footerExtra: () => (lastPagination ? `totalCount ${lastPagination.totalCount} / totalPage ${lastPagination.totalPage}` : undefined),
78
+ footerExtra: pagination.footerExtra,
104
79
  func: async (kwargs) => {
105
80
  const debug = Boolean(kwargs.debug);
106
81
  const { corpid, token, baseUrl, userId } = getRuntimeConfig();
107
82
  const payload = buildPayload(kwargs, corpid);
108
- const body = JSON.stringify(payload);
109
83
  if (!payload.corpid) return makeErrorRow('NO_CORPID', '缺少本地 corpid;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>');
110
84
  if (!token) return makeErrorRow('NO_TOKEN', MISSING_TOKEN_MESSAGE);
111
85
  if (String(kwargs.signInUserIdIn ?? '').trim() && !Array.isArray(parseArray(kwargs.signInUserIdIn))) return makeErrorRow('INVALID_SIGNINUSERIDIN', '--signInUserIdIn 必须是 JSON 数组字符串');
112
86
  if (String(kwargs.signInCustomerIdIn ?? '').trim() && !Array.isArray(parseArray(kwargs.signInCustomerIdIn))) return makeErrorRow('INVALID_SIGNINCUSTOMERIDIN', '--signInCustomerIdIn 必须是 JSON 数组字符串');
113
- const sign = crypto.createHash('sha256').update(body + token).digest('hex');
114
- const headers = Object.assign({ 'Content-Type': 'application/json;charset=UTF-8', sign }, userId ? { userId } : {});
115
- const apiUrl = buildApiUrl(baseUrl, API_URL);
116
- if (debug) {
117
- process.stderr.write(`[debug] URL: ${apiUrl}\n[debug] Headers: ${JSON.stringify(headers)}\n[debug] RequestBody: ${body}\n`);
87
+ const gateway = await requestGateway({
88
+ baseUrl,
89
+ apiPath: API_PATH,
90
+ payload,
91
+ token,
92
+ userId,
93
+ debug,
94
+ });
95
+ if (!gateway.ok) return makeErrorRow(gateway.code, gateway.msg);
96
+ pagination.update(gateway.data);
97
+ if (kwargs.raw) return [{ raw: gateway.responseBody }];
98
+ if (gateway.data.code !== 1) {
99
+ return makeErrorRow(gateway.data.code ?? '', gateway.data.msg ?? '未知错误');
118
100
  }
119
- const resp = await fetch(apiUrl, { method: 'POST', headers, body });
120
- if (!resp.ok) return makeErrorRow(resp.status, `HTTP ${resp.status} ${resp.statusText}`);
121
- const data = await resp.json();
122
- lastPagination = data?.code === 1 && data?.result?.totalCount != null && data?.result?.totalPage != null
123
- ? { totalCount: data.result.totalCount, totalPage: data.result.totalPage }
124
- : null;
125
- const responseBody = JSON.stringify(data);
126
- if (debug) process.stderr.write(`[debug] ResponseBody: ${responseBody}\n`);
127
- if (kwargs.raw) return [{ raw: responseBody }];
128
- if (data.code !== 1) return makeErrorRow(data.code ?? '', data.msg ?? '未知错误');
129
- const list = Array.isArray(data.result?.signInList) ? data.result.signInList : [];
101
+ const list = Array.isArray(gateway.data.result?.signInList) ? gateway.data.result.signInList : [];
130
102
  if (!list.length) return makeErrorRow('NO_DATA', '接口成功,但 signInList 为空');
131
103
  return list.map((item, index) => ({ rank: index + 1, userId: item.userId || '', userName: item.userName || '', customerId: item.customerId || '', customerName: item.customerName || '', status: item.status ?? '', inTime: item.inTime || '', outTime: item.outTime || '', address: item.address || '', outAddress: item.outAddress || '', data: JSON.stringify(item || {}), code: '', msg: '' }));
132
104
  },
package/stage-get.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/stage/get';
10
- const DEFAULT_BASE_URL = 'https://proapi.xbongbong.com';
4
+ const API_PATH = '/pro/v2/api/stage/get';
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 [{ stageProcessId: '', stageId: '', stageName: '', reasonText: '', reasonValue: '', code, msg }];
34
9
  }
@@ -61,26 +36,25 @@ cli({
61
36
  dataId: Number(kwargs.dataId || 0),
62
37
  };
63
38
  if (kwargs.userId) payload.userId = String(kwargs.userId);
64
- const requestBody = JSON.stringify(payload);
65
39
  if (!payload.corpid) return makeErrorRow('NO_CORPID', '缺少本地 corpid;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>');
66
40
  if (!payload.formId) return makeErrorRow('NO_FORMID', '缺少 --formId');
67
41
  if (!payload.businessType) return makeErrorRow('NO_BUSINESSTYPE', '缺少 --businessType');
68
42
  if (!payload.saasMark) return makeErrorRow('NO_SAASMARK', '缺少 --saasMark');
69
43
  if (!payload.dataId) return makeErrorRow('NO_DATAID', '缺少 --dataId');
70
44
  if (!token) return makeErrorRow('NO_TOKEN', MISSING_TOKEN_MESSAGE);
71
- const sign = crypto.createHash('sha256').update(requestBody + token).digest('hex');
72
- const headers = Object.assign({ 'Content-Type': 'application/json;charset=UTF-8', sign }, userId ? { userId } : {});
73
- const apiUrl = buildApiUrl(baseUrl, API_URL);
74
- if (debug) {
75
- process.stderr.write(`[debug] URL: ${apiUrl}\n[debug] Headers: ${JSON.stringify(headers)}\n[debug] RequestBody: ${requestBody}\n`);
45
+ const gateway = await requestGateway({
46
+ baseUrl,
47
+ apiPath: API_PATH,
48
+ payload,
49
+ token,
50
+ userId,
51
+ debug,
52
+ });
53
+ if (!gateway.ok) return makeErrorRow(gateway.code, gateway.msg);
54
+ if (gateway.data.code !== 1) {
55
+ return makeErrorRow(gateway.data.code ?? '', gateway.data.msg ?? '未知错误');
76
56
  }
77
- const resp = await fetch(apiUrl, { method: 'POST', headers, body: requestBody });
78
- if (!resp.ok) return makeErrorRow(resp.status, `HTTP ${resp.status} ${resp.statusText}`);
79
- const data = await resp.json();
80
- const responseBody = JSON.stringify(data);
81
- if (debug) process.stderr.write(`[debug] ResponseBody: ${responseBody}\n`);
82
- if (data.code !== 1) return makeErrorRow(data.code ?? '', data.msg ?? '未知错误');
83
- const result = data.result || {};
57
+ const result = gateway.data.result || {};
84
58
  const stageList = Array.isArray(result.stageList) ? result.stageList : [];
85
59
  const reasonList = Array.isArray(result.reasonList) ? result.reasonList : [];
86
60
  const size = Math.max(stageList.length, reasonList.length, 1);
@@ -90,8 +64,8 @@ cli({
90
64
  stageName: stageList[index]?.stageName || '',
91
65
  reasonText: reasonList[index]?.text || '',
92
66
  reasonValue: reasonList[index]?.value || '',
93
- code: data.code ?? '',
94
- msg: data.msg || '',
67
+ code: gateway.data.code ?? '',
68
+ msg: gateway.data.msg || '',
95
69
  }));
96
70
  },
97
71
  });
package/stage-jump.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/stage/jump';
10
- const DEFAULT_BASE_URL = 'https://proapi.xbongbong.com';
4
+ const API_PATH = '/pro/v2/api/stage/jump';
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 [{ dataId: '', resultCode: '', resultMsg: '', code, msg }];
34
9
  }
@@ -48,7 +23,7 @@ cli({
48
23
  { name: 'dataId', type: 'int', help: '表单数据id(必填)' },
49
24
  { name: 'toStageId', type: 'int', help: '目标阶段id(必填)' },
50
25
  { name: 'stageProcessId', type: 'int', help: '阶段流程id(必填)' },
51
- { name: 'reasonId', type: 'int', default: '', help: '原因id(可选)' },
26
+ { name: 'reasonId', type: 'str', default: '', help: '原因id(可选)' },
52
27
  { name: 'memo', type: 'str', default: '', help: '备注(可选)' },
53
28
  { name: 'userId', type: 'str', default: '', help: '操作人id(可选)' },
54
29
  { name: 'debug', type: 'bool', default: false, help: '输出请求体和返回体调试信息' },
@@ -69,7 +44,6 @@ cli({
69
44
  if (kwargs.userId) payload.userId = String(kwargs.userId);
70
45
  if (String(kwargs.reasonId ?? '') !== '') payload.reasonId = Number(kwargs.reasonId);
71
46
  if (String(kwargs.memo ?? '') !== '') payload.memo = String(kwargs.memo);
72
- const requestBody = JSON.stringify(payload);
73
47
 
74
48
  if (!payload.corpid) return makeErrorRow('NO_CORPID', '缺少本地 corpid;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>');
75
49
  if (!payload.formId) return makeErrorRow('NO_FORMID', '缺少 --formId');
@@ -80,27 +54,19 @@ cli({
80
54
  if (!payload.stageProcessId) return makeErrorRow('NO_STAGEPROCESSID', '缺少 --stageProcessId');
81
55
  if (!token) return makeErrorRow('NO_TOKEN', MISSING_TOKEN_MESSAGE);
82
56
 
83
- const sign = crypto.createHash('sha256').update(requestBody + token).digest('hex');
84
- const headers = Object.assign({ 'Content-Type': 'application/json;charset=UTF-8', sign }, userId ? { userId } : {});
85
- if (debug) {
86
- process.stderr.write(`[debug] URL: ${buildApiUrl(baseUrl, API_URL)}\n[debug] Headers: ${JSON.stringify(headers)}\n[debug] RequestBody: ${requestBody}\n`);
87
- }
88
- const resp = await fetch(buildApiUrl(baseUrl, API_URL), {
89
- method: 'POST',
90
- headers,
91
- body: requestBody,
57
+ const gateway = await requestGateway({
58
+ baseUrl,
59
+ apiPath: API_PATH,
60
+ payload,
61
+ token,
62
+ userId,
63
+ debug,
92
64
  });
93
-
94
- if (!resp.ok) {
95
- const errText = await resp.text();
96
- if (debug) process.stderr.write(`[debug] ResponseBody: ${errText}\n`);
97
- return makeErrorRow(resp.status, `HTTP ${resp.status} ${resp.statusText}`);
65
+ if (!gateway.ok) return makeErrorRow(gateway.code, gateway.msg);
66
+ if (gateway.data.code !== 1) {
67
+ return makeErrorRow(gateway.data.code ?? '', gateway.data.msg ?? '未知错误');
98
68
  }
99
- const data = await resp.json();
100
- const responseBody = JSON.stringify(data);
101
- if (debug) process.stderr.write(`[debug] ResponseBody: ${responseBody}\n`);
102
- if (data.code !== 1) return makeErrorRow(data.code ?? '', data.msg ?? '未知错误');
103
- const result = data.result || {};
104
- return [{ dataId: result.dataId || payload.dataId || '', resultCode: result.code ?? '', resultMsg: result.msg || '', code: data.code ?? '', msg: data.msg || '' }];
69
+ const result = gateway.data.result || {};
70
+ return [{ dataId: result.dataId || payload.dataId || '', resultCode: result.code ?? '', resultMsg: result.msg || '', code: gateway.data.code ?? '', msg: gateway.data.msg || '' }];
105
71
  },
106
72
  });
package/supplier-add.js CHANGED
@@ -1,33 +1,7 @@
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_DIR = path.join(os.homedir(), '.xbbcli');
9
- const CONFIG_FILE = path.join(CONFIG_DIR, 'config.env');
10
- const API_URL = 'https://proapi.xbongbong.com/pro/v2/api/supplier/add';
11
- const DEFAULT_BASE_URL = 'https://proapi.xbongbong.com';
12
-
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
- }
4
+ const API_PATH = '/pro/v2/api/supplier/add';
31
5
 
32
6
  function makeErrorRow(code, msg) {
33
7
  return [{
@@ -84,7 +58,6 @@ cli({
84
58
  payload.dataList = parsedDataList;
85
59
  }
86
60
 
87
- const body = JSON.stringify(payload);
88
61
 
89
62
  if (!payload.corpid) {
90
63
  return makeErrorRow('NO_CORPID', '缺少本地 corpid;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>');
@@ -99,41 +72,26 @@ cli({
99
72
  return makeErrorRow('INVALID_DATALIST', '--dataList 必须是 JSON 对象字符串');
100
73
  }
101
74
 
102
- const sign = crypto.createHash('sha256').update(body + token).digest('hex');
103
- const headers = Object.assign({
104
- 'Content-Type': 'application/json;charset=UTF-8',
105
- sign,
106
- }, userId ? { userId } : {});
107
- const apiUrl = buildApiUrl(baseUrl, API_URL);
108
- if (debug) {
109
- process.stderr.write(`[debug] URL: ${apiUrl}\n[debug] Headers: ${JSON.stringify(headers)}\n[debug] RequestBody: ${body}\n`);
110
- }
111
- const resp = await fetch(apiUrl, {
112
- method: 'POST',
113
- headers,
114
- body,
75
+ const gateway = await requestGateway({
76
+ baseUrl,
77
+ apiPath: API_PATH,
78
+ payload,
79
+ token,
80
+ userId,
81
+ debug,
115
82
  });
116
-
117
- if (!resp.ok) {
118
- const responseText = await resp.text();
119
- if (debug) process.stderr.write(`[debug] ResponseBody: ${responseText}\n`);
120
- return makeErrorRow(resp.status, `HTTP ${resp.status} ${resp.statusText}`);
121
- }
122
-
123
- const data = await resp.json();
124
- const responseBody = JSON.stringify(data);
125
- if (debug) process.stderr.write(`[debug] ResponseBody: ${responseBody}\n`);
126
- if (data.code !== 1) {
127
- return makeErrorRow(data.code ?? '', data.msg ?? '未知错误');
83
+ if (!gateway.ok) return makeErrorRow(gateway.code, gateway.msg);
84
+ if (gateway.data.code !== 1) {
85
+ return makeErrorRow(gateway.data.code ?? '', gateway.data.msg ?? '未知错误');
128
86
  }
129
87
 
130
- const result = data.result || {};
88
+ const result = gateway.data.result || {};
131
89
  return [{
132
90
  dataId: result.dataId || '',
133
91
  resultCode: result.code ?? '',
134
92
  resultMsg: result.msg || '',
135
- code: data.code ?? '',
136
- msg: data.msg || '',
93
+ code: gateway.data.code ?? '',
94
+ msg: gateway.data.msg || '',
137
95
  }];
138
96
  },
139
97
  });
package/token-del.js CHANGED
@@ -127,7 +127,7 @@ async function delCompany(kwargs) {
127
127
  cli({
128
128
  site: 'xbb',
129
129
  name: 'token-del',
130
- description: '删除指定的已保存公司配置,并保证剩余配置中仅且只有一个被启用;默认同时删除 XBB_* 环境变量',
130
+ description: '删除指定的已保存公司配置',
131
131
  strategy: Strategy.PUBLIC,
132
132
  access: 'write',
133
133
  browser: false,
package/token-list.js CHANGED
@@ -57,20 +57,39 @@ function makeErrorRow(code, msg) {
57
57
  cli({
58
58
  site: 'xbb',
59
59
  name: 'token-list',
60
- description: '列出本地保存的多家公司配置,并标记唯一启用的公司(enable=true)',
60
+ description: '列出本地保存的多家公司配置',
61
61
  strategy: Strategy.PUBLIC,
62
62
  access: 'read',
63
63
  browser: false,
64
64
  domain: 'proapi.xbongbong.com',
65
65
  args: [
66
66
  { name: 'showToken', type: 'bool', default: false, help: '显示完整 token;默认只显示脱敏预览' },
67
+ { name: 'raw', type: 'bool', default: false, help: '输出本地配置原文(token 仍按 --showToken 决定是否掩码)' },
68
+ { name: 'debug', type: 'bool', default: false, help: '输出配置路径等调试信息' },
67
69
  ],
68
70
  columns: ['enable', 'corpid', 'userId', 'baseurl', 'token', 'corpName', 'userName', 'code', 'msg', 'source'],
69
71
  func: async (kwargs) => {
70
72
  const showToken = Boolean(kwargs.showToken);
73
+ const debug = Boolean(kwargs.debug);
71
74
  const companies = readCompanies();
72
75
  const envConfig = readEnvConfig();
73
76
  const envPresent = hasEnvConfig(envConfig);
77
+ if (debug) {
78
+ process.stderr.write(`[debug] ConfigFile: ${CONFIG_FILE}\n[debug] CompanyCount: ${companies.length}\n`);
79
+ }
80
+
81
+ // token-list 无网络请求;--raw 输出本地配置原始结构(token 仍按 --showToken 决定是否掩码)
82
+ if (kwargs.raw) {
83
+ const rawCompanies = companies.map((item) => ({
84
+ ...item,
85
+ token: showToken ? String(item.token || '') : maskToken(item.token),
86
+ }));
87
+ const rawEnv = envPresent
88
+ ? { ...envConfig, token: showToken ? String(envConfig.token || '') : maskToken(envConfig.token) }
89
+ : null;
90
+ return [{ raw: JSON.stringify({ companies: rawCompanies, env: rawEnv }, null, 2) }];
91
+ }
92
+
74
93
  const rows = [];
75
94
 
76
95
  // 环境变量行:XBB_CORPID / XBB_TOKEN 有值就回显,source=env;仅供外部系统消费,业务命令不再读取
package/token-set.js CHANGED
@@ -4,7 +4,7 @@ import { saveCompanyCredentials } from './xbb-token-store.js';
4
4
  cli({
5
5
  site: 'xbb',
6
6
  name: 'token-set',
7
- description: '保存 xbb API token,corpid,formId清单 到本地配置文件,并缓存部门与员工清单(<corpid>.department-user.json);其他命令需要意图识别或找formId时,优先查命令映射文件(<corpid>.command-map.md)',
7
+ description: '保存token,corpid,formId清单等文件 到本地,需意图识别或找formId时,优先查命令映射文件(<corpid>.command-map.md)',
8
8
  strategy: Strategy.PUBLIC,
9
9
  access: 'write',
10
10
  browser: false,
package/token-use.js CHANGED
@@ -2,8 +2,6 @@ import fs from 'node:fs';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { cli, Strategy } from './xbb-registry.js';
5
- import { hasEnvConfig, persistEnvVars } from './xbb-config.js';
6
- import { resolveBaseUrl } from './xbb-token-store.js';
7
5
 
8
6
  const CONFIG_DIR = path.join(os.homedir(), '.xbbcli');
9
7
  const CONFIG_FILE = path.join(CONFIG_DIR, 'config.env');
@@ -68,8 +66,6 @@ async function useCompany(kwargs) {
68
66
  return createResult('error', '缺少 --corpid', '', '', '');
69
67
  }
70
68
 
71
- const envPresent = hasEnvConfig();
72
-
73
69
  const companies = readCompanies();
74
70
  if (!companies.length) {
75
71
  return createResult('error', '缺少本地配置;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>', corpid, '', 0);
@@ -80,45 +76,16 @@ async function useCompany(kwargs) {
80
76
  return createResult('error', `未找到 corpid=${corpid} 的本地配置`, corpid, '', companies.length);
81
77
  }
82
78
 
83
- const target = companies[index];
84
- // XBB_* 有值时会同步覆盖环境变量,需要完整凭证:缺 token 时直接拒绝,避免残留上一家公司的 XBB_TOKEN
85
- if (envPresent && !String(target.token || '').trim()) {
86
- return createResult('error', `corpid=${corpid} 的本地配置缺少 token,无法同步到 XBB_* 环境变量;请先执行 xbbcli token-set --corpid ${corpid} --token <TOKEN> --userId <USERID>`, corpid, '', companies.length);
87
- }
88
-
89
79
  const next = enableOnly(companies, index);
90
80
  writeCompanies(next);
91
81
 
92
- const parts = [`已启用 corpid=${corpid},其余公司已标记为 enable=false`];
93
-
94
- // 环境变量中有值时把启用公司凭证同步写回 XBB_*(供外部系统消费,本 CLI 不再读取)
95
- if (envPresent) {
96
- try {
97
- persistEnvVars({
98
- corpid: target.corpid,
99
- token: target.token,
100
- // 条目缺少 baseurl 时按 corpid 规则推导,避免残留上一家公司的 XBB_BASEURL
101
- baseurl: target.baseurl || resolveBaseUrl(target.corpid),
102
- userId: target.userId,
103
- corpName: target.corpName,
104
- userName: target.userName,
105
- });
106
- const suffix = process.platform === 'win32'
107
- ? '(Windows 需重开终端后才生效)'
108
- : '(重新 source ~/.xbbcli/env.sh 后才生效)';
109
- parts.push(`检测到环境变量 XBB_* 有值,已同步更新为该公司凭证(供外部系统使用,本 CLI 不读取)${suffix}`);
110
- } catch (error) {
111
- return createResult('partial', `已启用 corpid=${corpid},但同步更新环境变量失败:${String(error.message || error)}`, corpid, 'true', next.length);
112
- }
113
- }
114
-
115
- return createResult('ok', parts.join(';'), corpid, 'true', next.length);
82
+ return createResult('ok', `已启用 corpid=${corpid},其余公司已标记为 enable=false`, corpid, 'true', next.length);
116
83
  }
117
84
 
118
85
  cli({
119
86
  site: 'xbb',
120
87
  name: 'token-use',
121
- description: '切换当前启用的公司(enable),保证仅且只有一个公司被启用;XBB_* 环境变量有值时同步更新为该公司凭证(供外部系统使用,本 CLI 不读取)',
88
+ description: '切换当前启用的公司(enable),保证仅且只有一个公司被启用',
122
89
  strategy: Strategy.PUBLIC,
123
90
  access: 'write',
124
91
  browser: false,
package/user-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/user/add';
10
- const DEFAULT_BASE_URL = 'https://proapi.xbongbong.com';
4
+ const API_PATH = '/pro/v2/api/user/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 parseJsonArray(raw) {
33
8
  if (Array.isArray(raw)) return raw;
34
9
  const text = String(raw || '').trim();
@@ -77,24 +52,24 @@ cli({
77
52
  if (String(kwargs.position || '').trim()) payload.position = String(kwargs.position);
78
53
  if (String(kwargs.email || '').trim()) payload.email = String(kwargs.email);
79
54
  if (kwargs.userId) payload.userId = String(kwargs.userId);
80
- const requestBody = JSON.stringify(payload);
81
55
  if (!payload.name) return makeErrorRow('NO_NAME', '缺少 --name');
82
56
  if (!payload.mobile) return makeErrorRow('NO_MOBILE', '缺少 --mobile');
83
57
  if (!payload.corpid) return makeErrorRow('NO_CORPID', '缺少本地 corpid;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>');
84
58
  if (!Array.isArray(roleIds) || !roleIds.length) return makeErrorRow(roleIds === undefined ? 'INVALID_ROLEIDS' : 'NO_ROLEIDS', roleIds === undefined ? '--roleIds 必须是 JSON 数组字符串' : '缺少 --roleIds');
85
59
  if (!Array.isArray(userDepInfoList) || !userDepInfoList.length) return makeErrorRow(userDepInfoList === undefined ? 'INVALID_USERDEPINFOLIST' : 'NO_USERDEPINFOLIST', userDepInfoList === undefined ? '--userDepInfoList 必须是 JSON 数组字符串' : '缺少 --userDepInfoList');
86
60
  if (!token) return makeErrorRow('NO_TOKEN', MISSING_TOKEN_MESSAGE);
87
- const sign = crypto.createHash('sha256').update(requestBody + token).digest('hex');
88
- const headers = Object.assign({ 'Content-Type': 'application/json;charset=UTF-8', sign }, userId ? { userId } : {});
89
- if (debug) {
90
- process.stderr.write(`[debug] URL: ${buildApiUrl(baseUrl, API_URL)}\n[debug] Headers: ${JSON.stringify(headers)}\n[debug] RequestBody: ${requestBody}\n`);
61
+ const gateway = await requestGateway({
62
+ baseUrl,
63
+ apiPath: API_PATH,
64
+ payload,
65
+ token,
66
+ userId,
67
+ debug,
68
+ });
69
+ if (!gateway.ok) return makeErrorRow(gateway.code, gateway.msg);
70
+ if (gateway.data.code !== 1) {
71
+ return makeErrorRow(gateway.data.code ?? '', gateway.data.msg ?? '未知错误');
91
72
  }
92
- const resp = await fetch(buildApiUrl(baseUrl, API_URL), { method: 'POST', headers, body: requestBody });
93
- if (!resp.ok) return makeErrorRow(resp.status, `HTTP ${resp.status} ${resp.statusText}`);
94
- const data = await resp.json();
95
- const responseBody = JSON.stringify(data);
96
- if (debug) process.stderr.write(`[debug] ResponseBody: ${responseBody}\n`);
97
- if (data.code !== 1) return makeErrorRow(data.code ?? '', data.msg ?? '未知错误');
98
- return [{ code: data.code ?? '', msg: data.msg || '' }];
73
+ return [{ code: gateway.data.code ?? '', msg: gateway.data.msg || '' }];
99
74
  },
100
75
  });