Commit 21d75bb6 authored by wuyongsheng's avatar wuyongsheng

feat: 添加项目成员优化

parent ca0fc530
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-13 09:56:57 * @Date: 2022-06-13 09:56:57
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-08-15 17:10:49 * @LastEditTime: 2022-09-01 15:30:28
* @FilePath: /bkunyun/src/api/api_manager.ts * @FilePath: /bkunyun/src/api/api_manager.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -45,6 +45,9 @@ const RESTAPI = { ...@@ -45,6 +45,9 @@ const RESTAPI = {
API_TASK_OVERVIEW_LIST:`${BACKEND_API_URI_PREFIX}/cpp/workflowJobInformation`, // 查询任务概览 API_TASK_OVERVIEW_LIST:`${BACKEND_API_URI_PREFIX}/cpp/workflowJobInformation`, // 查询任务概览
API_OPERATOR_LISTSTREAMACTORS:`${BACKEND_API_URI_PREFIX}/cpp/workflow/liststreamactors`, // 获取流算子列表,可用于模糊查询,返回所有版本流算子 API_OPERATOR_LISTSTREAMACTORS:`${BACKEND_API_URI_PREFIX}/cpp/workflow/liststreamactors`, // 获取流算子列表,可用于模糊查询,返回所有版本流算子
API_SAVE_BATCHACTOR:`${BACKEND_API_URI_PREFIX}/cpp/workflow/savebatchactor`, // 保存批算子 API_SAVE_BATCHACTOR:`${BACKEND_API_URI_PREFIX}/cpp/workflow/savebatchactor`, // 保存批算子
API_PROJECT_USERS_LIST:`${BACKEND_API_URI_PREFIX}/cpp/project/listusers`, // 获取项目成员
API_ADD_PROJECT_USER:`${BACKEND_API_URI_PREFIX}/cpp/project/updatemember`, // 添加项目成员
API_GET_PROJECT_POWER:`${BACKEND_API_URI_PREFIX}/cpp/project/listroles`, // 获取项目权限
}; };
export default RESTAPI; export default RESTAPI;
...@@ -318,6 +318,34 @@ const saveBatchActor = (params: saveBatchParams) => { ...@@ -318,6 +318,34 @@ const saveBatchActor = (params: saveBatchParams) => {
}); });
}; };
// 获取项目成员
const fetchProjectUsersList = (params: {id: string}) => {
return request({
url: Api.API_PROJECT_USERS_LIST,
method: "get",
params,
});
};
// 修改项目成员信息
const addProjectUser = (id: string, params: any) => {
return request({
url: `${Api.API_ADD_PROJECT_USER}?id=${id}`,
method: "put",
data: params,
});
};
// 获取项目权限
const fetchProjectPower = (params: {id: string}) => {
return request({
url: Api.API_GET_PROJECT_POWER,
method: "get",
params,
});
};
export { export {
current, current,
menu, menu,
...@@ -342,5 +370,8 @@ export { ...@@ -342,5 +370,8 @@ export {
getTaskOverview, getTaskOverview,
getOperatorList, getOperatorList,
saveBatchActor, saveBatchActor,
fetchFlowOutputNumber fetchFlowOutputNumber,
fetchProjectUsersList,
addProjectUser,
fetchProjectPower
}; };
This diff is collapsed.
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生 15770852798@163.com * @Author: 吴永生 15770852798@163.com
* @Date: 2022-07-26 10:23:43 * @Date: 2022-07-26 10:23:43
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-07-26 11:53:00 * @LastEditTime: 2022-09-01 16:00:34
* @FilePath: /bkunyun/src/components/mui/MyTable/interface.ts * @FilePath: /bkunyun/src/components/mui/MyTable/interface.ts
* @Description: 这是默认设置,请设置`customMade`,打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`,打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -32,7 +32,7 @@ export interface ITableProps { ...@@ -32,7 +32,7 @@ export interface ITableProps {
/** 每行双击事件 */ /** 每行双击事件 */
onDoubleClick?: any, onDoubleClick?: any,
/** 是否loading */ /** 是否loading */
load?: boolean, loading?: boolean,
/** table size */ /** table size */
size?: any, size?: any,
/** 选中的checkbox数据 */ /** 选中的checkbox数据 */
...@@ -71,4 +71,6 @@ export interface ITableProps { ...@@ -71,4 +71,6 @@ export interface ITableProps {
onRef?: any; onRef?: any;
/** 手型 */ /** 手型 */
cursor?: string cursor?: string
/** 没有数据文案 */
noDataText?: string
} }
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-10 18:05:21 * @Date: 2022-06-10 18:05:21
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-09-01 14:09:28 * @LastEditTime: 2022-09-01 15:54:33
* @FilePath: /bkunyun/src/views/ConsoleLayout/components/TransferList/index.tsx * @FilePath: /bkunyun/src/views/ConsoleLayout/components/TransferList/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13 * @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-09-01 14:09:34 * @LastEditTime: 2022-09-01 16:14:10
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx * @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -13,12 +13,17 @@ import { memo, useCallback, useEffect, useMemo, useState } from "react"; ...@@ -13,12 +13,17 @@ import { memo, useCallback, useEffect, useMemo, useState } from "react";
import { Box, OutlinedInput } from "@mui/material"; import { Box, OutlinedInput } from "@mui/material";
import Dialog from "@/components/mui/MyDialog"; import Dialog from "@/components/mui/MyDialog";
import { IResponse, useHttp } from "@/api/http"; import useMyRequest from "@/hooks/useMyRequest";
import { useStores } from "@/store"; import { useStores } from "@/store";
import { useMessage } from "@/components/MySnackbar"; import { useMessage } from "@/components/MySnackbar";
import MySelect, { IOption } from "@/components/mui/MySelect"; import MySelect, { IOption } from "@/components/mui/MySelect";
import MyTable from "@/components/mui/MyTable"; import MyTable from "@/components/mui/MyTable";
import SearchInput from "@/components/BusinessComponents/SearchInput"; import SearchInput from "@/components/BusinessComponents/SearchInput";
import {
addProjectUser,
fetchProjectPower,
fetchProjectUsersList,
} from "@/api/project_api";
interface IProps { interface IProps {
setAddMemberDialog: (val: boolean) => void; setAddMemberDialog: (val: boolean) => void;
...@@ -29,7 +34,6 @@ interface IProps { ...@@ -29,7 +34,6 @@ interface IProps {
const AddMember = observer((props: IProps) => { const AddMember = observer((props: IProps) => {
const { addMemberDialog, setAddMemberDialog, getTableList } = props; const { addMemberDialog, setAddMemberDialog, getTableList } = props;
const http = useHttp();
const { currentProjectStore } = useStores(); const { currentProjectStore } = useStores();
const [tableData, setTableData] = useState([]); const [tableData, setTableData] = useState([]);
...@@ -76,14 +80,6 @@ const AddMember = observer((props: IProps) => { ...@@ -76,14 +80,6 @@ const AddMember = observer((props: IProps) => {
]; ];
}, [changePermission, selectOptions]); }, [changePermission, selectOptions]);
useEffect(() => {
if (addMemberDialog) {
http.get<IResponse<any>>("/cpp/project/listroles").then((res) => {
setSelectOptions(res.data);
});
}
}, [addMemberDialog, http]);
/** 过滤表格数据 */ /** 过滤表格数据 */
useEffect(() => { useEffect(() => {
if (!!projectMember) { if (!!projectMember) {
...@@ -97,18 +93,48 @@ const AddMember = observer((props: IProps) => { ...@@ -97,18 +93,48 @@ const AddMember = observer((props: IProps) => {
} }
}, [projectMember, tableData]); }, [projectMember, tableData]);
// 获取表格数据接口
const { run: getProjectUsersList } = useMyRequest(fetchProjectUsersList, {
onSuccess: (res: any) => {
setTableData(res?.data);
},
});
// 获取项目权限
const { run: getProjectPower } = useMyRequest(fetchProjectPower, {
onSuccess: (res: any) => {
setSelectOptions(res.data);
},
});
// 添加项目成员
const { run: saveProjectUser } = useMyRequest(addProjectUser, {
onSuccess: (res: any) => {
const { errorCode } = res;
if (errorCode === 0) {
Message.success("新增成功!");
getTableList();
setAddMemberDialog(false);
}
},
});
useEffect(() => {
if (addMemberDialog) {
getProjectPower();
}
}, [addMemberDialog, getProjectPower]);
/** 获取表格数据 */ /** 获取表格数据 */
useEffect(() => { useEffect(() => {
if (!addMemberDialog) return; if (!addMemberDialog) return;
const projectInfo = toJS(currentProjectStore?.currentProjectInfo); const projectInfo = toJS(currentProjectStore?.currentProjectInfo);
http getProjectUsersList({ id: projectInfo?.id || "" });
.get<IResponse<any>>("/cpp/project/listusers", { }, [
params: { id: projectInfo?.id || "" }, currentProjectStore?.currentProjectInfo,
}) addMemberDialog,
.then((res) => { getProjectUsersList,
setTableData(res?.data); ]);
});
}, [currentProjectStore?.currentProjectInfo, http, addMemberDialog]);
const onClose = (event: any = {}, reason: any = "other") => { const onClose = (event: any = {}, reason: any = "other") => {
// 点击弹窗外不关闭弹窗 // 点击弹窗外不关闭弹窗
...@@ -124,19 +150,7 @@ const AddMember = observer((props: IProps) => { ...@@ -124,19 +150,7 @@ const AddMember = observer((props: IProps) => {
return checkData.includes(item?.username); return checkData.includes(item?.username);
}); });
if (params.length) { if (params.length) {
http saveProjectUser(projectInfo?.id || "", params);
.put<IResponse<any>>(
`/cpp/project/updatemember?id=${projectInfo?.id || ""}`,
params
)
.then((res) => {
const { errorCode } = res;
if (errorCode === 0) {
Message.success("新增成功!");
getTableList();
setAddMemberDialog(false);
}
});
} else { } else {
Message.info("请先选择项目成员!"); Message.info("请先选择项目成员!");
} }
...@@ -162,6 +176,9 @@ const AddMember = observer((props: IProps) => { ...@@ -162,6 +176,9 @@ const AddMember = observer((props: IProps) => {
/> />
<div style={{ overflow: "overlay", maxHeight: 400 }}> <div style={{ overflow: "overlay", maxHeight: 400 }}>
<MyTable <MyTable
noDataText={
projectMember ? `暂无 "${projectMember}" 搜索结果` : undefined
}
tableContainerStyle={{ height: 346 }} tableContainerStyle={{ height: 346 }}
checkboxData={(val: string[]) => setCheckData(val)} checkboxData={(val: string[]) => setCheckData(val)}
param="username" param="username"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13 * @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-08-22 15:33:02 * @LastEditTime: 2022-09-01 16:35:02
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx * @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -87,29 +87,26 @@ const ProjectMembers = observer(() => { ...@@ -87,29 +87,26 @@ const ProjectMembers = observer(() => {
const [jobData, setJobData] = useState(""); const [jobData, setJobData] = useState("");
const [openDialog, setOpenDialog] = useState(false); const [openDialog, setOpenDialog] = useState(false);
const [dialogType, setDialogType] = useState("del"); const [dialogType, setDialogType] = useState("del");
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false);
// 获取作业列表 // 获取作业列表
const { run: getWorkflowJobInfo } = useMyRequest( const { run: getWorkflowJobInfo } = useMyRequest(getWorkflowJobList, {
getWorkflowJobList, onSuccess: (result: any) => {
{ setLoading(false);
onSuccess: (result: any) => { setJobList(result.data.content);
setLoading(false) setCount(result.data.totalElements);
setJobList(result.data.content); timer && clearTimeout(timer as number);
setCount(result.data.totalElements); timer = null;
timer && clearTimeout(timer as number); timer = setTimeout(() => {
timer = null; getWorkflowJobInfo({
timer = setTimeout(() => { projectId: currentProjectStore.currentProjectInfo.id as string,
getWorkflowJobInfo({ page: page,
projectId: currentProjectStore.currentProjectInfo.id as string, size: size,
page: page, name: jobName,
size: size, state: currency === "ALL" ? "" : currency,
name: jobName, });
state: currency === "ALL" ? "" : currency, }, 60000);
}); },
}, 60000); });
},
}
);
useEffect(() => { useEffect(() => {
return () => { return () => {
...@@ -298,7 +295,7 @@ const ProjectMembers = observer(() => { ...@@ -298,7 +295,7 @@ const ProjectMembers = observer(() => {
const handleKeyWordChangeKeyUp = (e: any) => { const handleKeyWordChangeKeyUp = (e: any) => {
if (e.keyCode === 13) { if (e.keyCode === 13) {
setJobName(e.target.value); setJobName(e.target.value);
setLoading(true) setLoading(true);
} }
}; };
...@@ -367,7 +364,7 @@ const ProjectMembers = observer(() => { ...@@ -367,7 +364,7 @@ const ProjectMembers = observer(() => {
name: jobName, name: jobName,
state: currency === "ALL" ? "" : currency, state: currency === "ALL" ? "" : currency,
}); });
setLoading(true) setLoading(true);
}} }}
> >
<img alt="" src={onload} /> <img alt="" src={onload} />
...@@ -375,124 +372,128 @@ const ProjectMembers = observer(() => { ...@@ -375,124 +372,128 @@ const ProjectMembers = observer(() => {
</Box> </Box>
<Box className={styles.body} style={{ position: "relative" }}> <Box className={styles.body} style={{ position: "relative" }}>
<MyCircularProgress loading={loading} /> <MyCircularProgress loading={loading}>
{jobList.length === 0 && !loading && ( {jobList.length === 0 && !loading && (
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
flexDirection: "column", flexDirection: "column",
minHeight: "calc(100vh - 376px)", minHeight: "calc(100vh - 376px)",
justifyContent: "center", justifyContent: "center",
}} }}
>
<img alt="" src={noData} />
<Typography
sx={{ fontSize: "12px", fontWeight: "400", color: "#8A9099" }}
> >
暂无任务 <img alt="" src={noData} />
</Typography> <Typography
</Box> sx={{ fontSize: "12px", fontWeight: "400", color: "#8A9099" }}
)} >
{jobList.length > 0 && 暂无任务
jobList.map((item: any, key) => { </Typography>
return ( </Box>
<Box className={styles.tabBox} onClick={() => rowClick(item.id)}> )}
<Box className={styles.tabBoxInfo}> {jobList.length > 0 &&
<div className={styles.tabBoxTitle}>{item.name}</div> jobList.map((item: any, key) => {
<Box className={styles.tabBoxDescInfo}> return (
<div <Box
className={styles.tabBoxDesc} className={styles.tabBox}
style={{ marginRight: "24px" }} onClick={() => rowClick(item.id)}
> >
创建时间:{moment(item.createTime).format("YYYY-MM-DD")} <Box className={styles.tabBoxInfo}>
</div> <div className={styles.tabBoxTitle}>{item.name}</div>
<div className={styles.tabBoxDesc}> <Box className={styles.tabBoxDescInfo}>
创建人:{item.creator} <div
className={styles.tabBoxDesc}
style={{ marginRight: "24px" }}
>
创建时间:{moment(item.createTime).format("YYYY-MM-DD")}
</div>
<div className={styles.tabBoxDesc}>
创建人:{item.creator}
</div>
</Box>
</Box>
<Box className={styles.tabBoxMiddle}>
<img alt="" src={runTime} />
<div className={styles.tabBoxTime}>{item.costTime}</div>
</Box>
<Box className={styles.tabBoxMiddle}>
<img alt="" src={jobCost} />
<div className={styles.tabBoxTime}>
{item.jobCost ? item.jobCost.toFixed(2) : "--"}
</div> </div>
</Box> </Box>
</Box> <Box className={styles.tabBoxJobStatus}>
<Box className={styles.tabBoxMiddle}> <img alt="" src={renderStatusIcon(item.state)} />
<img alt="" src={runTime} /> <div className={styles.tabBoxStatusText}>
<div className={styles.tabBoxTime}>{item.costTime}</div> {renderStatusText(item.state)}
</Box> </div>
<Box className={styles.tabBoxMiddle}> <Box sx={{ width: "100%" }}>
<img alt="" src={jobCost} /> <MyProgress
<div className={styles.tabBoxTime}> color={renderProgressColor(item.state)}
{item.jobCost ? item.jobCost.toFixed(2) : "--"} value={(item.completeNum / item.totalNum) * 100}
</div> sx={{
</Box> marginRight: "16px",
<Box className={styles.tabBoxJobStatus}> }}
<img alt="" src={renderStatusIcon(item.state)} /> />
<div className={styles.tabBoxStatusText}> </Box>
{renderStatusText(item.state)} <div
</div> style={{
<Box sx={{ width: "100%" }}> color: renderTextColor(item.state),
<MyProgress margin: "0px",
color={renderProgressColor(item.state)}
value={(item.completeNum / item.totalNum) * 100}
sx={{
marginRight: "16px",
}} }}
/> className={styles.tabBoxStatusText}
>
{item.completeNum + "/" + item.totalNum}
</div>
</Box> </Box>
<div
style={{
color: renderTextColor(item.state),
margin: "0px",
}}
className={styles.tabBoxStatusText}
>
{item.completeNum + "/" + item.totalNum}
</div>
</Box>
{(item.state === "RUNNING" || item.state === "SUBMITTED") && {(item.state === "RUNNING" || item.state === "SUBMITTED") &&
isPass("PROJECT_WORKBENCH_JOBS_STOP", "USER") && ( isPass("PROJECT_WORKBENCH_JOBS_STOP", "USER") && (
<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 ? (
"" ""
) : ( ) : (
<img
alt=""
src={jobStop}
style={{ cursor: "pointer" }}
onClick={(event) => {
event.stopPropagation();
event.nativeEvent.stopImmediatePropagation();
setJobData(item.id);
setOpenDialog(true);
setDialogType("stop");
}}
/>
)}
</Box>
)}
{item.state !== "RUNNING" &&
item.state !== "SUBMITTED" &&
isPass("PROJECT_WORKBENCH_JOBS_DELETE", "MANAGER") && (
<Box className={styles.tabBoxJobOperate}>
<img <img
alt="" alt=""
src={jobStop} src={jobDel}
style={{ cursor: "pointer" }} style={{ cursor: "pointer" }}
onClick={(event) => { onClick={(event) => {
event.stopPropagation(); event.stopPropagation();
event.nativeEvent.stopImmediatePropagation(); event.nativeEvent.stopImmediatePropagation();
setJobData(item.id); setJobData(item.id);
setOpenDialog(true); setOpenDialog(true);
setDialogType("stop"); setDialogType("del");
}} }}
/> />
)} </Box>
</Box> )}
)} </Box>
{item.state !== "RUNNING" && );
item.state !== "SUBMITTED" && })}
isPass("PROJECT_WORKBENCH_JOBS_DELETE", "MANAGER") && ( </MyCircularProgress>
<Box className={styles.tabBoxJobOperate}>
<img
alt=""
src={jobDel}
style={{ cursor: "pointer" }}
onClick={(event) => {
event.stopPropagation();
event.nativeEvent.stopImmediatePropagation();
setJobData(item.id);
setOpenDialog(true);
setDialogType("del");
}}
/>
</Box>
)}
</Box>
);
})}
</Box> </Box>
<TablePagination <TablePagination
......
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