test-chat-sdk 0.0.0

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 (208) hide show
  1. package/.prettierrc.js +24 -0
  2. package/README.md +46 -0
  3. package/config/env.js +104 -0
  4. package/config/getHttpsConfig.js +66 -0
  5. package/config/jest/babelTransform.js +29 -0
  6. package/config/jest/cssTransform.js +14 -0
  7. package/config/jest/fileTransform.js +40 -0
  8. package/config/modules.js +134 -0
  9. package/config/paths.js +77 -0
  10. package/config/webpack/persistentCache/createEnvironmentHash.js +9 -0
  11. package/config/webpack.config.js +785 -0
  12. package/config/webpackDevServer.config.js +127 -0
  13. package/dist/Chat/AgentList/index.d.ts +9 -0
  14. package/dist/Chat/ChatFooter/index.d.ts +17 -0
  15. package/dist/Chat/Conversation/index.d.ts +11 -0
  16. package/dist/Chat/MessageContainer/index.d.ts +19 -0
  17. package/dist/Chat/MobileAgents/index.d.ts +11 -0
  18. package/dist/Chat/components/AgentTip/index.d.ts +8 -0
  19. package/dist/Chat/components/ConversationModal/index.d.ts +10 -0
  20. package/dist/Chat/components/CopilotAvatar/index.d.ts +2 -0
  21. package/dist/Chat/components/Message.d.ts +10 -0
  22. package/dist/Chat/components/RecommendQuestions/index.d.ts +6 -0
  23. package/dist/Chat/components/Text.d.ts +9 -0
  24. package/dist/Chat/constants.d.ts +19 -0
  25. package/dist/Chat/index.d.ts +17 -0
  26. package/dist/Chat/service.d.ts +11 -0
  27. package/dist/Chat/type.d.ts +97 -0
  28. package/dist/Copilot/constants.d.ts +11 -0
  29. package/dist/Copilot/index.d.ts +13 -0
  30. package/dist/ShowCase/index.d.ts +8 -0
  31. package/dist/ShowCase/service.d.ts +2 -0
  32. package/dist/ShowCase/type.d.ts +11 -0
  33. package/dist/common/constants.d.ts +58 -0
  34. package/dist/common/env.d.ts +3 -0
  35. package/dist/common/type.d.ts +247 -0
  36. package/dist/components/ChatItem/ExecuteItem.d.ts +25 -0
  37. package/dist/components/ChatItem/ExpandParseTip.d.ts +20 -0
  38. package/dist/components/ChatItem/FilterItem.d.ts +17 -0
  39. package/dist/components/ChatItem/Loading.d.ts +2 -0
  40. package/dist/components/ChatItem/ParseTip.d.ts +26 -0
  41. package/dist/components/ChatItem/ParseTipUtils.d.ts +10 -0
  42. package/dist/components/ChatItem/SimilarQuestionItem.d.ts +10 -0
  43. package/dist/components/ChatItem/SqlItem.d.ts +17 -0
  44. package/dist/components/ChatItem/SwitchEntity.d.ts +9 -0
  45. package/dist/components/ChatItem/Text.d.ts +6 -0
  46. package/dist/components/ChatItem/Typing.d.ts +2 -0
  47. package/dist/components/ChatItem/index.d.ts +33 -0
  48. package/dist/components/ChatMsg/ApplyAuth/index.d.ts +7 -0
  49. package/dist/components/ChatMsg/Bar/index.d.ts +13 -0
  50. package/dist/components/ChatMsg/DateOptions/index.d.ts +9 -0
  51. package/dist/components/ChatMsg/FilterSection/index.d.ts +8 -0
  52. package/dist/components/ChatMsg/MarkDown/index.d.ts +10 -0
  53. package/dist/components/ChatMsg/Message/index.d.ts +18 -0
  54. package/dist/components/ChatMsg/MetricCard/PeriodCompareItem.d.ts +7 -0
  55. package/dist/components/ChatMsg/MetricCard/index.d.ts +10 -0
  56. package/dist/components/ChatMsg/MetricTrend/MetricInfo.d.ts +8 -0
  57. package/dist/components/ChatMsg/MetricTrend/MetricTrendChart.d.ts +14 -0
  58. package/dist/components/ChatMsg/MetricTrend/MultiMetricsTrendChart.d.ts +12 -0
  59. package/dist/components/ChatMsg/MetricTrend/index.d.ts +16 -0
  60. package/dist/components/ChatMsg/NoPermissionChart/index.d.ts +8 -0
  61. package/dist/components/ChatMsg/Pie/PieChart.d.ts +11 -0
  62. package/dist/components/ChatMsg/Pie/index.d.ts +14 -0
  63. package/dist/components/ChatMsg/Table/index.d.ts +12 -0
  64. package/dist/components/ChatMsg/Text/index.d.ts +9 -0
  65. package/dist/components/ChatMsg/WebPage/index.d.ts +8 -0
  66. package/dist/components/ChatMsg/index.d.ts +15 -0
  67. package/dist/components/DrillDownDimensions/DimensionSection.d.ts +11 -0
  68. package/dist/components/DrillDownDimensions/index.d.ts +13 -0
  69. package/dist/components/IconFont/index.d.ts +3 -0
  70. package/dist/components/MetricOptions/index.d.ts +11 -0
  71. package/dist/components/RecommendOptions/index.d.ts +9 -0
  72. package/dist/components/Tools/FeedbackModal.d.ts +9 -0
  73. package/dist/components/Tools/index.d.ts +12 -0
  74. package/dist/demo/Chat.d.ts +2 -0
  75. package/dist/demo/ChatDemo.d.ts +4 -0
  76. package/dist/demo/CopilotDemo.d.ts +2 -0
  77. package/dist/hooks/index.d.ts +3 -0
  78. package/dist/hooks/useComposing.d.ts +5 -0
  79. package/dist/hooks/useExportByEcharts.d.ts +10 -0
  80. package/dist/hooks/useMethodRegister.d.ts +4 -0
  81. package/dist/index.d.ts +10 -0
  82. package/dist/index.es.js +1 -0
  83. package/dist/service/axiosInstance.d.ts +3 -0
  84. package/dist/service/index.d.ts +25 -0
  85. package/dist/utils/utils.d.ts +45 -0
  86. package/package.json +214 -0
  87. package/public/favicon.ico +0 -0
  88. package/public/index.html +43 -0
  89. package/public/manifest.json +15 -0
  90. package/public/robots.txt +3 -0
  91. package/rollup/rollup.config.mjs +37 -0
  92. package/rollup/rollup.esm.config.mjs +21 -0
  93. package/rollup/rollup.umd.config.mjs +30 -0
  94. package/scripts/build.js +217 -0
  95. package/scripts/start.js +154 -0
  96. package/scripts/test.js +52 -0
  97. package/src/Chat/AgentList/index.tsx +52 -0
  98. package/src/Chat/AgentList/style.module.less +83 -0
  99. package/src/Chat/ChatFooter/index.tsx +423 -0
  100. package/src/Chat/ChatFooter/style.module.less +225 -0
  101. package/src/Chat/Conversation/index.tsx +236 -0
  102. package/src/Chat/Conversation/style.module.less +171 -0
  103. package/src/Chat/MessageContainer/index.tsx +145 -0
  104. package/src/Chat/MessageContainer/style.module.less +53 -0
  105. package/src/Chat/MobileAgents/index.tsx +62 -0
  106. package/src/Chat/MobileAgents/style.module.less +55 -0
  107. package/src/Chat/components/AgentTip/index.tsx +48 -0
  108. package/src/Chat/components/AgentTip/style.module.less +44 -0
  109. package/src/Chat/components/ConversationModal/index.tsx +65 -0
  110. package/src/Chat/components/CopilotAvatar/index.tsx +8 -0
  111. package/src/Chat/components/CopilotAvatar/style.module.less +13 -0
  112. package/src/Chat/components/Message.tsx +38 -0
  113. package/src/Chat/components/RecommendQuestions/index.tsx +64 -0
  114. package/src/Chat/components/RecommendQuestions/style.module.less +36 -0
  115. package/src/Chat/components/Text.tsx +42 -0
  116. package/src/Chat/components/style.module.less +311 -0
  117. package/src/Chat/constants.ts +37 -0
  118. package/src/Chat/index.tsx +526 -0
  119. package/src/Chat/service.ts +49 -0
  120. package/src/Chat/style.module.less +119 -0
  121. package/src/Chat/type.ts +107 -0
  122. package/src/Copilot/constants.ts +11 -0
  123. package/src/Copilot/index.tsx +149 -0
  124. package/src/Copilot/style.module.less +151 -0
  125. package/src/ShowCase/index.tsx +120 -0
  126. package/src/ShowCase/service.ts +12 -0
  127. package/src/ShowCase/style.module.less +46 -0
  128. package/src/ShowCase/type.ts +14 -0
  129. package/src/common/constants.ts +93 -0
  130. package/src/common/env.ts +5 -0
  131. package/src/common/type.ts +270 -0
  132. package/src/components/ChatItem/ExecuteItem.tsx +210 -0
  133. package/src/components/ChatItem/ExpandParseTip.tsx +333 -0
  134. package/src/components/ChatItem/FilterItem.tsx +209 -0
  135. package/src/components/ChatItem/Loading.tsx +14 -0
  136. package/src/components/ChatItem/ParseTip.tsx +322 -0
  137. package/src/components/ChatItem/ParseTipUtils.tsx +205 -0
  138. package/src/components/ChatItem/SimilarQuestionItem.tsx +84 -0
  139. package/src/components/ChatItem/SqlItem.tsx +410 -0
  140. package/src/components/ChatItem/SwitchEntity.tsx +52 -0
  141. package/src/components/ChatItem/Text.tsx +17 -0
  142. package/src/components/ChatItem/Typing.tsx +19 -0
  143. package/src/components/ChatItem/index.tsx +843 -0
  144. package/src/components/ChatItem/style.less +670 -0
  145. package/src/components/ChatMsg/ApplyAuth/index.tsx +30 -0
  146. package/src/components/ChatMsg/ApplyAuth/style.less +13 -0
  147. package/src/components/ChatMsg/Bar/index.tsx +208 -0
  148. package/src/components/ChatMsg/Bar/style.less +60 -0
  149. package/src/components/ChatMsg/DateOptions/index.tsx +46 -0
  150. package/src/components/ChatMsg/DateOptions/style.less +43 -0
  151. package/src/components/ChatMsg/FilterSection/index.tsx +42 -0
  152. package/src/components/ChatMsg/FilterSection/style.less +37 -0
  153. package/src/components/ChatMsg/MarkDown/index.tsx +26 -0
  154. package/src/components/ChatMsg/MarkDown/style.less +9 -0
  155. package/src/components/ChatMsg/Message/index.tsx +105 -0
  156. package/src/components/ChatMsg/Message/style.less +119 -0
  157. package/src/components/ChatMsg/MetricCard/PeriodCompareItem.tsx +29 -0
  158. package/src/components/ChatMsg/MetricCard/index.tsx +80 -0
  159. package/src/components/ChatMsg/MetricCard/style.less +126 -0
  160. package/src/components/ChatMsg/MetricTrend/MetricInfo.tsx +60 -0
  161. package/src/components/ChatMsg/MetricTrend/MetricTrendChart.tsx +235 -0
  162. package/src/components/ChatMsg/MetricTrend/MultiMetricsTrendChart.tsx +162 -0
  163. package/src/components/ChatMsg/MetricTrend/index.tsx +127 -0
  164. package/src/components/ChatMsg/MetricTrend/style.less +195 -0
  165. package/src/components/ChatMsg/NoPermissionChart/index.tsx +28 -0
  166. package/src/components/ChatMsg/NoPermissionChart/style.less +26 -0
  167. package/src/components/ChatMsg/Pie/PieChart.tsx +120 -0
  168. package/src/components/ChatMsg/Pie/index.tsx +88 -0
  169. package/src/components/ChatMsg/Pie/style.less +43 -0
  170. package/src/components/ChatMsg/Table/index.tsx +103 -0
  171. package/src/components/ChatMsg/Table/style.less +131 -0
  172. package/src/components/ChatMsg/Text/index.tsx +70 -0
  173. package/src/components/ChatMsg/Text/style.less +38 -0
  174. package/src/components/ChatMsg/WebPage/index.tsx +125 -0
  175. package/src/components/ChatMsg/index.tsx +428 -0
  176. package/src/components/ChatMsg/style.less +28 -0
  177. package/src/components/DrillDownDimensions/DimensionSection.tsx +99 -0
  178. package/src/components/DrillDownDimensions/index.tsx +76 -0
  179. package/src/components/DrillDownDimensions/style.less +64 -0
  180. package/src/components/IconFont/index.tsx +7 -0
  181. package/src/components/MetricOptions/index.tsx +75 -0
  182. package/src/components/MetricOptions/style.less +69 -0
  183. package/src/components/RecommendOptions/index.tsx +126 -0
  184. package/src/components/RecommendOptions/style.less +24 -0
  185. package/src/components/Tools/FeedbackModal.tsx +55 -0
  186. package/src/components/Tools/index.tsx +126 -0
  187. package/src/components/Tools/style.less +67 -0
  188. package/src/demo/Chat.tsx +73 -0
  189. package/src/demo/ChatDemo.tsx +14 -0
  190. package/src/demo/CopilotDemo.tsx +43 -0
  191. package/src/demo/style.module.less +19 -0
  192. package/src/hooks/index.ts +3 -0
  193. package/src/hooks/useComposing.ts +31 -0
  194. package/src/hooks/useExportByEcharts.ts +41 -0
  195. package/src/hooks/useMethodRegister.ts +25 -0
  196. package/src/index.tsx +44 -0
  197. package/src/service/axiosInstance.ts +58 -0
  198. package/src/service/index.ts +174 -0
  199. package/src/setupProxy.js +18 -0
  200. package/src/setupTests.ts +5 -0
  201. package/src/styles/global.less +52 -0
  202. package/src/styles/index.less +39 -0
  203. package/src/styles/reboot.less +14 -0
  204. package/src/styles/variables.less +80 -0
  205. package/src/typings.d.ts +179 -0
  206. package/src/utils/utils.ts +346 -0
  207. package/tsconfig.build.json +20 -0
  208. package/tsconfig.json +27 -0
