Commit 11c4f786 authored by 刘松's avatar 刘松

init

parents
{
"presets": ["react","es2015"]
}
\ No newline at end of file
node_modules
babelCache
draft/
config/dev.js
.vscode
*.logs
*.log
.DS_Store
package-lock.json
FROM node:7.6
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app/
RUN npm install --production --registry=https://registry.npm.taobao.org
# RUN npm install yarn --registry=https://registry.npm.taobao.org
# RUN yarn config set registry https://registry.npm.taobao.org
# RUN yarn config set disturl https://npm.taobao.org/dist
# RUN yarn install
COPY . /usr/src/app
EXPOSE 9401
CMD node app.js
\ No newline at end of file
/*
console for taokouling
*?
功能:
数据统计
后台设置
\ No newline at end of file
'use strict';
const express = require('express');
const path = require('path');
const config = require('./config/index');
const logger = require('morgan');
const app = express();
const routes = require('./routes/index');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const session = require('cookie-session');
const mongoose = require('mongoose');
const sessions = require('./db/mongo/session');
const cron = require('./lib/cron');
const options = {
useMongoClient: true
};
mongoose.connect(config.mongo, options);
console.log('MONGO CONNECT INFO: ', config.MONGO_DB);
global.Promise = mongoose.Promise = require('bluebird');
app.use(logger('dev'));
app.use(cookieParser('f7f926ad3fc8fe90eb4784643bc4d747'));
app.use(session({secret: '5f1d65f27e370c36dfd845f6dc78b869'}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(__dirname+'/app'));
app.use(async function(req,res,next){
if(req.url == '/session' || req.url == '/') return next();
let sess = req.cookies['sess'];
let flag = await sessions.findById(sess)
if(flag) return next();
else res.redirect('/');
});
app.get('/', function (req, res){
console.dir('login');
res.sendFile(path.resolve(__dirname, 'app', 'index.html'))
});
app.get('/manage', function (req, res){
res.sendFile(path.resolve(__dirname, 'app', 'index.html'))
});
app.get('/manage/*', function (req, res){
res.sendFile(path.resolve(__dirname, 'app', 'index.html'))
});
app.use(routes);
console.dir(config);
app.listen(config.port);
console.log('server started on port ' + config.port);
/*cron.start();*/
/*! This file is created by phyllis */
webpackJsonp([0],{1679:function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function o(e){return e}var p=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),u=n(213),s=n(0),c=n(112).connect,l=n(214),d=(n(163),n(8)),f=function(e){function t(e){return r(this,t),a(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e))}return i(t,e),p(t,[{key:"componentDidMount",value:function(){this.props.dispatch(l.getDetailData({limit:30,skip:0}))}},{key:"handleTableChange",value:function(e,t,n){var r=this.props.data.detail.pagination;r.current=e.current,this.props.dispatch(l.getDetailData({limit:30,skip:parseInt(r.current)-1}))}},{key:"render",value:function(){for(var e=[{title:"用户",dataIndex:"name",key:"name",width:100,render:function(e){return s.createElement("a",{href:"#"},e)}},{title:"电话",dataIndex:"phone",key:"phone",width:100,render:function(e){return s.createElement("a",{href:"#"},e)}},{title:"账户数量",dataIndex:"ups",key:"ups",width:100,render:function(e){return s.createElement("a",{href:"#"},e)}},{title:"注册时间",dataIndex:"date",key:"date",width:100,render:function(e){return s.createElement("a",{href:"#"},e)}}],t=this.props.data.detail?this.props.data.detail.users:[],n=this.props.data.detail?this.props.data.detail.upstreams:[],r={},a=[],i=0;i<n.length;i++){r[n[i]._id.creater]=n[i].count}for(var o=0;o<t.length;o++){var p=t[o];a.push({key:o,name:p.username||"-",phone:p.phone||"-",ups:r[p._id]||0,date:d(p.createdAt).format("YYYY/MM/DD HH:mm:ss")})}return s.createElement(u.Spin,{spinning:"pending"==this.props.data.status},s.createElement(u.Table,{columns:e,dataSource:a,pagination:this.props.data.detail.pagination,size:"middle",onChange:this.handleTableChange.bind(this),bordered:!0}))}}]),t}(s.Component);e.exports=c(o)(f)}});
\ No newline at end of file
/*! This file is created by phyllis */
webpackJsonp([1],{1597:function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function u(e){return{list:e.users.list}}var c=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),f=n(0),a=n(88).connect,l=function(e){function t(e){return r(this,t),o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e))}return i(t,e),c(t,[{key:"render",value:function(){return f.createElement("div",null,this.props.list)}}]),t}(f.Component);e.exports=a(u)(l)}});
\ No newline at end of file
/*! This file is created by phyllis */
webpackJsonp([2],{1596:function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function u(e){return{stras:e.strategy.stras}}var c=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=n(0),f=n(88).connect,s=function(e){function t(e){return r(this,t),o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e))}return i(t,e),c(t,[{key:"render",value:function(){return a.createElement("div",null,this.props.stras)}}]),t}(a.Component);e.exports=f(u)(s)}});
\ No newline at end of file
/*! This file is created by phyllis */
webpackJsonp([3],{1595:function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function c(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function i(e){return{p_datas:e.packages.p_datas}}var u=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=n(0),f=n(88).connect,p=function(e){function t(e){return r(this,t),o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e))}return c(t,e),u(t,[{key:"render",value:function(){return a.createElement("div",null,this.props.p_datas)}}]),t}(a.Component);e.exports=f(i)(p)}});
\ No newline at end of file
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
body{
background: #ececec
}
.wrapper,.login-wrapper{
background: #ececec;
display: inline-block;
width: 100%;
height: 100%;
}
.login-wrapper{
text-align: center;
}
.login-wrapper:before{
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -.25em;
}
.login-wrapper .m{
width: 400px;
margin: auto;
padding: 0;
display: inline-block;
vertical-align: middle;
text-align: left;
white-space: normal;
}
.wrapper .menu{
position: absolute;
background: #404040;
bottom: 0px;
top: 0px;
}
.wrapper .menu .top_menu{
height: 50px;
text-align: center;
}
.wrapper .menu .top_menu i{
font-size: 35px;
color: #fff;
line-height: 50px;
}
.wrapper .main{
margin-left: 200px;
}
.wrapper .main .head{
height: 50px;
background: #fff;
}
.wrapper .main .content{
margin: 20px 15px;
padding: 10px;
background: #ffffff;
}
.logo{
width: 120px;
height: 31px;
float: left;
}
.logo span{
color: #f04134;
font-size: 20px;
}
.box{
box-shadow: 0 0 1px #ddd;
background: #f7f7f7;
border-radius: 4px;
display: flex;
justify-content: flex-start;
align-items: center;
overflow: hidden;
margin: 5px 10px;
}
.box h3{
width: 40%;
height: 100%;
padding: 10px;
color: #fff;
text-align: center;
background: #5587b3;
}
.box span{
font-size: 20px;
width: 58%;
padding: 0 20px;
text-align: center;
}
\ No newline at end of file
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>口令管理</title>
<meta content="sig,cmcc,toolbar" name="keywords">
<link rel="stylesheet" type="text/css" href="/css/antd.min.css">
<link rel="stylesheet" type="text/css" href="/css/main.css">
</head>
<body>
<div id="main" style="height: 100%;"></div>
<a id="bottom"></a>
<script type="text/javascript" src="/built/common.bundle.js"></script>
<script type="text/javascript">
window.onload = function () {
var s = document.createElement("script");
s.src = "/built/app.bundle.js";
document.body.appendChild(s);
};
</script>
</body>
</html>
\ No newline at end of file
module.exports = {
LOGINSTATUS: 'LOGINSTATUS',
CURRENTPAGE: 'CURRENTPAGE',
MAINDATA:'MAINDATA',
COUNTDATA:'COUNTDATA',
DETAILDATA:'DETAILDATA',
STATUS:'STATUS'
};
const types = require('./actionTypes');
const api = require('../api');
exports.fetchTest = (dispatch, getState) => {
return (dispatch) => {
api('GET', 'test').then((res) => {
dispatch(setText(res.result));
});
};
};
exports.getSession = (data) => {
return (dispatch) => {
api('POST', 'session', data).then((res) => {
if(res.result == 'ok'){
location.href = "/manage";
// dispatch({ status:'login', user:{ username:data.username,password:data.password }, type: types.LOGINSTATUS});
}
});
};
}
exports.getMainData = (data) => {
return (dispatch) => {
api('POST', 'data', data).then((res) => {
dispatch({status: 'pending', type: types.STATUS});
dispatch({ status:res.result, data:res.data, type: types.MAINDATA});
});
};
}
exports.getCountData= () => {
return (dispatch) => {
api('GET', 'count').then((res) => {
dispatch({ status:res.result, data:res.data, type: types.COUNTDATA});
});
};
}
exports.getDetailData = (data) => {
return (dispatch) => {
dispatch({status: 'pending', type: types.STATUS});
api('POST', 'detail', data).then((res) => {
dispatch({ status:res.result, data:res.data, type: types.DETAILDATA});
});
};
}
exports.getMenu = () => {
const mapLocations = ['/manage','/manage/statistics','/manage/setting'];
let key = mapLocations.indexOf(location.pathname);
return (dispatch) => {
dispatch({currentPage:key, type: types.CURRENTPAGE})
//dispatch({ data, type: types.CURRENTPAGE});
};
}
const $ = require('jquery');
const Promise = require('bluebird');
const request = function(method,path,data) {
return new Promise((resolve,reject) => {
let url = '/' + path;
let body;
$.ajax({
url:url,
data:data,
dataType:'json',
method:method,
success:(resp) =>{
resolve(resp);
},
error:(resp) =>{
console.dir('error resp',JSON.stringfy(resp));
resolve(resp);
}
})
});
}
module.exports = request;
\ No newline at end of file
"use strict";
require('es6-promise');
// require('babel-polyfill');
const RectDOM = require('react-dom');
const React = require('react');
const routes = require('./routes/routes');
const reactRouter = require('react-router');
// const reactRouterRedux = require('react-router-redux-ie8');
const Router = reactRouter.Router;
const browserHistory = reactRouter.browserHistory;
const reactRedux = require('react-redux');
const Provider = reactRedux.Provider;
const Store = require('./store').configureStore;
const ReduxDevTools = require('./store').ReduxDevTools;
const store = Store();
const Main =require('../jsx/main.jsx');
RectDOM.render(
<Provider store = { store } >
<div style={{ height:"100%" }}>
<Router routes = { routes } history = { browserHistory }/>
</div>
</Provider>,document.getElementById('main')
);
import XLSX from 'xlsx'
import { saveAs } from 'file-saver'
function s2ab (s) {
const buf = new ArrayBuffer(s.length)
const view = new Uint8Array(buf)
for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
return buf
}
export default function json2xlsx (json, {sheetName = 'sheet1', filename = 'statistics.xlsx'} = {}) {
const wb = {
SheetNames: [],
Sheets: {},
Props: {
Title: '小云蜂巢数据统计',
Author: '小云蜂巢'
}
}
const ws = XLSX.utils.json_to_sheet(json)
XLSX.utils.book_append_sheet(wb, ws, sheetName)
const wbout = XLSX.write(wb, {
bookType: 'xlsx',
bookSST: false,
type: 'binary'
})
saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), filename)
}
const types = require('../actions/actionTypes');
const Cookies = require('js-cookie');
const moment = require('moment');
const _ = require('lodash');
const defaultData = {
status: 'pending', // waiting login,
users:[],
range:[moment().subtract(6,'days').format('YYYYMMDD'), moment().format('YYYYMMDD')]
};
module.exports = function data (state = defaultData, action) {
switch (action.type) {
case types.MAINDATA:
return _.assign({}, state, {status: action.status,userCount:action.data.userCount,upCount:action.data.upCount, users: action.data.users,upstreams:action.data.upstreams,range: action.data.range});
case types.COUNTDATA:
return _.assign({}, state, {count:action.data});
case types.DETAILDATA:
return _.assign({}, state, {status: action.status,detail:action.data});
case types.STATUS:
return _.assign({}, state, {status: action.status});
default:
return state;
}
};
const redux = require('redux');
const loginReducer = require('./loginReducer');
const menuReducer = require('./menuReducer');
const dataReducer = require('./dataReducer');
const rootReducer = redux.combineReducers({
login: loginReducer,
menu: menuReducer,
data: dataReducer
});
module.exports = rootReducer;
const types = require('../actions/actionTypes');
const Cookies = require('js-cookie');
const _ = require('lodash');
const defaultData = {
status: Cookies.get('sess') ? 'login' : 'logout', // waiting login,
user: {
username: Cookies.get('username'),
password: null
}
};
module.exports = function login (state = defaultData, action) {
switch (action.type) {
case types.LOGINSTATUS:
return _.assign({}, state, {session: action.session, status: action.status, user: action.user});
default:
return state;
}
};
const types = require('../actions/actionTypes');
const _ = require('lodash');
const mapLocations = ['/manage','/manage/statistics','/manage/setting'];
const key = mapLocations.indexOf(location.pathname);
const defaultData = {
currentPage: key
};
module.exports = function menu (state = defaultData, action) {
switch (action.type) {
case types.CURRENTPAGE:
return _.assign({}, state, {currentPage: action.currentPage});
default:
return state;
}
};
module.exports = {
path:'manage',
component:require('../../jsx/main.jsx'),
indexRoute:{ component:require('../../jsx/statistics/dashboard.jsx') },
childRoutes:[
{
path:'statistics',
component:require('../../jsx/statistics/dashboard.jsx')
},
{
path:'setting',
component:require('../../jsx/setting/agent.jsx')
}
]
}
\ No newline at end of file
module.exports = {
path:'statistics',
getComponent(nextState,cb){
require.ensure([],(require) => {
cb(null,require('../../../jsx/statistics/detail.jsx'))
})
}
}
\ No newline at end of file
'use strict';
module.exports = {
path:'/',
component:require('../../jsx/home.jsx'),
indexRoute:{ component:require('../../jsx/login.jsx') },
childRoutes:[
require('./manageRoute')
]
}
\ No newline at end of file
const React = require('react');
const redux = require('redux');
const rootReducer = require('../reducers');
const createDevTools = require('redux-devtools-ie8').createDevTools;
const LogMonitor = require('redux-devtools-log-monitor-ie8').default;
const DockMonitor = require('redux-devtools-dock-monitor-ie8').default;
import sequenceAction from 'redux-sequence-action';
const thunk = require('redux-thunk').default;
const ReduxDevTools = createDevTools(
<DockMonitor
toggleVisibilityKey = 'ctrl-h'
changePositionKey = 'ctrl-w'
>
<LogMonitor />
</DockMonitor>
) ;
module.exports.configureStore = function configureStore () {
return redux.createStore(
rootReducer,
redux.compose(
redux.applyMiddleware(thunk,sequenceAction),
ReduxDevTools.instrument()
)
)
}
module.exports.ReduxDevTools = ReduxDevTools;
const React = require('react');
const Home = React.createClass({
render() {
return (
<div className = 'wrapper' style={{ height:'100%'}}>
{this.props.children}
</div>
);
}
});
Home.propTypes = {
children: React.PropTypes.node
};
Home.defaultProps = {
children: <div></div>
};
module.exports = Home;
const React = require('react');
const connect = require('react-redux').connect;
class Users extends React.Component{
constructor(props){
super(props);
//this.state= { main :"hello" };
}
render(){
return (
<div>{ this.props.list }</div>
)
}
}
function mapStateToProps (state) {
return {
list:state.users.list
}
}
module.exports = connect(mapStateToProps)(Users);
\ No newline at end of file
const React = require('react');
const connect = require('react-redux').connect;
const actions = require('../js/actions');
import {Card, Form, Icon, Input, Button, Checkbox} from 'antd';
const FormItem = Form.Item;
class Login extends React.Component{
constructor(props){
super(props);
}
componentWillMount(){
if(this.props.login && this.props.login.status == 'login')
location.href = '/manage'
const { dispatch } = this.props;
}
hasErrors(fieldsError) {
return Object.keys(fieldsError).some(field => fieldsError[field]);
}
handleSubmit(e){
e.preventDefault();
var data = {};
this.props.form.validateFields((err, values) => {
if (!err) {
data = values;
this.props.dispatch(actions.getSession(data));
}
});
}
render(){
const { getFieldDecorator , getFieldsError } = this.props.form;
return (
<div className = 'login-wrapper'>
<Card
className = { 'm' }
title = { '淘口令后台' }
extra = { <span>登陆</span> }
style = {{ width:400,margin:'auto' }}
>
<Form className='login-form' onSubmit = { this.handleSubmit.bind(this) }>
<FormItem>
{ getFieldDecorator('username', {
rules: [{ required: true, message: '请输入正确账号' }],
})(
<Input prefix={<Icon type='user' style={{ fontSize: 13 }} />} placeholder='username' />
)}
</FormItem>
<FormItem>
{getFieldDecorator('password', {
rules: [{ required: true, message: '请输入密码' }],
})(
<Input prefix={<Icon type='lock' style={{ fontSize: 13 }} />} type='password' placeholder='password' />
)}
</FormItem>
<FormItem>
<Button
className='login-form-button'
type='primary'
htmlType='submit'
>
登陆
</Button>
</FormItem>
</Form>
</Card>
</div>
)
}
}
function mapStateToProps (state) {
return state;
}
module.exports = connect(mapStateToProps)(Form.create()(Login));
\ No newline at end of file
const React = require('react');
const connect = require('react-redux').connect;
const actions = require('../js/actions');
import { Menu,Icon,Button,Layout,Breadcrumb} from 'antd';
const SubMenu = Menu.SubMenu;
const MenuItemGroup = Menu.ItemGroup;
const ButtonGroup = Button.Group;
const { Header, Footer, Sider, Content } = Layout;
const mapLocations = ['/manage','/manage/statistics','/manage/setting']
class Main extends React.Component{
constructor(props){
super(props);
this.map = ['数据统计','数据统计','配置']
this.state = {
current: '0',
openKeys: [],
theme: 'dark'
}
}
handleClick(e){
//this.props.dispatch(actions.getMenu());
location.href = mapLocations[ e.key ];
}
onOpenChange(openKeys){
this.setState({ openKeys: openKeys });
}
componentWillMount(){
if(this.props.login && this.props.login.status == 'logout')
location.href = '/'
const { dispatch } = this.props;
}
render(){
console.log(this.props.menu.currentPage);
return (
<Layout className="layout">
<Header>
<div className="logo" >
<span>淘口令</span>
</div>
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys = {[ this.props.menu.currentPage ]}
onClick={ this.handleClick.bind(this) }
style={{ lineHeight: '64px' }}
>
<SubMenu title={<span>数据统计</span>}>
<Menu.Item key="0">口令数据</Menu.Item>
<Menu.Item key="1">详细数据</Menu.Item>
</SubMenu>
<Menu.Item key="2">配置</Menu.Item>
</Menu>
</Header>
<Content style={{ padding: '0 50px' }}>
<Breadcrumb style={{ margin: '12px 0' }}>
<Breadcrumb.Item>{ this.map[ this.props.menu.currentPage ]}</Breadcrumb.Item>
<Breadcrumb.Item>{ this.props.menu.currentPage == '0' ? '基础数据' : (this.props.menu.currentPage == '1' ? '详细数据' : "账户与配置" )}</Breadcrumb.Item>
</Breadcrumb>
<div style={{ background: '#fff', padding: 24, minHeight: 280 }}>{
this.props.children
}</div>
</Content>
<Footer style={{ textAlign: 'center' }}>
xiaoyun.com ©2017 Created by xiaoyun
</Footer>
</Layout>
)
}
}
function mapStateToProps (state) {
return state;
}
module.exports = connect(mapStateToProps)(Main);
\ No newline at end of file
const React = require('react');
class Agent extends React.Component{
constructor(props){
super(props);
}
render(){
return (
<div>agent</div>
)
}
}
module.exports = Agent
\ No newline at end of file
const React = require('react');
/*const connect = require('react-redux').connect;
const actions = require('../../js/actions');*/
const moment = require('moment');
const api = require('../../js/api');
import json2xlsx from '../../js/json2xlsx';
import { Table, Icon, DatePicker, Alert, Row, Col, Spin, Button} from 'antd';
const { RangePicker } = DatePicker;
class DashBoard extends React.Component{
constructor(props){
super(props);
this.range = [moment().subtract(6,'days').format('YYYYMMDD'), moment().format('YYYYMMDD')];
this.state= { logs :[],status:'pending' };
}
componentDidMount(){
let data = { start:moment().add(-6,'days').format('YYYYMMDD'),end:moment().format('YYYYMMDD')};
api('GET', 'logs').then((res) => {
this.setState({logs:res.result,status:'ready'})
console.dir(res.result);
});
}
onChange(date, dateString) {
let data = { start:dateString[0],end:dateString[1]};
//this.props.dispatch(actions.getMainData(data));
}
exportData(){
//json2xlsx(data,{sheetName:"基础数据", filename : '基础数据'+moment().format('YYYYMMDD')+'.xlsx'});
}
render(){
const columns = [
{
title: '日期',
dataIndex: 'date',
key: 'date',
width: 100,
render: text => <a href="#">{text}</a>,
},
{
title: '淘口令',
dataIndex: 'info',
key: 'info',
width: 100,
render: text => <a href="#">{text}</a>,
},{
title: '请求数',
dataIndex: 'times',
key: 'times',
width: 100,
render: text => <a href="#">{text}</a>,
},
{
title: '渠道',
dataIndex: 'qd',
key: 'qd',
width: 100,
render: text => <a href="#">{text}</a>,
},{
title: '最近更新',
dataIndex: 'update',
key: 'update',
width: 100,
render: text => <a href="#">{text}</a>,
}
];
let range = this.range;
var start = range[0];
var end = range[1];
let ranges = [];
ranges.push(moment(start,'YYYYMMDD'));
ranges.push(moment(end,'YYYYMMDD'));
let data = [];
let count = 0;
let logs = this.state.logs;
for(let i = 0;i<logs.length;i++){
data.push({
key:i,
date:logs[i].date,
info:logs[i].key,
times:logs[i].times,
qd:(logs[i].qd && logs[i].qd['user']) || '--',
update:logs[i].updatedAt
});
}
return (
<div>
<RangePicker onChange={ this.onChange.bind(this) } value={ ranges } format={'YYYYMMDD'} style={{margin:'10px 0px'}}/>
<Button type="primary" icon="export" onClick={ this.exportData.bind(this) } style={{ float:'right',margin:'10px 0px'}}>
导出数据
</Button>
<Spin spinning= { this.state.status == 'pending' }>
<Table columns={columns} dataSource = { data } size="middle" bordered/>
</Spin>
</div>
)
}
}
/*
function mapStateToProps (state) {
return state;
}
module.exports = connect(mapStateToProps)(DashBoard);*/
module.exports = DashBoard;
module.exports = {
host: '0.0.0.0',
port: process.env.PORT ? process.env.PORT : 9401,
mongo:'mongodb://127.0.0.1:27017/taoarticle'
};
\ No newline at end of file
module.exports = {
host: '0.0.0.0',
port: process.env.PORT ? process.env.PORT : 9401,
mongo:'mongodb://user:password@mongo-gp-content-distribution-1.localhost:1302,mongo-gp-content-distribution-2.localhost:1302,mongo-gp-content-distribution-3.localhost:1302/distribution?replicaSet=gp-content-aiweibang'
};
\ No newline at end of file
'use strict';
try {
module.exports = require('./config.default.js');
} catch (err) {
module.exports = require('./config.default.js');
}
\ No newline at end of file
const hash = require('../../utils/hash');
const mongoose = require('mongoose');
const {ObjectId} = mongoose.SchemaTypes;
const session = mongoose.Schema({
user:{
type: ObjectId,
ref: 'tao-agent'
}
}, {
timestamps: true
});
// user.pre('save', async function (next) {
// if (!this.isNew) return next();
// this.id = await module.exports.count() + 1;
// next();
// });
module.exports = mongoose.model('session', session);
const mongoose = require('mongoose');
const hash = require('../../utils/hash');
const {ObjectId} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
user: {
type: String,
unique: true,
required: true
},
password:{
type: String,
required: true,
set: v => hash(v)
},
role: {
type: String,
required: true
}
}, {
timestamps: true
});
schema.index({user: 1});
module.exports = mongoose.model('tao-agent', schema);
const mongoose = require('mongoose');
const {ObjectId} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
info: {
type: String,
required: true
},
creater:{
type:ObjectId,
required: true,
ref:'tao-agent'
},
status:{
type: String,
required: true
}
}, {
timestamps: true
});
schema.index({info: 1});
module.exports = mongoose.model('tao-kouling', schema);
const mongoose = require('mongoose');
const {ObjectId} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
key: {
type: String,
required: true
},
qd:{
type:ObjectId,
required: true,
ref:'tao-agent'
},
times:{
type:Number,
required: true
},
date:{
type:String,
required: true
},
}, {
timestamps: true
});
schema.index({info: 1});
module.exports = mongoose.model('tao-log', schema);
const tao = require('./tao');
var mongoose = require('mongoose');
var moment = require('moment');
var log = require('../db/mongo/tao-log');
exports.putAgent = async (req, res, next) => {
console.dir('iniinn')
let {user,password,role = 'channel'} = req.body;
if(!user || !password) res.status(400).send('params not full error');
else{
var u = await agent.findOne({user:user});
if(!u)
tao.saveAgent({user,password,role},function(e,result){
res.send({status:'ok',result:result});
});
else
res.status(400).send('already exsits error');
}
}
exports.putTbkl = async (req, res, next) => {
let {info,creater,status = 'use'} = req.body;
if(!info || !creater) res.status(400).send('params not full error');
else{
var kl = await kouling.findOne({info:info});
creater = mongoose.Types.ObjectId(creater);
if(!kl)
tao.saveKouling({info,creater,status},function(e,result){
res.send({status:'ok',result:result});
});
else
res.status(400).send('already exsits error');
}
};
exports.logs = async (req, res, next) => {
var options = {limit: 1000, skip: 0, sort: {'updatedAt':-1}};
var logs = await log.find({},null,options).populate('qd','user role');
logs = logs.map(x => { var d = x.toJSON();d['updatedAt'] = moment(new Date(d['updatedAt']).getTime(),'x').format('YYYYMMDD HH:mm:ss');return d;});
res.send({ status:'ok',result:logs });
}
\ No newline at end of file
// const cron = require('cron');
// const UserAuth = require('../db/mongo/user-auto-auth');
// const UserAuthLog = require('../db/mongo/user-auto-used-log');
// const nodemailer = require('nodemailer');
// const _ = require('lodash');
// const moment = require('moment');
// var CronJob = cron.CronJob;
// var job = new CronJob({
// cronTime: '00 00 00 * * 0-6',
// onTick: function() {
// clearUserAuths();
// },
// start: false,
// });
// async function sendMail(email,body) {
// var smtpTransport = nodemailer.createTransport({
// auth: {
// user: "liusong@goyoo.com",
// pass: "323609zhang"
// },
// host: 'smtp.exmail.qq.com',
// port: 465
// });
// var mailOptions = {
// from: "liusong@goyoo.com",
// to: email, //发给谁
// subject: '小云蜂巢定时任务错误', //主题
// text: body
// };
// smtpTransport.sendMail(mailOptions, function (err, response) {
// if (!err) {
// console.log('发送邮件成功');
// } else {
// console.log('发送邮件失败,请重试');
// }
// });
// }
// async function clearUserAuths () {
// console.log('定时更新开始 =====> ');
// try {
// let userAuths = await UserAuth.find({}).limit(500);
// userAuths.forEach( async item => {
// let log = item.toJSON();
// if(moment(log['updatedAt']).format('YYYYMMDD') !== moment().format('YYYYMMDD')){
// let auth = new UserAuthLog(_.omit(log, ['_id', 'createdAt', 'updatedAt']));
// await auth.save();
// }else{
// console.log('skip job');
// }
// });
// let data = {
// '$set':{
// used: 0
// }
// };
// await UserAuth.update({}, data, {multi:true});
// } catch (err) {
// console.dir(err);
// console.dir('更新异常 =====>');
// let mailList = 'liusong@goyoo.com';
// sendMail(mailList, err.toString());
// }
// console.log(' 更新结束 ');
// }
// module.exports.start = function ()
// {
// job.start();
// };
const express = require('request-promise');
const crypto = require('crypto');
const agent = require('../db/mongo/tao-agent');
const session = require('../db/mongo/session');
const _ = require('lodash');
exports.login = async (req,res,next) => {
let {username,password} = req.body;
console.dir(crypto.createHash('md5').update(password).digest('hex'));
let user = await agent.findOne({user:username,password:crypto.createHash('md5').update(password).digest('hex')});
console.dir(user);
if(user){
let sess = { user: user._id};
const _sess = await new session(sess).save();
res.cookie('sess',_sess._id+'');
res.cookie('username',username);
res.send({result: 'ok'});
}
else
res.status(500).send({result:'密码不正确'});
};
\ No newline at end of file
var config = require('../config/index');
var Agent = require('../db/mongo/tao-agent');
var Kouling = require('../db/mongo/tao-kouling');
var log = require('../db/mongo/tao-log');
var mongoose = require('mongoose');
exports.saveKouling = async (data,cb) => {
try {
var kouling = new Kouling(data);
cb(null,await kouling.save());
} catch(e){
cb(e);
}
}
exports.saveAgent = async (data,cb) => {
try {
var agent = new Agent(data);
cb(null,await agent.save())
} catch(e){
cb(e);
}
}
exports.findAgent = async (qs,cb) => {
try {
cb(null,await Agent.find(qs))
} catch(e){
cb(e);
}
}
exports.findKouling = async (qs,cb) => {
try {
cb(null,await Kouling.find(qs))
} catch(e){
cb(e);
}
}
{
"name": "fengchao-admin",
"version": "0.0.1",
"description": "console with react es6 ,es7",
"scripts": {
"build": "webpack --config webpack.config.js && node app.js",
"start": "node app.js"
},
"dependencies": {
"antd": "^2.12.5",
"babel-plugin-import": "^1.1.1",
"babel-polyfill": "^6.23.0",
"bluebird": "^3.5.0",
"body-parser": "^1.17.2",
"cookie-parser": "^1.4.3",
"cookie-session": "^1.3.0",
"cron": "^1.2.1",
"es6-promise": "^4.0.5",
"eslint-plugin-react": "^7.1.0",
"express": "^4.14.1",
"file-saver": "^1.3.3",
"jquery": "^3.2.1",
"js-cookie": "^2.1.4",
"lodash": "^4.17.4",
"moment": "^2.18.1",
"mongoose": "^4.11.5",
"morgan": "^1.8.1",
"nodemailer": "^4.0.1",
"react": "^0.14.7",
"react-dom": "^0.14.7",
"react-redux": "^4.4.0",
"react-router": "2.0.1",
"react-router-redux-ie8": "0.0.3",
"react-tap-event-plugin": "^0.2.2",
"redux": "^3.3.1",
"redux-devtools-ie8": "0.0.1",
"redux-sequence-action": "^0.2.1",
"redux-thunk": "^2.2.0",
"request": "^2.81.0",
"request-promise": "^4.2.1",
"xlsx": "^0.11.3"
},
"devDependencies": {
"babel-core": "^6.4.5",
"babel-loader": "^6.2.1",
"postcss-cssnext": "^2.4.0",
"postcss-loader": "^0.8.0",
"postcss-scss": "^0.1.3",
"sass-loader": "^3.1.2",
"style-loader": "^0.13.0",
"css-loader": "^0.23.1",
"babel-plugin-import": "^1.0.1",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"babel-preset-stage-0": "^6.3.13",
"webpack": "^2.2.1",
"redux-devtools": "^3.0.0",
"redux-devtools-log-monitor": "^1.0.1",
"redux-devtools-dock-monitor-ie8": "0.0.2",
"redux-devtools-ie8": "0.0.1",
"redux-devtools-log-monitor-ie8": "0.0.1"
}
}
'use strict';
var express = require('express');
var router = express.Router();
var controller = require( '../lib/controller.js' );
var session = require( '../lib/session.js' );
router.get('/logs',controller.logs);
router.post('/agent',controller.putAgent);
router.post('/tbkl',controller.putTbkl);
router.post('/session',session.login);
module.exports = router;
\ No newline at end of file
const crypto = require('crypto');
module.exports = (str, algo = 'sha256') => {
if (!str) return '';
const hash = crypto.createHash(algo);
hash.update(str);
return hash.digest('hex');
};
'use strict'
var webpack = require('webpack');
var commonChunkPlugin = webpack.optimize.CommonsChunkPlugin;
module.exports = {
entry:{
app:['./app/js/index.js'],
common: ['react', 'react-dom', 'jquery','lodash', 'redux', 'react-router', 'react-redux', 'react-router-redux-ie8']
},
output:{
path:__dirname + '/app/built',
publicPath: '/app/built/',
filename:'[name].bundle.js',
chunkFilename: '[id].chunk.js'
},
module:{
loaders:[
{
test: /\.jsx?$/,
loaders: ['babel-loader?cacheDirectory=' + __dirname + '/babelCache'],//babel缓存后 编译缩短至2s
exclude: /node_modules|vendors/
},
{ test: /\.less$/,
loader: 'style-loader!css-loader!less-loader'
}, // use ! to chain loaders
{ test: /\.css$/,
loader: 'style-loader!css-loader!postcss-loader'
}
]
},
plugins:[
new commonChunkPlugin({ name: 'common' }),
new webpack.BannerPlugin('This file is created by phyllis'),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
drop_console: false
}
})
]
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment