Authored by 周少峰

rootWords

No preview for this file type
... ... @@ -4,6 +4,7 @@ const Router = require('koa-router');
const _ = require('lodash');
const md5 = require('md5');
const pager = require('../utils/pager');
const seoModel = require('../models/seoModel');
let r = new Router();
... ... @@ -209,17 +210,23 @@ const tdk = {
// 词根
const rootWords = {
index: async(ctx, next) => {
let model = new seoModel(ctx);
let resData = {};
resData = await model.rootWordsData();
await ctx.render('action/seo_root_words', Object.assign(resData, {
title: '词根管理'
}));
},
add: async(ctx, next) => {
let model = new seoModel(ctx);
let resData = {};
resData = await model.addRootWordsData();
await ctx.render('action/seo_root_add', Object.assign(resData, {
title: '添加词根'
}));
... ... @@ -227,7 +234,7 @@ const rootWords = {
},
doAdd: async(ctx, next) => {
ctx.redirect('/seo/rootwords');
},
delete: async(ctx, next) => {
... ... @@ -235,6 +242,15 @@ const rootWords = {
},
edit: async(ctx, next) => {
},
getSubSorts: async(ctx, next) => {
let model = new seoModel(ctx);
let sortId = ctx.request.body.sortId,
resData;
resData = await model.getSubSorts(sortId);
ctx.response.body = resData;
}
}
... ... @@ -250,6 +266,7 @@ r.get('/rootwords/add', rootWords.add);
r.post('/rootwords/doadd', rootWords.doAdd);
r.post('/rootwords/edit', rootWords.edit);
r.post('/rootwords/delete', rootWords.delete);
r.post('/rootwords/getsubsorts', rootWords.getSubSorts);
module.exports = r;
... ...
... ... @@ -5,6 +5,7 @@
*/
'use strict';
const path = require('path');
const json = require('koa-json')
const Koa = require('koa');
const hbs = require('../../middleware/yoho-koa-hbs');
... ... @@ -16,6 +17,8 @@ const redis = require('../../lib/redis');
const app = new Koa();
app.use(json())
app.use(hbs({
views: path.join(__dirname, '/views'),
defaultLayout: 'layout',
... ...
'use strict';
const _ = require('lodash');
const seoHelper = require('../utils/seoHelper');
const model = require('../../../lib/model');
class seoModel extends model {
constructor(ctx) {
super(ctx);
}
/**
* 获取所有品牌(redis || api)
*/
getBrands() {
let brandsRedisKey = 'global:yoho:brands';
// 先取redis
return this.ctx.redis.getAsync(brandsRedisKey).then(brands => {
if (!brands) {
// 调用接口
return this.get('http://192.168.102.216:8080/yohosearch/brand/list.json').then(res => {
if (res) {
this.ctx.redis.setAsync(brandsRedisKey, JSON.stringify(res));
brands = res;
}
return brands;
})
} else {
return JSON.parse(brands);
}
}).catch(()=>{
return {};
});
}
/**
* 获取所有分类 (redis || api)
*/
getSort() {
let sortsRedisKey = 'global:yoho:sorts';
// 先取redis
return this.ctx.redis.getAsync(sortsRedisKey).then(sorts => {
if (!sorts) {
// 调用接口
return this.get('http://192.168.102.216:8080/yohosearch/sortgroup.json',{needAllSort:1, needSmallSort: 1}).then(res => {
if (res) {
this.ctx.redis.setAsync(sortsRedisKey, JSON.stringify(res));
sorts = res;
}
return sorts;
})
} else {
return JSON.parse(sorts);
}
}).catch(()=>{
return {};
});
}
/**
* 添加词根数据
*/
addRootWordsData() {
return Promise.all([this.getBrands(), this.getSort()]).then(result => {
return {brand: seoHelper.sortBrands(result[0]), sort: seoHelper.getSubSorts(result[1])};
})
}
/**
* 词根列表数据
*/
rootWordsData() {
return Promise.all([this.getBrands(), this.getSort()]).then(result => {
return {brand: seoHelper.sortBrands(result[0]), sort: seoHelper.getSubSorts(result[1])};
})
}
/**
* 获取子分类
*/
getSubSorts(sortId) {
return this.getSort().then(sorts => {
return seoHelper.getSubSorts(sorts, sortId);
});
}
}
module.exports = seoModel;
... ...
'use strict';
const _ = require('lodash');
// 品牌按字母分类
const sortBrands = (brands) => {
let data = {
'0-9': []
};
let number = /^[\d]*$/;
_.forEach(_.get(brands, 'data'), (val, key) => {
let brand = {id: val.id, brandName: val.brand_name};
if (number.test(val.brand_alif)) {
data['0-9'].push(brand);
} else {
if (!data[val.brand_alif]) {
data[val.brand_alif] = [];
}
data[val.brand_alif].push(brand);
}
})
return data;
}
// 获取子分类
const getSubSorts = (sort, sortId) => {
let noSortIdresult = [],
specialSorts = [];
_.forEach(_.get(sort, 'data.sort'), (msort) => {
if (sortId) {
if (sortId === msort.sort_id) {
specialSorts = msort.sub;
return;
}
_.forEach(msort.sub, (misort) => {
if (sortId === misort.sort_id) {
specialSorts = misort.sub;
return;
}
})
} else {
noSortIdresult.push({id: msort.sort_id, sortName: msort.sort_name});
}
})
return !_.isEmpty(specialSorts) ? specialSorts : noSortIdresult;
}
module.exports = {
sortBrands,
getSubSorts
}
\ No newline at end of file
... ...
<style>
.brand-list {
max-height: 400px;
overflow: auto;
}
.brand-list a{
display:inline-block;
color: #000;
padding: 5px 10px;
margin: 3px 0;
}
.brand-list a.active{
color: #fff;
background: #428bca;
padding: 5px 10px;
}
</style>
<div class="pageheader">
... ... @@ -23,68 +37,56 @@
<div class="contentpanel seo-root-page" style="padding-bottom:0;">
<div class="panel panel-default">
<div class="panel-body">
<form action="/seo/rootwords/doadd" type="post">
<div class="form-group">
<label for="exampleInputEmail1">词根</label>
<input type="text" class="form-control" >
</div>
<div class="form-group">
<label for="exampleInputEmail1">品牌</label>
<ul id="brandTab" class="nav nav-tabs">
<li class="active"><a href="#home" data-toggle="tab">0~9</a></li>
<li><a href="#a" data-toggle="tab">a</a></li>
<li><a href="#b" data-toggle="tab">b</a></li>
</ul>
<div id="brandTabContent" class="tab-content">
<div class="tab-pane fade in active" id="home">
<a>0addidas</a>
<a>1addidas</a>
<a>2addidas</a>
</div>
<div class="tab-pane fade" id="a">
<a>addidas</a>
<a>ALTAMONT</a>
<a>Anthony</a>
</div>
<div class="tab-pane fade" id="b">
<a>baddidas</a>
<a>baddidas</a>
<a>baddidas</a>
</div>
<div class="form-group">
<label for="exampleInputEmail1">词根</label>
<input type="text" name="rootWord" class="form-control" >
</div>
<div class="form-group">
<label >品牌</label>
<ul id="brandTab" class="nav nav-tabs brand-category">
{{#each brand}}
<li {{#if @first}}class="active"{{/if}}><a href="#{{@key}}" data-toggle="tab">{{@key}}</a></li>
{{/each}}
</ul>
<div id="brandTabContent" class="tab-content brand-list">
{{#each brand}}
<div class="tab-pane fade {{#if @first}}in active{{/if}}" id="{{@key}}">
{{# .}}<a data-id="{{id}}"> {{brandName}} </a>{{/ .}}
</div>
{{/each}}
</div>
<div class="form-group">
<label for="exampleInputEmail1">品类</label>
<div class="row">
<div class="col-md-3">
<select id="msort" class="form-control">
<option value="1" class="form-control">上衣</option>
</select>
</div>
<div class="col-md-3">
<select id="msort" class="form-control">
<option value="1">T恤</option>
</select>
</div>
<div class="col-md-3">
<select class="form-control">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
</div>
<div class="form-group">
<label for="exampleInputEmail1">品类</label>
<div class="row">
<div class="col-md-3">
<select id="msort" class="form-control">
<option class="form-control">请选择</option>
{{#each sort}}
<option data="{{id}}" value="{{id}}" class="form-control">{{sortName}}</option>
{{/each}}
</select>
</div>
<div class="col-md-3">
<select id="misort" class="form-control">
<option class="form-control">请选择</option>
</select>
</div>
<div class="col-md-3">
<select id="sort" class="form-control">
<option class="form-control">请选择</option>
</select>
</div>
</div>
<div class="form-group">
<label for="exampleInputEmail1">过滤词</label>
<input type="text" class="form-control" >
</div>
<button type="submit" class="btn btn-default">提交</button>
</form>
</div>
<div class="form-group">
<label for="exampleInputEmail1">过滤词</label>
<input type="text" name="filter" class="form-control" >
</div>
<button type="submit" id="submit" class="btn btn-default">提交</button>
</div>
</div>
... ... @@ -92,3 +94,62 @@
</div>
<script>
$(function(){
var brand = $('.brand-list a'), selectBrand = 0;
var msort = $('#msort'), misort = $('#misort'), sort = $('#sort');
// 选择品牌
brand.on('click', function(){
brand.removeClass('active');
$(this).toggleClass('active');
selectBrand = $(this).data('id');
})
// 切换大分类
msort.on('change',function() {
selectInit('misort');
selectInit('sort');
getSubSorts($(this).val(), 'misort');
})
// 切换中分类
misort.on('change',function() {
selectInit('sort');
getSubSorts($(this).val(), 'sort');
})
// 提交TODO: 前端校验,数据提交,后端数据保存;删除功能;
// 获取子分类数据
function getSubSorts(sortId, id) {
$.ajax({
url: '/seo/rootwords/getsubsorts',
dataType: 'json',
type: 'POST',
data: {
sortId: sortId
},
success: function(data) {
var option = '';
$.each(data, function(key, val) {
option +='<option value="' + val.sort_id + '">' + val.sort_name + '</option>';
console.log(val);
});
$('#'+id).append(option);
},
error: function(err) {
console.log(err);
}
});
}
// 清空子分类
function selectInit(id) {
$('#'+id).html('<option class="form-control">请选择</option>');
}
})
</script>
\ No newline at end of file
... ...
... ... @@ -14,8 +14,8 @@ const defaults = {
},
redis: {
connect: {
// host: '127.0.0.1',
host: 'web.redis.yohoops.org',
host: '127.0.0.1',
//host: 'web.redis.yohoops.org',
},
port: '6379',
retry_strategy(options) {
... ... @@ -38,6 +38,40 @@ const defaults = {
password: 'yh_test',
port: '3306',
database: 'seo',
},
domains: {
// test3
singleApi: 'http://api-test3.yohops.com:9999/',
api: 'http://api-test3.yohops.com:9999/',
service: 'http://service-test3.yohops.com:9999/',
serviceNotify: 'http://service-test3.yohops.com:9999/',
global: 'http://global-test-soa.yohops.com:9999/',
platformApi: 'http://192.168.102.48:8088/',
// prod
// singleApi: 'http://single.yoho.cn/',
// api: 'http://api.yoho.cn/',
// service: 'http://service.yoho.cn/',
// serviceNotify: 'http://service.yoho.cn/',
// global: 'http://api-global.yohobuy.com/',
// platformApi: 'http://172.16.6.210:8088/',
// gray
// singleApi: 'http://single.gray.yohops.com/',
// api: 'http://api.gray.yohops.com/',
// service: 'http://service.gray.yohops.com/',
// platformApi: 'http://172.16.6.210:8088/',
// dev
// api: 'http://dev-api.yohops.com:9999/',
// service: 'http://dev-service.yohops.com:9999/',
// serviceNotify: 'http://dev-service.yohops.com:9999/',
// singleApi: 'http://dev-api.yohops.com:9999/',
// platformApi: 'http://192.168.102.48:8088/',,
imSocket: 'ws://socket.yohobuy.com:10240',
imCs: 'http://im.yohobuy.com/api',
unionApi: 'http://172.16.6.90:8080/'
}
};
... ...
'use strict';
const sign = require('./sign');
const rp = require('request-promise');
const qs = require('querystring');
class model {
constructor(ctx) {
this.ctx = ctx;
}
get(url,qs, params) {
let options = {
uri: url,
method: 'GET',
qs: qs || {},
headers: {
'User-Agent': 'Request-Promise'
},
json: true
};
return rp(options).then(result => {
return result;
}).catch(()=>{
return {};
});
}
}
module.exports = model;
\ No newline at end of file
... ...
... ... @@ -38,6 +38,7 @@
"koa": "^2.0.0",
"koa-body": "^1.4.0",
"koa-convert": "^1.2.0",
"koa-json": "^2.0.2",
"koa-mount": "^2.0.0",
"koa-router": "^7.0.1",
"koa-session": "^3.3.1",
... ...