Commit fb25906a authored by 刘松's avatar 刘松

增加定时任务

parent e6497245
......@@ -12,6 +12,7 @@ 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
......@@ -51,3 +52,4 @@ app.use(routes);
app.listen(config.port);
console.log('server started on port ' + config.port);
cron.start();
/*! 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)}});
\ No newline at end of file
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 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.
......@@ -13,7 +13,9 @@ const defaultData = {
detail:{
pagination:{ current:1, total:1, pageSize:3 },
users:[],
upstreams:[]
upstreams:[],
auths:[],
unbindhistorys:[]
},
range:[moment().subtract(6,'days').format('YYYYMMDD'), moment().format('YYYYMMDD')]
};
......
......@@ -6,6 +6,10 @@ module.exports = {
{
path:'statistics',
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{
width: 100,
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: '注册时间',
dataIndex: 'date',
......@@ -56,15 +70,30 @@ class Detail extends React.Component{
render: text => <a href="#">{text}</a>,
},
];
let pluginMap = {
''
}
let users = this.props.data.detail ? this.props.data.detail.users : [];
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 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 < 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++){
let item = users[i];
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');
const user = require('../db/mongo/user');
const upstream = require('../db/mongo/upstream');
const moment = require('moment');
const UserAuth = require('../db/mongo/user-auto-auth');
const UpstreamUnbindHistory = require('../db/mongo/upstream-unbind-history');
const mongoose = require('mongoose');
exports.data = 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 ) {
console.dir(err);
res.status(400);
......
......@@ -14,6 +14,7 @@
"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",
......@@ -23,6 +24,7 @@
"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",
......
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