Sfoglia il codice sorgente

Merge branch 'dev' of http://gogsb.soaringnova.com/chenguilong/aihub-web into dev

leo 2 anni fa
parent
commit
6fc4cfc66f

+ 192 - 175
src/module/homePage/ApplicationManagePage.jsx

@@ -1,175 +1,192 @@
-import React from 'react';
-import { PropTypes } from 'prop-types';
-import { Modal, message } from 'antd';
-import DevelopmentProgress from './components/developmentProgress/DevelopmentProgress';
-import ApplicationClass from './components/applicationClass/ApplicationClass';
-import { getCurrentContext } from 'utils/authPermit';
-import styled from 'styled-components';
-import { ModalView } from 'components';
-import projectApi from 'redux/services/sysManager/projectManage';
-import ApplyInfoPage from 'module/sysManage/projectManager/editPage/component/ApplyInfoPage';
-
-const PageWrapper = styled.div`
-  background: #f0f2f5;
-`;
-
-class ApplicationManagePage extends React.Component {
-  constructor(props) {
-    super(props);
-    let { role, id } = getCurrentContext();
-    if (this.props.projectId) {
-      this.projectId = this.props.projectId;
-    } else if (role === 'PROJECT') {
-      this.projectId = id;
-    }
-    this.classTypeId = '';
-    this.state = {
-      currentClassTypeId: '',
-      refresh: false,
-    };
-  }
-
-  componentDidMount() {}
-
-  openVisible = () => {
-    this.setState({
-      modalVisible: true,
-      viewType: 'create',
-    });
-  };
-
-  callVisible = () => {
-    this.setState({
-      modalVisible: false,
-    });
-  };
-
-  submitModalOk = data => {
-    this.setState({
-      submitLoading: true,
-      refresh: false,
-    });
-    projectApi
-      .editApplication(data, { projectId: this.projectId }, this.state.viewType)
-      .then(() => {
-        message.success('保存成功!');
-        this.setState({
-          submitLoading: false,
-          modalVisible: false,
-          refresh: true,
-        });
-      })
-      .catch(error => {
-        this.setState({
-          submitLoading: false,
-        });
-        message.error(error.message);
-      });
-  };
-
-  handelApplicationDelete = projectApplicationId => {
-    let _this = this;
-    this.setState({
-      refresh: false,
-    });
-    Modal.confirm({
-      title: '提示信息',
-      content: `确定删除此应用?`,
-      okText: '确认',
-      cancelText: '取消',
-      okType: 'danger',
-      onOk: () =>
-        new Promise((resolve, reject) => {
-          projectApi
-            .deleteApplication(projectApplicationId, this.projectId)
-            .then(() => {
-              message.success('删除成功');
-              _this.setState({
-                refresh: true,
-              });
-              resolve();
-            })
-            .catch(error => {
-              reject();
-              message.error(error.message);
-            });
-        }),
-    });
-  };
-
-  handleApplicationEdit = projectApplicationId => {
-    this.setState({
-      modalVisible: true,
-      viewType: 'edit',
-    });
-    this.projectApplicationId = projectApplicationId;
-  };
-
-  onClassTypeAdd = ({ viewType, classTypeId, parentClassTypeId }) => {
-    this.setState({
-      modalVisible: true,
-      viewType: viewType,
-    });
-    this.classTypeId = classTypeId;
-    this.parentClassTypeId = parentClassTypeId;
-  };
-
-  handleClassTypeChange = applicationTypeId => {
-    this.setState({ currentClassTypeId: applicationTypeId });
-  };
-
-  render() {
-    return (
-      <PageWrapper>
-        <ModalView
-          modalTitle={this.state.viewType === 'edit' ? '应用修改' : '应用新建'}
-          onCancelType={false}
-          confirmLoading={this.state.submitLoading}
-          width={1000}
-          callVisible={this.callVisible}
-          modalVisible={this.state.modalVisible}
-          okText="保 存"
-          submitModalOk={() => {
-            this.applyInfoPage.savaOrSubmit();
-          }}
-          comp={
-            <ApplyInfoPage
-              viewType={this.state.viewType}
-              onRef={ref => {
-                this.applyInfoPage = ref;
-              }}
-              classTypeId={this.classTypeId}
-              parentClassTypeId={this.parentClassTypeId}
-              projectInfo={{ projectId: this.projectId }}
-              projectApplicationId={this.projectApplicationId}
-              submitModalOk={this.submitModalOk}
-            />
-          }
-        />
-        <section>
-          <ApplicationClass
-            projectId={this.projectId}
-            refresh={this.state.refresh}
-            onClassTypeChange={this.handleClassTypeChange}
-            onClassTypeAdd={this.onClassTypeAdd}
-          />
-        </section>
-        <section style={{ marginTop: 20 }}>
-          <DevelopmentProgress
-            refresh={this.state.refresh}
-            classTypeId={this.state.currentClassTypeId}
-            projectId={this.projectId}
-            onApplicationEdit={this.handleApplicationEdit}
-            onApplicationDelete={this.handelApplicationDelete}
-          />
-        </section>
-      </PageWrapper>
-    );
-  }
-}
-
-ApplicationManagePage.propTypes = {
-  projectId: PropTypes.array,
-};
-
-export default ApplicationManagePage;
+import React from 'react';
+import { PropTypes } from 'prop-types';
+import { Modal, message } from 'antd';
+import DevelopmentProgress from './components/developmentProgress/DevelopmentProgress';
+import ApplicationClass from './components/applicationClass/ApplicationClass';
+import { getCurrentContext } from 'utils/authPermit';
+import styled from 'styled-components';
+import { ModalView } from 'components';
+import projectApi from 'redux/services/sysManager/projectManage';
+import ApplyInfoPage from 'module/sysManage/projectManager/editPage/component/ApplyInfoPage';
+
+const PageWrapper = styled.div`
+  background: #f0f2f5;
+`;
+
+class ApplicationManagePage extends React.Component {
+  constructor(props) {
+    super(props);
+    let { role, id } = getCurrentContext();
+    if (this.props.projectId) {
+      this.projectId = this.props.projectId;
+    } else if (role === 'PROJECT') {
+      this.projectId = id;
+    }
+    this.classTypeId = '';
+    this.state = {
+      currentClassTypeId: '',
+      refresh: false,
+    };
+  }
+
+  componentDidMount() {}
+
+  openVisible = () => {
+    this.setState({
+      modalVisible: true,
+      viewType: 'create',
+    });
+  };
+
+  callVisible = () => {
+    this.setState({
+      modalVisible: false,
+    });
+  };
+
+  submitModalOk = data => {
+    this.setState({
+      submitLoading: true,
+      refresh: false,
+    });
+    projectApi
+      .editApplication(data, { projectId: this.projectId }, this.state.viewType)
+      .then(() => {
+        message.success('保存成功!');
+        this.setState({
+          submitLoading: false,
+          modalVisible: false,
+          refresh: true,
+        });
+      })
+      .catch(error => {
+        this.setState({
+          submitLoading: false,
+        });
+        message.error(error.message);
+      });
+  };
+
+  handelApplicationDelete = projectApplicationId => {
+    let _this = this;
+    this.setState({
+      refresh: false,
+    });
+    Modal.confirm({
+      title: '提示信息',
+      content: `确定删除此应用?`,
+      okText: '确认',
+      cancelText: '取消',
+      okType: 'danger',
+      onOk: () =>
+        new Promise((resolve, reject) => {
+          // projectApi
+          //   .deleteApplication(projectApplicationId, this.projectId)
+          //   .then(() => {
+          //     message.success('删除成功');
+          //     _this.setState({
+          //       refresh: true,
+          //     });
+          //     resolve();
+          //   })
+          //   .catch(error => {
+          //     reject();
+          //     message.error(error.message);
+          //   });
+          projectApi
+            .deleteApplication2(projectApplicationId, this.projectId)
+            .then(res => {
+              if (res.code == '000000') {
+                message.success(res.message || '删除成功');
+                _this.setState({
+                  refresh: true,
+                });
+              } else {
+                message.error(res.message || error.message);
+              }
+              resolve();
+            })
+            .catch(error => {
+              reject();
+              message.error(error.message);
+            });
+        }),
+    });
+  };
+
+  handleApplicationEdit = projectApplicationId => {
+    this.setState({
+      modalVisible: true,
+      viewType: 'edit',
+    });
+    this.projectApplicationId = projectApplicationId;
+  };
+
+  onClassTypeAdd = ({ viewType, classTypeId, parentClassTypeId }) => {
+    this.setState({
+      modalVisible: true,
+      viewType: viewType,
+    });
+    this.classTypeId = classTypeId;
+    this.parentClassTypeId = parentClassTypeId;
+  };
+
+  handleClassTypeChange = applicationTypeId => {
+    this.setState({ currentClassTypeId: applicationTypeId });
+  };
+
+  render() {
+    return (
+      <PageWrapper>
+        <ModalView
+          modalTitle={this.state.viewType === 'edit' ? '应用修改' : '应用新建'}
+          onCancelType={false}
+          confirmLoading={this.state.submitLoading}
+          width={1000}
+          callVisible={this.callVisible}
+          modalVisible={this.state.modalVisible}
+          okText="保 存"
+          submitModalOk={() => {
+            this.applyInfoPage.savaOrSubmit();
+          }}
+          comp={
+            <ApplyInfoPage
+              viewType={this.state.viewType}
+              onRef={ref => {
+                this.applyInfoPage = ref;
+              }}
+              classTypeId={this.classTypeId}
+              parentClassTypeId={this.parentClassTypeId}
+              projectInfo={{ projectId: this.projectId }}
+              projectApplicationId={this.projectApplicationId}
+              submitModalOk={this.submitModalOk}
+            />
+          }
+        />
+        <section>
+          <ApplicationClass
+            projectId={this.projectId}
+            refresh={this.state.refresh}
+            onClassTypeChange={this.handleClassTypeChange}
+            onClassTypeAdd={this.onClassTypeAdd}
+          />
+        </section>
+        <section style={{ marginTop: 20 }}>
+          <DevelopmentProgress
+            refresh={this.state.refresh}
+            classTypeId={this.state.currentClassTypeId}
+            projectId={this.projectId}
+            onApplicationEdit={this.handleApplicationEdit}
+            onApplicationDelete={this.handelApplicationDelete}
+          />
+        </section>
+      </PageWrapper>
+    );
+  }
+}
+
+ApplicationManagePage.propTypes = {
+  projectId: PropTypes.array,
+};
+
+export default ApplicationManagePage;

+ 351 - 352
src/module/homePage/components/developmentProgress/TableRow.jsx

