[improvement][headless-fe] 1.Added configuration for the large language model in the agent; 2.upgraded React version from 17 to 18; 3.modified some UI effects. (#1049)

* [improvement][semantic-fe] Add model alias setting & Add view permission restrictions to the model permission management tab.
[improvement][semantic-fe] Add permission control to the action buttons for the main domain; apply high sensitivity filtering to the authorization of metrics/dimensions.
[improvement][semantic-fe] Optimize the editing mode in the dimension/metric/datasource components to use the modelId stored in the database for data, instead of relying on the data from the state manager.

* [improvement][semantic-fe] Add time granularity setting in the data source configuration.

* [improvement][semantic-fe] Dictionary import for dimension values supported in Q&A visibility

* [improvement][semantic-fe] Modification of data source creation prompt wording"

* [improvement][semantic-fe] metric market experience optimization

* [improvement][semantic-fe] enhance the analysis of metric trends

* [improvement][semantic-fe] optimize the presentation of metric trend permissions

* [improvement][semantic-fe] add metric trend download functionality

* [improvement][semantic-fe] fix the dimension initialization issue in metric correlation

* [improvement][semantic-fe] Fix the issue of database changes not taking effect when creating based on an SQL data source.

* [improvement][semantic-fe] Optimizing pagination logic and some CSS styles

* [improvement][semantic-fe] Fixing the API for the indicator list by changing "current" to "pageNum"

* [improvement][semantic-fe] Fixing the default value setting for the indicator list

* [improvement][semantic-fe] Adding batch operations for indicators/dimensions/models

* [improvement][semantic-fe] Replacing the single status update API for indicators/dimensions with a batch update API

* [improvement][semantic-fe] Redesigning the indicator homepage to incorporate trend charts and table functionality for indicators

* [improvement][semantic-fe] Optimizing the logic for setting dimension values and editing data sources, and adding system settings functionality

* [improvement][semantic-fe] Upgrading antd version to 5.x, extracting the batch operation button component, optimizing the interaction for system settings, and expanding the configuration generation types for list-to-select component.

* [improvement][semantic-fe] Adding the ability to filter dimensions based on whether they are tags or not.

* [improvement][semantic-fe] Adding the ability to edit relationships between models in the canvas.

* [improvement][semantic-fe] Updating the datePicker component to use dayjs instead.

* [improvement][semantic-fe] Fixing the issue with passing the model ID for dimensions in the indicator market.

* [improvement][semantic-fe] Fixing the abnormal state of the popup when creating a model.

* [improvement][semantic-fe] Adding permission logic for bulk operations in the indicator market.

* [improvement][semantic-fe] Adding the ability to download and transpose data.

* [improvement][semantic-fe] Fixing the initialization issue with the date selection component in the indicator details page when switching time granularity.

* [improvement][semantic-fe] Fixing the logic error in the dimension value setting.

* [improvement][semantic-fe] Fixing the synchronization issue with the question and answer settings information.

* [improvement][semantic-fe] Optimizing the canvas functionality for better performance and user experience.

* [improvement][semantic-fe] Optimizing the update process for drawing model relationship edges in the canvas.

* [improvement][semantic-fe] Changing the line type for canvas connections.

* [improvement][semantic-fe] Replacing the initialization variable from "semantic" to "headless".

* [improvement][semantic-fe] Fixing the missing migration issue for default drill-down dimension configuration in model editing. Additionally, optimizing the data retrieval method for initializing fields in the model.

* [improvement][semantic-fe] Updating the logic for the fieldName.

* [improvement][semantic-fe] Adjusting the position of the metrics tab.

* [improvement][semantic-fe] Changing the 字段名称 to 英文名称.

* [improvement][semantic-fe] Fix metric measurement deletion.

* [improvement][semantic-fe] UI optimization for metric details page.

* [improvement][semantic-fe] UI optimization for metric details page.

* [improvement][semantic-fe] UI adjustment for metric details page.

* [improvement][semantic-fe] The granularity field in the time type of model editing now supports setting it as empty.

* [improvement][semantic-fe] Added field type and metric type to the metric creation options.

* [improvement][semantic-fe] The organization structure selection feature has been added to the permission management.

* [improvement][semantic-fe] Improved user experience for the metric list.

* [improvement][semantic-fe] fix update the metric list.

* [improvement][headless-fe] Added view management functionality.

* [improvement][headless-fe] The view management functionality has been added. This feature allows users to create, edit, and manage different views within the system.

* [improvement][headless-fe] Added model editing side effect detection.

* [improvement][headless-fe] Fixed the logic error in view editing.

* [improvement][headless-fe] Fixed the issue with initializing dimension associations in metric settings.

* [improvement][headless-fe] Added the ability to hide the Q&A settings entry point.

* [improvement][headless-fe] Fixed the issue with selecting search results in metric field creation.

* [improvement][headless-fe] Added search functionality to the field list in model editing.

* [improvement][headless-fe] fix the field list in model editing

* [improvement][headless-fe] Restructured the data for the dimension value settings interface.

* [improvement][headless-fe] Added dynamic variable functionality to model creation based on SQL scripts.

* [improvement][headless-fe] Added support for passing dynamic variables as parameters in the executeSql function.

* [improvement][headless-fe] Resolved the issue where users were unable to select all options for dimensions, metrics, and fields in the metric generation process.

* [improvement][headless-fe] Replaced the term "view" with "dataset"

* [improvement][headless-fe] Added the ability to export metrics and dimensions to a specific target.

* [improvement][headless-fe] Enhanced dataset creation to support the tag mode.

* [improvement][headless-fe] Added tag value setting.

* [improvement][headless-fe] Optimized the tag setting system.

* [improvement][headless-fe] Optimized the tag setting system.

* [improvement][headless-fe] Updated the data initialization for model editing to use API requests instead.

* [improvement][headless-fe] Added search functionality to model management.

* [improvement][headless-fe] Removed field null validation during model editing.

* [improvement][headless-fe] Updated the batch operation button component.

* [improvement][headless-fe] Optimized the logic for initializing indicators in dimension value settings.

* [improvement][headless-fe] Adjusted the length of the input field for model editing names.

* [improvement][headless-fe]  Lock the version of the @ant-design/pro-table component and replace it with @ant-design/pro-components.

* [improvement][headless-fe] Optimized the style of the metrics market and tags market.

* [improvement][headless-fe] The quick creation of model fields now defaults to using the "comment" field for filling.

* [improvement][headless-fe] The quick creation of model fields now defaults to using the "comment" field for filling

* [improvement][headless-fe] The quick creation of model fields now defaults to using the "comment" field for filling.

* [improvement][headless-fe] Fixed the issue where the conditions for metric measurement creation were not being saved correctly.

* [improvement][headless-fe] Default value setting for hiding dimensions.

* [improvement][headless-fe] Updated the file imports in the project.

* [improvement][headless-fe] Adjusted the logic for displaying the tab in the theme domain.

* [improvement][headless-fe] Added term management functionality.

* [improvement][headless-fe] When creating a model, the current metric operator now allows for clearance.

* [improvement][headless-fe] Term management interface transformation

* [improvement][headless-fe] Migrating scaffold version to @umi/max

* [improvement][headless-fe] remove modle column

* [improvement][headless-fe] 1.Added configuration for the large language model in the agent; 2.upgraded React version from 17 to 18; 3.modified some UI effects.
This commit is contained in:
tristanliu
2024-05-30 10:40:01 +08:00
committed by GitHub
parent 8aab359def
commit 6aaf471582
22 changed files with 1951 additions and 2451 deletions

View File

@@ -1,6 +1,6 @@
import { Settings as LayoutSettings } from '@ant-design/pro-layout'; import { ProLayoutProps } from '@ant-design/pro-components';
const Settings: LayoutSettings & { const Settings: ProLayoutProps & {
pwa?: boolean; pwa?: boolean;
logo?: string; logo?: string;
} = { } = {
@@ -14,11 +14,11 @@ const Settings: LayoutSettings & {
title: '', title: '',
pwa: false, pwa: false,
iconfontUrl: '//at.alicdn.com/t/c/font_4120566_x5c4www9bqm.js', iconfontUrl: '//at.alicdn.com/t/c/font_4120566_x5c4www9bqm.js',
splitMenus: true, // splitMenus: true,
menu: { // menu: {
autoClose: false, // autoClose: false,
ignoreFlatMenu: true, // ignoreFlatMenu: true,
}, // },
}; };
export const publicPath = '/webapp/'; export const publicPath = '/webapp/';

View File

@@ -57,7 +57,6 @@
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.2.6", "@ant-design/icons": "^5.2.6",
"@ant-design/pro-components": "2.7.0", "@ant-design/pro-components": "2.7.0",
"@ant-design/pro-layout": "^7.17.15",
"@antv/dom-util": "^2.0.4", "@antv/dom-util": "^2.0.4",
"@antv/g6": "^4.8.23", "@antv/g6": "^4.8.23",
"@antv/g6-core": "^0.8.23", "@antv/g6-core": "^0.8.23",
@@ -83,22 +82,20 @@
"jsencrypt": "^3.0.1", "jsencrypt": "^3.0.1",
"lodash": "^4.17.11", "lodash": "^4.17.11",
"moment": "^2.29.1", "moment": "^2.29.1",
"nprogress": "^0.2.0",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"omit.js": "^2.0.2", "omit.js": "^2.0.2",
"path-to-regexp": "^2.4.0", "path-to-regexp": "^2.4.0",
"qs": "^6.9.0", "qs": "^6.9.0",
"query-string": "^9.0.0", "query-string": "^9.0.0",
"react": "^17.0.0", "react": "^18.3.1",
"react-ace": "^9.4.1", "react-ace": "^9.4.1",
"react-dev-inspector": "^1.8.4", "react-dom": "^18.3.1",
"react-dom": "^17.0.2", "react-spinners": "^0.13.8",
"react-fast-marquee": "^1.6.0",
"react-helmet-async": "^1.0.4",
"react-spinners": "^0.10.6",
"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": "^1.1.6", "supersonic-chat-sdk": "^1.1.7",
"supersonic-insights-flow-components": "^1.4.9", "supersonic-insights-flow-components": "^1.4.9",
"umi-request": "1.4.0" "umi-request": "1.4.0"
}, },
@@ -114,11 +111,11 @@
"@types/lodash": "^4.14.144", "@types/lodash": "^4.14.144",
"@types/pinyin": "^2.8.3", "@types/pinyin": "^2.8.3",
"@types/qs": "^6.5.3", "@types/qs": "^6.5.3",
"@types/react": "^17.0.0", "@types/react": "18.3.1",
"@types/react-dom": "^17.0.0", "@types/react-dom": "^18.3.0",
"@types/react-helmet": "^6.1.0", "@types/react-helmet": "^6.1.0",
"@umijs/max": "^4.2.5",
"@umijs/fabric": "^4.0.1", "@umijs/fabric": "^4.0.1",
"@umijs/max": "^4.2.5",
"@umijs/plugin-model": "^2.6.2", "@umijs/plugin-model": "^2.6.2",
"carlo": "^0.9.46", "carlo": "^0.9.46",
"cross-port-killer": "^1.1.1", "cross-port-killer": "^1.1.1",
@@ -141,7 +138,7 @@
"node": ">=16.0.0 <20.0.0" "node": ">=16.0.0 <20.0.0"
}, },
"resolutions": { "resolutions": {
"@types/react": "17.0.0" "@types/react": "18.3.1"
}, },
"__npminstall_done": false "__npminstall_done": false
} }

