mirror of
https://github.com/cloudreve/frontend.git
synced 2025-12-25 19:52:48 +00:00
feat: add remote storage policy
This commit is contained in:
parent
3b97ba3dcf
commit
a9f044a93d
|
|
@ -314,6 +314,50 @@
|
|||
"policyName": "Storage policy name",
|
||||
"finish": "Finish",
|
||||
"furtherActions": "To use this storage policy, go to the user group setting page and bind this storage policy for the appropriate user group.",
|
||||
"backToList": "Back to storage policy list"
|
||||
"backToList": "Back to storage policy list",
|
||||
"magicVar": {
|
||||
"fileNameMagicVar": "File name magic variables",
|
||||
"pathMagicVar": "Path magic variables",
|
||||
"variable": "Variable",
|
||||
"description": "Description",
|
||||
"example": "Example",
|
||||
"16digitsRandomString": "16 digits random string",
|
||||
"8digitsRandomString": "8 digits random string",
|
||||
"secondTimestamp": "Timestamp",
|
||||
"nanoTimestamp": "Nano timestamp",
|
||||
"uid": "User ID",
|
||||
"originalFileName": "Original file name",
|
||||
"extension": "File extension name",
|
||||
"uuidV4": "UUID V4",
|
||||
"date": "Date",
|
||||
"dateAndTime": "Date and time",
|
||||
"year": "Year",
|
||||
"month": "Month",
|
||||
"day": "Day",
|
||||
"hour": "Hour",
|
||||
"minute": "Minute",
|
||||
"second": "Second",
|
||||
"userUploadPath": "Upload path"
|
||||
},
|
||||
"storageNode": "Storage node",
|
||||
"communicationOK": "通信正常",
|
||||
"editRemoteStoragePolicy": "Edit remote storage policy",
|
||||
"addRemoteStoragePolicy": "Add remote storage policy",
|
||||
"remoteDescription": "The remote storage policy allows you to use a server that is also running Cloudreve as the slave storage node, and users' upload and download traffic are directly transmitted over HTTP.",
|
||||
"remoteCopyBinaryDescription": "Copy the Cloudreve executable with the same version as master to the server you want to use as a slave storage node.",
|
||||
"remoteSecretDescription": "The following is the randomly generated slave secret, usually no need to change. If you have customization requirement, you can fill in your own secret into the following field.",
|
||||
"remoteSecret": "Slave node secret",
|
||||
"modifyRemoteConfig": "Modify the Cloudreve config file on slave node.",
|
||||
"addRemoteConfigDes": " Create a new <0>conf.ini</0> file in the same directory as the slave Cloudreve, fill in the slave configuration, and start/restart the slave Cloudreve. The following is an example configuration for your slave Cloudreve, where the secret section is pre-filled in for you as generated in the previous step.",
|
||||
"remoteConfigDifference": "The configuration file format on the slave side is roughly the same as the master side, with the following differences:",
|
||||
"remoteConfigDifference1": "The <1>mode</1> field under the <0>System</0> section must be changed to <2>slave</2>.",
|
||||
"remoteConfigDifference2": "You must specify the <1>Secret</1> field under the <0>Slave</0> section, whose value is the secret filled in or generated in step 2.",
|
||||
"remoteConfigDifference3": "The cross-origin configuration, i.e. the contents of the <0>CORS</0> field, must be enabled, as described in the example above or in the official documentation. If the configuration is not correct, users will not be able to upload files to the slave node via the web browser.",
|
||||
"inputRemoteAddress": "Enter slave node address.",
|
||||
"inputRemoteAddressDes": "If HTTPS is enabled on the master, the slave also needs to enable it and fill in the address with HTTPS protocol below.",
|
||||
"remoteAddress": "Slave node address",
|
||||
"testCommunicationDes": "After completing the above steps, you can test if the communication is working by clicking the test button below.",
|
||||
"testCommunication": "Test slave communication",
|
||||
"pathMagicVarDesRemote": "Enter the physical path to the folder you want to store files. Either absolute or relative (relative to slave Cloudreve executable) path is supported. You can use magic variables in the path, which will be automatically replaced with the corresponding values when the file is uploaded; see <0>List of path magic variables</0> for available magic variables."
|
||||
}
|
||||
}
|
||||
|
|
@ -313,6 +313,50 @@
|
|||
"policyName": "存储策略名",
|
||||
"finish": "完成",
|
||||
"furtherActions": "要使用此存储策略,请到用户组管理页面,为相应用户组绑定此存储策略。",
|
||||
"backToList": "返回存储策略列表"
|
||||
"backToList": "返回存储策略列表",
|
||||
"magicVar": {
|
||||
"fileNameMagicVar": "文件名魔法变量",
|
||||
"pathMagicVar": "路径魔法变量",
|
||||
"variable": "魔法变量",
|
||||
"description": "描述",
|
||||
"example": "示例",
|
||||
"16digitsRandomString": "16 位随机字符",
|
||||
"8digitsRandomString": "8 位随机字符",
|
||||
"secondTimestamp": "秒级时间戳",
|
||||
"nanoTimestamp": "纳秒级时间戳",
|
||||
"uid": "用户 ID",
|
||||
"originalFileName": "原始文件名",
|
||||
"extension": "文件扩展名",
|
||||
"uuidV4": "UUID V4",
|
||||
"date": "日期",
|
||||
"dateAndTime": "日期时间",
|
||||
"year": "年份",
|
||||
"month": "月份",
|
||||
"day": "日",
|
||||
"hour": "小时",
|
||||
"minute": "分钟",
|
||||
"second": "秒",
|
||||
"userUploadPath": "用户上传路径"
|
||||
},
|
||||
"storageNode": "存储端配置",
|
||||
"communicationOK": "通信正常",
|
||||
"editRemoteStoragePolicy": "修改从机存储策略",
|
||||
"addRemoteStoragePolicy": "添加从机存储策略",
|
||||
"remoteDescription": "从机存储策略允许你使用同样运行了 Cloudreve 的服务器作为存储端, 用户上传下载流量通过 HTTP 直传。",
|
||||
"remoteCopyBinaryDescription": "将和主站相同版本的 Cloudreve 程序拷贝至要作为从机的服务器上。",
|
||||
"remoteSecretDescription": "下方为系统为您随机生成的从机端密钥,一般无需改动,如果有自定义需求,可将您的密钥填入下方:",
|
||||
"remoteSecret": "从机密钥",
|
||||
"modifyRemoteConfig": "修改从机配置文件。",
|
||||
"addRemoteConfigDes": " 在从机端 Cloudreve 的同级目录下新建 <0>conf.ini</0> 文件,填入从机配置,启动/重启从机端 Cloudreve。以下为一个可供参考的配置例子,其中密钥部分已帮您填写为上一步所生成的。",
|
||||
"remoteConfigDifference": "从机端配置文件格式大致与主站端相同,区别在于:",
|
||||
"remoteConfigDifference1": "<0>System</0> 分区下的 <1>mode</1> 字段必须更改为 <2>slave</2>。",
|
||||
"remoteConfigDifference2": "必须指定 <0>Slave</0> 分区下的 <1>Secret</1> 字段,其值为第二步里填写或生成的密钥。",
|
||||
"remoteConfigDifference3": "必须启动跨域配置,即 <0>CORS</0> 字段的内容,具体可参考上文范例或官方文档。如果配置不正确,用户将无法通过 Web 端向从机上传文件。",
|
||||
"inputRemoteAddress": "填写从机地址。",
|
||||
"inputRemoteAddressDes": "如果主站启用了 HTTPS,从机也需要启用,并在下方填入 HTTPS 协议的地址。",
|
||||
"remoteAddress": "从机地址",
|
||||
"testCommunicationDes": "完成以上步骤后,你可以点击下方的测试按钮测试通信是否正常。",
|
||||
"testCommunication": "测试从机通信",
|
||||
"pathMagicVarDesRemote": "请在下方输入文件的存储目录路径,可以为绝对路径或相对路径(相对于 从机的 Cloudreve)。路径中可以使用魔法变量,文件在上传时会自动替换这些变量为相应值; 可用魔法变量可参考 <0>路径魔法变量列表</0>。"
|
||||
}
|
||||
}
|
||||
|
|
@ -10,107 +10,110 @@ import TableContainer from "@material-ui/core/TableContainer";
|
|||
import TableHead from "@material-ui/core/TableHead";
|
||||
import TableRow from "@material-ui/core/TableRow";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const magicVars = [
|
||||
{
|
||||
value: "{randomkey16}",
|
||||
des: "16位随机字符",
|
||||
des: "16digitsRandomString",
|
||||
example: "N6IimT5XZP324ACK",
|
||||
fileOnly: false,
|
||||
},
|
||||
{
|
||||
value: "{randomkey8}",
|
||||
des: "8位随机字符",
|
||||
des: "8digitsRandomString",
|
||||
example: "gWz78q30",
|
||||
fileOnly: false,
|
||||
},
|
||||
{
|
||||
value: "{timestamp}",
|
||||
des: "秒级时间戳",
|
||||
des: "secondTimestamp",
|
||||
example: "1582692933",
|
||||
fileOnly: false,
|
||||
},
|
||||
{
|
||||
value: "{timestamp_nano}",
|
||||
des: "纳秒级时间戳",
|
||||
des: "nanoTimestamp",
|
||||
example: "1582692933231834600",
|
||||
fileOnly: false,
|
||||
},
|
||||
{
|
||||
value: "{uid}",
|
||||
des: "用户ID",
|
||||
des: "uid",
|
||||
example: "1",
|
||||
fileOnly: false,
|
||||
},
|
||||
{
|
||||
value: "{originname}",
|
||||
des: "原始文件名",
|
||||
des: "originalFileName",
|
||||
example: "MyPico.mp4",
|
||||
fileOnly: true,
|
||||
},
|
||||
{
|
||||
value: "{ext}",
|
||||
des: "文件扩展名",
|
||||
des: "extension",
|
||||
example: ".jpg",
|
||||
fileOnly: true,
|
||||
},
|
||||
{
|
||||
value: "{uuid}",
|
||||
des: "UUID V4",
|
||||
des: "uuidV4",
|
||||
example: "31f0a770-659d-45bf-a5a9-166c06f33281",
|
||||
fileOnly: true,
|
||||
},
|
||||
{
|
||||
value: "{date}",
|
||||
des: "日期",
|
||||
des: "date",
|
||||
example: "20060102",
|
||||
fileOnly: false,
|
||||
},
|
||||
{
|
||||
value: "{datetime}",
|
||||
des: "日期时间",
|
||||
des: "dateAndTime",
|
||||
example: "20060102150405",
|
||||
fileOnly: false,
|
||||
},
|
||||
{
|
||||
value: "{year}",
|
||||
des: "年份",
|
||||
des: "year",
|
||||
example: "2006",
|
||||
fileOnly: false,
|
||||
},
|
||||
{
|
||||
value: "{month}",
|
||||
des: "月份",
|
||||
des: "month",
|
||||
example: "01",
|
||||
fileOnly: false,
|
||||
},
|
||||
{
|
||||
value: "{day}",
|
||||
des: "日",
|
||||
des: "day",
|
||||
example: "02",
|
||||
fileOnly: false,
|
||||
},
|
||||
{
|
||||
value: "{hour}",
|
||||
des: "小时",
|
||||
des: "hour",
|
||||
example: "15",
|
||||
fileOnly: false,
|
||||
},
|
||||
{
|
||||
value: "{minute}",
|
||||
des: "分钟",
|
||||
des: "minute",
|
||||
example: "04",
|
||||
fileOnly: false,
|
||||
},
|
||||
{
|
||||
value: "{second}",
|
||||
des: "秒",
|
||||
des: "second",
|
||||
example: "05",
|
||||
fileOnly: false,
|
||||
},
|
||||
];
|
||||
|
||||
export default function MagicVar({ isFile, open, onClose, isSlave }) {
|
||||
const { t } = useTranslation("dashboard", { keyPrefix: "policy.magicVar" });
|
||||
const { t: tCommon } = useTranslation("common");
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
|
|
@ -119,16 +122,16 @@ export default function MagicVar({ isFile, open, onClose, isSlave }) {
|
|||
aria-describedby="alert-dialog-description"
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">
|
||||
{isFile ? "文件名魔法变量" : "路径魔法变量"}
|
||||
{isFile ? t("fileNameMagicVar") : t("pathMagicVar")}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<TableContainer>
|
||||
<Table size="small" aria-label="a dense table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>魔法变量</TableCell>
|
||||
<TableCell>描述</TableCell>
|
||||
<TableCell>示例</TableCell>
|
||||
<TableCell>{t("variable")}</TableCell>
|
||||
<TableCell>{t("description")}</TableCell>
|
||||
<TableCell>{t("example")}</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
|
|
@ -142,7 +145,7 @@ export default function MagicVar({ isFile, open, onClose, isSlave }) {
|
|||
>
|
||||
{m.value}
|
||||
</TableCell>
|
||||
<TableCell>{m.des}</TableCell>
|
||||
<TableCell>{t(m.des)}</TableCell>
|
||||
<TableCell>{m.example}</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
|
|
@ -153,8 +156,8 @@ export default function MagicVar({ isFile, open, onClose, isSlave }) {
|
|||
<TableCell component="th" scope="row">
|
||||
{"{path}"}
|
||||
</TableCell>
|
||||
<TableCell>用户上传路径</TableCell>
|
||||
<TableCell>/我的文件/学习资料/</TableCell>
|
||||
<TableCell>{t("userUploadPath")}</TableCell>
|
||||
<TableCell>/MyFile/Documents/</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
|
|
@ -163,7 +166,7 @@ export default function MagicVar({ isFile, open, onClose, isSlave }) {
|
|||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onClose} color="primary">
|
||||
关闭
|
||||
{tCommon("close")}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import { getNumber, randomStr } from "../../../../utils";
|
|||
import DomainInput from "../../Common/DomainInput";
|
||||
import SizeInput from "../../Common/SizeInput";
|
||||
import MagicVar from "../../Dialogs/MagicVar";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
stepContent: {
|
||||
|
|
@ -90,28 +91,29 @@ const useStyles = makeStyles((theme) => ({
|
|||
|
||||
const steps = [
|
||||
{
|
||||
title: "存储端配置",
|
||||
title: "storageNode",
|
||||
optional: false,
|
||||
},
|
||||
{
|
||||
title: "上传路径",
|
||||
title: "storagePathStep",
|
||||
optional: false,
|
||||
},
|
||||
{
|
||||
title: "直链设置",
|
||||
title: "sourceLinkStep",
|
||||
optional: false,
|
||||
},
|
||||
{
|
||||
title: "上传设置",
|
||||
title: "uploadSettingStep",
|
||||
optional: false,
|
||||
},
|
||||
{
|
||||
title: "完成",
|
||||
title: "finishStep",
|
||||
optional: false,
|
||||
},
|
||||
];
|
||||
|
||||
export default function RemoteGuide(props) {
|
||||
const { t } = useTranslation("dashboard", { keyPrefix: "policy" });
|
||||
const classes = useStyles();
|
||||
const history = useHistory();
|
||||
|
||||
|
|
@ -179,7 +181,7 @@ export default function RemoteGuide(props) {
|
|||
secret: policy.SecretKey,
|
||||
})
|
||||
.then(() => {
|
||||
ToggleSnackbar("top", "right", "通信正常", "success");
|
||||
ToggleSnackbar("top", "right", t("communicationOK"), "success");
|
||||
})
|
||||
.catch((error) => {
|
||||
ToggleSnackbar("top", "right", error.message, "error");
|
||||
|
|
@ -229,7 +231,7 @@ export default function RemoteGuide(props) {
|
|||
ToggleSnackbar(
|
||||
"top",
|
||||
"right",
|
||||
"存储策略已" + (props.policy ? "保存" : "添加"),
|
||||
props.policy ? t("policySaved") : t("policyAdded"),
|
||||
"success"
|
||||
);
|
||||
setActiveStep(5);
|
||||
|
|
@ -247,7 +249,9 @@ export default function RemoteGuide(props) {
|
|||
return (
|
||||
<div>
|
||||
<Typography variant={"h6"}>
|
||||
{props.policy ? "修改" : "添加"}从机存储策略
|
||||
{props.policy
|
||||
? t("editRemoteStoragePolicy")
|
||||
: t("addRemoteStoragePolicy")}
|
||||
</Typography>
|
||||
<Stepper activeStep={activeStep}>
|
||||
{steps.map((label, index) => {
|
||||
|
|
@ -255,7 +259,9 @@ export default function RemoteGuide(props) {
|
|||
const labelProps = {};
|
||||
if (label.optional) {
|
||||
labelProps.optional = (
|
||||
<Typography variant="caption">可选</Typography>
|
||||
<Typography variant="caption">
|
||||
{t("optional")}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
if (isStepSkipped(index)) {
|
||||
|
|
@ -263,7 +269,9 @@ export default function RemoteGuide(props) {
|
|||
}
|
||||
return (
|
||||
<Step key={label.title} {...stepProps}>
|
||||
<StepLabel {...labelProps}>{label.title}</StepLabel>
|
||||
<StepLabel {...labelProps}>
|
||||
{t(label.title)}
|
||||
</StepLabel>
|
||||
</Step>
|
||||
);
|
||||
})}
|
||||
|
|
@ -278,8 +286,7 @@ export default function RemoteGuide(props) {
|
|||
}}
|
||||
>
|
||||
<Alert severity="info" style={{ marginBottom: 10 }}>
|
||||
从机存储策略允许你使用同样运行了 Cloudreve
|
||||
的服务器作为存储端, 用户上传下载流量通过 HTTP 直传。
|
||||
{t("remoteDescription")}
|
||||
</Alert>
|
||||
|
||||
<div className={classes.subStepContainer}>
|
||||
|
|
@ -288,8 +295,7 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
将和主站相同版本的 Cloudreve
|
||||
程序拷贝至要作为从机的服务器上。
|
||||
{t("remoteCopyBinaryDescription")}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -300,13 +306,12 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
下方为系统为您随机生成的从机端密钥,一般无需改动,如果有自定义需求,
|
||||
可将您的密钥填入下方:
|
||||
{t("remoteSecretDescription")}
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel htmlFor="component-helper">
|
||||
从机密钥
|
||||
{t("remoteSecret")}
|
||||
</InputLabel>
|
||||
<Input
|
||||
required
|
||||
|
|
@ -327,12 +332,13 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
修改从机配置文件。
|
||||
{t("modifyRemoteConfig")}
|
||||
<br />
|
||||
在从机端 Cloudreve 的同级目录下新建
|
||||
<code>conf.ini</code>
|
||||
文件,填入从机配置,启动/重启从机端 Cloudreve。
|
||||
以下为一个可供参考的配置例子,其中密钥部分已帮您填写为上一步所生成的。
|
||||
<Trans
|
||||
ns={"dashboard"}
|
||||
i18nKey={"policy.addRemoteConfigDes"}
|
||||
components={[<code key={0} />]}
|
||||
/>
|
||||
</Typography>
|
||||
<pre>
|
||||
[System]
|
||||
|
|
@ -355,24 +361,41 @@ export default function RemoteGuide(props) {
|
|||
AllowHeaders = *<br />
|
||||
</pre>
|
||||
<Typography variant={"body2"}>
|
||||
从机端配置文件格式大致与主站端相同,区别在于:
|
||||
{t("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>
|
||||
<li>
|
||||
必须启动跨域配置,即<code>CORS</code>
|
||||
字段的内容,
|
||||
具体可参考上文范例或官方文档。如果配置不正确,用户将无法通过
|
||||
Web 端向从机上传文件。
|
||||
<Trans
|
||||
ns={"dashboard"}
|
||||
i18nKey={
|
||||
"policy.remoteConfigDifference3"
|
||||
}
|
||||
components={[<code key={0} />]}
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</Typography>
|
||||
|
|
@ -385,16 +408,14 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
填写从机地址。
|
||||
{t("inputRemoteAddress")}
|
||||
<br />
|
||||
如果主站启用了
|
||||
HTTPS,从机也需要启用,并在下方填入 HTTPS
|
||||
协议的地址。
|
||||
{t("inputRemoteAddressDes")}
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel htmlFor="component-helper">
|
||||
从机地址
|
||||
{t("remoteAddress")}
|
||||
</InputLabel>
|
||||
<Input
|
||||
fullWidth
|
||||
|
|
@ -414,7 +435,7 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
完成以上步骤后,你可以点击下方的测试按钮测试通信是否正常。
|
||||
{t("testCommunicationDes")}
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<Button
|
||||
|
|
@ -423,7 +444,7 @@ export default function RemoteGuide(props) {
|
|||
variant={"outlined"}
|
||||
color={"primary"}
|
||||
>
|
||||
测试从机通信
|
||||
{t("testCommunication")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -436,7 +457,7 @@ export default function RemoteGuide(props) {
|
|||
variant={"contained"}
|
||||
color={"primary"}
|
||||
>
|
||||
下一步
|
||||
{t("next")}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -456,25 +477,23 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
请在下方输入文件的存储目录路径,可以为绝对路径或相对路径(相对于
|
||||
从机的
|
||||
Cloudreve)。路径中可以使用魔法变量,文件在上传时会自动替换这些变量为相应值;
|
||||
可用魔法变量可参考{" "}
|
||||
<Link
|
||||
color={"secondary"}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setMagicVar("path");
|
||||
}}
|
||||
>
|
||||
路径魔法变量列表
|
||||
</Link>{" "}
|
||||
。
|
||||
<Trans
|
||||
ns={"dashboard"}
|
||||
i18nKey={"policy.filePathMagicVarDes"}
|
||||
components={[
|
||||
<Link
|
||||
key={0}
|
||||
color={"secondary"}
|
||||
href={"javascript:void()"}
|
||||
onClick={() => setMagicVar("file")}
|
||||
/>,
|
||||
]}
|
||||
/>
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel htmlFor="component-helper">
|
||||
存储目录
|
||||
{t("pathOfFolderToStoreFiles")}
|
||||
</InputLabel>
|
||||
<Input
|
||||
required
|
||||
|
|
@ -520,14 +539,14 @@ export default function RemoteGuide(props) {
|
|||
control={
|
||||
<Radio color={"primary"} />
|
||||
}
|
||||
label="开启重命名"
|
||||
label={t("autoRenameStoredFile")}
|
||||
/>
|
||||
<FormControlLabel
|
||||
value={"false"}
|
||||
control={
|
||||
<Radio color={"primary"} />
|
||||
}
|
||||
label="不开启"
|
||||
label={t("keepOriginalFileName")}
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
|
|
@ -537,7 +556,7 @@ export default function RemoteGuide(props) {
|
|||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel htmlFor="component-helper">
|
||||
命名规则
|
||||
{t("renameRule")}
|
||||
</InputLabel>
|
||||
<Input
|
||||
required={
|
||||
|
|
@ -560,7 +579,7 @@ export default function RemoteGuide(props) {
|
|||
className={classes.button}
|
||||
onClick={() => setActiveStep(0)}
|
||||
>
|
||||
上一步
|
||||
{t("back")}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={loading}
|
||||
|
|
@ -568,7 +587,7 @@ export default function RemoteGuide(props) {
|
|||
variant={"contained"}
|
||||
color={"primary"}
|
||||
>
|
||||
下一步
|
||||
{t("next")}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -588,9 +607,9 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
是否允许获取文件永久直链?
|
||||
{t("enableGettingPermanentSourceLink")}
|
||||
<br />
|
||||
开启后,用户可以请求获得能直接访问到文件内容的直链,适用于图床应用或自用。
|
||||
{t("enableGettingPermanentSourceLinkDes")}
|
||||
</Typography>
|
||||
|
||||
<div className={classes.form}>
|
||||
|
|
@ -608,14 +627,14 @@ export default function RemoteGuide(props) {
|
|||
control={
|
||||
<Radio color={"primary"} />
|
||||
}
|
||||
label="允许"
|
||||
label={t("allowed")}
|
||||
/>
|
||||
<FormControlLabel
|
||||
value={"false"}
|
||||
control={
|
||||
<Radio color={"primary"} />
|
||||
}
|
||||
label="禁止"
|
||||
label={t("forbidden")}
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
|
|
@ -630,10 +649,9 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
是否要对下载/直链使用 CDN?
|
||||
{t("useCDN")}
|
||||
<br />
|
||||
开启后,用户访问文件时的 URL
|
||||
中的域名部分会被替换为 CDN 域名。
|
||||
{t("useCDNDes")}
|
||||
</Typography>
|
||||
|
||||
<div className={classes.form}>
|
||||
|
|
@ -659,14 +677,14 @@ export default function RemoteGuide(props) {
|
|||
control={
|
||||
<Radio color={"primary"} />
|
||||
}
|
||||
label="使用"
|
||||
label={t("use")}
|
||||
/>
|
||||
<FormControlLabel
|
||||
value={"false"}
|
||||
control={
|
||||
<Radio color={"primary"} />
|
||||
}
|
||||
label="不使用"
|
||||
label={t("notUse")}
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
|
|
@ -681,7 +699,7 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
选择协议并填写 CDN 域名
|
||||
{t("cdnDomain")}
|
||||
</Typography>
|
||||
|
||||
<div className={classes.form}>
|
||||
|
|
@ -692,7 +710,7 @@ export default function RemoteGuide(props) {
|
|||
policy.IsOriginLinkEnable ===
|
||||
"true" && useCDN === "true"
|
||||
}
|
||||
label={"CDN 前缀"}
|
||||
label={t("cdnPrefix")}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -706,7 +724,7 @@ export default function RemoteGuide(props) {
|
|||
className={classes.button}
|
||||
onClick={() => setActiveStep(1)}
|
||||
>
|
||||
上一步
|
||||
{t("back")}
|
||||
</Button>{" "}
|
||||
<Button
|
||||
disabled={loading}
|
||||
|
|
@ -714,7 +732,7 @@ export default function RemoteGuide(props) {
|
|||
variant={"contained"}
|
||||
color={"primary"}
|
||||
>
|
||||
下一步
|
||||
{t("next")}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -734,7 +752,7 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
是否限制上传的单文件大小?
|
||||
{t("limitFileSize")}
|
||||
</Typography>
|
||||
|
||||
<div className={classes.form}>
|
||||
|
|
@ -766,14 +784,14 @@ export default function RemoteGuide(props) {
|
|||
control={
|
||||
<Radio color={"primary"} />
|
||||
}
|
||||
label="限制"
|
||||
label={t("limit")}
|
||||
/>
|
||||
<FormControlLabel
|
||||
value={"false"}
|
||||
control={
|
||||
<Radio color={"primary"} />
|
||||
}
|
||||
label="不限制"
|
||||
label={t("notLimit")}
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
|
|
@ -788,7 +806,7 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
输入限制:
|
||||
{t("enterSizeLimit")}
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<SizeInput
|
||||
|
|
@ -796,7 +814,7 @@ export default function RemoteGuide(props) {
|
|||
onChange={handleChange("MaxSize")}
|
||||
min={0}
|
||||
max={9223372036854775807}
|
||||
label={"单文件大小限制"}
|
||||
label={t("maxSizeOfSingleFile")}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -811,7 +829,7 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
是否限制上传文件扩展名?
|
||||
{t("limitFileExt")}
|
||||
</Typography>
|
||||
|
||||
<div className={classes.form}>
|
||||
|
|
@ -851,14 +869,14 @@ export default function RemoteGuide(props) {
|
|||
control={
|
||||
<Radio color={"primary"} />
|
||||
}
|
||||
label="限制"
|
||||
label={t("limit")}
|
||||
/>
|
||||
<FormControlLabel
|
||||
value={"false"}
|
||||
control={
|
||||
<Radio color={"primary"} />
|
||||
}
|
||||
label="不限制"
|
||||
label={t("notLimit")}
|
||||
/>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
|
|
@ -875,13 +893,12 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
输入允许上传的文件扩展名,多个请以半角逗号 ,
|
||||
隔开
|
||||
{t("enterFileExt")}
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel htmlFor="component-helper">
|
||||
扩展名列表
|
||||
{t("extList")}
|
||||
</InputLabel>
|
||||
<Input
|
||||
value={
|
||||
|
|
@ -909,10 +926,9 @@ export default function RemoteGuide(props) {
|
|||
</div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
请指定分片上传时的分片大小,填写为 0
|
||||
表示不使用分片上传。
|
||||
{t("chunkSizeLabel")}
|
||||
<br />
|
||||
启用分片上传后,用户上传的文件将会被切分成分片逐个上传到存储端,当上传中断后,用户可以选择从上次上传的分片后继续开始上传。
|
||||
{t("chunkSizeDes")}
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<SizeInput
|
||||
|
|
@ -920,7 +936,7 @@ export default function RemoteGuide(props) {
|
|||
onChange={handleOptionChange("chunk_size")}
|
||||
min={0}
|
||||
max={9223372036854775807}
|
||||
label={"分片上传大小"}
|
||||
label={t("chunkSize")}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -932,7 +948,7 @@ export default function RemoteGuide(props) {
|
|||
className={classes.button}
|
||||
onClick={() => setActiveStep(2)}
|
||||
>
|
||||
上一步
|
||||
{t("back")}
|
||||
</Button>{" "}
|
||||
<Button
|
||||
disabled={loading}
|
||||
|
|
@ -940,7 +956,7 @@ export default function RemoteGuide(props) {
|
|||
variant={"contained"}
|
||||
color={"primary"}
|
||||
>
|
||||
下一步
|
||||
{t("next")}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -952,12 +968,12 @@ export default function RemoteGuide(props) {
|
|||
<div className={classes.stepNumberContainer}></div>
|
||||
<div className={classes.subStepContent}>
|
||||
<Typography variant={"body2"}>
|
||||
最后一步,为此存储策略命名:
|
||||
{t("nameThePolicy")}
|
||||
</Typography>
|
||||
<div className={classes.form}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel htmlFor="component-helper">
|
||||
存储策略名
|
||||
{t("policyName")}
|
||||
</InputLabel>
|
||||
<Input
|
||||
required
|
||||
|
|
@ -974,7 +990,7 @@ export default function RemoteGuide(props) {
|
|||
className={classes.button}
|
||||
onClick={() => setActiveStep(3)}
|
||||
>
|
||||
上一步
|
||||
{t("back")}
|
||||
</Button>{" "}
|
||||
<Button
|
||||
disabled={loading}
|
||||
|
|
@ -982,7 +998,7 @@ export default function RemoteGuide(props) {
|
|||
variant={"contained"}
|
||||
color={"primary"}
|
||||
>
|
||||
完成
|
||||
{t("finish")}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -992,10 +1008,10 @@ export default function RemoteGuide(props) {
|
|||
<>
|
||||
<form className={classes.stepContent}>
|
||||
<Typography>
|
||||
存储策略已{props.policy ? "保存" : "添加"}!
|
||||
{props.policy ? t("policySaved") : t("policyAdded")}
|
||||
</Typography>
|
||||
<Typography variant={"body2"} color={"textSecondary"}>
|
||||
要使用此存储策略,请到用户组管理页面,为相应用户组绑定此存储策略。
|
||||
{t("furtherActions")}
|
||||
</Typography>
|
||||
</form>
|
||||
<div className={classes.stepFooter}>
|
||||
|
|
@ -1004,7 +1020,7 @@ export default function RemoteGuide(props) {
|
|||
className={classes.button}
|
||||
onClick={() => history.push("/admin/policy")}
|
||||
>
|
||||
返回存储策略列表
|
||||
{t("backToList")}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
Loading…
Reference in New Issue