import { lighten, makeStyles } from "@material-ui/core/styles"; import React, { useCallback, useState } from "react"; import Stepper from "@material-ui/core/Stepper"; import StepLabel from "@material-ui/core/StepLabel"; import Step from "@material-ui/core/Step"; import Typography from "@material-ui/core/Typography"; import { useDispatch } from "react-redux"; import Link from "@material-ui/core/Link"; import FormControl from "@material-ui/core/FormControl"; import InputLabel from "@material-ui/core/InputLabel"; import Input from "@material-ui/core/Input"; import RadioGroup from "@material-ui/core/RadioGroup"; import FormControlLabel from "@material-ui/core/FormControlLabel"; import Radio from "@material-ui/core/Radio"; import Collapse from "@material-ui/core/Collapse"; import Button from "@material-ui/core/Button"; import API from "../../../../middleware/Api"; import MagicVar from "../../Dialogs/MagicVar"; import DomainInput from "../../Common/DomainInput"; import SizeInput from "../../Common/SizeInput"; import { useHistory } from "react-router"; import Alert from "@material-ui/lab/Alert"; import { getNumber, randomStr } from "../../../../utils"; import { toggleSnackbar } from "../../../../redux/explorer"; import { Trans, useTranslation } from "react-i18next"; import { transformPolicyRequest } from "../utils"; 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), }, "@global": { code: { color: "rgba(0, 0, 0, 0.87)", display: "inline-block", padding: "2px 6px", fontSize: "14px", fontFamily: ' Consolas, "Liberation Mono", Menlo, Courier, monospace', borderRadius: "2px", backgroundColor: "rgba(255,229,100,0.1)", }, pre: { margin: "24px 0", padding: "12px 18px", overflow: "auto", direction: "ltr", borderRadius: "4px", backgroundColor: "#272c34", color: "#fff", }, }, })); const steps = [ { title: "storageNode", optional: false, }, { title: "storagePathStep", optional: false, }, { title: "sourceLinkStep", optional: false, }, { title: "uploadSettingStep", optional: false, }, { title: "finishStep", optional: false, }, ]; export default function RemoteGuide(props) { const { t } = useTranslation("dashboard", { keyPrefix: "policy" }); const classes = useStyles(); const history = useHistory(); const [activeStep, setActiveStep] = useState(0); const [loading, setLoading] = useState(false); const [skipped] = React.useState(new Set()); const [magicVar, setMagicVar] = useState(""); const [useCDN, setUseCDN] = useState("false"); const [policy, setPolicy] = useState( props.policy ? props.policy : { Type: "remote", Name: "", Server: "https://example.com:5212", SecretKey: randomStr(64), DirNameRule: "uploads/{year}/{month}/{day}", AutoRename: "true", FileNameRule: "{randomkey8}_{originname}", IsOriginLinkEnable: "false", BaseURL: "", IsPrivate: "true", MaxSize: "0", OptionsSerialized: { file_type: "", chunk_size: 25 << 20, }, } ); 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 testSlave = () => { setLoading(true); // 测试路径是否可用 API.post("/admin/policy/test/slave", { server: policy.Server, secret: policy.SecretKey, }) .then(() => { ToggleSnackbar("top", "right", t("communicationOK"), "success"); }) .catch((error) => { ToggleSnackbar("top", "right", error.message, "error"); }) .then(() => { setLoading(false); }); }; const submitPolicy = (e) => { e.preventDefault(); setLoading(true); let policyCopy = { ...policy }; policyCopy.OptionsSerialized = { ...policyCopy.OptionsSerialized }; // 处理存储策略 if (useCDN === "false" || policy.IsOriginLinkEnable === "false") { policyCopy.BaseURL = ""; } // 类型转换 policyCopy = transformPolicyRequest(policyCopy); API.post("/admin/policy", { policy: policyCopy, }) .then(() => { ToggleSnackbar( "top", "right", props.policy ? t("policySaved") : t("policyAdded"), "success" ); setActiveStep(5); }) .catch((error) => { ToggleSnackbar("top", "right", error.message, "error"); }) .then(() => { setLoading(false); }); setLoading(false); }; return (
{props.policy ? t("editRemoteStoragePolicy") : t("addRemoteStoragePolicy")} {steps.map((label, index) => { const stepProps = {}; const labelProps = {}; if (label.optional) { labelProps.optional = ( {t("optional")} ); } if (isStepSkipped(index)) { stepProps.completed = false; } return ( {t(label.title)} ); })} {activeStep === 0 && (
{ e.preventDefault(); setActiveStep(1); }} > {t("remoteDescription")}
1
{t("remoteCopyBinaryDescription")}
2
{t("remoteSecretDescription")}
{t("remoteSecret")}
3
{t("modifyRemoteConfig")}
]} />
                                [System]
                                
Mode = slave
Listen = :5212

[Slave]
Secret = {policy.SecretKey}

[CORS]
AllowOrigins = *
AllowMethods = OPTIONS,GET,POST
AllowHeaders = *
{t("remoteConfigDifference")}
  • , , , ]} />
  • , , ]} />
  • ]} />
4
{t("inputRemoteAddress")}
{t("inputRemoteAddressDes")}
{t("remoteAddress")}
5
{t("testCommunicationDes")}
)} {activeStep === 1 && (
{ e.preventDefault(); setActiveStep(2); }} >
1
setMagicVar("path")} />, ]} />
{t("pathOfFolderToStoreFiles")}
2
{ e.preventDefault(); setMagicVar("file"); }} />, ]} />
} label={t("autoRenameStoredFile")} /> } label={t("keepOriginalFileName")} />
{t("renameRule")}
)} {activeStep === 2 && (
{ e.preventDefault(); setActiveStep(3); }} >
1
{t("enableGettingPermanentSourceLink")}
{t("enableGettingPermanentSourceLinkDes")}
} label={t("allowed")} /> } label={t("forbidden")} />
2
{t("useCDN")}
{t("useCDNDes")}
{ if ( e.target.value === "false" ) { setPolicy({ ...policy, BaseURL: "", }); } setUseCDN(e.target.value); }} row > } label={t("use")} /> } label={t("notUse")} />
3
{t("cdnDomain")}
{" "}
)} {activeStep === 3 && (
{ e.preventDefault(); setActiveStep(4); }} >
1
{t("limitFileSize")}
{ if (e.target.value === "true") { setPolicy({ ...policy, MaxSize: "10485760", }); } else { setPolicy({ ...policy, MaxSize: "0", }); } }} row > } label={t("limit")} /> } label={t("notLimit")} />
2
{t("enterSizeLimit")}
{policy.MaxSize !== "0" ? "3" : "2"}
{t("limitFileExt")}
{ 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 > } label={t("limit")} /> } label={t("notLimit")} />
{policy.MaxSize !== "0" ? "4" : "3"}
{t("enterFileExt")}
{t("extList")}
{getNumber(3, [ policy.MaxSize !== "0", policy.OptionsSerialized.file_type !== "", ])}
{t("chunkSizeLabel")}
{t("chunkSizeDes")}
{" "}
)} {activeStep === 4 && (
{t("nameThePolicy")}
{t("policyName")}
{" "}
)} {activeStep === 5 && ( <>
{props.policy ? t("policySaved") : t("policyAdded")} {t("furtherActions")}
)} setMagicVar("")} /> setMagicVar("")} />
); }