Commit 26ae1b6c authored by wuyongsheng's avatar wuyongsheng

Merge branch 'release' into 'staging'

Release

See merge request !173
parents e5fc0ad2 e4ad730c
...@@ -10561,6 +10561,11 @@ ...@@ -10561,6 +10561,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
}, },
"react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmmirror.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"react-refresh": { "react-refresh": {
"version": "0.11.0", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
...@@ -10594,6 +10599,19 @@ ...@@ -10594,6 +10599,19 @@
"prop-types": "^15.6.2" "prop-types": "^15.6.2"
} }
}, },
"react-virtualized": {
"version": "9.22.3",
"resolved": "https://registry.npmmirror.com/react-virtualized/-/react-virtualized-9.22.3.tgz",
"integrity": "sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw==",
"requires": {
"@babel/runtime": "^7.7.2",
"clsx": "^1.0.4",
"dom-helpers": "^5.1.3",
"loose-envify": "^1.4.0",
"prop-types": "^15.7.2",
"react-lifecycles-compat": "^3.0.4"
}
},
"readable-stream": { "readable-stream": {
"version": "3.6.0", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
......
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
"react-flow-renderer": "^10.3.7", "react-flow-renderer": "^10.3.7",
"react-refresh": "^0.11.0", "react-refresh": "^0.11.0",
"react-router-dom": "^6.3.0", "react-router-dom": "^6.3.0",
"react-virtualized": "^9.22.3",
"resolve": "^1.20.0", "resolve": "^1.20.0",
"resolve-url-loader": "^4.0.0", "resolve-url-loader": "^4.0.0",
"sass": "^1.55.0", "sass": "^1.55.0",
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-19 17:09:23 * @Date: 2022-10-19 17:09:23
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-27 11:23:29 * @LastEditTime: 2022-10-31 11:22:34
* @FilePath: /bkunyun/src/api/resourceCenter.ts * @FilePath: /bkunyun/src/api/resourceCenter.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -118,9 +118,9 @@ const getWorkflowspecList = (params: {productId?: string, title?: string}) => { ...@@ -118,9 +118,9 @@ const getWorkflowspecList = (params: {productId?: string, title?: string}) => {
// API_WORKFLOWSPEC_LIST // API_WORKFLOWSPEC_LIST
// 新增应用环境 // 新增应用环境
const saveOperator = (params: any, isEdit: boolean) => { const saveOperator = (params: any) => {
return request({ return request({
url: `${Api.API_SAVE_OPERATOR}?isEdit=${isEdit}`, url: `${Api.API_SAVE_OPERATOR}`,
method: "post", method: "post",
data: params, data: params,
}); });
......
...@@ -9,6 +9,7 @@ interface ICardTableProps { ...@@ -9,6 +9,7 @@ interface ICardTableProps {
numberOfColumns?: number; // 列数 每行渲染几个 numberOfColumns?: number; // 列数 每行渲染几个
horizontalSpacing?: number; // 水平方向的间隔 horizontalSpacing?: number; // 水平方向的间隔
verticalSpacing?: number; // 垂直方向的间隔 verticalSpacing?: number; // 垂直方向的间隔
renderBefore?: any;
} }
const CardTable = (props: ICardTableProps) => { const CardTable = (props: ICardTableProps) => {
...@@ -20,6 +21,7 @@ const CardTable = (props: ICardTableProps) => { ...@@ -20,6 +21,7 @@ const CardTable = (props: ICardTableProps) => {
horizontalSpacing = 20, horizontalSpacing = 20,
verticalSpacing = 20, verticalSpacing = 20,
itemMinWidth, itemMinWidth,
renderBefore,
} = props; } = props;
const [numberOfColumns, setNumberOfColumns] = useState(3); const [numberOfColumns, setNumberOfColumns] = useState(3);
...@@ -59,6 +61,20 @@ const CardTable = (props: ICardTableProps) => { ...@@ -59,6 +61,20 @@ const CardTable = (props: ICardTableProps) => {
}} }}
ref={tableBoxRef} ref={tableBoxRef}
> >
{renderBefore && renderBefore() && (
<div
className={style.itemBox}
style={{
width: boxWidth,
paddingLeft: `${horizontalSpacing / 2}px`,
paddingRight: `${horizontalSpacing / 2}px`,
paddingBottom: `${verticalSpacing}px`,
boxSizing: "border-box",
}}
>
{renderBefore()}
</div>
)}
{data.map((item, index) => { {data.map((item, index) => {
return ( return (
<div <div
......
import { List } from "react-virtualized";
interface IVirtuallyListProps {
list: Array<any>;
renderRow: any;
}
const VirtuallyList = (props: IVirtuallyListProps) => {
const { list, renderRow } = props;
return (
<List
width={300}
height={300}
rowCount={list.length}
rowHeight={20}
rowRenderer={renderRow}
overscanRowCount={20}
/>
);
};
export default VirtuallyList;
...@@ -15,6 +15,7 @@ import { ThemeProvider, createTheme } from "@mui/material/styles"; ...@@ -15,6 +15,7 @@ import { ThemeProvider, createTheme } from "@mui/material/styles";
import { TabContext, TabList, TabPanel } from "@mui/lab"; import { TabContext, TabList, TabPanel } from "@mui/lab";
import { Typography } from "@mui/material"; import { Typography } from "@mui/material";
import classNames from "classnames"; import classNames from "classnames";
import { useNavigate } from "react-router-dom";
import styles from "./index.module.css"; import styles from "./index.module.css";
...@@ -46,6 +47,8 @@ interface IProps { ...@@ -46,6 +47,8 @@ interface IProps {
tabPanelSx?: any; tabPanelSx?: any;
/** 是否允许空值 */ /** 是否允许空值 */
allowNullValue?: boolean; allowNullValue?: boolean;
/** 路由地址 配合navigate和MyTabs组件的defaultValue组合使用、F5刷新也可以保存激活的tab */
navigateUrl?: string;
} }
const theme = createTheme({ const theme = createTheme({
...@@ -101,8 +104,11 @@ const Tabs = (props: IProps) => { ...@@ -101,8 +104,11 @@ const Tabs = (props: IProps) => {
tabPanelSx = { padding: "20px 0 0 0" }, tabPanelSx = { padding: "20px 0 0 0" },
title, title,
titleClass, titleClass,
navigateUrl,
} = props; } = props;
const navigate = useNavigate();
const [tabValue, setTabValue] = useState( const [tabValue, setTabValue] = useState(
defaultValue defaultValue
? defaultValue ? defaultValue
...@@ -116,6 +122,10 @@ const Tabs = (props: IProps) => { ...@@ -116,6 +122,10 @@ const Tabs = (props: IProps) => {
const onTabChange = (val: string) => { const onTabChange = (val: string) => {
setTabValue(val); setTabValue(val);
onChange && onChange(val); onChange && onChange(val);
navigateUrl &&
navigate(navigateUrl, {
state: { defaultTab: val },
});
}; };
const getImgSrc = useCallback( const getImgSrc = useCallback(
......
...@@ -86,4 +86,6 @@ declare module "tus-js-client"; ...@@ -86,4 +86,6 @@ declare module "tus-js-client";
declare module "uuid"; declare module "uuid";
declare module "kekule"; declare module "kekule";
declare module 'ngl'; declare module 'ngl';
declare module 'react-virtualized';
...@@ -52,7 +52,13 @@ const OperatorList = (props: IProps) => { ...@@ -52,7 +52,13 @@ const OperatorList = (props: IProps) => {
}; };
}); });
setIsLastPage(res?.data?.last); setIsLastPage(res?.data?.last);
/** 兼容更改其他条件初始化,重置数据 */
if (res?.data?.pageable?.pageNumber === 0) {
setList(arr);
} else {
setList([...list, ...arr]); setList([...list, ...arr]);
}
}, },
}); });
......
...@@ -20,42 +20,26 @@ ...@@ -20,42 +20,26 @@
overflow: overlay; overflow: overlay;
} }
.templateList { .addTemplate {
/* height: 2000px; */ border: 2px solid #fff;
display: flex; box-shadow: 0px 3px 12px 0px rgba(3, 47, 105, 0.09);
justify-content: space-between; border-radius: 6px;
flex-wrap: wrap; background: linear-gradient(180deg, #f5f7fa 0%, #ffffff 100%);
} height: 208px;
.templateLi {
height: 170px;
box-sizing: border-box; box-sizing: border-box;
padding: 16px 20px; padding: 16px 20px;
/* cursor: pointer; */ transition: box-shadow 0.2s cubic-bezier(0, 0, 1, 1);
border: 1px solid rgba(235, 237, 240, 1);
border-radius: 4px;
min-width: 20%;
flex: 1;
margin-right: 16px;
margin-bottom: 16px;
transition: box-shadow .2s cubic-bezier(0, 0, 1, 1);
}
.templateLiCustom {
height: 170px;
}
.templateLiHidden {
visibility: hidden;
}
.addCustomTemplate {
height: 170px;
box-sizing: border-box;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
flex-direction: column; flex-direction: column;
height: 208px;
box-sizing: border-box;
cursor: pointer;
}
.addTemplate:hover {
box-shadow: 0px 6px 24px 0px rgb(3 47 105 / 14%);
} }
.addCustomTemplateText { .addCustomTemplateText {
...@@ -65,53 +49,7 @@ ...@@ -65,53 +49,7 @@
color: rgba(138, 144, 153, 1); color: rgba(138, 144, 153, 1);
} }
.templateLi:hover {
box-shadow: 6px 8px 22px 0px rgba(0, 24, 57, 0.08);
}
.templateLi:nth-child(4n) {
margin-right: 0;
}
.templateLiTop {
display: flex;
justify-content: space-between;
align-items: center;
}
.templateTitle {
font-size: 14px;
font-weight: 600;
color: #1e2633;
margin-bottom: 4px;
overflow: hidden;
text-overflow: ellipsis;
line-height: 22px;
}
.templateLiInfo {
margin-bottom: 8px;
}
.templateLiInfoText {
line-height: 20px;
font-size: 12px;
color: rgba(19, 112, 255, 1);
}
.templateLiDesc {
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
display: -webkit-box;
height: 54px;
font-size: 12px;
color: rgba(138, 144, 153, 1);
}
.templateLiEditBox { .templateLiEditBox {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
/* margin-top: 16px; */
} }
...@@ -12,6 +12,8 @@ import AddIcon from "@mui/icons-material/Add"; ...@@ -12,6 +12,8 @@ import AddIcon from "@mui/icons-material/Add";
import WorkFlowEdit from "@/views/WorkFlowEdit"; import WorkFlowEdit from "@/views/WorkFlowEdit";
import noData from "../../../../../../assets/project/noTemplate.svg"; import noData from "../../../../../../assets/project/noTemplate.svg";
import { ICustomTemplate } from "../../interface"; import { ICustomTemplate } from "../../interface";
import TemplateItem from "@/views/ResourceCenter/UserResources/UserResourcesTemplate/TemplateItem";
import CardTable from "@/components/CommonComponents/CardTable";
import { useMessage } from "@/components/MySnackbar"; import { useMessage } from "@/components/MySnackbar";
import { import {
getAddWorkbenchTemplate, getAddWorkbenchTemplate,
...@@ -203,16 +205,6 @@ const AddTemplate = (props: IAddTemplateProps) => { ...@@ -203,16 +205,6 @@ const AddTemplate = (props: IAddTemplateProps) => {
} }
}; };
const hiddenBoxArr = useMemo(() => {
const length =
templateType === "public"
? addTemplateList.length
: addTemplateList.length + 1;
const hiddenBoxNumber = 4 - (length % 4);
const arr = new Array(hiddenBoxNumber).fill("");
return arr;
}, [addTemplateList, templateType]);
return ( return (
<FullScreenDrawer handleClose={setShowAddTemplate}> <FullScreenDrawer handleClose={setShowAddTemplate}>
<div className={style.content}> <div className={style.content}>
...@@ -259,19 +251,6 @@ const AddTemplate = (props: IAddTemplateProps) => { ...@@ -259,19 +251,6 @@ const AddTemplate = (props: IAddTemplateProps) => {
radioOptions={radioOptions} radioOptions={radioOptions}
handleRadio={handleRadio} handleRadio={handleRadio}
/> />
{/* <MyButton
onClick={handleAddTemplate}
size={"small"}
style={{
marginLeft: "12px",
}}
text={
"添加模版" +
(selectTemplateData.length === 0
? ""
: `(${selectTemplateData.length})`)
}
/> */}
</Box> </Box>
</Box> </Box>
</div> </div>
...@@ -294,12 +273,14 @@ const AddTemplate = (props: IAddTemplateProps) => { ...@@ -294,12 +273,14 @@ const AddTemplate = (props: IAddTemplateProps) => {
</Typography> </Typography>
</Box> </Box>
)} )}
<div className={style.templateList}> <CardTable
{templateType !== "public" && ( data={addTemplateList}
renderBefore={() => {
if (templateType !== "public") {
return (
<div <div
className={classNames({ className={classNames({
[style.templateLi]: true, [style.addTemplate]: true,
[style.addCustomTemplate]: true,
})} })}
onClick={handleAddCustomTemplate} onClick={handleAddCustomTemplate}
> >
...@@ -308,76 +289,29 @@ const AddTemplate = (props: IAddTemplateProps) => { ...@@ -308,76 +289,29 @@ const AddTemplate = (props: IAddTemplateProps) => {
创建自定义模板 创建自定义模板
</span> </span>
</div> </div>
)} );
{addTemplateList.map((item: any, index) => { }
return ( return null;
<div
className={classNames({
[style.templateLi]: true,
[style.templateLiCustom]: templateType !== "public",
})}
key={index}
onClick={() => {
handleSelectTemplate(item.id);
}} }}
> renderItem={(item: any) => {
<div className={style.templateLiTop}> return (
<span className={style.templateTitle}>{item.title}</span> <TemplateItem
{/* <Checkbox templateInfo={item}
size="small" footer={() => {
sx={{ padding: "0px" }} return (
checked={selectTemplateData.includes(item.id)}
/> */}
</div>
<div className={style.templateLiInfo}>
<span
className={style.templateLiInfoText}
style={{ marginRight: "24px" }}
>
版本:{item.version}
</span>
<span className={style.templateLiInfoText}>
更新时间:{item.updatedTime}
</span>
</div>
<div className={style.templateLiDesc}>{item.description}</div>
<div className={style.templateLiEditBox}> <div className={style.templateLiEditBox}>
<MySwitch <MySwitch
defaultChecked={item.favorited} defaultChecked={item.favorited}
onChange={(e: any) => templateSwitch(e, item.id)} onChange={(e: any) => templateSwitch(e, item.id)}
></MySwitch> ></MySwitch>
</div> </div>
{/* {templateType !== "public" && (
<MyButton
onClick={() => handleEditTemplate(item)}
size={"small"}
style={{
height: "32px",
}}
color="inherit"
text="编辑模板"
/>
</div>
)} */}
</div>
); );
})} }}
></TemplateItem>
{hiddenBoxArr.length !== 4 &&
hiddenBoxArr.map((item, index) => {
return (
<div
key={`-${index}`}
className={classNames({
[style.templateLi]: true,
[style.templateLiHidden]: true,
})}
/>
); );
})} }}
</div> itemMinWidth={377}
></CardTable>
</div> </div>
</div> </div>
{customTemplateInfo?.show ? ( {customTemplateInfo?.show ? (
......
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-17 14:48:57
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-27 14:02:54
* @FilePath: /bkunyun/src/views/Project/ProjectWorkbench/workbenchTemplate/components/templateBox.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { memo, useCallback, useState } from "react";
import styles from "../index.module.css";
import { Box, Typography } from "@mui/material";
import MyButton from "@/components/mui/MyButton";
import usePass from "@/hooks/usePass";
import RemindBudgetDialog from "./RemindBudgetDialog";
import { useNavigate } from "react-router-dom";
import { toJS } from "mobx";
import { useStores } from "@/store";
import { observer } from "mobx-react-lite";
const TemplateBox = observer((props: any) => {
const info = props.data;
const { isParentUser, isOwner, greaterThan100 } = props;
const { currentProjectStore } = useStores();
const productId = toJS(currentProjectStore.currentProductInfo.id); // 产品ID
const isPass = usePass();
const navigate = useNavigate();
const [rbOpen, setRbOpen] = useState(false);
const [id, setId] = useState("");
const goToProjectSubmitWork = useCallback(
(id: string) => {
navigate(`/product/${productId || "cadd"}/projectSubmitWork`, {
state: { id },
});
},
[navigate, productId]
);
const handleJudgeBudget = useCallback(
(id: string) => {
setId(id);
if (greaterThan100) {
goToProjectSubmitWork(id);
} else {
setRbOpen(true);
}
},
[goToProjectSubmitWork, setRbOpen, setId, greaterThan100]
);
return (
<>
<Box className={styles.template}>
<Box className={styles.templateBlock}>
<Box>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<Typography
sx={{
fontSize: "14px",
fontWeight: "600",
color: "#1E2633",
marginBottom: "4px",
overflow: "hidden",
textOverflow: "ellipsis",
}}
>
{info.title}
</Typography>
{info.creator !== "root" && (
<Box
sx={{
backgroundColor: "rgba(227, 250, 236, 1)",
color: "rgba(2, 171, 131, 1)",
lineHeight: "20px",
padding: "1px 9px",
fontSize: "12px",
}}
>
自定义
</Box>
)}
</Box>
<Box sx={{ display: "flex", marginBottom: "8px" }}>
<Typography
sx={{
fontSize: "12px",
fontWeight: "400",
color: "#1370FF",
marginRight: "24px",
}}
>
版本:{info.version}
</Typography>
<Typography
sx={{ fontSize: "12px", fontWeight: "400", color: "#1370FF" }}
>
更新时间:{info.updatedTime}
</Typography>
</Box>
<Typography className={styles.templateDescText}>
{info.description ? info.description : "此模板暂无描述。"}
</Typography>
</Box>
<Box
sx={{
display: "flex",
justifyContent: "end",
}}
>
{isPass("PROJECT_WORKBENCH_FLOES_USE", "MANAGER") && (
<MyButton
size="medium"
text="移除模版"
onClick={() => {
props.startDialog(info.id);
}}
style={{ backgroundColor: "#F0F2F5", color: "#565C66" }}
/>
)}
{isPass("PROJECT_WORKBENCH_FLOES_USE", "USER") && (
<MyButton
size="medium"
text="使用模版"
onClick={() => handleJudgeBudget(info.id)}
style={{ marginLeft: "12px" }}
/>
)}
</Box>
</Box>
</Box>
{rbOpen && (
<RemindBudgetDialog
rbOpen={rbOpen}
rbClose={() => setRbOpen(false)}
id={id}
goToProjectSubmitWork={goToProjectSubmitWork}
isParentUser={isParentUser}
isOwner={isOwner}
></RemindBudgetDialog>
)}
</>
);
});
export default memo(TemplateBox);
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx * @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
import { memo, useEffect, useState } from "react"; import { memo, useEffect, useState, useCallback } from "react";
import { Box, Typography } from "@mui/material"; import { Box, Typography } from "@mui/material";
import { toJS } from "mobx"; import { toJS } from "mobx";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
...@@ -16,10 +16,13 @@ import { getLoaclStorageOfKey } from "@/api/fileserver/utils"; ...@@ -16,10 +16,13 @@ import { getLoaclStorageOfKey } from "@/api/fileserver/utils";
import MyButton from "@/components/mui/MyButton"; import MyButton from "@/components/mui/MyButton";
import SearchInput from "@/components/BusinessComponents/SearchInput"; import SearchInput from "@/components/BusinessComponents/SearchInput";
import useMyRequest from "@/hooks/useMyRequest"; import useMyRequest from "@/hooks/useMyRequest";
import TemplateBox from "./components/templateBox"; import { useNavigate } from "react-router-dom";
import TemplateItem from "@/views/ResourceCenter/UserResources/UserResourcesTemplate/TemplateItem";
import SimpleDialog from "./components/simpleDialog"; import SimpleDialog from "./components/simpleDialog";
import AddTemplate from "./components/AddTemplate/index"; import AddTemplate from "./components/AddTemplate/index";
import noData from "../../../../assets/project/noTemplate.svg"; import noData from "../../../../assets/project/noTemplate.svg";
import RemindBudgetDialog from "./components/RemindBudgetDialog";
import CardTable from "@/components/CommonComponents/CardTable";
import { import {
getWorkbenchTemplate, getWorkbenchTemplate,
deleteWorkbenchTemplate, deleteWorkbenchTemplate,
...@@ -37,7 +40,10 @@ const ProjectMembers = observer(() => { ...@@ -37,7 +40,10 @@ const ProjectMembers = observer(() => {
const { currentProjectStore } = useStores(); const { currentProjectStore } = useStores();
const projectIdData = toJS(currentProjectStore.currentProjectInfo.id); const projectIdData = toJS(currentProjectStore.currentProjectInfo.id);
const productId = toJS(currentProjectStore.currentProductInfo.id); const productId = toJS(currentProjectStore.currentProductInfo.id);
const navigate = useNavigate();
const isPass = usePass(); const isPass = usePass();
const [selectId, setSelectId] = useState("");
const [rbOpen, setRbOpen] = useState(false);
/** 搜索模板名称 */ /** 搜索模板名称 */
const [templateName, setTemplateName] = useState(""); const [templateName, setTemplateName] = useState("");
...@@ -156,6 +162,27 @@ const ProjectMembers = observer(() => { ...@@ -156,6 +162,27 @@ const ProjectMembers = observer(() => {
}); });
}, [currentProjectStore.currentProjectInfo.id, getProjectFn]); }, [currentProjectStore.currentProjectInfo.id, getProjectFn]);
const goToProjectSubmitWork = useCallback(
(id: string) => {
navigate(`/product/${productId || "cadd"}/projectSubmitWork`, {
state: { id },
});
},
[navigate, productId]
);
const handleJudgeBudget = useCallback(
(id: string) => {
setSelectId(id);
if (greaterThan100) {
goToProjectSubmitWork(id);
} else {
setRbOpen(true);
}
},
[goToProjectSubmitWork, setRbOpen, setSelectId, greaterThan100]
);
return ( return (
<Box className={styles.headerBox}> <Box className={styles.headerBox}>
<Box className={styles.tabBox}> <Box className={styles.tabBox}>
...@@ -188,24 +215,49 @@ const ProjectMembers = observer(() => { ...@@ -188,24 +215,49 @@ const ProjectMembers = observer(() => {
</Typography> </Typography>
</Box> </Box>
)} )}
{templateList.length > 0 && ( <CardTable
<Box className={styles.templateBox}> data={templateList}
{templateList && renderItem={(item: any) => {
templateList.length > 0 &&
templateList.map((item, key) => {
return ( return (
<TemplateBox <TemplateItem
key={key} templateInfo={item}
data={item} footer={() => {
startDialog={startDialog} return (
isParentUser={isParentUser} <Box
isOwner={isOwner} sx={{
greaterThan100={greaterThan100} display: "flex",
justifyContent: "end",
}}
>
{isPass("PROJECT_WORKBENCH_FLOES_USE", "MANAGER") && (
<MyButton
size="medium"
text="移除模版"
onClick={() => {
startDialog(item.id);
}}
style={{
backgroundColor: "#F0F2F5",
color: "#565C66",
}}
/> />
);
})}
</Box>
)} )}
{isPass("PROJECT_WORKBENCH_FLOES_USE", "USER") && (
<MyButton
size="medium"
text="使用模版"
onClick={() => handleJudgeBudget(item.id)}
style={{ marginLeft: "12px" }}
/>
)}
</Box>
);
}}
></TemplateItem>
);
}}
itemMinWidth={377}
></CardTable>
{showAddTemplate && ( {showAddTemplate && (
<AddTemplate <AddTemplate
...@@ -222,6 +274,17 @@ const ProjectMembers = observer(() => { ...@@ -222,6 +274,17 @@ const ProjectMembers = observer(() => {
/> />
)} )}
{rbOpen && (
<RemindBudgetDialog
rbOpen={rbOpen}
rbClose={() => setRbOpen(false)}
id={selectId}
goToProjectSubmitWork={goToProjectSubmitWork}
isParentUser={isParentUser}
isOwner={isOwner}
></RemindBudgetDialog>
)}
<SimpleDialog <SimpleDialog
text={"确认移除该模板吗?"} text={"确认移除该模板吗?"}
title="移除模板" title="移除模板"
......
...@@ -78,6 +78,18 @@ ...@@ -78,6 +78,18 @@
.code { .code {
background-color: rgba(247, 248, 250, 1); background-color: rgba(247, 248, 250, 1);
flex: 1; flex: 1;
position: relative;
}
.codeHelper {
width: 100%;
box-sizing: border-box;
position: absolute;
bottom: 0;
color: rgba(255, 78, 78, 1);
font-size: 12px;
line-height: 20px;
padding: 6px 20px;
background-color: rgba(255, 232, 232, 1);
} }
.label { .label {
color: rgba(30, 38, 51, 1); color: rgba(30, 38, 51, 1);
......
...@@ -27,10 +27,11 @@ import { getTokenInfo } from "@/utils/util"; ...@@ -27,10 +27,11 @@ import { getTokenInfo } from "@/utils/util";
type IAddEnvironmentProps = { type IAddEnvironmentProps = {
setAddopen: any; setAddopen: any;
setTitle: any;
}; };
const AddEnvironment = (props: IAddEnvironmentProps) => { const AddEnvironment = (props: IAddEnvironmentProps) => {
const { setAddopen } = props; const { setAddopen, setTitle } = props;
const Message = useMessage(); const Message = useMessage();
let tokenInfo = getTokenInfo(); let tokenInfo = getTokenInfo();
const [hpczoneList, setHpczoneList] = useState<Array<any>>([]); // 计算区列表 通过计算区列表和计算区id拿fileServerEndPoint const [hpczoneList, setHpczoneList] = useState<Array<any>>([]); // 计算区列表 通过计算区列表和计算区id拿fileServerEndPoint
...@@ -63,6 +64,14 @@ const AddEnvironment = (props: IAddEnvironmentProps) => { ...@@ -63,6 +64,14 @@ const AddEnvironment = (props: IAddEnvironmentProps) => {
error: false, error: false,
text: "", text: "",
}); });
const [shellHelper] = useState({
error: false,
text: "请输入Shell脚本",
});
const [pythonHelper] = useState({
error: false,
text: "请输入Python脚本",
});
const onDrop = useCallback( const onDrop = useCallback(
(acceptedFiles: any) => { (acceptedFiles: any) => {
let origin = ""; let origin = "";
...@@ -111,6 +120,10 @@ const AddEnvironment = (props: IAddEnvironmentProps) => { ...@@ -111,6 +120,10 @@ const AddEnvironment = (props: IAddEnvironmentProps) => {
setIsUploading(false); setIsUploading(false);
setFilePaths([`/ProjectData/${homeDirectoryMountPoint}/${path}`]); setFilePaths([`/ProjectData/${homeDirectoryMountPoint}/${path}`]);
setFileName(path); setFileName(path);
setFilePathsHelper({
error: false,
text: "",
});
}, },
}); });
setIsUploading(true); setIsUploading(true);
...@@ -164,6 +177,7 @@ const AddEnvironment = (props: IAddEnvironmentProps) => { ...@@ -164,6 +177,7 @@ const AddEnvironment = (props: IAddEnvironmentProps) => {
{ {
onSuccess: () => { onSuccess: () => {
Message.success("开始构建应用环境"); Message.success("开始构建应用环境");
setTitle("");
setAddopen(false); setAddopen(false);
}, },
} }
...@@ -339,7 +353,10 @@ const AddEnvironment = (props: IAddEnvironmentProps) => { ...@@ -339,7 +353,10 @@ const AddEnvironment = (props: IAddEnvironmentProps) => {
<SwitchBatchFolw <SwitchBatchFolw
active={taskType} active={taskType}
setActive={setTaskType} setActive={setTaskType}
goBack={() => setAddopen(false)} goBack={() => {
setTitle("");
setAddopen(false);
}}
></SwitchBatchFolw> ></SwitchBatchFolw>
</div> </div>
<div className={style.right}> <div className={style.right}>
...@@ -499,6 +516,9 @@ const AddEnvironment = (props: IAddEnvironmentProps) => { ...@@ -499,6 +516,9 @@ const AddEnvironment = (props: IAddEnvironmentProps) => {
height="535px" height="535px"
width={`${codeWidth}px`} width={`${codeWidth}px`}
/> />
{taskType === "BATCH" && !code && (
<div className={style.codeHelper}>{shellHelper.text}</div>
)}
</div> </div>
</div> </div>
</div> </div>
...@@ -508,13 +528,16 @@ const AddEnvironment = (props: IAddEnvironmentProps) => { ...@@ -508,13 +528,16 @@ const AddEnvironment = (props: IAddEnvironmentProps) => {
Python脚本 Python脚本
<span className={style.required}>*</span> <span className={style.required}>*</span>
</div> </div>
<div className={style.code} id="addEnvironmentCode"> <div className={style.code}>
<Code <Code
value={flowCode} value={flowCode}
onChange={(e: string) => setFlowCode(e)} onChange={(e: string) => setFlowCode(e)}
height="535px" height="535px"
width={`${codeWidth + 368}px`} width={`${codeWidth + 368}px`}
/> />
{!flowCode && (
<div className={style.codeHelper}>{pythonHelper.text}</div>
)}
</div> </div>
</div> </div>
)} )}
......
.environment { .environment {
padding: 19px 24px 0; padding: 20px 24px 0;
} }
.top { .top {
display: flex; display: flex;
......
...@@ -198,6 +198,7 @@ const UserResourcesEnvironment = () => { ...@@ -198,6 +198,7 @@ const UserResourcesEnvironment = () => {
<div className={style.environment}> <div className={style.environment}>
<div className={style.top}> <div className={style.top}>
<div className={style.topLeft}> <div className={style.topLeft}>
{!addOpen && (
<SearchInput <SearchInput
sx={{ width: 340, marginRight: "16px" }} sx={{ width: 340, marginRight: "16px" }}
onKeyUp={(e: any) => { onKeyUp={(e: any) => {
...@@ -206,11 +207,12 @@ const UserResourcesEnvironment = () => { ...@@ -206,11 +207,12 @@ const UserResourcesEnvironment = () => {
} }
}} }}
></SearchInput> ></SearchInput>
)}
{!addOpen && ( {!addOpen && (
<MySelect <MySelect
options={[ options={[
{ {
label: "全部", label: "全部环境",
value: "ALL", value: "ALL",
}, },
{ {
...@@ -264,7 +266,12 @@ const UserResourcesEnvironment = () => { ...@@ -264,7 +266,12 @@ const UserResourcesEnvironment = () => {
setSortState={setSortState} setSortState={setSortState}
></MyTable> ></MyTable>
</div> </div>
{addOpen && <AddEnvironment setAddopen={setAddopen}></AddEnvironment>} {addOpen && (
<AddEnvironment
setAddopen={setAddopen}
setTitle={setTitle}
></AddEnvironment>
)}
{deleteOpen && ( {deleteOpen && (
<DeleteEnvironment <DeleteEnvironment
id={id} id={id}
......
.templateBox {
border: 2px solid #fff;
box-shadow: 0px 3px 12px 0px rgba(3, 47, 105, 0.09);
border-radius: 6px;
background: linear-gradient(180deg, #f5f7fa 0%, #ffffff 100%);
height: 208px;
box-sizing: border-box;
padding: 16px 20px;
transition: box-shadow 0.2s cubic-bezier(0, 0, 1, 1);
&:hover {
box-shadow: 0px 6px 24px 0px rgb(3 47 105 / 14%);
}
.templateTop {
display: flex;
align-items: center;
justify-content: flex-start;
margin-bottom: 12px;
.templateTopItem {
font-size: 12px;
line-height: 20px;
color: rgba(138, 144, 153, 1);
}
.templateTopLine {
width: 1px;
height: 16px;
background-color: rgba(221, 225, 230, 1);
margin: 0 11px;
}
}
.templateTitleBox {
height: 24px;
display: flex;
align-items: center;
justify-content: flex-start;
margin-bottom: 12px;
.templateTitle {
font-size: 15px;
line-height: 22px;
color: rgba(30, 38, 51, 1);
margin-left: 8px;
font-weight: 550;
}
}
.templateDesc {
height: 60px;
font-size: 12px;
line-height: 20px;
color: rgba(86, 92, 102, 1);
margin-bottom: 16px;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
display: -webkit-box;
}
}
import { useStores } from "@/store";
import { toJS } from "mobx";
import templateIcon from "@/assets/resourceCenter/templateIcon.svg";
import style from "./index.module.scss";
interface ITemplateItemPorps {
templateInfo: any;
footer: any;
}
const TemplateItem = (props: ITemplateItemPorps) => {
const { templateInfo, footer } = props;
const { productListStore } = useStores();
const getProductName = (productId: string) => {
let res = "-";
toJS(productListStore.productList).forEach((item) => {
if (item.value === productId) {
res = item.label;
}
});
return res;
};
return (
<div className={style.templateBox}>
<div className={style.templateTop}>
<div className={style.templateTopItem}>
{getProductName(templateInfo.productId)}
</div>
{templateInfo.creator !== "root" && (
<>
<div className={style.templateTopLine}></div>
<div className={style.templateTopItem}>自定义</div>
</>
)}
<div className={style.templateTopLine}></div>
<div className={style.templateTopItem}>{templateInfo.version}</div>
<div className={style.templateTopLine}></div>
<div className={style.templateTopItem}>{templateInfo.updatedTime}</div>
</div>
<div className={style.templateTitleBox}>
<img src={templateIcon} alt="" />
<div className={style.templateTitle}>{templateInfo.title}</div>
</div>
<div className={style.templateDesc}>{templateInfo.description}</div>
{footer && footer()}
</div>
);
};
export default TemplateItem;
.template { .template {
padding: 19px 24px 0; padding: 20px 24px 0;
} }
.top { .top {
display: flex; display: flex;
...@@ -10,60 +10,7 @@ ...@@ -10,60 +10,7 @@
.tableBox { .tableBox {
height: calc(100vh - 177px); height: calc(100vh - 177px);
} }
.templateBox {
border: 2px solid #fff;
box-shadow: 0px 3px 12px 0px rgba(3, 47, 105, 0.09);
border-radius: 6px;
background: linear-gradient(180deg, #f5f7fa 0%, #ffffff 100%);
height: 208px;
box-sizing: border-box;
padding: 16px 20px;
}
.templateTop {
display: flex;
align-items: center;
justify-content: flex-start;
margin-bottom: 12px;
}
.templateTopItem {
font-size: 12px;
line-height: 20px;
color: rgba(138, 144, 153, 1);
}
.templateTopLine {
width: 1px;
height: 16px;
background-color: rgba(221, 225, 230, 1);
margin: 0 11px;
}
.templateTitleBox {
display: flex;
align-items: center;
justify-content: flex-start;
margin-bottom: 12px;
}
.templateTitleBox {
height: 24px;
}
.templateTitle {
font-size: 14px;
line-height: 22px;
color: rgba(30, 38, 51, 1);
margin-left: 8px;
font-weight: 550;
}
.templateDesc {
height: 60px;
font-size: 12px;
line-height: 20px;
color: rgba(86, 92, 102, 1);
margin-bottom: 16px;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
display: -webkit-box;
}
.templateButtons { .templateButtons {
display: flex; display: flex;
align-items: center; align-items: center;
......
...@@ -8,14 +8,13 @@ import CardTable from "@/components/CommonComponents/CardTable"; ...@@ -8,14 +8,13 @@ import CardTable from "@/components/CommonComponents/CardTable";
import useMyRequest from "@/hooks/useMyRequest"; import useMyRequest from "@/hooks/useMyRequest";
import { getWorkflowspecList, deleteWorkflowspec } from "@/api/resourceCenter"; import { getWorkflowspecList, deleteWorkflowspec } from "@/api/resourceCenter";
import MyDialog from "@/components/mui/MyDialog"; import MyDialog from "@/components/mui/MyDialog";
import templateIcon from "@/assets/resourceCenter/templateIcon.svg";
import { useStores } from "@/store"; import { useStores } from "@/store";
import { toJS } from "mobx";
import ProductSelect from "@/components/BusinessComponents/ProductSelect"; import ProductSelect from "@/components/BusinessComponents/ProductSelect";
import WorkFlowEdit from "@/views/WorkFlowEdit"; import WorkFlowEdit from "@/views/WorkFlowEdit";
import { useMessage } from "@/components/MySnackbar"; import { useMessage } from "@/components/MySnackbar";
import TemplateDetail from "./TemplateDetail"; import TemplateDetail from "./TemplateDetail";
import style from "./index.module.css"; import style from "./index.module.css";
import TemplateItem from "./TemplateItem";
import NoData from "@/components/BusinessComponents/NoData"; import NoData from "@/components/BusinessComponents/NoData";
const UserResourcesTemplate = observer(() => { const UserResourcesTemplate = observer(() => {
...@@ -26,36 +25,16 @@ const UserResourcesTemplate = observer(() => { ...@@ -26,36 +25,16 @@ const UserResourcesTemplate = observer(() => {
const [showDeleteDialog, setShowDeleteDialog] = useState(false); const [showDeleteDialog, setShowDeleteDialog] = useState(false);
const [showDetail, setShowDetail] = useState(false); // 详情 const [showDetail, setShowDetail] = useState(false); // 详情
const [templateId, setTemplateId] = useState(""); const [templateId, setTemplateId] = useState("");
const [product, setProduct] = useState(""); // 搜索列表用 const [product, setProduct] = useState("all"); // 搜索列表用
const [productId, setProductId] = useState(""); // 新增模板用 const [productId, setProductId] = useState(""); // 新增模板用
const [list, setList] = useState([]); const [list, setList] = useState([]);
const { productListStore } = useStores(); const { productListStore } = useStores();
const getProductName = (productId: string) => {
let res = "-";
toJS(productListStore.productList).forEach((item) => {
if (item.value === productId) {
res = item.label;
}
});
return res;
};
const renderItem = (item: any) => { const renderItem = (item: any) => {
return ( return (
<div className={style.templateBox}> <TemplateItem
<div className={style.templateTop}> templateInfo={item}
<div className={style.templateTopItem}> footer={() => {
{getProductName(item.productId)} return (
</div>
<div className={style.templateTopLine}></div>
<div className={style.templateTopItem}>{item.version}</div>
<div className={style.templateTopLine}></div>
<div className={style.templateTopItem}>{item.updatedTime}</div>
</div>
<div className={style.templateTitleBox}>
<img src={templateIcon} alt="" />
<div className={style.templateTitle}>{item.title}</div>
</div>
<div className={style.templateDesc}>{item.description}</div>
<div className={style.templateButtons}> <div className={style.templateButtons}>
<div className={style.templateBL}> <div className={style.templateBL}>
<span <span
...@@ -93,7 +72,9 @@ const UserResourcesTemplate = observer(() => { ...@@ -93,7 +72,9 @@ const UserResourcesTemplate = observer(() => {
></MyButton> ></MyButton>
</div> </div>
</div> </div>
</div> );
}}
></TemplateItem>
); );
}; };
...@@ -143,7 +124,7 @@ const UserResourcesTemplate = observer(() => { ...@@ -143,7 +124,7 @@ const UserResourcesTemplate = observer(() => {
<MySelect <MySelect
options={ options={
[ [
{ label: "全部", value: "all" }, { label: "全部产品", value: "all" },
...productListStore?.productList, ...productListStore?.productList,
] || [] ] || []
} }
......
...@@ -33,12 +33,12 @@ ...@@ -33,12 +33,12 @@
.content { .content {
display: flex; display: flex;
/* position: relative; */ position: relative;
/* overflow: hidden; */
border-radius: 4px; border-radius: 4px;
margin-bottom: 20px; margin-bottom: 20px;
height: 600px; height: 562px;
} }
.form { .form {
width: 368px; width: 368px;
min-width: 368px; min-width: 368px;
...@@ -97,6 +97,11 @@ ...@@ -97,6 +97,11 @@
padding-left: 32px; padding-left: 32px;
} }
.helpBox {
width: 368px;
height: 100%;
}
.codeErrorBox { .codeErrorBox {
padding-left: 20px; padding-left: 20px;
height: 32px; height: 32px;
...@@ -109,3 +114,34 @@ ...@@ -109,3 +114,34 @@
.react-flow > div:last-child { .react-flow > div:last-child {
display: none; display: none;
} }
.formOpen {
position: absolute;
height: 100%;
left: -420px;
}
.formClose {
height: 100%;
}
.helpOpen {
height: 100%;
}
.helpClose {
position: absolute;
height: 100%;
right: -420px;
}
.preBox {
background-color: #f7f8fa;
height: calc(100% - 84px);
padding: 20px;
font-size: 12px;
color: #1e2633;
overflow: auto;
word-wrap: break-word;
white-space: pre-wrap;
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-18 16:12:55 * @Date: 2022-10-18 16:12:55
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-28 16:48:21 * @LastEditTime: 2022-11-01 11:34:04
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/components/AddOperator/index.tsx * @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/components/AddOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -41,13 +41,13 @@ import { ...@@ -41,13 +41,13 @@ import {
import batchOperator from "@/assets/resourceCenter/batchOperator.svg"; import batchOperator from "@/assets/resourceCenter/batchOperator.svg";
import flowOperator from "@/assets/resourceCenter/flowOperator.svg"; import flowOperator from "@/assets/resourceCenter/flowOperator.svg";
import { useMessage } from "@/components/MySnackbar"; import { useMessage } from "@/components/MySnackbar";
import MyPopover from "@/components/mui/MyPopover"; import CloseIcon from "@mui/icons-material/Close";
import useCheckOperator from "@/views/CustomOperator/useCheckOperator"; import useCheckOperator from "@/views/CustomOperator/useCheckOperator";
import { saveBatchActor } from "@/api/project_api"; import { saveBatchActor } from "@/api/project_api";
import positionTransform from "@/views/CustomOperator/utils"; import positionTransform from "@/views/CustomOperator/utils";
import MyTooltip from "@/components/mui/MyTooltip";
import style from "./index.module.css"; import style from "./index.module.css";
import MyTooltip from "@/components/mui/MyTooltip";
interface IAddOperator { interface IAddOperator {
pageType: string; pageType: string;
...@@ -326,7 +326,7 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -326,7 +326,7 @@ const AddOperator = observer((props: IAddOperator) => {
body: positionTransform(params?.parameters || []), body: positionTransform(params?.parameters || []),
}); });
} else { } else {
runSaveOperator(params, detailsId ? true : false); runSaveOperator(params);
} }
}, [ }, [
batchBuildType, batchBuildType,
...@@ -348,7 +348,7 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -348,7 +348,7 @@ const AddOperator = observer((props: IAddOperator) => {
try { try {
const newData = JSON.parse(code); const newData = JSON.parse(code);
const nameArr = newData?.map((item: any) => { const nameArr = newData?.map((item: any) => {
return `${item.name}: ~{$actorName$.${item.name}}`; return `${item.title}: ~{$actorName$.${item.name}}`;
}); });
newText = nameArr?.join("\n"); newText = nameArr?.join("\n");
} catch (err) { } catch (err) {
...@@ -392,12 +392,13 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -392,12 +392,13 @@ const AddOperator = observer((props: IAddOperator) => {
/> />
</div> </div>
) : null} ) : null}
<div className={style.content}> <div className={style.content}>
<div <div
className={classNames({ className={classNames({
[style.form]: batchBuildType === "ENVIRONMENT", [style.form]: batchBuildType === "ENVIRONMENT",
[style.newForm]: batchBuildType !== "ENVIRONMENT", [style.newForm]: batchBuildType !== "ENVIRONMENT",
[style.formOpen]: batchBuildType !== "OPERATOR" && tipsOpen,
[style.formClose]: !tipsOpen,
})} })}
> >
<FormItemBox <FormItemBox
...@@ -418,7 +419,6 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -418,7 +419,6 @@ const AddOperator = observer((props: IAddOperator) => {
placeholder="请输入算子名称" placeholder="请输入算子名称"
value={formData?.title} value={formData?.title}
onChange={(e) => { onChange={(e) => {
if (e.target.value?.length > 15) return;
changeFormData({ title: e.target.value }); changeFormData({ title: e.target.value });
}} }}
/> />
...@@ -499,7 +499,7 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -499,7 +499,7 @@ const AddOperator = observer((props: IAddOperator) => {
style={{ style={{
position: "absolute", position: "absolute",
fontSize: "14px", fontSize: "14px",
bottom: "7px", top: "96px",
right: "12px", right: "12px",
color: color:
Number(formData?.description?.length) >= 300 Number(formData?.description?.length) >= 300
...@@ -517,19 +517,12 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -517,19 +517,12 @@ const AddOperator = observer((props: IAddOperator) => {
<div className={style.codeBox}> <div className={style.codeBox}>
<div className={style.codeTitle}> <div className={style.codeTitle}>
<span>参数配置</span> <span>参数配置</span>
<MyPopover <span
open={tipsOpen} onClick={() => setTipsOpen(!tipsOpen)}
changeOpen={(val) => setTipsOpen(val)} style={{ color: "#1370FF", cursor: "pointer" }}
content={<pre>{text}</pre>}
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
> >
<span style={{ color: "#1370FF", cursor: "pointer" }}>
帮助手册 帮助手册
</span> </span>
</MyPopover>
</div> </div>
<div className={style.code}> <div className={style.code}>
<Code <Code
...@@ -539,7 +532,7 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -539,7 +532,7 @@ const AddOperator = observer((props: IAddOperator) => {
setCode(e); setCode(e);
}} }}
onBlur={paramsConfigBlur} onBlur={paramsConfigBlur}
height={parametersError ? "480px" : "512px"} height={parametersError ? "486px" : "518px"}
width="600" width="600"
style={{ flex: 1 }} style={{ flex: 1 }}
/> />
...@@ -572,7 +565,7 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -572,7 +565,7 @@ const AddOperator = observer((props: IAddOperator) => {
style={{ style={{
position: "absolute", position: "absolute",
fontSize: "14px", fontSize: "14px",
bottom: "7px", top: "216px",
right: "12px", right: "12px",
color: color:
Number(formData?.description?.length) >= 300 Number(formData?.description?.length) >= 300
...@@ -585,8 +578,40 @@ const AddOperator = observer((props: IAddOperator) => { ...@@ -585,8 +578,40 @@ const AddOperator = observer((props: IAddOperator) => {
</FormItemBox> </FormItemBox>
</div> </div>
)} )}
<div></div> {batchBuildType !== "OPERATOR" && (
<div
className={classNames({
[style.helpBox]: true,
[style.helpOpen]: tipsOpen,
[style.helpClose]: !tipsOpen,
})}
>
<div className={style.codeTitle}>
<span>帮助手册</span>
<CloseIcon
onClick={() => setTipsOpen(false)}
sx={{
fontSize: "16px",
color: "#C2C6CC",
cursor: "pointer",
":hover": {
background: "#f0f2f5",
borderRadius: "2px",
},
}}
/>
</div>
<pre
className={classNames({
[style.preBox]: true,
})}
>
{text}
</pre>
</div> </div>
)}
</div>
{taskType === "FLOW" ? null : ( {taskType === "FLOW" ? null : (
<div <div
className={style.parameterConfigBox} className={style.parameterConfigBox}
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-20 17:36:14 * @Date: 2022-10-20 17:36:14
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-28 15:22:13 * @LastEditTime: 2022-11-01 11:05:39
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/components/AddOperator/utils.ts * @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/components/AddOperator/utils.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -155,33 +155,27 @@ export const initCode = [{ ...@@ -155,33 +155,27 @@ export const initCode = [{
export const text = `{ export const text = `{
// 参数名, 必填, 在15字符以内,仅限大小写字母、数字、"_",且只能以大小写字母开头 // 参数名; 必填, 在15字符以内,仅限大小写字母、数字、"_",且只能以大小写字母开头
"name" : "timeout", "name" : "timeout",
/** 参数类型, 必填, 可选值有 STRING:字符串、FILE:文件、DATASET:数据集、INT:整型、FLOAT:单精度浮点型、 // 参数类型; 必填, 可选值有 STRING:字符串、FILE:文件、DATASET:数据集、INT:整型、FLOAT:单精度浮点型、DOUBLE:多精度浮点型、BOOLEAN:布尔值、ARRAY_STRING:字符串数组、ARRAY_FILE:文件数组、ARRAY_DATASET:数据集数组、ARRAY_INT:整型数组、ARRAY_FLOAT:单精度浮点型数组、ARRAY_DOUBLE:多精度浮点型数组、ARRAY_BOOLEAN:布尔值数组
* DOUBLE:多精度浮点型、BOOLEAN:布尔值、ARRAY_STRING:字符串数组、ARRAY_FILE:文件数组、ARRAY_DATASET:数据集数组、
* ARRAY_INT:整型数组、ARRAY_FLOAT:单精度浮点型数组、ARRAY_DOUBLE:多精度浮点型数组、ARRAY_BOOLEAN:布尔值数组
*/
"classType" : "INT", "classType" : "INT",
// 是否必填在使用该算子时是否必须输入改参数的值 // 是否必填; 在使用该算子时是否必须输入改参数的值
"required" : false, "required" : false,
// 默认值 // 默认值
"defaultValue" : 10000, "defaultValue" : 10000,
// 参数描述在300字符以内 // 参数描述; 在300字符以内
"description" : "", "description" : "",
// 是否隐藏, 必填, 隐藏就在页面不显示该参数 必填 // 是否隐藏; 必填, 隐藏就在页面不显示该参数 必填
"hidden" : true, "hidden" : true,
// 页面展示的参数的名称 必填, 在15字符以内,仅限大小写字母、数字、中文 // 页面展示的参数的名称; 必填, 在15字符以内,仅限大小写字母、数字、中文
"title" : "", "title" : "",
// 参数展示的顺序优先级 // 参数展示的顺序优先级
"order" : 0, "order" : 0,
// 参数分组 必填, 可选值有 in: 输入、out:输出、basis:基础、senior:高级 // 参数分组; 必填, 可选值有 in: 输入、out:输出、basis:基础、senior:高级
"parameterGroup": "in", "parameterGroup": "in",
/** // 前端填值的方式; 必填, 可选值有 PATH:路径选择器、DATASET:数据集选择器、FILE:文件选择器、INPUT:输入框、SELECT:下拉框、MULTIPLESELECT:多选下拉框、RADIO:单选按钮、CHECKBOX:多选按钮
* 前端填值的方式, 必填, 可选值有 PATH:路径选择器、DATASET:数据集选择器、FILE:文件选择器、INPUT:输入框、
* SELECT:下拉框、MULTIPLESELECT:多选下拉框、RADIO:单选按钮、CHECKBOX:多选按钮
*/
"domType" : "INPUT", "domType" : "INPUT",
// 选项当domType为SELECT、MULTIPLESELECT、RADIO、CHECKBOX时生效。以对象数组的形式保存 // 选项; 当domType为SELECT、MULTIPLESELECT、RADIO、CHECKBOX时生效。以对象数组的形式保存
"choices" : [ "choices" : [
{ {
// 在前端展示的值 // 在前端展示的值
...@@ -190,7 +184,7 @@ export const text = `{ ...@@ -190,7 +184,7 @@ export const text = `{
"value" : "true" "value" : "true"
}, },
], ],
//用于校验输入值。以对象数组的形式保存 //用于校验输入值; 以对象数组的形式保存
"validators" : [ "validators" : [
{ {
//正则表达式 //正则表达式
......
...@@ -6,10 +6,14 @@ ...@@ -6,10 +6,14 @@
box-shadow: 0px 3px 12px 0px rgba(3, 47, 105, 0.09); box-shadow: 0px 3px 12px 0px rgba(3, 47, 105, 0.09);
border-radius: 6px; border-radius: 6px;
border: 2px solid #ffffff; border: 2px solid #ffffff;
transition: box-shadow 0.2s cubic-bezier(0, 0, 1, 1);
} }
.itemBox:hover { .itemBox:hover {
box-shadow: 0px 6px 24px 0px rgba(3, 47, 105, 0.14); box-shadow: 0px 6px 24px 0px rgba(3, 47, 105, 0.14);
} }
.itemBox:hover .titleBox {
color: #1370ff;
}
.itemHeaderBox { .itemHeaderBox {
display: flex; display: flex;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-17 14:35:11 * @Date: 2022-10-17 14:35:11
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-28 14:54:39 * @LastEditTime: 2022-11-01 10:59:40
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx * @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -209,9 +209,10 @@ const OperatorDetails = observer(() => { ...@@ -209,9 +209,10 @@ const OperatorDetails = observer(() => {
{ label: "应用环境", value: envName }, { label: "应用环境", value: envName },
]} ]}
/> />
{description ? (
<BasicInfo infoList={[{ label: "描述", value: description }]} /> <BasicInfo
) : null} infoList={[{ label: "描述", value: description || "暂无描述" }]}
/>
</div> </div>
{type === "BATCH" ? ( {type === "BATCH" ? (
<div style={{ padding: "26px 0 16px 0" }}> <div style={{ padding: "26px 0 16px 0" }}>
......
...@@ -16,3 +16,6 @@ ...@@ -16,3 +16,6 @@
.contentBox { .contentBox {
padding: 0 20px 24px; padding: 0 20px 24px;
} }
.noDataHeight {
height: calc(100vh - 177px);
}
...@@ -79,7 +79,6 @@ const WorkflowOperator = observer(() => { ...@@ -79,7 +79,6 @@ const WorkflowOperator = observer(() => {
<div> <div>
<SearchInput <SearchInput
sx={{ width: 340, marginRight: "16px" }} sx={{ width: 340, marginRight: "16px" }}
placeholder="输入关键词搜索"
value={searchParams.keyword} value={searchParams.keyword}
onKeyUp={handleKeyWordChangeKeyUp} onKeyUp={handleKeyWordChangeKeyUp}
onChange={(e) => { onChange={(e) => {
...@@ -87,11 +86,9 @@ const WorkflowOperator = observer(() => { ...@@ -87,11 +86,9 @@ const WorkflowOperator = observer(() => {
}} }}
/> />
<MySelect <MySelect
title="所属产品"
isTitle={true}
options={ options={
[ [
{ label: "全部", value: "all" }, { label: "全部产品", value: "all" },
...productListStore?.productList, ...productListStore?.productList,
] || [] ] || []
} }
...@@ -103,14 +100,12 @@ const WorkflowOperator = observer(() => { ...@@ -103,14 +100,12 @@ const WorkflowOperator = observer(() => {
sx={{ width: "150px", height: "32px" }} sx={{ width: "150px", height: "32px" }}
/> />
<MySelect <MySelect
title="环境类型"
isTitle={true}
value={searchParams.type} value={searchParams.type}
onChange={(e) => { onChange={(e) => {
setSearchParams({ ...searchParams, type: e }); setSearchParams({ ...searchParams, type: e });
}} }}
options={[ options={[
{ label: "全部", value: "all" }, { label: "全部环境", value: "all" },
{ {
label: "批式", label: "批式",
value: "BATCH", value: "BATCH",
...@@ -148,7 +143,7 @@ const WorkflowOperator = observer(() => { ...@@ -148,7 +143,7 @@ const WorkflowOperator = observer(() => {
></CardTable> ></CardTable>
</div> </div>
) : ( ) : (
<div style={{ height: 300 }}> <div className={styles.noDataHeight}>
<NoData text="暂无工作流算子"></NoData> <NoData text="暂无工作流算子"></NoData>
</div> </div>
)} )}
......
...@@ -40,6 +40,7 @@ const UserResources = () => { ...@@ -40,6 +40,7 @@ const UserResources = () => {
tabList={tabList} tabList={tabList}
defaultValue={location?.state?.defaultTab || "USERRESOURCES_TEMPLATE"} defaultValue={location?.state?.defaultTab || "USERRESOURCES_TEMPLATE"}
tabPanelSx={{ padding: "0" }} tabPanelSx={{ padding: "0" }}
navigateUrl="/utility/resourceCenter/userResources"
/> />
{/* <OperatorDetails /> */} {/* <OperatorDetails /> */}
</div> </div>
......
import VirtuallyList from "@/components/CommonComponents/VirtuallyList";
const VirtuallyListDemo = () => {
let listData: Array<any> = [];
for (let i = 0; i < 10000; i++) {
listData.push({
name: "data" + i,
id: "data" + i,
});
}
const renderRow = ({
index,
isScrolling,
isVisible,
key,
parent,
style,
}: any) => {
// const name = listData[index].name;
// // const content = isScrolling ? "..." : <div>{name}</div>;
// const content = <div>{name}</div>;
return (
<div key={key} style={style}>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<div>{listData[index].name}</div>
<div>{listData[index].name}</div>
<div>{listData[index].name}</div>
<div>{listData[index].name}</div>
<div>{listData[index].name}</div>
<div>{listData[index].name}</div>
<div>{listData[index].name}</div>
</div>
</div>
);
};
return (
<div>
<div>
<VirtuallyList list={listData} renderRow={renderRow}></VirtuallyList>;
</div>
<div style={{ width: "300px", height: "300px", overflow: "auto" }}>
{listData.map((item, index) => {
return (
<div
key={index}
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<div>{listData[index].name}</div>
<div>{listData[index].name}</div>
<div>{listData[index].name}</div>
<div>{listData[index].name}</div>
<div>{listData[index].name}</div>
<div>{listData[index].name}</div>
<div>{listData[index].name}</div>
</div>
);
})}
</div>
</div>
);
};
export default VirtuallyListDemo;
...@@ -2,6 +2,7 @@ import MyTableDemo from "./MyTableDemo"; ...@@ -2,6 +2,7 @@ import MyTableDemo from "./MyTableDemo";
import QueueSelectDemo from "./QueueSelectDemo"; import QueueSelectDemo from "./QueueSelectDemo";
import IconfontDemo from "./IconfontDemo"; import IconfontDemo from "./IconfontDemo";
import CardTableDemo from "./CardTableDemo"; import CardTableDemo from "./CardTableDemo";
import VirtuallyListDemo from "./VirtuallyListDemo";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle"; import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import { useState } from "react"; import { useState } from "react";
import styles from "./index.module.css"; import styles from "./index.module.css";
...@@ -9,6 +10,10 @@ import style from "./index.module.scss"; ...@@ -9,6 +10,10 @@ import style from "./index.module.scss";
const Demo = () => { const Demo = () => {
const radioOptionsArr = [ const radioOptionsArr = [
{
value: "virtuallyListDemo",
label: "virtuallyListDemo",
},
{ {
value: "cardTable", value: "cardTable",
label: "cardTable", label: "cardTable",
...@@ -33,7 +38,7 @@ const Demo = () => { ...@@ -33,7 +38,7 @@ const Demo = () => {
const handleRadio = (e: string) => { const handleRadio = (e: string) => {
setSelectDemo(e); setSelectDemo(e);
}; };
const [selectDemo, setSelectDemo] = useState("cardTable"); const [selectDemo, setSelectDemo] = useState("virtuallyListDemo");
return ( return (
<div className={styles.demoBox}> <div className={styles.demoBox}>
...@@ -43,13 +48,15 @@ const Demo = () => { ...@@ -43,13 +48,15 @@ const Demo = () => {
handleRadio={handleRadio} handleRadio={handleRadio}
/> />
<div className={styles.demoContentBox}> <div className={styles.demoContentBox}>
{selectDemo === "virtuallyListDemo" && (
<VirtuallyListDemo></VirtuallyListDemo>
)}
{selectDemo === "cardTable" && <CardTableDemo></CardTableDemo>} {selectDemo === "cardTable" && <CardTableDemo></CardTableDemo>}
{selectDemo === "iconfont" && <IconfontDemo></IconfontDemo>} {selectDemo === "iconfont" && <IconfontDemo></IconfontDemo>}
{selectDemo === "队列选择器" && <QueueSelectDemo></QueueSelectDemo>} {selectDemo === "队列选择器" && <QueueSelectDemo></QueueSelectDemo>}
{selectDemo === "表格" && <MyTableDemo></MyTableDemo>} {selectDemo === "表格" && <MyTableDemo></MyTableDemo>}
{selectDemo === "box" && <div>box</div>} {selectDemo === "box" && <div>box</div>}
</div> </div>
<div className={style.box}>123</div>
</div> </div>
); );
}; };
......
...@@ -3477,6 +3477,11 @@ cliui@^7.0.2: ...@@ -3477,6 +3477,11 @@ cliui@^7.0.2:
strip-ansi "^6.0.0" strip-ansi "^6.0.0"
wrap-ansi "^7.0.0" wrap-ansi "^7.0.0"
clsx@^1.0.4:
version "1.2.1"
resolved "https://registry.npmmirror.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
clsx@^1.1.1: clsx@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz" resolved "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz"
...@@ -4202,7 +4207,7 @@ dom-converter@^0.2.0: ...@@ -4202,7 +4207,7 @@ dom-converter@^0.2.0:
dependencies: dependencies:
utila "~0.4" utila "~0.4"
dom-helpers@^5.0.1: dom-helpers@^5.0.1, dom-helpers@^5.1.3:
version "5.2.1" version "5.2.1"
resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz" resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz"
integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
...@@ -8053,6 +8058,11 @@ react-is@^18.0.0: ...@@ -8053,6 +8058,11 @@ react-is@^18.0.0:
resolved "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz" resolved "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz"
integrity sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg== integrity sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==
react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.npmmirror.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
react-refresh@^0.11.0: react-refresh@^0.11.0:
version "0.11.0" version "0.11.0"
resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz" resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz"
...@@ -8083,6 +8093,18 @@ react-transition-group@^4.4.2: ...@@ -8083,6 +8093,18 @@ react-transition-group@^4.4.2:
loose-envify "^1.4.0" loose-envify "^1.4.0"
prop-types "^15.6.2" prop-types "^15.6.2"
react-virtualized@^9.22.3:
version "9.22.3"
resolved "https://registry.npmmirror.com/react-virtualized/-/react-virtualized-9.22.3.tgz#f430f16beb0a42db420dbd4d340403c0de334421"
integrity sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw==
dependencies:
"@babel/runtime" "^7.7.2"
clsx "^1.0.4"
dom-helpers "^5.1.3"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-lifecycles-compat "^3.0.4"
react@^18.1.0: react@^18.1.0:
version "18.1.0" version "18.1.0"
resolved "https://registry.npmjs.org/react/-/react-18.1.0.tgz" resolved "https://registry.npmjs.org/react/-/react-18.1.0.tgz"
......
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