neo-cmp-cli 1.13.17 → 1.13.19

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 (91) hide show
  1. package/README.md +23 -3
  2. package/dist/index2.js +1 -1
  3. package/dist/neo/env.js +1 -1
  4. package/dist/neo/pushCmp.js +1 -1
  5. package/dist/package.json.js +1 -1
  6. package/package.json +3 -2
  7. package/template/asset-manage-template/docs/README.md +1 -232
  8. package/template/echarts-custom-cmp-template/package.json +1 -1
  9. package/template/neo-bi-cmps/package.json +1 -1
  10. package/template/neo-bi-cmps/src/components/filterBar__c/common.scss +1 -1
  11. package/template/neo-bi-cmps/src/components/filterBar__c/index.tsx +18 -10
  12. package/template/neo-bi-cmps/src/components/filterBar__c/model.ts +8 -2
  13. package/template/neo-bi-cmps/src/components/targetNumber__c/model.ts +1 -1
  14. package/template/neo-bi-cmps/src/utils/common.ts +18 -20
  15. package/template/neo-bi-cmps/src/utils/filter2chartFilter.ts +4 -6
  16. package/template/neo-bi-cmps/src/utils/pipelineFunnel.ts +4 -2
  17. package/template/neo-bi-cmps/src/utils/simpleTable.tsx +21 -16
  18. package/template/neo-custom-cmp-template/docs/README.md +0 -231
  19. package/template/neo-custom-cmp-template/package.json +1 -1
  20. package/template/neo-h5-cmps/src/components/entityList__c/index.tsx +1 -2
  21. package/template/neo-h5-cmps/src/components/entityTabs__c/index.tsx +1 -1
  22. package/template/neo-h5-cmps/src/components/globalSearchInput__c/index.tsx +1 -1
  23. package/template/neo-h5-cmps/src/components/openChatPageBtn__c/index.tsx +1 -2
  24. package/template/neo-pipeline-cmps/neo.config.js +11 -0
  25. package/template/neo-pipeline-cmps/src/assets/css/common.scss +16 -16
  26. package/template/neo-pipeline-cmps/src/assets/css/mixin.scss +5 -5
  27. package/template/neo-pipeline-cmps/src/components/filterBar__c/README.md +9 -9
  28. package/template/neo-pipeline-cmps/src/components/filterBar__c/common.scss +5 -5
  29. package/template/neo-pipeline-cmps/src/components/filterBar__c/index.tsx +47 -46
  30. package/template/neo-pipeline-cmps/src/components/filterBar__c/model.ts +22 -12
  31. package/template/neo-pipeline-cmps/src/components/filterBar__c/style.scss +1 -1
  32. package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/README.md +17 -17
  33. package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/index.tsx +24 -22
  34. package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/model.ts +31 -18
  35. package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/reset.scss +4 -0
  36. package/template/neo-pipeline-cmps/src/components/showHealthResult__c/index.tsx +33 -26
  37. package/template/neo-pipeline-cmps/src/components/showHealthResult__c/model.ts +9 -9
  38. package/template/neo-pipeline-cmps/src/components/simpleTable__c/README.md +53 -54
  39. package/template/neo-pipeline-cmps/src/components/simpleTable__c/common.scss +5 -5
  40. package/template/neo-pipeline-cmps/src/components/simpleTable__c/index.tsx +70 -68
  41. package/template/neo-pipeline-cmps/src/components/simpleTable__c/model.ts +41 -41
  42. package/template/neo-pipeline-cmps/src/components/simpleTable__c/style.scss +2 -3
  43. package/template/neo-pipeline-cmps/src/components/stageSwitch__c/README.md +15 -15
  44. package/template/neo-pipeline-cmps/src/components/stageSwitch__c/index.tsx +35 -33
  45. package/template/neo-pipeline-cmps/src/components/stageSwitch__c/model.ts +29 -16
  46. package/template/neo-pipeline-cmps/src/components/stageTimeChart__c/README.md +18 -18
  47. package/template/neo-pipeline-cmps/src/components/stageTimeChart__c/index.tsx +20 -20
  48. package/template/neo-pipeline-cmps/src/components/stageTimeChart__c/model.ts +34 -19
  49. package/template/neo-pipeline-cmps/src/utils/common.ts +14 -14
  50. package/template/neo-pipeline-cmps/src/utils/filter2chartFilter.ts +21 -23
  51. package/template/neo-pipeline-cmps/src/utils/filterBar.ts +14 -14
  52. package/template/neo-pipeline-cmps/src/utils/pipelineFunnel.ts +5 -5
  53. package/template/neo-pipeline-cmps/src/utils/queryByCustomSQL.ts +26 -22
  54. package/template/neo-pipeline-cmps/src/utils/requestDebounce.ts +3 -3
  55. package/template/neo-pipeline-cmps/src/utils/simpleTable.tsx +31 -26
  56. package/template/neo-pipeline-cmps/src/utils/stageSwitch.ts +1 -1
  57. package/template/neo-pipeline-cmps/src/utils/stageTimeChart.ts +5 -5
  58. package/template/neo-pipeline-cmps/src/utils/targetNumber.ts +2 -2
  59. package/template/neo-web-entity-grid/src/components/createForm__c/index.tsx +271 -259
  60. package/template/neo-web-entity-grid/src/components/createForm__c/model.ts +17 -3
  61. package/template/neo-web-entity-grid/src/components/createForm__c/resetAntd.scss +0 -1
  62. package/template/neo-web-entity-grid/src/components/createForm__c/style.scss +1 -1
  63. package/template/neo-web-entity-grid/src/components/entityGrid2__c/index.tsx +5 -1
  64. package/template/neo-web-entity-grid/src/components/entityGrid2__c/model.ts +4 -3
  65. package/template/neo-web-entity-grid/src/components/entityGrid3__c/index.tsx +1 -1
  66. package/template/neo-web-entity-grid/src/components/searchForm__c/index.tsx +4 -3
  67. package/template/neo-web-entity-grid/src/components/searchForm__c/model.ts +9 -4
  68. package/template/neo-web-entity-grid/src/components/searchForm__c/style.scss +2 -1
  69. package/template/neo-web-form/package.json +1 -1
  70. package/template/neo-web-form/src/components/batchAddTable__c/index.tsx +179 -59
  71. package/template/neo-web-form/src/components/batchAddTable__c/model.ts +12 -14
  72. package/template/neo-web-form/src/components/listSummary__c/index.tsx +6 -5
  73. package/template/react-custom-cmp-template/package.json +1 -1
  74. package/template/asset-manage-template/src/utils/axiosFetcher.ts +0 -37
  75. package/template/asset-manage-template/src/utils/queryObjectData.ts +0 -112
  76. package/template/asset-manage-template/src/utils/xobjects.ts +0 -162
  77. package/template/neo-custom-cmp-template/src/utils/axiosFetcher.ts +0 -37
  78. package/template/neo-custom-cmp-template/src/utils/queryObjectData.ts +0 -112
  79. package/template/neo-custom-cmp-template/src/utils/xobjects.ts +0 -162
  80. package/template/neo-h5-cmps/src/utils/axiosFetcher.ts +0 -37
  81. package/template/neo-h5-cmps/src/utils/queryObjectData.ts +0 -112
  82. package/template/neo-h5-cmps/src/utils/xobjects.ts +0 -167
  83. package/template/neo-order-cmps/src/utils/axiosFetcher.ts +0 -37
  84. package/template/neo-order-cmps/src/utils/queryObjectData.ts +0 -112
  85. package/template/neo-order-cmps/src/utils/xobjects.ts +0 -162
  86. package/template/neo-web-entity-grid/src/utils/axiosFetcher.ts +0 -37
  87. package/template/neo-web-entity-grid/src/utils/queryObjectData.ts +0 -112
  88. package/template/neo-web-entity-grid/src/utils/xobjects.ts +0 -167
  89. package/template/neo-web-form/src/utils/axiosFetcher.ts +0 -37
  90. package/template/neo-web-form/src/utils/queryObjectData.ts +0 -112
  91. package/template/neo-web-form/src/utils/xobjects.ts +0 -167
