[feature](webapp) merge query steps to one card

This commit is contained in:
williamhliu
2023-08-29 22:14:14 +08:00
parent 93ca060c45
commit 36fd737440
40 changed files with 994 additions and 496 deletions

View File

@@ -1,9 +1,11 @@
import React, { ReactNode } from 'react';
import { AGG_TYPE_MAP, PREFIX_CLS } from '../../common/constants';
import { ChatContextType } from '../../common/type';
import Text from './Text';
import Typing from './Typing';
import { CheckCircleFilled, InfoCircleOutlined } from '@ant-design/icons';
import classNames from 'classnames';
import SwicthEntity from './SwitchEntity';
import { Tooltip } from 'antd';
import Loading from './Loading';
type Props = {
parseLoading: boolean;
@@ -12,6 +14,7 @@ type Props = {
currentParseInfo?: ChatContextType;
optionMode?: boolean;
onSelectParseInfo: (parseInfo: ChatContextType) => void;
onSwitchEntity: (entityId: string) => void;
};
const MAX_OPTION_VALUES_COUNT = 2;
@@ -23,15 +26,34 @@ const ParseTip: React.FC<Props> = ({
currentParseInfo,
optionMode,
onSelectParseInfo,
onSwitchEntity,
}) => {
const prefixCls = `${PREFIX_CLS}-item`;
const getNode = (tipTitle: string, tipNode?: ReactNode, parseSucceed?: boolean) => {
const contentContainerClass = classNames(`${prefixCls}-content-container`, {
[`${prefixCls}-content-container-succeed`]: parseSucceed,
});
return (
<div className={`${prefixCls}-parse-tip`}>
<div className={`${prefixCls}-title-bar`}>
<CheckCircleFilled className={`${prefixCls}-step-icon`} />
<div className={`${prefixCls}-step-title`}>
{tipTitle}
{!tipNode && <Loading />}
</div>
</div>
{tipNode && <div className={contentContainerClass}>{tipNode}</div>}
</div>
);
};
if (parseLoading) {
return <Typing />;
return getNode('意图解析中');
}
if (parseTip) {
return <Text data={parseTip} />;
return getNode('意图解析失败', parseTip);
}
if (parseInfoOptions.length === 0) {
@@ -81,6 +103,45 @@ const ParseTip: React.FC<Props> = ({
const fields =
queryMode === 'ENTITY_DETAIL' ? dimensionItems?.concat(metrics || []) : dimensionItems;
const getFilterContent = (filters: any) => {
return (
<div className={`${prefixCls}-tip-item-filter-content`}>
{filters.map((filter: any, index: number) => (
<div className={itemValueClass}>
<span>
{filter.name}
{filter.operator !== '=' ? ` ${filter.operator} ` : ''}
</span>
<span>{Array.isArray(filter.value) ? filter.value.join('、') : filter.value}</span>
{index !== filters.length - 1 && <span></span>}
</div>
))}
</div>
);
};
const getFiltersNode = () => {
return (
<div className={`${prefixCls}-tip-item`}>
<div className={`${prefixCls}-tip-item-name`}></div>
<Tooltip
title={
dimensionFilters.length > MAX_OPTION_VALUES_COUNT
? getFilterContent(dimensionFilters)
: ''
}
color="#fff"
overlayStyle={{ maxWidth: 'none' }}
>
<div className={`${prefixCls}-tip-item-content`}>
{getFilterContent(dimensionFilters.slice(0, MAX_OPTION_VALUES_COUNT))}
{dimensionFilters.length > MAX_OPTION_VALUES_COUNT && ' ...'}
</div>
</Tooltip>
</div>
);
};
return (
<div
className={tipContentClass}
@@ -91,20 +152,28 @@ const ParseTip: React.FC<Props> = ({
}}
>
{index !== undefined && <div>{index + 1}.</div>}
{!!agentType ? (
{!!agentType && queryMode !== 'DSL' ? (
<div className={`${prefixCls}-tip-item`}>
{agentType === 'plugin' ? '插件' : '内置'}
<span className={itemValueClass}>{agentName}</span>
</div>
) : (
<>
{queryMode.includes('ENTITY') &&
{(queryMode.includes('ENTITY') || queryMode === 'DSL') &&
typeof entityId === 'string' &&
!!entityAlias &&
!!entityName ? (
<div className={`${prefixCls}-tip-item`}>
<div className={`${prefixCls}-tip-item-name`}>{entityAlias}</div>
<div className={itemValueClass}>{entityName}</div>
{!isOptions && (entityAlias === '歌曲' || entityAlias === '艺人') ? (
<SwicthEntity
entityName={entityName}
chatContext={parseInfo}
onSwitchEntity={onSwitchEntity}
/>
) : (
<div className={itemValueClass}>{entityName}</div>
)}
</div>
) : (
<div className={`${prefixCls}-tip-item`}>
@@ -112,7 +181,7 @@ const ParseTip: React.FC<Props> = ({
<div className={itemValueClass}>{modelName}</div>
</div>
)}
{metric && (
{queryMode !== 'ENTITY_ID' && metric && (
<div className={`${prefixCls}-tip-item`}>
<div className={`${prefixCls}-tip-item-name`}></div>
<div className={itemValueClass}>{metric.name}</div>
@@ -120,7 +189,7 @@ const ParseTip: React.FC<Props> = ({
)}
{!isOptions && (
<div className={`${prefixCls}-tip-item`}>
<div className={`${prefixCls}-tip-item-name`}></div>
<div className={`${prefixCls}-tip-item-name`}></div>
<div className={itemValueClass}>
{startDate === endDate ? startDate : `${startDate} ~ ${endDate}`}
</div>
@@ -148,23 +217,11 @@ const ParseTip: React.FC<Props> = ({
'ENTITY_DETAIL',
'ENTITY_LIST_FILTER',
'ENTITY_ID',
'DSL',
].includes(queryMode) &&
dimensionFilters &&
dimensionFilters?.length > 0 && (
<div className={`${prefixCls}-tip-item`}>
<div className={`${prefixCls}-tip-item-name`}></div>
{dimensionFilters.slice(0, MAX_OPTION_VALUES_COUNT).map((filter, index) => (
<div className={itemValueClass}>
<span>{filter.name}</span>
<span>
{Array.isArray(filter.value) ? filter.value.join('、') : filter.value}
</span>
{index !== dimensionFilters.length - 1 && <span></span>}
</div>
))}
{dimensionFilters.length > MAX_OPTION_VALUES_COUNT && '...'}
</div>
)}
dimensionFilters?.length > 0 &&
getFiltersNode()}
{queryMode === 'METRIC_ORDERBY' && aggType && aggType !== 'NONE' && (
<div className={`${prefixCls}-tip-item`}>
<div className={`${prefixCls}-tip-item-name`}></div>
@@ -191,16 +248,29 @@ const ParseTip: React.FC<Props> = ({
</div>
);
} else {
const agentType = parseInfoOptions[0]?.properties?.type;
const { type } = parseInfoOptions[0]?.properties || {};
const entityAlias = parseInfoOptions[0]?.entity?.alias?.[0]?.split('.')?.[0];
const entityName = parseInfoOptions[0]?.elementMatches?.find(
item => item.element?.type === 'ID'
)?.element.name;
const queryMode = parseInfoOptions[0]?.queryMode;
tipNode = (
<div className={`${prefixCls}-tip`}>
<div>{!!agentType ? '您的问题' : '您的问题解析为:'}</div>
{getTipNode(parseInfoOptions[0])}
{(!type || queryMode === 'DSL') && entityAlias && entityName && (
<div className={`${prefixCls}-switch-entity-tip`}>
<InfoCircleOutlined />
<div>
{entityAlias}{entityAlias}
</div>
</div>
)}
</div>
);
}
return <Text data={tipNode} />;
return getNode('意图解析结果', tipNode, true);
};
export default ParseTip;