Browse Source

chore: merge dev

pull/27/head
cp3hnu 1 year ago
parent
commit
ad18ae498a
22 changed files with 384 additions and 127 deletions
  1. BIN
      react-ui/src/assets/img/clock.png
  2. BIN
      react-ui/src/assets/img/creatBy.png
  3. +29
    -13
      react-ui/src/global.less
  4. +0
    -1
      react-ui/src/icons/dataset-select-button.svg
  5. +0
    -1
      react-ui/src/icons/mirror-select-button.svg
  6. +0
    -1
      react-ui/src/icons/model-select-button.svg
  7. +51
    -14
      react-ui/src/pages/Dataset/index.less
  8. +25
    -9
      react-ui/src/pages/Dataset/personalData.jsx
  9. +24
    -8
      react-ui/src/pages/Dataset/publicData.jsx
  10. +43
    -13
      react-ui/src/pages/Model/index.less
  11. +24
    -8
      react-ui/src/pages/Model/personalData.jsx
  12. +24
    -8
      react-ui/src/pages/Model/publicData.jsx
  13. +26
    -16
      react-ui/src/pages/Pipeline/editPipeline/index.jsx
  14. +19
    -0
      react-ui/src/pages/Pipeline/editPipeline/props.jsx
  15. +9
    -1
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/dataset/DatasetController.java
  16. +2
    -2
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageController.java
  17. +9
    -1
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageVersionController.java
  18. +3
    -4
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ImageService.java
  19. +63
    -14
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java
  20. +3
    -2
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java
  21. +29
    -10
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/ImageVo.java
  22. +1
    -1
      ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ImageDaoMapper.xml

BIN
react-ui/src/assets/img/clock.png View File

Before After
Width: 200  |  Height: 200  |  Size: 8.0 kB

BIN
react-ui/src/assets/img/creatBy.png View File

Before After
Width: 48  |  Height: 48  |  Size: 1.6 kB

+ 29
- 13
react-ui/src/global.less View File

@@ -1,12 +1,9 @@
@import '@/styles/theme.less';

html,
body,
#root {
height: 100%;
margin: 0;
padding: 0;
overflow-y: hidden;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji';
@@ -35,24 +32,28 @@ body {
-moz-osx-font-smoothing: grayscale;
}
.ant-pro-layout .ant-pro-layout-content {
padding: 0 10px 10px;
overflow-y: hidden;
background-color: @background-color;
padding: 10px;
}
.ant-pro-layout .ant-pro-layout-bg-list {
background: @background-color;
background: #f9fafb;
}

.ant-menu-light .ant-menu-item-selected {
background: rgba(197, 232, 255, 0.8) !important;
}
.ant-menu-light .ant-menu-item-selected .ant-pro-base-menu-inline-item-text {
// color: #1664ff;
}
.ant-pro-layout .ant-pro-sider .ant-layout-sider-children {
background: #f2f5f7;
}
.ant-pro-base-menu-inline-item-title .ant-pro-base-menu-inline-item-text {
color: #1d1d20;
// color: #1d1d20;
font-size: 16px;
}
// .ant-menu-light .ant-menu-item-selected{
// color:#1664ff;
// }
.ant-pro-layout .ant-pro-sider-menu {
padding-top: 40px;
}
@@ -74,7 +75,9 @@ body {
background: #f2f5f7;
border-radius: 0px 20px 20px 0px;
}

