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