| @@ -100,10 +100,10 @@ body { | |||||
| padding: 21px 16px; | padding: 21px 16px; | ||||
| background-color: #fff; | background-color: #fff; | ||||
| } | } | ||||
| .ant-table-wrapper .ant-table { | |||||
| height: 81vh; | |||||
| overflow-y: auto; | |||||
| } | |||||
| // .ant-table-wrapper .ant-table { | |||||
| // height: 81vh; | |||||
| // // overflow-y: auto; | |||||
| // } | |||||
| .ant-pro-global-header-logo img { | .ant-pro-global-header-logo img { | ||||
| height: 21px; | height: 21px; | ||||
| } | } | ||||
| @@ -111,7 +111,7 @@ body { | |||||
| height: 94vh; | height: 94vh; | ||||
| } | } | ||||
| .ant-pro-layout .ant-pro-layout-container { | .ant-pro-layout .ant-pro-layout-container { | ||||
| height: 98vh; | |||||
| height: 100vh; | |||||
| } | } | ||||
| .ant-modal-confirm .ant-modal-confirm-paragraph { | .ant-modal-confirm .ant-modal-confirm-paragraph { | ||||
| margin: 54px 0 auto; | margin: 54px 0 auto; | ||||
| @@ -377,7 +377,7 @@ const Dataset = () => { | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <Upload {...props} data={{ uuid: uuid }}> | |||||
| <Upload {...props} data={{ uuid: uuid }} accept=".zip,.tgz"> | |||||
| <Button | <Button | ||||
| style={{ | style={{ | ||||
| fontSize: '14px', | fontSize: '14px', | ||||
| @@ -240,7 +240,7 @@ | |||||
| line-height: 0px; | line-height: 0px; | ||||
| background: linear-gradient( | background: linear-gradient( | ||||
| to right, | to right, | ||||
| rgba(22, 100, 255, 0.6) 0, | |||||
| rgba(22, 100, 255, 0.3) 0, | |||||
| rgba(22, 100, 255, 0) 100% | rgba(22, 100, 255, 0) 100% | ||||
| ); | ); | ||||
| } | } | ||||
| @@ -1,9 +1,10 @@ | |||||
| import { getAccessToken } from '@/access'; | import { getAccessToken } from '@/access'; | ||||
| import clock from '@/assets/img/clock.png'; | import clock from '@/assets/img/clock.png'; | ||||
| import creatByImg from '@/assets/img/creatBy.png'; | import creatByImg from '@/assets/img/creatBy.png'; | ||||
| import KFIcon from '@/components/KFIcon'; | |||||
| import { addDatesetAndVesion, getAssetIcon, getDatasetList } from '@/services/dataset/index.js'; | import { addDatesetAndVesion, getAssetIcon, getDatasetList } from '@/services/dataset/index.js'; | ||||
| import { getDictSelectOption } from '@/services/system/dict'; | import { getDictSelectOption } from '@/services/system/dict'; | ||||
| import { PlusCircleOutlined, UploadOutlined } from '@ant-design/icons'; | |||||
| import { UploadOutlined } from '@ant-design/icons'; | |||||
| import { Button, Form, Input, Modal, Pagination, Radio, Select, Upload } from 'antd'; | import { Button, Form, Input, Modal, Pagination, Radio, Select, Upload } from 'antd'; | ||||
| import moment from 'moment'; | import moment from 'moment'; | ||||
| import React, { useEffect, useState } from 'react'; | import React, { useEffect, useState } from 'react'; | ||||
| @@ -261,10 +262,10 @@ const PublicData = (React.FC = () => { | |||||
| }} | }} | ||||
| /> | /> | ||||
| <Button | <Button | ||||
| type="primary" | |||||
| className={Styles.plusButton} | |||||
| type="default" | |||||
| style={{ marginLeft: '20px' }} | |||||
| onClick={showModal} | onClick={showModal} | ||||
| icon={<PlusCircleOutlined style={{ color: '#1664ff' }} />} | |||||
| icon={<KFIcon type="icon-xinjian2" />} | |||||
| > | > | ||||
| 新建数据集 | 新建数据集 | ||||
| </Button> | </Button> | ||||
| @@ -424,7 +425,7 @@ const PublicData = (React.FC = () => { | |||||
| </Radio.Group> | </Radio.Group> | ||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item label="数据文件" name="dataset_version_vos"> | <Form.Item label="数据文件" name="dataset_version_vos"> | ||||
| <Upload {...props} data={{ uuid: uuid }}> | |||||
| <Upload {...props} data={{ uuid: uuid }} accept=".zip,.tgz"> | |||||
| <Button | <Button | ||||
| style={{ | style={{ | ||||
| fontSize: '14px', | fontSize: '14px', | ||||
| @@ -379,149 +379,153 @@ function Experiment() { | |||||
| }, | }, | ||||
| ]; | ]; | ||||
| return ( | return ( | ||||
| <div> | |||||
| <div className={Styles.experimentBox}> | |||||
| <div className={Styles.pipelineTopBox}> | <div className={Styles.pipelineTopBox}> | ||||
| <Button type="default" onClick={createExperiment} icon={<KFIcon type="icon-xinjian2" />}> | <Button type="default" onClick={createExperiment} icon={<KFIcon type="icon-xinjian2" />}> | ||||
| 新建实验 | 新建实验 | ||||
| </Button> | </Button> | ||||
| </div> | </div> | ||||
| <Table | |||||
| columns={columns} | |||||
| dataSource={experimentList} | |||||
| pagination={paginationProps} | |||||
| rowKey="id" | |||||
| expandable={{ | |||||
| expandedRowRender: (record) => ( | |||||
| <div> | |||||
| {experimentInList && experimentInList.length > 0 ? ( | |||||
| <div className={Styles.tableExpandBox} style={{ paddingBottom: '16px' }}> | |||||
| <div className={Styles.index}>序号</div> | |||||
| <div className={Styles.tensorBoard}>可视化</div> | |||||
| <div className={Styles.description}> | |||||
| <div style={{ width: '50%' }}>运行时长</div> | |||||
| <div style={{ width: '50%' }}>开始时间</div> | |||||
| <div className={classNames('vertical-scroll-table', Styles.experimentTable)}> | |||||
| <Table | |||||
| columns={columns} | |||||
| dataSource={experimentList} | |||||
| pagination={paginationProps} | |||||
| rowKey="id" | |||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| expandable={{ | |||||
| expandedRowRender: (record) => ( | |||||
| <div> | |||||
| {experimentInList && experimentInList.length > 0 ? ( | |||||
| <div className={Styles.tableExpandBox} style={{ paddingBottom: '16px' }}> | |||||
| <div className={Styles.index}>序号</div> | |||||
| <div className={Styles.tensorBoard}>可视化</div> | |||||
| <div className={Styles.description}> | |||||
| <div style={{ width: '50%' }}>运行时长</div> | |||||
| <div style={{ width: '50%' }}>开始时间</div> | |||||
| </div> | |||||
| <div className={Styles.status}>状态</div> | |||||
| <div className={Styles.operation}>操作</div> | |||||
| </div> | </div> | ||||
| <div className={Styles.status}>状态</div> | |||||
| <div className={Styles.operation}>操作</div> | |||||
| </div> | |||||
| ) : ( | |||||
| '' | |||||
| )} | |||||
| ) : ( | |||||
| '' | |||||
| )} | |||||
| {experimentInList && experimentInList.length > 0 | |||||
| ? experimentInList.map((item, index) => ( | |||||
| <div | |||||
| key={item.id} | |||||
| className={classNames(Styles.tableExpandBox, Styles.tableExpandBoxContent)} | |||||
| > | |||||
| <a | |||||
| className={Styles.index} | |||||
| style={{ padding: '0 16px' }} | |||||
| onClick={(e) => routerToText(e, item, record)} | |||||
| {experimentInList && experimentInList.length > 0 | |||||
| ? experimentInList.map((item, index) => ( | |||||
| <div | |||||
| key={item.id} | |||||
| className={classNames(Styles.tableExpandBox, Styles.tableExpandBoxContent)} | |||||
| > | > | ||||
| {index + 1} | |||||
| </a> | |||||
| <div className={Styles.tensorBoard}> | |||||
| {item.nodes_result?.tensorboard_log ? ( | |||||
| <TensorBoardStatus | |||||
| status={item.tensorBoardStatus} | |||||
| onClick={() => handleTensorboard(item)} | |||||
| ></TensorBoardStatus> | |||||
| ) : ( | |||||
| '-' | |||||
| )} | |||||
| </div> | |||||
| <div className={Styles.description}> | |||||
| <div style={{ width: '50%' }}> | |||||
| {item.finish_time | |||||
| ? elapsedTime(new Date(item.create_time), new Date(item.finish_time)) | |||||
| : elapsedTime(new Date(item.create_time), new Date())} | |||||
| <a | |||||
| className={Styles.index} | |||||
| style={{ padding: '0 16px' }} | |||||
| onClick={(e) => routerToText(e, item, record)} | |||||
| > | |||||
| {index + 1} | |||||
| </a> | |||||
| <div className={Styles.tensorBoard}> | |||||
| {item.nodes_result?.tensorboard_log ? ( | |||||
| <TensorBoardStatus | |||||
| status={item.tensorBoardStatus} | |||||
| onClick={() => handleTensorboard(item)} | |||||
| ></TensorBoardStatus> | |||||
| ) : ( | |||||
| '-' | |||||
| )} | |||||
| </div> | </div> | ||||
| <div style={{ width: '50%' }}> | |||||
| {momnet(item.create_time).format('YYYY-MM-DD HH:mm:ss')} | |||||
| <div className={Styles.description}> | |||||
| <div style={{ width: '50%' }}> | |||||
| {item.finish_time | |||||
| ? elapsedTime(new Date(item.create_time), new Date(item.finish_time)) | |||||
| : elapsedTime(new Date(item.create_time), new Date())} | |||||
| </div> | |||||
| <div style={{ width: '50%' }}> | |||||
| {momnet(item.create_time).format('YYYY-MM-DD HH:mm:ss')} | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | |||||
| <div className={Styles.statusBox}> | |||||
| <img | |||||
| style={{ width: '17px', marginRight: '7px' }} | |||||
| src={experimentStatusInfo[item.status]?.icon} | |||||
| />{' '} | |||||
| <span | |||||
| style={{ color: experimentStatusInfo[item.status]?.color }} | |||||
| className={Styles.statusIcon} | |||||
| > | |||||
| {experimentStatusInfo[item.status]?.label} | |||||
| </span> | |||||
| </div> | |||||
| <div className={Styles.operation}> | |||||
| <Button | |||||
| type="link" | |||||
| size="small" | |||||
| key="stop" | |||||
| disabled={ | |||||
| item.status === 'Succeeded' || | |||||
| item.status === 'Failed' || | |||||
| item.status === 'Terminated' | |||||
| } | |||||
| icon={<KFIcon type="icon-zhongzhi" />} | |||||
| onClick={async () => { | |||||
| putQueryByExperimentInsId(item.id).then((ret) => { | |||||
| if (ret.code === 200) { | |||||
| message.success('终止成功'); | |||||
| getQueryByExperiment(record.id); | |||||
| } else { | |||||
| message.error(ret.msg); | |||||
| } | |||||
| }); | |||||
| }} | |||||
| > | |||||
| 终止 | |||||
| </Button> | |||||
| <ConfigProvider | |||||
| theme={{ | |||||
| token: { | |||||
| colorLink: themes['warningColor'], | |||||
| }, | |||||
| }} | |||||
| > | |||||
| <div className={Styles.statusBox}> | |||||
| <img | |||||
| style={{ width: '17px', marginRight: '7px' }} | |||||
| src={experimentStatusInfo[item.status]?.icon} | |||||
| />{' '} | |||||
| <span | |||||
| style={{ color: experimentStatusInfo[item.status]?.color }} | |||||
| className={Styles.statusIcon} | |||||
| > | |||||
| {experimentStatusInfo[item.status]?.label} | |||||
| </span> | |||||
| </div> | |||||
| <div className={Styles.operation}> | |||||
| <Button | <Button | ||||
| type="link" | type="link" | ||||
| size="small" | size="small" | ||||
| key="batchRemove" | |||||
| disabled={item.status === 'Running' || item.status === 'Pending'} | |||||
| icon={<KFIcon type="icon-shanchu" />} | |||||
| onClick={() => { | |||||
| modalConfirm({ | |||||
| title: '确定删除该条实例吗?', | |||||
| onOk: () => { | |||||
| deleteQueryByExperimentInsId(item.id).then((ret) => { | |||||
| if (ret.code === 200) { | |||||
| message.success('删除成功'); | |||||
| getQueryByExperiment(record.id); | |||||
| } else { | |||||
| message.error(ret.msg); | |||||
| } | |||||
| }); | |||||
| }, | |||||
| key="stop" | |||||
| disabled={ | |||||
| item.status === 'Succeeded' || | |||||
| item.status === 'Failed' || | |||||
| item.status === 'Terminated' | |||||
| } | |||||
| icon={<KFIcon type="icon-zhongzhi" />} | |||||
| onClick={async () => { | |||||
| putQueryByExperimentInsId(item.id).then((ret) => { | |||||
| if (ret.code === 200) { | |||||
| message.success('终止成功'); | |||||
| getQueryByExperiment(record.id); | |||||
| } else { | |||||
| message.error(ret.msg); | |||||
| } | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| 删除 | |||||
| 终止 | |||||
| </Button> | </Button> | ||||
| </ConfigProvider> | |||||
| <ConfigProvider | |||||
| theme={{ | |||||
| token: { | |||||
| colorLink: themes['warningColor'], | |||||
| }, | |||||
| }} | |||||
| > | |||||
| <Button | |||||
| type="link" | |||||
| size="small" | |||||
| key="batchRemove" | |||||
| disabled={item.status === 'Running' || item.status === 'Pending'} | |||||
| icon={<KFIcon type="icon-shanchu" />} | |||||
| onClick={() => { | |||||
| modalConfirm({ | |||||
| title: '确定删除该条实例吗?', | |||||
| onOk: () => { | |||||
| deleteQueryByExperimentInsId(item.id).then((ret) => { | |||||
| if (ret.code === 200) { | |||||
| message.success('删除成功'); | |||||
| getQueryByExperiment(record.id); | |||||
| } else { | |||||
| message.error(ret.msg); | |||||
| } | |||||
| }); | |||||
| }, | |||||
| }); | |||||
| }} | |||||
| > | |||||
| 删除 | |||||
| </Button> | |||||
| </ConfigProvider> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | |||||
| )) | |||||
| : ''} | |||||
| </div> | |||||
| ), | |||||
| onExpand: (e, a) => { | |||||
| expandChange(e, a); | |||||
| }, | |||||
| expandedRowKeys: [expandedRowKeys], | |||||
| rowExpandable: (record) => true, | |||||
| }} | |||||
| /> | |||||
| )) | |||||
| : ''} | |||||
| </div> | |||||
| ), | |||||
| onExpand: (e, a) => { | |||||
| expandChange(e, a); | |||||
| }, | |||||
| expandedRowKeys: [expandedRowKeys], | |||||
| rowExpandable: (record) => true, | |||||
| }} | |||||
| /> | |||||
| </div> | |||||
| {isModalOpen && ( | {isModalOpen && ( | ||||
| <AddExperimentModal | <AddExperimentModal | ||||
| isAdd={isAdd} | isAdd={isAdd} | ||||
| @@ -76,3 +76,16 @@ | |||||
| .statusBox:hover .statusIcon { | .statusBox:hover .statusIcon { | ||||
| visibility: visible; | visibility: visible; | ||||
| } | } | ||||
| .experimentBox{ | |||||
| height: calc(100% - 20px); | |||||
| .experimentTable{ | |||||
| height: calc(100% - 60px); | |||||
| :global{ | |||||
| .ant-table-wrapper .ant-table{ | |||||
| // overflow-y: auto; | |||||
| height: calc(100% - 48px); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -211,17 +211,8 @@ | |||||
| width: 100%; | width: 100%; | ||||
| .dataItem { | .dataItem { | ||||
| position: relative; | position: relative; | ||||
| <<<<<<< HEAD | |||||
| width: 23.8%; | width: 23.8%; | ||||
| height:164px; | height:164px; | ||||
| background:#ffffff; | |||||
| border:1px solid; | |||||
| border-color:#eaeaea; | |||||
| border-radius:4px; | |||||
| ======= | |||||
| width: 23.5%; | |||||
| height: 164px; | |||||
| >>>>>>> 708a5facb090bd542e06a0356466fa159720a223 | |||||
| margin: 0 20px 25px 0; | margin: 0 20px 25px 0; | ||||
| background: #ffffff; | background: #ffffff; | ||||
| border: 1px solid; | border: 1px solid; | ||||
| @@ -239,7 +230,7 @@ | |||||
| line-height: 0px; | line-height: 0px; | ||||
| background: linear-gradient( | background: linear-gradient( | ||||
| to right, | to right, | ||||
| rgba(22, 100, 255, 0.6) 0, | |||||
| rgba(22, 100, 255, 0.3) 0, | |||||
| rgba(22, 100, 255, 0) 100% | rgba(22, 100, 255, 0) 100% | ||||
| ); | ); | ||||
| } | } | ||||
| @@ -375,7 +375,7 @@ const Dataset = () => { | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <Upload {...props} data={{ uuid: uuid }}> | |||||
| <Upload {...props} data={{ uuid: uuid }} accept=".zip,.tgz"> | |||||
| <Button | <Button | ||||
| style={{ | style={{ | ||||
| fontSize: '14px', | fontSize: '14px', | ||||
| @@ -1,8 +1,9 @@ | |||||
| import { getAccessToken } from '@/access'; | import { getAccessToken } from '@/access'; | ||||
| import clock from '@/assets/img/clock.png'; | import clock from '@/assets/img/clock.png'; | ||||
| import creatByImg from '@/assets/img/creatBy.png'; | import creatByImg from '@/assets/img/creatBy.png'; | ||||
| import KFIcon from '@/components/KFIcon'; | |||||
| import { addModel, getAssetIcon, getModelList } from '@/services/dataset/index.js'; | import { addModel, getAssetIcon, getModelList } from '@/services/dataset/index.js'; | ||||
| import { PlusCircleOutlined, UploadOutlined } from '@ant-design/icons'; | |||||
| import { UploadOutlined } from '@ant-design/icons'; | |||||
| import { Button, Form, Input, Modal, Pagination, Radio, Select, Upload } from 'antd'; | import { Button, Form, Input, Modal, Pagination, Radio, Select, Upload } from 'antd'; | ||||
| import moment from 'moment'; | import moment from 'moment'; | ||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| @@ -264,10 +265,10 @@ const PublicData = () => { | |||||
| }} | }} | ||||
| /> | /> | ||||
| <Button | <Button | ||||
| type="primary" | |||||
| className={Styles.plusButton} | |||||
| type="default" | |||||
| style={{ marginLeft: '20px' }} | |||||
| onClick={showModal} | onClick={showModal} | ||||
| icon={<PlusCircleOutlined style={{ color: '#1664ff' }} />} | |||||
| icon={<KFIcon type="icon-xinjian2" />} | |||||
| > | > | ||||
| 模型注册 | 模型注册 | ||||
| </Button> | </Button> | ||||
| @@ -413,7 +414,7 @@ const PublicData = () => { | |||||
| <Select allowClear placeholder="请选择模型标签" options={[]} /> | <Select allowClear placeholder="请选择模型标签" options={[]} /> | ||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item label="模型文件" name="models_version_vos"> | <Form.Item label="模型文件" name="models_version_vos"> | ||||
| <Upload {...props} data={{ uuid: uuid }}> | |||||
| <Upload {...props} data={{ uuid: uuid }} accept=".zip,.tgz"> | |||||
| <Button | <Button | ||||
| style={{ | style={{ | ||||
| fontSize: '14px', | fontSize: '14px', | ||||
| @@ -10,12 +10,12 @@ import { | |||||
| import themes from '@/styles/theme.less'; | import themes from '@/styles/theme.less'; | ||||
| import { modalConfirm } from '@/utils/ui'; | import { modalConfirm } from '@/utils/ui'; | ||||
| import { Button, ConfigProvider, Form, Input, Modal, Space, Table, message } from 'antd'; | import { Button, ConfigProvider, Form, Input, Modal, Space, Table, message } from 'antd'; | ||||
| import classNames from 'classnames'; | |||||
| import momnet from 'moment'; | import momnet from 'moment'; | ||||
| import { useEffect, useRef, useState } from 'react'; | import { useEffect, useRef, useState } from 'react'; | ||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||
| import Styles from './index.less'; | import Styles from './index.less'; | ||||
| const { TextArea } = Input; | const { TextArea } = Input; | ||||
| const Pipeline = () => { | const Pipeline = () => { | ||||
| const [form] = Form.useForm(); | const [form] = Form.useForm(); | ||||
| const navgite = useNavigate(); | const navgite = useNavigate(); | ||||
| @@ -239,13 +239,21 @@ const Pipeline = () => { | |||||
| }, | }, | ||||
| ]; | ]; | ||||
| return ( | return ( | ||||
| <div> | |||||
| <div className={Styles.PipelineBox}> | |||||
| <div className={Styles.pipelineTopBox}> | <div className={Styles.pipelineTopBox}> | ||||
| <Button type="default" onClick={showModal} icon={<KFIcon type="icon-xinjian2" />}> | <Button type="default" onClick={showModal} icon={<KFIcon type="icon-xinjian2" />}> | ||||
| 新建流水线 | 新建流水线 | ||||
| </Button> | </Button> | ||||
| </div> | </div> | ||||
| <Table columns={columns} dataSource={pipeList} pagination={paginationProps} rowKey="id" /> | |||||
| <div className={classNames('vertical-scroll-table', Styles.PipelineTable)}> | |||||
| <Table | |||||
| columns={columns} | |||||
| dataSource={pipeList} | |||||
| pagination={paginationProps} | |||||
| rowKey="id" | |||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| /> | |||||
| </div> | |||||
| <Modal | <Modal | ||||
| title={ | title={ | ||||
| <div style={{ display: 'flex', alignItems: 'center', fontWeight: 500 }}> | <div style={{ display: 'flex', alignItems: 'center', fontWeight: 500 }}> | ||||
| @@ -8,6 +8,7 @@ | |||||
| padding-right: 30px; | padding-right: 30px; | ||||
| background-image: url(/assets/images/pipeline-back.png); | background-image: url(/assets/images/pipeline-back.png); | ||||
| background-size: 100% 100%; | background-size: 100% 100%; | ||||
| } | } | ||||
| .modal { | .modal { | ||||
| @@ -50,3 +51,17 @@ | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| .PipelineBox{ | |||||
| height: calc(100% - 20px); | |||||
| .PipelineTable{ | |||||
| height: calc(100% - 60px); | |||||
| :global{ | |||||
| .ant-table-wrapper .ant-table{ | |||||
| // overflow-y: auto; | |||||
| height: calc(100% - 48px); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -8,9 +8,7 @@ let remoteMenu: any = null; | |||||
| export function getRemoteMenu() { | export function getRemoteMenu() { | ||||
| return remoteMenu; | return remoteMenu; | ||||
| } | } | ||||
| const IconFont = createFromIconfontCN({ | |||||
| scriptUrl: '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js', // 在 iconfont.cn 上生成 | |||||
| }); | |||||
| export function setRemoteMenu(data: any) { | export function setRemoteMenu(data: any) { | ||||
| remoteMenu = data; | remoteMenu = data; | ||||
| } | } | ||||