Commit a208a45b authored by chenshouchao's avatar chenshouchao

Merge branch 'feat-20220801' into 'staging'

Feat 20220801

See merge request !46
parents 537687c6 fcdfe186
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 12</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-12">
<rect id="背景" x="0" y="0" width="16" height="16"></rect>
<g id="项目管理" transform="translate(1.000000, 0.500000)" stroke="#8A9099" stroke-width="1.60714286">
<path d="M9.40680569,0.803571429 L13.1232896,4.61571277 L13.1964286,13.9285714 L1.07142857,14.1964286 L0.803571429,1.07142857 L9.40680569,0.803571429 Z" id="矩形"></path>
<line x1="3.69384615" y1="5.25" x2="8.00153846" y2="5.25" id="路径-2"></line>
<line x1="3.69384615" y1="9.53571429" x2="10.1553846" y2="9.53571429" id="路径-2备份"></line>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 12备份 8</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-12备份-8">
<rect id="背景" x="0" y="0" width="16" height="16"></rect>
<g id="项目管理" transform="translate(1.000000, 0.500000)" stroke="#1370FF" stroke-width="1.60714286">
<path d="M9.40680569,0.803571429 L13.1232896,4.61571277 L13.1964286,13.9285714 L1.07142857,14.1964286 L0.803571429,1.07142857 L9.40680569,0.803571429 Z" id="矩形"></path>
<line x1="3.69384615" y1="5.25" x2="8.00153846" y2="5.25" id="路径-2"></line>
<line x1="3.69384615" y1="9.53571429" x2="10.1553846" y2="9.53571429" id="路径-2备份"></line>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="17px" height="17px" viewBox="0 0 17 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组">
<rect id="矩形备份-4" x="0" y="0.242640687" width="16" height="16"></rect>
<g id="编组-4备份" transform="translate(1.000000, 0.000000)" stroke="#8A9099" stroke-width="1.5">
<rect id="矩形" x="0.75" y="1.99264069" width="4.5" height="4.5" rx="1"></rect>
<rect id="矩形备份-2" x="0.75" y="9.99264069" width="4.5" height="4.5" rx="1"></rect>
<rect id="矩形备份" transform="translate(10.892641, 4.242641) rotate(-45.000000) translate(-10.892641, -4.242641) " x="8.64264069" y="1.99264069" width="4.5" height="4.5" rx="1"></rect>
<rect id="矩形备份-3" x="8.5" y="9.99264069" width="4.5" height="4.5" rx="1"></rect>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="17px" height="17px" viewBox="0 0 17 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组备份 3</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组备份-3">
<rect id="矩形备份-4" x="0" y="0.242640687" width="16" height="16"></rect>
<g id="编组-4备份" transform="translate(1.000000, 0.000000)" stroke="#1370FF" stroke-width="1.5">
<rect id="矩形" x="0.75" y="1.99264069" width="4.5" height="4.5" rx="1"></rect>
<rect id="矩形备份-2" x="0.75" y="9.99264069" width="4.5" height="4.5" rx="1"></rect>
<rect id="矩形备份" transform="translate(10.892641, 4.242641) rotate(-45.000000) translate(-10.892641, -4.242641) " x="8.64264069" y="1.99264069" width="4.5" height="4.5" rx="1"></rect>
<rect id="矩形备份-3" x="8.5" y="9.99264069" width="4.5" height="4.5" rx="1"></rect>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 58</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-56">
<rect id="背景" x="0" y="0" width="16" height="16"></rect>
<g id="项目设置" stroke="#8A9099" stroke-width="1.5">
<path d="M5.58808928,0.759546858 C6.24087167,1.18742985 7.27894484,2.03357391 8.0410091,2.03357391 C8.79391996,2.03357391 9.82900874,1.20312298 10.1257116,0.879260616 L10.1257116,0.879260616 L12.4223498,1.92673302 C12.4838159,2.4170648 12.2821914,2.95405099 12.2821914,3.4239819 C12.2821914,4.19023092 12.5792307,4.88335657 13.0540612,5.3859324 C13.5439168,5.90441126 14.2215221,6.22104975 14.9662484,6.22104975 C15.1008851,6.51473263 15.25,7.34188133 15.25,8.00533082 C15.25,8.66737979 15.1010676,9.49361375 15.0943199,9.53058939 C14.2354924,9.80169918 13.5671599,10.1121377 13.083231,10.6039797 C12.5858984,11.1094446 12.2822113,11.8099862 12.2822113,12.5854135 C12.2822113,13.0633674 12.4859773,13.5981268 12.5031644,13.6416351 L12.5031644,13.6416351 L10.5347562,15.1859987 C9.8023742,14.7872629 8.74070743,13.8890234 7.95899092,13.8890234 C7.23777174,13.8890234 6.20467319,14.6831976 5.82852375,15.113358 L5.82852375,15.113358 L3.57620168,14.0817426 C3.50474061,13.6209845 3.71780868,13.0708966 3.71780868,12.5853924 C3.71780868,11.8193033 3.42075488,11.1262121 2.94586849,10.6236497 C2.45602443,10.1052579 1.77845122,9.7886411 1.03377167,9.7886411 C0.897650311,9.48798028 0.75,8.66482749 0.75,8.0053097 C0.75,7.34441337 0.897848614,6.52032512 0.905715983,6.47853298 C1.76432975,6.20788019 2.43260143,5.89750044 2.91648052,5.40589587 C3.4140514,4.90038092 3.71780868,4.19971123 3.71780868,3.42400299 C3.71780868,2.94206588 3.51060559,2.40259827 3.49603335,2.36594194 L3.49603335,2.36594194 Z" id="路径" fill-rule="nonzero"></path>
<circle id="椭圆形备份" cx="8" cy="8" r="2.45"></circle>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 56备份 2</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-56备份">
<rect id="背景" x="0" y="0" width="16" height="16"></rect>
<g id="项目设置" stroke="#1370FF" stroke-width="1.5">
<path d="M5.58808928,0.759546858 C6.24087167,1.18742985 7.27894484,2.03357391 8.0410091,2.03357391 C8.79391996,2.03357391 9.82900874,1.20312298 10.1257116,0.879260616 L10.1257116,0.879260616 L12.4223498,1.92673302 C12.4838159,2.4170648 12.2821914,2.95405099 12.2821914,3.4239819 C12.2821914,4.19023092 12.5792307,4.88335657 13.0540612,5.3859324 C13.5439168,5.90441126 14.2215221,6.22104975 14.9662484,6.22104975 C15.1008851,6.51473263 15.25,7.34188133 15.25,8.00533082 C15.25,8.66737979 15.1010676,9.49361375 15.0943199,9.53058939 C14.2354924,9.80169918 13.5671599,10.1121377 13.083231,10.6039797 C12.5858984,11.1094446 12.2822113,11.8099862 12.2822113,12.5854135 C12.2822113,13.0633674 12.4859773,13.5981268 12.5031644,13.6416351 L12.5031644,13.6416351 L10.5347562,15.1859987 C9.8023742,14.7872629 8.74070743,13.8890234 7.95899092,13.8890234 C7.23777174,13.8890234 6.20467319,14.6831976 5.82852375,15.113358 L5.82852375,15.113358 L3.57620168,14.0817426 C3.50474061,13.6209845 3.71780868,13.0708966 3.71780868,12.5853924 C3.71780868,11.8193033 3.42075488,11.1262121 2.94586849,10.6236497 C2.45602443,10.1052579 1.77845122,9.7886411 1.03377167,9.7886411 C0.897650311,9.48798028 0.75,8.66482749 0.75,8.0053097 C0.75,7.34441337 0.897848614,6.52032512 0.905715983,6.47853298 C1.76432975,6.20788019 2.43260143,5.89750044 2.91648052,5.40589587 C3.4140514,4.90038092 3.71780868,4.19971123 3.71780868,3.42400299 C3.71780868,2.94206588 3.51060559,2.40259827 3.49603335,2.36594194 L3.49603335,2.36594194 Z" id="路径" fill-rule="nonzero"></path>
<circle id="椭圆形备份" cx="8" cy="8" r="2.45"></circle>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 57</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-57">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="工作台" transform="translate(0.500000, 1.500000)" stroke="#8A9099" stroke-width="1.5">
<rect id="矩形" x="0.75" y="0.75" width="13.5" height="8.5" rx="1"></rect>
<line x1="2.5" y1="12" x2="12.5" y2="12" id="路径-3"></line>
<line x1="11.5" y1="6" x2="6.5" y2="6" id="路径-4备份"></line>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 62</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-62">
<rect id="矩形备份-22" x="0" y="0" width="16" height="16"></rect>
<g id="工作台备份" transform="translate(0.500000, 1.500000)" stroke="#1370FF" stroke-width="1.5">
<rect id="矩形" x="0.75" y="0.75" width="13.5" height="8.5" rx="1"></rect>
<line x1="2.5" y1="12" x2="12.5" y2="12" id="路径-3"></line>
<line x1="11.5" y1="6" x2="6.5" y2="6" id="路径-4备份"></line>
</g>
</g>
</g>
</svg>
\ No newline at end of file
/* 修改滚动条样式 */
div::-webkit-scrollbar,
main::-webkit-scrollbar {
width: 8px;
width: 4px;
height: 5px !important;
}
......@@ -15,11 +15,12 @@ main::-webkit-scrollbar-track {
div::-webkit-scrollbar-thumb,
main::-webkit-scrollbar-thumb {
background-color: #d8d8d8;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
background-color: #C2C6CC;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
height: 5px !important;
width: 4px!important;
}
body,
......
.noDataBox {
background-color: #fff;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
}
.noDataText {
margin-top: 8px;
font-size: 14px;
line-height: 22px;
color: #8a9099;
}
import noFile from "@/assets/project/noFile.svg";
import style from "./index.module.css";
type INoDataProps = {
text?: string;
noDataBoxStyle?: any;
};
const NoData = (props: INoDataProps) => {
return (
<div className={style.noDataBox} style={{ ...props.noDataBoxStyle }}>
<img className={style.noDataImg} src={noFile} alt="" />
<span className={style.noDataText}>
{props.text ? props.text : "暂无数据"}
</span>
</div>
);
};
export default NoData;
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-08-02 11:43:28
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-08-03 14:07:23
* @FilePath: /bkunyun/src/components/BusinessComponents/SearchInput/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import OutlinedInput, { OutlinedInputProps } from "@mui/material/OutlinedInput";
import { ThemeProvider, createTheme } from "@mui/material/styles";
import SearchIcon from "@mui/icons-material/Search";
......@@ -17,7 +25,7 @@ interface SearchInputProps extends OutlinedInputProps {
const SearchInput = (props: SearchInputProps) => {
const {
size = "small",
placeholder = "输入关键词搜索",
placeholder = "输入关键词按回车搜索",
fullWidth = true,
...other
} = props;
......@@ -30,6 +38,9 @@ const SearchInput = (props: SearchInputProps) => {
height: "32px",
fontSize: "14px",
paddingRight: "8px",
"& .MuiOutlinedInput-notchedOutline": {
borderColor: '#DDE1E6',
},
":hover": {
"& .MuiOutlinedInput-notchedOutline": {
borderColor: "#1370ff",
......
......@@ -8,12 +8,9 @@
z-index: 100;
display: flex;
flex-direction: column;
animation: showBG 1s ease;
-webkit-animation: showBG 1s ease;
}
.drawerBoxHidden {
animation: hiddenBG 1s ease;
-webkit-animation: hiddenBG 1s ease;
align-items: center;
animation: showBG 0.31s ease;
-webkit-animation: showBG 0.31s ease;
}
.closeBox {
display: flex;
......@@ -23,13 +20,6 @@
position: fixed;
top: 0;
left: 0;
align-items: center;
animation: showClose 1s ease;
-webkit-animation: showClose 1s ease;
}
.closeBoxHidden {
animation: hiddenClose 1s ease;
-webkit-animation: hiddenClose 1s ease;
}
.closeiIcon {
position: absolute;
......@@ -44,17 +34,14 @@
position: fixed;
top: 40px;
left: 0;
right: 0;
background-color: #fff;
border-radius: 16px 0 0 0;
/* padding: 24px 32px; */
box-sizing: border-box;
overflow: scroll;
animation: showDrawer 1s ease;
-webkit-animation: showDrawer 1s ease;
}
.contentBoxHidden {
animation: hiddenDrawer 1s ease;
-webkit-animation: hiddenDrawer 1s ease;
animation: showDrawer 0.31s ease;
-webkit-animation: showDrawer 0.31s ease;
margin: 0 auto;
}
@keyframes showBG {
......@@ -66,47 +53,15 @@
}
}
@keyframes hiddenBG {
from {
background-color: rgba(0, 0, 0, 0.78);
}
to {
background-color: rgba(0, 0, 0, 0);
}
}
@keyframes showClose {
from {
top: calc(100% - 40px);
}
to {
top: 0px;
}
}
@keyframes hiddenClose {
from {
top: 0px;
}
to {
top: calc(100% - 40px);
}
}
@keyframes showDrawer {
from {
top: 100%;
top: 160px;
width: calc(100vw - 28px);
opacity: 0;
}
to {
top: 40px;
}
}
@keyframes hiddenDrawer {
from {
top: 40px;
}
to {
top: 100%;
width: 100vw;
opacity: 1;
}
}
// 从下往上弹的全屏抽屉
import { useState } from "react";
// import { useState } from "react";
import style from "./index.module.css";
import classNames from "classnames";
import CloseOutlinedIcon from "@mui/icons-material/CloseOutlined";
......@@ -7,30 +7,25 @@ import CloseOutlinedIcon from "@mui/icons-material/CloseOutlined";
type IFullScreenDrawerProps = {
children: React.ReactNode;
handleClose: any;
zIndex?: any;
};
const FullScreenDrawer = (props: IFullScreenDrawerProps) => {
const { children, handleClose } = props;
const [closeing, setCloseing] = useState(false);
const handleReadyToClose = () => {
setCloseing(true);
setTimeout(() => {
setCloseing(false);
handleClose();
}, 1000);
handleClose();
};
return (
<div
className={classNames({
[style.drawerBox]: true,
[style.drawerBoxHidden]: closeing,
})}
style={{ zIndex: props.zIndex }}
>
<div
className={classNames({
[style.closeBox]: true,
[style.closeBoxHidden]: closeing,
})}
>
<CloseOutlinedIcon
......@@ -41,7 +36,6 @@ const FullScreenDrawer = (props: IFullScreenDrawerProps) => {
<div
className={classNames({
[style.contentBox]: true,
[style.contentBoxHidden]: closeing,
})}
>
{children}
......
......@@ -4,29 +4,42 @@
align-items: center;
border: 1px solid #e6e8eb;
border-radius: 4px;
background-color: #e6e8eb;
background-color: #F0F2F5;
cursor: pointer;
height: 32px;
box-sizing: border-box;
padding: 2px;
}
.radio {
position: relative;
min-width: 64px;
height: 28px;
box-sizing: border-box;
font-size: 14px;
color: #565c66;
border-radius: 4px;
border-radius: 2px;
line-height: 20px;
padding: 3px 18px;
background-color: #e6e8eb;
padding: 6px 16px;
/* background-color: #e6e8eb; */
flex: 1;
display: flex;
align-items: center;
justify-content: center;
white-space: nowrap;
}
.radio:not(:last-child)::before {
position: absolute;
width: 1px;
height: 16px;
top: 6px;
right: 0;
content: '';
background-color: #D1D6DE;
}
.radioActive {
color: #1370ff;
background-color: #fff;
border: 1px solid #e6e8eb;
box-shadow: 2px 4px 12px 0px rgba(0,27,63,0.06);
}
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-07-11 11:56:58
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-08-02 17:40:14
* @FilePath: /bkunyun/src/components/CommonComponents/RadioGroupOfButtonStyle/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// 按钮样式的单选组
import classnames from "classnames";
import style from "./index.module.css";
......
import React, { Fragment, ReactNode } from "react";
import React, { Fragment, ReactNode, useMemo } from "react";
import { Snackbar, Alert, Fade, Grow } from "@mui/material";
import useMySnackbar from "./useMySnackbar";
import snackbarContext from "./snackbarContext";
import { ThemeProvider, createTheme } from "@mui/material/styles";
type MySnackbarProviderProp = {
vertical?: "bottom" | "top";
......@@ -42,7 +43,7 @@ const getTransitionComponent = (transition: "grow" | "fade") => {
const MySnackbarProvider = ({
vertical = "top",
horizontal = "center",
autoHideDuration = 5000,
autoHideDuration = 890000,
snackerClasses,
ClickAwayListenerProps,
ContentProps,
......@@ -73,8 +74,44 @@ const MySnackbarProvider = ({
info,
close,
} = useMySnackbar();
// .MuiAlert-filledInfo
const getColorStyle = useMemo(()=>{
if(messageInfo.severity === 'success'){
return '#02AB83'
}
if(messageInfo.severity === 'info'){
return '#1370FF'
}
if(messageInfo.severity === 'warning'){
return '#FFB919'
}
if(messageInfo.severity === 'error'){
return '#FF4E4E'
}
},[messageInfo.severity])
const theme = createTheme({
components: {
MuiAlert: {
styleOverrides: {
root: {
color: getColorStyle,
"& .MuiAlert-icon": {
color: getColorStyle
},
}
},
},
},
});
return (
<Fragment>
<ThemeProvider theme={theme}>
<Snackbar
open={open}
autoHideDuration={autoHideDuration}
......@@ -108,6 +145,7 @@ const MySnackbarProvider = ({
{messageInfo?.content}
</Alert>
</Snackbar>
</ThemeProvider>
<snackbarContext.Provider value={{ success, error, warning, info }}>
{children}
</snackbarContext.Provider>
......
......@@ -10,6 +10,7 @@ import {
ExtendButtonBase,
ButtonTypeMap,
} from "@mui/material";
import LoadingButton from "@mui/lab/LoadingButton";
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
interface ButtonTagProps
......@@ -35,6 +36,8 @@ interface ButtonTagProps
disabled?: boolean; //是否禁用
style?: any; //按钮自定义样式
img?: JSX.Element; //图标按钮中的图标
isLoadingButton?: boolean; // 是否是loadingbutton
loading?: boolean; // 是否处于loading状态
selectCallBack?: (item: any, key: number) => void; //选择按钮的回调
}
......@@ -51,6 +54,9 @@ const theme = createTheme({
color: "rgba(255, 78, 78, 1)",
border: "1px solid rgba(255, 78, 78, 1)",
},
"& .MuiLoadingButton-loadingIndicator": {
color: "#fff",
},
},
contained: {
backgroundColor: "#1370FF",
......@@ -75,6 +81,12 @@ const theme = createTheme({
"&:hover": { backgroundColor: "#ECF4FF " },
},
containedPrimary: {
"&.Mui-disabled": {
backgroundColor: "#A6D3FF",
},
},
containedSecondary: {
backgroundColor: "#FF4E4E",
"&:hover": {
......@@ -126,10 +138,17 @@ const theme = createTheme({
},
},
},
MuiTypography: {
styleOverrides: {
root: {
whiteSpace: "nowrap",
},
},
},
},
});
const ButtonComponent = (props: ButtonTagProps) => {
const MyButton = (props: ButtonTagProps) => {
const {
size,
disabled,
......@@ -138,6 +157,8 @@ const ButtonComponent = (props: ButtonTagProps) => {
img,
select,
selectCallBack,
isLoadingButton,
loading,
...other
} = props;
const { classes, cx } = useStyles({});
......@@ -166,34 +187,68 @@ const ButtonComponent = (props: ButtonTagProps) => {
return (
<ThemeProvider theme={theme}>
<Button
size={size || "medium"}
variant={variant || "contained"}
color={color || "primary"}
disableRipple={true}
disableFocusRipple={true}
disabled={disabled || false}
style={{ ...props.style }}
onClick={props.select ? handleClick : props.onClick || defaultClick}
{...other}
>
{img || ""}
<Typography style={{ fontSize: props.fontSize }}>
{props.text}
</Typography>
{((props.select && props.select.length > 0) || props.drop) && (
<ArrowDropDownIcon
classes={{
root: cx({
[classes.ArrowDropDownIconRoot]: true,
[classes.ArrowDropDownIconRootOpen]: Boolean(
props.dropValue || anchorEl
),
}),
}}
/>
)}
</Button>
{isLoadingButton && (
<LoadingButton
size={size || "medium"}
variant={variant || "contained"}
color={color || "primary"}
disableRipple={true}
disableFocusRipple={true}
disabled={disabled || false}
style={{ ...props.style }}
onClick={props.select ? handleClick : props.onClick || defaultClick}
loading={loading}
{...other}
>
{img || ""}
<Typography style={{ fontSize: props.fontSize }}>
{props.text}
</Typography>
{((props.select && props.select.length > 0) || props.drop) && (
<ArrowDropDownIcon
classes={{
root: cx({
[classes.ArrowDropDownIconRoot]: true,
[classes.ArrowDropDownIconRootOpen]: Boolean(
props.dropValue || anchorEl
),
}),
}}
/>
)}
</LoadingButton>
)}
{!isLoadingButton && (
<Button
size={size || "medium"}
variant={variant || "contained"}
color={color || "primary"}
disableRipple={true}
disableFocusRipple={true}
disabled={disabled || false}
style={{ ...props.style }}
onClick={props.select ? handleClick : props.onClick || defaultClick}
{...other}
>
{img || ""}
<Typography style={{ fontSize: props.fontSize }}>
{props.text}
</Typography>
{((props.select && props.select.length > 0) || props.drop) && (
<ArrowDropDownIcon
classes={{
root: cx({
[classes.ArrowDropDownIconRoot]: true,
[classes.ArrowDropDownIconRootOpen]: Boolean(
props.dropValue || anchorEl
),
}),
}}
/>
)}
</Button>
)}
<Menu
id="simple-menu"
anchorEl={anchorEl}
......@@ -228,4 +283,4 @@ const useStyles = makeStyles<{}>()((theme) => ({
ArrowDropDownIconRootOpen: { color: "#8A9099", transform: "rotate(180deg)" },
}));
export default ButtonComponent;
export default MyButton;
// 局部loading组件
// 使用方法1 用一个div包裹children,在children上加一个蒙层和loading
// <MyCircularProgress loading={loading}>children</MyCircularProgress>
// 使用方法2 挂载在目标块下,目标块最少要添加一个position: relative; 或者absolute
// <div style={{ position: "relative", }} >
// <MyCircularProgress loading={loading}/>
// </div>
import CircularProgress from "@mui/material/CircularProgress";
type IMyCircularProgressProps = {
loading: boolean; // 是否处于loading状态
children?: React.ReactNode; // 包裹的子元素
minHeight?: string;
maxHeight?: string;
zIndex?: number;
};
const MyCircularProgress = (props: IMyCircularProgressProps) => {
const {
loading,
minHeight = "none",
maxHeight = "100vh",
zIndex = "100",
children,
} = props;
if (loading) {
if (children) {
return (
<div
style={{
position: "relative",
}}
>
<div
style={{
width: "100%",
height: "100%",
position: "absolute",
top: 0,
opacity: 0.6,
background: "#fff",
zIndex: zIndex,
}}
></div>
<div
style={{
width: "100%",
height: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
position: "absolute",
top: 0,
zIndex: zIndex,
maxHeight: maxHeight,
}}
>
<CircularProgress></CircularProgress>
</div>
{children}
</div>
);
} else {
return (
<div
style={{
width: "100%",
height: "100%",
position: "absolute",
top: 0,
zIndex: zIndex,
minHeight: minHeight,
}}
>
<div
style={{
width: "100%",
height: "100%",
position: "absolute",
top: 0,
opacity: 0.6,
background: "#fff",
}}
></div>
<div
style={{
width: "100%",
height: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
maxHeight: maxHeight,
}}
>
<CircularProgress></CircularProgress>
</div>
</div>
);
}
} else {
if (children) {
return <>{children}</>;
} else {
return null;
}
}
};
export default MyCircularProgress;
......@@ -43,6 +43,7 @@ export interface IDialogProps {
clickMaskClose?: boolean;
/** 确认按钮样式*/
okSx?: any;
loading?: boolean; // 确认按钮是否处于loading状态
}
const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
......@@ -64,6 +65,7 @@ const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
okText,
disabledConfirm,
clickMaskClose = false,
loading = false,
okSx = {},
} = props;
......@@ -82,13 +84,13 @@ const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
return footerRender ? (
footerRender()
) : (
<DialogActions style={{ padding: "0 24px 24px 24px" }}>
<DialogActions style={{ padding: "0 24px 16px 24px" }}>
{showCancel ? (
<MyButton
text={cancelText || "取消"}
onClick={onClose}
variant="outlined"
size="small"
// size="small"
color="secondary"
/>
) : null}
......@@ -97,8 +99,10 @@ const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
text={okText || "确定"}
onClick={onConfirm}
variant="contained"
size="small"
// size="small"
disabled={disabledConfirm}
isLoadingButton={true}
loading={loading}
style={{ ...okSx }}
/>
) : null}
......@@ -132,15 +136,15 @@ const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
fontWeight: 600,
}}
>
<span>{title}</span>
<span style={{fontSize: 16, lineHeight: '24px', color: '#1E2633'}}>{title}</span>
<CloseIcon
onClick={onClose}
style={{ color: "#C2C6CC", cursor: "pointer" }}
sx={{ color: "#C2C6CC", cursor: "pointer", ":hover": { background: "#f0f2f5", borderRadius:'2px' } }}
/>
</div>
</DialogTitle>
)}
<DialogContent style={{ minWidth: 400 }}>{children}</DialogContent>
<DialogContent style={{ minWidth: 388 }}>{children}</DialogContent>
{Footer()}
</Dialog>
);
......
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-07-05 14:00:37
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-21 17:33:59
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-08-03 14:05:58
* @FilePath: /bkunyun/src/components/mui/MyInput.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -67,6 +67,9 @@ const MyInput = (props: MyInputProps) => {
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
borderWidth: "1px",
},
"& .MuiOutlinedInput-notchedOutline": {
borderColor: '#DDE1E6',
},
":hover": {
"& .MuiOutlinedInput-notchedOutline": error
? {}
......
......@@ -6,7 +6,7 @@ import MyButton from "./MyButton";
import tipsIcon from "@/assets/project/information-outline.svg";
import Popper from "@mui/material/Popper";
interface IMyPopconfirmProps {
interface IMyPopconfirmProps {
title: string | ReactNode;
placement?:
| "auto-end"
......@@ -30,7 +30,7 @@ interface IMyPopconfirmProps {
showCancel?: boolean;
onCancel?: any;
onConfirm?: any;
};
}
const MyPopconfirm = (props: IMyPopconfirmProps) => {
const {
......@@ -75,7 +75,12 @@ const MyPopconfirm = (props: IMyPopconfirmProps) => {
>
<Box sx={{ marginBottom: "16px" }}>
<img
style={{ marginRight: "12px", position: "relative", top: "3px" }}
style={{
width: "16px",
marginRight: "12px",
position: "relative",
top: "3px",
}}
src={tipsIcon}
alt=""
/>
......@@ -85,18 +90,13 @@ const MyPopconfirm = (props: IMyPopconfirmProps) => {
{showCancel && (
<MyButton
text={cancelText}
variant='outlined'
size="small"
variant="outlined"
color="inherit"
onClick={handleCancel}
style={{ marginRight: "12px" }}
/>
)}
<MyButton
text={okText}
size="small"
onClick={handleOk}
/>
<MyButton text={okText} onClick={handleOk} />
</Box>
</Popper>
);
......
......@@ -11,75 +11,75 @@ import Popover, { PopoverProps } from "@mui/material/Popover";
import Typography from "@mui/material/Typography";
interface IProps extends Omit<PopoverProps, "open"> {
/** 触发行为 */
trigger?: "hover" | "click";
/** 触发dom */
children: React.ReactNode;
/** 显示内容 */
content: React.ReactNode;
/** 触发行为 */
trigger?: "hover" | "click";
/** 触发dom */
children: React.ReactNode;
/** 显示内容 */
content: React.ReactNode;
}
const MyPopover = (props: IProps) => {
const [anchorEl, setAnchorEl] = React.useState<any | null>(null);
const [anchorEl, setAnchorEl] = React.useState<any | null>(null);
const {
trigger = "click",
children,
content,
anchorOrigin,
transformOrigin,
} = props;
const {
trigger = "click",
children,
content,
anchorOrigin,
transformOrigin,
} = props;
const handlePopoverOpen = (event: any) => {
setAnchorEl(event.currentTarget);
};
const handlePopoverOpen = (event: any) => {
setAnchorEl(event.currentTarget);
};
const handelClick = (event: any) => {
setAnchorEl(event?.currentTarget);
};
const handelClick = (event: any) => {
setAnchorEl(event?.currentTarget);
};
const handlePopoverClose = () => {
setAnchorEl(null);
};
const handlePopoverClose = () => {
setAnchorEl(null);
};
const open = Boolean(anchorEl);
const id = open ? "simple-popover" : undefined;
const open = Boolean(anchorEl);
const id = open ? "simple-popover" : undefined;
return (
<div>
<Typography
aria-owns={id}
onClick={trigger === "click" ? handelClick : undefined}
onMouseEnter={trigger === "hover" ? handlePopoverOpen : undefined}
onMouseLeave={trigger === "hover" ? handlePopoverClose : undefined}
>
{children}
</Typography>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handlePopoverClose}
sx={{
pointerEvents: trigger === "hover" ? "none" : undefined,
}}
anchorOrigin={
anchorOrigin || {
vertical: "bottom",
horizontal: "center",
}
}
transformOrigin={
transformOrigin || {
vertical: "top",
horizontal: "center",
}
}
>
<Typography sx={{ p: 1 }}>{content}</Typography>
</Popover>
</div>
);
return (
<div>
<Typography
aria-owns={id}
onClick={trigger === "click" ? handelClick : undefined}
onMouseEnter={trigger === "hover" ? handlePopoverOpen : undefined}
onMouseLeave={trigger === "hover" ? handlePopoverClose : undefined}
>
{children}
</Typography>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handlePopoverClose}
sx={{
pointerEvents: trigger === "hover" ? "none" : undefined,
}}
anchorOrigin={
anchorOrigin || {
vertical: "bottom",
horizontal: "center",
}
}
transformOrigin={
transformOrigin || {
vertical: "top",
horizontal: "center",
}
}
>
<Typography sx={{ p: 1 }}>{content}</Typography>
</Popover>
</div>
);
};
export default MyPopover;
......@@ -69,14 +69,14 @@ const Tabs = (props: IProps) => {
tabList,
defaultValue,
allowNullValue = false,
tabPanelSx = { padding: "20px 0 0 0" },
tabPanelSx = { padding: "24px 0 0 0" },
} = props;
const [value, setValue] = useState(
defaultValue
? defaultValue
: allowNullValue
? ""
: tabList.filter((e) => !e.hide)[0].value
? ""
: tabList.filter((e) => !e.hide)[0].value
);
const onChange = (val: string) => {
......@@ -88,14 +88,14 @@ const Tabs = (props: IProps) => {
<Box style={{ display: "flex", alignItems: "center" }}>
{item.icon ? (
<img
style={{ width: "14px", marginRight: "10px" }}
style={{ width: "16px", marginRight: "8px" }}
src={value === item.value ? item.iconed : item.icon}
alt=""
/>
) : (
""
)}
<Typography sx={{ fontSize: "14px", fontWeight: "400" }}>
<Typography sx={{ fontSize: "14px", lineHeight: "22px", height: "22px", fontWeight: "400" }}>
{item.label}
</Typography>
</Box>
......
......@@ -113,3 +113,16 @@ export const getUrlThroughParams = (params: any, encodeArr: Array<string> = [],
})
return url
}
// 判断上拉滚动是否需要加载 scrollLoaderThreshold 加载阈值 如0.25表示 离底部四分之一高度(包裹盒子的高)触发加载
export const getScrollLoader = (e: any, scrollLoaderThreshold: number = 0.25) => {
const clientHeight = e.target.clientHeight; // 滚动的外层盒子高度
const scrollHeight = e.target.scrollHeight; // 列表总高度
const scrollTop = e.target.scrollTop; // 滚动的高度
if (scrollTop + clientHeight * (1+scrollLoaderThreshold)> scrollHeight) {
return true
} else {
return false
}
}
\ No newline at end of file
......@@ -120,7 +120,7 @@ const FileItem = observer((props: IProps) => {
width: 300,
margin: "6px 0",
}}
color="error"
color="success"
value={itemInfo?.percentage}
/>
) : null}
......
......@@ -13,10 +13,26 @@
}
.logo {
padding: 0px 25px 0px 20px;
padding: 0px 16px 0px 20px;
margin-top: -10px;
}
.uploadIconBox{
width: 32px;
height: 32px;
display: flex;
justify-content: center;
align-items: center;
margin-right: 16px;
}
.uploadIconBox:hover{
background-color: #f0f2f5;
border-radius: 2px;
cursor: pointer;
}
.topRightBox {
display: flex;
justify-content: flex-end;
......
......@@ -5,6 +5,7 @@ import { observer } from "mobx-react-lite";
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
import Avatar from "@mui/material/Avatar";
import { Box, Menu, MenuItem } from "@mui/material";
import classNames from "classnames";
import uploadIcon from "@/assets/img/uploadIcon.svg";
import globalText from "@/utils/globalText_CN";
......@@ -20,6 +21,7 @@ import {
setFileServerEndPointLocalStorage,
getFiletokenAccordingToId,
} from "@/views/Project/project";
import style from "./index.module.css";
const ConsoleLayout = observer(() => {
......@@ -92,7 +94,7 @@ const ConsoleLayout = observer(() => {
<MyButton
text={globalText.product}
variant={"text"}
style={{ color: "#565C66" }}
style={{ color: "#565C66", paddingLeft: '8px' }}
onClick={handleProductClick}
dropValue={productOpen}
drop={true}
......@@ -143,12 +145,14 @@ const ConsoleLayout = observer(() => {
horizontal: "right",
}}
>
<img
className={style.topRightItem}
src={uploadIcon}
alt=""
style={{ verticalAlign: "middle" }}
/>
<div className={classNames(style.uploadIconBox)}>
<img
src={uploadIcon}
alt=""
style={{ verticalAlign: "middle" }}
/>
</div>
</MyPopover>
<Box className={style.topRightItem}>
<Box
......@@ -209,4 +213,4 @@ const ConsoleLayout = observer(() => {
);
});
export default ConsoleLayout;
export default ConsoleLayout;
\ No newline at end of file
.operatorList {
width: 226px;
height: calc(100% - 40px);
position: absolute;
top: 16px;
left: 16px;
background-color: #fff;
z-index: 10;
}
.searchBox {
height: 54px;
border-bottom: 1px solid rgba(240, 242, 245, 1);
box-sizing: border-box;
padding: 16px;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.searchButton {
width: 22px;
height: 22px;
}
.searchIcon {
color: #999999;
}
.searchInput {
margin: 0 6px;
flex: 1;
color: #1e2633;
font-size: 14px;
line-height: 22px;
}
.list {
height: calc(100% - 55px);
overflow-y: auto;
padding: 15px 20px;
box-sizing: border-box;
}
.li {
background-color: RGBA(240, 242, 245, 1);
padding: 7px 7px 7px 28px;
color: rgba(30, 38, 51, 1);
font-size: 14px;
line-height: 22px;
margin-bottom: 12px;
position: relative;
}
.name {
margin-right: 8px;
}
.icon {
width: 6px;
height: 10px;
position: absolute;
top: 13px;
left: 9px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.iconLi {
display: flex;
justify-content: space-between;
}
.iconItem {
width: 2px;
height: 2px;
background-color: rgba(86, 92, 102, 1);
}
import { InputBase, IconButton } from "@mui/material";
import SearchIcon from "@mui/icons-material/Search";
import styles from "./index.module.css";
import { getScrollLoader } from "@/utils/util";
import { useState } from "react";
const OperatorList = () => {
const [name, setName] = useState("");
const nameChange = (e: any) => {
setName(e.target.value);
};
const list = [
{
name: "这是中文",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
{
name: "asdf",
version: "1.0.0",
},
];
window.onscroll = (e) => {
console.log(e);
};
const handleScroll = (e: any) => {
console.log(e);
if (getScrollLoader(e)) {
console.log("加载");
}
};
const randerIcon = () => {
return (
<div className={styles.icon}>
<div className={styles.iconLi}>
<div className={styles.iconItem}></div>
<div className={styles.iconItem}></div>
</div>
<div className={styles.iconLi}>
<div className={styles.iconItem}></div>
<div className={styles.iconItem}></div>
</div>
<div className={styles.iconLi}>
<div className={styles.iconItem}></div>
<div className={styles.iconItem}></div>
</div>
</div>
);
};
return (
<div className={styles.operatorList}>
<div className={styles.searchBox}>
<IconButton
type="submit"
className={styles.searchButton}
aria-label="search"
>
<SearchIcon
className={styles.searchIcon}
style={{ color: "rgba(153, 153, 153, 1)" }}
/>
</IconButton>
<InputBase
className={styles.searchInput}
placeholder="请输入算子名称"
value={name}
onChange={nameChange}
/>
</div>
<div className={styles.list} onScroll={(e) => handleScroll(e)}>
{list.map((item, index) => {
return (
<div key={index} className={styles.li}>
{randerIcon()}
<span className={styles.name}>{item.name}</span>
<span className={styles.version}>{item.version}</span>
</div>
);
})}
</div>
</div>
);
};
export default OperatorList;
.customOperator {
padding: 4px 32px 24px;
background-color: #fff;
display: flex;
flex-direction: column;
height: 100%;
box-sizing: border-box;
}
.coTop {
display: flex;
justify-content: space-between;
padding: 17px 0;
}
.coTitle {
color: rgba(30, 38, 51, 1);
font-size: 18px;
line-height: 26px;
font-weight: 600;
}
.coContent {
flex: 1;
background-color: RGBA(247, 248, 250, 1);
position: relative;
}
import React, { useCallback, useEffect, useState } from "react";
import { observer } from "mobx-react-lite";
import FullScreenDrawer from "@/components/CommonComponents/FullScreenDrawer";
import MyButton from "@/components/mui/MyButton";
import OperatorList from "./components/OperatorList";
import Flow from "../Project/components/Flow";
import styles from "./index.module.css";
type IProps = {
setShowCustomOperator: any;
};
const CustomOperator = observer((props: IProps) => {
const { setShowCustomOperator } = props;
// const [showCustomOperator, setShowCustomOperator] = useState(false);
return (
<FullScreenDrawer handleClose={setShowCustomOperator} zIndex={1100}>
<div className={styles.customOperator}>
<div className={styles.coTop}>
<div className={styles.coTitle}>添加算子</div>
<MyButton text="添加"></MyButton>
</div>
<div className={styles.coContent}>
<OperatorList />
<Flow
showControls={false}
// tasks={templateConfigInfo}
// setTasks={setTemplateConfigInfo}
type="edit"
// onFlowNodeClick={handleNodeClick}
// ListenState={!saveFormDialog}
/>
</div>
</div>
</FullScreenDrawer>
);
});
export default CustomOperator;
......@@ -27,6 +27,12 @@
.listItem:hover {
background-color: #EEF1F5;
}
.routerIcon{
vertical-align: middle;
margin-right: 12px;
line-height: 22px;
}
.active {
border-left: 3px solid #1370ff;
color: #1370ff;
......
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-08-02 11:43:28
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-08-03 19:05:48
* @FilePath: /bkunyun/src/views/MenuLayout/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { Box, List } from "@mui/material";
import CurrentProject from "../Project/components/CurrentProject";
import React from "react";
......@@ -21,11 +29,25 @@ const MenuLayout = observer(() => {
navigate("/home");
}
const routerIcon = (id: string, isSelect: boolean) => {
try {
const result = require(`../../assets/project/${id}${isSelect ? '_BLUE' : ''}.svg`)
return result || ''
} catch (error) {
console.log(error)
}
}
return (
<Box className={style.container}>
<Box className={style.aside}>
<CurrentProject />
<List>
<List
sx={{
paddingTop: 0,
paddingBottom: 0,
}}
>
{permissionStore.sidebarRouters.map((item, index) => {
if (item.show) {
return (
......@@ -37,7 +59,8 @@ const MenuLayout = observer(() => {
})}
onClick={() => item.type === "page" && navigate(item.path)}
>
{item.name}
<img className={style.routerIcon} src={routerIcon(item.id || '', `/v3${item.path}` === pathname) || undefined} alt='' />
<span style={{ verticalAlign: 'middle' }}>{item.name}</span>
</li>
);
}
......
......@@ -60,7 +60,9 @@ const AddFolder = (props: IAddFolderProps) => {
const handleFileNameChange = (e: any) => {
const fileName = e.target.value;
setFileName(fileName);
if (fileName.length <= 30) {
setFileName(fileName);
}
if (!fileName) {
setFileNameCheck({
error: true,
......@@ -123,7 +125,7 @@ const AddFolder = (props: IAddFolderProps) => {
helperText={fileNameCheck.help}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<InputAdornment position="end" style={{ color: fileName.length >= 30 ? "#d32f2f" : "#C2C6CC" }}>
{fileName.length}/30
</InputAdornment>
),
......
......@@ -12,6 +12,9 @@
font-weight: 600;
margin-bottom: 24px;
}
.projectDataHeader {
position: relative;
}
.projectDataButtonAndSearch {
display: flex;
justify-content: space-between;
......
......@@ -2,7 +2,6 @@ import React, { useState, useCallback, useEffect, useMemo } from "react";
import style from "./index.module.css";
import classnames from "classnames";
import { IconButton } from "@mui/material";
import SearchIcon from "@mui/icons-material/Search";
import RefreshIcon from "@mui/icons-material/Refresh";
import MyTable from "@/components/mui/MyTable";
import dataSetIcon from "@/assets/project/dataSetIcon.svg";
......@@ -26,7 +25,6 @@ import { useLocation } from "react-router-dom";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import SeeDataset from "./SeeDataset";
import { getDataFind, getDataFileSearch } from "@/api/project_api";
import MyInput from "@/components/mui/MyInput";
import MyButton from "@/components/mui/MyButton";
import SearchInput from "@/components/BusinessComponents/SearchInput";
......@@ -491,10 +489,10 @@ const ProjectData = observer(() => {
{index === 0
? "ProjectData"
: index > pathArr.length - 4
? item
: ""}
? item
: ""}
{index === pathArr.length - 1 ||
(index <= pathArr.length - 4 && index > 0) ? null : (
(index <= pathArr.length - 4 && index > 0) ? null : (
<i className={style.showPathI}>{">"}</i>
)}
{index === 1 && "..."}
......@@ -558,7 +556,10 @@ const ProjectData = observer(() => {
size="small"
onClick={handleRefresh}
disabled={!isPass("PROJECT_DATA_REFRESH", "USER")}
sx={{ marginLeft: "17px" }}
sx={{ marginLeft: "17px", width: '32px', height: '32px', ":hover": {
backgroundColor: "#F0F2F5 ",
borderRadius: 2
} }}
>
<RefreshIcon sx={{ fontSize: "18px" }} />
</IconButton>
......
......@@ -6,7 +6,7 @@
width: 100vw;
height: 100vh;
background-color: RGBA(247, 248, 250, 1);
overflow-y: scroll;
overflow-y: auto;
}
.swHeader {
z-index: 1001;
......
......@@ -14,7 +14,7 @@ import { useLocation, useNavigate } from "react-router-dom";
import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew";
import IconButton from "@mui/material/IconButton";
import ButtonComponent from "@/components/mui/MyButton";
import MyButton from "@/components/mui/MyButton";
import useMyRequest from "@/hooks/useMyRequest";
import { fetchWorkFlowJob, getworkFlowTaskInfo } from "@/api/project_api";
import { IResponse } from "@/api/http";
......@@ -352,7 +352,7 @@ const ProjectSubmitWork = observer(() => {
state === "RUNNING" ? onStopJob() : onDeleteJob();
}}
> */}
<ButtonComponent
<MyButton
text={state === "RUNNING" ? "终止" : "删除"}
variant="outlined"
color="secondary"
......@@ -365,7 +365,7 @@ const ProjectSubmitWork = observer(() => {
)
}
// click={onStopJob}
></ButtonComponent>
></MyButton>
{/* </MyPopconfirm> */}
</div>
)}
......
......@@ -36,11 +36,17 @@
}
.taskName {
min-width: 100px;
font-size: 14px;
line-height: 22px;
font-weight: 500;
cursor: pointer;
}
.taskName:hover{
color: #1370FF;
}
.taskStatus {
display: flex;
align-items: center;
......@@ -59,12 +65,13 @@
.taskCreator {
font-size: 12px;
line-height: 20px;
color: #1E2633;
margin-top: 5px;
margin-top: 4px;
}
.taskProgress {
height: 40px;
height: 32px;
margin: 12px 0;
}
......
.basicInformation {
display: flex;
justify-content: space-between;
margin: 28px 24px 0 24px;
margin: 24px 24px 0 24px;
padding-bottom: 20px;
border-bottom: 1px solid #F0F2F5;
}
......@@ -14,12 +14,13 @@
.titleBox {
display: flex;
align-items: center;
align-items: flex-end;
}
.projectName {
margin-left: 12px;
font-size: 18px;
line-height: 26px;
font-weight: 600;
}
......@@ -39,6 +40,8 @@
}
.otherInformationBoxRight{
line-height: 22px;
margin-bottom: 4px;
color: #565C66;
}
......@@ -51,15 +54,15 @@
.verticalLine {
height: 32px;
border: 1px solid #EBEDF0;
margin-left: 20px;
margin-right: 20px;
border-right: 1px solid #EBEDF0;
margin-left: 28px;
margin-right: 28px;
}
.searchBox {
display: flex;
justify-content: space-between;
margin: 28px 24px 0 24px;
margin: 24px 24px 0 24px;
}
.searchLineLeft {
......
......@@ -43,6 +43,7 @@ const ProjectOverview = observer(() => {
setTaskList(result.data.content);
},
});
useEffect(() => {
if (currentProjectStore.currentProjectInfo.id) {
getOverview({
......@@ -69,6 +70,10 @@ const ProjectOverview = observer(() => {
}
}
const handleKeyWordChangeBlur=(e:any)=>{
setJobName(e.target.value);
}
const storageUnitFromB = (b: number) => {
if (b <= 0) {
return { data: '0.00', unit: 'KB' };
......@@ -142,6 +147,7 @@ const ProjectOverview = observer(() => {
</div>
<SearchInput
onKeyUp={handleKeyWordChangeKeyUp}
onBlur={handleKeyWordChangeBlur}
sx={{ width: 340 }}
/>
</div>
......
......@@ -41,6 +41,7 @@
height: 82px;
padding: 7px 12px;
resize: none;
font-size: 14px;
}
.projectInfoSelect {
width: 560px;
......
......@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-07-26 20:39:32
* @LastEditTime: 2022-07-28 18:32:03
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -196,7 +196,15 @@ const BaseInfo = observer(() => {
const checkBudget = (budget: string, showMessage = false) => {
let help = "";
if (budget) {
if (budget.indexOf(" ") !== -1) {
help = "格式错误,请输入0~10000000之间的数值,结果最高保留两位小数。";
setBudgetCheck({
error: true,
help,
});
showMessage && message.error(help);
return false;
} else if (budget) {
if (isNaN(Number(budget)) || Number(budget) > 10000000 || Number(budget) < 0) {
help = "格式错误,请输入0~10000000之间的数值,结果最高保留两位小数。";
setBudgetCheck({
......@@ -232,10 +240,12 @@ const BaseInfo = observer(() => {
}
const budgetBlur = (e: any) => {
setProjectInfo({
...projectInfo,
projectBudget: Number(e.target.value) ? Number(e.target.value).toFixed(2) : e.target.value,
});
if (e.target.value.indexOf(" ") == -1 && e.target.value) {
setProjectInfo({
...projectInfo,
projectBudget: Number(e.target.value) || Number(e.target.value) == 0 ? Number(e.target.value).toFixed(2) : e.target.value,
});
}
};
const { run: updateProjectRun, loading: updateLoading } = useMyRequest(
......@@ -318,7 +328,8 @@ const BaseInfo = observer(() => {
>
项目名称
</div>
<TextField
<MyInput
required
error={nameCheck.error}
id="name"
......@@ -326,21 +337,8 @@ const BaseInfo = observer(() => {
value={projectInfo.name}
onChange={nameChange}
helperText={nameCheck.help}
size="small"
sx={{
width: "560px",
"& .MuiOutlinedInput-root": {
height: "36px",
},
}}
style={{ width: "560px" }}
/>
{/* <input
value={projectInfo.name}
className={style.projectInfoListLiValue}
onChange={nameChange}
maxLength={30}
placeholder="请输入项目名称"
></input> */}
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>项目描述</div>
......@@ -354,6 +352,13 @@ const BaseInfo = observer(() => {
placeholder="项目描述限制100字以内"
maxLength={100}
></textarea>
{/* <MyInput
value={projectInfo.desc}
multiline
rows={4}
placeholder="项目描述限制100字以内"
onChange={descChange}
/> */}
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>计算区</div>
......@@ -375,59 +380,48 @@ const BaseInfo = observer(() => {
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>创建人</div>
<input
<MyInput
value={projectInfo.owner}
disabled
className={classnames({
[style.projectInfoListLiValue]: true,
[style.disable]: true,
})}
></input>
style={{ width: "560px" }}
/>
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>项目预算</div>
{/* <MyInput
sx={{
width: "560px",
'& .MuiOutlinedInput-root': {
height: '36px'
}
}}
/> */}
<TextField
<MyInput
required
error={budgetCheck.error}
disabled={currentUserName !== projectInfo.tenantUser}
id="projectBudget"
// id="projectBudget"
variant="outlined"
value={projectInfo.projectBudget}
onChange={budgetChange}
onBlur={budgetBlur}
helperText={budgetCheck.help}
size="small"
sx={{
width: "560px",
"& .MuiOutlinedInput-root": {
height: "36px",
},
}}
// size="small"
style={{ width: "560px" }}
InputProps={{
startAdornment: (
<InputAdornment position="start">¥</InputAdornment>
),
}}
sx={{
"& .MuiOutlinedInput-input": {
padding: "6.5px 2px",
},
"& .MuiTypography-root": {
fontSize: '14px'
}
}}
/>
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>扣费账号</div>
<input
<MyInput
value={projectInfo.tenantUser}
disabled
className={classnames({
[style.projectInfoListLiValue]: true,
[style.disable]: true,
})}
></input>
style={{ width: "560px" }}
/>
</div>
<div className={style.projectInfoListLi}>
<LoadingButton
......
......@@ -2,23 +2,24 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-07-26 11:13:10
* @LastEditTime: 2022-08-03 14:29:19
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { toJS } from "mobx";
import { observer } from "mobx-react-lite";
import _ from "lodash";
import Dialog from "@/components/mui/MyDialog";
import { memo, useCallback, useEffect, useMemo, useState } from "react";
import { Box, OutlinedInput } from "@mui/material";
import SearchIcon from "@mui/icons-material/Search";
import Dialog from "@/components/mui/MyDialog";
import { IResponse, useHttp } from "@/api/http";
import { useStores } from "@/store";
import { useMessage } from "@/components/MySnackbar";
import MySelect, { IOption } from "@/components/mui/MySelect";
import MyTable from "@/components/mui/MyTable";
import SearchInput from "@/components/BusinessComponents/SearchInput";
interface IProps {
setAddMemberDialog: (val: boolean) => void;
addMemberDialog: boolean;
......@@ -145,7 +146,7 @@ const AddMember = observer((props: IProps) => {
}
});
} else {
Message.warning("请先选择项目成员!");
Message.info("请先选择项目成员!");
}
};
......@@ -158,19 +159,15 @@ const AddMember = observer((props: IProps) => {
title="添加成员"
>
<Box>
<Box sx={{ mb: 2 }}>
<OutlinedInput
onChange={(e: any) => {
_.debounce(() => {
setProjectMember(e.target.value);
}, 200)();
}}
placeholder="搜索项目成员"
size="small"
sx={{ width: "100%", height: 32 }}
endAdornment={<SearchIcon style={{ color: "#8A9099" }} />}
/>
</Box>
<SearchInput
onKeyUp={(e: any) => {
if (e.keyCode === 13) {
setProjectMember(e.target.value);
}
}}
placeholder="搜索项目成员"
sx={{ mb: 2 }}
/>
<div style={{ overflowY: "scroll", maxHeight: 400 }}>
<MyTable
checkboxData={(val: string[]) => setCheckData(val)}
......
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-21 11:34:55
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-07-29 11:28:09
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -94,6 +94,7 @@ const ChangePermission = observer((props: IProps) => {
>
<div style={{ marginTop: 12 }}>
<MySelect
fullWidth
title="项目权限"
isTitle={true}
value={selectValue}
......
......@@ -154,7 +154,7 @@ const ProjectMembers = observer(() => {
<Box className={styles.headerBox}>
<SearchInput
onKeyUp={handleKeyWordChangeKeyUp}
placeholder="搜索项目成员"
placeholder="输入项目成员按回车搜索"
sx={{ width: 340 }}
/>
{currentProjectStore?.currentProjectInfo?.projectRole === "OWNER" ? (
......
.swBox {
position: fixed;
z-index: 1000;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: RGBA(247, 248, 250, 1);
overflow-y: scroll;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: RGBA(247, 248, 250, 1);
overflow-y: auto;
}
.swHeader {
z-index: 1001;
position: sticky;
top: 0;
height: 56px;
background-color: #fff;
box-shadow: 0px 3px 10px 0px rgba(0, 24, 57, 0.04);
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
z-index: 1001;
position: sticky;
top: 0;
height: 56px;
background-color: #fff;
box-shadow: 0px 3px 10px 0px rgba(0, 24, 57, 0.04);
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
}
.swHeaderLeft {
display: flex;
justify-content: flex-start;
align-items: center;
display: flex;
justify-content: flex-start;
align-items: center;
}
.swTemplateTitle {
margin: 0 19px 0 8px;
line-height: 22px;
font-size: 14px;
color: rgba(30, 38, 51, 1);
font-weight: 600;
padding-right: 20px;
border-right: 1px solid rgba(235, 237, 240, 1);
margin: 0 19px 0 8px;
line-height: 22px;
font-size: 14px;
color: rgba(30, 38, 51, 1);
font-weight: 600;
padding-right: 20px;
border-right: 1px solid rgba(235, 237, 240, 1);
}
.swHeaderLable {
color: rgba(138, 144, 153, 1);
font-size: 12px;
color: rgba(138, 144, 153, 1);
font-size: 12px;
}
.swHeaderValue {
color: rgba(30, 38, 51, 1);
font-size: 12px;
margin-right: 24px;
color: rgba(30, 38, 51, 1);
font-size: 12px;
margin-right: 24px;
}
.swContent {
display: flex;
height: calc(100vh - 56px);
display: flex;
height: calc(100vh - 56px);
}
.swFormBox {
background-color: #fff;
border-right: 1xp solid rgba(235, 237, 240, 1);
width: 608px;
overflow-y: scroll;
box-sizing: border-box;
padding: 36px;
background-color: #fff;
border-right: 1xp solid rgba(235, 237, 240, 1);
width: 608px;
overflow-y: scroll;
box-sizing: border-box;
padding: 36px;
}
.swFlowBox {
flex: 1;
height: calc(100vh - 56px);
flex: 1;
height: calc(100vh - 56px);
}
.fullScreenBox {
position: absolute;
background-color: #fff;
cursor: pointer;
z-index: 1000;
right: 24px;
bottom: 24px;
padding: 8px;
position: absolute;
background-color: #fff;
cursor: pointer;
z-index: 1000;
right: 24px;
bottom: 24px;
padding: 8px;
}
.fullScreenBox:hover {
opacity: 0.6;
}
\ No newline at end of file
opacity: 0.6;
}
......@@ -16,7 +16,7 @@ import moment from "moment";
import ConfigForm from "./ConfigForm";
import WorkFlow from "./WorkFlow";
import ButtonComponent from "@/components/mui/MyButton";
import MyButton from "@/components/mui/MyButton";
import { ITemplateConfig } from "./interface";
import useMyRequest from "@/hooks/useMyRequest";
import { fetchTemplateConfigInfo, submitWorkFlow } from "@/api/project_api";
......@@ -272,12 +272,12 @@ const ProjectSubmitWork = observer(() => {
title="提交前请先确认参数填写无误,确认提交吗?"
onConfirm={handleSubmitForm}
> */}
<ButtonComponent
<MyButton
text="提交任务"
onClick={(e: any) =>
handleShowPopper(e, "提交前请先确认参数填写无误,确认提交吗?")
}
></ButtonComponent>
></MyButton>
{/* </MyPopconfirm> */}
</div>
</div>
......
......@@ -8,66 +8,66 @@
*/
type IType = "BATCH" | "FLOW";
export interface IParameter {
hidden: boolean;
hidden: boolean; // 使用模板时是否展示 true 不展示 用户不需要填写
id?: string;
name: string;
required: boolean;
defaultValue: any;
domType: IDomType;
classType: string;
classTypeName: string;
value: any;
description: string;
language: string;
languageVersion: string;
name: string; // 参数名称
required: boolean; // 是否必填
defaultValue: any; // 默认值
domType: IDomType; // 前端组件类型
classType: string; // 后端数据类型
classTypeName: string; // 前端展示的数据类型 classType对应的描述
value: any; // 值
description: string; // 该参数的描述、解释
language: string; //
languageVersion: string; //
tags: Array<string>;
source: string;
productId: string;
// tasks: ITask[];
linked?: boolean;
validators: Array<IValidator>;
choices: Array<IChoice>;
error?: boolean;
helperText?: string;
parameterGroup?: string;
validators: Array<IValidator>; // 校验方式的数组, 有正则和对应的提示语
choices: Array<IChoice>; // 提供给用户选择的选项组
error?: boolean; // 表单校验是否通过
helperText?: string; // 表单校验提示文案
parameterGroup?: string; //
}
export type IExecutionStatus = "Pending" | "Running" | "Done" | "Failed";
export interface ITask {
id: string;
title: string;
description: string;
version?: string;
allVersions?: string[]
position: {
title: string; // 批流算子名称
description: string; // 描述
version?: string; // 版本
allVersions?: string[]; // 全部版本
position: { // 流程图位置信息
x: number;
y: number;
};
tags?: string[];
type: IType | string;
parentNode?: string;
parameters: Array<IParameter>;
type: IType | string; // 算子类型(批算子、流算子)
parentNode?: string; //
parameters: Array<IParameter>; // 参数组
edges: Array<IEdge>;
isCheck?: boolean;
executionStatus?: IExecutionStatus;
isCheck?: boolean; // 表单校验是否通过
executionStatus?: IExecutionStatus; // 算子的状态
}
export interface ITemplateConfig {
title: string;
version: string;
updateTime?: string;
description: string;
export interface ITemplateConfig { // 模板信息
title: string; // 标题
version: string; // 版本
updateTime?: string; // 更新时间
description: string; // 模板描述
language: string;
languageVersion: string;
tags: Array<string>;
source: string;
productId: string;
tasks: ITask[];
productId: string; // 产品id
tasks: ITask[]; // 算子组
id: string;
}
export type IDomType =
export type IDomType = // 前端组件类型
| "path"
| "dataset"
| "file"
......@@ -78,12 +78,12 @@ export type IDomType =
| "checkbox";
// 待定
export type IValidator = {
export type IValidator = { // 表单校验中的一项
regex: string;
message: string;
};
export interface IChoice {
export interface IChoice { // 表单选项中的一项
label: string;
value: string;
}
......@@ -98,7 +98,7 @@ export interface IEdge {
}
// 提交任务时的动态表单的数据结构
export type IRenderTasks = Array<IRenderTask>;
export type IRenderTasks = Array<IRenderTask>; // 将批算子、流算子、批算子下的流算子混合在一起的一维数组转换成批算子、流算子的二维数组
export type IRenderTask = {
id: string;
title: string;
......@@ -114,18 +114,19 @@ export type IRenderTask = {
isCheck: boolean; // 里面的子项表单校验是否全部通过
};
// 工作流详情
export interface ITaskInfo extends ITemplateConfig {
name: string;
outputPath: string;
state: IState;
specTitle: string;
specVersion: string;
jobCost: string;
creator: string;
createTime: string;
costTime: string;
logPath: string;
outputs?: any;
name: string; // 任务(工作流)名称
outputPath: string; // 任务结果 输出文件路径
state: IState; // 任务状态
specTitle: string; // 源模板
specVersion: string; // 源模板版本
jobCost: string; // 花费(元)
creator: string; // 创建人
createTime: string; // 创建时间
costTime: string; // 运行时间
logPath: string; // 日志文件
outputs?: any; // 结果文件
}
type IState = "SUCCEEDED" | "RUNNING" | "ABORTED" | "FAILED";
......@@ -63,10 +63,9 @@ const ProjectWorkbench = observer(() => {
}, [isPass]);
return (
<div style={{ padding: 24 }}>
<div style={{ padding:'28px 24px 24px' }}>
<div style={{ display: "flex", alignItems: "center" }}>
<img src={projectImg} alt="项目logo" />
<span style={{ marginLeft: 12 }}>工作台</span>
<span style={{ fontSize: "18px", lineHeight: "26px", fontWeight: "600", color: "#1E2633" }}>工作台</span>
</div>
<Box sx={{ width: "100%", typography: "body1" }}>
<Tabs
......
.headerBox {
margin-bottom: 20px;
}
/* .headerBox { */
/* margin-bottom: 20px; */
/* } */
.tabHeader {
display: flex;
......@@ -17,11 +17,11 @@
border-top: 1px solid #F0F2F5;
overflow: hidden;
overflow-y: auto;
height: calc(100vh - 290px);
height: calc(100vh - 325px);
}
.tabBox {
padding: 15px 0px 16px 24px;
padding: 16px 0px 16px 24px;
display: flex;
align-items: center;
width: 100%;
......@@ -34,6 +34,7 @@
.tabBoxInfo {
width: 24%;
min-width: 280px;
}
.tabBoxDescInfo {
......@@ -43,13 +44,16 @@
.tabBoxTitle {
font-size: 14px;
line-height: 22px;
font-weight: 600;
color: #1E2633;
margin-bottom: 10px;
margin-bottom: 8px;
}
.tabBoxDesc {
font-size: 12px;
line-height: 20px;
white-space: nowrap;
font-weight: 400;
color: #8A9099;
}
......@@ -65,12 +69,15 @@
display: flex;
align-items: center;
width: 10%;
min-width: 105px;
white-space: nowrap;
}
.tabBoxJobStatus {
display: flex;
align-items: center;
width: 46%;
min-width: 180px;
}
.tabBoxStatusText {
......
......@@ -11,7 +11,6 @@ import Checkbox from "@mui/material/Checkbox";
import useMyRequest from "@/hooks/useMyRequest";
import AddIcon from "@mui/icons-material/Add";
import WorkFlowEdit from "@/views/WorkFlowEdit";
import _ from "lodash";
import noData from "../../../../../../assets/project/noTemplate.svg";
import { ICustomTemplate } from "../../interface";
import { useMessage } from "@/components/MySnackbar";
......@@ -92,7 +91,7 @@ const AddTemplate = (props: IAddTemplateProps) => {
// 添加工作流模板-获取模板列表
const { run: getAddTemplateList } = useMyRequest(getAddWorkbenchTemplate, {
onSuccess: (result: any) => {
setAddTemplateList(result.data);
setAddTemplateList(result?.data?.content || []);
// setOpenAddTemplate(true);
},
});
......
import { memo, useCallback, useEffect, useMemo, useState } from "react";
import styles from "../index.module.css";
import { Box, Typography } from "@mui/material";
import MyButton from "@/components/mui/MyButton";
import OutlinedInput from "@mui/material/OutlinedInput";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import SearchIcon from "@mui/icons-material/Search";
import Checkbox from "@mui/material/Checkbox";
import CloseOutlinedIcon from "@mui/icons-material/CloseOutlined";
import noData from "../../../../../assets/project/noTemplate.svg";
import _ from "lodash";
const AddTemplate = (props: any) => {
const {
openAddTemplate,
closeAddTemplateBlock,
addTemplateList,
templateSelectCallback,
selectTemplateData,
addTemplateCallback,
searchTemplateNameCallback,
} = props;
const [templateType, setTemplateType] = useState("public");
const radioOptions = [
{
value: "public",
label: "公共",
},
{
value: "custom",
label: "自定义",
},
];
const handleRadio = (value: string) => {
setTemplateType(value);
};
return (
<Box
className={styles.addTemplateMask}
sx={{ display: openAddTemplate ? "flex" : "none" }}
>
<Box sx={{ height: "50px", display: "flex", alignItems: "center" }}>
<CloseOutlinedIcon
sx={{ color: "#ffffff", marginRight: "10px", cursor: "pointer" }}
onClick={() => {
closeAddTemplateBlock();
}}
/>
</Box>
<Box className={styles.addTemplateBlock}>
<Box sx={{ padding: "24px 32px" }}>
<Typography
sx={{ fontSize: "18px", fontWeight: "600", color: "#1E2633" }}
>
添加工作流模版
</Typography>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
marginBottom: "20px",
}}
>
<OutlinedInput
onChange={(e: any) => {
_.debounce(() => {
searchTemplateNameCallback(e.target.value);
}, 200)();
}}
placeholder="输入关键词搜索"
size="small"
sx={{ width: 340, height: 32, marginTop: "20px" }}
endAdornment={<SearchIcon style={{ color: "#8A9099" }} />}
/>
<Box
sx={{
display: "flex",
justifyContent: "flex-end",
alignItems: "center",
}}
>
<RadioGroupOfButtonStyle
value={templateType}
radioOptions={radioOptions}
handleRadio={handleRadio}
></RadioGroupOfButtonStyle>
<MyButton
onClick={addTemplateCallback}
size={"small"}
style={{
marginLeft: "12px",
}}
text={
"添加模版" +
(selectTemplateData.length === 0
? ""
: `(${selectTemplateData.length})`)
}
/>
</Box>
</Box>
{addTemplateList.length === 0 && (
<Box
sx={{
display: "flex",
alignItems: "center",
flexDirection: "column",
minHeight: "calc(100vh - 376px)",
justifyContent: "center",
}}
>
<img alt="" src={noData} />
<Typography
sx={{ fontSize: "12px", fontWeight: "400", color: "#8A9099" }}
>
暂无相关模版
</Typography>
</Box>
)}
<Box
sx={{
display: "flex",
flexWrap: "wrap",
overflowX: "hidden",
overflowY: "overlay",
marginLeft: "-8px",
}}
>
{addTemplateList.map((item: any, key: any) => {
return (
<Box
className={styles.addTemplateBox}
onClick={() => {
templateSelectCallback(item.id);
}}
sx={{
border: selectTemplateData.includes(item.id)
? "1px solid #1370FF"
: "1px solid #EBEDF0;",
}}
key={item.id}
>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<Typography
sx={{
fontSize: "14px",
fontWeight: "600",
color: "#1E2633",
marginBottom: "4px",
overflow: "hidden",
textOverflow: "ellipsis",
}}
>
{item.title}
</Typography>
<Checkbox
size="small"
sx={{ padding: "0px" }}
checked={selectTemplateData.includes(item.id)}
/>
</Box>
<Box sx={{ display: "flex", marginBottom: "8px" }}>
<Typography
sx={{
fontSize: "12px",
fontWeight: "400",
color: "#1370FF",
marginRight: "24px",
}}
>
版本:{item.version}
</Typography>
<Typography
sx={{
fontSize: "12px",
fontWeight: "400",
color: "#1370FF",
}}
>
更新时间:{item.updateTime}
</Typography>
</Box>
<Typography className={styles.templateDescText}>
{item.description}
</Typography>
</Box>
);
})}
</Box>
</Box>
</Box>
</Box>
);
};
export default memo(AddTemplate);
......@@ -17,17 +17,48 @@
}
.templateBlock {
width: 21.4876%;
height: 160px;
height: 194px;
background: #ffffff;
box-shadow: 0px 3px 10px 0px rgba(0,24,57,0.0400);
border-radius: 4px;
border: 1px solid #ebedf0;
padding: 16px 20px;
display: flex;
flex-direction: column;
justify-content: space-between;
margin: 8px;
margin-bottom: 16px;
position: relative;
box-sizing: border-box;
}
@media screen and (max-width:1220px) {
.templateBlock {
width: 49%;
margin-right: 2%;
}
.templateBlock:nth-child(2n){
margin-right: 0;
}
}
@media screen and (min-width:1220px) and (max-width:1600px) {
.templateBlock {
width: 32.423%;
margin-right: 1.365%;
}
.templateBlock:nth-child(3n){
margin-right: 0;
}
}
@media screen and (min-width:1600px) {
.templateBlock {
width: 24%;
margin-right: 1.333%;
}
.templateBlock:nth-child(4n){
margin-right: 0;
}
}
.addTemplateMask {
......
......@@ -101,12 +101,12 @@ const ProjectMembers = observer(() => {
}, 300);
}, [templateName, getTemplateInfo, projectIdData]);
// 回车搜索
// 回车搜索
const handleKeyWordChangeKeyUp = (e: any) => {
if (e.keyCode === 13) {
setTemplateName(e.target.value);
}
}
if (e.keyCode === 13) {
setTemplateName(e.target.value);
}
}
return (
<Box className={styles.headerBox}>
......@@ -145,7 +145,7 @@ const ProjectMembers = observer(() => {
</Box>
)}
{templateList.length > 0 && (
<Box sx={{ display: "flex", flexWrap: "wrap", marginLeft: "-8px" }}>
<Box sx={{ display: "flex", flexWrap: "wrap" }}>
{templateList &&
templateList.length > 0 &&
templateList.map((item, key) => {
......
import style from "./index.module.css";
import { MenuItem } from "@mui/material";
import React, { useState, useEffect } from "react";
import MyInput from "@/components/mui/MyInput";
import MyDialog from "@/components/mui/MyDialog";
import React, { useState, useEffect } from "react";
import useMyRequest from "@/hooks/useMyRequest";
import { hpczone, addProject } from "@/api/project_api";
import { useMessage } from "@/components/MySnackbar";
......@@ -14,6 +14,8 @@ import {
getFiletokenAccordingToId,
} from "@/views/Project/project";
import style from "./index.module.css";
type zoneIdOption = {
id: string;
name: string;
......@@ -40,6 +42,7 @@ const AddProject = (props: IAddProjectProps) => {
});
const [zoneId, setZoneId] = useState("");
const [zoneIdOptions, setZoneIdOptions] = useState<Array<zoneIdOption>>([]);
const [loading, setLoading] = useState(false);
// 设置计算区
const { run } = useMyRequest(hpczone, {
......@@ -49,9 +52,13 @@ const AddProject = (props: IAddProjectProps) => {
},
});
const { run: addProjectRun } = useMyRequest(addProject, {
onBefore: () => {
setLoading(true);
},
onSuccess: async (result: any) => {
if (result.data) {
setAddOpen(false);
setLoading(false);
message.success("新建项目成功");
const projectList = await getProjectList();
currentProjectStore.setProjectList(projectList);
......@@ -70,7 +77,7 @@ const AddProject = (props: IAddProjectProps) => {
}
},
onError: () => {
setAddOpen(false);
setLoading(false);
},
});
......@@ -82,6 +89,7 @@ const AddProject = (props: IAddProjectProps) => {
if (addOpen) {
setName("");
setDesc("");
setLoading(false);
if (zoneIdOptions.length > 0) {
setZoneId(zoneIdOptions[0].id);
}
......@@ -126,18 +134,18 @@ const AddProject = (props: IAddProjectProps) => {
const handleDescChange = (e: any) => {
const desc = e.target.value;
setDesc(desc);
if (desc.length > 100) {
setDescCheck({
error: true,
help: "格式不正确,必须在100字符以内",
});
} else {
setDescCheck({
error: false,
help: "",
});
}
setDesc(desc.slice(0,100));
// if (desc.length > 100) {
// setDescCheck({
// error: true,
// help: "格式不正确,必须在100字符以内",
// });
// } else {
// setDescCheck({
// error: false,
// help: "",
// });
// }
};
const handleSubmit = () => {
......@@ -164,6 +172,7 @@ const AddProject = (props: IAddProjectProps) => {
onConfirm={handleSubmit}
onClose={() => setAddOpen(false)}
title="新建项目"
loading={loading}
>
<div className={style.formBox} onClick={handleFromBox}>
<MyInput
......@@ -202,7 +211,7 @@ const AddProject = (props: IAddProjectProps) => {
id="desc"
label="项目描述"
multiline
rows={4}
rows={5}
placeholder="请输入项目描述"
onChange={handleDescChange}
helperText={descCheck.help}
......@@ -212,7 +221,7 @@ const AddProject = (props: IAddProjectProps) => {
position: "absolute",
bottom: "7px",
right: "12px",
color: "rgba(194, 198, 204, 1)",
color: desc.length >= 100 ? "#d32f2f" : "#C2C6CC"
}}
>
{desc.length}/100
......
......@@ -7,10 +7,15 @@
align-items: center;
cursor: pointer;
}
.currentProject:hover{
background-color: #EEF1F5;
}
.logo {
width: 32px;
border-radius: 4px;
background-color: #fff;
box-shadow: 2px 2px 8px 0px rgba(0,27,67,0.0600);
margin-right: 12px;
display: block;
}
......@@ -26,7 +31,7 @@
.projectName {
color: #8a9099;
line-height: 20px;
font-size: 14px;
font-size: 12px;
width: 125px;
white-space: nowrap;
text-overflow: ellipsis;
......
.reactFlowBox>div:last-child {
display: none;
}
\ No newline at end of file
......@@ -18,6 +18,8 @@ import FlowNode from "./components/FlowNode";
import { getCustomTemplateParameterCheckResult } from "@/views/WorkFlowEdit/util";
import { useMessage } from "@/components/MySnackbar";
import styles from './index.module.css'
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-22 10:15:22
......@@ -42,6 +44,8 @@ interface IProps extends ReactFlowProps {
onFlowNodeClick?: (val: string) => void;
/** 监听事件的状态 */
ListenState?: boolean;
// 是否显示Controls(放大缩小全屏等按钮)
showControls?: boolean;
}
const Flow = (props: IProps) => {
......@@ -54,6 +58,7 @@ const Flow = (props: IProps) => {
setTasks,
onFlowNodeClick,
ListenState = true,
showControls = true,
...other
} = props;
/** 自定义的节点类型 */
......@@ -525,6 +530,7 @@ const Flow = (props: IProps) => {
return (
<ReactFlow
className={styles.reactFlowBox}
nodes={nodes}
edges={edges}
fitView={flowType === "default" ? true : false}
......@@ -535,7 +541,7 @@ const Flow = (props: IProps) => {
onNodeClick={onNodeClick}
{...other}
>
<Controls />
{showControls && <Controls />}
<Background color="#aaa" gap={16} />
</ReactFlow>
);
......
.projectBox {
width: calc(100vw - 220px);
height: calc(100vh - 57px);
background-color: rgba(0, 0, 0, .5);
/* width: 260px;
height: calc(100vh - 57px); */
/* width: 260px;
height: calc(100vh - 57px);
background-color: #fff;
border-right: 1px solid #ebedf0;
display: flex;
flex-direction: column; */
}
.mainBox{
width: 260px;
height: calc(100vh - 57px);
background-color: #fff;
border-right: 1px solid #ebedf0;
display: flex;
flex-direction: column;
border-left: 1px solid #DDE1E6;;
}
.searchBox {
box-sizing: border-box;
height: 56px;
......
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-08-02 11:43:28
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-08-02 19:36:32
* @FilePath: /bkunyun/src/views/Project/components/ProjectListPopper/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import smallLogo from "@/assets/project/projectIconSmall.svg";
import style from "./index.module.css";
import { InputBase, IconButton } from "@mui/material";
......@@ -14,7 +22,7 @@ const ProjectListPopper = observer((props: any) => {
const { handleChangeCurrentProject, handleClickOpen } = props;
const { currentProjectStore } = useStores();
const projectList = toJS(currentProjectStore.projectList);
const currentProjectName = toJS(currentProjectStore.currentProjectInfo.name);
const currentProjectId = toJS(currentProjectStore.currentProjectInfo.id);
// 通过名称本地搜索
const [name, setName] = useState("");
const nameChange = (e: any) => {
......@@ -33,6 +41,7 @@ const ProjectListPopper = observer((props: any) => {
return (
<div className={style.projectBox} onClick={handleProjectBox}>
<div className={style.mainBox}>
<div className={style.searchBox}>
<IconButton
type="submit"
......@@ -66,7 +75,7 @@ const ProjectListPopper = observer((props: any) => {
<div
className={classNames({
[style.projectli]: true,
[style.projectliActive]: item.name === currentProjectName,
[style.projectliActive]: item.id === currentProjectId,
})}
key={item.id}
onClick={() => handleChangeCurrentProject(item)}
......@@ -89,6 +98,7 @@ const ProjectListPopper = observer((props: any) => {
);
})}
</div>
</div>
</div>
);
});
......
......@@ -50,6 +50,7 @@
.listBox {
overflow-y: scroll;
height: calc(100% - 48px);
position: relative;
}
.versionBox {
......
......@@ -211,9 +211,7 @@ const OperatorItem = (props: IOperatorItemProps) => {
const OperatorList = observer((props: IOperatorListProps) => {
const { currentProjectStore } = useStores();
const productId = toJS(currentProjectStore.currentProductInfo.id);
const { templateConfigInfo, setTemplateConfigInfo } = props;
const [operatorListData, setOperatorListData] = useState<ITask[]>([]);
const [keyword, setKeyword] = useState<string>("");
......
......@@ -478,7 +478,7 @@ const ParameterSetting = (props: IParameterSettingProps) => {
onChange={(e: any) =>
handleParameterChange(e, parameter.name || "")
}
placeholder="请输入"
placeholder="可输入默认值"
error={parameter.error || false}
helperText={parameter.helperText}
disabled={parameter.parameterGroup === "out"}
......
......@@ -6,7 +6,7 @@
width: 100vw;
height: 100vh;
background-color: RGBA(247, 248, 250, 1);
overflow-y: scroll;
overflow-y: auto;
}
.swHeader {
z-index: 1001;
......@@ -36,6 +36,23 @@
height: 100%;
/* overflow-y: scroll; */
box-sizing: border-box;
position: relative;
}
.addOperator {
position: absolute;
right: 24px;
bottom: 20px;
width: 36px;
height: 36px;
border-radius: 50%;
box-shadow: 0px 3px 10px 0px rgba(0, 24, 57, 0.14);
font-size: 30px;
line-height: 36px;
text-align: center;
color: RGBA(66, 141, 255, 1);
cursor: pointer;
background-color: #fff;
}
.swFlowBox {
flex: 1;
......
......@@ -14,7 +14,7 @@ import { observer } from "mobx-react-lite";
import MyPopconfirm from "@/components/mui/MyPopconfirm";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import ButtonComponent from "@/components/mui/MyButton";
import MyButton from "@/components/mui/MyButton";
import OperatorList from "./components/OperatorList";
import Flow from "../Project/components/Flow";
import ParameterSetting from "./components/ParameterSetting";
......@@ -23,6 +23,7 @@ import { ITask } from "../Project/ProjectSubmitWork/interface";
import { fetchTemplateConfigInfo } from "@/api/project_api";
import { getCustomTemplateParameterCheckResult } from "./util";
import useMyRequest from "@/hooks/useMyRequest";
import CustomOperator from "../CustomOperator";
import SaveCustomTemplate from "./components/SaveCustomTemplate";
import styles from "./index.module.css";
......@@ -47,7 +48,7 @@ const WorkFlowEdit = observer((props: IProps) => {
const { onBack, id } = props;
const Message = useMessage();
const [templateConfigInfo, setTemplateConfigInfo] = useState<ITask[]>([]); // 算子大数组
const [showCustomOperator, setShowCustomOperator] = useState(false); // 是否显示自定义算子
const [saveFormDialog, setSaveFormDialog] = useState(false); // 保存弹窗显示与否控制
const [title, setTitle] = useState(""); // 自定义模板名称
const [version, setVersion] = useState("1.0.0"); // 自定义模板版本
......@@ -181,10 +182,7 @@ const WorkFlowEdit = observer((props: IProps) => {
</IconButton>
</div>
<div className={styles.swHeaderRight}>
<ButtonComponent
text="保存"
onClick={() => handlePreserve()}
></ButtonComponent>
<MyButton text="保存" onClick={() => handlePreserve()}></MyButton>
</div>
</div>
<div className={styles.swContent}>
......@@ -217,6 +215,12 @@ const WorkFlowEdit = observer((props: IProps) => {
taskId={selectTaskId || ""}
/>
)}
<div
className={styles.addOperator}
onClick={() => setShowCustomOperator(true)}
>
+
</div>
</div>
<div className={styles.swFlowBox} id="workFlowEditRight">
<Flow
......@@ -251,6 +255,11 @@ const WorkFlowEdit = observer((props: IProps) => {
oldversion={oldversion}
/>
)}
{showCustomOperator && (
<CustomOperator
setShowCustomOperator={() => setShowCustomOperator(false)}
/>
)}
</div>
);
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment