mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-12 12:37:55 +00:00
(feature)(webapp) use nativeQuery field to determine whether it is a selection (#222)
This commit is contained in:
@@ -2,7 +2,6 @@ import { Form, Input, Modal } from 'antd';
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { updateConversationName } from '../../service';
|
import { updateConversationName } from '../../service';
|
||||||
import type { ConversationDetailType } from '../../type';
|
import type { ConversationDetailType } from '../../type';
|
||||||
import { CHAT_TITLE } from '../../constants';
|
|
||||||
|
|
||||||
const FormItem = Form.Item;
|
const FormItem = Form.Item;
|
||||||
|
|
||||||
@@ -44,7 +43,7 @@ const ConversationModal: React.FC<Props> = ({ visible, editConversation, onClose
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={`修改${CHAT_TITLE}问答名称`}
|
title="修改问答名称"
|
||||||
open={visible}
|
open={visible}
|
||||||
onCancel={onClose}
|
onCancel={onClose}
|
||||||
onOk={onConfirm}
|
onOk={onConfirm}
|
||||||
@@ -53,7 +52,7 @@ const ConversationModal: React.FC<Props> = ({ visible, editConversation, onClose
|
|||||||
<Form {...layout} form={form}>
|
<Form {...layout} form={form}>
|
||||||
<FormItem name="conversationName" label="名称" rules={[{ required: true }]}>
|
<FormItem name="conversationName" label="名称" rules={[{ required: true }]}>
|
||||||
<Input
|
<Input
|
||||||
placeholder={`请输入${CHAT_TITLE}问答名称`}
|
placeholder="请输入问答名称"
|
||||||
ref={conversationNameInputRef}
|
ref={conversationNameInputRef}
|
||||||
onPressEnter={onConfirm}
|
onPressEnter={onConfirm}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import classNames from 'classnames';
|
|||||||
import LeftAvatar from './CopilotAvatar';
|
import LeftAvatar from './CopilotAvatar';
|
||||||
import Message from './Message';
|
import Message from './Message';
|
||||||
import styles from './style.module.less';
|
import styles from './style.module.less';
|
||||||
|
import { userAvatarUrl } from '../../common/env';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
position: 'left' | 'right';
|
position: 'left' | 'right';
|
||||||
@@ -15,6 +16,7 @@ const Text: React.FC<Props> = ({ position, data, quote }) => {
|
|||||||
const textWrapperClass = classNames(styles.textWrapper, {
|
const textWrapperClass = classNames(styles.textWrapper, {
|
||||||
[styles.rightTextWrapper]: position === 'right',
|
[styles.rightTextWrapper]: position === 'right',
|
||||||
});
|
});
|
||||||
|
const rightAvatarUrl = userAvatarUrl;
|
||||||
return (
|
return (
|
||||||
<div className={textWrapperClass}>
|
<div className={textWrapperClass}>
|
||||||
{!isMobile && position === 'left' && <LeftAvatar />}
|
{!isMobile && position === 'left' && <LeftAvatar />}
|
||||||
@@ -22,6 +24,9 @@ const Text: React.FC<Props> = ({ position, data, quote }) => {
|
|||||||
{position === 'right' && quote && <div className={styles.quote}>{quote}</div>}
|
{position === 'right' && quote && <div className={styles.quote}>{quote}</div>}
|
||||||
<div className={styles.text}>{data}</div>
|
<div className={styles.text}>{data}</div>
|
||||||
</Message>
|
</Message>
|
||||||
|
{!isMobile && position === 'right' && rightAvatarUrl && (
|
||||||
|
<Avatar shape="circle" size={40} src={rightAvatarUrl} className={styles.rightAvatar} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,16 +43,8 @@ export const AGENT_ICONS = [
|
|||||||
|
|
||||||
export const HOLDER_TAG = '@_supersonic_@';
|
export const HOLDER_TAG = '@_supersonic_@';
|
||||||
|
|
||||||
export const CHAT_TITLE = '';
|
|
||||||
|
|
||||||
export const DEFAULT_CONVERSATION_NAME = '新问答对话';
|
export const DEFAULT_CONVERSATION_NAME = '新问答对话';
|
||||||
|
|
||||||
export const PAGE_TITLE = '问答对话';
|
|
||||||
|
|
||||||
export const WEB_TITLE = '问答对话';
|
|
||||||
|
|
||||||
export const MOBILE_TITLE = '问答对话';
|
|
||||||
|
|
||||||
export const PLACE_HOLDER = '请输入您的问题,或输入“/”切换助理';
|
export const PLACE_HOLDER = '请输入您的问题,或输入“/”切换助理';
|
||||||
|
|
||||||
export const SIMPLE_PLACE_HOLDER = '请输入您的问题';
|
export const SIMPLE_PLACE_HOLDER = '请输入您的问题';
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import { useThrottleFn } from 'ahooks';
|
|||||||
import Conversation from './Conversation';
|
import Conversation from './Conversation';
|
||||||
import ChatFooter from './ChatFooter';
|
import ChatFooter from './ChatFooter';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { CHAT_TITLE } from './constants';
|
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
import AgentList from './AgentList';
|
import AgentList from './AgentList';
|
||||||
import MobileAgents from './MobileAgents';
|
import MobileAgents from './MobileAgents';
|
||||||
@@ -59,7 +58,7 @@ const Chat: ForwardRefRenderFunction<any, Props> = (
|
|||||||
const [historyInited, setHistoryInited] = useState(false);
|
const [historyInited, setHistoryInited] = useState(false);
|
||||||
const [currentConversation, setCurrentConversation] = useState<
|
const [currentConversation, setCurrentConversation] = useState<
|
||||||
ConversationDetailType | undefined
|
ConversationDetailType | undefined
|
||||||
>(isMobile ? { chatId: 0, chatName: `${CHAT_TITLE}问答` } : undefined);
|
>(isMobile ? { chatId: 0, chatName: '问答' } : undefined);
|
||||||
const [historyVisible, setHistoryVisible] = useState(false);
|
const [historyVisible, setHistoryVisible] = useState(false);
|
||||||
const [agentList, setAgentList] = useState<AgentType[]>([]);
|
const [agentList, setAgentList] = useState<AgentType[]>([]);
|
||||||
const [currentAgent, setCurrentAgent] = useState<AgentType>();
|
const [currentAgent, setCurrentAgent] = useState<AgentType>();
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { AgentType } from '../Chat/type';
|
|||||||
import { setToken } from '../utils/utils';
|
import { setToken } from '../utils/utils';
|
||||||
import { SendMsgParamsType } from '../common/type';
|
import { SendMsgParamsType } from '../common/type';
|
||||||
import styles from './style.module.less';
|
import styles from './style.module.less';
|
||||||
|
import { copilotTitle } from '../common/env';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
token?: string;
|
token?: string;
|
||||||
@@ -123,7 +124,7 @@ const Copilot: ForwardRefRenderFunction<any, Props> = (
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.title}>内容库问答</div>
|
<div className={styles.title}>{copilotTitle}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.chat}>
|
<div className={styles.chat}>
|
||||||
<Chat
|
<Chat
|
||||||
|
|||||||
7
webapp/packages/chat-sdk/src/common/env.ts
Normal file
7
webapp/packages/chat-sdk/src/common/env.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export const proxyTarget = 'http://localhost:9080';
|
||||||
|
|
||||||
|
export const userAvatarUrl = '';
|
||||||
|
|
||||||
|
export const webPageHost = '';
|
||||||
|
|
||||||
|
export const copilotTitle = 'Copilot';
|
||||||
@@ -183,7 +183,7 @@ export enum SemanticTypeEnum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const SEMANTIC_TYPE_MAP = {
|
export const SEMANTIC_TYPE_MAP = {
|
||||||
[SemanticTypeEnum.DOMAIN]: '数据来源',
|
[SemanticTypeEnum.DOMAIN]: '数据模型',
|
||||||
[SemanticTypeEnum.DIMENSION]: '维度',
|
[SemanticTypeEnum.DIMENSION]: '维度',
|
||||||
[SemanticTypeEnum.METRIC]: '指标',
|
[SemanticTypeEnum.METRIC]: '指标',
|
||||||
[SemanticTypeEnum.VALUE]: '维度值',
|
[SemanticTypeEnum.VALUE]: '维度值',
|
||||||
|
|||||||
@@ -150,7 +150,6 @@ const FilterItem: React.FC<Props> = ({
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
mode={isArray(filter.value) ? 'multiple' : undefined}
|
mode={isArray(filter.value) ? 'multiple' : undefined}
|
||||||
showSearch
|
showSearch
|
||||||
// allowClear
|
|
||||||
/>
|
/>
|
||||||
) : entityAlias &&
|
) : entityAlias &&
|
||||||
['歌曲', '艺人'].includes(entityAlias) &&
|
['歌曲', '艺人'].includes(entityAlias) &&
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ const ParseTip: React.FC<Props> = ({
|
|||||||
queryMode,
|
queryMode,
|
||||||
properties,
|
properties,
|
||||||
entity,
|
entity,
|
||||||
// entityInfo,
|
|
||||||
elementMatches,
|
elementMatches,
|
||||||
nativeQuery,
|
nativeQuery,
|
||||||
} = currentParseInfo || {};
|
} = currentParseInfo || {};
|
||||||
@@ -198,7 +197,7 @@ const ParseTip: React.FC<Props> = ({
|
|||||||
<div className={`${prefixCls}-tip-item-filter-content`}>
|
<div className={`${prefixCls}-tip-item-filter-content`}>
|
||||||
<div className={`${prefixCls}-tip-item-option`}>
|
<div className={`${prefixCls}-tip-item-option`}>
|
||||||
<span className={`${prefixCls}-tip-item-filter-name`}>数据时间:</span>
|
<span className={`${prefixCls}-tip-item-filter-name`}>数据时间:</span>
|
||||||
{dimensions?.some(item => item.bizName?.includes('_id')) ? (
|
{nativeQuery ? (
|
||||||
<span className={itemValueClass}>
|
<span className={itemValueClass}>
|
||||||
{startDate === endDate ? startDate : `${startDate} ~ ${endDate}`}
|
{startDate === endDate ? startDate : `${startDate} ~ ${endDate}`}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -61,6 +61,11 @@ const Table: React.FC<Props> = ({ data, size, onApplyAuth }) => {
|
|||||||
return index % 2 !== 0 ? `${prefixCls}-even-row` : '';
|
return index % 2 !== 0 ? `${prefixCls}-even-row` : '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dateColumn = queryColumns.find(column => column.type === 'DATE');
|
||||||
|
const dataSource = dateColumn
|
||||||
|
? queryResults.sort((a, b) => moment(a[dateColumn.nameEn]).diff(moment(b[dateColumn.nameEn])))
|
||||||
|
: queryResults;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={prefixCls}>
|
<div className={prefixCls}>
|
||||||
<AntTable
|
<AntTable
|
||||||
@@ -68,8 +73,8 @@ const Table: React.FC<Props> = ({ data, size, onApplyAuth }) => {
|
|||||||
queryResults.length <= 10 ? false : { defaultPageSize: 10, position: ['bottomCenter'] }
|
queryResults.length <= 10 ? false : { defaultPageSize: 10, position: ['bottomCenter'] }
|
||||||
}
|
}
|
||||||
columns={tableColumns}
|
columns={tableColumns}
|
||||||
dataSource={queryResults}
|
dataSource={dataSource}
|
||||||
style={{ width: '100%', overflowX: 'auto' }}
|
style={{ width: '100%', overflowX: 'auto', overflowY: 'hidden' }}
|
||||||
rowClassName={getRowClassName}
|
rowClassName={getRowClassName}
|
||||||
size={size}
|
size={size}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { MsgDataType } from '../../../common/type';
|
import { MsgDataType } from '../../../common/type';
|
||||||
import { getToken, isProd } from '../../../utils/utils';
|
import { getToken, isProd } from '../../../utils/utils';
|
||||||
|
import { webPageHost } from '../../../common/env';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
id: string | number;
|
id: string | number;
|
||||||
@@ -88,6 +89,7 @@ const WebPage: React.FC<Props> = ({ id, data }) => {
|
|||||||
'?',
|
'?',
|
||||||
`?token=${getToken()}&miniProgram=true&reportName=${name}&filterData=${filterData}&`
|
`?token=${getToken()}&miniProgram=true&reportName=${name}&filterData=${filterData}&`
|
||||||
);
|
);
|
||||||
|
urlValue = `${webPageHost}${urlValue}`;
|
||||||
} else {
|
} else {
|
||||||
const params = Object.keys(valueParams || {}).map(key => `${key}=${valueParams[key]}`);
|
const params = Object.keys(valueParams || {}).map(key => `${key}=${valueParams[key]}`);
|
||||||
if (params.length > 0) {
|
if (params.length > 0) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Input } from 'antd';
|
|||||||
import styles from './style.module.less';
|
import styles from './style.module.less';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import ChatItem from '../components/ChatItem';
|
import ChatItem from '../components/ChatItem';
|
||||||
import { searchRecommend } from '../service';
|
import { MsgDataType } from '../common/type';
|
||||||
|
|
||||||
const { Search } = Input;
|
const { Search } = Input;
|
||||||
|
|
||||||
@@ -10,8 +10,9 @@ const Chat = () => {
|
|||||||
const [data, setData] = useState<any>();
|
const [data, setData] = useState<any>();
|
||||||
const [inputMsg, setInputMsg] = useState('');
|
const [inputMsg, setInputMsg] = useState('');
|
||||||
const [msg, setMsg] = useState('');
|
const [msg, setMsg] = useState('');
|
||||||
const [followQuestions, setFollowQuestions] = useState<string[]>([]);
|
|
||||||
const [triggerResize, setTriggerResize] = useState(false);
|
const [triggerResize, setTriggerResize] = useState(false);
|
||||||
|
const [executeItemNode, setExecuteItemNode] = useState<React.ReactNode>();
|
||||||
|
const [chatItemVisible, setChatItemVisible] = useState(false);
|
||||||
|
|
||||||
const onWindowResize = () => {
|
const onWindowResize = () => {
|
||||||
setTriggerResize(true);
|
setTriggerResize(true);
|
||||||
@@ -34,14 +35,24 @@ const Chat = () => {
|
|||||||
|
|
||||||
const onSearch = () => {
|
const onSearch = () => {
|
||||||
setMsg(inputMsg);
|
setMsg(inputMsg);
|
||||||
|
setChatItemVisible(false);
|
||||||
|
setTimeout(() => {
|
||||||
|
setChatItemVisible(true);
|
||||||
|
}, 200);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onMsgDataLoaded = (msgData: any) => {
|
const onMsgDataLoaded = (msgData: MsgDataType) => {
|
||||||
setData(msgData);
|
setData(msgData);
|
||||||
setFollowQuestions(['测试1234测试', '测试1234测试', '测试1234测试']);
|
const { queryColumns, queryResults, queryMode } = msgData;
|
||||||
|
const songIds = queryColumns.some(column => column.nameEn === 'zyqk_song_id')
|
||||||
|
? (queryResults || []).map(result => result['zyqk_song_id'])
|
||||||
|
: [];
|
||||||
|
if (queryMode === 'DSL') {
|
||||||
|
setExecuteItemNode(<>test</>);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 5: 查信息,6: 智能圈选
|
//预发环境: 5: 查信息,6: 智能圈选,12:问指标,15:歌曲库,16:艺人库
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.page}>
|
<div className={styles.page}>
|
||||||
@@ -53,15 +64,19 @@ const Chat = () => {
|
|||||||
onSearch={onSearch}
|
onSearch={onSearch}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{inputMsg && (
|
{msg && chatItemVisible && (
|
||||||
<div className={styles.chatItem}>
|
<div className={styles.chatItem}>
|
||||||
<ChatItem
|
<ChatItem
|
||||||
msg={msg}
|
msg={msg}
|
||||||
// msgData={data}
|
// msgData={data}
|
||||||
agentId={6}
|
agentId={5}
|
||||||
|
conversationId={112211121}
|
||||||
onMsgDataLoaded={onMsgDataLoaded}
|
onMsgDataLoaded={onMsgDataLoaded}
|
||||||
isLastMessage
|
isLastMessage
|
||||||
triggerResize={triggerResize}
|
triggerResize={triggerResize}
|
||||||
|
integrateSystem="wiki"
|
||||||
|
executeItemNode={executeItemNode}
|
||||||
|
isDeveloper
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -35,14 +35,7 @@ const CopilotDemo = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
))}
|
))}
|
||||||
</Space>
|
</Space>
|
||||||
<Copilot
|
<Copilot isDeveloper ref={copilotRef} />
|
||||||
// token={localStorage.getItem('SUPERSONIC_TOKEN') || ''}
|
|
||||||
// agentIds={[8]}
|
|
||||||
isDeveloper
|
|
||||||
// integrateSystem="c2"
|
|
||||||
ref={copilotRef}
|
|
||||||
// noInput
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import './styles/index.less';
|
|||||||
// import ChatDemo from './demo/ChatDemo';
|
// import ChatDemo from './demo/ChatDemo';
|
||||||
// import CopilotDemo from './demo/CopilotDemo';
|
// import CopilotDemo from './demo/CopilotDemo';
|
||||||
// const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
|
// const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
|
||||||
// root.render(<ChatDemo />);
|
// root.render(<Chat />);
|
||||||
|
|
||||||
export { default as Chat } from './Chat';
|
export { default as Chat } from './Chat';
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import axios from './axiosInstance';
|
import axios from './axiosInstance';
|
||||||
import { ChatContextType, DrillDownDimensionType, EntityInfoType, HistoryType, MsgDataType, ParseDataType, SearchRecommendItem } from '../common/type';
|
import { ChatContextType, DrillDownDimensionType, EntityInfoType, HistoryType, MsgDataType, ParseDataType, SearchRecommendItem } from '../common/type';
|
||||||
|
import { isMobile } from '../utils/utils';
|
||||||
|
|
||||||
const DEFAULT_CHAT_ID = 0;
|
const DEFAULT_CHAT_ID = 0;
|
||||||
|
|
||||||
const prefix = '/api';
|
const prefix = isMobile ? '/openapi' : '/api';
|
||||||
|
|
||||||
export function searchRecommend(queryText: string, chatId?: number, modelId?: number, agentId?: number) {
|
export function searchRecommend(queryText: string, chatId?: number, modelId?: number, agentId?: number) {
|
||||||
return axios.post<SearchRecommendItem[]>(`${prefix}/chat/query/search`, {
|
return axios.post<SearchRecommendItem[]>(`${prefix}/chat/query/search`, {
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
const { createProxyMiddleware } = require('http-proxy-middleware');
|
const { createProxyMiddleware } = require('http-proxy-middleware');
|
||||||
|
const { proxyTarget } = require('./common/env');
|
||||||
|
|
||||||
module.exports = function(app) {
|
module.exports = function(app) {
|
||||||
app.use(
|
app.use(
|
||||||
'/api',
|
'/api',
|
||||||
createProxyMiddleware({
|
createProxyMiddleware({
|
||||||
target: 'http://localhost:9080',
|
target: proxyTarget,
|
||||||
|
changeOrigin: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
app.use(
|
||||||
|
'/openapi',
|
||||||
|
createProxyMiddleware({
|
||||||
|
target: proxyTarget,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user