@@ -0,0 +1,29 @@
1
+ import classNames from 'classnames';
2
+ import { PREFIX_CLS } from '../../../common/constants';
3
+ import IconFont from '../../IconFont';
4
+
5
+ type Props = {
6
+ title: string;
7
+ value: string;
8
+ };
9
+
10
+ const PeriodCompareItem: React.FC<Props> = ({ title, value }) => {
11
+ const prefixCls = `${PREFIX_CLS}-metric-card`;
12
+
13
+ const itemValueClass = classNames(`${prefixCls}-period-compare-item-value`, {
14
+ [`${prefixCls}-period-compare-item-value-up`]: !value.includes('-'),
15
+ [`${prefixCls}-period-compare-item-value-down`]: value.includes('-'),
16
+ });
17
+
18
+ return (
19
+ <div className={`${prefixCls}-period-compare-item`}>
20
+ <div className={`${prefixCls}-period-compare-item-title`}>{title}</div>
21
+ <div className={itemValueClass}>
22
+ <IconFont type={!value.includes('-') ? 'icon-shangsheng' : 'icon-xiajiang'} />
23
+ <div>{value}</div>
24
+ </div>
25
+ </div>
26
+ );
27
+ };
28
+
29
+ export default PeriodCompareItem;
@@ -0,0 +1,80 @@
1
+ import { PREFIX_CLS } from '../../../common/constants';
2
+ import { formatByDataFormatType, formatMetric, formatNumberWithCN } from '../../../utils/utils';
3
+ import ApplyAuth from '../ApplyAuth';
4
+ import { MsgDataType } from '../../../common/type';
5
+ import PeriodCompareItem from './PeriodCompareItem';
6
+ import { Spin } from 'antd';
7
+ import classNames from 'classnames';
8
+ import { SwapOutlined } from '@ant-design/icons';
9
+ import { useState } from 'react';
10
+
11
+ type Props = {
12
+ data: MsgDataType;
13
+ question: string;
14
+ loading: boolean;
15
+ onApplyAuth?: (model: string) => void;
16
+ };
17
+
18
+ const MetricCard: React.FC<Props> = ({ data, question, loading, onApplyAuth }) => {
19
+ const { queryMode, queryColumns, queryResults, entityInfo, aggregateInfo } = data;
20
+
21
+ const { metricInfos } = aggregateInfo || {};
22
+
23
+ const indicatorColumn = queryColumns?.find(column => column.showType === 'NUMBER');
24
+ const indicatorColumnName = indicatorColumn?.bizName || '';
25
+
26
+ const { dataFormatType, dataFormat } = indicatorColumn || {};
27
+ const value = queryResults?.[0]?.[indicatorColumnName] || 0;
28
+
29
+ const prefixCls = `${PREFIX_CLS}-metric-card`;
30
+
31
+ const matricCardClass = classNames(prefixCls, {
32
+ [`${PREFIX_CLS}-metric-card-dsl`]: queryMode === 'LLM_S2SQL',
33
+ });
34
+
35
+ const [isNumber, setIsNumber] = useState(false);
36
+ const handleNumberClick = () => {
37
+ setIsNumber(!isNumber);
38
+ };
39
+
40
+ return (
41
+ <div className={matricCardClass}>
42
+ <div className={`${prefixCls}-top-bar`}>
43
+ <div className={`${prefixCls}-indicator-name`}>{question}</div>
44
+ </div>
45
+ <Spin spinning={loading}>
46
+ <div className={`${prefixCls}-indicator`}>
47
+ {indicatorColumn && !indicatorColumn?.authorized ? (
48
+ <ApplyAuth model={entityInfo?.dataSetInfo.name || ''} onApplyAuth={onApplyAuth} />
49
+ ) : (
50
+ <div style={{ display: 'flex', alignItems: 'flex-end' }}>
51
+ <div className={`${prefixCls}-indicator-value`}>
52
+ {typeof value === 'string' && isNaN(+value)
53
+ ? value
54
+ : dataFormatType === 'percent' || dataFormatType === 'decimal'
55
+ ? formatByDataFormatType(value, dataFormatType, dataFormat)
56
+ : isNumber
57
+ ? formatMetric(value) || '-'
58
+ : formatNumberWithCN(+value)}
59
+ </div>
60
+ {!isNaN(+value) && +value >= 10000 && (
61
+ <div className={`${prefixCls}-indicator-switch`}>
62
+ <SwapOutlined onClick={handleNumberClick} />
63
+ </div>
64
+ )}
65
+ </div>
66
+ )}
67
+ {metricInfos?.length > 0 && (
68
+ <div className={`${prefixCls}-period-compare`}>
69
+ {Object.keys(metricInfos[0].statistics).map((key: any) => (
70
+ <PeriodCompareItem title={key} value={metricInfos[0].statistics[key]} />
71
+ ))}
72
+ </div>
73
+ )}
74
+ </div>
75
+ </Spin>
76
+ </div>
77
+ );
78
+ };
79
+
80
+ export default MetricCard;
@@ -0,0 +1,126 @@
1
+ @import '../../../styles/index.less';
2
+
3
+ @metric-card-prefix-cls: ~'@{supersonic-chat-prefix}-metric-card';
4
+
5
+ .@{metric-card-prefix-cls} {
6
+ width: 100%;
7
+ row-gap: 4px;
8
+
9
+ &-dsl {
10
+ height: 90px;
11
+ }
12
+
13
+ &-top-bar {
14
+ display: flex;
15
+ align-items: baseline;
16
+ flex-wrap: wrap;
17
+ column-gap: 8px;
18
+ }
19
+
20
+ &-filter-section-wrapper {
21
+ display: flex;
22
+ align-items: center;
23
+ color: var(--text-color-third);
24
+ }
25
+
26
+ &-filter-section {
27
+ display: flex;
28
+ align-items: center;
29
+ font-size: 13px;
30
+ column-gap: 12px;
31
+ color: var(--text-color-third);
32
+ }
33
+
34
+ &-filter-item {
35
+ margin-right: 4px;
36
+ display: flex;
37
+ align-items: center;
38
+ }
39
+
40
+ &-filter-item-label {
41
+ color: var(--text-color-third);
42
+ }
43
+
44
+ &-filter-item-value {
45
+ color: var(--text-color);
46
+ font-weight: 500;
47
+ }
48
+
49
+ &-indicator-name {
50
+ font-size: 14px;
51
+ color: var(--text-color);
52
+ font-weight: 500;
53
+ margin-top: 2px;
54
+ }
55
+
56
+ &-query-tootip {
57
+ margin-left: 5px;
58
+ }
59
+
60
+ &-indicator {
61
+ display: flex;
62
+ flex-direction: column;
63
+ align-items: flex-start;
64
+ justify-content: flex-start;
65
+ margin: 12px 0;
66
+ }
67
+
68
+ &-date-range {
69
+ color: var(--text-color-fourth);
70
+ font-size: 12px;
71
+ margin-top: 8px;
72
+ }
73
+
74
+ &-indicator-value {
75
+ color: var(--text-color);
76
+ font-weight: 700;
77
+ font-size: 40px;
78
+ color: var(--chat-blue);
79
+ }
80
+
81
+ &-indicator-switch {
82
+ color: var(--text-color-fourth);
83
+ font-size: 18px;
84
+ margin-left: 6px;
85
+ margin-bottom: 3px;
86
+ }
87
+
88
+ &-period-compare {
89
+ width: 100%;
90
+ display: flex;
91
+ align-items: center;
92
+ column-gap: 40px;
93
+ font-size: 13px;
94
+ overflow-x: auto;
95
+ margin-bottom: 12px;
96
+ }
97
+
98
+ &-period-compare-item {
99
+ display: flex;
100
+ align-items: center;
101
+ column-gap: 10px;
102
+ }
103
+
104
+ &-period-compare-item-title {
105
+ color: var(--text-color-fourth);
106
+ }
107
+
108
+ &-period-compare-item-value {
109
+ display: flex;
110
+ align-items: center;
111
+ column-gap: 4px;
112
+ font-weight: 500;
113
+ }
114
+
115
+ &-period-compare-item-value-up {
116
+ color: rgb(252, 103, 114);
117
+ }
118
+
119
+ &-period-compare-item-value-down {
120
+ color: rgb(45, 202, 147);
121
+ }
122
+
123
+ &-drill-down-dimensions {
124
+ margin-top: 2px;
125
+ }
126
+ }
@@ -0,0 +1,60 @@
1
+ import { PREFIX_CLS } from '../../../common/constants';
2
+ import { formatByDataFormatType, formatMetric, formatNumberWithCN } from '../../../utils/utils';
3
+ import { AggregateInfoType, ColumnType } from '../../../common/type';
4
+ import PeriodCompareItem from '../MetricCard/PeriodCompareItem';
5
+ import { SwapOutlined } from '@ant-design/icons';
6
+ import { useState } from 'react';
7
+
8
+ type Props = {
9
+ aggregateInfo: AggregateInfoType;
10
+ currentMetricField: ColumnType;
11
+ };
12
+
13
+ const MetricInfo: React.FC<Props> = ({ aggregateInfo, currentMetricField }) => {
14
+ const { metricInfos } = aggregateInfo || {};
15
+ const metricInfo = metricInfos?.[0] || {};
16
+ const { date, value, statistics } = metricInfo || {};
17
+ const { dataFormatType, dataFormat } = currentMetricField;
18
+
19
+ const prefixCls = `${PREFIX_CLS}-metric-info`;
20
+
21
+ const [isNumber, setIsNumber] = useState(false);
22
+ const handleNumberClick = () => {
23
+ setIsNumber(!isNumber);
24
+ };
25
+
26
+ return (
27
+ <div className={prefixCls}>
28
+ <div className={`${prefixCls}-indicator`}>
29
+ <div style={{ display: 'flex', alignItems: 'flex-end' }}>
30
+ <div className={`${prefixCls}-indicator-value`}>
31
+ {dataFormatType === 'percent' || dataFormatType === 'decimal'
32
+ ? formatByDataFormatType(value, dataFormatType, dataFormat)
33
+ : isNumber
34
+ ? formatMetric(value)
35
+ : formatNumberWithCN(+value)}
36
+ </div>
37
+ {!isNaN(+value) && +value >= 10000 && (
38
+ <div className={`${prefixCls}-indicator-switch`}>
39
+ <SwapOutlined onClick={handleNumberClick} />
40
+ </div>
41
+ )}
42
+ </div>
43
+ <div className={`${prefixCls}-bottom-section`}>
44
+ <div className={`${prefixCls}-date`}>
45
+ 最新数据日期:<span className={`${prefixCls}-date-value`}>{date}</span>
46
+ </div>
47
+ {metricInfos?.length > 0 && (
48
+ <div className={`${prefixCls}-period-compare`}>
49
+ {Object.keys(statistics).map((key: any) => (
50
+ <PeriodCompareItem title={key} value={metricInfos[0].statistics[key]} />
51
+ ))}
52
+ </div>
53
+ )}
54
+ </div>
55
+ </div>
56
+ </div>
57
+ );
58
+ };
59
+
60
+ export default MetricInfo;
@@ -0,0 +1,235 @@
1
+ import { CHART_SECONDARY_COLOR, CLS_PREFIX, THEME_COLOR_LIST } from '../../../common/constants';
2
+ import {
3
+ formatByDataFormatType,
4
+ getFormattedValue,
5
+ getMinMaxDate,
6
+ groupByColumn,
7
+ normalizeTrendData,
8
+ } from '../../../utils/utils';
9
+ import type { ECharts } from 'echarts';
10
+ import * as echarts from 'echarts';
11
+ import React, { useContext, useEffect, useRef, useState } from 'react';
12
+ import moment from 'moment';
13
+ import { ColumnType } from '../../../common/type';
14
+ import NoPermissionChart from '../NoPermissionChart';
15
+ import classNames from 'classnames';
16
+ import { isArray } from 'lodash';
17
+ import { useExportByEcharts } from '../../../hooks';
18
+ import { ChartItemContext } from '../../ChatItem';
19
+
20
+ type Props = {
21
+ model?: string;
22
+ dateColumnName: string;
23
+ categoryColumnName: string;
24
+ metricField: ColumnType;
25
+ resultList: any[];
26
+ triggerResize?: boolean;
27
+ onApplyAuth?: (model: string) => void;
28
+ chartType?: string;
29
+ };
30
+
31
+ const MetricTrendChart: React.FC<Props> = ({
32
+ model,
33
+ dateColumnName,
34
+ categoryColumnName,
35
+ metricField,
36
+ resultList,
37
+ triggerResize,
38
+ onApplyAuth,
39
+ chartType,
40
+ }) => {
41
+ const chartRef = useRef<any>();
42
+ const instanceRef = useRef<ECharts>();
43
+
44
+ const renderChart = () => {
45
+ let instanceObj: any;
46
+ if (!instanceRef.current) {
47
+ instanceObj = echarts.init(chartRef.current);
48
+ instanceRef.current = instanceObj;
49
+ } else {
50
+ instanceObj = instanceRef.current;
51
+ instanceObj.clear();
52
+ }
53
+
54
+ const valueColumnName = metricField.bizName;
55
+ const dataSource = resultList.map((item: any) => {
56
+ return {
57
+ ...item,
58
+ [dateColumnName]: Array.isArray(item[dateColumnName])
59
+ ? moment(item[dateColumnName].join('')).format('MM-DD')
60
+ : item[dateColumnName],
61
+ };
62
+ });
63
+
64
+ const groupDataValue = groupByColumn(dataSource, categoryColumnName);
65
+ const [startDate, endDate] = getMinMaxDate(dataSource, dateColumnName);
66
+ const groupData = Object.keys(groupDataValue).reduce((result: any, key) => {
67
+ result[key] =
68
+ startDate &&
69
+ endDate &&
70
+ (dateColumnName.includes('date') || dateColumnName.includes('month'))
71
+ ? normalizeTrendData(
72
+ groupDataValue[key],
73
+ dateColumnName,
74
+ valueColumnName,
75
+ startDate,
76
+ endDate,
77
+ dateColumnName.includes('month') ? 'months' : 'days'
78
+ )
79
+ : groupDataValue[key];
80
+ return result;
81
+ }, {});
82
+
83
+ const sortedGroupKeys = Object.keys(groupData).sort((a, b) => {
84
+ return (
85
+ groupData[b][groupData[b].length - 1][valueColumnName] -
86
+ groupData[a][groupData[a].length - 1][valueColumnName]
87
+ );
88
+ });
89
+
90
+ const xData = groupData[sortedGroupKeys[0]]?.map((item: any) => {
91
+ const date = isArray(item[dateColumnName])
92
+ ? item[dateColumnName].join('-')
93
+ : `${item[dateColumnName]}`;
94
+ return date.length === 10 ? moment(date).format('MM-DD') : date;
95
+ });
96
+
97
+ instanceObj.setOption({
98
+ legend: categoryColumnName && {
99
+ left: 0,
100
+ top: 0,
101
+ icon: 'rect',
102
+ itemWidth: 15,
103
+ itemHeight: 5,
104
+ type: 'scroll',
105
+ },
106
+ xAxis: {
107
+ type: 'category',
108
+ axisTick: {
109
+ alignWithLabel: true,
110
+ lineStyle: {
111
+ color: CHART_SECONDARY_COLOR,
112
+ },
113
+ },
114
+ axisLine: {
115
+ lineStyle: {
116
+ color: CHART_SECONDARY_COLOR,
117
+ },
118
+ },
119
+ axisLabel: {
120
+ showMaxLabel: true,
121
+ color: '#999',
122
+ },
123
+ data: xData,
124
+ },
125
+ yAxis: {
126
+ type: 'value',
127
+ splitLine: {
128
+ lineStyle: {
129
+ opacity: 0.3,
130
+ },
131
+ },
132
+ axisLabel: {
133
+ formatter: function (value: any) {
134
+ return value === 0
135
+ ? 0
136
+ : metricField.dataFormatType === 'percent'
137
+ ? formatByDataFormatType(value, metricField.dataFormatType, metricField.dataFormat)
138
+ : getFormattedValue(value);
139
+ },
140
+ },
141
+ },
142
+ tooltip: {
143
+ trigger: 'axis',
144
+ formatter: function (params: any[]) {
145
+ const param = params[0];
146
+ const valueLabels = params
147
+ .sort((a, b) => b.value - a.value)
148
+ .map(
149
+ (item: any) =>
150
+ `<div style="margin-top: 3px;">${
151
+ item.marker
152
+ } <span style="display: inline-block; width: 70px; margin-right: 12px;">${
153
+ item.seriesName
154
+ }</span><span style="display: inline-block; width: 90px; text-align: right; font-weight: 500;">${
155
+ item.value === ''
156
+ ? '-'
157
+ : metricField.dataFormatType === 'percent' ||
158
+ metricField.dataFormatType === 'decimal'
159
+ ? formatByDataFormatType(item.value, metricField.dataFormatType, metricField.dataFormat)
160
+ : getFormattedValue(item.value)
161
+ }</span></div>`
162
+ )
163
+ .join('');
164
+ return `${param.name}<br />${valueLabels}`;
165
+ },
166
+ },
167
+ grid: {
168
+ left: '1%',
169
+ right: '4%',
170
+ bottom: '3%',
171
+ top: categoryColumnName ? 45 : 20,
172
+ containLabel: true,
173
+ },
174
+ series: sortedGroupKeys.slice(0, 20).map((category, index) => {
175
+ const data = groupData[category];
176
+ return {
177
+ type: chartType,
178
+ name: categoryColumnName ? category : metricField.name,
179
+ symbol: 'circle',
180
+ showSymbol: data.length === 1,
181
+ smooth: true,
182
+ data: data.map((item: any) => {
183
+ const value = item[valueColumnName];
184
+ return (metricField.dataFormatType === 'percent' ||
185
+ metricField.dataFormatType === 'decimal') &&
186
+ metricField.dataFormat?.needMultiply100
187
+ ? value * 100
188
+ : value;
189
+ }),
190
+ color: THEME_COLOR_LIST[index],
191
+ };
192
+ }),
193
+ });
194
+ instanceObj.resize();
195
+ };
196
+
197
+ const { downloadChartAsImage } = useExportByEcharts({
198
+ instanceRef,
199
+ question: metricField.name,
200
+ });
201
+
202
+ const { register } = useContext(ChartItemContext);
203
+
204
+ register('downloadChartAsImage', downloadChartAsImage);
205
+
206
+ useEffect(() => {
207
+ if (metricField.authorized) {
208
+ renderChart();
209
+ }
210
+ }, [resultList, metricField, chartType]);
211
+
212
+ useEffect(() => {
213
+ if (triggerResize && instanceRef.current) {
214
+ instanceRef.current.resize();
215
+ }
216
+ }, [triggerResize]);
217
+
218
+ const prefixCls = `${CLS_PREFIX}-metric-trend`;
219
+
220
+ const flowTrendChartClass = classNames(`${prefixCls}-flow-trend-chart`, {
221
+ [`${prefixCls}-flow-trend-chart-single`]: !categoryColumnName,
222
+ });
223
+
224
+ return (
225
+ <div>
226
+ {!metricField.authorized ? (
227
+ <NoPermissionChart model={model || ''} onApplyAuth={onApplyAuth} />
228
+ ) : (
229
+ <div className={flowTrendChartClass} ref={chartRef} />
230
+ )}
231
+ </div>
232
+ );
233
+ };
234
+
235
+ export default MetricTrendChart;
@@ -0,0 +1,162 @@
1
+ import { CHART_SECONDARY_COLOR, CLS_PREFIX, THEME_COLOR_LIST } from '../../../common/constants';
2
+ import { getFormattedValue } from '../../../utils/utils';
3
+ import type { ECharts } from 'echarts';
4
+ import * as echarts from 'echarts';
5
+ import React, { useContext, useEffect, useRef, useState } from 'react';
6
+ import moment from 'moment';
7
+ import { ColumnType } from '../../../common/type';
8
+ import { isArray } from 'lodash';
9
+ import { ChartItemContext } from '../../ChatItem';
10
+ import { useExportByEcharts } from '../../../hooks';
11
+
12
+ type Props = {
13
+ dateColumnName: string;
14
+ metricFields: ColumnType[];
15
+ resultList: any[];
16
+ triggerResize?: boolean;
17
+ chartType?: string;
18
+ question: string;
19
+ };
20
+
21
+ const MultiMetricsTrendChart: React.FC<Props> = ({
22
+ dateColumnName,
23
+ metricFields,
24
+ resultList,
25
+ triggerResize,
26
+ chartType,
27
+ question,
28
+ }) => {
29
+ const chartRef = useRef<any>();
30
+ const instanceRef = useRef<ECharts>();
31
+ const renderChart = () => {
32
+ let instanceObj: any;
33
+ if (!instanceRef.current) {
34
+ instanceObj = echarts.init(chartRef.current);
35
+ instanceRef.current = instanceObj;
36
+ } else {
37
+ instanceObj = instanceRef.current;
38
+ instanceObj.clear();
39
+ }
40
+
41
+ const xData = resultList?.map((item: any) => {
42
+ const date = isArray(item[dateColumnName])
43
+ ? item[dateColumnName].join('-')
44
+ : `${item[dateColumnName]}`;
45
+ return date.length === 10 ? moment(date).format('MM-DD') : date;
46
+ });
47
+
48
+ instanceObj.setOption({
49
+ legend: {
50
+ left: 0,
51
+ top: 0,
52
+ icon: 'rect',
53
+ itemWidth: 15,
54
+ itemHeight: 5,
55
+ type: 'scroll',
56
+ },
57
+ xAxis: {
58
+ type: 'category',
59
+ axisTick: {
60
+ alignWithLabel: true,
61
+ lineStyle: {
62
+ color: CHART_SECONDARY_COLOR,
63
+ },
64
+ },
65
+ axisLine: {
66
+ lineStyle: {
67
+ color: CHART_SECONDARY_COLOR,
68
+ },
69
+ },
70
+ axisLabel: {
71
+ showMaxLabel: true,
72
+ color: '#999',
73
+ },
74
+ data: xData,
75
+ },
76
+ yAxis: {
77
+ type: 'value',
78
+ splitLine: {
79
+ lineStyle: {
80
+ opacity: 0.3,
81
+ },
82
+ },
83
+ axisLabel: {
84
+ formatter: function (value: any) {
85
+ return value === 0 ? 0 : getFormattedValue(value);
86
+ },
87
+ },
88
+ },
89
+ tooltip: {
90
+ trigger: 'axis',
91
+ formatter: function (params: any[]) {
92
+ const param = params[0];
93
+ const valueLabels = params
94
+ .sort((a, b) => b.value - a.value)
95
+ .map(
96
+ (item: any) =>
97
+ `<div style="margin-top: 3px;">${
98
+ item.marker
99
+ } <span style="display: inline-block; width: 70px; margin-right: 12px;">${
100
+ item.seriesName
101
+ }</span><span style="display: inline-block; width: 90px; text-align: right; font-weight: 500;">${
102
+ item.value === '' ? '-' : getFormattedValue(item.value)
103
+ }</span></div>`
104
+ )
105
+ .join('');
106
+ return `${param.name}<br />${valueLabels}`;
107
+ },
108
+ },
109
+ grid: {
110
+ left: '1%',
111
+ right: '4%',
112
+ bottom: '3%',
113
+ top: 45,
114
+ containLabel: true,
115
+ },
116
+ series: metricFields.map((metricField, index) => {
117
+ return {
118
+ type: chartType,
119
+ name: metricField.name,
120
+ symbol: 'circle',
121
+ showSymbol: resultList.length === 1,
122
+ smooth: true,
123
+ data: resultList.map((item: any) => {
124
+ const value = item[metricField.bizName];
125
+ return (metricField.dataFormatType === 'percent' ||
126
+ metricField.dataFormatType === 'decimal') &&
127
+ metricField.dataFormat?.needMultiply100
128
+ ? value * 100
129
+ : value;
130
+ }),
131
+ color: THEME_COLOR_LIST[index],
132
+ };
133
+ }),
134
+ });
135
+ instanceObj.resize();
136
+ };
137
+
138
+ const { downloadChartAsImage } = useExportByEcharts({
139
+ instanceRef,
140
+ question,
141
+ });
142
+
143
+ const { register } = useContext(ChartItemContext);
144
+
145
+ register('downloadChartAsImage', downloadChartAsImage);
146
+
147
+ useEffect(() => {
148
+ renderChart();
149
+ }, [resultList, chartType]);
150
+
151
+ useEffect(() => {
152
+ if (triggerResize && instanceRef.current) {
153
+ instanceRef.current.resize();
154
+ }
155
+ }, [triggerResize]);
156
+
157
+ const prefixCls = `${CLS_PREFIX}-metric-trend`;
158
+
159
+ return <div className={`${prefixCls}-flow-trend-chart`} ref={chartRef} />;
160
+ };
161
+
162
+ export default MultiMetricsTrendChart;