Authored by 郝肖肖

'task-log'

@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 const Router = require('koa-router'); 3 const Router = require('koa-router');
4 const _ = require('lodash'); 4 const _ = require('lodash');
5 const md5 = require('md5'); 5 const md5 = require('md5');
  6 +const moment = require('moment');
6 const pager = require('../utils/pager'); 7 const pager = require('../utils/pager');
7 const seoModel = require('../models/seoModel'); 8 const seoModel = require('../models/seoModel');
8 9
@@ -16,12 +17,12 @@ const TYPE_LIST = [ @@ -16,12 +17,12 @@ const TYPE_LIST = [
16 ]; 17 ];
17 const JOB_TASK = [ 18 const JOB_TASK = [
18 { 19 {
19 - k: 'global:yoho:seo:task:minute', 20 + k: 'global:yoho:task:minute',
20 v: '1 */10 * * * *', 21 v: '1 */10 * * * *',
21 info: '每10分钟执行一次' 22 info: '每10分钟执行一次'
22 }, 23 },
23 { 24 {
24 - k: 'global:yoho:seo:task:day', 25 + k: 'global:yoho:task:day',
25 v: '30 30 1 * * *', 26 v: '30 30 1 * * *',
26 info: '每天的1点30分30s执行一次' 27 info: '每天的1点30分30s执行一次'
27 } 28 }
@@ -694,17 +695,23 @@ const task = { @@ -694,17 +695,23 @@ const task = {
694 }); 695 });
695 }, 696 },
696 log: async(ctx, next) => { 697 log: async(ctx, next) => {
697 - let key = ctx.query.key || '';  
698 - let resData = {  
699 - typeList: [  
700 - {type: 'text', name: '文字友链'},  
701 - {type: 'img', name: '图片友链'},  
702 - ]  
703 - }; 698 + let params = ctx.request.body || {};
  699 + let key = params.code || '';
  700 + let start = params.start || 0;
  701 + let stop = params.stop || 100;
  702 +
  703 + return ctx.redis.lrangeAsync(`global:yoho:task:log:${key}`, start, stop).then(rdata => {
  704 + let data = _.map(rdata, item => {
  705 + item = JSON.parse(item || '{}');
  706 + return Object.assign(item, {time: moment(item.time).format('YYYY-MM-DD HH:mm:ss')});
  707 + });
704 708
705 - await ctx.render('action/seo_task', Object.assign(resData, {  
706 - title: '定时任务日志',  
707 - })); 709 + return ctx.body = {
  710 + code: 200,
  711 + message: 'success',
  712 + data: data
  713 + };
  714 + });
708 }, 715 },
709 }; 716 };
710 717
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 <a class="btn btn-default deleteAll">删除</a> 21 <a class="btn btn-default deleteAll">删除</a>
22 <a class="btn btn-default" href="/keywords/add">增加</a> 22 <a class="btn btn-default" href="/keywords/add">增加</a>
23 <a class="btn btn-default" href="javascript:sendUrl();">推送百度</a> 23 <a class="btn btn-default" href="javascript:sendUrl();">推送百度</a>
24 - <a class="btn btn-default rand-words" href="javascript:void(0);">关键词随机关联</a> 24 + <!--<a class="btn btn-default rand-words" href="javascript:void(0);">关键词随机关联</a>-->
25 <div class="input-append pull-right"> 25 <div class="input-append pull-right">
26 <form id="query-form" action="/keywords/expand" class="query-form" method="get"> 26 <form id="query-form" action="/keywords/expand" class="query-form" method="get">
27 <!-- <div class="btn-group"> 27 <!-- <div class="btn-group">
@@ -272,4 +272,4 @@ @@ -272,4 +272,4 @@
272 alert(data.message); 272 alert(data.message);
273 }) 273 })
274 } 274 }
275 -</script>  
  275 +</script>
1 <style type="text/css"> 1 <style type="text/css">
2 - .add-task ul { 2 + .task-add {
  3 + padding-top: 20px;
  4 + }
  5 + .task-add ul {
3 list-style: none; 6 list-style: none;
4 } 7 }
5 - .add-task ul li { 8 + .task-add ul li {
6 height: 40px; 9 height: 40px;
7 } 10 }
8 - .add-task select,  
9 - .add-task input { 11 + .task-add select,
  12 + .task-add input {
10 width: 70%; 13 width: 70%;
11 height: 30px; 14 height: 30px;
12 padding: 5px; 15 padding: 5px;
13 } 16 }
  17 + .task-add .job-select {
  18 + margin-left: -3px;
  19 + }
  20 +
  21 + .task-log {
  22 + padding: 20px;
  23 + }
  24 + .task-log table, .task-log table tr th,.task-log table tr td {
  25 + border: none;
  26 + }
  27 + .task-log tbody tr {
  28 + height: 40px;
  29 + }
  30 + .task-log table {
  31 + border-collapse: separate;
  32 + border-spacing: 0 4px;
  33 + }
  34 + .task-log tbody tr:nth-child(odd) td:first-child {
  35 + border-left: 2px solid #00C656;
  36 + }
  37 + .task-log tbody tr:nth-child(even) td:first-child {
  38 + border-left: 2px solid #4F95E8;
  39 + }
  40 + .task-log tbody tr.empty td {
  41 + border: none !important;
  42 + }
