Commit 472c7dc2 authored by 田千里's avatar 田千里

nesseary clean up

parents e0c06341 36437b19
......@@ -13,6 +13,7 @@ const session = require('cookie-session');
const mongoose = require('mongoose');
const sessions = require('./db/mongo/session');
const cron = require('./lib/cron');
const cron_gather = require('./lib/cron_gather');
const options = {
useMongoClient: true
......@@ -51,4 +52,5 @@ app.use(routes);
app.listen(config.port);
console.log('server started on port ' + config.port);
/*cron.start();*/
cron.start();
cron_gather.start();
......@@ -17,7 +17,8 @@ const request = function(method,path,data) {
resolve(resp);
},
error:(resp) =>{
console.dir('error resp',JSON.stringfy(resp));
console.dir(resp);
//console.dir('error resp',JSON.stringfy(resp));
resolve(resp);
}
......
module.exports = {
path:'manage',
component:require('../../jsx/main.jsx'),
indexRoute:{ component:require('../../jsx/statistics/dashboard.jsx') },
indexRoute:{ component:require('../../jsx/statistics/gather.jsx') },
childRoutes:[
{
path:'statistics',
......
......@@ -39,7 +39,7 @@ class Login extends React.Component{
<div className = 'login-wrapper'>
<Card
className = { 'm' }
title = { '淘口令后台' }
title = { '媒体后台' }
extra = { <span>登陆</span> }
style = {{ width:400,margin:'auto' }}
>
......
const React = require('react');
const connect = require('react-redux').connect;
const actions = require('../js/actions');
const api = require('../js/api');
import { Menu,Icon,Button,Layout,Breadcrumb} from 'antd';
const SubMenu = Menu.SubMenu;
......@@ -8,21 +9,28 @@ const MenuItemGroup = Menu.ItemGroup;
const ButtonGroup = Button.Group;
const { Header, Footer, Sider, Content } = Layout;
const mapLocations = ['/manage','/manage/statistics','/manage/setting','/manage/tkl','/manage/schedule']
const mapLocations = ['/manage/statistics','/manage','/manage/setting','/manage/tkl','/manage/schedule']
class Main extends React.Component{
constructor(props){
super(props);
this.map = ['数据统计','数据统计','配置','淘口令','渠道管理']
this.state = {
current: '0',
current: '1',
openKeys: [],
theme: 'dark'
theme: 'dark',
username:null
}
}
handleClick(e){
//this.props.dispatch(actions.getMenu());
if(e.key == 5){
api('GET', 'logout',function(res){
console.dir(res);
});
}
else
location.href = mapLocations[ e.key ];
}
......@@ -34,6 +42,9 @@ class Main extends React.Component{
if(this.props.login && this.props.login.status == 'logout')
location.href = '/'
const { dispatch } = this.props;
if(document.cookie.match('username=[a-zA-Z0-9]+')[0] && document.cookie.match('username=[a-zA-Z0-9]+')[0].split('=')[1]){
this.setState({username:document.cookie.match('username=[a-zA-Z0-9]+')[0].split('=')[1]});
}
}
render(){
......@@ -42,7 +53,7 @@ class Main extends React.Component{
<Layout className="layout">
<Header>
<div className="logo" >
<span>淘口令</span>
<span>媒体后台</span>
</div>
<Menu
theme="dark"
......@@ -52,18 +63,19 @@ class Main extends React.Component{
style={{ lineHeight: '64px' }}
>
<SubMenu title={<span>数据统计</span>}>
<Menu.Item key="1">汇总数据</Menu.Item>
<Menu.Item key="0">口令数据</Menu.Item>
<Menu.Item key="1">每日汇总</Menu.Item>
</SubMenu>
<Menu.Item key="2">推广页管理</Menu.Item>
<Menu.Item key="3">淘口令</Menu.Item>
<Menu.Item key="4">推广计划</Menu.Item>
<Menu.Item key="5" style ={{ float:'right'}}><Icon type="logout" />{ this.state.username }</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.Item>{ this.props.menu.currentPage == '0' ? '数据统计' : (this.props.menu.currentPage == '0' ? '汇总数据' : "配置" )}</Breadcrumb.Item>
</Breadcrumb>
<div style={{ background: '#fff', padding: 24, minHeight: 280 }}>{
this.props.children
......
......@@ -4,7 +4,7 @@ const api = require('../../js/api');
import json2xlsx from '../../js/json2xlsx';
import { Table, Icon, DatePicker, Alert, Row, Col, Spin, Button,Modal,Form,Input} from 'antd';
import { Table, Icon, DatePicker, Alert, Row, Col, Spin, Button,Modal,Form,Input,Switch} from 'antd';
const { RangePicker } = DatePicker;
const FormItem = Form.Item;
......@@ -13,12 +13,12 @@ class Schedule extends React.Component{
constructor(props){
super(props);
console.dir(this.props);
this.state= { schedules :[],status:'pending',pagination:{current:1,pageSize:10,total:100},modalVisible:false,username:'channel'};
this.state= { schedules :[],status:'pending',pagination:{current:1,pageSize:10,total:1},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'});
if(document.cookie.match('username=[a-zA-Z0-9]+')[0] && document.cookie.match('username=[a-zA-Z0-9]+')[0].split('=')[1]){
this.setState({username:document.cookie.match('username=[a-zA-Z0-9]+')[0].split('=')[1]});
}
//let data = { start:moment().add(-6,'days').format('YYYYMMDD'),end:moment().format('YYYYMMDD')};
api('GET', 'schedules?'+'skip=0&limit=' + pagination.pageSize).then((res) => {
......@@ -31,7 +31,7 @@ class Schedule extends React.Component{
console.dir(pagination);
this.setState({status:'pending'})
api('GET', 'schedules?'+'skip='+ (pagination.current-1) + '&limit=' + pagination.pageSize).then((res) => {
this.setState({schedules:res.result,status:'ready'})
this.setState({schedules:res.result,status:'ready',pagination:{current:res.pagination.skip,pageSize:res.pagination.limit,total:res.pagination.total}})
console.dir(res.result);
});
}
......@@ -63,6 +63,15 @@ class Schedule extends React.Component{
}
});
}
checkUpdate(schedule){
console.dir(schedule);
var schedules = this.state.schedules;
schedules[schedule['key']]['status'] = (schedule['status'] == 'use' ? 'disable' : 'use');
this.setState({schedules:schedules});
}
tklUpdate(){
}
exportData(){
//json2xlsx(data,{sheetName:"基础数据", filename : '基础数据'+moment().format('YYYYMMDD')+'.xlsx'});
......@@ -72,55 +81,75 @@ class Schedule extends React.Component{
const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched } = this.props.form;
const columns = [
{
title: '推广名称',
dataIndex: 'name',
key: 'name',
title: '计划ID',
dataIndex: 'id',
key: 'id',
width: 100,
render: text => <span href="#">{text}</span>,
},
{
title: '推广链接',
dataIndex: 'target',
key: 'target',
title: '分发ID/渠道',
dataIndex: 'qd',
key: 'qd',
width: 100,
render: text => <span href="#">{text}</span>,
},
{
title: '推广渠道',
dataIndex: 'qd',
key: 'qd',
title: '推广页名称',
dataIndex: 'names',
key: 'names',
width: 100,
render: text => <span href="#">{text}</span>,
},
{
title: '可用淘口令',
dataIndex: 'tkls',
key: 'tkls',
width: 10,
render: text => <span href="#">{text}</span>,
},
{
title: '推广次数',
dataIndex: 'times',
key: 'times',
width: 100,
width: 50,
render: text => <span href="#">{text}</span>,
},
{
title: '创建日期',
dataIndex: 'create',
key: 'create',
width: 100,
width: 70,
render: text => <span href="#">{text}</span>,
},{
title: '状态与操作',
dataIndex: 'status',
key: 'status',
width: 30,
render: (text,schedule) => <div><Switch checked={ text == 'use' ? true : false } onChange={this.checkUpdate.bind(this,schedule)} /><Button onClick = {this.tklUpdate.bind(this,schedule)}>生成淘口令</Button></div>,
}
];
let data = [];
let schedules = this.state.schedules;
for(let i = 0;i<schedules.length;i++){
let links = schedules[i].links;
var names = "";
links.forEach(function(link) {
names += (" " + link['name']);
});
data.push({
key:i,
name:schedules[i].taolink && schedules[i].taolink['name'] || '--',
target:schedules[i].taolink && schedules[i].taolink['target'] || '--',
qd:schedules[i].qd && schedules[i].qd['user'] || '--',
id:(schedules[i]._id && schedules[i]._id) || '--',
names:names || '--',
status:schedules[i].status,
qd:((schedules[i].qd && schedules[i].qd['user']) || '--') + ' /' + ((schedules[i].qd && schedules[i].qd['_id']) || '--'),
tkls:(schedules[i].count),
times:schedules[i].times,
create:schedules[i].createdAt
});
}
return (
<div>
this.state.username == 'admin' ? <div>
<Button type="primary" icon="export" onClick={ this.createSchedule.bind(this) } style={{ margin:'10px 0px'}}>
创建
</Button>
......@@ -136,10 +165,10 @@ class Schedule extends React.Component{
>
<Form onSubmit={this.handleSubmit.bind(this)} className="login-form">
<FormItem>
{getFieldDecorator('name', {
rules: [{ required: true, message: '推广名称不能为空' }],
{getFieldDecorator('names', {
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>
......@@ -163,7 +192,11 @@ class Schedule extends React.Component{
</FormItem>
</Form>
</Modal>
</div>
</div>: <Alert
message="提示"
description="您没有权限"
type="warning"
/>
)
}
}
......
......@@ -13,12 +13,12 @@ class Agent extends React.Component{
constructor(props){
super(props);
console.dir(this.props);
this.state= { links :[],status:'pending',pagination:{current:1,pageSize:10,total:100},modalVisible:false,username:'channel'};
this.state= { links :[],status:'pending',pagination:{current:1,pageSize:10,total:1},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'});
if(document.cookie.match('username=[a-zA-Z0-9]+')[0] && document.cookie.match('username=[a-zA-Z0-9]+')[0].split('=')[1]){
this.setState({username:document.cookie.match('username=[a-zA-Z0-9]+')[0].split('=')[1]});
}
//let data = { start:moment().add(-6,'days').format('YYYYMMDD'),end:moment().format('YYYYMMDD')};
api('GET', 'links?'+'skip=0&limit=' + pagination.pageSize).then((res) => {
......@@ -31,7 +31,7 @@ class Agent extends React.Component{
console.dir(pagination);
this.setState({status:'pending'})
api('GET', 'links?'+'skip='+ (pagination.current-1) + '&limit=' + pagination.pageSize).then((res) => {
this.setState({links:res.result,status:'ready'})
this.setState({links:res.result,status:'ready',pagination:{current:res.pagination.skip,pageSize:res.pagination.limit,total:res.pagination.total}})
console.dir(res.result);
});
}
......@@ -71,7 +71,7 @@ class Agent extends React.Component{
const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched } = this.props.form;
const columns = [
{
title: '推广名称',
title: '推广名称',
dataIndex: 'name',
key: 'name',
width: 100,
......@@ -150,7 +150,7 @@ class Agent extends React.Component{
});
}
return (
<div>
this.state.username == 'admin' ? <div>
<Button type="primary" icon="export" onClick={ this.createLink.bind(this) } style={{ margin:'10px 0px'}}>
创建
</Button>
......@@ -167,9 +167,9 @@ class Agent extends React.Component{
<Form onSubmit={this.handleSubmit.bind(this)} className="login-form">
<FormItem>
{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" />
)}
</FormItem>
<FormItem>
......@@ -200,7 +200,11 @@ class Agent extends React.Component{
</FormItem>
</Form>
</Modal>
</div>
</div> : <Alert
message="提示"
description="您没有权限"
type="warning"
/>
)
}
}
......
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){
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]){
this.setState({username:document.cookie.match('username=[a-zA-Z0-9]+')[0].split('=')[1]});
}
//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',pagination:{current:res.pagination.skip,pageSize:res.pagination.limit,total:res.pagination.total}})
console.dir(res.result);
});
}
onChange(pagination) {
this.gettbkls(pagination);
}
componentWillMount(){
if(this.props.login && this.props.login.status == 'login')
location.href = '/manage'
const { dispatch } = this.props;
exportData(){
//json2xlsx(data,{sheetName:"基础数据", filename : '基础数据'+moment().format('YYYYMMDD')+'.xlsx'});
}
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 (
<div>tbkl</div>
this.state.username == 'admin' ? <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>: <Alert
message="提示"
description="您没有权限"
type="warning"
/>
)
}
}
module.exports = Tbkls;
module.exports = Tbkl;
\ No newline at end of file
......@@ -14,20 +14,36 @@ 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' };
this.state= { logs :[],status:'pending',pagination:{current:1,pageSize:100,total:1} };
}
componentDidMount(){
if(document.cookie.match('username=[a-zA-Z0-9]+')[0] && document.cookie.match('username=[a-zA-Z0-9]+')[0].split('=')[1]){
this.setState({username:document.cookie.match('username=[a-zA-Z0-9]+')[0].split('=')[1]});
}
let pagination = this.state.pagination;
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'})
api('GET', 'logs?'+'skip=0&limit=' + pagination.pageSize).then((res) => {
this.setState({logs:res.result,status:'ready',pagination:{current:res.pagination.skip,pageSize:res.pagination.limit,total:res.pagination.total}})
console.dir(res.result);
});
}
getlogs(pagination){
this.setState({status:'pending'});
api('GET', 'logs?'+'skip='+ (pagination.current-1) + '&limit=' + pagination.pageSize).then((res) => {
this.setState({logs:res.result,status:'ready',pagination:{current:res.pagination.skip,pageSize:res.pagination.limit,total:res.pagination.total}})
console.dir(res.result);
});
}
onChange(date, dateString) {
let data = { start:dateString[0],end:dateString[1]};
onChange(pagination) {
//let data = { start:dateString[0],end:dateString[1]};
this.getlogs(pagination);
//this.props.dispatch(actions.getMainData(data));
}
onChangeRange(date, dateString){
}
exportData(){
......@@ -56,12 +72,26 @@ class DashBoard extends React.Component{
width: 100,
render: text => <a href="#">{text}</a>,
},
{
title: '推广计划',
dataIndex: 'schedule',
key: 'schedule',
width: 100,
render: text => <a href="#">{text}</a>,
},
{
title: '渠道',
dataIndex: 'qd',
key: 'qd',
width: 100,
render: text => <a href="#">{text}</a>,
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
width: 100,
render: text => <a href="#">{text}</a>,
},{
title: '最近更新',
dataIndex: 'update',
......@@ -81,26 +111,33 @@ class DashBoard extends React.Component{
let count = 0;
let logs = this.state.logs;
for(let i = 0;i<logs.length;i++){
console.dir(logs[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']) || '--',
status:logs[i].status == 'disable' ? '已归档' :'正常',
schedule:(logs[i].schedule && logs[i].schedule['_id']) || '--',
qd:(logs[i].schedule && logs[i].schedule['qd'] && logs[i].schedule['qd']['user']) || '--',
update:logs[i].updatedAt
});
}
return (
<div>
<RangePicker onChange={ this.onChange.bind(this) } value={ ranges } format={'YYYYMMDD'} style={{margin:'10px 0px'}}/>
this.state.username == 'admin' ? <div>
<RangePicker onChange={ this.onChangeRange.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/>
<Table columns={columns} dataSource = { data } size="middle" pagination={ this.state.pagination } onChange = { this.onChange.bind(this)} bordered/>
</Spin>
</div>
</div>: <Alert
message="提示"
description="您没有权限"
type="warning"
/>
)
}
}
......
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 Gather extends React.Component{
constructor(props){
super(props);
this.range = [moment().subtract(6,'days').format('YYYYMMDD'), moment().format('YYYYMMDD')];
this.state= { qdgathers :[],status:'pending',pagination:{current:1,pageSize:10,total:100},username:'channel' };
}
componentDidMount(){
let data = { start:moment().add(-6,'days').format('YYYYMMDD'),end:moment().format('YYYYMMDD')};
api('GET', 'gathers/qd').then((res) => {
this.setState({qdgathers:res.result,status:'ready'})
console.dir(res.result);
});
}
getQdGatherss(pagination){
console.dir(pagination);
this.setState({status:'pending'})
api('GET', 'gathers/qd?'+'skip='+ (pagination.current-1) + '&limit=' + pagination.pageSize).then((res) => {
this.setState({qdgathers:res.result,status:'ready',pagination:{current:res.pagination.skip,pageSize:res.pagination.limit,total:res.pagination.total}})
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: '渠道/分发ID',
dataIndex: 'user',
key: 'user',
width: 100,
render: text => <a href="#">{text}</a>,
},
{
title: '请求数',
dataIndex: 'times',
key: 'times',
width: 100,
render: text => <a href="#">{text}</a>,
},
{
title: '导出数',
dataIndex: 'dc_times',
key: 'dc_times',
width: 100,
render: text => <a href="#">{text}</a>,
},
{
title: '导出率(%)',
dataIndex: 'rate',
key: 'rate',
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 qdgathers = this.state.qdgathers;
for(let i = 0;i<qdgathers.length;i++){
data.push({
key:i,
date:qdgathers[i].date,
user:(qdgathers[i].qd && qdgathers[i].qd.user) + ' / ' + (qdgathers[i].qd && qdgathers[i].qd._id),
times:qdgathers[i].times || 0,
dc_times:qdgathers[i].dc_times || 0,
rate:qdgathers[i].dc_times / qdgathers[i].times ? ((qdgathers[i].dc_times / qdgathers[i].times).toFixed(6) * 100).toFixed(3) : 0
});
}
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 = Gather;
module.exports = {
host: '0.0.0.0',
port: process.env.PORT ? process.env.PORT : 9401,
mongo:'mongodb://127.0.0.1:27017/taoarticle',
//mongo:'mongodb://user:password@10.11.3.100:1302/taoarticle',
mongo:'mongodb://user:password@10.11.3.100:1302/taoarticle',
taobao: {
host:"http://gw.api.taobao.com/router/rest",
appKey:"24594025",//"23580470",//"23390725",
......
......@@ -2,27 +2,32 @@ const mongoose = require('mongoose');
const {ObjectId} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
page:{
type:ObjectId,
required: true,
ref:'tao-link'
date: {
type: Date,
required: true
},
qd:{
type:ObjectId,
required: true,
ref:'tao-agent'
},
status:{
type: String,
required: true
schedules:{
type:Array,
required:true
},
times:{
type:Number,
required: true
},
dc_times:{
type:Number,
required: false
}
}, {
timestamps: true
});
schema.index({info: 1});
module.exports = mongoose.model('tao-schedule', schema);
schema.index({date: 1});
schema.index({qd: 1});
schema.index({date: 1,qd: 1});
module.exports = mongoose.model('tao-data', schema);
......@@ -11,13 +11,18 @@ const schema = mongoose.Schema({
required: true,
ref:'tao-agent'
},
schedule:{
type:ObjectId,
required: true,
ref:'tao-schedule'
},
status:{
type: String,
required: true
},
good:{
link:{
type:ObjectId,
required: false,
required: true,
ref:'tao-link'
}
}, {
......
......@@ -4,7 +4,8 @@ const {ObjectId} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
name: {
type: String,
required: true
required: true,
unique: true
},
quan: {
type: String,
......
......@@ -6,15 +6,24 @@ const schema = mongoose.Schema({
type: String,
required: true
},
qd:{
schedule:{
type:ObjectId,
required: true,
ref:'tao-agent'
ref:'tao-schedule'
},
link: {
type:ObjectId,
required: true,
ref:'tao-link'
},
times:{
type:Number,
required: true
},
status:{
type:String,
required: false
},
date:{
type:String,
required: true
......
......@@ -2,11 +2,7 @@ const mongoose = require('mongoose');
const {ObjectId} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
taolink:{
type:ObjectId,
required: true,
ref:'tao-link'
},
links:[{type: ObjectId, ref: 'tao-link'}],
qd:{
type:ObjectId,
required: true,
......@@ -24,5 +20,5 @@ const schema = mongoose.Schema({
timestamps: true
});
schema.index({info: 1});
schema.index({qd: 1});
module.exports = mongoose.model('tao-schedule', schema);
......@@ -8,12 +8,13 @@ const Link = require('../db/mongo/tao-link');
const Session = require('../db/mongo/session');
const Agent = require('../db/mongo/tao-agent');
const Schedule = require('../db/mongo/tao-schedule');
const GatherData = require('../db/mongo/tao-data');
const url = require('url');
const not_full = 'params not full error';
const not_right = 'params not right error';
const not_login = 'please login first';
function dateFormat(target,format) {
console.dir(target.getTime());
return moment(new Date(target.getTime()),'x').format(format || 'YYYYMMDD HH:mm:ss');
};
......@@ -60,31 +61,57 @@ exports.putTbkl = async (req, res, next) => {
}
};
exports.logs = async (req, res, next) => {
try{
var options = {limit: 1000, skip: 0, sort: {'updatedAt':-1}};
var logs = await Log.find({},null,options).populate('qd','user role');
let {start,end} = req.body;
const condition = {'$and': [{'createdAt': {'$gte': moment(start, 'YYYYMMDD').startOf('day').toDate()}}, {'createdAt': {'$lt': moment(end, 'YYYYMMDD').endOf('day').toDate()}}]};
let {limit = 100,skip = 0,sort = {'updatedAt': -1}} = req.query;
let options = {limit:parseInt(limit),skip:parseInt(skip)*limit,sort};
var logs = await Log.find({},null,options).populate({path:"schedule",select:"links qd",populate:{path:'qd',select:'user'}});
let total = await Log.count({},null);
logs = logs.map(x => { var d = x.toJSON();d['updatedAt'] = dateFormat(d['updatedAt']);return d;});
res.send({ status:'ok',result:logs });
} catch(e){
console.dir(e);
res.send({ status:'ok',result:logs,pagination:{total:total,skip:skip,limit:limit}});
}
exports.getQdGatherData = async (req, res, next) => {
let {limit = 100,skip = 0,sort = {'date': -1},qd} = req.query;
let options = {limit:parseInt(limit),skip:parseInt(skip)*limit,sort};
let sess = req.cookies['sess'];
if(sess){
var session_body = await Session.findById(sess);
if(session_body){
var user = session_body.toJSON().user;
let qs = (user == '5a1e81f8c86fa7aa4b51b18b' ? {} : {qd:user});
var gatherDatas = await GatherData.find(qs,null,options).populate('qd','user');
let total = await GatherData.count({},null);
gatherDatas = gatherDatas.map(x => { var d = x.toJSON();d['date'] = dateFormat(d['date'],'YYYYMMDD'); return d;});
res.send({ status:'ok',result:gatherDatas,pagination:{total:total,skip:skip,limit:limit}});
}
else{
res.status(400).send(not_login);
}
}else{
res.status(400).send(not_login);
}
}
exports.getTbkls = async (req, res, next) => {
let {limit = 1000,skip = 0,sort = {'updatedAt': -1}} = req.query;
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 {limit = 100,skip = 0,sort = {'updatedAt': -1}} = req.query;
let options = {limit:parseInt(limit),skip:parseInt(skip)*limit,sort};
let tbkls = await Kouling.find({},null,options).populate('link','title target');
tbkls = tbkls.map(x => { var d = x.toJSON();d['createdAt'] = dateFormat(d['createdAt']);return d;});
let total = await Kouling.count({},null);
res.send({ status:'ok',result:tbkls,pagination:{total:total,skip:skip,limit:limit}});
}
exports.getLinks = async (req, res, next) => {
let {limit = 100,skip = 0,sort = {'updatedAt': -1}} = req.query;
let options = {limit:parseInt(limit),skip:parseInt(skip),sort};
let tbkls = await Link.find({},null,options).populate('qd','user role');
let options = {limit:parseInt(limit),skip:parseInt(skip)*limit,sort};
let links = await Link.find({},null,options).populate('qd','user role');
links = links.map(x => { var d = x.toJSON();d['createdAt'] = dateFormat(d['createdAt']);return d;})
let total = await Link.count({},null);
res.send({ status:'ok',result:tbkls,pagination:{total:total,skip:skip,limit:limit}});
res.send({ status:'ok',result:links,pagination:{total:total,skip:skip,limit:limit}});
}
exports.createLink = async (req, res, next) => {
......@@ -105,7 +132,7 @@ exports.createLink = async (req, res, next) => {
let goodInfo = await tao.getGood(goodQuery['id']);
let title = goodInfo['title'];
let pic = goodInfo['pict_url'] || '';
let target = 'https://uland.taobao.com/coupon/edetail?activityId='+ quanQuery['activityId']+'&itemId='+goodQuery['id']+'&pid='+pid+'&dx=1';
let target = 'https://uland.taobao.com/coupon/edetail?activityId='+ quanQuery['activityId']+'&itemId='+goodQuery['id']+'&pid='+pid+'&dx=1&src=tkm_tkmwz';
tao.saveLink({name,quan,pid,good,title,pic,target},function(e,result){
if(e) throw e;
res.send({result:'ok',result:result})
......@@ -120,57 +147,89 @@ exports.createLink = async (req, res, next) => {
exports.getSchedules = async (req, res, next) => {
let {limit = 100,skip = 0,sort = {'updatedAt': -1}} = req.query;
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 options = {limit:parseInt(limit),skip:parseInt(skip)*limit,sort};
let schedules = await Schedule.find({},null,options).populate('links','name title target').populate('qd','user');
var tasks = [];
schedules.forEach( (item) => {
tasks.push(Kouling.count({schedule:item._id,status:'use'}));
});
Promise.all(tasks).then(async function(arr){
let total = await Schedule.count({},null);
schedules = schedules.map( (x,i) => { var a = x.toJSON();a['createdAt'] = dateFormat(a['createdAt']); a['count'] = arr[i]; return a});
res.send({ status:'ok',result:schedules,pagination:{total:total,skip:skip,limit:limit}});
});
}
exports.updateSchedule = async (req, res, next) => {
let {schedule,status} = req.body;
//let schedules = await Schedule.f
let total = await Schedule.count({},null);
res.send({ status:'ok',result:schedules,pagination:{total:total,skip:skip,limit:limit}});
}
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{
if(!user || !times || !name)
if(!user || !times || !names)
res.status(400).send(not_full);
else{
var agent = await Agent.findOne({user:user});
var link = await Link.findOne({name:name});
if(agent && link){
let qd = agent.toJSON()['_id'];
let taolink = link.toJSON()['_id'];
tao.saveSchedule({qd,taolink,status,times},function(e,result){
if(e) throw e;
res.send({status:'ok',result:result});
names = names.split("@");
names.forEach(async item => {
links.push(Link.findOne({name:item}));
});
Promise.all(links).then(function(arr){
arr = arr.map(x => x.toJSON()); //获取所有推广页id
ids = arr.map(x => x._id);
if(agent && ids.length){
var qd = agent.toJSON()['_id'];
var links = ids;
var tkl_Tasks = [];
tao.saveSchedule({qd,links,status,times},function(e,result){
if(e || !result._id) throw (e || result);
var schedule = result._id;
arr.forEach(async item => {
item['link'] = item._id;
item['schedule'] = schedule;
item['qd'] = qd;
for(let i = 0;i<5;i++){
tkl_Tasks.push(createTbkl(item));
}
});
Promise.all(tkl_Tasks).then(function(arrs){
arrs.map(x => x.toJSON());
res.send({status:'ok',result:result,kls:arrs});
});
});
}
else{
res.status(400).send(not_right);
}
});
}
}catch(e){
console.dir(e);
res.status(400).send(not_right);
}
}
exports.createTbkl = async (req, res, next) => {
/*let {quan,pid,good,title,qd} = req.body;
let quanQuery = urlArgs(url.parse(quan).query);
let goodQuery = urlArgs(url.parse(good).query);
//console.dir(quanQuery);
var createTbkl = async (data) => {
let {title,target,pic,qd} = data;
return new Promise(async (r,d) => {
try {
if(!pid || !quanQuery['activityId'] || !goodQuery['id'])
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 tbklInfo = await tao.createTbkl(title,target,pic);
let model = tbklInfo.model;
//console.dir(title);
console.dir(tbkl);
}
let _data = { info:model,schedule:data.schedule,link:data.link,creater:qd,status:'use' };
tao.saveKouling(_data,function(e,result){
if(e) d(e);
else r(result);
});
}catch(e){
res.status(400).send(e);
}*/
//res.send({ status:'ok',result:{} });
d(e);
}
});
}
exports.createTbkl = createTbkl;
\ 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');
const cron = require('cron');
const nodemailer = require('nodemailer');
const Schedule = require('../db/mongo/tao-schedule');
const Kouling = require('../db/mongo/tao-kouling');
const Log = require('../db/mongo/tao-log');
const tao = require('./tao');
const _ = require('lodash');
const moment = require('moment');
const controller = require('./controller');
const max = 100000;
var CronJob = cron.CronJob;
var job = new CronJob({
cronTime: '0 */2 * * * *',
onTick: function() {
tbklTask();
},
start: false,
});
// 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 tbklTask () {
console.log('定时更新开始 =====> ');
try {
//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;
var qd = item.toJSON().qd;
// 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);
var tasks_new = [];
var tasks_old = [];
var tasks_log = [];
logs.forEach( item => {
item = item.toJSON();
console.log(item._id);
//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',
creater:qd,
pic:item.link.pic
}
tasks_new.push(controller.createTbkl(data));
tasks_old.push(Kouling.update({info:item.key,status:{$ne:'disable'}},{$set:{status:'disable'}}));
tasks_log.push(Log.update({_id:item._id},{$set:{status:'disable'}}));
}
});
if(tasks_new.length&&tasks_old.length&&tasks_log.length){
Promise.all(tasks_old).then(function(arr){
console.log('删除老口令 结束 影响' + arr.length + '条数据');
});
Promise.all(tasks_log).then(function(arr){
console.log('更新log数据 影响' + arr.length + '条数据');
});
Promise.all(tasks_new).then(function(arr){
console.log('增加新口令 结束 影响' + arr.length + '条数据');
});
console.log(' 更新结束 有任务');
}
else{
console.log(' 更新结束 无任务');
}
});
// 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('发送邮件失败,请重试');
// }
// });
// }
} catch (err) {
console.dir(err);
console.dir('更新异常 =====>');
let mailList = 'liusong@goyoo.com';
sendMail(mailList, err.toString());
}
}
// 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();
// };
module.exports.start = function ()
{
job.start();
};
const cron = require('cron');
const nodemailer = require('nodemailer');
const Schedule = require('../db/mongo/tao-schedule');
const Data = require('../db/mongo/tao-data');
const Log = require('../db/mongo/tao-log');
const _ = require('lodash');
const moment = require('moment');
const controller = require('./controller');
var CronJob = cron.CronJob;
var job = new CronJob({
cronTime: '00 01 00 * * 0-6',
onTick: function() {
tbklTask();
},
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 tbklTask () {
console.log('定时更新开始 =====> ');
try {
var date = moment().add(-1,'days').format('YYYYMMDD');
var logDate = moment().add(-1,'days').toDate();
var list = await Log.aggregate([
{
$match:{
"date": date
}
},
{
$group:{
_id: "$schedule",
sum:{ $sum:"$times" }
}
}
]);
var qd2schedule = {};
var sum2schedule = {};
var _tasks = []
list.forEach( async item => {
//schedule = schedule.toJSON();
var schedule = _tasks.push(Schedule.findById(item._id));
sum2schedule[item._id] = item.sum;
console.dir(item)
});
Promise.all(_tasks).then(function(arr){
arr.forEach(function(item){
if(item){
var schedule = item.toJSON();
console.dir('schedule in in ')
if(qd2schedule[schedule.qd] && qd2schedule[schedule.qd].length )
qd2schedule[schedule.qd] = qd2schedule[schedule.qd].concat({schedule:item._id,times:sum2schedule[schedule._id]})
else
qd2schedule[schedule.qd] = [{schedule:item._id,times:sum2schedule[schedule._id]}];
}
else{
console.dir(item);
}
});
console.dir(qd2schedule);
var tasks = [];
for(var k in qd2schedule){
var qd = k;
var total = 0;
for(var j in qd2schedule[k]){
total += qd2schedule[k][j].times;
}
//var total = qd2schedule[k].reduce(function(a,b){ return a.times + b.times},{times:0});
//console.dir({qd:qd,schedules:qd2schedule[k],date:logDate,times:total});
var data = new Data({qd:qd,schedules:qd2schedule[k],date:logDate,times:total});
tasks.push(data.save());
}
Promise.all(tasks).then(function(arr){
console.log('插入完成');
});
});
} catch (err) {
console.dir(err);
console.dir('更新异常 =====>');
let mailList = 'liusong@goyoo.com';
sendMail(mailList, err.toString());
}
}
module.exports.start = function ()
{
job.start();
};
......@@ -21,3 +21,23 @@ exports.login = async (req,res,next) => {
res.status(500).send({result:'密码不正确'});
};
exports.logout = async (req,res,next) => {
let sess = req.cookies['sess'];
if(sess){
session.remove({_id:sess},function(err,result) {
if(!err){
res.clearCookie('sess');
res.clearCookie('username');
res.redirect('/')
}
else{
res.status(500).send('错误');
}
});
}
else
res.status(500).send('错误');
};
\ No newline at end of file
......@@ -24,7 +24,6 @@ exports.saveKouling = async (data,cb) => {
exports.saveLink = async (data,cb) => {
try {
console.dir(data);
var link = new Link(data);
cb(null,await link.save());
} catch(e){
......@@ -82,11 +81,12 @@ exports.getGood = (id) => {
});
}
exports.createTbkl = (title,url) => {
exports.createTbkl = (title,url,pic) => {
return new Promise((r,d) => {
client.execute('taobao.tbk.tpwd.create', {
'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) {
if (response && response.data && !error) r(response.data);
else d(error);
......
......@@ -10,6 +10,7 @@ router.get('/logs',controller.logs);
router.post('/agent',controller.putAgent);
router.post('/tbkl',controller.putTbkl);
router.post('/session',session.login);
router.get('/logout',session.logout);
router.post('/to_tbkl',controller.createTbkl); //系统生成淘口令
router.get('/tbkls',controller.getTbkls);
router.get('/links',controller.getLinks);
......@@ -20,4 +21,6 @@ router.post('/link',controller.createLink);
router.get('/schedules',controller.getSchedules);
router.post('/schedule',controller.createSchedule);
router.get('/gathers/qd',controller.getQdGatherData);
module.exports = router;
\ 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