mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-10 19:51:00 +00:00
Merge pull request #29 from sevenliu1896/master
[improvement][semantic-fe] Restructured the code to extract the quest…
This commit is contained in:
6
package-lock.json
generated
Normal file
6
package-lock.json
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "github-supersonic",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
||||
@@ -15,9 +15,9 @@ const ROUTES = [
|
||||
envEnableList: [ENV_KEY.CHAT],
|
||||
},
|
||||
{
|
||||
path: '/chatSetting/:modelId?/:menuKey?',
|
||||
path: '/chatSetting/model/:domainId?/:modelId?/:menuKey?',
|
||||
component: './SemanticModel/ChatSetting/ChatSetting',
|
||||
name: 'chatSetting',
|
||||
component: './SemanticModel/ChatSetting',
|
||||
envEnableList: [ENV_KEY.CHAT],
|
||||
},
|
||||
{
|
||||
@@ -27,9 +27,9 @@ const ROUTES = [
|
||||
envEnableList: [ENV_KEY.CHAT],
|
||||
},
|
||||
{
|
||||
path: '/semanticModel/:modelId?/:menuKey?',
|
||||
path: '/semanticModel/model/:domainId?/:modelId?/:menuKey?',
|
||||
component: './SemanticModel/DomainManager',
|
||||
name: 'semanticModel',
|
||||
component: './SemanticModel/ProjectManager',
|
||||
envEnableList: [ENV_KEY.SEMANTIC],
|
||||
},
|
||||
{
|
||||
@@ -47,10 +47,10 @@ const ROUTES = [
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
redirect: APP_TARGET === 'inner' ? '/semanticModel' : '/chat',
|
||||
redirect: APP_TARGET === 'inner' ? '/semanticModel/model/' : '/chat',
|
||||
envRedirect: {
|
||||
[ENV_KEY.CHAT]: '/chat',
|
||||
[ENV_KEY.SEMANTIC]: '/semanticModel',
|
||||
[ENV_KEY.SEMANTIC]: '/semanticModel/model',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
export const EnumTransDbType = {
|
||||
mysql: 'mysql',
|
||||
tdw: 'tdw',
|
||||
clickhouse: 'clickhouse',
|
||||
kafka: 'kafka',
|
||||
binlog: 'binlog',
|
||||
hbase: 'hbase',
|
||||
kugou_datahub: 'kugou_datahub',
|
||||
aiting_datahub: 'aiting_datahub',
|
||||
http: 'http',
|
||||
};
|
||||
|
||||
export const EnumTransModelType = {
|
||||
edit: '编辑',
|
||||
add: '新增',
|
||||
@@ -29,20 +17,3 @@ export const EnumDescSensitivity = {
|
||||
label: '高',
|
||||
},
|
||||
};
|
||||
|
||||
export const EnumDbTypeOwnKeys = {
|
||||
mysql: ['ip', 'port', 'dbName', 'username', 'password'],
|
||||
clickhouse: ['ip', 'port', 'dbName', 'username', 'password'],
|
||||
tdw: ['dbName', 'username', 'password'],
|
||||
kafka: ['bootstrap', 'dbName', 'username', 'password'],
|
||||
binlog: ['ip', 'port', 'dbName', 'username', 'password'],
|
||||
hbase: ['config'],
|
||||
kugou_datahub: ['config'],
|
||||
aiting_datahub: ['config'],
|
||||
http: ['url'],
|
||||
};
|
||||
|
||||
export enum EnumDashboardType {
|
||||
DIR = 0, // 目录
|
||||
DASHBOARD = 1, // 看板
|
||||
}
|
||||
|
||||
@@ -1,205 +0,0 @@
|
||||
import { Tabs, Popover, message } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { connect, Helmet, useParams, history } from 'umi';
|
||||
import DomainListTree from './components/DomainList';
|
||||
import styles from './components/style.less';
|
||||
import type { StateType } from './model';
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
import EntitySection from './components/Entity/EntitySection';
|
||||
import RecommendedQuestionsSection from './components/Entity/RecommendedQuestionsSection';
|
||||
import { ISemantic } from './data';
|
||||
import { getDomainList } from './service';
|
||||
import OverView from './components/OverView';
|
||||
import { findLeafNodesFromDomainList } from './utils';
|
||||
import { ChatConfigType } from './enum';
|
||||
import type { Dispatch } from 'umi';
|
||||
|
||||
type Props = {
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
};
|
||||
|
||||
const ChatSetting: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const defaultTabKey = 'metric';
|
||||
const params: any = useParams();
|
||||
const menuKey = params.menuKey ? params.menuKey : defaultTabKey;
|
||||
const modelId = params.modelId;
|
||||
const { selectDomainId, selectDomainName, domainList } = domainManger;
|
||||
const [modelList, setModelList] = useState<ISemantic.IDomainItem[]>([]);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [isModel, setIsModel] = useState<boolean>(false);
|
||||
const [activeKey, setActiveKey] = useState<string>(menuKey);
|
||||
|
||||
const handleOpenChange = (newOpen: boolean) => {
|
||||
setOpen(newOpen);
|
||||
};
|
||||
useEffect(() => {
|
||||
if (selectDomainId) {
|
||||
dispatch({
|
||||
type: 'domainManger/queryDimensionList',
|
||||
payload: {
|
||||
domainId: selectDomainId,
|
||||
},
|
||||
});
|
||||
dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
domainId: selectDomainId,
|
||||
},
|
||||
});
|
||||
pushUrlMenu(selectDomainId, menuKey);
|
||||
}
|
||||
}, [selectDomainId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectDomainId) {
|
||||
return;
|
||||
}
|
||||
const list = findLeafNodesFromDomainList(domainList, selectDomainId);
|
||||
setModelList(list);
|
||||
if (Array.isArray(list) && list.length > 0) {
|
||||
setIsModel(false);
|
||||
pushUrlMenu(selectDomainId, 'overview');
|
||||
setActiveKey('overview');
|
||||
} else {
|
||||
setIsModel(true);
|
||||
const currentMenuKey = menuKey === 'overview' ? defaultTabKey : menuKey;
|
||||
pushUrlMenu(selectDomainId, currentMenuKey);
|
||||
setActiveKey(currentMenuKey);
|
||||
}
|
||||
}, [domainList, selectDomainId]);
|
||||
|
||||
const initSelectedDomain = (domainList: ISemantic.IDomainItem[]) => {
|
||||
const targetNode = domainList.filter((item: any) => {
|
||||
return `${item.id}` === modelId;
|
||||
})[0];
|
||||
if (!targetNode) {
|
||||
const firstRootNode = domainList.filter((item: any) => {
|
||||
return item.parentId === 0;
|
||||
})[0];
|
||||
if (firstRootNode) {
|
||||
const { id, name } = firstRootNode;
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectDomain',
|
||||
selectDomainId: id,
|
||||
selectDomainName: name,
|
||||
domainData: firstRootNode,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const { id, name } = targetNode;
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectDomain',
|
||||
selectDomainId: id,
|
||||
selectDomainName: name,
|
||||
domainData: targetNode,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const initProjectTree = async () => {
|
||||
const { code, data, msg } = await getDomainList();
|
||||
if (code === 200) {
|
||||
if (!selectDomainId) {
|
||||
initSelectedDomain(data);
|
||||
}
|
||||
dispatch({
|
||||
type: 'domainManger/setDomainList',
|
||||
payload: { domainList: data },
|
||||
});
|
||||
} else {
|
||||
message.error(msg);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
initProjectTree();
|
||||
}, []);
|
||||
|
||||
const pushUrlMenu = (domainId: number, menuKey: string) => {
|
||||
history.push(`/chatSetting/${domainId}/${menuKey}`);
|
||||
};
|
||||
|
||||
const tabItem = [
|
||||
{
|
||||
label: '子主题域',
|
||||
key: 'overview',
|
||||
children: <OverView modelList={modelList} />,
|
||||
},
|
||||
];
|
||||
|
||||
const isModelItem = [
|
||||
{
|
||||
label: '指标模式',
|
||||
key: 'metric',
|
||||
children: <EntitySection chatConfigType={ChatConfigType.AGG} />,
|
||||
},
|
||||
{
|
||||
label: '实体模式',
|
||||
key: 'dimenstion',
|
||||
children: <EntitySection chatConfigType={ChatConfigType.DETAIL} />,
|
||||
},
|
||||
{
|
||||
label: '推荐问题',
|
||||
key: 'recommendedQuestions',
|
||||
children: <RecommendedQuestionsSection />,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className={styles.projectBody}>
|
||||
<Helmet title={'问答设置-超音数'} />
|
||||
<div className={styles.projectManger}>
|
||||
<h2 className={styles.title}>
|
||||
<Popover
|
||||
zIndex={1000}
|
||||
overlayInnerStyle={{
|
||||
overflow: 'scroll',
|
||||
maxHeight: '800px',
|
||||
}}
|
||||
content={
|
||||
<DomainListTree
|
||||
createDomainBtnVisible={false}
|
||||
onTreeSelected={() => {
|
||||
setOpen(false);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
trigger="click"
|
||||
open={open}
|
||||
onOpenChange={handleOpenChange}
|
||||
>
|
||||
<div className={styles.domainSelector}>
|
||||
<span className={styles.domainTitle}>
|
||||
{selectDomainName ? `选择的主题域:${selectDomainName}` : '主题域信息'}
|
||||
</span>
|
||||
<span className={styles.downIcon}>
|
||||
<DownOutlined />
|
||||
</span>
|
||||
</div>
|
||||
</Popover>
|
||||
</h2>
|
||||
{selectDomainId ? (
|
||||
<>
|
||||
<Tabs
|
||||
className={styles.tab}
|
||||
activeKey={activeKey}
|
||||
destroyInactiveTabPane
|
||||
onChange={(menuKey: string) => {
|
||||
setActiveKey(menuKey);
|
||||
pushUrlMenu(selectDomainId, menuKey);
|
||||
}}
|
||||
items={!isModel ? tabItem : isModelItem}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<h2 className={styles.mainTip}>请选择项目</h2>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(ChatSetting);
|
||||
@@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
import { connect, Helmet } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
import OverviewContainer from '../OverviewContainer';
|
||||
import type { Dispatch } from 'umi';
|
||||
|
||||
type Props = {
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
};
|
||||
const ChatSetting: React.FC<Props> = () => {
|
||||
return (
|
||||
<>
|
||||
<Helmet title={'模型管理-超音数'} />
|
||||
<OverviewContainer mode={'chatSetting'} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(ChatSetting);
|
||||
@@ -0,0 +1,102 @@
|
||||
import { Tabs, Button } from 'antd';
|
||||
import React from 'react';
|
||||
import { connect } from 'umi';
|
||||
|
||||
import styles from '../components/style.less';
|
||||
import type { StateType } from '../model';
|
||||
import { LeftOutlined } from '@ant-design/icons';
|
||||
import EntitySection from '../components/Entity/EntitySection';
|
||||
import RecommendedQuestionsSection from '../components/Entity/RecommendedQuestionsSection';
|
||||
import { ISemantic } from '../data';
|
||||
|
||||
import OverView from '../components/OverView';
|
||||
import { ChatConfigType } from '../enum';
|
||||
import type { Dispatch } from 'umi';
|
||||
|
||||
type Props = {
|
||||
isModel: boolean;
|
||||
activeKey: string;
|
||||
modelList: ISemantic.IModelItem[];
|
||||
handleModelChange: (model?: ISemantic.IModelItem) => void;
|
||||
onBackDomainBtnClick?: () => void;
|
||||
onMenuChange?: (menuKey: string) => void;
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
};
|
||||
|
||||
const ChatSetting: React.FC<Props> = ({
|
||||
isModel,
|
||||
activeKey,
|
||||
modelList,
|
||||
handleModelChange,
|
||||
onBackDomainBtnClick,
|
||||
onMenuChange,
|
||||
}) => {
|
||||
const defaultTabKey = 'metric';
|
||||
|
||||
const isModelItem = [
|
||||
{
|
||||
label: '指标模式',
|
||||
key: 'metric',
|
||||
children: <EntitySection chatConfigType={ChatConfigType.AGG} />,
|
||||
},
|
||||
{
|
||||
label: '实体模式',
|
||||
key: 'dimenstion',
|
||||
children: <EntitySection chatConfigType={ChatConfigType.DETAIL} />,
|
||||
},
|
||||
{
|
||||
label: '推荐问题',
|
||||
key: 'recommendedQuestions',
|
||||
children: <RecommendedQuestionsSection />,
|
||||
},
|
||||
];
|
||||
|
||||
const tabItem = [
|
||||
{
|
||||
label: '模型',
|
||||
key: 'overview',
|
||||
children: (
|
||||
<OverView
|
||||
modelList={modelList}
|
||||
disabledEdit={true}
|
||||
onModelChange={(model) => {
|
||||
handleModelChange(model);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tabs
|
||||
className={styles.tab}
|
||||
items={isModel ? isModelItem : tabItem}
|
||||
activeKey={activeKey || defaultTabKey}
|
||||
destroyInactiveTabPane
|
||||
tabBarExtraContent={
|
||||
isModel ? (
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<LeftOutlined />}
|
||||
onClick={() => {
|
||||
onBackDomainBtnClick?.();
|
||||
}}
|
||||
style={{ marginRight: 10 }}
|
||||
>
|
||||
返回主题域
|
||||
</Button>
|
||||
) : undefined
|
||||
}
|
||||
onChange={(menuKey: string) => {
|
||||
onMenuChange?.(menuKey);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(ChatSetting);
|
||||
@@ -10,14 +10,12 @@ import { createDatasource, updateDatasource, getColumns } from '../../service';
|
||||
import type { Dispatch } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import { connect } from 'umi';
|
||||
import { isUndefined } from 'lodash';
|
||||
|
||||
export type CreateFormProps = {
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
createModalVisible: boolean;
|
||||
sql?: string;
|
||||
domainId: number;
|
||||
dataSourceItem: DataInstanceItem | any;
|
||||
onCancel?: () => void;
|
||||
onSubmit?: (dataSourceInfo: any) => void;
|
||||
@@ -37,7 +35,6 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
domainManger,
|
||||
onCancel,
|
||||
createModalVisible,
|
||||
domainId,
|
||||
scriptColumns,
|
||||
sql = '',
|
||||
onSubmit,
|
||||
@@ -51,7 +48,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
const [hasEmptyNameField, setHasEmptyNameField] = useState<boolean>(false);
|
||||
const formValRef = useRef(initFormVal as any);
|
||||
const [form] = Form.useForm();
|
||||
const { dataBaseConfig } = domainManger;
|
||||
const { dataBaseConfig, selectModelId: modelId } = domainManger;
|
||||
const updateFormVal = (val: any) => {
|
||||
formValRef.current = val;
|
||||
};
|
||||
@@ -163,7 +160,7 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
|
||||
databaseId: dataSourceItem?.databaseId || dataBaseConfig.id,
|
||||
queryType: basicInfoFormMode === 'fast' ? 'table_query' : 'sql_query',
|
||||
tableQuery: dbName && tableName ? `${dbName}.${tableName}` : '',
|
||||
domainId,
|
||||
modelId,
|
||||
};
|
||||
const queryDatasource = isEdit ? updateDatasource : createDatasource;
|
||||
const { code, msg, data } = await queryDatasource(queryParams);
|
||||
|
||||
@@ -18,7 +18,6 @@ import FullScreen from '@/components/FullScreen';
|
||||
import SqlEditor from '@/components/SqlEditor';
|
||||
import type { TaskResultItem, DataInstanceItem, TaskResultColumn } from '../data';
|
||||
import { excuteSql } from '@/pages/SemanticModel/service';
|
||||
// import { getDatabaseByDomainId } from '../../service';
|
||||
import DataSourceCreateForm from './DataSourceCreateForm';
|
||||
import type { Dispatch } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
@@ -33,7 +32,6 @@ type IProps = {
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
dataSourceItem: DataInstanceItem;
|
||||
domainId: number;
|
||||
onUpdateSql?: (sql: string) => void;
|
||||
sql?: string;
|
||||
onSubmitSuccess?: (dataSourceInfo: any) => void;
|
||||
@@ -59,12 +57,11 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
domainManger,
|
||||
dataSourceItem,
|
||||
onSubmitSuccess,
|
||||
domainId,
|
||||
sql = '',
|
||||
onUpdateSql,
|
||||
onJdbcSourceChange,
|
||||
}) => {
|
||||
const { dataBaseConfig } = domainManger;
|
||||
const { dataBaseConfig, selectModelId: modelId } = domainManger;
|
||||
const [resultTable, setResultTable] = useState<ResultTableItem[]>([]);
|
||||
const [resultTableLoading, setResultTableLoading] = useState(false);
|
||||
const [resultCols, setResultCols] = useState<ResultColItem[]>([]);
|
||||
@@ -82,8 +79,6 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
y: 200,
|
||||
});
|
||||
|
||||
// const [dataSourceResult, setDataSourceResult] = useState<any>({});
|
||||
|
||||
const [runState, setRunState] = useState<boolean | undefined>();
|
||||
|
||||
const [taskLog, setTaskLog] = useState('');
|
||||
@@ -93,7 +88,6 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
const [isSqlIdeFullScreen, setIsSqlIdeFullScreen] = useState<boolean>(false);
|
||||
const [isSqlResFullScreen, setIsSqlResFullScreen] = useState<boolean>(false);
|
||||
|
||||
// const [sqlParams, setSqlParams] = useState<SqlParamsItem[]>([]);
|
||||
const resultInnerWrap = useRef<HTMLDivElement>();
|
||||
|
||||
const [editorSize, setEditorSize] = useState<number>(0);
|
||||
@@ -104,18 +98,6 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
const [isRight, setIsRight] = useState(false);
|
||||
|
||||
const [scriptColumns, setScriptColumns] = useState<any[]>([]);
|
||||
// const [jdbcSourceName, setJdbcSourceName] = useState<string>(() => {
|
||||
// const sourceId = dataSourceItem.databaseId;
|
||||
// if (sourceId) {
|
||||
// const target: any = jdbcSourceItems.filter((item: any) => {
|
||||
// return item.key === Number(sourceId);
|
||||
// })[0];
|
||||
// if (target) {
|
||||
// return target.label;
|
||||
// }
|
||||
// }
|
||||
// return 'ClickHouse';
|
||||
// });
|
||||
|
||||
useEffect(() => {
|
||||
setJdbcSourceItems([
|
||||
@@ -127,21 +109,6 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
onJdbcSourceChange?.(dataBaseConfig?.id && Number(dataBaseConfig?.id));
|
||||
}, [dataBaseConfig]);
|
||||
|
||||
// const queryDatabaseConfig = async () => {
|
||||
// const { code, data } = await getDatabaseByDomainId(domainId);
|
||||
// if (code === 200) {
|
||||
// setJdbcSourceItems([
|
||||
// {
|
||||
// label: data?.name,
|
||||
// key: data?.id,
|
||||
// },
|
||||
// ]);
|
||||
// onJdbcSourceChange?.(data?.id && Number(data?.id));
|
||||
// return;
|
||||
// }
|
||||
// message.error('数据库配置获取错误');
|
||||
// };
|
||||
|
||||
function creatCalcItem(key: string, data: string) {
|
||||
const line = document.createElement('div'); // 需要每条数据一行,这样避免数据换行的时候获得的宽度不准确
|
||||
const child = document.createElement('span');
|
||||
@@ -245,7 +212,7 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
setResultTableLoading(true);
|
||||
const { code, data, msg } = await excuteSql({
|
||||
sql: value,
|
||||
domainId,
|
||||
modelId,
|
||||
});
|
||||
setResultTableLoading(false);
|
||||
if (code === 200) {
|
||||
@@ -521,7 +488,6 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
{dataSourceModalVisible && (
|
||||
<DataSourceCreateForm
|
||||
sql={sql}
|
||||
domainId={domainId}
|
||||
dataSourceItem={dataSourceItem}
|
||||
scriptColumns={scriptColumns}
|
||||
onCancel={() => {
|
||||
|
||||
@@ -22,14 +22,13 @@ type TableRef = {
|
||||
|
||||
type Props = {
|
||||
initialValues: any;
|
||||
domainId: number;
|
||||
onSubmitSuccess?: (dataSourceInfo: any) => void;
|
||||
};
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
const LIST_KEY = 'list';
|
||||
|
||||
const SqlSide: React.FC<Props> = ({ initialValues, domainId, onSubmitSuccess }) => {
|
||||
const SqlSide: React.FC<Props> = ({ initialValues, onSubmitSuccess }) => {
|
||||
const defaultPanes: Panes[] = [
|
||||
{
|
||||
key: '数据源查询',
|
||||
@@ -98,8 +97,6 @@ const SqlSide: React.FC<Props> = ({ initialValues, domainId, onSubmitSuccess })
|
||||
<SqlDetail
|
||||
onSubmitSuccess={onSubmitSuccess}
|
||||
dataSourceItem={dataSourceItem}
|
||||
oprType={pane.type}
|
||||
domainId={domainId}
|
||||
onUpdateSql={(sql: string) => {
|
||||
updateTabSql(sql, pane.key);
|
||||
}}
|
||||
|
||||
@@ -7,13 +7,12 @@ import { RightOutlined, LeftOutlined } from '@ant-design/icons';
|
||||
|
||||
type Props = {
|
||||
initialValues: any;
|
||||
domainId: number;
|
||||
onSubmitSuccess?: (dataSourceInfo: any) => void;
|
||||
};
|
||||
|
||||
const DEFAULT_RIGHT_SIZE = '300px';
|
||||
|
||||
const DataExploreView: React.FC<Props> = ({ initialValues, domainId, onSubmitSuccess }) => {
|
||||
const DataExploreView: React.FC<Props> = ({ initialValues, onSubmitSuccess }) => {
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -51,11 +50,7 @@ const DataExploreView: React.FC<Props> = ({ initialValues, domainId, onSubmitSuc
|
||||
{collapsed ? <LeftOutlined /> : <RightOutlined />}
|
||||
</div>
|
||||
)}
|
||||
<SqlSide
|
||||
initialValues={initialValues}
|
||||
domainId={domainId}
|
||||
onSubmitSuccess={onSubmitSuccess}
|
||||
/>
|
||||
<SqlSide initialValues={initialValues} onSubmitSuccess={onSubmitSuccess} />
|
||||
</div>
|
||||
|
||||
<Pane initialSize={0} />
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
import { connect, Helmet } from 'umi';
|
||||
import type { StateType } from './model';
|
||||
import OverviewContainer from './OverviewContainer';
|
||||
import type { Dispatch } from 'umi';
|
||||
|
||||
type Props = {
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
};
|
||||
const DomainManager: React.FC<Props> = () => {
|
||||
return (
|
||||
<>
|
||||
<Helmet title={'模型管理-超音数'} />
|
||||
<OverviewContainer mode={'domain'} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(DomainManager);
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Form, Select, Input } from 'antd';
|
||||
import { Form, Input } from 'antd';
|
||||
import StandardFormRow from '@/components/StandardFormRow';
|
||||
import TagSelect from '@/components/TagSelect';
|
||||
import React, { useEffect } from 'react';
|
||||
@@ -64,7 +64,7 @@ const MetricFilter: React.FC<Props> = ({ filterValues = {}, onFiltersChange }) =
|
||||
>
|
||||
<StandardFormRow key="search" block>
|
||||
<div className={styles.searchBox}>
|
||||
<FormItem name={'name'} noStyle>
|
||||
<FormItem name={'key'} noStyle>
|
||||
<div className={styles.searchInput}>
|
||||
<Input.Search
|
||||
placeholder="请输入需要查询指标的ID、指标名称、字段名称"
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import type { ActionType, ProColumns } from '@ant-design/pro-table';
|
||||
import ProTable from '@ant-design/pro-table';
|
||||
import { message } from 'antd';
|
||||
import { message, Space, Popconfirm } from 'antd';
|
||||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import type { Dispatch } from 'umi';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
import { SENSITIVE_LEVEL_ENUM } from '../constant';
|
||||
import { queryMetric } from '../service';
|
||||
import { queryMetric, deleteMetric } from '../service';
|
||||
import MetricFilter from './components/MetricFilter';
|
||||
|
||||
import MetricInfoCreateForm from '../components/MetricInfoCreateForm';
|
||||
import moment from 'moment';
|
||||
import styles from './style.less';
|
||||
import { IDataSource, ISemantic } from '../data';
|
||||
|
||||
type Props = {
|
||||
dispatch: Dispatch;
|
||||
@@ -26,14 +27,17 @@ type QueryMetricListParams = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
const ClassMetricTable: React.FC<Props> = () => {
|
||||
const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const { selectDomainId } = domainManger;
|
||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||
const [pagination, setPagination] = useState({
|
||||
current: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [dataSource, setDataSource] = useState<any[]>([]);
|
||||
const [dataSource, setDataSource] = useState<IDataSource.IDataSourceItem[]>([]);
|
||||
const [metricItem, setMetricItem] = useState<ISemantic.IMetricItem>();
|
||||
const [filterParams, setFilterParams] = useState<Record<string, any>>({});
|
||||
const actionRef = useRef<ActionType>();
|
||||
|
||||
@@ -92,8 +96,8 @@ const ClassMetricTable: React.FC<Props> = () => {
|
||||
title: '字段名称',
|
||||
},
|
||||
{
|
||||
dataIndex: 'domainName',
|
||||
title: '主题域',
|
||||
dataIndex: 'modelName',
|
||||
title: '所属模型',
|
||||
},
|
||||
{
|
||||
dataIndex: 'sensitiveLevel',
|
||||
@@ -127,6 +131,50 @@ const ClassMetricTable: React.FC<Props> = () => {
|
||||
return value && value !== '-' ? moment(value).format('YYYY-MM-DD HH:mm:ss') : '-';
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'x',
|
||||
valueType: 'option',
|
||||
render: (_, record) => {
|
||||
return (
|
||||
<Space>
|
||||
<a
|
||||
key="metricEditBtn"
|
||||
onClick={() => {
|
||||
setMetricItem(record);
|
||||
setCreateModalVisible(true);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</a>
|
||||
|
||||
<Popconfirm
|
||||
title="确认删除?"
|
||||
okText="是"
|
||||
cancelText="否"
|
||||
onConfirm={async () => {
|
||||
const { code, msg } = await deleteMetric(record.id);
|
||||
if (code === 200) {
|
||||
setMetricItem(undefined);
|
||||
actionRef.current?.reload();
|
||||
} else {
|
||||
message.error(msg);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<a
|
||||
key="metricDeleteBtn"
|
||||
onClick={() => {
|
||||
setMetricItem(record);
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</a>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const handleFilterChange = async (filterParams: {
|
||||
@@ -179,6 +227,26 @@ const ClassMetricTable: React.FC<Props> = () => {
|
||||
size="small"
|
||||
options={{ reload: false, density: false, fullScreen: false }}
|
||||
/>
|
||||
{createModalVisible && (
|
||||
<MetricInfoCreateForm
|
||||
domainId={Number(selectDomainId)}
|
||||
createModalVisible={createModalVisible}
|
||||
metricItem={metricItem}
|
||||
onSubmit={() => {
|
||||
setCreateModalVisible(false);
|
||||
actionRef?.current?.reload();
|
||||
dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
domainId: selectDomainId,
|
||||
},
|
||||
});
|
||||
}}
|
||||
onCancel={() => {
|
||||
setCreateModalVisible(false);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,290 @@
|
||||
import { Popover, message, Space } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { connect, Helmet, history, useParams, useRouteMatch, useLocation } from 'umi';
|
||||
import DomainListTree from './components/DomainList';
|
||||
|
||||
import styles from './components/style.less';
|
||||
import type { StateType } from './model';
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
import { ISemantic } from './data';
|
||||
import { getDomainList, getModelList } from './service';
|
||||
import ChatSettingTab from './ChatSetting/ChatSettingTab';
|
||||
import DomainManagerTab from './components/DomainManagerTab';
|
||||
import type { Dispatch } from 'umi';
|
||||
|
||||
type Props = {
|
||||
mode: 'domain' | 'chatSetting';
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
};
|
||||
|
||||
const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) => {
|
||||
const params: any = useParams();
|
||||
const domainId = params.domainId;
|
||||
const modelId = params.modelId;
|
||||
|
||||
const menuKey = params.menuKey ? params.menuKey : !Number(modelId) ? 'overview' : '';
|
||||
const { selectDomainId, selectModelId, selectDomainName, selectModelName, domainList } =
|
||||
domainManger;
|
||||
const [modelList, setModelList] = useState<ISemantic.IDomainItem[]>([]);
|
||||
const [isModel, setIsModel] = useState<boolean>(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [activeKey, setActiveKey] = useState<string>(menuKey);
|
||||
|
||||
const handleOpenChange = (newOpen: boolean) => {
|
||||
setOpen(newOpen);
|
||||
};
|
||||
|
||||
const initSelectedDomain = (domainList: ISemantic.IDomainItem[]) => {
|
||||
const targetNode = domainList.filter((item: any) => {
|
||||
return `${item.id}` === domainId;
|
||||
})[0];
|
||||
|
||||
if (!targetNode) {
|
||||
const firstRootNode = domainList.filter((item: any) => {
|
||||
return item.parentId === 0;
|
||||
})[0];
|
||||
if (firstRootNode) {
|
||||
const { id, name } = firstRootNode;
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectDomain',
|
||||
selectDomainId: id,
|
||||
selectDomainName: name,
|
||||
domainData: firstRootNode,
|
||||
});
|
||||
setActiveKey(menuKey);
|
||||
pushUrlMenu(id, 0, menuKey);
|
||||
}
|
||||
} else {
|
||||
const { id, name } = targetNode;
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectDomain',
|
||||
selectDomainId: id,
|
||||
selectDomainName: name,
|
||||
domainData: targetNode,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const initProjectTree = async () => {
|
||||
const { code, data, msg } = await getDomainList();
|
||||
if (code === 200) {
|
||||
initSelectedDomain(data);
|
||||
dispatch({
|
||||
type: 'domainManger/setDomainList',
|
||||
payload: { domainList: data },
|
||||
});
|
||||
} else {
|
||||
message.error(msg);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
initProjectTree();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectDomainId) {
|
||||
return;
|
||||
}
|
||||
queryModelList();
|
||||
dispatch({
|
||||
type: 'domainManger/queryDatabaseByDomainId',
|
||||
payload: {
|
||||
domainId: selectDomainId,
|
||||
},
|
||||
});
|
||||
}, [selectDomainId]);
|
||||
|
||||
const queryModelList = async () => {
|
||||
const { code, data } = await getModelList(selectDomainId);
|
||||
if (code === 200) {
|
||||
setModelList(data);
|
||||
const model = data.filter((item: any) => {
|
||||
return `${item.id}` === modelId;
|
||||
})[0];
|
||||
if (model) {
|
||||
const { id, name } = model;
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectModel',
|
||||
selectModelId: id,
|
||||
selectModelName: name,
|
||||
modelData: model,
|
||||
});
|
||||
setActiveKey(menuKey);
|
||||
setIsModel(true);
|
||||
pushUrlMenu(selectDomainId, id, menuKey);
|
||||
}
|
||||
} else {
|
||||
message.error('获取模型列表失败!');
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectDomainId) {
|
||||
return;
|
||||
}
|
||||
setIsModel(false);
|
||||
setActiveKey(menuKey);
|
||||
}, [domainList, selectDomainId]);
|
||||
|
||||
const initModelConfig = () => {
|
||||
setIsModel(true);
|
||||
const currentMenuKey = menuKey === 'overview' ? '' : menuKey;
|
||||
pushUrlMenu(selectDomainId, selectModelId, currentMenuKey);
|
||||
setActiveKey(currentMenuKey);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectModelId) {
|
||||
return;
|
||||
}
|
||||
initModelConfig();
|
||||
dispatch({
|
||||
type: 'domainManger/queryDimensionList',
|
||||
payload: {
|
||||
modelId: selectModelId,
|
||||
},
|
||||
});
|
||||
dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
modelId: selectModelId,
|
||||
},
|
||||
});
|
||||
}, [selectModelId]);
|
||||
|
||||
const pushUrlMenu = (domainId: number, modelId: number, menuKey: string) => {
|
||||
const path = mode === 'domain' ? 'semanticModel' : 'chatSetting';
|
||||
history.push(`/${path}/model/${domainId}/${modelId || 0}/${menuKey}`);
|
||||
};
|
||||
|
||||
const handleModelChange = (model?: ISemantic.IModelItem) => {
|
||||
queryModelList();
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
if (`${model.id}` === `${selectModelId}`) {
|
||||
initModelConfig();
|
||||
}
|
||||
const { id, name } = model;
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectModel',
|
||||
selectModelId: id,
|
||||
selectModelName: name,
|
||||
modelData: model,
|
||||
});
|
||||
};
|
||||
|
||||
const cleanModelInfo = (domainId: number) => {
|
||||
setIsModel(false);
|
||||
pushUrlMenu(domainId, 0, 'overview');
|
||||
setActiveKey('overview');
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectModel',
|
||||
selectModelId: 0,
|
||||
selectModelName: '',
|
||||
modelData: undefined,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.projectBody}>
|
||||
<Helmet title={'模型管理-超音数'} />
|
||||
<div className={styles.projectManger}>
|
||||
<h2 className={styles.title}>
|
||||
<Popover
|
||||
zIndex={1000}
|
||||
overlayInnerStyle={{
|
||||
overflow: 'scroll',
|
||||
maxHeight: '800px',
|
||||
}}
|
||||
content={
|
||||
<DomainListTree
|
||||
createDomainBtnVisible={mode === 'domain' ? true : false}
|
||||
onTreeSelected={(domainData) => {
|
||||
setOpen(false);
|
||||
const { id, name } = domainData;
|
||||
cleanModelInfo(id);
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectDomain',
|
||||
selectDomainId: id,
|
||||
selectDomainName: name,
|
||||
domainData,
|
||||
});
|
||||
}}
|
||||
onTreeDataUpdate={() => {
|
||||
initProjectTree();
|
||||
}}
|
||||
/>
|
||||
}
|
||||
trigger="click"
|
||||
open={open}
|
||||
onOpenChange={handleOpenChange}
|
||||
>
|
||||
<div className={styles.domainSelector}>
|
||||
<span className={styles.domainTitle}>
|
||||
<Space>
|
||||
{selectDomainName ? `当前主题域:${selectDomainName}` : '主题域信息'}
|
||||
{selectModelName && (
|
||||
<>
|
||||
<span style={{ position: 'relative', top: '-2px' }}> | </span>
|
||||
<span style={{ fontSize: 16, color: '#296DF3' }}>{selectModelName}</span>
|
||||
</>
|
||||
)}
|
||||
</Space>
|
||||
</span>
|
||||
<span className={styles.downIcon}>
|
||||
<DownOutlined />
|
||||
</span>
|
||||
</div>
|
||||
</Popover>
|
||||
</h2>
|
||||
|
||||
{selectDomainId ? (
|
||||
<>
|
||||
{mode === 'domain' ? (
|
||||
<DomainManagerTab
|
||||
isModel={isModel}
|
||||
activeKey={activeKey}
|
||||
modelList={modelList}
|
||||
handleModelChange={(model) => {
|
||||
handleModelChange(model);
|
||||
}}
|
||||
onBackDomainBtnClick={() => {
|
||||
cleanModelInfo(selectDomainId);
|
||||
}}
|
||||
onMenuChange={(menuKey) => {
|
||||
setActiveKey(menuKey);
|
||||
pushUrlMenu(selectDomainId, selectModelId, menuKey);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<ChatSettingTab
|
||||
isModel={isModel}
|
||||
activeKey={activeKey}
|
||||
modelList={modelList}
|
||||
handleModelChange={(model) => {
|
||||
handleModelChange(model);
|
||||
}}
|
||||
onBackDomainBtnClick={() => {
|
||||
cleanModelInfo(selectDomainId);
|
||||
}}
|
||||
onMenuChange={(menuKey) => {
|
||||
setActiveKey(menuKey);
|
||||
pushUrlMenu(selectDomainId, selectModelId, menuKey);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<h2 className={styles.mainTip}>请选择项目</h2>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(OverviewContainer);
|
||||
@@ -1,251 +0,0 @@
|
||||
import { Tabs, Popover, message } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { connect, Helmet, history, useParams } from 'umi';
|
||||
import DomainListTree from './components/DomainList';
|
||||
import ClassDataSourceTable from './components/ClassDataSourceTable';
|
||||
import ClassDimensionTable from './components/ClassDimensionTable';
|
||||
import ClassMetricTable from './components/ClassMetricTable';
|
||||
import PermissionSection from './components/Permission/PermissionSection';
|
||||
import DatabaseSection from './components/Database/DatabaseSection';
|
||||
import EntitySettingSection from './components/Entity/EntitySettingSection';
|
||||
import OverView from './components/OverView';
|
||||
import styles from './components/style.less';
|
||||
import type { StateType } from './model';
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
import { ISemantic } from './data';
|
||||
import { findLeafNodesFromDomainList } from './utils';
|
||||
import SemanticGraphCanvas from './SemanticGraphCanvas';
|
||||
import { getDomainList } from './service';
|
||||
import type { Dispatch } from 'umi';
|
||||
|
||||
type Props = {
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
};
|
||||
|
||||
const DomainManger: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const defaultTabKey = 'xflow';
|
||||
const params: any = useParams();
|
||||
const menuKey = params.menuKey ? params.menuKey : defaultTabKey;
|
||||
const modelId = params.modelId;
|
||||
const { selectDomainId, selectDomainName, domainList } = domainManger;
|
||||
const [modelList, setModelList] = useState<ISemantic.IDomainItem[]>([]);
|
||||
const [isModel, setIsModel] = useState<boolean>(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [activeKey, setActiveKey] = useState<string>(menuKey);
|
||||
|
||||
useEffect(() => {
|
||||
setActiveKey(menuKey);
|
||||
}, [menuKey]);
|
||||
|
||||
const initSelectedDomain = (domainList: ISemantic.IDomainItem[]) => {
|
||||
const targetNode = domainList.filter((item: any) => {
|
||||
return `${item.id}` === modelId;
|
||||
})[0];
|
||||
if (!targetNode) {
|
||||
const firstRootNode = domainList.filter((item: any) => {
|
||||
return item.parentId === 0;
|
||||
})[0];
|
||||
if (firstRootNode) {
|
||||
const { id, name } = firstRootNode;
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectDomain',
|
||||
selectDomainId: id,
|
||||
selectDomainName: name,
|
||||
domainData: firstRootNode,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const { id, name } = targetNode;
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectDomain',
|
||||
selectDomainId: id,
|
||||
selectDomainName: name,
|
||||
domainData: targetNode,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const initProjectTree = async () => {
|
||||
const { code, data, msg } = await getDomainList();
|
||||
if (code === 200) {
|
||||
if (!selectDomainId) {
|
||||
initSelectedDomain(data);
|
||||
}
|
||||
dispatch({
|
||||
type: 'domainManger/setDomainList',
|
||||
payload: { domainList: data },
|
||||
});
|
||||
} else {
|
||||
message.error(msg);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
initProjectTree();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectDomainId) {
|
||||
return;
|
||||
}
|
||||
const list = findLeafNodesFromDomainList(domainList, selectDomainId);
|
||||
setModelList(list);
|
||||
if (Array.isArray(list) && list.length > 0) {
|
||||
setIsModel(false);
|
||||
pushUrlMenu(selectDomainId, 'overview');
|
||||
setActiveKey('overview');
|
||||
} else {
|
||||
setIsModel(true);
|
||||
const currentMenuKey = menuKey === 'overview' ? defaultTabKey : menuKey;
|
||||
pushUrlMenu(selectDomainId, currentMenuKey);
|
||||
setActiveKey(currentMenuKey);
|
||||
}
|
||||
}, [domainList, selectDomainId]);
|
||||
|
||||
const handleOpenChange = (newOpen: boolean) => {
|
||||
setOpen(newOpen);
|
||||
};
|
||||
|
||||
const pushUrlMenu = (domainId: number, menuKey: string) => {
|
||||
history.push(`/semanticModel/${domainId}/${menuKey}`);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (selectDomainId) {
|
||||
dispatch({
|
||||
type: 'domainManger/queryDimensionList',
|
||||
payload: {
|
||||
domainId: selectDomainId,
|
||||
},
|
||||
});
|
||||
dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
domainId: selectDomainId,
|
||||
},
|
||||
});
|
||||
dispatch({
|
||||
type: 'domainManger/queryDatabaseByDomainId',
|
||||
payload: {
|
||||
domainId: selectDomainId,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [selectDomainId]);
|
||||
|
||||
const tabItem = [
|
||||
{
|
||||
label: '子主题域',
|
||||
key: 'overview',
|
||||
children: <OverView modelList={modelList} />,
|
||||
},
|
||||
{
|
||||
label: '权限管理',
|
||||
key: 'permissonSetting',
|
||||
children: <PermissionSection />,
|
||||
},
|
||||
];
|
||||
|
||||
const isModelItem = [
|
||||
{
|
||||
label: '画布',
|
||||
key: 'xflow',
|
||||
children: (
|
||||
<div style={{ width: '100%', marginTop: -20 }}>
|
||||
<SemanticGraphCanvas />
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: '数据库',
|
||||
key: 'dataBase',
|
||||
children: <DatabaseSection />,
|
||||
},
|
||||
{
|
||||
label: '数据源',
|
||||
key: 'dataSource',
|
||||
children: <ClassDataSourceTable />,
|
||||
},
|
||||
{
|
||||
label: '维度',
|
||||
key: 'dimenstion',
|
||||
children: <ClassDimensionTable key={selectDomainId} />,
|
||||
},
|
||||
{
|
||||
label: '指标',
|
||||
key: 'metric',
|
||||
children: <ClassMetricTable />,
|
||||
},
|
||||
{
|
||||
label: '实体',
|
||||
key: 'entity',
|
||||
children: <EntitySettingSection />,
|
||||
},
|
||||
|
||||
{
|
||||
label: '权限管理',
|
||||
key: 'permissonSetting',
|
||||
children: <PermissionSection />,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className={styles.projectBody}>
|
||||
<Helmet title={'模型管理-超音数'} />
|
||||
<div className={styles.projectManger}>
|
||||
<h2 className={styles.title}>
|
||||
<Popover
|
||||
zIndex={1000}
|
||||
overlayInnerStyle={{
|
||||
overflow: 'scroll',
|
||||
maxHeight: '800px',
|
||||
}}
|
||||
content={
|
||||
<DomainListTree
|
||||
onTreeSelected={() => {
|
||||
setOpen(false);
|
||||
}}
|
||||
onTreeDataUpdate={() => {
|
||||
initProjectTree();
|
||||
}}
|
||||
/>
|
||||
}
|
||||
trigger="click"
|
||||
open={open}
|
||||
onOpenChange={handleOpenChange}
|
||||
>
|
||||
<div className={styles.domainSelector}>
|
||||
<span className={styles.domainTitle}>
|
||||
{selectDomainName ? `当前主题域:${selectDomainName}` : '主题域信息'}
|
||||
</span>
|
||||
<span className={styles.downIcon}>
|
||||
<DownOutlined />
|
||||
</span>
|
||||
</div>
|
||||
</Popover>
|
||||
</h2>
|
||||
{selectDomainId ? (
|
||||
<>
|
||||
<Tabs
|
||||
className={styles.tab}
|
||||
items={!isModel ? tabItem : isModelItem}
|
||||
activeKey={activeKey}
|
||||
destroyInactiveTabPane
|
||||
onChange={(menuKey: string) => {
|
||||
setActiveKey(menuKey);
|
||||
pushUrlMenu(selectDomainId, menuKey);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<h2 className={styles.mainTip}>请选择项目</h2>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(DomainManger);
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
deleteDatasource,
|
||||
getDimensionList,
|
||||
createOrUpdateViewInfo,
|
||||
getViewInfoList,
|
||||
deleteDatasourceRela,
|
||||
} from '../service';
|
||||
import { message } from 'antd';
|
||||
@@ -85,8 +84,8 @@ export namespace GraphApi {
|
||||
|
||||
export const loadDataSourceData = async (args: NsGraph.IGraphMeta) => {
|
||||
const { domainManger, graphConfig } = args.meta;
|
||||
const { selectDomainId } = domainManger;
|
||||
const { code, data = [] } = await getDatasourceList({ domainId: selectDomainId });
|
||||
const { selectModelId } = domainManger;
|
||||
const { code, data = [] } = await getDatasourceList({ modelId: selectModelId });
|
||||
const dataSourceMap = data.reduce(
|
||||
(itemMap: Record<string, IDataSource.IDataSourceItem>, item: IDataSource.IDataSourceItem) => {
|
||||
const { id, name } = item;
|
||||
@@ -161,8 +160,8 @@ export namespace GraphApi {
|
||||
|
||||
export const loadDimensionData = async (args: NsGraph.IGraphMeta) => {
|
||||
const { domainManger } = args.meta;
|
||||
const { domainId } = domainManger;
|
||||
const { code, data } = await getDimensionList({ domainId });
|
||||
const { selectModelId } = domainManger;
|
||||
const { code, data } = await getDimensionList({ modelId: selectModelId });
|
||||
if (code === 200) {
|
||||
const { list } = data;
|
||||
const nodes: NsGraph.INodeConfig[] = list.map((item: any) => {
|
||||
@@ -210,7 +209,7 @@ export namespace GraphApi {
|
||||
const { domainManger, graphConfig } = graphMeta.meta;
|
||||
const { code, msg } = await createOrUpdateViewInfo({
|
||||
id: graphConfig?.id,
|
||||
domainId: domainManger.selectDomainId,
|
||||
modelId: domainManger.selectModelId,
|
||||
type: 'datasource',
|
||||
config: JSON.stringify(tempGraphData),
|
||||
});
|
||||
|
||||
@@ -18,7 +18,6 @@ const DeleteConfirmModal: React.FC<Props> = ({
|
||||
}) => {
|
||||
const [confirmLoading, setConfirmLoading] = useState(false);
|
||||
const deleteNode = async () => {
|
||||
setConfirmLoading(true);
|
||||
const { id, nodeType } = nodeData;
|
||||
let deleteQuery;
|
||||
if (nodeType === SemanticNodeType.DIMENSION) {
|
||||
@@ -34,6 +33,7 @@ const DeleteConfirmModal: React.FC<Props> = ({
|
||||
message.error('当前节点类型不是维度,指标,数据源中的一种,请确认节点数据');
|
||||
return;
|
||||
}
|
||||
setConfirmLoading(true);
|
||||
const { code, msg } = await deleteQuery(id);
|
||||
setConfirmLoading(false);
|
||||
if (code === 200) {
|
||||
|
||||
@@ -32,7 +32,6 @@ import GraphLegendVisibleModeItem from './components/GraphLegendVisibleModeItem'
|
||||
// import { cloneDeep } from 'lodash';
|
||||
|
||||
type Props = {
|
||||
domainId: number;
|
||||
// graphShowType?: SemanticNodeType;
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
@@ -40,7 +39,6 @@ type Props = {
|
||||
|
||||
const DomainManger: React.FC<Props> = ({
|
||||
domainManger,
|
||||
domainId,
|
||||
// graphShowType = SemanticNodeType.DIMENSION,
|
||||
// graphShowType,
|
||||
dispatch,
|
||||
@@ -65,7 +63,7 @@ const DomainManger: React.FC<Props> = ({
|
||||
|
||||
const [dataSourceInfoList, setDataSourceInfoList] = useState<IDataSource.IDataSourceItem[]>([]);
|
||||
|
||||
const { dimensionList, metricList } = domainManger;
|
||||
const { dimensionList, metricList, selectModelId: modelId, selectDomainId } = domainManger;
|
||||
|
||||
const dimensionListRef = useRef<ISemantic.IDimensionItem[]>([]);
|
||||
const metricListRef = useRef<ISemantic.IMetricItem[]>([]);
|
||||
@@ -139,10 +137,10 @@ const DomainManger: React.FC<Props> = ({
|
||||
};
|
||||
|
||||
const queryDataSourceList = async (params: {
|
||||
domainId: number;
|
||||
modelId: number;
|
||||
graphShowType?: SemanticNodeType;
|
||||
}) => {
|
||||
const { code, data } = await getDomainSchemaRela(params.domainId);
|
||||
const { code, data } = await getDomainSchemaRela(params.modelId);
|
||||
if (code === 200) {
|
||||
if (data) {
|
||||
setDataSourceInfoList(
|
||||
@@ -165,8 +163,8 @@ const DomainManger: React.FC<Props> = ({
|
||||
useEffect(() => {
|
||||
graphLegendDataSourceIds.current = undefined;
|
||||
graphRef.current = null;
|
||||
queryDataSourceList({ domainId });
|
||||
}, [domainId]);
|
||||
queryDataSourceList({ modelId });
|
||||
}, [modelId]);
|
||||
|
||||
// const getLegendDataFilterFunctions = () => {
|
||||
// legendDataRef.current.map((item: any) => {
|
||||
@@ -273,7 +271,7 @@ const DomainManger: React.FC<Props> = ({
|
||||
if (targetData.nodeType === SemanticNodeType.DIMENSION) {
|
||||
const targetItem = dimensionListRef.current.find((item) => item.id === targetData.uid);
|
||||
if (targetItem) {
|
||||
setCurrentNodeData(targetItem);
|
||||
setCurrentNodeData({ ...targetData, ...targetItem });
|
||||
setConfirmModalOpenState(true);
|
||||
} else {
|
||||
message.error('获取维度初始化数据失败');
|
||||
@@ -282,7 +280,7 @@ const DomainManger: React.FC<Props> = ({
|
||||
if (targetData.nodeType === SemanticNodeType.METRIC) {
|
||||
const targetItem = metricListRef.current.find((item) => item.id === targetData.uid);
|
||||
if (targetItem) {
|
||||
setCurrentNodeData(targetItem);
|
||||
setCurrentNodeData({ ...targetData, ...targetItem });
|
||||
setConfirmModalOpenState(true);
|
||||
} else {
|
||||
message.error('获取指标初始化数据失败');
|
||||
@@ -515,7 +513,7 @@ const DomainManger: React.FC<Props> = ({
|
||||
|
||||
const updateGraphData = async (params?: { graphShowType?: SemanticNodeType }) => {
|
||||
const graphRootData = await queryDataSourceList({
|
||||
domainId,
|
||||
modelId,
|
||||
graphShowType: params?.graphShowType,
|
||||
});
|
||||
if (graphRootData) {
|
||||
@@ -571,7 +569,7 @@ const DomainManger: React.FC<Props> = ({
|
||||
/>
|
||||
<div
|
||||
ref={ref}
|
||||
key={`${domainId}`}
|
||||
key={`${modelId}`}
|
||||
id="semanticGraph"
|
||||
style={{ width: '100%', height: 'calc(100vh - 175px)', position: 'relative' }}
|
||||
/>
|
||||
@@ -595,7 +593,7 @@ const DomainManger: React.FC<Props> = ({
|
||||
dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
domainId,
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -603,7 +601,7 @@ const DomainManger: React.FC<Props> = ({
|
||||
dispatch({
|
||||
type: 'domainManger/queryDimensionList',
|
||||
payload: {
|
||||
domainId,
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -612,7 +610,7 @@ const DomainManger: React.FC<Props> = ({
|
||||
|
||||
{createDimensionModalVisible && (
|
||||
<DimensionInfoModal
|
||||
domainId={domainId}
|
||||
modelId={modelId}
|
||||
bindModalVisible={createDimensionModalVisible}
|
||||
dimensionItem={dimensionItem}
|
||||
dataSourceList={nodeDataSource ? [nodeDataSource] : dataSourceInfoList}
|
||||
@@ -622,7 +620,7 @@ const DomainManger: React.FC<Props> = ({
|
||||
dispatch({
|
||||
type: 'domainManger/queryDimensionList',
|
||||
payload: {
|
||||
domainId,
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
}}
|
||||
@@ -633,7 +631,8 @@ const DomainManger: React.FC<Props> = ({
|
||||
)}
|
||||
{createMetricModalVisible && (
|
||||
<MetricInfoCreateForm
|
||||
domainId={domainId}
|
||||
domainId={selectDomainId}
|
||||
modelId={modelId}
|
||||
key={metricItem?.id}
|
||||
datasourceId={nodeDataSource?.id}
|
||||
createModalVisible={createMetricModalVisible}
|
||||
@@ -644,7 +643,7 @@ const DomainManger: React.FC<Props> = ({
|
||||
dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
domainId,
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
}}
|
||||
@@ -676,13 +675,13 @@ const DomainManger: React.FC<Props> = ({
|
||||
? dispatch({
|
||||
type: 'domainManger/queryDimensionList',
|
||||
payload: {
|
||||
domainId,
|
||||
modelId,
|
||||
},
|
||||
})
|
||||
: dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
domainId,
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -38,7 +38,7 @@ const SemanticGraphCanvas: React.FC<Props> = ({ domainManger }) => {
|
||||
</div>
|
||||
) : ( */}
|
||||
<div style={{ width: '100%' }}>
|
||||
<SemanticGraph domainId={selectDomainId} />
|
||||
<SemanticGraph />
|
||||
</div>
|
||||
{/* )} */}
|
||||
</div>
|
||||
|
||||
@@ -113,6 +113,7 @@ const BindMeasuresTable: React.FC<CreateFormProps> = ({
|
||||
size="small"
|
||||
search={false}
|
||||
options={false}
|
||||
scroll={{ y: 800 }}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
@@ -15,7 +15,7 @@ type Props = {
|
||||
};
|
||||
|
||||
const ClassDataSourceTable: React.FC<Props> = ({ dispatch, domainManger }) => {
|
||||
const { selectDomainId } = domainManger;
|
||||
const { selectModelId } = domainManger;
|
||||
const [dataSourceItem, setDataSourceItem] = useState<any>();
|
||||
const [createDataSourceModalOpen, setCreateDataSourceModalOpen] = useState(false);
|
||||
|
||||
@@ -59,7 +59,7 @@ const ClassDataSourceTable: React.FC<Props> = ({ dispatch, domainManger }) => {
|
||||
return (
|
||||
<Space>
|
||||
<a
|
||||
key="classEditBtn"
|
||||
key="datasourceEditBtn"
|
||||
onClick={() => {
|
||||
setDataSourceItem(record);
|
||||
setCreateDataSourceModalOpen(true);
|
||||
@@ -82,7 +82,7 @@ const ClassDataSourceTable: React.FC<Props> = ({ dispatch, domainManger }) => {
|
||||
}}
|
||||
>
|
||||
<a
|
||||
key="classEditBtn"
|
||||
key="datasourceDeleteBtn"
|
||||
onClick={() => {
|
||||
setDataSourceItem(record);
|
||||
}}
|
||||
@@ -127,7 +127,7 @@ const ClassDataSourceTable: React.FC<Props> = ({ dispatch, domainManger }) => {
|
||||
actionRef={actionRef}
|
||||
rowKey="id"
|
||||
columns={columns}
|
||||
params={{ domainId: selectDomainId }}
|
||||
params={{ modelId: selectModelId }}
|
||||
request={queryDataSourceList}
|
||||
pagination={false}
|
||||
search={false}
|
||||
|
||||
@@ -28,7 +28,7 @@ const ClassDataSourceTypeModal: React.FC<Props> = ({
|
||||
onCancel,
|
||||
dispatch,
|
||||
}) => {
|
||||
const { selectDomainId, dataBaseConfig } = domainManger;
|
||||
const { selectDomainId, dataBaseConfig, selectModelId } = domainManger;
|
||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||
|
||||
const [dataSourceModalVisible, setDataSourceModalVisible] = useState(false);
|
||||
@@ -128,7 +128,7 @@ const ClassDataSourceTypeModal: React.FC<Props> = ({
|
||||
type="primary"
|
||||
key="console"
|
||||
onClick={() => {
|
||||
history.replace(`/semanticModel/${selectDomainId}/dataBase`);
|
||||
history.replace(`/semanticModel/${selectDomainId}/0/dataBase`);
|
||||
onCancel?.();
|
||||
}}
|
||||
>
|
||||
@@ -173,7 +173,6 @@ const ClassDataSourceTypeModal: React.FC<Props> = ({
|
||||
>
|
||||
<DataSource
|
||||
initialValues={dataSourceItem}
|
||||
domainId={Number(selectDomainId)}
|
||||
onSubmitSuccess={() => {
|
||||
setCreateModalVisible(false);
|
||||
onSubmit?.();
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
import { Modal, Card, Row, Col, Result, Button } from 'antd';
|
||||
import { ConsoleSqlOutlined, CoffeeOutlined } from '@ant-design/icons';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { history, connect } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
const { Meta } = Card;
|
||||
type Props = {
|
||||
open: boolean;
|
||||
domainManger: StateType;
|
||||
onTypeChange: (type: 'fast' | 'normal') => void;
|
||||
onCancel?: () => void;
|
||||
};
|
||||
|
||||
const ClassDataSourceTypeModal: React.FC<Props> = ({
|
||||
open,
|
||||
onTypeChange,
|
||||
domainManger,
|
||||
onCancel,
|
||||
}) => {
|
||||
const { selectDomainId, dataBaseConfig } = domainManger;
|
||||
const [createDataSourceModalOpen, setCreateDataSourceModalOpen] = useState(false);
|
||||
useEffect(() => {
|
||||
setCreateDataSourceModalOpen(open);
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
open={createDataSourceModalOpen}
|
||||
onCancel={() => {
|
||||
setCreateDataSourceModalOpen(false);
|
||||
onCancel?.();
|
||||
}}
|
||||
footer={null}
|
||||
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);
|
||||
}}
|
||||
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);
|
||||
}}
|
||||
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}/dataBase`);
|
||||
onCancel?.();
|
||||
}}
|
||||
>
|
||||
去设置
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(ClassDataSourceTypeModal);
|
||||
@@ -19,7 +19,7 @@ type Props = {
|
||||
};
|
||||
|
||||
const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const { selectDomainId } = domainManger;
|
||||
const { selectModelId: modelId } = domainManger;
|
||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||
const [dimensionItem, setDimensionItem] = useState<ISemantic.IDimensionItem>();
|
||||
const [dataSourceList, setDataSourceList] = useState<any[]>([]);
|
||||
@@ -40,7 +40,7 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const { code, data, msg } = await getDimensionList({
|
||||
...params,
|
||||
...pagination,
|
||||
domainId: selectDomainId,
|
||||
modelId,
|
||||
});
|
||||
const { list, pageSize, current, total } = data || {};
|
||||
let resData: any = {};
|
||||
@@ -67,7 +67,7 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
};
|
||||
|
||||
const queryDataSourceList = async () => {
|
||||
const { code, data, msg } = await getDatasourceList({ domainId: selectDomainId });
|
||||
const { code, data, msg } = await getDatasourceList({ modelId });
|
||||
if (code === 200) {
|
||||
setDataSourceList(data);
|
||||
} else {
|
||||
@@ -77,7 +77,7 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
|
||||
useEffect(() => {
|
||||
queryDataSourceList();
|
||||
}, [selectDomainId]);
|
||||
}, [modelId]);
|
||||
|
||||
const columns: ProColumns[] = [
|
||||
{
|
||||
@@ -139,7 +139,7 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
return (
|
||||
<Space>
|
||||
<a
|
||||
key="classEditBtn"
|
||||
key="dimensionEditBtn"
|
||||
onClick={() => {
|
||||
setDimensionItem(record);
|
||||
setCreateModalVisible(true);
|
||||
@@ -148,7 +148,7 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
编辑
|
||||
</a>
|
||||
<a
|
||||
key="classEditBtn"
|
||||
key="dimensionValueEditBtn"
|
||||
onClick={() => {
|
||||
setDimensionItem(record);
|
||||
setDimensionValueSettingModalVisible(true);
|
||||
@@ -176,7 +176,7 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
}}
|
||||
>
|
||||
<a
|
||||
key="classEditBtn"
|
||||
key="dimensionDeleteEditBtn"
|
||||
onClick={() => {
|
||||
setDimensionItem(record);
|
||||
}}
|
||||
@@ -195,7 +195,6 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
<ProTable
|
||||
className={`${styles.classTable} ${styles.classTableSelectColumnAlignLeft}`}
|
||||
actionRef={actionRef}
|
||||
// headerTitle="维度列表"
|
||||
rowKey="id"
|
||||
columns={columns}
|
||||
request={queryDimensionList}
|
||||
@@ -236,7 +235,7 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
|
||||
{createModalVisible && (
|
||||
<DimensionInfoModal
|
||||
domainId={selectDomainId}
|
||||
modelId={modelId}
|
||||
bindModalVisible={createModalVisible}
|
||||
dimensionItem={dimensionItem}
|
||||
dataSourceList={dataSourceList}
|
||||
@@ -246,7 +245,7 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
dispatch({
|
||||
type: 'domainManger/queryDimensionList',
|
||||
payload: {
|
||||
domainId: selectDomainId,
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
return;
|
||||
@@ -269,7 +268,7 @@ const ClassDimensionTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
dispatch({
|
||||
type: 'domainManger/queryDimensionList',
|
||||
payload: {
|
||||
domainId: selectDomainId,
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
setDimensionValueSettingModalVisible(false);
|
||||
|
||||
@@ -12,6 +12,7 @@ import MetricInfoCreateForm from './MetricInfoCreateForm';
|
||||
|
||||
import moment from 'moment';
|
||||
import styles from './style.less';
|
||||
import { ISemantic } from '../data';
|
||||
|
||||
type Props = {
|
||||
dispatch: Dispatch;
|
||||
@@ -19,9 +20,9 @@ type Props = {
|
||||
};
|
||||
|
||||
const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const { selectDomainId } = domainManger;
|
||||
const { selectModelId: modelId, selectDomainId } = domainManger;
|
||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||
const [metricItem, setMetricItem] = useState<any>();
|
||||
const [metricItem, setMetricItem] = useState<ISemantic.IMetricItem>();
|
||||
const [pagination, setPagination] = useState({
|
||||
current: 1,
|
||||
pageSize: 20,
|
||||
@@ -33,7 +34,7 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const { code, data, msg } = await queryMetric({
|
||||
...params,
|
||||
...pagination,
|
||||
domainId: selectDomainId,
|
||||
modelId,
|
||||
});
|
||||
const { list, pageSize, current, total } = data || {};
|
||||
let resData: any = {};
|
||||
@@ -95,7 +96,6 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
{
|
||||
dataIndex: 'type',
|
||||
title: '指标类型',
|
||||
// search: false,
|
||||
valueEnum: {
|
||||
ATOMIC: '原子指标',
|
||||
DERIVED: '衍生指标',
|
||||
@@ -128,7 +128,7 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
return (
|
||||
<Space>
|
||||
<a
|
||||
key="classEditBtn"
|
||||
key="metricEditBtn"
|
||||
onClick={() => {
|
||||
setMetricItem(record);
|
||||
setCreateModalVisible(true);
|
||||
@@ -152,7 +152,7 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
}}
|
||||
>
|
||||
<a
|
||||
key="classEditBtn"
|
||||
key="metricDeleteBtn"
|
||||
onClick={() => {
|
||||
setMetricItem(record);
|
||||
}}
|
||||
@@ -171,7 +171,6 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
<ProTable
|
||||
className={`${styles.classTable} ${styles.classTableSelectColumnAlignLeft}`}
|
||||
actionRef={actionRef}
|
||||
// headerTitle="指标列表"
|
||||
rowKey="id"
|
||||
search={{
|
||||
span: 4,
|
||||
@@ -181,7 +180,7 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
},
|
||||
}}
|
||||
columns={columns}
|
||||
params={{ domainId: selectDomainId }}
|
||||
params={{ modelId }}
|
||||
request={queryMetricList}
|
||||
pagination={pagination}
|
||||
tableAlertRender={() => {
|
||||
@@ -212,7 +211,8 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
/>
|
||||
{createModalVisible && (
|
||||
<MetricInfoCreateForm
|
||||
domainId={Number(selectDomainId)}
|
||||
domainId={selectDomainId}
|
||||
modelId={Number(modelId)}
|
||||
createModalVisible={createModalVisible}
|
||||
metricItem={metricItem}
|
||||
onSubmit={() => {
|
||||
@@ -221,7 +221,7 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
domainId: selectDomainId,
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, forwardRef, useImperativeHandle, useState } from 'react';
|
||||
import type { ForwardRefRenderFunction } from 'react';
|
||||
import { message, Form, Input, Select, Button, Space } from 'antd';
|
||||
import { saveDatabase, getDatabaseByDomainId, testDatabaseConnect } from '../../service';
|
||||
import { saveDatabase, testDatabaseConnect } from '../../service';
|
||||
import { formLayout } from '@/components/FormHelper/utils';
|
||||
|
||||
import styles from '../style.less';
|
||||
|
||||
@@ -10,7 +10,7 @@ import { createDimension, updateDimension } from '../service';
|
||||
import { message } from 'antd';
|
||||
|
||||
export type CreateFormProps = {
|
||||
domainId: number;
|
||||
modelId: number;
|
||||
dimensionItem?: ISemantic.IDimensionItem;
|
||||
onCancel: () => void;
|
||||
bindModalVisible: boolean;
|
||||
@@ -24,7 +24,7 @@ const { Option } = Select;
|
||||
const { TextArea } = Input;
|
||||
|
||||
const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
domainId,
|
||||
modelId,
|
||||
onCancel,
|
||||
bindModalVisible,
|
||||
dimensionItem,
|
||||
@@ -55,7 +55,7 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
|
||||
|
||||
const saveDimension = async (fieldsValue: any, isSilenceSubmit = false) => {
|
||||
const queryParams = {
|
||||
domainId,
|
||||
modelId,
|
||||
type: 'categorical',
|
||||
...fieldsValue,
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@ type DomainListProps = {
|
||||
createDomainBtnVisible?: boolean;
|
||||
dispatch: Dispatch;
|
||||
onCreateDomainBtnClick?: () => void;
|
||||
onTreeSelected?: () => void;
|
||||
onTreeSelected?: (targetNodeData: ISemantic.IDomainItem) => void;
|
||||
onTreeDataUpdate?: () => void;
|
||||
};
|
||||
|
||||
@@ -57,7 +57,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
||||
const [projectInfoParams, setProjectInfoParams] = useState<any>({});
|
||||
const [filterValue, setFliterValue] = useState<string>('');
|
||||
const [expandedKeys, setExpandedKeys] = useState<string[]>([]);
|
||||
const [classList, setClassList] = useState<any[]>([]);
|
||||
const [classList, setClassList] = useState<ISemantic.IDomainItem[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const treeData = addPathInTreeData(constructorClassTreeFromList(domainList));
|
||||
@@ -77,13 +77,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
||||
const targetNodeData = classList.filter((item: any) => {
|
||||
return item.id === selectedKeys;
|
||||
})[0];
|
||||
onTreeSelected?.();
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectDomain',
|
||||
selectDomainId: selectedKeys,
|
||||
selectDomainName: projectName,
|
||||
domainData: targetNodeData,
|
||||
});
|
||||
onTreeSelected?.(targetNodeData);
|
||||
};
|
||||
|
||||
const editProject = async (values: any) => {
|
||||
@@ -134,7 +128,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
||||
</span>
|
||||
{createDomainBtnVisible && (
|
||||
<span className={styles.operation}>
|
||||
{Array.isArray(path) && path.length < 3 && (
|
||||
{Array.isArray(path) && path.length < 2 && (
|
||||
<PlusOutlined
|
||||
className={styles.icon}
|
||||
onClick={() => {
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
import { Tabs, Button } from 'antd';
|
||||
import React from 'react';
|
||||
import { connect } from 'umi';
|
||||
|
||||
import ClassDataSourceTable from './ClassDataSourceTable';
|
||||
import ClassDimensionTable from './ClassDimensionTable';
|
||||
import ClassMetricTable from './ClassMetricTable';
|
||||
import PermissionSection from './Permission/PermissionSection';
|
||||
import DatabaseSection from './Database/DatabaseSection';
|
||||
import EntitySettingSection from './Entity/EntitySettingSection';
|
||||
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 type { Dispatch } from 'umi';
|
||||
|
||||
type Props = {
|
||||
isModel: boolean;
|
||||
activeKey: string;
|
||||
modelList: ISemantic.IModelItem[];
|
||||
handleModelChange: (model?: ISemantic.IModelItem) => void;
|
||||
onBackDomainBtnClick?: () => void;
|
||||
onMenuChange?: (menuKey: string) => void;
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
};
|
||||
const DomainManagerTab: React.FC<Props> = ({
|
||||
isModel,
|
||||
activeKey,
|
||||
modelList,
|
||||
handleModelChange,
|
||||
onBackDomainBtnClick,
|
||||
onMenuChange,
|
||||
}) => {
|
||||
const defaultTabKey = 'xflow';
|
||||
|
||||
const tabItem = [
|
||||
{
|
||||
label: '模型',
|
||||
key: 'overview',
|
||||
children: (
|
||||
<OverView
|
||||
modelList={modelList}
|
||||
onModelChange={(model) => {
|
||||
handleModelChange(model);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: '数据库',
|
||||
key: 'dataBase',
|
||||
children: <DatabaseSection />,
|
||||
},
|
||||
{
|
||||
label: '权限管理',
|
||||
key: 'permissonSetting',
|
||||
children: <PermissionSection permissionTarget={'domain'} />,
|
||||
},
|
||||
];
|
||||
|
||||
const isModelItem = [
|
||||
{
|
||||
label: '画布',
|
||||
key: 'xflow',
|
||||
children: (
|
||||
<div style={{ width: '100%', marginTop: -20 }}>
|
||||
<SemanticGraphCanvas />
|
||||
</div>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
label: '数据源',
|
||||
key: 'dataSource',
|
||||
children: <ClassDataSourceTable />,
|
||||
},
|
||||
{
|
||||
label: '维度',
|
||||
key: 'dimenstion',
|
||||
children: <ClassDimensionTable />,
|
||||
},
|
||||
{
|
||||
label: '指标',
|
||||
key: 'metric',
|
||||
children: <ClassMetricTable />,
|
||||
},
|
||||
{
|
||||
label: '实体',
|
||||
key: 'entity',
|
||||
children: <EntitySettingSection />,
|
||||
},
|
||||
|
||||
{
|
||||
label: '权限管理',
|
||||
key: 'permissonSetting',
|
||||
children: <PermissionSection permissionTarget={'model'} />,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tabs
|
||||
className={styles.tab}
|
||||
items={!isModel ? tabItem : isModelItem}
|
||||
activeKey={activeKey || defaultTabKey}
|
||||
destroyInactiveTabPane
|
||||
tabBarExtraContent={
|
||||
isModel ? (
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<LeftOutlined />}
|
||||
onClick={() => {
|
||||
onBackDomainBtnClick?.();
|
||||
}}
|
||||
style={{ marginRight: 10 }}
|
||||
>
|
||||
返回主题域
|
||||
</Button>
|
||||
) : undefined
|
||||
}
|
||||
onChange={(menuKey: string) => {
|
||||
onMenuChange?.(menuKey);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(DomainManagerTab);
|
||||
@@ -143,7 +143,7 @@ const DefaultSettingForm: ForwardRefRenderFunction<any, Props> = (
|
||||
};
|
||||
const { code, msg, data } = await saveDomainExtendQuery({
|
||||
[chatConfigKey]: params,
|
||||
domainId,
|
||||
// domainId,
|
||||
id,
|
||||
});
|
||||
if (code === 200) {
|
||||
|
||||
@@ -126,7 +126,7 @@ const DimensionAndMetricVisibleModal: React.FC<Props> = ({
|
||||
|
||||
const { code, msg } = await saveDomainExtendQuery({
|
||||
[chatConfigKey]: params,
|
||||
domainId,
|
||||
// domainId,
|
||||
id,
|
||||
});
|
||||
if (code === 200) {
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import { useEffect, useState, forwardRef, useImperativeHandle } from 'react';
|
||||
import type { ForwardRefRenderFunction } from 'react';
|
||||
import { message, Form, Input, Select, Button } from 'antd';
|
||||
import { updateDomain } from '../../service';
|
||||
import { updateModel } from '../../service';
|
||||
import type { ISemantic } from '../../data';
|
||||
import { formLayout } from '@/components/FormHelper/utils';
|
||||
import styles from '../style.less';
|
||||
|
||||
type Props = {
|
||||
domainData?: ISemantic.IDomainItem;
|
||||
modelData?: ISemantic.IModelItem;
|
||||
dimensionList: ISemantic.IDimensionList;
|
||||
domainId: number;
|
||||
modelId: number;
|
||||
onSubmit: () => void;
|
||||
};
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
const EntityCreateForm: ForwardRefRenderFunction<any, Props> = (
|
||||
{ domainData, dimensionList, domainId, onSubmit },
|
||||
{ modelData, dimensionList, modelId, onSubmit },
|
||||
ref,
|
||||
) => {
|
||||
const [form] = Form.useForm();
|
||||
@@ -27,15 +27,15 @@ const EntityCreateForm: ForwardRefRenderFunction<any, Props> = (
|
||||
|
||||
useEffect(() => {
|
||||
form.resetFields();
|
||||
if (!domainData?.entity) {
|
||||
if (!modelData?.entity) {
|
||||
return;
|
||||
}
|
||||
const { entity } = domainData;
|
||||
const { entity } = modelData;
|
||||
form.setFieldsValue({
|
||||
...entity,
|
||||
name: entity.names.join(','),
|
||||
});
|
||||
}, [domainData]);
|
||||
}, [modelData]);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
getFormValidateFields,
|
||||
@@ -54,14 +54,14 @@ const EntityCreateForm: ForwardRefRenderFunction<any, Props> = (
|
||||
const saveEntity = async () => {
|
||||
const values = await form.validateFields();
|
||||
const { name } = values;
|
||||
const { code, msg, data } = await updateDomain({
|
||||
...domainData,
|
||||
const { code, msg, data } = await updateModel({
|
||||
...modelData,
|
||||
entity: {
|
||||
...values,
|
||||
names: name.split(','),
|
||||
},
|
||||
id: domainId,
|
||||
domainId,
|
||||
id: modelId,
|
||||
modelId,
|
||||
});
|
||||
|
||||
if (code === 200) {
|
||||
@@ -79,20 +79,11 @@ const EntityCreateForm: ForwardRefRenderFunction<any, Props> = (
|
||||
<FormItem hidden={true} name="id" label="ID">
|
||||
<Input placeholder="id" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
name="name"
|
||||
label="实体别名"
|
||||
// rules={[{ required: true, message: '请输入实体别名' }]}
|
||||
>
|
||||
<FormItem name="name" label="实体别名">
|
||||
<Input placeholder="请输入实体别名,多个名称以英文逗号分隔" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
name="entityId"
|
||||
label="唯一标识"
|
||||
// rules={[{ required: true, message: '请选择实体标识' }]}
|
||||
>
|
||||
<FormItem name="entityId" label="唯一标识">
|
||||
<Select
|
||||
// mode="multiple"
|
||||
allowClear
|
||||
style={{ width: '100%' }}
|
||||
// filterOption={(inputValue: string, item: any) => {
|
||||
|
||||
@@ -22,22 +22,22 @@ const EntitySection: React.FC<Props> = ({
|
||||
dispatch,
|
||||
chatConfigType = ChatConfigType.DETAIL,
|
||||
}) => {
|
||||
const { selectDomainId, dimensionList, metricList } = domainManger;
|
||||
const { selectDomainId, selectModelId: modelId, dimensionList, metricList } = domainManger;
|
||||
|
||||
const [entityData, setentityData] = useState<IChatConfig.IChatRichConfig>();
|
||||
const [entityData, setEntityData] = useState<IChatConfig.IChatRichConfig>();
|
||||
|
||||
const queryThemeListData: any = async () => {
|
||||
const { code, data } = await getDomainExtendDetailConfig({
|
||||
domainId: selectDomainId,
|
||||
modelId,
|
||||
});
|
||||
|
||||
if (code === 200) {
|
||||
const { chatAggRichConfig, chatDetailRichConfig, id, domainId } = data;
|
||||
const { chatAggRichConfig, chatDetailRichConfig, id, domainId, modelId } = data;
|
||||
if (chatConfigType === ChatConfigType.DETAIL) {
|
||||
setentityData({ ...chatDetailRichConfig, id, domainId });
|
||||
setEntityData({ ...chatDetailRichConfig, id, domainId, modelId });
|
||||
}
|
||||
if (chatConfigType === ChatConfigType.AGG) {
|
||||
setentityData({ ...chatAggRichConfig, id, domainId });
|
||||
setEntityData({ ...chatAggRichConfig, id, domainId, modelId });
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -50,8 +50,11 @@ const EntitySection: React.FC<Props> = ({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!modelId) {
|
||||
return;
|
||||
}
|
||||
initPage();
|
||||
}, [selectDomainId]);
|
||||
}, [modelId]);
|
||||
|
||||
return (
|
||||
<div style={{ width: 800, margin: '0 auto' }}>
|
||||
|
||||
@@ -3,7 +3,7 @@ import React, { useState, useEffect, useRef } from 'react';
|
||||
import type { Dispatch } from 'umi';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import { getDomainDetail } from '../../service';
|
||||
import { getModelDetail } from '../../service';
|
||||
import ProCard from '@ant-design/pro-card';
|
||||
import EntityCreateForm from './EntityCreateForm';
|
||||
import type { ISemantic } from '../../data';
|
||||
@@ -14,19 +14,19 @@ type Props = {
|
||||
};
|
||||
|
||||
const EntitySettingSection: React.FC<Props> = ({ domainManger }) => {
|
||||
const { selectDomainId, dimensionList } = domainManger;
|
||||
const { dimensionList, selectModelId: modelId } = domainManger;
|
||||
|
||||
const [domainData, setDomainData] = useState<ISemantic.IDomainItem>();
|
||||
const [modelData, setModelData] = useState<ISemantic.IModelItem>();
|
||||
|
||||
const entityCreateRef = useRef<any>({});
|
||||
|
||||
const queryDomainData: any = async () => {
|
||||
const { code, data } = await getDomainDetail({
|
||||
domainId: selectDomainId,
|
||||
const { code, data } = await getModelDetail({
|
||||
modelId,
|
||||
});
|
||||
|
||||
if (code === 200) {
|
||||
setDomainData(data);
|
||||
setModelData(data);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -40,7 +40,7 @@ const EntitySettingSection: React.FC<Props> = ({ domainManger }) => {
|
||||
|
||||
useEffect(() => {
|
||||
initPage();
|
||||
}, [selectDomainId]);
|
||||
}, [modelId]);
|
||||
|
||||
return (
|
||||
<div style={{ width: 800, margin: '0 auto' }}>
|
||||
@@ -49,8 +49,8 @@ const EntitySettingSection: React.FC<Props> = ({ domainManger }) => {
|
||||
<ProCard title="实体" bordered>
|
||||
<EntityCreateForm
|
||||
ref={entityCreateRef}
|
||||
domainId={Number(selectDomainId)}
|
||||
domainData={domainData}
|
||||
modelId={Number(modelId)}
|
||||
modelData={modelData}
|
||||
dimensionList={dimensionList}
|
||||
onSubmit={() => {
|
||||
queryDomainData();
|
||||
|
||||
@@ -12,14 +12,14 @@ type Props = {
|
||||
};
|
||||
|
||||
const RecommendedQuestionsSection: React.FC<Props> = ({ domainManger }) => {
|
||||
const { selectDomainId } = domainManger;
|
||||
const { selectModelId: modelId } = domainManger;
|
||||
|
||||
const [questionData, setQuestionData] = useState<string[]>([]);
|
||||
const [currentRecordId, setCurrentRecordId] = useState<number>(0);
|
||||
|
||||
const queryThemeListData: any = async () => {
|
||||
const { code, data } = await getDomainExtendConfig({
|
||||
domainId: selectDomainId,
|
||||
modelId,
|
||||
});
|
||||
|
||||
if (code === 200) {
|
||||
@@ -51,7 +51,7 @@ const RecommendedQuestionsSection: React.FC<Props> = ({ domainManger }) => {
|
||||
return { question };
|
||||
}),
|
||||
id: currentRecordId,
|
||||
domainId: selectDomainId,
|
||||
modelId,
|
||||
});
|
||||
|
||||
if (code === 200) {
|
||||
@@ -65,8 +65,11 @@ const RecommendedQuestionsSection: React.FC<Props> = ({ domainManger }) => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!modelId) {
|
||||
return;
|
||||
}
|
||||
initPage();
|
||||
}, [selectDomainId]);
|
||||
}, [modelId]);
|
||||
|
||||
return (
|
||||
<div style={{ width: 800, margin: '0 auto' }}>
|
||||
|
||||
@@ -16,15 +16,15 @@ import { SENSITIVE_LEVEL_OPTIONS } from '../constant';
|
||||
import { formLayout } from '@/components/FormHelper/utils';
|
||||
import FormItemTitle from '@/components/FormHelper/FormItemTitle';
|
||||
import styles from './style.less';
|
||||
import { getMeasureListByDomainId } from '../service';
|
||||
import { getMeasureListByModelId } from '../service';
|
||||
import { creatExprMetric, updateExprMetric } from '../service';
|
||||
import { ISemantic } from '../data';
|
||||
import { history } from 'umi';
|
||||
import { check } from 'prettier';
|
||||
|
||||
export type CreateFormProps = {
|
||||
datasourceId?: number;
|
||||
domainId: number;
|
||||
modelId: number;
|
||||
createModalVisible: boolean;
|
||||
metricItem: any;
|
||||
onCancel?: () => void;
|
||||
@@ -39,6 +39,7 @@ const { Option } = Select;
|
||||
const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
datasourceId,
|
||||
domainId,
|
||||
modelId,
|
||||
onCancel,
|
||||
createModalVisible,
|
||||
metricItem,
|
||||
@@ -65,7 +66,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
const backward = () => setCurrentStep(currentStep - 1);
|
||||
|
||||
const queryClassMeasureList = async () => {
|
||||
const { code, data } = await getMeasureListByDomainId(domainId);
|
||||
const { code, data } = await getMeasureListByModelId(modelId);
|
||||
if (code === 200) {
|
||||
setClassMeasureList(data);
|
||||
if (datasourceId) {
|
||||
@@ -147,7 +148,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
|
||||
const saveMetric = async (fieldsValue: any) => {
|
||||
const queryParams = {
|
||||
domainId,
|
||||
modelId,
|
||||
...fieldsValue,
|
||||
};
|
||||
const { typeParams } = queryParams;
|
||||
@@ -351,7 +352,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
type="primary"
|
||||
key="console"
|
||||
onClick={() => {
|
||||
history.replace(`/semanticModel/${domainId}/dataSource`);
|
||||
history.replace(`/semanticModel/${domainId}/${modelId}/dataSource`);
|
||||
onCancel?.();
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Form, Button, Modal, Input, Switch } from 'antd';
|
||||
import styles from './style.less';
|
||||
import { message } from 'antd';
|
||||
import { formLayout } from '@/components/FormHelper/utils';
|
||||
import { createModel, updateModel } from '../service';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
export type ModelCreateFormModalProps = {
|
||||
domainId: number;
|
||||
basicInfo: any;
|
||||
onCancel: () => void;
|
||||
onSubmit: (values: any) => void;
|
||||
};
|
||||
|
||||
const ModelCreateFormModal: React.FC<ModelCreateFormModalProps> = (props) => {
|
||||
const { basicInfo, domainId, onCancel, onSubmit } = props;
|
||||
|
||||
const [formVals, setFormVals] = useState<any>(basicInfo);
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useEffect(() => {
|
||||
form.setFieldsValue(basicInfo);
|
||||
}, [basicInfo]);
|
||||
|
||||
const handleConfirm = async () => {
|
||||
const fieldsValue = await form.validateFields();
|
||||
const columnsValue = { ...fieldsValue, isUnique: 1, domainId };
|
||||
const submitData = { ...formVals, ...columnsValue };
|
||||
setFormVals(submitData);
|
||||
setSaveLoading(true);
|
||||
const { code, msg } = await (!submitData.id ? createModel : updateModel)(submitData);
|
||||
setSaveLoading(false);
|
||||
if (code === 200) {
|
||||
onSubmit?.(submitData);
|
||||
} else {
|
||||
message.error(msg);
|
||||
}
|
||||
};
|
||||
|
||||
const footer = (
|
||||
<>
|
||||
<Button onClick={onCancel}>取消</Button>
|
||||
<Button type="primary" loading={saveLoading} onClick={handleConfirm}>
|
||||
确定
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
width={640}
|
||||
bodyStyle={{ padding: '32px 40px 48px' }}
|
||||
destroyOnClose
|
||||
title={'模型信息'}
|
||||
open={true}
|
||||
footer={footer}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Form
|
||||
{...formLayout}
|
||||
form={form}
|
||||
initialValues={{
|
||||
...formVals,
|
||||
}}
|
||||
className={styles.form}
|
||||
>
|
||||
<FormItem
|
||||
name="name"
|
||||
label="模型名称"
|
||||
rules={[{ required: true, message: '请输入模型名称!' }]}
|
||||
>
|
||||
<Input placeholder="模型名称不可重复" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
name="bizName"
|
||||
label="模型英文名称"
|
||||
rules={[{ required: true, message: '请输入模型英文名称!' }]}
|
||||
>
|
||||
<Input placeholder="请输入模型英文名称" />
|
||||
</FormItem>
|
||||
<FormItem name="description" label="模型描述">
|
||||
<Input.TextArea placeholder="模型描述" />
|
||||
</FormItem>
|
||||
<FormItem name="isUnique" label="是否唯一" hidden={true}>
|
||||
<Switch size="small" checked={true} />
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModelCreateFormModal;
|
||||
@@ -1,23 +1,36 @@
|
||||
import { CheckCard } from '@ant-design/pro-components';
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { Button, Dropdown, message, Popconfirm } from 'antd';
|
||||
import { PlusOutlined, EllipsisOutlined } from '@ant-design/icons';
|
||||
import { ISemantic } from '../data';
|
||||
import { connect } from 'umi';
|
||||
import icon from '../../../assets/icon/cloudEditor.svg';
|
||||
import type { Dispatch } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
import { formatNumber } from '../../../utils/utils';
|
||||
import { deleteModel } from '../service';
|
||||
import ModelCreateFormModal from './ModelCreateFormModal';
|
||||
import styles from './style.less';
|
||||
|
||||
type Props = {
|
||||
modelList: ISemantic.IDomainItem[];
|
||||
disabledEdit?: boolean;
|
||||
modelList: ISemantic.IModelItem[];
|
||||
onModelChange?: (model?: ISemantic.IModelItem) => void;
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
};
|
||||
|
||||
const OverView: React.FC<Props> = ({ domainManger, dispatch, modelList }) => {
|
||||
const { selectDomainId } = domainManger;
|
||||
const OverView: React.FC<Props> = ({
|
||||
modelList,
|
||||
disabledEdit = false,
|
||||
onModelChange,
|
||||
domainManger,
|
||||
}) => {
|
||||
const { selectDomainId, selectModelId } = domainManger;
|
||||
const [currentModel, setCurrentModel] = useState<any>({});
|
||||
const [modelCreateFormModalVisible, setModelCreateFormModalVisible] = useState<boolean>(false);
|
||||
|
||||
const extraNode = (model: ISemantic.IDomainItem) => {
|
||||
const descNode = (model: ISemantic.IDomainItem) => {
|
||||
const { metricCnt, dimensionCnt } = model;
|
||||
return (
|
||||
<div className={styles.overviewExtraContainer}>
|
||||
@@ -40,33 +53,103 @@ const OverView: React.FC<Props> = ({ domainManger, dispatch, modelList }) => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const extraNode = (model: ISemantic.IDomainItem) => {
|
||||
return (
|
||||
<Dropdown
|
||||
placement="top"
|
||||
menu={{
|
||||
onClick: ({ key, domEvent }) => {
|
||||
domEvent.stopPropagation();
|
||||
if (key === 'edit') {
|
||||
setCurrentModel(model);
|
||||
setModelCreateFormModalVisible(true);
|
||||
}
|
||||
},
|
||||
items: [
|
||||
{
|
||||
label: '编辑',
|
||||
key: 'edit',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<Popconfirm
|
||||
title="确认删除?"
|
||||
okText="是"
|
||||
cancelText="否"
|
||||
onConfirm={async () => {
|
||||
const { code, msg } = await deleteModel(model.id);
|
||||
if (code === 200) {
|
||||
onModelChange?.();
|
||||
} else {
|
||||
message.error(msg);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<a key="modelDeleteBtn">删除</a>
|
||||
</Popconfirm>
|
||||
),
|
||||
key: 'delete',
|
||||
},
|
||||
],
|
||||
}}
|
||||
>
|
||||
<EllipsisOutlined
|
||||
style={{ fontSize: 22, color: 'rgba(0,0,0,0.5)' }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
/>
|
||||
</Dropdown>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<CheckCard.Group value={selectDomainId} defaultValue={selectDomainId}>
|
||||
<div style={{ padding: '0px 20px 20px' }}>
|
||||
{!disabledEdit && (
|
||||
<div style={{ paddingBottom: '20px' }}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setModelCreateFormModalVisible(true);
|
||||
}}
|
||||
type="primary"
|
||||
>
|
||||
<PlusOutlined />
|
||||
新增模型
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<CheckCard.Group value={selectModelId} defaultValue={selectModelId}>
|
||||
{modelList &&
|
||||
modelList.map((model: ISemantic.IDomainItem) => {
|
||||
return (
|
||||
<CheckCard
|
||||
avatar={icon}
|
||||
title={model.name}
|
||||
title={`${model.name}`}
|
||||
key={model.id}
|
||||
value={model.id}
|
||||
// description={model.description || '模型描述...'}
|
||||
description={extraNode(model)}
|
||||
description={descNode(model)}
|
||||
extra={!disabledEdit && extraNode(model)}
|
||||
onClick={() => {
|
||||
const { id, name } = model;
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectDomain',
|
||||
selectDomainId: id,
|
||||
selectDomainName: name,
|
||||
domainData: model,
|
||||
});
|
||||
onModelChange?.(model);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</CheckCard.Group>
|
||||
</>
|
||||
{modelCreateFormModalVisible && (
|
||||
<ModelCreateFormModal
|
||||
domainId={selectDomainId}
|
||||
basicInfo={currentModel}
|
||||
onSubmit={() => {
|
||||
setModelCreateFormModalVisible(false);
|
||||
onModelChange?.();
|
||||
}}
|
||||
onCancel={() => {
|
||||
setModelCreateFormModalVisible(false);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -6,10 +6,11 @@ import { connect } from 'umi';
|
||||
import type { Dispatch } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import FormItemTitle from '@/components/FormHelper/FormItemTitle';
|
||||
import { updateDomain, getDomainDetail } from '../../service';
|
||||
import { updateDomain, updateModel, getDomainDetail, getModelDetail } from '../../service';
|
||||
|
||||
import styles from '../style.less';
|
||||
type Props = {
|
||||
permissionTarget: 'model' | 'domain';
|
||||
dispatch: Dispatch;
|
||||
domainManger: StateType;
|
||||
onSubmit?: (data?: any) => void;
|
||||
@@ -18,15 +19,22 @@ type Props = {
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
const PermissionAdminForm: React.FC<Props> = ({ domainManger, onValuesChange }) => {
|
||||
const PermissionAdminForm: React.FC<Props> = ({
|
||||
permissionTarget,
|
||||
domainManger,
|
||||
onValuesChange,
|
||||
}) => {
|
||||
const [form] = Form.useForm();
|
||||
const [isOpenState, setIsOpenState] = useState<boolean>(true);
|
||||
const [classDetail, setClassDetail] = useState<any>({});
|
||||
const { selectDomainId } = domainManger;
|
||||
const { selectModelId: modelId, selectDomainId } = domainManger;
|
||||
const { APP_TARGET } = process.env;
|
||||
|
||||
const queryClassDetail = async (domainId: number) => {
|
||||
const { code, msg, data } = await getDomainDetail({ domainId });
|
||||
const queryClassDetail = async () => {
|
||||
const selectId = permissionTarget === 'model' ? modelId : selectDomainId;
|
||||
const { code, msg, data } = await (permissionTarget === 'model'
|
||||
? getModelDetail
|
||||
: getDomainDetail)({ modelId: selectId });
|
||||
if (code === 200) {
|
||||
setClassDetail(data);
|
||||
const fieldsValue = {
|
||||
@@ -44,8 +52,8 @@ const PermissionAdminForm: React.FC<Props> = ({ domainManger, onValuesChange })
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
queryClassDetail(selectDomainId);
|
||||
}, [selectDomainId]);
|
||||
queryClassDetail();
|
||||
}, [modelId]);
|
||||
|
||||
const saveAuth = async () => {
|
||||
const values = await form.validateFields();
|
||||
@@ -57,9 +65,10 @@ const PermissionAdminForm: React.FC<Props> = ({ domainManger, onValuesChange })
|
||||
viewers,
|
||||
isOpen: isOpen ? 1 : 0,
|
||||
};
|
||||
const { code, msg } = await updateDomain(queryClassData);
|
||||
const { code, msg } = await (permissionTarget === 'model' ? updateModel : updateDomain)(
|
||||
queryClassData,
|
||||
);
|
||||
if (code === 200) {
|
||||
// message.success('保存成功');
|
||||
return;
|
||||
}
|
||||
message.error(msg);
|
||||
@@ -123,16 +132,6 @@ const PermissionAdminForm: React.FC<Props> = ({ domainManger, onValuesChange })
|
||||
</FormItem>
|
||||
</>
|
||||
)}
|
||||
{/* <FormItem>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
saveAuth();
|
||||
}}
|
||||
>
|
||||
保 存
|
||||
</Button>
|
||||
</FormItem> */}
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -14,7 +14,6 @@ import styles from '../style.less';
|
||||
type Props = {
|
||||
domainManger: StateType;
|
||||
permissonData: any;
|
||||
domainId: number;
|
||||
onCancel: () => void;
|
||||
visible: boolean;
|
||||
onSubmit: (params?: any) => void;
|
||||
@@ -25,11 +24,10 @@ const PermissionCreateDrawer: React.FC<Props> = ({
|
||||
domainManger,
|
||||
visible,
|
||||
permissonData,
|
||||
domainId,
|
||||
onCancel,
|
||||
onSubmit,
|
||||
}) => {
|
||||
const { dimensionList, metricList } = domainManger;
|
||||
const { dimensionList, metricList, selectModelId: modelId } = domainManger;
|
||||
const [form] = Form.useForm();
|
||||
const basicInfoFormRef = useRef<any>(null);
|
||||
const [selectedDimensionKeyList, setSelectedDimensionKeyList] = useState<string[]>([]);
|
||||
@@ -65,7 +63,7 @@ const PermissionCreateDrawer: React.FC<Props> = ({
|
||||
metrics: selectedMetricKeyList,
|
||||
},
|
||||
],
|
||||
domainId,
|
||||
modelId,
|
||||
});
|
||||
|
||||
if (code === 200) {
|
||||
@@ -136,11 +134,7 @@ const PermissionCreateDrawer: React.FC<Props> = ({
|
||||
<div style={{ overflow: 'auto', margin: '0 auto', width: '1200px' }}>
|
||||
<Space direction="vertical" style={{ width: '100%' }} size={20}>
|
||||
<ProCard title="基本信息" bordered>
|
||||
<PermissionCreateForm
|
||||
ref={basicInfoFormRef}
|
||||
permissonData={permissonData}
|
||||
domainId={domainId}
|
||||
/>
|
||||
<PermissionCreateForm ref={basicInfoFormRef} permissonData={permissonData} />
|
||||
</ProCard>
|
||||
|
||||
<ProCard title="列权限" bordered tooltip="仅对敏感度为高的指标/维度进行授权">
|
||||
|
||||
@@ -6,7 +6,6 @@ import SelectTMEPerson from '@/components/SelectTMEPerson';
|
||||
import { formLayout } from '@/components/FormHelper/utils';
|
||||
import styles from '../style.less';
|
||||
type Props = {
|
||||
domainId: number;
|
||||
permissonData: any;
|
||||
onSubmit?: (data?: any) => void;
|
||||
onValuesChange?: (value, values) => void;
|
||||
|
||||
@@ -8,20 +8,20 @@ import PermissionTable from './PermissionTable';
|
||||
import PermissionAdminForm from './PermissionAdminForm';
|
||||
|
||||
type Props = {
|
||||
permissionTarget: 'model' | 'domain';
|
||||
dispatch: Dispatch;
|
||||
domainManger: StateType;
|
||||
};
|
||||
|
||||
const PermissionSection: React.FC<Props> = () => {
|
||||
const PermissionSection: React.FC<Props> = ({ permissionTarget }) => {
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<Space direction="vertical" style={{ width: '100%' }} size={20}>
|
||||
<ProCard title="邀请成员" bordered>
|
||||
<PermissionAdminForm />
|
||||
<PermissionAdminForm permissionTarget={permissionTarget} />
|
||||
</ProCard>
|
||||
|
||||
<PermissionTable />
|
||||
{permissionTarget === 'model' && <PermissionTable />}
|
||||
</Space>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -19,7 +19,7 @@ type Props = {
|
||||
const PermissionTable: React.FC<Props> = ({ domainManger }) => {
|
||||
const { APP_TARGET } = process.env;
|
||||
const isInner = APP_TARGET === 'inner';
|
||||
const { dimensionList, metricList, selectDomainId } = domainManger;
|
||||
const { dimensionList, metricList, selectModelId: modelId } = domainManger;
|
||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||
|
||||
const [permissonData, setPermissonData] = useState<any>({});
|
||||
@@ -37,7 +37,7 @@ const PermissionTable: React.FC<Props> = ({ domainManger }) => {
|
||||
const actionRef = useRef<ActionType>();
|
||||
|
||||
const queryListData = async () => {
|
||||
const { code, data } = await getGroupAuthInfo(selectDomainId);
|
||||
const { code, data } = await getGroupAuthInfo(modelId);
|
||||
if (code === 200) {
|
||||
setIntentionList(data);
|
||||
return;
|
||||
@@ -46,10 +46,10 @@ const PermissionTable: React.FC<Props> = ({ domainManger }) => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (selectDomainId) {
|
||||
if (modelId) {
|
||||
queryListData();
|
||||
}
|
||||
}, [selectDomainId]);
|
||||
}, [modelId]);
|
||||
|
||||
const queryDepartmentData = async () => {
|
||||
const { code, data } = await getOrganizationTree();
|
||||
@@ -184,7 +184,7 @@ const PermissionTable: React.FC<Props> = ({ domainManger }) => {
|
||||
return (
|
||||
<Space>
|
||||
<a
|
||||
key="classEditBtn"
|
||||
key="permissionEditBtn"
|
||||
onClick={() => {
|
||||
setPermissonData(record);
|
||||
setCreateModalVisible(true);
|
||||
@@ -216,7 +216,7 @@ const PermissionTable: React.FC<Props> = ({ domainManger }) => {
|
||||
cancelText="否"
|
||||
onConfirm={async () => {
|
||||
const { code, msg } = await removeGroupAuth({
|
||||
domainId: record.domainId,
|
||||
modelId: record.modelId,
|
||||
groupId: record.groupId,
|
||||
});
|
||||
if (code === 200) {
|
||||
@@ -228,7 +228,7 @@ const PermissionTable: React.FC<Props> = ({ domainManger }) => {
|
||||
}}
|
||||
>
|
||||
<a
|
||||
key="classEditBtn"
|
||||
key="permissionDeleteBtn"
|
||||
onClick={() => {
|
||||
setPermissonData(record);
|
||||
}}
|
||||
@@ -277,7 +277,6 @@ const PermissionTable: React.FC<Props> = ({ domainManger }) => {
|
||||
/>
|
||||
{createModalVisible && (
|
||||
<PermissionCreateDrawer
|
||||
domainId={Number(selectDomainId)}
|
||||
visible={createModalVisible}
|
||||
permissonData={permissonData}
|
||||
onSubmit={() => {
|
||||
|
||||
@@ -25,7 +25,6 @@ const ProjectInfoForm: React.FC<ProjectInfoFormProps> = (props) => {
|
||||
|
||||
const handleConfirm = async () => {
|
||||
const fieldsValue = await form.validateFields();
|
||||
// const columnsValue = { ...fieldsValue, isUnique: fieldsValue.isUnique === true ? 1 : 0 };
|
||||
const columnsValue = { ...fieldsValue, isUnique: 1 };
|
||||
setFormVals({ ...formVals, ...columnsValue });
|
||||
setSaveLoading(true);
|
||||
@@ -97,24 +96,11 @@ const ProjectInfoForm: React.FC<ProjectInfoFormProps> = (props) => {
|
||||
>
|
||||
<Input placeholder="请输入主题域英文名称" />
|
||||
</FormItem>
|
||||
<FormItem name="description" label="主题域描述">
|
||||
<FormItem name="description" label="主题域描述" hidden={true}>
|
||||
<Input.TextArea placeholder="主题域描述" />
|
||||
</FormItem>
|
||||
<FormItem name="isUnique" label="是否唯一" hidden={true}>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={true}
|
||||
// onChange={(checked) => {
|
||||
// setFormVals({ ...formVals, isUnique: checked });
|
||||
// }}
|
||||
/>
|
||||
{/* <Switch
|
||||
size="small"
|
||||
checked={formVals.isUnique ? true : false}
|
||||
onChange={(checked) => {
|
||||
setFormVals({ ...formVals, isUnique: checked });
|
||||
}}
|
||||
/> */}
|
||||
<Switch size="small" checked={true} />
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
@@ -94,6 +94,30 @@ export declare namespace ISemantic {
|
||||
metricCnt?: number;
|
||||
}
|
||||
|
||||
interface IModelItem {
|
||||
createdBy?: string;
|
||||
updatedBy?: string;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
id: number;
|
||||
name: string;
|
||||
bizName: string;
|
||||
description: any;
|
||||
status?: number;
|
||||
typeEnum?: any;
|
||||
sensitiveLevel?: number;
|
||||
parentId: number;
|
||||
fullPath?: string;
|
||||
viewers?: any[];
|
||||
viewOrgs?: any[];
|
||||
admins?: string[];
|
||||
adminOrgs?: any[];
|
||||
isOpen?: number;
|
||||
entity?: { entityId: number; names: string[] };
|
||||
dimensionCnt?: number;
|
||||
metricCnt?: number;
|
||||
}
|
||||
|
||||
interface IDimensionItem {
|
||||
createdBy: string;
|
||||
updatedBy: string;
|
||||
|
||||
@@ -6,14 +6,17 @@ import { getDimensionList, queryMetric, excuteSql, getDatabaseByDomainId } from
|
||||
export type StateType = {
|
||||
current: number;
|
||||
pageSize: number;
|
||||
selectModelId: number;
|
||||
selectDomainId: number;
|
||||
selectDomainName: string;
|
||||
selectModelName: string;
|
||||
dimensionList: ISemantic.IDimensionList;
|
||||
metricList: ISemantic.IMetricList;
|
||||
searchParams: Record<string, any>;
|
||||
dataBaseResultColsMap: any;
|
||||
dataBaseConfig: any;
|
||||
domainData?: ISemantic.IDomainItem;
|
||||
modelData?: ISemantic.IDomainItem;
|
||||
domainList: ISemantic.IDomainItem[];
|
||||
};
|
||||
|
||||
@@ -28,6 +31,7 @@ export type ModelType = {
|
||||
};
|
||||
reducers: {
|
||||
setSelectDomain: Reducer<StateType>;
|
||||
setSelectModel: Reducer<StateType>;
|
||||
setDomainList: Reducer<StateType>;
|
||||
setPagination: Reducer<StateType>;
|
||||
setDimensionList: Reducer<StateType>;
|
||||
@@ -42,7 +46,10 @@ export const defaultState: StateType = {
|
||||
current: 1,
|
||||
pageSize: 20,
|
||||
selectDomainId: 0,
|
||||
selectModelId: 0,
|
||||
modelData: undefined,
|
||||
selectDomainName: '',
|
||||
selectModelName: '',
|
||||
searchParams: {},
|
||||
dimensionList: [],
|
||||
metricList: [],
|
||||
@@ -123,6 +130,14 @@ const Model: ModelType = {
|
||||
domainData: action.domainData,
|
||||
};
|
||||
},
|
||||
setSelectModel(state = defaultState, action) {
|
||||
return {
|
||||
...state,
|
||||
selectModelId: action.selectModelId,
|
||||
selectModelName: action.selectModelName,
|
||||
modelData: action.modelData,
|
||||
};
|
||||
},
|
||||
setDomainList(state = defaultState, action) {
|
||||
return {
|
||||
...state,
|
||||
|
||||
@@ -12,11 +12,11 @@ export function getDomainList(): Promise<any> {
|
||||
}
|
||||
|
||||
export function getDatasourceList(data: any): Promise<any> {
|
||||
return request.get(`${process.env.API_BASE_URL}datasource/getDatasourceList/${data.domainId}`);
|
||||
return request.get(`${process.env.API_BASE_URL}datasource/getDatasourceList/${data.modelId}`);
|
||||
}
|
||||
|
||||
export function getDomainDetail(data: any): Promise<any> {
|
||||
return request.get(`${process.env.API_BASE_URL}domain/getDomain/${data.domainId}`);
|
||||
return request.get(`${process.env.API_BASE_URL}domain/getDomain/${data.modelId}`);
|
||||
}
|
||||
|
||||
export function createDomain(data: any): Promise<any> {
|
||||
@@ -44,9 +44,15 @@ export function updateDatasource(data: any): Promise<any> {
|
||||
}
|
||||
|
||||
export function getDimensionList(data: any): Promise<any> {
|
||||
const { domainId } = data;
|
||||
const { domainId, modelId } = data;
|
||||
const queryParams = {
|
||||
data: { current: 1, pageSize: 999999, ...data, ...(domainId ? { domainIds: [domainId] } : {}) },
|
||||
data: {
|
||||
current: 1,
|
||||
pageSize: 999999,
|
||||
...data,
|
||||
...(domainId ? { domainIds: [domainId] } : {}),
|
||||
...(modelId ? { modelIds: [modelId] } : {}),
|
||||
},
|
||||
};
|
||||
if (getRunningEnv() === 'chat') {
|
||||
return request.post(`${process.env.CHAT_API_BASE_URL}conf/dimension/page`, queryParams);
|
||||
@@ -67,9 +73,15 @@ export function updateDimension(data: any): Promise<any> {
|
||||
}
|
||||
|
||||
export function queryMetric(data: any): Promise<any> {
|
||||
const { domainId } = data;
|
||||
const { domainId, modelId } = data;
|
||||
const queryParams = {
|
||||
data: { current: 1, pageSize: 999999, ...data, ...(domainId ? { domainIds: [domainId] } : {}) },
|
||||
data: {
|
||||
current: 1,
|
||||
pageSize: 999999,
|
||||
...data,
|
||||
...(domainId ? { domainIds: [domainId] } : {}),
|
||||
...(modelId ? { modelIds: [modelId] } : {}),
|
||||
},
|
||||
};
|
||||
if (getRunningEnv() === 'chat') {
|
||||
return request.post(`${process.env.CHAT_API_BASE_URL}conf/metric/page`, queryParams);
|
||||
@@ -89,8 +101,8 @@ export function updateExprMetric(data: any): Promise<any> {
|
||||
});
|
||||
}
|
||||
|
||||
export function getMeasureListByDomainId(domainId: number): Promise<any> {
|
||||
return request.get(`${process.env.API_BASE_URL}datasource/getMeasureListOfDomain/${domainId}`);
|
||||
export function getMeasureListByModelId(modelId: number): Promise<any> {
|
||||
return request.get(`${process.env.API_BASE_URL}datasource/getMeasureListOfModel/${modelId}`);
|
||||
}
|
||||
|
||||
export function deleteDatasource(id: any): Promise<any> {
|
||||
@@ -117,12 +129,10 @@ export function deleteDomain(id: any): Promise<any> {
|
||||
});
|
||||
}
|
||||
|
||||
export function getGroupAuthInfo(id: number): Promise<any> {
|
||||
export function getGroupAuthInfo(modelId: number): Promise<any> {
|
||||
return request(`${process.env.AUTH_API_BASE_URL}queryGroup`, {
|
||||
method: 'GET',
|
||||
params: {
|
||||
domainId: id,
|
||||
},
|
||||
params: { modelId },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -169,7 +179,7 @@ export function getDomainExtendConfig(data: any): Promise<any> {
|
||||
}
|
||||
|
||||
export function getDomainExtendDetailConfig(data: any): Promise<any> {
|
||||
return request(`${process.env.CHAT_API_BASE_URL}conf/richDesc/${data.domainId}`, {
|
||||
return request(`${process.env.CHAT_API_BASE_URL}conf/richDesc/${data.modelId}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
@@ -246,7 +256,7 @@ export function testDatabaseConnect(data: SaveDatabaseParams): Promise<any> {
|
||||
|
||||
type ExcuteSqlParams = {
|
||||
sql: string;
|
||||
domainId: number;
|
||||
modelId: number;
|
||||
};
|
||||
|
||||
// 执行脚本
|
||||
@@ -272,3 +282,37 @@ export function getColumns(dbId: number, dbName: string, tableName: string): Pro
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
export function getModelList(domainId: number): Promise<any> {
|
||||
if (getRunningEnv() === 'chat') {
|
||||
return request(`${process.env.CHAT_API_BASE_URL}conf/modelList/${domainId}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
return request(`${process.env.API_BASE_URL}model/getModelList/${domainId}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
export function createModel(data: any): Promise<any> {
|
||||
return request(`${process.env.API_BASE_URL}model/createModel`, {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
export function updateModel(data: any): Promise<any> {
|
||||
return request(`${process.env.API_BASE_URL}model/updateModel`, {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteModel(modelId: number): Promise<any> {
|
||||
return request(`${process.env.API_BASE_URL}model/deleteModel/${modelId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
export function getModelDetail(data: any): Promise<any> {
|
||||
return request.get(`${process.env.API_BASE_URL}model/getModel/${data.modelId}`);
|
||||
}
|
||||
|
||||
@@ -175,12 +175,12 @@ declare namespace API {
|
||||
comment: string; // 项目描述
|
||||
creator: string; // 项目创建人
|
||||
projectType: number; // 项目类别 0-为私有项目 1-为公共项目
|
||||
childProjectList?: ProjectList;
|
||||
children?: ProjectList;
|
||||
childDomainList?: DomainList;
|
||||
children?: DomainList;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type ProjectList = ProjectItem[];
|
||||
export type DomainList = ProjectItem[];
|
||||
|
||||
// 数据实例详情
|
||||
export type DataInstanceDetail = {
|
||||
|
||||
Reference in New Issue
Block a user