frontend/src/component/Admin/Policy/Guid/COSGuide.js
2020-12-08 19:38:11 +08:00

1179 lines
53 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Button from "@material-ui/core/Button";
import Collapse from "@material-ui/core/Collapse";
import FormControl from "@material-ui/core/FormControl";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Input from "@material-ui/core/Input";
import InputLabel from "@material-ui/core/InputLabel";
import Link from "@material-ui/core/Link";
import MenuItem from "@material-ui/core/MenuItem";
import Radio from "@material-ui/core/Radio";
import RadioGroup from "@material-ui/core/RadioGroup";
import Select from "@material-ui/core/Select";
import Step from "@material-ui/core/Step";
import StepLabel from "@material-ui/core/StepLabel";
import Stepper from "@material-ui/core/Stepper";
import { lighten, makeStyles } from "@material-ui/core/styles";
import Typography from "@material-ui/core/Typography";
import React, { useCallback, useState } from "react";
import { useDispatch } from "react-redux";
import { useHistory } from "react-router";
import { toggleSnackbar } from "../../../../actions";
import API from "../../../../middleware/Api";
import { getNumber } from "../../../../utils";
import DomainInput from "../../Common/DomainInput";
import SizeInput from "../../Common/SizeInput";
import MagicVar from "../../Dialogs/MagicVar";
const useStyles = makeStyles(theme => ({
stepContent: {
padding: "16px 32px 16px 32px"
},
form: {
maxWidth: 400,
marginTop: 20
},
formContainer: {
[theme.breakpoints.up("md")]: {
padding: "0px 24px 0 24px"
}
},
subStepContainer: {
display: "flex",
marginBottom: 20,
padding: 10,
transition: theme.transitions.create("background-color", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
}),
"&:focus-within": {
backgroundColor: theme.palette.background.default
}
},
stepNumber: {
width: 20,
height: 20,
backgroundColor: lighten(theme.palette.secondary.light, 0.2),
color: theme.palette.secondary.contrastText,
textAlign: "center",
borderRadius: " 50%"
},
stepNumberContainer: {
marginRight: 10
},
stepFooter: {
marginTop: 32
},
button: {
marginRight: theme.spacing(1)
},
viewButtonLabel: { textTransform: "none" },
"@global": {
code: {
color: "rgba(0, 0, 0, 0.87)",
display: "inline-block",
padding: "2px 6px",
fontFamily:
' Consolas, "Liberation Mono", Menlo, Courier, monospace',
borderRadius: "2px",
backgroundColor: "rgba(255,229,100,0.1)"
}
}
}));
const steps = [
{
title: "存储空间",
optional: false
},
{
title: "上传路径",
optional: false
},
{
title: "直链设置",
optional: false
},
{
title: "上传限制",
optional: false
},
{
title: "跨域策略",
optional: true
},
{
title: "云函数回调",
optional: true
},
{
title: "完成",
optional: false
}
];
export default function COSGuide(props) {
const classes = useStyles();
const history = useHistory();
const [activeStep, setActiveStep] = useState(0);
const [loading, setLoading] = useState(false);
const [skipped, setSkipped] = React.useState(new Set());
const [magicVar, setMagicVar] = useState("");
const [useCDN, setUseCDN] = useState("false");
const [policy, setPolicy] = useState(
props.policy
? props.policy
: {
Type: "cos",
Name: "",
SecretKey: "",
AccessKey: "",
BaseURL: "",
Server: "",
IsPrivate: "true",
DirNameRule: "uploads/{year}/{month}/{day}",
AutoRename: "true",
FileNameRule: "{randomkey8}_{originname}",
IsOriginLinkEnable: "false",
MaxSize: "0",
OptionsSerialized: {
file_type: ""
}
}
);
const [policyID, setPolicyID] = useState(
props.policy ? props.policy.ID : 0
);
const [region, setRegion] = useState("ap-chengdu");
const handleChange = name => event => {
setPolicy({
...policy,
[name]: event.target.value
});
};
const handleOptionChange = name => event => {
setPolicy({
...policy,
OptionsSerialized: {
...policy.OptionsSerialized,
[name]: event.target.value
}
});
};
const isStepSkipped = step => {
return skipped.has(step);
};
const dispatch = useDispatch();
const ToggleSnackbar = useCallback(
(vertical, horizontal, msg, color) =>
dispatch(toggleSnackbar(vertical, horizontal, msg, color)),
[dispatch]
);
const submitPolicy = e => {
e.preventDefault();
setLoading(true);
const policyCopy = { ...policy };
policyCopy.OptionsSerialized = { ...policyCopy.OptionsSerialized };
if (useCDN === "false") {
policyCopy.BaseURL = policy.Server;
}
// 类型转换
policyCopy.AutoRename = policyCopy.AutoRename === "true";
policyCopy.IsOriginLinkEnable =
policyCopy.IsOriginLinkEnable === "true";
policyCopy.IsPrivate = policyCopy.IsPrivate === "true";
policyCopy.MaxSize = parseInt(policyCopy.MaxSize);
policyCopy.OptionsSerialized.file_type = policyCopy.OptionsSerialized.file_type.split(
","
);
if (
policyCopy.OptionsSerialized.file_type.length === 1 &&
policyCopy.OptionsSerialized.file_type[0] === ""
) {
policyCopy.OptionsSerialized.file_type = [];
}
API.post("/admin/policy", {
policy: policyCopy
})
.then(response => {
ToggleSnackbar(
"top",
"right",
"存储策略已" + (props.policy ? "保存" : "添加"),
"success"
);
setActiveStep(4);
setPolicyID(response.data);
})
.catch(error => {
ToggleSnackbar("top", "right", error.message, "error");
})
.then(() => {
setLoading(false);
});
setLoading(false);
};
const createCORS = () => {
setLoading(true);
API.post("/admin/policy/cors", {
id: policyID
})
.then(() => {
ToggleSnackbar("top", "right", "跨域策略已添加", "success");
setActiveStep(5);
})
.catch(error => {
ToggleSnackbar("top", "right", error.message, "error");
})
.then(() => {
setLoading(false);
});
};
const creatCallback = () => {
setLoading(true);
API.post("/admin/policy/scf", {
id: policyID,
region: region
})
.then(() => {
ToggleSnackbar("top", "right", "回调云函数已添加", "success");
setActiveStep(6);
})
.catch(error => {
ToggleSnackbar("top", "right", error.message, "error");
})
.then(() => {
setLoading(false);
});
};
return (
<div>
<Typography variant={"h6"}>
{props.policy ? "修改" : "添加"} 腾讯云 COS 存储策略
</Typography>
<Stepper activeStep={activeStep}>
{steps.map((label, index) => {
const stepProps = {};
const labelProps = {};
if (label.optional) {
labelProps.optional = (
<Typography variant="caption">可选</Typography>
);
}
if (isStepSkipped(index)) {
stepProps.completed = false;
}
return (
<Step key={label.title} {...stepProps}>
<StepLabel {...labelProps}>{label.title}</StepLabel>
</Step>
);
})}
</Stepper>
{activeStep === 0 && (
<form
className={classes.stepContent}
onSubmit={e => {
e.preventDefault();
setActiveStep(1);
}}
>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>0</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
在使用 腾讯云 COS 储策略前请确保您在 参数设置
- 站点信息 - 站点URL 中填写的
地址与实际相符并且
<strong>能够被外网正常访问</strong>
</Typography>
</div>
</div>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>1</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
前往
<Link
href={
"https://console.cloud.tencent.com/cos5"
}
target={"_blank"}
>
COS 管理控制台
</Link>
创建存储桶
</Typography>
</div>
</div>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>2</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
转到所创建存储桶的基础配置页面
<code>空间名称</code>
</Typography>
<div className={classes.form}>
<FormControl fullWidth>
<InputLabel htmlFor="component-helper">
空间名称
</InputLabel>
<Input
inputProps={{
pattern: "[a-z0-9-]+-[0-9]+",
title:
"空间名格式不正确, 举例ccc-1252109809"
}}
required
value={policy.BucketName}
onChange={handleChange("BucketName")}
/>
</FormControl>
</div>
</div>
</div>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>3</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
在下方选择您创建的空间的访问权限类型推荐选择
<code>私有读写</code>
以获得更高的安全性私有空间无法开启获取直链功能
</Typography>
<div className={classes.form}>
<FormControl required component="fieldset">
<RadioGroup
required
value={policy.IsPrivate}
onChange={handleChange("IsPrivate")}
row
>
<FormControlLabel
value={"true"}
control={
<Radio color={"primary"} />
}
label="私有读写"
/>
<FormControlLabel
value={"false"}
control={
<Radio color={"primary"} />
}
label="公共读私有写"
/>
</RadioGroup>
</FormControl>
</div>
</div>
</div>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>4</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
转到所创建 Bucket 的基础配置填写
<code>基本信息</code> {" "}
<code>访问域名</code>
</Typography>
<div className={classes.form}>
<DomainInput
value={policy.Server}
onChange={handleChange("Server")}
required
label={"访问域名"}
/>
</div>
</div>
</div>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>5</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
是否要使用配套的 腾讯云CDN 加速 COS 访问
</Typography>
<div className={classes.form}>
<FormControl required component="fieldset">
<RadioGroup
required
value={useCDN}
onChange={e => {
setUseCDN(e.target.value);
}}
row
>
<FormControlLabel
value={"true"}
control={
<Radio color={"primary"} />
}
label="使用"
/>
<FormControlLabel
value={"false"}
control={
<Radio color={"primary"} />
}
label="不使用"
/>
</RadioGroup>
</FormControl>
</div>
</div>
</div>
<Collapse in={useCDN === "true"}>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>6</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
前往
<Link
href={
"https://console.cloud.tencent.com/cdn/access/guid"
}
target={"_blank"}
>
腾讯云 CDN 管理控制台
</Link>
创建 CDN 加速域名并设定源站为刚创建的 COS
存储桶在下方填写 CDN
加速域名并选择是否使用 HTTPS
</Typography>
<div className={classes.form}>
<DomainInput
value={policy.BaseURL}
onChange={handleChange("BaseURL")}
required={useCDN === "true"}
label={"CDN 加速域名"}
/>
</div>
</div>
</div>
</Collapse>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>
{getNumber(6, [useCDN === "true"])}
</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
在腾讯云
<Link
href={
"https://console.cloud.tencent.com/cam/capi"
}
target={"_blank"}
>
访问密钥
</Link>
页面获取
一对访问密钥并填写在下方请确保这对密钥拥有
COS SCF 服务的访问权限
</Typography>
<div className={classes.form}>
<FormControl fullWidth>
<InputLabel htmlFor="component-helper">
SecretId
</InputLabel>
<Input
required
inputProps={{
pattern: "\\S+",
title: "不能含有空格"
}}
value={policy.AccessKey}
onChange={handleChange("AccessKey")}
/>
</FormControl>
</div>
<div className={classes.form}>
<FormControl fullWidth>
<InputLabel htmlFor="component-helper">
SecretKey
</InputLabel>
<Input
required
inputProps={{
pattern: "\\S+",
title: "不能含有空格"
}}
value={policy.SecretKey}
onChange={handleChange("SecretKey")}
/>
</FormControl>
</div>
</div>
</div>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>
{getNumber(7, [useCDN === "true"])}
</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
为此存储策略命名
</Typography>
<div className={classes.form}>
<FormControl fullWidth>
<InputLabel htmlFor="component-helper">
存储策略名
</InputLabel>
<Input
required
value={policy.Name}
onChange={handleChange("Name")}
/>
</FormControl>
</div>
</div>
</div>
<div className={classes.stepFooter}>
<Button
disabled={loading}
type={"submit"}
variant={"contained"}
color={"primary"}
>
下一步
</Button>
</div>
</form>
)}
{activeStep === 1 && (
<form
className={classes.stepContental}
onSubmit={e => {
e.preventDefault();
setActiveStep(2);
}}
>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>1</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
请在下方输入文件的存储目录路径可以为绝对路径或相对路径相对于
从机的
Cloudreve路径中可以使用魔法变量文件在上传时会自动替换这些变量为相应值
可用魔法变量可参考{" "}
<Link
color={"secondary"}
onClick={e => {
e.preventDefault();
setMagicVar("path");
}}
>
路径魔法变量列表
</Link>{" "}
</Typography>
<div className={classes.form}>
<FormControl fullWidth>
<InputLabel htmlFor="component-helper">
存储目录
</InputLabel>
<Input
required
value={policy.DirNameRule}
onChange={handleChange("DirNameRule")}
/>
</FormControl>
</div>
</div>
</div>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>2</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
是否需要对存储的物理文件进行重命名此处的重命名不会影响最终呈现给用户的
文件名文件名也可使用魔法变量
可用魔法变量可参考{" "}
<Link
color={"secondary"}
onClick={e => {
e.preventDefault();
setMagicVar("file");
}}
>
文件名魔法变量列表
</Link>{" "}
</Typography>
<div className={classes.form}>
<FormControl required component="fieldset">
<RadioGroup
aria-label="gender"
name="gender1"
value={policy.AutoRename}
onChange={handleChange("AutoRename")}
row
>
<FormControlLabel
value={"true"}
control={
<Radio color={"primary"} />
}
label="开启重命名"
/>
<FormControlLabel
value={"false"}
control={
<Radio color={"primary"} />
}
label="不开启"
/>
</RadioGroup>
</FormControl>
</div>
<Collapse in={policy.AutoRename === "true"}>
<div className={classes.form}>
<FormControl fullWidth>
<InputLabel htmlFor="component-helper">
命名规则
</InputLabel>
<Input
required={
policy.AutoRename === "true"
}
value={policy.FileNameRule}
onChange={handleChange(
"FileNameRule"
)}
/>
</FormControl>
</div>
</Collapse>
</div>
</div>
<div className={classes.stepFooter}>
<Button
color={"default"}
className={classes.button}
onClick={() => setActiveStep(0)}
>
上一步
</Button>
<Button
disabled={loading}
type={"submit"}
variant={"contained"}
color={"primary"}
>
下一步
</Button>
</div>
</form>
)}
{activeStep === 2 && (
<form
className={classes.stepContent}
onSubmit={e => {
e.preventDefault();
setActiveStep(3);
}}
>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>1</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
是否允许获取文件永久直链
<br />
开启后用户可以请求获得能直接访问到文件内容的直链适用于图床应用或自用
</Typography>
<div className={classes.form}>
<FormControl required component="fieldset">
<RadioGroup
required
value={policy.IsOriginLinkEnable}
onChange={e => {
if (
policy.IsPrivate === "true" &&
e.target.value === "true"
) {
ToggleSnackbar(
"top",
"right",
"私有空间无法开启此功能",
"warning"
);
return;
}
handleChange("IsOriginLinkEnable")(
e
);
}}
row
>
<FormControlLabel
value={"true"}
control={
<Radio color={"primary"} />
}
label="允许"
/>
<FormControlLabel
value={"false"}
control={
<Radio color={"primary"} />
}
label="禁止"
/>
</RadioGroup>
</FormControl>
</div>
</div>
</div>
<div className={classes.stepFooter}>
<Button
color={"default"}
className={classes.button}
onClick={() => setActiveStep(1)}
>
上一步
</Button>{" "}
<Button
disabled={loading}
type={"submit"}
variant={"contained"}
color={"primary"}
>
下一步
</Button>
</div>
</form>
)}
{activeStep === 3 && (
<form className={classes.stepContent} onSubmit={submitPolicy}>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>1</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
是否限制上传的单文件大小
</Typography>
<div className={classes.form}>
<FormControl required component="fieldset">
<RadioGroup
required
value={
policy.MaxSize === "0"
? "false"
: "true"
}
onChange={e => {
if (e.target.value === "true") {
setPolicy({
...policy,
MaxSize: "10485760"
});
} else {
setPolicy({
...policy,
MaxSize: "0"
});
}
}}
row
>
<FormControlLabel
value={"true"}
control={
<Radio color={"primary"} />
}
label="限制"
/>
<FormControlLabel
value={"false"}
control={
<Radio color={"primary"} />
}
label="不限制"
/>
</RadioGroup>
</FormControl>
</div>
</div>
</div>
<Collapse in={policy.MaxSize !== "0"}>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>2</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
输入限制
</Typography>
<div className={classes.form}>
<SizeInput
value={policy.MaxSize}
onChange={handleChange("MaxSize")}
min={0}
max={9223372036854775807}
label={"单文件大小限制"}
/>
</div>
</div>
</div>
</Collapse>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>
{policy.MaxSize !== "0" ? "3" : "2"}
</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
是否限制上传文件扩展名
</Typography>
<div className={classes.form}>
<FormControl required component="fieldset">
<RadioGroup
required
value={
policy.OptionsSerialized
.file_type === ""
? "false"
: "true"
}
onChange={e => {
if (e.target.value === "true") {
setPolicy({
...policy,
OptionsSerialized: {
...policy.OptionsSerialized,
file_type:
"jpg,png,mp4,zip,rar"
}
});
} else {
setPolicy({
...policy,
OptionsSerialized: {
...policy.OptionsSerialized,
file_type: ""
}
});
}
}}
row
>
<FormControlLabel
value={"true"}
control={
<Radio color={"primary"} />
}
label="限制"
/>
<FormControlLabel
value={"false"}
control={
<Radio color={"primary"} />
}
label="不限制"
/>
</RadioGroup>
</FormControl>
</div>
</div>
</div>
<Collapse in={policy.OptionsSerialized.file_type !== ""}>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer}>
<div className={classes.stepNumber}>
{policy.MaxSize !== "0" ? "4" : "3"}
</div>
</div>
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
输入允许上传的文件扩展名多个请以半角逗号 ,
隔开
</Typography>
<div className={classes.form}>
<FormControl fullWidth>
<InputLabel htmlFor="component-helper">
扩展名列表
</InputLabel>
<Input
value={
policy.OptionsSerialized
.file_type
}
onChange={handleOptionChange(
"file_type"
)}
/>
</FormControl>
</div>
</div>
</div>
</Collapse>
<div className={classes.stepFooter}>
<Button
color={"default"}
className={classes.button}
onClick={() => setActiveStep(2)}
>
上一步
</Button>{" "}
<Button
disabled={loading}
type={"submit"}
variant={"contained"}
color={"primary"}
>
下一步
</Button>
</div>
</form>
)}
{activeStep === 4 && (
<form className={classes.stepContent}>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer} />
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
COS 存储桶 需要正确配置跨域策略后才能使用 Web
端上传文件Cloudreve
可以帮您自动设置您也可以参考文档步骤手动设置如果您已设置过此
Bucket 的跨域策略此步骤可以跳过
</Typography>
<div className={classes.form}>
<Button
disabled={loading}
color={"secondary"}
variant={"contained"}
className={classes.button}
onClick={() => createCORS()}
classes={{ label: classes.viewButtonLabel }}
>
Cloudreve 帮我设置
</Button>
</div>
</div>
</div>
<div className={classes.stepFooter}>
<Button
color={"default"}
className={classes.button}
onClick={() => {
setActiveStep(
prevActiveStep => prevActiveStep + 1
);
setSkipped(prevSkipped => {
const newSkipped = new Set(
prevSkipped.values()
);
newSkipped.add(activeStep);
return newSkipped;
});
}}
>
跳过
</Button>{" "}
</div>
</form>
)}
{activeStep === 5 && (
<form className={classes.stepContent}>
<div className={classes.subStepContainer}>
<div className={classes.stepNumberContainer} />
<div className={classes.subStepContent}>
<Typography variant={"body2"}>
COS 存储桶 客户端直传需要借助腾讯云的
<Link
href={
"https://console.cloud.tencent.com/scf/index?rid=16"
}
target={"_blank"}
>
云函数
</Link>
产品以确保上传回调可控如果您打算将此存储策略自用或者分配给可信赖用户组此步骤可以跳过
如果是作为公有使用请务必创建回调云函数
<br />
<br />
</Typography>
<Typography variant={"body2"}>
Cloudreve 可以尝试帮你自动创建回调云函数请选择
COS 存储桶 所在地域后继续
创建可能会花费数秒钟请耐心等待创建前请确保您的腾讯云账号已开启云函数服务
</Typography>
<div className={classes.form}>
<FormControl>
<InputLabel htmlFor="component-helper">
存储桶所在地区
</InputLabel>
<Select
value={region}
onChange={e =>
setRegion(e.target.value)
}
required
>
<MenuItem value={"ap-beijing"}>
华北地区(北京)
</MenuItem>
<MenuItem value={"ap-chengdu"}>
西南地区(成都)
</MenuItem>
<MenuItem value={"ap-guangzhou"}>
华南地区(广州)
</MenuItem>
<MenuItem value={"ap-guangzhou-open"}>
华南地区(广州Open)
</MenuItem>
<MenuItem value={"ap-hongkong"}>
港澳台地区(中国香港)
</MenuItem>
<MenuItem value={"ap-mumbai"}>
亚太南部(孟买)
</MenuItem>
<MenuItem value={"ap-shanghai"}>
华东地区(上海)
</MenuItem>
<MenuItem value={"ap-singapore"}>
亚太东南(新加坡)
</MenuItem>
<MenuItem value={"na-siliconvalley"}>
美国西部(硅谷)
</MenuItem>
<MenuItem value={"na-toronto"}>
北美地区(多伦多)
</MenuItem>
</Select>
</FormControl>
</div>
<div className={classes.form}>
<Button
disabled={loading}
color={"secondary"}
variant={"contained"}
className={classes.button}
onClick={() => creatCallback()}
classes={{ label: classes.viewButtonLabel }}
>
Cloudreve 帮我创建
</Button>
</div>
</div>
</div>
<div className={classes.stepFooter}>
<Button
color={"default"}
className={classes.button}
onClick={() => {
setActiveStep(
prevActiveStep => prevActiveStep + 1
);
setSkipped(prevSkipped => {
const newSkipped = new Set(
prevSkipped.values()
);
newSkipped.add(activeStep);
return newSkipped;
});
}}
>
跳过
</Button>{" "}
</div>
</form>
)}
{activeStep === 6 && (
<>
<form className={classes.stepContent}>
<Typography>
存储策略已{props.policy ? "保存" : "添加"}
</Typography>
<Typography variant={"body2"} color={"textSecondary"}>
要使用此存储策略请到用户组管理页面为相应用户组绑定此存储策略
</Typography>
</form>
<div className={classes.stepFooter}>
<Button
color={"primary"}
className={classes.button}
onClick={() => history.push("/admin/policy")}
>
返回存储策略列表
</Button>
</div>
</>
)}
<MagicVar
open={magicVar === "file"}
isFile
onClose={() => setMagicVar("")}
/>
<MagicVar
open={magicVar === "path"}
onClose={() => setMagicVar("")}
/>
</div>
);
}