mirror of
https://github.com/cloudreve/frontend.git
synced 2025-12-26 04:02:47 +00:00
Feat: list nodes
This commit is contained in:
parent
0ce8d9250e
commit
8fff5d2d26
|
|
@ -32,6 +32,7 @@ import Download from "./component/Admin/Task/Download";
|
|||
import Task from "./component/Admin/Task/Task";
|
||||
import Import from "./component/Admin/File/Import";
|
||||
import Captcha from "./component/Admin/Setting/Captcha";
|
||||
import Node from "./component/Admin/Node/Node";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
|
|
@ -183,6 +184,10 @@ export default function Admin() {
|
|||
<Route path={`${path}/task`} exact>
|
||||
<Task />
|
||||
</Route>
|
||||
|
||||
<Route path={`${path}/node`} exact>
|
||||
<Node />
|
||||
</Route>
|
||||
</Switch>
|
||||
)}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import {
|
|||
SettingsEthernet,
|
||||
Share,
|
||||
Storage,
|
||||
Contactless,
|
||||
} from "@material-ui/icons";
|
||||
import ChevronLeftIcon from "@material-ui/icons/ChevronLeft";
|
||||
import ChevronRightIcon from "@material-ui/icons/ChevronRight";
|
||||
|
|
@ -232,6 +233,11 @@ const items = [
|
|||
icon: <Storage />,
|
||||
path: "policy",
|
||||
},
|
||||
{
|
||||
title: "从机节点",
|
||||
icon: <Contactless />,
|
||||
path: "node",
|
||||
},
|
||||
{
|
||||
title: "用户组",
|
||||
icon: <Group />,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,237 @@
|
|||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import API from "../../../middleware/Api";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { toggleSnackbar } from "../../../actions";
|
||||
import Paper from "@material-ui/core/Paper";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import TableContainer from "@material-ui/core/TableContainer";
|
||||
import Table from "@material-ui/core/Table";
|
||||
import TableHead from "@material-ui/core/TableHead";
|
||||
import TableRow from "@material-ui/core/TableRow";
|
||||
import TableCell from "@material-ui/core/TableCell";
|
||||
import TableBody from "@material-ui/core/TableBody";
|
||||
import TablePagination from "@material-ui/core/TablePagination";
|
||||
import { useHistory } from "react-router";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import { Delete, Edit } from "@material-ui/icons";
|
||||
import Tooltip from "@material-ui/core/Tooltip";
|
||||
import Chip from "@material-ui/core/Chip";
|
||||
import classNames from "classnames";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
[theme.breakpoints.up("md")]: {
|
||||
marginLeft: 100,
|
||||
},
|
||||
marginBottom: 40,
|
||||
},
|
||||
content: {
|
||||
padding: theme.spacing(2),
|
||||
},
|
||||
container: {
|
||||
overflowX: "auto",
|
||||
},
|
||||
tableContainer: {
|
||||
marginTop: 16,
|
||||
},
|
||||
header: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
},
|
||||
disabledBadge: {
|
||||
marginLeft: theme.spacing(1),
|
||||
height: 18,
|
||||
},
|
||||
disabledCell: {
|
||||
color: theme.palette.text.disabled,
|
||||
},
|
||||
}));
|
||||
|
||||
const columns = [
|
||||
{ id: "#", label: "#", minWidth: 50 },
|
||||
{ id: "name", label: "名称", minWidth: 170 },
|
||||
{
|
||||
id: "status",
|
||||
label: "当前状态",
|
||||
minWidth: 50,
|
||||
},
|
||||
{
|
||||
id: "features",
|
||||
label: "已启用功能",
|
||||
minWidth: 170,
|
||||
},
|
||||
{
|
||||
id: "action",
|
||||
label: "操作",
|
||||
minWidth: 170,
|
||||
},
|
||||
];
|
||||
|
||||
export default function Node() {
|
||||
const classes = useStyles();
|
||||
const [nodes, setNodes] = useState([]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [pageSize, setPageSize] = useState(10);
|
||||
const [total, setTotal] = useState(0);
|
||||
|
||||
const history = useHistory();
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const ToggleSnackbar = useCallback(
|
||||
(vertical, horizontal, msg, color) =>
|
||||
dispatch(toggleSnackbar(vertical, horizontal, msg, color)),
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const loadList = () => {
|
||||
API.post("/admin/node/list", {
|
||||
page: page,
|
||||
page_size: pageSize,
|
||||
order_by: "id desc",
|
||||
})
|
||||
.then((response) => {
|
||||
setNodes(response.data.items);
|
||||
setTotal(response.data.total);
|
||||
})
|
||||
.catch((error) => {
|
||||
ToggleSnackbar("top", "right", error.message, "error");
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
loadList();
|
||||
}, [page, pageSize]);
|
||||
|
||||
const deletePolicy = (id) => {
|
||||
API.delete("/admin/group/" + id)
|
||||
.then(() => {
|
||||
loadList();
|
||||
ToggleSnackbar("top", "right", "用户组已删除", "success");
|
||||
})
|
||||
.catch((error) => {
|
||||
ToggleSnackbar("top", "right", error.message, "error");
|
||||
});
|
||||
};
|
||||
|
||||
const getStatusBadge = (status) => {
|
||||
if (status === 1) {
|
||||
return (
|
||||
<Chip
|
||||
className={classes.disabledBadge}
|
||||
size="small"
|
||||
label="未启用"
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const getFeatureBadge = (node) => {
|
||||
if (node.Aria2Enabled) {
|
||||
return "0";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={classes.header}>
|
||||
<Button
|
||||
color={"primary"}
|
||||
onClick={() => history.push("/admin/node/add")}
|
||||
variant={"contained"}
|
||||
>
|
||||
接入新节点
|
||||
</Button>
|
||||
<div className={classes.headerRight}>
|
||||
<Button
|
||||
color={"primary"}
|
||||
onClick={() => loadList()}
|
||||
variant={"outlined"}
|
||||
>
|
||||
刷新
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Paper square className={classes.tableContainer}>
|
||||
<TableContainer className={classes.container}>
|
||||
<Table aria-label="sticky table" size={"small"}>
|
||||
<TableHead>
|
||||
<TableRow style={{ height: 52 }}>
|
||||
{columns.map((column) => (
|
||||
<TableCell
|
||||
key={column.id}
|
||||
align={column.align}
|
||||
style={{
|
||||
minWidth: column.minWidthclassNames,
|
||||
}}
|
||||
>
|
||||
{column.label}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{nodes.map((row) => (
|
||||
<TableRow hover key={row.ID}>
|
||||
<TableCell>{row.ID}</TableCell>
|
||||
<TableCell
|
||||
className={classNames({
|
||||
[classes.disabledCell]:
|
||||
row.Status === 1,
|
||||
})}
|
||||
>
|
||||
{row.Name}
|
||||
{getStatusBadge(row.Status)}
|
||||
</TableCell>
|
||||
<TableCell>...</TableCell>
|
||||
<TableCell>
|
||||
{getFeatureBadge(row)}
|
||||
</TableCell>
|
||||
|
||||
<TableCell align={"right"}>
|
||||
<Tooltip title={"编辑"}>
|
||||
<IconButton
|
||||
onClick={() =>
|
||||
history.push(
|
||||
"/admin/node/edit/" +
|
||||
row.ID
|
||||
)
|
||||
}
|
||||
size={"small"}
|
||||
>
|
||||
<Edit />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title={"删除"}>
|
||||
<IconButton
|
||||
onClick={() =>
|
||||
deletePolicy(row.ID)
|
||||
}
|
||||
size={"small"}
|
||||
>
|
||||
<Delete />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<TablePagination
|
||||
rowsPerPageOptions={[10, 25, 100]}
|
||||
component="div"
|
||||
count={total}
|
||||
rowsPerPage={pageSize}
|
||||
page={page - 1}
|
||||
onChangePage={(e, p) => setPage(p + 1)}
|
||||
onChangeRowsPerPage={(e) => {
|
||||
setPageSize(e.target.value);
|
||||
setPage(1);
|
||||
}}
|
||||
/>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue