Authored by 周少峰

Merge branch 'feature/sitemap' into feature/seo

  1 +'use strict';
  2 +
  3 +const helpers = global.yoho.helpers;
  4 +const Promise = require('bluebird');
  5 +const _ = require('lodash');
  6 +const sm = require('sitemap');
  7 +const staticUrls = require('../../../config/staticUrls');
  8 +const api = global.yoho.API;
  9 +const Service = global.yoho.ServiceAPI;
  10 +const headerModel = require('../../../doraemon/models/header');
  11 +
  12 +
  13 +const getStaticUrls = (currentStatics) => {
  14 + let urls = [];
  15 +
  16 + _.forEach(_.get(currentStatics, 'loc', []), url => {
  17 + urls.push({
  18 + url: url,
  19 + changefreq: currentStatics.changefreq,
  20 + priority: currentStatics.priority
  21 + });
  22 + });
  23 +
  24 +
  25 + _.forEach(currentStatics, (value) => {
  26 + _.forEach(value.loc, url => {
  27 + urls.push({
  28 + url: url,
  29 + changefreq: value.changefreq,
  30 + priority: value.priority
  31 + });
  32 + });
  33 + });
  34 +
  35 + return Promise.resolve(urls);
  36 +};
  37 +
  38 +// www 地图数据
  39 +const wwwXmlData = () => {// eslint-disable-line
  40 + return getStaticUrls(_.get(staticUrls, 'www'));
  41 +};
  42 +
  43 +// list 地图数据
  44 +const listXmlData = () => {// eslint-disable-line
  45 + return Promise.all([getStaticUrls(_.get(staticUrls, 'list')), headerModel.requestHeaderData()]).then(result => {
  46 +
  47 + // 获取导航中的列表链接
  48 + let listNav = [],
  49 + listPatten = /list\.yohobuy\.com/;
  50 +
  51 + _.forEach(_.get(result[1], 'headerData.subNavGroup'), val => {
  52 + _.forEach(val.subNav, sub => {
  53 + if (listPatten.test(sub.link)) {
  54 + listNav.push({url: sub.link, changefreq: 'daily', priority: 0.3});
  55 + }
  56 + _.forEach(_.get(sub, 'thirdNav'), third => {
  57 + if (listPatten.test(third.link)) {
  58 + listNav.push({url: third.link, changefreq: 'daily', priority: 0.3});
  59 + }
  60 + });
  61 + });
  62 + });
  63 +
  64 + return _.union(result[0], _.uniqBy(listNav, 'url'));
  65 + });
  66 +};
  67 +
  68 +// item 地图数据
  69 +const itemXmlData = () => {// eslint-disable-line
  70 + let urls = [];
  71 +
  72 + return api.get('', {method: 'web.product.bdPromotion'}, {cache: 86400}).then(res => {
  73 + _.forEach(_.get(res, 'data', ''), val => {
  74 + urls.push({
  75 + url: `https:${helpers.getUrlBySkc(val.id)}`,
  76 + changefreq: 'daily',
  77 + priority: 0.3
  78 + });
  79 + });
  80 +
  81 + return urls;
  82 + });
  83 +};
  84 +
  85 +const getArticleUrls = () => {
  86 + let urls = [];
  87 +
  88 + return Service.get('/guang/api/v2/article/getLastArticleList', {limit: 1000}, {cache: 86400}).then(res => {
  89 +
  90 + _.forEach(_.get(res, 'data.artList', ''), val => {
  91 + urls.push({
  92 + url: `https:${helpers.urlFormat(`/${val.articleId}.html`, '', 'guang')}`,
  93 + changefreq: 'daily',
  94 + priority: 0.3
  95 + });
  96 + });
  97 +
  98 + return urls;
  99 + });
  100 +};
  101 +
  102 +// guang 地图数据
  103 +const guangXmlData = () => {// eslint-disable-line
  104 + return Promise.all([getStaticUrls(_.get(staticUrls, 'guang')), getArticleUrls()]).then(res => {
  105 + return _.union(res[0], res[1]);
  106 + });
  107 +};
  108 +
  109 +// 站点地图
  110 +const siteMap = (req, res, next) => {
  111 +
  112 + let siteList = ['www', 'list', 'item', 'guang'],
  113 + subdomain = req.subdomains[0] || 'www';
  114 +
  115 + if (_.find(siteList, subdomain)) {
  116 + res.end('end');
  117 + return;
  118 + }
  119 +
  120 + eval(subdomain + 'XmlData')().then(urls => {// eslint-disable-line
  121 + sm.createSitemap({
  122 + hostname: `https://${subdomain}.yohobuy.com`,
  123 + xmlNs: ' ',
  124 + urls: urls
  125 + }).toXML(function(err, xml) {
  126 + if (err) {
  127 + return res.status(500).end();
  128 + }
  129 + res.header('Content-Type', 'application/xml');
  130 + res.send(xml);
  131 + });
  132 + }).catch(next);
  133 +};
  134 +
  135 +module.exports = {
  136 + siteMap
  137 +};
