mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-12 20:51:48 +00:00
[feature](webapp) add mobile agents drawer (#64)
This commit is contained in:
@@ -192,6 +192,6 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.18.0"
|
"node": ">=16"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,6 +248,8 @@
|
|||||||
&-entity-info {
|
&-entity-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
row-gap: 6px;
|
||||||
column-gap: 12px;
|
column-gap: 12px;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
color: var(--text-color-third);
|
color: var(--text-color-third);
|
||||||
@@ -257,6 +259,8 @@
|
|||||||
&-dimension-item {
|
&-dimension-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
row-gap: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-dimension-name {
|
&-dimension-name {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const ROUTES = [
|
|||||||
component: './Agent',
|
component: './Agent',
|
||||||
envEnableList: [ENV_KEY.CHAT],
|
envEnableList: [ENV_KEY.CHAT],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/model',
|
path: '/model',
|
||||||
name: 'semanticModel',
|
name: 'semanticModel',
|
||||||
envEnableList: [ENV_KEY.SEMANTIC],
|
envEnableList: [ENV_KEY.SEMANTIC],
|
||||||
@@ -53,7 +53,6 @@ const ROUTES = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/database',
|
path: '/database',
|
||||||
name: 'database',
|
name: 'database',
|
||||||
|
|||||||
@@ -98,7 +98,7 @@
|
|||||||
"react-split-pane": "^2.0.3",
|
"react-split-pane": "^2.0.3",
|
||||||
"react-syntax-highlighter": "^15.4.3",
|
"react-syntax-highlighter": "^15.4.3",
|
||||||
"sql-formatter": "^2.3.3",
|
"sql-formatter": "^2.3.3",
|
||||||
"supersonic-chat-sdk": "^0.5.29",
|
"supersonic-chat-sdk": "0.0.0",
|
||||||
"umi": "3.5",
|
"umi": "3.5",
|
||||||
"umi-request": "^1.0.8"
|
"umi-request": "^1.0.8"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,20 +4,7 @@ import styles from './style.less';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
import IconFont from '@/components/IconFont';
|
import IconFont from '@/components/IconFont';
|
||||||
|
import { AGENT_ICONS } from '../constants';
|
||||||
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 = {
|
type Props = {
|
||||||
agentList: AgentType[];
|
agentList: AgentType[];
|
||||||
@@ -49,8 +36,7 @@ const AgentList: React.FC<Props> = ({ agentList, currentAgent, onSelectAgent })
|
|||||||
onSelectAgent(agent);
|
onSelectAgent(agent);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* <img src={agents[index % agents.length]} alt="avatar" className={styles.avatar} /> */}
|
<IconFont type={AGENT_ICONS[index % AGENT_ICONS.length]} className={styles.avatar} />
|
||||||
<IconFont type={agents[index % agents.length]} className={styles.avatar} />
|
|
||||||
<div className={styles.agentInfo}>
|
<div className={styles.agentInfo}>
|
||||||
<div className={styles.agentName}>{agent.name}</div>
|
<div className={styles.agentName}>{agent.name}</div>
|
||||||
<div className={styles.agentDesc}>{agent.description}</div>
|
<div className={styles.agentDesc}>{agent.description}</div>
|
||||||
|
|||||||
@@ -66,10 +66,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover, &.active {
|
&:hover,
|
||||||
|
&.active {
|
||||||
background: #22a5f7;
|
background: #22a5f7;
|
||||||
|
|
||||||
.agentName, .agentDesc {
|
.agentName,
|
||||||
|
.agentDesc {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ type Props = {
|
|||||||
currentAgent?: AgentType;
|
currentAgent?: AgentType;
|
||||||
agentList: AgentType[];
|
agentList: AgentType[];
|
||||||
onToggleHistoryVisible: () => void;
|
onToggleHistoryVisible: () => void;
|
||||||
|
onOpenMobileAgents: () => void;
|
||||||
onInputMsgChange: (value: string) => void;
|
onInputMsgChange: (value: string) => void;
|
||||||
onSendMsg: (msg: string, modelId?: number) => void;
|
onSendMsg: (msg: string, modelId?: number) => void;
|
||||||
onAddConversation: (agent?: AgentType) => void;
|
onAddConversation: (agent?: AgentType) => void;
|
||||||
@@ -41,6 +42,7 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
|
|||||||
currentAgent,
|
currentAgent,
|
||||||
agentList,
|
agentList,
|
||||||
onToggleHistoryVisible,
|
onToggleHistoryVisible,
|
||||||
|
onOpenMobileAgents,
|
||||||
onInputMsgChange,
|
onInputMsgChange,
|
||||||
onSendMsg,
|
onSendMsg,
|
||||||
onAddConversation,
|
onAddConversation,
|
||||||
@@ -310,6 +312,12 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
|
|||||||
<div>历史对话</div>
|
<div>历史对话</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{isMobile && (
|
||||||
|
<div className={styles.toolItem} onClick={onOpenMobileAgents}>
|
||||||
|
<IconFont type="icon-zhinengzhuli" className={styles.toolIcon} />
|
||||||
|
<div>智能助理</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.composer}>
|
<div className={styles.composer}>
|
||||||
<div className={styles.composerInputWrapper}>
|
<div className={styles.composerInputWrapper}>
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import IconFont from '@/components/IconFont';
|
||||||
|
import { Drawer } from 'antd';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { AGENT_ICONS } from '../constants';
|
||||||
|
import { AgentType } from '../type';
|
||||||
|
import styles from './style.less';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
open: boolean;
|
||||||
|
agentList: AgentType[];
|
||||||
|
currentAgent?: AgentType;
|
||||||
|
onSelectAgent: (agent: AgentType) => void;
|
||||||
|
onClose: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const MobileAgents: React.FC<Props> = ({
|
||||||
|
open,
|
||||||
|
agentList,
|
||||||
|
currentAgent,
|
||||||
|
onSelectAgent,
|
||||||
|
onClose,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Drawer
|
||||||
|
title="智能助理"
|
||||||
|
placement="bottom"
|
||||||
|
open={open}
|
||||||
|
height="85%"
|
||||||
|
className={styles.mobileAgents}
|
||||||
|
onClose={onClose}
|
||||||
|
>
|
||||||
|
<div className={styles.agentListContent}>
|
||||||
|
{agentList.map((agent, index) => {
|
||||||
|
const agentItemClass = classNames(styles.agentItem, {
|
||||||
|
[styles.active]: currentAgent?.id === agent.id,
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={agent.id}
|
||||||
|
className={agentItemClass}
|
||||||
|
onClick={() => {
|
||||||
|
onSelectAgent(agent);
|
||||||
|
onClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className={styles.agentTitleBar}>
|
||||||
|
<IconFont
|
||||||
|
type={AGENT_ICONS[index % AGENT_ICONS.length]}
|
||||||
|
className={styles.avatar}
|
||||||
|
/>
|
||||||
|
<div className={styles.agentName}>{agent.name}</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.agentDesc}>{agent.description}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</Drawer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MobileAgents;
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
.mobileAgents {
|
||||||
|
:global {
|
||||||
|
.ant-drawer-content {
|
||||||
|
border-top-left-radius: 12px;
|
||||||
|
border-top-right-radius: 12px;
|
||||||
|
|
||||||
|
.ant-drawer-header {
|
||||||
|
padding: 16px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-drawer-body {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.agentListContent {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: 12px;
|
||||||
|
|
||||||
|
.agentItem {
|
||||||
|
padding: 12px 16px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 10px;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border: 1px solid var(--chat-blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
.agentTitleBar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
column-gap: 6px;
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agentName {
|
||||||
|
color: var(--text-color);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.agentDesc {
|
||||||
|
margin-top: 8px;
|
||||||
|
color: var(--text-color-third);
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,20 @@ export const SEMANTIC_TYPE_MAP = {
|
|||||||
[SemanticTypeEnum.VALUE]: '维度值',
|
[SemanticTypeEnum.VALUE]: '维度值',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const AGENT_ICONS = [
|
||||||
|
'icon-fukuanbaobiaochaxun',
|
||||||
|
'icon-hangweifenxi1',
|
||||||
|
'icon-xiaofeifenxi',
|
||||||
|
'icon-renwuchaxun',
|
||||||
|
'icon-baobiao',
|
||||||
|
'icon-liushuichaxun',
|
||||||
|
'icon-cangkuchaxun',
|
||||||
|
'icon-xiaoshoushuju',
|
||||||
|
'icon-tongji',
|
||||||
|
'icon-shujutongji',
|
||||||
|
'icon-mendiankanban',
|
||||||
|
];
|
||||||
|
|
||||||
export const CHAT_TITLE = '';
|
export const CHAT_TITLE = '';
|
||||||
|
|
||||||
export const DEFAULT_CONVERSATION_NAME = '新问答对话';
|
export const DEFAULT_CONVERSATION_NAME = '新问答对话';
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import 'supersonic-chat-sdk/dist/index.css';
|
|||||||
import { setToken as setChatSdkToken } from 'supersonic-chat-sdk';
|
import { setToken as setChatSdkToken } from 'supersonic-chat-sdk';
|
||||||
import AgentList from './AgentList';
|
import AgentList from './AgentList';
|
||||||
import { AUTH_TOKEN_KEY } from '@/common/constants';
|
import { AUTH_TOKEN_KEY } from '@/common/constants';
|
||||||
|
import MobileAgents from './MobileAgents';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isCopilotMode?: boolean;
|
isCopilotMode?: boolean;
|
||||||
@@ -58,6 +59,7 @@ const Chat: React.FC<Props> = ({
|
|||||||
const [defaultEntity, setDefaultEntity] = useState<DefaultEntityType>();
|
const [defaultEntity, setDefaultEntity] = useState<DefaultEntityType>();
|
||||||
const [agentList, setAgentList] = useState<AgentType[]>([]);
|
const [agentList, setAgentList] = useState<AgentType[]>([]);
|
||||||
const [currentAgent, setCurrentAgent] = useState<AgentType>();
|
const [currentAgent, setCurrentAgent] = useState<AgentType>();
|
||||||
|
const [mobileAgentsVisible, setMobileAgentsVisible] = useState(false);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const conversationRef = useRef<any>();
|
const conversationRef = useRef<any>();
|
||||||
@@ -403,6 +405,9 @@ const Chat: React.FC<Props> = ({
|
|||||||
onSendMsg={sendMsg}
|
onSendMsg={sendMsg}
|
||||||
onAddConversation={onAddConversation}
|
onAddConversation={onAddConversation}
|
||||||
onSelectAgent={onSelectAgent}
|
onSelectAgent={onSelectAgent}
|
||||||
|
onOpenMobileAgents={() => {
|
||||||
|
setMobileAgentsVisible(true);
|
||||||
|
}}
|
||||||
ref={chatFooterRef}
|
ref={chatFooterRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -423,6 +428,15 @@ const Chat: React.FC<Props> = ({
|
|||||||
ref={conversationRef}
|
ref={conversationRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<MobileAgents
|
||||||
|
open={mobileAgentsVisible}
|
||||||
|
agentList={agentList}
|
||||||
|
currentAgent={currentAgent}
|
||||||
|
onSelectAgent={onSelectAgent}
|
||||||
|
onClose={() => {
|
||||||
|
setMobileAgentsVisible(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
|||||||
<FormItem name="pattern" label="函数描述">
|
<FormItem name="pattern" label="函数描述">
|
||||||
<TextArea placeholder="请输入函数描述,多个描述换行分隔" allowClear />
|
<TextArea placeholder="请输入函数描述,多个描述换行分隔" allowClear />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem name="params" label="函数参数" hidden={pluginType === PluginTypeEnum.DSL}>
|
{/* <FormItem name="params" label="函数参数" hidden={pluginType === PluginTypeEnum.DSL}>
|
||||||
<div className={styles.paramsSection}>
|
<div className={styles.paramsSection}>
|
||||||
{functionParams.map((functionParam: FunctionParamFormItemType) => {
|
{functionParams.map((functionParam: FunctionParamFormItemType) => {
|
||||||
const { id, name, type, description } = functionParam;
|
const { id, name, type, description } = functionParam;
|
||||||
@@ -300,7 +300,7 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
|||||||
新增函数参数
|
新增函数参数
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</FormItem> */}
|
||||||
<FormItem name="exampleQuestions" label="示例问题">
|
<FormItem name="exampleQuestions" label="示例问题">
|
||||||
<div className={styles.paramsSection}>
|
<div className={styles.paramsSection}>
|
||||||
{examples.map((example) => {
|
{examples.map((example) => {
|
||||||
@@ -340,7 +340,7 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
|||||||
<FormItem name="url" label="地址" rules={[{ required: true, message: '请输入地址' }]}>
|
<FormItem name="url" label="地址" rules={[{ required: true, message: '请输入地址' }]}>
|
||||||
<Input placeholder="请输入地址" allowClear />
|
<Input placeholder="请输入地址" allowClear />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem name="params" label="参数">
|
<FormItem name="params" label="函数参数">
|
||||||
<div className={styles.paramsSection}>
|
<div className={styles.paramsSection}>
|
||||||
{filters.map((filter: any) => {
|
{filters.map((filter: any) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
|
"suppressImplicitAnyIndexErrors": true,
|
||||||
"ignoreDeprecations": "5.0",
|
"ignoreDeprecations": "5.0",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
|
|||||||
Reference in New Issue
Block a user