Commit 026cab6a authored by chenshouchao's avatar chenshouchao

Merge branch 'feat-20220705-customTemplate' into 'release'

cn-feat: 参数设置部分样式完成, 切换产品时产品id修改, 算子版本字段修改

See merge request !92
parents 4ba0aef4 2bfb4ed6
......@@ -17,11 +17,13 @@ class Menus {
productList: Array<{
name: string;
path: string;
id: string;
}> = [];
utilityList: Array<{
name: string;
path: string;
id: string;
}> = [];
initMenu = (list: projectList) => {
......@@ -32,11 +34,13 @@ class Menus {
this.productList.push({
name: item.name,
path: item.routes[0].path,
id: item.id,
});
} else if (item.type === "utility") {
this.utilityList.push({
name: item.name,
path: item.routes[0].path,
id: item.id,
});
}
}
......
......@@ -17,199 +17,199 @@ import TranSferList from "./components/TransferList";
import { getProjectList } from "@/api/project_api";
import useMyRequest from "@/hooks/useMyRequest";
import {
setFileServerEndPointLocalStorage,
getFiletokenAccordingToId,
setFileServerEndPointLocalStorage,
getFiletokenAccordingToId,
} from "@/views/Project/project";
import style from "./index.module.css";
const ConsoleLayout = observer(() => {
const {
productAnchorEl,
utilityAnchorEl,
productOpen,
utilityOpen,
handleProductClick,
handleUtilityClick,
handleClose,
} = useIndex();
const {
productAnchorEl,
utilityAnchorEl,
productOpen,
utilityOpen,
handleProductClick,
handleUtilityClick,
handleClose,
} = useIndex();
const [currentProduct, setCurrentProduct] = useState<{
path: string;
name: string;
}>();
const [currentProduct, setCurrentProduct] = useState<{
path: string;
name: string;
}>();
const { currentProjectStore } = useStores();
const { run: runGetProjectList } = useMyRequest(getProjectList, {
onSuccess: (res) => {
let list = res.data;
if (list.length === 0) {
currentProjectStore.setProjectList([]);
currentProjectStore.changeProject({});
navigate(currentProduct?.path as string);
} else {
currentProjectStore.setProjectList(list);
currentProjectStore.changeProject(list[0]);
setFileServerEndPointLocalStorage(list[0].zoneId);
getFiletokenAccordingToId(list[0].id).then((res) => {
list[0].filetoken = res;
currentProjectStore.changeProject(list[0]);
});
navigate(currentProduct?.path as string);
}
},
});
const { currentProjectStore } = useStores();
const { run: runGetProjectList } = useMyRequest(getProjectList, {
onSuccess: (res) => {
let list = res.data;
if (list.length === 0) {
currentProjectStore.setProjectList([]);
currentProjectStore.changeProject({});
navigate(currentProduct?.path as string);
} else {
currentProjectStore.setProjectList(list);
currentProjectStore.changeProject(list[0]);
setFileServerEndPointLocalStorage(list[0].zoneId);
getFiletokenAccordingToId(list[0].id).then((res) => {
list[0].filetoken = res;
currentProjectStore.changeProject(list[0]);
});
navigate(currentProduct?.path as string);
}
},
});
// 切换产品
const getProduct = (item: any) => {
currentProjectStore.changeProductInfo({ id: item.name, name: item.name });
setCurrentProduct(item);
runGetProjectList({
product: item.name,
});
};
// 切换产品
const getProduct = (item: any) => {
currentProjectStore.changeProductInfo({ id: item.id, name: item.name });
setCurrentProduct(item);
runGetProjectList({
product: item.name,
});
};
const navigate = useNavigate();
const location = useLocation();
const { permissionStore, menuStore } = useStores();
const navigate = useNavigate();
const location = useLocation();
const { permissionStore, menuStore } = useStores();
useEffect(() => {
permissionStore.setSidebarRouters(location.pathname);
}, [location, permissionStore]);
useEffect(() => {
permissionStore.setSidebarRouters(location.pathname);
}, [location, permissionStore]);
return (
<Box>
<Box className={style.topApp}>
<Box className={style.topLeftBox}>
<img src={logo} alt="" className={style.logo} />
return (
<Box>
<Box className={style.topApp}>
<Box className={style.topLeftBox}>
<img src={logo} alt="" className={style.logo} />
<Button
text={globalText.console}
variant={"text"}
style={{ color: "#565C66" }}
click={() => navigate("/home")}
/>
<Button
text={globalText.console}
variant={"text"}
style={{ color: "#565C66" }}
click={() => navigate("/home")}
/>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Button
text={globalText.product}
variant={"text"}
style={{ color: "#565C66" }}
click={handleProductClick}
dropValue={productOpen}
drop={true}
/>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Button
text={globalText.product}
variant={"text"}
style={{ color: "#565C66" }}
click={handleProductClick}
dropValue={productOpen}
drop={true}
/>
{/* <ArrowDropDownIcon classes={{
{/* <ArrowDropDownIcon classes={{
root: cx({
[style.ArrowDropDownIconRoot]: true,
[style.ArrowDropDownIconRootOpen]: Boolean(productOpen)
})
}} /> */}
<Menu
id="product-menu"
anchorEl={productAnchorEl}
open={productOpen}
onClose={handleClose}
classes={{
paper: style.menuPaper,
}}
MenuListProps={{
"aria-labelledby": "product-button",
}}
>
{menuStore.productList.map((item) => {
return (
<MenuItem
key={item.path}
classes={{
root: style.menuItemRoot,
}}
onClick={() => {
getProduct(item);
handleClose();
}}
>
{item.name}
</MenuItem>
);
})}
</Menu>
</Box>
</Box>
<Menu
id="product-menu"
anchorEl={productAnchorEl}
open={productOpen}
onClose={handleClose}
classes={{
paper: style.menuPaper,
}}
MenuListProps={{
"aria-labelledby": "product-button",
}}
>
{menuStore.productList.map((item) => {
return (
<MenuItem
key={item.path}
classes={{
root: style.menuItemRoot,
}}
onClick={() => {
getProduct(item);
handleClose();
}}
>
{item.name}
</MenuItem>
);
})}
</Menu>
</Box>
</Box>
<Box className={style.topRightBox}>
<MyPopover
content={<TranSferList />}
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
>
<img
className={style.topRightItem}
src={uploadIcon}
alt=""
style={{ verticalAlign: "middle" }}
/>
</MyPopover>
<Box className={style.topRightItem}>
<Box
sx={{ display: "flex", alignItems: "center" }}
onClick={handleUtilityClick}
>
<Avatar
sx={{
bgcolor: "#1370FF",
width: 28,
height: 28,
fontSize: "14px",
cursor: "pointer",
}}
>
H
</Avatar>
<ArrowDropDownIcon
classes={{
root: cx({
[style.ArrowDropDownIconRoot]: true,
[style.ArrowDropDownIconRootOpen]: Boolean(utilityOpen),
}),
}}
/>
</Box>
<Box className={style.topRightBox}>
<MyPopover
content={<TranSferList />}
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
>
<img
className={style.topRightItem}
src={uploadIcon}
alt=""
style={{ verticalAlign: "middle" }}
/>
</MyPopover>
<Box className={style.topRightItem}>
<Box
sx={{ display: "flex", alignItems: "center" }}
onClick={handleUtilityClick}
>
<Avatar
sx={{
bgcolor: "#1370FF",
width: 28,
height: 28,
fontSize: "14px",
cursor: "pointer",
}}
>
H
</Avatar>
<ArrowDropDownIcon
classes={{
root: cx({
[style.ArrowDropDownIconRoot]: true,
[style.ArrowDropDownIconRootOpen]: Boolean(utilityOpen),
}),
}}
/>
</Box>
<Menu
id="utility-menu"
anchorEl={utilityAnchorEl}
open={utilityOpen}
onClose={handleClose}
MenuListProps={{
"aria-labelledby": "utility-button",
}}
>
{menuStore.utilityList.map((item) => {
return (
<MenuItem
key={item.path}
onClick={() => {
navigate(item.path);
handleClose();
}}
>
{item.name}
</MenuItem>
);
})}
</Menu>
</Box>
</Box>
</Box>
<Box>
<Outlet></Outlet>
</Box>
</Box>
);
<Menu
id="utility-menu"
anchorEl={utilityAnchorEl}
open={utilityOpen}
onClose={handleClose}
MenuListProps={{
"aria-labelledby": "utility-button",
}}
>
{menuStore.utilityList.map((item) => {
return (
<MenuItem
key={item.path}
onClick={() => {
navigate(item.path);
handleClose();
}}
>
{item.name}
</MenuItem>
);
})}
</Menu>
</Box>
</Box>
</Box>
<Box>
<Outlet></Outlet>
</Box>
</Box>
);
});
export default ConsoleLayout;
......@@ -545,7 +545,7 @@ const ProjectSubmitWork = observer(() => {
<div className={styles.taskInfoLi}>
<div className={styles.taskInfoParams}>算子版本</div>
<div className={styles.taskInfoValue}>
{patchInfo?.creator || "-"}
{patchInfo?.version || "-"}
</div>
</div>
<div className={styles.taskInfoLi}>
......
......@@ -11,10 +11,10 @@ import React, { memo, useEffect, useMemo, useState } from "react";
import style from "./index.module.css";
import useMyRequest from "@/hooks/useMyRequest";
import {
getProject,
hpczone,
updateProject,
deleteProject,
getProject,
hpczone,
updateProject,
deleteProject,
} from "@/api/project_api";
import { useStores } from "@/store";
import { toJS } from "mobx";
......@@ -29,376 +29,376 @@ import MyDialog from "@/components/mui/MyDialog";
import { getProjectList } from "../../project";
import { checkIsNumberLetterChinese } from "@/utils/util";
import {
setFileServerEndPointLocalStorage,
getFiletokenAccordingToId,
setFileServerEndPointLocalStorage,
getFiletokenAccordingToId,
} from "@/views/Project/project";
type zoneIdOption = {
id: string;
name: string;
id: string;
name: string;
};
const BaseInfo = observer(() => {
const message = useMessage();
const { currentProjectStore } = useStores();
const [projectInfo, setProjectInfo] = useState<any>({});
const [deleteProjectName, setDeleteProjectName] = useState("");
const [nameCheck, setNameCheck] = useState({
error: false,
help: "",
});
const currentUserName = JSON.parse(
localStorage.getItem("userInfo") || "{}"
).name;
// 是否拥有编辑权限
const hasEditAuth = useMemo(() => {
if (!currentUserName) {
return false;
} else if (!projectInfo.members) {
return false;
} else {
return projectInfo.members.some((item: any) => {
return (
item.username === currentUserName && item.projectRole === "OWNER"
);
});
}
}, [currentUserName, projectInfo]);
const { run, loading } = useMyRequest(getProject, {
onSuccess: (result: any) => {
setProjectInfo(result.data);
},
});
useEffect(() => {
run({
id: currentProjectStore.currentProjectInfo.id as string,
});
}, [currentProjectStore.currentProjectInfo.id, run]);
const [zoneIdMap, setZoneIdMap] = useState<Map<string, string>>(new Map());
const [zoneIdOptions, setZoneIdOptions] = useState<Array<zoneIdOption>>([]);
const message = useMessage();
const { currentProjectStore } = useStores();
const [projectInfo, setProjectInfo] = useState<any>({});
const [deleteProjectName, setDeleteProjectName] = useState("");
const [nameCheck, setNameCheck] = useState({
error: false,
help: "",
});
const currentUserName = JSON.parse(
localStorage.getItem("userInfo") || "{}"
).name;
// 是否拥有编辑权限
const hasEditAuth = useMemo(() => {
if (!currentUserName) {
return false;
} else if (!projectInfo.members) {
return false;
} else {
return projectInfo.members.some((item: any) => {
return (
item.username === currentUserName && item.projectRole === "OWNER"
);
});
}
}, [currentUserName, projectInfo]);
const { run, loading } = useMyRequest(getProject, {
onSuccess: (result: any) => {
setProjectInfo(result.data);
},
});
useEffect(() => {
run({
id: currentProjectStore.currentProjectInfo.id as string,
});
}, [currentProjectStore.currentProjectInfo.id, run]);
const [zoneIdMap, setZoneIdMap] = useState<Map<string, string>>(new Map());
const [zoneIdOptions, setZoneIdOptions] = useState<Array<zoneIdOption>>([]);
// 获取计算区信息
const { run: getZone } = useMyRequest(hpczone, {
onSuccess: (result: any) => {
setZoneIdOptions(result);
let zoneMap: Map<string, string> = new Map();
result.forEach((item: zoneIdOption) => {
zoneMap.set(item.id, item.name);
});
setZoneIdMap(zoneMap);
},
});
// 获取计算区信息
const { run: getZone } = useMyRequest(hpczone, {
onSuccess: (result: any) => {
setZoneIdOptions(result);
let zoneMap: Map<string, string> = new Map();
result.forEach((item: zoneIdOption) => {
zoneMap.set(item.id, item.name);
});
setZoneIdMap(zoneMap);
},
});
useEffect(() => {
getZone();
}, [getZone]);
useEffect(() => {
getZone();
}, [getZone]);
// 项目信息展示数据转换
const infoList = useMemo(() => {
return [
{
label: "项目名称:",
value: projectInfo.name,
},
{
label: "项目描述:",
value: projectInfo.desc,
},
{
label: "计算区:",
value: zoneIdMap.get(projectInfo.zoneId) || projectInfo.zoneId,
},
{
label: "创建人:",
value: projectInfo.owner,
},
{
label: "扣费账号:",
value: projectInfo.tenantUser,
},
];
}, [projectInfo, zoneIdMap]);
// 项目信息展示数据转换
const infoList = useMemo(() => {
return [
{
label: "项目名称:",
value: projectInfo.name,
},
{
label: "项目描述:",
value: projectInfo.desc,
},
{
label: "计算区:",
value: zoneIdMap.get(projectInfo.zoneId) || projectInfo.zoneId,
},
{
label: "创建人:",
value: projectInfo.owner,
},
{
label: "扣费账号:",
value: projectInfo.tenantUser,
},
];
}, [projectInfo, zoneIdMap]);
const checkName = (name: string, showMessage = false) => {
let help = "";
if (name) {
if (name.length > 30) {
help = "格式不正确,必须在30字符以内,仅限大小写字母、数字、中文";
setNameCheck({
error: true,
help,
});
showMessage && message.error(help);
return false;
} else if (checkIsNumberLetterChinese(name)) {
setNameCheck({
error: false,
help: "",
});
return true;
} else {
help = "格式不正确,必须在30字符以内,仅限大小写字母、数字、中文";
setNameCheck({
error: true,
help,
});
showMessage && message.error(help);
return false;
}
} else {
help = "项目名称不能为空";
setNameCheck({
error: true,
help,
});
showMessage && message.error(help);
return false;
}
};
const checkName = (name: string, showMessage = false) => {
let help = "";
if (name) {
if (name.length > 30) {
help = "格式不正确,必须在30字符以内,仅限大小写字母、数字、中文";
setNameCheck({
error: true,
help,
});
showMessage && message.error(help);
return false;
} else if (checkIsNumberLetterChinese(name)) {
setNameCheck({
error: false,
help: "",
});
return true;
} else {
help = "格式不正确,必须在30字符以内,仅限大小写字母、数字、中文";
setNameCheck({
error: true,
help,
});
showMessage && message.error(help);
return false;
}
} else {
help = "项目名称不能为空";
setNameCheck({
error: true,
help,
});
showMessage && message.error(help);
return false;
}
};
const nameChange = (e: any) => {
setProjectInfo({
...projectInfo,
name: e.target.value,
});
checkName(e.target.value);
// setNameCheck
};
const nameChange = (e: any) => {
setProjectInfo({
...projectInfo,
name: e.target.value,
});
checkName(e.target.value);
// setNameCheck
};
const descChange = (e: any) => {
setProjectInfo({
...projectInfo,
desc: e.target.value,
});
};
const descChange = (e: any) => {
setProjectInfo({
...projectInfo,
desc: e.target.value,
});
};
const { run: updateProjectRun, loading: updateLoading } = useMyRequest(
updateProject,
{
onSuccess: async (result: any) => {
message.success("修改成功");
const projectList = await getProjectList();
currentProjectStore.setProjectList(projectList);
currentProjectStore.changeProject(projectInfo);
},
}
);
const { run: updateProjectRun, loading: updateLoading } = useMyRequest(
updateProject,
{
onSuccess: async (result: any) => {
message.success("修改成功");
const projectList = await getProjectList();
currentProjectStore.setProjectList(projectList);
currentProjectStore.changeProject(projectInfo);
},
}
);
// 修改项目
const handleClickUpdate = () => {
if (checkName(projectInfo.name, true)) {
updateProjectRun({ ...projectInfo, product: "CADD" });
} else {
return;
}
};
// 修改项目
const handleClickUpdate = () => {
if (checkName(projectInfo.name, true)) {
updateProjectRun({ ...projectInfo, product: "cadd" });
} else {
return;
}
};
const { run: deleteProjectRun, loading: deleteLoading } = useMyRequest(
deleteProject,
{
onSuccess: async (result: any) => {
message.success("删除成功");
DialogRef.current.handleClose();
const projectList = await getProjectList();
currentProjectStore.setProjectList(projectList);
// 项目删完了
if (projectList.length === 0) {
currentProjectStore.changeProject({});
localStorage.setItem("fileServerEndPoint", "");
setProjectInfo({});
} else {
projectList[0].filetoken = getFiletokenAccordingToId(
projectList[0].id
);
currentProjectStore.changeProject(projectList[0]);
setFileServerEndPointLocalStorage(projectList[0].zoneId);
getFiletokenAccordingToId(projectList[0].id).then((res) => {
projectList[0].filetoken = res;
currentProjectStore.changeProject(projectList[0]);
});
setProjectInfo(projectList[0]);
}
},
}
);
const { run: deleteProjectRun, loading: deleteLoading } = useMyRequest(
deleteProject,
{
onSuccess: async (result: any) => {
message.success("删除成功");
DialogRef.current.handleClose();
const projectList = await getProjectList();
currentProjectStore.setProjectList(projectList);
// 项目删完了
if (projectList.length === 0) {
currentProjectStore.changeProject({});
localStorage.setItem("fileServerEndPoint", "");
setProjectInfo({});
} else {
projectList[0].filetoken = getFiletokenAccordingToId(
projectList[0].id
);
currentProjectStore.changeProject(projectList[0]);
setFileServerEndPointLocalStorage(projectList[0].zoneId);
getFiletokenAccordingToId(projectList[0].id).then((res) => {
projectList[0].filetoken = res;
currentProjectStore.changeProject(projectList[0]);
});
setProjectInfo(projectList[0]);
}
},
}
);
let DialogRef: any = React.createRef();
// 显示删除弹窗
const handleClickDelete = () => {
DialogRef.current.handleClickOpen();
setDeleteProjectName("");
};
let DialogRef: any = React.createRef();
// 显示删除弹窗
const handleClickDelete = () => {
DialogRef.current.handleClickOpen();
setDeleteProjectName("");
};
const deleteProjectNameChange = (e: any) => {
setDeleteProjectName(e.target.value);
};
const deleteProjectNameChange = (e: any) => {
setDeleteProjectName(e.target.value);
};
// 删除项目
const handleSubmitDelete = () => {
if (
deleteProjectName === toJS(currentProjectStore.currentProjectInfo.name)
) {
deleteProjectRun({ id: projectInfo.id });
} else {
message.error("项目名称不匹配");
}
};
// 删除项目
const handleSubmitDelete = () => {
if (
deleteProjectName === toJS(currentProjectStore.currentProjectInfo.name)
) {
deleteProjectRun({ id: projectInfo.id });
} else {
message.error("项目名称不匹配");
}
};
if (loading) {
return (
<div className={style.loadingBox}>
<Loading />
</div>
);
} else if (!hasEditAuth) {
return <InformationDisplay infoList={infoList} />;
} else {
return (
<div className={style.projectInfoList}>
<div className={style.projectInfoListLi}>
<div
className={classnames({
[style.projectInfoListLiLabel]: true,
[style.projectInfoName]: true,
})}
>
项目名称
</div>
<TextField
required
error={nameCheck.error}
id="name"
variant="outlined"
value={projectInfo.name}
onChange={nameChange}
helperText={nameCheck.help}
size="small"
sx={{
width: "560px",
}}
/>
{/* <input
if (loading) {
return (
<div className={style.loadingBox}>
<Loading />
</div>
);
} else if (!hasEditAuth) {
return <InformationDisplay infoList={infoList} />;
} else {
return (
<div className={style.projectInfoList}>
<div className={style.projectInfoListLi}>
<div
className={classnames({
[style.projectInfoListLiLabel]: true,
[style.projectInfoName]: true,
})}
>
项目名称
</div>
<TextField
required
error={nameCheck.error}
id="name"
variant="outlined"
value={projectInfo.name}
onChange={nameChange}
helperText={nameCheck.help}
size="small"
sx={{
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>
<textarea
value={projectInfo.desc}
className={classnames({
[style.projectInfoListLiValue]: true,
[style.projectInfoTextarea]: true,
})}
onChange={descChange}
placeholder="项目描述限制100字以内"
maxLength={100}
></textarea>
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>计算区</div>
<select
value={projectInfo.zoneId}
disabled
className={classnames({
[style.projectInfoListLiValue]: true,
[style.projectInfoSelect]: true,
[style.disable]: true,
})}
>
{zoneIdOptions.map((option) => (
<option key={option.id} value={option.id}>
{option.name}
</option>
))}
</select>
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>创建人</div>
<input
value={projectInfo.owner}
disabled
className={classnames({
[style.projectInfoListLiValue]: true,
[style.disable]: true,
})}
></input>
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>扣费账号</div>
<input
value={projectInfo.tenantUser}
disabled
className={classnames({
[style.projectInfoListLiValue]: true,
[style.disable]: true,
})}
></input>
</div>
<div className={style.projectInfoListLi}>
<LoadingButton
variant="outlined"
className={style.updateButton}
onClick={handleClickUpdate}
loading={updateLoading}
>
保存修改
</LoadingButton>
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>删除项目</div>
<div className={style.projectInfoListLiText}>
删除项目将删除其存储的数据和所有相关资源,并且已删除的项目无法恢复!请谨慎操作!
</div>
<Button
variant="contained"
className={style.updateButton}
onClick={handleClickDelete}
style={{
backgroundColor: "#fff",
color: "#FF4E4E",
border: "1px solid #FF4E4E",
}}
>
删除项目
</Button>
</div>
<MyDialog
handleSubmit={handleSubmitDelete}
onRef={DialogRef}
title="删除项目"
submitloading={deleteLoading}
submitStyle={{ background: "#FF4E4E", color: "#fff" }}
>
<div className={style.deleteBox}>
<div className={style.deleteText1}>
您要删除本项目。已删除的项目将无法恢复!您真的确定吗?
</div>
<div className={style.deleteText2}>
此操作可能会导致数据丢失。为防止意外操作,我们要求您确认您的操作。
</div>
<div className={style.deleteText3}>
请输入“
<span className={style.deleteProjectName}>
{currentProjectStore.currentProjectInfo.name}
</span>
”以确认此操作。
</div>
<input
value={deleteProjectName}
className={style.deleteProjectInput}
onChange={deleteProjectNameChange}
maxLength={30}
placeholder="请输入项目名称"
></input>
</div>
</MyDialog>
</div>
);
}
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>项目描述</div>
<textarea
value={projectInfo.desc}
className={classnames({
[style.projectInfoListLiValue]: true,
[style.projectInfoTextarea]: true,
})}
onChange={descChange}
placeholder="项目描述限制100字以内"
maxLength={100}
></textarea>
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>计算区</div>
<select
value={projectInfo.zoneId}
disabled
className={classnames({
[style.projectInfoListLiValue]: true,
[style.projectInfoSelect]: true,
[style.disable]: true,
})}
>
{zoneIdOptions.map((option) => (
<option key={option.id} value={option.id}>
{option.name}
</option>
))}
</select>
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>创建人</div>
<input
value={projectInfo.owner}
disabled
className={classnames({
[style.projectInfoListLiValue]: true,
[style.disable]: true,
})}
></input>
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>扣费账号</div>
<input
value={projectInfo.tenantUser}
disabled
className={classnames({
[style.projectInfoListLiValue]: true,
[style.disable]: true,
})}
></input>
</div>
<div className={style.projectInfoListLi}>
<LoadingButton
variant="outlined"
className={style.updateButton}
onClick={handleClickUpdate}
loading={updateLoading}
>
保存修改
</LoadingButton>
</div>
<div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>删除项目</div>
<div className={style.projectInfoListLiText}>
删除项目将删除其存储的数据和所有相关资源,并且已删除的项目无法恢复!请谨慎操作!
</div>
<Button
variant="contained"
className={style.updateButton}
onClick={handleClickDelete}
style={{
backgroundColor: "#fff",
color: "#FF4E4E",
border: "1px solid #FF4E4E",
}}
>
删除项目
</Button>
</div>
<MyDialog
handleSubmit={handleSubmitDelete}
onRef={DialogRef}
title="删除项目"
submitloading={deleteLoading}
submitStyle={{ background: "#FF4E4E", color: "#fff" }}
>
<div className={style.deleteBox}>
<div className={style.deleteText1}>
您要删除本项目。已删除的项目将无法恢复!您真的确定吗?
</div>
<div className={style.deleteText2}>
此操作可能会导致数据丢失。为防止意外操作,我们要求您确认您的操作。
</div>
<div className={style.deleteText3}>
请输入“
<span className={style.deleteProjectName}>
{currentProjectStore.currentProjectInfo.name}
</span>
”以确认此操作。
</div>
<input
value={deleteProjectName}
className={style.deleteProjectInput}
onChange={deleteProjectNameChange}
maxLength={30}
placeholder="请输入项目名称"
></input>
</div>
</MyDialog>
</div>
);
}
});
export default memo(BaseInfo);
......@@ -28,6 +28,7 @@ export interface IParameter {
choices: Array<IChoice>;
error?: boolean;
helperText?: string;
parameterGroup?: string;
}
export type IExecutionStatus = "Pending" | "Running" | "Done" | "Failed";
......@@ -36,6 +37,7 @@ export interface ITask {
id: string;
title: string;
description: string;
version?: string;
position: {
x: number;
y: number;
......
......@@ -8,7 +8,7 @@ export const templateConfigJson = {
languageVersion: "draft-2",
tags: ["Docking", "Gromax"],
source: "BASE64_ENCODED_WDL/CWL",
productId: "CADD",
productId: "cadd",
id: "123",
tasks: [
{
......@@ -160,7 +160,7 @@ export const templateConfigJson = {
// languageVersion: "1.0",
// tags: ["Docking", "Gromax"],
// source: "",
// productId: "CADD",
// productId: "cadd",
// updateTime: "20220622",
// tasks: [
// {
......@@ -514,7 +514,7 @@ export const templateConfigJson = {
// languageVersion: "draft-2",
// tags: ["Docking", "Gromax"],
// source: "BASE64_ENCODED_WDL/CWL",
// productId: "CADD",
// productId: "cadd",
// tasks: [
// {
// id: "批式算子ID1",
......
......@@ -9,214 +9,214 @@ import { getProjectList } from "../../project";
import { useStores } from "@/store";
import { checkIsNumberLetterChinese } from "@/utils/util";
import {
setFileServerEndPointLocalStorage,
getFiletokenAccordingToId,
setFileServerEndPointLocalStorage,
getFiletokenAccordingToId,
} from "@/views/Project/project";
type zoneIdOption = {
id: string;
name: string;
id: string;
name: string;
};
const AddProject = (props: any) => {
const { currentProjectStore } = useStores();
const message = useMessage();
let DialogRef: any = React.createRef();
const [name, setName] = useState("");
const [nameCheck, setNameCheck] = useState({
error: false,
help: "",
});
const [desc, setDesc] = useState("");
const [descCheck, setDescCheck] = useState({
error: false,
help: "",
});
const [zoneId, setZoneId] = useState("");
const [zoneIdOptions, setZoneIdOptions] = useState<Array<zoneIdOption>>([]);
const [submitloading, setSubmitloading] = useState(false);
useImperativeHandle(props.onRef, () => {
return {
handleClickOpen: handleClickOpen,
};
});
const { currentProjectStore } = useStores();
const message = useMessage();
let DialogRef: any = React.createRef();
const [name, setName] = useState("");
const [nameCheck, setNameCheck] = useState({
error: false,
help: "",
});
const [desc, setDesc] = useState("");
const [descCheck, setDescCheck] = useState({
error: false,
help: "",
});
const [zoneId, setZoneId] = useState("");
const [zoneIdOptions, setZoneIdOptions] = useState<Array<zoneIdOption>>([]);
const [submitloading, setSubmitloading] = useState(false);
useImperativeHandle(props.onRef, () => {
return {
handleClickOpen: handleClickOpen,
};
});
// 设置计算区
const { run } = useMyRequest(hpczone, {
onSuccess: (result: any) => {
setZoneIdOptions(result);
setZoneId(result[0].id || "");
},
});
const { run: addProjectRun } = useMyRequest(addProject, {
onBefore: () => {
setSubmitloading(true);
},
onSuccess: async (result: any) => {
if (result.data) {
setSubmitloading(false);
DialogRef.current.handleClose();
message.success("新建项目成功");
const projectList = await getProjectList();
currentProjectStore.setProjectList(projectList);
let project: any = {};
projectList.forEach((item: any) => {
if (item.name === name) {
project = { ...item };
}
});
currentProjectStore.changeProject(project);
setFileServerEndPointLocalStorage(project.zoneId);
getFiletokenAccordingToId(project.id).then((res) => {
project.filetoken = res;
currentProjectStore.changeProject(project);
});
}
},
onError: () => {
setSubmitloading(false);
},
});
// 设置计算区
const { run } = useMyRequest(hpczone, {
onSuccess: (result: any) => {
setZoneIdOptions(result);
setZoneId(result[0].id || "");
},
});
const { run: addProjectRun } = useMyRequest(addProject, {
onBefore: () => {
setSubmitloading(true);
},
onSuccess: async (result: any) => {
if (result.data) {
setSubmitloading(false);
DialogRef.current.handleClose();
message.success("新建项目成功");
const projectList = await getProjectList();
currentProjectStore.setProjectList(projectList);
let project: any = {};
projectList.forEach((item: any) => {
if (item.name === name) {
project = { ...item };
}
});
currentProjectStore.changeProject(project);
setFileServerEndPointLocalStorage(project.zoneId);
getFiletokenAccordingToId(project.id).then((res) => {
project.filetoken = res;
currentProjectStore.changeProject(project);
});
}
},
onError: () => {
setSubmitloading(false);
},
});
useEffect(() => {
run();
}, [run]);
useEffect(() => {
run();
}, [run]);
const handleClickOpen = () => {
DialogRef.current.handleClickOpen();
initData();
};
const handleClickOpen = () => {
DialogRef.current.handleClickOpen();
initData();
};
const initData = () => {
setName("");
setDesc("");
if (zoneIdOptions.length > 0) {
setZoneId(zoneIdOptions[0].id);
}
};
const initData = () => {
setName("");
setDesc("");
if (zoneIdOptions.length > 0) {
setZoneId(zoneIdOptions[0].id);
}
};
const checkName = (name: string) => {
if (name) {
if (name.length > 30) {
setNameCheck({
error: true,
help: "格式不正确,必须在30字符以内,仅限大小写字母、数字、中文",
});
} else if (checkIsNumberLetterChinese(name)) {
setNameCheck({
error: false,
help: "",
});
} else {
setNameCheck({
error: true,
help: "格式不正确,必须在30字符以内,仅限大小写字母、数字、中文",
});
}
} else {
setNameCheck({
error: true,
help: "项目名称不能为空",
});
}
};
const checkName = (name: string) => {
if (name) {
if (name.length > 30) {
setNameCheck({
error: true,
help: "格式不正确,必须在30字符以内,仅限大小写字母、数字、中文",
});
} else if (checkIsNumberLetterChinese(name)) {
setNameCheck({
error: false,
help: "",
});
} else {
setNameCheck({
error: true,
help: "格式不正确,必须在30字符以内,仅限大小写字母、数字、中文",
});
}
} else {
setNameCheck({
error: true,
help: "项目名称不能为空",
});
}
};
const handleNameChange = (e: any) => {
const name = e.target.value;
setName(name);
checkName(name);
};
const handleNameChange = (e: any) => {
const name = e.target.value;
setName(name);
checkName(name);
};
const handleZoneIdChange = (e: any) => {
setZoneId(e.target.value);
};
const handleZoneIdChange = (e: any) => {
setZoneId(e.target.value);
};
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: "",
});
}
};
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: "",
});
}
};
const handleSubmit = () => {
checkName(name);
if (!nameCheck.error && !descCheck.error && zoneId) {
addProjectRun({
name,
desc,
zoneId,
product: "CADD",
});
} else {
return;
}
};
const handleSubmit = () => {
checkName(name);
if (!nameCheck.error && !descCheck.error && zoneId) {
addProjectRun({
name,
desc,
zoneId,
product: "cadd",
});
} else {
return;
}
};
const handleFromBox = (e: React.SyntheticEvent) => {
e.nativeEvent.stopImmediatePropagation();
};
const handleFromBox = (e: React.SyntheticEvent) => {
e.nativeEvent.stopImmediatePropagation();
};
return (
<MyDialog
handleSubmit={handleSubmit}
onRef={DialogRef}
title="新建项目"
submitloading={submitloading}
>
<div className={style.formBox} onClick={handleFromBox}>
<TextField
required
error={nameCheck.error}
id="name"
label="项目名称"
variant="outlined"
value={name}
onChange={handleNameChange}
helperText={nameCheck.help}
size="small"
/>
<TextField
id="zoneId"
select
required
label="计算区"
value={zoneId}
onChange={handleZoneIdChange}
variant="outlined"
onClick={handleFromBox}
size="small"
>
{zoneIdOptions &&
zoneIdOptions.map((option) => (
<MenuItem key={option.id} value={option.id}>
{option.name}
</MenuItem>
))}
</TextField>
<TextField
value={desc}
error={descCheck.error}
id="desc"
label="项目描述"
multiline
rows={4}
placeholder="请输入项目描述"
onChange={handleDescChange}
helperText={descCheck.help}
size="small"
/>
</div>
</MyDialog>
);
return (
<MyDialog
handleSubmit={handleSubmit}
onRef={DialogRef}
title="新建项目"
submitloading={submitloading}
>
<div className={style.formBox} onClick={handleFromBox}>
<TextField
required
error={nameCheck.error}
id="name"
label="项目名称"
variant="outlined"
value={name}
onChange={handleNameChange}
helperText={nameCheck.help}
size="small"
/>
<TextField
id="zoneId"
select
required
label="计算区"
value={zoneId}
onChange={handleZoneIdChange}
variant="outlined"
onClick={handleFromBox}
size="small"
>
{zoneIdOptions &&
zoneIdOptions.map((option) => (
<MenuItem key={option.id} value={option.id}>
{option.name}
</MenuItem>
))}
</TextField>
<TextField
value={desc}
error={descCheck.error}
id="desc"
label="项目描述"
multiline
rows={4}
placeholder="请输入项目描述"
onChange={handleDescChange}
helperText={descCheck.help}
size="small"
/>
</div>
</MyDialog>
);
};
export default AddProject;
......@@ -13,7 +13,7 @@ import {
} from "@/api/project_api";
export const getProjectList = async () => {
const res = await getProjectListApi({ product: "CADD" });
const res = await getProjectListApi({ product: "cadd" });
return res.data;
};
......
.parameterSetting {
background-color: #fff;
height: calc(100vh - 140px);
width: 360px;
box-sizing: border-box;
overflow-y: scroll;
padding: 0 24px;
}
.taskInfo {
margin-bottom: 20px;
position: relative;
}
.taskTitle {
color: rgba(30, 38, 51, 1);
font-size: 16px;
line-height: 24px;
margin-bottom: 8px;
font-weight: 600;
}
.taskVersion {
color: rgba(138, 144, 153, 1);
font-size: 12px;
line-height: 20px;
margin-bottom: 8px;
}
.taskDescription {
font-size: 12px;
color: rgba(86, 92, 102, 1);
line-height: 20px;
position: relative;
max-height: 60px;
overflow: hidden;
}
.taskDescriptionAll {
font-size: 12px;
color: rgba(86, 92, 102, 1);
line-height: 20px;
position: relative;
}
.taskDescriptionHeight {
font-size: 12px;
color: rgba(86, 92, 102, 1);
line-height: 20px;
position: absolute;
top: 0;
visibility: hidden;
max-height: 80px;
overflow: hidden;
}
.descButton {
position: absolute;
bottom: 0;
right: 0;
color: rgba(19, 112, 255, 1);
padding-left: 30px;
background-image: linear-gradient(
to right,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 1) 50%,
rgba(255, 255, 255, 1) 100%
);
cursor: pointer;
}
.noData {
height: calc(100vh - 140px);
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.noDataImg {
margin-bottom: 8px;
}
.noDataText {
font-size: 14px;
line-height: 22px;
color: rgba(138, 144, 153, 1);
}
import styles from "./index.module.css";
import {
ITask,
IParameter,
} from "../../../Project/ProjectSubmitWork/interface";
import noTemplate from "@/assets/project/noTemplate.svg";
import { useEffect, useMemo, useRef, useState } from "react";
import classNames from "classnames";
type IParameterSettingProps = {
templateConfigInfo: ITask[];
taskId: string;
};
const ParameterSetting = (props: IParameterSettingProps) => {
const { templateConfigInfo, taskId } = props;
const [descRef, setDescRef] = useState<any>(useRef());
const [descHeight, setDescHeight] = useState(0);
const [isShowAllDese, setIsShowAllDese] = useState(false);
useEffect(() => {
const div = document.getElementById("descHeight");
if (div) {
setDescHeight(div.offsetHeight);
}
}, [descRef]);
const taskInfo: ITask | null = useMemo(() => {
if (!taskId) {
return null;
} else {
const randerTaskArr = templateConfigInfo.filter(
(task) => task.id === taskId
);
if (randerTaskArr.length > 0) {
return randerTaskArr[0];
} else {
return null;
}
}
}, [templateConfigInfo, taskId]);
// 输入参数
const inParameters: Array<IParameter> = useMemo(() => {
if (!taskInfo) {
return [];
} else {
return taskInfo.parameters.filter(
(parameter) => parameter.parameterGroup === "in"
);
}
}, [taskInfo]);
// 输出参数
const outParameters: Array<IParameter> = useMemo(() => {
if (!taskInfo) {
return [];
} else {
return taskInfo.parameters.filter(
(parameter) => parameter.parameterGroup === "out"
);
}
}, [taskInfo]);
// 基础参数
const basisParameters: Array<IParameter> = useMemo(() => {
if (!taskInfo) {
return [];
} else {
return taskInfo.parameters.filter(
(parameter) => parameter.parameterGroup === "basis"
);
}
}, [taskInfo]);
// 高级选项
const seniorParameters: Array<IParameter> = useMemo(() => {
if (!taskInfo) {
return [];
} else {
return taskInfo.parameters.filter(
(parameter) => parameter.parameterGroup === "senior"
);
}
}, [taskInfo]);
// 硬件配置
const hardwareParameters: Array<IParameter> = useMemo(() => {
if (!taskInfo) {
return [];
} else {
return taskInfo.parameters.filter(
(parameter) => parameter.parameterGroup === "hardware"
);
}
}, [taskInfo]);
return (
<div className={styles.parameterSetting}>
{/* <div className={styles.taskInfo}>
<div className={styles.taskTitle}>taskTitle</div>
<div className={styles.taskVersion}>version</div>
<div
className={styles.taskDescriptionHeight}
id="descHeight"
ref={descRef}
>
埃里克梵蒂冈和艰苦拉萨规定了卡号是德国埃里克梵蒂冈和艰苦拉萨规定了卡号是德国埃里克梵蒂冈和艰苦拉萨规定了卡号是德国埃里克梵蒂冈和艰苦拉萨规定了卡号是德国埃里克梵蒂冈和艰苦拉萨规定了卡号是德国埃里克梵蒂冈和艰苦拉萨规定了卡号是德国
</div>
<div
className={classNames({
[styles.taskDescriptionAll]: isShowAllDese,
[styles.taskDescription]: !isShowAllDese,
})}
>
埃里克梵蒂冈和艰苦拉萨规定了卡号是德国埃里克梵蒂冈和艰苦拉萨规定了卡号是德国埃里克梵蒂冈和艰苦拉萨规定了卡号是德国埃里克梵蒂冈和艰苦拉萨规定了卡号是德国埃里克梵蒂冈和艰苦拉萨规定了卡号是德国埃里克梵蒂冈和艰苦拉萨规定了卡号是德国
{descHeight > 60 && (
<span
className={styles.descButton}
onClick={() => setIsShowAllDese(!isShowAllDese)}
>
{isShowAllDese ? "收起" : "展开"}
</span>
)}
</div>
</div> */}
{taskInfo && (
<div className={styles.taskInfo}>
<div className={styles.taskTitle}>{taskInfo.title || "-"}</div>
<div className={styles.taskVersion}>
版本:{taskInfo.version || "-"}
</div>
<div
className={styles.taskDescriptionHeight}
id="descHeight"
ref={descRef}
>
{taskInfo.description || "-"}
</div>
<div
className={classNames({
[styles.taskDescriptionAll]: isShowAllDese,
[styles.taskDescription]: !isShowAllDese,
})}
>
{taskInfo.description || "-"}
{descHeight > 60 && (
<span
className={styles.descButton}
onClick={() => setIsShowAllDese(!isShowAllDese)}
>
{isShowAllDese ? "收起" : "展开"}
</span>
)}
</div>
</div>
)}
{/* {!taskInfo && (
<div className={styles.noData}>
<img src={noTemplate} alt="" className={styles.noDataImg} />
<span className={styles.noDataText}>选中任意算子进行参数设置</span>
</div>
)} */}
</div>
);
};
export default ParameterSetting;
......@@ -15,10 +15,10 @@ import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfB
import ButtonComponent from "@/components/mui/Button";
import OperatorList from "./components/OperatorList";
import Flow from "../Project/components/Flow";
import ParameterSetting from "./components/ParameterSetting";
import { ITask } from "../Project/ProjectSubmitWork/interface";
import styles from "./index.module.css";
import { style } from "@mui/system";
const radioOptions = [
{
......@@ -102,7 +102,12 @@ const WorkFlowEdit = (props: IProps) => {
/>
</div>
)}
{leftContentType !== "list" && <div>123</div>}
{leftContentType !== "list" && (
<ParameterSetting
templateConfigInfo={templateConfigInfo}
taskId={""}
/>
)}
</div>
<div id="workFlowEditRight">
<Flow tasks={templateConfigInfo} />
......
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