@@ -1,5 +1,5 @@
1
1
  /**
2
- * 多组件共用的纯工具方法(筛选 where、阶段名、金额展示、NeoBI 请求体等)
2
+ * Shared pure utility methods across multiple components (filter where, stage name, amount display, NeoBI request body, etc.)
3
3
  */
4
4
 
5
5
  export interface PropsContext {
@@ -10,7 +10,7 @@ export interface PropsContext {
10
10
  };
11
11
  };
12
12
  }
13
- /** 筛选项转有限数字,无效返回 null(与 filter2chartFilter 等一致) */
13
+ /** Convert filter option to finite number, returns null if invalid (consistent with filter2chartFilter, etc.) */
14
14
  export function toFiniteNumber(v: unknown): number | null {
15
15
  if (v == null || v === '') return null;
16
16
  if (typeof v === 'number' && Number.isFinite(v)) return v;
@@ -18,7 +18,7 @@ export function toFiniteNumber(v: unknown): number | null {
18
18
  return Number.isFinite(n) ? n : null;
19
19
  }
20
20
 
21
- /** 时间区间起止:均为有效数字时返回闭区间 [start, end](毫秒时间戳,与 FilterBar 一致) */
21
+ /** Time range start/end: returns closed interval [start, end] when both are valid numbers (millisecond timestamps, consistent with FilterBar) */
22
22
  export function closeRangeFromFilter(
23
23
  range: unknown,
24
24
  ): { start: number; end: number } | null {
@@ -30,7 +30,7 @@ export function closeRangeFromFilter(
30
30
  return { start, end };
31
31
  }
32
32
 
33
- /** opportunityOwner 用于 where 的用户 id 列表(字符串避免大整数精度丢失) */
33
+ /** opportunityOwner -> user id list for where clause (string to avoid big integer precision loss) */
34
34
  export function normalizeOwnerIdsForWhere(owner: unknown): string[] {
35
35
  if (owner == null || owner === '') return [];
36
36
  const raw = Array.isArray(owner) ? owner : [owner];
@@ -51,7 +51,7 @@ export function entityTypeIdForWhere(businessType: unknown): string | null {
51
51
  return s.replace(/,/g, '');
52
52
  }
53
53
 
54
- /** 从阶段展示名取「第一个 . 之后」的片段,用于匹配 customItem1__c */
54
+ /** Extract the segment after the first '.' from stage display name, used for matching customItem1__c, etc. */
55
55
  export function extractStageKeyFromStageName(stageName: string): string {
56
56
  const s = String(stageName ?? '').trim();
57
57
  const i = s.indexOf('.');
@@ -59,7 +59,7 @@ export function extractStageKeyFromStageName(stageName: string): string {
59
59
  return s.slice(i + 1).trim();
60
60
  }
61
61
 
62
- /** 商机行等:空或无法解析时为 0 */
62
+ /** Opportunity rows, etc.: returns 0 when empty or unparseable */
63
63
  export function parseNumberOrZero(raw: unknown): number {
64
64
  if (raw === null || raw === undefined || raw === '') return 0;
65
65
  const n =
@@ -69,7 +69,7 @@ export function parseNumberOrZero(raw: unknown): number {
69
69
  return Number.isFinite(n) ? n : 0;
70
70
  }
71
71
 
72
- /** 阈值配置等:空或无法解析时为 NaN */
72
+ /** Threshold config, etc.: returns NaN when empty or unparseable */
73
73
  export function parseNumberOrNaN(raw: unknown): number {
74
74
  if (raw === null || raw === undefined || raw === '') return NaN;
75
75
  const n =
@@ -79,7 +79,7 @@ export function parseNumberOrNaN(raw: unknown): number {
79
79
  return Number.isFinite(n) ? n : NaN;
80
80
  }
81
81
 
82
- /** 展示用金额:$ 前缀;≥1e3 时使用 K / M / B / T 缩写 */
82
+ /** Display amount: $ prefix; uses K / M / B / T abbreviation when >= 1e3 */
83
83
  export function formatAmountDisplay(n: number): string {
84
84
  if (!Number.isFinite(n)) return '-';
85
85
  const sign = n < 0 ? '-' : '';
@@ -110,7 +110,7 @@ export function formatAmountDisplay(n: number): string {
110
110
  return `${sign}$${body}${suffix}`;
111
111
  }
112
112
 
113
- /** queryDataTaskx-www-form-urlencoded 表单体(filter JSON 字符串传递) */
113
+ /** queryDataTask: x-www-form-urlencoded form body (filter passed as JSON string) */
114
114
  export function buildQueryDataTaskFormBody(params: {
115
115
  viewId: string;
116
116
  userId: string | number;
@@ -125,11 +125,11 @@ export function buildQueryDataTaskFormBody(params: {
125
125
  return form.toString();
126
126
  }
127
127
 
128
- /** 负责人多选默认值:当前登录用户 id(与 __NeoCurrentUser 一致) */
128
+ /** Owner multi-select default: current logged-in user id (consistent with __NeoCurrentUser) */
129
129
  export function getDefaultOpportunityOwnerIds(
130
130
  props: PropsContext,
131
131
  ): (number | string)[] {
132
- // return [1246045]; // 默认用户改成 Alice
132
+ // return [1246045]; // Default user changed to (Alice)
133
133
  const curUser = props.data?.__NeoCurrentUser;
134
134
  if (
135
135
  curUser?.id == null ||
@@ -141,9 +141,9 @@ export function getDefaultOpportunityOwnerIds(
141
141
  return [curUser.id];
142
142
  }
143
143
 
144
- /** 负责人多选默认值:当前登录用户 id(与 __NeoCurrentUser 一致) */
144
+ /** Owner multi-select default: current logged-in user id (consistent with __NeoCurrentUser) */
145
145
  export function getDefaultFilterWhereByProps(props: any = {}): any {
146
- let userId = 1246045; // 默认用户(Alice
146
+ let userId = 1246045; // Default user (Alice)
147
147
  const curUser = props.data?.__NeoCurrentUser;
148
148
  if (curUser?.id) {
149
149
  userId = curUser.id;
@@ -207,7 +207,7 @@ export function getDefaultFilterWhereByProps(props: any = {}): any {
207
207
  }
208
208
 
209
209
  export function getDefaultFilterByProps(props: any = {}): any {
210
- let userId = 1246045; // 默认用户(Alice
210
+ let userId = 1246045; // Default user (Alice)
211
211
  const curUser = props.data?.__NeoCurrentUser;
212
212
  if (curUser?.id) {
213
213
  userId = curUser.id;
@@ -1,26 +1,26 @@
1
1
  /**
2
- * 过滤条件格式化
3
- * 将筛选栏组件得到的过滤条件格式化为接口需要的格式。
2
+ * Filter condition formatting
3
+ * Formats the filter conditions from the filter bar component into the format required by the API.
4
4
  *
5
- * 数据转换规则:
5
+ * Data conversion rules:
6
6
  1. closeDate
7
7
 
8
- custom:用 toFiniteNumber 把选项值(如 201 / "201")转成数字,timeType: 'relative'value: [{ val, baseType: 'system' }]
9
- custom:读取 closeDateCustomRange.start / end,二者均为有效数字时,timeType: 'absolute'value 为两条 { val, close: 1 };缺区间则不生成该项。
8
+ Non-custom: Use toFiniteNumber to convert the option value (e.g. 201 / "201") to a number, timeType: 'relative', value: [{ val, baseType: 'system' }].
9
+ custom: Read closeDateCustomRange.start / end; when both are valid numbers, timeType: 'absolute', value is two { val, close: 1 } entries; if range is missing, this item is not generated.
10
10
 
11
- 2. opportunityOwner ownerId
12
- 支持单值(字符串/数字)或多选数组;逐项 toFiniteNumber,无效项丢弃。至少一个有效 id 时生成 refer 条件(referKey: 'user'optionType: 'user'operate: 'in'includeNullValue: 0)。
13
- value 为数组,每个用户为 { val, sub: false, source: 'internal', specialType: 0 }
11
+ 2. opportunityOwner -> ownerId
12
+ Supports single value (string/number) or multi-select array; toFiniteNumber each item, invalid items are discarded. When at least one valid id exists, generates a refer condition (referKey: 'user', optionType: 'user', operate: 'in', includeNullValue: 0).
13
+ value is an array, each user is { val, sub: false, source: 'internal', specialType: 0 }.
14
14
 
15
- 3. businessType entityType
16
- 有值且能转成数字时,生成 refer + value: [{ val }];空字符串不传 entityType
15
+ 3. businessType -> entityType
16
+ When a value exists and can be converted to a number, generates refer + value: [{ val }]; empty string does not pass entityType.
17
17
 
18
18
  4. relation
19
- 按最终条目的 seq 拼成 "1 and 2 and 3";没有任何条件时为 ''filter []
19
+ Concatenated as "1 and 2 and 3" based on the seq of final items; when there are no conditions, it is '', filter is [].
20
20
 
21
21
  *
22
- * 例如:
23
- * 筛选栏组件得到的过滤条件:
22
+ * Example:
23
+ * Filter conditions from the filter bar component:
24
24
  {
25
25
  "closeDate": "custom",
26
26
  "closeDateCustomRange": {
@@ -33,7 +33,7 @@ value 为数组,每个用户为 { val, sub: false, source: 'internal', special
33
33
  "changesSinceCustomTime": 1776268800000
34
34
  }
35
35
 
36
- 接口需要的格式:
36
+ Format required by the API:
37
37
  {
38
38
  "relation": "1 and 2 and 3",
39
39
  "filter": [
@@ -96,7 +96,7 @@ value 为数组,每个用户为 { val, sub: false, source: 'internal', special
96
96
  ]
97
97
  }
98
98
 
99
- 如果是 closeDate custom,则需要将 closeDateCustomRange 格式化为接口需要的格式
99
+ If closeDate is custom, the closeDateCustomRange needs to be formatted into the API-required format
100
100
  {
101
101
  "seq": 3,
102
102
  "fieldKey": "closeDate",
@@ -193,7 +193,7 @@ const ownerUserValueItem = (val: number) => ({
193
193
  specialType: 0,
194
194
  });
195
195
 
196
- /** opportunityOwner(单值或 id 数组)解析出有效的用户 id 列表 */
196
+ /** Parse valid user id list from opportunityOwner (single value or id array) */
197
197
  function normalizeOwnerIds(owner: unknown): number[] {
198
198
  if (owner == null || owner === '') return [];
199
199
  const raw = Array.isArray(owner) ? owner : [owner];
@@ -244,15 +244,13 @@ function entityTypeChunk(
244
244
  }
245
245
 
246
246
  /**
247
- * 将筛选栏 payload 转为图表/接口 filter 结构;仅映射 closeDateownerIdentityType
247
+ * Convert filter bar payload to chart/API filter structure; only maps closeDate, ownerId, entityType.
248
248
  */
249
249
  export const filter2chartFilter = (filter: any): ChartFilterPayload => {
250
250
  const f = filter && typeof filter === 'object' ? filter : {};
251
- const parts = [
252
- closeDateChunk(f),
253
- ownerChunk(f),
254
- entityTypeChunk(f),
255
- ].filter(Boolean) as Omit<ChartFilterItem, 'seq'>[];
251
+ const parts = [closeDateChunk(f), ownerChunk(f), entityTypeChunk(f)].filter(
252
+ Boolean,
253
+ ) as Omit<ChartFilterItem, 'seq'>[];
256
254
 
257
255
  const filterOut: ChartFilterItem[] = parts.map((p, i) => ({
258
256
  ...p,
@@ -265,4 +263,4 @@ export const filter2chartFilter = (filter: any): ChartFilterPayload => {
265
263
  : filterOut.map((x) => String(x.seq)).join(' and ');
266
264
 
267
265
  return { relation, filter: filterOut };
268
- };
266
+ };
@@ -1,22 +1,22 @@
1
1
  /**
2
- * 筛选栏 filterBar 专用工具方法
2
+ * Filter bar filterBar specific utility methods
3
3
  */
4
4
  import moment from 'moment';
5
5
 
6
6
  export interface FilterOption {
7
7
  value: string | number;
8
8
  label: string;
9
- /** 业务类型等接口项上的 apiKey,用于与 defaultBusiType 配置对齐 */
9
+ /** apiKey on API items like business type, used to align with defaultBusiType config */
10
10
  apiKey?: string;
11
11
  }
12
12
 
13
- /** 自定义日期区间:起止为 Unix 毫秒时间戳(日为本地 startOfDay / endOfDay */
13
+ /** Custom date range: start/end are Unix millisecond timestamps (day is local startOfDay / endOfDay) */
14
14
  export interface TimestampRange {
15
15
  start?: number;
16
16
  end?: number;
17
17
  }
18
18
 
19
- /** 规范化下拉项的 value / label */
19
+ /** Normalize dropdown item value / label */
20
20
  export function normalizeOptions(list?: FilterOption[]): FilterOption[] {
21
21
  if (!Array.isArray(list) || list.length === 0) return [];
22
22
  return list.map((o) => ({
@@ -25,7 +25,7 @@ export function normalizeOptions(list?: FilterOption[]): FilterOption[] {
25
25
  }));
26
26
  }
27
27
 
28
- /** Changes Since 下拉默认项 */
28
+ /** Changes Since dropdown default options */
29
29
  export function defaultChangesSinceOptions(): FilterOption[] {
30
30
  return [
31
31
  { value: 'Start of the Period', label: 'Start of the Period' },
@@ -33,7 +33,7 @@ export function defaultChangesSinceOptions(): FilterOption[] {
33
33
  ];
34
34
  }
35
35
 
36
- /** RangePicker 选中的两天转为起止时间戳(含当日) */
36
+ /** Convert two selected days from RangePicker to start/end timestamps (inclusive of the day) */
37
37
  export function momentRangeToTimestamps(dates: any): TimestampRange | null {
38
38
  const m0 = dates?.[0];
39
39
  const m1 = dates?.[1];
@@ -45,8 +45,8 @@ export function momentRangeToTimestamps(dates: any): TimestampRange | null {
45
45
  }
46
46
 
47
47
  /**
48
- * Close Date 相对周期编码转为本地自然日的起止时间戳(起点 0 点,终点 23:59:59.999)。
49
- * 约定:百位 2=本周(iso )3=本月、4=本季度(如 201/301/401 及同段其它编码)。
48
+ * Convert Close Date relative period code to local calendar day start/end timestamps (start at midnight, end at 23:59:59.999).
49
+ * Convention: hundreds digit 2=this week (ISO week), 3=this month, 4=this quarter (e.g. 201/301/401 and other codes in the same range).
50
50
  */
51
51
  export function relativeCloseDateRangeFromCode(
52
52
  encoded: number | string,
@@ -62,7 +62,7 @@ export function relativeCloseDateRangeFromCode(
62
62
  };
63
63
  }
64
64
  if (curEncoded === 301) {
65
- // This Month(起点为月初次日 0 点)
65
+ // This Month (start is the second day of the month at midnight)
66
66
  return {
67
67
  start: now
68
68
  .clone()
@@ -74,7 +74,7 @@ export function relativeCloseDateRangeFromCode(
74
74
  };
75
75
  }
76
76
  if (curEncoded === 401) {
77
- // This Quarter(起点为季首次日 0 点)
77
+ // This Quarter (start is the second day of the quarter at midnight)
78
78
  return {
79
79
  start: now
80
80
  .clone()
@@ -88,7 +88,7 @@ export function relativeCloseDateRangeFromCode(
88
88
  return null;
89
89
  }
90
90
 
91
- /** user 实体查询结果转为负责人下拉项(按 id 去重) */
91
+ /** Convert user entity query results to owner dropdown options (deduplicated by id) */
92
92
  export function parseUserRecordsToOwnerOptions(records: any): FilterOption[] {
93
93
  const arr = Array.isArray(records) ? records : [];
94
94
  const seen = new Set<string>();
@@ -104,7 +104,7 @@ export function parseUserRecordsToOwnerOptions(records: any): FilterOption[] {
104
104
  return out;
105
105
  }
106
106
 
107
- /** 从业务类型接口响应中取出列表数组 */
107
+ /** Extract list array from business type API response */
108
108
  export function getBusinessTypeRawList(res: any): any[] {
109
109
  const raw = res?.data !== undefined ? res.data : res;
110
110
  const arr = Array.isArray(raw)
@@ -113,7 +113,7 @@ export function getBusinessTypeRawList(res: any): any[] {
113
113
  return Array.isArray(arr) ? arr : [];
114
114
  }
115
115
 
116
- /** 解析业务类型接口结果为下拉选项(保留 apiKey 供默认项匹配) */
116
+ /** Parse business type API results to dropdown options (preserving apiKey for default item matching) */
117
117
  export function parseBusinessTypes(res: any): FilterOption[] {
118
118
  const arr = getBusinessTypeRawList(res);
119
119
  return arr
@@ -126,7 +126,7 @@ export function parseBusinessTypes(res: any): FilterOption[] {
126
126
  }
127
127
 
128
128
  /**
129
- * 在业务类型选项中按 apiKey === defaultBusiType 解析默认选中值(与下拉 value 一致,一般为 id
129
+ * Resolve default selected value in business type options by apiKey === defaultBusiType (consistent with dropdown value, usually id)
130
130
  */
131
131
  export function resolveDefaultBusinessTypeValue(
132
132
  options: FilterOption[],
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Pipeline 漏斗 pipelineFunnel 专用(解析表格行、ECharts 配置)
2
+ * Pipeline funnel pipelineFunnel specific (parse table rows, ECharts config)
3
3
  */
4
4
  import * as echarts from 'echarts';
5
5
 
@@ -41,7 +41,7 @@ export function isTruthyProp(v: unknown): boolean {
41
41
  return v === true || v === 'true' || v === 1 || v === '1';
42
42
  }
43
43
 
44
- /** 与后端阶段名比对时忽略大小写与连续空白 */
44
+ /** Ignore case and consecutive whitespace when comparing with backend stage names */
45
45
  export function isClosedLostStageName(raw: unknown): boolean {
46
46
  const n = String(raw ?? '')
47
47
  .trim()
@@ -50,7 +50,7 @@ export function isClosedLostStageName(raw: unknown): boolean {
50
50
  return n === 'closed lost';
51
51
  }
52
52
 
53
- /** 去掉 Closed Lost 阶段行,保留表头;须在 parseRowsToStages 之前调用,以免计入总额与占比 */
53
+ /** Remove Closed Lost stage rows, keep header; must be called before parseRowsToStages to avoid counting in total and percentage */
54
54
  export function filterOutClosedLostRows(table: unknown[][]): unknown[][] {
55
55
  if (!Array.isArray(table) || table.length < 2) return table;
56
56
  const header = table[0];
@@ -122,7 +122,7 @@ export function funnelValueForStage(
122
122
  return 0;
123
123
  }
124
124
 
125
- /** 经典漏斗:宽度仍由 value(顺序)控制;层高按金额占比分配(与 series.gap 一致,单位为 px */
125
+ /** Classic funnel: width still controlled by value (order); layer height allocated by amount proportion (consistent with series.gap, unit is px) */
126
126
  export function classicFunnelLayerHeightPercents(
127
127
  amountNums: number[],
128
128
  viewHeightPx: number,
@@ -144,7 +144,7 @@ export function classicFunnelLayerHeightPercents(
144
144
  }
145
145
 
146
146
  export interface BuildFunnelChartOptionParams {
147
- /** 容器高度(px),经典模式下用于计算各层 height 百分比;变化时应重新 setOption */
147
+ /** Container height (px), used in classic mode to calculate layer height percentages; should re-setOption when changed */
148
148
  chartViewHeightPx?: number;
149
149
  funnelGap?: number;
150
150
  }
@@ -2,10 +2,10 @@
2
2
  import { request as axiosFetcher } from 'neo-open-api';
3
3
 
4
4
  /**
5
- * 这里存放通用查询类 Open API
5
+ * Common query Open APIs are stored here
6
6
  */
7
7
 
8
- /** where 规范为 SQL 片段:字符串直接使用;数组用 and 拼接各条件 */
8
+ /** Normalize where to SQL fragment: string is used directly; array items are joined with 'and' */
9
9
  function normalizeWhere(where: unknown): string {
10
10
  if (where == null || where === '') {
11
11
  return '';
@@ -22,7 +22,7 @@ function normalizeWhere(where: unknown): string {
22
22
  return '';
23
23
  }
24
24
 
25
- // 根据 sql 查询 BI 数据
25
+ // Query BI data by SQL
26
26
  export const queryByCustomSQL = async (options?: any) => {
27
27
  const apiUrl = '/rest/neobi/v2.0/query/queryByCustomSQL';
28
28
  const curOptions = options || {};
@@ -31,34 +31,34 @@ export const queryByCustomSQL = async (options?: any) => {
31
31
  const page = curOptions.page || 1;
32
32
  const pageSize = curOptions.pageSize || 10;
33
33
 
34
- // 自动添加 objectId 字段
34
+ // Automatically add objectId field
35
35
  if (!fields.includes('id')) {
36
36
  fields.push('id');
37
37
  }
38
38
 
39
- // 计算分页偏移量
39
+ // Calculate pagination offset
40
40
  const offset = (page - 1) * pageSize;
41
41
 
42
- // 构建 SQL 查询
42
+ // Build SQL query
43
43
  let querySql = `select ${fields.join(',')} from ${xObjectApiKey}`;
44
44
 
45
- // 添加排序条件(如果有的话)
45
+ // Add sort conditions (if any)
46
46
  if (curOptions.orderBy) {
47
47
  querySql += ` order by ${curOptions.orderBy}`;
48
48
  }
49
49
 
50
50
  /**
51
- * 添加过滤条件(如果有的话)
52
- * 支持的操作符包括:=、!=、likenot likenot inis not nullis null、>、<、<>、>=、<=、inbetween ... and ...。
53
- * 对于 =、like in 有以下说明:
54
- * “=” 作为字符串的条件时,表示精确匹配。例如,查询条件 city = '北京',将返回 city 字段值严格等于 "北京" 的所有记录。
55
- * "like" 作为字符串的条件时,需要使用"%" 通配符进行模糊匹配。例如,city like‘北京%',将返回 city 字段值以 "北京" 开头的所有记录。
56
- * 目前仅支持将通配符“%” 放到已知内容之后的查询方式,例如,不支持 city like ‘% 北京'的查询方式。
57
- * SQL 查询中包含“%”等特殊字符时,需要对 SQL 进行 URL 编码处理。
58
- * 支持"in",但不包括子查询。
59
- * 支持的逻辑运算符包括:andor
51
+ * Add filter conditions (if any)
52
+ * Supported operators: =, !=, like, not like, not in, is not null, is null, >, <, <>, >=, <=, in, between ... and ...
53
+ * Notes for =, like and in:
54
+ * "=" as a string condition means exact match. For example, city = 'Beijing' returns all records where city is strictly equal to "Beijing".
55
+ * "like" as a string condition requires "%" wildcard for fuzzy matching. For example, city like 'Beijing%' returns all records where city starts with "Beijing".
56
+ * Currently only supports placing "%" after the known content; e.g., city like '% Beijing' is not supported.
57
+ * When the SQL query contains special characters like "%", URL encoding is required.
58
+ * Supports "in", but not subqueries.
59
+ * Supported logical operators: and, or.
60
60
  *
61
- * `where` 可为字符串,或字符串数组(多项默认以 and 连接,等价于手写 `a and b`)。
61
+ * `where` can be a string, or a string array (multiple items joined with 'and' by default, equivalent to `a and b`).
62
62
  */
63
63
  const whereClause = normalizeWhere(curOptions.where);
64
64
 
@@ -67,7 +67,7 @@ export const queryByCustomSQL = async (options?: any) => {
67
67
  }
68
68
 
69
69
  if (curOptions.page || curOptions.pageSize) {
70
- // 添加分页限制
70
+ // Add pagination limit
71
71
  querySql += ` limit ${offset},${pageSize}`;
72
72
  }
73
73
 
@@ -91,7 +91,8 @@ export const queryByCustomSQL = async (options?: any) => {
91
91
  return {
92
92
  status: true,
93
93
  code: resultData.code,
94
- msg: resultData.msg || '获取业务对象数据列表成功',
94
+ msg:
95
+ resultData.msg || 'Successfully retrieved business object data list',
95
96
  totalSize: records.length,
96
97
  data: records || [],
97
98
  };
@@ -100,15 +101,18 @@ export const queryByCustomSQL = async (options?: any) => {
100
101
  return {
101
102
  status: false,
102
103
  code: resultData.code,
103
- msg: resultData.msg || '获取业务对象数据列表失败',
104
+ msg: resultData.msg || 'Failed to retrieve business object data list',
104
105
  data: [],
105
106
  };
106
107
  } catch (error) {
107
- console.error('获取业务对象数据列表失败:', error);
108
+ console.error('Failed to retrieve business object data list:', error);
108
109
 
109
110
  return {
110
111
  status: false,
111
- msg: error.msg || error.message || '获取业务对象数据列表失败',
112
+ msg:
113
+ error.msg ||
114
+ error.message ||
115
+ 'Failed to retrieve business object data list',
112
116
  data: [],
113
117
  };
114
118
  }
@@ -1,10 +1,10 @@
1
1
  // @ts-nocheck
2
2
  import debounce from 'lodash/debounce';
3
3
 
4
- /** 组件内数据请求防抖间隔(毫秒),用于合并短时间内的重复触发 */
4
+ /** Data request debounce interval in milliseconds for components, used to merge repeated triggers within a short time */
5
5
  export const REQUEST_DEBOUNCE_MS = 280;
6
6
 
7
- /** lodash debounce 实例(避免依赖 @types/lodash */
7
+ /** lodash debounce instance (avoids dependency on @types/lodash) */
8
8
  export type DebouncedRequestFn = {
9
9
  (): void;
10
10
  cancel(): void;
@@ -12,7 +12,7 @@ export type DebouncedRequestFn = {
12
12
  };
13
13
 
14
14
  /**
15
- * 尾部防抖:连续触发时仅在停顿后执行一次,适合 filter / props 连更新场景。
15
+ * Trailing debounce: executes only once after a pause during continuous triggers, suitable for filter / props rapid update scenarios.
16
16
  */
17
17
  export function createRequestDebounce(
18
18
  fn: () => void,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * 表格 simpleTable 专用:格式化、历史快照、趋势与单元格渲染
2
+ * Table simpleTable specific: formatting, history snapshots, trends and cell rendering
3
3
  */
4
4
  import * as React from 'react';
5
5
  import { Card, Popover } from 'antd';
@@ -7,7 +7,7 @@ import moment from 'moment';
7
7
 
8
8
  import { toFiniteNumber } from './common';
9
9
 
10
- /** 期间初商机快照(与当前行 id 关联) */
10
+ /** Period-start opportunity snapshot (associated with current row id) */
11
11
  export interface HistoryOppSnap {
12
12
  id: string;
13
13
  closeDate: unknown;
@@ -67,7 +67,7 @@ function closeDateTrend(
67
67
  return 'same';
68
68
  }
69
69
 
70
- /** 自定义 SQL 返回行:数组列顺序与 HISTORY_QUERY_FIELDS 一致;或对象字段 */
70
+ /** Custom SQL return row: array column order matches HISTORY_QUERY_FIELDS; or object fields */
71
71
  export function historyRowToSnap(row: unknown): HistoryOppSnap | null {
72
72
  if (row == null) return null;
73
73
  if (Array.isArray(row)) {
@@ -91,9 +91,7 @@ export function historyRowToSnap(row: unknown): HistoryOppSnap | null {
91
91
  opportunityName: String(
92
92
  o.opportunity_1_opportunityName ?? o.opportunityName ?? '',
93
93
  ),
94
- saleStageId: String(
95
- o.opportunity_1_saleStageId ?? o.saleStageId ?? '',
96
- ),
94
+ saleStageId: String(o.opportunity_1_saleStageId ?? o.saleStageId ?? ''),
97
95
  money: o.opportunity_1_money ?? o.money,
98
96
  };
99
97
  }
@@ -123,7 +121,7 @@ export function formatActivityDateTime(value: unknown): string {
123
121
  return m.isValid() ? m.format('YYYY-MM-DD HH:mm:ss') : String(value);
124
122
  }
125
123
 
126
- /** customItem246/247:变更记录时间(毫秒/秒时间戳或可被 moment 解析的值)→ YYYY-MM-DD */
124
+ /** customItem246/247: change record time (ms/s timestamp or moment-parseable value) -> YYYY-MM-DD */
127
125
  export function formatChangeRecordedAt(value: unknown): string {
128
126
  if (value == null || value === '') return '—';
129
127
  const n = toFiniteNumber(value);
@@ -136,7 +134,7 @@ export function formatChangeRecordedAt(value: unknown): string {
136
134
  return m.isValid() ? m.format('YYYY-MM-DD') : String(value);
137
135
  }
138
136
 
139
- /** 金额列:$ 前缀 + 千分位(不缩写) */
137
+ /** Money column: $ prefix + thousands separator (no abbreviation) */
140
138
  export function formatMoneyCell(value: unknown): string {
141
139
  if (value == null || value === '') return '—';
142
140
  const n = parseFloat(String(value).replace(/,/g, '').trim());
@@ -150,8 +148,10 @@ export function formatMoneyCell(value: unknown): string {
150
148
  return `$${part}`;
151
149
  }
152
150
 
153
- /** oppHealthAssessmentLevel:数值 健康度标签(带颜色背景) */
154
- export function renderOppHealthAssessmentLevel(value: unknown): React.ReactNode {
151
+ /** oppHealthAssessmentLevel: numeric value -> health label (with colored background) */
152
+ export function renderOppHealthAssessmentLevel(
153
+ value: unknown,
154
+ ): React.ReactNode {
155
155
  if (value == null || value === '') return '—';
156
156
  const n = toFiniteNumber(value);
157
157
  if (n === 5) {
@@ -160,7 +160,9 @@ export function renderOppHealthAssessmentLevel(value: unknown): React.ReactNode
160
160
  );
161
161
  }
162
162
  if (n === 6) {
163
- return <span className="opp-health-tag opp-health-tag--yellow">Health</span>;
163
+ return (
164
+ <span className="opp-health-tag opp-health-tag--yellow">Health</span>
165
+ );
164
166
  }
165
167
  if (n === 7) {
166
168
  return <span className="opp-health-tag opp-health-tag--red">Risk</span>;
@@ -172,7 +174,7 @@ export function renderOppHealthAssessmentLevel(value: unknown): React.ReactNode
172
174
  }
173
175
 
174
176
  /**
175
- * 百分比列:末尾加 %;接口常见为 01 小数或 0100 数值,均按可读方式展示
177
+ * Percentage column: appends %; API commonly returns 0-1 decimal or 0-100 numeric, both displayed in readable format
176
178
  */
177
179
  export function formatPercentCell(value: unknown): string {
178
180
  if (value == null || value === '') return '—';
@@ -205,7 +207,9 @@ export function moneyChangeTooltipTitle(
205
207
  <div className="simpleTable-change-tip__detail">
206
208
  {formatMoneyCell(h.money)}
207
209
  {' → '}
208
- <span className="simpleTable-change-tip__to">{formatMoneyCell(current)}</span>
210
+ <span className="simpleTable-change-tip__to">
211
+ {formatMoneyCell(current)}
212
+ </span>
209
213
  </div>
210
214
  <div className="simpleTable-change-tip__meta">
211
215
  Changed on {formatChangeRecordedAt(preset)}
@@ -227,7 +231,9 @@ export function closeDateChangeTooltipTitle(
227
231
  <div className="simpleTable-change-tip__detail">
228
232
  {formatCloseDate(h.closeDate)}
229
233
  {' → '}
230
- <span className="simpleTable-change-tip__to">{formatCloseDate(current)}</span>
234
+ <span className="simpleTable-change-tip__to">
235
+ {formatCloseDate(current)}
236
+ </span>
231
237
  </div>
232
238
  <div className="simpleTable-change-tip__meta">
233
239
  Changed on {formatChangeRecordedAt(preset)}
@@ -268,22 +274,17 @@ export function renderTrendCell(args: {
268
274
  );
269
275
  }
270
276
 
271
- /** demo.html winRateTooltip 风格 */
277
+ /** demo.html winRateTooltip style */
272
278
  export function renderWinRateHoverCard(record: any): React.ReactNode {
273
279
  const baseline = record?.customItem244__c;
274
280
  const positives = record?.customItem241__c;
275
281
  const negatives = record?.customItem242__c;
276
282
  const winRate = record?.customItem239__c;
277
283
 
278
- const fmtLine = (v: unknown) =>
279
- v == null || v === '' ? '—' : String(v);
284
+ const fmtLine = (v: unknown) => (v == null || v === '' ? '—' : String(v));
280
285
 
281
286
  return (
282
- <Card
283
- size="small"
284
- bordered={false}
285
- className="simpleTable-winrate-card"
286
- >
287
+ <Card size="small" bordered={false} className="simpleTable-winrate-card">
287
288
  <div className="simpleTable-winrate-card__baseline">
288
289
  Baseline Probability{' '}
289
290
  <span className="simpleTable-winrate-card__baseline-val">
@@ -291,12 +292,16 @@ export function renderWinRateHoverCard(record: any): React.ReactNode {
291
292
  </span>
292
293
  </div>
293
294
  <hr className="simpleTable-winrate-card__hr" />
294
- <div className="simpleTable-winrate-card__section-title">Positive Factors</div>
295
+ <div className="simpleTable-winrate-card__section-title">
296
+ Positive Factors
297
+ </div>
295
298
  <div className="simpleTable-winrate-card__positives">
296
299
  {fmtLine(positives)}
297
300
  </div>
298
301
  <hr className="simpleTable-winrate-card__hr" />
299
- <div className="simpleTable-winrate-card__section-title">Negative Factors</div>
302
+ <div className="simpleTable-winrate-card__section-title">
303
+ Negative Factors
304
+ </div>
300
305
  <div className="simpleTable-winrate-card__negatives">
301
306
  {fmtLine(negatives)}
302
307
  </div>
@@ -311,7 +316,7 @@ export function renderWinRateHoverCard(record: any): React.ReactNode {
311
316
  );
312
317
  }
313
318
 
314
- /** 汇总金额展示(与 formatMoneyCell 数字格式一致) */
319
+ /** Summary amount display (number format consistent with formatMoneyCell) */
315
320
  export function formatMoneySummaryAmount(n: number): string {
316
321
  const part = Number.isInteger(n)
317
322
  ? n.toLocaleString('en-US')
@@ -322,7 +327,7 @@ export function formatMoneySummaryAmount(n: number): string {
322
327
  return `$${part}`;
323
328
  }
324
329
 
325
- /** 按字段 apiKey 汇总行金额(解析规则与金额列一致) */
330
+ /** Sum row amounts by field apiKey (parsing rules consistent with money column) */
326
331
  export function sumMoneyRows(rows: any[], moneyFieldKey: string): number {
327
332
  let total = 0;
328
333
  for (const row of rows) {