mirror of
https://github.com/cloudreve/frontend.git
synced 2025-12-25 19:52:48 +00:00
i18n: node settings
This commit is contained in:
parent
a8fd669d84
commit
01be7286d7
|
|
@ -537,5 +537,77 @@
|
|||
"placeHolderWithSize": "Use placeholder before uploading",
|
||||
"placeHolderWithSizeDes": "Whether to create a placeholder file before uploading .Only supported in partial storage policy.",
|
||||
"saveChanges": "Save changes"
|
||||
},
|
||||
"node": {
|
||||
"#": "#",
|
||||
"name": "Name",
|
||||
"status": "Status",
|
||||
"features": "Enabled features",
|
||||
"action": "Actions",
|
||||
"remoteDownload": "Remote download",
|
||||
"nodeDisabled": "Node is disabled.",
|
||||
"nodeEnabled": "Node is enabled.",
|
||||
"nodeDeleted": "Node is deleted.",
|
||||
"disabled": "Disabled",
|
||||
"online": "Online",
|
||||
"offline": "Offline",
|
||||
"addNewNode": "Add new node",
|
||||
"refresh": "Refresh",
|
||||
"enableNode": "Enable node",
|
||||
"disableNode": "Disable node",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"slaveNodeDes": "You can add a server that is also running Cloudreve as a slave node. A slave node can share the load of certain asynchronous tasks (such as remote downloads) for the master. Please refer to the following wizard to deploy and configure a slave node. <0> If you have already deployed a remote node storage policy on the target server, you can skip some steps on this page and just fill in the slave secret and server address here, keep them as the same in the remote storage policy. </0> In subsequent releases, the configuration related to the remote storage policy will be merged into here.",
|
||||
"overwriteDes": "; The following settings are optional and correspond to the relevant parameters of the master node, <0></0>; which can be applied to the slave node via the configuration file, please adjust them according to <0></0>; the actual situation. Changing the following settings requires a restart of the slave node to take effect.",
|
||||
"workerNumDes": "Maximum number of tasks to be executed in parallel in the task queue.",
|
||||
"parallelTransferDes": "Maximum number of parallel goroutine when transferring files in the task queue",
|
||||
"chunkRetriesDes": "Maximum number of retries after a failed upload of a chunk.",
|
||||
"multipleMasterDes": "A slave Cloudreve instance can interface to multiple Cloudreve master nodes; simply add this slave node to all master nodes and keep the secret consistent.",
|
||||
"ariaSuccess": "Successfully connected, Aria2 version: {{version}}",
|
||||
"slave": "slave",
|
||||
"master": "master",
|
||||
"aria2Des": "Cloudreve's remote download functionality is powered by <0>Aria2</0>. To use it, start Aria2 as the same user running Cloudreve on the target node server, and enable the RPC service in the Aria2 config file, <1>Aria2 needs to share the same file system as the {{mode}} Cloudreve process. </1> For more information and guidelines, refer the <2>Offline Downloads</2> section of the documentation.",
|
||||
"slaveTakeOverRemoteDownload": "Do you need this node to take over remote download tasks?",
|
||||
"masterTakeOverRemoteDownload": "Do you need the master to take over the remote download task?",
|
||||
"routeTaskSlave": "After enabled, users' remote download requests can be scheduled to this node for processing.",
|
||||
"routeTaskMaster": "After enabled, users' remote download requests can be scheduled to master node for processing.",
|
||||
"enable": "Enable",
|
||||
"disable": "Disable",
|
||||
"slaveNodeTarget": "on slave node which shares the same file system with slave Cloudreve",
|
||||
"masterNodeTarget": "which shares the same file system with Cloudreve",
|
||||
"aria2ConfigDes": "Boot Aria2 {{target}} which shares the same file system with Cloudreve. When you start Aria2, you need to enable the RPC service in its config file and set the RPC Secret for future use. The following is a config example for reference.",
|
||||
"enableRPCComment": "Enable RPC service",
|
||||
"rpcPortComment": "RPC port to listen on",
|
||||
"rpcSecretComment": "RPC secret, you can change it on your own.",
|
||||
"rpcConfigDes": "It is recommended to start Aria2 before the node Cloudreve in the routine startup process, so that node Cloudreve can subscribe to event notifications to Aria2 and download status changes are handled in a more timely manner. Of course, if this process is not available, node Cloudreve will also track the task status via polling.",
|
||||
"rpcServerDes": "Fill in the address of the RPC service that {{mode}} Cloudreve uses to communicate with Aria2. This can be filled in as <0>http://127.0.0.1:6800/</0>, where the port number <1>6800</1> is consistent with <2>rpc-listen-port</2> in the config file above.",
|
||||
"rpcServer": "RPC Server",
|
||||
"rpcServerHelpDes": "RPC server address contain full port number, e.g. http://127.0.0.1:6800/, Leave blank to indicate that the Aria2 service is not enabled.",
|
||||
"rpcTokenDes": "RPC secret, consistent with <0>rpc-secret</0> in the Aria2 configuration file; leave blank if not set.",
|
||||
"aria2PathDes": "Fill in the <0>absolute path</0> on the node that Aria2 uses as a temporary download directory. The Cloudreve process on the node needs read, write, and execute permissions on this directory.",
|
||||
"aria2SettingDes": "Fill in some additional Aria2 parameter information below, as your need.",
|
||||
"refreshInterval": "Status refresh interval (seconds)",
|
||||
"refreshIntervalDes": "The interval at which Cloudreve requests a refresh of the task state from Aria2.",
|
||||
"rpcTimeout": "RPC timeouts (seconds)",
|
||||
"rpcTimeoutDes": "Maximum wait time when calling RPC services.",
|
||||
"globalOptions": "Global job options",
|
||||
"globalOptionsDes": "Additional settings carried when creating a download job, written in JSON encoded format, you can also write these settings in the Aria2 config file, see the Aria2 official documentation for available settings.",
|
||||
"testAria2Des": "Once you have completed these steps, you can click the Test button below to test that if {{mode}} Cloudreve is communicating properly to Aria2.",
|
||||
"testAria2DesSlaveAddition": "Please make sure you have performed and passed the \"Slave Communication Test\" on the previous page before performing the test.",
|
||||
"testAria2": "Testing Aria2 Communication",
|
||||
"aria2DocURL": "https://docs.cloudreve.org/v/en/use/aria2",
|
||||
"nameNode": "Enter the name of this node:",
|
||||
"loadBalancerRankDes": "Specify a load balancing weight for this node, the value is an integer. Some load balancing policies will weight the nodes based on this value.",
|
||||
"loadBalancerRank": "Load balancing weight",
|
||||
"nodeSaved": "Node saved successfully.",
|
||||
"nodeSavedFutureAction": "If you add a new node, you will also need to manually enable the node in the node list for it to work properly.",
|
||||
"backToNodeList": "Back to node list",
|
||||
"communication": "Communication",
|
||||
"otherSettings": "Other settings",
|
||||
"finish": "Finish",
|
||||
"nodeAdded": "Node added successfully.",
|
||||
"nodeSavedNow": "Node saved successfully.",
|
||||
"editNode": "Edit node",
|
||||
"addNode": "Add node"
|
||||
}
|
||||
}
|
||||
|
|
@ -536,5 +536,77 @@
|
|||
"placeHolderWithSize": "上传前预支用户存储",
|
||||
"placeHolderWithSizeDes": "是否在上传会话创建时就对用户存储进行预支,仅部分存储策略支持",
|
||||
"saveChanges": "保存更改"
|
||||
},
|
||||
"node": {
|
||||
"#": "#",
|
||||
"name": "名称",
|
||||
"status": "当前状态",
|
||||
"features": "已启用功能",
|
||||
"action": "操作",
|
||||
"remoteDownload": "离线下载",
|
||||
"nodeDisabled": "节点已暂停使用",
|
||||
"nodeEnabled": "节点已启用",
|
||||
"nodeDeleted": "节点已删除",
|
||||
"disabled": "未启用",
|
||||
"online": "在线",
|
||||
"offline": "离线",
|
||||
"addNewNode": "接入新节点",
|
||||
"refresh": "刷新",
|
||||
"enableNode": "启用节点",
|
||||
"disableNode": "暂停使用节点",
|
||||
"edit": "编辑",
|
||||
"delete": "删除",
|
||||
"slaveNodeDes": "您可以添加同样运行了 Cloudreve 的服务器作为从机端,正常运行工作的从机端可以为主机分担某些异步任务(如离线下载)。请参考下面向导部署并配置连接 Cloudreve 从机节点。<0>如果你已经在目标服务器上部署了从机存储策略,您可以跳过本页面的某些步骤,只将从机密钥、服务器地址在这里填写并保持与从机存储策略中一致即可。</0> 在后续版本中,从机存储策略的相关配置会合并到这里。",
|
||||
"overwriteDes": "; 以下为可选的设置,对应主机节点的相关参数,可以通过配置文件应用到从机节点,请根据<0></0>; 实际情况调整。更改下面设置需要重启从机节点后生效。",
|
||||
"workerNumDes": "任务队列最多并行执行的任务数",
|
||||
"parallelTransferDes": "任务队列中转任务传输时,最大并行协程数",
|
||||
"chunkRetriesDes": "中转分片上传失败后重试的最大次数",
|
||||
"multipleMasterDes": "一个从机 Cloudreve 实例可以对接多个 Cloudreve 主节点,只需在所有主节点中添加此从机节点并保持密钥一致即可。",
|
||||
"ariaSuccess": "连接成功,Aria2 版本为:{{version}}",
|
||||
"slave": "从机",
|
||||
"master": "主机",
|
||||
"aria2Des": "Cloudreve 的离线下载功能由 <0>Aria2</0> 驱动。如需使用,请在目标节点服务器上以和运行 Cloudreve 相同的用户身份启动 Aria2, 并在 Aria2 的配置文件中开启 RPC 服务,<1>Aria2 需要和{{mode}} Cloudreve 进程共用相同的文件系统。</1> 更多信息及指引请参考文档的 <2>离线下载</2> 章节。",
|
||||
"slaveTakeOverRemoteDownload": "是否需要此节点接管离线下载任务?",
|
||||
"masterTakeOverRemoteDownload": "是否需要主机接管离线下载任务?",
|
||||
"routeTaskSlave": "开启后,用户的离线下载请求可以被分流到此节点处理。",
|
||||
"routeTaskMaster": "开启后,用户的离线下载请求可以被分流到主机处理。",
|
||||
"enable": "启用",
|
||||
"disable": "关闭",
|
||||
"slaveNodeTarget": "在目标节点服务器上与节点",
|
||||
"masterNodeTarget": "在与",
|
||||
"aria2ConfigDes": "{{target}} Cloudreve 进程相同的文件系统环境下启动 Aria2 进程。在启动 Aria2 时,需要在其配置文件中启用 RPC 服务,并设定 RPC Secret,以便后续使用。以下为一个供参考的配置:",
|
||||
"enableRPCComment": "启用 RPC 服务",
|
||||
"rpcPortComment": "RPC 监听端口",
|
||||
"rpcSecretComment": "RPC 授权令牌,可自行设定",
|
||||
"rpcConfigDes": "推荐在日常启动流程中,先启动 Aria2,再启动节点 Cloudreve,这样节点 Cloudreve 可以向 Aria2 订阅事件通知,下载状态变更处理更及时。当然,如果没有这一流程,节点 Cloudreve 也会通过轮询追踪任务状态。",
|
||||
"rpcServerDes": "在下方填写{{mode}} Cloudreve 与 Aria2 通信的 RPC 服务地址。一般可填写为 <0>http://127.0.0.1:6800/</0>,其中端口号 <1>6800</1> 与上文配置文件中 <2>rpc-listen-port</2>保持一致。",
|
||||
"rpcServer": "RPC 服务器地址",
|
||||
"rpcServerHelpDes": "包含端口的完整 RPC 服务器地址,例如:http://127.0.0.1:6800/,留空表示不启用 Aria2 服务",
|
||||
"rpcTokenDes": "RPC 授权令牌,与 Aria2 配置文件中 <0>rpc-secret</0> 保持一致,未设置请留空。",
|
||||
"aria2PathDes": "在下方填写 Aria2 用作临时下载目录的 节点上的 <0>绝对路径</0>,节点上的 Cloudreve 进程需要此目录的读、写、执行权限。",
|
||||
"aria2SettingDes": "在下方按需要填写一些 Aria2 额外参数信息。",
|
||||
"refreshInterval": "状态刷新间隔 (秒)",
|
||||
"refreshIntervalDes": "Cloudreve 向 Aria2 请求刷新任务状态的间隔。",
|
||||
"rpcTimeout": "RPC 调用超时 (秒)",
|
||||
"rpcTimeoutDes": "调用 RPC 服务时最长等待时间",
|
||||
"globalOptions": "全局任务参数",
|
||||
"globalOptionsDes": "创建下载任务时携带的额外设置参数,以 JSON 编码后的格式书写,您可也可以将这些设置写在 Aria2 配置文件里,可用参数请查阅官方文档",
|
||||
"testAria2Des": "完成以上步骤后,你可以点击下方的测试按钮测试{{mode}} Cloudreve 向 Aria2 通信是否正常。",
|
||||
"testAria2DesSlaveAddition": "在进行测试前请先确保您已进行并通过上一页面中的“从机通信测试”。",
|
||||
"testAria2": "测试 Aria2 通信",
|
||||
"aria2DocURL": "https://docs.cloudreve.org/use/aria2",
|
||||
"nameNode": "为此节点命名:",
|
||||
"loadBalancerRankDes": "为此节点指定负载均衡权重,数值为整数。某些负载均衡策略会根据此数值加权选择节点",
|
||||
"loadBalancerRank": "负载均衡权重",
|
||||
"nodeSaved": "节点已保存!",
|
||||
"nodeSavedFutureAction": "如果您添加了新节点,还需要在节点列表手动启动节点才能正常使用。"
|
||||
"backToNodeList": "返回节点列表",
|
||||
"communication": "通信配置",
|
||||
"otherSettings": "杂项信息",
|
||||
"finish": "完成",
|
||||
"nodeAdded": "节点已添加",
|
||||
"nodeSavedNow": "节点已保存",
|
||||
"editNode": "编辑节点",
|
||||
"addNode": "添加节点"
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ import Box from "@material-ui/core/Box";
|
|||
import FormHelperText from "@material-ui/core/FormHelperText";
|
||||
import API from "../../../../middleware/Api";
|
||||
import { toggleSnackbar } from "../../../../redux/explorer";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
stepContent: {
|
||||
|
|
@ -85,6 +86,8 @@ const useStyles = makeStyles((theme) => ({
|
|||
}));
|
||||
|
||||
export default function Aria2RPC(props) {
|
||||
const { t } = useTranslation("dashboard", { keyPrefix: "node" });
|
||||
const { t: tDashboard } = useTranslation("dashboard");
|
||||
const classes = useStyles();
|
||||
const dispatch = useDispatch();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
|
@ -107,7 +110,7 @@ export default function Aria2RPC(props) {
|
|||
ToggleSnackbar(
|
||||
"top",
|
||||
"right",
|
||||
"连接成功,Aria2 版本为:" + response.data,
|
||||
t("ariaSuccess", { version: response.data }),
|
||||
"success"
|
||||
);
|
||||
})
|
||||
|
|
@ -119,7 +122,7 @@ export default function Aria2RPC(props) {
|
|||
});
|
||||
};
|
||||
|
||||
const mode = props.node.Type === 0 ? "从机" : "主机";
|
||||
const mode = props.node.Type === 0 ? t("slave") : t("master");
|
||||
|
||||
return (
|
||||
<form
|
||||
|
|
@ -131,24 +134,30 @@ export default function Aria2RPC(props) {
|
|||
>
|
||||
<Alert severity="info" style={{ marginBottom: 10 }}>
|
||||
<Typography variant="body2">
|
||||
Cloudreve 的离线下载功能由{" "}
|
||||
<Link href={"https://aria2.github.io/"} target={"_blank"}>
|
||||
Aria2
|
||||
</Link>{" "}
|
||||
驱动。如需使用,请在目标节点服务器上以和运行 Cloudreve
|
||||
相同的用户身份启动 Aria2, 并在 Aria2 的配置文件中开启 RPC
|
||||
服务,
|
||||
<Box component="span" fontWeight="fontWeightBold">
|
||||
Aria2 需要和{mode} Cloudreve 进程共用相同的文件系统。
|
||||
</Box>{" "}
|
||||
更多信息及指引请参考文档的{" "}
|
||||
<Link
|
||||
href={"https://docs.cloudreve.org/use/aria2"}
|
||||
target={"_blank"}
|
||||
>
|
||||
离线下载
|
||||
</Link>{" "}
|
||||
章节。
|
||||
<Trans
|
||||
ns={"dashboard"}
|
||||
i18nKey={"node.aria2Des"}
|
||||
values={{
|
||||
mode: mode,
|
||||
}}
|
||||
components={[
|
||||
<Link
|
||||
href={"https://aria2.github.io/"}
|
||||
target={"_blank"}
|
||||
key={0}
|
||||
/>,
|
||||
<Box
|
||||
component="span"
|
||||
fontWeight="fontWeightBold"
|
||||
key={1}
|
||||
/>,
|
||||
<Link
|
||||
href={t("aria2DocURL")}
|
||||
target={"_blank"}
|
||||
key={2}
|
||||
/>,
|
||||
]}
|
||||
/>
|
||||
</Typography>
|
||||
</Alert>
|
||||
|
||||
|
|
@ -159,12 +168,12 @@ export default function Aria2RPC(props) {
|
|||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
{props.node.Type === 0
|
||||
? "是否需要此节点接管离线下载任务?"
|
||||
: "是否需要主机接管离线下载任务?"}
|
||||
? t("slaveTakeOverRemoteDownload")
|
||||
: t("masterTakeOverRemoteDownload")}
|
||||
<br />
|
||||
{props.node.Type === 0
|
||||
? "开启后,用户的离线下载请求可以被分流到此节点处理。"
|
||||
: "开启后,用户的离线下载请求可以被分流到主机处理。"}
|
||||
? t("routeTaskSlave")
|
||||
: t("routeTaskMaster")}
|
||||
</Typography>
|
||||
|
||||
<div className={classes.form}>
|
||||
|
|
@ -180,12 +189,12 @@ export default function Aria2RPC(props) {
|
|||
<FormControlLabel
|
||||
value={"true"}
|
||||
control={<Radio color={"primary"} />}
|
||||
label="启用"
|
||||
label={t("enable")}
|
||||
/>
|
||||
<FormControlLabel
|
||||
value={"false"}
|
||||
control={<Radio color={"primary"} />}
|
||||
label="关闭"
|
||||
label={t("disable")}
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
|
|
@ -200,24 +209,21 @@ export default function Aria2RPC(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
{props.node.Type === 0
|
||||
? " 在目标节点服务器上与节点 "
|
||||
: "在与 "}
|
||||
Cloudreve 进程相同的文件系统环境下启动 Aria2
|
||||
进程。在启动 Aria2 时,需要在其配置文件中启用 RPC
|
||||
服务,并设定 RPC
|
||||
Secret,以便后续使用。以下为一个供参考的配置:
|
||||
{t("aria2ConfigDes", {
|
||||
target:
|
||||
props.node.Type === 0
|
||||
? t("slaveNodeTarget")
|
||||
: t("masterNodeTarget"),
|
||||
})}
|
||||
</Typography>
|
||||
<pre>
|
||||
# 启用 RPC 服务
|
||||
# {t("enableRPCComment")}
|
||||
<br />
|
||||
enable-rpc=true
|
||||
<br />
|
||||
# RPC 监听端口
|
||||
<br /># {t("rpcPortComment")}
|
||||
<br />
|
||||
rpc-listen-port=6800
|
||||
<br />
|
||||
# RPC 授权令牌,可自行设定
|
||||
<br /># {t("rpcSecretComment")}
|
||||
<br />
|
||||
rpc-secret=
|
||||
{props.node.Aria2OptionsSerialized.token}
|
||||
|
|
@ -225,10 +231,7 @@ export default function Aria2RPC(props) {
|
|||
</pre>
|
||||
<Alert severity="info" style={{ marginBottom: 10 }}>
|
||||
<Typography variant="body2">
|
||||
推荐在日常启动流程中,先启动 Aria2,再启动节点
|
||||
Cloudreve,这样节点 Cloudreve 可以向 Aria2
|
||||
订阅事件通知,下载状态变更处理更及时。当然,如果没有这一流程,节点
|
||||
Cloudreve 也会通过轮询追踪任务状态。
|
||||
{t("rpcConfigDes")}
|
||||
</Typography>
|
||||
</Alert>
|
||||
</div>
|
||||
|
|
@ -240,16 +243,23 @@ export default function Aria2RPC(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
在下方填写{mode} Cloudreve 与 Aria2 通信的 RPC
|
||||
服务地址。一般可填写为
|
||||
<code>http://127.0.0.1:6800/</code>,其中端口号
|
||||
<code>6800</code>与上文配置文件中
|
||||
<code>rpc-listen-port</code>保持一致。
|
||||
<Trans
|
||||
ns={"dashboard"}
|
||||
i18nKey={"node.rpcServerDes"}
|
||||
values={{
|
||||
mode: mode,
|
||||
}}
|
||||
components={[
|
||||
<code key={0} />,
|
||||
<code key={1} />,
|
||||
<code key={2} />,
|
||||
]}
|
||||
/>
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel htmlFor="component-helper">
|
||||
RPC 服务器地址
|
||||
{t("rpcServer")}
|
||||
</InputLabel>
|
||||
<Input
|
||||
required
|
||||
|
|
@ -262,9 +272,7 @@ export default function Aria2RPC(props) {
|
|||
)}
|
||||
/>
|
||||
<FormHelperText id="component-helper-text">
|
||||
包含端口的完整 RPC
|
||||
服务器地址,例如:http://127.0.0.1:6800/,留空表示不启用
|
||||
Aria2 服务
|
||||
{t("rpcServerHelpDes")}
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
</div>
|
||||
|
|
@ -277,8 +285,11 @@ export default function Aria2RPC(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
RPC 授权令牌,与 Aria2 配置文件中
|
||||
<code>rpc-secret</code>保持一致,未设置请留空。
|
||||
<Trans
|
||||
ns={"dashboard"}
|
||||
i18nKey={"node.rpcTokenDes"}
|
||||
components={[<code key={0} />]}
|
||||
/>
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<Input
|
||||
|
|
@ -295,9 +306,11 @@ export default function Aria2RPC(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
在下方填写 Aria2 用作临时下载目录的 节点上的
|
||||
<strong>绝对路径</strong>,节点上的 Cloudreve
|
||||
进程需要此目录的读、写、执行权限。
|
||||
<Trans
|
||||
ns={"dashboard"}
|
||||
i18nKey={"node.aria2PathDes"}
|
||||
components={[<strong key={0} />]}
|
||||
/>
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<Input
|
||||
|
|
@ -316,12 +329,12 @@ export default function Aria2RPC(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
在下方按需要填写一些 Aria2 额外参数信息。
|
||||
{t("aria2SettingDes")}
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel htmlFor="component-helper">
|
||||
状态刷新间隔 (秒)
|
||||
{t("refreshInterval")}
|
||||
</InputLabel>
|
||||
<Input
|
||||
type={"number"}
|
||||
|
|
@ -339,14 +352,14 @@ export default function Aria2RPC(props) {
|
|||
)}
|
||||
/>
|
||||
<FormHelperText id="component-helper-text">
|
||||
Cloudreve 向 Aria2 请求刷新任务状态的间隔。
|
||||
{t("refreshIntervalDes")}
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
</div>
|
||||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel htmlFor="component-helper">
|
||||
RPC 调用超时 (秒)
|
||||
{t("rpcTimeout")}
|
||||
</InputLabel>
|
||||
<Input
|
||||
type={"number"}
|
||||
|
|
@ -364,14 +377,14 @@ export default function Aria2RPC(props) {
|
|||
)}
|
||||
/>
|
||||
<FormHelperText id="component-helper-text">
|
||||
调用 RPC 服务时最长等待时间
|
||||
{t("rpcTimeoutDes")}
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
</div>
|
||||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel htmlFor="component-helper">
|
||||
全局任务参数
|
||||
{t("globalOptions")}
|
||||
</InputLabel>
|
||||
<Input
|
||||
multiline
|
||||
|
|
@ -385,9 +398,7 @@ export default function Aria2RPC(props) {
|
|||
)}
|
||||
/>
|
||||
<FormHelperText id="component-helper-text">
|
||||
创建下载任务时携带的额外设置参数,以 JSON
|
||||
编码后的格式书写,您可也可以将这些设置写在
|
||||
Aria2 配置文件里,可用参数请查阅官方文档
|
||||
{t("globalOptionsDes")}
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
</div>
|
||||
|
|
@ -400,11 +411,9 @@ export default function Aria2RPC(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
完成以上步骤后,你可以点击下方的测试按钮测试
|
||||
{mode}
|
||||
Cloudreve 向 Aria2 通信是否正常。
|
||||
{t("testAria2Des", { mode })}
|
||||
{props.node.Type === 0 &&
|
||||
"在进行测试前请先确保您已进行并通过上一页面中的“从机通信测试”。"}
|
||||
t("testAria2DesSlaveAddition")}
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<Button
|
||||
|
|
@ -413,7 +422,7 @@ export default function Aria2RPC(props) {
|
|||
onClick={() => testAria2()}
|
||||
color={"primary"}
|
||||
>
|
||||
测试 Aria2 通信
|
||||
{t("testAria2")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -427,7 +436,7 @@ export default function Aria2RPC(props) {
|
|||
className={classes.button}
|
||||
onClick={props.onBack}
|
||||
>
|
||||
上一步
|
||||
{tDashboard("policy.back")}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
|
|
@ -437,7 +446,7 @@ export default function Aria2RPC(props) {
|
|||
color={"primary"}
|
||||
onClick={props.onSubmit}
|
||||
>
|
||||
下一步
|
||||
{tDashboard("policy.next")}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import API from "../../../../middleware/Api";
|
|||
import Alert from "@material-ui/lab/Alert";
|
||||
import Box from "@material-ui/core/Box";
|
||||
import { toggleSnackbar } from "../../../../redux/explorer";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
stepContent: {
|
||||
|
|
@ -79,6 +80,8 @@ const useStyles = makeStyles((theme) => ({
|
|||
}));
|
||||
|
||||
export default function Communication(props) {
|
||||
const { t } = useTranslation("dashboard", { keyPrefix: "node" });
|
||||
const { t: tDashboard } = useTranslation("dashboard");
|
||||
const classes = useStyles();
|
||||
const dispatch = useDispatch();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
|
@ -97,7 +100,12 @@ export default function Communication(props) {
|
|||
secret: props.node.SlaveKey,
|
||||
})
|
||||
.then(() => {
|
||||
ToggleSnackbar("top", "right", "通信正常", "success");
|
||||
ToggleSnackbar(
|
||||
"top",
|
||||
"right",
|
||||
tDashboard("policy.communicationOK"),
|
||||
"success"
|
||||
);
|
||||
})
|
||||
.catch((error) => {
|
||||
ToggleSnackbar("top", "right", error.message, "error");
|
||||
|
|
@ -116,14 +124,11 @@ export default function Communication(props) {
|
|||
}}
|
||||
>
|
||||
<Alert severity="info" style={{ marginBottom: 10 }}>
|
||||
您可以添加同样运行了 Cloudreve 的服务器作为从机端,
|
||||
正常运行工作的从机端可以为主机分担某些异步任务(如离线下载)。
|
||||
请参考下面向导部署并配置连接 Cloudreve 从机节点。
|
||||
<Box fontWeight="fontWeightBold">
|
||||
如果你已经在目标服务器上部署了从机存储策略,您可以跳过本页面的某些步骤,
|
||||
只将从机密钥、服务器地址在这里填写并保持与从机存储策略中一致即可。
|
||||
</Box>
|
||||
在后续版本中,从机存储策略的相关配置会合并到这里。
|
||||
<Trans
|
||||
ns={"dashboard"}
|
||||
i18nKey={"node.slaveNodeDes"}
|
||||
components={[<Box key={0} fontWeight="fontWeightBold" />]}
|
||||
/>
|
||||
</Alert>
|
||||
|
||||
<div className={classes.subStepContainer}>
|
||||
|
|
@ -132,8 +137,7 @@ export default function Communication(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
将和主站相同版本的 Cloudreve
|
||||
程序拷贝至要作为从机的服务器上。
|
||||
{tDashboard("policy.remoteCopyBinaryDescription")}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -144,13 +148,12 @@ export default function Communication(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
下方为系统为您随机生成的从机端密钥,一般无需改动,如果有自定义需求,
|
||||
可将您的密钥填入下方:
|
||||
{tDashboard("policy.remoteSecretDescription")}
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel htmlFor="component-helper">
|
||||
从机密钥
|
||||
{tDashboard("policy.remoteSecret")}
|
||||
</InputLabel>
|
||||
<Input
|
||||
required
|
||||
|
|
@ -171,12 +174,13 @@ export default function Communication(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
修改从机配置文件。
|
||||
{tDashboard("policy.modifyRemoteConfig")}
|
||||
<br />
|
||||
在从机端 Cloudreve 的同级目录下新建
|
||||
<code>conf.ini</code>
|
||||
文件,填入从机配置,启动/重启从机端 Cloudreve。
|
||||
以下为一个可供参考的配置例子,其中密钥部分已帮您填写为上一步所生成的。
|
||||
<Trans
|
||||
ns={"dashboard"}
|
||||
i18nKey={"policy.addRemoteConfigDes"}
|
||||
components={[<code key={0} />]}
|
||||
/>
|
||||
</Typography>
|
||||
<pre>
|
||||
[System]
|
||||
|
|
@ -190,42 +194,50 @@ export default function Communication(props) {
|
|||
<br />
|
||||
Secret = {props.node.SlaveKey}
|
||||
<br />
|
||||
<br />;
|
||||
以下为可选的设置,对应主机节点的相关参数,可以通过配置文件应用到从机节点,请根据
|
||||
<br />
|
||||
; 实际情况调整。更改下面设置需要重启从机节点后生效。
|
||||
<Trans
|
||||
ns={"dashboard"}
|
||||
i18nKey={"node.overwriteDes"}
|
||||
components={[<br key={0} />, <br key={1} />]}
|
||||
/>
|
||||
<br />
|
||||
[OptionOverwrite]
|
||||
<br />
|
||||
; 任务队列最多并行执行的任务数
|
||||
<br />; {t("workerNumDes")}
|
||||
<br />
|
||||
max_worker_num = 50
|
||||
<br />
|
||||
; 任务队列中转任务传输时,最大并行协程数
|
||||
<br />; {t("parallelTransferDes")}
|
||||
<br />
|
||||
max_parallel_transfer = 10
|
||||
<br />
|
||||
; 中转分片上传失败后重试的最大次数
|
||||
<br />; {t("chunkRetriesDes")}
|
||||
<br />
|
||||
chunk_retries = 10
|
||||
</pre>
|
||||
<Typography variant={"body2"}>
|
||||
从机端配置文件格式大致与主站端相同,区别在于:
|
||||
{tDashboard("policy.remoteConfigDifference")}
|
||||
<ul>
|
||||
<li>
|
||||
<code>System</code>
|
||||
分区下的
|
||||
<code>mode</code>
|
||||
字段必须更改为<code>slave</code>
|
||||
<Trans
|
||||
ns={"dashboard"}
|
||||
i18nKey={"policy.remoteConfigDifference1"}
|
||||
components={[
|
||||
<code key={0} />,
|
||||
<code key={1} />,
|
||||
<code key={2} />,
|
||||
]}
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
必须指定<code>Slave</code>分区下的
|
||||
<code>Secret</code>
|
||||
字段,其值为第二步里填写或生成的密钥。
|
||||
<Trans
|
||||
ns={"dashboard"}
|
||||
i18nKey={"policy.remoteConfigDifference2"}
|
||||
components={[
|
||||
<code key={0} />,
|
||||
<code key={1} />,
|
||||
]}
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
一个从机 Cloudreve 实例可以对接多个 Cloudreve
|
||||
主节点,只需在所有主节点中添加此从机节点并保持密钥一致即可。
|
||||
{t("multipleMasterDes")}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -236,15 +248,14 @@ export default function Communication(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
填写从机地址。
|
||||
{tDashboard("policy.inputRemoteAddress")}
|
||||
<br />
|
||||
如果主站启用了 HTTPS,从机也需要启用,并在下方填入 HTTPS
|
||||
协议的地址。
|
||||
{tDashboard("policy.inputRemoteAddressDes")}
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel htmlFor="component-helper">
|
||||
从机地址
|
||||
{tDashboard("policy.remoteAddress")}
|
||||
</InputLabel>
|
||||
<Input
|
||||
fullWidth
|
||||
|
|
@ -264,7 +275,7 @@ export default function Communication(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
完成以上步骤后,你可以点击下方的测试按钮测试通信是否正常。
|
||||
{tDashboard("policy.testCommunicationDes")}
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<Button
|
||||
|
|
@ -273,7 +284,7 @@ export default function Communication(props) {
|
|||
onClick={() => testSlave()}
|
||||
color={"primary"}
|
||||
>
|
||||
测试从机通信
|
||||
{tDashboard("policy.testCommunication")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -286,7 +297,7 @@ export default function Communication(props) {
|
|||
variant={"contained"}
|
||||
color={"primary"}
|
||||
>
|
||||
下一步
|
||||
{tDashboard("policy.next")}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,9 @@
|
|||
import { lighten, makeStyles } from "@material-ui/core/styles";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import React from "react";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import { useDispatch } from "react-redux";
|
||||
import FormControl from "@material-ui/core/FormControl";
|
||||
import InputLabel from "@material-ui/core/InputLabel";
|
||||
import Input from "@material-ui/core/Input";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import API from "../../../../middleware/Api";
|
||||
import Alert from "@material-ui/lab/Alert";
|
||||
import Box from "@material-ui/core/Box";
|
||||
import { useHistory } from "react-router";
|
||||
import { toggleSnackbar } from "../../../../redux/explorer";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
stepContent: {
|
||||
|
|
@ -80,14 +73,15 @@ const useStyles = makeStyles((theme) => ({
|
|||
}));
|
||||
|
||||
export default function Completed(props) {
|
||||
const { t } = useTranslation("dashboard", { keyPrefix: "node" });
|
||||
const classes = useStyles();
|
||||
const history = useHistory();
|
||||
|
||||
return (
|
||||
<form className={classes.stepContent}>
|
||||
<Typography>节点已保存!</Typography>
|
||||
<Typography>{t("nodeSaved")}</Typography>
|
||||
<Typography variant={"body2"} color={"textSecondary"}>
|
||||
如果您添加了新节点,还需要在节点列表手动启动节点才能正常使用。
|
||||
{t("nodeSavedFutureAction")}
|
||||
</Typography>
|
||||
|
||||
<div className={classes.stepFooter}>
|
||||
|
|
@ -96,7 +90,7 @@ export default function Completed(props) {
|
|||
className={classes.button}
|
||||
onClick={() => history.push("/admin/node")}
|
||||
>
|
||||
返回节点列表
|
||||
{t("backToNodeList")}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -6,10 +6,8 @@ import FormControl from "@material-ui/core/FormControl";
|
|||
import InputLabel from "@material-ui/core/InputLabel";
|
||||
import Input from "@material-ui/core/Input";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import API from "../../../../middleware/Api";
|
||||
import Alert from "@material-ui/lab/Alert";
|
||||
import Box from "@material-ui/core/Box";
|
||||
import { toggleSnackbar } from "../../../../redux/explorer";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
stepContent: {
|
||||
|
|
@ -79,6 +77,8 @@ const useStyles = makeStyles((theme) => ({
|
|||
}));
|
||||
|
||||
export default function Metainfo(props) {
|
||||
const { t } = useTranslation("dashboard", { keyPrefix: "node" });
|
||||
const { t: tDashboard } = useTranslation("dashboard");
|
||||
const classes = useStyles();
|
||||
const dispatch = useDispatch();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
|
@ -101,7 +101,7 @@ export default function Metainfo(props) {
|
|||
<div className={classes.stepNumber}>1</div>
|
||||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>为此节点命名:</Typography>
|
||||
<Typography variant={"body2"}>{t("nameNode")}</Typography>
|
||||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<Input
|
||||
|
|
@ -120,12 +120,12 @@ export default function Metainfo(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
为此节点指定负载均衡权重,数值为整数。某些负载均衡策略会根据此数值加权选择节点
|
||||
{t("loadBalancerRankDes")}
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel htmlFor="component-helper">
|
||||
负载均衡权重
|
||||
{t("loadBalancerRank")}
|
||||
</InputLabel>
|
||||
<Input
|
||||
type={"number"}
|
||||
|
|
@ -149,7 +149,7 @@ export default function Metainfo(props) {
|
|||
variant={"contained"}
|
||||
color={"primary"}
|
||||
>
|
||||
下一步
|
||||
{tDashboard("policy.next")}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -11,11 +11,12 @@ import API from "../../../../middleware/Api";
|
|||
import Metainfo from "./Metainfo";
|
||||
import Completed from "./Completed";
|
||||
import { toggleSnackbar } from "../../../../redux/explorer";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const steps = [
|
||||
{
|
||||
slaveOnly: true,
|
||||
title: "通信配置",
|
||||
title: "communication",
|
||||
optional: false,
|
||||
component: function show(p) {
|
||||
return <Communication {...p} />;
|
||||
|
|
@ -23,7 +24,7 @@ const steps = [
|
|||
},
|
||||
{
|
||||
slaveOnly: false,
|
||||
title: "离线下载",
|
||||
title: "remoteDownload",
|
||||
optional: false,
|
||||
component: function show(p) {
|
||||
return <Aria2RPC {...p} />;
|
||||
|
|
@ -31,7 +32,7 @@ const steps = [
|
|||
},
|
||||
{
|
||||
slaveOnly: false,
|
||||
title: "杂项信息",
|
||||
title: "otherSettings",
|
||||
optional: false,
|
||||
component: function show(p) {
|
||||
return <Metainfo {...p} />;
|
||||
|
|
@ -39,7 +40,7 @@ const steps = [
|
|||
},
|
||||
{
|
||||
slaveOnly: false,
|
||||
title: "完成",
|
||||
title: "finish",
|
||||
optional: false,
|
||||
component: function show(p) {
|
||||
return <Completed {...p} />;
|
||||
|
|
@ -48,6 +49,8 @@ const steps = [
|
|||
];
|
||||
|
||||
export default function NodeGuide(props) {
|
||||
const { t } = useTranslation("dashboard", { keyPrefix: "node" });
|
||||
const { t: tDashboard } = useTranslation("dashboard");
|
||||
const [activeStep, setActiveStep] = useState(0);
|
||||
const [skipped, setSkipped] = React.useState(new Set());
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
|
@ -126,7 +129,7 @@ export default function NodeGuide(props) {
|
|||
ToggleSnackbar(
|
||||
"top",
|
||||
"right",
|
||||
"节点已" + (props.node ? "保存" : "添加"),
|
||||
props.node ? t("nodeSavedNow") : t("nodeAdded"),
|
||||
"success"
|
||||
);
|
||||
setActiveStep(activeStep + 1);
|
||||
|
|
@ -146,7 +149,7 @@ export default function NodeGuide(props) {
|
|||
return (
|
||||
<div>
|
||||
<Typography variant={"h6"}>
|
||||
{props.node ? "修改" : "添加"} 节点
|
||||
{props.node ? t("editNode") : t("addNode")}
|
||||
</Typography>
|
||||
<Stepper activeStep={activeStep}>
|
||||
{usedSteps.map((label, index) => {
|
||||
|
|
@ -154,7 +157,9 @@ export default function NodeGuide(props) {
|
|||
const labelProps = {};
|
||||
if (label.optional) {
|
||||
labelProps.optional = (
|
||||
<Typography variant="caption">可选</Typography>
|
||||
<Typography variant="caption">
|
||||
{tDashboard("policy.optional")}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
if (isStepSkipped(index)) {
|
||||
|
|
@ -164,7 +169,7 @@ export default function NodeGuide(props) {
|
|||
return (
|
||||
<Step key={label.title} {...stepProps}>
|
||||
<StepLabel {...labelProps}>
|
||||
{label.title}
|
||||
{t(label.title)}
|
||||
</StepLabel>
|
||||
</Step>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -14,18 +14,19 @@ import TablePagination from "@material-ui/core/TablePagination";
|
|||
import { useHistory } from "react-router";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import {
|
||||
Delete,
|
||||
Edit,
|
||||
Cancel,
|
||||
CheckCircle,
|
||||
PlayArrow,
|
||||
Delete,
|
||||
Edit,
|
||||
Pause,
|
||||
PlayArrow,
|
||||
} from "@material-ui/icons";
|
||||
import Tooltip from "@material-ui/core/Tooltip";
|
||||
import Chip from "@material-ui/core/Chip";
|
||||
import classNames from "classnames";
|
||||
import Box from "@material-ui/core/Box";
|
||||
import { toggleSnackbar } from "../../../redux/explorer";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
|
|
@ -61,21 +62,18 @@ const useStyles = makeStyles((theme) => ({
|
|||
}));
|
||||
|
||||
const columns = [
|
||||
{ id: "#", label: "#", minWidth: 50 },
|
||||
{ id: "name", label: "名称", minWidth: 170 },
|
||||
{ id: "#", minWidth: 50 },
|
||||
{ id: "name", minWidth: 170 },
|
||||
{
|
||||
id: "status",
|
||||
label: "当前状态",
|
||||
minWidth: 50,
|
||||
},
|
||||
{
|
||||
id: "features",
|
||||
label: "已启用功能",
|
||||
minWidth: 170,
|
||||
},
|
||||
{
|
||||
id: "action",
|
||||
label: "操作",
|
||||
minWidth: 170,
|
||||
},
|
||||
];
|
||||
|
|
@ -83,11 +81,12 @@ const columns = [
|
|||
const features = [
|
||||
{
|
||||
field: "Aria2Enabled",
|
||||
name: "离线下载",
|
||||
name: "remoteDownload",
|
||||
},
|
||||
];
|
||||
|
||||
export default function Node() {
|
||||
const { t } = useTranslation("dashboard", { keyPrefix: "node" });
|
||||
const classes = useStyles();
|
||||
const [nodes, setNodes] = useState([]);
|
||||
const [isActive, setIsActive] = useState({});
|
||||
|
|
@ -129,7 +128,7 @@ export default function Node() {
|
|||
ToggleSnackbar(
|
||||
"top",
|
||||
"right",
|
||||
"节点已" + (desired === 1 ? "暂停使用" : "启用"),
|
||||
desired === 1 ? t("nodeDisabled") : t("nodeEnabled"),
|
||||
"success"
|
||||
);
|
||||
})
|
||||
|
|
@ -146,7 +145,7 @@ export default function Node() {
|
|||
API.delete("/admin/node/" + id)
|
||||
.then(() => {
|
||||
loadList();
|
||||
ToggleSnackbar("top", "right", "节点已删除", "success");
|
||||
ToggleSnackbar("top", "right", t("nodeDeleted"), "success");
|
||||
})
|
||||
.catch((error) => {
|
||||
ToggleSnackbar("top", "right", error.message, "error");
|
||||
|
|
@ -166,7 +165,7 @@ export default function Node() {
|
|||
<Chip
|
||||
className={classes.disabledBadge}
|
||||
size="small"
|
||||
label="未启用"
|
||||
label={t("disabled")}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -180,7 +179,7 @@ export default function Node() {
|
|||
className={classes.disabledBadge}
|
||||
size="small"
|
||||
color="primary"
|
||||
label={feature.name}
|
||||
label={t(feature.name)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -193,12 +192,12 @@ export default function Node() {
|
|||
className={classes.verticalAlign}
|
||||
fontSize="small"
|
||||
/>{" "}
|
||||
<span className={classes.verticalAlign}>在线</span>
|
||||
<span className={classes.verticalAlign}>{t("online")}</span>
|
||||
</Box>
|
||||
) : (
|
||||
<Box color="error.main" fontSize="small">
|
||||
<Cancel className={classes.verticalAlign} fontSize="small" />{" "}
|
||||
<span className={classes.verticalAlign}>离线</span>
|
||||
<span className={classes.verticalAlign}>{t("offline")}</span>
|
||||
</Box>
|
||||
);
|
||||
|
||||
|
|
@ -210,7 +209,7 @@ export default function Node() {
|
|||
onClick={() => history.push("/admin/node/add")}
|
||||
variant={"contained"}
|
||||
>
|
||||
接入新节点
|
||||
{t("addNewNode")}
|
||||
</Button>
|
||||
<div className={classes.headerRight}>
|
||||
<Button
|
||||
|
|
@ -218,7 +217,7 @@ export default function Node() {
|
|||
onClick={() => loadList()}
|
||||
variant={"outlined"}
|
||||
>
|
||||
刷新
|
||||
{t("refresh")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -236,7 +235,7 @@ export default function Node() {
|
|||
minWidth: column.minWidthclassNames,
|
||||
}}
|
||||
>
|
||||
{column.label}
|
||||
{t(column.id)}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
|
|
@ -265,8 +264,8 @@ export default function Node() {
|
|||
<Tooltip
|
||||
title={
|
||||
row.Status === 1
|
||||
? "启用节点"
|
||||
: "暂停使用节点"
|
||||
? t("enableNode")
|
||||
: t("disableNode")
|
||||
}
|
||||
>
|
||||
<IconButton
|
||||
|
|
@ -285,7 +284,7 @@ export default function Node() {
|
|||
{row.Status !== 1 && <Pause />}
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title={"编辑"}>
|
||||
<Tooltip title={t("edit")}>
|
||||
<IconButton
|
||||
disabled={loading}
|
||||
onClick={() =>
|
||||
|
|
@ -299,7 +298,7 @@ export default function Node() {
|
|||
<Edit />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title={"删除"}>
|
||||
<Tooltip title={t("delete")}>
|
||||
<IconButton
|
||||
onClick={() =>
|
||||
deleteNode(row.ID)
|
||||
|
|
|
|||
Loading…
Reference in New Issue