mirror of
https://github.com/tencentmusic/supersonic.git
synced 2026-04-18 12:24:21 +08:00
(feature)(webapp) add display of time consumption at each stage (#331)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Button, Spin } from 'antd';
|
||||
import { CheckCircleFilled, ReloadOutlined } from '@ant-design/icons';
|
||||
import { Spin } from 'antd';
|
||||
import { CheckCircleFilled } from '@ant-design/icons';
|
||||
import { PREFIX_CLS } from '../../common/constants';
|
||||
import { MsgDataType } from '../../common/type';
|
||||
import ChatMsg from '../ChatMsg';
|
||||
@@ -17,7 +17,7 @@ type Props = {
|
||||
renderCustomExecuteNode?: boolean;
|
||||
data?: MsgDataType;
|
||||
triggerResize?: boolean;
|
||||
onRefresh: () => void;
|
||||
isDeveloper?: boolean;
|
||||
};
|
||||
|
||||
const ExecuteItem: React.FC<Props> = ({
|
||||
@@ -30,7 +30,7 @@ const ExecuteItem: React.FC<Props> = ({
|
||||
renderCustomExecuteNode,
|
||||
data,
|
||||
triggerResize,
|
||||
onRefresh,
|
||||
isDeveloper,
|
||||
}) => {
|
||||
const prefixCls = `${PREFIX_CLS}-item`;
|
||||
|
||||
@@ -49,19 +49,20 @@ const ExecuteItem: React.FC<Props> = ({
|
||||
);
|
||||
};
|
||||
|
||||
const reloadNode = (
|
||||
<Button className={`${prefixCls}-reload`} size="small" onClick={onRefresh}>
|
||||
<ReloadOutlined />
|
||||
重新查询
|
||||
</Button>
|
||||
);
|
||||
|
||||
if (executeLoading) {
|
||||
return getNodeTip('数据查询中');
|
||||
}
|
||||
|
||||
if (executeTip) {
|
||||
return getNodeTip(<>数据查询失败:{reloadNode}</>, executeTip);
|
||||
return getNodeTip(
|
||||
<>
|
||||
数据查询失败
|
||||
{data?.queryTimeCost && isDeveloper && (
|
||||
<span className={`${prefixCls}-title-tip`}>(耗时: {data.queryTimeCost}ms)</span>
|
||||
)}
|
||||
</>,
|
||||
executeTip
|
||||
);
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
@@ -73,8 +74,10 @@ const ExecuteItem: React.FC<Props> = ({
|
||||
<div className={`${prefixCls}-title-bar`}>
|
||||
<CheckCircleFilled className={`${prefixCls}-step-icon`} />
|
||||
<div className={`${prefixCls}-step-title`}>
|
||||
数据查询:
|
||||
{reloadNode}
|
||||
数据查询
|
||||
{data?.queryTimeCost && isDeveloper && (
|
||||
<span className={`${prefixCls}-title-tip`}>(耗时: {data.queryTimeCost}ms)</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${prefixCls}-content-container`}>
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import { Select, Spin, InputNumber } from 'antd';
|
||||
import { Select, Spin, InputNumber, DatePicker } from 'antd';
|
||||
import { PREFIX_CLS } from '../../common/constants';
|
||||
import { ChatContextType, FilterItemType } from '../../common/type';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { queryDimensionValues } from '../../service';
|
||||
import { debounce, isArray } from 'lodash';
|
||||
import SwicthEntity from './SwitchEntity';
|
||||
import moment from 'moment';
|
||||
|
||||
type Props = {
|
||||
modelId: number;
|
||||
filters: FilterItemType[];
|
||||
filter: FilterItemType;
|
||||
index: number;
|
||||
chatContext: ChatContextType;
|
||||
agentId?: number;
|
||||
entityAlias?: string;
|
||||
@@ -22,6 +24,7 @@ const FilterItem: React.FC<Props> = ({
|
||||
modelId,
|
||||
filters,
|
||||
filter,
|
||||
index,
|
||||
chatContext,
|
||||
agentId,
|
||||
entityAlias,
|
||||
@@ -44,7 +47,7 @@ const FilterItem: React.FC<Props> = ({
|
||||
''
|
||||
);
|
||||
setOptions(
|
||||
data?.resultList.map((item: any) => ({
|
||||
data?.resultList?.map((item: any) => ({
|
||||
label: item[filter.bizName],
|
||||
value: item[filter.bizName],
|
||||
})) || []
|
||||
@@ -87,8 +90,8 @@ const FilterItem: React.FC<Props> = ({
|
||||
}, [queryDimensionValues]);
|
||||
|
||||
const onOperatorChange = (value: string) => {
|
||||
const newFilters = filters.map(item => {
|
||||
if (item.bizName === filter.bizName) {
|
||||
const newFilters = filters.map((item, indexValue) => {
|
||||
if (item.bizName === filter.bizName && index === indexValue) {
|
||||
item.operator = value;
|
||||
}
|
||||
return item;
|
||||
@@ -97,8 +100,8 @@ const FilterItem: React.FC<Props> = ({
|
||||
};
|
||||
|
||||
const onChange = (value: string | string[] | number | null) => {
|
||||
const newFilters = filters.map(item => {
|
||||
if (item.bizName === filter.bizName) {
|
||||
const newFilters = filters.map((item, indexValue) => {
|
||||
if (item.bizName === filter.bizName && index === indexValue) {
|
||||
item.value =
|
||||
typeof filter.value === 'number' || filter.value === null
|
||||
? value
|
||||
@@ -123,28 +126,46 @@ const FilterItem: React.FC<Props> = ({
|
||||
onFiltersChange(newFilters);
|
||||
};
|
||||
|
||||
const onDateChange = (_: any, date: string) => {
|
||||
console.log('onDateChange', date);
|
||||
const newFilters = filters.map((item, indexValue) => {
|
||||
if (item.bizName === filter.bizName && index === indexValue) {
|
||||
item.value = date;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
onFiltersChange(newFilters);
|
||||
};
|
||||
|
||||
return (
|
||||
<span className={prefixCls}>
|
||||
<span className={`${prefixCls}-filter-name`}>{filter.name}:</span>
|
||||
{(typeof filter.value === 'number' || filter.value === null) &&
|
||||
!filter.bizName?.includes('_id') ? (
|
||||
<>
|
||||
{(typeof filter.value === 'number' ||
|
||||
filter.value === null ||
|
||||
(filter.operator && !['IN', '=', 'LIKE'].includes(filter.operator))) &&
|
||||
!filter.bizName?.includes('_id') && (
|
||||
<Select
|
||||
options={[
|
||||
{ label: '大于等于', value: '>=' },
|
||||
{ label: '大于', value: '>' },
|
||||
{ label: '等于', value: '=' },
|
||||
{ label: '小于等于', value: '<=' },
|
||||
{ label: '小于', value: '<' },
|
||||
]}
|
||||
className={`${prefixCls}-operator-control`}
|
||||
value={filter.operator}
|
||||
onChange={onOperatorChange}
|
||||
/>
|
||||
<InputNumber
|
||||
className={`${prefixCls}-input-number-control`}
|
||||
value={filter.value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{(typeof filter.value === 'number' || filter.value === null) &&
|
||||
!filter.bizName?.includes('_id') ? (
|
||||
<InputNumber
|
||||
className={`${prefixCls}-input-number-control`}
|
||||
value={filter.value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
) : typeof filter.value === 'string' && moment(filter.value, 'YYYY-MM-DD').isValid() ? (
|
||||
<DatePicker value={moment(filter.value)} onChange={onDateChange} allowClear={false} />
|
||||
) : (typeof filter.value === 'string' || isArray(filter.value)) &&
|
||||
!filter.bizName?.includes('_id') ? (
|
||||
<Select
|
||||
@@ -173,7 +194,9 @@ const FilterItem: React.FC<Props> = ({
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<span className={`${prefixCls}-filter-value`}>{filter.value}</span>
|
||||
<span className={`${prefixCls}-filter-value`}>
|
||||
{typeof filter.value !== 'object' ? filter.value : ''}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
import { AGG_TYPE_MAP, PREFIX_CLS } from '../../common/constants';
|
||||
import { ChatContextType, DateInfoType, EntityInfoType, FilterItemType } from '../../common/type';
|
||||
import { DatePicker } from 'antd';
|
||||
import { CheckCircleFilled } from '@ant-design/icons';
|
||||
import { Button, DatePicker } from 'antd';
|
||||
import { CheckCircleFilled, ReloadOutlined } from '@ant-design/icons';
|
||||
import Loading from './Loading';
|
||||
import FilterItem from './FilterItem';
|
||||
import moment from 'moment';
|
||||
@@ -21,10 +21,13 @@ type Props = {
|
||||
dateInfo: DateInfoType;
|
||||
entityInfo: EntityInfoType;
|
||||
integrateSystem?: string;
|
||||
parseTimeCost?: number;
|
||||
isDeveloper?: boolean;
|
||||
onSelectParseInfo: (parseInfo: ChatContextType) => void;
|
||||
onSwitchEntity: (entityId: string) => void;
|
||||
onFiltersChange: (filters: FilterItemType[]) => void;
|
||||
onDateInfoChange: (dateRange: any) => void;
|
||||
onRefresh: () => void;
|
||||
};
|
||||
|
||||
const MAX_OPTION_VALUES_COUNT = 2;
|
||||
@@ -39,10 +42,13 @@ const ParseTip: React.FC<Props> = ({
|
||||
dateInfo,
|
||||
entityInfo,
|
||||
integrateSystem,
|
||||
parseTimeCost,
|
||||
isDeveloper,
|
||||
onSelectParseInfo,
|
||||
onSwitchEntity,
|
||||
onFiltersChange,
|
||||
onDateInfoChange,
|
||||
onRefresh,
|
||||
}) => {
|
||||
const prefixCls = `${PREFIX_CLS}-item`;
|
||||
|
||||
@@ -66,7 +72,15 @@ const ParseTip: React.FC<Props> = ({
|
||||
}
|
||||
|
||||
if (parseTip) {
|
||||
return getNode('意图解析失败', parseTip);
|
||||
return getNode(
|
||||
<>
|
||||
意图解析失败
|
||||
{parseTimeCost && isDeveloper && (
|
||||
<span className={`${prefixCls}-title-tip`}>(耗时: {parseTimeCost}ms)</span>
|
||||
)}
|
||||
</>,
|
||||
parseTip
|
||||
);
|
||||
}
|
||||
|
||||
if (parseInfoOptions.length === 0) {
|
||||
@@ -218,18 +232,19 @@ const ParseTip: React.FC<Props> = ({
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{filters?.map((filter: any) => (
|
||||
{filters?.map((filter: any, index: number) => (
|
||||
<FilterItem
|
||||
modelId={modelId!}
|
||||
filters={dimensionFilters}
|
||||
filter={filter}
|
||||
index={index}
|
||||
chatContext={currentParseInfo!}
|
||||
entityAlias={entityAlias}
|
||||
agentId={agentId}
|
||||
integrateSystem={integrateSystem}
|
||||
onFiltersChange={onFiltersChange}
|
||||
onSwitchEntity={onSwitchEntity}
|
||||
key={filter.name}
|
||||
key={`${filter.name}_${index}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -238,23 +253,39 @@ const ParseTip: React.FC<Props> = ({
|
||||
|
||||
const getFiltersNode = () => {
|
||||
return (
|
||||
<div className={`${prefixCls}-tip-item`}>
|
||||
<div className={`${prefixCls}-tip-item-name`}>筛选条件:</div>
|
||||
<div className={`${prefixCls}-tip-item-content`}>{getFilterContent(dimensionFilters)}</div>
|
||||
</div>
|
||||
<>
|
||||
<div className={`${prefixCls}-tip-item`}>
|
||||
<div className={`${prefixCls}-tip-item-name`}>筛选条件:</div>
|
||||
<div className={`${prefixCls}-tip-item-content`}>
|
||||
{getFilterContent(dimensionFilters)}
|
||||
</div>
|
||||
</div>
|
||||
<Button className={`${prefixCls}-reload`} size="small" onClick={onRefresh}>
|
||||
<ReloadOutlined />
|
||||
重新查询
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const { type: agentType } = properties || {};
|
||||
|
||||
const tipNode = (
|
||||
<div className={`${prefixCls}-tip`}>
|
||||
{getTipNode()}
|
||||
{getFiltersNode()}
|
||||
{!(!!agentType && queryMode !== 'LLM_S2QL') && getFiltersNode()}
|
||||
</div>
|
||||
);
|
||||
|
||||
return getNode(
|
||||
<div className={`${prefixCls}-title-bar`}>
|
||||
<div>意图解析{parseInfoOptions?.length > 1 ? ':' : ''}</div>
|
||||
<div>
|
||||
意图解析
|
||||
{parseTimeCost && isDeveloper && (
|
||||
<span className={`${prefixCls}-title-tip`}>(耗时: {parseTimeCost}ms)</span>
|
||||
)}
|
||||
{parseInfoOptions?.length > 1 ? ':' : ''}
|
||||
</div>
|
||||
{parseInfoOptions?.length > 1 && (
|
||||
<div className={`${prefixCls}-content-options`}>
|
||||
{parseInfoOptions.map((parseInfo, index) => (
|
||||
|
||||
@@ -11,9 +11,10 @@ import { SqlInfoType } from '../../common/type';
|
||||
type Props = {
|
||||
integrateSystem?: string;
|
||||
sqlInfo: SqlInfoType;
|
||||
sqlTimeCost?: number;
|
||||
};
|
||||
|
||||
const SqlItem: React.FC<Props> = ({ integrateSystem, sqlInfo }) => {
|
||||
const SqlItem: React.FC<Props> = ({ integrateSystem, sqlInfo, sqlTimeCost }) => {
|
||||
const [sqlType, setSqlType] = useState('');
|
||||
|
||||
const tipPrefixCls = `${PREFIX_CLS}-item`;
|
||||
@@ -36,7 +37,11 @@ const SqlItem: React.FC<Props> = ({ integrateSystem, sqlInfo }) => {
|
||||
<div className={`${tipPrefixCls}-title-bar`}>
|
||||
<CheckCircleFilled className={`${tipPrefixCls}-step-icon`} />
|
||||
<div className={`${tipPrefixCls}-step-title`}>
|
||||
SQL生成:
|
||||
SQL生成
|
||||
{sqlTimeCost && (
|
||||
<span className={`${tipPrefixCls}-title-tip`}>(耗时: {sqlTimeCost}ms)</span>
|
||||
)}
|
||||
:
|
||||
{sqlType && (
|
||||
<span className={`${prefixCls}-toggle-expand-btn`} onClick={onCollapse}>
|
||||
<UpOutlined />
|
||||
@@ -53,7 +58,7 @@ const SqlItem: React.FC<Props> = ({ integrateSystem, sqlInfo }) => {
|
||||
setSqlType(sqlType === 's2QL' ? '' : 's2QL');
|
||||
}}
|
||||
>
|
||||
S2QL
|
||||
解析S2QL
|
||||
</div>
|
||||
)}
|
||||
{sqlInfo.logicSql && (
|
||||
@@ -65,7 +70,7 @@ const SqlItem: React.FC<Props> = ({ integrateSystem, sqlInfo }) => {
|
||||
setSqlType(sqlType === 'logicSql' ? '' : 'logicSql');
|
||||
}}
|
||||
>
|
||||
逻辑SQL
|
||||
修正S2QL
|
||||
</div>
|
||||
)}
|
||||
{sqlInfo.querySql && (
|
||||
@@ -77,7 +82,7 @@ const SqlItem: React.FC<Props> = ({ integrateSystem, sqlInfo }) => {
|
||||
setSqlType(sqlType === 'querySql' ? '' : 'querySql');
|
||||
}}
|
||||
>
|
||||
物理SQL
|
||||
执行SQL
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -91,7 +96,7 @@ const SqlItem: React.FC<Props> = ({ integrateSystem, sqlInfo }) => {
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{sqlType && (
|
||||
{sqlType && sqlInfo[sqlType] && (
|
||||
<>
|
||||
<SyntaxHighlighter
|
||||
className={`${prefixCls}-code`}
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
FilterItemType,
|
||||
MsgDataType,
|
||||
ParseStateEnum,
|
||||
ParseTimeCostType,
|
||||
SimilarQuestionType,
|
||||
} from '../../common/type';
|
||||
import { useEffect, useState } from 'react';
|
||||
@@ -27,8 +28,8 @@ type Props = {
|
||||
agentId?: number;
|
||||
score?: number;
|
||||
filter?: any[];
|
||||
isLastMessage?: boolean;
|
||||
parseInfos?: ChatContextType[];
|
||||
parseTimeCostValue?: ParseTimeCostType;
|
||||
msgData?: MsgDataType;
|
||||
triggerResize?: boolean;
|
||||
isDeveloper?: boolean;
|
||||
@@ -47,9 +48,9 @@ const ChatItem: React.FC<Props> = ({
|
||||
agentId,
|
||||
score,
|
||||
filter,
|
||||
isLastMessage,
|
||||
triggerResize,
|
||||
parseInfos,
|
||||
parseTimeCostValue,
|
||||
msgData,
|
||||
isDeveloper,
|
||||
integrateSystem,
|
||||
@@ -61,6 +62,7 @@ const ChatItem: React.FC<Props> = ({
|
||||
}) => {
|
||||
const [data, setData] = useState<MsgDataType>();
|
||||
const [parseLoading, setParseLoading] = useState(false);
|
||||
const [parseTimeCost, setParseTimeCost] = useState<ParseTimeCostType>();
|
||||
const [parseInfo, setParseInfo] = useState<ChatContextType>();
|
||||
const [parseInfoOptions, setParseInfoOptions] = useState<ChatContextType[]>([]);
|
||||
const [parseTip, setParseTip] = useState('');
|
||||
@@ -97,24 +99,50 @@ const ChatItem: React.FC<Props> = ({
|
||||
return true;
|
||||
};
|
||||
|
||||
const onExecute = async (parseInfoValue: ChatContextType) => {
|
||||
const onExecute = async (
|
||||
parseInfoValue: ChatContextType,
|
||||
parseInfos?: ChatContextType[],
|
||||
isSwitchParseInfo?: boolean
|
||||
) => {
|
||||
setExecuteMode(true);
|
||||
setExecuteLoading(true);
|
||||
if (isSwitchParseInfo) {
|
||||
setEntitySwitchLoading(true);
|
||||
} else {
|
||||
setExecuteLoading(true);
|
||||
}
|
||||
try {
|
||||
const res: any = await chatExecute(msg, conversationId!, parseInfoValue);
|
||||
setExecuteLoading(false);
|
||||
const valid = updateData(res);
|
||||
onMsgDataLoaded?.(
|
||||
{
|
||||
...res.data,
|
||||
chatContext: parseInfoValue,
|
||||
parseInfos,
|
||||
queryId: parseInfoValue.queryId,
|
||||
},
|
||||
valid
|
||||
);
|
||||
} catch (e) {
|
||||
setExecuteLoading(false);
|
||||
setExecuteTip(SEARCH_EXCEPTION_TIP);
|
||||
}
|
||||
if (isSwitchParseInfo) {
|
||||
setEntitySwitchLoading(false);
|
||||
} else {
|
||||
setExecuteLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const updateDimensionFitlers = (filters: FilterItemType[]) => {
|
||||
setDimensionFilters(
|
||||
filters.sort((a, b) => {
|
||||
if (a.name < b.name) {
|
||||
return -1;
|
||||
}
|
||||
if (a.name > b.name) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const sendMsg = async () => {
|
||||
@@ -122,7 +150,7 @@ const ChatItem: React.FC<Props> = ({
|
||||
const parseData: any = await chatParse(msg, conversationId, modelId, agentId, filter);
|
||||
setParseLoading(false);
|
||||
const { code, data } = parseData || {};
|
||||
const { state, selectedParses, candidateParses, queryId } = data || {};
|
||||
const { state, selectedParses, candidateParses, queryId, parseTimeCost } = data || {};
|
||||
if (
|
||||
code !== 200 ||
|
||||
state === ParseStateEnum.FAILED ||
|
||||
@@ -143,10 +171,11 @@ const ChatItem: React.FC<Props> = ({
|
||||
setParseInfoOptions(parseInfos || []);
|
||||
const parseInfoValue = parseInfos[0];
|
||||
setParseInfo(parseInfoValue);
|
||||
setParseTimeCost(parseTimeCost);
|
||||
setEntityInfo(parseInfoValue.entityInfo || {});
|
||||
setDimensionFilters(parseInfoValue?.dimensionFilters || []);
|
||||
updateDimensionFitlers(parseInfoValue?.dimensionFilters || []);
|
||||
setDateInfo(parseInfoValue?.dateInfo);
|
||||
onExecute(parseInfoValue);
|
||||
onExecute(parseInfoValue, parseInfos);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -161,7 +190,8 @@ const ChatItem: React.FC<Props> = ({
|
||||
const parseInfoValue = parseInfoOptionsValue[0];
|
||||
setParseInfoOptions(parseInfoOptionsValue);
|
||||
setParseInfo(parseInfoValue);
|
||||
setDimensionFilters(parseInfoValue.dimensionFilters || []);
|
||||
setParseTimeCost(parseTimeCostValue);
|
||||
updateDimensionFitlers(parseInfoValue.dimensionFilters || []);
|
||||
setDateInfo(parseInfoValue.dateInfo);
|
||||
setExecuteMode(true);
|
||||
updateData({ code: 200, data: msgData, msg: 'success' });
|
||||
@@ -179,7 +209,7 @@ const ChatItem: React.FC<Props> = ({
|
||||
const chatContextValue = { ...(chatContext || {}), queryId: parseInfo?.queryId };
|
||||
setParseInfo(chatContextValue);
|
||||
setEntityInfo(entityInfo);
|
||||
setDimensionFilters(chatContextValue?.dimensionFilters || []);
|
||||
updateDimensionFitlers(chatContextValue?.dimensionFilters || []);
|
||||
setDateInfo(chatContextValue?.dateInfo);
|
||||
};
|
||||
|
||||
@@ -213,7 +243,12 @@ const ChatItem: React.FC<Props> = ({
|
||||
if (res.code === 200) {
|
||||
const resChatContext = res.data?.chatContext;
|
||||
const contextValue = { ...(resChatContext || chatContextValue), queryId };
|
||||
const dataValue = { ...res.data, chatContext: contextValue };
|
||||
const dataValue = {
|
||||
...res.data,
|
||||
chatContext: contextValue,
|
||||
parseInfos: parseInfoOptions,
|
||||
queryId,
|
||||
};
|
||||
onMsgDataLoaded?.(dataValue, true, true);
|
||||
setData(dataValue);
|
||||
setParseInfo(contextValue);
|
||||
@@ -227,13 +262,14 @@ const ChatItem: React.FC<Props> = ({
|
||||
|
||||
const onSelectParseInfo = async (parseInfoValue: ChatContextType) => {
|
||||
setParseInfo(parseInfoValue);
|
||||
setDimensionFilters(parseInfoValue.dimensionFilters || []);
|
||||
updateDimensionFitlers(parseInfoValue.dimensionFilters || []);
|
||||
setDateInfo(parseInfoValue.dateInfo);
|
||||
if (parseInfoValue.entityInfo) {
|
||||
setEntityInfo(parseInfoValue.entityInfo);
|
||||
} else {
|
||||
getEntityInfo(parseInfoValue);
|
||||
}
|
||||
onExecute(parseInfoValue, parseInfoOptions, true);
|
||||
};
|
||||
|
||||
const onSelectQuestion = (question: SimilarQuestionType) => {
|
||||
@@ -261,15 +297,22 @@ const ChatItem: React.FC<Props> = ({
|
||||
dateInfo={dateInfo}
|
||||
entityInfo={entityInfo}
|
||||
integrateSystem={integrateSystem}
|
||||
parseTimeCost={parseTimeCost?.parseTime}
|
||||
isDeveloper={isDeveloper}
|
||||
onSelectParseInfo={onSelectParseInfo}
|
||||
onSwitchEntity={onSwitchEntity}
|
||||
onFiltersChange={onFiltersChange}
|
||||
onDateInfoChange={onDateInfoChange}
|
||||
onRefresh={onRefresh}
|
||||
/>
|
||||
{executeMode && (
|
||||
<>
|
||||
{!isMobile && parseInfo?.sqlInfo && isDeveloper && integrateSystem !== 'c2' && (
|
||||
<SqlItem integrateSystem={integrateSystem} sqlInfo={parseInfo.sqlInfo} />
|
||||
<SqlItem
|
||||
integrateSystem={integrateSystem}
|
||||
sqlInfo={parseInfo.sqlInfo}
|
||||
sqlTimeCost={parseTimeCost?.sqlTime}
|
||||
/>
|
||||
)}
|
||||
<ExecuteItem
|
||||
queryId={parseInfo?.queryId}
|
||||
@@ -280,8 +323,8 @@ const ChatItem: React.FC<Props> = ({
|
||||
data={data}
|
||||
triggerResize={triggerResize}
|
||||
executeItemNode={executeItemNode}
|
||||
isDeveloper={isDeveloper}
|
||||
renderCustomExecuteNode={renderCustomExecuteNode}
|
||||
onRefresh={onRefresh}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@@ -294,11 +337,9 @@ const ChatItem: React.FC<Props> = ({
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{(parseTip !== '' || (executeMode && !executeLoading)) &&
|
||||
integrateSystem !== 'c2' &&
|
||||
integrateSystem !== 'showcase' && (
|
||||
<Tools queryId={parseInfo?.queryId || 0} scoreValue={score} />
|
||||
)}
|
||||
{(parseTip !== '' || (executeMode && !executeLoading)) && integrateSystem !== 'c2' && (
|
||||
<Tools queryId={parseInfo?.queryId || 0} scoreValue={score} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -133,6 +133,12 @@
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
&-title-tip {
|
||||
margin-left: 2px;
|
||||
color: var(--text-color-third);
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
&-step-title {
|
||||
font-weight: 500;
|
||||
color: var(--text-color);
|
||||
@@ -140,6 +146,7 @@
|
||||
|
||||
&-reload {
|
||||
margin-left: 2px;
|
||||
width: fit-content;
|
||||
font-weight: normal;
|
||||
color: var(--text-color-secondary);
|
||||
font-size: 13px !important;
|
||||
|
||||
@@ -36,7 +36,9 @@ const BarChart: React.FC<Props> = ({ data, triggerResize, loading, onApplyAuth }
|
||||
const data = (queryResults || []).sort(
|
||||
(a: any, b: any) => b[metricColumnName] - a[metricColumnName]
|
||||
);
|
||||
const xData = data.map(item => item[categoryColumnName]);
|
||||
const xData = data.map(item =>
|
||||
item[categoryColumnName] !== undefined ? item[categoryColumnName] : '未知'
|
||||
);
|
||||
instanceObj.setOption({
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
|
||||
@@ -52,7 +52,9 @@ const MetricCard: React.FC<Props> = ({ data, loading, onApplyAuth }) => {
|
||||
) : (
|
||||
<div style={{ display: 'flex', alignItems: 'flex-end' }}>
|
||||
<div className={`${prefixCls}-indicator-value`}>
|
||||
{dataFormatType === 'percent' || dataFormatType === 'decimal'
|
||||
{typeof value === 'string' && isNaN(+value)
|
||||
? value
|
||||
: dataFormatType === 'percent' || dataFormatType === 'decimal'
|
||||
? `${formatByDecimalPlaces(
|
||||
dataFormat?.needMultiply100 ? +value * 100 : value,
|
||||
dataFormat?.decimalPlaces || 2
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { formatByDecimalPlaces, getFormattedValue } from '../../../utils/utils';
|
||||
import { formatByDecimalPlaces, getFormattedValue, isMobile } from '../../../utils/utils';
|
||||
import { Table as AntTable } from 'antd';
|
||||
import { MsgDataType } from '../../../common/type';
|
||||
import { CLS_PREFIX } from '../../../common/constants';
|
||||
@@ -70,7 +70,13 @@ const Table: React.FC<Props> = ({ data, size, onApplyAuth }) => {
|
||||
<div className={prefixCls}>
|
||||
<AntTable
|
||||
pagination={
|
||||
queryResults.length <= 10 ? false : { defaultPageSize: 10, position: ['bottomCenter'] }
|
||||
queryResults.length <= 10
|
||||
? false
|
||||
: {
|
||||
defaultPageSize: 10,
|
||||
position: ['bottomCenter'],
|
||||
size: isMobile ? 'small' : 'default',
|
||||
}
|
||||
}
|
||||
columns={tableColumns}
|
||||
dataSource={dataSource}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { PREFIX_CLS } from '../../common/constants';
|
||||
import Text from './Text';
|
||||
import DrillDownDimensions from '../DrillDownDimensions';
|
||||
import MetricOptions from '../MetricOptions';
|
||||
import { isMobile } from '../../utils/utils';
|
||||
|
||||
type Props = {
|
||||
queryId?: number;
|
||||
@@ -115,7 +116,11 @@ const ChatMsg: React.FC<Props> = ({ queryId, data, chartIndex, triggerResize })
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (categoryField?.length > 0 && metricFields?.length > 0) {
|
||||
if (
|
||||
categoryField?.length > 0 &&
|
||||
metricFields?.length > 0 &&
|
||||
(isMobile ? dataSource?.length <= 20 : dataSource?.length <= 50)
|
||||
) {
|
||||
return (
|
||||
<Bar
|
||||
data={{ ...data, queryColumns: columns, queryResults: dataSource }}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createFromIconfontCN } from '@ant-design/icons';
|
||||
|
||||
const IconFont = createFromIconfontCN({
|
||||
scriptUrl: '//at.alicdn.com/t/c/font_4120566_2vn019wsui6.js',
|
||||
scriptUrl: '//at.alicdn.com/t/c/font_4120566_x6akuij1kod.js',
|
||||
});
|
||||
|
||||
export default IconFont;
|
||||
|
||||
Reference in New Issue
Block a user