Authored by 陈峰

逛rss订阅功能开发完成

@@ -247,7 +247,7 @@ const index = (req, res, next) => { @@ -247,7 +247,7 @@ const index = (req, res, next) => {
247 } 247 }
248 248
249 // 获取详情内容信息, 异常则跳到错误页面 249 // 获取详情内容信息, 异常则跳到错误页面
250 - return infoModel.package(id, isApp).then(detail => { 250 + return infoModel.packageData(id, isApp).then(detail => {
251 let data = { 251 let data = {
252 guangDetail: true, 252 guangDetail: true,
253 guang: {} 253 guang: {}
@@ -341,7 +341,7 @@ const mini = (req, res, next) => { @@ -341,7 +341,7 @@ const mini = (req, res, next) => {
341 } 341 }
342 342
343 // 获取详情内容信息, 异常则跳到错误页面 343 // 获取详情内容信息, 异常则跳到错误页面
344 - return infoModel.package(id, isApp).then(detail => { 344 + return infoModel.packageData(id, isApp).then(detail => {
345 let data = { 345 let data = {
346 guangEzine: true, 346 guangEzine: true,
347 guang: {} 347 guang: {}
@@ -410,7 +410,7 @@ const foryoho = (req, res, next) => { @@ -410,7 +410,7 @@ const foryoho = (req, res, next) => {
410 } 410 }
411 411
412 // 获取详情内容信息, 异常则跳到错误页面 412 // 获取详情内容信息, 异常则跳到错误页面
413 - return infoModel.package(id, isApp).then(detail => { 413 + return infoModel.packageData(id, isApp).then(detail => {
414 let data = {}; 414 let data = {};
415 415
416 if (detail.code !== 400) { 416 if (detail.code !== 400) {
  1 +/**
  2 + * 逛rss订阅
  3 + * @author: chenfeng<feng.chen@yoho.cn>
  4 + * @date: 2016/09/13
  5 + */
  6 +'use strict';
  7 +
  8 +const mRoot = '../models';
  9 +const rssModel = require(`${mRoot}/rss`);
  10 +const helpers = global.yoho.helpers;
  11 +
  12 +/**
  13 + * [订阅逛最新的资讯]
  14 + */
  15 +const index = (req, res, next) => {
  16 + let gender = req.query.gender || '1,2,3',
  17 + items = [];
  18 +
  19 + res.setHeader('Content-Type', 'text/xml; charset=utf-8');
  20 + return rssModel.getRssArticle(gender).then((result) => {
  21 + return res.render('rss/index', {
  22 + layout: false,
  23 + time: '',
  24 + items: result
  25 + })
  26 + });
  27 +}
  28 +
  29 +
  30 +module.exports = {
  31 + index
  32 +}
@@ -14,7 +14,7 @@ const api = global.yoho.API; @@ -14,7 +14,7 @@ const api = global.yoho.API;
14 * @param {string} opt [操作(ok:表示确定,cancel:表示取消)] 14 * @param {string} opt [操作(ok:表示确定,cancel:表示取消)]
15 * @return {[array]} 15 * @return {[array]}
16 */ 16 */
17 -const _favoriteBrand = (uid, id, isBrand, opt) => { 17 +const favoriteBrand = (uid, id, isBrand, opt) => {
18 let param = { 18 let param = {
19 uid: uid, 19 uid: uid,
20 type: isBrand ? 'brand' : 'product' 20 type: isBrand ? 'brand' : 'product'
@@ -32,5 +32,5 @@ const _favoriteBrand = (uid, id, isBrand, opt) => { @@ -32,5 +32,5 @@ const _favoriteBrand = (uid, id, isBrand, opt) => {
32 32
33 33
34 module.exports = { 34 module.exports = {
35 - favoriteBrand: _favoriteBrand 35 + favoriteBrand
36 }; 36 };
@@ -15,7 +15,7 @@ const guangProcess = require(`${global.utils}/guang-process`); @@ -15,7 +15,7 @@ const guangProcess = require(`${global.utils}/guang-process`);
15 * @param {[int]} id [作者id] 15 * @param {[int]} id [作者id]
16 * @return {[object]} 16 * @return {[object]}
17 */ 17 */
18 -const _getAuthor = (id) => { 18 +const getAuthor = (id) => {
19 return serviceAPI.get('guang/service/v1/author/getAuthor', { 19 return serviceAPI.get('guang/service/v1/author/getAuthor', {
20 author_id: id 20 author_id: id
21 }, { 21 }, {
@@ -56,7 +56,7 @@ const _category = () => { @@ -56,7 +56,7 @@ const _category = () => {
56 * @param {Boolean} useCache [是否使用缓存] 56 * @param {Boolean} useCache [是否使用缓存]
57 * @return {[array]} 57 * @return {[array]}
58 */ 58 */
59 -const _getArticleList = (gender, sortId, uid, udid, page, tag, authorId, limit, useCache) => { 59 +const getArticleList = (gender, sortId, uid, udid, page, tag, authorId, limit, useCache) => {
60 let param = { 60 let param = {
61 page: page || 1, 61 page: page || 1,
62 uid: uid || 0, 62 uid: uid || 0,
@@ -95,8 +95,8 @@ const _getArticleList = (gender, sortId, uid, udid, page, tag, authorId, limit, @@ -95,8 +95,8 @@ const _getArticleList = (gender, sortId, uid, udid, page, tag, authorId, limit,
95 * @param {Boolean} isTab [是否为tab切换操作] 95 * @param {Boolean} isTab [是否为tab切换操作]
96 * @return {[array]} 96 * @return {[array]}
97 */ 97 */
98 -const _getPageData = (gender, sortId, uid, udid, page, tag, authorId, isApp, showAuthor, isTab) => {  
99 - return _getArticleList(gender, sortId, uid, udid, page, tag, authorId).then(article => { 98 +const getPageData = (gender, sortId, uid, udid, page, tag, authorId, isApp, showAuthor, isTab) => {
  99 + return getArticleList(gender, sortId, uid, udid, page, tag, authorId).then(article => {
100 let result = {}; 100 let result = {};
101 101
102 if (!article.data.list.artList) { 102 if (!article.data.list.artList) {
@@ -260,8 +260,8 @@ const getArticle = (param) => { @@ -260,8 +260,8 @@ const getArticle = (param) => {
260 }; 260 };
261 261
262 module.exports = { 262 module.exports = {
263 - getAuthor: _getAuthor,  
264 - getArticleList: _getArticleList,  
265 - getPageData: _getPageData, 263 + getAuthor,
  264 + getArticleList,
  265 + getPageData,
266 getArticle 266 getArticle
267 }; 267 };
@@ -15,7 +15,7 @@ const URI_PACKAGE_AUTHOR = 'guang/service/v1/author/'; @@ -15,7 +15,7 @@ const URI_PACKAGE_AUTHOR = 'guang/service/v1/author/';
15 * @param {Boolean} isApp [标识是否是APP访问] 15 * @param {Boolean} isApp [标识是否是APP访问]
16 * @return {[array]} 16 * @return {[array]}
17 */ 17 */
18 -const _package = (id, isApp) => { 18 +const packageData = (id, isApp) => {
19 let result = { 19 let result = {
20 getAuthor: {}, 20 getAuthor: {},
21 getArticle: {}, 21 getArticle: {},
@@ -110,6 +110,23 @@ const _package = (id, isApp) => { @@ -110,6 +110,23 @@ const _package = (id, isApp) => {
110 }); 110 });
111 }; 111 };
112 112
  113 +/**
  114 + * [获取详情信息]
  115 + * @param {[int]} id [资讯id]
  116 + * @return {[object]}
  117 + */
  118 +const intro = (id) => {
  119 + let param = {
  120 + article_id: id,
  121 + client_type: 'h5'
  122 + };
  123 +
  124 + return serviceAPI.get(`${URI_PACKAGE_ARTICLE}getArticleContent`, param, {
  125 + cache: true
  126 + });
  127 +};
  128 +
113 module.exports = { 129 module.exports = {
114 - package: _package 130 + packageData,
  131 + intro
115 }; 132 };
@@ -13,7 +13,7 @@ const serviceAPI = global.yoho.ServiceAPI; @@ -13,7 +13,7 @@ const serviceAPI = global.yoho.ServiceAPI;
13 * @param {[string]} opt [操作(ok:表示确定,cancel:表示取消)] 13 * @param {[string]} opt [操作(ok:表示确定,cancel:表示取消)]
14 * @return {[array]} 14 * @return {[array]}
15 */ 15 */
16 -const _praiseArticle = (udid, id, opt) => { 16 +const praiseArticle = (udid, id, opt) => {
17 let param = { 17 let param = {
18 article_id: id, 18 article_id: id,
19 udid: udid 19 udid: udid
@@ -33,7 +33,7 @@ const _praiseArticle = (udid, id, opt) => { @@ -33,7 +33,7 @@ const _praiseArticle = (udid, id, opt) => {
33 * @param {[string]} opt [操作(ok:表示确定,cancel:表示取消)] 33 * @param {[string]} opt [操作(ok:表示确定,cancel:表示取消)]
34 * @return {[array]} 34 * @return {[array]}
35 */ 35 */
36 -const _collectArticle = (uid, id, opt) => { 36 +const collectArticle = (uid, id, opt) => {
37 let param = { 37 let param = {
38 article_id: id, 38 article_id: id,
39 uid: uid 39 uid: uid
@@ -48,6 +48,6 @@ const _collectArticle = (uid, id, opt) => { @@ -48,6 +48,6 @@ const _collectArticle = (uid, id, opt) => {
48 48
49 49
50 module.exports = { 50 module.exports = {
51 - praiseArticle: _praiseArticle,  
52 - collectArticle: _collectArticle 51 + praiseArticle,
  52 + collectArticle
53 }; 53 };
  1 +/**
  2 + * 逛rss订阅models
  3 + * @author: chenfeng<feng.chen@yoho.cn>
  4 + * @date: 2016/09/13
  5 + */
  6 +'use strict';
  7 +const serviceAPI = global.yoho.ServiceAPI;
  8 +const mRoot = '../models';
  9 +const indexModel = require(`${mRoot}/index`);
  10 +const infoModel = require(`${mRoot}/info`);
  11 +const guangProcess = require(`${global.utils}/guang-process`);
  12 +const htmlProcess = require(`${global.utils}/html-process`);
  13 +const helpers = global.yoho.helpers;
  14 +
  15 +/**
  16 + * [获取订阅的资讯文章列表]
  17 + * @param {[int]} gender [性别参数(1,3表示男, 2,3表示女, 默认为所有)]
  18 + * @return {[array]}
  19 + */
  20 +const getRssArticle = (gender) => {
  21 + let result = [],
  22 + article = {},
  23 + articlePromise;
  24 +
  25 + switch (gender) {
  26 + case '1,3':
  27 + articlePromise = indexModel.getArticleList('1,3', 0, 0, '', 1, null, null, 10, false);
  28 + break;
  29 + case '2,3':
  30 + articlePromise = indexModel.getArticleList('2,3', 0, 0, '', 1, null, null, 10, false);
  31 + break;
  32 + default:
  33 + articlePromise = indexModel.getArticleList('1,2,3', 0, 0, '', 1, null, null, 10, false);
  34 + break;
  35 + }
  36 + return articlePromise.then((article) => {
  37 + // 内容列表
  38 + if (article.data.list.artList) {
  39 + let build = {};
  40 +
  41 + let artListFunc = (i, len, resolve) => {
  42 + if (i < len) {
  43 + let value = article.data.list.artList[i];
  44 + if (typeof value.id !== 'undefined') {
  45 + build = guangProcess.formatArticle(value, false, false, true);
  46 + build.author.name = build.author.name || '';
  47 + return _genIntro(value.id).then((intro) => {
  48 + build.intro = intro;
  49 + result.push(build);
  50 + artListFunc(++i, len, resolve);
  51 + });
  52 + }
  53 + } else {
  54 + resolve(result);
  55 + }
  56 + }
  57 + return new Promise((resolve) => {
  58 + artListFunc(0, article.data.list.artList.length, resolve);
  59 + })
  60 +
  61 + }
  62 + });
  63 +}
  64 +
  65 +/**
  66 + * [构建信息内容]
  67 + * @param {[int]} id [资讯id]
  68 + * @return {[string]}
  69 + */
  70 +const _genIntro = (id) => {
  71 + let result = '';
  72 +
  73 + return infoModel.intro(id).then((resData) => {
  74 + if (resData.data) {
  75 + resData.data.forEach((value) => {
  76 + if (value.text) { //文字
  77 + result += htmlProcess.removeHtml(htmlProcess.escapeToHtml(value.text.data.text)) + '<br/>';
  78 + } else if (value.singleImage) {// 单张图
  79 + result += `<img src="${helpers.image(value.singleImage.data[0].src, 640, 640)}"/><br/>`;
  80 + } else if (value.smallPic && value.smallPic.data) { // 多张小图
  81 + value.smallPic.data.forEach((small) => {
  82 + result += `<img src="${helpers.image(small.src, 315, 420)}"/>`;
  83 + })
  84 + result += '<br/>';
  85 + }
  86 + })
  87 + return result;
  88 + }
  89 + });
  90 +
  91 +}
  92 +module.exports = {
  93 + getRssArticle
  94 +}
@@ -14,6 +14,7 @@ const index = require(cRoot + '/index'); @@ -14,6 +14,7 @@ const index = require(cRoot + '/index');
14 const opt = require(cRoot + '/opt'); 14 const opt = require(cRoot + '/opt');
15 const info = require(cRoot + '/info'); 15 const info = require(cRoot + '/info');
16 const plustar = require(cRoot + '/plustar'); 16 const plustar = require(cRoot + '/plustar');
  17 +const rss = require(cRoot + '/rss');
17 18
18 const router = express.Router(); // eslint-disable-line 19 const router = express.Router(); // eslint-disable-line
19 20
@@ -43,4 +44,6 @@ router.get('/info/foryoho', info.foryoho); // 逛foryoho内容页 @@ -43,4 +44,6 @@ router.get('/info/foryoho', info.foryoho); // 逛foryoho内容页
43 44
44 router.get('/plustar', plustar.getListData); // 国际优选 45 router.get('/plustar', plustar.getListData); // 国际优选
45 46
  47 +router.get('/rss', rss.index); //订阅资讯
  48 +
46 module.exports = router; 49 module.exports = router;
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  3 + <channel>
  4 + <title>有货逛</title>
  5 + <link>http://yohobuy.com</link>
  6 + <generator>http://m.yohobuy.com</generator>
  7 + <description>Yoho!Buy有货 | 年轻人潮流购物中心</description>
  8 + <atom:link href="http://guang.m.yohobuy.com/rss" rel="self"></atom:link>
  9 + <atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/>
  10 + <language>zh-cn</language>
  11 + <copyright>2015 yoho.inc</copyright>
  12 + <lastBuildDate>{{time}}</lastBuildDate>
  13 + <ttl>50</ttl>
  14 + {{# items}}
  15 + <item>
  16 + <title><![CDATA[{{title}}]]></title>
  17 + <link>
  18 + <![CDATA[{{{url}}}&ref=rss]]>
  19 + </link>
  20 + <description>
  21 + <![CDATA[{{{intro}}}]]>
  22 + </description>
  23 + <pubDate>{{publishTime}}</pubDate>
  24 + <author>
  25 + <![CDATA[{{author.name}}]]>
  26 + </author>
  27 + <guid>
  28 + <![CDATA[{{{url}}}&ref=rss]]>
  29 + </guid>
  30 + <source>有货</source>
  31 + </item>
  32 + {{/items}}
  33 + </channel>
  34 +</rss>
@@ -10,7 +10,7 @@ const helpers = global.yoho.helpers; @@ -10,7 +10,7 @@ const helpers = global.yoho.helpers;
10 * @param {[string]} url [需要转换的url] 10 * @param {[string]} url [需要转换的url]
11 * @return {[string]} [description] 11 * @return {[string]} [description]
12 */ 12 */
13 -const _transHttpsUrl = (url) => { 13 +const transHttpsUrl = (url) => {
14 return url.replace(/^\/\//g, 'http://'); 14 return url.replace(/^\/\//g, 'http://');
15 }; 15 };
16 16
@@ -19,7 +19,7 @@ const _transHttpsUrl = (url) => { @@ -19,7 +19,7 @@ const _transHttpsUrl = (url) => {
19 * @param {[string]} url [url地址] 19 * @param {[string]} url [url地址]
20 * @return {[strng]} 20 * @return {[strng]}
21 */ 21 */
22 -const _getFilterUrl = (url) => { 22 +const getFilterUrl = (url) => {
23 url = url.replace('.m.yohobuy.com', global.yoho.config.subDomains.host).replace('www.yohobuy.com', global.yoho.config.siteUrl); 23 url = url.replace('.m.yohobuy.com', global.yoho.config.subDomains.host).replace('www.yohobuy.com', global.yoho.config.siteUrl);
24 24
25 const whiteDomains = ['m.yohobuy.com', 'cdn.yoho.cn/myohobuy']; 25 const whiteDomains = ['m.yohobuy.com', 'cdn.yoho.cn/myohobuy'];
@@ -31,7 +31,7 @@ const _getFilterUrl = (url) => { @@ -31,7 +31,7 @@ const _getFilterUrl = (url) => {
31 } 31 }
32 32
33 if (url.includes('feature.yoho.cn')) { 33 if (url.includes('feature.yoho.cn')) {
34 - url = _transHttpsUrl(url); 34 + url = transHttpsUrl(url);
35 } 35 }
36 if (url.includes('openby:yohobuy=')) { 36 if (url.includes('openby:yohobuy=')) {
37 let filters = ['openby:yohobuy=', '&', '?']; 37 let filters = ['openby:yohobuy=', '&', '?'];
@@ -55,7 +55,7 @@ const _getFilterUrl = (url) => { @@ -55,7 +55,7 @@ const _getFilterUrl = (url) => {
55 * @param {[string]} reqQueryString [查询字符串] 55 * @param {[string]} reqQueryString [查询字符串]
56 * @return {[array | false]} 56 * @return {[array | false]}
57 */ 57 */
58 -const _formatArticle = (articleData, showTag, isApp, showAuthor, uid, reqQueryString) => { 58 +const formatArticle = (articleData, showTag, isApp, showAuthor, uid, reqQueryString) => {
59 // 资讯ID不存在,则不显示 59 // 资讯ID不存在,则不显示
60 if (!articleData.id) { 60 if (!articleData.id) {
61 return false; 61 return false;
@@ -73,7 +73,7 @@ const _formatArticle = (articleData, showTag, isApp, showAuthor, uid, reqQuerySt @@ -73,7 +73,7 @@ const _formatArticle = (articleData, showTag, isApp, showAuthor, uid, reqQuerySt
73 73
74 if (result.url.includes('feature.yoho.cn') || 74 if (result.url.includes('feature.yoho.cn') ||
75 result.url.includes('cdn.yoho.cn')) { 75 result.url.includes('cdn.yoho.cn')) {
76 - result.url = _transHttpsUrl(result.url); 76 + result.url = transHttpsUrl(result.url);
77 } 77 }
78 78
79 // 收藏 79 // 收藏
@@ -104,7 +104,7 @@ const _formatArticle = (articleData, showTag, isApp, showAuthor, uid, reqQuerySt @@ -104,7 +104,7 @@ const _formatArticle = (articleData, showTag, isApp, showAuthor, uid, reqQuerySt
104 // 判断是否显示作者信息 104 // 判断是否显示作者信息
105 if (showAuthor && articleData.author) { 105 if (showAuthor && articleData.author) {
106 if (!isApp) { 106 if (!isApp) {
107 - articleData.author.url = _getFilterUrl(articleData.author.url); 107 + articleData.author.url = getFilterUrl(articleData.author.url);
108 } 108 }
109 109
110 // 编辑人员 app跳转url处理 20160601 110 // 编辑人员 app跳转url处理 20160601
@@ -148,7 +148,7 @@ const _formatArticle = (articleData, showTag, isApp, showAuthor, uid, reqQuerySt @@ -148,7 +148,7 @@ const _formatArticle = (articleData, showTag, isApp, showAuthor, uid, reqQuerySt
148 * @param {[int]} type [类型] 148 * @param {[int]} type [类型]
149 * @return {[type]} 149 * @return {[type]}
150 */ 150 */
151 -const _getProductIcon = (type) => { 151 +const getProductIcon = (type) => {
152 const icons = { 152 const icons = {
153 1: 'cloth', 153 1: 'cloth',
154 3: 'pants', 154 3: 'pants',
@@ -218,7 +218,7 @@ const _procProductImg = (images, gender) => { @@ -218,7 +218,7 @@ const _procProductImg = (images, gender) => {
218 * @param int gender 性别 218 * @param int gender 性别
219 * @return array | false 219 * @return array | false
220 */ 220 */
221 -const _formatProduct = (productData, showTags, showNew, showSale, width, height, isApp, showPoint, gender) => { 221 +const formatProduct = (productData, showTags, showNew, showSale, width, height, isApp, showPoint, gender) => {
222 // 商品信息有问题,则不显示 222 // 商品信息有问题,则不显示
223 if (!productData.product_skn || !productData.goods_list[0]) { 223 if (!productData.product_skn || !productData.goods_list[0]) {
224 return false; 224 return false;
@@ -306,9 +306,9 @@ const _formatProduct = (productData, showTags, showNew, showSale, width, height, @@ -306,9 +306,9 @@ const _formatProduct = (productData, showTags, showNew, showSale, width, height,
306 306
307 307
308 module.exports = { 308 module.exports = {
309 - formatArticle: _formatArticle,  
310 - transHttpsUrl: _transHttpsUrl,  
311 - getFilterUrl: _getFilterUrl,  
312 - formatProduct: _formatProduct,  
313 - getProductIcon: _getProductIcon 309 + formatArticle,
  310 + transHttpsUrl,
  311 + getFilterUrl,
  312 + formatProduct,
  313 + getProductIcon
314 }; 314 };
  1 +/**
  2 + * html字符处理
  3 + */
  4 +
  5 +'use strict';
  6 +
  7 +const _htmlMap = {'<':'&lt;','>':'&gt;','&':'&amp;','"':'&quot;'};
  8 +const _EscapeMap = {'lt':'<','gt':'>','nbsp':' ','amp':'&','quot':'"'};
  9 +
  10 +/**
  11 + * [移除html标签]
  12 + */
  13 +const removeHtml = (str) => {
  14 + return str.replace(/<[^>]+>/g, '');
  15 +}
  16 +
  17 +/**
  18 + * [html转为转义]
  19 + */
  20 +const htmlToEscape = (html) => {
  21 + return html.replace(/[<>&"]/g, (e) => {
  22 + return _htmlMap[e];
  23 + })
  24 +}
  25 +
  26 +/**
  27 + * [转义符转为html]
  28 + */
  29 +const escapeToHtml = (str) => {
  30 + return str.replace(/&(lt|gt|nbsp|amp|quot);/g, (match, e) => {
  31 + return _EscapeMap[e];
  32 + })
  33 +}
  34 +
  35 +module.exports = {
  36 + removeHtml,
  37 + htmlToEscape,
  38 + escapeToHtml
  39 +}
@@ -9,10 +9,10 @@ @@ -9,10 +9,10 @@
9 * @param {[string]} str [验证参数] 9 * @param {[string]} str [验证参数]
10 * @return {[Boolean]} 10 * @return {[Boolean]}
11 */ 11 */
12 -const _isNumeric = (str) => { 12 +const isNumeric = (str) => {
13 return /^\d+(\.\d+)?$/.test(str); 13 return /^\d+(\.\d+)?$/.test(str);
14 }; 14 };
15 15
16 module.exports = { 16 module.exports = {
17 - isNumeric: _isNumeric 17 + isNumeric
18 }; 18 };