14 </style> 43 </style>
15 <div class="pageheader"> 44 <div class="pageheader">
16 <div class="media"> 45 <div class="media">
@@ -57,12 +86,12 @@ @@ -57,12 +86,12 @@
57 {{#each tasks}} 86 {{#each tasks}}
58 <tr data-code="{{code}}" data-type="{{type}}"> 87 <tr data-code="{{code}}" data-type="{{type}}">
59 <td>&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" /></td> 88 <td>&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" /></td>
60 - <td class="text-center" >{{name}}</td> 89 + <td class="text-center td-name" >{{name}}</td>
61 <td class="text-center" >{{url}}</td> 90 <td class="text-center" >{{url}}</td>
62 <td class="text-center" >{{time}}</td> 91 <td class="text-center" >{{time}}</td>
63 <td class="text-center" >{{job_name}}</td> 92 <td class="text-center" >{{job_name}}</td>
64 <td class="text-center"> 93 <td class="text-center">
65 - <a href="#pop" class="edit-btn" data-toggle="modal">执行日志</a> 94 + <a href="javascript:;" class="log-btn">执行日志</a>
66 <a href="javascript:;" class="del-btn">删除</a> 95 <a href="javascript:;" class="del-btn">删除</a>
67 </td> 96 </td>
68 </tr> 97 </tr>
@@ -96,8 +125,7 @@ @@ -96,8 +125,7 @@
96 </div><!--/contentpanel--> 125 </div><!--/contentpanel-->
97 126
98 <script id="task-add-tpl" type="text/tmpl"> 127 <script id="task-add-tpl" type="text/tmpl">
99 -<br />  
100 -<div class="add-task"> 128 +<div class="task-add">
101 <ul> 129 <ul>
102 <li> 130 <li>
103 执行频率: 131 执行频率:
@@ -111,16 +139,34 @@ @@ -111,16 +139,34 @@
111 <li>任务名称:<input type="text" class="job-name" placeholder='请输入任务名称...'></li> 139 <li>任务名称:<input type="text" class="job-name" placeholder='请输入任务名称...'></li>
112 <li>执行链接:<input type="text" class="job-link" placeholder='请输入执行链接...'></li> 140 <li>执行链接:<input type="text" class="job-link" placeholder='请输入执行链接...'></li>
113 <li>延迟时间:<input type="text" class="job-time" placeholder='请输入延迟时间...'></li> 141 <li>延迟时间:<input type="text" class="job-time" placeholder='请输入延迟时间...'></li>
114 - <li><span class="err-tip"></span></li>  
115 </ul> 142 </ul>
  143 + <p><span class="err-tip"></span></p>
116 </div> 144 </div>
  145 +</script>
117 146
  147 +<script id="task-log-tpl" type="text/tmpl">
  148 +<div class="task-log">
  149 + <table class="table table-striped table-bordered">
  150 + <thead>
  151 + <tr>
  152 + <th class="text-center" width="20%">执行时间</th>
  153 + <th class="text-center" width="20%">状态码</th>
  154 + <th class="text-center" width="50%">执行结果</th>
  155 + <th class="text-right" width="10%">
  156 + <a href="javascript:;" class="btn btn-default btn-refresh-log">刷新</a>
  157 + </th>
  158 + </tr>
  159 + </thead>
  160 + <tbody></tbody>
  161 + </table>
  162 +</div>
118 </script> 163 </script>
119 164
120 <script> 165 <script>
121 var tasks = { 166 var tasks = {
122 init: function() { 167 init: function() {
123 var that = this; 168 var that = this;
  169 + var taskData = {};
124 170
125 this.$base = $('.contentpanel'); 171 this.$base = $('.contentpanel');
126 172
@@ -134,6 +180,36 @@ @@ -134,6 +180,36 @@
134 that.del([$tr.data()], () => $tr.remove()); 180 that.del([$tr.data()], () => $tr.remove());
135 }); 181 });
136 182
  183 + // 日志
  184 + this.$base.on('click', '.log-btn', function() {
  185 + let $tr = $(this).closest('tr');
  186 +
  187 + taskData = $tr.data();
  188 +
  189 + return that.getTaskLog(taskData).then(rdata => {
  190 + layer.open({
  191 + type: 1,
  192 + area: ['800px', '500px'],
  193 + title: '《' + $tr.find('.td-name').text() + '》执行明细',
  194 + content: that.taskLogTpl
  195 + });
  196 +
  197 + that.rendLog(rdata.data);
  198 + });
  199 + });
  200 +
  201 + // 日志刷新
  202 + $('body').on('click', '.btn-refresh-log', function() {
  203 + var layerIndex = layer.load(1);
  204 +
  205 + return that.getTaskLog(taskData).then(rdata => {
  206 + setTimeout(function() {
  207 + layer.close(layerIndex);
  208 + that.rendLog(rdata.data);
  209 + }, 2000);
  210 + });
  211 + });
  212 +
137 // 删除全部 213 // 删除全部
138 this.$base.on('click', '.delete-all', function() { 214 this.$base.on('click', '.delete-all', function() {
139 let arr = []; 215 let arr = [];
@@ -144,15 +220,17 @@ @@ -144,15 +220,17 @@
144 220
145 that.del(arr, () => history.go(0)); 221 that.del(arr, () => history.go(0));
146 }); 222 });
  223 +
  224 + this.taskAddTpl = $('#task-add-tpl').html();
  225 + this.taskLogTpl = $('#task-log-tpl').html();
147 }, 226 },
148 add: function() { 227 add: function() {
149 var that = this; 228 var that = this;
150 var layerIndex = layer.open({ 229 var layerIndex = layer.open({
151 type: 1, 230 type: 1,
152 - width: 500,  
153 - area: ['500px'], 231 + area: ['450px'],
154 title: '任务添加', 232 title: '任务添加',
155 - content: $('#task-add-tpl').html(), 233 + content: that.taskAddTpl,
156 btn: '添加', 234 btn: '添加',
157 yes: function() { 235 yes: function() {
158 var data = { 236 var data = {
@@ -163,11 +241,11 @@ @@ -163,11 +241,11 @@
163 }; 241 };
164 242
165 if (data.type < 0) { 243 if (data.type < 0) {
166 - return that.tips('执行频率必填...', '.job-select'); 244 + return that.tips('请选择执行频率...', '.job-select');
167 } else if (data.name === '') { 245 } else if (data.name === '') {
168 return that.tips('任务名称必填...', '.job-name'); 246 return that.tips('任务名称必填...', '.job-name');
169 - } else if (data.url === '') {  
170 - return that.tips('执行链接必填...', '.job-link'); 247 + } else if (data.url === '' || data.url.indexOf('http') === -1) {
  248 + return that.tips('请输入正确的执行链接...', '.job-link');
171 } 249 }
172 250
173 return that.ajax({ 251 return that.ajax({
@@ -187,6 +265,10 @@ @@ -187,6 +265,10 @@
187 }); 265 });
188 }, 266 },
189 del: function(data, callback) { 267 del: function(data, callback) {
  268 + if (data.length <= 0) {
  269 + return false;
  270 + }
  271 +
190 var that = this; 272 var that = this;
191 var layerIndex = layer.confirm('您确定要删除吗!!!', { 273 var layerIndex = layer.confirm('您确定要删除吗!!!', {
192 btn: ['确定', '取消'] 274 btn: ['确定', '取消']
@@ -202,13 +284,38 @@ @@ -202,13 +284,38 @@
202 }); 284 });
203 }); 285 });
204 }, 286 },
  287 + rendLog: function(rdata) {
  288 + var $tbody = $('.task-log tbody');
  289 + $tbody.empty();
  290 +
  291 + if (rdata.length <= 0) {
  292 + $tbody.append(`<tr class="empty">
  293 + <td class="text-center" colspan="4">暂无数据</td>
  294 + </tr>`);
  295 + } else {
  296 + $.each(rdata, (key, item)=> {
  297 + $tbody.append(`<tr>
  298 + <td class="text-center" >${item.time}</td>
  299 + <td class="text-center" >${item.code}</td>
  300 + <td class="text-center" colspan="2">${item.message}</td>
  301 + </tr>`);
  302 + });
  303 + }
  304 + },
  305 + getTaskLog: function(data) {
  306 + return this.ajax({
  307 + url: '/seo/task/log',
  308 + type: 'POST',
  309 + data: data,
  310 + });
  311 + },
205 ajax: function(options) { 312 ajax: function(options) {
206 return Promise.resolve($.ajax(options)); 313 return Promise.resolve($.ajax(options));
207 }, 314 },
208 tips: function(tip, dom) { 315 tips: function(tip, dom) {
209 return layer.tips(tip, dom, { 316 return layer.tips(tip, dom, {
210 tips: [1, '#000'], 317 tips: [1, '#000'],
211 - time: 4000 318 + time: 2000
212 }); 319 });
213 } 320 }
214 }; 321 };