| @@ -108,7 +108,9 @@ export default defineConfig({ | |||||
| * @description 内置了 babel import 插件 | * @description 内置了 babel import 插件 | ||||
| * @doc https://umijs.org/docs/max/antd#antd | * @doc https://umijs.org/docs/max/antd#antd | ||||
| */ | */ | ||||
| antd: {}, | |||||
| antd: { | |||||
| configProvider: {}, | |||||
| }, | |||||
| /** | /** | ||||
| * @name 网络请求配置 | * @name 网络请求配置 | ||||
| * @description 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。 | * @description 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。 | ||||
| @@ -1,6 +1,5 @@ | |||||
| // 自定义 Modal | // 自定义 Modal | ||||
| import { ReactComponent as CloseIcon } from '@/assets/svg/modal-close.svg'; | |||||
| import ModalTitle from '@/components/ModalTitle'; | import ModalTitle from '@/components/ModalTitle'; | ||||
| import { Modal, type ModalProps } from 'antd'; | import { Modal, type ModalProps } from 'antd'; | ||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| @@ -15,7 +14,6 @@ function KFModal({ title, image, children, className, ...rest }: KFModalProps) { | |||||
| className={classNames(['kf-modal', className])} | className={classNames(['kf-modal', className])} | ||||
| {...rest} | {...rest} | ||||
| title={<ModalTitle title={title} image={image}></ModalTitle>} | title={<ModalTitle title={title} image={image}></ModalTitle>} | ||||
| closeIcon={<CloseIcon></CloseIcon>} | |||||
| > | > | ||||
| {children} | {children} | ||||
| </Modal> | </Modal> | ||||
| @@ -81,6 +81,37 @@ a{ | |||||
| .ant-pro-layout .ant-pro-layout-container { | .ant-pro-layout .ant-pro-layout-container { | ||||
| height: 98vh; | height: 98vh; | ||||
| } | } | ||||
| .ant-modal-confirm .ant-modal-confirm-paragraph{ | |||||
| margin: 40px 0 auto; | |||||
| text-align: center; | |||||
| } | |||||
| .ant-modal-confirm-confirm .ant-modal-confirm-body>.anticon{ | |||||
| display: none; | |||||
| } | |||||
| .ant-modal-confirm .ant-modal-confirm-btns { | |||||
| margin-top: 30px; | |||||
| text-align: center; | |||||
| } | |||||
| .ant-modal-confirm-btns .ant-btn-default{ | |||||
| width:91px; | |||||
| height:42px; | |||||
| background:rgba(22, 100, 255, 0.06); | |||||
| border-radius:10px; | |||||
| color:#1d1d20; | |||||
| font-size:16px; | |||||
| margin-right: 10px; | |||||
| } | |||||
| .ant-modal-confirm-btns .ant-btn-default:hover{ | |||||
| background:rgba(22, 100, 255, 0.06); | |||||
| border-color: transparent; | |||||
| } | |||||
| .ant-modal-confirm-btns .ant-btn-primary{ | |||||
| width:91px; | |||||
| height:42px; | |||||
| background:#1664ff; | |||||
| border-radius:10px; | |||||
| font-size: 16px; | |||||
| } | |||||
| .ant-modal .ant-modal-close-x{ | .ant-modal .ant-modal-close-x{ | ||||
| border: 2px solid #272536; | border: 2px solid #272536; | ||||
| border-radius: 50%; | border-radius: 50%; | ||||
| @@ -91,6 +122,18 @@ a{ | |||||
| .ant-modal-content{ | .ant-modal-content{ | ||||
| margin-left: -130px; | margin-left: -130px; | ||||
| margin-top: 50px; | margin-top: 50px; | ||||
| } | |||||
| .ant-modal .ant-modal-content{ | |||||
| padding: 0; | |||||
| } | |||||
| .ant-modal-confirm-body-wrapper{ | |||||
| height:303px; | |||||
| border-radius:21px; | |||||
| background-image: url(/assets/images/modal-back.png); | |||||
| background-repeat:no-repeat; | |||||
| background-size:100%; | |||||
| background-position: top center; | |||||
| } | } | ||||
| .ant-modal .ant-modal-close:hover { | .ant-modal .ant-modal-close:hover { | ||||
| background-color: transparent; | background-color: transparent; | ||||
| @@ -59,12 +59,14 @@ const Dataset = () => { | |||||
| const locationParams = useParams(); //新版本获取路由参数接口 | const locationParams = useParams(); //新版本获取路由参数接口 | ||||
| const [wordList, setWordList] = useState([]); | const [wordList, setWordList] = useState([]); | ||||
| const [activeTabKey, setActiveTabKey] = useState('1'); | const [activeTabKey, setActiveTabKey] = useState('1'); | ||||
| const [uuid, setUuid] = useState(Date.now()); | |||||
| const getDatasetByDetail = () => { | const getDatasetByDetail = () => { | ||||
| getDatasetById(locationParams.id).then((ret) => { | getDatasetById(locationParams.id).then((ret) => { | ||||
| console.log(ret); | console.log(ret); | ||||
| setDatasetDetailObj(ret.data); | setDatasetDetailObj(ret.data); | ||||
| }); | }); | ||||
| }; | }; | ||||
| // 获取数据集版本 | |||||
| const getDatasetVersionList = () => { | const getDatasetVersionList = () => { | ||||
| getDatasetVersionsById(locationParams.id).then((ret) => { | getDatasetVersionsById(locationParams.id).then((ret) => { | ||||
| console.log(ret); | console.log(ret); | ||||
| @@ -77,6 +79,8 @@ const Dataset = () => { | |||||
| }; | }; | ||||
| }), | }), | ||||
| ); | ); | ||||
| setVersion(ret.data[0]); | |||||
| getDatasetVersions({ version: ret.data[0], dataset_id: locationParams.id }); | |||||
| } | } | ||||
| }); | }); | ||||
| }; | }; | ||||
| @@ -90,6 +94,7 @@ const Dataset = () => { | |||||
| form.setFieldsValue({ name: datasetDetailObj.name }); | form.setFieldsValue({ name: datasetDetailObj.name }); | ||||
| setDialogTitle('创建新版本'); | setDialogTitle('创建新版本'); | ||||
| setUuid(Date.now()); | |||||
| setIsModalOpen(true); | setIsModalOpen(true); | ||||
| }; | }; | ||||
| const handleCancel = () => { | const handleCancel = () => { | ||||
| @@ -102,16 +107,23 @@ const Dataset = () => { | |||||
| }; | }; | ||||
| const deleteDataset = () => { | const deleteDataset = () => { | ||||
| Modal.confirm({ | Modal.confirm({ | ||||
| title: '删除', | |||||
| content: '确定删除数据集版本?', | |||||
| title: ( | |||||
| <div> | |||||
| <img | |||||
| src="/assets/images/delete-icon.png" | |||||
| style={{ width: '120px', marginBottom: '24px' }} | |||||
| alt="" | |||||
| /> | |||||
| <div style={{ color: '#1d1d20', fontSize: '16px' }}>删除后,该数据集版本将不可恢复</div> | |||||
| </div> | |||||
| ), | |||||
| content: <div style={{ color: '#1d1d20', fontSize: '15px' }}>是否确认删除?</div>, | |||||
| okText: '确认', | okText: '确认', | ||||
| cancelText: '取消', | cancelText: '取消', | ||||
| onOk: () => { | onOk: () => { | ||||
| deleteDatasetVersion({ dataset_id: locationParams.id, version }).then((ret) => { | deleteDatasetVersion({ dataset_id: locationParams.id, version }).then((ret) => { | ||||
| setVersion(null); | |||||
| getDatasetVersionList(); | getDatasetVersionList(); | ||||
| getDatasetVersions({ version, dataset_id: locationParams.id }); | |||||
| message.success('删除成功'); | message.success('删除成功'); | ||||
| }); | }); | ||||
| }, | }, | ||||
| @@ -124,6 +136,7 @@ const Dataset = () => { | |||||
| message.success('创建成功'); | message.success('创建成功'); | ||||
| }); | }); | ||||
| }; | }; | ||||
| // 获取版本下的文件列表 | |||||
| const getDatasetVersions = (params) => { | const getDatasetVersions = (params) => { | ||||
| getDatasetVersionIdList(params).then((res) => { | getDatasetVersionIdList(params).then((res) => { | ||||
| setWordList(res?.data?.content ?? []); | setWordList(res?.data?.content ?? []); | ||||
| @@ -368,7 +381,7 @@ const Dataset = () => { | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <Upload {...props}> | |||||
| <Upload {...props} data={{ uuid: uuid }}> | |||||
| <Button | <Button | ||||
| style={{ | style={{ | ||||
| fontSize: '14px', | fontSize: '14px', | ||||
| @@ -24,7 +24,16 @@ const PublicData = (React.FC = () => { | |||||
| onChange({ file, fileList }) { | onChange({ file, fileList }) { | ||||
| if (file.status !== 'uploading') { | if (file.status !== 'uploading') { | ||||
| console.log(file, fileList); | console.log(file, fileList); | ||||
| form.setFieldsValue({ dataset_version_vos: fileList.map((item) => item.response.data[0]) }); | |||||
| form.setFieldsValue({ | |||||
| dataset_version_vos: fileList.map((item) => { | |||||
| const data = item.response.data[0]; | |||||
| return { | |||||
| file_name: data.fileName, | |||||
| file_size: data.fileSize, | |||||
| url: data.url, | |||||
| }; | |||||
| }), | |||||
| }); | |||||
| } | } | ||||
| }, | }, | ||||
| defaultFileList: [], | defaultFileList: [], | ||||
| @@ -98,7 +98,7 @@ function Experiment() { | |||||
| setExperimentInList(list); | setExperimentInList(list); | ||||
| // 获取 TensorBoard 状态 | // 获取 TensorBoard 状态 | ||||
| list.forEach((item) => { | list.forEach((item) => { | ||||
| if (item.nodes_result.tensorboard_log) { | |||||
| if (item.nodes_result?.tensorboard_log) { | |||||
| const timerId = setTimeout(() => { | const timerId = setTimeout(() => { | ||||
| getTensorBoardStatus(item); | getTensorBoardStatus(item); | ||||
| }, 0); | }, 0); | ||||
| @@ -161,8 +161,8 @@ function Experiment() { | |||||
| } | } | ||||
| }; | }; | ||||
| const expandChange = (e, record) => { | const expandChange = (e, record) => { | ||||
| clearExperimentInTimers(); | |||||
| if (record.id === expandedRowKeys) { | if (record.id === expandedRowKeys) { | ||||
| clearExperimentInTimers(); | |||||
| setExpandedRowKeys(null); | setExpandedRowKeys(null); | ||||
| } else { | } else { | ||||
| getQueryByExperiment(record.id); | getQueryByExperiment(record.id); | ||||
| @@ -350,8 +350,20 @@ function Experiment() { | |||||
| icon={<DeleteOutlined />} | icon={<DeleteOutlined />} | ||||
| onClick={async () => { | onClick={async () => { | ||||
| Modal.confirm({ | Modal.confirm({ | ||||
| title: '删除', | |||||
| content: '确定删除该条实验吗?', | |||||
| title: ( | |||||
| <div> | |||||
| <img | |||||
| src="/assets/images/delete-icon.png" | |||||
| style={{ width: '120px', marginBottom: '24px' }} | |||||
| alt="" | |||||
| /> | |||||
| <div style={{ color: '#1d1d20', fontSize: '16px' }}> | |||||
| 删除后,该实验将不可恢复 | |||||
| </div> | |||||
| </div> | |||||
| ), | |||||
| content: <div style={{ color: '#1d1d20', fontSize: '15px' }}>是否确认删除?</div>, | |||||
| closable: true, | |||||
| okText: '确认', | okText: '确认', | ||||
| cancelText: '取消', | cancelText: '取消', | ||||
| @@ -434,7 +446,7 @@ function Experiment() { | |||||
| {index + 1} | {index + 1} | ||||
| </a> | </a> | ||||
| <div style={{ width: '300px' }}> | <div style={{ width: '300px' }}> | ||||
| {item.nodes_result.tensorboard_log ? ( | |||||
| {item.nodes_result?.tensorboard_log ? ( | |||||
| <TensorBoardStatus | <TensorBoardStatus | ||||
| status={item.tensorBoardStatus} | status={item.tensorBoardStatus} | ||||
| onClick={() => handleTensorboard(item)} | onClick={() => handleTensorboard(item)} | ||||
| @@ -101,8 +101,17 @@ const Dataset = () => { | |||||
| }; | }; | ||||
| const deleteDataset = () => { | const deleteDataset = () => { | ||||
| Modal.confirm({ | Modal.confirm({ | ||||
| title: '删除', | |||||
| content: '确定删除模型版本?', | |||||
| title: ( | |||||
| <div> | |||||
| <img | |||||
| src="/assets/images/delete-icon.png" | |||||
| style={{ width: '120px', marginBottom: '24px' }} | |||||
| alt="" | |||||
| /> | |||||
| <div style={{ color: '#1d1d20', fontSize: '16px' }}>删除后,该模型版本将不可恢复</div> | |||||
| </div> | |||||
| ), | |||||
| content: <div style={{ color: '#1d1d20', fontSize: '15px' }}>是否确认删除?</div>, | |||||
| okText: '确认', | okText: '确认', | ||||
| cancelText: '取消', | cancelText: '取消', | ||||
| @@ -23,14 +23,23 @@ const PublicData = () => { | |||||
| onChange({ file, fileList }) { | onChange({ file, fileList }) { | ||||
| if (file.status !== 'uploading') { | if (file.status !== 'uploading') { | ||||
| console.log(file, fileList); | console.log(file, fileList); | ||||
| form.setFieldsValue({ dataset_version_vos: fileList.map((item) => item.response.data[0]) }); | |||||
| form.setFieldsValue({ | |||||
| models_version_vos: fileList.map((item) => { | |||||
| const data = item.response.data[0]; | |||||
| return { | |||||
| file_name: data.fileName, | |||||
| file_size: data.fileSize, | |||||
| url: data.url, | |||||
| }; | |||||
| }), | |||||
| }); | |||||
| } | } | ||||
| }, | }, | ||||
| defaultFileList: [], | defaultFileList: [], | ||||
| }; | }; | ||||
| const [queryFlow, setQueryFlow] = useState({ | const [queryFlow, setQueryFlow] = useState({ | ||||
| page: 0, | page: 0, | ||||
| size: 10, | |||||
| size: 20, | |||||
| name: null, | name: null, | ||||
| available_range: 0, | available_range: 0, | ||||
| }); | }); | ||||
| @@ -326,6 +335,21 @@ const PublicData = () => { | |||||
| <Input placeholder="请输入模型名称" showCount maxLength={64} /> | <Input placeholder="请输入模型名称" showCount maxLength={64} /> | ||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item | |||||
| label="模型版本" | |||||
| name="version" | |||||
| rules={ | |||||
| [ | |||||
| // { | |||||
| // required: true, | |||||
| // message: 'Please input your username!', | |||||
| // }, | |||||
| ] | |||||
| } | |||||
| > | |||||
| <Input placeholder="请输入模型版本" /> | |||||
| </Form.Item> | |||||
| <Form.Item | <Form.Item | ||||
| label="模型描述" | label="模型描述" | ||||
| name="description" | name="description" | ||||
| @@ -372,9 +396,19 @@ const PublicData = () => { | |||||
| > | > | ||||
| <Select allowClear placeholder="请选择模型标签" options={[]} /> | <Select allowClear placeholder="请选择模型标签" options={[]} /> | ||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item label="模型文件" name="dataset_version_vos"> | |||||
| <Form.Item label="模型文件" name="models_version_vos"> | |||||
| <Upload {...props} data={{ uuid: uuid }}> | <Upload {...props} data={{ uuid: uuid }}> | ||||
| <Button icon={<UploadOutlined style={{ color: '#1664ff' }} />}>上传文件</Button> | |||||
| <Button | |||||
| style={{ | |||||
| fontSize: '14px', | |||||
| border: '1px solid', | |||||
| borderColor: '#1664ff', | |||||
| background: '#fff', | |||||
| }} | |||||
| icon={<UploadOutlined style={{ color: '#1664ff', fontSize: '14px' }} />} | |||||
| > | |||||
| 上传文件 | |||||
| </Button> | |||||
| </Upload> | </Upload> | ||||
| </Form.Item> | </Form.Item> | ||||
| </Form> | </Form> | ||||
| @@ -10,7 +10,7 @@ const leftdataList = [1, 2, 3]; | |||||
| const PublicData = () => { | const PublicData = () => { | ||||
| const [queryFlow, setQueryFlow] = useState({ | const [queryFlow, setQueryFlow] = useState({ | ||||
| page: 0, | page: 0, | ||||
| size: 10, | |||||
| size: 20, | |||||
| name: null, | name: null, | ||||
| available_range: 1, | available_range: 1, | ||||
| }); | }); | ||||
| @@ -201,14 +201,27 @@ const Pipeline = () => { | |||||
| icon={<DeleteOutlined />} | icon={<DeleteOutlined />} | ||||
| onClick={async () => { | onClick={async () => { | ||||
| Modal.confirm({ | Modal.confirm({ | ||||
| title: '删除', | |||||
| content: '确定删除该条流水线吗?', | |||||
| title: ( | |||||
| <div> | |||||
| <img | |||||
| src="/assets/images/delete-icon.png" | |||||
| style={{ width: '120px', marginBottom: '24px' }} | |||||
| alt="" | |||||
| /> | |||||
| <div style={{ color: '#1d1d20', fontSize: '16px' }}> | |||||
| 删除后,该流水线将不可恢复 | |||||
| </div> | |||||
| </div> | |||||
| ), | |||||
| content: <div style={{ color: '#1d1d20', fontSize: '15px' }}>是否确认删除?</div>, | |||||
| closable: true, | |||||
| okText: '确认', | okText: '确认', | ||||
| cancelText: '取消', | cancelText: '取消', | ||||
| onOk: () => { | onOk: () => { | ||||
| console.log(record); | console.log(record); | ||||
| removeWorkflow(record.id).then((ret) => { | removeWorkflow(record.id).then((ret) => { | ||||
| if (ret.code == 200) { | |||||
| if (ret.code === 200) { | |||||
| message.success('删除成功'); | message.success('删除成功'); | ||||
| getList(); | getList(); | ||||
| } else { | } else { | ||||
| @@ -62,5 +62,6 @@ | |||||
| .ant-btn-primary { | .ant-btn-primary { | ||||
| background: #1664ff; | background: #1664ff; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -25,7 +25,7 @@ export function addDatesetAndVesion(data) { | |||||
| } | } | ||||
| // 新增模型 | // 新增模型 | ||||
| export function addModel(data) { | export function addModel(data) { | ||||
| return request(`/api/mmp//models`, { | |||||
| return request(`/api/mmp/models/addModelAndVersion`, { | |||||
| method: 'POST', | method: 'POST', | ||||
| headers: { | headers: { | ||||
| 'Content-Type': 'application/json;charset=UTF-8', | 'Content-Type': 'application/json;charset=UTF-8', | ||||