diff --git a/webapp/packages/supersonic-fe/config/routes.ts b/webapp/packages/supersonic-fe/config/routes.ts index 946e72eca..04a8413d8 100644 --- a/webapp/packages/supersonic-fe/config/routes.ts +++ b/webapp/packages/supersonic-fe/config/routes.ts @@ -62,27 +62,85 @@ const ROUTES = [ envEnableList: [ENV_KEY.SEMANTIC], routes: [ { - path: '/model/:domainId', - component: './SemanticModel/DomainManager', - envEnableList: [ENV_KEY.SEMANTIC], + path: '/model/', + redirect: '/model/domain', + }, + { + path: '/model/domain/', + component: './SemanticModel/OverviewContainer', routes: [ { - path: '/model/:domainId/:menuKey', + path: '/model/domain/:domainId', component: './SemanticModel/DomainManager', + routes: [ + { + path: '/model/domain/:domainId/:menuKey', + component: './SemanticModel/DomainManager', + }, + ], + }, + { + path: '/model/domain/manager/:domainId/:modelId', + component: './SemanticModel/ModelManager', + routes: [ + { + path: '/model/domain/manager/:domainId/:modelId/:menuKey', + component: './SemanticModel/ModelManager', + }, + ], }, ], }, { - path: '/model/manager/:domainId/:modelId', - 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', - }, - ], + // 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', // component: './SemanticModel/DomainManager', diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/DomainManager.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/DomainManager.tsx index 4ff772a5d..d278a710b 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/DomainManager.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/DomainManager.tsx @@ -1,103 +1,26 @@ -import { message } from 'antd'; -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { history, useParams, useModel } from '@umijs/max'; -import { ISemantic } from './data'; -import { getDomainList, getDataSetList } from './service'; import DomainManagerTab from './components/DomainManagerTab'; -import { isArrayOfValues } from '@/utils/utils'; type Props = {}; const DomainManager: React.FC = ({}) => { const defaultTabKey = 'overview'; const params: any = useParams(); - const domainId = params.domainId; const domainModel = useModel('SemanticModel.domainData'); - const modelModel = useModel('SemanticModel.modelData'); - const databaseModel = useModel('SemanticModel.databaseData'); - const { selectDomainId, domainList, setSelectDomain, setDomainList } = domainModel; - const { selectModelId } = modelModel; - const { MrefreshDatabaseList } = databaseModel; + + const { selectDomainId } = domainModel; const menuKey = params.menuKey ? params.menuKey : defaultTabKey; - const [collapsedState, setCollapsedState] = useState(true); + const [activeKey, setActiveKey] = useState(menuKey); - const [dataSetList, setDataSetList] = useState([]); - - // 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) => { - 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 ( { - cleanModelInfo(selectDomainId); - }} onMenuChange={(menuKey) => { setActiveKey(menuKey); pushUrlMenu(selectDomainId, menuKey); diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/Insights/Market.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/Insights/Market.tsx index bcb2df739..b2c931391 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/Insights/Market.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/Insights/Market.tsx @@ -155,7 +155,7 @@ const ClassMetricTable: React.FC = ({}) => { const columnsConfig = ColumnsConfig({ indicatorInfo: { - url: '/tag/detail/', + url: '/tag/detail/:indicatorId', starType: 'tag', }, }); diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/Metric/Edit.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/Metric/Edit.tsx index abcf8432d..e7bec7836 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/Metric/Edit.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/Metric/Edit.tsx @@ -1,7 +1,7 @@ import { message } from 'antd'; import React, { useState, useEffect } from 'react'; import { getMetricData } from '../service'; -import { useParams } from '@umijs/max'; +import { useParams, useModel } from '@umijs/max'; import styles from './style.less'; import { ISemantic } from '../data'; import MetricInfoEditSider from './MetricInfoEditSider'; @@ -14,7 +14,8 @@ const MetricDetail: React.FC = () => { const params: any = useParams(); const metricId = params.metricId; const [metircData, setMetircData] = useState(); - + const metricModel = useModel('SemanticModel.metricData'); + const { selectMetric, setSelectMetric } = metricModel; const [settingKey, setSettingKey] = useState(MetricSettingKey.BASIC); useEffect(() => { @@ -24,10 +25,17 @@ const MetricDetail: React.FC = () => { queryMetricData(metricId); }, [metricId]); + useEffect(() => { + return () => { + setSelectMetric(undefined); + }; + }, []); + const queryMetricData = async (metricId: string) => { const { code, data, msg } = await getMetricData(metricId); if (code === 200) { setMetircData({ ...data }); + setSelectMetric({ ...data }); return; } message.error(msg); diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/Metric/components/MetricInfoCreateForm.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/Metric/components/MetricInfoCreateForm.tsx index 2efcc3291..217b25e05 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/Metric/components/MetricInfoCreateForm.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/Metric/components/MetricInfoCreateForm.tsx @@ -905,7 +905,7 @@ const MetricInfoCreateForm: React.FC = ({ key="console" onClick={() => { history.replace( - `/model/manager/${domainId}/${modelId || metricItem?.modelId}/dataSource`, + `/model/domain/manager/${domainId}/${modelId || metricItem?.modelId}/dataSource`, ); onCancel?.(); }} diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/ModelManager.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/ModelManager.tsx index 9ec4abd73..1cf463814 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/ModelManager.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/ModelManager.tsx @@ -4,27 +4,18 @@ import ModelManagerTab from './components/ModelManagerTab'; type Props = {}; -const OverviewContainer: React.FC = ({}) => { +const ModelManager: React.FC = ({}) => { 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 { selectDomainId } = domainModel; + const { selectModelId, modelList } = modelModel; const { MrefreshDimensionList } = dimensionModel; const { MrefreshMetricList } = metricModel; - const { MrefreshDatabaseList } = databaseModel; const menuKey = params.menuKey ? params.menuKey : !Number(modelId) ? defaultTabKey : ''; const [activeKey, setActiveKey] = useState(menuKey); @@ -35,7 +26,7 @@ const OverviewContainer: React.FC = ({}) => { }; useEffect(() => { - if (!selectModelId) { + if (!selectModelId || `${selectModelId}` === `${modelId}`) { return; } initModelConfig(); @@ -44,22 +35,13 @@ const OverviewContainer: React.FC = ({}) => { }, [selectModelId]); const pushUrlMenu = (domainId: number, modelId: number, menuKey: string) => { - history.push(`/model/manager/${domainId}/${modelId}/${menuKey}`); - }; - - const cleanModelInfo = (domainId) => { - setActiveKey(defaultTabKey); - pushUrlMenu(domainId, 0, defaultTabKey); - setSelectModel(undefined); + history.push(`/model/domain/manager/${domainId}/${modelId}/${menuKey}`); }; return ( { - cleanModelInfo(selectDomainId); - }} onMenuChange={(menuKey) => { setActiveKey(menuKey); pushUrlMenu(selectDomainId, selectModelId, menuKey); @@ -68,4 +50,4 @@ const OverviewContainer: React.FC = ({}) => { ); }; -export default OverviewContainer; +export default ModelManager; diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/OverviewContainer.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/OverviewContainer.tsx new file mode 100644 index 000000000..e99c011ef --- /dev/null +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/OverviewContainer.tsx @@ -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 = ({}) => { + 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 ( +
+
+
+
+ { + const { id } = domainData; + cleanModelInfo(id); + setSelectDomain(domainData); + setModelTableHistoryParams({ + [id]: {}, + }); + }} + // onTreeDataUpdate={() => { + // // initProjectTree(); + // }} + /> +
+ +
{ + handleCollapsedBtn(); + }} + > + {collapsedState ? : } +
+
+
+ +
+
+
+ ); +}; + +export default OverviewContainer; diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/OverviewContainer1.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/OverviewContainer1.tsx deleted file mode 100644 index 63534cd48..000000000 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/OverviewContainer1.tsx +++ /dev/null @@ -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 = ({ 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(false); - const [collapsedState, setCollapsedState] = useState(true); - const [activeKey, setActiveKey] = useState(menuKey); - const [dataSetList, setDataSetList] = useState([]); - - 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 ( -
-
-
-
- { - const { id } = domainData; - cleanModelInfo(id); - setSelectDomain(domainData); - setModelTableHistoryParams({ - [id]: {}, - }); - }} - onTreeDataUpdate={() => { - initProjectTree(); - }} - /> -
- -
{ - handleCollapsedBtn(); - }} - > - {collapsedState ? : } -
-
-
- {selectDomainId ? ( - <> - - { - handleModelChange(model); - MrefreshModelList(selectDomainId); - }} - onBackDomainBtnClick={() => { - cleanModelInfo(selectDomainId); - }} - onMenuChange={(menuKey) => { - setActiveKey(menuKey); - pushUrlMenu(selectDomainId, selectModelId, menuKey); - }} - /> - - ) : ( -

请选择项目

- )} -
-
-
- ); -}; - -export default OverviewContainer; diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/OverviewContainerRight.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/OverviewContainerRight.tsx deleted file mode 100644 index c4d3430a6..000000000 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/OverviewContainerRight.tsx +++ /dev/null @@ -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 ( - <> - { - // onBackDomainBtnClick?.(); - setSelectModel(undefined); - history.push(`/model/${selectDomainId}/overview`); - }} - style={ - selectModelName ? { cursor: 'pointer' } : { color: '#296df3', fontWeight: 'bold' } - } - > - - {selectDomainName} - - ), - }, - { - type: 'separator', - separator: selectModelName ? '/' : '', - }, - { - title: selectModelName ? ( - { - history.push(`/model/manager/${selectDomainId}/${selectModelId}/`); - }} - style={{ color: '#296df3' }} - > - - {selectModelName} - - ) : undefined, - }, - ]} - /> - - - ); -}; - -export default OverviewContainerRight; diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/PageBreadcrumb.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/PageBreadcrumb.tsx new file mode 100644 index 000000000..8c3efdc37 --- /dev/null +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/PageBreadcrumb.tsx @@ -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: ( + { + setSelectModel(undefined); + history.push(`/model/domain/${selectDomainId}/overview`); + }} + > + + {selectDomainName} + + ), + }, + ]; + + if (selectModelName) { + items.push( + { + type: 'separator', + separator: '/', + }, + { + title: ( + { + setSelectMetric(undefined); + history.push(`/model/domain/manager/${selectDomainId}/${selectModelId}/`); + }} + > + + {selectModelName} + + ), + }, + ); + } + + if (selectMetric?.name) { + items.push( + { + type: 'separator', + separator: '/', + }, + { + title: selectMetric?.name ? ( + + + {selectMetric.name} + + ) : undefined, + }, + ); + } + return ( + <> + + + ); +}; + +export default PageBreadcrumb; diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/View/components/DataSetTable.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/View/components/DataSetTable.tsx index 2fea630fd..d75534090 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/View/components/DataSetTable.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/View/components/DataSetTable.tsx @@ -45,11 +45,10 @@ const DataSetTable: React.FC = ({ disabledEdit = false }) => { const [viewList, setViewList] = useState(); - // useEffect(() => { - // setViewList(dataSetList); - // }, [dataSetList]); - useEffect(() => { + if (!selectDomainId) { + return; + } queryDataSetList(); queryDomainAllModel(); }, [selectDomainId]); diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/ClassMetricTable.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/ClassMetricTable.tsx index 9e0958a2a..3a22ba7ec 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/ClassMetricTable.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/ClassMetricTable.tsx @@ -3,7 +3,7 @@ import { ProTable } from '@ant-design/pro-components'; import { message, Button, Space, Popconfirm, Input, Select, Tag } from 'antd'; import React, { useRef, useState, useEffect } from 'react'; 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 { queryMetric, @@ -32,7 +32,7 @@ const ClassMetricTable: React.FC = ({ onEmptyMetricData }) => { const metricModel = useModel('SemanticModel.metricData'); const { selectDomainId } = domainModel; const { selectModelId: modelId } = modelModel; - const { MrefreshMetricList } = metricModel; + const { MrefreshMetricList, selectMetric, setSelectMetric } = metricModel; const [batchSensitiveLevelOpenState, setBatchSensitiveLevelOpenState] = useState(false); const [createModalVisible, setCreateModalVisible] = useState(false); const [metricItem, setMetricItem] = useState(); @@ -144,7 +144,10 @@ const ClassMetricTable: React.FC = ({ onEmptyMetricData }) => { const columnsConfig = ColumnsConfig({ 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 = ({ onEmptyMetricData }) => { type="link" key="metricEditBtn" onClick={() => { - setMetricItem(record); - setCreateModalVisible(true); + history.push(`/model/metric/${record.domainId}/${record.modelId}/${record.id}`); + // setMetricItem(record); + // setCreateModalVisible(true); }} > 编辑 diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/DomainList.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/DomainList.tsx index d67bdfef4..59306b816 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/DomainList.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/DomainList.tsx @@ -1,14 +1,11 @@ -import { DownOutlined, PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'; -import { Input, message, Tree, Popconfirm, Tooltip, Row, Col, Button, Menu } from 'antd'; +import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'; +import { Input, message, Popconfirm, Tooltip, Row, Col, Button, Menu } from 'antd'; import type { DataNode } from 'antd/lib/tree'; import { useEffect, useState } from 'react'; -import type { FC, Key } from 'react'; +import type { FC } from 'react'; import { useModel } from '@umijs/max'; import { createDomain, updateDomain, deleteDomain } from '../service'; -import { treeParentKeyLists } from '../utils'; import DomainInfoForm from './DomainInfoForm'; -import { constructorClassTreeFromList, addPathInTreeData } from '../utils'; -import { AppstoreOutlined } from '@ant-design/icons'; import styles from './style.less'; import { ISemantic } from '../data'; @@ -42,20 +39,15 @@ const DomainListTree: FC = ({ onTreeSelected, onTreeDataUpdate, }) => { - const [projectTree, setProjectTree] = useState([]); const [projectInfoModalVisible, setProjectInfoModalVisible] = useState(false); const [domainInfoParams, setDomainInfoParams] = useState({}); const [filterValue, setFliterValue] = useState(''); - const [expandedKeys, setExpandedKeys] = useState([]); const [classList, setClassList] = useState([]); const domainModel = useModel('SemanticModel.domainData'); const { selectDomainId, domainList } = domainModel; useEffect(() => { - const treeData = addPathInTreeData(constructorClassTreeFromList(domainList)); - setProjectTree(treeData); setClassList(domainList); - setExpandedKeys(treeParentKeyLists(treeData)); }, [domainList]); const onSearch = (value: any) => { @@ -67,7 +59,7 @@ const DomainListTree: FC = ({ return; } const targetNodeData = classList.filter((item: any) => { - return item.id === selectedKeys; + return `${item.id}` === `${selectedKeys}`; })[0]; onTreeSelected?.(targetNodeData); }; @@ -84,20 +76,6 @@ const DomainListTree: FC = ({ } }; - // 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) => { if (values.modelType === 'add') { const { code, data } = await createDomain(values); @@ -126,21 +104,19 @@ const DomainListTree: FC = ({ const { id, name, path, hasEditPermission, parentId, hasModel } = node as any; const type = parentId === 0 ? 'top' : 'normal'; return ( -
- { - handleSelect(id); - }} - > - {name} - +
{ + // handleSelect(id); + // }} + > + {name} {createDomainBtnVisible && hasEditPermission && ( {Array.isArray(path) && path.length < 2 && !hasModel && ( { + onClick={(e) => { setDomainInfoParams({ modelType: 'add', type: 'normal', @@ -148,19 +124,21 @@ const DomainListTree: FC = ({ parentName: name, }); setProjectInfoModalVisible(true); + e.stopPropagation(); }} /> )} { + onClick={(e) => { setDomainInfoParams({ modelType: 'edit', type, ...node, }); setProjectInfoModalVisible(true); + e.stopPropagation(); }} /> = ({ okText="是" cancelText="否" > - + { + e.stopPropagation(); + }} + /> )} @@ -180,14 +163,14 @@ const DomainListTree: FC = ({ ); }; - const projectRenderTree = filterValue ? projectTreeFlat(projectTree, filterValue) : projectTree; - - const handleExpand = (_expandedKeys: Key[]) => { - setExpandedKeys(_expandedKeys as string[]); - }; - 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) => { return { key: domain.id, @@ -245,6 +228,12 @@ const DomainListTree: FC = ({ className={styles.search} placeholder="请输入名称搜索" onSearch={onSearch} + onChange={(e) => { + const value = e.target.value; + if (!value) { + setFliterValue(value); + } + }} /> {createDomainBtnVisible && ( @@ -265,25 +254,19 @@ const DomainListTree: FC = ({ )}
- - {/* } - defaultExpandAll={true} - treeData={projectRenderTree} - titleRender={titleRender} - /> */} + {selectDomainId && ( + { + handleSelect(info.key); + }} + /> + )} {projectInfoModalVisible && ( void; - onBackDomainBtnClick?: () => void; onMenuChange?: (menuKey: string) => void; }; -const DomainManagerTab: React.FC = ({ - activeKey, - // modelList, - dataSetList, - // handleModelChange, - onBackDomainBtnClick, - onMenuChange, -}) => { +const DomainManagerTab: React.FC = ({ activeKey, onMenuChange }) => { const initState = useRef(false); const defaultTabKey = 'metric'; const domainModel = useModel('SemanticModel.domainData'); const modelModel = useModel('SemanticModel.modelData'); - const { selectDomainId, selectDomainName, selectDomain: domainData } = domainModel; - const { selectModelId, modelList, selectModelName } = modelModel; + const { selectDomainId, selectDomain: domainData } = domainModel; + const { selectModelId, modelList } = modelModel; useEffect(() => { initState.current = false; diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/MetricInfoCreateForm.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/MetricInfoCreateForm.tsx index c8f069fc4..559989e46 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/MetricInfoCreateForm.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/MetricInfoCreateForm.tsx @@ -901,7 +901,7 @@ const MetricInfoCreateForm: React.FC = ({ key="console" onClick={() => { history.replace( - `/model/manager/${domainId}/${modelId || metricItem?.modelId}/dataSource`, + `/model/domain/manager/${domainId}/${modelId || metricItem?.modelId}/dataSource`, ); onCancel?.(); }} diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/ModelManagerTab.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/ModelManagerTab.tsx index dcd8749eb..be3d39d83 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/ModelManagerTab.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/ModelManagerTab.tsx @@ -18,28 +18,14 @@ import View from '../View'; type Props = { activeKey: string; modelList: ISemantic.IModelItem[]; - handleModelChange: (model?: ISemantic.IModelItem) => void; - onBackDomainBtnClick?: () => void; onMenuChange?: (menuKey: string) => void; }; -const ModelManagerTab: React.FC = ({ - activeKey, - modelList, - handleModelChange, - onBackDomainBtnClick, - onMenuChange, -}) => { +const ModelManagerTab: React.FC = ({ activeKey, onMenuChange }) => { const initState = useRef(false); const defaultTabKey = 'metric'; - const domainModel = useModel('SemanticModel.domainData'); const modelModel = useModel('SemanticModel.modelData'); - const { selectDomainId, selectDomainName, selectDomain: domainData } = domainModel; - const { selectModelId, selectModelName } = modelModel; - - useEffect(() => { - console.log(modelList, 'modelList'); - }, [modelList]); + const { selectModelId } = modelModel; useEffect(() => { initState.current = false; diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/ModelTable.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/ModelTable.tsx index ecd69002f..65df43670 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/ModelTable.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/ModelTable.tsx @@ -106,7 +106,7 @@ const ModelTable: React.FC = ({ modelList, disabledEdit = false, onModelC onClick={() => { setSelectModel(record); - history.push(`/model/manager/${domainId}/${id}`); + history.push(`/model/domain/manager/${domainId}/${id}`); // onModelChange?.(record); }} > diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/TableColumnRender.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/TableColumnRender.tsx index c24b816c3..0a06443cc 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/TableColumnRender.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/TableColumnRender.tsx @@ -6,32 +6,113 @@ import { history } from '@umijs/max'; import { ISemantic } from '../data'; import { isString } from 'lodash'; import dayjs from 'dayjs'; -import { isArrayOfValues } from '@/utils/utils'; +import { isArrayOfValues, replaceRouteParams } from '@/utils/utils'; import styles from './style.less'; import IndicatorStar, { StarType } from '../components/IndicatorStar'; +interface IndicatorInfo { + url?: string; + starType?: StarType; + onNameClick?: (record: ISemantic.IMetricItem) => void | boolean; +} + +interface ColumnsConfigParams { + indicatorInfo?: IndicatorInfo; +} + const { Text, Paragraph } = Typography; -export const ColumnsConfig: any = (params?: { - indicatorInfo?: { - url?: string; - starType?: StarType; - onNameClick?: (record: ISemantic.IMetricItem) => void; - }; -}) => { +export const ColumnsConfig = (params?: ColumnsConfigParams) => { + const renderAliasAndClassifications = ( + alias: string | undefined, + classifications: string[] | undefined, + ) => ( +
+ + {alias && ( + + +
别名:
+ + + {isString(alias) && + alias.split(',').map((aliasName: string) => ( + + + {aliasName} + + + ))} + + +
+ )} + + {isArrayOfValues(classifications) && ( + + +
分类:
+ + + {classifications.map((tag: string) => ( + + + {tag} + + + ))} + + +
+ )} +
+
+ ); + return { description: { - render: (_, record: ISemantic.IMetricItem) => { - const { description } = record; - return ( - - {description} - - ); - }, + render: (_, record: ISemantic.IMetricItem) => ( + + {record.description} + + ), }, dimensionInfo: { render: (_, record: ISemantic.IDimensionItem) => { @@ -46,70 +127,26 @@ export const ColumnsConfig: any = (params?: {
{bizName}
- - {alias && ( -
- - {alias && ( - - -
别名:
- - - {isString(alias) && - alias.split(',').map((aliasName: string) => { - return ( - - - {aliasName} - - - ); - })} - - -
- )} -
-
- )} + {renderAliasAndClassifications(alias, undefined)} ); }, }, indicatorInfo: { render: (_, record: ISemantic.IMetricItem) => { - const { name, alias, bizName, classifications, id, isCollect } = record; + const { name, alias, bizName, classifications, id, isCollect, domainId, modelId } = 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; - } + if (params?.indicatorInfo) { + url = replaceRouteParams(params.indicatorInfo.url || '', { + domainId: `${domainId}`, + modelId: `${modelId}`, + indicatorId: `${id}`, + }); + starType = params.indicatorInfo.starType || 'metric'; } + return ( <>
@@ -119,205 +156,71 @@ export const ColumnsConfig: any = (params?: { style={{ fontWeight: 500 }} onClick={(event: any) => { if (params?.indicatorInfo?.onNameClick) { - params?.indicatorInfo?.onNameClick(record); - } else { - history.push(`${url}${id}`); + const state = params.indicatorInfo.onNameClick(record); + if (state === false) { + return; + } } + history.push(url); event.preventDefault(); event.stopPropagation(); }} - // href={`/webapp${url}${id}`} > {name} - {/* - {SENSITIVE_LEVEL_ENUM[sensitiveLevel]} - */}
{bizName}
- - {(alias || isArrayOfValues(classifications)) && ( -
- - {alias && ( - - -
别名:
- - - {isString(alias) && - alias.split(',').map((aliasName: string) => { - return ( - - - {aliasName} - - - ); - })} - - -
- )} - - {isArrayOfValues(classifications) && ( - - -
分类:
- - - {classifications.map((tag: string) => { - return ( - - - {tag} - - - ); - })} - - -
- )} - {/* - - - : - {id} - - - - : - {createdBy} - - */} -
-
- )} + {renderAliasAndClassifications(alias, classifications)} ); }, }, sensitiveLevel: { - render: (_, record: ISemantic.IMetricItem) => { - const { sensitiveLevel } = record; - return SENSITIVE_LEVEL_COLOR[sensitiveLevel] ? ( - - {SENSITIVE_LEVEL_ENUM[sensitiveLevel]} - - ) : ( - - 未知 - - ); - }, + render: (_, record: ISemantic.IMetricItem) => ( + + {SENSITIVE_LEVEL_ENUM[record.sensitiveLevel] || '未知'} + + ), }, state: { render: (status) => { - let tagProps: { color: string; label: string; style?: any } = { + const tagProps = { color: 'default', label: '未知', style: {}, }; switch (status) { case StatusEnum.ONLINE: - tagProps = { - // color: 'processing', - color: 'geekblue', - label: '已启用', - }; + tagProps.color = 'geekblue'; + tagProps.label = '已启用'; break; case StatusEnum.OFFLINE: - tagProps = { - color: 'default', - label: '未启用', - style: { - color: 'rgb(95, 116, 141)', - fontWeight: 400, - }, - }; + tagProps.color = 'default'; + tagProps.label = '未启用'; + tagProps.style = { color: 'rgb(95, 116, 141)', fontWeight: 400 }; break; case StatusEnum.INITIALIZED: - tagProps = { - color: 'processing', - label: '初始化', - }; + tagProps.color = 'processing'; + tagProps.label = '初始化'; break; case StatusEnum.DELETED: - tagProps = { - color: 'default', - label: '已删除', - }; + tagProps.color = 'default'; + tagProps.label = '已删除'; break; case StatusEnum.UNAVAILABLE: - tagProps = { - color: 'default', - label: '不可用', - }; + tagProps.color = 'default'; + tagProps.label = '不可用'; break; default: break; @@ -344,14 +247,12 @@ export const ColumnsConfig: any = (params?: { tooltip: '创建人/更新时间', width: 180, search: false, - render: (value: any, record: ISemantic.IMetricItem) => { - return ( - - {record.createdBy} - {value && value !== '-' ? dayjs(value).format('YYYY-MM-DD HH:mm:ss') : '-'} - - ); - }, + render: (value: any, record: ISemantic.IMetricItem) => ( + + {record.createdBy} + {value && value !== '-' ? dayjs(value).format('YYYY-MM-DD HH:mm:ss') : '-'} + + ), }, }; }; diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/style.less b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/style.less index 96527bfae..e5e32db88 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/style.less +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/components/style.less @@ -6,6 +6,7 @@ .projectManger { + border-top: 1px solid #eee; width: 100%; min-height: calc(100vh - 56px); background-color: #fff; @@ -163,8 +164,8 @@ // } // } .tab { - border-top: 1px solid #eee; - margin-top: 10px; + + // margin-top: 10px; :global { .ant-tabs-tab-btn { font-size: 16px; @@ -338,12 +339,14 @@ .breadcrumb{ font-size: 18px; - margin: 17px 0 0 20px; - padding-bottom: 3px; + height: 48px; + line-height: 48px; + padding: 0 20px; :global { .ant-breadcrumb-link { height: 28px; color: #709bf1; + cursor: pointer; &:hover{ color: #296df3; } @@ -351,6 +354,14 @@ .anticon { font-size: 18px; } + li { + &:last-child { + .ant-breadcrumb-link { + color: #296df3; + } + + } + } } } diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/index.tsx b/webapp/packages/supersonic-fe/src/pages/SemanticModel/index.tsx index 7120a1482..0390e30ae 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/index.tsx +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/index.tsx @@ -1,44 +1,28 @@ import { message } from 'antd'; 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 styles from './components/style.less'; import { LeftOutlined, RightOutlined } from '@ant-design/icons'; import { ISemantic } from './data'; -import { getDomainList, getDataSetList } from './service'; -import { isArrayOfValues } from '@/utils/utils'; -import OverviewContainerRight from './OverviewContainerRight'; +import { getDomainList, getDataSetList, getModelDetail } from './service'; +import PageBreadcrumb from './PageBreadcrumb'; -type Props = { - mode: 'domain'; -}; +type Props = {}; -const OverviewContainer: React.FC = ({ mode = 'domain' }) => { - const defaultTabKey = 'overview'; +const SemanticModel: React.FC = ({}) => { 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 metricModel = useModel('SemanticModel.metricData'); + const { setSelectDomain, setDomainList, selectDomainId } = domainModel; + const { selectModel, setSelectModel, setModelTableHistoryParams, MrefreshModelList } = modelModel; const { MrefreshDatabaseList } = databaseModel; - const menuKey = params.menuKey ? params.menuKey : !Number(modelId) ? defaultTabKey : ''; - const [collapsedState, setCollapsedState] = useState(true); - const [activeKey, setActiveKey] = useState(menuKey); - // const [dataSetList, setDataSetList] = useState([]); + const { selectMetric, setSelectMetric } = metricModel; const initSelectedDomain = (domainList: ISemantic.IDomainItem[]) => { const targetNode = domainList.filter((item: any) => { @@ -51,8 +35,7 @@ const OverviewContainer: React.FC = ({ mode = 'domain' }) => { if (firstRootNode) { const { id } = firstRootNode; setSelectDomain(firstRootNode); - setActiveKey(menuKey); - pushUrlMenu(id, 0, menuKey); + // pushUrlMenu(id, menuKey); } } else { setSelectDomain(targetNode); @@ -69,121 +52,38 @@ const OverviewContainer: React.FC = ({ mode = 'domain' }) => { } }; + const initModelData = async () => { + const { code, data, msg } = await getModelDetail({ modelId }); + if (code === 200) { + setSelectModel(data); + } else { + message.error(msg); + } + }; + useEffect(() => { initProjectTree(); MrefreshDatabaseList(); + if (modelId && modelId !== selectModel) { + initModelData(); + } + return () => { 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 ( -
-
-
-
- { - const { id } = domainData; - cleanModelInfo(id); - setSelectDomain(domainData); - setModelTableHistoryParams({ - [id]: {}, - }); - }} - onTreeDataUpdate={() => { - initProjectTree(); - }} - /> -
- -
{ - handleCollapsedBtn(); - }} - > - {collapsedState ? : } -
-
-
- {selectDomainId ? ( - <> - - - ) : ( -

请选择项目

- )} -
+
+
+ +
+
+ + {/* */}
); }; -export default OverviewContainer; +export default SemanticModel; diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/models/metricData.ts b/webapp/packages/supersonic-fe/src/pages/SemanticModel/models/metricData.ts index caab8b12e..29123730c 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/models/metricData.ts +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/models/metricData.ts @@ -5,6 +5,7 @@ import { queryMetric } from '../service'; export default function Metric() { const [metricList, setMetricList] = useState([]); + const [selectMetric, setSelectMetric] = useState(); const queryMetricList = async (params: any) => { const { code, data, msg } = await queryMetric({ @@ -25,6 +26,8 @@ export default function Metric() { return { MmetricList: metricList, + setSelectMetric: setSelectMetric, + selectMetric: selectMetric, MrefreshMetricList: refreshMetricList, MqueryMetricList: queryMetricList, }; diff --git a/webapp/packages/supersonic-fe/src/pages/SemanticModel/service.ts b/webapp/packages/supersonic-fe/src/pages/SemanticModel/service.ts index 230ce74dc..c36de3f6c 100644 --- a/webapp/packages/supersonic-fe/src/pages/SemanticModel/service.ts +++ b/webapp/packages/supersonic-fe/src/pages/SemanticModel/service.ts @@ -453,7 +453,7 @@ export function getUnAvailableItem(data: any): Promise { export function getModelDetail(data: any): Promise { if (!data.modelId) { - return; + return {}; } return request.get(`${process.env.API_BASE_URL}model/getModel/${data.modelId}`); } diff --git a/webapp/packages/supersonic-fe/src/utils/utils.ts b/webapp/packages/supersonic-fe/src/utils/utils.ts index bf48da88f..e327acc85 100644 --- a/webapp/packages/supersonic-fe/src/utils/utils.ts +++ b/webapp/packages/supersonic-fe/src/utils/utils.ts @@ -502,3 +502,10 @@ export function decryptPassword(encryptPassword: string) { export function uniqueArray(arr: any[]) { return Array.from(new Set(arr)); } + +// 替换以:开头标记的变量 +export const replaceRouteParams = (template: string, values: Record): string => { + return template.replace(/:([a-zA-Z0-9_]+)/g, (match, key) => { + return values[key] !== undefined ? values[key] : match; + }); +};