diff --git a/.gitignore b/.gitignore index d944170..b678901 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ npm-debug.log.* package-lock.json sftp-config.json build +yarn-error.* +tslint.json diff --git a/README.md b/README.md index 440d6cd..c2575b4 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ -# react-pro-webpack4 \ No newline at end of file +# react-pro-webpack4 +## webpack4 + react + react-router + mobx + react-mobx + typescript diff --git a/package.json b/package.json index d2f5a2e..fd02a04 100644 --- a/package.json +++ b/package.json @@ -4,34 +4,67 @@ "description": "koa2-code-demo", "main": "index.js", "scripts": { - "dev": "webpack-dev-server --open --mode development --config ./static/config/webpack.config.base.js", + "init_sql": "node --harmony ./sql", + "dev_server": "nodemon ./app.js", + "devServer": "webpack-dev-server --open --mode development --config ./static/config/webpack.config.base.js", "watch": "webpack --mode development --config ./static/config/webpack.config.dev.js", - "prod": "webpack --mode production --config ./static/config/webpack.config.prod.js" + "prod": "webpack --mode production --config ./static/config/webpack.config.prod.js", + "start_server": "node --harmony ./app.js", + "dev": "npm run dev_server & npm run watch", + "start": "npm run prod & npm run start_server" }, "license": "MIT", "dependencies": { "axios": "^0.18.0", + "busboy": "^0.2.14", + "co": "^4.6.0", + "debug": "^2.6.0", "echarts": "^4.0.4", + "ejs": "^2.5.5", "element-react": "^1.4.10", "element-theme-default": "^1.4.13", "glob": "^5.0.15", "iconv-lite": "^0.4.19", + "koa": "^2.0.0", + "koa-bodyparser": "^3.2.0", + "koa-convert": "^1.2.0", + "koa-ejs": "4.1.0", + "koa-log4": "^2.3.0", + "koa-logger": "^1.3.0", + "koa-mysql-session": "0.0.2", + "koa-router": "^7.0.1", + "koa-send": "^3.2.0", + "koa-session-minimal": "^3.0.3", + "koa-static": "^2.0.0", + "koa-views": "^5.2.0", "lodash": "^4.17.4", - "mobx": "^4.1.0", + "mobx": "^4.2.0", "mobx-react": "^5.0.0", + "mysql": "^2.12.0", + "qs": "^6.5.1", "react": "^16.2.0", "react-dev-utils": "^5.0.0", "react-dom": "^16.2.0", "react-loadable": "^5.3.1", "react-router-config": "^1.0.0-beta.4", "react-router-dom": "^4.2.2", - "ua-parser-js": "^0.7.17" + "ua-parser-js": "^0.7.17", + "validator": "^6.2.0" }, "devDependencies": { - "autoprefixer": "7.1.6", + "@babel/preset-react": "^7.0.0-beta.44", + "@types/echarts": "^0.0.12", + "@types/qs": "^6.5.1", + "@types/react": "^16.3.11", + "@types/react-dom": "^16.0.5", + "@types/react-loadable": "^5.3.4", + "@types/react-router-config": "^1.0.6", + "@types/react-router-dom": "^4.2.6", + "@types/ua-parser-js": "^0.7.32", + "autoprefixer": "^7.1.6", "babel-core": "^6.26.0", "babel-eslint": "^7.2.3", - "babel-jest": "20.0.3", + "babel-jest": "^20.0.3", "babel-loader": "^7.1.4", "babel-plugin-import": "^1.7.0", "babel-plugin-syntax-dynamic-import": "^6.18.0", @@ -61,7 +94,6 @@ "eslint-plugin-import": "2.8.0", "eslint-plugin-jsx-a11y": "5.1.1", "eslint-plugin-react": "7.4.0", - "extract-text-webpack-plugin": "^2.0.0-beta.4", "file-loader": "^1.1.5", "fs-extra": "^3.0.1", "html-loader": "^0.5.5", @@ -75,12 +107,13 @@ "optimize-css-assets-webpack-plugin": "^4.0.0", "postcss-flexbugs-fixes": "^3.2.0", "postcss-loader": "^2.0.8", - "promise": "8.0.1", - "qs": "^6.5.1", + "promise": "^8.0.1", "raf": "^3.4.0", "source-map-loader": "^0.2.3", "style-loader": "^0.13.1", "sw-precache-webpack-plugin": "^0.11.4", + "ts-loader": "^4.2.0", + "typescript": "^2.8.1", "uglifyjs-webpack-plugin": "^1.2.4", "url-loader": "^0.6.2", "webpack": "^4.5.0", diff --git a/static/config/webpack.config.base.js b/static/config/webpack.config.base.js index 7cb4883..b21a49d 100644 --- a/static/config/webpack.config.base.js +++ b/static/config/webpack.config.base.js @@ -1,111 +1,10 @@ -const merge = require('webpack-merge'); -const webpack = require('webpack'); -// const baseWebpackConfig = require('./webpack.config.base'); const path = require('path'); -const outputPath = path.join(__dirname, './../build'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const rootPath = path.join(__dirname, './../../'); function resolve(dir) { return path.join(__dirname, './../../', dir) } -module.exports = { - context: rootPath, - module: { - rules: [ - { - test: /\.(js|jsx)$/, - exclude: resolve('node_modules'), - loader: ['babel-loader'] - }, { - test: /\.less$/, - use: [ - MiniCssExtractPlugin.loader, 'css-loader', 'less-loader' - ], - // use:['css-loader','less-loader'], include: [] - }, { - test: /\.css$/, - // use:['css-loader','postcss-loader'], - use: [ - MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader' - ], - // include:['../node_modules/element-theme-default'] - }, { - test: [ - /\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/ - ], - loader: require.resolve('url-loader'), - options: { - limit: 10000, - name: 'assets/images/[name].[hash:8].[ext]' - } - }, { - test: /\.(eot|woff|woff2|svg|ttf)([?]?.*)$/, - use: [ - { - loader: 'file-loader', - options: { - name: 'assets/fonts/[name].[ext]', - context: rootPath - } - } - ] - } - ] - }, - resolve: { - extensions: [ - '.ts', '.tsx', '.js', '.jsx' - ], - modules: [resolve('static/src'), resolve('node_modules')] - }, - entry: { - 'main': ['./static/src/index.js'], - vendor: [ - 'react', - 'react-dom', - 'react-router-dom', - 'react-router-config', - 'react-loadable', - 'mobx', - 'mobx-react' - ] - }, - output: { - path: outputPath, - publicPath: '/', - filename: 'assets/js/[name].[chunkhash:8].js', - chunkFilename: 'assets/js/[name].[chunkhash:8].js' - }, - optimization: { - runtimeChunk: { - name: "manifest" - }, - splitChunks: { - cacheGroups: { - vendor: { - test: /[\\/]node_modules[\\/]/, - name: "vendors", - priority: -20, - chunks: "all" - } - } - } - }, - plugins: [ - new webpack.DefinePlugin({ - 'process.env': { - NODE_ENV: JSON.stringify('development') - } - }), - new HtmlWebpackPlugin({ - title: 'My App', - filename: 'index.html', - template: resolve('static/public/index.html') - }), - new MiniCssExtractPlugin({filename: "assets/css/app.[contenthash].css", chunkFilename: "assets/css/app.[contenthash].[contenthash].css"}) - ] -} - +module.exports = { +} \ No newline at end of file diff --git a/static/config/webpack.config.dev.js b/static/config/webpack.config.dev.js index b7ec4c0..eccc9e8 100644 --- a/static/config/webpack.config.dev.js +++ b/static/config/webpack.config.dev.js @@ -14,6 +14,12 @@ module.exports = { module: { rules: [ { + test: /\.(ts|tsx)$/, + include: resolve('static/src'), + exclude: resolve('node_modules'), + // loader: ['babel-loader', 'awesome-typescript-loader'] + loader: ['babel-loader', 'ts-loader'] + }, { test: /\.(js|jsx)$/, exclude: resolve('node_modules'), loader: ['babel-loader'] @@ -60,7 +66,7 @@ module.exports = { modules: [resolve('static/src'), resolve('node_modules')] }, entry: { - 'main': ['./static/src/index.js'], + 'main': ['./static/src/index.tsx'], vendor: [ 'react', 'react-dom', diff --git a/static/config/webpack.config.prod.js b/static/config/webpack.config.prod.js index 97af0a7..dd3a8b9 100644 --- a/static/config/webpack.config.prod.js +++ b/static/config/webpack.config.prod.js @@ -12,8 +12,14 @@ function resolve(dir) { module.exports = { context: rootPath, module: { - rules: [ + rules: [ { + test: /\.(ts|tsx)$/, + include: resolve('static/src'), + exclude: resolve('node_modules'), + // loader: ['babel-loader', 'awesome-typescript-loader'] + loader: ['babel-loader', 'ts-loader'] + }, { test: /\.(js|jsx)$/, exclude: resolve('node_modules'), loader: ['babel-loader'] @@ -60,7 +66,7 @@ module.exports = { modules: [resolve('static/src'), resolve('node_modules')] }, entry: { - 'main': ['./static/src/index.js'], + 'main': ['./static/src/index.tsx'], vendor: [ 'react', 'react-dom', diff --git a/static/src/AppStatic.js b/static/src/AppStatic.js deleted file mode 100644 index 97adc51..0000000 --- a/static/src/AppStatic.js +++ /dev/null @@ -1,30 +0,0 @@ -import React, {Component} from 'react' -import {renderRoutes} from 'react-router-config' -import {HashRouter} from 'react-router-dom' -import Qs from 'qs'; -import List from './routerStatic' - -const routes = [...List] -// console.log(routes); -class App extends Component { - constructor(props, context) { - super(props, context) - console.log('App'); - // if(!window.location.hash) { - // window.location.href = '/#/overview/list?pid=0' - // } - } - render() { - return ( - -
-
- {renderRoutes(routes)} -
-
-
- ) - } -} - -export default App \ No newline at end of file diff --git a/static/src/AppStatic.tsx b/static/src/AppStatic.tsx new file mode 100644 index 0000000..c380815 --- /dev/null +++ b/static/src/AppStatic.tsx @@ -0,0 +1,63 @@ +// import React, {Component} from 'react'; +import * as React from "react"; +import {observer, inject} from 'mobx-react'; +import {renderRoutes} from 'react-router-config' +import {withRouter} from 'react-router-dom'; +import * as Qs from 'qs'; +import List from './routerStatic'; +import { Props } from "./utils/interface"; + +const routes = [...List]; +interface Params { + pid:string, + start_time:any, + end_time:any +} + +@inject('store') +@observer +class App extends React.Component < Props, {} > { + constructor(props:any, context?: any) { + super(props, context) + console.log('App-TS'); + this.setUrlParamsToStore() + } + formatParams() { + let res:Params = {} as Params; + res.pid = this.props.store.actived; + if(this.props.store.projectTime.startTime) res.start_time = this.props.store.projectTime.startTime; + if(this.props.store.projectTime.endTime) res.end_time = this.props.store.projectTime.endTime; + return res; + } + setUrlParamsToStore() { + let isLoginPages = this.props.location.pathname.indexOf('/login')>-1; + if(isLoginPages) return; + let urlParams:Params = Qs.parse(this.props.location.search.replace(/^\?/, '')); + if(urlParams&&urlParams.pid) { + if(urlParams.pid !== this.props.store.actived) this.props.store.updateActive(urlParams.pid); + if(urlParams.start_time&&urlParams.end_time) { + this.props.store.updateProjectTime({ + startTime:urlParams.start_time, + endTime:urlParams.end_time + }); + } + } else { + console.log('setUrlParamsToStore'); + console.log(routes,'routes') + this.props.history.push({ + pathname: '/overview/list', + search: '?'+ Qs.stringify(this.formatParams()) + }); + } + } + render() { + return ( +
+
+ {renderRoutes(routes)} +
+
+ ) + } +} +export default withRouter(App) \ No newline at end of file diff --git a/static/src/components/Left/index.js b/static/src/components/Left/index.js deleted file mode 100644 index d3cee96..0000000 --- a/static/src/components/Left/index.js +++ /dev/null @@ -1,66 +0,0 @@ -import React, {Component} from 'react' -import {observer, inject} from 'mobx-react'; -import {withRouter, NavLink} from 'react-router-dom' -import Qs from 'qs'; -import './left.less'; - -@withRouter -@inject('store') -@observer -class Left extends Component { - constructor(props) { - super(props); - this.props = props; - // console.log(this.props, 'Left') - // console.log(props, 'params') - - this.menuLink = [ - { - name: '概览', - action: '/list', - }, - { - name: '点赞', - action: '/like', - }, { - name: '评论', - action: '/comment', - }, { - name: '埋点', - action: '/points', - } - ] - } - - makeMeuns() { - return this - .menuLink - .map((item, index) =>
  • - - {item.name} -
  • ); - } - componentDidUpdate() { - let id = Qs.parse(this.props.location.search.replace(/^\?/, '')).pid; - this.props.store.updateActive(id) - } - render() { - let listsItem = this.makeMeuns(); - - return ( -
    - -
    - ) - } -} - -export default Left \ No newline at end of file diff --git a/static/src/components/Left/left.less b/static/src/components/Left/left.less deleted file mode 100644 index 74ce624..0000000 --- a/static/src/components/Left/left.less +++ /dev/null @@ -1,39 +0,0 @@ -.is-active { - .link { - color: #48576a; - } -} - -.meun { - background: #eef1f6; - li { - display: block; - height: 56px; - line-height: 56px; - font-size: 14px; - color: #48576a; - padding: 0 20px; - cursor: pointer; - position: relative; - transition: border-color .3s, background-color .3s, color .3s; - box-sizing: border-box; - white-space: nowrap; - .link { - display: block; - height: 56px; - line-height: 56px; - color: #48576a; - i { - margin-right: 5px; - width: 24px; - text-align: center; - } - } - .link-actvie { - color: #20a0ff; - i { - color: #20a0ff; - } - } - } -} \ No newline at end of file diff --git a/static/src/components/LineChartComponent/index.js b/static/src/components/LineChartComponent/index.tsx similarity index 60% rename from static/src/components/LineChartComponent/index.js rename to static/src/components/LineChartComponent/index.tsx index 054ea98..04d7fff 100644 --- a/static/src/components/LineChartComponent/index.js +++ b/static/src/components/LineChartComponent/index.tsx @@ -1,5 +1,5 @@ -import React, {Component} from 'react'; -import echarts from 'echarts/lib/echarts'; +import * as React from "react"; +import * as echarts from 'echarts/lib/echarts'; import theme from '../../utils/charts/theme' @@ -12,16 +12,20 @@ import 'echarts/lib/chart/line'; -class LineChart extends Component { - constructor(props) { +class LineChart extends React.Component { + ID:any; + lineRef:any + constructor(props:any) { super(props); console.log('LineChart-Component'); + this.lineRef = React.createRef(); this.init = this.init.bind(this); echarts.registerTheme('myTheme',theme); } init() { const { option={} } = this.props; - let myChart = echarts.init(this.ID,'myTheme',{renderer: 'svg'}) + // let myChart = echarts.init(this.ID,'myTheme',{renderer: 'svg'}); + let myChart = echarts.init(this.lineRef.current,'myTheme',{renderer: 'svg'}); myChart.setOption(option) window.onresize = function() { myChart.resize() @@ -35,7 +39,7 @@ class LineChart extends Component { componentDidUpdate() { this.init() } - componentWillUnmount = () => { + componentWillUnmount(){ this.setState = (state,callback)=>{ return; }; @@ -43,7 +47,8 @@ class LineChart extends Component { render() { const { width="100%", height="300px" } = this.props return ( -
    this.ID = ID} style={{width, height}}>
    + //
    this.ID = ID} style={{width, height}}>
    +
    ) } } diff --git a/static/src/components/Loading/Loading.js b/static/src/components/Loading/Loading.tsx similarity index 56% rename from static/src/components/Loading/Loading.js rename to static/src/components/Loading/Loading.tsx index eb67c99..b7bbf5c 100644 --- a/static/src/components/Loading/Loading.js +++ b/static/src/components/Loading/Loading.tsx @@ -1,11 +1,12 @@ -import React from 'react'; +import * as React from "react"; +import {Loading as Loaded} from 'element-react'; -export default function Loading(props) { +export default function Loading(props:any) { if (props.isLoading) { if (props.timedOut) { return
    Loader timed out!
    ; } else if (props.pastDelay) { - return
    Loading...
    ; + return ; } else { return null; } diff --git a/static/src/components/PieChartComponent/index.js b/static/src/components/PieChartComponent/index.tsx similarity index 60% rename from static/src/components/PieChartComponent/index.js rename to static/src/components/PieChartComponent/index.tsx index 9cdfa76..14c42bf 100644 --- a/static/src/components/PieChartComponent/index.js +++ b/static/src/components/PieChartComponent/index.tsx @@ -1,5 +1,5 @@ -import React, {Component} from 'react'; -import echarts from 'echarts/lib/echarts'; +import * as React from "react"; +import * as echarts from 'echarts/lib/echarts'; import theme from '../../utils/charts/theme' @@ -12,16 +12,20 @@ import 'echarts/lib/chart/pie'; -class PieChart extends Component { - constructor(props) { +class PieChart extends React.Component { + ID:any + pieRef:any + constructor(props:any) { super(props); console.log('PieChart-Component'); + this.pieRef = React.createRef(); this.init = this.init.bind(this); echarts.registerTheme('myTheme',theme); } init() { const { option={} } = this.props; - let myChart = echarts.init(this.ID,'myTheme',{renderer: 'svg'}) + // let myChart = echarts.init(this.ID,'myTheme',{renderer: 'svg'}); + let myChart = echarts.init(this.pieRef.current,'myTheme',{renderer: 'svg'}) myChart.setOption(option) window.onresize = function() { myChart.resize() @@ -35,7 +39,7 @@ class PieChart extends Component { componentDidUpdate() { this.init() } - componentWillUnmount = () => { + componentWillUnmount() { this.setState = (state,callback)=>{ return; }; @@ -43,7 +47,8 @@ class PieChart extends Component { render() { const { width="100%", height="300px" } = this.props; return ( -
    this.ID = ID} style={{width, height}}>
    + //
    this.ID = ID} style={{width, height}}>
    +
    ) } } diff --git a/static/src/components/SearchComponent/index.js b/static/src/components/SearchComponent/index.tsx similarity index 66% rename from static/src/components/SearchComponent/index.js rename to static/src/components/SearchComponent/index.tsx index 9118f72..424857c 100644 --- a/static/src/components/SearchComponent/index.js +++ b/static/src/components/SearchComponent/index.tsx @@ -1,14 +1,18 @@ -import React, {Component} from 'react'; +import * as React from "react"; import {observer, inject} from 'mobx-react'; import { DateRangePicker} from 'element-react'; -import {withRouter} from 'react-router-dom'; + import dateFormat from '../../utils/Date'; -@withRouter +interface states { + value: any[] +} + @inject('store') @observer -class Searchs extends Component { - constructor(props) { +class Searchs extends React.Component { + paras:any = {} + constructor(props:any) { super(props); // console.log(this.props.handleData, 'Searchs') this.props = props; @@ -20,21 +24,12 @@ class Searchs extends Component { }; this.paras = {}; } - componentWillUnmount = () => { + componentWillUnmount() { this.setState = (state,callback)=>{ return; }; } - componentWillReceiveProps(nextProps) { - if (nextProps.location.pathname !== this.props.location.pathname || nextProps.location.search !== this.props.location.search) { - console.log('Searchs-update-nextProps') - let {startTime,endTime} = this.props.store.projectTime; - let start_time = startTime?new Date(startTime):null; - let end_time = endTime?new Date(endTime):null; - this.setState({value: [start_time,end_time]}) - } - } - changeDate(date) { + changeDate(date:any) { // console.log('DateRangePicker1 changed: ', date) if(date.length>0) { this.paras.start_time = dateFormat(date[0]); diff --git a/static/src/components/Top/index.js b/static/src/components/Top/index.tsx similarity index 76% rename from static/src/components/Top/index.js rename to static/src/components/Top/index.tsx index b6476d5..2d60be7 100644 --- a/static/src/components/Top/index.js +++ b/static/src/components/Top/index.tsx @@ -1,20 +1,31 @@ -import React, {Component} from 'react' +import * as React from "react"; import {observer, inject} from 'mobx-react'; -import {withRouter} from 'react-router-dom' +import {withRouter} from 'react-router-dom'; import {Layout,Select,Message,Icon} from 'element-react'; -import Qs from 'qs'; +import * as Qs from 'qs'; import {getBase} from '../../utils/httpServers'; -import Searchs from '../SearchComponent' +import Searchs from '../SearchComponent/index' import './index.less' - -@withRouter +interface states { + path: any, + type: any, + showTimeDialog:any, + pv: any, + uv: any, + comment: any, + like: any, + point: any, + options: any[], + value: any +} +// @withRouter @inject('store') @observer -class Top extends Component { - constructor(props) { +class Top extends React.Component { + constructor(props:any) { super(props); - console.log('Top-Component') + console.log('Top-Component'); this.props = props; // let isLogin = props.store.isLogin; if(!isLogin) { // this.props.history.push(`/login`) } @@ -36,18 +47,17 @@ class Top extends Component { }], value: '0' } - this.setUrlParamsToStore(); } componentWillMount() { this.handleData(); } - componentWillReceiveProps(nextProps) { - if (nextProps.location.pathname !== this.props.location.pathname || nextProps.location.search !== this.props.location.search) { - console.log('top-update-nextProps') - this.handleData(); - } - } - componentWillUnmount = () => { + // componentWillReceiveProps(nextProps:any) { + // if (nextProps.location.pathname !== this.props.location.pathname || nextProps.location.search !== this.props.location.search) { + // console.log('top-update-nextProps') + // this.handleData(); + // } + // } + componentWillUnmount() { this.setState = (state, callback) => { return; }; @@ -56,7 +66,7 @@ class Top extends Component { const request = this.formatParams(); this.getBase(request); } - getBase(data) { + getBase(data:any) { getBase(data).then((res) => { if (res.status === 200 && res.data.status.code === 200) { this.assignBase(res.data.data); @@ -65,18 +75,18 @@ class Top extends Component { } }) } - assignBase(data) { + assignBase(data:any) { const {pv,uv,like,comment,point} = data; this.setState({pv,uv,like,comment,point}) } - onChange(value) { + onChange(value:any) { this.props.store.updateActive(value); this.props.history.push({ pathname: '/overview/list', search: '?'+Qs.stringify(this.formatParams()) }) } - linkTo(path) { + linkTo(path:any) { // console.log(this.props.location.pathname,'this.props.location.pathname '); let pathname = this.props.location.pathname; let linkPath = '/overview/'+path; @@ -89,7 +99,7 @@ class Top extends Component { search: '?' + Qs.stringify(this.formatParams()) }) } - showTime(date) { + showTime(date:any) { // console.log(date,'date') this.props.store.updateProjectTime({ startTime:date.start_time, @@ -100,31 +110,14 @@ class Top extends Component { }); } formatParams() { - const res = {}; + const res:any = {}; res.pid = this.props.store.actived; if(this.props.store.projectTime.startTime) res.start_time = this.props.store.projectTime.startTime; if(this.props.store.projectTime.endTime) res.end_time = this.props.store.projectTime.endTime; return res; } - setUrlParamsToStore() { - let urlParams = Qs.parse(this.props.location.search.replace(/^\?/, '')); - if(urlParams&&urlParams.pid) { - if(urlParams.pid !== this.props.store.actived) this.props.store.updateActive(urlParams.pid); - if(urlParams.start_time&&urlParams.end_time) { - this.props.store.updateProjectTime({ - startTime:urlParams.start_time, - endTime:urlParams.end_time - }); - } - } else { - this.props.history.push({ - pathname: '/overview/list', - search: '?'+ Qs.stringify(this.formatParams()) - }); - } - } render() { - const {pv,uv,like,comment,point} = this.state; + const {pv,uv,like,comment,point,options} = this.state; return (
    @@ -132,7 +125,7 @@ class Top extends Component {
    import('./index'), + loading: Loading +}) + +class Logins extends React.Component { + render() { + return ( + + ); + } +} +export default Logins \ No newline at end of file diff --git a/static/src/pages/Overview/index.js b/static/src/pages/Overview/index.js deleted file mode 100644 index 5c7dd7c..0000000 --- a/static/src/pages/Overview/index.js +++ /dev/null @@ -1,17 +0,0 @@ -import React, {Component} from 'react' -// import {observer,inject} from 'mobx-react'; -import Top from '../../components/Top' -// @inject('store') -// @observer -class Overview extends Component { - render() { - return ( -
    - - welcome123 -
    - ) - } -} - -export default Overview \ No newline at end of file diff --git a/static/src/pages/Overview/overview.js b/static/src/pages/Overview/overview.js deleted file mode 100644 index 44ee44a..0000000 --- a/static/src/pages/Overview/overview.js +++ /dev/null @@ -1,18 +0,0 @@ -import React, {Component} from 'react' -import Loadable from 'react-loadable'; -import Loading from '../../components/Loading/Loading' - - -const LoadableComponent = Loadable({ - loader: () => import('./index'), - loading: Loading -}) - -class Overview extends Component { - render() { - return ( - - ); - } -} -export default Overview \ No newline at end of file diff --git a/static/src/registerServiceWorker.js b/static/src/registerServiceWorker.js new file mode 100644 index 0000000..a3e6c0c --- /dev/null +++ b/static/src/registerServiceWorker.js @@ -0,0 +1,117 @@ +// In production, we register a service worker to serve assets from local cache. + +// This lets the app load faster on subsequent visits in production, and gives +// it offline capabilities. However, it also means that developers (and users) +// will only see deployed updates on the "N+1" visit to a page, since previously +// cached resources are updated in the background. + +// To learn more about the benefits of this model, read https://goo.gl/KwvDNy. +// This link also includes instructions on opting out of this behavior. + +const isLocalhost = Boolean( + window.location.hostname === 'localhost' || + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.1/8 is considered localhost for IPv4. + window.location.hostname.match( + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ + ) +); + +export default function register() { + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + // The URL constructor is available in all browsers that support SW. + const publicUrl = new URL(process.env.PUBLIC_URL, window.location); + if (publicUrl.origin !== window.location.origin) { + // Our service worker won't work if PUBLIC_URL is on a different origin + // from what our page is served on. This might happen if a CDN is used to + // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374 + return; + } + + window.addEventListener('load', () => { + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + + if (isLocalhost) { + // This is running on localhost. Lets check if a service worker still exists or not. + checkValidServiceWorker(swUrl); + + // Add some additional logging to localhost, pointing developers to the + // service worker/PWA documentation. + navigator.serviceWorker.ready.then(() => { + console.log( + 'This web app is being served cache-first by a service ' + + 'worker. To learn more, visit https://goo.gl/SC7cgQ' + ); + }); + } else { + // Is not local host. Just register service worker + registerValidSW(swUrl); + } + }); + } +} + +function registerValidSW(swUrl) { + navigator.serviceWorker + .register(swUrl) + .then(registration => { + registration.onupdatefound = () => { + const installingWorker = registration.installing; + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed') { + if (navigator.serviceWorker.controller) { + // At this point, the old content will have been purged and + // the fresh content will have been added to the cache. + // It's the perfect time to display a "New content is + // available; please refresh." message in your web app. + console.log('New content is available; please refresh.'); + } else { + // At this point, everything has been precached. + // It's the perfect time to display a + // "Content is cached for offline use." message. + console.log('Content is cached for offline use.'); + } + } + }; + }; + }) + .catch(error => { + console.error('Error during service worker registration:', error); + }); +} + +function checkValidServiceWorker(swUrl) { + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl) + .then(response => { + // Ensure service worker exists, and that we really are getting a JS file. + if ( + response.status === 404 || + response.headers.get('content-type').indexOf('javascript') === -1 + ) { + // No service worker found. Probably a different app. Reload the page. + navigator.serviceWorker.ready.then(registration => { + registration.unregister().then(() => { + window.location.reload(); + }); + }); + } else { + // Service worker found. Proceed as normal. + registerValidSW(swUrl); + } + }) + .catch(() => { + console.log( + 'No internet connection found. App is running in offline mode.' + ); + }); +} + +export function unregister() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready.then(registration => { + registration.unregister(); + }); + } +} diff --git a/static/src/routerStatic.js b/static/src/routerStatic.ts similarity index 69% rename from static/src/routerStatic.js rename to static/src/routerStatic.ts index 1051840..52f91d5 100644 --- a/static/src/routerStatic.js +++ b/static/src/routerStatic.ts @@ -1,25 +1,26 @@ -// import asyncComponent from './components/asyncComponent/asyncComponent' -// import overview from './pages/Overview/index'; -import Login from './pages/Login/login'; import Content from './pages/Content/content'; import ContentList from './pages/ContentList/contentList'; import ContentDetail from './pages/ContentDetail/contentDetail'; import ContentLike from './pages/ContentLike/contentLike'; import ContentComment from './pages/ContentComment/contentComment'; -import ContentPoint from './pages/ContentPoint/contentPoint' -import List from './pages/List/list'; +import ContentPoint from './pages/ContentPoint/contentPoint'; +import Logins from './pages/Logins/logins'; +// import Logins from './pages/Login/login'; -export default[ +export default [ { path : '/', exact : true, component : Content, - routes : [] - }, { + routes : [ + + ] + },{ path : '/login', - component : Login - }, { + // exact: true, + component : Logins + },{ path : '/overview', component : Content, routes : [ @@ -27,7 +28,8 @@ export default[ path: '/overview/list', exact: true, component: ContentList - }, { + }, + { path: '/overview/detail', exact: true, component: ContentDetail @@ -39,14 +41,11 @@ export default[ path: '/overview/comment', exact: true, component: ContentComment - },{ + }, { path: '/overview/point', exact: true, component: ContentPoint - } + }, ] - }, { - path : '/action/:type/', - component : List - } + }, ] \ No newline at end of file diff --git a/static/src/store/index.js b/static/src/store/index.js deleted file mode 100644 index e3b0d00..0000000 --- a/static/src/store/index.js +++ /dev/null @@ -1,41 +0,0 @@ -import {observable, action} from 'mobx' - -class Store { - @observable isLogin = false; - @action login = () => { - this.isLogin = true; - return Promise.resolve(true); - } - @action loginOut = () => { - this.isLogin = false; - } - - @observable actived = '0'; - @action updateActive = (id) => { - this.actived = id; - } - - @observable projectList = [ - { - name: '项目一', - id: '0' - }, { - name: '项目二', - id: '1' - } - ] - @action updateProjectList = (arr) => { - this.projectList = [].concat(arr); - } - - @observable projectTime = { - startTime: null, - endTime: null - } - @action updateProjectTime = ({startTime, endTime}) => { - this.projectTime.startTime = startTime; - this.projectTime.endTime = endTime; - } -} - -export default new Store() \ No newline at end of file diff --git a/static/src/store/index.ts b/static/src/store/index.ts new file mode 100644 index 0000000..666fb24 --- /dev/null +++ b/static/src/store/index.ts @@ -0,0 +1,60 @@ +import {observable, action} from 'mobx'; + +interface Stores { + actived: string, + updateActive: (id: string) => void, + projectList: any[], + updateProjectList : (arr:any[]) => void, + projectTime: ProjectTime, + updateProjectTime: ({startTime, endTime}:any) => void, + isLogin:boolean, + login:() => Promise +} +interface ProjectTime{ + startTime: any, + endTime: any +} +export interface store { + store:Stores +} + +class Store { + @observable isLogin = false; + @action login = () => { + this.isLogin = true; + return Promise.resolve(true); + } + @action loginOut = () => { + this.isLogin = false; + } + + @observable actived = '0'; + @action updateActive = (id:string) => { + this.actived = id; + } + + @observable projectList:any[] = [ + { + name: '项目一', + id: '0' + }, { + name: '项目二', + id: '1' + } + ] + @action updateProjectList = (arr:any[]) => { + let res:any[] = []; + this.projectList = res.concat(arr); + } + + @observable projectTime:ProjectTime = { + startTime: null, + endTime: null + } + @action updateProjectTime = ({startTime, endTime}:any) => { + this.projectTime.startTime = startTime; + this.projectTime.endTime = endTime; + } +} + +export default new Store() \ No newline at end of file diff --git a/static/src/texts/common.js b/static/src/texts/common.js deleted file mode 100644 index 404dcf8..0000000 --- a/static/src/texts/common.js +++ /dev/null @@ -1,7 +0,0 @@ -const common = { - BTN_SUBMIT_NAME: '确定', - - NO_LOGIN: '未登录', -} - -export default common \ No newline at end of file diff --git a/static/src/texts/user-text.js b/static/src/texts/user-text.js deleted file mode 100644 index 128b6d4..0000000 --- a/static/src/texts/user-text.js +++ /dev/null @@ -1,23 +0,0 @@ -const UserText = { - - USER_INFO_LABEL_NAME: '用户名称', - - USER_INFO_LABEL_EMAIL: '用户邮件', - - USER_INFO_LABEL_PASSWORD: '密码', - - USER_INFO_LABEL_CONFIRM_PASSWORD: '确认密码', - - USER_INFO_PLACEHOLDER_NAME: '请输入用户名称', - - USER_INFO_PLACEHOLDER_EMAIL: '请输入邮箱地址', - - USER_INFO_PLACEHOLDER_PASSWORD: '请输入密码', - - USER_INFO_PLACEHOLDER_CONFIRM_PASSWORD: '请再次输入密码确认', - - USER_INFO_BTN_SUBMIT: '确认', - -} - -export default UserText \ No newline at end of file diff --git a/static/src/utils/Date.js b/static/src/utils/Date.ts similarity index 74% rename from static/src/utils/Date.js rename to static/src/utils/Date.ts index d043c51..bed689e 100644 --- a/static/src/utils/Date.js +++ b/static/src/utils/Date.ts @@ -1,9 +1,9 @@ -export default function (date,format='yyyy-MM-dd hh:mm:ss') { +export default function (date:Date,format='yyyy-MM-dd hh:mm:ss') { // const date = new Date(format) /* * format='yyyy-MM-dd hh:mm:ss'; */ - var o = { + const o = { 'M+': date.getMonth() + 1, 'd+': date.getDate(), 'h+': date.getHours(), @@ -18,7 +18,7 @@ export default function (date,format='yyyy-MM-dd hh:mm:ss') { - RegExp.$1.length)); } - for (var k in o) { + for (let k in o) { if (new RegExp('(' + k + ')').test(format)) { format = format.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] @@ -26,4 +26,13 @@ export default function (date,format='yyyy-MM-dd hh:mm:ss') { } } return format; +} +interface Format { + 'M+': any, + 'd+': any, + 'h+': any, + 'm+': any, + 's+': any, + 'q+': any, + 'S': any } \ No newline at end of file diff --git a/static/src/utils/charts/makeLine.js b/static/src/utils/charts/makeLine.ts similarity index 60% rename from static/src/utils/charts/makeLine.js rename to static/src/utils/charts/makeLine.ts index 67ac7d4..2ee29b3 100644 --- a/static/src/utils/charts/makeLine.js +++ b/static/src/utils/charts/makeLine.ts @@ -1,4 +1,6 @@ -const lineOption = { +// import { inflate } from "zlib"; + +const lineOption:any = { title: { text: '时间点击分布图' }, @@ -8,7 +10,7 @@ const lineOption = { legend: { data: ['小时'] }, - grid : { + grid: { top: '100', right: '100', bottom: '60', @@ -17,17 +19,15 @@ const lineOption = { xAxis: [ { type: 'category', - offset:10, + offset: 10, boundaryGap: false, - data: [ - - ] + data: [] } ], yAxis: [ { type: 'value', - axisLabel:{ + axisLabel: { formatter: '{value} 次' } } @@ -36,26 +36,24 @@ const lineOption = { { name: '小时', type: 'line', - data: [ - ] + data: [] } ] }; -function tranformHour(val) { - return val>9?(val+':00'):('0'+val+':00') +function tranformHour(val:number) { + return val > 9 + ? (val + ':00') + : ('0' + val + ':00') } -export default function (data) { - const seriesData = []; - const xAxisData = []; - data.forEach((item) => { +export default function (data:any) { + const seriesData:any = []; + const xAxisData:any = []; + data.forEach((item:any) => { seriesData.push(item.count); xAxisData.push(tranformHour(item.hour)); }); lineOption.xAxis[0].data = xAxisData; lineOption.series[0].data = seriesData; return lineOption; - // return { - // seriesData, - // xAxisData - // } -} + // return { seriesData, xAxisData } +} \ No newline at end of file diff --git a/static/src/utils/charts/makePie.js b/static/src/utils/charts/makePie.ts similarity index 90% rename from static/src/utils/charts/makePie.js rename to static/src/utils/charts/makePie.ts index 2cef707..08f80b7 100644 --- a/static/src/utils/charts/makePie.js +++ b/static/src/utils/charts/makePie.ts @@ -1,4 +1,5 @@ export default class { + pieOption:any; constructor() { this.pieOption = { title: { @@ -36,9 +37,9 @@ export default class { }; // this.make(data,title); } - make(data,title) { - const legendData = []; - data.forEach((item) => { + make(data:any,title:any) { + const legendData:any = []; + data.forEach((item:any) => { legendData.push(item.name); }); this.pieOption.legend.data = legendData; diff --git a/static/src/utils/charts/theme.js b/static/src/utils/charts/theme.ts similarity index 100% rename from static/src/utils/charts/theme.js rename to static/src/utils/charts/theme.ts diff --git a/static/src/utils/http.js b/static/src/utils/http.ts similarity index 100% rename from static/src/utils/http.js rename to static/src/utils/http.ts diff --git a/static/src/utils/httpServers.js b/static/src/utils/httpServers.js deleted file mode 100644 index 30f0273..0000000 --- a/static/src/utils/httpServers.js +++ /dev/null @@ -1,75 +0,0 @@ -import axios from './http'; -import {Time, Base,Like,Point} from './resetApi'; -import Qs from 'qs' - -// export function postOverview(params) { -// return axios.post(ACTION.overview, -// params); } -function tranformParas(params) { - return (params)=>{ - return Qs.stringify(params).replace(/%3A/g, ':') - } -} -export function getTime(params) { - return axios.get(Time.Time, {params: params}); -} - -export function getBase(params) { - return axios.get(Base.Base, { - params: params, - paramsSerializer: tranformParas(params) - }); -} - -export function getBasePage(params) { - return axios.get(Base.BasePage, { - params: params, - paramsSerializer: tranformParas(params) - }); -} -export function getBasetTransfer(params) { - return axios.get(Base.BasetTransfer, { - params: params, - paramsSerializer: tranformParas(params) - }); -} -export function getTransfers(funs) { - return new Promise((resolve, reject)=>{ - axios.all(funs).then(axios.spread((basePage, basetTransfer)=>{ - const arr = []; - arr.push(basePage); - arr.push(basetTransfer); - resolve(arr); - })); - }) -} - -export function getBaseUa(params) { - return axios.get(Base.BaseUa, { - params: params - }); -} - -export function getLike(params) { - return axios.get(Like.Like, { - params: params - }); -} -export function getComment(params) { - return axios.get(Like.Comment, { - params: params - }); -} - -export function getPoint(params) { - return axios.get(Point.Point, { - params: params, - paramsSerializer: tranformParas(params) - }); -} -export function getPointHotel(params) { - return axios.get(Point.PointHotel, { - params: params, - paramsSerializer: tranformParas(params) - }); -} \ No newline at end of file diff --git a/static/src/utils/httpServers.ts b/static/src/utils/httpServers.ts new file mode 100644 index 0000000..6906b86 --- /dev/null +++ b/static/src/utils/httpServers.ts @@ -0,0 +1,78 @@ +import axios from './http'; +import {Time, Base,Like,Point} from './resetApi'; +import * as Qs from 'qs' + +interface Params { + pid:string, +} +interface ParamsBasePage extends Params { + start_time:string, + end_time:string +} + +interface ParamsBase extends ParamsBasePage { + groupType:number +} + +interface Likes extends Params{ + version:string, + url:string, + router:string +} + +interface Points extends Likes,ParamsBasePage{ + +} + +function tranformParas(params:any) { + return (params:any)=>{ + return Qs.stringify(params).replace(/%3A/g, ':') + } +} +export function getTime(params:any) { + return axios.get(Time.Time, {params: params}); +} + +export function getBase(params:ParamsBase) { + return axios.get(Base.Base, { + params: params, + paramsSerializer: tranformParas(params) + }); +} + +export function getBasePage(params:ParamsBasePage) { + return axios.get(Base.BasePage, { + params: params, + paramsSerializer: tranformParas(params) + }); +} + +export function getBaseUa(params:Params) { + return axios.get(Base.BaseUa, { + params: params + }); +} + +export function getLike(params:Likes) { + return axios.get(Like.Like, { + params: params + }); +} +export function getComment(params:Likes) { + return axios.get(Like.Comment, { + params: params + }); +} + +export function getPoint(params:Points) { + return axios.get(Point.Point, { + params: params, + paramsSerializer: tranformParas(params) + }); +} +export function getPointHotel(params:Points) { + return axios.get(Point.PointHotel, { + params: params, + paramsSerializer: tranformParas(params) + }); +} \ No newline at end of file diff --git a/static/src/utils/interface/index.tsx b/static/src/utils/interface/index.tsx new file mode 100644 index 0000000..32cb16f --- /dev/null +++ b/static/src/utils/interface/index.tsx @@ -0,0 +1,23 @@ +import {RouteComponentProps} from 'react-router-dom'; +import { store } from "../../store"; + +export interface RouteConfig { + path?: string; + exact?: boolean; + strict?: boolean; + routes?: RouteConfig[]; +} +export interface Routes { + route: RouteConfig; +} + +export interface Props extends RouteComponentProps,store { + +} + +export interface UrlConfig { + pid:string, + urls:string, + url:string, + router:string +} diff --git a/static/src/utils/resetApi.js b/static/src/utils/resetApi.ts similarity index 80% rename from static/src/utils/resetApi.js rename to static/src/utils/resetApi.ts index 8d74454..5ba7b36 100644 --- a/static/src/utils/resetApi.js +++ b/static/src/utils/resetApi.ts @@ -1,11 +1,9 @@ // 接口 + // Base export const Base = { - // 获取基础信息 Base: '/api/base', - // 获取分页信息 BasePage: '/api/base/page', - BasetTransfer:'/api/base/transfer', BaseUa: '/api/base/ua' }; // Time diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..0039eed --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "module": "esnext", + "target": "es5", + "lib": [ + "es6", + "dom" + ], + "outDir": "./static/build/", + "sourceMap": true, + "noImplicitAny": true, + "jsx": "react", + "experimentalDecorators": true, + "skipLibCheck": true, + "moduleResolution": "node", + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "strictNullChecks": true, + "suppressImplicitAnyIndexErrors": true, + "noUnusedLocals": true + }, + "include": [ + "./static/src/**/*" + ], + "exclude": [ + "node_modules" + ] +} \ No newline at end of file