@@ -1,352 +1,351 @@
-/** 流水线横向 Item */
-import React from 'react';
-import _ from 'lodash';
-import { DeleteOutlined, FormOutlined } from '@ant-design/icons';
-import { Form } from '@ant-design/compatible';
-import '@ant-design/compatible/assets/index.css';
-import { Row, Col, Tooltip } from 'antd';
-import { Link } from 'react-router-dom';
-import styled from 'styled-components';
-import { PropTypes } from 'prop-types';
-import RowItem from './RowItem';
-import RowStep from './step/HorizontalStep';
-import { hasText } from 'components/auth/textAuth';
-import { notebookViewUrl } from 'routes/routeHelper';
-
-const FormItem = Form.Item;
-
-const PageWrapper = styled.div`
-  margin-top: 20px;
-  width: 100%;
-  border: 1px solid rgba(151, 151, 151, 0.18);
-  border-radius: 2px;
-  display: flex;
-  flex-direction: column;
-  padding: 16px 20px;
-  .row__title-wrapper {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    width: 100%;
-  }
-  .row-left {
-    align-items: center;
-    display: flex;
-    color: #303133;
-    font-size: 14px;
-    font-weight: 600;
-  }
-  .row-right {
-    display: flex;
-    justify-content: center;
-    align-items: center;
-  }
-  .row__application-info {
-    margin-top: 16px;
-    width: 100%;
-    padding: 8px 24px;
-    background: #f7f8fa;
-    .ant-legacy-form-item-control-wrapper {
-      width: calc(100% - 65px);
-    }
-    .ant-legacy-form-item-children {
-      overflow: hidden;
-      text-overflow: ellipsis;
-      width: 100%;
-      display: block;
-      white-space: nowrap;
-    }
-  }
-  .row__step-wrapper {
-    width: 100%;
-    height: 32px;
-    margin: 16px 0 0;
-  }
-  .row__item-step {
-    width: 40%;
-    &:last-child {
-      width: 20%;
-    }
-  }
-  .ant-legacy-form-item {
-    width: 100%;
-  }
-  .ant-legacy-form-inline .ant-legacy-form-item {
-    display: flex;
-  }
-  .row__item-wrapper {
-    display: flex;
-    width: 100%;
-  }
-  .step__no-data {
-    .ant-steps-item-icon {
-      background: #eee;
-    }
-  }
-`;
-
-const TableRow = ({ item, onApplicationEdit, onApplicationDelete, onBindDataSet, projectId }) => {
-  let nodeInfo = _.get(item, 'nodeInfo', []);
-  let dataSetState = 'PROGRESSING';
-  let trainTaskState = 'PROGRESSING';
-  let reasonServiceState = 'PROGRESSING';
-  let codePackageState = 'PROGRESSING';
-  let dataSetName = '';
-  let trainTaskName = '';
-  let reasonServiceName = '';
-  let codePackageName = '';
-  let stepItems = [];
-
-  const nodeInfoMap = _.groupBy(nodeInfo, 'nodeType');
-  /** 各个步骤状态 */
-  let dataPreStatus = _.get(nodeInfoMap, 'DATAPRE_DATASETACC[0].nodeState', 'NOTSTARTED'); // 数据集接入
-  let dataPreTaskStatus = _.get(nodeInfoMap, 'DATAPRE_DATADEVTASK[0].nodeState', 'NOTSTARTED'); // 数据开发
-  let modelTrainStatus = _.get(nodeInfoMap, 'MODEDEV_MODELTRA[0].nodeState', 'NOTSTARTED');
-  let guideDevStatus = _.get(nodeInfoMap, 'GUIDEDEV_MODELTRA[0].nodeState', 'NOTSTARTED');
-  let modelSaveStatus = _.get(nodeInfoMap, 'MODEDEV_MODELPRE[0].nodeState', 'NOTSTARTED');
-  let codePackageStatus = _.get(nodeInfoMap, 'MODEDEV_CODEPACKAGE[0].nodeState', 'NOTSTARTED');
-  let serviceImageStatus = _.get(nodeInfoMap, 'SERVICEDEP_IMAGECON[0].nodeState', 'NOTSTARTED');
-  let serviceTestStatus = _.get(nodeInfoMap, 'SERVICEDEP_SERVICETEST[0].nodeState', 'NOTSTARTED');
-  let serviceProStatus = _.get(nodeInfoMap, 'SERVICEDEP_SERVICEPRO[0].nodeState', 'NOTSTARTED');
-
-  /** 节点 */
-  let dataPreNode = _.get(nodeInfoMap, 'DATAPRE_DATASETACC[0]', {}); // 数据集接入
-  let dataPreTaskNode = _.get(nodeInfoMap, 'DATAPRE_DATADEVTASK[0]', {}); // 数据开发
-  let modelTrainNode = _.get(nodeInfoMap, 'MODEDEV_MODELTRA[0]', {});
-  let guideDevNode = _.get(nodeInfoMap, 'GUIDEDEV_MODELTRA[0]', {});
-  let codePackageNode = _.get(nodeInfoMap, 'MODEDEV_CODEPACKAGE[0]', {});
-  // let serviceImageNode = _.get(nodeInfoMap, 'SERVICEDEP_IMAGECON[0]', {});
-  let serviceTestNode = _.get(nodeInfoMap, 'SERVICEDEP_SERVICETEST[0]', {});
-  let serviceProNode = _.get(nodeInfoMap, 'SERVICEDEP_SERVICEPRO[0]', {});
-
-  /** 子节点 */
-  let dataPreNodes = _.get(nodeInfoMap, 'DATAPRE_DATASETACC[0].node', []); // 数据集接入
-  let dataPreTaskNodes = _.get(nodeInfoMap, 'DATAPRE_DATADEVTASK[0].node', []); // 数据开发
-  let modelTrainNodes = _.get(nodeInfoMap, 'MODEDEV_MODELTRA[0].node', []);
-  let modelReasonNodes = _.get(nodeInfoMap, 'MODEDEV_REASONINGPRE[0].node', []);
-  let modelSaveNodes = _.get(nodeInfoMap, 'MODEDEV_MODELPRE[0].node', []);
-  let codePackageNodes = _.get(nodeInfoMap, 'MODEDEV_CODEPACKAGE[0].node', []);
-  let serviceTestNodes = _.get(nodeInfoMap, 'SERVICEDEP_SERVICETEST[0].node', []);
-  let serviceProNodes = _.get(nodeInfoMap, 'SERVICEDEP_SERVICEPRO[0].node', []);
-
-  /** 数据准备节点名称 */
-  if (dataPreTaskStatus !== 'NOTSTARTED') {
-    dataSetName = _.get(dataPreTaskNodes, `[${dataPreTaskNodes.length - 1}].nodeName`);
-  } else if (dataPreStatus !== 'NOTSTARTED') {
-    dataSetName = _.get(dataPreNodes, `[${dataPreNodes.length - 1}].nodeName`);
-  }
-  /** 数据准备状态 只要绑定了数据集状态就是已完成*/
-  dataSetState = dataPreStatus;
-
-  /** 模型开发节点名称 */
-  if (modelSaveStatus !== 'NOTSTARTED') {
-    trainTaskName = _.get(modelSaveNodes, `[${modelSaveNodes.length - 1}].nodeName`);
-  } else if (guideDevStatus !== 'NOTSTARTED') {
-    trainTaskName = _.get(modelReasonNodes, `[${modelReasonNodes.length - 1}].nodeName`);
-  } else if (modelTrainStatus !== 'NOTSTARTED') {
-    trainTaskName = _.get(modelTrainNodes, `[${modelTrainNodes.length - 1}].nodeName`);
-  }
-  /** 模型开发状态 */
-  if (modelSaveStatus === 'COMPLETED') {
-    trainTaskState = 'COMPLETED';
-  } else if (modelSaveStatus === 'NOTSTARTED' && guideDevStatus === 'NOTSTARTED' && modelTrainStatus === 'NOTSTARTED') {
-    trainTaskState = 'NOTSTARTED';
-  }
-
-  /** 代码部准备名称 */
-  if (codePackageStatus !== 'NOTSTARTED') {
-    codePackageName = _.get(codePackageNodes, `[${codePackageNodes.length - 1}].nodeName`);
-  }
-  /** 代码部准备状态 */
-  if (codePackageStatus === 'COMPLETED') {
-    codePackageState = 'COMPLETED';
-  } else if (codePackageStatus === 'NOTSTARTED') {
-    codePackageState = 'NOTSTARTED';
-  }
-
-  /** 服务部署节点名称 */
-  if (serviceProStatus !== 'NOTSTARTED') {
-    reasonServiceName = _.get(serviceProNodes, `[${serviceProNodes.length - 1}].nodeName`);
-  } else if (serviceTestStatus !== 'NOTSTARTED') {
-    reasonServiceName = _.get(serviceTestNodes, `[${serviceTestNodes.length - 1}].nodeName`);
-  }
-
-  /** 服务部署 */
-  if (serviceProStatus === 'COMPLETED') {
-    reasonServiceState = 'COMPLETED';
-  } else if (
-    (serviceProStatus === 'NOTSTARTED' && serviceTestStatus === 'NOTSTARTED') ||
-    serviceImageStatus === 'NOTSTARTED'
-  ) {
-    reasonServiceState = 'NOTSTARTED';
-  }
-
-  if (item.source === 'AI') {
-    stepItems = [
-      { id: 'dataSetId', state: dataSetState },
-      { id: 'trainTaskId', state: trainTaskState },
-      { id: 'reasonServiceId', state: reasonServiceState },
-    ];
-  } else if (item.source === 'NORMAL') {
-    stepItems = [
-      { id: 'codePackageId', state: codePackageState },
-      { id: 'reasonServiceId', state: reasonServiceState },
-    ];
-  } else {
-    stepItems = [{ id: 'reasonServiceId', state: reasonServiceState }];
-  }
-
-  const gitAddress = _.trimEnd(hasText('root.app.appGit'), '/');
-  let codeGitRepo = item.predictGitRepo ? item.predictGitRepo : `${gitAddress}/${projectId}/${item.applicationId}`;
-  const notStart =
-    dataSetState === 'NOTSTARTED' && trainTaskState === 'NOTSTARTED' && reasonServiceState === 'NOTSTARTED';
-  return (
-    <PageWrapper>
-      <div className="row__title-wrapper">
-        <div className="row-left">
-          {item.applicationName}
-          <span style={{ marginLeft: 8, color: 'rgba(0,0,0,0.2)' }}>({item.applicationId})</span>
-        </div>
-        <div className="row-right">
-          <a href="javascript:;" style={{ marginRight: 8 }}>
-            <span onClick={() => onApplicationEdit(item.projectApplicationId)}>
-              <FormOutlined style={{ marginRight: 4 }} />
-              修改
-            </span>
-          </a>
-
-          <a href="javascript:;" style={{ display: 'none' }}>
-            <DeleteOutlined style={{ marginRight: 4 }} />
-            <span onClick={() => onApplicationDelete(item.projectApplicationId)}>删除</span>
-          </a>
-        </div>
-      </div>
-      <div className="row__application-info">
-        <Form layout="inline">
-          <Row>
-            <Col span={6}>
-              <FormItem label="应用大类">
-                <Tooltip placement="topLeft" title={item.parentApplicationTypeName}>
-                  {item.parentApplicationTypeName}
-                </Tooltip>
-              </FormItem>
-            </Col>
-            <Col span={6}>
-              <FormItem label="应用小类">
-                <Tooltip placement="topLeft" title={item.applicationClassName}>
-                  {item.applicationClassName}
-                </Tooltip>
-              </FormItem>
-            </Col>
-            <Col span={12} style={{ position: 'relative' }}>
-              <FormItem label="应用描述" style={{ width: '100%' }} className="app__desc-item">
-                <Tooltip placement="topLeft" title={item.applicationDesc}>
-                  <span
-                    style={{
-                      width: '100%',
-                      display: 'inline-block',
-                      overflow: 'hidden',
-                      textOverflow: 'ellipsis',
-                    }}
-                  >
-                    {item.applicationDesc}
-                  </span>
-                </Tooltip>
-              </FormItem>
-            </Col>
-          </Row>
-          <Row>
-            <Col span={6}>
-              <FormItem label="创建人">
-                <Tooltip placement="topLeft" title={item.createBy}>
-                  {item.createBy}
-                </Tooltip>
-              </FormItem>
-            </Col>
-            <Col span={6}>
-              <FormItem label="创建时间">
-                <Tooltip placement="topLeft" title={item.createAt}>
-                  {item.createAt}
-                </Tooltip>
-              </FormItem>
-            </Col>
-
-            <Col span={12}>
-              <FormItem label="git仓库">
-                <Link
-                  to={{
-                    pathname: notebookViewUrl.view(projectId, item.applicationId, '/', false),
-                  }}
-                  target="_blank"
-                >
-                  <Tooltip title={codeGitRepo}>{`${projectId}/${item.applicationId}`}</Tooltip>
-                </Link>
-              </FormItem>
-            </Col>
-          </Row>
-        </Form>
-      </div>
-      <React.Fragment>
-        <div className="row__step-wrapper">
-          <RowStep stepItems={stepItems} />
-        </div>
-        <div className="row__item-wrapper">
-          {item.source === 'AI' && (
-            <React.Fragment>
-              <RowItem
-                notStart={notStart}
-                type="data"
-                rowItemName={dataSetName}
-                applicationId={item.projectApplicationId}
-                rowItem={[{ ...dataPreNode, subNode: [{ nodeType: 'DATAPRE_DATASET_BIND' }] }, dataPreTaskNode]}
-                rowState={dataSetState}
-                onBindDataSet={() => onBindDataSet(item.projectApplicationId)}
-              />
-              <RowItem
-                applicationId={item.projectApplicationId}
-                rowData={item}
-                type="train"
-                rowState={trainTaskState}
-                rowItemName={trainTaskName}
-                rowItem={[
-                  {
-                    ...modelTrainNode,
-                    nodeState: trainTaskState === 'COMPLETED' ? trainTaskState : modelTrainNode.nodeState,
-                    subNode: [guideDevNode, { nodeType: 'MODEDEV_CODEPACKAGE' }],
-                  },
-                ]}
-              />
-            </React.Fragment>
-          )}
-          {item.source === 'NORMAL' && (
-            <RowItem
-              applicationId={item.projectApplicationId}
-              type="codePackage"
-              rowState={codePackageState}
-              rowItemName={codePackageName}
-              rowItem={[codePackageNode]}
-            />
-          )}
-          <RowItem
-            applicationId={item.projectApplicationId}
-            type="service"
-            rowState={reasonServiceState}
-            rowItemName={reasonServiceName}
-            applicationType={item.source}
-            rowItem={[serviceTestNode, serviceProNode]}
-          />
-        </div>
-      </React.Fragment>
-    </PageWrapper>
-  );
-};
-
-TableRow.propTypes = {
-  item: PropTypes.object,
-  onApplicationDelete: PropTypes.func,
-  onApplicationEdit: PropTypes.func,
-  onBindDataSet: PropTypes.func,
-  projectId: PropTypes.string,
-};
-
-export default TableRow;
+/** 流水线横向 Item */
+import React from 'react';
+import _ from 'lodash';
+import { DeleteOutlined, FormOutlined } from '@ant-design/icons';
+import { Form } from '@ant-design/compatible';
+import '@ant-design/compatible/assets/index.css';
+import { Row, Col, Tooltip } from 'antd';
+import { Link } from 'react-router-dom';
+import styled from 'styled-components';
+import { PropTypes } from 'prop-types';
+import RowItem from './RowItem';
+import RowStep from './step/HorizontalStep';
+import { hasText } from 'components/auth/textAuth';
+import { notebookViewUrl } from 'routes/routeHelper';
+
+const FormItem = Form.Item;
+
+const PageWrapper = styled.div`
+  margin-top: 20px;
+  width: 100%;
+  border: 1px solid rgba(151, 151, 151, 0.18);
+  border-radius: 2px;
+  display: flex;
+  flex-direction: column;
+  padding: 16px 20px;
+  .row__title-wrapper {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    width: 100%;
+  }
+  .row-left {
+    align-items: center;
+    display: flex;
+    color: #303133;
+    font-size: 14px;
+    font-weight: 600;
+  }
+  .row-right {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+  .row__application-info {
+    margin-top: 16px;
+    width: 100%;
+    padding: 8px 24px;
+    background: #f7f8fa;
+    .ant-legacy-form-item-control-wrapper {
+      width: calc(100% - 65px);
+    }
+    .ant-legacy-form-item-children {
+      overflow: hidden;
+      text-overflow: ellipsis;
+      width: 100%;
+      display: block;
+      white-space: nowrap;
+    }
+  }
+  .row__step-wrapper {
+    width: 100%;
+    height: 32px;
+    margin: 16px 0 0;
+  }
+  .row__item-step {
+    width: 40%;
+    &:last-child {
+      width: 20%;
+    }
+  }
+  .ant-legacy-form-item {
+    width: 100%;
+  }
+  .ant-legacy-form-inline .ant-legacy-form-item {
+    display: flex;
+  }
+  .row__item-wrapper {
+    display: flex;
+    width: 100%;
+  }
+  .step__no-data {
+    .ant-steps-item-icon {
+      background: #eee;
+    }
+  }
+`;
+
+const TableRow = ({ item, onApplicationEdit, onApplicationDelete, onBindDataSet, projectId }) => {
+  let nodeInfo = _.get(item, 'nodeInfo', []);
+  let dataSetState = 'PROGRESSING';
+  let trainTaskState = 'PROGRESSING';
+  let reasonServiceState = 'PROGRESSING';
+  let codePackageState = 'PROGRESSING';
+  let dataSetName = '';
+  let trainTaskName = '';
+  let reasonServiceName = '';
+  let codePackageName = '';
+  let stepItems = [];
+
+  const nodeInfoMap = _.groupBy(nodeInfo, 'nodeType');
+  /** 各个步骤状态 */
+  let dataPreStatus = _.get(nodeInfoMap, 'DATAPRE_DATASETACC[0].nodeState', 'NOTSTARTED'); // 数据集接入
+  let dataPreTaskStatus = _.get(nodeInfoMap, 'DATAPRE_DATADEVTASK[0].nodeState', 'NOTSTARTED'); // 数据开发
+  let modelTrainStatus = _.get(nodeInfoMap, 'MODEDEV_MODELTRA[0].nodeState', 'NOTSTARTED');
+  let guideDevStatus = _.get(nodeInfoMap, 'GUIDEDEV_MODELTRA[0].nodeState', 'NOTSTARTED');
+  let modelSaveStatus = _.get(nodeInfoMap, 'MODEDEV_MODELPRE[0].nodeState', 'NOTSTARTED');
+  let codePackageStatus = _.get(nodeInfoMap, 'MODEDEV_CODEPACKAGE[0].nodeState', 'NOTSTARTED');
+  let serviceImageStatus = _.get(nodeInfoMap, 'SERVICEDEP_IMAGECON[0].nodeState', 'NOTSTARTED');
+  let serviceTestStatus = _.get(nodeInfoMap, 'SERVICEDEP_SERVICETEST[0].nodeState', 'NOTSTARTED');
+  let serviceProStatus = _.get(nodeInfoMap, 'SERVICEDEP_SERVICEPRO[0].nodeState', 'NOTSTARTED');
+
+  /** 节点 */
+  let dataPreNode = _.get(nodeInfoMap, 'DATAPRE_DATASETACC[0]', {}); // 数据集接入
+  let dataPreTaskNode = _.get(nodeInfoMap, 'DATAPRE_DATADEVTASK[0]', {}); // 数据开发
+  let modelTrainNode = _.get(nodeInfoMap, 'MODEDEV_MODELTRA[0]', {});
+  let guideDevNode = _.get(nodeInfoMap, 'GUIDEDEV_MODELTRA[0]', {});
+  let codePackageNode = _.get(nodeInfoMap, 'MODEDEV_CODEPACKAGE[0]', {});
+  // let serviceImageNode = _.get(nodeInfoMap, 'SERVICEDEP_IMAGECON[0]', {});
+  let serviceTestNode = _.get(nodeInfoMap, 'SERVICEDEP_SERVICETEST[0]', {});
+  let serviceProNode = _.get(nodeInfoMap, 'SERVICEDEP_SERVICEPRO[0]', {});
+
+  /** 子节点 */
+  let dataPreNodes = _.get(nodeInfoMap, 'DATAPRE_DATASETACC[0].node', []); // 数据集接入
+  let dataPreTaskNodes = _.get(nodeInfoMap, 'DATAPRE_DATADEVTASK[0].node', []); // 数据开发
+  let modelTrainNodes = _.get(nodeInfoMap, 'MODEDEV_MODELTRA[0].node', []);
+  let modelReasonNodes = _.get(nodeInfoMap, 'MODEDEV_REASONINGPRE[0].node', []);
+  let modelSaveNodes = _.get(nodeInfoMap, 'MODEDEV_MODELPRE[0].node', []);
+  let codePackageNodes = _.get(nodeInfoMap, 'MODEDEV_CODEPACKAGE[0].node', []);
+  let serviceTestNodes = _.get(nodeInfoMap, 'SERVICEDEP_SERVICETEST[0].node', []);
+  let serviceProNodes = _.get(nodeInfoMap, 'SERVICEDEP_SERVICEPRO[0].node', []);
+
+  /** 数据准备节点名称 */
+  if (dataPreTaskStatus !== 'NOTSTARTED') {
+    dataSetName = _.get(dataPreTaskNodes, `[${dataPreTaskNodes.length - 1}].nodeName`);
+  } else if (dataPreStatus !== 'NOTSTARTED') {
+    dataSetName = _.get(dataPreNodes, `[${dataPreNodes.length - 1}].nodeName`);
+  }
+  /** 数据准备状态 只要绑定了数据集状态就是已完成*/
+  dataSetState = dataPreStatus;
+
+  /** 模型开发节点名称 */
+  if (modelSaveStatus !== 'NOTSTARTED') {
+    trainTaskName = _.get(modelSaveNodes, `[${modelSaveNodes.length - 1}].nodeName`);
+  } else if (guideDevStatus !== 'NOTSTARTED') {
+    trainTaskName = _.get(modelReasonNodes, `[${modelReasonNodes.length - 1}].nodeName`);
+  } else if (modelTrainStatus !== 'NOTSTARTED') {
+    trainTaskName = _.get(modelTrainNodes, `[${modelTrainNodes.length - 1}].nodeName`);
+  }
+  /** 模型开发状态 */
+  if (modelSaveStatus === 'COMPLETED') {
+    trainTaskState = 'COMPLETED';
+  } else if (modelSaveStatus === 'NOTSTARTED' && guideDevStatus === 'NOTSTARTED' && modelTrainStatus === 'NOTSTARTED') {
+    trainTaskState = 'NOTSTARTED';
+  }
+
+  /** 代码部准备名称 */
+  if (codePackageStatus !== 'NOTSTARTED') {
+    codePackageName = _.get(codePackageNodes, `[${codePackageNodes.length - 1}].nodeName`);
+  }
+  /** 代码部准备状态 */
+  if (codePackageStatus === 'COMPLETED') {
+    codePackageState = 'COMPLETED';
+  } else if (codePackageStatus === 'NOTSTARTED') {
+    codePackageState = 'NOTSTARTED';
+  }
+
+  /** 服务部署节点名称 */
+  if (serviceProStatus !== 'NOTSTARTED') {
+    reasonServiceName = _.get(serviceProNodes, `[${serviceProNodes.length - 1}].nodeName`);
+  } else if (serviceTestStatus !== 'NOTSTARTED') {
+    reasonServiceName = _.get(serviceTestNodes, `[${serviceTestNodes.length - 1}].nodeName`);
+  }
+
+  /** 服务部署 */
+  if (serviceProStatus === 'COMPLETED') {
+    reasonServiceState = 'COMPLETED';
+  } else if (
+    (serviceProStatus === 'NOTSTARTED' && serviceTestStatus === 'NOTSTARTED') ||
+    serviceImageStatus === 'NOTSTARTED'
+  ) {
+    reasonServiceState = 'NOTSTARTED';
+  }
+
+  if (item.source === 'AI') {
+    stepItems = [
+      { id: 'dataSetId', state: dataSetState },
+      { id: 'trainTaskId', state: trainTaskState },
+      { id: 'reasonServiceId', state: reasonServiceState },
+    ];
+  } else if (item.source === 'NORMAL') {
+    stepItems = [
+      { id: 'codePackageId', state: codePackageState },
+      { id: 'reasonServiceId', state: reasonServiceState },
+    ];
+  } else {
+    stepItems = [{ id: 'reasonServiceId', state: reasonServiceState }];
+  }
+
+  const gitAddress = _.trimEnd(hasText('root.app.appGit'), '/');
+  let codeGitRepo = item.predictGitRepo ? item.predictGitRepo : `${gitAddress}/${projectId}/${item.applicationId}`;
+  const notStart =
+    dataSetState === 'NOTSTARTED' && trainTaskState === 'NOTSTARTED' && reasonServiceState === 'NOTSTARTED';
+  return (
+    <PageWrapper>
+      <div className="row__title-wrapper">
+        <div className="row-left">
+          {item.applicationName}
+          <span style={{ marginLeft: 8, color: 'rgba(0,0,0,0.2)' }}>({item.applicationId})</span>
+        </div>
+        <div className="row-right">
+          <a href="javascript:;" style={{ marginRight: 8 }}>
+            <span onClick={() => onApplicationEdit(item.projectApplicationId)}>
+              <FormOutlined style={{ marginRight: 4 }} />
+              修改
+            </span>
+          </a>
+          <a href="javascript:;" style={{ display: item.isAdmin ? 'inline' : 'none' }}>
+            <DeleteOutlined style={{ marginRight: 4 }} />
+            <span onClick={() => onApplicationDelete(item.projectApplicationId)}>删除</span>
+          </a>
+        </div>
+      </div>
+      <div className="row__application-info">
+        <Form layout="inline">
+          <Row>
+            <Col span={6}>
+              <FormItem label="应用大类">
+                <Tooltip placement="topLeft" title={item.parentApplicationTypeName}>
+                  {item.parentApplicationTypeName}
+                </Tooltip>
+              </FormItem>
+            </Col>
+            <Col span={6}>
+              <FormItem label="应用小类">
+                <Tooltip placement="topLeft" title={item.applicationClassName}>
+                  {item.applicationClassName}
+                </Tooltip>
+              </FormItem>
+            </Col>
+            <Col span={12} style={{ position: 'relative' }}>
+              <FormItem label="应用描述" style={{ width: '100%' }} className="app__desc-item">
+                <Tooltip placement="topLeft" title={item.applicationDesc}>
+                  <span
+                    style={{
+                      width: '100%',
+                      display: 'inline-block',
+                      overflow: 'hidden',
+                      textOverflow: 'ellipsis',
+                    }}
+                  >
+                    {item.applicationDesc}
+                  </span>
+                </Tooltip>
+              </FormItem>
+            </Col>
+          </Row>
+          <Row>
+            <Col span={6}>
+              <FormItem label="创建人">
+                <Tooltip placement="topLeft" title={item.createBy}>
+                  {item.createBy}
+                </Tooltip>
+              </FormItem>
+            </Col>
+            <Col span={6}>
+              <FormItem label="创建时间">
+                <Tooltip placement="topLeft" title={item.createAt}>
+                  {item.createAt}
+                </Tooltip>
+              </FormItem>
+            </Col>
+
+            <Col span={12}>
+              <FormItem label="git仓库">
+                <Link
+                  to={{
+                    pathname: notebookViewUrl.view(projectId, item.applicationId, '/', false),
+                  }}
+                  target="_blank"
+                >
+                  <Tooltip title={codeGitRepo}>{`${projectId}/${item.applicationId}`}</Tooltip>
+                </Link>
+              </FormItem>
+            </Col>
+          </Row>
+        </Form>
+      </div>
+      <React.Fragment>
+        <div className="row__step-wrapper">
+          <RowStep stepItems={stepItems} />
+        </div>
+        <div className="row__item-wrapper">
+          {item.source === 'AI' && (
+            <React.Fragment>
+              <RowItem
+                notStart={notStart}
+                type="data"
+                rowItemName={dataSetName}
+                applicationId={item.projectApplicationId}
+                rowItem={[{ ...dataPreNode, subNode: [{ nodeType: 'DATAPRE_DATASET_BIND' }] }, dataPreTaskNode]}
+                rowState={dataSetState}
+                onBindDataSet={() => onBindDataSet(item.projectApplicationId)}
+              />
+              <RowItem
+                applicationId={item.projectApplicationId}
+                rowData={item}
+                type="train"
+                rowState={trainTaskState}
+                rowItemName={trainTaskName}
+                rowItem={[
+                  {
+                    ...modelTrainNode,
+                    nodeState: trainTaskState === 'COMPLETED' ? trainTaskState : modelTrainNode.nodeState,
+                    subNode: [guideDevNode, { nodeType: 'MODEDEV_CODEPACKAGE' }],
+                  },
+                ]}
+              />
+            </React.Fragment>
+          )}
+          {item.source === 'NORMAL' && (
+            <RowItem
+              applicationId={item.projectApplicationId}
+              type="codePackage"
+              rowState={codePackageState}
+              rowItemName={codePackageName}
+              rowItem={[codePackageNode]}
+            />
+          )}
+          <RowItem
+            applicationId={item.projectApplicationId}
+            type="service"
+            rowState={reasonServiceState}
+            rowItemName={reasonServiceName}
+            applicationType={item.source}
+            rowItem={[serviceTestNode, serviceProNode]}
+          />
+        </div>
+      </React.Fragment>
+    </PageWrapper>
+  );
+};
+
+TableRow.propTypes = {
+  item: PropTypes.object,
+  onApplicationDelete: PropTypes.func,
+  onApplicationEdit: PropTypes.func,
+  onBindDataSet: PropTypes.func,
+  projectId: PropTypes.string,
+};
+
+export default TableRow;

