Authored by 郝肖肖

Merge branch 'feature/extWord' of git.yoho.cn:OPENTECH/yoho-node-ci into feature/extWord

No preview for this file type
1 .vscode/ 1 .vscode/
2 2
  3 +.DS_Store
  4 +
3 node_modules/ 5 node_modules/
4 6
5 db/** 7 db/**
@@ -206,11 +206,50 @@ const tdk = { @@ -206,11 +206,50 @@ const tdk = {
206 } 206 }
207 }; 207 };
208 208
  209 +// 词根
  210 +const rootWords = {
  211 + index: async(ctx, next) => {
  212 +
  213 + let resData = {};
  214 +
  215 + await ctx.render('action/seo_root_words', Object.assign(resData, {
  216 + title: '词根管理'
  217 + }));
  218 + },
  219 +
  220 + add: async(ctx, next) => {
  221 + let resData = {};
  222 +
  223 + await ctx.render('action/seo_root_add', Object.assign(resData, {
  224 + title: '添加词根'
  225 + }));
  226 +
  227 + },
  228 +
  229 + doAdd: async(ctx, next) => {
  230 +
  231 + },
  232 +
  233 + delete: async(ctx, next) => {
  234 +
  235 + },
  236 + edit: async(ctx, next) => {
  237 +
  238 + }
  239 +}
  240 +
209 r.get('/', tdk.index); 241 r.get('/', tdk.index);
210 r.get('/tdk', tdk.index); 242 r.get('/tdk', tdk.index);
211 r.post('/tdk/add', tdk.add); 243 r.post('/tdk/add', tdk.add);
212 r.post('/tdk/edit', tdk.edit); 244 r.post('/tdk/edit', tdk.edit);
213 r.post('/tdk/delete', tdk.delete); 245 r.post('/tdk/delete', tdk.delete);
214 246
  247 +// 词根管理
  248 +r.get('/rootwords', rootWords.index);
  249 +r.get('/rootwords/add', rootWords.add);
  250 +r.post('/rootwords/doadd', rootWords.doAdd);
  251 +r.post('/rootwords/edit', rootWords.edit);
  252 +r.post('/rootwords/delete', rootWords.delete);
  253 +
215 254
216 module.exports = r; 255 module.exports = r;
  1 +<style>
  2 +
  3 +</style>
  4 +
  5 +<div class="pageheader">
  6 + <div class="media">
  7 + <div class="pageicon pull-left">
  8 + <i class="fa fa-th-list"></i>
  9 + </div>
  10 + <div class="media-body">
  11 + <ul class="breadcrumb">
  12 + <li><a href=""><i class="glyphicon glyphicon-home"></i></a></li>
  13 + <li><a href="/seo/tdk">{{title}}</a></li>
  14 + <li>{{typeName}}</li>
  15 + </ul>
  16 + <h4>{{title}}</h4>
  17 + </div>
  18 + </div>
  19 + <!-- media -->
  20 +</div>
  21 +<!-- pageheader -->
  22 +
  23 +<div class="contentpanel seo-root-page" style="padding-bottom:0;">
  24 + <div class="panel panel-default">
  25 + <div class="panel-body">
  26 + <form action="/seo/rootwords/doadd" type="post">
  27 + <div class="form-group">
  28 + <label for="exampleInputEmail1">词根</label>
  29 + <input type="text" class="form-control" >
  30 + </div>
  31 + <div class="form-group">
  32 + <label for="exampleInputEmail1">品牌</label>
  33 + <ul id="brandTab" class="nav nav-tabs">
  34 + <li class="active"><a href="#home" data-toggle="tab">0~9</a></li>
  35 + <li><a href="#a" data-toggle="tab">a</a></li>
  36 + <li><a href="#b" data-toggle="tab">b</a></li>
  37 + </ul>
  38 + <div id="brandTabContent" class="tab-content">
  39 + <div class="tab-pane fade in active" id="home">
  40 + <a>0addidas</a>
  41 + <a>1addidas</a>
  42 + <a>2addidas</a>
  43 + </div>
  44 + <div class="tab-pane fade" id="a">
  45 + <a>addidas</a>
  46 + <a>ALTAMONT</a>
  47 + <a>Anthony</a>
  48 + </div>
  49 + <div class="tab-pane fade" id="b">
  50 + <a>baddidas</a>
  51 + <a>baddidas</a>
  52 + <a>baddidas</a>
  53 + </div>
  54 + </div>
  55 + </div>
  56 + <div class="form-group">
  57 + <label for="exampleInputEmail1">品类</label>
  58 + <div class="row">
  59 + <div class="col-md-3">
  60 + <select id="msort" class="form-control">
  61 + <option value="1" class="form-control">上衣</option>
  62 + </select>
  63 + </div>
  64 + <div class="col-md-3">
  65 + <select id="msort" class="form-control">
  66 + <option value="1">T恤</option>
  67 + </select>
  68 + </div>
  69 + <div class="col-md-3">
  70 + <select class="form-control">
  71 + <option>1</option>
  72 + <option>2</option>
  73 + <option>3</option>
  74 + <option>4</option>
  75 + <option>5</option>
  76 + </select>
  77 + </div>
  78 + </div>
  79 +
  80 + </div>
  81 + <div class="form-group">
  82 + <label for="exampleInputEmail1">过滤词</label>
  83 + <input type="text" class="form-control" >
  84 + </div>
  85 +
  86 + <button type="submit" class="btn btn-default">提交</button>
  87 + </form>
  88 + </div>
  89 + </div>
  90 +
  91 +
  92 +</div>
  93 +
  94 +
  1 +<style>
  2 + .seo-tdk-page ul {
  3 + padding: 0;
  4 + }
  5 +
  6 + .seo-tdk-page li {
  7 + list-style: none;
  8 + }
  9 +
  10 + .seo-tdk-page .query-form {
  11 + font-size: 0;
  12 + }
  13 +
  14 + .seo-tdk-page .query-form .btn-group {
  15 + margin-bottom: 0;
  16 + }
  17 +
  18 + .seo-tdk-page .query-form .dropdown-toggle {
  19 + border-top-right-radius: 0;
  20 + border-bottom-right-radius: 0;
  21 + }
  22 +
  23 + .seo-tdk-page .query-form .query-submit-btn {
  24 + height: 39px;
  25 + border-top-left-radius: 0;
  26 + border-bottom-left-radius: 0;
  27 + }
  28 +
  29 + .seo-tdk-page .query-key {
  30 + width: 300px;
  31 + height: 39px;
  32 + font-size: 14px;
  33 + vertical-align: middle;
  34 + outline: none;
  35 + }
  36 +
  37 + .seo-tdk-page .text-limit {
  38 + max-width: 78px;
  39 + display: inline-block;
  40 + vertical-align: top;
  41 + overflow: hidden;
  42 + text-overflow: ellipsis;
  43 + white-space: nowrap;
  44 + }
  45 +
  46 + .seo-tdk-page .pagination {
  47 + margin: 0;
  48 + }
  49 +
  50 + .seo-tdk-page #table-tdk th,
  51 + .seo-tdk-page #table-tdk td {
  52 + height: 36px;
  53 + }
  54 +
  55 + .seo-tdk-page #pop{
  56 + width:500px;
  57 + height: 434px;
  58 + background: #fff;
  59 + left: 0;
  60 + right: 0;
  61 + top: 0;
  62 + bottom: 0;
  63 + margin:auto;
  64 + }
  65 +
  66 + .seo-tdk-page #pop .cover-title {
  67 + position: absolute;
  68 + background: #fff;
  69 + margin-top: -34px;
  70 + }
  71 +
  72 + .seo-tdk-page #pop .control-label {
  73 + width: 60px;
  74 + text-align: right;
  75 + }
  76 +
  77 + .seo-tdk-page #pop li {
  78 + padding: 6px 0;
  79 + }
  80 +
  81 + .seo-tdk-page #pop select,
  82 + .seo-tdk-page #pop input {
  83 + height: 30px;
  84 + width: 200px;
  85 + }
  86 +
  87 + .seo-tdk-page #pop textarea {
  88 + height: 70px;
  89 + vertical-align: text-top;
  90 + border-color: #ccc;
  91 + resize: none;
  92 + }
  93 +
  94 + .seo-tdk-page #pop .full-w {
  95 + width: 390px;
  96 + }
  97 +
  98 + .seo-tdk-page #pop .controls {
  99 + display: inline-block;
  100 + }
  101 +
  102 + .seo-tdk-page #pop .err-tip {
  103 + color: #a94442;
  104 + }
  105 +</style>
  106 +
  107 +<div class="pageheader">
  108 + <div class="media">
  109 + <div class="pageicon pull-left">
  110 + <i class="fa fa-th-list"></i>
  111 + </div>
  112 + <div class="media-body">
  113 + <ul class="breadcrumb">
  114 + <li><a href=""><i class="glyphicon glyphicon-home"></i></a></li>
  115 + <li><a href="/seo/tdk">{{title}}</a></li>
  116 + <li>{{typeName}}</li>
  117 + </ul>
  118 + <h4>{{title}}</h4>
  119 + </div>
  120 + </div>
  121 + <!-- media -->
  122 +</div>
  123 +<!-- pageheader -->
  124 +
  125 +<div class="contentpanel seo-tdk-page" style="padding-bottom:0;">
  126 + <div class="panel panel-default">
  127 + <div class="panel-body">
  128 + <label style="margin-right:20px;"><input type="checkbox" id="check-all" style="margin-right:5px;">全选</label>
  129 + <a data-toggle="modal" href="/seo/rootwords/add" class="btn btn-default" style="margin-right:10px;">增加</a>
  130 + <button class="btn btn-default delete-all" type="submit">删除</button>
  131 +
  132 + <div class="input-append pull-right">
  133 + <form id="query-form" action="/seo/tdk" class="query-form" method="get">
  134 + <div class="btn-group">
  135 + <button class="btn dropdown-toggle" data-toggle="dropdown">
  136 + {{typeName}}
  137 + <span class="caret"></span>
  138 + </button>
  139 + <ul class="dropdown-menu">
  140 + {{# typeList}}
  141 + <li><a href="?type={{type}}">{{name}}</a></li>
  142 + {{/ typeList}}
  143 + </ul>
  144 + </div>
  145 + <input type="hidden" name="type" value="{{type}}">
  146 + <input class="span2 query-key" type="text" name="query" value="{{query}}">
  147 + <button class="btn query-submit-btn" type="submit">搜索</button>
  148 + </form>
  149 + </div>
  150 + </div>
  151 + </div>
  152 +
  153 + <div class="panel panel-default">
  154 + <div class="panel-body">
  155 + <table id="table-tdk" class="table table-striped table-bordered responsive">
  156 + <thead>
  157 + <tr>
  158 + <th class="text-center" width="60">ID</th>
  159 + <th class="text-center" width="160">类型</th>
  160 + <th class="text-center">标题</th>
  161 + <th class="text-center">关键词</th>
  162 + <th class="text-center">描述</th>
  163 + <th class="text-center" width="120">操作</th>
  164 + </tr>
  165 + </thead>
  166 +
  167 + <tbody>
  168 + {{#each tdkList}}
  169 + <tr data-type="{{../type}}" data-key="{{key}}" data-title="{{title}}" data-keywords="{{keywords}}" data-description="{{description}}">
  170 + <td class="text-center"><input type="checkbox" style="margin-right:5px;">{{id}}</td>
  171 + <td class="text-center" title="{{typeName}}({{typeLt}}:{{key}})">{{typeName}}({{typeLt}}:<span class="text-limit">{{key}}</span>)</td>
  172 + <td>{{title}}</td>
  173 + <td>{{keywords}}</td>
  174 + <td>{{description}}</td>
  175 + <td class="text-center">
  176 + <a href="#pop" class="edit-tdk-btn" data-toggle="modal">编辑</a>
  177 + <a href="javascript:;" class="del-tdk-btn">删除</a>
  178 + </td>
  179 + </tr>
  180 + {{/each}}
  181 + {{#unless tdkList}}
  182 + <tr>
  183 + <td class="text-center" colspan="6">暂无数据</td>
  184 + </tr>
  185 + {{/unless}}
  186 + </tbody>
  187 + </table>
  188 + {{# pager}}
  189 + <div class="text-right">
  190 + {{#if pages}}
  191 + <ul class="pagination">
  192 + {{# prePage}}
  193 + <li><a href="{{url}}">上一页</a></li>
  194 + {{/ prePage}}
  195 + {{# pages}}
  196 + <li class="{{#unless url}}disabled {{/unless}}{{#if cur}}active{{/if}}"><a {{#if url}}href="{{url}}"{{^}}href="javascript:;"{{/if}}>{{num}}</a></li>
  197 + {{/ pages}}
  198 + {{# nextPage}}
  199 + <li><a href="{{url}}">下一页</a></li>
  200 + {{/ nextPage}}
  201 + </ul>
  202 + {{/if}}
  203 + </div>
  204 + {{/ pager}}
  205 + </div>
  206 + </div>
  207 +
  208 + <div id="pop" class="modal fade in" style="display: none;">
  209 + <div class="modal-header">
  210 + <a class="close clear-input" data-dismiss="modal">×</a>
  211 + <h4>添加TDK</h4>
  212 + <h4 class="cover-title"></h4>
  213 + </div>
  214 + <div class="modal-body">
  215 + <ul>
  216 + <li>
  217 + <label class="control-label" for="select-type">类型:</label>
  218 + <div class="controls">
  219 + <select id="select-type">
  220 + {{# typeList}}
  221 + <option value="{{type}}">{{name}}</option>
  222 + {{/ typeList}}
  223 + </select>
  224 + </div>
  225 + </li>
  226 + <li>
  227 + <label class="control-label key-label" for="input-key">SKN:</label>
  228 + <div class="controls">
  229 + <input type="text" id="input-key">
  230 + </div>
  231 + </li>
  232 + <li>
  233 + <label class="control-label" for="input-title">标题:</label>
  234 + <div class="controls">
  235 + <input type="text" id="input-title" class="full-w">
  236 + </div>
  237 + </li>
  238 + <li>
  239 + <label class="control-label" for="input-keywords">关键词:</label>
  240 + <div class="controls">
  241 + <input type="text" id="input-keywords" class="full-w">
  242 + </div>
  243 + </li>
  244 + <li>
  245 + <label class="control-label" for="input-description">描述:</label>
  246 + <div class="controls">
  247 + <textarea id="input-description" class="full-w"></textarea>
  248 + </div>
  249 + </li>
  250 + </ul>
  251 + </div>
  252 + <div class="modal-footer">
  253 + <span class="err-tip"></span>
  254 + <a class="btn clear-input close-pop-btn" data-dismiss="modal">关闭</a>
  255 + <a class="btn btn-primary sure-btn">确定</a>
  256 + </div>
  257 + </div>
  258 +</div>
  259 +
  260 +<script>
  261 + var pop = {
  262 + ltList: {
  263 + skn: 'SKN:',
  264 + article: 'ID:',
  265 + shop: 'ShopId:',
  266 + url: 'URL:'
  267 + },
  268 + init: function() {
  269 + var that = this;
  270 +
  271 + this.$base = $('#pop');
  272 + this.$popTitle = $('.cover-title', this.$base);
  273 + this.$keyLabel = $('.key-label', this.$base);
  274 + this.$type = $('#select-type', this.$base);
  275 + this.$key = $('#input-key', this.$base);
  276 + this.$title = $('#input-title', this.$base);
  277 + this.$keywords = $('#input-keywords', this.$base);
  278 + this.$description = $('#input-description', this.$base);
  279 +
  280 + this.$closeBtn = $('.close-pop-btn', this.$base);
  281 + this.$errTip = $('.err-tip', this.$base);
  282 +
  283 + this.$base.on('change', '#select-type', function() {
  284 + that.$keyLabel.text(that.ltList[$(this).val()] || that.ltList.skn);
  285 + }).on('click', '.clear-input', function() {
  286 + that.clearInput();
  287 + }).on('click', '.sure-btn', function() {
  288 + var data;
  289 +
  290 + if (that.saving) {
  291 + return;
  292 + }
  293 +
  294 + data = that.packReqData();
  295 +
  296 + if (!data) {
  297 + that.$errTip.text('请填写完整tdk信息');
  298 + return;
  299 + }
  300 +
  301 + that.saving = true;
  302 +
  303 + $.ajax({
  304 + url: that.editInfo ? '/seo/tdk/edit' : '/seo/tdk/add',
  305 + type: 'POST',
  306 + data: data,
  307 + }).done(function(res) {
  308 + if (res.code === 200) {
  309 + history.go(0);
  310 + }
  311 + }).always(function() {
  312 + that.saving = false;
  313 + });
  314 + });
  315 + },
  316 + clearInput: function() {
  317 + this.editInfo = false;
  318 + this.$popTitle.empty();
  319 + this.$errTip.empty();
  320 + this.$type.val('skn').change();
  321 + this.$type.removeAttr('disabled')
  322 + this.$key.removeAttr('readonly');
  323 + $('input, textarea', this.$base).val('');
  324 + },
  325 + fillInput(info) {
  326 + if (info) {
  327 + this.editInfo = info;
  328 + this.$popTitle.text('编辑TDK');
  329 + this.$type.val(info.type).change().attr('disabled', true);
  330 + this.$key.attr('readonly', 'readonly').val(info.key);
  331 + this.$title.val(info.title);
  332 + this.$keywords.val(info.keywords);
  333 + this.$description.val(info.description);
  334 + }
  335 + this.$base.show();
  336 + },
  337 + packReqData() {
  338 + var data = {
  339 + type: this.$type.val(),
  340 + key: $.trim(this.$key.val()),
  341 + title: $.trim(this.$title.val()),
  342 + keywords: $.trim(this.$keywords.val()),
  343 + description: $.trim(this.$description.val())
  344 + };
  345 + var i;
  346 +
  347 + if (this.editInfo) {
  348 + data.type = this.editInfo.type;
  349 + data.key = this.editInfo.key;
  350 + }
  351 +
  352 + for (i in data) {
  353 + if (data.hasOwnProperty(i) && !data[i]) {
  354 + return false;
  355 + }
  356 + }
  357 +
  358 + return data;
  359 + },
  360 + close() {
  361 + this.$closeBtn.trigger('click');
  362 + }
  363 + };
  364 +
  365 + $(function(){
  366 + var $checkboxs = $('#table-tdk :checkbox');
  367 + var deling;
  368 +
  369 + pop.init();
  370 +
  371 + function delTdk(data) {
  372 + deling = true;
  373 +
  374 + $.ajax({
  375 + url: '/seo/tdk/delete',
  376 + type: 'POST',
  377 + data: {list: data},
  378 + }).done(function(res) {
  379 + if (res.code === 200) {
  380 + history.go(0);
  381 + }
  382 + }).always(function() {
  383 + deling = false;
  384 + });
  385 + };
  386 +
  387 + $('#check-all').click(function() {
  388 + if ($(this).attr('checked') === 'checked') {
  389 + $checkboxs.attr('checked', 'checked');
  390 + } else {
  391 + $checkboxs.removeAttr('checked');
  392 + }
  393 + });
  394 +
  395 + $('.delete-all').click(function() {
  396 + var arr = [];
  397 +
  398 + $('#table-tdk :checkbox:checked').each(function(){
  399 + arr.push($(this).closest('tr').data());
  400 + });
  401 + arr.length ? delTdk(arr) : false;
  402 + });
  403 +
  404 + $('#table-tdk').on('click', '.edit-tdk-btn', function(e) {
  405 + pop.fillInput($(e.target).closest('tr').data());
  406 + }).on('click', '.del-tdk-btn', function(e) {
  407 + var data = $(e.target).closest('tr').data();
  408 +
  409 + delTdk([data]);
  410 + });
  411 + });
  412 +</script>
@@ -14,9 +14,22 @@ const defaults = { @@ -14,9 +14,22 @@ const defaults = {
14 }, 14 },
15 redis: { 15 redis: {
16 connect: { 16 connect: {
17 - host: 'web.redis.yohoops.org',  
18 - port: '6379',  
19 - //password: '' 17 + // host: '127.0.0.1',
  18 + host: 'web.redis.yohoops.org',
  19 + },
  20 + port: '6379',
  21 + retry_strategy(options) {
  22 + if (options.error && options.error.code === 'ECONNREFUSED') {
  23 + console.log('redis连接不成功');
  24 + }
  25 + if (options.total_retry_time > 1000 * 60 * 60 * 6) {
  26 + console.log('redis连接超时');
  27 + return;
  28 + }
  29 + if (options.attempt > 10) {
  30 + return 1000 * 60 * 60 * 0.5;
  31 + }
  32 + return Math.min(options.attempt * 100, 1000);
20 } 33 }
21 }, 34 },
22 mysql: { 35 mysql: {
1 const redis = require('redis'); 1 const redis = require('redis');
2 const bluebird = require('bluebird'); 2 const bluebird = require('bluebird');
3 const config = require('../config/config'); 3 const config = require('../config/config');
  4 +let client;
4 5
5 -const client = redis.createClient(config.redis.connect); 6 +try {
  7 + client = redis.createClient(config.redis.connect);
6 8
7 -bluebird.promisifyAll(redis.RedisClient.prototype);  
8 -bluebird.promisifyAll(redis.Multi.prototype); 9 + bluebird.promisifyAll(redis.RedisClient.prototype);
  10 + bluebird.promisifyAll(redis.Multi.prototype);
  11 +
  12 + client.on('error', function() {
  13 + console.log('redis error');
  14 + client = '';
  15 + });
  16 +} catch (e) {
  17 + client = '';
  18 +}
9 19
10 20
11 module.exports = { 21 module.exports = {
No preview for this file type