Authored by 郭成尧

goods拆分

@@ -35,16 +35,16 @@ exports.index = (req, res) => { @@ -35,16 +35,16 @@ exports.index = (req, res) => {
35 responseData.devEnv = true; 35 responseData.devEnv = true;
36 36
37 // 假数据输出 37 // 假数据输出
38 - res.render('sale/index', Object.assign(responseData, simulation.saleIndex())); 38 + // res.render('sale/index', Object.assign(responseData, simulation.saleIndex()));
39 39
40 // 真实数据输出 40 // 真实数据输出
41 - /* return sale.getSaleIndexDate().then(result => { 41 + sale.getSaleIndexData().then(result => {
42 42
43 responseData.result = result; 43 responseData.result = result;
44 responseData.resultShow = JSON.stringify(result, null, 4); 44 responseData.resultShow = JSON.stringify(result, null, 4);
45 45
46 res.render('sale/index', responseData); 46 res.render('sale/index', responseData);
47 - });*/ 47 + });
48 }) 48 })
49 .catch(() => { 49 .catch(() => {
50 res.render('error', { devEnv: true, pageErr: true }); 50 res.render('error', { devEnv: true, pageErr: true });
@@ -175,3 +175,21 @@ exports.newSale = (req, res) => { @@ -175,3 +175,21 @@ exports.newSale = (req, res) => {
175 res.render('error', { devEnv: true, pageErr: true }); 175 res.render('error', { devEnv: true, pageErr: true });
176 }); 176 });
177 }; 177 };
  178 +
  179 +/**
  180 + * 获取商品列表
  181 + * @param {[type]} req [description]
  182 + * @param {[type]} res [description]
  183 + * @return {[type]} [description]
  184 + */
  185 +exports.getGoodsList = (req, res) => {
  186 + return sale.getSaleGoodsData().then(result => {
  187 + let responseData = {};
  188 +
  189 + responseData.devEnv = true;
  190 + responseData.result = result;
  191 + responseData.footerTop = false;
  192 +
  193 + res.render('goods', responseData);
  194 + });
  195 +};
@@ -19,7 +19,7 @@ app.engine('.hbs', hbs({ @@ -19,7 +19,7 @@ app.engine('.hbs', hbs({
19 defaultLayout: 'layout', 19 defaultLayout: 'layout',
20 layoutsDir: doraemon, 20 layoutsDir: doraemon,
21 partialsDir: [path.join(__dirname, 'views/partial'), `${doraemon}/partial`], 21 partialsDir: [path.join(__dirname, 'views/partial'), `${doraemon}/partial`],
22 - helpers: 'helpers' 22 + helpers: require('../../library/helpers')
23 })); 23 }));
24 24
25 // router 25 // router
@@ -2,29 +2,19 @@ @@ -2,29 +2,19 @@
2 * @Author: Targaryen 2 * @Author: Targaryen
3 * @Date: 2016-05-19 10:20:08 3 * @Date: 2016-05-19 10:20:08
4 * @Last Modified by: Targaryen 4 * @Last Modified by: Targaryen
5 - * @Last Modified time: 2016-05-21 14:39:36 5 + * @Last Modified time: 2016-05-23 16:39:03
6 */ 6 */
7 7
8 'use strict'; 8 'use strict';
9 const library = '../../../library'; 9 const library = '../../../library';
10 const API = require(`${library}/api`).API; 10 const API = require(`${library}/api`).API;
  11 +const TARAPI = require(`${library}/tar-api`).TARAPI;
11 const sign = require(`${library}/sign`); 12 const sign = require(`${library}/sign`);
12 const api = new API(); 13 const api = new API();
  14 +const tarApi = new TARAPI();