+ 95 - 119
src/module/sysManage/helpPage/component/data.json

@@ -1,119 +1,95 @@
-[{
-  "key": "1",
-  "title": "加入项目",
-  "img": "1-jrxm",
-  "hints": [{
-    "top": 7,
-    "left": 30,
-    "title": "创建项目/加入项目",
-    "content": "创建项目或加入已有项目,获取项目资源",
-    "close": true,
-    "next": true
-  }]
-}, {
-  "key": "2",
-  "title": "创建应用",
-  "img": "2-yygl",
-  "hints": [{
-    "top": 20,
-    "left": 7,
-    "title": "应用项目",
-    "content": "新增应用,用于后续流水线执行",
-    "close": true,
-    "up": true,
-    "next": true,
-    "contentDirection": false
-  }]
-}, {
-  "key": "3",
-  "title": "数据准备",
-  "img": "3-sjzb",
-  "hints": [{
-    "top": 40,
-    "left": 7,
-    "title": "数据准备",
-    "content": "结构化数据/非结构化数据集接入、绑定应用、数据开发和标注",
-    "close": true,
-    "up": true,
-    "next": true,
-    "titleDirection": false,
-    "contentDirection": false
-  }]
-}, {
-  "key": "4",
-  "title": "模型开发",
-  "img": "4-mxkf",
-  "hints": [{
-    "top": 50,
-    "left": 6,
-    "title": "模型开发",
-    "content": "编码训练模型,第三方模型、代码包导入",
-    "close": true,
-    "up": true,
-    "next": true,
-    "titleDirection": false,
-    "contentDirection": false
-  }]
-}, {
-  "key": "5",
-  "title": "服务部署",
-  "img": "5-fwbs",
-  "hints": [{
-    "top": 46,
-    "left": 10,
-    "title": "服务部署",
-    "content": "把模型、代码包、推理镜像发布成推理服务",
-    "close": true,
-    "up": true,
-    "next": true,
-    "titleDirection": false,
-    "contentDirection": false
-  }]
-}, {
-  "key": "6",
-  "title": "其余功能",
-  "img": "6-qygn",
-  "hints": [{
-    "top": 7,
-    "left": 69,
-    "title": "AI使用",
-    "content": "API用户和API服务管理",
-    "size": "small",
-    "titleDirection": "centre-top",
-    "contentDirection": false
-  }, {
-    "top": 7,
-    "left": 78,
-    "title": "专区和学件",
-    "content": "NLP专区和学件专区",
-    "size": "small",
-    "titleDirection": "centre-top",
-    "contentDirection": false
-  }, {
-    "top": 7,
-    "left": 87,
-    "title": "帮助",
-    "content": "帮助手册和常用名词解释",
-    "size": "small",
-    "titleDirection": "centre-top",
-    "contentDirection": false
-  }, {
-    "top": 35,
-    "left": 18,
-    "title": "镜像管理",
-    "content": "基础镜像、训练镜像、推理镜像、代码包情况",
-    "titleDirection": "left",
-    "close": true,
-    "contentDirection": false
-  }, {
-    "top": 57,
-    "left": 18,
-    "title": "项目配置",
-    "content": "项目的数据源、申请审批、资源、成员情况",
-    "close": true,
-    "up": true,
-    "next": true,
-    "titleDirection": "left",
-    "contentDirection": false
-  }]
-}]
+[{
+  "key": "1",
+  "title": "加入项目",
+  "img": "1-jrxm",
+  "hints": [{
+    "top": 7,
+    "left": 30,
+    "title": "创建项目/加入项目",
+    "content": "创建项目或加入已有项目,获取项目资源",
+    "close": true,
+    "next": true
+  }]
+}, {
+  "key": "2",
+  "title": "创建应用",
+  "img": "2-yygl",
+  "hints": [{
+    "top": 20,
+    "left": 7,
+    "title": "应用项目",
+    "content": "新增应用,用于后续流水线执行",
+    "close": true,
+    "up": true,
+    "next": true,
+    "contentDirection": false
+  }]
+}, {
+  "key": "3",
+  "title": "数据准备",
+  "img": "3-sjzb",
+  "hints": [{
+    "top": 40,
+    "left": 7,
+    "title": "数据准备",
+    "content": "结构化数据/非结构化数据集接入、绑定应用、数据开发和标注",
+    "close": true,
+    "up": true,
+    "next": true,
+    "titleDirection": false,
+    "contentDirection": false
+  }]
+}, {
+  "key": "4",
+  "title": "模型开发",
+  "img": "4-mxkf",
+  "hints": [{
+    "top": 50,
+    "left": 6,
+    "title": "模型开发",
+    "content": "编码训练模型,第三方模型、代码包导入",
+    "close": true,
+    "up": true,
+    "next": true,
+    "titleDirection": false,
+    "contentDirection": false
+  }]
+}, {
+  "key": "5",
+  "title": "服务部署",
+  "img": "5-fwbs",
+  "hints": [{
+    "top": 46,
+    "left": 10,
+    "title": "服务部署",
+    "content": "把模型、代码包、推理镜像发布成推理服务",
+    "close": true,
+    "up": true,
+    "next": true,
+    "titleDirection": false,
+    "contentDirection": false
+  }]
+}, {
+  "key": "6",
+  "title": "其余功能",
+  "img": "6-qygn",
+  "hints": [{
+    "top": 35,
+    "left": 18,
+    "title": "镜像管理",
+    "content": "基础镜像、训练镜像、推理镜像、代码包情况",
+    "titleDirection": "left",
+    "close": true,
+    "contentDirection": false
+  }, {
+    "top": 57,
+    "left": 18,
+    "title": "项目配置",
+    "content": "项目的数据源、申请审批、资源、成员情况",
+    "close": true,
+    "up": true,
+    "next": true,
+    "titleDirection": "left",
+    "contentDirection": false
+  }]
+}]

