mirror of
https://github.com/cloudreve/frontend.git
synced 2025-12-25 19:52:48 +00:00
Feat:quota page
This commit is contained in:
parent
a341a4558b
commit
d2d0e5ed4b
|
|
@ -101,6 +101,7 @@ module.exports = {
|
|||
search:'./src/pages/search.js',
|
||||
download:'./src/pages/download.js',
|
||||
login:'./src/pages/login.js',
|
||||
quota:'./src/pages/quota.js',
|
||||
// We include the app code last so that if there is a runtime error during
|
||||
// initialization, it doesn't blow up the WebpackDevServer client, and
|
||||
// changing JS code would still trigger a refresh.
|
||||
|
|
@ -405,6 +406,12 @@ module.exports = {
|
|||
filename:"download.html",
|
||||
template: './public/home/download.html',
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
chunks:['quota'],
|
||||
filename:"quota.html",
|
||||
template: './public/home/quota.html',
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
chunks:['login'],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-cn">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="{$options.themeColor}" />
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<title>离线下载管理- {$options.siteName}</title>
|
||||
<script type="text/javascript">
|
||||
colorTheme = {:json_encode($options["themeConfig"])};
|
||||
isHomePage = false;
|
||||
isSharePage = false;
|
||||
pageId="shareLock";
|
||||
userInfo = {
|
||||
uid: {$userInfo.uid},
|
||||
nick: "{$userInfo.userNick}",
|
||||
email: "{$userInfo.userMail}",
|
||||
group: "{$userInfo.groupData.group_name}",
|
||||
groupId: {$userInfo.groupData.id},
|
||||
groupColor: "{$userInfo.groupData.color}",
|
||||
};
|
||||
siteInfo = {
|
||||
mainTitle: "离线下载",
|
||||
};
|
||||
uploadConfig = {
|
||||
allowSource: false,
|
||||
allowShare: false,
|
||||
allowRemoteDownload: "0",
|
||||
allowTorrentDownload: "0",
|
||||
};
|
||||
isMobile = window.innerWidth < 600;
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -14,6 +14,7 @@ import AddIcon from '@material-ui/icons/Add';
|
|||
import DocIcon from '@material-ui/icons/FileCopy';
|
||||
import ShareIcon from '@material-ui/icons/Share';
|
||||
import BackIcon from '@material-ui/icons/ArrowBack';
|
||||
import SdStorage from '@material-ui/icons/SdStorage';
|
||||
import OpenIcon from '@material-ui/icons/OpenInNew'
|
||||
import DownloadIcon from '@material-ui/icons/CloudDownload'
|
||||
import OpenFolderIcon from '@material-ui/icons/FolderOpen'
|
||||
|
|
@ -436,6 +437,12 @@ class NavbarCompoment extends Component {
|
|||
</ListItemIcon>
|
||||
<ListItemText inset primary="离线下载" />
|
||||
</ListItem>
|
||||
<ListItem button key="容量配额" onClick={()=>window.location.href="/Home/Quota"}>
|
||||
<ListItemIcon>
|
||||
<SdStorage className={classes.iconFix} />
|
||||
</ListItemIcon>
|
||||
<ListItemText inset primary="容量配额" />
|
||||
</ListItem>
|
||||
{!window.isSharePage&&
|
||||
<div>
|
||||
<StorageBar></StorageBar>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,246 @@
|
|||
import React, { Component } from 'react'
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import { connect } from 'react-redux'
|
||||
import classNames from 'classnames';
|
||||
import { toggleSnackbar, } from "../actions/index"
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import Table from '@material-ui/core/Table';
|
||||
import TableBody from '@material-ui/core/TableBody';
|
||||
import TableCell from '@material-ui/core/TableCell';
|
||||
import TableHead from '@material-ui/core/TableHead';
|
||||
import TableRow from '@material-ui/core/TableRow';
|
||||
import axios from 'axios'
|
||||
|
||||
|
||||
const styles = theme => ({
|
||||
layout: {
|
||||
width: 'auto',
|
||||
marginTop: '50px',
|
||||
marginLeft: theme.spacing.unit * 3,
|
||||
marginRight: theme.spacing.unit * 3,
|
||||
[theme.breakpoints.up(1100 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 1100,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
},
|
||||
},
|
||||
|
||||
gird: {
|
||||
marginTop: "30px",
|
||||
},
|
||||
paper: {
|
||||
padding: theme.spacing.unit * 2,
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
data: {
|
||||
fontSize: "25px",
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
proBar:{
|
||||
height: "10px",
|
||||
},
|
||||
r1:{
|
||||
backgroundColor:"#f0ad4e",
|
||||
transition:"width .6s ease",
|
||||
height: "100%",
|
||||
fontSize: "12px",
|
||||
lineHeight: "20px",
|
||||
float: "left",
|
||||
},
|
||||
r2:{
|
||||
backgroundColor:"#4caf50",
|
||||
transition:"width .6s ease",
|
||||
height: "100%",
|
||||
fontSize: "12px",
|
||||
lineHeight: "20px",
|
||||
float: "left",
|
||||
},
|
||||
r3:{
|
||||
backgroundColor:"#5bc0de",
|
||||
transition:"width .6s ease",
|
||||
height: "100%",
|
||||
fontSize: "12px",
|
||||
lineHeight: "20px",
|
||||
float: "left",
|
||||
},
|
||||
note_block:{
|
||||
width: "10px",
|
||||
height: "10px",
|
||||
display: "inline-block",
|
||||
position: "relative",
|
||||
marginLeft: "10px",
|
||||
marginRight: "3px",
|
||||
},
|
||||
r1_block:{
|
||||
backgroundColor:"#f0ad4e",
|
||||
},
|
||||
r2_block:{
|
||||
backgroundColor:"#4caf50",
|
||||
},
|
||||
r3_block:{
|
||||
backgroundColor:"#5bc0de",
|
||||
},
|
||||
title:{
|
||||
marginTop: "30px",
|
||||
marginBottom: "30px",
|
||||
},
|
||||
button: {
|
||||
margin: theme.spacing.unit,
|
||||
},
|
||||
table:{
|
||||
overflowX:"auto",
|
||||
},
|
||||
})
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
toggleSnackbar: (vertical, horizontal, msg, color) => {
|
||||
dispatch(toggleSnackbar(vertical, horizontal, msg, color))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
class QuotaCompoment extends Component {
|
||||
|
||||
state = {
|
||||
data: {
|
||||
basic: "--",
|
||||
used: "--",
|
||||
total: "--",
|
||||
pack: "--",
|
||||
r1:0,
|
||||
r2:0,
|
||||
r3:0,
|
||||
},
|
||||
};
|
||||
|
||||
firstLoad = true;
|
||||
|
||||
componentDidMount(){
|
||||
if(this.firstLoad){
|
||||
this.firstLoad = !this.firstLoad;
|
||||
axios.get("/Member/Memory")
|
||||
.then( (response)=> {
|
||||
this.setState({
|
||||
data:{
|
||||
used:response.data.used,
|
||||
pack:response.data.pack,
|
||||
total:response.data.total,
|
||||
basic:response.data.basic,
|
||||
r1:response.data.r1,
|
||||
r2:response.data.r2,
|
||||
r3:response.data.r3,
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
.catch((error) =>{
|
||||
this.setState({
|
||||
loading:false,
|
||||
});
|
||||
this.props.toggleSnackbar("top","right",error.message ,"error");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
|
||||
|
||||
return (
|
||||
<div className={classes.layout}>
|
||||
<Typography color="textSecondary" variant="h3">容量配额</Typography>
|
||||
<Grid container className={classes.gird} spacing={24}>
|
||||
<Grid item xs={12} sm={3}>
|
||||
<Paper className={classes.paper}>
|
||||
<Typography className={classes.data}>{this.state.data.basic}</Typography>
|
||||
<Typography>用户组基础容量</Typography>
|
||||
</Paper>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={3}>
|
||||
<Paper className={classes.paper}>
|
||||
<Typography className={classes.data}>{this.state.data.pack}</Typography>
|
||||
<Typography>有效容量包附加附加容量</Typography>
|
||||
</Paper>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={3}>
|
||||
<Paper className={classes.paper}>
|
||||
<Typography className={classes.data}>{this.state.data.used}</Typography>
|
||||
<Typography>已使用容量</Typography>
|
||||
</Paper>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={3}>
|
||||
<Paper className={classes.paper}>
|
||||
<Typography className={classes.data}>{this.state.data.total}</Typography>
|
||||
<Typography>总容量</Typography>
|
||||
</Paper>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Paper className={classes.paper}>
|
||||
<div className={classes.proBar}>
|
||||
<div className={classes.r1} style={{"width":this.state.data.r1+"%"}}></div>
|
||||
<div className={classes.r2} style={{"width":this.state.data.r2+"%"}}></div>
|
||||
<div className={classes.r3} style={{"width":this.state.data.r3+"%"}}></div>
|
||||
</div>
|
||||
<div style={{textAlign:"right"}} >
|
||||
<span className={classNames(classes.r1_block,classes.note_block)}></span>已用容量
|
||||
<span className={classNames(classes.r2_block,classes.note_block)}></span>用户组基础容量
|
||||
<span className={classNames(classes.r3_block,classes.note_block)}></span>有效容量包附加附加容量
|
||||
</div>
|
||||
</Paper>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Typography color="textSecondary" variant="h3" className={classes.title}>可用容量包</Typography>
|
||||
<Paper className={classes.paper}>
|
||||
<Button variant="contained" color="secondary" className={classes.button}>
|
||||
购买容量包
|
||||
</Button>
|
||||
<Button variant="contained" className={classes.button}>
|
||||
使用激活码兑换
|
||||
</Button>
|
||||
<div className={classes.table}>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell align="left">容量包名称</TableCell>
|
||||
<TableCell align="center">大小</TableCell>
|
||||
<TableCell align="center">激活日期</TableCell>
|
||||
<TableCell align="center">有效期</TableCell>
|
||||
<TableCell align="center">过期日期</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{window.list.map(row => (
|
||||
<TableRow key={row.id}>
|
||||
<TableCell component="th" scope="row">
|
||||
{row.p_name}
|
||||
</TableCell>
|
||||
<TableCell align="center">{row.pack_size}</TableCell>
|
||||
<TableCell align="center">{row.act_time}</TableCell>
|
||||
<TableCell align="center">{row.active_time}天</TableCell>
|
||||
<TableCell align="center">{row.dlay_time}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const Quota = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(withStyles(styles)(QuotaCompoment))
|
||||
|
||||
export default Quota
|
||||
|
|
@ -57,7 +57,7 @@ const styles = theme => ({
|
|||
bottom: "0px",
|
||||
position: "absolute",
|
||||
backgroundColor:theme.palette.background.paper,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
class StorageBarCompoment extends Component {
|
||||
|
|
@ -72,8 +72,8 @@ class StorageBarCompoment extends Component {
|
|||
|
||||
componentDidMount = ()=>{
|
||||
if(this.firstLoad){
|
||||
this.updateStatus();
|
||||
this.firstLoad = !this.firstLoad;
|
||||
this.updateStatus();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import CssBaseline from '@material-ui/core/CssBaseline';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import Navbar from "../component/Navbar.js"
|
||||
import AlertBar from "../component/Snackbar"
|
||||
import Quota from "../component/Quota"
|
||||
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
|
||||
|
||||
const theme = createMuiTheme(window.colorTheme);
|
||||
const styles = theme => ({
|
||||
|
||||
root: {
|
||||
display: 'flex',
|
||||
},
|
||||
content: {
|
||||
flexGrow: 1,
|
||||
padding: theme.spacing.unit * 0,
|
||||
minWidth: 0,
|
||||
},
|
||||
toolbar: theme.mixins.toolbar,
|
||||
});
|
||||
|
||||
class QuatoApp extends Component {
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<MuiThemeProvider theme={theme}>
|
||||
<div className={classes.root} id="container">
|
||||
<CssBaseline />
|
||||
<AlertBar/>
|
||||
<Navbar />
|
||||
<main className={classes.content}>
|
||||
<div className={classes.toolbar} />
|
||||
<Quota/>
|
||||
</main>
|
||||
</div></MuiThemeProvider>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
QuatoApp.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default withStyles(styles)(QuatoApp);
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import { Provider } from 'react-redux'
|
||||
import { createStore } from 'redux'
|
||||
import QuotaApp from "./quota.app"
|
||||
import cloureveApp from '../reducers'
|
||||
|
||||
const defaultStatus = {
|
||||
navigator:{
|
||||
path:window.path,
|
||||
refresh:true,
|
||||
},
|
||||
viewUpdate:{
|
||||
open:window.isHomePage,
|
||||
explorerViewMethod: "icon",
|
||||
sortMethod:"timePos",
|
||||
contextType:"none",
|
||||
menuOpen:false,
|
||||
navigatorLoading:true,
|
||||
navigatorError:false,
|
||||
navigatorErrorMsg:null,
|
||||
modalsLoading:false,
|
||||
storageRefresh:false,
|
||||
modals:{
|
||||
createNewFolder:false,
|
||||
rename:false,
|
||||
move:false,
|
||||
remove:false,
|
||||
share:false,
|
||||
music:false,
|
||||
remoteDownload:false,
|
||||
torrentDownload:false,
|
||||
},
|
||||
snackbar:{
|
||||
toggle:false,
|
||||
vertical:"top",
|
||||
horizontal:"center",
|
||||
msg:"",
|
||||
color:"",
|
||||
}
|
||||
},
|
||||
explorer:{
|
||||
fileList:[],
|
||||
dirList:[
|
||||
],
|
||||
selected:[],
|
||||
selectProps:{
|
||||
isMultiple:false,
|
||||
withFolder:false,
|
||||
withFile:false,
|
||||
},
|
||||
imgPreview:{
|
||||
first:null,
|
||||
other:[],
|
||||
},
|
||||
keywords:null,
|
||||
}
|
||||
};
|
||||
|
||||
let store = createStore(cloureveApp,defaultStatus)
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<QuotaApp/>
|
||||
</Provider>
|
||||
, document.getElementById('root'));
|
||||
Loading…
Reference in New Issue