import React, { ReactNode } from 'react'; import { AGG_TYPE_MAP, PREFIX_CLS } from '../../common/constants'; import { ChatContextType, DateInfoType, EntityInfoType, FilterItemType } from '../../common/type'; import { Button, DatePicker } from 'antd'; import { CheckCircleFilled, ReloadOutlined } from '@ant-design/icons'; import Loading from './Loading'; import FilterItem from './FilterItem'; import moment from 'moment'; import classNames from 'classnames'; import { isMobile } from '../../utils/utils'; const { RangePicker } = DatePicker; type Props = { parseLoading: boolean; parseInfoOptions: ChatContextType[]; parseTip: string; currentParseInfo?: ChatContextType; agentId?: number; dimensionFilters: FilterItemType[]; 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; const ParseTip: React.FC = ({ parseLoading, parseInfoOptions, parseTip, currentParseInfo, agentId, dimensionFilters, dateInfo, entityInfo, integrateSystem, parseTimeCost, isDeveloper, onSelectParseInfo, onSwitchEntity, onFiltersChange, onDateInfoChange, onRefresh, }) => { const prefixCls = `${PREFIX_CLS}-item`; const getNode = (tipTitle: ReactNode, tipNode?: ReactNode, parseSucceed?: boolean) => { return (
{tipTitle} {!tipNode && }
{tipNode &&
{tipNode}
}
); }; if (parseLoading) { return getNode('意图解析中'); } if (parseTip) { return getNode( <> 意图解析失败 {parseTimeCost && isDeveloper && ( (耗时: {parseTimeCost}ms) )} , parseTip ); } if (parseInfoOptions.length === 0) { return null; } const { modelId, modelName, dimensions, metrics, aggType, queryMode, properties, entity, elementMatches, nativeQuery, } = currentParseInfo || {}; const entityAlias = entity?.alias?.[0]?.split('.')?.[0]; const entityDimensions = entityInfo?.dimensions?.filter( item => !['zyqk_song_id', 'song_name', 'singer_id', 'zyqk_cmpny_id'].includes(item.bizName) && !( entityInfo?.dimensions?.some(dimension => dimension.bizName === 'singer_id') && item.bizName === 'singer_name' ) && !( entityInfo?.dimensions?.some(dimension => dimension.bizName === 'zyqk_cmpny_id') && item.bizName === 'cmpny_name' ) ); const getTipNode = () => { const dimensionItems = dimensions?.filter(item => item.type === 'DIMENSION'); const itemValueClass = `${prefixCls}-tip-item-value`; const entityId = dimensionFilters?.length > 0 ? dimensionFilters[0].value : undefined; const entityAlias = entity?.alias?.[0]?.split('.')?.[0]; const entityName = elementMatches?.find(item => item.element?.type === 'ID')?.element.name; const { type: agentType, name: agentName } = properties || {}; const fields = queryMode === 'ENTITY_DETAIL' ? dimensionItems?.concat(metrics || []) : dimensionItems; return (
{!!agentType && queryMode !== 'LLM_S2QL' ? (
将由{agentType === 'plugin' ? '插件' : '内置'}工具 {agentName}来解答
) : ( <> {(queryMode?.includes('ENTITY') || queryMode === 'LLM_S2QL') && typeof entityId === 'string' && !!entityAlias && !!entityName ? (
{entityAlias}:
{entityName}
) : (
数据模型:
{modelName}
)} {!queryMode?.includes('ENTITY') && metrics && metrics.length > 0 && !dimensions?.some(item => item.bizName?.includes('_id')) && (
指标:
{metrics.map(metric => metric.name).join('、')}
)} {['METRIC_GROUPBY', 'METRIC_ORDERBY', 'ENTITY_DETAIL', 'LLM_S2QL'].includes( queryMode! ) && fields && fields.length > 0 && (
{queryMode === 'LLM_S2QL' ? nativeQuery ? '查询字段' : '下钻维度' : queryMode === 'ENTITY_DETAIL' ? '查询字段' : '下钻维度'} :
{fields .slice(0, MAX_OPTION_VALUES_COUNT) .map(field => field.name) .join('、')} {fields.length > MAX_OPTION_VALUES_COUNT && '...'}
)} {queryMode !== 'ENTITY_ID' && !dimensions?.some(item => item.bizName?.includes('_id')) && entityDimensions ?.filter(dimension => dimension.value != null) .map(dimension => (
{dimension.name}:
{dimension.value}
))} {(queryMode === 'METRIC_ORDERBY' || queryMode === 'METRIC_MODEL') && aggType && aggType !== 'NONE' && (
聚合方式:
{AGG_TYPE_MAP[aggType]}
)} )}
); }; const getFilterContent = (filters: any) => { const itemValueClass = `${prefixCls}-tip-item-value`; const { startDate, endDate } = dateInfo || {}; const tipItemOptionClass = classNames(`${prefixCls}-tip-item-option`, { [`${prefixCls}-mobile-tip-item-option`]: isMobile, }); return (
数据时间: {nativeQuery ? ( {startDate === endDate ? startDate : `${startDate} ~ ${endDate}`} ) : ( trigger.parentNode as HTMLElement} allowClear={false} /> )}
{filters?.map((filter: any, index: number) => ( ))}
); }; const getFiltersNode = () => { return ( <>
筛选条件:
{getFilterContent(dimensionFilters)}
); }; const { type: agentType } = properties || {}; const tipNode = (
{getTipNode()} {!(!!agentType && queryMode !== 'LLM_S2QL') && getFiltersNode()}
); return getNode(
意图解析 {parseTimeCost && isDeveloper && ( (耗时: {parseTimeCost}ms) )} {parseInfoOptions?.length > 1 ? ':' : ''}
{parseInfoOptions?.length > 1 && (
{parseInfoOptions.map((parseInfo, index) => (
{ onSelectParseInfo(parseInfo); }} key={parseInfo.id} > 解析{index + 1}
))}
)}
, tipNode, true ); }; export default ParseTip;