13 const _ = require('lodash'); 15 const _ = require('lodash');
14 16
15 /** 17 /**
16 - * 处理 sale 首页原始数据  
17 - * @param {Object} origin [原始数据]  
18 - * @return {Object} [结果]  
19 - */  
20 -const handleSaleIndexData = (origin) => {  
21 - var dest = {};  
22 -  
23 - dest = origin;  
24 - return dest;  
25 -};  
26 -  
27 -/**  
28 * 处理商品列表数据 18 * 处理商品列表数据
29 * @param {[type]} origin [description] 19 * @param {[type]} origin [description]
30 * @return {[type]} [description] 20 * @return {[type]} [description]
@@ -131,7 +121,7 @@ const handleSaleFilterData = (origin) => { @@ -131,7 +121,7 @@ const handleSaleFilterData = (origin) => {
131 }; 121 };
132 122
133 /** 123 /**
134 - * 处理分类筛选数据 124 + * 处理页面左侧分类筛选数据
135 * @return {[type]} [description] 125 * @return {[type]} [description]
136 */ 126 */
137 const handleSaleSortData = (origin) => { 127 const handleSaleSortData = (origin) => {
@@ -152,7 +142,19 @@ const handleSaleSortData = (origin) => { @@ -152,7 +142,19 @@ const handleSaleSortData = (origin) => {
152 }; 142 };
153 143
154 /** 144 /**
155 - * 返回商品列表 promise 对象 145 + * 处理折扣专区活动数据
  146 + * @param {[type]} origin [description]
  147 + * @return {[type]} [description]
  148 + */
  149 +const handleSaleActivityData = (origin) => {
  150 + var dest = {};
  151 +
  152 + dest = origin;
  153 + return dest;
  154 +};
  155 +
  156 +/**
  157 + * 获取商品列表 promise 对象
156 * @return {[type]} [description] 158 * @return {[type]} [description]
157 */ 159 */
158 const getSaleGoodsList = () => { 160 const getSaleGoodsList = () => {
@@ -167,7 +169,7 @@ const getSaleGoodsList = () => { @@ -167,7 +169,7 @@ const getSaleGoodsList = () => {
167 }; 169 };
168 170
169 /** 171 /**
170 - * 获取分类信息 promise 对象 172 + * 获取左侧分类信息数据 promise 对象
171 * @return {[type]} [description] 173 * @return {[type]} [description]
172 */ 174 */
173 const getSortList = () => { 175 const getSortList = () => {
@@ -178,22 +180,60 @@ const getSortList = () => { @@ -178,22 +180,60 @@ const getSortList = () => {
178 }; 180 };
179 181
180 /** 182 /**
181 - * 获取 Sale 首页数据 183 + * 获取折扣专区活动列表 promise 对象
182 * @return {[type]} [description] 184 * @return {[type]} [description]
183 */ 185 */
184 -exports.getSaleIndexDate = () => {  
185 - return api.get('', sign.apiSign({ 186 +const getSaleActivityList = () => {
  187 + return tarApi.getActivity('', sign.apiSign({
186 method: 'app.activity.get', 188 method: 'app.activity.get',
187 sort: 2, 189 sort: 2,
188 plateform: 2 190 plateform: 2
189 - })).then(result => { 191 + }));
  192 +};
  193 +
  194 +/**
  195 + * 获取 Sale 首页数据
  196 + * @return {[type]} [description]
  197 + */
  198 +exports.getSaleIndexData = () => {
  199 +
  200 + return api.all([getSaleActivityList(), getSaleGoodsList()]).then(result => {
  201 + var finalResult = {};
  202 +
  203 + if (result[0].code === 200) {
  204 + finalResult.activity = handleSaleActivityData(result[0].data);
  205 + }
  206 +
  207 + if (result[1].code === 200) {
  208 +
  209 + if (!_.isEmpty(result[1].data.product_list)) { // 处理商品列表数据
  210 + finalResult.saleCategory = {};
  211 + finalResult.saleCategory.saleImage = [];
  212 + finalResult.saleCategory.saleImage.push(handleSaleGoodsListData(result[1].data.product_list));
  213 + }
  214 + }
  215 + return finalResult;
  216 + });
  217 +};
  218 +
  219 +/**
  220 + * 获取商品列表数据
  221 + * @return {[type]} [description]
  222 + */
  223 +exports.getSaleGoodsData = () => {
  224 +
  225 + return getSaleGoodsList().then(result => {
  226 + let finalResult = {};
190 227
191 - return handleSaleIndexData(result); 228 + if (result.code === 200) {
  229 + finalResult.goods = handleSaleGoodsListData(result.data.product_list);
  230 + }
  231 + return finalResult;
192 }); 232 });
193 }; 233 };
194 234
195 /** 235 /**
196 - * 获取页面全部信息 236 + * 获取其他三个页面全部数据
197 * @return {[type]} [description] 237 * @return {[type]} [description]
198 */ 238 */
199 exports.getSaleData = () => { 239 exports.getSaleData = () => {
@@ -24,6 +24,7 @@ router.get('/sale/discount', sale.discount); @@ -24,6 +24,7 @@ router.get('/sale/discount', sale.discount);
24 router.get('/sale/vip', sale.vip); 24 router.get('/sale/vip', sale.vip);
25 router.get('/sale/breakingYards', sale.breakingYards); 25 router.get('/sale/breakingYards', sale.breakingYards);
26 router.get('/sale/newSale', sale.newSale); 26 router.get('/sale/newSale', sale.newSale);
  27 +router.get('/sale/goods', sale.getGoodsList);
27 28
28 // 奥特莱斯routers 29 // 奥特莱斯routers
29 router.get('/outlets/index', outlets.index); 30 router.get('/outlets/index', outlets.index);
  1 +{{# result}}
  2 +{{#each goods}}
  3 + <div class="good-info" data-skn="{{skn}}" data-from="{{from}}">
  4 + <div class="tag-container clearfix">
  5 + {{# tags}}
  6 + {{# isNew}}
  7 + <span class="good-tag new-tag">NEW</span>
  8 + {{/ isNew}}
  9 + {{# isReNew}}
  10 + <span class="good-tag renew-tag">再到着</span>
  11 + {{/ isReNew}}
  12 + {{# isSale}}
  13 + <span class="good-tag sale-tag">SALE</span>
  14 + {{/ isSale}}
  15 + {{# isNewFestival}}
  16 + <span class="good-tag new-festival-tag">新品节</span>
  17 + {{/ isNewFestival}}
  18 + {{# isLimit}}
  19 + <span class="good-tag limit-tag">限量商品</span>
  20 + {{/ isLimit}}
  21 + {{# isYearEndPromotion}}
  22 + <span class="good-tag yep-tag">年终大促</span>
  23 + {{/ isYearEndPromotion}}
  24 + {{# isYearMidPromotion}}
  25 + <span class="good-tag ymp-tag">年中热促</span>
  26 + {{/ isYearMidPromotion}}
  27 + {{/ tags}}
  28 + </div>
  29 + <div class="good-detail-img">
  30 + <a class="good-thumb" href="{{url}}" target="_blank">
  31 + <img class="lazy" data-original="{{image thumb 235 315}}">
  32 + </a>
  33 + {{# isFew}}
  34 + <p class="few-tag">即将售罄</p>
  35 + {{/ isFew}}
  36 +
  37 + {{#if showColBtn}}
  38 + <span class="col-btn iconfont{{#if coled}} coled{{/if}}">&#xe616;</span>
  39 + {{/if}}
  40 + </div>
  41 + <div class="good-detail-text">
  42 + <a href="{{url}}" target="_blank">{{{name}}}</a>
  43 + {{#brand}}
  44 + <p class="brand">
  45 + <a href="{{url}}">{{name}}</a>
  46 + </p>
  47 + {{/brand}}
  48 + <p class="price">
  49 + {{# marketPrice}}
  50 + <span class="market-price">¥{{.}}</span>
  51 + {{/ marketPrice}}
  52 + <span class="sale-price{{#unless marketPrice}}prime-cost{{/unless}}">
  53 + ¥{{salePrice}}
  54 + </span>
  55 + </p>
  56 + </div>
  57 + </div>
  58 +{{/each}}
  59 +{{/ result}}
@@ -12,7 +12,7 @@ const isTest = process.env.NODE_ENV === 'test'; @@ -12,7 +12,7 @@ const isTest = process.env.NODE_ENV === 'test';
12 module.exports = { 12 module.exports = {
13 port: 6002, 13 port: 6002,
14 domains: { 14 domains: {
15 - api: 'http://192.168.102.205:8080/gateway', 15 + api: 'http://192.168.102.205:8080/gateway', // 192.168.102.205:8080 testapi.yoho.cn:28078
16 service: 'http://testservice.yoho.cn:28077', 16 service: 'http://testservice.yoho.cn:28077',
17 search: 'http://192.168.10.64:8080/yohosearch/' 17 search: 'http://192.168.10.64:8080/yohosearch/'
18 }, 18 },
  1 +/*
  2 +* @Author: Targaryen
  3 +* @Date: 2016-05-23 15:27:46
  4 +* @Last Modified by: Targaryen
  5 +* @Last Modified time: 2016-05-23 16:40:48
  6 +*/
  7 +
  8 +'use strict';
  9 +
  10 +const rp = require('request-promise');
  11 +const qs = require('querystring');
  12 +const md5 = require('md5');
  13 +const _ = require('lodash');
  14 +const log = require('./logger');
  15 +const cache = require('./cache');
  16 +const Timer = require('./timer');
  17 +const config = require('../config/common');
  18 +const api = config.domains.api;
  19 +const serviceApi = config.domains.service;
  20 +const searchApi = config.domains.search;
  21 +
  22 +
  23 +let ApiUrl;
  24 +
  25 +class TARAPI {
  26 +
  27 + constructor() {
  28 + ApiUrl = api;
  29 + }
  30 +
  31 + /**
  32 + * 获取请求 ID
  33 + */
  34 + _getReqId(options) {
  35 + return md5(`${options.url}?${qs.stringify(options.qs || options.form)}`);
  36 + }
  37 +
  38 + /**
  39 + * 调用接口
  40 + */
  41 + _requestFromAPI(options, cacheOption, reqId) {
  42 + let timer = new Timer();
  43 +
  44 + timer.put('getApi');// 统计时间开始
  45 +
  46 + log.info(`get api: ${options.url}?${qs.stringify(options.qs)}`);
  47 + return rp(options).then((result) => {
  48 + let duration = timer.put('getApi');// 统计时间结束
  49 +
  50 + log.info(`get api success: use: ${duration}ms`);
  51 + if (config.useCache && cacheOption) {
  52 + reqId = reqId || this._getReqId(options);
  53 +
  54 + // 数据校验无误,写缓存, 否则返回 Slave 缓存服务器的数据
  55 + if (result && result.code) {
  56 + let cacheTime = _.isNumber(cacheOption) ? cacheOption : 60;
  57 +
  58 + cache.set(`apiCache:${reqId}`, result, cacheTime);
  59 + cache.setSlave(`apiCache:${reqId}`, result, cacheTime);
  60 + } else {
  61 + return this._requestFromCache(options, true);
  62 + }
  63 + }
  64 + return result;
  65 + }).catch((error)=>{
  66 + let duration = timer.put('getApi');// 统计时间结束
  67 +
  68 + log.error(`get api fail: use: ${duration}ms, statusCode: ${error.statusCode}, error: ${error.message}`);
  69 +
  70 + // 使用缓存的时候,读取二级缓存
  71 + if (config.useCache) {
  72 + return this._requestFromCache(options, true);
  73 + }
  74 + return Promise.reject({
  75 + error: '接口调用失败'
  76 + });
  77 + });
  78 + }
  79 +
  80 + /**
  81 + * 读取缓存
  82 + * @param {[object]} options
  83 + * @param {[boolean]} slave true: 读取二级缓存
  84 + * @return {[type]}
  85 + */
  86 + _requestFromCache(options, slave) {
  87 + let reqId = this._getReqId(options);
  88 + let getCache = slave ? cache.getFromSlave : cache.get;
  89 +
  90 + log.info(`get cache: ${reqId}, url: ${options.url}?${qs.stringify(options.qs)}`);
  91 + return getCache(`apiCache:${reqId}`).then((result) => {
  92 + if (!_.isNil(result)) {
  93 + try {
  94 + result = JSON.parse(result);
  95 + } finally {
  96 + log.info(slave ? 'get slave cache success' : 'get master cache success');
  97 + return result;
  98 + }
  99 + }
  100 +
  101 + if (!slave) {
  102 + return this._requestFromAPI(options, true, reqId);
  103 + }
  104 + }).catch(() => {
  105 + log.error(slave ? 'get slave cache fail' : 'get master cache fail');
  106 + if (!slave) {
  107 + return this._requestFromAPI(options, true, reqId);
  108 + }
  109 + });
  110 + }
  111 +
  112 + /**
  113 + * 使用 get 请求获取接口
  114 + * @param {[string]} url
  115 + * @param {[object]} data
  116 + * @param {[bool or number]} cacheOption 使用数字时,数字表示缓存时间
  117 + * @return {[type]}
  118 + */
  119 + get(url, data, cacheOption) {
  120 + let options = {
  121 + url: `${ApiUrl}${url}`,
  122 + qs: data,
  123 + json: true,
  124 + timeout: 3000
  125 + };
  126 +
  127 + // 从缓存获取数据
  128 + if (config.useCache && cacheOption) {
  129 + return this._requestFromCache(options);
  130 + }
  131 +
  132 + return this._requestFromAPI(options, cacheOption);
  133 + }
  134 +
  135 + /**
  136 + * 使用 get 请求获取接口
  137 + * @param {[string]} url
  138 + * @param {[object]} data
  139 + * @param {[bool or number]} cacheOption 使用数字时,数字表示缓存时间
  140 + * @return {[type]}
  141 + */
  142 + getActivity(url, data, cacheOption) {
  143 + let options = {
  144 + url: `http://testapi.yoho.cn:28078/gateway${url}`,
  145 + qs: data,
  146 + json: true,
  147 + timeout: 3000
  148 + };
  149 +
  150 + // 从缓存获取数据
  151 + if (config.useCache && cacheOption) {
  152 + return this._requestFromCache(options);
  153 + }
  154 +
  155 + return this._requestFromAPI(options, cacheOption);
  156 + }
  157 +
  158 + /**
  159 + * post
  160 + * @param url String
  161 + * @param data Obejct
  162 + */
  163 + post(url, data) {
  164 + let options = {
  165 + url: `${ApiUrl}${url}`,
  166 + form: data,
  167 + method: 'post',
  168 + json: true,
  169 + timeout: 3000
  170 + };
  171 +
  172 + return this._requestFromAPI(options);
  173 + }
  174 +
  175 + all(list) {
  176 + if (_.isArray(list)) {
  177 + return Promise.all(list);
  178 + }
  179 + throw Error('the parameters of api all method should be Array!');
  180 + }
  181 +}
  182 +
  183 +class ServiceAPI extends TARAPI {
  184 + constructor() {
  185 + super();
  186 + ApiUrl = serviceApi;
  187 + }
  188 +}
  189 +
  190 +class SearchAPI extends TARAPI {
  191 + constructor() {
  192 + super();
  193 + ApiUrl = searchApi;
  194 + }
  195 +}
  196 +
  197 +exports.TARAPI = TARAPI;
  198 +exports.ServiceAPI = ServiceAPI;
  199 +exports.SearchAPI = SearchAPI;