neo-cmp-cli 1.13.16 → 1.13.18
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 +2 -1
- package/dist/index2.js +1 -1
- package/dist/main2.js +1 -1
- package/dist/neo/env.js +1 -1
- package/dist/neo/neoLogin.js +1 -1
- package/dist/neo/pushCmp.js +1 -1
- package/dist/package.json.js +1 -1
- package/package.json +3 -2
- package/template/antd-custom-cmp-template/package.json +1 -1
- package/template/asset-manage-template/docs/README.md +1 -232
- package/template/asset-manage-template/package.json +2 -2
- package/template/echarts-custom-cmp-template/package.json +1 -1
- package/template/empty-custom-cmp-template/package.json +2 -2
- package/template/map-custom-cmp-template/package.json +1 -1
- package/template/neo-bi-cmps/neo.config.js +7 -1
- package/template/neo-bi-cmps/package.json +8 -7
- package/template/neo-bi-cmps/public/403.html +77 -0
- package/template/neo-bi-cmps/public/demo.html +2453 -0
- package/template/neo-bi-cmps/src/assets/icon/barChart.svg +1 -0
- package/template/neo-bi-cmps/src/assets/icon/card.svg +1 -0
- package/template/neo-bi-cmps/src/assets/icon/filter.svg +1 -0
- package/template/neo-bi-cmps/src/assets/icon/funnel.svg +1 -0
- package/template/neo-bi-cmps/src/assets/icon/tab.svg +1 -0
- package/template/neo-bi-cmps/src/components/filterBar__c/README.md +3 -14
- package/template/neo-bi-cmps/src/components/filterBar__c/common.scss +29 -0
- package/template/neo-bi-cmps/src/components/filterBar__c/index.tsx +668 -146
- package/template/neo-bi-cmps/src/components/filterBar__c/model.ts +26 -48
- package/template/neo-bi-cmps/src/components/filterBar__c/style.scss +46 -139
- package/template/neo-bi-cmps/src/components/targetNumber__c/customStyleConfig/index.tsx +11 -10
- package/template/neo-bi-cmps/src/components/targetNumber__c/index.tsx +9 -16
- package/template/neo-bi-cmps/src/components/targetNumber__c/model.ts +1 -1
- package/template/neo-bi-cmps/src/utils/common.ts +231 -0
- package/template/neo-bi-cmps/src/utils/filter2chartFilter.ts +268 -0
- package/template/neo-bi-cmps/src/utils/filterBar.ts +140 -0
- package/template/neo-bi-cmps/src/utils/pipelineFunnel.ts +341 -0
- package/template/{neo-h5-cmps/src/utils/queryObjectData.ts → neo-bi-cmps/src/utils/queryByCustomSQL.ts} +18 -13
- package/template/neo-bi-cmps/src/utils/requestDebounce.ts +22 -0
- package/template/neo-bi-cmps/src/utils/simpleTable.tsx +344 -0
- package/template/neo-bi-cmps/src/utils/stageSwitch.ts +15 -0
- package/template/neo-bi-cmps/src/utils/stageTimeChart.ts +90 -0
- package/template/neo-bi-cmps/src/utils/targetNumber.ts +12 -0
- package/template/neo-custom-cmp-template/docs/README.md +0 -231
- package/template/neo-custom-cmp-template/package.json +2 -2
- package/template/neo-h5-cmps/package.json +2 -2
- package/template/neo-h5-cmps/src/components/entityList__c/index.tsx +1 -2
- package/template/neo-h5-cmps/src/components/entityTabs__c/index.tsx +1 -1
- package/template/neo-h5-cmps/src/components/globalSearchInput__c/index.tsx +1 -1
- package/template/neo-h5-cmps/src/components/openChatPageBtn__c/index.tsx +1 -2
- package/template/neo-order-cmps/package.json +2 -2
- package/template/neo-pipeline-cmps/.prettierrc.js +12 -0
- package/template/neo-pipeline-cmps/@types/neo-ui-common.d.ts +36 -0
- package/template/neo-pipeline-cmps/README.md +99 -0
- package/template/neo-pipeline-cmps/commitlint.config.js +59 -0
- package/template/neo-pipeline-cmps/neo.config.js +135 -0
- package/template/neo-pipeline-cmps/package.json +66 -0
- package/template/neo-pipeline-cmps/public/403.html +77 -0
- package/template/neo-pipeline-cmps/public/css/base.css +283 -0
- package/template/neo-pipeline-cmps/public/demo.html +2453 -0
- package/template/neo-pipeline-cmps/public/scripts/app/bluebird.js +6679 -0
- package/template/neo-pipeline-cmps/public/template.html +13 -0
- package/template/neo-pipeline-cmps/src/assets/css/common.scss +127 -0
- package/template/neo-pipeline-cmps/src/assets/css/mixin.scss +47 -0
- package/template/neo-pipeline-cmps/src/assets/icon/barChart.svg +1 -0
- package/template/neo-pipeline-cmps/src/assets/icon/card.svg +1 -0
- package/template/neo-pipeline-cmps/src/assets/icon/filter.svg +1 -0
- package/template/neo-pipeline-cmps/src/assets/icon/funnel.svg +1 -0
- package/template/neo-pipeline-cmps/src/assets/icon/tab.svg +1 -0
- package/template/neo-pipeline-cmps/src/assets/img/AIBtn.gif +0 -0
- package/template/neo-pipeline-cmps/src/assets/img/NeoCRM.jpg +0 -0
- package/template/neo-pipeline-cmps/src/assets/img/aiLogo.png +0 -0
- package/template/neo-pipeline-cmps/src/assets/img/card-list.svg +1 -0
- package/template/neo-pipeline-cmps/src/assets/img/contact-form.svg +1 -0
- package/template/neo-pipeline-cmps/src/assets/img/custom-form.svg +1 -0
- package/template/neo-pipeline-cmps/src/assets/img/custom-widget.svg +1 -0
- package/template/neo-pipeline-cmps/src/assets/img/data-list.svg +1 -0
- package/template/neo-pipeline-cmps/src/assets/img/detail.svg +1 -0
- package/template/neo-pipeline-cmps/src/assets/img/favicon.png +0 -0
- package/template/neo-pipeline-cmps/src/assets/img/map.svg +1 -0
- package/template/neo-pipeline-cmps/src/assets/img/search.svg +1 -0
- package/template/neo-pipeline-cmps/src/assets/img/table.svg +1 -0
- package/template/neo-pipeline-cmps/src/components/filterBar__c/README.md +24 -0
- package/template/neo-pipeline-cmps/src/components/filterBar__c/common.scss +29 -0
- package/template/neo-pipeline-cmps/src/components/filterBar__c/index.tsx +731 -0
- package/template/neo-pipeline-cmps/src/components/filterBar__c/model.ts +52 -0
- package/template/neo-pipeline-cmps/src/components/filterBar__c/style.scss +119 -0
- package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/README.md +39 -0
- package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/index.tsx +416 -0
- package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/model.ts +80 -0
- package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/style.scss +83 -0
- package/template/neo-pipeline-cmps/src/components/showHealthResult__c/index.tsx +470 -0
- package/template/neo-pipeline-cmps/src/components/showHealthResult__c/model.ts +45 -0
- package/template/neo-pipeline-cmps/src/components/showHealthResult__c/style.scss +137 -0
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/README.md +89 -0
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/common.scss +195 -0
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/index.tsx +667 -0
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/model.ts +124 -0
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/style.scss +192 -0
- package/template/neo-pipeline-cmps/src/components/stageSwitch__c/README.md +36 -0
- package/template/neo-pipeline-cmps/src/components/stageSwitch__c/index.tsx +513 -0
- package/template/neo-pipeline-cmps/src/components/stageSwitch__c/model.ts +71 -0
- package/template/{neo-bi-cmps → neo-pipeline-cmps}/src/components/stageSwitch__c/style.scss +4 -2
- package/template/neo-pipeline-cmps/src/components/stageTimeChart__c/README.md +37 -0
- package/template/neo-pipeline-cmps/src/components/stageTimeChart__c/index.tsx +455 -0
- package/template/neo-pipeline-cmps/src/components/stageTimeChart__c/model.ts +106 -0
- package/template/{neo-bi-cmps → neo-pipeline-cmps}/src/components/stageTimeChart__c/style.scss +3 -2
- package/template/neo-pipeline-cmps/src/utils/common.ts +229 -0
- package/template/neo-pipeline-cmps/src/utils/filter2chartFilter.ts +266 -0
- package/template/neo-pipeline-cmps/src/utils/filterBar.ts +140 -0
- package/template/neo-pipeline-cmps/src/utils/pipelineFunnel.ts +343 -0
- package/template/neo-pipeline-cmps/src/utils/queryByCustomSQL.ts +121 -0
- package/template/neo-pipeline-cmps/src/utils/requestDebounce.ts +22 -0
- package/template/neo-pipeline-cmps/src/utils/simpleTable.tsx +349 -0
- package/template/neo-pipeline-cmps/src/utils/stageSwitch.ts +15 -0
- package/template/neo-pipeline-cmps/src/utils/stageTimeChart.ts +90 -0
- package/template/neo-pipeline-cmps/src/utils/targetNumber.ts +12 -0
- package/template/neo-pipeline-cmps/tsconfig.json +40 -0
- package/template/neo-web-entity-grid/package.json +2 -2
- package/template/neo-web-form/package.json +2 -2
- package/template/neo-web-form/src/components/batchAddTable__c/index.tsx +161 -41
- package/template/neo-web-form/src/components/batchAddTable__c/model.ts +4 -2
- 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/asset-manage-template/src/utils/axiosFetcher.ts +0 -37
- package/template/asset-manage-template/src/utils/queryObjectData.ts +0 -112
- package/template/asset-manage-template/src/utils/xobjects.ts +0 -162
- package/template/neo-bi-cmps/.npmrc copy +0 -1
- package/template/neo-bi-cmps/src/components/aiCommitDrawer__c/README.md +0 -52
- package/template/neo-bi-cmps/src/components/aiCommitDrawer__c/index.tsx +0 -183
- package/template/neo-bi-cmps/src/components/aiCommitDrawer__c/model.ts +0 -90
- package/template/neo-bi-cmps/src/components/aiCommitDrawer__c/style.scss +0 -218
- package/template/neo-bi-cmps/src/components/forecastChart__c/README.md +0 -31
- package/template/neo-bi-cmps/src/components/forecastChart__c/index.tsx +0 -158
- package/template/neo-bi-cmps/src/components/forecastChart__c/model.ts +0 -40
- package/template/neo-bi-cmps/src/components/forecastChart__c/style.scss +0 -154
- package/template/neo-bi-cmps/src/components/forecastGrid__c/README.md +0 -36
- package/template/neo-bi-cmps/src/components/forecastGrid__c/index.tsx +0 -86
- package/template/neo-bi-cmps/src/components/forecastGrid__c/model.ts +0 -62
- package/template/neo-bi-cmps/src/components/forecastGrid__c/style.scss +0 -48
- package/template/neo-bi-cmps/src/components/gapCloser__c/README.md +0 -24
- package/template/neo-bi-cmps/src/components/gapCloser__c/index.tsx +0 -100
- package/template/neo-bi-cmps/src/components/gapCloser__c/model.ts +0 -46
- package/template/neo-bi-cmps/src/components/gapCloser__c/style.scss +0 -60
- package/template/neo-bi-cmps/src/components/kpiCards__c/README.md +0 -35
- package/template/neo-bi-cmps/src/components/kpiCards__c/index.tsx +0 -70
- package/template/neo-bi-cmps/src/components/kpiCards__c/model.ts +0 -50
- package/template/neo-bi-cmps/src/components/kpiCards__c/style.scss +0 -33
- package/template/neo-bi-cmps/src/components/oppList__c/README.md +0 -52
- package/template/neo-bi-cmps/src/components/oppList__c/index.tsx +0 -285
- package/template/neo-bi-cmps/src/components/oppList__c/model.ts +0 -86
- package/template/neo-bi-cmps/src/components/oppList__c/style.scss +0 -133
- package/template/neo-bi-cmps/src/components/pipelineFunnel__c/README.md +0 -39
- package/template/neo-bi-cmps/src/components/pipelineFunnel__c/index.tsx +0 -130
- package/template/neo-bi-cmps/src/components/pipelineFunnel__c/model.ts +0 -66
- package/template/neo-bi-cmps/src/components/pipelineFunnel__c/style.scss +0 -133
- package/template/neo-bi-cmps/src/components/stageSwitch__c/README.md +0 -36
- package/template/neo-bi-cmps/src/components/stageSwitch__c/index.tsx +0 -118
- package/template/neo-bi-cmps/src/components/stageSwitch__c/model.ts +0 -92
- package/template/neo-bi-cmps/src/components/stageTimeChart__c/README.md +0 -37
- package/template/neo-bi-cmps/src/components/stageTimeChart__c/index.tsx +0 -126
- package/template/neo-bi-cmps/src/components/stageTimeChart__c/model.ts +0 -57
- package/template/neo-bi-cmps/src/components/tabSwitch__c/README.md +0 -37
- package/template/neo-bi-cmps/src/components/tabSwitch__c/index.tsx +0 -80
- package/template/neo-bi-cmps/src/components/tabSwitch__c/model.ts +0 -45
- package/template/neo-bi-cmps/src/components/tabSwitch__c/style.scss +0 -37
- package/template/neo-bi-cmps/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-bi-cmps/src/utils/queryObjectData.ts +0 -76
- package/template/neo-bi-cmps/src/utils/xobjects.ts +0 -162
- package/template/neo-custom-cmp-template/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-custom-cmp-template/src/utils/queryObjectData.ts +0 -112
- package/template/neo-custom-cmp-template/src/utils/xobjects.ts +0 -162
- package/template/neo-h5-cmps/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-h5-cmps/src/utils/xobjects.ts +0 -167
- package/template/neo-order-cmps/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-order-cmps/src/utils/queryObjectData.ts +0 -112
- package/template/neo-order-cmps/src/utils/xobjects.ts +0 -162
- package/template/neo-web-entity-grid/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-web-entity-grid/src/utils/queryObjectData.ts +0 -112
- package/template/neo-web-entity-grid/src/utils/xobjects.ts +0 -167
- package/template/neo-web-form/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-web-form/src/utils/queryObjectData.ts +0 -112
- package/template/neo-web-form/src/utils/xobjects.ts +0 -167
|
@@ -0,0 +1,667 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file XObject data table component (simplified version)
|
|
3
|
+
* @description XObject entity data table component based on the Neo platform, supports data display only
|
|
4
|
+
*/
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { Table, Spin, Empty, Popover } from 'antd';
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
import { xObject } from 'neo-open-api'; // Neo Open API
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
import isEqual from 'lodash/isEqual';
|
|
11
|
+
|
|
12
|
+
// Neo Open API// Import neo-ui-common / BaseCmp
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
import { BaseCmp } from 'neo-ui-common';
|
|
15
|
+
|
|
16
|
+
// Import neo-ui-common / NeoEvent
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
import { NeoEvent } from 'neo-ui-common';
|
|
19
|
+
|
|
20
|
+
import queryByCustomSQL from '../../utils/queryByCustomSQL';
|
|
21
|
+
import {
|
|
22
|
+
closeRangeFromFilter,
|
|
23
|
+
entityTypeIdForWhere,
|
|
24
|
+
normalizeOwnerIdsForWhere,
|
|
25
|
+
getDefaultFilterByProps,
|
|
26
|
+
} from '../../utils/common';
|
|
27
|
+
import {
|
|
28
|
+
buildHistoryMap,
|
|
29
|
+
closeDateChangeTooltipTitle,
|
|
30
|
+
closeDateTrend,
|
|
31
|
+
formatActivityDateTime,
|
|
32
|
+
formatCloseDate,
|
|
33
|
+
formatMoneyCell,
|
|
34
|
+
formatMoneySummaryAmount,
|
|
35
|
+
formatPercentCell,
|
|
36
|
+
isMoneyField,
|
|
37
|
+
moneyChangeTooltipTitle,
|
|
38
|
+
moneyTrend,
|
|
39
|
+
renderOppHealthAssessmentLevel,
|
|
40
|
+
renderTrendCell,
|
|
41
|
+
renderWinRateHoverCard,
|
|
42
|
+
sumMoneyRows,
|
|
43
|
+
type FieldInfo,
|
|
44
|
+
type HistoryOppSnap,
|
|
45
|
+
} from '../../utils/simpleTable';
|
|
46
|
+
|
|
47
|
+
import ShowHealthResult from '../showHealthResult__c';
|
|
48
|
+
|
|
49
|
+
import './common.scss';
|
|
50
|
+
import './style.scss';
|
|
51
|
+
|
|
52
|
+
export type { HistoryOppSnap } from '../../utils/simpleTable';
|
|
53
|
+
|
|
54
|
+
/** Opportunity detail page hash route (consistent with platform neoweb) */
|
|
55
|
+
function buildOpportunityDetailUrl(id: string, objectApiKey: string): string {
|
|
56
|
+
const q = new URLSearchParams({
|
|
57
|
+
objectApiKey,
|
|
58
|
+
recordId: id,
|
|
59
|
+
});
|
|
60
|
+
return `/bff/neoweb#/entityDetail/opportunity/${id}?${q.toString()}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Fields not displayed in the table (can still be fetched via xObjectDataApi.fields, used for hover cards / tooltips) */
|
|
64
|
+
const HIDDEN_TABLE_COLUMN_KEYS = new Set([
|
|
65
|
+
'customItem244__c',
|
|
66
|
+
'customItem241__c',
|
|
67
|
+
'customItem242__c',
|
|
68
|
+
'customItem246__c',
|
|
69
|
+
'customItem247__c',
|
|
70
|
+
'customItem245__c',
|
|
71
|
+
// 'objectId', // Needed for navigating to detail page
|
|
72
|
+
// 'businessTypeId' // Needed for navigating to detail page
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
/** Historical opportunity SQL consistent with stageSwitch; field order must match query fields (array rows parsed by column index) */
|
|
76
|
+
const HISTORY_OPPORTUNITY_BI_KEY = 'biCustomModel_397169_20260401104916618';
|
|
77
|
+
const HISTORY_QUERY_FIELDS = [
|
|
78
|
+
// 'id', // Historical version ID
|
|
79
|
+
'opportunity_1__id', // Opportunity ID
|
|
80
|
+
'opportunity_1_closeDate',
|
|
81
|
+
'opportunity_1_opportunityName',
|
|
82
|
+
'opportunity_1_saleStageId',
|
|
83
|
+
'opportunity_1_money',
|
|
84
|
+
] as const;
|
|
85
|
+
|
|
86
|
+
const defaultXObjectDataApi = {
|
|
87
|
+
xObjectApiKey: 'opportunity',
|
|
88
|
+
fields: [
|
|
89
|
+
'opportunityName', // OpportunityStageName Opportunity Name
|
|
90
|
+
'money', // Amount
|
|
91
|
+
'closeDate', // Close Date
|
|
92
|
+
'customItem248__c', // Stage
|
|
93
|
+
// 'oppHealthAssessmentScore',
|
|
94
|
+
'recentActivityRecordTime',
|
|
95
|
+
'oppHealthAssessmentLevel', // 1.AI Score; hover card: calls opportunity health assessment API
|
|
96
|
+
'customItem239__c', // 2.AI Win Rate: 3 fields shown in hover card (baseline, positiveFactors, negativeFactors)
|
|
97
|
+
'customItem244__c', // baseline
|
|
98
|
+
'customItem241__c', // positiveFactors
|
|
99
|
+
'customItem242__c', // negativeFactors
|
|
100
|
+
'customItem246__c', // AmoutChanged
|
|
101
|
+
'customItem247__c', // ClosedDateChanged
|
|
102
|
+
'customItem245__c', // StageChanged
|
|
103
|
+
// 'objectId', // Needed for navigating to detail page
|
|
104
|
+
// 'businessTypeId' // Needed for navigating to detail page
|
|
105
|
+
],
|
|
106
|
+
page: 1,
|
|
107
|
+
pageSize: 50,
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Component props interface
|
|
111
|
+
*/
|
|
112
|
+
interface SimpleTableProps {
|
|
113
|
+
/** XObject entity API Key, used to identify the data object to operate on */
|
|
114
|
+
xObjectDataApi: {
|
|
115
|
+
xObjectApiKey: string;
|
|
116
|
+
fields: string[];
|
|
117
|
+
fieldDescList?: any[];
|
|
118
|
+
autoFetchData?: boolean;
|
|
119
|
+
};
|
|
120
|
+
/** Neo platform data, including system information */
|
|
121
|
+
data?: any;
|
|
122
|
+
entityData?: any; // Entity data automatically fetched by Neo platform
|
|
123
|
+
/** Whether it is a custom entity object */
|
|
124
|
+
custom?: boolean;
|
|
125
|
+
/** Component class name */
|
|
126
|
+
className?: string;
|
|
127
|
+
/** Table title, takes priority */
|
|
128
|
+
title?: string;
|
|
129
|
+
/** Description text below the title */
|
|
130
|
+
description?: string;
|
|
131
|
+
/** Currently active sales stage */
|
|
132
|
+
activeStage?: string;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Component state interface
|
|
137
|
+
*/
|
|
138
|
+
interface SimpleTableState {
|
|
139
|
+
/** Table title */
|
|
140
|
+
title?: string;
|
|
141
|
+
fieldList: FieldInfo[];
|
|
142
|
+
/** Table data source */
|
|
143
|
+
dataSource: any[];
|
|
144
|
+
/** Loading state */
|
|
145
|
+
loading: boolean;
|
|
146
|
+
/** Error message */
|
|
147
|
+
error: string | null;
|
|
148
|
+
activeStage: string; // Currently active sales stage
|
|
149
|
+
/**
|
|
150
|
+
* Consistent with FilterBar event payload (closeDateCustomRange / opportunityOwner / businessType, etc.);
|
|
151
|
+
* Default value is defaultFilter, getFilterWhere only reads from it
|
|
152
|
+
*/
|
|
153
|
+
filter: any;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* XObject data table component (simplified version)
|
|
158
|
+
* Supports data display only, does not support CRUD operations
|
|
159
|
+
*/
|
|
160
|
+
export default class SimpleTable extends BaseCmp<
|
|
161
|
+
SimpleTableProps,
|
|
162
|
+
SimpleTableState
|
|
163
|
+
> {
|
|
164
|
+
constructor(props: SimpleTableProps) {
|
|
165
|
+
super(props);
|
|
166
|
+
|
|
167
|
+
// Initialize component state
|
|
168
|
+
this.state = {
|
|
169
|
+
fieldList: [],
|
|
170
|
+
dataSource: [],
|
|
171
|
+
loading: false,
|
|
172
|
+
error: null,
|
|
173
|
+
activeStage: props.activeStage || 'Prospecting',
|
|
174
|
+
filter: getDefaultFilterByProps(props),
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
this.loadData = this.loadData.bind(this);
|
|
178
|
+
this.loadFieldList = this.loadFieldList.bind(this);
|
|
179
|
+
this.getCurFieldList = this.getCurFieldList.bind(this);
|
|
180
|
+
this.getMoneyFieldApiKey = this.getMoneyFieldApiKey.bind(this);
|
|
181
|
+
this.generateColumns = this.generateColumns.bind(this);
|
|
182
|
+
this.getFilterWhere = this.getFilterWhere.bind(this);
|
|
183
|
+
this.setFilter = this.setFilter.bind(this);
|
|
184
|
+
this.updateActiveStage = this.updateActiveStage.bind(this);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
componentDidMount() {
|
|
188
|
+
// const { xObjectDataApi } = this.props;
|
|
189
|
+
// const { xObjectApiKey } = xObjectDataApi || {};
|
|
190
|
+
const { xObjectApiKey } = defaultXObjectDataApi;
|
|
191
|
+
|
|
192
|
+
if (xObjectApiKey) {
|
|
193
|
+
// Initialize field list and load data
|
|
194
|
+
this.loadFieldList();
|
|
195
|
+
this.loadData();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/*
|
|
199
|
+
// Broadcast event: update FilterBar filter
|
|
200
|
+
NeoEvent.listen('updateFilterData', (filterData: any) => {
|
|
201
|
+
console.log('SimpleTable received a broadcast event updateFilterData: ', filterData);
|
|
202
|
+
this.setFilter(filterData);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Broadcast event: update the currently active sales stage
|
|
206
|
+
NeoEvent.listen('updateActiveStage', (activeStage: string) => {
|
|
207
|
+
console.log('SimpleTable received a broadcast event updateActiveStage: ', activeStage);
|
|
208
|
+
this.updateActiveStage(activeStage);
|
|
209
|
+
});
|
|
210
|
+
*/
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Load field list
|
|
215
|
+
* Fetch XObject field description information from the Neo platform
|
|
216
|
+
*/
|
|
217
|
+
async loadFieldList() {
|
|
218
|
+
const xObjectDataApi: any = defaultXObjectDataApi;
|
|
219
|
+
|
|
220
|
+
// Method 1: Get field descriptions directly from props.xObjectDetailApi
|
|
221
|
+
if (xObjectDataApi && xObjectDataApi.fieldDescList) {
|
|
222
|
+
this.setState({ fieldList: xObjectDataApi.fieldDescList });
|
|
223
|
+
} else {
|
|
224
|
+
// Method 2: Fetch field descriptions via OpenAPI SDK
|
|
225
|
+
if (!xObjectDataApi.xObjectApiKey) return;
|
|
226
|
+
try {
|
|
227
|
+
const resultData = await xObject.getDesc(xObjectDataApi.xObjectApiKey);
|
|
228
|
+
if (resultData && resultData.status) {
|
|
229
|
+
const result = resultData.data || {};
|
|
230
|
+
const fieldList = result.fields || [];
|
|
231
|
+
this.setState({ fieldList, title: result.label });
|
|
232
|
+
}
|
|
233
|
+
} catch (error) {
|
|
234
|
+
console.error('Failed to get field list:', error);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Current visible field list for the table (consistent with column configuration)
|
|
241
|
+
*/
|
|
242
|
+
getCurFieldList(): FieldInfo[] {
|
|
243
|
+
// const { xObjectDataApi } = this.props;
|
|
244
|
+
const xObjectDataApi: any = defaultXObjectDataApi;
|
|
245
|
+
const { fieldList } = this.state;
|
|
246
|
+
const { fields, fieldDescList } = xObjectDataApi || {};
|
|
247
|
+
let curFieldList =
|
|
248
|
+
fieldDescList && fieldDescList.length > 0 ? fieldDescList : fieldList;
|
|
249
|
+
|
|
250
|
+
if (fields && fields.length > 0) {
|
|
251
|
+
curFieldList = curFieldList.filter((field: FieldInfo) =>
|
|
252
|
+
fields.includes(field.apiKey),
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
return curFieldList;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Money field apiKey for summary (consistent with the money column, takes the first currency field)
|
|
260
|
+
*/
|
|
261
|
+
getMoneyFieldApiKey(): string | null {
|
|
262
|
+
const moneyField = this.getCurFieldList().find((f) => isMoneyField(f));
|
|
263
|
+
return moneyField?.apiKey ?? null;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Generate table column configuration
|
|
268
|
+
* @returns Array of table column configurations
|
|
269
|
+
*/
|
|
270
|
+
generateColumns() {
|
|
271
|
+
const xObjectDataApi: any = defaultXObjectDataApi;
|
|
272
|
+
|
|
273
|
+
const curFieldList = this.getCurFieldList().filter(
|
|
274
|
+
(field) => !HIDDEN_TABLE_COLUMN_KEYS.has(field.apiKey),
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
// Generate base column configuration from field list
|
|
278
|
+
const columns: any[] = curFieldList.map((field) => {
|
|
279
|
+
const col: any = {
|
|
280
|
+
title: field.label,
|
|
281
|
+
dataIndex: field.apiKey,
|
|
282
|
+
key: field.apiKey,
|
|
283
|
+
ellipsis: true,
|
|
284
|
+
};
|
|
285
|
+
if (
|
|
286
|
+
field.apiKey === 'oppHealthAssessmentLevel' ||
|
|
287
|
+
field.apiKey === 'customItem239__c'
|
|
288
|
+
) {
|
|
289
|
+
col.title = (
|
|
290
|
+
<span className="simpleTable-th-title-with-ai-icon">
|
|
291
|
+
<span className="simpleTable-th-ai-icon" />
|
|
292
|
+
<span>{field.label}</span>
|
|
293
|
+
</span>
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
if (field.apiKey === 'closeDate') {
|
|
297
|
+
col.render = (text: unknown, record: any) => {
|
|
298
|
+
const display = formatCloseDate(text);
|
|
299
|
+
const trend = closeDateTrend(text, record?.historyData);
|
|
300
|
+
if (trend !== 'up' && trend !== 'down') {
|
|
301
|
+
return display;
|
|
302
|
+
}
|
|
303
|
+
return renderTrendCell({
|
|
304
|
+
displayText: display,
|
|
305
|
+
trend,
|
|
306
|
+
tooltip: closeDateChangeTooltipTitle(record, text),
|
|
307
|
+
});
|
|
308
|
+
};
|
|
309
|
+
} else if (field.apiKey === 'opportunityName') {
|
|
310
|
+
col.render = (text: unknown, record: any) => {
|
|
311
|
+
const display = text == null || text === '' ? '—' : String(text);
|
|
312
|
+
const id =
|
|
313
|
+
record?.id != null && record.id !== '' ? String(record.id) : '';
|
|
314
|
+
const objectApiKey = xObjectDataApi?.xObjectApiKey;
|
|
315
|
+
if (!id || !objectApiKey) {
|
|
316
|
+
return display;
|
|
317
|
+
}
|
|
318
|
+
const url = buildOpportunityDetailUrl(id, objectApiKey);
|
|
319
|
+
return (
|
|
320
|
+
<a
|
|
321
|
+
className="simpleTable-opp-name-link"
|
|
322
|
+
href={url}
|
|
323
|
+
target="_blank"
|
|
324
|
+
/*
|
|
325
|
+
onClick={(e) => {
|
|
326
|
+
e.preventDefault();
|
|
327
|
+
window.location.assign(url);
|
|
328
|
+
}}
|
|
329
|
+
*/
|
|
330
|
+
>
|
|
331
|
+
{display}
|
|
332
|
+
</a>
|
|
333
|
+
);
|
|
334
|
+
};
|
|
335
|
+
} else if (field.apiKey === 'recentActivityRecordTime') {
|
|
336
|
+
col.render = (text: unknown) => formatActivityDateTime(text);
|
|
337
|
+
} else if (field.apiKey === 'oppHealthAssessmentLevel') {
|
|
338
|
+
col.render = (text: unknown, record: any) => {
|
|
339
|
+
const cell = renderOppHealthAssessmentLevel(text);
|
|
340
|
+
const id =
|
|
341
|
+
record?.id != null && record.id !== '' ? String(record.id) : '';
|
|
342
|
+
const xObjectApiKey = xObjectDataApi?.xObjectApiKey;
|
|
343
|
+
if (!id || !xObjectApiKey) {
|
|
344
|
+
return cell;
|
|
345
|
+
}
|
|
346
|
+
return (
|
|
347
|
+
<Popover
|
|
348
|
+
content={
|
|
349
|
+
<div className="simpleTable-health-popover-body">
|
|
350
|
+
<ShowHealthResult id={id} xObjectApiKey={xObjectApiKey} />
|
|
351
|
+
</div>
|
|
352
|
+
}
|
|
353
|
+
trigger="hover"
|
|
354
|
+
placement="topLeft"
|
|
355
|
+
overlayClassName="simpleTable-health-popover-overlay"
|
|
356
|
+
mouseEnterDelay={0.08}
|
|
357
|
+
>
|
|
358
|
+
<span className="simpleTable-health-popover-trigger">{cell}</span>
|
|
359
|
+
</Popover>
|
|
360
|
+
);
|
|
361
|
+
};
|
|
362
|
+
} else if (field.apiKey === 'customItem239__c') {
|
|
363
|
+
col.align = 'center';
|
|
364
|
+
col.render = (_text: unknown, record: any) => (
|
|
365
|
+
<Popover
|
|
366
|
+
content={renderWinRateHoverCard(record)}
|
|
367
|
+
trigger="hover"
|
|
368
|
+
placement="topLeft"
|
|
369
|
+
overlayClassName="simpleTable-winrate-popover"
|
|
370
|
+
mouseEnterDelay={0.08}
|
|
371
|
+
>
|
|
372
|
+
<span className="simpleTable-winrate-trigger">
|
|
373
|
+
{formatPercentCell(record?.customItem239__c)}
|
|
374
|
+
</span>
|
|
375
|
+
</Popover>
|
|
376
|
+
);
|
|
377
|
+
} else if (isMoneyField(field)) {
|
|
378
|
+
// col.align = 'right';
|
|
379
|
+
col.render = (text: unknown, record: any) => {
|
|
380
|
+
const display = formatMoneyCell(text);
|
|
381
|
+
const trend = moneyTrend(text, record?.historyData);
|
|
382
|
+
if (trend !== 'up' && trend !== 'down') {
|
|
383
|
+
return display;
|
|
384
|
+
}
|
|
385
|
+
return renderTrendCell({
|
|
386
|
+
displayText: display,
|
|
387
|
+
trend,
|
|
388
|
+
tooltip: moneyChangeTooltipTitle(record, text),
|
|
389
|
+
});
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
return col;
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
return columns;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Convert FilterBar structured filter to xObject.query where string array (consistent with stageSwitch, SDK concatenates with AND in order)
|
|
400
|
+
*/
|
|
401
|
+
getFilterWhere(): string[] {
|
|
402
|
+
const raw = this.state.filter;
|
|
403
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
404
|
+
return [];
|
|
405
|
+
}
|
|
406
|
+
const curFilter = raw as Record<string, unknown>;
|
|
407
|
+
const where: string[] = [];
|
|
408
|
+
|
|
409
|
+
const range = closeRangeFromFilter(curFilter.closeDateCustomRange);
|
|
410
|
+
if (range) {
|
|
411
|
+
where.push(`closeDate >= ${range.start} and closeDate <= ${range.end}`);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const ownerIds = normalizeOwnerIdsForWhere(curFilter.opportunityOwner);
|
|
415
|
+
if (ownerIds.length === 1) {
|
|
416
|
+
where.push(`ownerId = ${ownerIds[0]}`);
|
|
417
|
+
} else if (ownerIds.length > 1) {
|
|
418
|
+
where.push(`ownerId in (${ownerIds.join(', ')})`);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const entityTypeId = entityTypeIdForWhere(curFilter.businessType);
|
|
422
|
+
if (entityTypeId != null) {
|
|
423
|
+
where.push(`entityType = ${entityTypeId}`);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/*
|
|
427
|
+
// If activeStage exists, add stage filter condition
|
|
428
|
+
if (this.state.activeStage) {
|
|
429
|
+
// customItem248__c is the sales stage field
|
|
430
|
+
where.push(`customItem248__c = '${this.state.activeStage}'`);
|
|
431
|
+
}
|
|
432
|
+
*/
|
|
433
|
+
|
|
434
|
+
return where;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/** Consistent with stageSwitch: historical opportunity custom SQL where (opportunity_1_* fields) */
|
|
438
|
+
getHistoryOpportunityQueryFilter(): string[] {
|
|
439
|
+
const raw = this.state.filter;
|
|
440
|
+
const defaultFilter = getDefaultFilterByProps(this.props);
|
|
441
|
+
|
|
442
|
+
const curFilter: Record<string, unknown> =
|
|
443
|
+
raw && typeof raw === 'object' && !Array.isArray(raw)
|
|
444
|
+
? Object.keys(raw as object).length > 0
|
|
445
|
+
? (raw as Record<string, unknown>)
|
|
446
|
+
: defaultFilter
|
|
447
|
+
: defaultFilter;
|
|
448
|
+
|
|
449
|
+
const where: string[] = [];
|
|
450
|
+
|
|
451
|
+
const range = closeRangeFromFilter(curFilter.closeDateCustomRange);
|
|
452
|
+
if (range) {
|
|
453
|
+
where.push(
|
|
454
|
+
`opportunity_1_closeDate >= ${range.start} and opportunity_1_closeDate <= ${range.end}`,
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const ownerIds = normalizeOwnerIdsForWhere(curFilter.opportunityOwner);
|
|
459
|
+
if (ownerIds.length === 1) {
|
|
460
|
+
where.push(`opportunity_1_ownerId = ${ownerIds[0]}`);
|
|
461
|
+
} else if (ownerIds.length > 1) {
|
|
462
|
+
where.push(`opportunity_1_ownerId in (${ownerIds.join(', ')})`);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const entityTypeId = entityTypeIdForWhere(curFilter.businessType);
|
|
466
|
+
if (entityTypeId != null) {
|
|
467
|
+
where.push(`opportunity_1_entityType = ${entityTypeId}`);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (curFilter.changesSinceCustomTime) {
|
|
471
|
+
where.push(`version = ${curFilter.changesSinceCustomTime}`);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
return where;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/** Query historical opportunity list for the period (same source as stageSwitch.fetchHistoryOpportunityList, fields extended as needed) */
|
|
478
|
+
async fetchHistoryOpportunityList(): Promise<unknown[]> {
|
|
479
|
+
const result = await queryByCustomSQL({
|
|
480
|
+
xObjectApiKey: HISTORY_OPPORTUNITY_BI_KEY,
|
|
481
|
+
fields: [...HISTORY_QUERY_FIELDS],
|
|
482
|
+
page: 1,
|
|
483
|
+
pageSize: 1000,
|
|
484
|
+
where: this.getHistoryOpportunityQueryFilter(),
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
return result?.status ? result.data ?? [] : [];
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Load table data
|
|
492
|
+
*/
|
|
493
|
+
@NeoEvent.function
|
|
494
|
+
async loadData() {
|
|
495
|
+
// const api = this.props.xObjectDataApi || {};
|
|
496
|
+
const api: any = defaultXObjectDataApi;
|
|
497
|
+
const { xObjectApiKey } = api;
|
|
498
|
+
if (!xObjectApiKey) return;
|
|
499
|
+
|
|
500
|
+
this.setState({ loading: true, error: null });
|
|
501
|
+
|
|
502
|
+
try {
|
|
503
|
+
const rawWhere = (api as { where?: unknown }).where;
|
|
504
|
+
const baseWhere: string[] = Array.isArray(rawWhere)
|
|
505
|
+
? rawWhere.filter((w): w is string => typeof w === 'string')
|
|
506
|
+
: typeof rawWhere === 'string' && rawWhere
|
|
507
|
+
? [rawWhere]
|
|
508
|
+
: [];
|
|
509
|
+
const filterWhere =
|
|
510
|
+
xObjectApiKey === 'opportunity' ? this.getFilterWhere() : [];
|
|
511
|
+
const [result, historyRows] = await Promise.all([
|
|
512
|
+
xObject.query({
|
|
513
|
+
...api,
|
|
514
|
+
where: [...baseWhere, ...filterWhere],
|
|
515
|
+
}),
|
|
516
|
+
this.fetchHistoryOpportunityList(),
|
|
517
|
+
]);
|
|
518
|
+
|
|
519
|
+
if (result && result.status) {
|
|
520
|
+
let records = result.data || [];
|
|
521
|
+
|
|
522
|
+
console.log('[SimpleTable__c] records:', records, historyRows);
|
|
523
|
+
|
|
524
|
+
// Filter data by stage
|
|
525
|
+
if (this.state.activeStage) {
|
|
526
|
+
records = records.filter((record: any) => {
|
|
527
|
+
return record.customItem248__c === this.state.activeStage;
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
const historyMap =
|
|
532
|
+
xObjectApiKey === 'opportunity'
|
|
533
|
+
? buildHistoryMap(historyRows)
|
|
534
|
+
: new Map<string, HistoryOppSnap>();
|
|
535
|
+
|
|
536
|
+
const merged = records.map((r: any) => {
|
|
537
|
+
const id = r?.id != null ? String(r.id) : '';
|
|
538
|
+
const historyData = id ? historyMap.get(id) ?? null : null;
|
|
539
|
+
return { ...r, historyData };
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
this.setState({
|
|
543
|
+
dataSource: merged,
|
|
544
|
+
loading: false,
|
|
545
|
+
});
|
|
546
|
+
} else {
|
|
547
|
+
this.setState({
|
|
548
|
+
error: result?.msg || 'Failed to fetch data',
|
|
549
|
+
loading: false,
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
} catch (error: any) {
|
|
553
|
+
this.setState({
|
|
554
|
+
error: error.message || 'Failed to fetch data',
|
|
555
|
+
loading: false,
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Consistent with stageSwitch: update FilterBar filter and re-fetch table data.
|
|
562
|
+
*/
|
|
563
|
+
@NeoEvent.function
|
|
564
|
+
setFilter(filter?: any) {
|
|
565
|
+
if (isEqual(filter, this.state.filter)) {
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
console.log('[SimpleTable__c] setFilter:', filter);
|
|
569
|
+
this.setState({ filter }, () => {
|
|
570
|
+
this.loadData();
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Update the currently active sales stage
|
|
576
|
+
*/
|
|
577
|
+
@NeoEvent.function
|
|
578
|
+
updateActiveStage(activeStage?: string) {
|
|
579
|
+
if (isEqual(activeStage, this.state.activeStage)) {
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
console.log('[SimpleTable__c] updateActiveStage:', activeStage);
|
|
583
|
+
this.setState({ activeStage: activeStage || '' }, () => {
|
|
584
|
+
this.loadData();
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Render component
|
|
590
|
+
* @returns Component JSX element
|
|
591
|
+
*/
|
|
592
|
+
render() {
|
|
593
|
+
const { title: stateTitle, dataSource, loading, error } = this.state;
|
|
594
|
+
const { className, title: propsTitle, description } = this.props;
|
|
595
|
+
// const { xObjectApiKey } = this.props.xObjectDataApi || {};
|
|
596
|
+
const { xObjectApiKey } = defaultXObjectDataApi;
|
|
597
|
+
const columns = this.generateColumns();
|
|
598
|
+
|
|
599
|
+
// Use props.title first, then state.title, and finally the default value
|
|
600
|
+
const displayTitle = propsTitle || stateTitle || 'Data Table';
|
|
601
|
+
|
|
602
|
+
const moneyKey = this.getMoneyFieldApiKey();
|
|
603
|
+
const totalAmount = moneyKey ? sumMoneyRows(dataSource, moneyKey) : 0;
|
|
604
|
+
const oppCount = dataSource.length;
|
|
605
|
+
const oppWord = oppCount === 1 ? 'opportunity' : 'opportunities';
|
|
606
|
+
const summaryText = `Total: ${formatMoneySummaryAmount(
|
|
607
|
+
totalAmount,
|
|
608
|
+
)} · ${oppCount} ${oppWord}`;
|
|
609
|
+
|
|
610
|
+
console.log(
|
|
611
|
+
'simpleTable__c / dataSource:',
|
|
612
|
+
dataSource,
|
|
613
|
+
this.props,
|
|
614
|
+
this.state,
|
|
615
|
+
);
|
|
616
|
+
|
|
617
|
+
return (
|
|
618
|
+
<div className={`simpleTable__c ${className}`} data-time="2026.4.17 01">
|
|
619
|
+
<div className="table-wrapper">
|
|
620
|
+
<div className="panel-header">
|
|
621
|
+
<div className="panel-header-text">
|
|
622
|
+
<h3>
|
|
623
|
+
{displayTitle} - {this.state.activeStage}
|
|
624
|
+
</h3>
|
|
625
|
+
{description ? (
|
|
626
|
+
<p className="panel-header-description">{description}</p>
|
|
627
|
+
) : null}
|
|
628
|
+
</div>
|
|
629
|
+
<div className="panel-header-summary" title={summaryText}>
|
|
630
|
+
Total:{' '}
|
|
631
|
+
<span className="summary-amount">
|
|
632
|
+
{formatMoneySummaryAmount(totalAmount)}
|
|
633
|
+
</span>
|
|
634
|
+
{' · '}
|
|
635
|
+
<span className="summary-amount">{oppCount}</span> {oppWord}
|
|
636
|
+
</div>
|
|
637
|
+
</div>
|
|
638
|
+
<div className="table-container">
|
|
639
|
+
<Spin spinning={loading} tip="Loading data...">
|
|
640
|
+
{error ? (
|
|
641
|
+
<Empty
|
|
642
|
+
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
|
643
|
+
description={
|
|
644
|
+
<div>
|
|
645
|
+
<div style={{ color: '#ff4d4f', marginBottom: 8 }}>
|
|
646
|
+
{error}
|
|
647
|
+
</div>
|
|
648
|
+
</div>
|
|
649
|
+
}
|
|
650
|
+
/>
|
|
651
|
+
) : (
|
|
652
|
+
<Table
|
|
653
|
+
key={`${xObjectApiKey}-${columns.length}`}
|
|
654
|
+
columns={columns}
|
|
655
|
+
dataSource={dataSource}
|
|
656
|
+
rowKey="id"
|
|
657
|
+
pagination={false}
|
|
658
|
+
scroll={{ x: 'max-content' }}
|
|
659
|
+
/>
|
|
660
|
+
)}
|
|
661
|
+
</Spin>
|
|
662
|
+
</div>
|
|
663
|
+
</div>
|
|
664
|
+
</div>
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
}
|