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
}; };
import React, { useCallback, useState} from "react"; import React, { useCallback, useState } from "react";
import Table from "@mui/material/Table"; import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody"; import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell"; import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer"; import TableContainer from "@mui/material/TableContainer";
import { TablePagination } from '@mui/material'; import { TablePagination } from "@mui/material";
import TableRow from "@mui/material/TableRow"; import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper"; import Paper from "@mui/material/Paper";
import Checkbox from "@mui/material/Checkbox"; import Checkbox from "@mui/material/Checkbox";
import { useEffect } from "react"; import { useEffect } from "react";
import { useImperativeHandle } from "react"; import { useImperativeHandle } from "react";
// import Spin from "./Spin"; import MyCircularProgress from "@/components/mui/MyCircularProgress";
import EnhancedTableHeadComponent from "./components/EnhancedTableHead" import EnhancedTableHeadComponent from "./components/EnhancedTableHead";
import { getComparator, stableSort, useStyles } from "./utils"; import { getComparator, stableSort, useStyles } from "./utils";
import ActionsComponent from "./components/ActionsComponent"; import ActionsComponent from "./components/ActionsComponent";
import {ITableProps} from './interface' import { ITableProps } from "./interface";
export default function EnhancedTable(props: ITableProps) { export default function EnhancedTable(props: ITableProps) {
const classes: any = useStyles; const classes: any = useStyles;
const [order, setOrder] = useState("asc"); const [order, setOrder] = useState("asc");
const [orderBy, setOrderBy] = useState(""); const [orderBy, setOrderBy] = useState("");
const { headCells, rows, footer = true, elevation1, tableStyle, tableCellStyle, tableContainerStyle, stickyHeader, onRowClick, defaultRow, minHeight = '', borderBottom = '', onDoubleClick, const {
load, size, checkboxData, rowsPerPage = 10, initSelected, page = 0, changePage = function () { }, toolbar, count, param, disabledParam = "id", headTableCellCheckbox, RowHeight = '', CellWidth = '', rowHover, TableNodataPadding = '', TableNodataLineHeight = '', tableBodySx, radioClick} = props; headCells,
const [selected, setSelected] = useState(initSelected || []); rows,
const [rowsPerPageOptions] = useState(initSelected || [5, 10, 20, 50, { value: -1, label: 'All' }]); footer = true,
const [onRow, setOnRow] = useState('') elevation1,
tableStyle,
// 重置复选框选中选项 tableCellStyle,
const initSelectedFunc = (e: any) => { tableContainerStyle,
setSelected(e) stickyHeader,
} onRowClick,
defaultRow,
useImperativeHandle(props.onRef, () => { minHeight = "",
return { borderBottom = "",
initSelectedFunc: initSelectedFunc, onDoubleClick,
}; loading = false,
}); noDataText = "暂无数据",
size,
useEffect(() => { checkboxData,
setOnRow(defaultRow) rowsPerPage = 10,
}, [defaultRow]) initSelected,
page = 0,
const onRowClickDefault = (value: any) => { changePage = function () {},
setOnRow(value) toolbar,
onRowClick && onRowClick(value) count,
} param,
disabledParam = "id",
const handleRequestSort = (event: any, property: any) => { headTableCellCheckbox,
const isAsc = orderBy === property && order === "asc"; RowHeight = "",
setOrder(isAsc ? "desc" : "asc"); CellWidth = "",
setOrderBy(property); rowHover,
}; TableNodataPadding = "",
TableNodataLineHeight = "",
const handleSelectAllClick = (event: any) => { tableBodySx,
if (event.target.checked) { radioClick,
const newSelecteds = rows.map((n: any) => n[param || 'id']); } = props;
setSelected(newSelecteds); const [selected, setSelected] = useState(initSelected || []);
checkboxData(newSelecteds); const [rowsPerPageOptions] = useState(
return; initSelected || [5, 10, 20, 50, { value: -1, label: "All" }]
} );
setSelected([]); const [onRow, setOnRow] = useState("");
checkboxData([]);
}; // 重置复选框选中选项
const handleClick = (event: any, name: any) => { const initSelectedFunc = (e: any) => {
const selectedIndex = selected.indexOf(name); setSelected(e);
let newSelected: any[] = []; };
if (selectedIndex === -1) { useImperativeHandle(props.onRef, () => {
newSelected = newSelected.concat(selected, name); return {
} else if (selectedIndex === 0) { initSelectedFunc: initSelectedFunc,
newSelected = newSelected.concat(selected.slice(1)); };
} else if (selectedIndex === selected.length - 1) { });
newSelected = newSelected.concat(selected.slice(0, -1));
} else if (selectedIndex > 0) { useEffect(() => {
newSelected = newSelected.concat( setOnRow(defaultRow);
selected.slice(0, selectedIndex), }, [defaultRow]);
selected.slice(selectedIndex + 1)
); const onRowClickDefault = (value: any) => {
} setOnRow(value);
checkboxData(newSelected) onRowClick && onRowClick(value);
setSelected(newSelected); };
};
const handleRequestSort = (event: any, property: any) => {
const handleRadioClick = (id: string) => { const isAsc = orderBy === property && order === "asc";
setSelected(id) setOrder(isAsc ? "desc" : "asc");
} setOrderBy(property);
};
const handleOnPageChange = (event: any, newPage: number) => {
changePage(newPage, Number(rowsPerPage)); const handleSelectAllClick = (event: any) => {
}; if (event.target.checked) {
const newSelecteds = rows.map((n: any) => n[param || "id"]);
const handleChangeRowsPerPage = (event: any) => { setSelected(newSelecteds);
changePage(0, parseInt(event.target.value, 10)); checkboxData(newSelecteds);
}; return;
}
const isSelected = (name: any) => selected.indexOf(name) !== -1; setSelected([]);
checkboxData([]);
// const emptyRows = rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage); };
const handleClick = (event: any, name: any) => {
const renderTableCellValue = useCallback(((item: any, row: any, index: number)=>{ const selectedIndex = selected.indexOf(name);
if( let newSelected: any[] = [];
item.render
) { if (selectedIndex === -1) {
return <>{item.render(row[item.id], row, index)}</> newSelected = newSelected.concat(selected, name);
} else if(row[item.id]) { } else if (selectedIndex === 0) {
return row[item.id] || '-' newSelected = newSelected.concat(selected.slice(1));
} else { } else if (selectedIndex === selected.length - 1) {
return '-' newSelected = newSelected.concat(selected.slice(0, -1));
} } else if (selectedIndex > 0) {
}),[]) newSelected = newSelected.concat(
selected.slice(0, selectedIndex),
return ( selected.slice(selectedIndex + 1)
<div className={classes.root}> );
<Paper sx={{ }
boxShadow: 'none' checkboxData(newSelected);
}} className={classes.paper} classes={{ elevation1: elevation1 || classes.elevation1 }} > setSelected(newSelected);
{/* <Spin spin={spin} /> */} };
{toolbar && toolbar}
<TableContainer style={{ ...tableContainerStyle }}> const handleRadioClick = (id: string) => {
<Table stickyHeader={stickyHeader || false} className={classes.table} style={{ ...tableStyle }} aria-labelledby="tableTitle" size={size || "medium"} aria-label="cloudam table header" > setSelected(id);
<EnhancedTableHeadComponent };
classes={classes()}
{...props} const handleOnPageChange = (event: any, newPage: number) => {
numSelected={selected.length} changePage(newPage, Number(rowsPerPage));
headTableCellCheckbox={headTableCellCheckbox} };
order={order}
orderBy={orderBy} const handleChangeRowsPerPage = (event: any) => {
onSelectAllClick={handleSelectAllClick} changePage(0, parseInt(event.target.value, 10));
onRequestSort={handleRequestSort} };
rowCount={rows.length}
headCells={headCells || []} const isSelected = (name: any) => selected.indexOf(name) !== -1;
/>
<TableBody sx={{ // const emptyRows = rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage);
...tableBodySx
}}> const renderTableCellValue = useCallback(
{ (item: any, row: any, index: number) => {
(rows.length === 0 && !load) && <TableRow> if (item.render) {
<TableCell return <>{item.render(row[item.id], row, index)}</>;
sx={{ } else if (row[item.id]) {
borderBottom: '1px solid #F0F2F5', return row[item.id] || "-";
textAlign: 'center' } else {
}} return "-";
colSpan={headCells?.filter((k: any) => k.id === "checkbox")?.length === 0 ? headCells?.length : headCells?.length + 1} }
className={classes.TypographyStyle} },
style={{ minHeight: minHeight, height: minHeight, borderBottom: borderBottom, padding: TableNodataPadding, lineHeight: TableNodataLineHeight }} []
> );
No Data
</TableCell> return (
</TableRow> <div className={classes.root}>
} <Paper
{stableSort(rows, getComparator(order, orderBy)).slice(page * Number(rowsPerPage), page * Number(rowsPerPage) + Number(rowsPerPage)).map((row: any, index: number) => { sx={{
const isItemSelected = isSelected(row[param || "id"]); boxShadow: "none",
const labelId = `enhanced-table-checkbox-${index}`; }}
return ( className={classes.paper}
<TableRow classes={{ elevation1: elevation1 || classes.elevation1 }}
hover={rowHover ? false : (row[disabledParam || "enabled"] ? true : false)} >
onDoubleClick={() => { {toolbar && toolbar}
onDoubleClick && onDoubleClick(row) <TableContainer style={{ ...tableContainerStyle }}>
}} <Table
style={{ stickyHeader={stickyHeader || false}
height: RowHeight, className={classes.table}
border: onRow === row[param || "id"] ? !row[disabledParam] ? "" : '1px solid #136EFA' : "", style={{ ...tableStyle }}
backgroundColor: onRow === row[param || "id"] ? !row[disabledParam] ? "rgba(255, 255, 255, 0.4)" : "rgba(19, 110, 250, 0.1)" : "", aria-labelledby="tableTitle"
cursor: props.cursor ? (row[props.cursor] ? "pointer" : "auto") : (onRowClick ? !row[disabledParam] ? "no-drop" : "pointer" : "auto"), size={size || "medium"}
}} aria-label="cloudam table header"
role="checkbox" >
aria-checked={isItemSelected} <MyCircularProgress loading={loading}>
tabIndex={-1} <EnhancedTableHeadComponent
key={row[param || "id"] || index} classes={classes()}
selected={isItemSelected} {...props}
onClick={() => { numSelected={selected.length}
radioClick && radioClick(row) headTableCellCheckbox={headTableCellCheckbox}
radioClick && handleRadioClick(row[param || "id"]) order={order}
}} orderBy={orderBy}
> onSelectAllClick={handleSelectAllClick}
{ onRequestSort={handleRequestSort}
headCells.filter((k: any) => k.id === "checkbox").length > 0 && <TableCell rowCount={rows.length}
sx={{ headCells={headCells || []}
borderBottom: '1px solid #F0F2F5' />
}} <TableBody
onClick={(event) => { sx={{
// if (!row[disabledParam]) return; ...tableBodySx,
onRowClick && onRowClickDefault(row[param || "id"]) }}
headCells.filter((k: any) => k.id === "checkbox").length > 0 && handleClick(event, row[param || "id"]) >
}} {rows.length === 0 && !loading && (
padding="checkbox"> <TableRow>
<Checkbox sx={{ color: '#D1D6DE' }} color={"primary"} checked={isItemSelected} inputProps={{ "aria-labelledby": labelId }} /> <TableCell
</TableCell> sx={{
} borderBottom: "1px solid #F0F2F5",
{ textAlign: "center",
headCells.filter((item: any) => item.id !== 'checkbox').map((item: any, k: any) => { color: "#8A9099",
return ( }}
<TableCell key={k} component="th" id={labelId + k} colSpan={
sx={{ headCells?.filter((k: any) => k.id === "checkbox")
borderBottom: '1px solid #F0F2F5' ?.length === 0
}} ? headCells?.length
// align={} : headCells?.length + 1
style={{ width: CellWidth, textAlign: item.numeric ? "right" : "left", paddingRight: item.sort && item.numeric ? "40px" : "", border: tableCellStyle }} }
scope="row" className={classes.TypographyStyle}
padding={item.disablePadding ? "none" : "normal"} style={{
classes={{ minHeight: minHeight,
body: classes.bodyTableCell height: minHeight,
}} borderBottom: borderBottom,
> { padding: TableNodataPadding,
renderTableCellValue(item, row, index) lineHeight: TableNodataLineHeight,
} }}
</TableCell> >
) {noDataText}
}) </TableCell>
} </TableRow>
</TableRow> )}
); {stableSort(rows, getComparator(order, orderBy))
})} .slice(
</TableBody> page * Number(rowsPerPage),
</Table> page * Number(rowsPerPage) + Number(rowsPerPage)
</TableContainer> )
{ .map((row: any, index: number) => {
footer ? <TablePagination const isItemSelected = isSelected(row[param || "id"]);
rowsPerPageOptions={rowsPerPageOptions} const labelId = `enhanced-table-checkbox-${index}`;
component="div" return (
count={count || rows.length} <TableRow
rowsPerPage={Number(rowsPerPage)} hover={
page={page} rowHover
ActionsComponent={ActionsComponent} ? false
onPageChange={handleOnPageChange} : row[disabledParam || "enabled"]
onRowsPerPageChange={handleChangeRowsPerPage} ? true
/> : null : false
} }
onDoubleClick={() => {
</Paper> onDoubleClick && onDoubleClick(row);
</div> }}
); style={{
height: RowHeight,
border:
onRow === row[param || "id"]
? !row[disabledParam]
? ""
: "1px solid #136EFA"
: "",
backgroundColor:
onRow === row[param || "id"]
? !row[disabledParam]
? "rgba(255, 255, 255, 0.4)"
: "rgba(19, 110, 250, 0.1)"
: "",
cursor: props.cursor
? row[props.cursor]
? "pointer"
: "auto"
: onRowClick
? !row[disabledParam]
? "no-drop"
: "pointer"
: "auto",
}}
role="checkbox"
aria-checked={isItemSelected}
tabIndex={-1}
key={row[param || "id"] || index}
selected={isItemSelected}
onClick={() => {
radioClick && radioClick(row);
radioClick && handleRadioClick(row[param || "id"]);
}}
>
{headCells.filter((k: any) => k.id === "checkbox")
.length > 0 && (
<TableCell
sx={{
borderBottom: "1px solid #F0F2F5",
}}
onClick={(event) => {
// if (!row[disabledParam]) return;
onRowClick &&
onRowClickDefault(row[param || "id"]);
headCells.filter((k: any) => k.id === "checkbox")
.length > 0 &&
handleClick(event, row[param || "id"]);
}}
padding="checkbox"
>
<Checkbox
sx={{ color: "#D1D6DE" }}
color={"primary"}
checked={isItemSelected}
inputProps={{ "aria-labelledby": labelId }}
/>
</TableCell>
)}
{headCells
.filter((item: any) => item.id !== "checkbox")
.map((item: any, k: any) => {
return (
<TableCell
key={k}
component="th"
id={labelId + k}
sx={{
borderBottom: "1px solid #F0F2F5",
}}
// align={}
style={{
width: CellWidth,
textAlign: item.numeric ? "right" : "left",
paddingRight:
item.sort && item.numeric ? "40px" : "",
border: tableCellStyle,
}}
scope="row"
padding={
item.disablePadding ? "none" : "normal"
}
classes={{
body: classes.bodyTableCell,
}}
>
{" "}
{renderTableCellValue(item, row, index)}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</MyCircularProgress>
</Table>
</TableContainer>
{footer ? (
<TablePagination
rowsPerPageOptions={rowsPerPageOptions}
component="div"
count={count || rows.length}
rowsPerPage={Number(rowsPerPage)}
page={page}
ActionsComponent={ActionsComponent}
onPageChange={handleOnPageChange}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
) : null}
</Paper>
</div>
);
} }
...@@ -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