Commit 181bec6a authored by wuyongsheng's avatar wuyongsheng

Merge branch 'feat-20221009-remind-budget' into 'master'

Feat 20221009 remind budget

See merge request !126
parents 76f010d7 490ff420
......@@ -7,6 +7,7 @@ import {
DialogTitle,
} from "@mui/material";
import CloseIcon from "@mui/icons-material/Close";
import { ThemeProvider, createTheme } from "@mui/material/styles";
import MyButton from "./MyButton";
......@@ -51,8 +52,27 @@ export interface IDialogProps {
| "info"
| "warning"; //按钮颜色风格
loading?: boolean; // 确认按钮是否处于loading状态
isText?: boolean; // 是否文本弹窗
}
const theme = createTheme({
// 0px 12px 15px -7px rgb(0 0 0 / 11%), 0px 24px 38px 3px rgb(0 0 0 / 9%), 0px 9px 46px 8px rgb(0 0 0 / 9%)
// .css-1t1j96h-MuiPaper-root-MuiDialog-paper
components: {
MuiPaper: {
styleOverrides: {
root: {
"&.MuiDialog-paper": {
boxShadow:
"0px 12px 15px -7px rgb(0 0 0 / 11%), 0px 24px 38px 3px rgb(0 0 0 / 9%), 0px 9px 46px 8px rgb(0 0 0 / 9%)",
},
},
},
},
},
});
const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
const {
title,
......@@ -74,6 +94,7 @@ const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
clickMaskClose = false,
loading = false,
okColor = "primary",
isText = false,
} = props;
const handelClose = (
......@@ -91,7 +112,7 @@ const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
return footerRender ? (
footerRender()
) : (
<DialogActions style={{ padding: "0 24px 16px 24px" }}>
<DialogActions style={{ padding: "16px 24px 16px 24px" }}>
{showCancel ? (
<MyButton
text={cancelText || "取消"}
......@@ -127,54 +148,66 @@ const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
loading,
showConfirm,
]);
const contentPadding = useMemo(() => {
if (isText) {
return "8px 24px 24px"; // 文本
} else {
return "8px 24px 12px"; // 表单
}
}, [isText]);
return (
<Dialog
open={open}
onClose={handelClose}
style={style}
className={className}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
sx={{
"& .MuiDialog-container": {
"& .MuiPaper-root": {
// 设置最大宽度, 实际宽度让子元素撑大
maxWidth: "1920px",
borderRadius: "8px",
<ThemeProvider theme={theme}>
<Dialog
open={open}
onClose={handelClose}
style={style}
className={className}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
sx={{
"& .MuiDialog-container": {
"& .MuiPaper-root": {
// 设置最大宽度, 实际宽度让子元素撑大
maxWidth: "1920px",
borderRadius: "8px",
},
},
},
}}
>
{isHideHeader ? null : (
<DialogTitle id="alert-dialog-title" sx={{ padding: "20px 24px" }}>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
fontWeight: 600,
}}
>
<span
style={{ fontSize: 16, lineHeight: "24px", color: "#1E2633" }}
>
{title}
</span>
<CloseIcon
onClick={onClose}
sx={{
fontSize: "18px",
color: "#C2C6CC",
cursor: "pointer",
":hover": { background: "#f0f2f5", borderRadius: "2px" },
}}
>
{isHideHeader ? null : (
<DialogTitle id="alert-dialog-title" sx={{ padding: "20px 24px" }}>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
fontWeight: 600,
}}
/>
</div>
</DialogTitle>
)}
<DialogContent style={{ minWidth: 388 }}>{children}</DialogContent>
{Footer}
</Dialog>
>
<span
style={{ fontSize: 16, lineHeight: "24px", color: "#1E2633" }}
>
{title}
</span>
<CloseIcon
onClick={onClose}
sx={{
fontSize: "18px",
color: "#C2C6CC",
cursor: "pointer",
":hover": { background: "#f0f2f5", borderRadius: "2px" },
}}
/>
</div>
</DialogTitle>
)}
<DialogContent style={{ minWidth: 388, padding: contentPadding }}>
{children}
</DialogContent>
{Footer}
</Dialog>
</ThemeProvider>
);
};
......
......@@ -77,11 +77,19 @@ const FileItem = observer((props: IProps) => {
if (text === "查看文件") {
if (
location?.state?.pathName !== fileItemInfo?.path ||
location?.pathname !== "/product/cadd/projectData"
location?.pathname !==
`/product/${
currentProjectStore.currentProductInfo.id || "cadd"
}/projectData`
) {
navigate(`/product/cadd/projectData`, {
state: { pathName: fileItemInfo?.path },
});
navigate(
`/product/${
currentProjectStore.currentProductInfo.id || "cadd"
}/projectData`,
{
state: { pathName: fileItemInfo?.path },
}
);
}
}
};
......
......@@ -10,6 +10,7 @@ import useMyRequest from "@/hooks/useMyRequest";
import { useStores } from "@/store";
import { toJS } from "mobx";
import { ITask } from "@/views/Project/ProjectSubmitWork/interface";
import { observer } from "mobx-react-lite";
type IProps = {
operatorList: ITask[];
......@@ -17,7 +18,7 @@ type IProps = {
setInputActive: any;
};
const OperatorList = (props: IProps) => {
const OperatorList = observer((props: IProps) => {
const { operatorList, setOperatorList, setInputActive } = props; // 流程图中流算子列表
const { currentProjectStore } = useStores();
const [list, setList] = useState<ITask[]>([]); // 算子列表
......@@ -249,6 +250,6 @@ const OperatorList = (props: IProps) => {
</div>
</div>
);
};
});
export default OperatorList;
......@@ -110,7 +110,7 @@ const AddFolder = (props: IAddFolderProps) => {
onConfirm={handleAddSubmit}
title="新建文件夹"
>
<div style={{ padding: "12px 0" }}>
<div>
<MyInput
sx={{
width: "388px",
......@@ -125,7 +125,12 @@ const AddFolder = (props: IAddFolderProps) => {
helperText={fileNameCheck.help}
InputProps={{
endAdornment: (
<InputAdornment position="end" style={{ color: fileName.length >= 30 ? "#d32f2f" : "#C2C6CC" }}>
<InputAdornment
position="end"
style={{
color: fileName.length >= 30 ? "#d32f2f" : "#C2C6CC",
}}
>
{fileName.length}/30
</InputAdornment>
),
......
......@@ -90,6 +90,7 @@ const DeleteDialog = (props: IDeleteFileProps) => {
onClose={() => setDeleteDialogOpen(false)}
onConfirm={handleSubmit}
okColor="error"
isText={true}
>
{currentOperateFile
? "确认删除该数据吗?"
......
......@@ -187,11 +187,11 @@ const ProjectSubmitWork = observer(() => {
const goToProjectData = (path: string) => {
path = path.slice(12);
if (path) {
navigate(`/product/cadd/projectData`, {
navigate(`/product/${productId || "cadd"}/projectData`, {
state: { pathName: path },
});
} else {
navigate(`/product/cadd/projectData`, {
navigate(`/product/${productId || "cadd"}/projectData`, {
state: { pathName: "/" },
});
}
......@@ -217,13 +217,13 @@ const ProjectSubmitWork = observer(() => {
/** 返回事件 */
const onBack = useCallback(() => {
if (locationInfo.from === "projectOverview") {
navigate("/product/cadd/projectOverview");
navigate(`/product/${productId || "cadd"}/projectOverview`);
} else {
navigate("/product/cadd/projectWorkbench", {
navigate(`/product/${productId || "cadd"}/projectWorkbench`, {
state: { type: "workbenchList" },
});
}
}, [navigate, locationInfo.from]);
}, [navigate, locationInfo.from, productId]);
const getOutouts = (outputs: any) => {
if (outputs) {
......
......@@ -2,6 +2,9 @@ import { useMemo, useCallback, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import MyProgress from "@/components/mui/MyProgress";
import style from "./index.module.css";
import { useStores } from "@/store";
import { toJS } from "mobx";
import { observer } from "mobx-react-lite";
import runTime from "../../../../assets/project/runTime.svg";
import jobCostImg from "../../../../assets/project/jobCost.svg";
......@@ -38,6 +41,8 @@ const TaskCard = (props: TaskCardProps) => {
} = props;
const navigate = useNavigate();
const [displayTitleBlue, setDisplayTitleBlue] = useState<boolean>(false);
const { currentProjectStore } = useStores();
const productId = toJS(currentProjectStore.currentProductInfo.id); // 产品ID
const randerOutputs = useMemo(() => {
if (outputs) {
......@@ -68,13 +73,13 @@ const TaskCard = (props: TaskCardProps) => {
path = path.slice(0, lastIndex);
}
path = path.slice(12);
navigate(`/product/cadd/projectData`, {
navigate(`/product/${productId || "cadd"}/projectData`, {
state: { pathName: path || "/", dataType: type },
});
};
// 跳转详情页
const gotoDetail = (id: string) => {
navigate(`/product/cadd/projectJobDetail`, {
navigate(`/product/${productId || "cadd"}/projectJobDetail`, {
state: { taskId: id, from: "projectOverview" },
});
};
......
......@@ -67,7 +67,9 @@
color: #1e2633;
margin-right: 8px;
}
.red{
color: rgba(255, 78, 78, 1);
}
.verticalLine {
height: 32px;
border-right: 1px solid #ebedf0;
......
......@@ -169,7 +169,10 @@ const ProjectOverview = observer(() => {
项目剩余预算
</div>
<div>
<span className={style.numberDisplay}>
<span className={classNames({
[style.numberDisplay]: true,
[style.red]:overviewInfo.projectRemainingBudget?.toFixed(2) < 100
})}>
{overviewInfo.projectRemainingBudget?.toFixed(2)}
</span>
......
......@@ -40,6 +40,7 @@ const BaseInfo = observer(() => {
const message = useMessage();
const { currentProjectStore } = useStores();
const fileToken = toJS(currentProjectStore.currentProjectInfo.filetoken);
const productId = toJS(currentProjectStore.currentProductInfo.id); // 产品ID
const [projectInfo, setProjectInfo] = useState<any>({});
const [deleteProjectName, setDeleteProjectName] = useState("");
const [nameCheck, setNameCheck] = useState({
......@@ -258,7 +259,7 @@ const BaseInfo = observer(() => {
{
onSuccess: async (result: any) => {
message.success("修改成功");
const projectList = await getProjectList();
const projectList = await getProjectList(productId);
currentProjectStore.setProjectList(projectList);
projectInfo.filetoken = fileToken;
currentProjectStore.changeProject(projectInfo);
......@@ -272,7 +273,7 @@ const BaseInfo = observer(() => {
checkName(projectInfo.name, true) &&
checkBudget(projectInfo.projectBudget, true)
) {
updateProjectRun({ ...projectInfo, product: "cadd" });
updateProjectRun({ ...projectInfo, product: `${productId || "cadd"}` });
} else {
return;
}
......@@ -282,7 +283,7 @@ const BaseInfo = observer(() => {
onSuccess: async (result: any) => {
message.success("删除成功");
setDialogOpen(false);
const projectList = await getProjectList();
const projectList = await getProjectList(productId);
currentProjectStore.setProjectList(projectList);
// 项目删完了
currentProjectStore.changeProject({});
......
......@@ -7,6 +7,7 @@
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { memo, useMemo } from "react";
import { useLocation } from "react-router-dom";
import { Box } from "@mui/system";
import { useStores } from "@/store/index";
......@@ -20,6 +21,7 @@ import usePass from "@/hooks/usePass";
const ProjectSetting = observer(() => {
const { currentProjectStore } = useStores();
const isPass = usePass();
const location: any = useLocation();
const tabList = useMemo(() => {
return [
{
......@@ -54,7 +56,10 @@ const ProjectSetting = observer(() => {
</span>
</div>
<Box sx={{ width: "100%", typography: "body1" }}>
<Tabs tabList={tabList} />
<Tabs
tabList={tabList}
defaultValue={location?.state?.type || "projectMember"}
/>
</Box>
</div>
);
......
......@@ -34,6 +34,7 @@ const ProjectSubmitWork = observer(() => {
const Message = useMessage();
const { currentProjectStore } = useStores();
const projectId = toJS(currentProjectStore.currentProjectInfo.id);
const productId = toJS(currentProjectStore.currentProductInfo.id); // 产品ID
const [templateConfigInfo, setTemplateConfigInfo] =
useState<ITemplateConfig>();
const location: any = useLocation();
......@@ -46,7 +47,7 @@ const ProjectSubmitWork = observer(() => {
// 前往工作台
const goToWorkbench = (toWorkbenchList = false) => {
navigate("/product/cadd/projectWorkbench", {
navigate(`/product/${productId || "cadd"}/projectWorkbench`, {
state: { type: toWorkbenchList ? "workbenchList" : "" },
});
};
......
......@@ -10,11 +10,13 @@ import { memo, useMemo } from "react";
import { Box } from "@mui/system";
import { observer } from "mobx-react-lite";
import { useLocation } from "react-router-dom";
import { useStores } from "@/store/index";
import WorkbenchTemplate from "./workbenchTemplate";
import WorkbenchList from "./workbenchList";
import Tabs from "@/components/mui/Tabs";
import usePass from "@/hooks/usePass";
import NoProject from "@/components/BusinessComponents/NoProject";
import Template from "@/assets/project/workbenchTemplate.svg";
import TemplateSelect from "@/assets/project/workbenchTemplate_select.svg";
import TemplateHover from "@/assets/project/workbenchTemplate_hover.svg";
......@@ -23,6 +25,7 @@ import ListHover from "@/assets/project/workbenchList_hover.svg";
import ListSelect from "@/assets/project/workbenchList_select.svg";
const ProjectWorkbench = observer(() => {
const { currentProjectStore } = useStores();
const isPass = usePass();
const location: any = useLocation();
......@@ -48,30 +51,33 @@ const ProjectWorkbench = observer(() => {
},
];
}, [isPass]);
return (
<div style={{ padding: "28px 24px 24px" }}>
<div style={{ display: "flex", alignItems: "center" }}>
<span
style={{
fontSize: "18px",
lineHeight: "26px",
fontWeight: "600",
color: "#1E2633",
marginBottom: "3px",
}}
>
工作台
</span>
if (currentProjectStore.currentProjectInfo.name) {
return (
<div style={{ padding: "28px 24px 24px" }}>
<div style={{ display: "flex", alignItems: "center" }}>
<span
style={{
fontSize: "18px",
lineHeight: "26px",
fontWeight: "600",
color: "#1E2633",
marginBottom: "3px",
}}
>
工作台
</span>
</div>
<Box sx={{ width: "100%", typography: "body1" }}>
<Tabs
tabList={tabList}
defaultValue={location?.state?.type || "workbenchTemplate"}
/>
</Box>
</div>
<Box sx={{ width: "100%", typography: "body1" }}>
<Tabs
tabList={tabList}
defaultValue={location?.state?.type || "workbenchTemplate"}
/>
</Box>
</div>
);
);
} else {
return <NoProject />;
}
});
export default memo(ProjectWorkbench);
......@@ -7,18 +7,15 @@
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { memo, useCallback, useEffect, useState } from "react";
import _ from "lodash";
import { useNavigate } from "react-router-dom";
import { Box, Typography } from "@mui/material";
import OutlinedInput from "@mui/material/OutlinedInput";
import { TablePagination } from "@mui/material";
import MyPagination from "@/components/mui/MyPagination";
import MySelect from "@/components/mui/MySelect";
import SimpleDialog from "./components/simpleDialog";
import { useStores } from "@/store";
import useMyRequest from "@/hooks/useMyRequest";
import ActionsComponent from "../../../../components/Material.Ui/Table/ActionsComponent";
import runTime from "../../../../assets/project/runTime.svg";
import jobCost from "../../../../assets/project/jobCost.svg";
import jobSue from "../../../../assets/project/jobSue.svg";
......@@ -77,6 +74,7 @@ const ProjectMembers = observer(() => {
const { currentProjectStore } = useStores();
const projectId = toJS(currentProjectStore.currentProjectInfo.id);
const productId = toJS(currentProjectStore.currentProductInfo.id); // 产品ID
const isPass = usePass();
const [jobName, setJobName] = useState("");
const [jobList, setJobList] = useState([]);
......@@ -287,11 +285,11 @@ const ProjectMembers = observer(() => {
/** 点击每一行 */
const rowClick = useCallback(
(id: string) => {
navigate(`/product/cadd/projectJobDetail`, {
navigate(`/product/${productId || "cadd"}/projectJobDetail`, {
state: { taskId: id, from: "workbenchList" },
});
},
[navigate]
[navigate, productId]
);
// 回车搜索
......@@ -312,7 +310,8 @@ const ProjectMembers = observer(() => {
<SearchInput
onKeyUp={handleKeyWordChangeKeyUp}
onBlur={handleKeyWordChangeBlur}
sx={{ width: 340 }} />
sx={{ width: 340 }}
/>
{/* <Box className={styles.tabHeaderSelect}>
<TextField
select
......@@ -463,7 +462,7 @@ const ProjectMembers = observer(() => {
<Box className={styles.tabBoxJobOperate}>
{currentProjectStore.currentProjectInfo.projectRole ===
"USER" &&
item.creator !==
item.creator !==
JSON.parse(localStorage.getItem("userInfo") || "{}")
?.name ? (
""
......
......@@ -4,11 +4,9 @@ import classNames from "classnames";
import { Box, Typography } from "@mui/material";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import SearchIcon from "@mui/icons-material/Search";
import MyButton from "@/components/mui/MyButton";
import OutlinedInput from "@mui/material/OutlinedInput";
import MySwitch from "@/components/mui/MySwitch";
import FullScreenDrawer from "@/components/CommonComponents/FullScreenDrawer";
import Checkbox from "@mui/material/Checkbox";
import useMyRequest from "@/hooks/useMyRequest";
import AddIcon from "@mui/icons-material/Add";
import WorkFlowEdit from "@/views/WorkFlowEdit";
......
.content {
width: 400px;
font-size: 14px;
line-height: 22px;
color: rgba(30, 38, 51, 1);
}
import MyDialog from "@/components/mui/MyDialog";
import MyButton from "@/components/mui/MyButton";
import { DialogActions } from "@mui/material";
import style from "./index.module.css";
import { useStores } from "@/store";
import { observer } from "mobx-react-lite";
import { toJS } from "mobx";
import { useNavigate } from "react-router-dom";
const RemindBudgetDialog = observer((props: any) => {
const navigate = useNavigate();
const { rbOpen, rbClose, goToProjectSubmitWork, id, isParentUser, isOwner } =
props;
const { currentProjectStore } = useStores();
const productId = toJS(currentProjectStore.currentProductInfo.id); // 产品ID
const goToprojectSetting = () => {
navigate(`/product/${productId || "cadd"}/projectSetting`, {
state: { type: "baseInfo" },
});
};
const footerRender = () => {
return (
<DialogActions style={{ padding: "16px 24px 16px 24px" }}>
<MyButton
text="继续使用"
onClick={() => goToProjectSubmitWork(id)}
variant="outlined"
color="secondary"
/>
{isParentUser && isOwner && (
<MyButton
text="添加预算"
onClick={() => goToprojectSetting()}
variant="contained"
style={{ marginLeft: "12px" }}
/>
)}
</DialogActions>
);
};
return (
<>
<MyDialog
open={rbOpen}
onClose={rbClose}
title="项目剩余预算不足提示"
footerRender={footerRender}
isText={true}
>
<div className={style.content}>
当前项目剩余预算不足100元,存在余额不足的风险,可能导致无法启动任务或中断运行中的任务,建议您先添加项目预算或联系项目所有者添加预算!
</div>
</MyDialog>
</>
);
});
export default RemindBudgetDialog;
......@@ -13,6 +13,7 @@ const SimpleDialog = (props: any) => {
onConfirm={onConfirm}
title={title}
okColor="error"
isText={true}
>
<Box>
<Typography sx={{ fontSize: "14px", fontWeight: "400" }}>
......
......@@ -6,113 +6,146 @@
* @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 } from "react";
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 = (props: any) => {
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 addTemplateBlock = useCallback(
const goToProjectSubmitWork = useCallback(
(id: string) => {
navigate(`/product/cadd/projectSubmitWork`, {
navigate(`/product/${productId || "cadd"}/projectSubmitWork`, {
state: { id },
});
},
[navigate]
[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
<>
<Box className={styles.template}>
<Box className={styles.templateBlock}>
<Box>
<Box
sx={{
fontSize: "14px",
fontWeight: "600",
color: "#1E2633",
marginBottom: "4px",
overflow: "hidden",
textOverflow: "ellipsis",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
{info.title}
</Typography>
{info.creator !== "root" && (
<Box
<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={{
backgroundColor: "rgba(227, 250, 236, 1)",
color: "rgba(2, 171, 131, 1)",
lineHeight: "20px",
padding: "1px 9px",
fontSize: "12px",
fontWeight: "400",
color: "#1370FF",
marginRight: "24px",
}}
>
自定义
</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}
版本:{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>
<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={() => addTemplateBlock(info.id)}
style={{ marginLeft: "12px" }}
/>
)}
<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>
</Box>
{rbOpen && (
<RemindBudgetDialog
rbOpen={rbOpen}
rbClose={() => setRbOpen(false)}
id={id}
goToProjectSubmitWork={goToProjectSubmitWork}
isParentUser={isParentUser}
isOwner={isOwner}
></RemindBudgetDialog>
)}
</>
);
};
});
export default memo(TemplateBox);
......@@ -10,8 +10,8 @@ import { memo, useEffect, useState } from "react";
import { Box, Typography } from "@mui/material";
import { toJS } from "mobx";
import { observer } from "mobx-react-lite";
import FormatListBulletedRoundedIcon from '@mui/icons-material/FormatListBulletedRounded';
import FormatListBulletedRoundedIcon from "@mui/icons-material/FormatListBulletedRounded";
import { getLoaclStorageOfKey } from "@/api/fileserver/utils";
import MyButton from "@/components/mui/MyButton";
import SearchInput from "@/components/BusinessComponents/SearchInput";
......@@ -24,11 +24,15 @@ import {
getWorkbenchTemplate,
deleteWorkbenchTemplate,
} from "@/api/workbench_api";
import { getOverviewInfo, getProject } from "@/api/project_api";
import usePass from "@/hooks/usePass";
import { useStores } from "@/store";
import styles from "./index.module.css";
const userInfo = getLoaclStorageOfKey("userInfo");
const ProjectMembers = observer(() => {
const { currentProjectStore } = useStores();
const projectIdData = toJS(currentProjectStore.currentProjectInfo.id);
......@@ -109,6 +113,49 @@ const ProjectMembers = observer(() => {
}
};
// 项目剩余预算是否大于100 Greater than 100
const [greaterThan100, setGreaterThan100] = useState(false);
// 获取概览基本信息 用于获取项目剩余预算 projectRemainingBudget
const { run: getOverview } = useMyRequest(getOverviewInfo, {
onSuccess: (result: any) => {
if (result.data.projectRemainingBudget > 100) {
setGreaterThan100(true);
} else {
setGreaterThan100(false);
}
},
});
useEffect(() => {
if (currentProjectStore.currentProjectInfo.id) {
getOverview({
id: currentProjectStore.currentProjectInfo.id as string,
});
}
}, [currentProjectStore.currentProjectInfo.id, getOverview]);
// 用户是否为父用户
const [isParentUser] = useState(!userInfo.parent ? true : false);
// 当前用户是否为项目的所有者
const [isOwner, setIsOwner] = useState(false);
const { run: getProjectFn } = useMyRequest(getProject, {
onSuccess: (result: any) => {
if (result.data.projectRole === "OWNER") {
setIsOwner(true);
} else {
setIsOwner(false);
}
},
});
useEffect(() => {
getProjectFn({
id: currentProjectStore.currentProjectInfo.id as string,
});
}, [currentProjectStore.currentProjectInfo.id, getProjectFn]);
return (
<Box className={styles.headerBox}>
<Box className={styles.tabBox}>
......@@ -116,7 +163,7 @@ const ProjectMembers = observer(() => {
{isPass("PROJECT_WORKBENCH_FLOES_ADD", "MANAGER") && (
<MyButton
text={"管理工作流模板"}
startIcon={<FormatListBulletedRoundedIcon fontSize="small"/>}
startIcon={<FormatListBulletedRoundedIcon fontSize="small" />}
onClick={addTemplateBlock}
size={"medium"}
/>
......@@ -147,7 +194,14 @@ const ProjectMembers = observer(() => {
templateList.length > 0 &&
templateList.map((item, key) => {
return (
<TemplateBox key={key} data={item} startDialog={startDialog} />
<TemplateBox
key={key}
data={item}
startDialog={startDialog}
isParentUser={isParentUser}
isOwner={isOwner}
greaterThan100={greaterThan100}
/>
);
})}
</Box>
......
......@@ -10,6 +10,8 @@ import { useMessage } from "@/components/MySnackbar";
import { getProjectList } from "../../project";
import { useStores } from "@/store";
import { checkIsNumberLetterChinese } from "@/utils/util";
import { observer } from "mobx-react-lite";
import { toJS } from "mobx";
import {
setFileServerEndPointLocalStorage,
getFiletokenAccordingToId,
......@@ -27,12 +29,13 @@ type IAddProjectProps = {
setAddOpen: any;
};
const AddProject = (props: IAddProjectProps) => {
const AddProject = observer((props: IAddProjectProps) => {
const { addOpen, setAddOpen } = props;
const { currentProjectStore } = useStores();
const navigate = useNavigate();
const message = useMessage();
const [name, setName] = useState("");
const productId = toJS(currentProjectStore.currentProductInfo.id); // 产品ID
const [nameCheck, setNameCheck] = useState({
error: false,
help: "",
......@@ -62,7 +65,7 @@ const AddProject = (props: IAddProjectProps) => {
setAddOpen(false);
setLoading(false);
message.success("新建项目成功");
const projectList = await getProjectList();
const projectList = await getProjectList(productId);
currentProjectStore.setProjectList(projectList);
let project: any = {};
projectList.forEach((item: any) => {
......@@ -75,7 +78,7 @@ const AddProject = (props: IAddProjectProps) => {
project.filetoken = res;
currentProjectStore.changeProject(project);
});
navigate(`/product/cadd/projectOverview`);
navigate(`/product/${productId || "cadd"}/projectOverview`);
}
},
onError: () => {
......@@ -157,7 +160,7 @@ const AddProject = (props: IAddProjectProps) => {
name,
desc,
zoneId,
product: "cadd",
product: productId || "cadd",
});
} else {
return;
......@@ -232,6 +235,6 @@ const AddProject = (props: IAddProjectProps) => {
</div>
</MyDialog>
);
};
});
export default AddProject;
......@@ -12,8 +12,8 @@ import {
getDataFileToken,
} from "@/api/project_api";
export const getProjectList = async () => {
const res = await getProjectListApi({ product: "cadd" });
export const getProjectList = async (id = 'cadd') => {
const res = await getProjectListApi({ product: id });
return res.data;
};
......
......@@ -64,7 +64,7 @@ const SaveCustomTemplate = (props: IProps) => {
});
// 自定义模板保存方法
const { run: saveUserSpecRun } = useMyRequest(saveUserSpec, {
const { run: saveUserSpecRun, loading } = useMyRequest(saveUserSpec, {
onSuccess: (res) => {
Message.success("保存成功!");
onBack && onBack();
......@@ -220,6 +220,7 @@ const SaveCustomTemplate = (props: IProps) => {
title="保存自定义模板"
onClose={handleCloseDialog}
onConfirm={handleOncofirm}
loading={loading}
>
<div className={styles.saveBox}>
<MyInput
......
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