diff --git a/launchers/standalone/src/main/java/com/tencent/supersonic/ConfigureDemo.java b/launchers/standalone/src/main/java/com/tencent/supersonic/ConfigureDemo.java index 247576710..ec1ac0eb9 100644 --- a/launchers/standalone/src/main/java/com/tencent/supersonic/ConfigureDemo.java +++ b/launchers/standalone/src/main/java/com/tencent/supersonic/ConfigureDemo.java @@ -200,7 +200,7 @@ public class ConfigureDemo implements ApplicationListener AgentConfig agentConfig = new AgentConfig(); RuleQueryTool ruleQueryTool = new RuleQueryTool(); ruleQueryTool.setType(AgentToolType.RULE); - ruleQueryTool.setModelIds(Lists.newArrayList(1L, 2L)); + ruleQueryTool.setModelIds(Lists.newArrayList(-1L)); ruleQueryTool.setQueryModes(Lists.newArrayList( "ENTITY_DETAIL", "ENTITY_LIST_FILTER", "ENTITY_ID", "METRIC_ENTITY", "METRIC_FILTER", "METRIC_GROUPBY", "METRIC_MODEL", "METRIC_ORDERBY" diff --git a/webapp/packages/chat-sdk/package.json b/webapp/packages/chat-sdk/package.json index 614b9f771..410c9740a 100644 --- a/webapp/packages/chat-sdk/package.json +++ b/webapp/packages/chat-sdk/package.json @@ -1,6 +1,6 @@ { "name": "supersonic-chat-sdk", - "version": "0.4.32", + "version": "0.5.28", "main": "dist/index.es.js", "module": "dist/index.es.js", "unpkg": "dist/index.umd.js", @@ -192,4 +192,4 @@ "engines": { "node": ">=14.18.0" } -} +} \ No newline at end of file diff --git a/webapp/packages/chat-sdk/src/common/type.ts b/webapp/packages/chat-sdk/src/common/type.ts index f46716b71..dfdc8d109 100644 --- a/webapp/packages/chat-sdk/src/common/type.ts +++ b/webapp/packages/chat-sdk/src/common/type.ts @@ -62,6 +62,13 @@ export type ModelType = { useCnt: number; } +export type EntityDimensionType = { + bizName: string; + itemId: number; + name: string; + value: string; +} + export type ChatContextType = { id: number; queryId: number; @@ -73,6 +80,7 @@ export type ChatContextType = { dimensions: FieldType[]; metrics: FieldType[]; entity: { alias: string[], id: number }; + entityInfo: { dimensions: EntityDimensionType[] }; elementMatches: any[]; queryMode: string; dimensionFilters: FilterItemType[]; @@ -137,6 +145,7 @@ export type ParseDataType = { } export type QueryDataType = { + chatContext: ChatContextType; aggregateInfo: AggregateInfoType; queryColumns: ColumnType[]; queryResults: any[]; diff --git a/webapp/packages/chat-sdk/src/components/ChatItem/ExecuteItem.tsx b/webapp/packages/chat-sdk/src/components/ChatItem/ExecuteItem.tsx index 93865b1d3..02eed4ac5 100644 --- a/webapp/packages/chat-sdk/src/components/ChatItem/ExecuteItem.tsx +++ b/webapp/packages/chat-sdk/src/components/ChatItem/ExecuteItem.tsx @@ -7,29 +7,23 @@ import WebPage from '../ChatMsg/WebPage'; import Loading from './Loading'; type Props = { - question: string; queryId?: number; executeLoading: boolean; entitySwitchLoading: boolean; chartIndex: number; executeTip?: string; data?: MsgDataType; - isMobileMode?: boolean; triggerResize?: boolean; - onChangeChart: () => void; }; const ExecuteItem: React.FC = ({ - question, queryId, executeLoading, entitySwitchLoading, chartIndex, executeTip, data, - isMobileMode, triggerResize, - onChangeChart, }) => { const prefixCls = `${PREFIX_CLS}-item`; @@ -71,13 +65,7 @@ const ExecuteItem: React.FC = ({ {data?.queryMode === 'WEB_PAGE' ? ( ) : ( - + )} diff --git a/webapp/packages/chat-sdk/src/components/ChatItem/FilterItem.tsx b/webapp/packages/chat-sdk/src/components/ChatItem/FilterItem.tsx new file mode 100644 index 000000000..82dd36435 --- /dev/null +++ b/webapp/packages/chat-sdk/src/components/ChatItem/FilterItem.tsx @@ -0,0 +1,94 @@ +import { Select, Spin } from 'antd'; +import { PREFIX_CLS } from '../../common/constants'; +import { FilterItemType } from '../../common/type'; +import { useEffect, useMemo, useRef, useState } from 'react'; +import { queryDimensionValues } from '../../service'; +import debounce from 'lodash/debounce'; + +type Props = { + modelId: number; + filters: FilterItemType[]; + filter: FilterItemType; + onFiltersChange: (filters: FilterItemType[]) => void; +}; + +const FilterItem: React.FC = ({ modelId, filters, filter, onFiltersChange }) => { + const [options, setOptions] = useState<{ label: string; value: string }[]>([]); + const [loading, setLoading] = useState(false); + const fetchRef = useRef(0); + + const prefixCls = `${PREFIX_CLS}-filter-item`; + + const initData = async () => { + const { data } = await queryDimensionValues(modelId, filter.bizName, ''); + setOptions( + data?.data?.resultList.map((item: any) => ({ + label: item[filter.bizName], + value: item[filter.bizName], + })) || [] + ); + }; + + useEffect(() => { + if (typeof filter.value === 'string' && options.length === 0) { + initData(); + } + }, []); + + const debounceFetcher = useMemo(() => { + const loadOptions = (value: string) => { + fetchRef.current += 1; + const fetchId = fetchRef.current; + setOptions([]); + setLoading(true); + + queryDimensionValues(modelId, filter.bizName, value).then(newOptions => { + if (fetchId !== fetchRef.current) { + return; + } + + setOptions( + newOptions.data?.data?.resultList.map((item: any) => ({ + label: item[filter.bizName], + value: item[filter.bizName], + })) || [] + ); + setLoading(false); + }); + }; + + return debounce(loadOptions, 800); + }, [queryDimensionValues]); + + const onChange = (value: string) => { + const newFilters = filters.map(item => { + if (item.bizName === filter.bizName) { + item.value = `${value}`; + } + return item; + }); + onFiltersChange(newFilters); + }; + + return ( + + {typeof filter.value === 'string' ? ( + + {(toolType === AgentToolTypeEnum.RULE || toolType === AgentToolTypeEnum.DSL) && ( + + ({ label: model.name, value: model.id }))} - placeholder="请选择主题域" - mode="multiple" - /> - - -
- {examples.map((example) => { - const { id, question } = example; - return ( -
- { - example.question = e.target.value; - setExamples([...examples]); - }} - allowClear - /> - { - setExamples(examples.filter((item) => item.id !== id)); - }} - /> -
- ); - })} - -
-
- + +
+ {examples.map((example) => { + const { id, question } = example; + return ( +
+ { + example.question = e.target.value; + setExamples([...examples]); + }} + allowClear + /> + { + setExamples(examples.filter((item) => item.id !== id)); + }} + /> +
+ ); + })} + +
+
)} {toolType === AgentToolTypeEnum.INTERPRET && ( <> diff --git a/webapp/packages/supersonic-fe/src/pages/Agent/type.ts b/webapp/packages/supersonic-fe/src/pages/Agent/type.ts index 1f4464313..3e12fa0ef 100644 --- a/webapp/packages/supersonic-fe/src/pages/Agent/type.ts +++ b/webapp/packages/supersonic-fe/src/pages/Agent/type.ts @@ -24,19 +24,19 @@ export enum QueryModeEnum { export const AGENT_TOOL_TYPE_LIST = [ { - label: '规则', + label: '规则语义解析', value: AgentToolTypeEnum.RULE }, { - label: 'LLM语义解析', + label: '大模型语义解析', value: AgentToolTypeEnum.DSL }, { - label: '指标解读', + label: '大模型指标解读', value: AgentToolTypeEnum.INTERPRET }, { - label: '插件', + label: '第三方插件', value: AgentToolTypeEnum.PLUGIN }, ] diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/AgentList/index.tsx b/webapp/packages/supersonic-fe/src/pages/Chat/AgentList/index.tsx new file mode 100644 index 000000000..263d9361a --- /dev/null +++ b/webapp/packages/supersonic-fe/src/pages/Chat/AgentList/index.tsx @@ -0,0 +1,66 @@ +import { PlusCircleOutlined } from '@ant-design/icons'; +import { AgentType } from '../type'; +import styles from './style.less'; +import classNames from 'classnames'; +import { message } from 'antd'; +import IconFont from '@/components/IconFont'; + +const agents = [ + 'icon-fukuanbaobiaochaxun', + 'icon-hangweifenxi1', + 'icon-xiaofeifenxi', + 'icon-renwuchaxun', + 'icon-liushuichaxun', + 'icon-baobiao', + 'icon-cangkuchaxun', + 'icon-xiaoshoushuju', + 'icon-tongji', + 'icon-shujutongji', + 'icon-mendiankanban', +]; + +type Props = { + agentList: AgentType[]; + currentAgent?: AgentType; + onSelectAgent: (agent: AgentType) => void; +}; + +const AgentList: React.FC = ({ agentList, currentAgent, onSelectAgent }) => { + const onAddAgent = () => { + message.info('正在开发中,敬请期待'); + }; + + return ( +
+
+
智能助理
+ +
+
+ {agentList.map((agent, index) => { + const agentItemClass = classNames(styles.agentItem, { + [styles.active]: currentAgent?.id === agent.id, + }); + return ( +
{ + onSelectAgent(agent); + }} + > + {/* avatar */} + +
+
{agent.name}
+
{agent.description}
+
+
+ ); + })} +
+
+ ); +}; + +export default AgentList; diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/AgentList/style.less b/webapp/packages/supersonic-fe/src/pages/Chat/AgentList/style.less new file mode 100644 index 000000000..e2df0d7ac --- /dev/null +++ b/webapp/packages/supersonic-fe/src/pages/Chat/AgentList/style.less @@ -0,0 +1,78 @@ +.agentList { + width: 248px; + height: 100%; + background: #f9f9f9; + border-right: 1px solid #f1f1f1; + + .header { + display: flex; + align-items: center; + justify-content: space-between; + height: 50px; + padding: 0 16px; + + .headerTitle { + color: var(--text-color); + font-weight: 500; + font-size: 15px; + } + + .plusIcon { + color: var(--text-color); + font-size: 15px; + cursor: pointer; + + &:hover { + color: var(--chat-blue); + } + } + } + + .agentListContent { + display: flex; + flex-direction: column; + padding: 4px 8px; + row-gap: 2px; + + .agentItem { + display: flex; + align-items: center; + padding: 8px 4px; + column-gap: 8px; + border-radius: 8px; + cursor: pointer; + + &:hover, + &.active { + background: #f0f0f0; + } + + .avatar { + // width: 40px; + // height: 40px; + // border-radius: 8px; + font-size: 40px; + } + + .agentInfo { + display: flex; + flex-direction: column; + row-gap: 2px; + + .agentName { + color: #000; + font-size: 14px; + } + + .agentDesc { + width: 160px; + overflow: hidden; + color: var(--text-color-fourth); + font-size: 12px; + white-space: nowrap; + text-overflow: ellipsis; + } + } + } + } +} diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/ChatFooter/index.tsx b/webapp/packages/supersonic-fe/src/pages/Chat/ChatFooter/index.tsx index 015b23553..54336a2ac 100644 --- a/webapp/packages/supersonic-fe/src/pages/Chat/ChatFooter/index.tsx +++ b/webapp/packages/supersonic-fe/src/pages/Chat/ChatFooter/index.tsx @@ -1,6 +1,6 @@ import IconFont from '@/components/IconFont'; import { getTextWidth, groupByColumn, isMobile } from '@/utils/utils'; -import { AutoComplete, Select, Tag, Tooltip } from 'antd'; +import { AutoComplete, Select, Tag } from 'antd'; import classNames from 'classnames'; import { debounce } from 'lodash'; import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'; @@ -8,25 +8,17 @@ import type { ForwardRefRenderFunction } from 'react'; import { searchRecommend } from 'supersonic-chat-sdk'; import { SemanticTypeEnum, SEMANTIC_TYPE_MAP } from '../constants'; import styles from './style.less'; -import { DefaultEntityType, AgentType, ModelType } from '../type'; -import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons'; +import { AgentType, ModelType } from '../type'; type Props = { inputMsg: string; chatId?: number; - currentModel?: ModelType; currentAgent?: AgentType; - defaultEntity?: DefaultEntityType; - isCopilotMode?: boolean; - copilotFullscreen?: boolean; - models: ModelType[]; agentList: AgentType[]; - collapsed: boolean; - onToggleCollapseBtn: () => void; + onToggleHistoryVisible: () => void; onInputMsgChange: (value: string) => void; onSendMsg: (msg: string, modelId?: number) => void; - onAddConversation: () => void; - onCancelDefaultFilter: () => void; + onAddConversation: (agent?: AgentType) => void; onSelectAgent: (agent: AgentType) => void; }; @@ -46,19 +38,12 @@ const ChatFooter: ForwardRefRenderFunction = ( { inputMsg, chatId, - currentModel, currentAgent, - defaultEntity, - models, agentList, - collapsed, - isCopilotMode, - copilotFullscreen, - onToggleCollapseBtn, + onToggleHistoryVisible, onInputMsgChange, onSendMsg, onAddConversation, - onCancelDefaultFilter, onSelectAgent, }, ref, @@ -119,14 +104,10 @@ const ChatFooter: ForwardRefRenderFunction = ( : data; }; - const processMsg = (msg: string, models: ModelType[]) => { + const processMsg = (msg: string) => { let msgValue = msg; let modelId: number | undefined; - if (msg?.[0] === '@') { - const model = models.find((item) => msg.includes(`@${item.name}`)); - msgValue = model ? msg.replace(`@${model.name}`, '') : msg; - modelId = model?.id; - } else if (msg?.[0] === '/') { + if (msg?.[0] === '/') { const agent = agentList.find((item) => msg.includes(`/${item.name}`)); msgValue = agent ? msg.replace(`/${agent.name}`, '') : msg; } @@ -134,12 +115,7 @@ const ChatFooter: ForwardRefRenderFunction = ( }; const debounceGetWordsFunc = useCallback(() => { - const getAssociateWords = async ( - msg: string, - models: ModelType[], - chatId?: number, - model?: ModelType, - ) => { + const getAssociateWords = async (msg: string, chatId?: number, currentAgent?: AgentType) => { if (isPinyin) { return; } @@ -148,9 +124,8 @@ const ChatFooter: ForwardRefRenderFunction = ( } fetchRef.current += 1; const fetchId = fetchRef.current; - const { msgValue, modelId } = processMsg(msg, models); - const modelIdValue = modelId || model?.id; - const res = await searchRecommend(msgValue.trim(), chatId, modelIdValue); + const { msgValue, modelId } = processMsg(msg); + const res = await searchRecommend(msgValue.trim(), chatId, modelId, currentAgent?.id); if (fetchId !== fetchRef.current) { return; } @@ -171,9 +146,9 @@ const ChatFooter: ForwardRefRenderFunction = ( const [debounceGetWords] = useState(debounceGetWordsFunc); useEffect(() => { - if (inputMsg.length === 1 && (inputMsg[0] === '@' || inputMsg[0] === '/')) { + if (inputMsg.length === 1 && inputMsg[0] === '/') { setOpen(true); - setModelOptions(inputMsg[0] === '/' ? agentList : models); + setModelOptions(agentList); setStepOptions({}); return; } else { @@ -184,8 +159,8 @@ const ChatFooter: ForwardRefRenderFunction = ( }, 50); } } - if (!isSelect && currentAgent?.name !== '问知识') { - debounceGetWords(inputMsg, models, chatId, currentModel); + if (!isSelect) { + debounceGetWords(inputMsg, chatId, currentAgent); } else { isSelect = false; } @@ -248,7 +223,9 @@ const ChatFooter: ForwardRefRenderFunction = ( } else { const agent = agentList.find((item) => value.includes(item.name)); if (agent) { - onSelectAgent(agent); + if (agent.id !== currentAgent?.id) { + onSelectAgent(agent); + } onInputMsgChange(''); } } @@ -260,40 +237,11 @@ const ChatFooter: ForwardRefRenderFunction = ( const chatFooterClass = classNames(styles.chatFooter, { [styles.mobile]: isMobile, - [styles.defaultCopilotMode]: isCopilotMode && !copilotFullscreen, }); - const restrictNode = currentModel && !isMobile && ( -
-
- 输入联想与问题回复将限定于:“ - - {!defaultEntity && <>主题域【{currentModel.name}】} - {defaultEntity && ( - <> - {`${currentModel.name.slice(0, currentModel.name.length - 1)}【`} - - {defaultEntity.entityName} - - - - )} - - ” -
-
- 取消限定 -
-
- ); - const modelOptionNodes = modelOptions.map((model) => { return ( - ); @@ -307,10 +255,7 @@ const ChatFooter: ForwardRefRenderFunction = ( Object.keys(stepOptions).length === 1 ? option.recommend : `${option.modelName || ''}${option.recommend}`; - if (inputMsg[0] === '@') { - const model = models.find((item) => inputMsg.includes(item.name)); - optionValue = model ? `@${model.name} ${option.recommend}` : optionValue; - } else if (inputMsg[0] === '/') { + if (inputMsg[0] === '/') { const agent = agentList.find((item) => inputMsg.includes(item.name)); optionValue = agent ? `/${agent.name} ${option.recommend}` : optionValue; } @@ -349,31 +294,34 @@ const ChatFooter: ForwardRefRenderFunction = ( return (
-
+
+
{ + onAddConversation(); + }} + > + +
新对话
+
{!isMobile && ( -
- {collapsed ? : } +
+ +
历史对话
)} - - - +
+
- {/* {restrictNode} - {currentAgentNode} */} { + onInputMsgChange(value); + }} onSelect={onSelect} autoFocus={!isMobile} backfill @@ -389,7 +337,9 @@ const ChatFooter: ForwardRefRenderFunction = ( } else { const agent = agentList.find((item) => chatInputEl.value.includes(item.name)); if (agent) { - onSelectAgent(agent); + if (agent.id !== currentAgent?.id) { + onSelectAgent(agent); + } onInputMsgChange(''); } } diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/ChatFooter/style.less b/webapp/packages/supersonic-fe/src/pages/Chat/ChatFooter/style.less index 47af8f8c5..8fde53180 100644 --- a/webapp/packages/supersonic-fe/src/pages/Chat/ChatFooter/style.less +++ b/webapp/packages/supersonic-fe/src/pages/Chat/ChatFooter/style.less @@ -3,17 +3,34 @@ z-index: 10; display: flex; flex-direction: column; - margin-top: 6px; - margin-right: 20px; - margin-bottom: 40px; + margin: 6px 20px 20px; - &.defaultCopilotMode { - margin-bottom: 30px; + .tools { + display: flex; + align-items: center; + margin-bottom: 6px; + column-gap: 8px; + + .toolItem { + display: flex; + align-items: center; + padding: 2px 6px; + color: var(--text-color-secondary); + font-size: 12px; + column-gap: 6px; + background-color: #f6f6f6; + border-radius: 6px; + cursor: pointer; + + &:hover { + background-color: #f1f1f1; + } + } } .composer { display: flex; - height: 46px; + height: 70px; .collapseBtn { height: 46px; @@ -45,50 +62,6 @@ position: relative; flex: 1; - .currentModel { - position: absolute; - top: -30px; - left: 15px; - display: flex; - align-items: center; - width: calc(100% - 30px); - height: 30px; - padding: 0 12px; - overflow-x: auto; - color: var(--text-color-third); - white-space: nowrap; - background: #f4f6f5; - border-top-left-radius: 6px; - border-top-right-radius: 6px; - - .currentModelName { - margin-right: 12px; - font-size: 14px; - - .entityName { - display: inline-block; - max-width: 100px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - vertical-align: top; - } - } - - .cancelModel { - padding: 0 6px; - font-size: 13px; - border: 1px solid var(--text-color-fourth); - border-radius: 4px; - cursor: pointer; - - &:hover { - color: var(--text-color-fourth); - border-color: var(--text-color-fifth); - } - } - } - .composerInput { width: 100%; height: 100%; @@ -98,18 +71,17 @@ height: 100%; overflow: hidden; color: rgba(0, 0, 0, 0.87); - font-size: 16px; + font-size: 14px; word-break: break-all; - background: #fff; + background: #f9f9f9; border: 0; - border-radius: 24px; - box-shadow: rgba(0, 0, 0, 0.07) 0px -0.5px 0px, rgba(0, 0, 0, 0.1) 0px 0px 18px; + border-radius: 8px; transition: border-color 0.15s ease-in-out; resize: none; .ant-select-selection-search-input { - height: 100% !important; - padding: 0 20px; + height: 40px !important; + padding: 0 16px; } .ant-select-selection-search { @@ -118,8 +90,8 @@ } .ant-select-selection-placeholder { - padding-left: 10px !important; - line-height: 45px; + padding-left: 6px; + line-height: 40px; } } @@ -146,8 +118,8 @@ .sendBtn { position: absolute; - top: 50%; - right: 6px; + right: 10px; + bottom: 10px; display: flex; align-items: center; justify-content: center; @@ -158,7 +130,6 @@ background-color: rgb(184, 184, 191); border: unset; border-radius: 50%; - transform: translateY(-50%); transition: background-color 0.3s ease 0s; &.sendBtnActive { @@ -167,9 +138,7 @@ } &.mobile { - height: 40px; - margin: 12px; - margin-bottom: 20px; + margin: 6px 10px 10px; .addConversation { height: 40px; @@ -178,17 +147,26 @@ .composer { height: 40px; - :global { .ant-select-selector { font-size: 14px !important; } + .ant-select-selection-search-input { + padding: 0 10px !important; + } + .ant-select-selection-placeholder { - line-height: 39px !important; + padding-left: 0 !important; + line-height: 38px !important; } } } + + .sendBtn { + right: 4px; + bottom: 6px; + } } } diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/Conversation.tsx b/webapp/packages/supersonic-fe/src/pages/Chat/Conversation/index.tsx similarity index 64% rename from webapp/packages/supersonic-fe/src/pages/Chat/Conversation.tsx rename to webapp/packages/supersonic-fe/src/pages/Chat/Conversation/index.tsx index c3b73f3de..20e88d1c5 100644 --- a/webapp/packages/supersonic-fe/src/pages/Chat/Conversation.tsx +++ b/webapp/packages/supersonic-fe/src/pages/Chat/Conversation/index.tsx @@ -1,4 +1,3 @@ -import IconFont from '@/components/IconFont'; import { Dropdown, Input, Menu } from 'antd'; import classNames from 'classnames'; import { @@ -9,19 +8,20 @@ import { useImperativeHandle, } from 'react'; import { useLocation } from 'umi'; -import ConversationModal from './components/ConversationModal'; -import { deleteConversation, getAllConversations, saveConversation } from './service'; +import ConversationModal from '../components/ConversationModal'; +import { deleteConversation, getAllConversations, saveConversation } from '../service'; import styles from './style.less'; -import { ConversationDetailType, DefaultEntityType } from './type'; -import { DEFAULT_CONVERSATION_NAME } from './constants'; +import { AgentType, ConversationDetailType, DefaultEntityType } from '../type'; +import { DEFAULT_CONVERSATION_NAME } from '../constants'; import moment from 'moment'; -import { SearchOutlined } from '@ant-design/icons'; +import { CloseOutlined, DeleteOutlined, SearchOutlined } from '@ant-design/icons'; type Props = { + agentList?: AgentType[]; + currentAgent?: AgentType; currentConversation?: ConversationDetailType; - collapsed?: boolean; + historyVisible?: boolean; isCopilotMode?: boolean; - defaultModelName?: string; defaultEntityFilter?: DefaultEntityType; triggerNewConversation?: boolean; onNewConversationTriggered?: () => void; @@ -30,19 +30,23 @@ type Props = { name?: string, modelId?: number, entityId?: string, + agent?: AgentType, ) => void; + onCloseConversation: () => void; }; const Conversation: ForwardRefRenderFunction = ( { + agentList, + currentAgent, currentConversation, - collapsed, + historyVisible, isCopilotMode, - defaultModelName, defaultEntityFilter, triggerNewConversation, onNewConversationTriggered, onSelectConversation, + onCloseConversation, }, ref, ) => { @@ -58,24 +62,20 @@ const Conversation: ForwardRefRenderFunction = ( onAddConversation, })); - const updateData = async () => { - const { data } = await getAllConversations(); + const updateData = async (agent?: AgentType) => { + const { data } = await getAllConversations(agent?.id || currentAgent?.id); const conversationList = data || []; - setConversations(conversationList.slice(0, 500)); + setConversations(conversationList.slice(0, 200)); return conversationList; }; const initData = async () => { const data = await updateData(); if (data.length > 0) { - const chatId = localStorage.getItem('CONVERSATION_ID') || cid; + const chatId = cid; if (chatId) { const conversation = data.find((item: any) => item.chatId === +chatId); - if (conversation) { - onSelectConversation(conversation); - } else { - onSelectConversation(data[0]); - } + onSelectConversation(conversation || data[0]); } else { onSelectConversation(data[0]); } @@ -84,36 +84,30 @@ const Conversation: ForwardRefRenderFunction = ( } }; - useEffect(() => { - if (triggerNewConversation) { - const conversationName = - defaultEntityFilter?.entityName && window.location.pathname.includes('detail') - ? defaultEntityFilter.entityName - : defaultModelName; - onAddConversation({ - name: conversationName, - type: 'CUSTOMIZE', - modelId: defaultEntityFilter?.modelId, - entityId: defaultEntityFilter?.entityId, - }); - onNewConversationTriggered?.(); - } - }, [triggerNewConversation]); + // useEffect(() => { + // if (triggerNewConversation) { + // return; + // } + // if (q && cid === undefined && window.location.href.includes('/chat')) { + // onAddConversation({ + // name: q, + // modelId: modelId ? +modelId : undefined, + // entityId, + // }); + // } else { + // initData(); + // } + // }, [q]); useEffect(() => { - if (triggerNewConversation) { - return; - } - if (q && cid === undefined && window.location.href.includes('/workbench/chat')) { - onAddConversation({ name: q, modelId: modelId ? +modelId : undefined, entityId }); - } else { + if (currentAgent && !triggerNewConversation) { initData(); } - }, [q]); + }, [currentAgent]); - const addConversation = async (name?: string) => { - await saveConversation(name || DEFAULT_CONVERSATION_NAME); - return updateData(); + const addConversation = async (name?: string, agent?: AgentType) => { + await saveConversation(name || DEFAULT_CONVERSATION_NAME, agent?.id || currentAgent!.id); + return updateData(agent); }; const onDeleteConversation = async (id: number) => { @@ -126,14 +120,24 @@ const Conversation: ForwardRefRenderFunction = ( modelId, entityId, type, + agent, }: { name?: string; modelId?: number; entityId?: string; type?: string; + agent?: AgentType; } = {}) => { - const data = await addConversation(name); - onSelectConversation(data[0], type || name, modelId, entityId); + const data = await addConversation(name, agent); + if (data.length > 0) { + onSelectConversation( + data[0], + type || name || DEFAULT_CONVERSATION_NAME, + modelId, + entityId, + agent, + ); + } }; const onOperate = (key: string, conversation: ConversationDetailType) => { @@ -146,7 +150,7 @@ const Conversation: ForwardRefRenderFunction = ( }; const conversationClass = classNames(styles.conversation, { - [styles.collapsed]: collapsed, + [styles.historyVisible]: historyVisible, [styles.copilotMode]: isCopilotMode, }); @@ -171,7 +175,21 @@ const Conversation: ForwardRefRenderFunction = ( return (
-
+
+
+
历史对话
+
+
{ + addConversation(); + }} + > + 新对话 +
+ +
+
= ( onSelectConversation(item); }} > -
-
{item.chatName}
+
+
{item.chatName}
+ {currentConversation?.chatId === item.chatId && ( +
当前对话
+ )} +
{convertTime(item.lastTime || '')}
-
{item.lastQuestion}
+
+
{item.lastQuestion}
+ { + e.stopPropagation(); + onDeleteConversation(item.chatId); + }} + /> +
diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/Conversation/style.less b/webapp/packages/supersonic-fe/src/pages/Chat/Conversation/style.less new file mode 100644 index 000000000..90c7a267e --- /dev/null +++ b/webapp/packages/supersonic-fe/src/pages/Chat/Conversation/style.less @@ -0,0 +1,176 @@ +.conversation { + position: relative; + width: 0; + height: 100%; + background: #fff; + + .rightSection { + width: 100%; + height: 100%; + + .titleBar { + display: flex; + align-items: center; + justify-content: space-between; + + .title { + color: var(--text-color); + font-weight: 500; + font-size: 15px; + } + + .rightOperation { + display: flex; + align-items: center; + column-gap: 12px; + + .newConversation { + color: var(--text-color); + font-size: 14px; + cursor: pointer; + + &:hover { + color: var(--chat-blue); + } + } + + .closeIcon { + color: var(--text-color); + font-size: 16px; + cursor: pointer; + + &:hover { + color: var(--chat-blue); + } + } + } + } + + .searchConversation { + display: flex; + align-items: center; + padding: 12px 0 10px; + + .searchIcon { + color: #999 !important; + } + + .searchTask { + font-size: 13px; + background-color: #f5f5f5; + border: 0; + border-radius: 4px; + box-shadow: none !important; + + :global { + .ant-input { + font-size: 13px !important; + background-color: transparent !important; + } + } + } + } + + .conversationList { + display: flex; + flex-direction: column; + height: calc(100% - 70px); + padding: 2px 0 0; + overflow-y: auto; + row-gap: 12px; + + .conversationItem { + display: flex; + align-items: center; + padding: 8px 12px; + border: 1px solid #efefef; + border-radius: 8px; + cursor: pointer; + + .conversationContent { + width: 100%; + + .topTitleBar { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + + .conversationTitleBar { + display: flex; + align-items: center; + column-gap: 6px; + + .conversationName { + max-width: 300px; + margin-right: 2px; + overflow: hidden; + color: var(--text-color); + font-weight: 500; + font-size: 14px; + white-space: nowrap; + text-overflow: ellipsis; + } + + .currentConversation { + padding: 0 4px; + color: var(--chat-blue); + font-size: 12px; + background-color: var(--light-blue-background); + border-radius: 4px; + } + } + + .conversationTime { + color: var(--text-color-six); + font-size: 12px; + } + } + + .bottomSection { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 4px; + + .subTitle { + width: 350px; + overflow: hidden; + color: var(--text-color-six); + font-size: 12px; + white-space: nowrap; + text-overflow: ellipsis; + } + + .deleteIcon { + color: var(--text-color-six); + font-size: 14px; + cursor: pointer; + + &:hover { + color: var(--chat-blue); + } + } + } + } + + &:hover, + &.activeConversationItem { + background-color: #f0f0f0; + } + } + } + } + + &.historyVisible { + width: 400px; + padding: 10px 16px; + border-left: 1px solid #f1f1f1; + } + + &.copilotMode { + &.collapsed { + width: 0 !important; + } + } +} diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/MessageContainer.tsx b/webapp/packages/supersonic-fe/src/pages/Chat/MessageContainer/index.tsx similarity index 71% rename from webapp/packages/supersonic-fe/src/pages/Chat/MessageContainer.tsx rename to webapp/packages/supersonic-fe/src/pages/Chat/MessageContainer/index.tsx index e5bd6c914..9906dfc3b 100644 --- a/webapp/packages/supersonic-fe/src/pages/Chat/MessageContainer.tsx +++ b/webapp/packages/supersonic-fe/src/pages/Chat/MessageContainer/index.tsx @@ -1,49 +1,41 @@ -import Text from './components/Text'; +import Text from '../components/Text'; import { memo, useCallback, useEffect, useState } from 'react'; import { isEqual } from 'lodash'; import { ChatItem } from 'supersonic-chat-sdk'; import type { MsgDataType } from 'supersonic-chat-sdk'; -import { AgentType, MessageItem, MessageTypeEnum } from './type'; -import { updateMessageContainerScroll } from '@/utils/utils'; +import { AgentType, MessageItem, MessageTypeEnum } from '../type'; +import { isMobile, updateMessageContainerScroll } from '@/utils/utils'; import styles from './style.less'; -import { MODEL_MODEL_ENTITY_ID_FILTER_MAP } from './constants'; -import AgentList from './components/AgentList'; -import RecommendQuestions from './components/RecommendQuestions'; +import { MODEL_MODEL_ENTITY_ID_FILTER_MAP } from '../constants'; +import AgentTip from '../components/AgentTip'; +import classNames from 'classnames'; type Props = { id: string; chatId: number; messageList: MessageItem[]; - isMobileMode?: boolean; - conversationCollapsed: boolean; - copilotFullscreen?: boolean; - agentList: AgentType[]; - onClickMessageContainer: () => void; + historyVisible: boolean; + currentAgent?: AgentType; + chatVisible?: boolean; onMsgDataLoaded: ( data: MsgDataType, questionId: string | number, question: string, valid: boolean, ) => void; - onCheckMore: (data: MsgDataType) => void; onApplyAuth: (model: string) => void; onSendMsg: (value: string) => void; - onSelectAgent: (agent: AgentType) => void; }; const MessageContainer: React.FC = ({ id, chatId, messageList, - isMobileMode, - conversationCollapsed, - copilotFullscreen, - agentList, - onClickMessageContainer, + historyVisible, + currentAgent, + chatVisible, onMsgDataLoaded, - onCheckMore, onSendMsg, - onSelectAgent, }) => { const [triggerResize, setTriggerResize] = useState(false); @@ -63,12 +55,7 @@ const MessageContainer: React.FC = ({ useEffect(() => { onResize(); - }, [conversationCollapsed]); - - useEffect(() => { - onResize(); - updateMessageContainerScroll(); - }, [copilotFullscreen]); + }, [historyVisible, chatVisible]); const getFilters = (modelId?: number, entityId?: string) => { if (!modelId || !entityId) { @@ -82,8 +69,10 @@ const MessageContainer: React.FC = ({ ]; }; + const messageContainerClass = classNames(styles.messageContainer, { [styles.mobile]: isMobile }); + return ( -
+
{messageList.map((msgItem: MessageItem, index: number) => { const { @@ -104,16 +93,8 @@ const MessageContainer: React.FC = ({ return (
{type === MessageTypeEnum.TEXT && } - {type === MessageTypeEnum.RECOMMEND_QUESTIONS && ( - - )} {type === MessageTypeEnum.AGENT_LIST && ( - + )} {type === MessageTypeEnum.QUESTION && ( <> @@ -127,7 +108,6 @@ const MessageContainer: React.FC = ({ agentId={agentId} filter={getFilters(modelId, entityId)} isLastMessage={index === messageList.length - 1} - isMobileMode={isMobileMode} isHistory={isHistory} triggerResize={triggerResize} onMsgDataLoaded={(data: MsgDataType, valid: boolean) => { @@ -145,7 +125,6 @@ const MessageContainer: React.FC = ({ agentId={agentId} filter={getFilters(modelId, entityId)} isLastMessage={index === messageList.length - 1} - isMobileMode={isMobileMode} isHistory={isHistory} triggerResize={triggerResize} parseOptions={parseOptions} @@ -167,9 +146,9 @@ function areEqual(prevProps: Props, nextProps: Props) { if ( prevProps.id === nextProps.id && isEqual(prevProps.messageList, nextProps.messageList) && - prevProps.conversationCollapsed === nextProps.conversationCollapsed && - prevProps.copilotFullscreen === nextProps.copilotFullscreen && - prevProps.agentList === nextProps.agentList + prevProps.historyVisible === nextProps.historyVisible && + prevProps.currentAgent === nextProps.currentAgent && + prevProps.chatVisible === nextProps.chatVisible ) { return true; } diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/MessageContainer/style.less b/webapp/packages/supersonic-fe/src/pages/Chat/MessageContainer/style.less new file mode 100644 index 000000000..a247e20b3 --- /dev/null +++ b/webapp/packages/supersonic-fe/src/pages/Chat/MessageContainer/style.less @@ -0,0 +1,148 @@ +.messageContainer { + position: relative; + display: flex; + flex: 1; + flex-direction: column; + min-height: 0; + overflow-x: hidden; + overflow-y: scroll; + + .messageList { + display: flex; + flex-direction: column; + padding: 70px 20px 60px 14px; + row-gap: 16px; + + .messageItem { + display: flex; + flex-direction: column; + row-gap: 20px; + + :global { + .ant-table-small { + .ant-table-tbody { + .ant-table-cell { + padding: 6px 0 !important; + } + } + .ss-chat-table-formatted-value { + font-size: 15px !important; + } + } + .ant-table-row { + background-color: #fff; + } + + .ant-table-tbody > tr > td { + border-bottom: 1px solid #f0f0f0; + transition: background 0.2s, border-color 0.2s; + } + + .ss-chat-table-even-row { + background-color: #fbfbfb; + } + + .ant-table-wrapper .ant-table-pagination { + display: flex; + flex-wrap: wrap; + justify-content: center; + margin: 16px 0 0; + row-gap: 8px; + } + + .ant-pagination .ant-pagination-prev, + .ant-pagination .ant-pagination-next { + display: inline-block; + min-width: 32px; + height: 32px; + color: rgba(0, 0, 0, 0.88); + line-height: 32px; + text-align: center; + vertical-align: middle; + list-style: none; + border-radius: 6px; + cursor: pointer; + transition: all 0.2s; + + .ant-pagination-item-link { + display: block; + width: 100%; + height: 100%; + padding: 0; + font-size: 12px; + text-align: center; + background-color: transparent; + border: 1px solid transparent; + border-radius: 6px; + outline: none; + transition: border 0.2s; + } + } + + .ant-pagination-jump-prev, + .ant-pagination-jump-next { + .ant-pagination-item-link { + display: inline-block; + min-width: 32px; + height: 32px; + color: rgba(0, 0, 0, 0.25); + line-height: 32px; + text-align: center; + vertical-align: middle; + list-style: none; + border-radius: 6px; + cursor: pointer; + transition: all 0.2s; + } + } + + .ant-pagination-options { + display: inline-block; + margin-left: 16px; + vertical-align: middle; + } + + .ant-pagination .ant-pagination-item { + display: inline-block; + min-width: 32px; + height: 32px; + line-height: 30px; + text-align: center; + vertical-align: middle; + list-style: none; + background-color: transparent; + border: 1px solid transparent; + border-radius: 6px; + outline: 0; + cursor: pointer; + user-select: none; + margin-inline-end: 8px; + } + + .ant-pagination .ant-pagination-item-active { + font-weight: 600; + background-color: #ffffff; + border-color: var(--primary-color); + } + + .ant-pagination { + box-sizing: border-box; + margin: 0; + padding: 0; + color: #606266; + font-size: 14px; + font-variant: tabular-nums; + line-height: 1.5715; + list-style: none; + font-feature-settings: 'tnum', 'tnum'; + } + } + } + } + + &.mobile { + .messageList { + padding: 20px 10px 30px; + } + } +} diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/components/AgentList/index.tsx b/webapp/packages/supersonic-fe/src/pages/Chat/components/AgentList/index.tsx deleted file mode 100644 index efc119ff8..000000000 --- a/webapp/packages/supersonic-fe/src/pages/Chat/components/AgentList/index.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import LeftAvatar from '../CopilotAvatar'; -import Message from '../Message'; -import styles from './style.less'; -import { AgentType } from '../../type'; -import classNames from 'classnames'; - -type Props = { - currentAgentName: string; - data: AgentType[]; - copilotFullscreen?: boolean; - onSelectAgent: (agent: AgentType) => void; -}; - -const AgentList: React.FC = ({ - currentAgentName, - data, - copilotFullscreen, - onSelectAgent, -}) => { - const agentClass = classNames(styles.agent, { - [styles.fullscreen]: copilotFullscreen, - }); - return ( -
- - -
- 您好,智能助理【{currentAgentName} - 】将与您对话,点击以下卡片或者输入“/”可切换助理: -
-
- {data.map((agent) => ( -
{ - onSelectAgent(agent); - }} - > -
-
{agent.name}
-
您可以这样问:
-
-
- {agent.examples?.length > 0 ? ( - agent.examples.map((example) => ( -
- “{example}” -
- )) - ) : ( -
{agent.description}
- )} -
-
- ))} -
-
-
- ); -}; - -export default AgentList; diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/components/AgentList/style.less b/webapp/packages/supersonic-fe/src/pages/Chat/components/AgentList/style.less deleted file mode 100644 index f74b1beeb..000000000 --- a/webapp/packages/supersonic-fe/src/pages/Chat/components/AgentList/style.less +++ /dev/null @@ -1,63 +0,0 @@ -.agentList { - display: flex; - margin-top: 12px; - - .agentListMsg { - padding: 12px 20px 20px !important; - - .title { - margin-bottom: 12px; - font-weight: 500; - font-size: 14px; - } - - .content { - display: flex; - flex-wrap: wrap; - margin-top: 20px; - column-gap: 14px; - row-gap: 14px; - - .agent { - flex: 0 0 calc(50% - 7px); - padding: 10px 14px 20px; - color: var(--text-color); - font-size: 14px; - background-color: #f4f4f4; - border-radius: 17px; - cursor: pointer; - - .topBar { - .agentName { - font-weight: 700; - } - - .tip { - margin-top: 2px; - font-size: 13px; - font-style: italic; - } - } - - .examples { - display: flex; - flex-direction: column; - margin-top: 12px; - font-size: 13px; - row-gap: 8px; - - .example { - padding: 4px 12px; - background-color: #ededed; - border-radius: 15px; - } - } - - &.fullscreen { - flex: none; - width: 280px; - } - } - } - } -} diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/components/AgentTip/index.tsx b/webapp/packages/supersonic-fe/src/pages/Chat/components/AgentTip/index.tsx new file mode 100644 index 000000000..3bd59eda4 --- /dev/null +++ b/webapp/packages/supersonic-fe/src/pages/Chat/components/AgentTip/index.tsx @@ -0,0 +1,48 @@ +import LeftAvatar from '../CopilotAvatar'; +import Message from '../Message'; +import styles from './style.less'; +import { AgentType } from '../../type'; +import { isMobile } from '@/utils/utils'; + +type Props = { + currentAgent?: AgentType; + onSendMsg: (value: string) => void; +}; + +const AgentTip: React.FC = ({ currentAgent, onSendMsg }) => { + if (!currentAgent) { + return null; + } + return ( +
+ {!isMobile && } + +
+ 您好,智能助理【{currentAgent.name} + 】将与您对话,试着问: +
+
+
+ {currentAgent.examples?.length > 0 ? ( + currentAgent.examples.map((example) => ( +
{ + onSendMsg(example); + }} + > + “{example}” +
+ )) + ) : ( +
{currentAgent.description}
+ )} +
+
+
+
+ ); +}; + +export default AgentTip; diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/components/AgentTip/style.less b/webapp/packages/supersonic-fe/src/pages/Chat/components/AgentTip/style.less new file mode 100644 index 000000000..1d7d1594c --- /dev/null +++ b/webapp/packages/supersonic-fe/src/pages/Chat/components/AgentTip/style.less @@ -0,0 +1,44 @@ +.agentTip { + display: flex; + + .agentTipMsg { + padding: 12px 20px 20px !important; + + .title { + margin-bottom: 12px; + font-size: 14px; + } + + .content { + display: flex; + flex-direction: column; + flex-wrap: wrap; + margin-top: 10px; + column-gap: 14px; + + .topBar { + .tip { + margin-top: 2px; + font-size: 13px; + } + } + + .examples { + display: flex; + flex-direction: column; + font-size: 13px; + row-gap: 8px; + + .example { + color: var(--chat-blue); + cursor: pointer; + } + } + + &.fullscreen { + flex: none; + width: 280px; + } + } + } +} diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/components/Plugin/constants.ts b/webapp/packages/supersonic-fe/src/pages/Chat/components/Plugin/constants.ts deleted file mode 100644 index bd5b53953..000000000 --- a/webapp/packages/supersonic-fe/src/pages/Chat/components/Plugin/constants.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const TRANS_30_REPORT_DASHBOARD_ID = '1165'; - -export const HEAT_COMPARE_REPORT_DASHBOARD_ID = '1148'; - -export const INSIGHTS_DETAIL_ID = 'DETAIL'; -export const INSIGHTS_ID = 'INSIGHT'; diff --git a/webapp/packages/supersonic-fe/src/pages/Chat/components/Plugin/index.tsx b/webapp/packages/supersonic-fe/src/pages/Chat/components/Plugin/index.tsx deleted file mode 100644 index 4b9887a44..000000000 --- a/webapp/packages/supersonic-fe/src/pages/Chat/components/Plugin/index.tsx +++ /dev/null @@ -1,187 +0,0 @@ -import { isProd } from '@/utils/utils'; -import { MsgDataType } from 'supersonic-chat-sdk'; -import classNames from 'classnames'; -import { useEffect, useState, useCallback } from 'react'; -import Message from '../Message'; -import { updateMessageContainerScroll } from '@/utils/utils'; -import styles from './style.less'; -import LeftAvatar from '../CopilotAvatar'; -import { DislikeOutlined, LikeOutlined } from '@ant-design/icons'; -import { updateQAFeedback } from '../../service'; - -type Props = { - id: string | number; - followQuestions?: string[]; - data: MsgDataType; - scoreValue?: number; - msg: string; - isHistory?: boolean; - isLastMessage: boolean; - isMobileMode?: boolean; - onReportLoaded: (height: number) => void; - onCheckMore: (data: MsgDataType) => void; -}; - -const DEFAULT_HEIGHT = 800; - -const Plugin: React.FC = ({ - id, - followQuestions, - data, - scoreValue, - msg, - isHistory, - isLastMessage, - isMobileMode, - onReportLoaded, - onCheckMore, -}) => { - const { - name, - webPage: { url, params }, - } = data.response || {}; - - const [pluginUrl, setPluginUrl] = useState(''); - const [height, setHeight] = useState(DEFAULT_HEIGHT); - const [score, setScore] = useState(scoreValue || 0); - - const handleMessage = useCallback((event: MessageEvent) => { - const messageData = event.data; - const { type, payload } = messageData; - if (type === 'changeMiniProgramContainerSize') { - const { msgId, height } = payload; - if (`${msgId}` === `${id}`) { - setHeight(height); - updateMessageContainerScroll(); - } - return; - } - if (messageData === 'storyResize') { - const ifr: any = document.getElementById(`reportIframe_${id}`); - const iDoc = ifr.contentDocument || ifr.document || ifr.contentWindow; - setTimeout(() => { - setHeight(isProd() ? calcPageHeight(iDoc) : DEFAULT_HEIGHT); - }, 200); - return; - } - }, []); - - useEffect(() => { - window.addEventListener('message', handleMessage); - return () => { - window.removeEventListener('message', handleMessage); - }; - }, [handleMessage]); - - function calcPageHeight(doc: any) { - const titleAreaEl = doc.getElementById('titleArea'); - const titleAreaHeight = Math.max( - titleAreaEl?.clientHeight || 0, - titleAreaEl?.scrollHeight || 0, - ); - const dashboardGridEl = doc.getElementsByClassName('dashboardGrid')?.[0]; - const dashboardGridHeight = Math.max( - dashboardGridEl?.clientHeight || 0, - dashboardGridEl?.scrollHeight || 0, - ); - return Math.max(titleAreaHeight + dashboardGridHeight + 10, DEFAULT_HEIGHT); - } - - const initData = () => { - const heightValue = - params?.find((option: any) => option.paramType === 'FORWARD' && option.key === 'height') - ?.value || DEFAULT_HEIGHT; - setHeight(heightValue); - let urlValue = url; - const valueParams = (params || []) - .filter((option: any) => option.paramType !== 'FORWARD') - .reduce((result: any, item: any) => { - result[item.key] = item.value; - return result; - }, {}); - if (urlValue.includes('?type=dashboard') || urlValue.includes('?type=widget')) { - const filterData = encodeURIComponent( - JSON.stringify( - urlValue.includes('dashboard') - ? { - global: valueParams, - } - : { - local: valueParams, - }, - ), - ); - urlValue = urlValue.replace( - '?', - `?miniProgram=true&reportName=${name}&filterData=${filterData}&`, - ); - urlValue = - !isProd() && !urlValue.includes('http') ? `http://s2.tmeoa.com${urlValue}` : urlValue; - } else { - const params = Object.keys(valueParams || {}).map((key) => `${key}=${valueParams[key]}`); - if (params.length > 0) { - if (url.includes('?')) { - urlValue = urlValue.replace('?', `?${params.join('&')}&`); - } else { - urlValue = `${urlValue}?${params.join('&')}`; - } - } - } - onReportLoaded(heightValue + 190); - setPluginUrl(urlValue); - }; - - useEffect(() => { - initData(); - }, []); - - const reportClass = classNames(styles.report, { - [styles.mobileMode]: isMobileMode, - }); - - const like = () => { - setScore(5); - updateQAFeedback(data.queryId, 5); - }; - - const dislike = () => { - setScore(1); - updateQAFeedback(data.queryId, 1); - }; - - const likeClass = classNames(styles.like, { - [styles.feedbackActive]: score === 5, - }); - - const dislikeClass = classNames(styles.dislike, { - [styles.feedbackActive]: score === 1, - }); - - return ( -
- -
- -