| @@ -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; | |||
| // } | |||
| @@ -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> | |||
| @@ -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> | |||
| @@ -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> | |||
| @@ -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; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -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 | |||
| @@ -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> | |||
| </> | |||
| @@ -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; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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(); | |||
| @@ -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); | |||
| // }, | |||
| })); | |||
| // 选择数据集、模型 | |||
| @@ -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)); | |||
| } | |||
| @@ -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)); | |||
| @@ -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)); | |||
| } | |||
| /** | |||
| * 通过主键查询单条数据 | |||
| * | |||
| @@ -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; | |||
| } | |||
| @@ -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); | |||
| } | |||
| } | |||
| @@ -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; | |||
| @@ -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; | |||
| } | |||
| } | |||
| @@ -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> | |||
| <!--查询指定行数据--> | |||