View File

@@ -1,6 +1,6 @@
import RightContent from '@/components/RightContent'; import RightContent from '@/components/RightContent';
import S2Icon, { ICON } from '@/components/S2Icon'; import S2Icon, { ICON } from '@/components/S2Icon';
import type { Settings as LayoutSettings } from '@ant-design/pro-layout'; import type { Settings as LayoutSettings } from '@ant-design/pro-components';
import { Space, Spin, ConfigProvider } from 'antd'; import { Space, Spin, ConfigProvider } from 'antd';
import ScaleLoader from 'react-spinners/ScaleLoader'; import ScaleLoader from 'react-spinners/ScaleLoader';
import { history, RunTimeLayoutConfig } from '@umijs/max'; import { history, RunTimeLayoutConfig } from '@umijs/max';
@@ -13,6 +13,7 @@ import { Copilot } from 'supersonic-chat-sdk';
import { configProviderTheme } from '../config/themeSettings'; import { configProviderTheme } from '../config/themeSettings';
export { request } from './services/request'; export { request } from './services/request';
import { ROUTE_AUTH_CODES } from '../config/routes'; import { ROUTE_AUTH_CODES } from '../config/routes';
import AppPage from './pages/index';
const replaceRoute = '/'; const replaceRoute = '/';
@@ -145,7 +146,8 @@ export const layout: RunTimeLayoutConfig = (params) => {
height: location.pathname.includes('chat') ? 'calc(100vh - 56px)' : undefined, height: location.pathname.includes('chat') ? 'calc(100vh - 56px)' : undefined,
}} }}
> >
{dom} <AppPage dom={dom} />
{/* {dom} */}
{history.location.pathname !== '/chat' && !isMobile && ( {history.location.pathname !== '/chat' && !isMobile && (
<Copilot token={getToken() || ''} isDeveloper /> <Copilot token={getToken() || ''} isDeveloper />
)} )}

