Feat: login

This commit is contained in:
HFO4 2019-11-23 12:49:02 +08:00
parent fa3e709238
commit 560dc1af89
23 changed files with 2402 additions and 1699 deletions

File diff suppressed because it is too large Load Diff

784
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -22,13 +22,11 @@
"css-loader": "1.0.0",
"dotenv": "6.0.0",
"dotenv-expand": "4.2.0",
"eslint": "5.6.0",
"eslint-config-react-app": "^3.0.8",
"eslint-loader": "2.1.1",
"eslint-plugin-flowtype": "2.50.1",
"eslint-plugin-import": "2.14.0",
"eslint-plugin-jsx-a11y": "6.1.2",
"eslint-plugin-react": "7.11.1",
"file-loader": "2.0.0",
"fs-extra": "7.0.0",
"html-webpack-plugin": "4.0.0-alpha.2",

23
src/.eslintrc.js Normal file
View File

@ -0,0 +1,23 @@
module.exports = {
"env": {
"browser": true,
"es6": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
}
};

View File

@ -1,62 +1,65 @@
import React, { Component } from 'react';
import AuthRoute from "./middleware/AuthRoute"
import Navbar from "./component/Navbar.js"
import AlertBar from "./component/Snackbar"
import LoginForm from "./component/Login/LoginForm"
import { createMuiTheme } from '@material-ui/core/styles';
import { connect,useSelector } from 'react-redux'
import React, { Component, Suspense } from "react";
import AuthRoute from "./middleware/AuthRoute";
import Navbar from "./component/Navbar.js";
import AlertBar from "./component/Snackbar";
import { createMuiTheme } from "@material-ui/core/styles";
import { connect, useSelector } from "react-redux";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useParams,
useRouteMatch
} from "react-router-dom";
BrowserRouter as Router,
Switch,
Route,
Link,
useParams,
useRouteMatch
} from "react-router-dom";
import { CssBaseline, makeStyles, ThemeProvider } from '@material-ui/core';
import { CssBaseline, makeStyles, ThemeProvider } from "@material-ui/core";
const mapStateToProps = state => {
return {
theme: state.siteConfig.theme,
}
const LoginForm = React.lazy(() => import("./component/Login/LoginForm"));
export default function App() {
const themeConfig = useSelector(state => state.siteConfig.theme);
let theme = createMuiTheme(themeConfig);
const useStyles = makeStyles(theme => ({
root: {
display: "flex"
},
content: {
flexGrow: 1,
padding: theme.spacing.unit * 0,
minWidth: 0
},
toolbar: theme.mixins.toolbar
}));
const classes = useStyles();
let { path, url } = useRouteMatch();
return (
<React.Fragment>
<ThemeProvider theme={theme}>
<div className={classes.root} id="container">
<CssBaseline />
<AlertBar />
<Navbar />
<main className={classes.content}>
<div className={classes.toolbar} />
<Switch>
<AuthRoute exact path={path}>
我是私有页面
</AuthRoute>
<AuthRoute path={`${path}Home`}>
我是私有Home页面
</AuthRoute>
<Route path={`${path}Login`}>
<Suspense fallback={<div>Loading...</div>}>
<LoginForm />
</Suspense>
</Route>
</Switch>
</main>
</div>
</ThemeProvider>
</React.Fragment>
);
}
export default function App(){
const themeConfig = useSelector(state => state.siteConfig.theme)
let theme = createMuiTheme(themeConfig);
const useStyles = makeStyles(theme=>({
root: {
display: 'flex',
},
content: {
flexGrow: 1,
padding: theme.spacing.unit * 0,
minWidth: 0,
},
toolbar: theme.mixins.toolbar,
}));
const classes = useStyles();
let { path, url } = useRouteMatch();
return (
<React.Fragment>
<ThemeProvider theme={theme}>
<div className={classes.root} id="container">
<CssBaseline />
<AlertBar/>
<Navbar />
<main className={classes.content}>
<div className={classes.toolbar} />
<Switch>
<AuthRoute exact path={path}>我是私有页面</AuthRoute>
<Route path={`${path}Login`}><LoginForm/></Route>
</Switch>
</main>
</div></ThemeProvider >
</React.Fragment>
);
}

View File

@ -1,9 +1,9 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
it("renders without crashing", () => {
const div = document.createElement("div");
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});

View File

@ -1,214 +1,213 @@
export const navitateTo = path => {
return {
type: 'NAVIGATOR_TO',
path:path,
}
}
type: "NAVIGATOR_TO",
path: path
};
};
export const navitateUp = () => {
return {
type: 'NAVIGATOR_UP',
}
}
type: "NAVIGATOR_UP"
};
};
export const drawerToggleAction = open => {
return {
type: 'DRAWER_TOGGLE',
open:open,
}
}
type: "DRAWER_TOGGLE",
open: open
};
};
export const changeViewMethod = method => {
return {
type: 'CHANGE_VIEW_METHOD',
method:method,
}
}
type: "CHANGE_VIEW_METHOD",
method: method
};
};
export const changeSortMethod = method => {
return {
type: 'CHANGE_SORT_METHOD',
method:method,
}
}
type: "CHANGE_SORT_METHOD",
method: method
};
};
export const updateFileList = list => {
return {
type: 'UPDATE_FILE_LIST',
list:list,
}
}
type: "UPDATE_FILE_LIST",
list: list
};
};
export const changeContextMenu = (type,open) => {
export const changeContextMenu = (type, open) => {
return {
type: 'CHANGE_CONTEXT_MENU',
menuType:type,
open:open,
}
}
type: "CHANGE_CONTEXT_MENU",
menuType: type,
open: open
};
};
export const addSelectedTarget = targets => {
return {
type: 'ADD_SELECTED_TARGET',
targets:targets,
}
}
type: "ADD_SELECTED_TARGET",
targets: targets
};
};
export const setSelectedTarget = targets => {
return {
type: 'SET_SELECTED_TARGET',
targets:targets,
}
}
type: "SET_SELECTED_TARGET",
targets: targets
};
};
export const removeSelectedTarget = id => {
return {
type: 'RMOVE_SELECTED_TARGET',
id:id,
}
}
type: "RMOVE_SELECTED_TARGET",
id: id
};
};
export const setNavigatorLoadingStatus = status => {
return {
type: 'SET_NAVIGATOR_LOADING_STATUE',
status:status,
}
}
type: "SET_NAVIGATOR_LOADING_STATUE",
status: status
};
};
export const setNavigatorError = (status,msg) => {
export const setNavigatorError = (status, msg) => {
return {
type: 'SET_NAVIGATOR_ERROR',
status:status,
msg:msg,
}
}
type: "SET_NAVIGATOR_ERROR",
status: status,
msg: msg
};
};
export const openCreateFolderDialog = () => {
return {
type: 'OPEN_CREATE_FOLDER_DIALOG',
}
}
type: "OPEN_CREATE_FOLDER_DIALOG"
};
};
export const setUserPopover = anchor => {
return {
type: 'SET_USER_POPOVER',
anchor: anchor,
}
}
type: "SET_USER_POPOVER",
anchor: anchor
};
};
export const openRenameDialog = () => {
return {
type: 'OPEN_RENAME_DIALOG',
}
}
type: "OPEN_RENAME_DIALOG"
};
};
export const openResaveDialog = () => {
return {
type: 'OPEN_RESAVE_DIALOG',
}
}
type: "OPEN_RESAVE_DIALOG"
};
};
export const openMoveDialog = () => {
return {
type: 'OPEN_MOVE_DIALOG',
}
}
type: "OPEN_MOVE_DIALOG"
};
};
export const openRemoveDialog = () => {
return {
type: 'OPEN_REMOVE_DIALOG',
}
}
type: "OPEN_REMOVE_DIALOG"
};
};
export const openShareDialog = () => {
return {
type: 'OPEN_SHARE_DIALOG',
}
}
type: "OPEN_SHARE_DIALOG"
};
};
export const openMusicDialog = () => {
return {
type: 'OPEN_MUSIC_DIALOG',
}
}
type: "OPEN_MUSIC_DIALOG"
};
};
export const openRemoteDownloadDialog = ()=>{
export const openRemoteDownloadDialog = () => {
return {
type:'OPEN_REMOTE_DOWNLOAD_DIALOG',
}
}
type: "OPEN_REMOTE_DOWNLOAD_DIALOG"
};
};
export const openTorrentDownloadDialog = ()=>{
export const openTorrentDownloadDialog = () => {
return {
type:'OPEN_TORRENT_DOWNLOAD_DIALOG',
}
}
type: "OPEN_TORRENT_DOWNLOAD_DIALOG"
};
};
export const openGetSourceDialog = ()=>{
export const openGetSourceDialog = () => {
return {
type:'OPEN_GET_SOURCE_DIALOG',
}
}
type: "OPEN_GET_SOURCE_DIALOG"
};
};
export const closeAllModals = () => {
return {
type: 'CLOSE_ALL_MODALS',
}
}
type: "CLOSE_ALL_MODALS"
};
};
export const toggleSnackbar = (vertical,horizontal,msg,color) => {
export const toggleSnackbar = (vertical, horizontal, msg, color) => {
return {
type: 'TOGGLE_SNACKBAR',
vertical:vertical,
horizontal:horizontal,
msg:msg,
color:color,
}
}
type: "TOGGLE_SNACKBAR",
vertical: vertical,
horizontal: horizontal,
msg: msg,
color: color
};
};
export const setModalsLoading = (status) => {
export const setModalsLoading = status => {
return {
type: 'SET_MODALS_LOADING',
status:status,
}
}
type: "SET_MODALS_LOADING",
status: status
};
};
export const refreshFileList = () => {
return {
type: 'REFRESH_FILE_LIST',
}
}
type: "REFRESH_FILE_LIST"
};
};
export const searchMyFile = (keywords) => {
export const searchMyFile = keywords => {
return {
type: 'SEARCH_MY_FILE',
keywords: keywords,
}
}
type: "SEARCH_MY_FILE",
keywords: keywords
};
};
export const showImgPreivew = (first) => {
export const showImgPreivew = first => {
return {
type: 'SHOW_IMG_PREIVEW',
first: first,
}
}
type: "SHOW_IMG_PREIVEW",
first: first
};
};
export const refreshStorage = () => {
return {
type: 'REFRESH_STORAGE',
}
}
type: "REFRESH_STORAGE"
};
};
export const saveFile = () => {
return {
type: 'SAVE_FILE',
}
}
type: "SAVE_FILE"
};
};
export const setSiteConfig = (config) => {
export const setSiteConfig = config => {
return {
type: 'SET_SITE_CONFIG',
config:config,
}
}
type: "SET_SITE_CONFIG",
config: config
};
};

