{
- const { graphNodeId, status, codeName, nodeDef = {}, ...options } = n;
+ const {
+ graphNodeId,
+ status,
+ codeName,
+ nodeDef = {},
+ parties = [],
+ ...options
+ } = n;
// 强行断言:后端没有定义 UNFINISHED 状态
let graphNodeStatus = nodeStatus[status || 'STAGING'] as unknown as NodeStatus;
if (graphNodeStatus === NodeStatus.default) {
@@ -57,14 +63,16 @@ export class GraphSubmitRequestService extends GraphRequestService {
* 初始化可以点击提交的算子
* 1. 成功的模型训练并且有输入边
* 2. 成功的模型预测并且有输入边并且上游还有线性模型参数修改算子
+ * 3. 成功的模型预测并且有输入边并且下游还有后处理算子
* 注意:目前模型提交逻辑,能提交 模型训练算子和 模型预测算子
* 提交模型训练算子,自动勾选上游预处理组件
- * 提交模型预测算子,自动勾选上游的线性模型参数修改算子,以及模型训练算子上游的预处理组件算子
- * 目前暂无 模型预测后面连接的后处理算子
+ * 提交模型预测算子,自动勾选上游的线性模型参数修改算子,以及模型训练算子上游的预处理组件算子, 和模型预测算子下游的后处理算子
+ * 目前(评分卡转换) 属于模型预测后面连接的后处理算子
* */
styles: {
isOpaque: !nodeCanOpaque(n, nodes),
isHighlighted: false,
+ nodeParties: parties,
},
nodeDef,
};
@@ -98,7 +106,7 @@ const getProjectId = () => {
};
const nodeCanOpaque = (node: API.GraphNodeDetail, nodes: API.GraphNode[]) => {
- const { inputs = [], nodeDef = {}, status } = node;
+ const { inputs = [], outputs = [], nodeDef = {}, status } = node;
const { domain } = nodeDef;
if (status !== 'SUCCEED' || inputs.length === 0) return false;
@@ -117,6 +125,17 @@ const nodeCanOpaque = (node: API.GraphNodeDetail, nodes: API.GraphNode[]) => {
) {
return true;
}
+
+ // 判断下游有没有后处理算子
+ const outputSlot = outputs[0];
+ const postNode = nodes.find((item: API.GraphNodeDetail) =>
+ (item?.inputs || []).includes(outputSlot),
+ ) as API.GraphNodeDetail;
+ if (!postNode) return false;
+ const { status: postNodeStatus, nodeDef: postNodeNodeDef } = postNode;
+ if (postNodeStatus === 'SUCCEED' && postNodeNodeDef?.domain === 'postprocessing') {
+ return true;
+ }
return false;
}
return domain === 'ml.train';
diff --git a/apps/platform/src/modules/dag-submit/graph-service.ts b/apps/platform/src/modules/dag-submit/graph-service.ts
index 03f05cf..62ce0bb 100644
--- a/apps/platform/src/modules/dag-submit/graph-service.ts
+++ b/apps/platform/src/modules/dag-submit/graph-service.ts
@@ -64,11 +64,12 @@ export class SubmitGraphService extends Model implements GraphEventHandlerProtoc
const graph = mainDag.graphManager.getGraphInstance();
if (!graph) return;
const { styles = {} } = data;
- const { isOpaque = false } = styles;
+ const { isOpaque = false, nodeParties = [] } = styles;
if (isOpaque !== true) {
this.modalManager.openModal(dagLogDrawer.id, {
nodeData: data,
from: 'pipeline',
+ nodeParties,
});
this.autoSelectModel(node);
this.resetSelectionEdge();
@@ -94,11 +95,11 @@ export class SubmitGraphService extends Model implements GraphEventHandlerProtoc
this.onCenterNode(node.getData().id);
const sameBrachNodes = getModelSameBranchNodes(node);
if (sameBrachNodes) {
- // 需要打包训练算子,不需要打包预测算子
+ // 需要打包训练算子,不需要打包预测算子, 也不需要打包后处理算子
const newSameBrachNodes = {
modelNode: sameBrachNodes?.modelNode,
preNodes: sameBrachNodes?.preNodes,
- nextNodes: sameBrachNodes?.nextNodes,
+ // nextNodes: sameBrachNodes?.nextNodes,
};
updateGraphNodesStyles(Object.values(newSameBrachNodes).flat(), {
isOpaque: false,
@@ -106,7 +107,7 @@ export class SubmitGraphService extends Model implements GraphEventHandlerProtoc
this.selectNodeIdsObj = {
modelNodeIds: sameBrachNodes.modelNode.map((item) => item.id),
preNodesIds: sameBrachNodes.preNodes.map((item) => item.id),
- nextNodesIds: sameBrachNodes.nextNodes.map((item) => item.id),
+ nextNodesIds: [],
predictNodesIds: [],
};
highlightSelectionByIds(this.getSelectIds());
diff --git a/apps/platform/src/modules/dag-submit/util.ts b/apps/platform/src/modules/dag-submit/util.ts
index 7af1caf..cbdf806 100644
--- a/apps/platform/src/modules/dag-submit/util.ts
+++ b/apps/platform/src/modules/dag-submit/util.ts
@@ -74,7 +74,10 @@ export const highlightSelectionByIds = (ids: string[]) => {
/**
* 重置画布展示样式
- * 只有成功的模型训练算子以及(模型预测算子并且上游有线性模型参数修改算子)才可点击
+ * 可点击的高亮算子
+ * 1. 成功的模型训练算子
+ * 2. 成功的模型预测算子并且上游有线性模型参数修改算子
+ * 3. 成功的模型预测算子并且下游有成功的后处理算子
* */
export const resetGraphStyles = () => {
const graph = mainDag.graphManager.getGraphInstance();
@@ -96,6 +99,7 @@ export const resetGraphStyles = () => {
/**
* 成功的模型训练算子高亮
* 成功的模型预测算子并且上游有线性模型参数修改算子高亮
+ * 成功的模型预测算子并且下游有后处理算子高亮
*/
export const nodeCanOpaque = (node: Node) => {
const graph = mainDag.graphManager.getGraphInstance();
@@ -113,7 +117,11 @@ export const nodeCanOpaque = (node: Node) => {
item.getData().nodeDef?.name === 'model_param_modifications' &&
item.getData().status === 0,
);
- return !!modelParamsModificationNode;
+
+ // 获取后处理算子
+ const postNodesResult = getPostNodes(node);
+
+ return !!modelParamsModificationNode || postNodesResult.length !== 0;
}
return domain === 'ml.train';
};
diff --git a/apps/platform/src/modules/data-manager/data-manager.service.ts b/apps/platform/src/modules/data-manager/data-manager.service.ts
index 766d1c2..2054ea2 100644
--- a/apps/platform/src/modules/data-manager/data-manager.service.ts
+++ b/apps/platform/src/modules/data-manager/data-manager.service.ts
@@ -31,4 +31,12 @@ export enum UploadStatus {
export enum DataSheetType {
'CSV' = 'CSV',
'HTTP' = 'HTTP',
+ 'OSS' = 'OSS',
+}
+
+export enum DataSourceType {
+ OSS = 'OSS',
+ HTTP = 'HTTP',
+ ODPS = 'ODPS',
+ LOCAL = 'LOCAL',
}
diff --git a/apps/platform/src/modules/data-manager/data-manager.view.tsx b/apps/platform/src/modules/data-manager/data-manager.view.tsx
index b1cad9b..6c6aab7 100644
--- a/apps/platform/src/modules/data-manager/data-manager.view.tsx
+++ b/apps/platform/src/modules/data-manager/data-manager.view.tsx
@@ -1,11 +1,6 @@
-import {
- SearchOutlined,
- InfoCircleOutlined,
- DownOutlined,
- ReloadOutlined,
-} from '@ant-design/icons';
-import type { MenuProps, RadioChangeEvent, TourProps } from 'antd';
-import { Dropdown, message, Tag } from 'antd';
+import { SearchOutlined, InfoCircleOutlined, ReloadOutlined } from '@ant-design/icons';
+import type { RadioChangeEvent, TourProps } from 'antd';
+import { message, Tag } from 'antd';
import {
Button,
Radio,
@@ -28,8 +23,7 @@ import React, { useEffect, useRef } from 'react';
import { confirmDelete } from '@/components/comfirm-delete';
import { EdgeAuthWrapper } from '@/components/edge-wrapper-auth';
import { Platform, hasAccess } from '@/components/platform-wrapper';
-import { HttpDataAddDrawer } from '@/modules/data-table-add/add-http-data/http-data-add.view';
-import { DataTableAddContent } from '@/modules/data-table-add/data-table-add.view';
+import { DataAddDrawer } from '@/modules/data-table-add/add-data/add-data.view';
import { DatatableInfoService } from '@/modules/data-table-info/component/data-table-auth/data-table-auth.service';
import { DataTableAuth } from '@/modules/data-table-info/data-table-auth-drawer';
import { DataTableInfoDrawer } from '@/modules/data-table-info/data-table-info.view';
@@ -49,7 +43,7 @@ import { LoginService } from '../login/login.service';
import {
DataManagerService,
- DataSheetType,
+ DataSourceType,
UploadStatus,
} from './data-manager.service';
import styles from './index.less';
@@ -87,13 +81,14 @@ export const DataManagerComponent: React.FC = () => {
),
},
{
- title: '表类型',
- dataIndex: 'type',
- key: 'type',
+ title: '数据源类型',
+ dataIndex: 'datasourceType',
+ key: 'datasourceType',
width: '10%',
filters: [
- { text: 'CSV', value: DataSheetType.CSV },
- { text: 'HTTP', value: DataSheetType.HTTP },
+ { text: 'OSS', value: DataSourceType.OSS },
+ { text: 'HTTP', value: DataSourceType.HTTP },
+ { text: 'LOCAL', value: DataSourceType.LOCAL },
],
},
{
@@ -138,7 +133,14 @@ export const DataManagerComponent: React.FC = () => {
},
},
{
- title: '状态',
+ title: (
+
+ 状态
+
+
+
+
+ ),
dataIndex: 'status',
key: 'status',
width: '14%',
@@ -176,7 +178,11 @@ export const DataManagerComponent: React.FC = () => {
dataIndex: 'pushToTeeStatus',
width: '15%',
render: (status: string, record: API.DatatableVO) => {
- if (record.type === DataSheetType.HTTP) return '-';
+ if (
+ record.datasourceType === DataSourceType.HTTP ||
+ record.datasourceType === DataSourceType.OSS
+ )
+ return '-';
if (!status || status === '') {
return (
+
+
+ );
+};
diff --git a/apps/platform/src/modules/data-source-list/components/data-source-info/index.less b/apps/platform/src/modules/data-source-list/components/data-source-info/index.less
new file mode 100644
index 0000000..61aa358
--- /dev/null
+++ b/apps/platform/src/modules/data-source-list/components/data-source-info/index.less
@@ -0,0 +1,35 @@
+.dataSourceInfoDrawer {
+ :global {
+ .ant-descriptions .ant-descriptions-item-container {
+ align-items: center;
+ }
+ }
+
+ .nodeTitle {
+ color: #000000e0;
+ font-size: 14px;
+ line-height: 22px;
+ }
+
+ .nodeContent {
+ display: flex;
+ align-items: center;
+ padding: 12px;
+ border-radius: 2px;
+ margin-top: 8px;
+ background: #00000005;
+
+ .nodeNumber {
+ margin-right: 3px;
+ color: #00000073;
+ font-size: 14px;
+ line-height: 20px;
+ }
+
+ .nodeName {
+ color: #000000d9;
+ font-size: 14px;
+ line-height: 20px;
+ }
+ }
+}
diff --git a/apps/platform/src/modules/data-source-list/components/data-source-info/index.tsx b/apps/platform/src/modules/data-source-list/components/data-source-info/index.tsx
new file mode 100644
index 0000000..f57feef
--- /dev/null
+++ b/apps/platform/src/modules/data-source-list/components/data-source-info/index.tsx
@@ -0,0 +1,138 @@
+import { CloseOutlined } from '@ant-design/icons';
+import { Descriptions, Drawer, Spin } from 'antd';
+import { parse } from 'query-string';
+import React from 'react';
+import { useLocation } from 'umi';
+
+import { EllipsisMiddle } from '@/components/text-ellipsis.tsx';
+import {
+ DataSourceService,
+ DataSourceType,
+} from '@/modules/data-source-list/data-source-list.service';
+import { useModel } from '@/util/valtio-helper';
+
+import styles from './index.less';
+import { HttpQueryExample } from '@/modules/data-table-add/component/httpQueryExample';
+
+const DataSourceOSSTypeInfo = (props: { data: API.DatasourceDetailVO }) => {
+ const { data } = props;
+
+ return (
+
+ );
+};
+
+const DataSourceHTTPTypeInfo = (props: { data: API.DatasourceDetailVO }) => {
+ const { data } = props;
+
+ return (
+
+ );
+};
+
+const DataSourceODPSTypeInfo = (props: { data: API.DatasourceDetailVO }) => {
+ const { data } = props;
+
+ return (
+
+ );
+};
+
+const DataSourceInfoRender = (props: { item: API.DatasourceDetailVO }) => {
+ const { item } = props;
+ if (!item.type) return <>{'--'}>;
+ const ContentMap = React.useMemo(
+ () => ({
+ [DataSourceType.OSS]:
,
+ }),
+ [item],
+ );
+ return ContentMap[item.type as DataSourceType];
+};
+
+export const DataSourceInfoDrawer: React.FC<{
+ onClose: () => void;
+ visible: boolean;
+ data: API.DatasourceListInfo;
+}> = ({ visible, onClose, data }) => {
+ const service = useModel(DataSourceService);
+ const { search } = useLocation();
+ const { nodeId } = parse(search);
+
+ React.useEffect(() => {
+ if (!visible) {
+ return;
+ }
+ service.getDataSourceDetail({
+ nodeId: nodeId as string,
+ datasourceId: data.datasourceId,
+ type: data.type,
+ });
+ }, [visible]);
+
+ return (
+