@@ -31,5 +31,4 @@ router.get('/material/getRecommendlist', auth, materialController.getRecommendli @@ -31,5 +31,4 @@ router.get('/material/getRecommendlist', auth, materialController.getRecommendli
31 router.get('/activate-count', auth, activate.index); 31 router.get('/activate-count', auth, activate.index);
32 router.get('/activate-count/getList', auth, activate.getList); 32 router.get('/activate-count/getList', auth, activate.getList);
33 router.get('/questionnaire/:id', auth, questionnaire.getQuestionnaire); 33 router.get('/questionnaire/:id', auth, questionnaire.getQuestionnaire);
34 -  
35 module.exports = router; 34 module.exports = router;
@@ -11,6 +11,8 @@ const cRoot = './controllers'; @@ -11,6 +11,8 @@ const cRoot = './controllers';
11 11
12 // Your controller here 12 // Your controller here
13 const channelController = require(`${cRoot}/index`); 13 const channelController = require(`${cRoot}/index`);
  14 +const sitemap = require('../3party/controllers/sitemap');
  15 +
14 16
15 // 频道页路由 17 // 频道页路由
16 router.get('/', channelController.index); 18 router.get('/', channelController.index);
@@ -27,4 +29,7 @@ router.get('/channel/isNewUserAjax', channelController.hasNewUserFloor); @@ -27,4 +29,7 @@ router.get('/channel/isNewUserAjax', channelController.hasNewUserFloor);
27 router.post('/common/getNewArrival', channelController.getNewArrival); 29 router.post('/common/getNewArrival', channelController.getNewArrival);
28 router.get('/guide', channelController.getIndexGuide); 30 router.get('/guide', channelController.getIndexGuide);
29 31
  32 +// www站点地图
  33 +router.get('/sitemap.xml', sitemap.siteMap);
  34 +
30 module.exports = router; 35 module.exports = router;
@@ -10,6 +10,7 @@ const router = require('express').Router(); // eslint-disable-line @@ -10,6 +10,7 @@ const router = require('express').Router(); // eslint-disable-line
10 const cRoot = './controllers'; 10 const cRoot = './controllers';
11 11
12 const guangController = require(`${cRoot}/index`); 12 const guangController = require(`${cRoot}/index`);
  13 +const sitemap = require('../3party/controllers/sitemap');
13 14
14 router.get(['/', '/index/index'], guangController.index); 15 router.get(['/', '/index/index'], guangController.index);
15 router.get(['/detail/:id', '/info/index'], guangController.detail); // guang/info/index 16 router.get(['/detail/:id', '/info/index'], guangController.detail); // guang/info/index
@@ -28,4 +29,7 @@ router.get('/info/detailData', guangController.detailDynamicData); @@ -28,4 +29,7 @@ router.get('/info/detailData', guangController.detailDynamicData);
28 29
29 // router.get('/info/commentData', guangController.detailCommentData); 30 // router.get('/info/commentData', guangController.detailCommentData);
30 31
  32 +// guang站点地图
  33 +router.get('/sitemap.xml', sitemap.siteMap);
  34 +
31 module.exports = router; 35 module.exports = router;
@@ -10,6 +10,7 @@ const router = require('express').Router(); // eslint-disable-line @@ -10,6 +10,7 @@ const router = require('express').Router(); // eslint-disable-line
10 const cRoot = './controllers'; 10 const cRoot = './controllers';
11 const auth = require(`${global.middleware}/auth`); 11 const auth = require(`${global.middleware}/auth`);
12 const gbk2utf = require(`${global.middleware}/gbk2utf`); 12 const gbk2utf = require(`${global.middleware}/gbk2utf`);
  13 +const sitemap = require('../3party/controllers/sitemap');
13 14
14 // 商品详情controller 15 // 商品详情controller
15 const detail = require(`${cRoot}/detail`); 16 const detail = require(`${cRoot}/detail`);
@@ -133,4 +134,8 @@ router.get('/students/list', students.list); // 获取优惠券领取状态 @@ -133,4 +134,8 @@ router.get('/students/list', students.list); // 获取优惠券领取状态
133 134
134 // 新品到着改版 135 // 新品到着改版
135 router.get('/newArrive', newArrive.index); // 获取优惠券领取状态 136 router.get('/newArrive', newArrive.index); // 获取优惠券领取状态
  137 +
  138 +// list&item 站点地图
  139 +router.get('/sitemap.xml', sitemap.siteMap);
  140 +
136 module.exports = router; 141 module.exports = router;
  1 +/**
  2 + * pc/wap站静态url 用于站点地图
  3 + *
  4 + */
  5 +
  6 +const moment = require('moment');
  7 +const today = moment().format('Y-M-D');
  8 +
  9 +module.exports = {
  10 + www: {
  11 + // 频道
  12 + channel: {
  13 + loc: ['https://www.yohobuy.com/', 'https://www.yohobuy.com/girls/', 'https://www.yohobuy.com/kids/', 'https://www.yohobuy.com/lifestyle/'],
  14 + lastmod: today,
  15 + changefreq: 'daily',
  16 + priority: 0.8
  17 + },
  18 +
  19 + // 品牌一览
  20 + brands: {
  21 + loc: ['https://www.yohobuy.com/boys-brands/', 'https://www.yohobuy.com/girls-brands/', 'https://www.yohobuy.com/kids-brands/', 'https://www.yohobuy.com/lifestyle-brands/'],
  22 + lastmod: today,
  23 + changefreq: 'daily',
  24 + priority: 0.5
  25 + },
  26 +
  27 + // 领券中心
  28 + coupon: {
  29 + loc: ['https://www.yohobuy.com/coupon/'],
  30 + lastmod: today,
  31 + changefreq: 'weekly',
  32 + priority: 0.3
  33 +
  34 + },
  35 +
  36 + // sale
  37 + salse: {
  38 + loc: ['https://www.yohobuy.com/product/boys-sale/', 'https://www.yohobuy.com/product/girls-sale/', 'https://www.yohobuy.com/product/kids-sale/', 'https://www.yohobuy.com/product/lifestyle-sale/'],
  39 + lastmod: today,
  40 + changefreq: 'daily',
  41 + priority: 0.3
  42 + }
  43 +
  44 + },
  45 + list: {
  46 + // 新品到着
  47 + new: {
  48 + loc: ['https://list.yohobuy.com/boys-new/', 'https://list.yohobuy.com/girls-new/', 'https://list.yohobuy.com/kids-new/', 'https://list.yohobuy.com/lifestyle-new/'],
  49 + lastmod: today,
  50 + changefreq: 'daily',
  51 + priority: 0.5
  52 + },
  53 +
  54 + // 分类列表
  55 + category: {
  56 + loc: [],
  57 + lastmod: today,
  58 + changefreq: 'daily',
  59 + priority: 0.3
  60 + }
  61 + },
  62 +
  63 + // 搜索列表
  64 + search: {
  65 + loc: ['https://search.yohobuy.com/'],
  66 + lastmod: today,
  67 + changefreq: 'daily',
  68 + priority: 0.3
  69 + },
  70 +
  71 + // 逛 编辑列表/标签列表/逛详情动态添加
  72 + guang: {
  73 + loc: ['https://guang.yohobuy.com/boys/', 'https://guang.yohobuy.com/girls/', 'https://guang.yohobuy.com/kids/', 'https://guang.yohobuy.com/lifestyle/'],
  74 + lastmod: today,
  75 + changefreq: 'daily',
  76 + priority: 0.3
  77 + },
  78 +
  79 + // 商品详情动态添加
  80 + item: {
  81 + loc: [],
  82 + lastmod: today,
  83 + changefreq: 'daily',
  84 + priority: 0.3
  85 + }
  86 +};
@@ -36,6 +36,7 @@ module.exports = [ @@ -36,6 +36,7 @@ module.exports = [
36 return `/product${req.url}`; 36 return `/product${req.url}`;
37 } 37 }
38 }, 38 },
  39 +
39 // 商品详情页新链接 40 // 商品详情页新链接
40 { 41 {
41 type: TYPE.rewrite, 42 type: TYPE.rewrite,
@@ -48,6 +48,7 @@ @@ -48,6 +48,7 @@
48 "request-ip": "^1.2.2", 48 "request-ip": "^1.2.2",
49 "request-promise": "^3.0.0", 49 "request-promise": "^3.0.0",
50 "serve-favicon": "^2.3.0", 50 "serve-favicon": "^2.3.0",
  51 + "sitemap": "^1.12.0",
51 "urlencode": "^1.1.0", 52 "urlencode": "^1.1.0",
52 "uuid": "^2.0.2", 53 "uuid": "^2.0.2",
53 "yoho-express-session": "^2.0.0", 54 "yoho-express-session": "^2.0.0",