View File

@ -163,7 +163,7 @@ class BuyQuotaCompoment extends Component {
dialog:"success",
});
}
}) .catch((error) =>{
}).catch((error) =>{
this.setState({
loading:false,
});
@ -194,7 +194,7 @@ class BuyQuotaCompoment extends Component {
redeemInfo:response.data.result,
});
}
}) .catch((error) =>{
}).catch((error) =>{
this.setState({
loading:false,
});
@ -245,7 +245,7 @@ class BuyQuotaCompoment extends Component {
this.querryLoop(response.data.id);
}, 3000);
}
}) .catch((error) =>{
}).catch((error) =>{
this.setState({
loading:false,
});

View File

@ -1,17 +1,26 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import ImageIcon from '@material-ui/icons/PhotoSizeSelectActual'
import VideoIcon from '@material-ui/icons/Videocam'
import AudioIcon from '@material-ui/icons/Audiotrack'
import PdfIcon from "@material-ui/icons/PictureAsPdf"
import RefreshIcon from "@material-ui/icons/Refresh"
import DeleteIcon from "@material-ui/icons/Delete"
import FileShowIcon from "@material-ui/icons/InsertDriveFile"
import {FileWordBox,FilePowerpointBox,FileExcelBox,ScriptText,MagnetOn,ZipBox,WindowRestore,Android} from 'mdi-material-ui'
import { toggleSnackbar,}from "../actions/index"
import axios from 'axios'
import {sizeToString} from '../untils/index'
import {mediaType} from "../config"
import React, { Component } from "react";
import { connect } from "react-redux";
import ImageIcon from "@material-ui/icons/PhotoSizeSelectActual";
import VideoIcon from "@material-ui/icons/Videocam";
import AudioIcon from "@material-ui/icons/Audiotrack";
import PdfIcon from "@material-ui/icons/PictureAsPdf";
import RefreshIcon from "@material-ui/icons/Refresh";
import DeleteIcon from "@material-ui/icons/Delete";
import FileShowIcon from "@material-ui/icons/InsertDriveFile";
import {
FileWordBox,
FilePowerpointBox,
FileExcelBox,
ScriptText,
MagnetOn,
ZipBox,
WindowRestore,
Android
} from "mdi-material-ui";
import { toggleSnackbar } from "../actions/index";
import axios from "axios";
import { sizeToString } from "../untils/index";
import { mediaType } from "../config";
import {
withStyles,
@ -20,339 +29,427 @@ import {
CardContent,
Typography,
Button,
IconButton,
} from '@material-ui/core';
IconButton
} from "@material-ui/core";
const styles = theme => ({
card: {
marginTop:"20px",
display: "flex",
justifyContent: "space-between",
marginTop: "20px",
display: "flex",
justifyContent: "space-between"
},
actions: {
display: 'flex',
display: "flex"
},
title:{
marginTop:"20px",
title: {
marginTop: "20px"
},
layout: {
width: 'auto',
marginTop:'30px',
width: "auto",
marginTop: "30px",
marginLeft: theme.spacing(3),
marginRight: theme.spacing(3),
[theme.breakpoints.up(1100 + theme.spacing(3) * 2)]: {
width: 700,
marginLeft: 'auto',
marginRight: 'auto',
},
},
shareTitle:{
maxWidth:"200px",
},
avatarFile:{
backgroundColor: theme.palette.primary.light,
},
avatarFolder:{
backgroundColor: theme.palette.secondary.light,
},
gird:{
marginTop:"30px",
},
iconContainer:{
width:"90px",
height:"90px",
padding: "29px",
marginTop: "6px",
paddingLeft: "35px",
[theme.breakpoints.down("md")]: {
display:"none"
}
},
content:{
width:"100%",
minWidth: 0,
},
contentSide:{
width: 700,
marginLeft: "auto",
marginRight: "auto"
}
},
shareTitle: {
maxWidth: "200px"
},
avatarFile: {
backgroundColor: theme.palette.primary.light
},
avatarFolder: {
backgroundColor: theme.palette.secondary.light
},
gird: {
marginTop: "30px"
},
iconContainer: {
width: "90px",
height: "90px",
padding: "29px",
marginTop: "6px",
paddingLeft: "35px",
[theme.breakpoints.down("md")]: {
display: "none"
}
},
content: {
width: "100%",
minWidth: 0
},
contentSide: {
minWidth: 0,
paddingTop: "24px",
paddingRight: "28px",
[theme.breakpoints.down("md")]: {
display:"none"
display: "none"
}
},
iconImgBig:{
color:"#d32f2f",
fontSize: "30px",
},
iconVideoBig:{
color:"#d50000",
fontSize: "30px",
iconImgBig: {
color: "#d32f2f",
fontSize: "30px"
},
iconAudioBig:{
color:"#651fff",
fontSize: "30px",
iconVideoBig: {
color: "#d50000",
fontSize: "30px"
},
iconPdfBig:{
color:"#f44336",
fontSize: "30px",
iconAudioBig: {
color: "#651fff",
fontSize: "30px"
},
iconWordBig:{
color:"#538ce5",
fontSize: "30px",
iconPdfBig: {
color: "#f44336",
fontSize: "30px"
},
iconPptBig:{
color:"rgb(239, 99, 63)",
fontSize: "30px",
iconWordBig: {
color: "#538ce5",
fontSize: "30px"
},
iconExcelBig:{
color:"#4caf50",
fontSize: "30px",
iconPptBig: {
color: "rgb(239, 99, 63)",
fontSize: "30px"
},
iconTextBig:{
color:"#607d8b",
fontSize: "30px",
iconExcelBig: {
color: "#4caf50",
fontSize: "30px"
},
iconFileBig:{
color:"#424242",
fontSize: "30px",
iconTextBig: {
color: "#607d8b",
fontSize: "30px"
},
iconTorrentBig:{
color:"#5c6bc0",
fontSize: "30px",
iconFileBig: {
color: "#424242",
fontSize: "30px"
},
iconZipBig:{
color:"#f9a825",
fontSize: "30px",
iconTorrentBig: {
color: "#5c6bc0",
fontSize: "30px"
},
iconAndroidBig:{
color:"#8bc34a",
fontSize: "30px",
iconZipBig: {
color: "#f9a825",
fontSize: "30px"
},
iconExeBig:{
color:"#1a237e",
fontSize: "30px",
iconAndroidBig: {
color: "#8bc34a",
fontSize: "30px"
},
hide:{
display:"none",
iconExeBig: {
color: "#1a237e",
fontSize: "30px"
},
loadingAnimation:{
borderRadius: "6px 6px 0 0",
hide: {
display: "none"
},
shareFix:{
marginLeft: "20px",
loadingAnimation: {
borderRadius: "6px 6px 0 0"
},
loadMore:{
textAlign:"center",
marginTop:"20px",
marginBottom:"20px",
shareFix: {
marginLeft: "20px"
},
loadMore: {
textAlign: "center",
marginTop: "20px",
marginBottom: "20px"
}
})
});
const mapStateToProps = state => {
return {
}
}
return {};
};
const mapDispatchToProps = dispatch => {
return {
toggleSnackbar:(vertical,horizontal,msg,color)=>{
dispatch(toggleSnackbar(vertical,horizontal,msg,color))
},
}
}
const getIcon = (classes,name)=>{
let iconBig;
let fileType =name.split(".").pop().toLowerCase();
if (mediaType["image"].indexOf(fileType)!==-1){
iconBig = (<ImageIcon className={classes.iconImgBig}/>);
}else if(mediaType["video"].indexOf(fileType)!==-1){
iconBig = (<VideoIcon className={classes.iconVideoBig}/>);
}else if(mediaType["audio"].indexOf(fileType)!==-1){
iconBig = (<AudioIcon className={classes.iconAudioBig}/>);
}else if(mediaType["pdf"].indexOf(fileType)!==-1){
iconBig = (<PdfIcon className={classes.iconPdfBig}/>);
}else if(mediaType["word"].indexOf(fileType)!==-1){
iconBig = (<FileWordBox className={classes.iconWordBig}/>);
}else if(mediaType["ppt"].indexOf(fileType)!==-1){
iconBig = (<FilePowerpointBox className={classes.iconPptBig}/>);
}else if(mediaType["excel"].indexOf(fileType)!==-1){
iconBig = (<FileExcelBox className={classes.iconExcelBig}/>);
}else if(mediaType["text"].indexOf(fileType)!==-1){
iconBig = (<ScriptText className={classes.iconTextBig}/>);
}else if(mediaType["torrent"].indexOf(fileType)!==-1){
iconBig = (<MagnetOn className={classes.iconTorrentBig}/>);
}else if(mediaType["zip"].indexOf(fileType)!==-1){
iconBig = (<ZipBox className={classes.iconZipBig}/>);
}else if(mediaType["excute"].indexOf(fileType)!==-1){
iconBig = (<WindowRestore className={classes.iconExeBig}/>);
}else if(mediaType["android"].indexOf(fileType)!==-1){
iconBig = (<Android className={classes.iconAndroidBig}/>);
}else{
iconBig = (<FileShowIcon className={classes.iconTextBig}/>);
toggleSnackbar: (vertical, horizontal, msg, color) => {
dispatch(toggleSnackbar(vertical, horizontal, msg, color));
}
return iconBig;
}
};
};
const getIcon = (classes, name) => {
let iconBig;
let fileType = name
.split(".")
.pop()
.toLowerCase();
if (mediaType["image"].indexOf(fileType) !== -1) {
iconBig = <ImageIcon className={classes.iconImgBig} />;
} else if (mediaType["video"].indexOf(fileType) !== -1) {
iconBig = <VideoIcon className={classes.iconVideoBig} />;
} else if (mediaType["audio"].indexOf(fileType) !== -1) {
iconBig = <AudioIcon className={classes.iconAudioBig} />;
} else if (mediaType["pdf"].indexOf(fileType) !== -1) {
iconBig = <PdfIcon className={classes.iconPdfBig} />;
} else if (mediaType["word"].indexOf(fileType) !== -1) {
iconBig = <FileWordBox className={classes.iconWordBig} />;
} else if (mediaType["ppt"].indexOf(fileType) !== -1) {
iconBig = <FilePowerpointBox className={classes.iconPptBig} />;
} else if (mediaType["excel"].indexOf(fileType) !== -1) {
iconBig = <FileExcelBox className={classes.iconExcelBig} />;
} else if (mediaType["text"].indexOf(fileType) !== -1) {
iconBig = <ScriptText className={classes.iconTextBig} />;
} else if (mediaType["torrent"].indexOf(fileType) !== -1) {
iconBig = <MagnetOn className={classes.iconTorrentBig} />;
} else if (mediaType["zip"].indexOf(fileType) !== -1) {
iconBig = <ZipBox className={classes.iconZipBig} />;
} else if (mediaType["excute"].indexOf(fileType) !== -1) {
iconBig = <WindowRestore className={classes.iconExeBig} />;
} else if (mediaType["android"].indexOf(fileType) !== -1) {
iconBig = <Android className={classes.iconAndroidBig} />;
} else {
iconBig = <FileShowIcon className={classes.iconTextBig} />;
}
return iconBig;
};
class DownloadCompoment extends Component {
page = 0;
page=0;
state = {
downloading: [],
loading: false,
finishedList: [],
continue: true
};
state={
downloading:[],
loading:false,
finishedList:[],
continue:true,
}
componentDidMount = ()=>{
componentDidMount = () => {
this.loadDownloading();
}
};
loadDownloading = ()=>{
loadDownloading = () => {
this.setState({
loading:true,
loading: true
});
axios.get('/RemoteDownload/FlushUser').then( (response)=> {
axios.post('/RemoteDownload/ListDownloading').then((response)=> {
this.setState({
downloading:response.data,
loading:false,
axios
.get("/RemoteDownload/FlushUser")
.then(response => {
axios.post("/RemoteDownload/ListDownloading").then(response => {
this.setState({
downloading: response.data,
loading: false
});
});
})
})
.catch((error) =>{
this.props.toggleSnackbar("top","right","加载失败","error");
this.setState({
loading:false,
.catch(error => {
this.props.toggleSnackbar("top", "right", "加载失败", "error");
this.setState({
loading: false
});
});
});
}
};
loadMore = ()=>{
loadMore = () => {
this.setState({
loading:true,
loading: true
});
axios.get('/RemoteDownload/ListFinished?page='+(++this.page)).then( (response)=> {
axios
.get("/RemoteDownload/ListFinished?page=" + ++this.page)
.then(response => {
this.setState({
finishedList:response.data,
loading:false,
continue:response.data.length<10?false:true,
finishedList: response.data,
loading: false,
continue: response.data.length < 10 ? false : true
});
})
.catch(error => {
this.props.toggleSnackbar("top", "right", "加载失败", "error");
this.setState({
loading: false
});
})
.catch((error) =>{
this.props.toggleSnackbar("top","right","加载失败","error");
this.setState({
loading:false,
});
});
}
};
cancelDownload = id=>{
axios.post('/RemoteDownload/Cancel',{
id:id,
}).then( (response)=> {
if(response.data.error!==0){
this.props.toggleSnackbar("top","right",response.message,"error");
}else{
this.setState({
downloading:this.state.downloading.filter(value=>{
return value.id!==id;
})
});
this.props.toggleSnackbar("top","right","取消成功","success");
}
})
.catch((error) =>{
this.props.toggleSnackbar("top","right",error.message,"error");
});
}
cancelDownload = id => {
axios
.post("/RemoteDownload/Cancel", {
id: id
})
.then(response => {
if (response.data.error !== 0) {
this.props.toggleSnackbar(
"top",
"right",
response.message,
"error"
);
} else {
this.setState({
downloading: this.state.downloading.filter(value => {
return value.id !== id;
})
});
this.props.toggleSnackbar(
"top",
"right",
"取消成功",
"success"
);
}
})
.catch(error => {
this.props.toggleSnackbar(
"top",
"right",
error.message,
"error"
);
});
};
render() {
const { classes } = this.props;
return (
<div className={classes.layout}>
<Typography color="textSecondary" variant="h4" className={classes.title}>进行中
<IconButton disabled={this.state.loading} onClick={this.loadDownloading}><RefreshIcon/></IconButton>
<div className={classes.layout}>
<Typography
color="textSecondary"
variant="h4"
className={classes.title}
>
进行中
<IconButton
disabled={this.state.loading}
onClick={this.loadDownloading}
>
<RefreshIcon />
</IconButton>
</Typography>
{this.state.downloading.map(value=>{
value.percent = !value.hasOwnProperty("completedLength")?0:(value.completedLength/value.totalLength)
{this.state.downloading.map(value => {
value.percent = !value.hasOwnProperty("completedLength")
? 0
: value.completedLength / value.totalLength;
return (
<Card className={classes.card} key={value.id}>
<div className={classes.iconContainer}>
{getIcon(classes,value.fileName)}
</div>
<CardContent className={classes.content}>
<Typography color="primary" variant="h6" noWrap>
{value.fileName}
</Typography>
<LinearProgress color="secondary" variant="determinate" value={value.percent*100} />
<Typography variant="subtitle1" color="textSecondary" noWrap >
{value.hasOwnProperty("completedLength")&&
<span>{(value.percent*100).toFixed(2)}% - {value.completedLength==="0"?"0Bytes":sizeToString(value.completedLength)}/{value.totalLength==="0"?"0Bytes":sizeToString(value.totalLength)} - {value.downloadSpeed==="0"?"0B/s":sizeToString(value.downloadSpeed)+"/s"}</span>
}
{!value.hasOwnProperty("completedLength")&&
<span> - </span>
}
</Typography>
</CardContent>
<CardContent className={classes.contentSide} onClick={()=>this.cancelDownload(value.id)}>
<IconButton><DeleteIcon/></IconButton>
</CardContent>
</Card>
)
<Card className={classes.card} key={value.id}>
<div className={classes.iconContainer}>
{getIcon(classes, value.fileName)}
</div>
<CardContent className={classes.content}>
<Typography color="primary" variant="h6" noWrap>
{value.fileName}
</Typography>
<LinearProgress
color="secondary"
variant="determinate"
value={value.percent * 100}
/>
<Typography
variant="subtitle1"
color="textSecondary"
noWrap
>
{value.hasOwnProperty(
"completedLength"
) && (
<span>
{(value.percent * 100).toFixed(2)}%
-{" "}
{value.completedLength === "0"
? "0Bytes"
: sizeToString(
value.completedLength
)}
/
{value.totalLength === "0"
? "0Bytes"
: sizeToString(
value.totalLength
)}{" "}
-{" "}
{value.downloadSpeed === "0"
? "0B/s"
: sizeToString(
value.downloadSpeed
) + "/s"}
</span>
)}
{!value.hasOwnProperty(
"completedLength"
) && <span> - </span>}
</Typography>
</CardContent>
<CardContent
className={classes.contentSide}
onClick={() => this.cancelDownload(value.id)}
>
<IconButton>
<DeleteIcon />
</IconButton>
</CardContent>
</Card>
);
})}
<Typography color="textSecondary" variant="h4" className={classes.title}>已完成</Typography>
<Typography
color="textSecondary"
variant="h4"
className={classes.title}
>
已完成
</Typography>
<div className={classes.loadMore}>
{this.state.finishedList.map(value=>{
{this.state.finishedList.map(value => {
return (
<Card className={classes.card} key={value.id}>
{JSON.stringify(value.fileName) !== "[]" && (
<div className={classes.iconContainer}>
{getIcon(classes, value.fileName)}
</div>
)}
return (
<Card className={classes.card} key={value.id}>
{(JSON.stringify(value.fileName) !== '[]')&&
<div className={classes.iconContainer}>
{getIcon(classes,value.fileName)}
</div>}
<CardContent className={classes.content}>
<Typography color="primary" variant="h6" style={{ textAlign: "left"}} noWrap>
{value.fileName}
</Typography>
<Typography variant="subtitle1" color="textSecondary" noWrap style={{ textAlign: "left"}}>
{(()=>{switch (value.status) {
case "canceled":
return (<div>已取消</div>);
case "error":
return (<div>错误{value.msg}</div>);
case "success":
return (<div>成功</div>);
default:
break;
}
})()}
</Typography>
</CardContent>
</Card>
)
})}
<Button size="large"
className={classes.margin}
disabled={!this.state.continue}
onClick={this.loadMore}
<CardContent className={classes.content}>
<Typography
color="primary"
variant="h6"
style={{ textAlign: "left" }}
noWrap
>
{value.fileName}
</Typography>
<Typography
variant="subtitle1"
color="textSecondary"
noWrap
style={{ textAlign: "left" }}
>
{(() => {
switch (value.status) {
case "canceled":
return <div>已取消</div>;
case "error":
return (
<div>
错误{value.msg}
</div>
);
case "success":
return <div>成功</div>;
default:
break;
}
})()}
</Typography>
</CardContent>
</Card>
);
})}
<Button
size="large"
className={classes.margin}
disabled={!this.state.continue}
onClick={this.loadMore}
>
加载更多
</Button>
</div>
</div>
</div>
);
}
}
const Download = connect(
mapStateToProps,
mapDispatchToProps
)( withStyles(styles)(DownloadCompoment))
)(withStyles(styles)(DownloadCompoment));
export default Download
export default Download;

View File

@ -59,7 +59,7 @@ const styles = theme => ({
class PathSelectorCompoment extends Component {
state={
state = {
presentPath:"/",
dirList:[],
selectedTarget:null,

View File

@ -2,8 +2,10 @@ import React, { Component } from 'react'
import { connect } from 'react-redux'
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';
import { toggleSnackbar, } from "../../actions/index"
import axios from 'axios'
import Placeholder from "../placeholder/captcha"
import {withRouter} from 'react-router-dom'
import API from "../../middleware/Api"
import Auth from "../../middleware/Auth"
import {
withStyles,
Button,
@ -56,10 +58,19 @@ const styles = theme => ({
captchaContainer:{
display:"flex",
marginTop: "10px",
}
},
captchaPlaceholder:{
width:200,
},
})
const mapStateToProps = state => {
return {
loginCaptcha: state.siteConfig.loginCaptcha,
title: state.siteConfig.title,
regCaptcha: state.siteConfig.regCaptcha,
forgetCaptcha: state.siteConfig.forgetCaptcha,
emailActive: state.siteConfig.emailActive,
QQLogin: state.siteConfig.QQLogin,
}
}
@ -78,13 +89,22 @@ class LoginFormCompoment extends Component {
pwd:"",
captcha:"",
loading:false,
captchaUrl:"/captcha?initial",
captchaData:null,
}
refreshCaptcha = ()=>{
this.setState({
captchaUrl:"/captcha?"+Math.random(),
API.get("/Captcha").then((response) =>{
this.setState({
captchaData:response.data,
});
}).catch((error)=> {
this.props.toggleSnackbar("top", "right", "无法加载验证码:" + error.message, "error");
});
}
componentDidMount = ()=>{
this.refreshCaptcha()
}
login = e=>{
@ -92,36 +112,37 @@ class LoginFormCompoment extends Component {
this.setState({
loading:true,
});
axios.post('/Member/Login',{
userMail:this.state.email,
userPass:this.state.pwd,
API.post('/User/Session',{
userName:this.state.email,
Password:this.state.pwd,
captchaCode:this.state.captcha,
}).then( (response)=> {
if(response.data.code!=="200"){
// console.log(response);
// if(response.data.code!=="200"){
// this.setState({
// loading:false,
// });
// if(response.data.message==="tsp"){
// window.location.href="/Member/TwoStep";
// }else{
// this.props.toggleSnackbar("top","right",response.data.message,"warning");
// this.refreshCaptcha();
// }
// }else{
this.setState({
loading:false,
});
if(response.data.message==="tsp"){
window.location.href="/Member/TwoStep";
}else{
this.props.toggleSnackbar("top","right",response.data.message,"warning");
this.refreshCaptcha();
}
}else{
this.setState({
loading:false,
});
window.location.href="/Home";
Auth.authenticate(response.data);
this.props.history.push('/Home')
this.props.toggleSnackbar("top","right","登录成功","success");
}
// }
})
.catch((error) =>{
this.setState({
loading:false,
});
this.props.toggleSnackbar("top","right",error.message,"error");
this.props.toggleSnackbar("top","right",error.message,"warning");
this.refreshCaptcha();
});
}
@ -141,7 +162,7 @@ class LoginFormCompoment extends Component {
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
登录{window.siteInfo.mainTitle}
登录{this.props.title}
</Typography>
<form className={classes.form} onSubmit={this.login}>
<FormControl margin="normal" required fullWidth>
@ -165,7 +186,7 @@ class LoginFormCompoment extends Component {
value={this.state.pwd}
autoComplete />
</FormControl>
{window.captcha==="1"&&
{this.props.loginCaptcha&&
<div className={classes.captchaContainer}>
<FormControl margin="normal" required fullWidth>
<InputLabel htmlFor="captcha">验证码</InputLabel>
@ -178,11 +199,12 @@ class LoginFormCompoment extends Component {
autoComplete />
</FormControl> <div>
<img src={this.state.captchaUrl} alt="captcha" onClick={this.refreshCaptcha}></img>
{this.state.captchaData ===null && <div className={classes.captchaPlaceholder}><Placeholder/></div>}
{this.state.captchaData !==null && <img src={this.state.captchaData} alt="captcha" onClick={this.refreshCaptcha}></img>}
</div>
</div>
}
{window.qqLogin&&
{this.props.QQLogin&&
<div>
<Button
type="submit"
@ -205,7 +227,7 @@ class LoginFormCompoment extends Component {
</Button>
</div>
}
{!window.qqLogin&&
{!this.props.QQLogin&&
<Button
type="submit"
fullWidth
@ -241,6 +263,6 @@ class LoginFormCompoment extends Component {
const LoginForm = connect(
mapStateToProps,
mapDispatchToProps
)(withStyles(styles)(LoginFormCompoment))
)(withStyles(styles)(withRouter(LoginFormCompoment)))
export default LoginForm

View File

@ -1,14 +1,14 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { toggleSnackbar,}from "../actions/index"
import axios from 'axios'
import OpenIcon from '@material-ui/icons/OpenInNew';
import FileIcon from '@material-ui/icons/InsertDriveFile';
import FolderIcon from '@material-ui/icons/Folder';
import LockIcon from '@material-ui/icons/Lock';
import UnlockIcon from '@material-ui/icons/LockOpen';
import EyeIcon from '@material-ui/icons/RemoveRedEye';
import DeleteIcon from '@material-ui/icons/Delete';
import React, { Component } from "react";
import { connect } from "react-redux";
import { toggleSnackbar } from "../actions/index";
import axios from "axios";
import OpenIcon from "@material-ui/icons/OpenInNew";
import FileIcon from "@material-ui/icons/InsertDriveFile";
import FolderIcon from "@material-ui/icons/Folder";
import LockIcon from "@material-ui/icons/Lock";
import UnlockIcon from "@material-ui/icons/LockOpen";
import EyeIcon from "@material-ui/icons/RemoveRedEye";
import DeleteIcon from "@material-ui/icons/Delete";
import {
withStyles,
@ -25,249 +25,327 @@ import {
DialogContent,
DialogTitle,
Button,
TextField,
} from '@material-ui/core';
TextField
} from "@material-ui/core";
const styles = theme => ({
card: {
maxWidth: 400,
margin: "0 auto",
margin: "0 auto"
},
actions: {
display: 'flex',
display: "flex"
},
layout: {
width: 'auto',
marginTop:'50px',
width: "auto",
marginTop: "50px",
marginLeft: theme.spacing(3),
marginRight: theme.spacing(3),
[theme.breakpoints.up(1100 + theme.spacing(3) * 2)]: {
width: 1100,
marginLeft: 'auto',
marginRight: 'auto',
},
},
shareTitle:{
maxWidth:"200px",
},
avatarFile:{
backgroundColor: theme.palette.primary.light,
},
avatarFolder:{
backgroundColor: theme.palette.secondary.light,
},
gird:{
marginTop:"30px",
},
loadMore:{
textAlign:"center",
marginTop:"20px",
marginBottom:"20px",
}
})
const mapStateToProps = state => {
return {
width: 1100,
marginLeft: "auto",
marginRight: "auto"
}
},
shareTitle: {
maxWidth: "200px"
},
avatarFile: {
backgroundColor: theme.palette.primary.light
},
avatarFolder: {
backgroundColor: theme.palette.secondary.light
},
gird: {
marginTop: "30px"
},
loadMore: {
textAlign: "center",
marginTop: "20px",
marginBottom: "20px"
}
}
});
const mapStateToProps = state => {
return {};
};
const mapDispatchToProps = dispatch => {
return {
toggleSnackbar:(vertical,horizontal,msg,color)=>{
dispatch(toggleSnackbar(vertical,horizontal,msg,color))
},
}
}
toggleSnackbar: (vertical, horizontal, msg, color) => {
dispatch(toggleSnackbar(vertical, horizontal, msg, color));
}
};
};
class MyShareCompoment extends Component {
state = {
page: 1,
shareList: [],
showPwd: null
};
state={
page:1,
shareList:[],
showPwd:null,
}
componentDidMount = ()=>{
componentDidMount = () => {
this.loadList(1);
}
};
loadMore = ()=>{
this.loadList(this.state.page+1);
}
loadMore = () => {
this.loadList(this.state.page + 1);
};
showPwd = (pwd)=>{
this.setState({showPwd:pwd});
}
showPwd = pwd => {
this.setState({ showPwd: pwd });
};
handleClose = ()=>{
this.setState({showPwd:null});
}
handleClose = () => {
this.setState({ showPwd: null });
};
removeShare = id=>{
axios.post('/Share/Delete', {
id:id,
}).then( (response)=> {
if(response.data.error!==1){
let oldList = this.state.shareList;
oldList = oldList.filter(value=>{
return value.share_key !== id;
});
this.setState({
shareList:oldList
});
this.props.toggleSnackbar("top","right","分享已取消","success");
}
})
.catch((error) =>{
this.props.toggleSnackbar("top","right","请求失败","error");
});
}
changePermission = id=>{
axios.post('/Share/ChangePromission', {
id:id,
}).then( (response)=> {
if(response.data.error!==1){
let oldList = this.state.shareList;
let shareIndex = oldList.findIndex(value=>{
return value.share_key === id;
});
oldList[shareIndex].type = (oldList[shareIndex].type==="public")?"private":"public";
oldList[shareIndex].share_pwd = response.data.newPwd;
this.setState({
shareList:oldList
});
}
})
.catch((error) =>{
this.props.toggleSnackbar("top","right","请求失败","error");
});
}
loadList= page=>{
axios.post('/Share/ListMyShare', {
page:page,
}).then( (response)=> {
if(response.data.length===0){
this.props.toggleSnackbar("top","right","没有更多了","info");
}
this.setState({
page:page,
shareList:this.state.shareList.concat(response.data),
removeShare = id => {
axios
.post("/Share/Delete", {
id: id
})
})
.catch((error) =>{
this.props.toggleSnackbar("top","right","加载失败","error");
});
}
.then(response => {
if (response.data.error !== 1) {
let oldList = this.state.shareList;
oldList = oldList.filter(value => {
return value.share_key !== id;
});
this.setState({
shareList: oldList
});
this.props.toggleSnackbar(
"top",
"right",
"分享已取消",
"success"
);
}
})
.catch(error => {
this.props.toggleSnackbar("top", "right", "请求失败", "error");
});
};
changePermission = id => {
axios
.post("/Share/ChangePromission", {
id: id
})
.then(response => {
if (response.data.error !== 1) {
let oldList = this.state.shareList;
let shareIndex = oldList.findIndex(value => {
return value.share_key === id;
});
oldList[shareIndex].type =
oldList[shareIndex].type === "public"
? "private"
: "public";
oldList[shareIndex].share_pwd = response.data.newPwd;
this.setState({
shareList: oldList
});
}
})
.catch(error => {
this.props.toggleSnackbar("top", "right", "请求失败", "error");
});
};
loadList = page => {
axios
.post("/Share/ListMyShare", {
page: page
})
.then(response => {
if (response.data.length === 0) {
this.props.toggleSnackbar(
"top",
"right",
"没有更多了",
"info"
);
}
this.setState({
page: page,
shareList: this.state.shareList.concat(response.data)
});
})
.catch(error => {
this.props.toggleSnackbar("top", "right", "加载失败", "error");
});
};
render() {
const { classes } = this.props;
return (
<div className={classes.layout}>
<Typography color="textSecondary" variant="h3">我的分享</Typography>
<div className={classes.layout}>
<Typography color="textSecondary" variant="h3">
{" "}
我的分享{" "}
</Typography>{" "}
<Grid container spacing={24} className={classes.gird}>
{this.state.shareList.map(value=>(
{" "}
{this.state.shareList.map(value => (
<Grid item xs={12} sm={4} key={value.id}>
<Card className={classes.card}>
<CardHeader
style={{paddingBottom: "0px"}}
avatar={
<div>
{value.source_type==="file"&&
<Avatar className={classes.avatarFile}>
<FileIcon/>
</Avatar>
}
{value.source_type==="dir"&&
<Avatar className={classes.avatarFolder}>
<FolderIcon/>
</Avatar>
}
</div>
}
title={<Tooltip placement="top" title={value.fileData}><Typography noWrap className={classes.shareTitle}>{value.fileData}</Typography></Tooltip>}
subheader={value.share_time}
style={{ paddingBottom: "0px" }}
avatar={
<div>
{" "}
{value.source_type === "file" && (
<Avatar
className={
classes.avatarFile
}
>
<FileIcon />
</Avatar>
)}{" "}
{value.source_type === "dir" && (
<Avatar
className={
classes.avatarFolder
}
>
<FolderIcon />
</Avatar>
)}
</div>
}
title={
<Tooltip
placement="top"
title={value.fileData}
>
{" "}
<Typography
noWrap
className={classes.shareTitle}
>
{" "}
{value.fileData}{" "}
</Typography>
</Tooltip>
}
subheader={value.share_time}
/>
<CardActions disableActionSpacing style={{textAlign:"right"}}>
<Tooltip placement="top" title="打开">
<IconButton onClick={()=>window.open("/s/"+value.share_key)}>
<OpenIcon />
</IconButton>
</Tooltip>
{value.type==="private"&&
<div>
<Tooltip placement="top" title="变更为公开分享" onClick={()=>this.changePermission(value.share_key)}>
<IconButton>
<LockIcon />
</IconButton>
</Tooltip>
<Tooltip placement="top" title="查看密码" onClick={()=>this.showPwd(value.share_pwd)}>
<IconButton>
<EyeIcon />
</IconButton>
</Tooltip>
</div>
}
{value.type==="public"&&
<Tooltip placement="top" title="变更为私密分享" onClick={()=>this.changePermission(value.share_key)}>
<IconButton>
<UnlockIcon />
</IconButton>
</Tooltip>
}
<Tooltip placement="top" title="取消分享" onClick={()=>this.removeShare(value.share_key)}>
<CardActions
disableActionSpacing
style={{ textAlign: "right" }}
>
<Tooltip placement="top" title="打开">
<IconButton
onClick={() =>
window.open(
"/s/" + value.share_key
)
}
>
<OpenIcon />
</IconButton>{" "}
</Tooltip>{" "}
{value.type === "private" && (
<div>
<Tooltip
placement="top"
title="变更为公开分享"
onClick={() =>
this.changePermission(
value.share_key
)
}
>
<IconButton>
<LockIcon />
</IconButton>{" "}
</Tooltip>{" "}
<Tooltip
placement="top"
title="查看密码"
onClick={() =>
this.showPwd(
value.share_pwd
)
}
>
<IconButton>
<EyeIcon />
</IconButton>{" "}
</Tooltip>{" "}
</div>
)}{" "}
{value.type === "public" && (
<Tooltip
placement="top"
title="变更为私密分享"
onClick={() =>
this.changePermission(
value.share_key
)
}
>
<IconButton>
<UnlockIcon />
</IconButton>{" "}
</Tooltip>
)}
<Tooltip
placement="top"
title="取消分享"
onClick={() =>
this.removeShare(value.share_key)
}
>
<IconButton>
<DeleteIcon />
</IconButton>
</IconButton>{" "}
</Tooltip>
</CardActions>
</Card>
</CardActions>{" "}
</Card>{" "}
</Grid>
))}
</Grid>
<div className={classes.loadMore}>
<Button size="large"
className={classes.margin}
disabled={this.state.shareList.length<18}
onClick={this.loadMore}
))}{" "}
</Grid>{" "}
<div className={classes.loadMore}>
<Button
size="large"
className={classes.margin}
disabled={this.state.shareList.length < 18}
onClick={this.loadMore}
>
继续加载
</Button>
</div>
继续加载{" "}
</Button>{" "}
</div>{" "}
<Dialog
open={this.state.showPwd!==null}
onClose={this.handleClose}
open={this.state.showPwd !== null}
onClose={this.handleClose}
>
<DialogTitle>分享密码</DialogTitle>
<DialogContent>
<TextField
id="standard-name"
value={this.state.showPwd}
margin="normal"
autoFocus
/>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="default">
关闭
</Button>
</DialogActions>
</Dialog>
</div>
<DialogTitle> 分享密码 </DialogTitle>{" "}
<DialogContent>
<TextField
id="standard-name"
value={this.state.showPwd}
margin="normal"
autoFocus
/>
</DialogContent>{" "}
<DialogActions>
<Button onClick={this.handleClose} color="default">
关闭{" "}
</Button>{" "}
</DialogActions>{" "}
</Dialog>{" "}
</div>
);
}
}
const MyShare = connect(
mapStateToProps,
mapDispatchToProps
)( withStyles(styles)(MyShareCompoment))
)(withStyles(styles)(MyShareCompoment));
export default MyShare
export default MyShare;

View File

@ -1,10 +1,9 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { toggleSnackbar,}from "../actions/index"
import OpenIcon from '@material-ui/icons/OpenInNew';
import FileIcon from '@material-ui/icons/InsertDriveFile';
import FolderIcon from '@material-ui/icons/Folder';
import React, { Component } from "react";
import { connect } from "react-redux";
import { toggleSnackbar } from "../actions/index";
import OpenIcon from "@material-ui/icons/OpenInNew";
import FileIcon from "@material-ui/icons/InsertDriveFile";
import FolderIcon from "@material-ui/icons/Folder";
import {
withStyles,
@ -14,98 +13,121 @@ import {
CardHeader,
Typography,
Grid,
IconButton,
} from '@material-ui/core';
IconButton
} from "@material-ui/core";
const styles = theme => ({
card: {
maxWidth: 400,
margin: "0 auto",
margin: "0 auto"
},
actions: {
display: 'flex',
display: "flex"
},
layout: {
width: 'auto',
marginTop:'50px',
width: "auto",
marginTop: "50px",
marginLeft: theme.spacing(3),
marginRight: theme.spacing(3),
[theme.breakpoints.up(1100 + theme.spacing(3) * 2)]: {
width: 1100,
marginLeft: 'auto',
marginRight: 'auto',
},
},
shareTitle:{
maxWidth:"200px",
},
avatarFile:{
backgroundColor: theme.palette.primary.light,
},
avatarFolder:{
backgroundColor: theme.palette.secondary.light,
},
gird:{
marginTop:"30px",
},
})
const mapStateToProps = state => {
return {
width: 1100,
marginLeft: "auto",
marginRight: "auto"
}
},
shareTitle: {
maxWidth: "200px"
},
avatarFile: {
backgroundColor: theme.palette.primary.light
},
avatarFolder: {
backgroundColor: theme.palette.secondary.light
},
gird: {
marginTop: "30px"
}
}
});
const mapStateToProps = state => {
return {};
};
const mapDispatchToProps = dispatch => {
return {
toggleSnackbar:(vertical,horizontal,msg,color)=>{
dispatch(toggleSnackbar(vertical,horizontal,msg,color))
},
}
}
toggleSnackbar: (vertical, horizontal, msg, color) => {
dispatch(toggleSnackbar(vertical, horizontal, msg, color));
}
};
};
class SearchCompoment extends Component {
state={
shareList:[],
}
state = {
shareList: []
};
render() {
const { classes } = this.props;
return (
<div className={classes.layout}>
<Typography color="textSecondary" variant="h3">搜索结果</Typography>
<div className={classes.layout}>
<Typography color="textSecondary" variant="h3">
搜索结果
</Typography>
<Grid container spacing={24} className={classes.gird}>
{window.list.map(value=>(
{window.list.map(value => (
<Grid item xs={12} sm={4} key={value.id}>
<Card className={classes.card}>
<CardHeader
avatar={
<div>
{value.source_type==="file"&&
<Avatar className={classes.avatarFile}>
<FileIcon/>
</Avatar>
}
{value.source_type==="dir"&&
<Avatar className={classes.avatarFolder}>
<FolderIcon/>
</Avatar>
}
</div>
}
action={<Tooltip placement="top" title="打开">
<IconButton onClick={()=>window.open("/s/"+value.share_key)}>
<OpenIcon />
</IconButton>
</Tooltip>}
title={<Tooltip placement="top" title={value.fileData}><Typography noWrap className={classes.shareTitle}>{value.fileData}</Typography></Tooltip>}
subheader={value.share_time}
avatar={
<div>
{value.source_type === "file" && (
<Avatar
className={
classes.avatarFile
}
>
<FileIcon />
</Avatar>
)}
{value.source_type === "dir" && (
<Avatar
className={
classes.avatarFolder
}
>
<FolderIcon />
</Avatar>
)}
</div>
}
action={
<Tooltip placement="top" title="打开">
<IconButton
onClick={() =>
window.open(
"/s/" + value.share_key
)
}
>
<OpenIcon />
</IconButton>
</Tooltip>
}
title={
<Tooltip
placement="top"
title={value.fileData}
>
<Typography
noWrap
className={classes.shareTitle}
>
{value.fileData}
</Typography>
</Tooltip>
}
subheader={value.share_time}
/>
</Card>
</Grid>
))}
@ -113,12 +135,11 @@ class SearchCompoment extends Component {
</div>
);
}
}
const Search = connect(
mapStateToProps,
mapDispatchToProps
)( withStyles(styles)(SearchCompoment))
)(withStyles(styles)(SearchCompoment));
export default Search
export default Search;

View File

@ -1,50 +1,58 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import UploadIcon from '@material-ui/icons/CloudUpload';
import { Drawer, withStyles, Divider, ListItem, ListItemIcon, ListItemText, List } from '@material-ui/core';
import React, { Component } from "react";
import PropTypes from "prop-types";
import UploadIcon from "@material-ui/icons/CloudUpload";
import {
Drawer,
withStyles,
Divider,
ListItem,
ListItemIcon,
ListItemText,
List
} from "@material-ui/core";
const drawerWidth = 240;
const styles = theme => ({
drawer: {
[theme.breakpoints.up('sm')]: {
[theme.breakpoints.up("sm")]: {
width: drawerWidth,
flexShrink: 0,
},
flexShrink: 0
}
},
drawerPaper: {
width: drawerWidth,
width: drawerWidth
},
toolbar: theme.mixins.toolbar,
toolbar: theme.mixins.toolbar
});
class SideDrawer extends Component {
state = {
mobileOpen: false,
mobileOpen: false
};
handleDrawerToggle = () => {
this.setState(state => ({ mobileOpen: !state.mobileOpen }));
};
upload(){
upload() {
alert("");
}
}
render() {
const { classes } = this.props;
const drawer = (
<div><div className={classes.toolbar} />
<div>
<div className={classes.toolbar} />
<List>
<ListItem button key="上传文d件" onClick={this.upload}>
<ListItemIcon><UploadIcon /></ListItemIcon>
<ListItemIcon>
<UploadIcon />
</ListItemIcon>
<ListItemText primary="上传文d件" />
</ListItem>
</List>
<Divider />
<List>
</List></div>
<List></List>
</div>
);
return (
@ -54,16 +62,16 @@ class SideDrawer extends Component {
container={this.props.container}
variant="temporary"
classes={{
paper: classes.drawerPaper,
paper: classes.drawerPaper
}}
anchor={theme.direction === 'rtl' ? 'right' : 'left'}
anchor={theme.direction === "rtl" ? "right" : "left"}
open={this.state.mobileOpen}
onClose={this.handleDrawerToggle}
classes={{
paper: classes.drawerPaper,
paper: classes.drawerPaper
}}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
keepMounted: true // Better open performance on mobile.
}}
>
{drawer}
@ -72,7 +80,7 @@ class SideDrawer extends Component {
<Hidden xsDown implementation="css">
<Drawer
classes={{
paper: classes.drawerPaper,
paper: classes.drawerPaper
}}
variant="permanent"
open
@ -83,10 +91,9 @@ class SideDrawer extends Component {
</nav>
);
}
}
SideDrawer.propTypes = {
classes: PropTypes.object.isRequired,
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(SideDrawer);
export default withStyles(styles)(SideDrawer);

View File

@ -120,12 +120,12 @@ class UploaderCompoment extends Component {
}
}
componentDidMount() {
const { isScriptLoaded, isScriptLoadSucceed } = this.props
if (isScriptLoaded && isScriptLoadSucceed) {
}
// componentDidMount() {
// // const { isScriptLoaded, isScriptLoadSucceed } = this.props
// // if (isScriptLoaded && isScriptLoadSucceed) {
// // }
}
// }
onError(){

View File

@ -0,0 +1,20 @@
import React from "react"
import ContentLoader from "react-content-loader"
const MyLoader = () => (
<ContentLoader
height={160}
width={400}
speed={2}
primaryColor="#f3f3f3"
secondaryColor="#e4e4e4"
>
<rect x="4" y="4" rx="7" ry="7" width="392" height="116" />
</ContentLoader>
)
function captchaPlacholder (){
return (<MyLoader />)
}
export default captchaPlacholder

View File

@ -16,6 +16,11 @@ serviceWorker.register();
const defaultStatus = InitSiteConfig({
siteConfig:{
title:"Cloudreve",
loginCaptcha: false,
regCaptcha: false,
forgetCaptcha: false,
emailActive: false,
QQLogin: false,
theme:{"palette":{"common":{"black":"#000","white":"#fff"},"background":{"paper":"#fff","default":"#fafafa"},"primary":{"light":"#7986cb","main":"#3f51b5","dark":"#303f9f","contrastText":"#fff"},"secondary":{"light":"#ff4081","main":"#f50057","dark":"#c51162","contrastText":"#fff"},"error":{"light":"#e57373","main":"#f44336","dark":"#d32f2f","contrastText":"#fff"},"text":{"primary":"rgba(0, 0, 0, 0.87)","secondary":"rgba(0, 0, 0, 0.54)","disabled":"rgba(0, 0, 0, 0.38)","hint":"rgba(0, 0, 0, 0.38)"},"explorer":{"filename":"#474849","icon":"#8f8f8f","bgSelected":"#D5DAF0","emptyIcon":"#e8e8e8"}}},
},
navigator:{

View File

@ -1,14 +1,23 @@
import axios from 'axios'
import axios from "axios";
const instance = axios.create({
baseURL: 'http://127.0.0.1:5000/Api/V3'
baseURL: "http://127.0.0.1:5000/Api/V3",
withCredentials: true,
crossDomain: true,
});
instance.interceptors.response.use(function (response) {
response.data = response.data.data
return response;
}, function (error) {
return Promise.reject(error);
});
instance.interceptors.response.use(
function(response) {
response.rawData = response.data;
response.data = response.data.data;
if (response.rawData.code != 0){
throw new Error(response.rawData.msg);
}
return response;
},
function(error) {
return Promise.reject(error);
}
);
export default instance
export default instance;

View File

@ -1,11 +1,11 @@
const fakeAuth = {
isAuthenticated: true,
const Auth = {
isAuthenticated: false,
authenticate(cb) {
fakeAuth.isAuthenticated = true;
setTimeout(cb, 100); // fake async
Auth.isAuthenticated = true;
},
signout(cb) {
fakeAuth.isAuthenticated = false;
setTimeout(cb, 100);
}
};
Auth.isAuthenticated = false;
},
};
export default Auth

View File

@ -1,5 +1,5 @@
import React from "react";
import fakeAuth from "./Auth"
import Auth from "./Auth"
import {
BrowserRouter as Router,
Route,
@ -11,7 +11,7 @@ function AuthRoute({ children, ...rest }) {
<Route
{...rest}
render={({ location }) =>
fakeAuth.isAuthenticated ? (
Auth.isAuthenticated ? (
children
) : (
<Redirect

View File

@ -1,21 +1,20 @@
import {setSiteConfig,toggleSnackbar} from "../actions/index"
import { setSiteConfig, toggleSnackbar } from "../actions/index"
import API from "./Api"
export var InitSiteConfig = (rawStore)=>{
let configCache = localStorage.getItem('siteConfigCache');
if (configCache != null){
export var InitSiteConfig = (rawStore) => {
let configCache = JSON.parse(localStorage.getItem('siteConfigCache'));
if (configCache != null) {
rawStore.siteConfig = configCache
}
return rawStore
}
export async function UpdateSiteConfig(store){
API.get("/Site/Config").then(function (response) {
export async function UpdateSiteConfig(store) {
API.get("/Site/Config").then(function(response) {
let themes = JSON.parse(response.data.themes);
response.data.theme = themes[response.data.defaultTheme]
store.dispatch(setSiteConfig(response.data));
localStorage.setItem('siteConfigCache',response.data);
}).catch(function (error) {
store.dispatch(toggleSnackbar("top","right","无法加载站点配置:"+error.message,"error"));
localStorage.setItem('siteConfigCache', JSON.stringify(response.data));
}).catch(function(error) {
store.dispatch(toggleSnackbar("top", "right", "无法加载站点配置:" + error.message, "error"));
});
}
}

View File

@ -15,7 +15,7 @@ const explorer = (state = [], action) => {
switch (action.type) {
case 'UPDATE_FILE_LIST':
var dirList = action.list.filter(function (x) {
return x .type === "dir";
return x.type === "dir";
});
return Object.assign({}, state, {
fileList: action.list,

View File

@ -166,9 +166,9 @@ const cloudreveApp = (state = [], action) => {
case 'NAVIGATOR_TO':
return doNavigate(action.path,state);
case 'NAVIGATOR_UP':
let pathSplit = state.navigator.path.split("/");
var pathSplit = state.navigator.path.split("/");
pathSplit.pop();
let newPath = pathSplit.length===1?"/":pathSplit.join("/");
var newPath = pathSplit.length===1?"/":pathSplit.join("/");
return doNavigate(newPath,state);
case 'OPEN_CREATE_FOLDER_DIALOG':
return Object.assign({}, state, {