Commit 1ae7fe7b authored by 刘松's avatar 刘松

cronjob & fix

parent 6c14d914
...@@ -51,4 +51,4 @@ app.use(routes); ...@@ -51,4 +51,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();*/ cron.start();
This diff is collapsed.
This diff is collapsed.
...@@ -72,16 +72,16 @@ class Schedule extends React.Component{ ...@@ -72,16 +72,16 @@ class Schedule extends React.Component{
const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched } = this.props.form; const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched } = this.props.form;
const columns = [ const columns = [
{ {
title: '推广名称', title: '分发ID',
dataIndex: 'name', dataIndex: 'id',
key: 'name', key: 'id',
width: 100, width: 100,
render: text => <span href="#">{text}</span>, render: text => <span href="#">{text}</span>,
}, },
{ {
title: '推广链接', title: '推广页名称',
dataIndex: 'target', dataIndex: 'names',
key: 'target', key: 'names',
width: 100, width: 100,
render: text => <span href="#">{text}</span>, render: text => <span href="#">{text}</span>,
}, },
...@@ -92,6 +92,13 @@ class Schedule extends React.Component{ ...@@ -92,6 +92,13 @@ class Schedule extends React.Component{
width: 100, width: 100,
render: text => <span href="#">{text}</span>, render: text => <span href="#">{text}</span>,
}, },
{
title: '状态',
dataIndex: 'status',
key: 'status',
width: 100,
render: text => <span href="#">{text}</span>,
},
{ {
title: '推广次数', title: '推广次数',
dataIndex: 'times', dataIndex: 'times',
...@@ -110,10 +117,16 @@ class Schedule extends React.Component{ ...@@ -110,10 +117,16 @@ class Schedule extends React.Component{
let data = []; let data = [];
let schedules = this.state.schedules; let schedules = this.state.schedules;
for(let i = 0;i<schedules.length;i++){ for(let i = 0;i<schedules.length;i++){
let links = schedules[i].links;
var names = "";
links.forEach(function(link) {
names += (" " + link['name']);
});
data.push({ data.push({
key:i, key:i,
name:schedules[i].taolink && schedules[i].taolink['name'] || '--', id:schedules[i]._id,
target:schedules[i].taolink && schedules[i].taolink['target'] || '--', names:names || '--',
status:schedules[i].status == 'use' ? '进行中' : '已暂停',
qd:schedules[i].qd && schedules[i].qd['user'] || '--', qd:schedules[i].qd && schedules[i].qd['user'] || '--',
times:schedules[i].times, times:schedules[i].times,
create:schedules[i].createdAt create:schedules[i].createdAt
...@@ -136,10 +149,10 @@ class Schedule extends React.Component{ ...@@ -136,10 +149,10 @@ class Schedule extends React.Component{
> >
<Form onSubmit={this.handleSubmit.bind(this)} className="login-form"> <Form onSubmit={this.handleSubmit.bind(this)} className="login-form">
<FormItem> <FormItem>
{getFieldDecorator('name', { {getFieldDecorator('names', {
rules: [{ required: true, message: '推广名称不能为空' }], rules: [{ required: true, message: '推广名称不能为空' }],
})( })(
<Input prefix={<span style={{ fontSize: 13 }}>推广名称</span>} placeholder="例如:推广1" /> <Input prefix={<span style={{ fontSize: 13 }}>推广名称</span>} placeholder="例如:商品1@商品2@商品3" />
)} )}
</FormItem> </FormItem>
<FormItem> <FormItem>
......
...@@ -71,7 +71,7 @@ class Agent extends React.Component{ ...@@ -71,7 +71,7 @@ class Agent extends React.Component{
const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched } = this.props.form; const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched } = this.props.form;
const columns = [ const columns = [
{ {
title: '推广名称', title: '推广名称',
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
width: 100, width: 100,
...@@ -167,7 +167,7 @@ class Agent extends React.Component{ ...@@ -167,7 +167,7 @@ class Agent extends React.Component{
<Form onSubmit={this.handleSubmit.bind(this)} className="login-form"> <Form onSubmit={this.handleSubmit.bind(this)} className="login-form">
<FormItem> <FormItem>
{getFieldDecorator('name', { {getFieldDecorator('name', {
rules: [{ required: true, message: '推广名称不能为空' }], rules: [{ required: true, message: '推广名称不能为空' }],
})( })(
<Input prefix={<span style={{ fontSize: 13 }}>推广名称</span>} placeholder="例如:推广1" /> <Input prefix={<span style={{ fontSize: 13 }}>推广名称</span>} placeholder="例如:推广1" />
)} )}
......
const React = require('react'); const React = require('react');
const moment = require('moment');
const api = require('../../js/api');
import json2xlsx from '../../js/json2xlsx';
import {Card, Form, Icon, Input, Button, Checkbox} from 'antd'; import { Table, Icon, DatePicker, Alert, Row, Col, Spin, Button} from 'antd';
const { RangePicker } = DatePicker;
const FormItem = Form.Item; class Tbkls extends React.Component{
class Tbkl extends React.Component{
constructor(props){ constructor(props){
super(props); super(props);
console.dir(this.props);
this.state= { tbkls :[],status:'pending',pagination:{current:1,pageSize:10,total:100},modalVisible:false,username:'channel'};
}
componentDidMount(){
let pagination = this.state.pagination;
if(document.cookie.match('username=[a-zA-Z0-9]+')[0] && document.cookie.match('username=[a-zA-Z0-9]+')[0].split('=')[1] == 'admin'){
this.setState({username:'admin'});
}
//let data = { start:moment().add(-6,'days').format('YYYYMMDD'),end:moment().format('YYYYMMDD')};
api('GET', 'tbkls?'+'skip=0&limit=' + pagination.pageSize).then((res) => {
this.setState({tbkls:res.result,status:'ready',pagination:{current:res.pagination.skip,pageSize:res.pagination.limit,total:res.pagination.total},info:{quan:'',good:''}})
console.dir(res.result);
});
}
gettbkls(pagination){
console.dir(pagination);
this.setState({status:'pending'})
api('GET', 'tbkls?'+'skip='+ (pagination.current-1) + '&limit=' + pagination.pageSize).then((res) => {
this.setState({tbkls:res.result,status:'ready'})
console.dir(res.result);
});
}
onChange(pagination) {
this.gettbkls(pagination);
} }
componentWillMount(){
if(this.props.login && this.props.login.status == 'login') exportData(){
location.href = '/manage' //json2xlsx(data,{sheetName:"基础数据", filename : '基础数据'+moment().format('YYYYMMDD')+'.xlsx'});
const { dispatch } = this.props;
} }
render(){ render(){
const columns = [
{
title: '淘口令',
dataIndex: 'info',
key: 'info',
width: 60,
render: text => <span href="#">{text}</span>,
},
{
title: '商品信息',
dataIndex: 'good',
key: 'good',
width: 100,
render: text => <span href="#">{text}</span>,
},
{
title: '推广连接',
dataIndex: 'target',
key: 'target',
width: 100,
render: text => <span href="#">{text}</span>,
},
{
title: '所属计划',
dataIndex: 'schedule',
key: 'schedule',
width: 100,
render: text => <span href="#">{text}</span>,
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
width: 40,
render: text => <span href="#">{text}</span>,
},
{
title: '创建日期',
dataIndex: 'create',
key: 'create',
width: 50,
render: text => <span href="#">{text}</span>,
}
];
let data = [];
let tbkls = this.state.tbkls;
for(let i = 0;i<tbkls.length;i++){
data.push({
key:i,
info:tbkls[i].info ,
good:(tbkls[i].link && tbkls[i].link['title']) || '--',
schedule:tbkls[i].schedule,
target:(tbkls[i].link && tbkls[i].link['target']) || '--',
status:tbkls[i].status == 'use' ? '进行中' : '已失效',
create:tbkls[i].createdAt
});
}
return ( return (
<div>tbkl</div> <div>
<Alert
message="提示"
description="淘口令油后台任务自动生成"
type="info"
/>
<Spin spinning= { this.state.status == 'pending' }>
<Table columns={columns} dataSource = { data } size="middle" pagination={ this.state.pagination } onChange = { this.onChange.bind(this)} bordered/>
</Spin>
</div>
) )
} }
} }
module.exports = Tbkls;
module.exports = Tbkl;
\ No newline at end of file
...@@ -57,11 +57,18 @@ class DashBoard extends React.Component{ ...@@ -57,11 +57,18 @@ class DashBoard extends React.Component{
render: text => <a href="#">{text}</a>, render: text => <a href="#">{text}</a>,
}, },
{ {
title: '渠道', title: '推广计划',
dataIndex: 'qd', dataIndex: 'qd',
key: 'qd', key: 'qd',
width: 100, width: 100,
render: text => <a href="#">{text}</a>, render: text => <a href="#">{text}</a>,
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
width: 100,
render: text => <a href="#">{text}</a>,
},{ },{
title: '最近更新', title: '最近更新',
dataIndex: 'update', dataIndex: 'update',
...@@ -86,7 +93,8 @@ class DashBoard extends React.Component{ ...@@ -86,7 +93,8 @@ class DashBoard extends React.Component{
date:logs[i].date, date:logs[i].date,
info:logs[i].key, info:logs[i].key,
times:logs[i].times, times:logs[i].times,
qd:(logs[i].qd && logs[i].qd['user']) || '--', status:logs[i].status == 'disable' ? '已归档' :'--',
qd:(logs[i].schedule) || '--',
update:logs[i].updatedAt update:logs[i].updatedAt
}); });
} }
......
...@@ -8,16 +8,21 @@ const schema = mongoose.Schema({ ...@@ -8,16 +8,21 @@ const schema = mongoose.Schema({
}, },
creater:{ creater:{
type:ObjectId, type:ObjectId,
required: true, required: false,
ref:'tao-agent' ref:'tao-agent'
}, },
schedule:{
type:ObjectId,
required: true,
ref:'tao-schedule'
},
status:{ status:{
type: String, type: String,
required: true required: true
}, },
good:{ link:{
type:ObjectId, type:ObjectId,
required: false, required: true,
ref:'tao-link' ref:'tao-link'
} }
}, { }, {
......
...@@ -6,15 +6,24 @@ const schema = mongoose.Schema({ ...@@ -6,15 +6,24 @@ const schema = mongoose.Schema({
type: String, type: String,
required: true required: true
}, },
qd:{ schedule:{
type:ObjectId, type:ObjectId,
required: true, required: true,
ref:'tao-agent' ref:'tao-schedule'
},
link: {
type:ObjectId,
required: true,
ref:'tao-link'
}, },
times:{ times:{
type:Number, type:Number,
required: true required: true
}, },
status:{
type:String,
required: false
},
date:{ date:{
type:String, type:String,
required: true required: true
......
...@@ -2,11 +2,7 @@ const mongoose = require('mongoose'); ...@@ -2,11 +2,7 @@ const mongoose = require('mongoose');
const {ObjectId} = mongoose.SchemaTypes; const {ObjectId} = mongoose.SchemaTypes;
const schema = mongoose.Schema({ const schema = mongoose.Schema({
taolink:{ links:[{type: ObjectId, ref: 'tao-link'}],
type:ObjectId,
required: true,
ref:'tao-link'
},
qd:{ qd:{
type:ObjectId, type:ObjectId,
required: true, required: true,
......
...@@ -72,9 +72,9 @@ exports.logs = async (req, res, next) => { ...@@ -72,9 +72,9 @@ exports.logs = async (req, res, next) => {
} }
exports.getTbkls = async (req, res, next) => { exports.getTbkls = async (req, res, next) => {
let {limit = 1000,skip = 0,sort = {'updatedAt': -1}} = req.query; let {limit = 100,skip = 0,sort = {'updatedAt': -1}} = req.query;
let options = {limit:parseInt(limit),skip:parseInt(skip),sort}; let options = {limit:parseInt(limit),skip:parseInt(skip),sort};
let tbkls = await Kouling.find({},null,options).populate('creater','user role').populate('good','title quan pid good'); let tbkls = await Kouling.find({},null,options).populate('link','title target');
let total = await Kouling.count({},null); let total = await Kouling.count({},null);
res.send({ status:'ok',result:tbkls,pagination:{total:total,skip:skip,limit:limit}}); res.send({ status:'ok',result:tbkls,pagination:{total:total,skip:skip,limit:limit}});
} }
...@@ -121,23 +121,29 @@ exports.createLink = async (req, res, next) => { ...@@ -121,23 +121,29 @@ exports.createLink = async (req, res, next) => {
exports.getSchedules = async (req, res, next) => { exports.getSchedules = async (req, res, next) => {
let {limit = 100,skip = 0,sort = {'updatedAt': -1}} = req.query; let {limit = 100,skip = 0,sort = {'updatedAt': -1}} = req.query;
let options = {limit:parseInt(limit),skip:parseInt(skip),sort}; let options = {limit:parseInt(limit),skip:parseInt(skip),sort};
let schedules = await Schedule.find({},null,options).populate('qd','user role').populate('taolink','name title target'); let schedules = await Schedule.find({},null,options).populate('links','name title target');
let total = await Schedule.count({},null); let total = await Schedule.count({},null);
res.send({ status:'ok',result:schedules,pagination:{total:total,skip:skip,limit:limit}}); res.send({ status:'ok',result:schedules,pagination:{total:total,skip:skip,limit:limit}});
} }
exports.createSchedule = async (req, res, next) => { exports.createSchedule = async (req, res, next) => {
let {user,times,status='use',name} = req.body; let {user,times,status='use',names} = req.body;
var links = [];
try{ try{
if(!user || !times || !name) if(!user || !times || !names)
res.status(400).send(not_full); res.status(400).send(not_full);
else{ else{
var agent = await Agent.findOne({user:user}); var agent = await Agent.findOne({user:user});
var link = await Link.findOne({name:name}); names = names.split("@");
if(agent && link){ names.forEach(async item => {
links.push(Link.findOne({name:item}));
});
Promise.all(links).then(function(arr){
let ids = arr.map(x => x.toJSON()._id);
if(agent && ids.length){
let qd = agent.toJSON()['_id']; let qd = agent.toJSON()['_id'];
let taolink = link.toJSON()['_id']; let links = ids;
tao.saveSchedule({qd,taolink,status,times},function(e,result){ tao.saveSchedule({qd,links,status,times},function(e,result){
if(e) throw e; if(e) throw e;
res.send({status:'ok',result:result}); res.send({status:'ok',result:result});
}); });
...@@ -145,32 +151,28 @@ exports.createSchedule = async (req, res, next) => { ...@@ -145,32 +151,28 @@ exports.createSchedule = async (req, res, next) => {
else{ else{
res.status(400).send(not_right); res.status(400).send(not_right);
} }
});
} }
}catch(e){ }catch(e){
console.dir(e);
res.status(400).send(not_right); res.status(400).send(not_right);
} }
} }
exports.createTbkl = async (req, res, next) => { exports.createTbkl = async (data) => {
/*let {quan,pid,good,title,qd} = req.body; let {title,target,pic} = data;
let quanQuery = urlArgs(url.parse(quan).query); return new Promise(async (r,d) => {
let goodQuery = urlArgs(url.parse(good).query);
//console.dir(quanQuery);
try { try {
if(!pid || !quanQuery['activityId'] || !goodQuery['id']) let tbklInfo = await tao.createTbkl(title,target,pic);
res.status(400).send(not_full);
else{
let urlTarget = 'https://uland.taobao.com/coupon/edetail?activityId='+ quanQuery['activityId']+'&itemId='+goodQuery['id']+'&pid='+pid;
let goodInfo = await tao.getGood(goodQuery['id']);
let tbklInfo = await tao.createTbkl(goodInfo['title'],urlTarget);
let model = tbklInfo.model; let model = tbklInfo.model;
//console.dir(title); let _data = { info:model,schedule:data.schedule,link:data.link,status:'use' };
console.dir(tbkl); tao.saveKouling(_data,function(e,result){
} if(e) d(e);
else r(result);
});
}catch(e){ }catch(e){
res.status(400).send(e); d(e);
}*/ }
//res.send({ status:'ok',result:{} }); });
} }
// const cron = require('cron'); const cron = require('cron');
// const UserAuth = require('../db/mongo/user-auto-auth'); const nodemailer = require('nodemailer');
// const UserAuthLog = require('../db/mongo/user-auto-used-log'); const Schedule = require('../db/mongo/tao-schedule');
// const nodemailer = require('nodemailer'); const Kouling = require('../db/mongo/tao-kouling');
// const _ = require('lodash'); const Log = require('../db/mongo/tao-log');
// const moment = require('moment'); const tao = require('./tao');
const _ = require('lodash');
const moment = require('moment');
const controller = require('./controller');
const max = 20000;
var CronJob = cron.CronJob;
var job = new CronJob({
cronTime: '* */1 * * *',
onTick: function() {
tbklTask();
},
start: false,
});
// var CronJob = cron.CronJob; async function sendMail(email,body) {
// var job = new CronJob({ var smtpTransport = nodemailer.createTransport({
// cronTime: '00 00 00 * * 0-6', auth: {
// onTick: function() { user: "liusong@goyoo.com",
// clearUserAuths(); pass: "323609zhang"
// }, },
// start: false, 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 tbklTask () {
console.log('定时更新开始 =====> ');
try {
console.log('=====> ');
//let tkls = await Kouling.find({status:'use'}).populate('link','title target').limit(1000);
// 查询进行中计划
let schedules = await Schedule.find({status:'use'}).limit(500);
schedules.forEach( async item => {
let schedule = item.toJSON()._id;
// console.dir(schedule);
// 查询计划内 超过20000 请求 淘口令
//console.dir({times:{$gte:10},status:'use',schedule:schedule});
let logs = await Log.find({times:{$gte:max},schedule:schedule,status:{$ne:'disable'}}).populate('link','title target pic').limit(1000);
//console.dir(logs.length);
var tasks_new = [];
var tasks_old = [];
var tasks_log = [];
logs.forEach( item => {
item = item.toJSON();
//console.dir(item);
if(item.link && item.link.title && item.link.target && item.times >= max){
var data = {
title:item.link.title,
target:item.link.target,
schedule:item.schedule,
link:item.link,
status:'use',
pic:item.link.pic
}
tasks_new.push(controller.createTbkl(data));
tasks_old.push(Kouling.update({info:item.key},{$set:{status:'disable'}}));
tasks_log.push(Log.update({key:item.key},{$set:{status:'disable'}}));
}
});
if(tasks_new.length&&tasks_old.length&&tasks_log.length){
Promise.all(tasks_new).then(function(arr){
console.log('增加老口令 结束 影响' + arr.length + '条数据');
});
Promise.all(tasks_old).then(function(arr){
console.log('删除老口令 结束 影响' + arr.length + '条数据');
});
Promise.all(tasks_log).then(function(arr){
console.log('更新log数据 影响' + arr.length + '条数据');
});
}
else{
console.log('没有任务 影响0条数据');
}
});
// async function sendMail(email,body) { } catch (err) {
// var smtpTransport = nodemailer.createTransport({ console.dir(err);
// auth: { console.dir('更新异常 =====>');
// user: "liusong@goyoo.com", let mailList = 'liusong@goyoo.com';
// pass: "323609zhang" sendMail(mailList, err.toString());
// }, }
// host: 'smtp.exmail.qq.com', console.log(' 更新结束 ');
// 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 () { module.exports.start = function ()
// console.log('定时更新开始 =====> '); {
// try { job.start();
// 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();
// };
...@@ -82,11 +82,15 @@ exports.getGood = (id) => { ...@@ -82,11 +82,15 @@ exports.getGood = (id) => {
}); });
} }
exports.createTbkl = (title,url) => { exports.createTbkl = (title,url,pic) => {
console.dir(title);
console.dir(url)
console.dir(pic)
return new Promise((r,d) => { return new Promise((r,d) => {
client.execute('taobao.tbk.tpwd.create', { client.execute('taobao.tbk.tpwd.create', {
'text':title, 'text':title,
'url':'https://uland.taobao.com/coupon/edetail?activityId=32fd90b87b9a418bb92d7c8cab52423a&itemId=527016966632&pid=mm_33320967_40070156_150834845&src=czhk_cztkl&ut_sk=1.utdid_null_1511245305902.TaoPassword-Outside.taoketop' 'url':url,
'logo':pic
}, function(error, response) { }, function(error, response) {
if (response && response.data && !error) r(response.data); if (response && response.data && !error) r(response.data);
else d(error); else d(error);
......
const mongoose = require('mongoose');
const {ObjectId} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
page:{
type:ObjectId,
required: true,
ref:'tao-link'
},
qd:{
type:ObjectId,
required: true,
ref:'tao-agent'
},
status:{
type: String,
required: true
},
times:{
type:Number,
required: true
}
}, {
timestamps: true
});
schema.index({info: 1});
module.exports = mongoose.model('tao-schedule', schema);
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