+ 342 - 335
src/redux/services/sysManager/projectManage.js

@@ -1,335 +1,342 @@
-import request from 'utils/request';
-import { ServicePath } from 'utils/constants';
-import { getUser } from 'utils/authPermit';
-export default {
-  //扩缩容接口
-  expandResource: (config, projectId) => {
-    let newConfig = _.cloneDeep(config);
-    for (let i = 0; newConfig && i < newConfig.length; i++) {
-      let array = [];
-      for (let n = 0; newConfig[i].resQuotaConf && n < newConfig[i].resQuotaConf.gpu.length; n++) {
-        if (newConfig[i].resQuotaConf.gpu[n].gpuNumber !== 0) {
-          array.push(newConfig[i].resQuotaConf.gpu[n]);
-        }
-      }
-      newConfig[i].resQuotaConf.gpu = array;
-    }
-    return request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/${projectId}/resources`,
-      method: 'put',
-      data: newConfig,
-    });
-  },
-
-  //获取租户下面剩余配额
-  getTenantsResource: tenantId =>
-    request({
-      basePath: ServicePath.RES_SERVICE,
-      url: `/tenants/${tenantId}/available-quota`,
-      method: 'get',
-    }),
-  //获取所有GPU型号和数量接口
-  getAllGpu: () =>
-    request({
-      basePath: ServicePath.RES_SERVICE,
-      url: `/tenants/${getUser().tenantId}/all-gpu`,
-      method: 'get',
-    }),
-  //根据项目名称生成项目ID
-  getProjectIdProduce: projectName =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/${projectName}/projectId`,
-      method: 'get',
-    }),
-  //项目应用服务API树形结构数据查询
-  getProjectApisList: ({ appId }) =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/apis`,
-      method: 'get',
-      params: {
-        appId,
-      },
-    }),
-  //项目审批
-  approveProject: config =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/approveSingles`,
-      method: 'post',
-      data: config,
-    }),
-  //项目审批列表数据
-  getApproveSinglesList: ({ projectName, approveStates, sortField, applyType }) =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/approveSingles/resource`,
-      method: 'get',
-      params: {
-        search: projectName,
-        approveStates,
-        sortBy: sortField,
-        applyType: applyType ? applyType : null,
-      },
-    }),
-  //项目审批列表数据
-  getProjectApproveList: ({ projectName, approveStates, sortField, applyType }) =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/approveSingles`,
-      method: 'get',
-      params: {
-        search: projectName,
-        approveStates,
-        sortBy: sortField,
-        applyType: applyType ? applyType : null,
-      },
-    }),
-  //根据ID查看项目申请详情
-  getProjectApplyInfo: applyId =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/applySingles/${applyId}`,
-      method: 'get',
-    }),
-  //编辑API申请
-  editProjectApply: (config, type) =>
-    request({
-      url: type === 'create' || type === 'apply' ? `/applySingles` : `/applySingles/${config.applyId}`,
-      basePath: ServicePath.AUTH_SERVICE,
-      method: type === 'create' || type === 'apply' ? 'post' : 'patch',
-      data: config,
-    }),
-  //删除项目下的成员
-  deleteProjectApply: applyId =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/applySingles/${applyId}`,
-      method: 'delete',
-    }),
-  //项目申请列表数据
-  getProjectApplyList: ({ projectName, approveStates, applyTypes }) =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/applySingles`,
-      method: 'get',
-      params: {
-        search: projectName,
-        approveStates,
-        applyTypes,
-      },
-    }),
-  //根据当前登录用户查询所有可申请加入项目数据带状态
-  getApplyProjectCurrentUser: params =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/apply-project`,
-      method: 'get',
-      params,
-    }),
-  //根据当前登录用选择的项目查询项目下应用
-  getApplicationsDropDown: () =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/applications`,
-      method: 'get',
-    }),
-  //根据应用ID查询详情
-  getApplicationsInfo: (projectApplicationId, projectId) =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/${projectId}/applications/${projectApplicationId}`,
-      method: 'get',
-    }),
-  //删除应用
-  deleteApplication: (projectApplicationId, projectId) =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/${projectId}/applications/${projectApplicationId}`,
-      method: 'delete',
-    }),
-  //修改应用到项目
-  updateApplication: (config, projectInfo) =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/${projectInfo.projectId}/applications/${config.projectApplicationId}`,
-      method: 'patch',
-      data: config,
-    }),
-  //编辑应用到项目
-  editApplication: (config, projectInfo, type) =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url:
-        type === 'create'
-          ? `/projects/${projectInfo.projectId}/applications`
-          : `/projects/${projectInfo.projectId}/applications/${config.projectApplicationId}`,
-      method: type === 'create' ? 'post' : 'patch',
-      data: config,
-    }),
-  //应用列表查询
-  getApplicationList: projectId =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/${projectId}/applications`,
-      method: 'get',
-    }),
-  //查询项目下所有资源 3类
-  getModelAvailableQuotaByProjectId: projectId =>
-    request({
-      basePath: ServicePath.RES_SERVICE,
-      url: `/projects/${projectId}/available-quota`,
-      method: 'get',
-    }),
-  //查询租户下所有资源 3类
-  getModelAvailableQuota: projectId =>
-    request({
-      basePath: ServicePath.RES_SERVICE,
-      // url: `/tenants/default/available-quota`,
-      url: `/projects/${projectId}/available-foot-quota`,
-      method: 'get',
-    }),
-  //添加用户成员到项目
-  saveProjectUser: (config, projectId) =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/${projectId}/operations/binding-members`,
-      method: 'post',
-      data: config,
-    }),
-  //修改用户角色可批量
-  updateProjectRoles: (config, projectId) =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/${projectId}/operations/change-members-roles`,
-      method: 'patch',
-      data: config,
-    }),
-  //保存项目
-  saveProject: (config, id, apply) =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects?apply=${apply}`,
-      method: 'post',
-      data: config,
-    }),
-  //修改项目
-  updateProject: config =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/${config.projectId}`,
-      method: 'patch',
-      data: config,
-    }),
-  //删除项目下的成员
-  deleteProjectUser: projectUser =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/${projectUser.projectId}/operations/unbinding-members/`,
-      method: 'delete',
-      data: {
-        projectId: projectUser.projectId,
-        userIds: projectUser.userIds,
-      },
-    }),
-  //查询项目下的成员
-  getProjectUserList: (projectId, userId) =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/${projectId}/members`,
-      method: 'get',
-      params: {
-        projectId,
-        userName: userId,
-        userId: userId,
-      },
-    }),
-  //项目管理列表
-  getProjectList: ({ projectName, sortType, projectPid, projectType, orgId }) =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects`,
-      method: 'get',
-      params: {
-        projectName,
-        sortBy: sortType,
-        projectPid,
-        projectType,
-        orgId,
-      },
-    }),
-  //用户项目列表
-  getUserProjectList: () =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/tenants/projects`,
-      method: 'get',
-    }),
-  //概要项目列表
-  getSummaryProjectList: () =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/summary-list`,
-      method: 'get',
-    }),
-  //删除项目
-  deleteProjectInfo: projectId =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/projects/${projectId}`,
-      method: 'delete',
-    }),
-
-  //根据项目ID获取项目对象
-  getProjectInfo: projectId =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: '/projects/' + projectId,
-      method: 'get',
-    }),
-  //查询网关信息
-  getIngressInfo: () =>
-    request({
-      basePath: ServicePath.SC_SERVICE,
-      url: '/routeIngress/',
-      method: 'get',
-    }),
-  //查询项目ID是否重复
-  checkAccessPathRepeat: params =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: '/projects/operations/check-path-repeat',
-      method: 'get',
-      params: params,
-    }),
-
-  /** 获取项目剩余资源 */
-  getProjectAvailableQuota: (pubEnvType, projectId = 'current') =>
-    request({
-      basePath: ServicePath.RES_SERVICE,
-      // url: `/projects/${projectId}/available-quota`,
-      url: `/projects/${projectId}/available-quota`,
-      method: 'get',
-      params: { quotaType: pubEnvType },
-    }),
-
-  /** 获取项目已分配GPU列表 */
-  getProjectGpuTypes: (pubEnvType, projectId = 'current') =>
-    request({
-      basePath: ServicePath.RES_SERVICE,
-      // url: `/projects/${projectId}/available-quota`,
-      url: `/projects/${projectId}/all-gpu`,
-      method: 'get',
-      params: { quotaTypes: pubEnvType },
-    }),
-
-  /**查询所有项目 */
-  getAllProjects: () =>
-    request({
-      basePath: ServicePath.AUTH_SERVICE,
-      url: `/all-projects`,
-      method: 'get',
-    }),
-};
+import request from 'utils/request';
+import { ServicePath } from 'utils/constants';
+import { getUser } from 'utils/authPermit';
+export default {
+  //扩缩容接口
+  expandResource: (config, projectId) => {
+    let newConfig = _.cloneDeep(config);
+    for (let i = 0; newConfig && i < newConfig.length; i++) {
+      let array = [];
+      for (let n = 0; newConfig[i].resQuotaConf && n < newConfig[i].resQuotaConf.gpu.length; n++) {
+        if (newConfig[i].resQuotaConf.gpu[n].gpuNumber !== 0) {
+          array.push(newConfig[i].resQuotaConf.gpu[n]);
+        }
+      }
+      newConfig[i].resQuotaConf.gpu = array;
+    }
+    return request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/${projectId}/resources`,
+      method: 'put',
+      data: newConfig,
+    });
+  },
+
+  //获取租户下面剩余配额
+  getTenantsResource: tenantId =>
+    request({
+      basePath: ServicePath.RES_SERVICE,
+      url: `/tenants/${tenantId}/available-quota`,
+      method: 'get',
+    }),
+  //获取所有GPU型号和数量接口
+  getAllGpu: () =>
+    request({
+      basePath: ServicePath.RES_SERVICE,
+      url: `/tenants/${getUser().tenantId}/all-gpu`,
+      method: 'get',
+    }),
+  //根据项目名称生成项目ID
+  getProjectIdProduce: projectName =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/${projectName}/projectId`,
+      method: 'get',
+    }),
+  //项目应用服务API树形结构数据查询
+  getProjectApisList: ({ appId }) =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/apis`,
+      method: 'get',
+      params: {
+        appId,
+      },
+    }),
+  //项目审批
+  approveProject: config =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/approveSingles`,
+      method: 'post',
+      data: config,
+    }),
+  //项目审批列表数据
+  getApproveSinglesList: ({ projectName, approveStates, sortField, applyType }) =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/approveSingles/resource`,
+      method: 'get',
+      params: {
+        search: projectName,
+        approveStates,
+        sortBy: sortField,
+        applyType: applyType ? applyType : null,
+      },
+    }),
+  //项目审批列表数据
+  getProjectApproveList: ({ projectName, approveStates, sortField, applyType }) =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/approveSingles`,
+      method: 'get',
+      params: {
+        search: projectName,
+        approveStates,
+        sortBy: sortField,
+        applyType: applyType ? applyType : null,
+      },
+    }),
+  //根据ID查看项目申请详情
+  getProjectApplyInfo: applyId =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/applySingles/${applyId}`,
+      method: 'get',
+    }),
+  //编辑API申请
+  editProjectApply: (config, type) =>
+    request({
+      url: type === 'create' || type === 'apply' ? `/applySingles` : `/applySingles/${config.applyId}`,
+      basePath: ServicePath.AUTH_SERVICE,
+      method: type === 'create' || type === 'apply' ? 'post' : 'patch',
+      data: config,
+    }),
+  //删除项目下的成员
+  deleteProjectApply: applyId =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/applySingles/${applyId}`,
+      method: 'delete',
+    }),
+  //项目申请列表数据
+  getProjectApplyList: ({ projectName, approveStates, applyTypes }) =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/applySingles`,
+      method: 'get',
+      params: {
+        search: projectName,
+        approveStates,
+        applyTypes,
+      },
+    }),
+  //根据当前登录用户查询所有可申请加入项目数据带状态
+  getApplyProjectCurrentUser: params =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/apply-project`,
+      method: 'get',
+      params,
+    }),
+  //根据当前登录用选择的项目查询项目下应用
+  getApplicationsDropDown: () =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/applications`,
+      method: 'get',
+    }),
+  //根据应用ID查询详情
+  getApplicationsInfo: (projectApplicationId, projectId) =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/${projectId}/applications/${projectApplicationId}`,
+      method: 'get',
+    }),
+  //删除应用
+  deleteApplication: (projectApplicationId, projectId) =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/${projectId}/applications/${projectApplicationId}`,
+      method: 'delete',
+    }),
+  //删除应用2
+  deleteApplication2: (projectApplicationId, projectId) =>
+    request({
+      basePath: ServicePath.REPO_SERVICE,
+      url: `/repositories/deleteApplications/${projectId}/${projectApplicationId}`,
+      method: 'post',
+    }),
+  //修改应用到项目
+  updateApplication: (config, projectInfo) =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/${projectInfo.projectId}/applications/${config.projectApplicationId}`,
+      method: 'patch',
+      data: config,
+    }),
+  //编辑应用到项目
+  editApplication: (config, projectInfo, type) =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url:
+        type === 'create'
+          ? `/projects/${projectInfo.projectId}/applications`
+          : `/projects/${projectInfo.projectId}/applications/${config.projectApplicationId}`,
+      method: type === 'create' ? 'post' : 'patch',
+      data: config,
+    }),
+  //应用列表查询
+  getApplicationList: projectId =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/${projectId}/applications`,
+      method: 'get',
+    }),
+  //查询项目下所有资源 3类
+  getModelAvailableQuotaByProjectId: projectId =>
+    request({
+      basePath: ServicePath.RES_SERVICE,
+      url: `/projects/${projectId}/available-quota`,
+      method: 'get',
+    }),
+  //查询租户下所有资源 3类
+  getModelAvailableQuota: projectId =>
+    request({
+      basePath: ServicePath.RES_SERVICE,
+      // url: `/tenants/default/available-quota`,
+      url: `/projects/${projectId}/available-foot-quota`,
+      method: 'get',
+    }),
+  //添加用户成员到项目
+  saveProjectUser: (config, projectId) =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/${projectId}/operations/binding-members`,
+      method: 'post',
+      data: config,
+    }),
+  //修改用户角色可批量
+  updateProjectRoles: (config, projectId) =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/${projectId}/operations/change-members-roles`,
+      method: 'patch',
+      data: config,
+    }),
+  //保存项目
+  saveProject: (config, id, apply) =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects?apply=${apply}`,
+      method: 'post',
+      data: config,
+    }),
+  //修改项目
+  updateProject: config =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/${config.projectId}`,
+      method: 'patch',
+      data: config,
+    }),
+  //删除项目下的成员
+  deleteProjectUser: projectUser =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/${projectUser.projectId}/operations/unbinding-members/`,
+      method: 'delete',
+      data: {
+        projectId: projectUser.projectId,
+        userIds: projectUser.userIds,
+      },
+    }),
+  //查询项目下的成员
+  getProjectUserList: (projectId, userId) =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/${projectId}/members`,
+      method: 'get',
+      params: {
+        projectId,
+        userName: userId,
+        userId: userId,
+      },
+    }),
+  //项目管理列表
+  getProjectList: ({ projectName, sortType, projectPid, projectType, orgId }) =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects`,
+      method: 'get',
+      params: {
+        projectName,
+        sortBy: sortType,
+        projectPid,
+        projectType,
+        orgId,
+      },
+    }),
+  //用户项目列表
+  getUserProjectList: () =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/tenants/projects`,
+      method: 'get',
+    }),
+  //概要项目列表
+  getSummaryProjectList: () =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/summary-list`,
+      method: 'get',
+    }),
+  //删除项目
+  deleteProjectInfo: projectId =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/projects/${projectId}`,
+      method: 'delete',
+    }),
+
+  //根据项目ID获取项目对象
+  getProjectInfo: projectId =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: '/projects/' + projectId,
+      method: 'get',
+    }),
+  //查询网关信息
+  getIngressInfo: () =>
+    request({
+      basePath: ServicePath.SC_SERVICE,
+      url: '/routeIngress/',
+      method: 'get',
+    }),
+  //查询项目ID是否重复
+  checkAccessPathRepeat: params =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: '/projects/operations/check-path-repeat',
+      method: 'get',
+      params: params,
+    }),
+
+  /** 获取项目剩余资源 */
+  getProjectAvailableQuota: (pubEnvType, projectId = 'current') =>
+    request({
+      basePath: ServicePath.RES_SERVICE,
+      // url: `/projects/${projectId}/available-quota`,
+      url: `/projects/${projectId}/available-quota`,
+      method: 'get',
+      params: { quotaType: pubEnvType },
+    }),
+
+  /** 获取项目已分配GPU列表 */
+  getProjectGpuTypes: (pubEnvType, projectId = 'current') =>
+    request({
+      basePath: ServicePath.RES_SERVICE,
+      // url: `/projects/${projectId}/available-quota`,
+      url: `/projects/${projectId}/all-gpu`,
+      method: 'get',
+      params: { quotaTypes: pubEnvType },
+    }),
+
+  /**查询所有项目 */
+  getAllProjects: () =>
+    request({
+      basePath: ServicePath.AUTH_SERVICE,
+      url: `/all-projects`,
+      method: 'get',
+    }),
+};