.ant-pro-layout .ant-pro-layout-content {
background-color: transparent;
}
.ant-drawer .ant-drawer-body {
padding: 0;
}
@@ -84,6 +87,9 @@ body {
.ant-drawer .ant-drawer-body .ant-form-item {
margin-bottom: 20px;
}
.ant-menu .ant-menu-submenu-title .anticon {
font-size: 16px;
}
.ant-table-wrapper .ant-table-pagination.ant-pagination {
margin: 0;
padding: 21px 16px;
@@ -99,8 +105,7 @@ body {
height: 94vh;
}
.ant-pro-layout .ant-pro-layout-container {
height: 100vh;
overflow-y: hidden;
height: 98vh;
}
.ant-modal-confirm .ant-modal-confirm-paragraph {
margin: 54px 0 auto;
@@ -117,7 +122,7 @@ body {
width: 110px;
height: 40px;
margin-right: 10px;
color: #1d1d20;
// color: #1d1d20;
font-size: 18px;
background: rgba(22, 100, 255, 0.06);
border-color: transparent;
@@ -132,6 +137,7 @@ body {
height: 40px;
font-size: 18px;
border-radius: 10px;
border-radius: 10px;
}
.ant-modal .ant-input-affix-wrapper {
height: 46px;
@@ -163,7 +169,6 @@ body {
background-repeat: no-repeat;
background-position: top center;
background-size: 100%;
border-radius: 21px;
border-radius: 0;
}
.ant-modal .ant-modal-content {
@@ -190,6 +195,17 @@ body {
border-radius: 6px;
}

.ant-tabs {
.ant-tabs-nav::before,
div > .ant-tabs-nav::before {
border: none;
}

.ant-tabs-nav {
margin-bottom: 0;
}
}

// ::-webkit-scrollbar-button {
// background: #97a1bd;
// }


+ 0
- 1
react-ui/src/icons/dataset-select-button.svg View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="12.572" height="12.993" viewBox="0 0 12.572 12.993" fill="currentColor"><path class="a" d="M88.236,67l-5.66-2.951a.627.627,0,0,0-.579,0l-5.655,2.906a.627.627,0,0,0-.342.558v6.009a.629.629,0,0,0,.348.563l5.658,2.82a.627.627,0,0,0,.561,0l5.657-2.82a.629.629,0,0,0,.348-.563V67.555A.626.626,0,0,0,88.236,67Zm-6,2.842-2.124-1.046,4.811-2.577L87,67.3Zm.045-5,1.742.909-4.836,2.59-1.9-.934Zm-5.447,3.276,2.007.988v2.2a.419.419,0,0,0,.838,0V69.516l2.184,1.075V75.9l-5.029-2.509ZM82.705,75.9V70.54l5.029-2.681v5.531Z" transform="translate(-76 -63.975)"/></svg>

+ 0
- 1
react-ui/src/icons/mirror-select-button.svg View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="11.246" height="11.246" viewBox="0 0 11.246 11.246" fill="currentColor"><path class="a" d="M70.025,64a.2.2,0,0,1,.2.2V75.045a.2.2,0,0,1-.2.2h-.8a.2.2,0,0,1-.2-.2V64.2a.2.2,0,0,1,.2-.2Zm-2.008,1.2a.2.2,0,0,1,.2.2v.8a.2.2,0,0,1-.2.2H65.2v6.426h2.812a.2.2,0,0,1,.2.2v.8a.2.2,0,0,1-.2.2H64.2a.2.2,0,0,1-.2-.2V65.406a.2.2,0,0,1,.2-.2Zm6.226,7.631v1.2h-1.2v-1.2Zm-2.008,0v1.2h-1.2v-1.2Zm3.012-1.807v1.2h-1.2v-1.2Zm0-2.008v1.2h-1.2v-1.2Zm0-2.008v1.2h-1.2v-1.2ZM72.234,65.2v1.2h-1.2V65.2Zm2.008,0v1.2h-1.2V65.2Z" transform="translate(-64 -64)"/></svg>

+ 0
- 1
react-ui/src/icons/model-select-button.svg View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="12.036" height="13.5" viewBox="0 0 12.036 13.5" fill="currentColor" stroke="currentColor"><defs><style>.a{stroke-width:0.1px;}</style></defs><g transform="translate(-205.25 -176.646)"><path class="a" d="M211.268,190.1a1.261,1.261,0,0,1-.626-.167l-4.717-2.721a1.255,1.255,0,0,1-.626-1.084v-5.442a1.258,1.258,0,0,1,.626-1.084l4.717-2.721a1.271,1.271,0,0,1,1.251,0l4.717,2.721a1.255,1.255,0,0,1,.626,1.084v5.442a1.255,1.255,0,0,1-.626,1.084l-4.717,2.721A1.276,1.276,0,0,1,211.268,190.1Zm0-12.6a.478.478,0,0,0-.232.062l-4.717,2.721a.466.466,0,0,0-.232.4v5.442a.464.464,0,0,0,.232.4l4.717,2.721a.469.469,0,0,0,.463,0l4.717-2.721a.466.466,0,0,0,.232-.4V180.68a.464.464,0,0,0-.232-.4l-4.717-2.721A.465.465,0,0,0,211.268,177.5Z" transform="translate(0 0)"/><path class="a" d="M282.168,379.033a1.242,1.242,0,0,1-.616-.163l-3.722-2.1a.394.394,0,1,1,.387-.685l3.722,2.1a.461.461,0,0,0,.451,0l3.847-2.105a.394.394,0,1,1,.377.691l-3.845,2.107A1.251,1.251,0,0,1,282.168,379.033Z" transform="translate(-70.894 -195.36)"/><path class="a" d="M486.392,383.935a.392.392,0,0,1-.393-.4l.016-4.236a1.252,1.252,0,0,1,.653-1.094l3.8-2.067a.393.393,0,1,1,.375.691l-3.8,2.067a.467.467,0,0,0-.242.405l-.016,4.236A.394.394,0,0,1,486.392,383.935Z" transform="translate(-275.124 -195.422)"/><path class="a" d="M282.23,383.9a.392.392,0,0,1-.393-.391l-.016-4.236a.463.463,0,0,0-.242-.407l-3.678-2.069a.394.394,0,0,1,.385-.687l3.676,2.067a1.245,1.245,0,0,1,.647,1.092l.016,4.234a.4.4,0,0,1-.4.4Z" transform="translate(-70.962 -195.384)"/></g></svg>

+ 51
- 14
react-ui/src/pages/Dataset/index.less View File

@@ -7,6 +7,7 @@
padding-right: 30px;
background-image: url(/assets/images/pipeline-back.png);
background-size: 100% 100%;
font-family: 'Alibaba';
}
.datasetIntroTopBox {
display: flex;
@@ -38,6 +39,7 @@
background: #ffffff;
border-radius: 10px;
box-shadow: 0px 2px 12px rgba(180, 182, 191, 0.09);
font-family: alibaba;
.dataButtonList {
display: flex;
align-items: center;
@@ -68,6 +70,7 @@
.datasetBox {
font-family: 'Alibaba';
background: #f9fafb;
:global {
.ant-tabs-top > .ant-tabs-nav {
margin: 0;
@@ -117,6 +120,7 @@
margin-right: 10px;
padding-top: 15px;
background: #ffffff;
font-family: 'Alibaba';
box-shadow: 0px 3px 6px rgba(146, 146, 146, 0.09);
.custTab {
display: flex;
@@ -136,6 +140,7 @@
padding: 15px 20px;
overflow-x: hidden;
overflow-y: auto;
font-family: 'Alibaba';
.itemTitle {
margin-bottom: 15px;
color: #1d1d20;
@@ -205,6 +210,7 @@
display: flex;
flex: 1;
flex-direction: column;
font-family: 'Alibaba';
height: 100%;
padding: 22px 30px 26px 30px;
background: #ffffff;
@@ -223,38 +229,69 @@
flex: 1;
flex-wrap: wrap;
align-content: flex-start;
width: 100%;
font-family: 'Alibaba';
width: 103%;
.dataItem {
position: relative;
width: 32%;
height: 66px;
margin: 0 15px 18px 0;
background: rgba(128, 128, 128, 0.05);
border-radius: 8px;
box-shadow: 0px 0px 12px rgba(75, 84, 137, 0.05);
width: 23%;
height:164px;
background:#ffffff;
border:1px solid;
border-color:#eaeaea;
border-radius:4px;
margin: 0 20px 25px 0;
cursor: pointer;
.itemText {
position: absolute;
top: 10px;
top: 20px;
left: 20px;
color: #1d1d20;
font-size: 15px;
background: linear-gradient(to right ,rgba(22, 100, 255,0.6) 0,rgba(22, 100, 255,0) 100%);
height: 6px;
line-height: 0px;
color:#1d1d20;
font-size:16px;

}
.itemDescripition{
position: absolute;
top: 57px;
left: 20px;
padding-right: 28px;
color:#575757;
font-size:14px;
word-break: break-all;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.itemTime {
position: absolute;
bottom: 10px;
display: flex;
align-items: center;
bottom: 22px;
left: 20px;
color: #808080;
font-size: 14px;
font-size: 13px;
}
.itemIcon {
position: absolute;
display: flex;
align-items: center;
right: 20px;
bottom: 10px;
bottom: 22px;
color: #808080;
font-size: 14px;
font-size: 13px;
}
}
.dataItem:hover{
border-color: #1664FF;
box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.2)
}
.dataItem:hover .itemText{
color: #1664FF;
}
}
}
}


+ 25
- 9
react-ui/src/pages/Dataset/personalData.jsx View File

@@ -1,4 +1,6 @@
import { getAccessToken } from '@/access';
import clock from '@/assets/img/clock.png';
import creatByImg from '@/assets/img/creatBy.png';
import { addDatesetAndVesion, getAssetIcon, getDatasetList } from '@/services/dataset/index.js';
import { getDictSelectOption } from '@/services/system/dict';
import { PlusCircleOutlined, UploadOutlined } from '@ant-design/icons';
@@ -40,7 +42,7 @@ const PublicData = (React.FC = () => {
};
const [queryFlow, setQueryFlow] = useState({
page: 0,
size: 10,
size: 20,
name: null,
available_range: 0,
});
@@ -149,6 +151,11 @@ const PublicData = (React.FC = () => {
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
const onPageChange = (pageNum, pageSize) => {
console.log(pageNum, pageSize);
setQueryFlow({ ...queryFlow, page: pageNum - 1, size: pageSize });
getDatasetlist({ ...queryFlow, page: pageNum - 1, size: pageSize });
};
useEffect(() => {
getDictSelectOption('available_cluster').then((data) => {
setClusterOptions(data);
@@ -268,17 +275,19 @@ const PublicData = (React.FC = () => {
? datasetList.map((item) => {
return (
<div className={Styles.dataItem} onClick={(e) => routeToIntro(e, item)}>
<div className={Styles.itemText}>{item.name}</div>
<span className={Styles.itemText}>{item.name}</span>
<div className={Styles.itemDescripition}>{item.description}</div>
<div className={Styles.itemTime}>
<span>最近更新: {moment(item.update_time).format('YYYY-MM-DD')}</span>
</div>
<div className={Styles.itemIcon}>
<img
style={{ width: '17px', marginRight: '3px' }}
src={`/assets/images/upload-icon.png`}
style={{ width: '17px', marginRight: '6px' }}
src={creatByImg}
alt=""
/>
<span>1582</span>
<span>{item.create_by}</span>
</div>
<div className={Styles.itemIcon}>
<img style={{ width: '12px', marginRight: '5px' }} src={clock} alt="" />
<span>最近更新: {moment(item.update_time).format('YYYY-MM-DD')}</span>
</div>
</div>
);
@@ -286,7 +295,14 @@ const PublicData = (React.FC = () => {
: ''}
{/* <Select.Option value="demo">Demo</Select.Option> */}
</div>
<Pagination size="small" total={total} showSizeChanger showQuickJumper />
<Pagination
total={total}
showSizeChanger
defaultPageSize={20}
pageSizeOptions={[20, 40, 60, 80, 100]}
showQuickJumper
onChange={onPageChange}
/>
</div>
</div>
<Modal


+ 24
- 8
react-ui/src/pages/Dataset/publicData.jsx View File

@@ -1,3 +1,5 @@
import clock from '@/assets/img/clock.png';
import creatByImg from '@/assets/img/creatBy.png';
import { getAssetIcon, getDatasetList } from '@/services/dataset/index.js';
import { Form, Input, Pagination } from 'antd';
import moment from 'moment';
@@ -109,6 +111,11 @@ const PublicData = (React.FC = () => {
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
const onPageChange = (pageNum, pageSize) => {
console.log(pageNum, pageSize);
setQueryFlow({ ...queryFlow, page: pageNum - 1, size: pageSize });
getDatasetlist({ ...queryFlow, page: pageNum - 1, size: pageSize });
};
useEffect(() => {
getAssetIconList(iconParams);
getDatasetlist(queryFlow);
@@ -217,17 +224,19 @@ const PublicData = (React.FC = () => {
? datasetList.map((item) => {
return (
<div className={Styles.dataItem} onClick={(e) => routeToIntro(e, item)}>
<div className={Styles.itemText}>{item.name}</div>
<span className={Styles.itemText}>{item.name}</span>
<div className={Styles.itemDescripition}>{item.description}</div>
<div className={Styles.itemTime}>
<span>最近更新: {moment(item.update_time).format('YYYY-MM-DD')}</span>
</div>
<div className={Styles.itemIcon}>
<img
style={{ width: '17px', marginRight: '3px' }}
src={`/assets/images/upload-icon.png`}
style={{ width: '17px', marginRight: '6px' }}
src={creatByImg}
alt=""
/>
<span>1582</span>
<span>{item.create_by}</span>
</div>
<div className={Styles.itemIcon}>
<img style={{ width: '12px', marginRight: '5px' }} src={clock} alt="" />
<span>最近更新: {moment(item.update_time).format('YYYY-MM-DD')}</span>
</div>
</div>
);
@@ -235,7 +244,14 @@ const PublicData = (React.FC = () => {
: ''}
{/* <Select.Option value="demo">Demo</Select.Option> */}
</div>
<Pagination size="small" total={total} showSizeChanger showQuickJumper />
<Pagination
total={total}
showSizeChanger
defaultPageSize={20}
pageSizeOptions={[20, 40, 60, 80, 100]}
showQuickJumper
onChange={onPageChange}
/>
</div>
</div>
</>


+ 43
- 13
react-ui/src/pages/Model/index.less View File

@@ -222,35 +222,65 @@
width: 100%;
.dataItem {
position: relative;
width: 32%;
height: 66px;
margin: 0 15px 18px 0;
background: rgba(128, 128, 128, 0.05);
border-radius: 8px;
box-shadow: 0px 0px 12px rgba(75, 84, 137, 0.05);
width: 23%;
height:164px;
background:#ffffff;
border:1px solid;
border-color:#eaeaea;
border-radius:4px;
margin: 0 20px 25px 0;
cursor: pointer;
.itemText {
position: absolute;
top: 10px;
top: 20px;
left: 20px;
color: #1d1d20;
font-size: 15px;
background: linear-gradient(to right ,rgba(22, 100, 255,0.6) 0,rgba(22, 100, 255,0) 100%);
height: 6px;
line-height: 0px;
color:#1d1d20;
font-size:16px;

}
.itemDescripition{
position: absolute;
top: 57px;
left: 20px;
padding-right: 28px;
color:#575757;
font-size:14px;
word-break: break-all;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.itemTime {
position: absolute;
bottom: 10px;
display: flex;
align-items: center;
bottom: 22px;
left: 20px;
color: #808080;
font-size: 14px;
font-size: 13px;
}
.itemIcon {
position: absolute;
display: flex;
align-items: center;
right: 20px;
bottom: 10px;
bottom: 22px;
color: #808080;
font-size: 14px;
font-size: 13px;
}
}
.dataItem:hover{
border-color: #1664FF;
box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.2)
}
.dataItem:hover .itemText{
color: #1664FF;
}
}
}
}


+ 24
- 8
react-ui/src/pages/Model/personalData.jsx View File

@@ -1,4 +1,6 @@
import { getAccessToken } from '@/access';
import clock from '@/assets/img/clock.png';
import creatByImg from '@/assets/img/creatBy.png';
import { addModel, getAssetIcon, getModelList } from '@/services/dataset/index.js';
import { PlusCircleOutlined, UploadOutlined } from '@ant-design/icons';
import { Button, Form, Input, Modal, Pagination, Radio, Select, Upload } from 'antd';
@@ -148,6 +150,11 @@ const PublicData = () => {
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
const onPageChange = (pageNum, pageSize) => {
console.log(pageNum, pageSize);
setQueryFlow({ ...queryFlow, page: pageNum - 1, size: pageSize });
getModelLists({ ...queryFlow, page: pageNum - 1, size: pageSize });
};
useEffect(() => {
getAssetIconList(iconParams);
getModelLists(queryFlow);
@@ -271,17 +278,19 @@ const PublicData = () => {
? datasetList.map((item) => {
return (
<div className={Styles.dataItem} onClick={(e) => routeToIntro(e, item)}>
<div className={Styles.itemText}>{item.name}</div>
<span className={Styles.itemText}>{item.name}</span>
<div className={Styles.itemDescripition}>{item.description}</div>
<div className={Styles.itemTime}>
<span>最近更新: {moment(item.update_time).format('YYYY-MM-DD')}</span>
</div>
<div className={Styles.itemIcon}>
<img
style={{ width: '17px', marginRight: '3px' }}
src={`/assets/images/upload-icon.png`}
style={{ width: '17px', marginRight: '6px' }}
src={creatByImg}
alt=""
/>
<span>1582</span>
<span>{item.create_by}</span>
</div>
<div className={Styles.itemIcon}>
<img style={{ width: '12px', marginRight: '5px' }} src={clock} alt="" />
<span>最近更新: {moment(item.update_time).format('YYYY-MM-DD')}</span>
</div>
</div>
);
@@ -289,7 +298,14 @@ const PublicData = () => {
: ''}
{/* <Select.Option value="demo">Demo</Select.Option> */}
</div>
<Pagination size="small" total={total} showSizeChanger showQuickJumper />
<Pagination
total={total}
showSizeChanger
defaultPageSize={20}
pageSizeOptions={[20, 40, 60, 80, 100]}
showQuickJumper
onChange={onPageChange}
/>
</div>
</div>
<Modal


+ 24
- 8
react-ui/src/pages/Model/publicData.jsx View File

@@ -1,3 +1,5 @@
import clock from '@/assets/img/clock.png';
import creatByImg from '@/assets/img/creatBy.png';
import { getAssetIcon, getModelList } from '@/services/dataset/index.js';
import { Form, Input, Modal, Pagination, Radio } from 'antd';
import moment from 'moment';
@@ -110,6 +112,11 @@ const PublicData = () => {
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
const onPageChange = (pageNum, pageSize) => {
console.log(pageNum, pageSize);
setQueryFlow({ ...queryFlow, page: pageNum - 1, size: pageSize });
getModelLists({ ...queryFlow, page: pageNum - 1, size: pageSize });
};
useEffect(() => {
getAssetIconList(iconParams);
getModelLists(queryFlow);
@@ -218,17 +225,19 @@ const PublicData = () => {
? datasetList.map((item) => {
return (
<div className={Styles.dataItem} onClick={(e) => routeToIntro(e, item)}>
<div className={Styles.itemText}>{item.name}</div>
<span className={Styles.itemText}>{item.name}</span>
<div className={Styles.itemDescripition}>{item.description}</div>
<div className={Styles.itemTime}>
<span>最近更新: {moment(item.update_time).format('YYYY-MM-DD')}</span>
</div>
<div className={Styles.itemIcon}>
<img
style={{ width: '17px', marginRight: '3px' }}
src={`/assets/images/upload-icon.png`}
style={{ width: '17px', marginRight: '6px' }}
src={creatByImg}
alt=""
/>
<span>1582</span>
<span>{item.create_by}</span>
</div>
<div className={Styles.itemIcon}>
<img style={{ width: '12px', marginRight: '5px' }} src={clock} alt="" />
<span>最近更新: {moment(item.update_time).format('YYYY-MM-DD')}</span>
</div>
</div>
);
@@ -236,7 +245,14 @@ const PublicData = () => {
: ''}
{/* <Select.Option value="demo">Demo</Select.Option> */}
</div>
<Pagination size="small" total={total} showSizeChanger showQuickJumper />
<Pagination
total={total}
showSizeChanger
defaultPageSize={20}
pageSizeOptions={[20, 40, 60, 80, 100]}
showQuickJumper
onChange={onPageChange}
/>
</div>
</div>
<Modal


+ 26
- 16
react-ui/src/pages/Pipeline/editPipeline/index.jsx View File

@@ -99,22 +99,32 @@ const EditPipeline = () => {
openParamsDrawer();
return;
}
const data = graph.save();
console.log(data);
const params = {
...locationParams,
dag: JSON.stringify(data),
global_param: JSON.stringify(res.global_param),
};
saveWorkflow(params).then((ret) => {
message.success('保存成功');
closeParamsDrawer();
setTimeout(() => {
if (val) {
navgite({ pathname: `/pipeline` });
}
}, 500);
});
const [propsRes, propsError] = await to(propsRef.current.getFieldsValue());
console.log(await to(propsRef.current.getFieldsValue()));
if (propsError) {
message.error('基本信息必填项需配置');
// handlerClick();
return;
}
propsRef.current.propClose();
setTimeout(() => {
const data = graph.save();
console.log(data);
const params = {
...locationParams,
dag: JSON.stringify(data),
global_param: JSON.stringify(res.global_param),
};
saveWorkflow(params).then((ret) => {
message.success('保存成功');
closeParamsDrawer();
setTimeout(() => {
if (val) {
navgite({ pathname: `/pipeline` });
}
}, 500);
});
}, 500);
};
const handlerClick = (e) => {
e.stopPropagation();


+ 19
- 0
react-ui/src/pages/Pipeline/editPipeline/props.jsx View File

@@ -10,6 +10,7 @@ import Styles from './editPipeline.less';
const { TextArea } = Input;
const Props = forwardRef(({ onParentChange }, ref) => {
const [form] = Form.useForm();

const [stagingItem, setStagingItem] = useState({});
const [open, setOpen] = useState(false);
const [selectedModel, setSelectedModel] = useState(undefined);
@@ -78,6 +79,15 @@ const Props = forwardRef(({ onParentChange }, ref) => {
console.log('Failed:', errorInfo);
};
useImperativeHandle(ref, () => ({
getFieldsValue: async () => {
const [propsRes, propsError] = await to(form.validateFields());
if (propsRes && !propsError) {
const values = form.getFieldsValue();
return values;
} else {
return Promise.reject(propsError);
}
},
showDrawer(e) {
if (e.item && e.item.getModel()) {
// console.log(e.item.getModel().in_parameters);
@@ -104,6 +114,15 @@ const Props = forwardRef(({ onParentChange }, ref) => {
setOpen(true);
}
},
propClose: async () => {
setOpen(false);
const [openRes, propsError] = await to(setOpen(false));
console.log(setOpen(false));
},
// propClose() {

// setOpen(false);
// },
}));

// 选择数据集、模型


+ 9
- 1
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/dataset/DatasetController.java View File

@@ -1,5 +1,6 @@
package com.ruoyi.platform.controller.dataset;

import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.platform.domain.Dataset;
@@ -54,11 +55,15 @@ public class DatasetController {
public AjaxResult queryByPage(Dataset dataset, @RequestParam("page") int page,
@RequestParam("size") int size,
@RequestParam(value = "available_range") int availableRange ,
@RequestParam(value = "data_type", required = false) String dataType) {
@RequestParam(value = "data_type", required = false) String dataType,
@RequestParam(value = "data_tag", required = false) String dataTag) {

if (dataType != null) { // 仅当dataType有值时设置
dataset.setDataType(dataType);
}
if (dataTag != null) {
dataset.setDataTag(dataTag);
}
dataset.setAvailableRange(availableRange);
PageRequest pageRequest = PageRequest.of(page, size);
return AjaxResult.success(this.datasetService.queryByPage(dataset, pageRequest));
@@ -79,6 +84,9 @@ public class DatasetController {
if (dataType != null) { // 仅当dataType有值时设置
dataset.setDataType(dataType);
}
if (dataTag != null) {
dataset.setDataTag(dataTag);
}
PageRequest pageRequest = PageRequest.of(page, size);
return AjaxResult.success(this.datasetService.queryByPage(dataset, pageRequest));
}


+ 2
- 2
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageController.java View File

@@ -122,7 +122,7 @@ public class ImageController extends BaseController {

@PostMapping("/net")
@ApiOperation("从网络上传构建镜像")
public GenericsAjaxResult<String> createImageFromNet(@RequestParam("name") String imageName,
public GenericsAjaxResult<Map<String, String>> createImageFromNet(@RequestParam("name") String imageName,
@RequestParam("tag") String imageTag,
@RequestParam("path") String path) throws Exception {
return genericsSuccess(this.imageService.createImageFromNet(imageName,imageTag,path));
@@ -130,7 +130,7 @@ public class ImageController extends BaseController {

@PostMapping("/local")
@ApiOperation("从本地上传构建镜像")
public GenericsAjaxResult<String> createImageFromLocal(@RequestParam("name") String imageName,
public GenericsAjaxResult<Map<String, String>> createImageFromLocal(@RequestParam("name") String imageName,
@RequestParam("tag") String imageTag,
@RequestParam("path") String path) throws Exception {
return genericsSuccess(this.imageService.createImageFromLocal(imageName,imageTag,path));


+ 9
- 1
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageVersionController.java View File

@@ -8,8 +8,10 @@ import io.swagger.annotations.ApiOperation;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.Map;

/**
* (ImageVersion)表控制层
@@ -36,11 +38,17 @@ public class ImageVersionController extends BaseController {
*/
@GetMapping
@ApiOperation("分页查询")
public GenericsAjaxResult<Page<ImageVersion>> queryByPage(ImageVersion imageVersion, int page, int size) {
public GenericsAjaxResult<Page<ImageVersion>> queryByPage(ImageVersion imageVersion, @RequestParam("page") int page,
@RequestParam("size") int size,
@RequestParam(value = "image_id") int imageId) {
imageVersion.setImageId(imageId);
PageRequest pageRequest = PageRequest.of(page,size);
return genericsSuccess(this.imageVersionService.queryByPage(imageVersion, pageRequest));

}



/**
* 通过主键查询单条数据
*


+ 3
- 4
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ImageService.java View File

@@ -1,13 +1,11 @@
package com.ruoyi.platform.service;

import com.ruoyi.platform.domain.Image;
import com.ruoyi.platform.domain.Workflow;
import com.ruoyi.platform.vo.ImageVo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.multipart.MultipartFile;

import java.util.Collection;
import java.util.Map;

/**
@@ -69,13 +67,14 @@ public interface ImageService {

/**
* 本地上传构建镜像
*
* @param imageName
* @param imageTag
* @param path
* @return
*/
String createImageFromLocal(String imageName, String imageTag, String path) throws Exception;
String createImageFromNet(String imageName, String imageTag, String NetPath) throws Exception;
Map<String, String> createImageFromLocal(String imageName, String imageTag, String path) throws Exception;
Map<String, String> createImageFromNet(String imageName, String imageTag, String NetPath) throws Exception;
Map<String, String> uploadImageFiles(MultipartFile file) throws Exception;

}

+ 63
- 14
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java View File

@@ -8,6 +8,7 @@ import com.ruoyi.platform.mapper.ImageVersionDao;
import com.ruoyi.platform.service.ImageService;
import com.ruoyi.platform.service.ImageVersionService;
import com.ruoyi.platform.service.MinioService;
import com.ruoyi.platform.utils.FileUtil;
import com.ruoyi.platform.utils.K8sClientUtil;
import com.ruoyi.platform.vo.ImageVo;
import com.ruoyi.system.api.model.LoginUser;
@@ -23,7 +24,9 @@ import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
* (Image)表服务实现类
@@ -171,7 +174,6 @@ public class ImageServiceImpl implements ImageService {
image.setName(imageVo.getName());
image.setDescription(imageVo.getDescription());
image.setImageType(imageVo.getImageType());

Image imageInsert = this.insert(image);
if (imageInsert == null){
throw new Exception("新增镜像失败");
@@ -181,17 +183,50 @@ public class ImageServiceImpl implements ImageService {
imageVersion.setVersion(imageVo.getVersion());
imageVersion.setUrl(imageVo.getUrl());
imageVersion.setTagName(imageVo.getTagName());
//imageVersion.setFileSize(datasetVo.getFileSize());
imageVersion.setFileSize(imageVo.getFileSize());
imageVersion.setStatus("building");
ImageVersion imageVersionInsert = this.imageVersionService.insert(imageVersion);
if (imageVersionInsert == null) {
throw new Exception("新增镜像失败");
}
return "新增镜像成功";
// 使用CompletableFuture异步执行不同的镜像构建逻辑
CompletableFuture.supplyAsync(() -> {
Map<String, String> resultMap = new HashMap<>();
try {
if(imageVo.getUploadType()==0){
resultMap = createImageFromNet(imageVo.getName(), imageVo.getTagName(), imageVo.getPath());
}else{
resultMap = createImageFromLocal(imageVo.getName(), imageVo.getTagName(), imageVo.getPath());
}
} catch (Exception e) {
imageVersion.setStatus("failed");
imageVersionService.update(imageVersion);
throw new RuntimeException("镜像构建失败: " + e.getMessage(), e);
}
return resultMap;
}).thenAccept(resultMap ->{
try {
String imageUrl = resultMap.get("url");
String fileSize = resultMap.get("filesize");
imageVersion.setUrl(imageUrl);
imageVersion.setFileSize(fileSize);
imageVersion.setStatus("available");
imageVersionService.update(imageVersion);
} catch (Exception e) {
System.err.println("更新数据库失败: " + e.getMessage());
}
}).exceptionally(ex -> {
System.err.println("异步操作发生错误: " + ex.getMessage());
return null;
});


return "新增镜像成功,镜像构建中...";
}

@Override
public String createImageFromNet(String imageName, String imageTag, String netPath) throws Exception {
public Map<String, String> createImageFromNet(String imageName, String imageTag, String netPath) throws Exception {
Map<String, String> resultMap = new HashMap<>();
// 得到容器
V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName);
if (pod == null) {
@@ -203,7 +238,7 @@ public class ImageServiceImpl implements ImageService {
// 在这个容器的/data/admin 目录下执行命令 docker load -i fileName 得到返回的镜像名字name:tag
String username = SecurityUtils.getLoginUser().getUsername();
//
String logs2 = k8sClientUtil.executeCommand(pod,"docker pull "+netPath);
String logs2 = k8sClientUtil.executeCommand(pod,"docker pull "+ netPath);
// 在容器里执行 docker tag name:tag nexus3.kube-system.svc:8083/imageName:imageTag
if (StringUtils.isNoneBlank(logs2)){
String substring = logs2.substring(logs2.indexOf(harborUrl), logs2.length());
@@ -211,19 +246,28 @@ public class ImageServiceImpl implements ImageService {
String cmd1 = "docker tag " + cleanedString+ " " + harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag;
String imageUrl = harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag;
String cmd2 = "docker push " + imageUrl;
String cmd3 = "docker inspect --format='{{.Size}}' " + imageUrl;

String s = k8sClientUtil.executeCommand(pod, cmd1);
if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, cmd2))){
return imageUrl;
resultMap.put("url", imageUrl);
//得到镜像文件大小
long sizeInBytes = Long.parseLong(k8sClientUtil.executeCommand(pod, cmd3));
String formattedImageSize = FileUtil.formatFileSize(sizeInBytes); // 格式化镜像文件大小
resultMap.put("fileSize", formattedImageSize);
return resultMap;

}else {
throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址");
throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址");
}
}else {
throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址");
throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址");
}
}

@Override
public String createImageFromLocal(String imageName, String imageTag, String path) throws Exception {
public Map<String, String> createImageFromLocal(String imageName, String imageTag, String path) throws Exception {
Map<String, String> resultMap = new HashMap<>();
// 得到容器
V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName);
if (pod == null) {
@@ -244,11 +288,17 @@ public class ImageServiceImpl implements ImageService {
String cmd1 = "docker tag " + cleanedString+ " " + harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag;
String imageUrl = harborUrl+"/"+repository+"/"+username+"/" + imageName + imageTag;
String cmd2 = "docker push " + imageUrl;
String cmd3 = "docker inspect --format='{{.Size}}' " + imageUrl;
String s = k8sClientUtil.executeCommand(pod, cmd1);
if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, cmd2))){
return imageUrl;
resultMap.put("url", imageUrl);
//得到镜像文件大小
long sizeInBytes = Long.parseLong(k8sClientUtil.executeCommand(pod, cmd3));
String formattedImageSize = FileUtil.formatFileSize(sizeInBytes); // 格式化镜像文件大小
resultMap.put("fileSize", formattedImageSize);
return resultMap;
}else {
throw new Exception("解析镜像压缩包失败,请检查镜像文件");
throw new Exception("解析镜像压缩包失败,请检查镜像文件");
}
}else {
throw new Exception("解析镜像压缩包失败,请检查镜像文件");
@@ -259,7 +309,6 @@ public class ImageServiceImpl implements ImageService {
public Map<String, String> uploadImageFiles(MultipartFile file) throws Exception {
LoginUser loginUser = SecurityUtils.getLoginUser();
String path = loginUser.getUsername()+"/"+file.getOriginalFilename();
Map<String, String> stringMap = minioService.uploadFile(bucketName, path, file);
return stringMap;
return minioService.uploadFile(bucketName, path, file);
}
}

+ 3
- 2
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java View File

@@ -382,9 +382,10 @@ public class K8sClientUtil {
// invokes the CoreV1Api client

for (V1Pod item : v1PodList.getItems()) {
if (item.getMetadata().getGenerateName().startsWith(deploymentName)) {
String generateName = item.getMetadata().getGenerateName();
if (StringUtils.isNotEmpty(generateName) && generateName.startsWith(deploymentName)) {
// 找到匹配的Pod,获取其名称
return item;
return item;
}
}
return null;


+ 29
- 10
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/ImageVo.java View File

@@ -9,10 +9,7 @@ import java.io.Serializable;
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class ImageVo implements Serializable {

/**
* 主键
*/
private Integer id;

/**
* 镜像名称
*/
@@ -58,13 +55,20 @@ public class ImageVo implements Serializable {
@ApiModelProperty(name = "status")
private String status;

public Integer getId() {
return id;
}
@ApiModelProperty(value = "上传方式, 基于公网上传0,基于本地上传1")
private Integer uploadType;

public void setId(Integer id) {
this.id = id;
}
@ApiModelProperty(value = "镜像上传路径")
private String path;


// public Integer getId() {
// return id;
// }
//
// public void setId(Integer id) {
// this.id = id;
// }

public String getName() {
return name;
@@ -129,4 +133,19 @@ public class ImageVo implements Serializable {
public void setStatus(String status) {
this.status = status;
}

public Integer getUploadType() {
return uploadType;
}

public void setUploadType(Integer uploadType) {
this.uploadType = uploadType;
}

public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}

+ 1
- 1
ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ImageDaoMapper.xml View File

@@ -19,7 +19,7 @@
select
id,name,description,image_type,create_by,create_time,update_by,update_time,state
from image
where id = #{id}
where id = #{id} and state = 1
</select>

<!--查询指定行数据-->


Loading…
Cancel
Save