Commit fb25906a authored by 刘松's avatar 刘松

增加定时任务

parent e6497245
...@@ -12,6 +12,7 @@ const cookieParser = require('cookie-parser'); ...@@ -12,6 +12,7 @@ const cookieParser = require('cookie-parser');
const session = require('cookie-session'); const session = require('cookie-session');
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const sessions = require('./db/mongo/session'); const sessions = require('./db/mongo/session');
const cron = require('./lib/cron');
const options = { const options = {
useMongoClient: true useMongoClient: true
...@@ -51,3 +52,4 @@ app.use(routes); ...@@ -51,3 +52,4 @@ app.use(routes);
app.listen(config.port); app.listen(config.port);
console.log('server started on port ' + config.port); console.log('server started on port ' + config.port);
cron.start();
/*! This file is created by phyllis */ /*! This file is created by phyllis */
webpackJsonp([0],{1708: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 e}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(108).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,"detail")}}]),t}(f.Component);e.exports=a(u)(l)}}); 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 \ No newline at end of file
This diff is collapsed.
This diff is collapsed.
...@@ -13,7 +13,9 @@ const defaultData = { ...@@ -13,7 +13,9 @@ const defaultData = {
detail:{ detail:{
pagination:{ current:1, total:1, pageSize:3 }, pagination:{ current:1, total:1, pageSize:3 },
users:[], users:[],
upstreams:[] upstreams:[],
auths:[],
unbindhistorys:[]
}, },
range:[moment().subtract(6,'days').format('YYYYMMDD'), moment().format('YYYYMMDD')] range:[moment().subtract(6,'days').format('YYYYMMDD'), moment().format('YYYYMMDD')]
}; };
......
...@@ -6,6 +6,10 @@ module.exports = { ...@@ -6,6 +6,10 @@ module.exports = {
{ {
path:'statistics', path:'statistics',
component:require('../../jsx/statistics/detail.jsx') component:require('../../jsx/statistics/detail.jsx')
},
{
path:'setting',
component:require('../../jsx/setting/account.jsx')
} }
] ]
} }
\ No newline at end of file
const React = require('react');
const connect = require('react-redux').connect;
const actions = require('../../js/actions');
const types = require('../../js/actions/actionTypes');
const moment = require('moment');
import { Table, Spin} from 'antd';
class Detail extends React.Component{
constructor(props){
super(props);
// this.state= { pagination : { current: 0,total: 0} };
}
componentDidMount (){
let limit = 30;
let skip = 0;
//await this.props.dispatch({status:'pending',type:types.DETAILDATA});
this.props.dispatch(actions.getDetailData({limit,skip}));
}
handleTableChange (pagination, filters, sorter) {
const pager = this.props.data.detail.pagination;
pager.current = pagination.current;
this.props.dispatch(actions.getDetailData({limit: 30,skip: parseInt(pager.current)-1 }));
}
render(){
const columns = [
{
title: '自动发文-百度',
children:[
{
title: '新增',
dataIndex: 'useradd',
key: 'useradd',
width: 100,
render: text => <a href="#">{text}</a>,
},
{
title: '合计',
dataIndex: 'usertotal',
key: 'usertotal',
width: 100,
render: text => <a href="#">{text}</a>,
}
]
},
{
title: '自动发文-网易',
children:[
{
title: '新增',
dataIndex: 'upstreamadd',
key: 'upstreamadd',
width: 100,
render: text => <a href="#">{text}</a>,
},
{
title: '合计',
dataIndex: 'upstreamtotal',
key: 'upstreamtotal',
width: 100,
render: text => <a href="#">{text}</a>,
}]
},{
title: '操作',
dataIndex: 'operation',
key: 'operation',
width: 100,
render: text => <a href="/manage/" >{ '详细' }</a>,
}
]
let users = this.props.data.detail ? this.props.data.detail.users : [];
let upstreams = this.props.data.detail ? this.props.data.detail.upstreams : [];
let upMap = {};
let data = [];
for(let i = 0;i < upstreams.length; i++){
let id = upstreams[i]['_id']['creater'];
upMap[id] = upstreams[i]['count'];
}
for(let i = 0;i < users.length; i++){
let item = users[i];
data.push({
key : i,
name : item['username'] || '-',
phone : item['phone'] || '-',
ups : upMap[ item['_id'] ] || 0,
date : moment(item['createdAt']).format('YYYY/MM/DD HH:mm:ss')
})
}
return (
<Spin spinning= { this.props.data.status == 'pending' }>
<Table columns={columns} dataSource = { data } pagination={ this.props.data.detail.pagination } size="middle" onChange = { this.handleTableChange.bind(this) } bordered/>
</Spin>
)
}
}
function mapStateToProps (state) {
return state;
}
module.exports = connect(mapStateToProps)(Detail);
\ No newline at end of file
...@@ -48,6 +48,20 @@ class Detail extends React.Component{ ...@@ -48,6 +48,20 @@ class Detail extends React.Component{
width: 100, width: 100,
render: text => <a href="#">{text}</a>, render: text => <a href="#">{text}</a>,
}, },
{
title: '解绑记录',
dataIndex: 'upsunbind',
key: 'upsunbind',
width: 100,
render: text => <a href="#">{text}</a>,
},
{
title: '充值记录',
dataIndex: 'charges',
key: 'charges',
width: 100,
render: text => <a href="#">{text}</a>,
}
{ {
title: '注册时间', title: '注册时间',
dataIndex: 'date', dataIndex: 'date',
...@@ -56,15 +70,30 @@ class Detail extends React.Component{ ...@@ -56,15 +70,30 @@ class Detail extends React.Component{
render: text => <a href="#">{text}</a>, render: text => <a href="#">{text}</a>,
}, },
]; ];
let pluginMap = {
''
}
let users = this.props.data.detail ? this.props.data.detail.users : []; let users = this.props.data.detail ? this.props.data.detail.users : [];
let upstreams = this.props.data.detail ? this.props.data.detail.upstreams : []; let upstreams = this.props.data.detail ? this.props.data.detail.upstreams : [];
let auths = this.props.data.detail ? this.props.data.detail.auths : [];
let unbindhistorys = this.props.data.detail ? this.props.data.detail.unbindhistorys : [];
let upMap = {}; let upMap = {};
let data = []; let data = [];
for(let i = 0;i < upstreams.length; i++){ for(let i = 0;i < upstreams.length; i++){
let id = upstreams[i]['_id']['creater']; let id = upstreams[i]['_id']['creater'];
upMap[id] = upstreams[i]['count']; upMap[id] = upstreams[i]['count'];
} }
for(let i = 0;i < auths.length; i++){
let id = upstreams[i]['_id']['creater'];
upMap[id] = upstreams[i]['count'];
}
for(let i = 0;i < unbindhistorys.length; i++){
let id = upstreams[i]['_id']['creater'];
upMap[id] = upstreams[i]['count'];
}
for(let i = 0;i < users.length; i++){ for(let i = 0;i < users.length; i++){
let item = users[i]; let item = users[i];
data.push({ data.push({
......
const mongoose = require('mongoose');
const {ObjectId} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
userId: {
type: ObjectId,
ref: 'user',
required: true
},
platform: {
type: String,
required: false
},
nickname: {
type: String,
required: false
},
category: {
type: String,
required: false
}
}, {
timestamps: true
});
schema.index({userId: 1});
module.exports = mongoose.model('upstream-unbind-history', schema);
const mongoose = require('mongoose');
const {ObjectId} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
category: {
type: Array,
default: []
},
userId: {
type: ObjectId,
ref: 'user',
required: true
},
times: {
type: Number,
default: 0,
required: true
},
used: {
type: Number,
default: 0,
required: false
},
plugin: {
type: String,
required: false
}
}, {
timestamps: true
});
schema.index({userId: 1});
schema.index({times: 1});
schema.index({category: 1});
module.exports = mongoose.model('user-auto-auth', schema);
const mongoose = require('mongoose');
const {ObjectId} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
userId: {
type: ObjectId,
ref: 'user',
required: true
},
times: {
type: Number,
default: 0,
required: true
},
used: {
type: Number,
default: 0,
required: false
},
plugin: {
type: String,
required: false
}
}, {
timestamps: true
});
schema.index({userId: 1});
module.exports = mongoose.model('user-auto-used-log', schema);
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();
let auth = new UserAuthLog(_.omit(log, ['_id', 'createdAt', 'updatedAt']));
await auth.save();
});
let data = {
'$set':{
used: 0
}
};
await UserAuth.update({}, data, {multi:true});
throw new Error('错误');
} catch (err) {
console.dir(err);
console.dir('更新异常 =====>');
let mailList = 'liusong@goyoo.com';
sendMail(mailList, err.toString());
}
console.log(' 更新结束 ');
}
module.exports.start = function ()
{
job.start();
};
...@@ -2,6 +2,9 @@ const express = require('request-promise'); ...@@ -2,6 +2,9 @@ const express = require('request-promise');
const user = require('../db/mongo/user'); const user = require('../db/mongo/user');
const upstream = require('../db/mongo/upstream'); const upstream = require('../db/mongo/upstream');
const moment = require('moment'); const moment = require('moment');
const UserAuth = require('../db/mongo/user-auto-auth');
const UpstreamUnbindHistory = require('../db/mongo/upstream-unbind-history');
const mongoose = require('mongoose'); const mongoose = require('mongoose');
exports.data = async (req,res,next) => { exports.data = async (req,res,next) => {
...@@ -82,8 +85,20 @@ exports.detail = async(req,res,next) => { ...@@ -82,8 +85,20 @@ exports.detail = async(req,res,next) => {
} }
} }
]; ];
const upstreams = await upstream.aggregate(pipeline);
res.send({result: 'ok' ,data: { users: users.map(x => x.toJSON()), upstreams: upstreams, pagination:{ current:parseInt(skip)+1,total: total, pageSize:parseInt(limit)}}}) const upstreamPromise = await upstream.aggregate(pipeline);
const authPromise = await UserAuth.find({userId: {'$in': creaters}});
const upstreamUnbindHistoryPromise = await UpstreamUnbindHistory.find({userId: {'$in': creaters}});
let upstreams = [];
let auths = [];
let unbindhistorys = []
await Promise.all([upstreamPromise, authPromise, upstreamUnbindHistoryPromise]).then( ([_upstreams, _auths, _unbindhistorys]) => {
upstreams = _upstreams;
auths = _auths;
unbindhistorys = _unbindhistorys;
});
res.send({result: 'ok' ,data: { users: users.map(x => x.toJSON()), upstreams: upstreams,auths: auths,unbindhistorys: unbindhistorys, pagination:{ current:parseInt(skip)+1,total: total, pageSize:parseInt(limit)}}})
} catch ( err ) { } catch ( err ) {
console.dir(err); console.dir(err);
res.status(400); res.status(400);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"body-parser": "^1.17.2", "body-parser": "^1.17.2",
"cookie-parser": "^1.4.3", "cookie-parser": "^1.4.3",
"cookie-session": "^1.3.0", "cookie-session": "^1.3.0",
"cron": "^1.2.1",
"es6-promise": "^4.0.5", "es6-promise": "^4.0.5",
"eslint-plugin-react": "^7.1.0", "eslint-plugin-react": "^7.1.0",
"express": "^4.14.1", "express": "^4.14.1",
...@@ -23,6 +24,7 @@ ...@@ -23,6 +24,7 @@
"moment": "^2.18.1", "moment": "^2.18.1",
"mongoose": "^4.11.5", "mongoose": "^4.11.5",
"morgan": "^1.8.1", "morgan": "^1.8.1",
"nodemailer": "^4.0.1",
"react": "^0.14.7", "react": "^0.14.7",
"react-dom": "^0.14.7", "react-dom": "^0.14.7",
"react-redux": "^4.4.0", "react-redux": "^4.4.0",
......
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