mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-18 00:07:21 +00:00
[feature](webapp) upgrade chat version
This commit is contained in:
@@ -19,6 +19,7 @@ type Props = {
|
||||
categoryColumnName: string;
|
||||
metricField: ColumnType;
|
||||
resultList: any[];
|
||||
triggerResize?: boolean;
|
||||
onApplyAuth?: (domain: string) => void;
|
||||
};
|
||||
|
||||
@@ -28,6 +29,7 @@ const MetricTrendChart: React.FC<Props> = ({
|
||||
categoryColumnName,
|
||||
metricField,
|
||||
resultList,
|
||||
triggerResize,
|
||||
onApplyAuth,
|
||||
}) => {
|
||||
const chartRef = useRef<any>();
|
||||
@@ -40,6 +42,7 @@ const MetricTrendChart: React.FC<Props> = ({
|
||||
setInstance(instanceObj);
|
||||
} else {
|
||||
instanceObj = instance;
|
||||
instanceObj.clear();
|
||||
}
|
||||
|
||||
const valueColumnName = metricField.nameEn;
|
||||
@@ -51,13 +54,13 @@ const MetricTrendChart: React.FC<Props> = ({
|
||||
endDate &&
|
||||
(dateColumnName.includes('date') || dateColumnName.includes('month'))
|
||||
? normalizeTrendData(
|
||||
groupDataValue[key],
|
||||
dateColumnName,
|
||||
valueColumnName,
|
||||
startDate,
|
||||
endDate,
|
||||
dateColumnName.includes('month') ? 'months' : 'days'
|
||||
)
|
||||
groupDataValue[key],
|
||||
dateColumnName,
|
||||
valueColumnName,
|
||||
startDate,
|
||||
endDate,
|
||||
dateColumnName.includes('month') ? 'months' : 'days'
|
||||
)
|
||||
: groupDataValue[key].reverse();
|
||||
return result;
|
||||
}, {});
|
||||
@@ -114,8 +117,8 @@ const MetricTrendChart: React.FC<Props> = ({
|
||||
return value === 0
|
||||
? 0
|
||||
: metricField.dataFormatType === 'percent'
|
||||
? `${formatByDecimalPlaces(value, metricField.dataFormat?.decimalPlaces || 2)}%`
|
||||
: getFormattedValue(value);
|
||||
? `${formatByDecimalPlaces(value, metricField.dataFormat?.decimalPlaces || 2)}%`
|
||||
: getFormattedValue(value);
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -135,11 +138,11 @@ const MetricTrendChart: React.FC<Props> = ({
|
||||
item.value === ''
|
||||
? '-'
|
||||
: metricField.dataFormatType === 'percent'
|
||||
? `${formatByDecimalPlaces(
|
||||
? `${formatByDecimalPlaces(
|
||||
item.value,
|
||||
metricField.dataFormat?.decimalPlaces || 2
|
||||
)}%`
|
||||
: getFormattedValue(item.value)
|
||||
: getFormattedValue(item.value)
|
||||
}</span></div>`
|
||||
)
|
||||
.join('');
|
||||
@@ -181,6 +184,12 @@ const MetricTrendChart: React.FC<Props> = ({
|
||||
}
|
||||
}, [resultList, metricField]);
|
||||
|
||||
useEffect(() => {
|
||||
if (triggerResize && instance) {
|
||||
instance.resize();
|
||||
}
|
||||
}, [triggerResize]);
|
||||
|
||||
const prefixCls = `${CLS_PREFIX}-metric-trend`;
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,30 +1,27 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { CLS_PREFIX, DATE_TYPES } from '../../../common/constants';
|
||||
import { ColumnType, MsgDataType } from '../../../common/type';
|
||||
import { groupByColumn, isMobile } from '../../../utils/utils';
|
||||
import { ColumnType, FieldType, MsgDataType } from '../../../common/type';
|
||||
import { isMobile } from '../../../utils/utils';
|
||||
import { queryData } from '../../../service';
|
||||
import MetricTrendChart from './MetricTrendChart';
|
||||
import classNames from 'classnames';
|
||||
import { Spin } from 'antd';
|
||||
import Table from '../Table';
|
||||
import SemanticInfoPopover from '../SemanticInfoPopover';
|
||||
|
||||
type Props = {
|
||||
data: MsgDataType;
|
||||
triggerResize?: boolean;
|
||||
onApplyAuth?: (domain: string) => void;
|
||||
onCheckMetricInfo?: (data: any) => void;
|
||||
};
|
||||
|
||||
const MetricTrend: React.FC<Props> = ({ data, onApplyAuth, onCheckMetricInfo }) => {
|
||||
const MetricTrend: React.FC<Props> = ({ data, triggerResize, onApplyAuth, onCheckMetricInfo }) => {
|
||||
const { queryColumns, queryResults, entityInfo, chatContext } = data;
|
||||
const [columns, setColumns] = useState<ColumnType[]>(queryColumns);
|
||||
const metricFields = columns.filter((column: any) => column.showType === 'NUMBER') || [];
|
||||
const currentMetricField = columns.find((column: any) => column.showType === 'NUMBER');
|
||||
|
||||
const [currentMetricField, setCurrentMetricField] = useState<ColumnType>(metricFields[0]);
|
||||
const [onlyOneDate, setOnlyOneDate] = useState(false);
|
||||
const [trendData, setTrendData] = useState(data);
|
||||
const [activeMetricField, setActiveMetricField] = useState<FieldType>(chatContext.metrics?.[0]);
|
||||
const [dataSource, setDataSource] = useState<any[]>(queryResults);
|
||||
const [mergeMetric, setMergeMetric] = useState(false);
|
||||
const [currentDateOption, setCurrentDateOption] = useState<number>();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
@@ -35,66 +32,17 @@ const MetricTrend: React.FC<Props> = ({ data, onApplyAuth, onCheckMetricInfo })
|
||||
const categoryColumnName =
|
||||
columns.find((column: any) => column.showType === 'CATEGORY')?.nameEn || '';
|
||||
|
||||
const getColumns = () => {
|
||||
const categoryFieldData = groupByColumn(dataSource, categoryColumnName);
|
||||
const result = [dateField];
|
||||
const columnsValue = Object.keys(categoryFieldData).map(item => ({
|
||||
authorized: currentMetricField.authorized,
|
||||
name: item !== 'undefined' ? item : currentMetricField.name,
|
||||
nameEn: `${item}${currentMetricField.name}`,
|
||||
showType: 'NUMBER',
|
||||
type: 'NUMBER',
|
||||
}));
|
||||
return result.concat(columnsValue);
|
||||
};
|
||||
|
||||
const getResultList = () => {
|
||||
return [
|
||||
{
|
||||
[dateField.nameEn]: dataSource[0][dateField.nameEn],
|
||||
...dataSource.reduce((result, item) => {
|
||||
result[`${item[categoryColumnName]}${currentMetricField.name}`] =
|
||||
item[currentMetricField.nameEn];
|
||||
return result;
|
||||
}, {}),
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setDataSource(queryResults);
|
||||
}, [queryResults]);
|
||||
|
||||
useEffect(() => {
|
||||
let onlyOneDateValue = false;
|
||||
let dataValue = trendData;
|
||||
if (dateColumnName && dataSource.length > 0) {
|
||||
const dateFieldData = groupByColumn(dataSource, dateColumnName);
|
||||
onlyOneDateValue =
|
||||
Object.keys(dateFieldData).length === 1 && Object.keys(dateFieldData)[0] !== undefined;
|
||||
if (onlyOneDateValue) {
|
||||
if (categoryColumnName !== '') {
|
||||
dataValue = {
|
||||
...trendData,
|
||||
queryColumns: getColumns(),
|
||||
queryResults: getResultList(),
|
||||
};
|
||||
} else {
|
||||
setMergeMetric(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
setOnlyOneDate(onlyOneDateValue);
|
||||
setTrendData(dataValue);
|
||||
}, [currentMetricField]);
|
||||
const dateOptions = DATE_TYPES[chatContext?.dateInfo?.period] || DATE_TYPES[0];
|
||||
|
||||
const dateOptions = DATE_TYPES[chatContext.dateInfo?.period] || DATE_TYPES[0];
|
||||
|
||||
const onLoadData = async (value: number) => {
|
||||
const onLoadData = async (value: any) => {
|
||||
setLoading(true);
|
||||
const { data } = await queryData({
|
||||
...chatContext,
|
||||
dateInfo: { ...chatContext.dateInfo, unit: value },
|
||||
...value,
|
||||
});
|
||||
setLoading(false);
|
||||
if (data.code === 200) {
|
||||
@@ -105,20 +53,21 @@ const MetricTrend: React.FC<Props> = ({ data, onApplyAuth, onCheckMetricInfo })
|
||||
|
||||
const selectDateOption = (dateOption: number) => {
|
||||
setCurrentDateOption(dateOption);
|
||||
// const { domainName, dimensions, metrics, aggType, filters } = chatContext || {};
|
||||
// const dimensionSection = dimensions?.join('、') || '';
|
||||
// const metricSection = metrics?.join('、') || '';
|
||||
// const aggregatorSection = aggType || '';
|
||||
// const filterSection = filters
|
||||
// .reduce((result, dimensionName) => {
|
||||
// result = result.concat(dimensionName);
|
||||
// return result;
|
||||
// }, [])
|
||||
// .join('、');
|
||||
onLoadData(dateOption);
|
||||
onLoadData({
|
||||
metrics: [activeMetricField],
|
||||
dateInfo: { ...chatContext?.dateInfo, unit: dateOption },
|
||||
});
|
||||
};
|
||||
|
||||
if (metricFields.length === 0) {
|
||||
const onSwitchMetric = (metricField: FieldType) => {
|
||||
setActiveMetricField(metricField);
|
||||
onLoadData({
|
||||
dateInfo: { ...chatContext.dateInfo, unit: currentDateOption || chatContext.dateInfo.unit },
|
||||
metrics: [metricField],
|
||||
});
|
||||
};
|
||||
|
||||
if (!currentMetricField) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -127,64 +76,66 @@ const MetricTrend: React.FC<Props> = ({ data, onApplyAuth, onCheckMetricInfo })
|
||||
return (
|
||||
<div className={prefixCls}>
|
||||
<div className={`${prefixCls}-charts`}>
|
||||
{!onlyOneDate && (
|
||||
<div className={`${prefixCls}-date-options`}>
|
||||
{dateOptions.map((dateOption: { label: string; value: number }, index: number) => {
|
||||
const dateOptionClass = classNames(`${prefixCls}-date-option`, {
|
||||
[`${prefixCls}-date-active`]: dateOption.value === currentDateOption,
|
||||
[`${prefixCls}-date-mobile`]: isMobile,
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
key={dateOption.value}
|
||||
className={dateOptionClass}
|
||||
onClick={() => {
|
||||
selectDateOption(dateOption.value);
|
||||
}}
|
||||
>
|
||||
{dateOption.label}
|
||||
{dateOption.value === currentDateOption && (
|
||||
<div className={`${prefixCls}-active-identifier`} />
|
||||
)}
|
||||
</div>
|
||||
{index !== dateOptions.length - 1 && (
|
||||
<div className={`${prefixCls}-date-option-divider`} />
|
||||
<div className={`${prefixCls}-date-options`}>
|
||||
{dateOptions.map((dateOption: { label: string; value: number }, index: number) => {
|
||||
const dateOptionClass = classNames(`${prefixCls}-date-option`, {
|
||||
[`${prefixCls}-date-active`]: dateOption.value === currentDateOption,
|
||||
[`${prefixCls}-date-mobile`]: isMobile,
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
key={dateOption.value}
|
||||
className={dateOptionClass}
|
||||
onClick={() => {
|
||||
selectDateOption(dateOption.value);
|
||||
}}
|
||||
>
|
||||
{dateOption.label}
|
||||
{dateOption.value === currentDateOption && (
|
||||
<div className={`${prefixCls}-active-identifier`} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
{metricFields.length > 1 && !mergeMetric && (
|
||||
</div>
|
||||
{index !== dateOptions.length - 1 && (
|
||||
<div className={`${prefixCls}-date-option-divider`} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{chatContext.metrics.length > 0 && (
|
||||
<div className={`${prefixCls}-metric-fields`}>
|
||||
{metricFields.map((metricField: ColumnType) => {
|
||||
{chatContext.metrics.map((metricField: FieldType) => {
|
||||
const metricFieldClass = classNames(`${prefixCls}-metric-field`, {
|
||||
[`${prefixCls}-metric-field-active`]:
|
||||
currentMetricField?.nameEn === metricField.nameEn,
|
||||
activeMetricField?.bizName === metricField.bizName &&
|
||||
chatContext.metrics.length > 1,
|
||||
[`${prefixCls}-metric-field-single`]: chatContext.metrics.length === 1,
|
||||
});
|
||||
return (
|
||||
<div
|
||||
className={metricFieldClass}
|
||||
key={metricField.nameEn}
|
||||
key={metricField.bizName}
|
||||
onClick={() => {
|
||||
setCurrentMetricField(metricField);
|
||||
if (chatContext.metrics.length > 1) {
|
||||
onSwitchMetric(metricField);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SemanticInfoPopover
|
||||
{/* <SemanticInfoPopover
|
||||
classId={chatContext.domainId}
|
||||
uniqueId={metricField.nameEn}
|
||||
uniqueId={metricField.bizName}
|
||||
onDetailBtnClick={onCheckMetricInfo}
|
||||
>
|
||||
{metricField.name}
|
||||
</SemanticInfoPopover>
|
||||
> */}
|
||||
{metricField.name}
|
||||
{/* </SemanticInfoPopover> */}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
{onlyOneDate ? (
|
||||
<Table data={trendData} onApplyAuth={onApplyAuth} />
|
||||
{dataSource?.length === 1 ? (
|
||||
<Table data={data} onApplyAuth={onApplyAuth} />
|
||||
) : (
|
||||
<Spin spinning={loading}>
|
||||
<MetricTrendChart
|
||||
@@ -193,6 +144,7 @@ const MetricTrend: React.FC<Props> = ({ data, onApplyAuth, onCheckMetricInfo })
|
||||
categoryColumnName={categoryColumnName}
|
||||
metricField={currentMetricField}
|
||||
resultList={dataSource}
|
||||
triggerResize={triggerResize}
|
||||
onApplyAuth={onApplyAuth}
|
||||
/>
|
||||
</Spin>
|
||||
|
||||
@@ -81,6 +81,17 @@
|
||||
background-color: var(--chat-blue);
|
||||
}
|
||||
|
||||
&-metric-field-single {
|
||||
padding-left: 0;
|
||||
font-weight: 500;
|
||||
cursor: default;
|
||||
color: var(--text-color-secondary);
|
||||
|
||||
&:hover {
|
||||
color: var(--text-color-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
&-date-options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user