neo-cmp-cli 1.13.13 → 1.13.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/neo/neoEnvManager.js +1 -1
- package/dist/neo/neoLogin.js +1 -1
- package/dist/neo/neoRequire.js +1 -1
- package/dist/package.json.js +1 -1
- package/docs//351/200/232/347/224/250/344/273/243/347/220/206/346/216/245/345/217/243/forward.zip +0 -0
- package/docs//351/200/232/347/224/250/344/273/243/347/220/206/346/216/245/345/217/243//350/207/252/345/256/232/344/271/211API:/351/200/232/347/224/250/344/273/243/347/220/206/346/216/245/345/217/243/344/275/277/347/224/250/350/257/264/346/230/216.md +13 -0
- package/package.json +1 -1
- package/template/antd-custom-cmp-template/package.json +1 -1
- package/template/asset-manage-template/package.json +1 -1
- package/template/echarts-custom-cmp-template/package.json +1 -1
- package/template/empty-custom-cmp-template/package.json +1 -1
- package/template/map-custom-cmp-template/package.json +1 -1
- package/template/neo-bi-cmps/package.json +1 -1
- package/template/neo-bi-cmps/src/components/aiCommitDrawer__c/index.tsx +17 -10
- package/template/neo-bi-cmps/src/components/aiCommitDrawer__c/model.ts +47 -6
- package/template/neo-bi-cmps/src/components/filterBar__c/index.tsx +21 -7
- package/template/neo-bi-cmps/src/components/forecastChart__c/index.tsx +6 -9
- package/template/neo-bi-cmps/src/components/forecastChart__c/model.ts +2 -1
- package/template/neo-bi-cmps/src/components/forecastGrid__c/model.ts +32 -4
- package/template/neo-bi-cmps/src/components/gapCloser__c/index.tsx +7 -2
- package/template/neo-bi-cmps/src/components/gapCloser__c/model.ts +6 -3
- package/template/neo-bi-cmps/src/components/kpiCards__c/model.ts +18 -3
- package/template/neo-bi-cmps/src/components/oppList__c/index.tsx +70 -13
- package/template/neo-bi-cmps/src/components/oppList__c/model.ts +50 -4
- package/template/neo-bi-cmps/src/components/pipelineFunnel__c/index.tsx +3 -1
- package/template/neo-bi-cmps/src/components/pipelineFunnel__c/model.ts +28 -4
- package/template/neo-bi-cmps/src/components/stageSwitch__c/index.tsx +21 -6
- package/template/neo-bi-cmps/src/components/stageSwitch__c/model.ts +60 -5
- package/template/neo-bi-cmps/src/components/stageTimeChart__c/model.ts +26 -4
- package/template/neo-custom-cmp-template/package.json +1 -1
- package/template/neo-h5-cmps/package.json +1 -1
- package/template/neo-order-cmps/package.json +1 -1
- package/template/neo-web-entity-grid/package.json +1 -1
- package/template/neo-web-form/package.json +1 -1
- package/template/neo-web-form/src/components/batchAddTable__c/index.tsx +17 -17
- package/template/react-custom-cmp-template/package.json +1 -1
- package/template/react-ts-custom-cmp-template/package.json +1 -1
- package/template/vue2-custom-cmp-template/package.json +1 -1
- package/template/neo-bi-cmps/docs/gartner-pipeline-apis.md +0 -279
- package/template/neo-bi-cmps/docs/gartner-pipeline-prd.md +0 -389
- package/template/neo-bi-cmps/docs/neo-backend-dev/SKILL.md +0 -188
- package/template/neo-bi-cmps/docs/neo-backend-dev/references/01-Trigger/345/274/200/345/217/221.md +0 -183
- package/template/neo-bi-cmps/docs/neo-backend-dev/references/02-/350/207/252/345/256/232/344/271/211API/345/274/200/345/217/221.md +0 -196
- package/template/neo-bi-cmps/docs/neo-backend-dev/references/03-SDK/345/267/245/345/205/267/347/261/273/346/216/245/345/217/243.md +0 -346
- package/template/neo-bi-cmps/docs/neo-backend-dev/references/04-/350/256/241/345/210/222/344/275/234/344/270/232/345/274/200/345/217/221.md +0 -188
- package/template/neo-bi-cmps/docs/neo-backend-dev/references/05-/351/241/265/351/235/242/345/274/200/345/217/221.md +0 -293
- package/template/neo-bi-cmps/docs/neo-backend-dev/references/06-/346/265/201/347/250/213/346/211/251/345/261/225/345/274/200/345/217/221.md +0 -175
- package/template/neo-bi-cmps/docs/neo-backend-dev/references/PaaS/345/271/263/345/217/260/345/274/200/345/217/221/346/211/213/345/206/214/350/247/243/350/257/273.md +0 -313
- package/template/neo-bi-cmps/docs/neo-backend-dev/references/auth-config.md +0 -77
- package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/deploy_server_script.py +0 -118
- package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/download_server_script.py +0 -74
- package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/gen_entity_desc.py +0 -69
- package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/gen_entitylist.py +0 -87
- package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/query_crm.py +0 -65
- package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/uninstall_server_script.py +0 -48
- package/template/neo-bi-cmps/docs/neo-backend-dev/scripts/update_model_jar.py +0 -49
- package/template/neo-bi-cmps/docs/neo-frontend-dev/SKILL.md +0 -138
- package/template/neo-bi-cmps/docs/neo-frontend-dev/references/auth-config.md +0 -77
- package/template/neo-bi-cmps/docs/neo-frontend-dev/references/component-dev.md +0 -205
- package/template/neo-bi-cmps/docs/neo-frontend-dev/references/entityTable-example.md +0 -167
- package/template/neo-bi-cmps/docs/neo-frontend-dev/references/templates.md +0 -38
- package/template/neo-bi-cmps/docs/neo-frontend-dev/scripts/gen_entity_desc.py +0 -69
- package/template/neo-bi-cmps/docs/neo-frontend-dev/scripts/gen_entitylist.py +0 -87
- package/template/neo-bi-cmps/docs/neo-frontend-dev/scripts/query_crm.py +0 -65
- package/template/neo-bi-cmps/docs/prototype-pipeline-forecasting.html +0 -2453
- package/template/neo-bi-cmps/docs//350/264/246/345/217/267/347/233/270/345/205/263/344/277/241/346/201/257.md +0 -10
|
@@ -142,7 +142,9 @@ class OppList extends BaseCmp<OppListProps, OppListState> {
|
|
|
142
142
|
{tabs.map((tab) => (
|
|
143
143
|
<button
|
|
144
144
|
key={tab.key}
|
|
145
|
-
className={`opp-tab-btn ${
|
|
145
|
+
className={`opp-tab-btn ${
|
|
146
|
+
activeTab === tab.key ? 'active' : ''
|
|
147
|
+
}`}
|
|
146
148
|
onClick={() => this.handleTabChange(tab.key)}
|
|
147
149
|
>
|
|
148
150
|
{tab.icon} {tab.label}
|
|
@@ -157,8 +159,14 @@ class OppList extends BaseCmp<OppListProps, OppListState> {
|
|
|
157
159
|
{filterChips.map((chip, index) => (
|
|
158
160
|
<button
|
|
159
161
|
key={index}
|
|
160
|
-
className={`watch-sub-tab ${
|
|
161
|
-
|
|
162
|
+
className={`watch-sub-tab ${
|
|
163
|
+
activeChip === chip.split('(')[0].trim().toLowerCase()
|
|
164
|
+
? 'active'
|
|
165
|
+
: ''
|
|
166
|
+
}`}
|
|
167
|
+
onClick={() =>
|
|
168
|
+
this.handleChipChange(chip.split('(')[0].trim().toLowerCase())
|
|
169
|
+
}
|
|
162
170
|
>
|
|
163
171
|
{chip}
|
|
164
172
|
</button>
|
|
@@ -178,14 +186,35 @@ class OppList extends BaseCmp<OppListProps, OppListState> {
|
|
|
178
186
|
<thead>
|
|
179
187
|
<tr>
|
|
180
188
|
{columns.map((col, index) => (
|
|
181
|
-
<th
|
|
189
|
+
<th
|
|
190
|
+
key={index}
|
|
191
|
+
style={{
|
|
192
|
+
textAlign:
|
|
193
|
+
col === 'Amount'
|
|
194
|
+
? 'right'
|
|
195
|
+
: col === 'Close Date' ||
|
|
196
|
+
col === 'Stage' ||
|
|
197
|
+
col === 'Last Activity' ||
|
|
198
|
+
col === 'AI Score' ||
|
|
199
|
+
col === 'AI Win Rate'
|
|
200
|
+
? 'center'
|
|
201
|
+
: 'left',
|
|
202
|
+
}}
|
|
203
|
+
>
|
|
182
204
|
{col}
|
|
183
205
|
<span
|
|
184
206
|
className="sort-icon"
|
|
185
207
|
onClick={() => this.handleSort(col)}
|
|
186
|
-
style={{
|
|
208
|
+
style={{
|
|
209
|
+
color: sortColumn === col ? '#6366f1' : '#ccc',
|
|
210
|
+
marginLeft: '4px',
|
|
211
|
+
}}
|
|
187
212
|
>
|
|
188
|
-
{sortColumn === col
|
|
213
|
+
{sortColumn === col
|
|
214
|
+
? sortDirection === 'asc'
|
|
215
|
+
? '↑'
|
|
216
|
+
: '↓'
|
|
217
|
+
: '⇅'}
|
|
189
218
|
</span>
|
|
190
219
|
</th>
|
|
191
220
|
))}
|
|
@@ -193,27 +222,55 @@ class OppList extends BaseCmp<OppListProps, OppListState> {
|
|
|
193
222
|
</thead>
|
|
194
223
|
<tbody>
|
|
195
224
|
{filteredRows.map((opp, index) => (
|
|
196
|
-
<tr
|
|
197
|
-
|
|
198
|
-
{opp.
|
|
199
|
-
|
|
225
|
+
<tr
|
|
226
|
+
key={index}
|
|
227
|
+
className={opp.source ? `opp-row source-${opp.source}` : ''}
|
|
228
|
+
>
|
|
229
|
+
<td
|
|
230
|
+
style={{
|
|
231
|
+
textAlign: 'left',
|
|
232
|
+
color: '#3b82f6',
|
|
233
|
+
cursor: 'pointer',
|
|
234
|
+
}}
|
|
235
|
+
>
|
|
236
|
+
{opp.name}
|
|
237
|
+
</td>
|
|
238
|
+
{opp.account && (
|
|
239
|
+
<td style={{ textAlign: 'left' }}>{opp.account}</td>
|
|
240
|
+
)}
|
|
241
|
+
{opp.forecastType && (
|
|
242
|
+
<td style={{ textAlign: 'left' }}>{opp.forecastType}</td>
|
|
243
|
+
)}
|
|
200
244
|
<td style={{ textAlign: 'right' }}>{opp.amount}</td>
|
|
201
245
|
<td style={{ textAlign: 'center' }}>{opp.closeDate}</td>
|
|
202
246
|
<td style={{ textAlign: 'center' }}>{opp.stage}</td>
|
|
203
247
|
{opp.aiScore && (
|
|
204
248
|
<td style={{ textAlign: 'center' }}>
|
|
205
|
-
<span
|
|
249
|
+
<span
|
|
250
|
+
style={this.getScoreBadgeStyle(
|
|
251
|
+
opp.aiScore,
|
|
252
|
+
opp.aiScoreColor,
|
|
253
|
+
)}
|
|
254
|
+
>
|
|
206
255
|
{opp.aiScore}
|
|
207
256
|
</span>
|
|
208
257
|
</td>
|
|
209
258
|
)}
|
|
210
259
|
{opp.aiWinRate && (
|
|
211
|
-
<td
|
|
260
|
+
<td
|
|
261
|
+
style={{
|
|
262
|
+
textAlign: 'center',
|
|
263
|
+
color: '#6366f1',
|
|
264
|
+
fontWeight: 600,
|
|
265
|
+
}}
|
|
266
|
+
>
|
|
212
267
|
{opp.aiWinRate}
|
|
213
268
|
</td>
|
|
214
269
|
)}
|
|
215
270
|
{opp.lastActivity && (
|
|
216
|
-
<td style={{ textAlign: 'center', color: '#999' }}>
|
|
271
|
+
<td style={{ textAlign: 'center', color: '#999' }}>
|
|
272
|
+
{opp.lastActivity}
|
|
273
|
+
</td>
|
|
217
274
|
)}
|
|
218
275
|
</tr>
|
|
219
276
|
))}
|
|
@@ -12,11 +12,57 @@ export class OppListModel {
|
|
|
12
12
|
{ key: 'all', label: 'All Opportunities', icon: '' },
|
|
13
13
|
],
|
|
14
14
|
filterChips: ['All (3)', 'Rescue (1)', 'Upgrade (2)'],
|
|
15
|
-
columns: [
|
|
15
|
+
columns: [
|
|
16
|
+
'Opportunity Name',
|
|
17
|
+
'Account',
|
|
18
|
+
'Forecast Type',
|
|
19
|
+
'Amount',
|
|
20
|
+
'Close Date',
|
|
21
|
+
'Stage',
|
|
22
|
+
'✨ AI Score',
|
|
23
|
+
'✨ AI Win Rate',
|
|
24
|
+
'Last Activity',
|
|
25
|
+
],
|
|
16
26
|
rows: [
|
|
17
|
-
{
|
|
18
|
-
|
|
19
|
-
|
|
27
|
+
{
|
|
28
|
+
name: 'Apollo Project',
|
|
29
|
+
account: 'Huawei Tech',
|
|
30
|
+
forecastType: 'Commit',
|
|
31
|
+
amount: '$1,000,000',
|
|
32
|
+
closeDate: '2026-04-15',
|
|
33
|
+
stage: 'Negotiation',
|
|
34
|
+
aiScore: 'Medium',
|
|
35
|
+
aiScoreColor: '#f59e0b',
|
|
36
|
+
aiWinRate: '42%',
|
|
37
|
+
lastActivity: '2026-03-28',
|
|
38
|
+
source: 'rescue',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'Aurora Solution',
|
|
42
|
+
account: 'ByteDance',
|
|
43
|
+
forecastType: 'Best Case',
|
|
44
|
+
amount: '$800,000',
|
|
45
|
+
closeDate: '2026-04-30',
|
|
46
|
+
stage: 'Proposal',
|
|
47
|
+
aiScore: 'High',
|
|
48
|
+
aiScoreColor: '#22c55e',
|
|
49
|
+
aiWinRate: '91%',
|
|
50
|
+
lastActivity: '2026-03-29',
|
|
51
|
+
source: 'upgrade',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'Cloud Migration',
|
|
55
|
+
account: 'Tencent',
|
|
56
|
+
forecastType: 'Pipeline',
|
|
57
|
+
amount: '$1,700,000',
|
|
58
|
+
closeDate: '2026-05-20',
|
|
59
|
+
stage: 'Discovery',
|
|
60
|
+
aiScore: 'Medium',
|
|
61
|
+
aiScoreColor: '#f59e0b',
|
|
62
|
+
aiWinRate: '78%',
|
|
63
|
+
lastActivity: '2026-03-27',
|
|
64
|
+
source: 'upgrade',
|
|
65
|
+
},
|
|
20
66
|
],
|
|
21
67
|
};
|
|
22
68
|
|
|
@@ -44,7 +44,9 @@ class PipelineFunnel extends BaseCmp<PipelineFunnelProps, PipelineFunnelState> {
|
|
|
44
44
|
|
|
45
45
|
getFunnelClipPath = (index: number, total: number): string => {
|
|
46
46
|
const offset = index * 10;
|
|
47
|
-
return `polygon(${offset}% 0%, ${100 - offset}% 0%, ${
|
|
47
|
+
return `polygon(${offset}% 0%, ${100 - offset}% 0%, ${
|
|
48
|
+
100 - offset - 10
|
|
49
|
+
}% 100%, ${offset + 10}% 100%)`;
|
|
48
50
|
};
|
|
49
51
|
|
|
50
52
|
render() {
|
|
@@ -9,10 +9,34 @@ export class PipelineFunnelModel {
|
|
|
9
9
|
title: 'Pipeline Funnel',
|
|
10
10
|
totalAmount: '$11.1M',
|
|
11
11
|
stages: [
|
|
12
|
-
{
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
{
|
|
13
|
+
name: 'Prospecting',
|
|
14
|
+
amount: '$3.2M',
|
|
15
|
+
count: 15,
|
|
16
|
+
conversionRate: '—',
|
|
17
|
+
color: '#3b82f6',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Needs Analysis',
|
|
21
|
+
amount: '$1.8M',
|
|
22
|
+
count: 7,
|
|
23
|
+
conversionRate: '56.3%',
|
|
24
|
+
color: '#22c55e',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'Proposal/Price Quote',
|
|
28
|
+
amount: '$4.5M',
|
|
29
|
+
count: 8,
|
|
30
|
+
conversionRate: '28.1%',
|
|
31
|
+
color: '#f59e0b',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'Closed Won',
|
|
35
|
+
amount: '$1.6M',
|
|
36
|
+
count: 3,
|
|
37
|
+
conversionRate: '10.0%',
|
|
38
|
+
color: '#8b5cf6',
|
|
39
|
+
},
|
|
16
40
|
],
|
|
17
41
|
showAiButton: true,
|
|
18
42
|
};
|
|
@@ -46,7 +46,10 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
componentWillReceiveProps(nextProps: StageSwitchProps) {
|
|
49
|
-
if (
|
|
49
|
+
if (
|
|
50
|
+
nextProps.activeStage &&
|
|
51
|
+
nextProps.activeStage !== this.props.activeStage
|
|
52
|
+
) {
|
|
50
53
|
this.setState({ activeStage: nextProps.activeStage });
|
|
51
54
|
}
|
|
52
55
|
}
|
|
@@ -69,7 +72,9 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
69
72
|
{stages.map((stage) => (
|
|
70
73
|
<div
|
|
71
74
|
key={stage.key}
|
|
72
|
-
className={`stage-tab ${
|
|
75
|
+
className={`stage-tab ${
|
|
76
|
+
activeStage === stage.key ? 'active' : ''
|
|
77
|
+
}`}
|
|
73
78
|
onClick={() => this.handleStageClick(stage)}
|
|
74
79
|
>
|
|
75
80
|
<div className="stage-name">{stage.name}</div>
|
|
@@ -80,15 +85,25 @@ class StageSwitch extends BaseCmp<StageSwitchProps, StageSwitchState> {
|
|
|
80
85
|
{stage.changes && (
|
|
81
86
|
<div className="stage-sub">
|
|
82
87
|
<span
|
|
83
|
-
className={`change-amount ${
|
|
88
|
+
className={`change-amount ${
|
|
89
|
+
stage.changes.amountDirection === 'up'
|
|
90
|
+
? 'positive'
|
|
91
|
+
: 'negative'
|
|
92
|
+
}`}
|
|
84
93
|
>
|
|
85
|
-
{stage.changes.amountDirection === 'up' ? '↑' : '↓'}
|
|
94
|
+
{stage.changes.amountDirection === 'up' ? '↑' : '↓'}{' '}
|
|
95
|
+
{stage.changes.amount}
|
|
86
96
|
</span>
|
|
87
97
|
<span> </span>
|
|
88
98
|
<span
|
|
89
|
-
className={`change-count ${
|
|
99
|
+
className={`change-count ${
|
|
100
|
+
stage.changes.countDirection === 'up'
|
|
101
|
+
? 'positive'
|
|
102
|
+
: 'negative'
|
|
103
|
+
}`}
|
|
90
104
|
>
|
|
91
|
-
{stage.changes.countDirection === 'up' ? '↑' : '↓'}
|
|
105
|
+
{stage.changes.countDirection === 'up' ? '↑' : '↓'}{' '}
|
|
106
|
+
{stage.changes.count}
|
|
92
107
|
</span>
|
|
93
108
|
</div>
|
|
94
109
|
)}
|
|
@@ -7,11 +7,66 @@ export class StageSwitchModel {
|
|
|
7
7
|
|
|
8
8
|
defaultComProps = {
|
|
9
9
|
stages: [
|
|
10
|
-
{
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
{
|
|
11
|
+
key: 'Prospecting',
|
|
12
|
+
name: 'Prospecting',
|
|
13
|
+
amount: '$3.2M',
|
|
14
|
+
count: 15,
|
|
15
|
+
changes: {
|
|
16
|
+
amount: '$280K',
|
|
17
|
+
amountDirection: 'up',
|
|
18
|
+
count: '3',
|
|
19
|
+
countDirection: 'up',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
key: 'Needs Analysis',
|
|
24
|
+
name: 'Needs Analysis',
|
|
25
|
+
amount: '$1.8M',
|
|
26
|
+
count: 7,
|
|
27
|
+
changes: {
|
|
28
|
+
amount: '$320K',
|
|
29
|
+
amountDirection: 'down',
|
|
30
|
+
count: '2',
|
|
31
|
+
countDirection: 'down',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
key: 'Proposal',
|
|
36
|
+
name: 'Proposal/Price Quote',
|
|
37
|
+
amount: '$4.5M',
|
|
38
|
+
count: 8,
|
|
39
|
+
changes: {
|
|
40
|
+
amount: '$500K',
|
|
41
|
+
amountDirection: 'up',
|
|
42
|
+
count: '3',
|
|
43
|
+
countDirection: 'up',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
key: 'Closed Won',
|
|
48
|
+
name: 'Closed Won',
|
|
49
|
+
amount: '$1.6M',
|
|
50
|
+
count: 3,
|
|
51
|
+
changes: {
|
|
52
|
+
amount: '$400K',
|
|
53
|
+
amountDirection: 'up',
|
|
54
|
+
count: '1',
|
|
55
|
+
countDirection: 'up',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
key: 'Closed Lost',
|
|
60
|
+
name: 'Closed Lost',
|
|
61
|
+
amount: '$0.9M',
|
|
62
|
+
count: 4,
|
|
63
|
+
changes: {
|
|
64
|
+
amount: '$200K',
|
|
65
|
+
amountDirection: 'down',
|
|
66
|
+
count: '2',
|
|
67
|
+
countDirection: 'up',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
15
70
|
],
|
|
16
71
|
activeStage: 'Prospecting',
|
|
17
72
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export class StageTimeChartModel {
|
|
2
2
|
label: string = '阶段停留时间';
|
|
3
|
-
description: string =
|
|
3
|
+
description: string =
|
|
4
|
+
'展示各销售阶段的平均停留时间,包含实际值、目标值和限制值';
|
|
4
5
|
iconUrl: string = 'https://custom-widgets.bj.bcebos.com/stageTimeChart.svg';
|
|
5
6
|
targetPage: string[] = ['all'];
|
|
6
7
|
targetDevice: string = 'all';
|
|
@@ -8,9 +9,30 @@ export class StageTimeChartModel {
|
|
|
8
9
|
defaultComProps = {
|
|
9
10
|
title: 'Avg. Time in Stage',
|
|
10
11
|
items: [
|
|
11
|
-
{
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
{
|
|
13
|
+
stageName: 'Prospecting',
|
|
14
|
+
actualTime: '8天6时',
|
|
15
|
+
actualPercent: 28,
|
|
16
|
+
actualColor: '#22c55e',
|
|
17
|
+
targetPercent: 33,
|
|
18
|
+
limitPercent: 50,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
stageName: 'Needs Analysis',
|
|
22
|
+
actualTime: '15天12时',
|
|
23
|
+
actualPercent: 52,
|
|
24
|
+
actualColor: '#eab308',
|
|
25
|
+
targetPercent: 40,
|
|
26
|
+
limitPercent: 60,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
stageName: 'Proposal/Price Quote',
|
|
30
|
+
actualTime: '22天8时',
|
|
31
|
+
actualPercent: 74,
|
|
32
|
+
actualColor: '#ef4444',
|
|
33
|
+
targetPercent: 50,
|
|
34
|
+
limitPercent: 67,
|
|
35
|
+
},
|
|
14
36
|
],
|
|
15
37
|
showAiButton: true,
|
|
16
38
|
};
|
|
@@ -410,11 +410,11 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
410
410
|
return;
|
|
411
411
|
}
|
|
412
412
|
const headers = fields.map((f) => f.label);
|
|
413
|
-
const ws = XLSX.utils.aoa_to_sheet([headers]);
|
|
414
|
-
const wb = XLSX.utils.book_new();
|
|
415
|
-
XLSX.utils.book_append_sheet(wb, ws, '导入模板');
|
|
416
|
-
const name = `${this.props.xObjectDataApi?.xObjectApiKey || 'data'}_导入模板.xlsx`;
|
|
417
|
-
XLSX.writeFile(wb, name);
|
|
413
|
+
const ws = XLSX.utils.aoa_to_sheet([headers]); // 将标题行转换为工作表
|
|
414
|
+
const wb = XLSX.utils.book_new(); // 创建新的工作簿
|
|
415
|
+
XLSX.utils.book_append_sheet(wb, ws, '导入模板'); // 将工作表添加到工作簿
|
|
416
|
+
const name = `${this.props.xObjectDataApi?.xObjectApiKey || 'data'}_导入模板.xlsx`; // 生成文件名
|
|
417
|
+
XLSX.writeFile(wb, name); // 将工作簿写入文件
|
|
418
418
|
message.success('模板已下载');
|
|
419
419
|
}
|
|
420
420
|
|
|
@@ -427,26 +427,26 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
427
427
|
const reader = new FileReader();
|
|
428
428
|
reader.onload = (e) => {
|
|
429
429
|
try {
|
|
430
|
-
const data = new Uint8Array(e.target?.result as ArrayBuffer);
|
|
431
|
-
const wb = XLSX.read(data, { type: 'array', cellDates: true });
|
|
432
|
-
const sheetName = wb.SheetNames[0];
|
|
430
|
+
const data = new Uint8Array(e.target?.result as ArrayBuffer); // 将文件内容转换为 Uint8Array
|
|
431
|
+
const wb = XLSX.read(data, { type: 'array', cellDates: true }); // 读取 Excel 文件
|
|
432
|
+
const sheetName = wb.SheetNames[0]; // 获取工作表名称
|
|
433
433
|
if (!sheetName) {
|
|
434
434
|
message.error('Excel 中未找到工作表');
|
|
435
435
|
return;
|
|
436
436
|
}
|
|
437
|
-
const sheet = wb.Sheets[sheetName];
|
|
438
|
-
const rowsAoA: any[][] = XLSX.utils.sheet_to_json(sheet, {
|
|
439
|
-
header: 1,
|
|
440
|
-
raw: true,
|
|
441
|
-
defval: '',
|
|
442
|
-
}) as any[][];
|
|
437
|
+
const sheet = wb.Sheets[sheetName]; // 获取工作表
|
|
438
|
+
const rowsAoA: any[][] = XLSX.utils.sheet_to_json(sheet, { // 将工作表转换为 JSON 数组
|
|
439
|
+
header: 1, // 使用第一行作为标题行
|
|
440
|
+
raw: true, // 保持原始数据格式
|
|
441
|
+
defval: '', // 默认值
|
|
442
|
+
}) as any[][]; // 将 JSON 数组转换为 any[][] 类型
|
|
443
443
|
if (!rowsAoA.length) {
|
|
444
444
|
message.error('Excel 内容为空');
|
|
445
445
|
return;
|
|
446
446
|
}
|
|
447
447
|
const headerRow = rowsAoA[0] || [];
|
|
448
|
-
const colMap = this.buildHeaderIndexMap(headerRow, fields);
|
|
449
|
-
const missing = fields.filter((f) => colMap[f.apiKey] === undefined);
|
|
448
|
+
const colMap = this.buildHeaderIndexMap(headerRow, fields); // 构建列索引映射
|
|
449
|
+
const missing = fields.filter((f) => colMap[f.apiKey] === undefined); // 过滤出未匹配的字段
|
|
450
450
|
if (missing.length) {
|
|
451
451
|
message.error(
|
|
452
452
|
`表头无法匹配字段:${missing.map((m) => m.label).join('、')}`,
|
|
@@ -462,7 +462,7 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
462
462
|
fields.forEach((f) => {
|
|
463
463
|
const idx = colMap[f.apiKey];
|
|
464
464
|
const raw = idx !== undefined ? line[idx] : undefined;
|
|
465
|
-
row[f.apiKey] = this.parseImportedCell(f, raw, entityTypeList);
|
|
465
|
+
row[f.apiKey] = this.parseImportedCell(f, raw, entityTypeList); // 解析导入的单元格值
|
|
466
466
|
});
|
|
467
467
|
newRows.push(row);
|
|
468
468
|
}
|