mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-13 13:07:32 +00:00
[improvement][headless-fe] Revised the interaction for semantic modeling routing and implemented the initial version of metric management switching.
This commit is contained in:
@@ -62,27 +62,85 @@ const ROUTES = [
|
|||||||
envEnableList: [ENV_KEY.SEMANTIC],
|
envEnableList: [ENV_KEY.SEMANTIC],
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: '/model/:domainId',
|
path: '/model/',
|
||||||
component: './SemanticModel/DomainManager',
|
redirect: '/model/domain',
|
||||||
envEnableList: [ENV_KEY.SEMANTIC],
|
},
|
||||||
|
{
|
||||||
|
path: '/model/domain/',
|
||||||
|
component: './SemanticModel/OverviewContainer',
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: '/model/:domainId/:menuKey',
|
path: '/model/domain/:domainId',
|
||||||
|
component: './SemanticModel/DomainManager',
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: '/model/domain/:domainId/:menuKey',
|
||||||
component: './SemanticModel/DomainManager',
|
component: './SemanticModel/DomainManager',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/model/manager/:domainId/:modelId',
|
path: '/model/domain/manager/:domainId/:modelId',
|
||||||
component: './SemanticModel/ModelManager',
|
component: './SemanticModel/ModelManager',
|
||||||
envEnableList: [ENV_KEY.SEMANTIC],
|
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: '/model/manager/:domainId/:modelId/:menuKey',
|
path: '/model/domain/manager/:domainId/:modelId/:menuKey',
|
||||||
component: './SemanticModel/ModelManager',
|
component: './SemanticModel/ModelManager',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/model/metric/:domainId/:modelId/:metricId',
|
||||||
|
component: './SemanticModel/Metric/Edit',
|
||||||
|
envEnableList: [ENV_KEY.SEMANTIC],
|
||||||
|
// routes: [
|
||||||
|
// {
|
||||||
|
// path: '/model/manager/:domainId/:modelId/:menuKey',
|
||||||
|
// component: './SemanticModel/ModelManager',
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// path: '/model/manager/',
|
||||||
|
// component: './SemanticModel/OverviewContainer',
|
||||||
|
// routes: [
|
||||||
|
// {
|
||||||
|
// path: '/model/manager/:domainId/:modelId',
|
||||||
|
// component: './SemanticModel/ModelManager',
|
||||||
|
// routes: [
|
||||||
|
// {
|
||||||
|
// path: '/model/manager/:domainId/:modelId/:menuKey',
|
||||||
|
// component: './SemanticModel/ModelManager',
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/model/:domainId',
|
||||||
|
// component: './SemanticModel/DomainManager',
|
||||||
|
// envEnableList: [ENV_KEY.SEMANTIC],
|
||||||
|
// routes: [
|
||||||
|
// {
|
||||||
|
// path: '/model/:domainId/:menuKey',
|
||||||
|
// component: './SemanticModel/DomainManager',
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/model/manager/:domainId/:modelId',
|
||||||
|
// component: './SemanticModel/ModelManager',
|
||||||
|
// envEnableList: [ENV_KEY.SEMANTIC],
|
||||||
|
// routes: [
|
||||||
|
// {
|
||||||
|
// path: '/model/manager/:domainId/:modelId/:menuKey',
|
||||||
|
// component: './SemanticModel/ModelManager',
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
|
||||||
// {
|
// {
|
||||||
// path: '/model/:domainId/:modelId/:menuKey',
|
// path: '/model/:domainId/:modelId/:menuKey',
|
||||||
// component: './SemanticModel/DomainManager',
|
// component: './SemanticModel/DomainManager',
|
||||||
|
|||||||
@@ -1,103 +1,26 @@
|
|||||||
import { message } from 'antd';
|
import React, { useState } from 'react';
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { history, useParams, useModel } from '@umijs/max';
|
import { history, useParams, useModel } from '@umijs/max';
|
||||||
import { ISemantic } from './data';
|
|
||||||
import { getDomainList, getDataSetList } from './service';
|
|
||||||
import DomainManagerTab from './components/DomainManagerTab';
|
import DomainManagerTab from './components/DomainManagerTab';
|
||||||
import { isArrayOfValues } from '@/utils/utils';
|
|
||||||
|
|
||||||
type Props = {};
|
type Props = {};
|
||||||
|
|
||||||
const DomainManager: React.FC<Props> = ({}) => {
|
const DomainManager: React.FC<Props> = ({}) => {
|
||||||
const defaultTabKey = 'overview';
|
const defaultTabKey = 'overview';
|
||||||
const params: any = useParams();
|
const params: any = useParams();
|
||||||
const domainId = params.domainId;
|
|
||||||
const domainModel = useModel('SemanticModel.domainData');
|
const domainModel = useModel('SemanticModel.domainData');
|
||||||
const modelModel = useModel('SemanticModel.modelData');
|
|
||||||
const databaseModel = useModel('SemanticModel.databaseData');
|
const { selectDomainId } = domainModel;
|
||||||
const { selectDomainId, domainList, setSelectDomain, setDomainList } = domainModel;
|
|
||||||
const { selectModelId } = modelModel;
|
|
||||||
const { MrefreshDatabaseList } = databaseModel;
|
|
||||||
const menuKey = params.menuKey ? params.menuKey : defaultTabKey;
|
const menuKey = params.menuKey ? params.menuKey : defaultTabKey;
|
||||||
const [collapsedState, setCollapsedState] = useState(true);
|
|
||||||
const [activeKey, setActiveKey] = useState<string>(menuKey);
|
const [activeKey, setActiveKey] = useState<string>(menuKey);
|
||||||
const [dataSetList, setDataSetList] = useState<ISemantic.IDatasetItem[]>([]);
|
|
||||||
|
|
||||||
// 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 } = firstRootNode;
|
|
||||||
// setSelectDomain(firstRootNode);
|
|
||||||
// setActiveKey(menuKey);
|
|
||||||
// pushUrlMenu(id, 0, menuKey);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// setSelectDomain(targetNode);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const initProjectTree = async () => {
|
|
||||||
// const { code, data, msg } = await getDomainList();
|
|
||||||
// if (code === 200) {
|
|
||||||
// initSelectedDomain(data);
|
|
||||||
// setDomainList(data);
|
|
||||||
// } else {
|
|
||||||
// message.error(msg);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// initProjectTree();
|
|
||||||
// MrefreshDatabaseList();
|
|
||||||
// }, []);
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (!selectDomainId) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// // queryModelList();
|
|
||||||
// queryDataSetList();
|
|
||||||
// }, [selectDomainId]);
|
|
||||||
|
|
||||||
// const queryDataSetList = async () => {
|
|
||||||
// const { code, data, msg } = await getDataSetList(selectDomainId);
|
|
||||||
// if (code === 200) {
|
|
||||||
// setDataSetList(data);
|
|
||||||
// if (!isArrayOfValues(data)) {
|
|
||||||
// setActiveKey(defaultTabKey);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// message.error(msg);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
const pushUrlMenu = (domainId: number, menuKey: string) => {
|
const pushUrlMenu = (domainId: number, menuKey: string) => {
|
||||||
history.push(`/model/${domainId}/${menuKey}`);
|
history.push(`/model/domain/${domainId}/${menuKey}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const cleanModelInfo = (domainId) => {
|
|
||||||
setActiveKey(defaultTabKey);
|
|
||||||
pushUrlMenu(domainId, defaultTabKey);
|
|
||||||
// setSelectModel(undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
// const handleCollapsedBtn = () => {
|
|
||||||
// setCollapsedState(!collapsedState);
|
|
||||||
// };
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DomainManagerTab
|
<DomainManagerTab
|
||||||
activeKey={activeKey}
|
activeKey={activeKey}
|
||||||
dataSetList={dataSetList}
|
|
||||||
onBackDomainBtnClick={() => {
|
|
||||||
cleanModelInfo(selectDomainId);
|
|
||||||
}}
|
|
||||||
onMenuChange={(menuKey) => {
|
onMenuChange={(menuKey) => {
|
||||||
setActiveKey(menuKey);
|
setActiveKey(menuKey);
|
||||||
pushUrlMenu(selectDomainId, menuKey);
|
pushUrlMenu(selectDomainId, menuKey);
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ const ClassMetricTable: React.FC<Props> = ({}) => {
|
|||||||
|
|
||||||
const columnsConfig = ColumnsConfig({
|
const columnsConfig = ColumnsConfig({
|
||||||
indicatorInfo: {
|
indicatorInfo: {
|
||||||
url: '/tag/detail/',
|
url: '/tag/detail/:indicatorId',
|
||||||
starType: 'tag',
|
starType: 'tag',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { getMetricData } from '../service';
|
import { getMetricData } from '../service';
|
||||||
import { useParams } from '@umijs/max';
|
import { useParams, useModel } from '@umijs/max';
|
||||||
import styles from './style.less';
|
import styles from './style.less';
|
||||||
import { ISemantic } from '../data';
|
import { ISemantic } from '../data';
|
||||||
import MetricInfoEditSider from './MetricInfoEditSider';
|
import MetricInfoEditSider from './MetricInfoEditSider';
|
||||||
@@ -14,7 +14,8 @@ const MetricDetail: React.FC<Props> = () => {
|
|||||||
const params: any = useParams();
|
const params: any = useParams();
|
||||||
const metricId = params.metricId;
|
const metricId = params.metricId;
|
||||||
const [metircData, setMetircData] = useState<ISemantic.IMetricItem>();
|
const [metircData, setMetircData] = useState<ISemantic.IMetricItem>();
|
||||||
|
const metricModel = useModel('SemanticModel.metricData');
|
||||||
|
const { selectMetric, setSelectMetric } = metricModel;
|
||||||
const [settingKey, setSettingKey] = useState<MetricSettingKey>(MetricSettingKey.BASIC);
|
const [settingKey, setSettingKey] = useState<MetricSettingKey>(MetricSettingKey.BASIC);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -24,10 +25,17 @@ const MetricDetail: React.FC<Props> = () => {
|
|||||||
queryMetricData(metricId);
|
queryMetricData(metricId);
|
||||||
}, [metricId]);
|
}, [metricId]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
setSelectMetric(undefined);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const queryMetricData = async (metricId: string) => {
|
const queryMetricData = async (metricId: string) => {
|
||||||
const { code, data, msg } = await getMetricData(metricId);
|
const { code, data, msg } = await getMetricData(metricId);
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
setMetircData({ ...data });
|
setMetircData({ ...data });
|
||||||
|
setSelectMetric({ ...data });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
message.error(msg);
|
message.error(msg);
|
||||||
|
|||||||
@@ -905,7 +905,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
|||||||
key="console"
|
key="console"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
history.replace(
|
history.replace(
|
||||||
`/model/manager/${domainId}/${modelId || metricItem?.modelId}/dataSource`,
|
`/model/domain/manager/${domainId}/${modelId || metricItem?.modelId}/dataSource`,
|
||||||
);
|
);
|
||||||
onCancel?.();
|
onCancel?.();
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -4,27 +4,18 @@ import ModelManagerTab from './components/ModelManagerTab';
|
|||||||
|
|
||||||
type Props = {};
|
type Props = {};
|
||||||
|
|
||||||
const OverviewContainer: React.FC<Props> = ({}) => {
|
const ModelManager: React.FC<Props> = ({}) => {
|
||||||
const defaultTabKey = 'overview';
|
const defaultTabKey = 'overview';
|
||||||
const params: any = useParams();
|
const params: any = useParams();
|
||||||
const domainId = params.domainId;
|
|
||||||
const modelId = params.modelId;
|
const modelId = params.modelId;
|
||||||
const domainModel = useModel('SemanticModel.domainData');
|
const domainModel = useModel('SemanticModel.domainData');
|
||||||
const modelModel = useModel('SemanticModel.modelData');
|
const modelModel = useModel('SemanticModel.modelData');
|
||||||
const dimensionModel = useModel('SemanticModel.dimensionData');
|
const dimensionModel = useModel('SemanticModel.dimensionData');
|
||||||
const metricModel = useModel('SemanticModel.metricData');
|
const metricModel = useModel('SemanticModel.metricData');
|
||||||
const databaseModel = useModel('SemanticModel.databaseData');
|
const { selectDomainId } = domainModel;
|
||||||
const { selectDomainId, domainList, setSelectDomain, setDomainList } = domainModel;
|
const { selectModelId, modelList } = modelModel;
|
||||||
const {
|
|
||||||
selectModelId,
|
|
||||||
modelList,
|
|
||||||
MrefreshModelList,
|
|
||||||
setSelectModel,
|
|
||||||
setModelTableHistoryParams,
|
|
||||||
} = modelModel;
|
|
||||||
const { MrefreshDimensionList } = dimensionModel;
|
const { MrefreshDimensionList } = dimensionModel;
|
||||||
const { MrefreshMetricList } = metricModel;
|
const { MrefreshMetricList } = metricModel;
|
||||||
const { MrefreshDatabaseList } = databaseModel;
|
|
||||||
const menuKey = params.menuKey ? params.menuKey : !Number(modelId) ? defaultTabKey : '';
|
const menuKey = params.menuKey ? params.menuKey : !Number(modelId) ? defaultTabKey : '';
|
||||||
const [activeKey, setActiveKey] = useState<string>(menuKey);
|
const [activeKey, setActiveKey] = useState<string>(menuKey);
|
||||||
|
|
||||||
@@ -35,7 +26,7 @@ const OverviewContainer: React.FC<Props> = ({}) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!selectModelId) {
|
if (!selectModelId || `${selectModelId}` === `${modelId}`) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
initModelConfig();
|
initModelConfig();
|
||||||
@@ -44,22 +35,13 @@ const OverviewContainer: React.FC<Props> = ({}) => {
|
|||||||
}, [selectModelId]);
|
}, [selectModelId]);
|
||||||
|
|
||||||
const pushUrlMenu = (domainId: number, modelId: number, menuKey: string) => {
|
const pushUrlMenu = (domainId: number, modelId: number, menuKey: string) => {
|
||||||
history.push(`/model/manager/${domainId}/${modelId}/${menuKey}`);
|
history.push(`/model/domain/manager/${domainId}/${modelId}/${menuKey}`);
|
||||||
};
|
|
||||||
|
|
||||||
const cleanModelInfo = (domainId) => {
|
|
||||||
setActiveKey(defaultTabKey);
|
|
||||||
pushUrlMenu(domainId, 0, defaultTabKey);
|
|
||||||
setSelectModel(undefined);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModelManagerTab
|
<ModelManagerTab
|
||||||
activeKey={activeKey}
|
activeKey={activeKey}
|
||||||
modelList={modelList}
|
modelList={modelList}
|
||||||
onBackDomainBtnClick={() => {
|
|
||||||
cleanModelInfo(selectDomainId);
|
|
||||||
}}
|
|
||||||
onMenuChange={(menuKey) => {
|
onMenuChange={(menuKey) => {
|
||||||
setActiveKey(menuKey);
|
setActiveKey(menuKey);
|
||||||
pushUrlMenu(selectDomainId, selectModelId, menuKey);
|
pushUrlMenu(selectDomainId, selectModelId, menuKey);
|
||||||
@@ -68,4 +50,4 @@ const OverviewContainer: React.FC<Props> = ({}) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default OverviewContainer;
|
export default ModelManager;
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { history, useParams, useModel, Outlet } from '@umijs/max';
|
||||||
|
import DomainListTree from './components/DomainList';
|
||||||
|
import styles from './components/style.less';
|
||||||
|
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||||||
|
import { ISemantic } from './data';
|
||||||
|
|
||||||
|
type Props = {};
|
||||||
|
|
||||||
|
const OverviewContainer: React.FC<Props> = ({}) => {
|
||||||
|
const defaultTabKey = 'overview';
|
||||||
|
const params: any = useParams();
|
||||||
|
const domainId = params.domainId;
|
||||||
|
const modelId = params.modelId;
|
||||||
|
const domainModel = useModel('SemanticModel.domainData');
|
||||||
|
const modelModel = useModel('SemanticModel.modelData');
|
||||||
|
const databaseModel = useModel('SemanticModel.databaseData');
|
||||||
|
const { setSelectDomain, setDomainList, selectDomainId } = domainModel;
|
||||||
|
const { setSelectModel, setModelTableHistoryParams, MrefreshModelList } = modelModel;
|
||||||
|
const { MrefreshDatabaseList } = databaseModel;
|
||||||
|
const menuKey = params.menuKey ? params.menuKey : !Number(modelId) ? defaultTabKey : '';
|
||||||
|
const [collapsedState, setCollapsedState] = useState(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!selectDomainId || `${domainId}` === `${selectDomainId}`) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pushUrlMenu(selectDomainId, menuKey);
|
||||||
|
}, [selectDomainId]);
|
||||||
|
|
||||||
|
// 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 } = firstRootNode;
|
||||||
|
// setSelectDomain(firstRootNode);
|
||||||
|
// pushUrlMenu(id, menuKey);
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// setSelectDomain(targetNode);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const initProjectTree = async () => {
|
||||||
|
// const { code, data, msg } = await getDomainList();
|
||||||
|
// if (code === 200) {
|
||||||
|
// initSelectedDomain(data);
|
||||||
|
// setDomainList(data);
|
||||||
|
// } else {
|
||||||
|
// message.error(msg);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// initProjectTree();
|
||||||
|
// MrefreshDatabaseList();
|
||||||
|
// return () => {
|
||||||
|
// setSelectDomain(undefined);
|
||||||
|
// };
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
const pushUrlMenu = (domainId: number, menuKey: string) => {
|
||||||
|
history.push(`/model/domain/${domainId}/${menuKey}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const cleanModelInfo = (domainId) => {
|
||||||
|
pushUrlMenu(domainId, defaultTabKey);
|
||||||
|
setSelectModel(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCollapsedBtn = () => {
|
||||||
|
setCollapsedState(!collapsedState);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!selectDomainId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
queryModelList();
|
||||||
|
}, [selectDomainId]);
|
||||||
|
|
||||||
|
const queryModelList = async () => {
|
||||||
|
await MrefreshModelList(selectDomainId);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.projectBody}>
|
||||||
|
<div className={styles.projectManger}>
|
||||||
|
<div className={`${styles.sider} ${!collapsedState ? styles.siderCollapsed : ''}`}>
|
||||||
|
<div className={styles.treeContainer}>
|
||||||
|
<DomainListTree
|
||||||
|
onTreeSelected={(domainData: ISemantic.IDomainItem) => {
|
||||||
|
const { id } = domainData;
|
||||||
|
cleanModelInfo(id);
|
||||||
|
setSelectDomain(domainData);
|
||||||
|
setModelTableHistoryParams({
|
||||||
|
[id]: {},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
// onTreeDataUpdate={() => {
|
||||||
|
// // initProjectTree();
|
||||||
|
// }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={styles.siderCollapsedButton}
|
||||||
|
onClick={() => {
|
||||||
|
handleCollapsedBtn();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{collapsedState ? <LeftOutlined /> : <RightOutlined />}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<Outlet />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OverviewContainer;
|
||||||
@@ -1,215 +0,0 @@
|
|||||||
import { message } from 'antd';
|
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { history, useParams, useModel } from '@umijs/max';
|
|
||||||
import DomainListTree from './components/DomainList';
|
|
||||||
import styles from './components/style.less';
|
|
||||||
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
|
|
||||||
import { ISemantic } from './data';
|
|
||||||
import { getDomainList, getDataSetList } from './service';
|
|
||||||
import DomainManagerTab from './components/DomainManagerTab';
|
|
||||||
import { isArrayOfValues } from '@/utils/utils';
|
|
||||||
import OverviewContainerRight from './components/OverviewContainerRight';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
mode: 'domain';
|
|
||||||
};
|
|
||||||
|
|
||||||
const OverviewContainer: React.FC<Props> = ({ mode = 'domain' }) => {
|
|
||||||
const defaultTabKey = 'overview';
|
|
||||||
const params: any = useParams();
|
|
||||||
const domainId = params.domainId;
|
|
||||||
const modelId = params.modelId;
|
|
||||||
const domainModel = useModel('SemanticModel.domainData');
|
|
||||||
const modelModel = useModel('SemanticModel.modelData');
|
|
||||||
const dimensionModel = useModel('SemanticModel.dimensionData');
|
|
||||||
const metricModel = useModel('SemanticModel.metricData');
|
|
||||||
const databaseModel = useModel('SemanticModel.databaseData');
|
|
||||||
const { selectDomainId, domainList, setSelectDomain, setDomainList } = domainModel;
|
|
||||||
const {
|
|
||||||
selectModelId,
|
|
||||||
modelList,
|
|
||||||
MrefreshModelList,
|
|
||||||
setSelectModel,
|
|
||||||
setModelTableHistoryParams,
|
|
||||||
} = modelModel;
|
|
||||||
const { MrefreshDimensionList } = dimensionModel;
|
|
||||||
const { MrefreshMetricList } = metricModel;
|
|
||||||
const { MrefreshDatabaseList } = databaseModel;
|
|
||||||
const menuKey = params.menuKey ? params.menuKey : !Number(modelId) ? defaultTabKey : '';
|
|
||||||
const [isModel, setIsModel] = useState<boolean>(false);
|
|
||||||
const [collapsedState, setCollapsedState] = useState(true);
|
|
||||||
const [activeKey, setActiveKey] = useState<string>(menuKey);
|
|
||||||
const [dataSetList, setDataSetList] = useState<ISemantic.IDatasetItem[]>([]);
|
|
||||||
|
|
||||||
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 } = firstRootNode;
|
|
||||||
setSelectDomain(firstRootNode);
|
|
||||||
setActiveKey(menuKey);
|
|
||||||
pushUrlMenu(id, 0, menuKey);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setSelectDomain(targetNode);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const initProjectTree = async () => {
|
|
||||||
const { code, data, msg } = await getDomainList();
|
|
||||||
if (code === 200) {
|
|
||||||
initSelectedDomain(data);
|
|
||||||
setDomainList(data);
|
|
||||||
} else {
|
|
||||||
message.error(msg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
initProjectTree();
|
|
||||||
MrefreshDatabaseList();
|
|
||||||
return () => {
|
|
||||||
setSelectDomain(undefined);
|
|
||||||
setSelectModel(undefined);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!selectDomainId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
queryModelList();
|
|
||||||
queryDataSetList();
|
|
||||||
}, [selectDomainId]);
|
|
||||||
|
|
||||||
const queryDataSetList = async () => {
|
|
||||||
const { code, data, msg } = await getDataSetList(selectDomainId);
|
|
||||||
if (code === 200) {
|
|
||||||
setDataSetList(data);
|
|
||||||
if (!isArrayOfValues(data)) {
|
|
||||||
setActiveKey(defaultTabKey);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
message.error(msg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const queryModelList = async () => {
|
|
||||||
await MrefreshModelList(selectDomainId);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!selectDomainId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setIsModel(false);
|
|
||||||
}, [domainList, selectDomainId]);
|
|
||||||
|
|
||||||
const initModelConfig = () => {
|
|
||||||
setIsModel(true);
|
|
||||||
const currentMenuKey = menuKey === defaultTabKey ? '' : menuKey;
|
|
||||||
pushUrlMenu(selectDomainId, selectModelId, currentMenuKey);
|
|
||||||
setActiveKey(currentMenuKey);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!selectModelId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
initModelConfig();
|
|
||||||
MrefreshDimensionList({ modelId: selectModelId });
|
|
||||||
MrefreshMetricList({ modelId: selectModelId });
|
|
||||||
}, [selectModelId]);
|
|
||||||
|
|
||||||
const pushUrlMenu = (domainId: number, modelId: number, menuKey: string) => {
|
|
||||||
history.push(`/model/${domainId}/${modelId || 0}/${menuKey}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleModelChange = (model?: ISemantic.IModelItem) => {
|
|
||||||
if (!model) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (`${model.id}` === `${selectModelId}`) {
|
|
||||||
initModelConfig();
|
|
||||||
}
|
|
||||||
setSelectModel(model);
|
|
||||||
};
|
|
||||||
|
|
||||||
const cleanModelInfo = (domainId) => {
|
|
||||||
setIsModel(false);
|
|
||||||
setActiveKey(defaultTabKey);
|
|
||||||
pushUrlMenu(domainId, 0, defaultTabKey);
|
|
||||||
setSelectModel(undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCollapsedBtn = () => {
|
|
||||||
setCollapsedState(!collapsedState);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.projectBody}>
|
|
||||||
<div className={styles.projectManger}>
|
|
||||||
<div className={`${styles.sider} ${!collapsedState ? styles.siderCollapsed : ''}`}>
|
|
||||||
<div className={styles.treeContainer}>
|
|
||||||
<DomainListTree
|
|
||||||
createDomainBtnVisible={mode === 'domain' ? true : false}
|
|
||||||
onTreeSelected={(domainData: ISemantic.IDomainItem) => {
|
|
||||||
const { id } = domainData;
|
|
||||||
cleanModelInfo(id);
|
|
||||||
setSelectDomain(domainData);
|
|
||||||
setModelTableHistoryParams({
|
|
||||||
[id]: {},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
onTreeDataUpdate={() => {
|
|
||||||
initProjectTree();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className={styles.siderCollapsedButton}
|
|
||||||
onClick={() => {
|
|
||||||
handleCollapsedBtn();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{collapsedState ? <LeftOutlined /> : <RightOutlined />}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={styles.content}>
|
|
||||||
{selectDomainId ? (
|
|
||||||
<>
|
|
||||||
<OverviewContainerRight />
|
|
||||||
<DomainManagerTab
|
|
||||||
isModel={isModel}
|
|
||||||
activeKey={activeKey}
|
|
||||||
modelList={modelList}
|
|
||||||
dataSetList={dataSetList}
|
|
||||||
handleModelChange={(model) => {
|
|
||||||
handleModelChange(model);
|
|
||||||
MrefreshModelList(selectDomainId);
|
|
||||||
}}
|
|
||||||
onBackDomainBtnClick={() => {
|
|
||||||
cleanModelInfo(selectDomainId);
|
|
||||||
}}
|
|
||||||
onMenuChange={(menuKey) => {
|
|
||||||
setActiveKey(menuKey);
|
|
||||||
pushUrlMenu(selectDomainId, selectModelId, menuKey);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<h2 className={styles.mainTip}>请选择项目</h2>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default OverviewContainer;
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
import { Outlet } from '@umijs/max';
|
|
||||||
import { Tabs, Breadcrumb, Space, Radio } from 'antd';
|
|
||||||
import React, { useRef, useEffect, useState } from 'react';
|
|
||||||
import { history, useModel } from '@umijs/max';
|
|
||||||
import { HomeOutlined, FundViewOutlined } from '@ant-design/icons';
|
|
||||||
import styles from './components/style.less';
|
|
||||||
|
|
||||||
const OverviewContainerRight: React.FC = () => {
|
|
||||||
const domainModel = useModel('SemanticModel.domainData');
|
|
||||||
const modelModel = useModel('SemanticModel.modelData');
|
|
||||||
|
|
||||||
const { selectDomainId, selectDomainName, selectDomain: domainData } = domainModel;
|
|
||||||
const { selectModelId, selectModelName, setSelectModel } = modelModel;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Breadcrumb
|
|
||||||
className={styles.breadcrumb}
|
|
||||||
separator=""
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
title: (
|
|
||||||
<Space
|
|
||||||
onClick={() => {
|
|
||||||
// onBackDomainBtnClick?.();
|
|
||||||
setSelectModel(undefined);
|
|
||||||
history.push(`/model/${selectDomainId}/overview`);
|
|
||||||
}}
|
|
||||||
style={
|
|
||||||
selectModelName ? { cursor: 'pointer' } : { color: '#296df3', fontWeight: 'bold' }
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<HomeOutlined />
|
|
||||||
<span>{selectDomainName}</span>
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'separator',
|
|
||||||
separator: selectModelName ? '/' : '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: selectModelName ? (
|
|
||||||
<Space
|
|
||||||
onClick={() => {
|
|
||||||
history.push(`/model/manager/${selectDomainId}/${selectModelId}/`);
|
|
||||||
}}
|
|
||||||
style={{ color: '#296df3' }}
|
|
||||||
>
|
|
||||||
<FundViewOutlined style={{ position: 'relative', top: '2px' }} />
|
|
||||||
<span>{selectModelName}</span>
|
|
||||||
</Space>
|
|
||||||
) : undefined,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
<Outlet />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default OverviewContainerRight;
|
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import { Outlet } from '@umijs/max';
|
||||||
|
import { Tabs, Breadcrumb, Space, Radio } from 'antd';
|
||||||
|
import React, { useRef, useEffect, useState } from 'react';
|
||||||
|
import { history, useModel } from '@umijs/max';
|
||||||
|
import { HomeOutlined, FundViewOutlined } from '@ant-design/icons';
|
||||||
|
import styles from './components/style.less';
|
||||||
|
|
||||||
|
const PageBreadcrumb: React.FC = () => {
|
||||||
|
const domainModel = useModel('SemanticModel.domainData');
|
||||||
|
const modelModel = useModel('SemanticModel.modelData');
|
||||||
|
const metricModel = useModel('SemanticModel.metricData');
|
||||||
|
const { selectDomainId, selectDomainName, selectDomain: domainData } = domainModel;
|
||||||
|
const { selectModelId, selectModelName, setSelectModel } = modelModel;
|
||||||
|
|
||||||
|
const { selectMetric, setSelectMetric } = metricModel;
|
||||||
|
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
title: (
|
||||||
|
<Space
|
||||||
|
onClick={() => {
|
||||||
|
setSelectModel(undefined);
|
||||||
|
history.push(`/model/domain/${selectDomainId}/overview`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<HomeOutlined />
|
||||||
|
<span>{selectDomainName}</span>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (selectModelName) {
|
||||||
|
items.push(
|
||||||
|
{
|
||||||
|
type: 'separator',
|
||||||
|
separator: '/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: (
|
||||||
|
<Space
|
||||||
|
onClick={() => {
|
||||||
|
setSelectMetric(undefined);
|
||||||
|
history.push(`/model/domain/manager/${selectDomainId}/${selectModelId}/`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FundViewOutlined style={{ position: 'relative', top: '2px' }} />
|
||||||
|
<span>{selectModelName}</span>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectMetric?.name) {
|
||||||
|
items.push(
|
||||||
|
{
|
||||||
|
type: 'separator',
|
||||||
|
separator: '/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: selectMetric?.name ? (
|
||||||
|
<Space>
|
||||||
|
<FundViewOutlined style={{ position: 'relative', top: '2px' }} />
|
||||||
|
<span>{selectMetric.name}</span>
|
||||||
|
</Space>
|
||||||
|
) : undefined,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Breadcrumb className={styles.breadcrumb} separator="" items={items} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PageBreadcrumb;
|
||||||
@@ -45,11 +45,10 @@ const DataSetTable: React.FC<Props> = ({ disabledEdit = false }) => {
|
|||||||
|
|
||||||
const [viewList, setViewList] = useState<ISemantic.IDatasetItem[]>();
|
const [viewList, setViewList] = useState<ISemantic.IDatasetItem[]>();
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// setViewList(dataSetList);
|
|
||||||
// }, [dataSetList]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!selectDomainId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
queryDataSetList();
|
queryDataSetList();
|
||||||
queryDomainAllModel();
|
queryDomainAllModel();
|
||||||
}, [selectDomainId]);
|
}, [selectDomainId]);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ProTable } from '@ant-design/pro-components';
|
|||||||
import { message, Button, Space, Popconfirm, Input, Select, Tag } from 'antd';
|
import { message, Button, Space, Popconfirm, Input, Select, Tag } from 'antd';
|
||||||
import React, { useRef, useState, useEffect } from 'react';
|
import React, { useRef, useState, useEffect } from 'react';
|
||||||
import { StatusEnum, SemanticNodeType } from '../enum';
|
import { StatusEnum, SemanticNodeType } from '../enum';
|
||||||
import { useModel } from '@umijs/max';
|
import { useModel, history } from '@umijs/max';
|
||||||
import { SENSITIVE_LEVEL_ENUM, SENSITIVE_LEVEL_OPTIONS, TAG_DEFINE_TYPE } from '../constant';
|
import { SENSITIVE_LEVEL_ENUM, SENSITIVE_LEVEL_OPTIONS, TAG_DEFINE_TYPE } from '../constant';
|
||||||
import {
|
import {
|
||||||
queryMetric,
|
queryMetric,
|
||||||
@@ -32,7 +32,7 @@ const ClassMetricTable: React.FC<Props> = ({ onEmptyMetricData }) => {
|
|||||||
const metricModel = useModel('SemanticModel.metricData');
|
const metricModel = useModel('SemanticModel.metricData');
|
||||||
const { selectDomainId } = domainModel;
|
const { selectDomainId } = domainModel;
|
||||||
const { selectModelId: modelId } = modelModel;
|
const { selectModelId: modelId } = modelModel;
|
||||||
const { MrefreshMetricList } = metricModel;
|
const { MrefreshMetricList, selectMetric, setSelectMetric } = metricModel;
|
||||||
const [batchSensitiveLevelOpenState, setBatchSensitiveLevelOpenState] = useState<boolean>(false);
|
const [batchSensitiveLevelOpenState, setBatchSensitiveLevelOpenState] = useState<boolean>(false);
|
||||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||||
const [metricItem, setMetricItem] = useState<ISemantic.IMetricItem>();
|
const [metricItem, setMetricItem] = useState<ISemantic.IMetricItem>();
|
||||||
@@ -144,7 +144,10 @@ const ClassMetricTable: React.FC<Props> = ({ onEmptyMetricData }) => {
|
|||||||
|
|
||||||
const columnsConfig = ColumnsConfig({
|
const columnsConfig = ColumnsConfig({
|
||||||
indicatorInfo: {
|
indicatorInfo: {
|
||||||
url: '/model/metric/edit/',
|
url: '/model/metric/:domainId/:modelId/:indicatorId',
|
||||||
|
onNameClick: (record: ISemantic.IMetricItem) => {
|
||||||
|
setSelectMetric(record);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -240,8 +243,9 @@ const ClassMetricTable: React.FC<Props> = ({ onEmptyMetricData }) => {
|
|||||||
type="link"
|
type="link"
|
||||||
key="metricEditBtn"
|
key="metricEditBtn"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setMetricItem(record);
|
history.push(`/model/metric/${record.domainId}/${record.modelId}/${record.id}`);
|
||||||
setCreateModalVisible(true);
|
// setMetricItem(record);
|
||||||
|
// setCreateModalVisible(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
编辑
|
编辑
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
import { DownOutlined, PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
|
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||||
import { Input, message, Tree, Popconfirm, Tooltip, Row, Col, Button, Menu } from 'antd';
|
import { Input, message, Popconfirm, Tooltip, Row, Col, Button, Menu } from 'antd';
|
||||||
import type { DataNode } from 'antd/lib/tree';
|
import type { DataNode } from 'antd/lib/tree';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import type { FC, Key } from 'react';
|
import type { FC } from 'react';
|
||||||
import { useModel } from '@umijs/max';
|
import { useModel } from '@umijs/max';
|
||||||
import { createDomain, updateDomain, deleteDomain } from '../service';
|
import { createDomain, updateDomain, deleteDomain } from '../service';
|
||||||
import { treeParentKeyLists } from '../utils';
|
|
||||||
import DomainInfoForm from './DomainInfoForm';
|
import DomainInfoForm from './DomainInfoForm';
|
||||||
import { constructorClassTreeFromList, addPathInTreeData } from '../utils';
|
|
||||||
import { AppstoreOutlined } from '@ant-design/icons';
|
|
||||||
import styles from './style.less';
|
import styles from './style.less';
|
||||||
import { ISemantic } from '../data';
|
import { ISemantic } from '../data';
|
||||||
|
|
||||||
@@ -42,20 +39,15 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
onTreeSelected,
|
onTreeSelected,
|
||||||
onTreeDataUpdate,
|
onTreeDataUpdate,
|
||||||
}) => {
|
}) => {
|
||||||
const [projectTree, setProjectTree] = useState<DataNode[]>([]);
|
|
||||||
const [projectInfoModalVisible, setProjectInfoModalVisible] = useState<boolean>(false);
|
const [projectInfoModalVisible, setProjectInfoModalVisible] = useState<boolean>(false);
|
||||||
const [domainInfoParams, setDomainInfoParams] = useState<any>({});
|
const [domainInfoParams, setDomainInfoParams] = useState<any>({});
|
||||||
const [filterValue, setFliterValue] = useState<string>('');
|
const [filterValue, setFliterValue] = useState<string>('');
|
||||||
const [expandedKeys, setExpandedKeys] = useState<string[]>([]);
|
|
||||||
const [classList, setClassList] = useState<ISemantic.IDomainItem[]>([]);
|
const [classList, setClassList] = useState<ISemantic.IDomainItem[]>([]);
|
||||||
const domainModel = useModel('SemanticModel.domainData');
|
const domainModel = useModel('SemanticModel.domainData');
|
||||||
const { selectDomainId, domainList } = domainModel;
|
const { selectDomainId, domainList } = domainModel;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const treeData = addPathInTreeData(constructorClassTreeFromList(domainList));
|
|
||||||
setProjectTree(treeData);
|
|
||||||
setClassList(domainList);
|
setClassList(domainList);
|
||||||
setExpandedKeys(treeParentKeyLists(treeData));
|
|
||||||
}, [domainList]);
|
}, [domainList]);
|
||||||
|
|
||||||
const onSearch = (value: any) => {
|
const onSearch = (value: any) => {
|
||||||
@@ -67,7 +59,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const targetNodeData = classList.filter((item: any) => {
|
const targetNodeData = classList.filter((item: any) => {
|
||||||
return item.id === selectedKeys;
|
return `${item.id}` === `${selectedKeys}`;
|
||||||
})[0];
|
})[0];
|
||||||
onTreeSelected?.(targetNodeData);
|
onTreeSelected?.(targetNodeData);
|
||||||
};
|
};
|
||||||
@@ -84,20 +76,6 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// const createDefaultModelSet = async (domainId: number) => {
|
|
||||||
// const { code, msg } = await createDomain({
|
|
||||||
// modelType: 'add',
|
|
||||||
// type: 'normal',
|
|
||||||
// parentId: domainId,
|
|
||||||
// name: '默认模型集',
|
|
||||||
// bizName: `defaultModelSet_${(Math.random() * 1000000).toFixed(0)}`,
|
|
||||||
// isUnique: 1,
|
|
||||||
// });
|
|
||||||
// if (code !== 200) {
|
|
||||||
// message.error(msg);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
const domainSubmit = async (values: any) => {
|
const domainSubmit = async (values: any) => {
|
||||||
if (values.modelType === 'add') {
|
if (values.modelType === 'add') {
|
||||||
const { code, data } = await createDomain(values);
|
const { code, data } = await createDomain(values);
|
||||||
@@ -126,21 +104,19 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
const { id, name, path, hasEditPermission, parentId, hasModel } = node as any;
|
const { id, name, path, hasEditPermission, parentId, hasModel } = node as any;
|
||||||
const type = parentId === 0 ? 'top' : 'normal';
|
const type = parentId === 0 ? 'top' : 'normal';
|
||||||
return (
|
return (
|
||||||
<div className={styles.projectItem}>
|
<div
|
||||||
<span
|
className={styles.projectItem}
|
||||||
className={styles.projectItemTitle}
|
// onClick={() => {
|
||||||
onClick={() => {
|
// handleSelect(id);
|
||||||
handleSelect(id);
|
// }}
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{name}
|
<span className={styles.projectItemTitle}>{name}</span>
|
||||||
</span>
|
|
||||||
{createDomainBtnVisible && hasEditPermission && (
|
{createDomainBtnVisible && hasEditPermission && (
|
||||||
<span className={`${styles.operation} ${styles.rowHover} `}>
|
<span className={`${styles.operation} ${styles.rowHover} `}>
|
||||||
{Array.isArray(path) && path.length < 2 && !hasModel && (
|
{Array.isArray(path) && path.length < 2 && !hasModel && (
|
||||||
<PlusOutlined
|
<PlusOutlined
|
||||||
className={styles.icon}
|
className={styles.icon}
|
||||||
onClick={() => {
|
onClick={(e) => {
|
||||||
setDomainInfoParams({
|
setDomainInfoParams({
|
||||||
modelType: 'add',
|
modelType: 'add',
|
||||||
type: 'normal',
|
type: 'normal',
|
||||||
@@ -148,19 +124,21 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
parentName: name,
|
parentName: name,
|
||||||
});
|
});
|
||||||
setProjectInfoModalVisible(true);
|
setProjectInfoModalVisible(true);
|
||||||
|
e.stopPropagation();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<EditOutlined
|
<EditOutlined
|
||||||
className={styles.icon}
|
className={styles.icon}
|
||||||
onClick={() => {
|
onClick={(e) => {
|
||||||
setDomainInfoParams({
|
setDomainInfoParams({
|
||||||
modelType: 'edit',
|
modelType: 'edit',
|
||||||
type,
|
type,
|
||||||
...node,
|
...node,
|
||||||
});
|
});
|
||||||
setProjectInfoModalVisible(true);
|
setProjectInfoModalVisible(true);
|
||||||
|
e.stopPropagation();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
@@ -172,7 +150,12 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
okText="是"
|
okText="是"
|
||||||
cancelText="否"
|
cancelText="否"
|
||||||
>
|
>
|
||||||
<DeleteOutlined className={styles.icon} />
|
<DeleteOutlined
|
||||||
|
className={styles.icon}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@@ -180,14 +163,14 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const projectRenderTree = filterValue ? projectTreeFlat(projectTree, filterValue) : projectTree;
|
|
||||||
|
|
||||||
const handleExpand = (_expandedKeys: Key[]) => {
|
|
||||||
setExpandedKeys(_expandedKeys as string[]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const items = domainList
|
const items = domainList
|
||||||
.filter((domain) => domain.parentId === 0)
|
.filter((domain) => {
|
||||||
|
if (filterValue) {
|
||||||
|
return domain.parentId === 0 && domain.name.includes(filterValue);
|
||||||
|
} else {
|
||||||
|
return domain.parentId === 0;
|
||||||
|
}
|
||||||
|
})
|
||||||
.map((domain: ISemantic.IDomainItem) => {
|
.map((domain: ISemantic.IDomainItem) => {
|
||||||
return {
|
return {
|
||||||
key: domain.id,
|
key: domain.id,
|
||||||
@@ -245,6 +228,12 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
className={styles.search}
|
className={styles.search}
|
||||||
placeholder="请输入名称搜索"
|
placeholder="请输入名称搜索"
|
||||||
onSearch={onSearch}
|
onSearch={onSearch}
|
||||||
|
onChange={(e) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
if (!value) {
|
||||||
|
setFliterValue(value);
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
{createDomainBtnVisible && (
|
{createDomainBtnVisible && (
|
||||||
@@ -265,25 +254,19 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
|
{selectDomainId && (
|
||||||
<Menu
|
<Menu
|
||||||
mode="inline"
|
mode="inline"
|
||||||
defaultSelectedKeys={['231']}
|
defaultSelectedKeys={[`${selectDomainId}`]}
|
||||||
openKeys={stateOpenKeys}
|
openKeys={stateOpenKeys}
|
||||||
onOpenChange={onOpenChange}
|
onOpenChange={onOpenChange}
|
||||||
style={{ width: 256 }}
|
style={{ width: 256 }}
|
||||||
items={items}
|
items={items}
|
||||||
|
onClick={(info) => {
|
||||||
|
handleSelect(info.key);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
{/* <Tree
|
)}
|
||||||
expandedKeys={expandedKeys}
|
|
||||||
onExpand={handleExpand}
|
|
||||||
className={styles.tree}
|
|
||||||
selectedKeys={[selectDomainId]}
|
|
||||||
blockNode={true}
|
|
||||||
switcherIcon={<DownOutlined />}
|
|
||||||
defaultExpandAll={true}
|
|
||||||
treeData={projectRenderTree}
|
|
||||||
titleRender={titleRender}
|
|
||||||
/> */}
|
|
||||||
{projectInfoModalVisible && (
|
{projectInfoModalVisible && (
|
||||||
<DomainInfoForm
|
<DomainInfoForm
|
||||||
basicInfo={domainInfoParams}
|
basicInfo={domainInfoParams}
|
||||||
|
|||||||
@@ -1,45 +1,27 @@
|
|||||||
import { Tabs, Breadcrumb, Space, Radio } from 'antd';
|
import { Tabs, Radio } from 'antd';
|
||||||
import React, { useRef, useEffect, useState } from 'react';
|
import React, { useRef, useEffect, useState } from 'react';
|
||||||
import { history, useModel } from '@umijs/max';
|
import { useModel } from '@umijs/max';
|
||||||
import ClassDimensionTable from './ClassDimensionTable';
|
|
||||||
import ClassMetricTable from './ClassMetricTable';
|
|
||||||
import PermissionSection from './Permission/PermissionSection';
|
import PermissionSection from './Permission/PermissionSection';
|
||||||
import TagObjectTable from '../Insights/components/TagObjectTable';
|
import TagObjectTable from '../Insights/components/TagObjectTable';
|
||||||
import TermTable from '../components/Term/TermTable';
|
import TermTable from '../components/Term/TermTable';
|
||||||
import OverView from './OverView';
|
import OverView from './OverView';
|
||||||
import styles from './style.less';
|
import styles from './style.less';
|
||||||
import { HomeOutlined, FundViewOutlined } from '@ant-design/icons';
|
|
||||||
import { ISemantic } from '../data';
|
|
||||||
import SemanticGraphCanvas from '../SemanticGraphCanvas';
|
import SemanticGraphCanvas from '../SemanticGraphCanvas';
|
||||||
import Dimension from '../Dimension';
|
|
||||||
import ModelMetric from '../components/ModelMetric';
|
|
||||||
import View from '../View';
|
import View from '../View';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
// isModel: boolean;
|
|
||||||
activeKey: string;
|
activeKey: string;
|
||||||
// modelList: ISemantic.IModelItem[];
|
|
||||||
dataSetList: ISemantic.IDatasetItem[];
|
|
||||||
// handleModelChange: (model?: ISemantic.IModelItem) => void;
|
|
||||||
onBackDomainBtnClick?: () => void;
|
|
||||||
onMenuChange?: (menuKey: string) => void;
|
onMenuChange?: (menuKey: string) => void;
|
||||||
};
|
};
|
||||||
const DomainManagerTab: React.FC<Props> = ({
|
const DomainManagerTab: React.FC<Props> = ({ activeKey, onMenuChange }) => {
|
||||||
activeKey,
|
|
||||||
// modelList,
|
|
||||||
dataSetList,
|
|
||||||
// handleModelChange,
|
|
||||||
onBackDomainBtnClick,
|
|
||||||
onMenuChange,
|
|
||||||
}) => {
|
|
||||||
const initState = useRef<boolean>(false);
|
const initState = useRef<boolean>(false);
|
||||||
const defaultTabKey = 'metric';
|
const defaultTabKey = 'metric';
|
||||||
|
|
||||||
const domainModel = useModel('SemanticModel.domainData');
|
const domainModel = useModel('SemanticModel.domainData');
|
||||||
const modelModel = useModel('SemanticModel.modelData');
|
const modelModel = useModel('SemanticModel.modelData');
|
||||||
|
|
||||||
const { selectDomainId, selectDomainName, selectDomain: domainData } = domainModel;
|
const { selectDomainId, selectDomain: domainData } = domainModel;
|
||||||
const { selectModelId, modelList, selectModelName } = modelModel;
|
const { selectModelId, modelList } = modelModel;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initState.current = false;
|
initState.current = false;
|
||||||
|
|||||||
@@ -901,7 +901,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
|||||||
key="console"
|
key="console"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
history.replace(
|
history.replace(
|
||||||
`/model/manager/${domainId}/${modelId || metricItem?.modelId}/dataSource`,
|
`/model/domain/manager/${domainId}/${modelId || metricItem?.modelId}/dataSource`,
|
||||||
);
|
);
|
||||||
onCancel?.();
|
onCancel?.();
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -18,28 +18,14 @@ import View from '../View';
|
|||||||
type Props = {
|
type Props = {
|
||||||
activeKey: string;
|
activeKey: string;
|
||||||
modelList: ISemantic.IModelItem[];
|
modelList: ISemantic.IModelItem[];
|
||||||
handleModelChange: (model?: ISemantic.IModelItem) => void;
|
|
||||||
onBackDomainBtnClick?: () => void;
|
|
||||||
onMenuChange?: (menuKey: string) => void;
|
onMenuChange?: (menuKey: string) => void;
|
||||||
};
|
};
|
||||||
const ModelManagerTab: React.FC<Props> = ({
|
const ModelManagerTab: React.FC<Props> = ({ activeKey, onMenuChange }) => {
|
||||||
activeKey,
|
|
||||||
modelList,
|
|
||||||
handleModelChange,
|
|
||||||
onBackDomainBtnClick,
|
|
||||||
onMenuChange,
|
|
||||||
}) => {
|
|
||||||
const initState = useRef<boolean>(false);
|
const initState = useRef<boolean>(false);
|
||||||
const defaultTabKey = 'metric';
|
const defaultTabKey = 'metric';
|
||||||
const domainModel = useModel('SemanticModel.domainData');
|
|
||||||
const modelModel = useModel('SemanticModel.modelData');
|
const modelModel = useModel('SemanticModel.modelData');
|
||||||
|
|
||||||
const { selectDomainId, selectDomainName, selectDomain: domainData } = domainModel;
|
const { selectModelId } = modelModel;
|
||||||
const { selectModelId, selectModelName } = modelModel;
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
console.log(modelList, 'modelList');
|
|
||||||
}, [modelList]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initState.current = false;
|
initState.current = false;
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ const ModelTable: React.FC<Props> = ({ modelList, disabledEdit = false, onModelC
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectModel(record);
|
setSelectModel(record);
|
||||||
|
|
||||||
history.push(`/model/manager/${domainId}/${id}`);
|
history.push(`/model/domain/manager/${domainId}/${id}`);
|
||||||
// onModelChange?.(record);
|
// onModelChange?.(record);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -6,62 +6,37 @@ import { history } from '@umijs/max';
|
|||||||
import { ISemantic } from '../data';
|
import { ISemantic } from '../data';
|
||||||
import { isString } from 'lodash';
|
import { isString } from 'lodash';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { isArrayOfValues } from '@/utils/utils';
|
import { isArrayOfValues, replaceRouteParams } from '@/utils/utils';
|
||||||
import styles from './style.less';
|
import styles from './style.less';
|
||||||
import IndicatorStar, { StarType } from '../components/IndicatorStar';
|
import IndicatorStar, { StarType } from '../components/IndicatorStar';
|
||||||
|
|
||||||
const { Text, Paragraph } = Typography;
|
interface IndicatorInfo {
|
||||||
|
|
||||||
export const ColumnsConfig: any = (params?: {
|
|
||||||
indicatorInfo?: {
|
|
||||||
url?: string;
|
url?: string;
|
||||||
starType?: StarType;
|
starType?: StarType;
|
||||||
onNameClick?: (record: ISemantic.IMetricItem) => void;
|
onNameClick?: (record: ISemantic.IMetricItem) => void | boolean;
|
||||||
};
|
}
|
||||||
}) => {
|
|
||||||
return {
|
|
||||||
description: {
|
|
||||||
render: (_, record: ISemantic.IMetricItem) => {
|
|
||||||
const { description } = record;
|
|
||||||
return (
|
|
||||||
<Paragraph
|
|
||||||
ellipsis={{ tooltip: description, rows: 3 }}
|
|
||||||
style={{ width: 250, marginBottom: 0 }}
|
|
||||||
>
|
|
||||||
{description}
|
|
||||||
</Paragraph>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
dimensionInfo: {
|
|
||||||
render: (_, record: ISemantic.IDimensionItem) => {
|
|
||||||
const { name, alias, bizName } = record;
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div>
|
|
||||||
<Space>
|
|
||||||
<span style={{ fontWeight: 500 }}>{name}</span>
|
|
||||||
</Space>
|
|
||||||
</div>
|
|
||||||
<div style={{ color: '#5f748d', fontSize: 14, marginTop: 5, marginLeft: 0 }}>
|
|
||||||
{bizName}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{alias && (
|
interface ColumnsConfigParams {
|
||||||
|
indicatorInfo?: IndicatorInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { Text, Paragraph } = Typography;
|
||||||
|
|
||||||
|
export const ColumnsConfig = (params?: ColumnsConfigParams) => {
|
||||||
|
const renderAliasAndClassifications = (
|
||||||
|
alias: string | undefined,
|
||||||
|
classifications: string[] | undefined,
|
||||||
|
) => (
|
||||||
<div style={{ marginTop: 8 }}>
|
<div style={{ marginTop: 8 }}>
|
||||||
<Space direction="vertical" size={4}>
|
<Space direction="vertical" size={4}>
|
||||||
{alias && (
|
{alias && (
|
||||||
<Space
|
<Space size={4} style={{ color: '#5f748d', fontSize: 12, margin: '5px 0 5px 0' }}>
|
||||||
size={4}
|
|
||||||
style={{ color: '#5f748d', fontSize: 12, margin: '5px 0 5px 0' }}
|
|
||||||
>
|
|
||||||
<ReadOutlined />
|
<ReadOutlined />
|
||||||
<div style={{ width: 'max-content' }}>别名:</div>
|
<div style={{ width: 'max-content' }}>别名:</div>
|
||||||
<span style={{ marginLeft: 2 }}>
|
<span style={{ marginLeft: 2 }}>
|
||||||
<Space size={[0, 8]} wrap>
|
<Space size={[0, 8]} wrap>
|
||||||
{isString(alias) &&
|
{isString(alias) &&
|
||||||
alias.split(',').map((aliasName: string) => {
|
alias.split(',').map((aliasName: string) => (
|
||||||
return (
|
|
||||||
<Tag
|
<Tag
|
||||||
color="#eee"
|
color="#eee"
|
||||||
key={aliasName}
|
key={aliasName}
|
||||||
@@ -84,120 +59,19 @@ export const ColumnsConfig: any = (params?: {
|
|||||||
{aliasName}
|
{aliasName}
|
||||||
</Text>
|
</Text>
|
||||||
</Tag>
|
</Tag>
|
||||||
);
|
))}
|
||||||
})}
|
|
||||||
</Space>
|
|
||||||
</span>
|
|
||||||
</Space>
|
|
||||||
)}
|
|
||||||
</Space>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
indicatorInfo: {
|
|
||||||
render: (_, record: ISemantic.IMetricItem) => {
|
|
||||||
const { name, alias, bizName, classifications, id, isCollect } = record;
|
|
||||||
let url = `/metric/detail/`;
|
|
||||||
let starType: StarType = 'metric';
|
|
||||||
if (params) {
|
|
||||||
if (params?.indicatorInfo?.url) {
|
|
||||||
url = params.indicatorInfo.url;
|
|
||||||
}
|
|
||||||
if (params?.indicatorInfo?.starType) {
|
|
||||||
starType = params.indicatorInfo.starType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div>
|
|
||||||
<Space>
|
|
||||||
<a
|
|
||||||
className={styles.textLink}
|
|
||||||
style={{ fontWeight: 500 }}
|
|
||||||
onClick={(event: any) => {
|
|
||||||
if (params?.indicatorInfo?.onNameClick) {
|
|
||||||
params?.indicatorInfo?.onNameClick(record);
|
|
||||||
} else {
|
|
||||||
history.push(`${url}${id}`);
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
}}
|
|
||||||
// href={`/webapp${url}${id}`}
|
|
||||||
>
|
|
||||||
{name}
|
|
||||||
</a>
|
|
||||||
<IndicatorStar indicatorId={id} type={starType} initState={isCollect} />
|
|
||||||
{/* <Tag
|
|
||||||
color={SENSITIVE_LEVEL_COLOR[sensitiveLevel]}
|
|
||||||
style={{ lineHeight: '16px', position: 'relative', top: '-1px' }}
|
|
||||||
>
|
|
||||||
{SENSITIVE_LEVEL_ENUM[sensitiveLevel]}
|
|
||||||
</Tag> */}
|
|
||||||
</Space>
|
|
||||||
</div>
|
|
||||||
<div style={{ color: '#5f748d', fontSize: 14, marginTop: 5, marginLeft: 0 }}>
|
|
||||||
{bizName}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{(alias || isArrayOfValues(classifications)) && (
|
|
||||||
<div style={{ marginTop: 8 }}>
|
|
||||||
<Space direction="vertical" size={4}>
|
|
||||||
{alias && (
|
|
||||||
<Space
|
|
||||||
size={4}
|
|
||||||
style={{ color: '#5f748d', fontSize: 12, margin: '5px 0 5px 0' }}
|
|
||||||
>
|
|
||||||
<ReadOutlined />
|
|
||||||
<div style={{ width: 'max-content' }}>别名:</div>
|
|
||||||
<span style={{ marginLeft: 2 }}>
|
|
||||||
<Space size={[0, 8]} wrap>
|
|
||||||
{isString(alias) &&
|
|
||||||
alias.split(',').map((aliasName: string) => {
|
|
||||||
return (
|
|
||||||
<Tag
|
|
||||||
color="#eee"
|
|
||||||
key={aliasName}
|
|
||||||
style={{
|
|
||||||
borderRadius: 44,
|
|
||||||
maxWidth: 90,
|
|
||||||
minWidth: 40,
|
|
||||||
backgroundColor: 'rgba(18, 31, 67, 0.04)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
maxWidth: 80,
|
|
||||||
color: 'rgb(95, 116, 141)',
|
|
||||||
textAlign: 'center',
|
|
||||||
fontSize: 12,
|
|
||||||
}}
|
|
||||||
ellipsis={{ tooltip: aliasName }}
|
|
||||||
>
|
|
||||||
{aliasName}
|
|
||||||
</Text>
|
|
||||||
</Tag>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Space>
|
</Space>
|
||||||
</span>
|
</span>
|
||||||
</Space>
|
</Space>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isArrayOfValues(classifications) && (
|
{isArrayOfValues(classifications) && (
|
||||||
<Space
|
<Space size={4} style={{ color: '#5f748d', fontSize: 12, margin: '5px 0 5px 0' }}>
|
||||||
size={4}
|
|
||||||
style={{ color: '#5f748d', fontSize: 12, margin: '5px 0 5px 0' }}
|
|
||||||
>
|
|
||||||
<TagsOutlined />
|
<TagsOutlined />
|
||||||
<div style={{ width: 'max-content' }}>分类:</div>
|
<div style={{ width: 'max-content' }}>分类:</div>
|
||||||
<span style={{ marginLeft: 2 }}>
|
<span style={{ marginLeft: 2 }}>
|
||||||
<Space size={[0, 8]} wrap>
|
<Space size={[0, 8]} wrap>
|
||||||
{classifications.map((tag: string) => {
|
{classifications.map((tag: string) => (
|
||||||
return (
|
|
||||||
<Tag
|
<Tag
|
||||||
color="#eee"
|
color="#eee"
|
||||||
key={tag}
|
key={tag}
|
||||||
@@ -220,104 +94,133 @@ export const ColumnsConfig: any = (params?: {
|
|||||||
{tag}
|
{tag}
|
||||||
</Text>
|
</Text>
|
||||||
</Tag>
|
</Tag>
|
||||||
);
|
))}
|
||||||
})}
|
|
||||||
</Space>
|
</Space>
|
||||||
</span>
|
</span>
|
||||||
</Space>
|
</Space>
|
||||||
)}
|
)}
|
||||||
{/* <Space size={10}>
|
|
||||||
<Space
|
|
||||||
size={2}
|
|
||||||
style={{ color: '#5f748d', fontSize: 12, position: 'relative', top: '1px' }}
|
|
||||||
>
|
|
||||||
<FieldNumberOutlined style={{ fontSize: 16, position: 'relative', top: '1px' }} />
|
|
||||||
<span>:</span>
|
|
||||||
<span style={{ marginLeft: 0 }}>{id}</span>
|
|
||||||
</Space>
|
|
||||||
<Space size={2} style={{ color: '#5f748d', fontSize: 12 }}>
|
|
||||||
<UserOutlined />
|
|
||||||
<span>:</span>
|
|
||||||
<span style={{ marginLeft: 0 }}>{createdBy}</span>
|
|
||||||
</Space>
|
|
||||||
</Space> */}
|
|
||||||
</Space>
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
)}
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
description: {
|
||||||
|
render: (_, record: ISemantic.IMetricItem) => (
|
||||||
|
<Paragraph
|
||||||
|
ellipsis={{ tooltip: record.description, rows: 3 }}
|
||||||
|
style={{ width: 250, marginBottom: 0 }}
|
||||||
|
>
|
||||||
|
{record.description}
|
||||||
|
</Paragraph>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
dimensionInfo: {
|
||||||
|
render: (_, record: ISemantic.IDimensionItem) => {
|
||||||
|
const { name, alias, bizName } = record;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<Space>
|
||||||
|
<span style={{ fontWeight: 500 }}>{name}</span>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
<div style={{ color: '#5f748d', fontSize: 14, marginTop: 5, marginLeft: 0 }}>
|
||||||
|
{bizName}
|
||||||
|
</div>
|
||||||
|
{renderAliasAndClassifications(alias, undefined)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
indicatorInfo: {
|
||||||
|
render: (_, record: ISemantic.IMetricItem) => {
|
||||||
|
const { name, alias, bizName, classifications, id, isCollect, domainId, modelId } = record;
|
||||||
|
|
||||||
|
let url = `/metric/detail/`;
|
||||||
|
let starType: StarType = 'metric';
|
||||||
|
if (params?.indicatorInfo) {
|
||||||
|
url = replaceRouteParams(params.indicatorInfo.url || '', {
|
||||||
|
domainId: `${domainId}`,
|
||||||
|
modelId: `${modelId}`,
|
||||||
|
indicatorId: `${id}`,
|
||||||
|
});
|
||||||
|
starType = params.indicatorInfo.starType || 'metric';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<Space>
|
||||||
|
<a
|
||||||
|
className={styles.textLink}
|
||||||
|
style={{ fontWeight: 500 }}
|
||||||
|
onClick={(event: any) => {
|
||||||
|
if (params?.indicatorInfo?.onNameClick) {
|
||||||
|
const state = params.indicatorInfo.onNameClick(record);
|
||||||
|
if (state === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
history.push(url);
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</a>
|
||||||
|
<IndicatorStar indicatorId={id} type={starType} initState={isCollect} />
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
<div style={{ color: '#5f748d', fontSize: 14, marginTop: 5, marginLeft: 0 }}>
|
||||||
|
{bizName}
|
||||||
|
</div>
|
||||||
|
{renderAliasAndClassifications(alias, classifications)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sensitiveLevel: {
|
sensitiveLevel: {
|
||||||
render: (_, record: ISemantic.IMetricItem) => {
|
render: (_, record: ISemantic.IMetricItem) => (
|
||||||
const { sensitiveLevel } = record;
|
|
||||||
return SENSITIVE_LEVEL_COLOR[sensitiveLevel] ? (
|
|
||||||
<Tag
|
|
||||||
color={SENSITIVE_LEVEL_COLOR[sensitiveLevel]}
|
|
||||||
style={{
|
|
||||||
borderRadius: '40px',
|
|
||||||
padding: '2px 16px',
|
|
||||||
fontSize: '13px',
|
|
||||||
// color: '#8ca3ba',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{SENSITIVE_LEVEL_ENUM[sensitiveLevel]}
|
|
||||||
</Tag>
|
|
||||||
) : (
|
|
||||||
<Tag
|
<Tag
|
||||||
|
color={SENSITIVE_LEVEL_COLOR[record.sensitiveLevel] || 'default'}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '40px',
|
borderRadius: '40px',
|
||||||
padding: '2px 16px',
|
padding: '2px 16px',
|
||||||
fontSize: '13px',
|
fontSize: '13px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
未知
|
{SENSITIVE_LEVEL_ENUM[record.sensitiveLevel] || '未知'}
|
||||||
</Tag>
|
</Tag>
|
||||||
);
|
),
|
||||||
},
|
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
render: (status) => {
|
render: (status) => {
|
||||||
let tagProps: { color: string; label: string; style?: any } = {
|
const tagProps = {
|
||||||
color: 'default',
|
color: 'default',
|
||||||
label: '未知',
|
label: '未知',
|
||||||
style: {},
|
style: {},
|
||||||
};
|
};
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case StatusEnum.ONLINE:
|
case StatusEnum.ONLINE:
|
||||||
tagProps = {
|
tagProps.color = 'geekblue';
|
||||||
// color: 'processing',
|
tagProps.label = '已启用';
|
||||||
color: 'geekblue',
|
|
||||||
label: '已启用',
|
|
||||||
};
|
|
||||||
break;
|
break;
|
||||||
case StatusEnum.OFFLINE:
|
case StatusEnum.OFFLINE:
|
||||||
tagProps = {
|
tagProps.color = 'default';
|
||||||
color: 'default',
|
tagProps.label = '未启用';
|
||||||
label: '未启用',
|
tagProps.style = { color: 'rgb(95, 116, 141)', fontWeight: 400 };
|
||||||
style: {
|
|
||||||
color: 'rgb(95, 116, 141)',
|
|
||||||
fontWeight: 400,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
break;
|
break;
|
||||||
case StatusEnum.INITIALIZED:
|
case StatusEnum.INITIALIZED:
|
||||||
tagProps = {
|
tagProps.color = 'processing';
|
||||||
color: 'processing',
|
tagProps.label = '初始化';
|
||||||
label: '初始化',
|
|
||||||
};
|
|
||||||
break;
|
break;
|
||||||
case StatusEnum.DELETED:
|
case StatusEnum.DELETED:
|
||||||
tagProps = {
|
tagProps.color = 'default';
|
||||||
color: 'default',
|
tagProps.label = '已删除';
|
||||||
label: '已删除',
|
|
||||||
};
|
|
||||||
break;
|
break;
|
||||||
case StatusEnum.UNAVAILABLE:
|
case StatusEnum.UNAVAILABLE:
|
||||||
tagProps = {
|
tagProps.color = 'default';
|
||||||
color: 'default',
|
tagProps.label = '不可用';
|
||||||
label: '不可用',
|
|
||||||
};
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -344,14 +247,12 @@ export const ColumnsConfig: any = (params?: {
|
|||||||
tooltip: '创建人/更新时间',
|
tooltip: '创建人/更新时间',
|
||||||
width: 180,
|
width: 180,
|
||||||
search: false,
|
search: false,
|
||||||
render: (value: any, record: ISemantic.IMetricItem) => {
|
render: (value: any, record: ISemantic.IMetricItem) => (
|
||||||
return (
|
|
||||||
<Space direction="vertical">
|
<Space direction="vertical">
|
||||||
<span> {record.createdBy}</span>
|
<span> {record.createdBy}</span>
|
||||||
<span>{value && value !== '-' ? dayjs(value).format('YYYY-MM-DD HH:mm:ss') : '-'}</span>
|
<span>{value && value !== '-' ? dayjs(value).format('YYYY-MM-DD HH:mm:ss') : '-'}</span>
|
||||||
</Space>
|
</Space>
|
||||||
);
|
),
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
|
|
||||||
.projectManger {
|
.projectManger {
|
||||||
|
border-top: 1px solid #eee;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: calc(100vh - 56px);
|
min-height: calc(100vh - 56px);
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
@@ -163,8 +164,8 @@
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
.tab {
|
.tab {
|
||||||
border-top: 1px solid #eee;
|
|
||||||
margin-top: 10px;
|
// margin-top: 10px;
|
||||||
:global {
|
:global {
|
||||||
.ant-tabs-tab-btn {
|
.ant-tabs-tab-btn {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@@ -338,12 +339,14 @@
|
|||||||
|
|
||||||
.breadcrumb{
|
.breadcrumb{
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
margin: 17px 0 0 20px;
|
height: 48px;
|
||||||
padding-bottom: 3px;
|
line-height: 48px;
|
||||||
|
padding: 0 20px;
|
||||||
:global {
|
:global {
|
||||||
.ant-breadcrumb-link {
|
.ant-breadcrumb-link {
|
||||||
height: 28px;
|
height: 28px;
|
||||||
color: #709bf1;
|
color: #709bf1;
|
||||||
|
cursor: pointer;
|
||||||
&:hover{
|
&:hover{
|
||||||
color: #296df3;
|
color: #296df3;
|
||||||
}
|
}
|
||||||
@@ -351,6 +354,14 @@
|
|||||||
.anticon {
|
.anticon {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
li {
|
||||||
|
&:last-child {
|
||||||
|
.ant-breadcrumb-link {
|
||||||
|
color: #296df3;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +1,28 @@
|
|||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { history, useParams, useModel } from '@umijs/max';
|
import { history, useParams, useModel, Outlet } from '@umijs/max';
|
||||||
import DomainListTree from './components/DomainList';
|
import DomainListTree from './components/DomainList';
|
||||||
import styles from './components/style.less';
|
import styles from './components/style.less';
|
||||||
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
|
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||||||
import { ISemantic } from './data';
|
import { ISemantic } from './data';
|
||||||
import { getDomainList, getDataSetList } from './service';
|
import { getDomainList, getDataSetList, getModelDetail } from './service';
|
||||||
import { isArrayOfValues } from '@/utils/utils';
|
import PageBreadcrumb from './PageBreadcrumb';
|
||||||
import OverviewContainerRight from './OverviewContainerRight';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {};
|
||||||
mode: 'domain';
|
|
||||||
};
|
|
||||||
|
|
||||||
const OverviewContainer: React.FC<Props> = ({ mode = 'domain' }) => {
|
const SemanticModel: React.FC<Props> = ({}) => {
|
||||||
const defaultTabKey = 'overview';
|
|
||||||
const params: any = useParams();
|
const params: any = useParams();
|
||||||
const domainId = params.domainId;
|
const domainId = params.domainId;
|
||||||
const modelId = params.modelId;
|
const modelId = params.modelId;
|
||||||
const domainModel = useModel('SemanticModel.domainData');
|
const domainModel = useModel('SemanticModel.domainData');
|
||||||
const modelModel = useModel('SemanticModel.modelData');
|
const modelModel = useModel('SemanticModel.modelData');
|
||||||
const dimensionModel = useModel('SemanticModel.dimensionData');
|
|
||||||
const metricModel = useModel('SemanticModel.metricData');
|
|
||||||
const databaseModel = useModel('SemanticModel.databaseData');
|
const databaseModel = useModel('SemanticModel.databaseData');
|
||||||
const { selectDomainId, domainList, setSelectDomain, setDomainList } = domainModel;
|
const metricModel = useModel('SemanticModel.metricData');
|
||||||
const {
|
const { setSelectDomain, setDomainList, selectDomainId } = domainModel;
|
||||||
selectModelId,
|
const { selectModel, setSelectModel, setModelTableHistoryParams, MrefreshModelList } = modelModel;
|
||||||
modelList,
|
|
||||||
MrefreshModelList,
|
|
||||||
setSelectModel,
|
|
||||||
setModelTableHistoryParams,
|
|
||||||
} = modelModel;
|
|
||||||
const { MrefreshDimensionList } = dimensionModel;
|
|
||||||
const { MrefreshMetricList } = metricModel;
|
|
||||||
const { MrefreshDatabaseList } = databaseModel;
|
const { MrefreshDatabaseList } = databaseModel;
|
||||||
const menuKey = params.menuKey ? params.menuKey : !Number(modelId) ? defaultTabKey : '';
|
|
||||||
|
|
||||||
const [collapsedState, setCollapsedState] = useState(true);
|
const { selectMetric, setSelectMetric } = metricModel;
|
||||||
const [activeKey, setActiveKey] = useState<string>(menuKey);
|
|
||||||
// const [dataSetList, setDataSetList] = useState<ISemantic.IDatasetItem[]>([]);
|
|
||||||
|
|
||||||
const initSelectedDomain = (domainList: ISemantic.IDomainItem[]) => {
|
const initSelectedDomain = (domainList: ISemantic.IDomainItem[]) => {
|
||||||
const targetNode = domainList.filter((item: any) => {
|
const targetNode = domainList.filter((item: any) => {
|
||||||
@@ -51,8 +35,7 @@ const OverviewContainer: React.FC<Props> = ({ mode = 'domain' }) => {
|
|||||||
if (firstRootNode) {
|
if (firstRootNode) {
|
||||||
const { id } = firstRootNode;
|
const { id } = firstRootNode;
|
||||||
setSelectDomain(firstRootNode);
|
setSelectDomain(firstRootNode);
|
||||||
setActiveKey(menuKey);
|
// pushUrlMenu(id, menuKey);
|
||||||
pushUrlMenu(id, 0, menuKey);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setSelectDomain(targetNode);
|
setSelectDomain(targetNode);
|
||||||
@@ -69,121 +52,38 @@ const OverviewContainer: React.FC<Props> = ({ mode = 'domain' }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const initModelData = async () => {
|
||||||
|
const { code, data, msg } = await getModelDetail({ modelId });
|
||||||
|
if (code === 200) {
|
||||||
|
setSelectModel(data);
|
||||||
|
} else {
|
||||||
|
message.error(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initProjectTree();
|
initProjectTree();
|
||||||
MrefreshDatabaseList();
|
MrefreshDatabaseList();
|
||||||
|
if (modelId && modelId !== selectModel) {
|
||||||
|
initModelData();
|
||||||
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
setSelectDomain(undefined);
|
setSelectDomain(undefined);
|
||||||
// setSelectModel(undefined);
|
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!selectDomainId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log(selectDomainId, 'selectDomainIdselectDomainId');
|
|
||||||
queryModelList();
|
|
||||||
// queryDataSetList();
|
|
||||||
}, [selectDomainId]);
|
|
||||||
|
|
||||||
// const queryDataSetList = async () => {
|
|
||||||
// const { code, data, msg } = await getDataSetList(selectDomainId);
|
|
||||||
// if (code === 200) {
|
|
||||||
// setDataSetList(data);
|
|
||||||
// if (!isArrayOfValues(data)) {
|
|
||||||
// setActiveKey(defaultTabKey);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// message.error(msg);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
const queryModelList = async () => {
|
|
||||||
await MrefreshModelList(selectDomainId);
|
|
||||||
};
|
|
||||||
|
|
||||||
// const initModelConfig = () => {
|
|
||||||
// const currentMenuKey = menuKey === defaultTabKey ? '' : menuKey;
|
|
||||||
// pushUrlMenu(selectDomainId, selectModelId, currentMenuKey);
|
|
||||||
// setActiveKey(currentMenuKey);
|
|
||||||
// };
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (!selectModelId) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// // initModelConfig();
|
|
||||||
// MrefreshDimensionList({ modelId: selectModelId });
|
|
||||||
// MrefreshMetricList({ modelId: selectModelId });
|
|
||||||
// }, [selectModelId]);
|
|
||||||
|
|
||||||
const pushUrlMenu = (domainId: number, modelId: number, menuKey: string) => {
|
|
||||||
history.push(`/model/${domainId}/${menuKey}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
// // const handleModelChange = (model?: ISemantic.IModelItem) => {
|
|
||||||
// // if (!model) {
|
|
||||||
// // return;
|
|
||||||
// // }
|
|
||||||
// // if (`${model.id}` === `${selectModelId}`) {
|
|
||||||
// // initModelConfig();
|
|
||||||
// // }
|
|
||||||
// // setSelectModel(model);
|
|
||||||
// // };
|
|
||||||
|
|
||||||
const cleanModelInfo = (domainId) => {
|
|
||||||
setActiveKey(defaultTabKey);
|
|
||||||
pushUrlMenu(domainId, 0, defaultTabKey);
|
|
||||||
setSelectModel(undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCollapsedBtn = () => {
|
|
||||||
setCollapsedState(!collapsedState);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.projectBody}>
|
<div>
|
||||||
<div className={styles.projectManger}>
|
<div style={{ background: '#fff' }}>
|
||||||
<div className={`${styles.sider} ${!collapsedState ? styles.siderCollapsed : ''}`}>
|
<PageBreadcrumb />
|
||||||
<div className={styles.treeContainer}>
|
|
||||||
<DomainListTree
|
|
||||||
createDomainBtnVisible={mode === 'domain' ? true : false}
|
|
||||||
onTreeSelected={(domainData: ISemantic.IDomainItem) => {
|
|
||||||
const { id } = domainData;
|
|
||||||
cleanModelInfo(id);
|
|
||||||
setSelectDomain(domainData);
|
|
||||||
setModelTableHistoryParams({
|
|
||||||
[id]: {},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
onTreeDataUpdate={() => {
|
|
||||||
initProjectTree();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className={styles.siderCollapsedButton}
|
|
||||||
onClick={() => {
|
|
||||||
handleCollapsedBtn();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{collapsedState ? <LeftOutlined /> : <RightOutlined />}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={styles.content}>
|
|
||||||
{selectDomainId ? (
|
|
||||||
<>
|
|
||||||
<OverviewContainerRight />
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<h2 className={styles.mainTip}>请选择项目</h2>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<Outlet />
|
||||||
|
{/* <OverviewContainer /> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default OverviewContainer;
|
export default SemanticModel;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { queryMetric } from '../service';
|
|||||||
|
|
||||||
export default function Metric() {
|
export default function Metric() {
|
||||||
const [metricList, setMetricList] = useState<ISemantic.IMetricItem[]>([]);
|
const [metricList, setMetricList] = useState<ISemantic.IMetricItem[]>([]);
|
||||||
|
const [selectMetric, setSelectMetric] = useState<ISemantic.IMetricItem>();
|
||||||
|
|
||||||
const queryMetricList = async (params: any) => {
|
const queryMetricList = async (params: any) => {
|
||||||
const { code, data, msg } = await queryMetric({
|
const { code, data, msg } = await queryMetric({
|
||||||
@@ -25,6 +26,8 @@ export default function Metric() {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
MmetricList: metricList,
|
MmetricList: metricList,
|
||||||
|
setSelectMetric: setSelectMetric,
|
||||||
|
selectMetric: selectMetric,
|
||||||
MrefreshMetricList: refreshMetricList,
|
MrefreshMetricList: refreshMetricList,
|
||||||
MqueryMetricList: queryMetricList,
|
MqueryMetricList: queryMetricList,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -453,7 +453,7 @@ export function getUnAvailableItem(data: any): Promise<any> {
|
|||||||
|
|
||||||
export function getModelDetail(data: any): Promise<any> {
|
export function getModelDetail(data: any): Promise<any> {
|
||||||
if (!data.modelId) {
|
if (!data.modelId) {
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
return request.get(`${process.env.API_BASE_URL}model/getModel/${data.modelId}`);
|
return request.get(`${process.env.API_BASE_URL}model/getModel/${data.modelId}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -502,3 +502,10 @@ export function decryptPassword(encryptPassword: string) {
|
|||||||
export function uniqueArray(arr: any[]) {
|
export function uniqueArray(arr: any[]) {
|
||||||
return Array.from(new Set(arr));
|
return Array.from(new Set(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 替换以:开头标记的变量
|
||||||
|
export const replaceRouteParams = (template: string, values: Record<string, string>): string => {
|
||||||
|
return template.replace(/:([a-zA-Z0-9_]+)/g, (match, key) => {
|
||||||
|
return values[key] !== undefined ? values[key] : match;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user