BIN
src/styles/images/sysManager/1-jrxm.jpg


BIN
src/styles/images/sysManager/2-yygl.jpg


BIN
src/styles/images/sysManager/3-sjzb.jpg


BIN
src/styles/images/sysManager/4-mxkf.jpg


BIN
src/styles/images/sysManager/5-fwbs.jpg


+ 417 - 416
src/utils/request.js

@@ -1,416 +1,417 @@
-// @flow
-/**
- * @name utils/request.js
- * @fileOverview 封装异步请求调用
- * @author liyi
- */
-import axios from 'axios';
-import _ from 'lodash';
-import qs from 'qs';
-import {
-  getApiUrl,
-  getNewApiUrl,
-  getApiUrlByServiceType,
-  getNewApiUrlByServiceType,
-  ServicePath,
-  getAjaxUrl,
-  getUrlPath,
-} from 'utils/constants';
-import NProgress from 'nprogress';
-import 'nprogress/nprogress.css';
-import { removeLoginData, getRefreshToken, getToken, getCurrentContext } from 'utils/authPermit';
-import { notification, Modal } from 'antd';
-import cryptoJS from 'crypto-js';
-import { hasFeatureAuths } from 'components/auth/switchAuth';
-
-let isRefreshing = true;
-let subscribers = [];
-axios.defaults.retry = 4;
-axios.defaults.retryDelay = 10000;
-//let globalModal = null;
-const tplApiUrl = _.template(getApiUrl());
-const tplNewApiUrl = _.template(getNewApiUrl());
-const newServiceNames = [
-  'codemodel',
-  'project',
-  'dsem',
-  'ocr',
-  'appscene',
-  'ammc',
-  'soc',
-  'sic',
-  'biz',
-  'rcc',
-  'scc',
-  'labels',
-  'mc',
-  'route',
-  'upload',
-  'uc',
-  'learning',
-  'job-manage',
-  'job-serve',
-  'guide-train',
-  'gitlab',
-  'data-pre',
-  'streaming-reasoning',
-  'tp',
-];
-NProgress.configure({
-  showSpinner: true,
-  easing: 'ease',
-  speed: 500,
-});
-
-/**
- * 检测请求响应状态码,检测请求结果状态,错误时抛出异常
- * @param {*} response
- */
-/* eslint-disable prefer-promise-reject-errors */
-function handleResponse(response) {
-  NProgress.done();
-  if (response && response.status >= 200 && response.status < 300) {
-    const { data: result } = response;
-    if (
-      (result.code && result.code > 0) ||
-      result.success === true ||
-      result.code === '1' ||
-      typeof result.code === 'string'
-    ) {
-      const authorization = response.headers.authorization || response.headers.Authorization;
-      if (authorization) {
-        localStorage.setItem('AI.token', authorization);
-      }
-      return Promise.resolve({
-        success: true,
-        code: result.code,
-        message: result.message,
-        data: _.get(result, 'data', result.value || ''),
-        pagination: result.pagination,
-      });
-    }
-    if ((result.code && result.code < 0) || result.success === false) {
-      return Promise.reject({
-        success: result.success,
-        code: result.code,
-        message: result.message,
-        error: result.error || result.errors || '',
-      });
-    }
-    return Promise.resolve({
-      data: _.get(result, 'data', result.value) || response.data,
-      datalearn: response.data, //学件中心接口返回使用
-    });
-  }
-  return Promise.reject({
-    success: false,
-    code: _.get(response || {}, 'status', -1),
-    message: _.get(response || {}, 'statusText', '请求异常'),
-    error: _.get(response || {}, 'statusText', '请求异常'),
-    data: _.get(response, 'result.data', {}),
-  });
-}
-/* eslint-disable prefer-promise-reject-errors */
-
-function handleError(error) {
-  NProgress.done();
-  const { statusText, status } = error.response || {};
-  let errInfo = _.get(error.response || {}, ['data', 'message']) || error.message || '请求服务出错';
-  const errCode = _.get(error.response || {}, ['data', 'code']) || error.code || -1;
-  // 请求资源不存在
-  if (status === 404) errInfo = `请求的资源[${_.get(error.response, ['config', 'url'])}]不存在!`;
-  if (errCode === '4016' || errCode === '4019') {
-    if (isRefreshing) {
-      let { role, id } = getCurrentContext();
-      refreshToken(role, id);
-    }
-    isRefreshing = false;
-    let config = error.config;
-    const retryOriginalRequest = new Promise(resolve => {
-      addSubscriber(() => {
-        resolve(nextAjax(config));
-      });
-    });
-    return retryOriginalRequest;
-  }
-  //更新服务端客户端时间差
-  if (errCode === '1310002') {
-    const nowDate = new Date().getTime();
-    const serverTime = getServerTime();
-    const timeDeviation = serverTime - nowDate;
-    localStorage.setItem('AI.timeDeviation', timeDeviation);
-  }
-  // 请求超时打断
-  if (errCode === 'ECONNABORTED') {
-    errInfo = '服务连接失败或请求超时!';
-  }
-  /* eslint-disable */
-  if (status === 401 && !_.includes(window.location.pathname, '/login')) {
-    handleLoginTimeout('授权失败');
-  } else if (errCode === '4035' || errCode === '4018') {
-    handleLoginTimeout('登录超时');
-  } else {
-    notification.error({
-      key: 'SYSTEM_ERROR',
-      message: '系统错误',
-      description: errInfo,
-    });
-  }
-  return Promise.reject({
-    success: false,
-    code: errCode,
-    message: errInfo || statusText,
-    error: errInfo || statusText,
-    data: _.get(error.response, 'data.data', {}),
-  });
-}
-/* eslint-disable prefer-promise-reject-errors */
-function onAccessTokenFetched() {
-  subscribers.forEach(callback => {
-    callback();
-  });
-  subscribers = [];
-}
-
-function addSubscriber(callback) {
-  console.dir('callback:加入' + callback);
-  subscribers.push(callback);
-}
-const nextAjax = config => {
-  const token = getToken();
-  console.dir('2次请求' + token);
-  config.headers.Authorization = token; //将token设置成请求头
-  return axiosInstance(config);
-};
-/**
- * 处理登录超时/授权失败
- */
-const handleLoginTimeout = (errorMsg = '登录超时') => {
-  logOut();
-  let secondsToGo = 5;
-  const modal = Modal.warn({
-    title: errorMsg,
-    content: `系统${errorMsg},${secondsToGo} 秒后自动跳转至登录页面!`,
-    okText: '立即跳转至登录页面',
-    onOk: () => {
-      clearInterval(timer);
-      modal.destroy();
-      window.location.reload();
-    },
-  });
-  const timer = setInterval(() => {
-    secondsToGo -= 1;
-    if (modal.update) {
-      modal.update({
-        content: `${errorMsg},${secondsToGo} 秒后自动跳转至登录页面!`,
-      });
-    }
-  }, 1000);
-  setTimeout(() => {
-    clearInterval(timer);
-    modal.destroy();
-    const token = getToken();
-    window.location.reload();
-  }, secondsToGo * 1000);
-  return modal;
-};
-/**
- * 创建axios实例,设置默认api请求跟路径、超时时间,请求头content-type
- */
-const axiosInstance = axios.create({
-  timeout: 1200000,
-  headers: {
-    'Content-Type': 'application/json;charset=UTF-8',
-    Accept: 'application/json',
-  },
-});
-/**
- * axios 拦截
- * TODO 通过config为每次api请求调用添加token
- */
-axiosInstance.interceptors.request.use(
-  function(config) {
-    const token = getToken();
-    const ssoType = config.url.indexOf('/authc/sso') !== -1 || config.url.indexOf('/oauth/token') !== -1 ? true : false;
-    if (token && !ssoType) {
-      //判断token是否存在
-      config.headers.Authorization = token; //将token设置成请求头
-    }
-    //拦截所有AI图像、文字识别的参数,赋值store供界面显示
-    if (config.dispatch) {
-      //SET_REQUEST_CONFIG
-      config.dispatch(platFormActions.setRequestConfig(config));
-    }
-    const isOld = _.indexOf(newServiceNames, config.basePath) === -1 && config.url !== '/oauth/token';
-    const basePath = config.basePath || ServicePath.MODELING_SERVICE;
-    const urlPath = config.url;
-    //专门为切换网关访问场景IP
-    if (config.serviceType) {
-      let upServiceType = _.toUpper(config.serviceType);
-      config.baseURL = isOld
-        ? getApiUrlByServiceType(upServiceType, basePath)
-        : getNewApiUrlByServiceType(upServiceType, basePath);
-      // mc 服务网关地址切换
-    } else if (config.serviceType2Mc) {
-      let upServiceType2Mc = _.toUpper(config.serviceType2Mc);
-      config.baseURL = isOld
-        ? getApiUrlByServiceType(upServiceType2Mc, basePath, true)
-        : getNewApiUrlByServiceType(upServiceType2Mc, basePath, true);
-    } else {
-      if (config.basePath === 'relative') {
-        config.baseURL = '/';
-      } else {
-        config.baseURL = isOld ? tplApiUrl({ BASE_PATH: basePath }) : tplNewApiUrl({ BASE_PATH: basePath });
-      }
-    }
-
-    //updateExpiredTime();
-    if (!config.sync && _.isEmpty({})) {
-      NProgress.start();
-    }
-    let params = config.params || {};
-    if (hasFeatureAuths('root.app.enableSignature')) {
-      params = getSignatureParams({ params, isOld, basePath, urlPath });
-    }
-    config.params = params;
-    return config;
-  },
-  function(error) {
-    return Promise.reject(error);
-  }
-);
-export const refreshToken = async (scopeType, scopeId) => {
-  console.log(getToken());
-  console.log('refreshToken过期正在去换取开始~~~');
-  const refreshToken = getRefreshToken();
-  const result = await axios
-    .post(
-      getAjaxUrl() + `${ServicePath.AUTH_SERVICE}/oauth/token`,
-      qs.stringify({
-        grant_type: 'refresh_token',
-        refresh_token: refreshToken,
-        client_id: 'AI_FRONT',
-        client_secret: '23dfd110-6864-4d53-a7fb-8e671687a7bf',
-        scopeType,
-        scopeId,
-      }),
-      {
-        headers: {
-          Authorization: 'Basic QUlfRlJPTlQ6MjNkZmQxMTAtNjg2NC00ZDUzLWE3ZmItOGU2NzE2ODdhN2Jm',
-          'Content-Type': 'application/x-www-form-urlencoded',
-          __ai_refresh_token: refreshToken,
-        },
-      }
-    )
-    .then(res => {
-      console.log('refreshToken过期换取成功');
-      localStorage.setItem('AI.token', res.data.access_token ? 'Bearer ' + res.data.access_token : '');
-      localStorage.setItem('AI.refreshToken', res.data.refresh_token);
-      localStorage.setItem('AI.expiresIn', res.data.expires_in); //储存过期时间(秒)
-      console.dir('新' + res.data.access_token);
-      onAccessTokenFetched();
-      isRefreshing = true;
-      return true;
-    })
-    .catch(error => {
-      console.log('refreshToken过期换取失败' + error);
-      // onAccessTokenFetched();
-      // isRefreshing = true;
-      handleLoginTimeout();
-      return false;
-    });
-  return result;
-};
-
-/**获取签名参数 */
-function getSignatureParams({ params, isOld, basePath, urlPath }) {
-  let timeDeviation = localStorage.getItem('AI.timeDeviation');
-  const nowDate = new Date().getTime();
-  if (!timeDeviation) {
-    const serverTime = getServerTime();
-    timeDeviation = serverTime - nowDate;
-    localStorage.setItem('AI.timeDeviation', timeDeviation);
-  }
-  const url = getUrlPath(isOld, basePath, urlPath);
-  delete params['sign'];
-  params['signTimestamp'] = nowDate + Number(timeDeviation);
-  const sign = generateSignature(params, url);
-  params['sign'] = sign;
-  return params;
-}
-
-/***
- 	+ * url 签名
- 	+ */
-function generateSignature(params, urlPath) {
-  const urlInfos = urlPath.split('?');
-  const urlParams = qs.parse(urlInfos[1]);
-  let sign = '';
-  params = Object.assign({}, params, urlParams);
-  const orderParams = {};
-  Object.keys(params)
-    .sort()
-    .forEach(function(key) {
-      if (!_.isNull(params[key]) && !_.isUndefined(params[key])) {
-        orderParams[key] = params[key];
-      }
-    });
-  let secretParams = '';
-  for (let key in orderParams) {
-    if (Array.isArray(orderParams[key])) {
-      let sortArray = params[key].sort();
-      for (let i = 0; i < sortArray.length; i++) {
-        secretParams = secretParams ? `${secretParams}&${key}=${sortArray[i]}` : `${key}=${sortArray[i]}`;
-      }
-    } else {
-      secretParams = secretParams ? `${secretParams}&${key}=${orderParams[key]}` : `${key}=${orderParams[key]}`;
-    }
-  }
-
-  const secretText = `${urlInfos[0]}?${secretParams}`;
-  const secretKey = '5ebe2294ecd0e0f08eab7690d2a6ee69';
-  sign = encryptByDES(secretText, secretKey);
-  return sign;
-}
-
-function encryptByDES(message, key) {
-  const keyHex = cryptoJS.enc.Utf8.parse(key);
-  const encrypted = cryptoJS.DES.encrypt(message, keyHex, { mode: cryptoJS.mode.ECB, padding: cryptoJS.pad.Pkcs7 });
-  return encrypted.toString();
-}
-
-function getServerTime() {
-  var xhr = null;
-  if (window.XMLHttpRequest) {
-    xhr = new window.XMLHttpRequest();
-  } else {
-    xhr = new ActiveObject('Microsoft');
-  }
-
-  xhr.open('GET', '/', false);
-  xhr.send(null);
-  var date = xhr.getResponseHeader('Date');
-  date = new Date(date).getTime();
-  return date;
-}
-
-/** 退出登录(超时后跳到嵌入iframe登录页面时,iframe页面自动重定向了)*/
-function logOut() {
-  const token = getToken();
-  removeLoginData();
-  axiosInstance({
-    basePath: 'relative',
-    url: `/aiSquare/openApi/uc/oauth/logout?token=${token}`,
-    method: 'get',
-  });
-}
-
-/**
- * axios 拦截
- */
-axiosInstance.interceptors.response.use(
-  response => handleResponse(response),
-  error => handleError(error)
-);
-
-export default axiosInstance;
+// @flow
+/**
+ * @name utils/request.js
+ * @fileOverview 封装异步请求调用
+ * @author liyi
+ */
+import axios from 'axios';
+import _ from 'lodash';
+import qs from 'qs';
+import {
+  getApiUrl,
+  getNewApiUrl,
+  getApiUrlByServiceType,
+  getNewApiUrlByServiceType,
+  ServicePath,
+  getAjaxUrl,
+  getUrlPath,
+} from 'utils/constants';
+import NProgress from 'nprogress';
+import 'nprogress/nprogress.css';
+import { removeLoginData, getRefreshToken, getToken, getCurrentContext } from 'utils/authPermit';
+import { notification, Modal } from 'antd';
+import cryptoJS from 'crypto-js';
+import { hasFeatureAuths } from 'components/auth/switchAuth';
+
+let isRefreshing = true;
+let subscribers = [];
+axios.defaults.retry = 4;
+axios.defaults.retryDelay = 10000;
+//let globalModal = null;
+const tplApiUrl = _.template(getApiUrl());
+const tplNewApiUrl = _.template(getNewApiUrl());
+const newServiceNames = [
+  'codemodel',
+  'project',
+  'dsem',
+  'ocr',
+  'appscene',
+  'ammc',
+  'soc',
+  'sic',
+  'biz',
+  'rcc',
+  'scc',
+  'labels',
+  'mc',
+  'route',
+  'upload',
+  'uc',
+  'learning',
+  'job-manage',
+  'job-serve',
+  'guide-train',
+  'gitlab',
+  'data-pre',
+  'streaming-reasoning',
+  'tp',
+];
+NProgress.configure({
+  showSpinner: true,
+  easing: 'ease',
+  speed: 500,
+});
+
+/**
+ * 检测请求响应状态码,检测请求结果状态,错误时抛出异常
+ * @param {*} response
+ */
+/* eslint-disable prefer-promise-reject-errors */
+function handleResponse(response) {
+  NProgress.done();
+  if (response && response.status >= 200 && response.status < 300) {
+    const { data: result } = response;
+    if (
+      (result.code && result.code > 0) ||
+      result.success === true ||
+      result.code === '1' ||
+      typeof result.code === 'string'
+    ) {
+      const authorization = response.headers.authorization || response.headers.Authorization;
+      if (authorization) {
+        localStorage.setItem('AI.token', authorization);
+      }
+      return Promise.resolve({
+        success: true,
+        code: result.code,
+        message: result.message,
+        data: _.get(result, 'data', result.value || ''),
+        pagination: result.pagination,
+      });
+    }
+    if ((result.code && result.code < 0) || result.success === false) {
+      return Promise.reject({
+        success: result.success,
+        code: result.code,
+        message: result.message,
+        error: result.error || result.errors || '',
+      });
+    }
+    return Promise.resolve({
+      data: _.get(result, 'data', result.value) || response.data,
+      datalearn: response.data, //学件中心接口返回使用
+    });
+  }
+  return Promise.reject({
+    success: false,
+    code: _.get(response || {}, 'status', -1),
+    message: _.get(response || {}, 'statusText', '请求异常'),
+    error: _.get(response || {}, 'statusText', '请求异常'),
+    data: _.get(response, 'result.data', {}),
+  });
+}
+/* eslint-disable prefer-promise-reject-errors */
+
+function handleError(error) {
+  NProgress.done();
+  const { statusText, status } = error.response || {};
+  let errInfo = _.get(error.response || {}, ['data', 'message']) || error.message || '请求服务出错';
+  const errCode = _.get(error.response || {}, ['data', 'code']) || error.code || -1;
+  // 请求资源不存在
+  if (status === 404) errInfo = `请求的资源[${_.get(error.response, ['config', 'url'])}]不存在!`;
+  if (errCode === '4016' || errCode === '4019') {
+    if (isRefreshing) {
+      let { role, id } = getCurrentContext();
+      refreshToken(role, id);
+    }
+    isRefreshing = false;
+    let config = error.config;
+    const retryOriginalRequest = new Promise(resolve => {
+      addSubscriber(() => {
+        resolve(nextAjax(config));
+      });
+    });
+    return retryOriginalRequest;
+  }
+  //更新服务端客户端时间差
+  if (errCode === '1310002') {
+    const nowDate = new Date().getTime();
+    const serverTime = getServerTime();
+    const timeDeviation = serverTime - nowDate;
+    localStorage.setItem('AI.timeDeviation', timeDeviation);
+  }
+  // 请求超时打断
+  if (errCode === 'ECONNABORTED') {
+    errInfo = '服务连接失败或请求超时!';
+  }
+  /* eslint-disable */
+  if (status === 401 && !_.includes(window.location.pathname, '/login')) {
+    handleLoginTimeout('授权失败');
+  } else if (errCode === '4035' || errCode === '4018') {
+    handleLoginTimeout('登录超时');
+  } else {
+    notification.error({
+      key: 'SYSTEM_ERROR',
+      message: '系统错误',
+      description: errInfo,
+    });
+  }
+  return Promise.reject({
+    success: false,
+    code: errCode,
+    message: errInfo || statusText,
+    error: errInfo || statusText,
+    data: _.get(error.response, 'data.data', {}),
+  });
+}
+/* eslint-disable prefer-promise-reject-errors */
+function onAccessTokenFetched() {
+  subscribers.forEach(callback => {
+    callback();
+  });
+  subscribers = [];
+}
+
+function addSubscriber(callback) {
+  console.dir('callback:加入' + callback);
+  subscribers.push(callback);
+}
+const nextAjax = config => {
+  const token = getToken();
+  console.dir('2次请求' + token);
+  config.headers.Authorization = token; //将token设置成请求头
+  return axiosInstance(config);
+};
+/**
+ * 处理登录超时/授权失败
+ */
+const handleLoginTimeout = (errorMsg = '登录超时') => {
+  logOut();
+  let secondsToGo = 5;
+  const modal = Modal.warn({
+    title: errorMsg,
+    content: `系统${errorMsg},${secondsToGo} 秒后自动跳转至登录页面!`,
+    okText: '立即跳转至登录页面',
+    onOk: () => {
+      clearInterval(timer);
+      modal.destroy();
+      window.location.reload();
+    },
+  });
+  const timer = setInterval(() => {
+    secondsToGo -= 1;
+    if (modal.update) {
+      modal.update({
+        content: `${errorMsg},${secondsToGo} 秒后自动跳转至登录页面!`,
+      });
+    }
+  }, 1000);
+  setTimeout(() => {
+    clearInterval(timer);
+    modal.destroy();
+    const token = getToken();
+    window.location.reload();
+  }, secondsToGo * 1000);
+  return modal;
+};
+/**
+ * 创建axios实例,设置默认api请求跟路径、超时时间,请求头content-type
+ */
+const axiosInstance = axios.create({
+  timeout: 1200000,
+  headers: {
+    'Content-Type': 'application/json;charset=UTF-8',
+    Accept: 'application/json',
+  },
+});
+/**
+ * axios 拦截
+ * TODO 通过config为每次api请求调用添加token
+ */
+axiosInstance.interceptors.request.use(
+  function(config) {
+    const token = getToken();
+    const ssoType = config.url.indexOf('/authc/sso') !== -1 || config.url.indexOf('/oauth/token') !== -1 ? true : false;
+    if (token && !ssoType) {
+      //判断token是否存在
+      config.headers.Authorization = token; //将token设置成请求头
+    }
+    //拦截所有AI图像、文字识别的参数,赋值store供界面显示
+    if (config.dispatch) {
+      //SET_REQUEST_CONFIG
+      config.dispatch(platFormActions.setRequestConfig(config));
+    }
+    const isOld = _.indexOf(newServiceNames, config.basePath) === -1 && config.url !== '/oauth/token';
+    const basePath = config.basePath || ServicePath.MODELING_SERVICE;
+    const urlPath = config.url;
+    //专门为切换网关访问场景IP
+    if (config.serviceType) {
+      let upServiceType = _.toUpper(config.serviceType);
+      config.baseURL = isOld
+        ? getApiUrlByServiceType(upServiceType, basePath)
+        : getNewApiUrlByServiceType(upServiceType, basePath);
+      // mc 服务网关地址切换
+    } else if (config.serviceType2Mc) {
+      let upServiceType2Mc = _.toUpper(config.serviceType2Mc);
+      config.baseURL = isOld
+        ? getApiUrlByServiceType(upServiceType2Mc, basePath, true)
+        : getNewApiUrlByServiceType(upServiceType2Mc, basePath, true);
+    } else {
+      if (config.basePath === 'relative') {
+        config.baseURL = '/';
+      } else {
+        config.baseURL = isOld ? tplApiUrl({ BASE_PATH: basePath }) : tplNewApiUrl({ BASE_PATH: basePath });
+      }
+    }
+
+    //updateExpiredTime();
+    if (!config.sync && _.isEmpty({})) {
+      NProgress.start();
+    }
+    let params = config.params || {};
+    if (hasFeatureAuths('root.app.enableSignature')) {
+      params = getSignatureParams({ params, isOld, basePath, urlPath });
+    }
+    config.params = params;
+    config.data = config.data || {};
+    return config;
+  },
+  function(error) {
+    return Promise.reject(error);
+  }
+);
+export const refreshToken = async (scopeType, scopeId) => {
+  console.log(getToken());
+  console.log('refreshToken过期正在去换取开始~~~');
+  const refreshToken = getRefreshToken();
+  const result = await axios
+    .post(
+      getAjaxUrl() + `${ServicePath.AUTH_SERVICE}/oauth/token`,
+      qs.stringify({
+        grant_type: 'refresh_token',
+        refresh_token: refreshToken,
+        client_id: 'AI_FRONT',
+        client_secret: '23dfd110-6864-4d53-a7fb-8e671687a7bf',
+        scopeType,
+        scopeId,
+      }),
+      {
+        headers: {
+          Authorization: 'Basic QUlfRlJPTlQ6MjNkZmQxMTAtNjg2NC00ZDUzLWE3ZmItOGU2NzE2ODdhN2Jm',
+          'Content-Type': 'application/x-www-form-urlencoded',
+          __ai_refresh_token: refreshToken,
+        },
+      }
+    )
+    .then(res => {
+      console.log('refreshToken过期换取成功');
+      localStorage.setItem('AI.token', res.data.access_token ? 'Bearer ' + res.data.access_token : '');
+      localStorage.setItem('AI.refreshToken', res.data.refresh_token);
+      localStorage.setItem('AI.expiresIn', res.data.expires_in); //储存过期时间(秒)
+      console.dir('新' + res.data.access_token);
+      onAccessTokenFetched();
+      isRefreshing = true;
+      return true;
+    })
+    .catch(error => {
+      console.log('refreshToken过期换取失败' + error);
+      // onAccessTokenFetched();
+      // isRefreshing = true;
+      handleLoginTimeout();
+      return false;
+    });
+  return result;
+};
+
+/**获取签名参数 */
+function getSignatureParams({ params, isOld, basePath, urlPath }) {
+  let timeDeviation = localStorage.getItem('AI.timeDeviation');
+  const nowDate = new Date().getTime();
+  if (!timeDeviation) {
+    const serverTime = getServerTime();
+    timeDeviation = serverTime - nowDate;
+    localStorage.setItem('AI.timeDeviation', timeDeviation);
+  }
+  const url = getUrlPath(isOld, basePath, urlPath);
+  delete params['sign'];
+  params['signTimestamp'] = nowDate + Number(timeDeviation);
+  const sign = generateSignature(params, url);
+  params['sign'] = sign;
+  return params;
+}
+
+/***
+ 	+ * url 签名
+ 	+ */
+function generateSignature(params, urlPath) {
+  const urlInfos = urlPath.split('?');
+  const urlParams = qs.parse(urlInfos[1]);
+  let sign = '';
+  params = Object.assign({}, params, urlParams);
+  const orderParams = {};
+  Object.keys(params)
+    .sort()
+    .forEach(function(key) {
+      if (!_.isNull(params[key]) && !_.isUndefined(params[key])) {
+        orderParams[key] = params[key];
+      }
+    });
+  let secretParams = '';
+  for (let key in orderParams) {
+    if (Array.isArray(orderParams[key])) {
+      let sortArray = params[key].sort();
+      for (let i = 0; i < sortArray.length; i++) {
+        secretParams = secretParams ? `${secretParams}&${key}=${sortArray[i]}` : `${key}=${sortArray[i]}`;
+      }
+    } else {
+      secretParams = secretParams ? `${secretParams}&${key}=${orderParams[key]}` : `${key}=${orderParams[key]}`;
+    }
+  }
+
+  const secretText = `${urlInfos[0]}?${secretParams}`;
+  const secretKey = '5ebe2294ecd0e0f08eab7690d2a6ee69';
+  sign = encryptByDES(secretText, secretKey);
+  return sign;
+}
+
+function encryptByDES(message, key) {
+  const keyHex = cryptoJS.enc.Utf8.parse(key);
+  const encrypted = cryptoJS.DES.encrypt(message, keyHex, { mode: cryptoJS.mode.ECB, padding: cryptoJS.pad.Pkcs7 });
+  return encrypted.toString();
+}
+
+function getServerTime() {
+  var xhr = null;
+  if (window.XMLHttpRequest) {
+    xhr = new window.XMLHttpRequest();
+  } else {
+    xhr = new ActiveObject('Microsoft');
+  }
+
+  xhr.open('GET', '/', false);
+  xhr.send(null);
+  var date = xhr.getResponseHeader('Date');
+  date = new Date(date).getTime();
+  return date;
+}
+
+/** 退出登录(超时后跳到嵌入iframe登录页面时,iframe页面自动重定向了)*/
+function logOut() {
+  const token = getToken();
+  removeLoginData();
+  axiosInstance({
+    basePath: 'relative',
+    url: `/aiSquare/openApi/uc/oauth/logout?token=${token}`,
+    method: 'get',
+  });
+}
+
+/**
+ * axios 拦截
+ */
+axiosInstance.interceptors.response.use(
+  response => handleResponse(response),
+  error => handleError(error)
+);
+
+export default axiosInstance;