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