Initial commit
This commit is contained in:
		
							
								
								
									
										30
									
								
								.eslintrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								.eslintrc
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "extends": "airbnb",
 | 
				
			||||||
 | 
					    "plugins": [
 | 
				
			||||||
 | 
					        "react"
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "env": {
 | 
				
			||||||
 | 
					        "browser": true,
 | 
				
			||||||
 | 
					        "commonjs": true,
 | 
				
			||||||
 | 
					        "es6": true,
 | 
				
			||||||
 | 
					        "node": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "parserOptions": {
 | 
				
			||||||
 | 
					        "ecmaFeatures": {
 | 
				
			||||||
 | 
					            "jsx": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "sourceType": "module"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "rules": {
 | 
				
			||||||
 | 
					        "no-const-assign": "warn",
 | 
				
			||||||
 | 
					        "no-this-before-super": "warn",
 | 
				
			||||||
 | 
					        "no-undef": "warn",
 | 
				
			||||||
 | 
					        "no-unreachable": "warn",
 | 
				
			||||||
 | 
					        "no-unused-vars": "warn",
 | 
				
			||||||
 | 
					        "constructor-super": "warn",
 | 
				
			||||||
 | 
					        "valid-typeof": "warn",
 | 
				
			||||||
 | 
					        "semi": [2, "always"],
 | 
				
			||||||
 | 
					        "indent": [2,4],
 | 
				
			||||||
 | 
					        "no-path-concat": 0
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					dist
 | 
				
			||||||
 | 
					node_modules
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					.vscode
 | 
				
			||||||
							
								
								
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					The MIT License (MIT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2017 Zijin Xiao
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					THE SOFTWARE.
 | 
				
			||||||
							
								
								
									
										27
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					# private-music-react
 | 
				
			||||||
 | 
					A front-end impl of [Private Cloud Music](https://github.com/BLumia/Private-Cloud-Music) by React and Antd.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Install
 | 
				
			||||||
 | 
					``` bash
 | 
				
			||||||
 | 
					# Clone the repository once
 | 
				
			||||||
 | 
					$ git clone https://github.com/BearKidsTeam/private-music-react
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Go into the repository (rename it as you wish)
 | 
				
			||||||
 | 
					$ cd private-music-react
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Install the dependencies once
 | 
				
			||||||
 | 
					$ npm install
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Usage
 | 
				
			||||||
 | 
					``` bash
 | 
				
			||||||
 | 
					$ npm start
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Build
 | 
				
			||||||
 | 
					``` bash
 | 
				
			||||||
 | 
					$ npm run build
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					The files will be in ```./dist```
 | 
				
			||||||
 | 
					## License
 | 
				
			||||||
 | 
					[MIT](http://opensource.org/licenses/MIT)
 | 
				
			||||||
							
								
								
									
										16
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html lang="en">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					  <meta charset="UTF-8">
 | 
				
			||||||
 | 
					  <title>Demo</title>
 | 
				
			||||||
 | 
					  <link rel="stylesheet" href="index.css" />
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div id="root"></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script src="common.js"></script>
 | 
				
			||||||
 | 
					<script src="index.js"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										14
									
								
								index.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								index.jsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import ReactDOM from 'react-dom';
 | 
				
			||||||
 | 
					import './index.css';
 | 
				
			||||||
 | 
					import Player from './player';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function App() {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <div id="app" style={{ height: '100%' }}>
 | 
				
			||||||
 | 
					        <Player />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ReactDOM.render(<App />, document.getElementById('root'));
 | 
				
			||||||
							
								
								
									
										44
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "private-music-react",
 | 
				
			||||||
 | 
					  "version": "1.0.0",
 | 
				
			||||||
 | 
					  "description": "A front-end impl of Private Cloud Music by React and Antd",
 | 
				
			||||||
 | 
					  "author": "Zijin Xiao <ZijinX@outlook.com>",
 | 
				
			||||||
 | 
					  "repository": "BearKidsTeam/private-music-react",
 | 
				
			||||||
 | 
					  "license": "MIT",
 | 
				
			||||||
 | 
					  "entry": {
 | 
				
			||||||
 | 
					    "index": "./index.jsx"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "antd": "^2.7.1",
 | 
				
			||||||
 | 
					    "axios": "^0.15.3",
 | 
				
			||||||
 | 
					    "react": "^15.1.0",
 | 
				
			||||||
 | 
					    "react-dom": "^15.1.0"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "atool-build": "^0.9.0",
 | 
				
			||||||
 | 
					    "atool-test-mocha": "^0.1.4",
 | 
				
			||||||
 | 
					    "babel-eslint": "^7.0.0",
 | 
				
			||||||
 | 
					    "babel-plugin-import": "^1.0.1",
 | 
				
			||||||
 | 
					    "babel-plugin-transform-runtime": "^6.8.0",
 | 
				
			||||||
 | 
					    "babel-runtime": "^6.9.2",
 | 
				
			||||||
 | 
					    "dora": "0.4.x",
 | 
				
			||||||
 | 
					    "dora-plugin-webpack": "^0.8.1",
 | 
				
			||||||
 | 
					    "eslint": "^3.15.0",
 | 
				
			||||||
 | 
					    "eslint-config-airbnb": "^12.0.0",
 | 
				
			||||||
 | 
					    "eslint-plugin-import": "^2.2.0",
 | 
				
			||||||
 | 
					    "eslint-plugin-jsx-a11y": "^2.2.3",
 | 
				
			||||||
 | 
					    "eslint-plugin-react": "^6.9.0",
 | 
				
			||||||
 | 
					    "expect": "^1.20.1",
 | 
				
			||||||
 | 
					    "pre-commit": "1.x",
 | 
				
			||||||
 | 
					    "redbox-react": "^1.2.6"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "pre-commit": [
 | 
				
			||||||
 | 
					    "lint"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "scripts": {
 | 
				
			||||||
 | 
					    "build": "atool-build",
 | 
				
			||||||
 | 
					    "lint": "eslint --ext .js,.jsx src/",
 | 
				
			||||||
 | 
					    "start": "dora --plugins webpack",
 | 
				
			||||||
 | 
					    "test": "atool-test-mocha ./**/__tests__/*-test.js"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										247
									
								
								player.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								player.jsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,247 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import ReactDOM from 'react-dom';
 | 
				
			||||||
 | 
					import { Row,Col,Button,Checkbox,Layout, Menu, Icon, Table, Slider, Modal, Input } from 'antd';
 | 
				
			||||||
 | 
					import axios from 'axios';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { Header, Content, Footer, Sider } = Layout;
 | 
				
			||||||
 | 
					const SubMenu = Menu.SubMenu;
 | 
				
			||||||
 | 
					const ButtonGroup = Button.Group;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const columns = [{
 | 
				
			||||||
 | 
					    title: 'File Name',
 | 
				
			||||||
 | 
					    dataIndex: 'fileName',
 | 
				
			||||||
 | 
					    key: 'fileName',
 | 
				
			||||||
 | 
					    render: text => <a href="#">{text}</a>,
 | 
				
			||||||
 | 
					}];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function formatTime(t) {
 | 
				
			||||||
 | 
					    const m = Math.floor(t / 60);
 | 
				
			||||||
 | 
					    const s = Math.round(t - Math.floor(t / 60) * 60);
 | 
				
			||||||
 | 
					    if (s < 10) {
 | 
				
			||||||
 | 
					        return m + ":0" + s;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (s === 60) {
 | 
				
			||||||
 | 
					        return (m + 1) + ":00";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        return m + ":" + s;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Player extends React.Component {
 | 
				
			||||||
 | 
					    audio = null;
 | 
				
			||||||
 | 
					    currentFolder = '';
 | 
				
			||||||
 | 
					    pagination = {
 | 
				
			||||||
 | 
					        total: 0,
 | 
				
			||||||
 | 
					        showSizeChanger: true
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    state = {
 | 
				
			||||||
 | 
					        playing:'',
 | 
				
			||||||
 | 
					        loop: false,
 | 
				
			||||||
 | 
					        order: false,
 | 
				
			||||||
 | 
					        playIcon: 'caret-right',
 | 
				
			||||||
 | 
					        percent: 0,
 | 
				
			||||||
 | 
					        curTime: 0,
 | 
				
			||||||
 | 
					        totTime: 0,
 | 
				
			||||||
 | 
					        data: [],
 | 
				
			||||||
 | 
					        fdlist: [],
 | 
				
			||||||
 | 
					        collapsed: false,
 | 
				
			||||||
 | 
					        source: 'http://direct.blumia.cn/hidden',
 | 
				
			||||||
 | 
					        newSource: 'http://direct.blumia.cn/hidden',
 | 
				
			||||||
 | 
					        settingsVisible: false
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    onCollapse = (collapsed) => {
 | 
				
			||||||
 | 
					        this.setState({ collapsed });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    init = () => {
 | 
				
			||||||
 | 
					        this.audio = document.getElementsByTagName('audio')[0];
 | 
				
			||||||
 | 
					        this.fetchPlaylist();
 | 
				
			||||||
 | 
					        this.audio.ontimeupdate = () => {
 | 
				
			||||||
 | 
					            this.setState({curTime: this.audio.currentTime, totTime: this.audio.duration, percent: this.audio.currentTime * 1.0 / this.audio.duration * 100.0});
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        this.audio.onpause = () => {
 | 
				
			||||||
 | 
					            this.setState({playIcon: 'caret-right'});
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.audio.onplay = () => {
 | 
				
			||||||
 | 
					            this.setState({playIcon: 'pause'});
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    fetchPlaylist = () => {
 | 
				
			||||||
 | 
					        axios({method: 'POST', url: this.state.source + '/api.php',data:'do=getplaylist&folder=/', headers:{'Content-Type':'application/x-www-form-urlencoded'}})
 | 
				
			||||||
 | 
					        .then((response) => {
 | 
				
			||||||
 | 
					            this.setState({fdlist: response.data.result.data.subFolderList.map(x => decodeURIComponent(x))});
 | 
				
			||||||
 | 
					        }).catch(() => {});
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    fetchMusic = (folder) => {
 | 
				
			||||||
 | 
					        axios({method: 'POST', url: this.state.source + '/api.php',data:'do=getplaylist&folder=' + folder, headers:{'Content-Type':'application/x-www-form-urlencoded'}})
 | 
				
			||||||
 | 
					        .then((response) => {
 | 
				
			||||||
 | 
					            this.pagination =  {
 | 
				
			||||||
 | 
					                total: response.data.result.data.musicList.length,
 | 
				
			||||||
 | 
					                showSizeChanger: true
 | 
				
			||||||
 | 
					            } 
 | 
				
			||||||
 | 
					            this.setState({data: response.data.result.data.musicList.map(x=> { x.fileName = decodeURIComponent(x.fileName); return x})});
 | 
				
			||||||
 | 
					        }).catch(() => {});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    onMenuClick = ({item, key, keyPath}) => {
 | 
				
			||||||
 | 
					        if (key === 'settings') {
 | 
				
			||||||
 | 
					            this.setState({settingsVisible : true, newRandomKey: Math.random()});
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (key !== 'settings' && this.state.collapsed) {
 | 
				
			||||||
 | 
					            this.setState({collapsed:false});
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.currentFolder = key;
 | 
				
			||||||
 | 
					        this.fetchMusic(key);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    componentDidMount() {
 | 
				
			||||||
 | 
					        this.init();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    playAtIndex = (i) => {
 | 
				
			||||||
 | 
					        const filename = this.state.data[i].fileName;
 | 
				
			||||||
 | 
					        this.audio.pause();
 | 
				
			||||||
 | 
					        this.audio.src = this.state.source + this.currentFolder + '/' + filename;
 | 
				
			||||||
 | 
					        this.audio.load();
 | 
				
			||||||
 | 
					        this.audio.play();
 | 
				
			||||||
 | 
					        this.setState({playing: filename});
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    onRowClick = (record,index) => {
 | 
				
			||||||
 | 
					        this.audio.pause();
 | 
				
			||||||
 | 
					        this.audio.src = this.state.source + this.currentFolder + '/' + record.fileName;
 | 
				
			||||||
 | 
					        this.audio.load();
 | 
				
			||||||
 | 
					        this.audio.play();
 | 
				
			||||||
 | 
					        this.setState({playing: record.fileName});
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    onPlayClick = () => {
 | 
				
			||||||
 | 
					        if(this.state.playIcon === 'pause') {
 | 
				
			||||||
 | 
					            this.audio.pause();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            this.audio.play();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    onPrevClick = () => {
 | 
				
			||||||
 | 
					        const currentIndex = this.state.data.findIndex(x => x.fileName === this.state.playing);
 | 
				
			||||||
 | 
					        if (currentIndex === -1) {
 | 
				
			||||||
 | 
					            this.playAtIndex(0);
 | 
				
			||||||
 | 
					        } else if (currentIndex === 0) {
 | 
				
			||||||
 | 
					            this.playAtIndex(this.state.data.length - 1);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            this.playAtIndex(Number(currentIndex) - 1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    onNextClick = () => {
 | 
				
			||||||
 | 
					        const currentIndex = this.state.data.findIndex(x => x.fileName === this.state.playing);
 | 
				
			||||||
 | 
					        if (currentIndex === -1) {
 | 
				
			||||||
 | 
					            this.playAtIndex(0);
 | 
				
			||||||
 | 
					        } else if (currentIndex === (this.state.data.length - 1)) {
 | 
				
			||||||
 | 
					            this.playAtIndex(0);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            this.playAtIndex(Number(currentIndex) + 1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    onLoopChange = (value) => {
 | 
				
			||||||
 | 
					        if (value.target.checked) {
 | 
				
			||||||
 | 
					            this.audio.loop = true;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            this.audio.loop = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    onOrderChange = (value) => {
 | 
				
			||||||
 | 
					        if (value.target.checked) {
 | 
				
			||||||
 | 
					            this.audio.onended = () => {
 | 
				
			||||||
 | 
					                if (this.audio.loop === 0) {
 | 
				
			||||||
 | 
					                    this.onNextClick();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            this.audio.onended = undefined;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    onSettingsOk = () => {
 | 
				
			||||||
 | 
					        this.setState({source: this.state.newSource,settingsVisible:false});
 | 
				
			||||||
 | 
					        this.init();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    onSettingsCancel = () => {
 | 
				
			||||||
 | 
					        this.setState({settingsVisible: false,newSource: this.state.source});
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    onChange = (event) => {
 | 
				
			||||||
 | 
					        this.setState({newSource: event.target.value});
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    onProgressChange = (value) => {
 | 
				
			||||||
 | 
					        this.audio.currentTime = value;
 | 
				
			||||||
 | 
					        this.setState({percent: value * 1.0 / this.state.totTime,curTime: value});
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    onAfterChange = (value) => {
 | 
				
			||||||
 | 
					        this.audio.currentTime = value;
 | 
				
			||||||
 | 
					        this.setState({percent: value * 1.0 / this.state.totTime,curTime: value});
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    render() {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <div style={{ height: '100%' }}>
 | 
				
			||||||
 | 
					                <audio></audio>
 | 
				
			||||||
 | 
					                <Layout style={{ height: '100%' }}>
 | 
				
			||||||
 | 
					                    <Layout style={{ height: '100%' }}>
 | 
				
			||||||
 | 
					                        <Sider collapsible collapsed={this.state.collapsed} onCollapse={this.onCollapse} style={{ height: '100%' }}>
 | 
				
			||||||
 | 
					                            <Menu theme="dark" mode="inline" openKeys={['sub1']} selectedKeys={this.state.collapsed ? [] : [this.currentFolder]} style={{ height: '100%' }} onClick={this.onMenuClick}>
 | 
				
			||||||
 | 
					                                { !this.state.collapsed  && 
 | 
				
			||||||
 | 
					                                    <SubMenu key="sub1" title={<span><Icon type="folder" /><span>Folder List</span></span>}>
 | 
				
			||||||
 | 
					                                        {this.state.fdlist.map(x => <Menu.Item key={x}>{x}</Menu.Item>)}
 | 
				
			||||||
 | 
					                                    </SubMenu>
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                                { this.state.collapsed &&
 | 
				
			||||||
 | 
					                                    <Menu.Item key="1">
 | 
				
			||||||
 | 
					                                        <Icon type="folder"/>
 | 
				
			||||||
 | 
					                                    </Menu.Item>
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                                <Menu.Item key="settings">
 | 
				
			||||||
 | 
					                                    <Icon type="setting" /> { !this.state.collapsed && 'Settings' }
 | 
				
			||||||
 | 
					                                </Menu.Item>
 | 
				
			||||||
 | 
					                            </Menu>
 | 
				
			||||||
 | 
					                        </Sider>
 | 
				
			||||||
 | 
					                        <Layout style={{ background: '#fff' }}>
 | 
				
			||||||
 | 
					                            <Content style={{ margin: '0px' }}>
 | 
				
			||||||
 | 
					                                <Table dataSource={this.state.data} columns={columns} style={{ background: '#fff' }} showHeader={false} pagination={this.pagination} onRowClick = {this.onRowClick}/>
 | 
				
			||||||
 | 
					                            </Content>
 | 
				
			||||||
 | 
					                        </Layout>
 | 
				
			||||||
 | 
					                    </Layout>
 | 
				
			||||||
 | 
					                    <Footer style={{ textAlign: 'center', background: '#494949', paddingLeft:0, paddingRight:0 }}>
 | 
				
			||||||
 | 
					                        <Layout style={{background: '#494949'}}>
 | 
				
			||||||
 | 
					                            <Sider style={{background: '#494949', color:'#fff'}}>
 | 
				
			||||||
 | 
					                                <Row type="flex" justify="space-around" align="middle" style={{height: '100%'}}>
 | 
				
			||||||
 | 
					                                    <Col span={24}>
 | 
				
			||||||
 | 
					                                        {this.state.playing}
 | 
				
			||||||
 | 
					                                    </Col>
 | 
				
			||||||
 | 
					                                </Row>
 | 
				
			||||||
 | 
					                            </Sider>
 | 
				
			||||||
 | 
					                            <Content style={{paddingLeft:0,paddingRight:0}}>
 | 
				
			||||||
 | 
					                                <Row type="flex" justify="space-around" align="middle">
 | 
				
			||||||
 | 
					                                    <Col style={{ width:30, color:'#fff' }}> {formatTime(this.state.curTime)} </Col>
 | 
				
			||||||
 | 
					                                    <Col style={{ width:'calc(100% - 340px)', padding:5 }}>
 | 
				
			||||||
 | 
					                                        <Slider value={this.state.curTime} min={0} max={this.state.totTime} step={1} onChange={this.onProgressChange} tipFormatter={formatTime} style={{ borderTop:'4px solid #494949', borderBottom:'4px solid #494949' }} />
 | 
				
			||||||
 | 
					                                    </Col>
 | 
				
			||||||
 | 
					                                    <Col style={{width:30, color:'#fff'}}> {formatTime(this.state.totTime)} </Col>
 | 
				
			||||||
 | 
					                                    <Col style={{overflowY:'hidden', width:280, display:'block'}}>
 | 
				
			||||||
 | 
					                                        <ButtonGroup>
 | 
				
			||||||
 | 
					                                            <Button type="primary" size='large' icon="step-backward" onClick={this.onPrevClick}/>
 | 
				
			||||||
 | 
					                                            <Button type="primary" size='large' icon={this.state.playIcon} onClick={this.onPlayClick} />
 | 
				
			||||||
 | 
					                                            <Button type="primary" size='large' icon="step-forward" onClick={this.onNextClick}/>
 | 
				
			||||||
 | 
					                                        </ButtonGroup>
 | 
				
			||||||
 | 
					                                            
 | 
				
			||||||
 | 
					                                        <Checkbox style={{ color:'#fff' }} onChange={this.onLoopChange}>Loop</Checkbox>
 | 
				
			||||||
 | 
					                                        <Checkbox style={{ color:'#fff' }} onChange={this.onOrderChange}>Order</Checkbox>
 | 
				
			||||||
 | 
					                                    </Col>
 | 
				
			||||||
 | 
					                                </Row>
 | 
				
			||||||
 | 
					                            </Content>
 | 
				
			||||||
 | 
					                        </Layout>
 | 
				
			||||||
 | 
					                    </Footer>
 | 
				
			||||||
 | 
					                </Layout>
 | 
				
			||||||
 | 
					                <Modal title="Settings" key={this.state.newRandomKey} visible={this.state.settingsVisible}
 | 
				
			||||||
 | 
					                    onOk={this.onSettingsOk} onCancel={this.onSettingsCancel}>
 | 
				
			||||||
 | 
					                    <Input addonBefore={'PCM Source'} defaultValue={this.state.source} value={this.state.newSource} onChange={this.onChange} />
 | 
				
			||||||
 | 
					                </Modal>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Player;
 | 
				
			||||||
							
								
								
									
										12
									
								
								webpack.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								webpack.config.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					// Learn more on how to config.
 | 
				
			||||||
 | 
					// - https://github.com/ant-tool/atool-build#配置扩展
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = function (webpackConfig) {
 | 
				
			||||||
 | 
					    webpackConfig.babel.plugins.push('transform-runtime');
 | 
				
			||||||
 | 
					    webpackConfig.babel.plugins.push(['import', {
 | 
				
			||||||
 | 
					        libraryName: 'antd',
 | 
				
			||||||
 | 
					        style: 'css',
 | 
				
			||||||
 | 
					    }]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return webpackConfig;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
		Reference in New Issue
	
	Block a user