View File

@@ -1,6 +1,6 @@
.title { .title {
font-family: var(--tencent-font-family); font-family: var(--tencent-font-family);
margin-bottom: 5px; // margin-bottom: 5px;
} }
.subTitleContainer { .subTitleContainer {

View File

@@ -96,42 +96,35 @@ ol {
} }
} }
.ant-card-body { // .ant-card-body {
padding: 24px !important; // padding: 24px !important;
} // }
.ant-modal-body { .ant-modal-body {
padding: 24px; padding: 24px;
} }
.ant-pro-page-container-children-content { // .ant-pro-page-container-children-content {
margin: 12px 12px 0 !important; // margin: 12px 12px 0 !important;
} // }
// .ant-page-header { // .ant-page-header {
// padding-bottom: 10px !important; // padding-bottom: 10px !important;
// } // }
.ant-spin-spinning { // .ant-spin-spinning {
display: flex !important; // display: flex !important;
align-items: center !important; // align-items: center !important;
justify-content: center !important; // justify-content: center !important;
} // }
// .ant-table-selection-extra {
// .ant-dropdown-trigger {
// display: none !important;
// }
// }
.ant-table-selection-extra {
.ant-dropdown-trigger {
display: none !important;
}
}
.initialLoading {
.ant-spin-spinning {
max-height: none !important;
}
.loadingPlaceholder {
height: 100vh;
}
}
.ant-pro-layout .ant-pro-layout-bg-list { .ant-pro-layout .ant-pro-layout-bg-list {
background: #fafafb; background: #fafafb;
} }
@@ -146,56 +139,39 @@ ol {
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.ant-table-wrapper {
.ant-spin .ant-spin-dot {
// .ant-menu-root>.ant-menu-item, font-size: 30px;
// .ant-menu-root>.ant-menu-submenu { }
// font-weight: bold; }
// font-size: 14px;
// &>span>a,
// &>a {
// color: white;
// &:hover {
// color: white;
// }
// }
// &:hover {
// background-color: #296DF3!important;
// }
// }
.ant-menu-root>.ant-menu-item.ant-menu-item-selected { .ant-menu-root>.ant-menu-item.ant-menu-item-selected {
// background-color: #296DF3!important;
color: var(--tme-primary-color); color: var(--tme-primary-color);
font-size: 15px;
font-weight: 500; font-weight: 500;
} }
.ant-menu-light.ant-menu-horizontal >.ant-menu-item-selected::after { .ant-menu-light.ant-menu-horizontal >.ant-menu-item:hover {
background: #f0f5ff;
}
.ant-menu-light .ant-menu-item:not(.ant-menu-item-selected):not(.ant-menu-submenu-selected):hover {
color: var(--tme-primary-color);
}
.ant-menu-light.ant-menu-horizontal >.ant-menu-item-selected:hover::after {
border-bottom-color: var(--tme-primary-color);
border-bottom-width: 2px; border-bottom-width: 2px;
}
.ant-menu-light.ant-menu-horizontal >.ant-menu-item-selected::after {
border-bottom-color: var(--tme-primary-color); border-bottom-color: var(--tme-primary-color);
border-bottom-width: 2px;
} }
// .ant-menu-light.ant-menu-horizontal >.ant-menu-item-selected::hover { .ant-menu-light.ant-menu-horizontal >.ant-menu-item:hover::after {
// border-bottom-width: 2px; border-bottom-color: var(--tme-primary-color);
// border-bottom-color: var(--tme-primary-color);
// }
.ant-pro-top-nav-header-logo h1 {
// font-size: 18px;
color: var(--tme-primary-color)
} }
.ant-pro-table-list-toolbar-container-mobile {
flex-direction: unset;
}
// .ant-pro-top-nav-header-main-left {
// min-width: 100px !important;
// }
// .ant-pro-top-nav-header-logo {
// min-width: 100px !important;
// }
.logo { .logo {
position: relative; position: relative;
@@ -291,4 +267,50 @@ ol {
color: rgb(38, 38, 38); color: rgb(38, 38, 38);
} }
} }
.ant-form-item .ant-form-item-label > label {
font-family: "tencentFont", sans-serif;
margin-right: 10px;
}
.supersonicForm {
padding: 0 20px;
:global {
.ant-input-search .ant-input-search-button {
height: 42px;
}
.ant-switch.ant-switch-checked {
background: var(--tme-primary-color);
}
.ant-form-item .ant-form-item-label > label {
color:#262626;
}
.ant-form-item-label {
font-family: "tencentFont", sans-serif;
margin-right: 10px;
}
.ant-input {
padding: 9px 14px 9px 12px;
}
.ant-select {
&.ant-select-single {
height: auto;
}
&.ant-select-multiple {
.ant-select-selector {
padding: 6px 14px 6px 12px;
}
}
.ant-select-selector {
padding: 5px 14px 5px 12px;
.ant-select-selection-placeholder {
padding: 0px 8px 0px 8px;
}
.ant-select-selection-overflow-item {
.ant-select-selection-item {
color: rgb(22, 119, 255);
background-color: rgb(230, 244, 255);
}
}
}
}
}
}

View File

@@ -1,9 +1,23 @@
import { Form, Modal, Input, Button, Switch } from 'antd'; import {
Form,
Modal,
Input,
Button,
Switch,
Tabs,
Slider,
InputNumber,
Select,
Row,
Col,
Space,
} from 'antd';
import { AgentType } from './type'; import { AgentType } from './type';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import styles from './style.less'; import styles from './style.less';
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons'; import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
import { uuid } from '@/utils/utils'; import { uuid } from '@/utils/utils';
import globalStyles from '@/global.less';
const FormItem = Form.Item; const FormItem = Form.Item;
const { TextArea } = Input; const { TextArea } = Input;
@@ -17,6 +31,7 @@ type Props = {
const AgentModal: React.FC<Props> = ({ editAgent, onSaveAgent, onCancel }) => { const AgentModal: React.FC<Props> = ({ editAgent, onSaveAgent, onCancel }) => {
const [saveLoading, setSaveLoading] = useState(false); const [saveLoading, setSaveLoading] = useState(false);
const [examples, setExamples] = useState<{ id: string; question?: string }[]>([]); const [examples, setExamples] = useState<{ id: string; question?: string }[]>([]);
const [formData, setFormData] = useState<any>({});
const [form] = Form.useForm(); const [form] = Form.useForm();
useEffect(() => { useEffect(() => {
@@ -32,7 +47,8 @@ const AgentModal: React.FC<Props> = ({ editAgent, onSaveAgent, onCancel }) => {
const layout = { const layout = {
labelCol: { span: 6 }, labelCol: { span: 6 },
wrapperCol: { span: 14 }, wrapperCol: { span: 16 },
// layout: 'vertical',
}; };
const onOk = async () => { const onOk = async () => {
@@ -48,6 +64,135 @@ const AgentModal: React.FC<Props> = ({ editAgent, onSaveAgent, onCancel }) => {
setSaveLoading(false); setSaveLoading(false);
}; };
const formTabList = [
{
label: '基本信息',
children: (
<>
<FormItem
name="name"
label="名称"
rules={[{ required: true, message: '请输入助理名称' }]}
>
<Input placeholder="请输入助理名称" />
</FormItem>
{/* <FormItem name={['visualConfig', 'defaultShowType']} label="问答默认格式">
<Select
placeholder=""
options={[
{
label: '文本',
value: 'TEXT',
},
{
label: '表格',
value: 'TABLE',
},
{
label: '图表',
value: 'WIDGET',
},
]}
/>
</FormItem> */}
<FormItem name="enableSearch" label="支持联想" valuePropName="checked">
<Switch />
</FormItem>
<FormItem
name={['multiTurnConfig', 'enableMultiTurn']}
label="开启多轮"
valuePropName="checked"
>
<Switch />
</FormItem>
<FormItem name="examples" label="示例问题">
<div className={styles.paramsSection}>
{examples.map((example) => {
const { id, question } = example;
return (
<div className={styles.filterRow} key={id}>
<Input
placeholder="示例问题"
value={question}
className={styles.questionExample}
onChange={(e) => {
example.question = e.target.value;
setExamples([...examples]);
}}
allowClear
/>
<DeleteOutlined
onClick={() => {
setExamples(examples.filter((item) => item.id !== id));
}}
/>
</div>
);
})}
<Button
onClick={() => {
setExamples([...examples, { id: uuid() }]);
}}
>
<PlusOutlined />
</Button>
</div>
</FormItem>
<FormItem name="description" label="描述">
<TextArea placeholder="请输入助理描述" />
</FormItem>
</>
),
},
{
label: '大模型配置',
children: (
<>
<FormItem name={['llmConfig', 'provider']} label="模型提供方式">
<Select placeholder="">
{['OPEN_AI'].map((item) => (
<Select.Option key={item} value={item}>
{item}
</Select.Option>
))}
</Select>
</FormItem>
<FormItem name={['llmConfig', 'modelName']} label="大模型名称">
<Input placeholder="请输入大模型名称" />
</FormItem>
<FormItem name={['llmConfig', 'baseUrl']} label="Base URL">
<Input placeholder="请输入Base URL" />
</FormItem>
<FormItem
name={['llmConfig', 'apiKey']}
label="API KEY"
// hidden={formData?.llmConfig?.provider === 'LOCAL_AI'}
>
<Input placeholder="请输入API KEY" />
</FormItem>
<FormItem name={['llmConfig', 'temperature']} label="回复随机性">
<Slider
min={0}
max={1}
step={0.1}
marks={{
0: '精准',
1: '随机',
}}
defaultValue={0}
/>
</FormItem>
<FormItem name={['llmConfig', 'timeOut']} label="超时时间(秒)">
<InputNumber />
</FormItem>
</>
),
},
];
return ( return (
<Modal <Modal
open open
@@ -57,50 +202,32 @@ const AgentModal: React.FC<Props> = ({ editAgent, onSaveAgent, onCancel }) => {
onOk={onOk} onOk={onOk}
onCancel={onCancel} onCancel={onCancel}
> >
<Form {...layout} form={form} initialValues={{ enableSearch: true }}> <Form
<FormItem name="name" label="名称" rules={[{ required: true, message: '请输入助理名称' }]}> {...layout}
<Input placeholder="请输入助理名称" /> form={form}
</FormItem> initialValues={{
<FormItem name="enableSearch" label="支持联想" valuePropName="checked"> enableSearch: true,
<Switch checkedChildren="开启" unCheckedChildren="关闭" /> llmConfig: {
</FormItem> timeOut: 60,
<FormItem name="examples" label="示例问题"> provider: 'OPEN_AI',
<div className={styles.paramsSection}> },
{examples.map((example) => { }}
const { id, question } = example; onValuesChange={(value, values) => {
return ( setFormData(values);
<div className={styles.filterRow} key={id}> }}
<Input className={globalStyles.supersonicForm}
placeholder="示例问题" >
value={question} <Tabs
className={styles.questionExample} tabPosition={'left'}
onChange={(e) => { items={formTabList.map((item) => {
example.question = e.target.value; const { label, children } = item;
setExamples([...examples]); return {
}} label,
allowClear key: label,
/> children,
<DeleteOutlined };
onClick={() => { })}
setExamples(examples.filter((item) => item.id !== id)); />
}}
/>
</div>
);
})}
<Button
onClick={() => {
setExamples([...examples, { id: uuid() }]);
}}
>
<PlusOutlined />
</Button>
</div>
</FormItem>
<FormItem name="description" label="描述">
<TextArea placeholder="请输入助理描述" />
</FormItem>
</Form> </Form>
</Modal> </Modal>
); );

View File

@@ -93,19 +93,50 @@ const ToolsSection: React.FC<Props> = ({ currentAgent, onSaveAgent, onEditAgent,
onEditAgent(currentAgent); onEditAgent(currentAgent);
}} }}
> >
</Button> </Button>
</div> </div>
<div className={styles.infoContent}> <div className={styles.infoContent}>
<div className={styles.infoItem}> <div className={styles.infoItem}>
<span className={styles.label}> </span>
<Space> <Space>
{currentAgent?.examples?.map((item) => ( {currentAgent?.examples?.map((item) => (
<Tag key={item}>{item}</Tag> <Tag key={item}>{item}</Tag>
))} ))}
</Space> </Space>
</div> </div>
<div className={styles.infoItem}>{currentAgent?.description}</div> <div className={styles.infoItem}>
<span className={styles.label}> </span>
{currentAgent?.description}
</div>
</div>
</div>
<div className={styles.basicInfo}>
<div className={styles.basicInfoTitle}></div>
<div className={styles.infoContent}>
<div className={styles.infoItem}>
<span className={styles.label}> </span>
{currentAgent?.llmConfig?.provider}
</div>
<div className={styles.infoItem}>
<span className={styles.label}>:</span>
{currentAgent?.llmConfig?.modelName}
</div>
<div className={styles.infoItem}>
<span className={styles.label}>Base URL: </span>
{currentAgent?.llmConfig?.baseUrl}
</div>
<div className={styles.infoItem}>
<span className={styles.label}>API KEY:</span>
{currentAgent?.llmConfig?.apiKey}
</div>
<div className={styles.infoItem}>
<span className={styles.label}>: </span>
{currentAgent?.llmConfig?.temperature}
</div>
<div className={styles.infoItem}>
<span className={styles.label}>(): </span> {currentAgent?.llmConfig?.timeOut}
</div>
</div> </div>
</div> </div>
<div className={styles.toolSection}> <div className={styles.toolSection}>

View File

@@ -15,13 +15,13 @@
} }
.content { .content {
margin-top: 20px; // margin-top: 20px;
.searchBar { .searchBar {
display: flex; display: flex;
align-items: center; align-items: center;
column-gap: 30px; column-gap: 30px;
margin-bottom: 40px; margin-bottom: 20px;
justify-content: right;
.searchControl { .searchControl {
width: 500px; width: 500px;
} }
@@ -195,6 +195,14 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
row-gap: 12px; row-gap: 12px;
.infoItem {
margin-bottom: 10px;
.label {
font-family: var(--tencent-font-family);
margin-right: 10px;
font-size: 14px;
}
}
} }
} }

View File

@@ -27,7 +27,7 @@ export const AGENT_TOOL_TYPE_LIST = [
export enum QueryModeEnum { export enum QueryModeEnum {
METRIC = 'METRIC', METRIC = 'METRIC',
TAG = 'TAG', DETAIL = 'DETAIL',
} }
export const QUERY_MODE_LIST = [ export const QUERY_MODE_LIST = [
@@ -36,8 +36,8 @@ export const QUERY_MODE_LIST = [
value: QueryModeEnum.METRIC, value: QueryModeEnum.METRIC,
}, },
{ {
label: '标签模式', label: '明细模式',
value: QueryModeEnum.TAG, value: QueryModeEnum.DETAIL,
}, },
]; ];
@@ -56,6 +56,22 @@ export type AgentConfigType = {
tools: AgentToolType[]; tools: AgentToolType[];
}; };
export type LlmConfigType = {
provider: string;
baseUrl: string;
apiKey: string;
modelName: string;
temperature: number;
timeOut: number;
};
export type MultiTurnConfig = {
enableMultiTurn: boolean;
};
export type VisualConfig = {
defaultShowType: string;
};
export type AgentType = { export type AgentType = {
id?: number; id?: number;
name?: string; name?: string;
@@ -68,6 +84,9 @@ export type AgentType = {
status?: 0 | 1; status?: 0 | 1;
enableSearch?: 0 | 1; enableSearch?: 0 | 1;
agentConfig?: AgentConfigType; agentConfig?: AgentConfigType;
llmConfig?: LlmConfigType;
multiTurnConfig?: MultiTurnConfig;
visualConfig?: VisualConfig;
}; };
export type ModelType = { export type ModelType = {

View File

@@ -191,6 +191,17 @@ const ModelBasicForm: React.FC<Props> = ({
<FormItem name="description" label="模型描述"> <FormItem name="description" label="模型描述">
<TextArea placeholder="请输入模型描述" /> <TextArea placeholder="请输入模型描述" />
</FormItem> </FormItem>
<FormItem
name={['ext', 'usId']}
label="上游任务ID"
>
<Select
mode="tags"
placeholder="输入ID后回车确认多ID输入、复制粘贴支持英文逗号自动分隔"
tokenSeparators={[',']}
maxTagCount={9}
/>
</FormItem>
</Spin> </Spin>
); );
}; };

View File

@@ -337,26 +337,10 @@ const ModelCreateForm: React.FC<CreateFormProps> = ({
}; };
const formatterInitData = (columns: any[], extendParams: Record<string, any> = {}) => { const formatterInitData = (columns: any[], extendParams: Record<string, any> = {}) => {
const { const { modelDetail, filterSql, drillDownDimensions = [] } = modelItem;
id,
name,
bizName,
description,
modelDetail,
databaseId,
filterSql,
alias,
drillDownDimensions = [],
} = modelItem;
const { dimensions, identifiers, measures } = modelDetail || {}; const { dimensions, identifiers, measures } = modelDetail || {};
const initValue = { const initValue = {
id, ...modelItem,
name,
bizName,
description,
databaseId,
filterSql,
alias,
drillDownDimensions: Array.isArray(drillDownDimensions) drillDownDimensions: Array.isArray(drillDownDimensions)
? drillDownDimensions.map((item) => { ? drillDownDimensions.map((item) => {
return item.dimensionId; return item.dimensionId;

View File

@@ -34,7 +34,7 @@ const ClassMetricTable: React.FC<Props> = ({}) => {
total: 0, total: 0,
}; };
const [pagination, setPagination] = useState(defaultPagination); const [pagination, setPagination] = useState(defaultPagination);
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(true);
const [dataSource, setDataSource] = useState<ISemantic.ITagItem[]>([]); const [dataSource, setDataSource] = useState<ISemantic.ITagItem[]>([]);
const [tagItem, setTagItem] = useState<ISemantic.ITagItem>(); const [tagItem, setTagItem] = useState<ISemantic.ITagItem>();
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);

View File

@@ -3,7 +3,7 @@ import { ProTable } from '@ant-design/pro-components';
import { message, Space, Popconfirm, Spin } from 'antd'; import { message, Space, Popconfirm, Spin } from 'antd';
import MetricAddClass from './components/MetricAddClass'; import MetricAddClass from './components/MetricAddClass';
import React, { useRef, useState, useEffect } from 'react'; import React, { useRef, useState, useEffect } from 'react';
import { history, useModel } from '@umijs/max'; import { history, useModel } from '@umijs/max';
import { SENSITIVE_LEVEL_ENUM } from '../constant'; import { SENSITIVE_LEVEL_ENUM } from '../constant';
import { import {
queryMetric, queryMetric,
@@ -16,16 +16,14 @@ import {
import MetricFilter from './components/MetricFilter'; import MetricFilter from './components/MetricFilter';
import MetricInfoCreateForm from '../components/MetricInfoCreateForm'; import MetricInfoCreateForm from '../components/MetricInfoCreateForm';
import MetricCardList from './components/MetricCardList'; import MetricCardList from './components/MetricCardList';
import { StatusEnum } from '../enum'; import { StatusEnum } from '../enum';
import moment from 'moment'; import moment from 'moment';
import styles from './style.less'; import styles from './style.less';
import { ISemantic } from '../data'; import { ISemantic } from '../data';
import BatchCtrlDropDownButton from '@/components/BatchCtrlDropDownButton'; import BatchCtrlDropDownButton from '@/components/BatchCtrlDropDownButton';
import { ColumnsConfig } from '../components/TableColumnRender'; import { ColumnsConfig } from '../components/TableColumnRender';
type Props = { type Props = {};
};
type QueryMetricListParams = { type QueryMetricListParams = {
id?: string; id?: string;
@@ -36,7 +34,7 @@ type QueryMetricListParams = {
[key: string]: any; [key: string]: any;
}; };
const ClassMetricTable: React.FC<Props> = ({ }) => { const ClassMetricTable: React.FC<Props> = ({}) => {
const { initialState = {} } = useModel('@@initialState'); const { initialState = {} } = useModel('@@initialState');
const { currentUser = {} } = initialState as any; const { currentUser = {} } = initialState as any;
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false); const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
@@ -46,7 +44,7 @@ const ClassMetricTable: React.FC<Props> = ({ }) => {
total: 0, total: 0,
}; };
const [pagination, setPagination] = useState(defaultPagination); const [pagination, setPagination] = useState(defaultPagination);
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(true);
const [dataSource, setDataSource] = useState<ISemantic.IMetricItem[]>([]); const [dataSource, setDataSource] = useState<ISemantic.IMetricItem[]>([]);
const [metricItem, setMetricItem] = useState<ISemantic.IMetricItem>(); const [metricItem, setMetricItem] = useState<ISemantic.IMetricItem>();
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
@@ -154,8 +152,9 @@ const ClassMetricTable: React.FC<Props> = ({ }) => {
}; };
const handleMetricEdit = (metricItem: ISemantic.IMetricItem) => { const handleMetricEdit = (metricItem: ISemantic.IMetricItem) => {
setMetricItem(metricItem); // setMetricItem(metricItem);
setCreateModalVisible(true); // setCreateModalVisible(true);
history.push(`/model/metric/edit/${metricItem.id}`);
}; };
const queryBatchUpdatePublish = async (ids: React.Key[], status: boolean) => { const queryBatchUpdatePublish = async (ids: React.Key[], status: boolean) => {
@@ -458,4 +457,4 @@ const ClassMetricTable: React.FC<Props> = ({ }) => {
</> </>
); );
}; };
export default ClassMetricTable export default ClassMetricTable;

View File

@@ -38,6 +38,7 @@ import { createMetric, updateMetric, mockMetricAlias, getMetricTags } from '../.
import { MetricSettingKey, MetricSettingWording } from '../constants'; import { MetricSettingKey, MetricSettingWording } from '../constants';
import { ISemantic } from '../../data'; import { ISemantic } from '../../data';
import { history } from '@umijs/max'; import { history } from '@umijs/max';
import globalStyles from '@/global.less';
export type CreateFormProps = { export type CreateFormProps = {
datasourceId?: number; datasourceId?: number;
@@ -868,7 +869,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
</div> </div>
<div className={styles.infoCardContainer}> <div className={styles.infoCardContainer}>
<Form <Form
className={styles.supersonicForm} className={globalStyles.supersonicForm}
{...formLayout} {...formLayout}
form={form} form={form}
initialValues={{ initialValues={{

View File

@@ -124,7 +124,6 @@ const OverviewContainer: React.FC<Props> = ({ mode }) => {
}; };
const handleModelChange = (model?: ISemantic.IModelItem) => { const handleModelChange = (model?: ISemantic.IModelItem) => {
console.log(model, 1111);
if (!model) { if (!model) {
return; return;
} }

View File

@@ -167,19 +167,6 @@ const ViewCreateFormModal: React.FC<ModelCreateFormModalProps> = ({
return ( return (
<> <>
<div style={{ display: currentStep === 1 ? 'block' : 'none' }}> <div style={{ display: currentStep === 1 ? 'block' : 'none' }}>
{/* <div style={{ marginBottom: 10, paddingLeft: 12 }}>
<Radio.Group
buttonStyle="solid"
value={queryType}
onChange={(e) => {
setQueryType(e.target.value);
}}
>
<Radio.Button value="METRIC">指标模式</Radio.Button>
<Radio.Button value="TAG">标签模式</Radio.Button>
</Radio.Group>
</div> */}
<ViewModelConfigTransfer <ViewModelConfigTransfer
key={queryType} key={queryType}
queryType={queryType} queryType={queryType}

View File

@@ -7,7 +7,7 @@ import { createView, updateView, getDimensionList, queryMetric, getTagList } fro
import { ISemantic } from '../../data'; import { ISemantic } from '../../data';
import DefaultSettingForm from './DefaultSettingForm'; import DefaultSettingForm from './DefaultSettingForm';
import { isArrayOfValues } from '@/utils/utils'; import { isArrayOfValues } from '@/utils/utils';
import { ProCard } from '@ant-design/pro-components'; import { ProCard } from '@ant-design/pro-components';
import { TransType, ChatConfigType } from '../../enum'; import { TransType, ChatConfigType } from '../../enum';
import { number } from 'echarts'; import { number } from 'echarts';
@@ -141,7 +141,7 @@ const ViewSearchFormModal: React.FC<ModelCreateFormModalProps> = ({
)} )}
{viewItem?.queryType === TransType.TAG && ( {viewItem?.queryType === TransType.TAG && (
<ProCard title="标签模式"> <ProCard title="明细模式">
<DefaultSettingForm form={form} tagList={tagList} chatConfigType={ChatConfigType.TAG} /> <DefaultSettingForm form={form} tagList={tagList} chatConfigType={ChatConfigType.TAG} />
</ProCard> </ProCard>
)} )}

View File

@@ -57,14 +57,13 @@ const DomainManagerTab: React.FC<Props> = ({
children: children:
showModelType === 'list' ? ( showModelType === 'list' ? (
<OverView <OverView
key={selectDomainId}
modelList={modelList} modelList={modelList}
onModelChange={(model) => { onModelChange={(model) => {
handleModelChange(model); handleModelChange(model);
}} }}
/> />
) : ( ) : (
<div style={{ width: '100%' }}> <div style={{ width: '100%' }} key={selectDomainId}>
<SemanticGraphCanvas /> <SemanticGraphCanvas />
{/* <HeadlessFlows /> */} {/* <HeadlessFlows /> */}
</div> </div>
@@ -208,6 +207,7 @@ const DomainManagerTab: React.FC<Props> = ({
className={styles.tab} className={styles.tab}
items={!isModel ? tabItem : isModelItem} items={!isModel ? tabItem : isModelItem}
activeKey={getActiveKey()} activeKey={getActiveKey()}
// destroyInactiveTabPane
tabBarExtraContent={{ tabBarExtraContent={{
right: right:
getActiveKey() === 'overview' ? ( getActiveKey() === 'overview' ? (

View File

@@ -2,7 +2,7 @@ import { Space, Tag, Typography } from 'antd';
import { StatusEnum } from '../enum'; import { StatusEnum } from '../enum';
import { SENSITIVE_LEVEL_ENUM, SENSITIVE_LEVEL_COLOR } from '../constant'; import { SENSITIVE_LEVEL_ENUM, SENSITIVE_LEVEL_COLOR } from '../constant';
import { TagsOutlined, ReadOutlined } from '@ant-design/icons'; import { TagsOutlined, ReadOutlined } from '@ant-design/icons';
import { history } from 'umi'; import { history } from '@umijs/max';
import { ISemantic } from '../data'; import { ISemantic } from '../data';
import { isString } from 'lodash'; import { isString } from 'lodash';
import dayjs from 'dayjs'; import dayjs from 'dayjs';

View File

@@ -445,43 +445,5 @@
} }
} }
.supersonicForm {
padding: 0 20px;
:global {
.ant-input-search .ant-input-search-button {
height: 42px;
}
.ant-form-item .ant-form-item-label > label {
color:#262626;
}
.ant-form-item-label {
font-family: "tencentFont", sans-serif;
}
.ant-input {
padding: 9px 14px 9px 12px;
}
.ant-select {
&.ant-select-single {
height: auto;
}
&.ant-select-multiple {
.ant-select-selector {
padding: 6px 14px 6px 12px;
}
}
.ant-select-selector {
padding: 5px 14px 5px 12px;
.ant-select-selection-placeholder {
padding: 0px 8px 0px 8px;
}
.ant-select-selection-overflow-item {
.ant-select-selection-item {
color: rgb(22, 119, 255);
background-color: rgb(230, 244, 255);
}
}
}
}
}
}

View File

@@ -0,0 +1,39 @@
import { useEffect, useTransition } from 'react';
import { useLocation } from '@umijs/max';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
NProgress.configure({ showSpinner: false });
const startProgress = () => {
NProgress.start();
};
const stopProgress = () => {
NProgress.done();
};
const Page = ({ dom }) => {
const [isPending, startTransition] = useTransition();
const location = useLocation();
useEffect(() => {
startTransition(() => {
startProgress();
});
return () => {
stopProgress();
};
}, [location]);
useEffect(() => {
if (!isPending) {
stopProgress();
}
}, [isPending]);
return <>{dom}</>;
};
export default Page;

3756
webapp/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff