mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-17 16:02:14 +00:00
[improvement][semantic-fe] Refactor database settings functionality.
This commit is contained in:
@@ -28,7 +28,7 @@ const ClassDataSourceTypeModal: React.FC<Props> = ({
|
||||
onCancel,
|
||||
dispatch,
|
||||
}) => {
|
||||
const { selectDomainId, dataBaseConfig, selectModelId } = domainManger;
|
||||
const { selectDomainId } = domainManger;
|
||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||
|
||||
const [dataSourceModalVisible, setDataSourceModalVisible] = useState(false);
|
||||
@@ -77,66 +77,47 @@ const ClassDataSourceTypeModal: React.FC<Props> = ({
|
||||
centered
|
||||
closable={false}
|
||||
>
|
||||
{dataBaseConfig && dataBaseConfig.id ? (
|
||||
<Row gutter={16} style={{ marginTop: '0px' }}>
|
||||
<Col span={12}>
|
||||
<Card
|
||||
hoverable
|
||||
style={{ height: 220 }}
|
||||
onClick={() => {
|
||||
onTypeChange?.('fast');
|
||||
setCreateDataSourceModalOpen(false);
|
||||
<Row gutter={16} style={{ marginTop: '0px' }}>
|
||||
<Col span={12}>
|
||||
<Card
|
||||
hoverable
|
||||
style={{ height: 220 }}
|
||||
onClick={() => {
|
||||
onTypeChange?.('fast');
|
||||
setCreateDataSourceModalOpen(false);
|
||||
|
||||
setDataSourceModalVisible(true);
|
||||
}}
|
||||
cover={
|
||||
<CoffeeOutlined
|
||||
width={240}
|
||||
style={{ paddingTop: '45px', height: 120, fontSize: '48px', color: '#1890ff' }}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Meta title="快速创建" description="自动进行数据源可视化创建" />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Card
|
||||
onClick={() => {
|
||||
onTypeChange?.('normal');
|
||||
setCreateDataSourceModalOpen(false);
|
||||
setDataSourceModalVisible(true);
|
||||
}}
|
||||
cover={
|
||||
<CoffeeOutlined
|
||||
width={240}
|
||||
style={{ paddingTop: '45px', height: 120, fontSize: '48px', color: '#1890ff' }}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Meta title="快速创建" description="自动进行数据源可视化创建" />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Card
|
||||
onClick={() => {
|
||||
onTypeChange?.('normal');
|
||||
setCreateDataSourceModalOpen(false);
|
||||
|
||||
setCreateModalVisible(true);
|
||||
}}
|
||||
hoverable
|
||||
style={{ height: 220 }}
|
||||
cover={
|
||||
<ConsoleSqlOutlined
|
||||
style={{ paddingTop: '45px', height: 120, fontSize: '48px', color: '#1890ff' }}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Meta title="SQL脚本" description="自定义SQL脚本创建数据源" />
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
) : (
|
||||
<Result
|
||||
status="warning"
|
||||
subTitle="创建数据源需要先完成数据库设置"
|
||||
extra={
|
||||
<Button
|
||||
type="primary"
|
||||
key="console"
|
||||
onClick={() => {
|
||||
history.replace(`/semanticModel/${selectDomainId}/0/dataBase`);
|
||||
onCancel?.();
|
||||
}}
|
||||
>
|
||||
去设置
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
setCreateModalVisible(true);
|
||||
}}
|
||||
hoverable
|
||||
style={{ height: 220 }}
|
||||
cover={
|
||||
<ConsoleSqlOutlined
|
||||
style={{ paddingTop: '45px', height: 120, fontSize: '48px', color: '#1890ff' }}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Meta title="SQL脚本" description="自定义SQL脚本创建数据源" />
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</Modal>
|
||||
|
||||
{dataSourceModalVisible && (
|
||||
|
||||
@@ -83,6 +83,7 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
{
|
||||
dataIndex: 'id',
|
||||
title: 'ID',
|
||||
width: 80,
|
||||
order: 100,
|
||||
},
|
||||
{
|
||||
@@ -92,16 +93,19 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
{
|
||||
dataIndex: 'alias',
|
||||
title: '别名',
|
||||
width: 300,
|
||||
ellipsis: true,
|
||||
search: false,
|
||||
},
|
||||
{
|
||||
dataIndex: 'bizName',
|
||||
title: '字段名称',
|
||||
order: 9,
|
||||
// order: 9,
|
||||
},
|
||||
{
|
||||
dataIndex: 'sensitiveLevel',
|
||||
title: '敏感度',
|
||||
width: 80,
|
||||
valueEnum: SENSITIVE_LEVEL_ENUM,
|
||||
},
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
{
|
||||
dataIndex: 'id',
|
||||
title: 'ID',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
dataIndex: 'name',
|
||||
@@ -72,6 +73,8 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
{
|
||||
dataIndex: 'alias',
|
||||
title: '别名',
|
||||
width: 300,
|
||||
ellipsis: true,
|
||||
search: false,
|
||||
},
|
||||
{
|
||||
@@ -81,6 +84,7 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
{
|
||||
dataIndex: 'sensitiveLevel',
|
||||
title: '敏感度',
|
||||
width: 80,
|
||||
valueEnum: SENSITIVE_LEVEL_ENUM,
|
||||
},
|
||||
{
|
||||
@@ -93,24 +97,14 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
title: '描述',
|
||||
search: false,
|
||||
},
|
||||
{
|
||||
dataIndex: 'type',
|
||||
title: '指标类型',
|
||||
valueEnum: {
|
||||
ATOMIC: '原子指标',
|
||||
DERIVED: '衍生指标',
|
||||
},
|
||||
// render: (type: any) => {
|
||||
// switch (type) {
|
||||
// case 'ATOMIC':
|
||||
// return '原子指标';
|
||||
// case 'DERIVED':
|
||||
// return '衍生指标';
|
||||
// default:
|
||||
// return '未知';
|
||||
// }
|
||||
// },
|
||||
},
|
||||
// {
|
||||
// dataIndex: 'type',
|
||||
// title: '指标类型',
|
||||
// valueEnum: {
|
||||
// ATOMIC: '原子指标',
|
||||
// DERIVED: '衍生指标',
|
||||
// },
|
||||
// },
|
||||
|
||||
{
|
||||
dataIndex: 'updatedAt',
|
||||
|
||||
@@ -3,19 +3,22 @@ import type { ForwardRefRenderFunction } from 'react';
|
||||
import { message, Form, Input, Select, Button, Space } from 'antd';
|
||||
import { saveDatabase, testDatabaseConnect } from '../../service';
|
||||
import { formLayout } from '@/components/FormHelper/utils';
|
||||
import SelectTMEPerson from '@/components/SelectTMEPerson';
|
||||
import { ISemantic } from '../../data';
|
||||
|
||||
import styles from '../style.less';
|
||||
type Props = {
|
||||
domainId: number;
|
||||
dataBaseConfig: any;
|
||||
onSubmit: (params?: any) => void;
|
||||
domainId?: number;
|
||||
dataBaseConfig?: ISemantic.IDatabaseItem;
|
||||
hideSubmitBtn?: boolean;
|
||||
onSubmit?: (params?: any) => void;
|
||||
};
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const TextArea = Input.TextArea;
|
||||
|
||||
const DatabaseCreateForm: ForwardRefRenderFunction<any, Props> = (
|
||||
{ domainId, dataBaseConfig, onSubmit },
|
||||
{ domainId, dataBaseConfig, onSubmit, hideSubmitBtn = false },
|
||||
ref,
|
||||
) => {
|
||||
const [form] = Form.useForm();
|
||||
@@ -25,8 +28,10 @@ const DatabaseCreateForm: ForwardRefRenderFunction<any, Props> = (
|
||||
|
||||
useEffect(() => {
|
||||
form.resetFields();
|
||||
form.setFieldsValue({ ...dataBaseConfig });
|
||||
setSelectedDbType(dataBaseConfig?.type);
|
||||
if (dataBaseConfig) {
|
||||
form.setFieldsValue({ ...dataBaseConfig });
|
||||
setSelectedDbType(dataBaseConfig?.type);
|
||||
}
|
||||
}, [dataBaseConfig]);
|
||||
|
||||
const getFormValidateFields = async () => {
|
||||
@@ -35,11 +40,14 @@ const DatabaseCreateForm: ForwardRefRenderFunction<any, Props> = (
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
getFormValidateFields,
|
||||
saveDatabaseConfig,
|
||||
testDatabaseConnection,
|
||||
}));
|
||||
|
||||
const saveDatabaseConfig = async () => {
|
||||
const values = await form.validateFields();
|
||||
const { code, msg } = await saveDatabase({
|
||||
...dataBaseConfig,
|
||||
...values,
|
||||
domainId,
|
||||
});
|
||||
@@ -115,6 +123,23 @@ const DatabaseCreateForm: ForwardRefRenderFunction<any, Props> = (
|
||||
</FormItem>
|
||||
</>
|
||||
)}
|
||||
|
||||
{selectedDbType === 'mysql' && (
|
||||
<FormItem
|
||||
name="version"
|
||||
label="数据库版本"
|
||||
rules={[{ required: true, message: '请选择数据库版本' }]}
|
||||
>
|
||||
<Select
|
||||
style={{ width: '100%' }}
|
||||
placeholder="请选择数据库版本"
|
||||
options={[
|
||||
{ value: '5.7', label: '5.7' },
|
||||
{ value: '8.0', label: '8.0' },
|
||||
]}
|
||||
/>
|
||||
</FormItem>
|
||||
)}
|
||||
<FormItem
|
||||
name="username"
|
||||
label="用户名"
|
||||
@@ -128,34 +153,44 @@ const DatabaseCreateForm: ForwardRefRenderFunction<any, Props> = (
|
||||
<FormItem name="database" label="数据库名称">
|
||||
<Input placeholder="请输入数据库名称" />
|
||||
</FormItem>
|
||||
<FormItem name="version" label="数据库版本">
|
||||
<Input placeholder="请输入数据库版本" />
|
||||
<FormItem
|
||||
name="admins"
|
||||
label="管理员"
|
||||
// rules={[{ required: true, message: '请设定数据库连接管理者' }]}
|
||||
>
|
||||
<SelectTMEPerson placeholder="请邀请团队成员" />
|
||||
</FormItem>
|
||||
<FormItem name="viewers" label="使用者">
|
||||
<SelectTMEPerson placeholder="请邀请团队成员" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem name="description" label="描述">
|
||||
<TextArea placeholder="请输入数据库描述" style={{ height: 100 }} />
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
loading={testLoading}
|
||||
onClick={() => {
|
||||
testDatabaseConnection();
|
||||
}}
|
||||
>
|
||||
连接测试
|
||||
</Button>
|
||||
{!hideSubmitBtn && (
|
||||
<FormItem>
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
loading={testLoading}
|
||||
onClick={() => {
|
||||
testDatabaseConnection();
|
||||
}}
|
||||
>
|
||||
连接测试
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
saveDatabaseConfig();
|
||||
}}
|
||||
>
|
||||
保 存
|
||||
</Button>
|
||||
</Space>
|
||||
</FormItem>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
saveDatabaseConfig();
|
||||
}}
|
||||
>
|
||||
保 存
|
||||
</Button>
|
||||
</Space>
|
||||
</FormItem>
|
||||
)}
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import React, { useState, useRef } from 'react';
|
||||
import { Button, Modal, Space } from 'antd';
|
||||
import DatabaseCreateForm from './DatabaseCreateForm';
|
||||
import { ISemantic } from '../../data';
|
||||
|
||||
export type CreateFormProps = {
|
||||
onCancel: () => void;
|
||||
databaseItem?: ISemantic.IDatabaseItem;
|
||||
open: boolean;
|
||||
onSubmit: (values?: any) => void;
|
||||
};
|
||||
|
||||
const DatabaseSettingModal: React.FC<CreateFormProps> = ({
|
||||
onCancel,
|
||||
databaseItem,
|
||||
open,
|
||||
onSubmit,
|
||||
}) => {
|
||||
const [testLoading, setTestLoading] = useState<boolean>(false);
|
||||
|
||||
const createFormRef = useRef<any>({});
|
||||
|
||||
const handleTestConnection = async () => {
|
||||
setTestLoading(true);
|
||||
await createFormRef.current.testDatabaseConnection();
|
||||
setTestLoading(false);
|
||||
};
|
||||
|
||||
const renderFooter = () => {
|
||||
return (
|
||||
<>
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
loading={testLoading}
|
||||
onClick={() => {
|
||||
handleTestConnection();
|
||||
}}
|
||||
>
|
||||
连接测试
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
createFormRef.current.saveDatabaseConfig();
|
||||
}}
|
||||
>
|
||||
保 存
|
||||
</Button>
|
||||
</Space>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
width={1200}
|
||||
destroyOnClose
|
||||
title="数据库连接设置"
|
||||
style={{ top: 48 }}
|
||||
maskClosable={false}
|
||||
open={open}
|
||||
footer={renderFooter()}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<DatabaseCreateForm
|
||||
hideSubmitBtn={true}
|
||||
ref={createFormRef}
|
||||
dataBaseConfig={databaseItem}
|
||||
onSubmit={() => {
|
||||
onSubmit?.();
|
||||
}}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default DatabaseSettingModal;
|
||||
@@ -0,0 +1,162 @@
|
||||
import type { ActionType, ProColumns } from '@ant-design/pro-table';
|
||||
import ProTable from '@ant-design/pro-table';
|
||||
import { message, Button, Space, Popconfirm } from 'antd';
|
||||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import DatabaseSettingModal from './DatabaseSettingModal';
|
||||
import { ISemantic } from '../../data';
|
||||
import { getDatabaseList, deleteDatabase } from '../../service';
|
||||
|
||||
import moment from 'moment';
|
||||
import styles from '../style.less';
|
||||
|
||||
type Props = {};
|
||||
|
||||
const DatabaseTable: React.FC<Props> = ({}) => {
|
||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||
const [databaseItem, setDatabaseItem] = useState<ISemantic.IDatabaseItem>();
|
||||
const [dataBaseList, setDataBaseList] = useState<any[]>([]);
|
||||
|
||||
const actionRef = useRef<ActionType>();
|
||||
|
||||
const queryDatabaseList = async () => {
|
||||
const { code, data, msg } = await getDatabaseList();
|
||||
if (code === 200) {
|
||||
setDataBaseList(data);
|
||||
} else {
|
||||
message.error(msg);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
queryDatabaseList();
|
||||
}, []);
|
||||
|
||||
const columns: ProColumns[] = [
|
||||
{
|
||||
dataIndex: 'id',
|
||||
title: 'ID',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
dataIndex: 'name',
|
||||
title: '连接名称',
|
||||
},
|
||||
|
||||
{
|
||||
dataIndex: 'type',
|
||||
title: '类型',
|
||||
search: false,
|
||||
},
|
||||
{
|
||||
dataIndex: 'createdBy',
|
||||
title: '创建人',
|
||||
search: false,
|
||||
},
|
||||
|
||||
{
|
||||
dataIndex: 'description',
|
||||
title: '描述',
|
||||
search: false,
|
||||
},
|
||||
|
||||
{
|
||||
dataIndex: 'updatedAt',
|
||||
title: '更新时间',
|
||||
search: false,
|
||||
render: (value: any) => {
|
||||
return value && value !== '-' ? moment(value).format('YYYY-MM-DD HH:mm:ss') : '-';
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'x',
|
||||
valueType: 'option',
|
||||
render: (_, record) => {
|
||||
if (!record.hasEditPermission) {
|
||||
return <></>;
|
||||
}
|
||||
return (
|
||||
<Space>
|
||||
<a
|
||||
key="dimensionEditBtn"
|
||||
onClick={() => {
|
||||
setDatabaseItem(record);
|
||||
setCreateModalVisible(true);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</a>
|
||||
<Popconfirm
|
||||
title="确认删除?"
|
||||
okText="是"
|
||||
cancelText="否"
|
||||
onConfirm={async () => {
|
||||
const { code, msg } = await deleteDatabase(record.id);
|
||||
if (code === 200) {
|
||||
setDatabaseItem(undefined);
|
||||
queryDatabaseList();
|
||||
} else {
|
||||
message.error(msg);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<a
|
||||
key="dimensionDeleteEditBtn"
|
||||
onClick={() => {
|
||||
setDatabaseItem(record);
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</a>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div style={{ margin: 20 }}>
|
||||
<ProTable
|
||||
className={`${styles.classTable} ${styles.classTableSelectColumnAlignLeft}`}
|
||||
actionRef={actionRef}
|
||||
rowKey="id"
|
||||
columns={columns}
|
||||
dataSource={dataBaseList}
|
||||
search={false}
|
||||
tableAlertRender={() => {
|
||||
return false;
|
||||
}}
|
||||
size="small"
|
||||
options={{ reload: false, density: false, fullScreen: false }}
|
||||
toolBarRender={() => [
|
||||
<Button
|
||||
key="create"
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setDatabaseItem(undefined);
|
||||
setCreateModalVisible(true);
|
||||
}}
|
||||
>
|
||||
创建数据库连接
|
||||
</Button>,
|
||||
]}
|
||||
/>
|
||||
{createModalVisible && (
|
||||
<DatabaseSettingModal
|
||||
open={createModalVisible}
|
||||
databaseItem={databaseItem}
|
||||
onCancel={() => {
|
||||
setCreateModalVisible(false);
|
||||
}}
|
||||
onSubmit={() => {
|
||||
setCreateModalVisible(false);
|
||||
queryDatabaseList();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default DatabaseTable;
|
||||
@@ -1,12 +1,13 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Button, Form, Input, Modal, Select } from 'antd';
|
||||
import { Button, Form, Input, Modal, Select, Row, Col, Space, Tooltip } from 'antd';
|
||||
import { SENSITIVE_LEVEL_OPTIONS } from '../constant';
|
||||
import { formLayout } from '@/components/FormHelper/utils';
|
||||
import SqlEditor from '@/components/SqlEditor';
|
||||
import InfoTagList from './InfoTagList';
|
||||
import { ISemantic } from '../data';
|
||||
import { createDimension, updateDimension } from '../service';
|
||||
// import DimensionValueSettingModal from './DimensionValueSettingModal';
|
||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
import { createDimension, updateDimension, mockDimensionAlias } from '../service';
|
||||
|
||||
import { message } from 'antd';
|
||||
|
||||
export type CreateFormProps = {
|
||||
@@ -37,8 +38,8 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
>([]);
|
||||
const [form] = Form.useForm();
|
||||
const { setFieldsValue, resetFields } = form;
|
||||
// const [dimensionValueSettingModalVisible, setDimensionValueSettingModalVisible] =
|
||||
// useState<boolean>(false);
|
||||
const [llmLoading, setLlmLoading] = useState<boolean>(false);
|
||||
|
||||
const handleSubmit = async (
|
||||
isSilenceSubmit = false,
|
||||
dimValueMaps?: ISemantic.IDimensionValueSettingItem[],
|
||||
@@ -48,6 +49,7 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
{
|
||||
...fieldsValue,
|
||||
dimValueMaps: dimValueMaps || dimensionValueSettingList,
|
||||
alias: Array.isArray(fieldsValue.alias) ? fieldsValue.alias.join(',') : '',
|
||||
},
|
||||
isSilenceSubmit,
|
||||
);
|
||||
@@ -75,7 +77,10 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
};
|
||||
|
||||
const setFormVal = () => {
|
||||
setFieldsValue(dimensionItem);
|
||||
if (dimensionItem) {
|
||||
const { alias } = dimensionItem;
|
||||
setFieldsValue({ ...dimensionItem, alias: alias && alias.trim() ? alias.split(',') : [] });
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -110,6 +115,24 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
const generatorDimensionAlias = async () => {
|
||||
const fieldsValue = await form.validateFields();
|
||||
setLlmLoading(true);
|
||||
const { code, data } = await mockDimensionAlias({
|
||||
...dimensionItem,
|
||||
...fieldsValue,
|
||||
alias: fieldsValue.alias?.join(','),
|
||||
});
|
||||
setLlmLoading(false);
|
||||
const formAlias = form.getFieldValue('alias');
|
||||
setLlmLoading(false);
|
||||
if (code === 200) {
|
||||
form.setFieldValue('alias', Array.from(new Set([...formAlias, ...data])));
|
||||
} else {
|
||||
message.error('大语言模型解析异常');
|
||||
}
|
||||
};
|
||||
|
||||
const renderContent = () => {
|
||||
return (
|
||||
<>
|
||||
@@ -131,7 +154,6 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
>
|
||||
<Input placeholder="名称不可重复" disabled={isEdit} />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
hidden={isEdit}
|
||||
name="datasourceId"
|
||||
@@ -146,8 +168,39 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
))}
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem name="alias" label="别名">
|
||||
<Input placeholder="多个别名用英文逗号隔开" />
|
||||
<FormItem label="别名">
|
||||
<Row>
|
||||
<Col flex="1 1 200px">
|
||||
<FormItem name="alias" noStyle>
|
||||
<Select
|
||||
mode="tags"
|
||||
placeholder="输入别名后回车确认,多别名输入、复制粘贴支持英文逗号自动分隔"
|
||||
tokenSeparators={[',']}
|
||||
maxTagCount={9}
|
||||
/>
|
||||
</FormItem>
|
||||
</Col>
|
||||
{isEdit && (
|
||||
<Col flex="0 1 75px">
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
loading={llmLoading}
|
||||
style={{ top: '2px' }}
|
||||
onClick={() => {
|
||||
generatorDimensionAlias();
|
||||
}}
|
||||
>
|
||||
<Space>
|
||||
智能填充
|
||||
<Tooltip title="智能填充将根据维度相关信息,使用大语言模型获取维度别名">
|
||||
<InfoCircleOutlined />
|
||||
</Tooltip>
|
||||
</Space>
|
||||
</Button>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
name="semanticType"
|
||||
@@ -185,16 +238,6 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
>
|
||||
<TextArea placeholder="请输入维度描述" />
|
||||
</FormItem>
|
||||
{/* <FormItem name="dimValueMaps" label="维度值设置">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setDimensionValueSettingModalVisible(true);
|
||||
}}
|
||||
>
|
||||
设置
|
||||
</Button>
|
||||
</FormItem> */}
|
||||
<FormItem
|
||||
name="expr"
|
||||
label="表达式"
|
||||
@@ -223,22 +266,6 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
{renderContent()}
|
||||
</Form>
|
||||
</Modal>
|
||||
{/* {dimensionValueSettingModalVisible && (
|
||||
<DimensionValueSettingModal
|
||||
dimensionValueSettingList={dimensionValueSettingList}
|
||||
open={dimensionValueSettingModalVisible}
|
||||
onCancel={() => {
|
||||
setDimensionValueSettingModalVisible(false);
|
||||
}}
|
||||
onSubmit={(dimValueMaps) => {
|
||||
if (isEdit) {
|
||||
handleSubmit(true, dimValueMaps);
|
||||
}
|
||||
setDimensionValueSettingList(dimValueMaps);
|
||||
setDimensionValueSettingModalVisible(false);
|
||||
}}
|
||||
/>
|
||||
)} */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Button, Modal, message } from 'antd';
|
||||
import { Button, Modal, message, Space, Tooltip } from 'antd';
|
||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
import { ISemantic } from '../data';
|
||||
import CommonEditTable from './CommonEditTable';
|
||||
import { createDimension, updateDimension } from '../service';
|
||||
import { updateDimension, mockDimensionValuesAlias } from '../service';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
|
||||
@@ -15,7 +16,7 @@ export type CreateFormProps = {
|
||||
domainManger: StateType;
|
||||
};
|
||||
|
||||
type TableDataSource = { techName: string; bizName: string; alias: string };
|
||||
type TableDataSource = { techName: string; bizName: string; alias?: string[] };
|
||||
|
||||
const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
onCancel,
|
||||
@@ -28,16 +29,10 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
const [tableDataSource, setTableDataSource] = useState<TableDataSource[]>([]);
|
||||
const { selectDomainId } = domainManger;
|
||||
const [dimValueMaps, setDimValueMaps] = useState<ISemantic.IDimensionValueSettingItem[]>([]);
|
||||
const [llmLoading, setLlmLoading] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
const dataSource = dimensionValueSettingList.map((item) => {
|
||||
const { alias } = item;
|
||||
return {
|
||||
...item,
|
||||
alias: Array.isArray(alias) ? alias.join(',') : '',
|
||||
};
|
||||
});
|
||||
setTableDataSource(dataSource);
|
||||
setTableDataSource(dimensionValueSettingList);
|
||||
setDimValueMaps(dimensionValueSettingList);
|
||||
}, [dimensionValueSettingList]);
|
||||
|
||||
@@ -62,9 +57,37 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
message.error(msg);
|
||||
};
|
||||
|
||||
const generatorDimensionValue = async () => {
|
||||
setLlmLoading(true);
|
||||
const { code, data } = await mockDimensionValuesAlias({ ...dimensionItem });
|
||||
setLlmLoading(false);
|
||||
if (code === 200) {
|
||||
if (Array.isArray(data)) {
|
||||
setDimValueMaps([...dimValueMaps, ...data]);
|
||||
setTableDataSource([...tableDataSource, ...data]);
|
||||
}
|
||||
} else {
|
||||
message.error('大语言模型解析异常');
|
||||
}
|
||||
};
|
||||
|
||||
const renderFooter = () => {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
type="primary"
|
||||
loading={llmLoading}
|
||||
onClick={() => {
|
||||
generatorDimensionValue();
|
||||
}}
|
||||
>
|
||||
<Space>
|
||||
智能填充
|
||||
<Tooltip title="智能填充将根据维度相关信息,使用大语言模型获取可能被使用的维度值">
|
||||
<InfoCircleOutlined />
|
||||
</Tooltip>
|
||||
</Space>
|
||||
</Button>
|
||||
<Button onClick={onCancel}>取消</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
@@ -83,6 +106,7 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
title: '技术名称',
|
||||
dataIndex: 'techName',
|
||||
width: 200,
|
||||
tooltip: '数据库中存储的维度值数据。 比如数据库中维度平台的维度值有kw、qy等',
|
||||
formItemProps: {
|
||||
fieldProps: {
|
||||
placeholder: '请填写技术名称',
|
||||
@@ -100,6 +124,8 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
title: '业务名称',
|
||||
dataIndex: 'bizName',
|
||||
width: 200,
|
||||
tooltip:
|
||||
'查询完成后,最终返回给用户的维度值信息。比如将技术名称kw转换成酷我平台,最终返回给用户是酷我平台',
|
||||
fieldProps: {
|
||||
placeholder: '请填写业务名称',
|
||||
},
|
||||
@@ -116,15 +142,21 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
{
|
||||
title: '别名',
|
||||
dataIndex: 'alias',
|
||||
valueType: 'select',
|
||||
width: 500,
|
||||
tooltip:
|
||||
'解析用户查询意图时,支持别名到技术名称的转换。比如用户输入kw、kuwo、酷我,完成设置后,都可以将其转换成技术名称kw',
|
||||
fieldProps: {
|
||||
placeholder: '多个别名用英文逗号隔开',
|
||||
placeholder: '输入别名后回车确认,多别名输入、复制粘贴支持英文逗号自动分隔',
|
||||
mode: 'tags',
|
||||
maxTagCount: 5,
|
||||
tokenSeparators: [','],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Modal
|
||||
width={1000}
|
||||
width={1200}
|
||||
destroyOnClose
|
||||
title="维度值设置"
|
||||
style={{ top: 48 }}
|
||||
@@ -140,7 +172,7 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
const dimValueMaps = tableData.map((item: TableDataSource) => {
|
||||
return {
|
||||
...item,
|
||||
alias: item.alias ? `${item.alias}`.split(',') : [],
|
||||
// alias: item.alias ? `${item.alias}`.split(',') : [],
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -6,14 +6,16 @@ import ClassDataSourceTable from './ClassDataSourceTable';
|
||||
import ClassDimensionTable from './ClassDimensionTable';
|
||||
import ClassMetricTable from './ClassMetricTable';
|
||||
import PermissionSection from './Permission/PermissionSection';
|
||||
import DatabaseSection from './Database/DatabaseSection';
|
||||
// import DatabaseSection from './Database/DatabaseSection';
|
||||
import EntitySettingSection from './Entity/EntitySettingSection';
|
||||
import ChatSettingSection from '../ChatSetting/ChatSettingSection';
|
||||
import OverView from './OverView';
|
||||
import styles from './style.less';
|
||||
import type { StateType } from '../model';
|
||||
import { LeftOutlined } from '@ant-design/icons';
|
||||
import { ISemantic } from '../data';
|
||||
import SemanticGraphCanvas from '../SemanticGraphCanvas';
|
||||
import RecommendedQuestionsSection from '../components/Entity/RecommendedQuestionsSection';
|
||||
|
||||
import type { Dispatch } from 'umi';
|
||||
|
||||
@@ -50,11 +52,11 @@ const DomainManagerTab: React.FC<Props> = ({
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: '数据库',
|
||||
key: 'dataBase',
|
||||
children: <DatabaseSection />,
|
||||
},
|
||||
// {
|
||||
// label: '数据库',
|
||||
// key: 'dataBase',
|
||||
// children: <DatabaseSection />,
|
||||
// },
|
||||
{
|
||||
label: '权限管理',
|
||||
key: 'permissonSetting',
|
||||
@@ -93,13 +95,27 @@ const DomainManagerTab: React.FC<Props> = ({
|
||||
key: 'entity',
|
||||
children: <EntitySettingSection />,
|
||||
},
|
||||
|
||||
{
|
||||
label: '权限管理',
|
||||
key: 'permissonSetting',
|
||||
children: <PermissionSection permissionTarget={'model'} />,
|
||||
},
|
||||
];
|
||||
{
|
||||
label: '问答设置',
|
||||
key: 'chatSetting',
|
||||
children: <ChatSettingSection />,
|
||||
},
|
||||
{
|
||||
label: '推荐问题',
|
||||
key: 'recommendedQuestions',
|
||||
children: <RecommendedQuestionsSection />,
|
||||
},
|
||||
].filter((item) => {
|
||||
if (window.RUNNING_ENV === 'semantic') {
|
||||
return !['chatSetting', 'recommendedQuestions'].includes(item.key);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -12,6 +12,7 @@ import { ISemantic } from '../data';
|
||||
|
||||
type Props = {
|
||||
value?: any;
|
||||
width?: number | string;
|
||||
onChange?: () => void;
|
||||
treeSelectProps?: Record<string, any>;
|
||||
domainList: ISemantic.IDomainItem[];
|
||||
@@ -20,6 +21,7 @@ type Props = {
|
||||
|
||||
const DomainTreeSelect: FC<Props> = ({
|
||||
value,
|
||||
width = 300,
|
||||
onChange,
|
||||
treeSelectProps = {},
|
||||
domainList,
|
||||
@@ -51,7 +53,12 @@ const DomainTreeSelect: FC<Props> = ({
|
||||
}, [domainList]);
|
||||
|
||||
return (
|
||||
<div className={styles.domainTreeSelect}>
|
||||
<div
|
||||
className={styles.domainTreeSelect}
|
||||
style={{
|
||||
width,
|
||||
}}
|
||||
>
|
||||
<TreeSelect
|
||||
showSearch
|
||||
style={{ width: '100%' }}
|
||||
|
||||
@@ -53,7 +53,7 @@ const EntityCreateForm: ForwardRefRenderFunction<any, Props> = (
|
||||
|
||||
const saveEntity = async () => {
|
||||
const values = await form.validateFields();
|
||||
const { name } = values;
|
||||
const { name = '' } = values;
|
||||
const { code, msg, data } = await updateModel({
|
||||
...modelData,
|
||||
entity: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { message, Space } from 'antd';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import type { Dispatch } from 'umi';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
|
||||
@@ -6,18 +6,25 @@ import {
|
||||
Steps,
|
||||
Input,
|
||||
Select,
|
||||
Radio,
|
||||
Switch,
|
||||
InputNumber,
|
||||
message,
|
||||
Result,
|
||||
Row,
|
||||
Col,
|
||||
Space,
|
||||
Tooltip,
|
||||
} from 'antd';
|
||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
import MetricMeasuresFormTable from './MetricMeasuresFormTable';
|
||||
import { SENSITIVE_LEVEL_OPTIONS } from '../constant';
|
||||
import { formLayout } from '@/components/FormHelper/utils';
|
||||
import FormItemTitle from '@/components/FormHelper/FormItemTitle';
|
||||
import styles from './style.less';
|
||||
import { getMeasureListByModelId } from '../service';
|
||||
import { creatExprMetric, updateExprMetric } from '../service';
|
||||
import TableTitleTooltips from '../components/TableTitleTooltips';
|
||||
import { creatExprMetric, updateExprMetric, mockMetricAlias } from '../service';
|
||||
import { ISemantic } from '../data';
|
||||
import { history } from 'umi';
|
||||
|
||||
@@ -50,7 +57,11 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
const formValRef = useRef({} as any);
|
||||
const [form] = Form.useForm();
|
||||
const updateFormVal = (val: any) => {
|
||||
formValRef.current = val;
|
||||
const formVal = {
|
||||
...formValRef.current,
|
||||
...val,
|
||||
};
|
||||
formValRef.current = formVal;
|
||||
};
|
||||
|
||||
const [classMeasureList, setClassMeasureList] = useState<ISemantic.IMeasure[]>([]);
|
||||
@@ -60,7 +71,9 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
const [exprSql, setExprSql] = useState<string>('');
|
||||
|
||||
const [isPercentState, setIsPercentState] = useState<boolean>(false);
|
||||
const [isDecimalState, setIsDecimalState] = useState<boolean>(false);
|
||||
const [hasMeasuresState, setHasMeasuresState] = useState<boolean>(true);
|
||||
const [llmLoading, setLlmLoading] = useState<boolean>(false);
|
||||
|
||||
const forward = () => setCurrentStep(currentStep + 1);
|
||||
const backward = () => setCurrentStep(currentStep - 1);
|
||||
@@ -93,7 +106,6 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
expr: exprSql,
|
||||
measures: exprTypeParamsState,
|
||||
},
|
||||
dataFormatType: isPercentState ? 'percent' : '',
|
||||
};
|
||||
updateFormVal(submitForm);
|
||||
if (currentStep < 1) {
|
||||
@@ -116,14 +128,16 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
alias,
|
||||
} = metricItem as any;
|
||||
const isPercent = dataFormatType === 'percent';
|
||||
const isDecimal = dataFormatType === 'decimal';
|
||||
const initValue = {
|
||||
id,
|
||||
name,
|
||||
bizName,
|
||||
sensitiveLevel,
|
||||
description,
|
||||
isPercent,
|
||||
alias,
|
||||
// isPercent,
|
||||
dataFormatType,
|
||||
alias: alias && alias.trim() ? alias.split(',') : [],
|
||||
dataFormat: dataFormat || {
|
||||
decimalPlaces: 2,
|
||||
needMultiply100: false,
|
||||
@@ -138,6 +152,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
setExprTypeParamsState(typeParams.measures);
|
||||
setExprSql(typeParams.expr);
|
||||
setIsPercentState(isPercent);
|
||||
setIsDecimalState(isDecimal);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -151,11 +166,15 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
modelId,
|
||||
...fieldsValue,
|
||||
};
|
||||
const { typeParams } = queryParams;
|
||||
const { typeParams, alias, dataFormatType } = queryParams;
|
||||
queryParams.alias = Array.isArray(alias) ? alias.join(',') : '';
|
||||
if (!typeParams?.expr) {
|
||||
message.error('请输入度量表达式');
|
||||
return;
|
||||
}
|
||||
if (!dataFormatType) {
|
||||
delete queryParams.dataFormat;
|
||||
}
|
||||
if (!(Array.isArray(typeParams?.measures) && typeParams.measures.length > 0)) {
|
||||
message.error('请添加一个度量');
|
||||
return;
|
||||
@@ -173,6 +192,18 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
message.error(msg);
|
||||
};
|
||||
|
||||
const generatorMetricAlias = async () => {
|
||||
setLlmLoading(true);
|
||||
const { code, data } = await mockMetricAlias({ ...metricItem });
|
||||
const formAlias = form.getFieldValue('alias');
|
||||
setLlmLoading(false);
|
||||
if (code === 200) {
|
||||
form.setFieldValue('alias', Array.from(new Set([...formAlias, ...data])));
|
||||
} else {
|
||||
message.error('大语言模型解析异常');
|
||||
}
|
||||
};
|
||||
|
||||
const renderContent = () => {
|
||||
if (currentStep === 1) {
|
||||
return (
|
||||
@@ -212,8 +243,39 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
>
|
||||
<Input placeholder="名称不可重复" disabled={isEdit} />
|
||||
</FormItem>
|
||||
<FormItem name="alias" label="别名">
|
||||
<Input placeholder="多个别名用英文逗号隔开" />
|
||||
<FormItem label="别名">
|
||||
<Row>
|
||||
<Col flex="1 1 200px">
|
||||
<FormItem name="alias" noStyle>
|
||||
<Select
|
||||
mode="tags"
|
||||
placeholder="输入别名后回车确认,多别名输入、复制粘贴支持英文逗号自动分隔"
|
||||
tokenSeparators={[',']}
|
||||
maxTagCount={9}
|
||||
/>
|
||||
</FormItem>
|
||||
</Col>
|
||||
{isEdit && (
|
||||
<Col flex="0 1 75px">
|
||||
<Button
|
||||
type="link"
|
||||
loading={llmLoading}
|
||||
size="small"
|
||||
style={{ top: '2px' }}
|
||||
onClick={() => {
|
||||
generatorMetricAlias();
|
||||
}}
|
||||
>
|
||||
<Space>
|
||||
智能填充
|
||||
<Tooltip title="智能填充将根据指标相关信息,使用大语言模型获取指标别名">
|
||||
<InfoCircleOutlined />
|
||||
</Tooltip>
|
||||
</Space>
|
||||
</Button>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
name="sensitiveLevel"
|
||||
@@ -230,12 +292,47 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
</FormItem>
|
||||
<FormItem
|
||||
name="description"
|
||||
label="指标描述"
|
||||
rules={[{ required: true, message: '请输入指标描述' }]}
|
||||
label={
|
||||
<TableTitleTooltips
|
||||
title="业务口径"
|
||||
overlayInnerStyle={{ width: 600 }}
|
||||
tooltips={
|
||||
<>
|
||||
<p>
|
||||
在录入指标时,请务必详细填写指标口径。口径描述对于理解指标的含义、计算方法和使用场景至关重要。一个清晰、准确的口径描述可以帮助其他用户更好地理解和使用该指标,避免因为误解而导致错误的数据分析和决策。在填写口径时,建议包括以下信息:
|
||||
</p>
|
||||
<p>1. 指标的计算方法:详细说明指标是如何计算的,包括涉及的公式、计算步骤等。</p>
|
||||
<p>2. 数据来源:描述指标所依赖的数据来源,包括数据表、字段等信息。</p>
|
||||
<p>3. 使用场景:说明该指标适用于哪些业务场景,以及如何在这些场景中使用该指标。</p>
|
||||
<p>4. 任何其他相关信息:例如数据更新频率、数据质量要求等。</p>
|
||||
<p>
|
||||
请确保口径描述清晰、简洁且易于理解,以便其他用户能够快速掌握指标的核心要点。
|
||||
</p>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
}
|
||||
rules={[{ required: true, message: '请输入业务口径' }]}
|
||||
>
|
||||
<TextArea placeholder="请输入指标描述" />
|
||||
<TextArea placeholder="请输入业务口径" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label={
|
||||
<FormItemTitle
|
||||
title={'数据格式化'}
|
||||
// subTitle={'开启后,指标数据展示时会根据配置进行格式化,如0.02 -> 2%'}
|
||||
/>
|
||||
}
|
||||
name="dataFormatType"
|
||||
>
|
||||
<Radio.Group buttonStyle="solid" size="middle">
|
||||
<Radio.Button value="">默认</Radio.Button>
|
||||
<Radio.Button value="decimal">小数</Radio.Button>
|
||||
<Radio.Button value="percent">百分比</Radio.Button>
|
||||
</Radio.Group>
|
||||
</FormItem>
|
||||
|
||||
{/* <FormItem
|
||||
label={
|
||||
<FormItemTitle
|
||||
title={'是否展示为百分比'}
|
||||
@@ -250,20 +347,24 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
form.setFieldValue(['dataFormat', 'needMultiply100'], checked);
|
||||
}}
|
||||
/>
|
||||
</FormItem>
|
||||
</FormItem> */}
|
||||
{(isPercentState || isDecimalState) && (
|
||||
<FormItem
|
||||
label={
|
||||
<FormItemTitle
|
||||
title={'小数位数'}
|
||||
subTitle={`对小数位数进行设置,如保留两位,0.021252 -> 2.12${
|
||||
isPercentState ? '%' : ''
|
||||
}`}
|
||||
/>
|
||||
}
|
||||
name={['dataFormat', 'decimalPlaces']}
|
||||
>
|
||||
<InputNumber placeholder="请输入需要保留小数位数" style={{ width: '300px' }} />
|
||||
</FormItem>
|
||||
)}
|
||||
{isPercentState && (
|
||||
<>
|
||||
<FormItem
|
||||
label={
|
||||
<FormItemTitle
|
||||
title={'小数位数'}
|
||||
subTitle={'对小数位数进行设置,如保留两位,0.021252 -> 2.12%'}
|
||||
/>
|
||||
}
|
||||
name={['dataFormat', 'decimalPlaces']}
|
||||
>
|
||||
<InputNumber placeholder="请输入需要保留小数位数" style={{ width: '300px' }} />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label={
|
||||
<FormItemTitle
|
||||
@@ -331,11 +432,24 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
form={form}
|
||||
initialValues={{
|
||||
...formValRef.current,
|
||||
dataFormatType: '',
|
||||
}}
|
||||
onValuesChange={(value) => {
|
||||
const { isPercent } = value;
|
||||
if (isPercent !== undefined) {
|
||||
setIsPercentState(isPercent);
|
||||
onValuesChange={(value, values: any) => {
|
||||
const { isPercent, dataFormatType } = values;
|
||||
// if (isPercent !== undefined) {
|
||||
// setIsPercentState(isPercent);
|
||||
// }
|
||||
if (dataFormatType === 'percent') {
|
||||
setIsPercentState(true);
|
||||
setIsDecimalState(false);
|
||||
}
|
||||
if (dataFormatType === 'decimal') {
|
||||
setIsPercentState(false);
|
||||
setIsDecimalState(true);
|
||||
}
|
||||
if (!dataFormatType) {
|
||||
setIsPercentState(false);
|
||||
setIsDecimalState(false);
|
||||
}
|
||||
}}
|
||||
className={styles.form}
|
||||
@@ -352,7 +466,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
type="primary"
|
||||
key="console"
|
||||
onClick={() => {
|
||||
history.replace(`/semanticModel/${domainId}/${modelId}/dataSource`);
|
||||
history.replace(`/model/${domainId}/${modelId}/dataSource`);
|
||||
onCancel?.();
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import { Space, Tooltip } from 'antd';
|
||||
import React from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons';
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
tooltips: string;
|
||||
tooltips: string | ReactNode;
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
const TableTitleTooltips: React.FC<Props> = ({ title, tooltips }) => {
|
||||
const TableTitleTooltips: React.FC<Props> = ({ title, tooltips, ...rest }) => {
|
||||
return (
|
||||
<>
|
||||
<Space>
|
||||
<span>{title}</span>
|
||||
<Tooltip title={tooltips}>
|
||||
<Tooltip title={tooltips} {...rest}>
|
||||
<ExclamationCircleOutlined />
|
||||
</Tooltip>
|
||||
</Space>
|
||||
|
||||
@@ -31,16 +31,34 @@
|
||||
|
||||
.title {
|
||||
margin-bottom: 0;
|
||||
padding: 20px;
|
||||
// padding: 20px;
|
||||
font-size: 20px;
|
||||
line-height: 34px;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
display: flex;
|
||||
}
|
||||
.navContainer {
|
||||
padding: 20px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
.backBtn {
|
||||
background-color: #f8f8f8;
|
||||
padding: 5px;
|
||||
color: #b0b4bc;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
&:hover {
|
||||
background-color: #7599e5;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.tab {
|
||||
:global {
|
||||
.ant-tabs-tab-btn {
|
||||
font-size: 16px !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
.ant-tabs-nav-wrap {
|
||||
padding: 0 20px;
|
||||
@@ -50,6 +68,16 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.chatSettingSectionTab {
|
||||
:global {
|
||||
.ant-tabs-tab-btn {
|
||||
font-size: 14px;
|
||||
}
|
||||
.ant-tabs-nav-wrap {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mainTip {
|
||||
padding: 20px;
|
||||
@@ -60,9 +88,7 @@
|
||||
padding: 0 !important;
|
||||
}
|
||||
.ant-tabs-content-holder {
|
||||
margin-top: 20px;
|
||||
// overflow: scroll;
|
||||
// height: calc(100vh - 175px);
|
||||
padding-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +122,7 @@
|
||||
}
|
||||
|
||||
.domainTreeSelect {
|
||||
width: 300px;
|
||||
// width: 300px;
|
||||
}
|
||||
|
||||
.domainList {
|
||||
|
||||
Reference in New Issue
Block a user