Authored by htoooth

Merge branch 'master' into release/6.0

# Conflicts:
#	config/common.js
Showing 45 changed files with 1179 additions and 821 deletions
@@ -8,6 +8,7 @@ const staticUrls = require('../../../config/staticUrls'); @@ -8,6 +8,7 @@ const staticUrls = require('../../../config/staticUrls');
8 const api = global.yoho.API; 8 const api = global.yoho.API;
9 const Service = global.yoho.ServiceAPI; 9 const Service = global.yoho.ServiceAPI;
10 const headerModel = require('../../../doraemon/models/header'); 10 const headerModel = require('../../../doraemon/models/header');
  11 +const redis = global.yoho.redis;
11 12
12 13
13 const getStaticUrls = (currentStatics) => { 14 const getStaticUrls = (currentStatics) => {
@@ -35,9 +36,30 @@ const getStaticUrls = (currentStatics) => { @@ -35,9 +36,30 @@ const getStaticUrls = (currentStatics) => {
35 return Promise.resolve(urls); 36 return Promise.resolve(urls);
36 }; 37 };
37 38
  39 +// 关键词页面
  40 +const keywordsPage = () => {
  41 + return redis.getAsync('golobal:yoho:seo:keywords:allIds').then(function(res) {
  42 + let page = [];
  43 +
  44 + _.forEach(JSON.parse(res), val => {
  45 + page.push({
  46 + url: `https://www.yohobuy.com/chanpin/${val}.html`,
  47 + changefreq: 'daily',
  48 + priority: 0.5
  49 + });
  50 + });
  51 +
  52 + return page;
  53 + }).catch(()=>{
  54 + return {};
  55 + });
  56 +};
  57 +
38 // www 地图数据 58 // www 地图数据
39 const wwwXmlData = () => {// eslint-disable-line 59 const wwwXmlData = () => {// eslint-disable-line
40 - return getStaticUrls(_.get(staticUrls, 'www')); 60 + return Promise.all([keywordsPage(), getStaticUrls(_.get(staticUrls, 'www'))]).then(result => {
  61 + return _.concat(result[1], result[0]);
  62 + });
41 }; 63 };
42 64
43 // list 地图数据 65 // list 地图数据
@@ -19,7 +19,7 @@ const brandsService = require(`${mRoot}/brands-service`); // students 页 model @@ -19,7 +19,7 @@ const brandsService = require(`${mRoot}/brands-service`); // students 页 model
19 exports.index = (req, res, next) => { 19 exports.index = (req, res, next) => {
20 let channel = req.query.channel || req.cookies._Channel || 'boys'; 20 let channel = req.query.channel || req.cookies._Channel || 'boys';
21 21
22 - brandsService.getBrandViewList(channel, req).then(result => { 22 + req.ctx(brandsService).getBrandViewList(channel, req).then(result => {
23 // 返回null,不cashe 23 // 返回null,不cashe
24 if (result.noCashe) { 24 if (result.noCashe) {
25 res.set('Cache-Control', 'no-cache'); 25 res.set('Cache-Control', 'no-cache');
@@ -35,7 +35,7 @@ exports.index = (req, res, next) => { @@ -35,7 +35,7 @@ exports.index = (req, res, next) => {
35 exports.brandList = (req, res, next) => { 35 exports.brandList = (req, res, next) => {
36 let channel = req.query.channel || req.cookies._Channel || 'boys'; 36 let channel = req.query.channel || req.cookies._Channel || 'boys';
37 37
38 - brandsService.getBrandList(channel, req.body.start).then(result => { 38 + req.ctx(brandsService).getBrandList(channel, req.body.start).then(result => {
39 39
40 res.render('brands/brand-list', Object.assign({layout: false}, result)); 40 res.render('brands/brand-list', Object.assign({layout: false}, result));
41 41
@@ -52,7 +52,7 @@ exports.brandInfo = (req, res, next) => { @@ -52,7 +52,7 @@ exports.brandInfo = (req, res, next) => {
52 52
53 let brandId = req.query.brandId || 0; 53 let brandId = req.query.brandId || 0;
54 54
55 - brandsService.brandInfo(brandId, req.user.uid).then(result => { 55 + req.ctx(brandsService).brandInfo(brandId, req.user.uid).then(result => {
56 // 返回null,不cashe 56 // 返回null,不cashe
57 if (result.noCashe) { 57 if (result.noCashe) {
58 res.set('Cache-Control', 'no-cache'); 58 res.set('Cache-Control', 'no-cache');
@@ -67,7 +67,7 @@ exports.brandInfo = (req, res, next) => { @@ -67,7 +67,7 @@ exports.brandInfo = (req, res, next) => {
67 exports.plusstarList = (req, res, next) => { 67 exports.plusstarList = (req, res, next) => {
68 let channel = req.query.channel || req.yoho.channel; 68 let channel = req.query.channel || req.yoho.channel;
69 69
70 - brandsService.plusstarList(channel, req).then(result => { 70 + req.ctx(brandsService).plusstarList(channel, req).then(result => {
71 // 返回null,不cashe 71 // 返回null,不cashe
72 if (result.noCashe) { 72 if (result.noCashe) {
73 res.set('Cache-Control', 'no-cache'); 73 res.set('Cache-Control', 'no-cache');
@@ -4,100 +4,159 @@ @@ -4,100 +4,159 @@
4 * @date: 2016/9/29 4 * @date: 2016/9/29
5 */ 5 */
6 'use strict'; 6 'use strict';
7 -const api = global.yoho.API;  
8 -const serviceAPI = global.yoho.ServiceAPI;  
9 -const config = global.yoho.config;  
10 7
11 -/**  
12 - * 分开取数,品牌一览 顶部的轮翻广告及热门品牌数据-PC  
13 - * 顶部的轮翻广告及热门品牌数据  
14 - * @param string $contentCode 获取广告资源需要的位置码  
15 - */  
16 -const getBrandTopData = (contentCode) => {  
17 - return serviceAPI.get('operations/api/v5/resource/get', {  
18 - content_code: contentCode  
19 - }, config.apiCache);  
20 -}; 8 +module.exports = class extends global.yoho.BaseModel {
  9 + constructor(ctx) {
  10 + super(ctx);
  11 + }
21 12
22 -/**  
23 - * 分开取数,获取品牌一览 "按字母'A-Z'分组的品牌列表数据"  
24 - * @param int $channel 频道标识 1:男,2:女,3:潮童,4:创意生活  
25 - */  
26 -const getBrandListData = channel => {  
27 - let params = {method: 'app.brand.allBrandList'}; 13 + /**
  14 + * 分开取数,品牌一览 顶部的轮翻广告及热门品牌数据-PC
  15 + * 顶部的轮翻广告及热门品牌数据
  16 + * @param string $contentCode 获取广告资源需要的位置码
  17 + */
  18 + getBrandTopData(contentCode) {
  19 + return this.get({
  20 + url: 'operations/api/v5/resource/get',
  21 + data: {
  22 + content_code: contentCode
  23 + },
  24 + param: {
  25 + cache: true
  26 + },
  27 + api: global.yoho.ServiceAPI
  28 + });
  29 + }
  30 +
  31 + /**
  32 + * 分开取数,获取品牌一览 "按字母'A-Z'分组的品牌列表数据"
  33 + * @param int $channel 频道标识 1:男,2:女,3:潮童,4:创意生活
  34 + */
  35 + getBrandListData(channel) {
  36 +
  37 + let data = {
  38 + method: 'app.brand.allBrandList'
  39 + };
28 40
29 - if (!isNaN(channel)) {  
30 - params.yh_channel = channel; 41 + if (!isNaN(channel)) {
  42 + data.yh_channel = channel;
  43 + }
  44 +
  45 + return this.get({
  46 + data: data,
  47 + param: {
  48 + code: 200,
  49 + cache: true
  50 + }
  51 + });
31 } 52 }
32 - return api.get('', params, config.apiCache);  
33 -};  
34 53
35 -/**  
36 - * 获取品牌简介  
37 - *  
38 - * @param integer $brandId 品牌ID  
39 - * @param int 用户ID  
40 - * @return array 品牌介绍信息  
41 - */  
42 -const getBrandIntro = (brandId, uid) => {  
43 - let param = {}; 54 + /**
  55 + * 获取品牌简介
  56 + *
  57 + * @param integer $brandId 品牌ID
  58 + * @param int 用户ID
  59 + * @return array 品牌介绍信息
  60 + */
  61 + getBrandIntro(brandId, uid) {
  62 +
  63 + let data = {
  64 + method: 'app.brand.getBrandIntro',
  65 + brand_id: brandId,
  66 + uid: uid
  67 + };
44 68
45 - if (!uid) {  
46 - param.cache = 3600; 69 + if (!uid) {
  70 + data.cache = 3600;
  71 + }
  72 +
  73 + return this.get({
  74 + data: data,
  75 + param: {
  76 + code: 200,
  77 + cache: true
  78 + }
  79 + });
47 } 80 }
48 - return api.get('', {  
49 - method: 'app.brand.getBrandIntro',  
50 - brand_id: brandId,  
51 - uid: uid  
52 - }, param, config.apiCache);  
53 -};  
54 81
55 -/**  
56 - * 获取品牌中产品图片  
57 - * @param int 品牌ID  
58 - * @return array 品牌产品信息  
59 - */  
60 -const getProductByBrand = (brandId, limit) => {  
61 - return api.get('', {  
62 - method: 'web.search.search',  
63 - brand: brandId,  
64 - limit: limit  
65 - }, config.apiCache);  
66 -}; 82 + /**
  83 + * 获取品牌中产品图片
  84 + * @param int 品牌ID
  85 + * @return array 品牌产品信息
  86 + */
  87 + getProductByBrand(brandId, limit) {
67 88
68 -/**  
69 - * 获取品牌信息  
70 - *  
71 - * @param array $ids  
72 - * @return array  
73 - */  
74 -const getBrandInfoByIds = (ids) => {  
75 - return api.get('', {  
76 - method: 'web.brand.info',  
77 - ids: ids instanceof Array ? ids.join(',') : parseInt(ids, 10)  
78 - }, config.apiCache);  
79 -}; 89 + let data = {
  90 + method: 'web.search.search',
  91 + brand: brandId,
  92 + limit: limit
  93 + };
80 94
81 -/**  
82 - * 获取品牌列表  
83 - *  
84 - * @param int $brandType  
85 - * @param string $gender  
86 - * @param string $type  
87 - * @return array  
88 - */  
89 -const getPlusstarList = (brandType, gender) => {  
90 - return serviceAPI.get('guang/api/v3/plustar/getlist', {  
91 - gender: gender,  
92 - brand_type: brandType  
93 - }, config.apiCache);  
94 -}; 95 + return this.get({
  96 + data: data,
  97 + param: {
  98 + code: 200,
  99 + cache: true
  100 + }
  101 + });
  102 + }
  103 +
  104 + /**
  105 + * 获取品牌信息
  106 + *
  107 + * @param array $ids
  108 + * @return array
  109 + */
  110 + getBrandInfoByIds(ids) {
  111 +
  112 + let data = {
  113 + method: 'web.brand.info',
  114 + ids: ids instanceof Array ? ids.join(',') : parseInt(ids, 10)
  115 + };
  116 +
  117 + return this.get({
  118 + data: data,
  119 + param: {
  120 + code: 200,
  121 + cache: true
  122 + }
  123 + });
  124 + }
  125 +
  126 + /**
  127 + * 获取品牌列表
  128 + *
  129 + * @param int $brandType
  130 + * @param string $gender
  131 + * @param string $type
  132 + * @return array
  133 + */
  134 + getPlusstarList(brandType, gender) {
  135 + return this.get({
  136 + url: 'guang/api/v3/plustar/getlist',
  137 + data: {
  138 + gender: gender,
  139 + brand_type: brandType
  140 + },
  141 + param: {
  142 + cache: true
  143 + },
  144 + api: global.yoho.ServiceAPI
  145 + });
  146 + }
  147 +
  148 + getPlusstarBrandListItem(code) {
  149 + return this.get({
  150 + url: 'operations/api/v5/resource/get',
  151 + data: {
  152 + content_code: code
  153 + },
  154 + param: {
  155 + cache: 3600
  156 + },
  157 + api: global.yoho.ServiceAPI
  158 + });
  159 + }
95 160
96 -module.exports = {  
97 - getBrandTopData,  
98 - getBrandListData,  
99 - getBrandIntro,  
100 - getProductByBrand,  
101 - getPlusstarList,  
102 - getBrandInfoByIds  
103 }; 161 };
  162 +
@@ -10,8 +10,9 @@ const Promise = require('bluebird'); @@ -10,8 +10,9 @@ const Promise = require('bluebird');
10 const co = Promise.coroutine; 10 const co = Promise.coroutine;
11 const _ = require('lodash'); 11 const _ = require('lodash');
12 const helpers = global.yoho.helpers; 12 const helpers = global.yoho.helpers;
13 -const brandApi = require('./brands-api');  
14 -const serviceApi = global.yoho.ServiceAPI; 13 +const BrandApi = require('./brands-api');
  14 +const path = require('path');
  15 +const imgUtils = require(path.join(global.utils, 'images'));
15 16
16 // 品牌一览资源位CODE码 17 // 品牌一览资源位CODE码
17 const channelCode = { 18 const channelCode = {
@@ -33,410 +34,431 @@ const LIFESTYLE = 'lifestyle'; @@ -33,410 +34,431 @@ const LIFESTYLE = 'lifestyle';
33 34
34 const GLOBAL_BASE_URI = '/product/global/list'; 35 const GLOBAL_BASE_URI = '/product/global/list';
35 36
36 -/**  
37 - * 获取品牌一览资源位&channelType  
38 - *  
39 - * @param string $channelStr  
40 - * @return array  
41 - */  
42 -const switchBrandParams = channel => {  
43 - let req = {};  
44 -  
45 - switch (channel) {  
46 -  
47 - case BOYS:  
48 - req = {  
49 - channelType: 1,  
50 - brandCode: channelCode.brand_plusstar_banner_boys  
51 - };  
52 - break;  
53 - case GIRLS:  
54 - req = {  
55 - channelType: 2,  
56 - brandCode: channelCode.brand_plusstar_banner_girls  
57 - };  
58 - break;  
59 - case KIDS:  
60 - req = {  
61 - channelType: 3,  
62 - brandCode: channelCode.kids_brand  
63 - };  
64 - break;  
65 - case LIFESTYLE:  
66 - req = {  
67 - channelType: 4,  
68 - brandCode: channelCode.lifestyle_brand  
69 - };  
70 - break;  
71 - default:  
72 - req = {  
73 - channelType: 1,  
74 - brandCode: channelCode.boys_brand  
75 - };  
76 - break; 37 +module.exports = class extends global.yoho.BaseModel {
  38 + constructor(ctx) {
  39 + super(ctx);
77 } 40 }
78 - return req;  
79 -};  
80 41
81 -/**  
82 - * 获取品牌一览页面,品牌top  
83 - * @param string $channel 频道名称  
84 - */  
85 -const getBrandViewTop = channel => {  
86 - return co(function*() {  
87 - let switchParams = switchBrandParams(channel); 42 + /**
  43 + * 获取品牌一览资源位&channelType
  44 + *
  45 + * @param string $channelStr
  46 + * @return array
  47 + */
  48 + switchBrandParams(channel) {
88 49
89 - let res = yield brandApi.getBrandTopData(switchParams.brandCode); 50 + let req = {};
90 51
91 - let result = {},  
92 - brandAds = [],  
93 - brandLogos = []; 52 + switch (channel) {
94 53
95 - if (!res || res.code !== 200) {  
96 - return result; 54 + case BOYS:
  55 + req = {
  56 + channelType: 1,
  57 + brandCode: channelCode.brand_plusstar_banner_boys
  58 + };
  59 + break;
  60 + case GIRLS:
  61 + req = {
  62 + channelType: 2,
  63 + brandCode: channelCode.brand_plusstar_banner_girls
  64 + };
  65 + break;
  66 + case KIDS:
  67 + req = {
  68 + channelType: 3,
  69 + brandCode: channelCode.kids_brand
  70 + };
  71 + break;
  72 + case LIFESTYLE:
  73 + req = {
  74 + channelType: 4,
  75 + brandCode: channelCode.lifestyle_brand
  76 + };
  77 + break;
  78 + default:
  79 + req = {
  80 + channelType: 1,
  81 + brandCode: channelCode.boys_brand
  82 + };
  83 + break;
97 } 84 }
  85 + return req;
  86 + }
98 87
99 - // 头部10个品牌小图块 url  
100 - if (res.data && res.data instanceof Array && res.data[1].data && res.data[1].data.list) { 88 + /**
  89 + * 获取品牌一览页面,品牌top
  90 + * @param string $channel 频道名称
  91 + */
  92 + getBrandViewTop(channel) {
  93 + let that = this;
  94 + let brandData = new BrandApi(that.ctx);
101 95
102 - _.forEach(res.data[1].data.list, subValue => {  
103 - brandAds.push({  
104 - name: subValue.name,  
105 - src: helpers.image(subValue.src, 80, 50, 3),  
106 - url: subValue.url  
107 - });  
108 - });  
109 - } 96 + return co(function*() {
  97 + let switchParams = that.switchBrandParams(channel);
110 98
111 - // 头部品牌图块,广告位  
112 - if (res.data && res.data instanceof Array && res.data[0].data) {  
113 - _.forEach(res.data[0].data, (subValue, k) => {  
114 - let srcUrl;  
115 -  
116 - // kids lifestyle 第一张图尺寸不同  
117 - if (switchParams.channelType === 1 || switchParams.channelType === 2) {  
118 - srcUrl = helpers.image(subValue.src, 222, 180, 3);  
119 - } else {  
120 - srcUrl = (k === 0) ? helpers.image(subValue.src, 570, 280, 3) :  
121 - helpers.image(subValue.src, 280, 280, 3);  
122 - }  
123 - let brandPlusstarItem = {  
124 - name: subValue.title,  
125 - src: srcUrl,  
126 - url: subValue.url  
127 - }; 99 + let res = yield brandData.getBrandTopData(switchParams.brandCode);
128 100
129 - if (channel === BOYS || channel === GIRLS) {  
130 - if (k === 0) {  
131 - brandPlusstarItem.url = helpers.urlFormat('/brands/plusstar', {channel: channel});  
132 - } else {  
133 - brandPlusstarItem.url = helpers.urlFormat('/brands/plusstar', {id: k, channel: channel});  
134 - }  
135 - } 101 + let result = {},
  102 + brandAds = [],
  103 + brandLogos = [];
136 104
137 - brandLogos.push(brandPlusstarItem);  
138 - });  
139 - } 105 + if (!res || res.code !== 200) {
  106 + return result;
  107 + }
140 108
141 - // 整合brandTop数据结构,boys、girls  
142 - if (switchParams.channelType === 1 || switchParams.channelType === 2) {  
143 - result.isTab = true;  
144 - }  
145 - result.tabHeader = brandLogos;  
146 - result.logos = brandAds; 109 + // 头部10个品牌小图块 url
  110 + if (res.data && res.data instanceof Array && res.data[1].data && res.data[1].data.list) {
  111 +
  112 + _.forEach(res.data[1].data.list, subValue => {
  113 + brandAds.push({
  114 + name: subValue.name,
  115 + src: helpers.image(imgUtils.getImageUrl(
  116 + (subValue.src.match(/(\S*)imageView2/)[1] +
  117 + 'imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/' +
  118 + 'background/d2hpdGU=/position/center/quality/80'),
  119 + 136, 57), 136, 57),
  120 + url: subValue.url
  121 + });
  122 + });
  123 + }
147 124
148 - return result;  
149 - })();  
150 -}; 125 + // 头部品牌图块,广告位
  126 + if (res.data && res.data instanceof Array && res.data[0].data) {
  127 + _.forEach(res.data[0].data, (subValue, k) => {
  128 + let srcUrl;
151 129
152 -/**  
153 - * 获取品牌一览list  
154 - * @param string $channel 频道名称  
155 - * @param int start 开始位置 1 开始  
156 - * @param int length 取数长度 0 取到最后  
157 - */  
158 -const getBrandViewList = (channel, start, length) => {  
159 - return co(function*() {  
160 - let switchParams = switchBrandParams(channel); 130 + // kids lifestyle 第一张图尺寸不同
  131 + if (switchParams.channelType === 1 || switchParams.channelType === 2) {
  132 + srcUrl = helpers.image(subValue.src, 222, 180, 3);
  133 + } else {
  134 + srcUrl = (k === 0) ? helpers.image(subValue.src, 570, 280, 3) :
  135 + helpers.image(subValue.src, 280, 280, 3);
  136 + }
  137 + let brandPlusstarItem = {
  138 + name: subValue.title,
  139 + src: srcUrl,
  140 + url: subValue.url
  141 + };
  142 +
  143 + if (channel === BOYS || channel === GIRLS) {
  144 + if (k === 0) {
  145 + brandPlusstarItem.url = helpers.urlFormat('/brands/plusstar', {channel: channel});
  146 + } else {
  147 + brandPlusstarItem.url = helpers.urlFormat('/brands/plusstar', {id: k, channel: channel});
  148 + }
  149 + }
161 150
162 - let res = yield brandApi.getBrandListData(switchParams.channelType); 151 + brandLogos.push(brandPlusstarItem);
  152 + });
  153 + }
163 154
164 - let result = [],  
165 - numResult = {}; 155 + // 整合brandTop数据结构,boys、girls
  156 + if (switchParams.channelType === 1 || switchParams.channelType === 2) {
  157 + result.isTab = true;
  158 + }
  159 + result.tabHeader = brandLogos;
  160 + result.logos = brandAds;
166 161
167 - if (!res || res.code !== 200) {  
168 return result; 162 return result;
169 - } 163 + })();
  164 + }
170 165
171 - // 品牌list A-Z 0-9  
172 - if (res.data && res.data.all_list) { 166 + /**
  167 + * 获取品牌一览list
  168 + * @param string $channel 频道名称
  169 + * @param int start 开始位置 1 开始
  170 + * @param int length 取数长度 0 取到最后
  171 + */
  172 + getBrandViewList(channel, start, length) {
  173 + let that = this;
  174 + let brandData = new BrandApi(that.ctx);
173 175
174 - _.forEach(res.data.all_list, (subValue, key) => {  
175 - let listTmp = []; 176 + return co(function*() {
  177 + let switchParams = that.switchBrandParams(channel);
176 178
177 - _.forEach(subValue, ssubValue => {  
178 - let extQs = {};  
179 - let baseUri = ''; 179 + let res = yield brandData.getBrandListData(switchParams.channelType);
180 180
181 - // 为品牌名称  
182 - let href; 181 + let result = [],
  182 + numResult = {};
183 183
184 - if (switchParams.channelType === 1) {  
185 - Object.assign(extQs, {gender: '1,3'});  
186 - } else if (switchParams.channelType === 2) {  
187 - Object.assign(extQs, {gender: '2,3'});  
188 - }  
189 - let shopInfo, shopId;  
190 -  
191 - switch (ssubValue.type * 1) {  
192 - case 1:  
193 - extQs = {  
194 - query: ssubValue.brand_name,  
195 - brand: ssubValue.id  
196 - };  
197 - ssubValue.brand_domain = 'search';  
198 - break;  
199 - case 2:  
200 - shopInfo = _.get(ssubValue, 'shop_info.yoho_shop_list[0]', {});  
201 - shopId = shopInfo.shop_id || ssubValue.shop_id;  
202 -  
203 - ssubValue.brand_domain = shopInfo.shop_domain || ssubValue.brand_domain;  
204 - if (shopId) {  
205 - Object.assign(extQs, {shopId: shopId});  
206 - }  
207 - break;  
208 - case 3:  
209 - Object.assign(extQs, {brand: ssubValue.global_brand_id});  
210 - ssubValue.brand_domain = '';  
211 - baseUri = GLOBAL_BASE_URI;  
212 - break;  
213 - default:  
214 - break;  
215 - } 184 + if (!res || res.code !== 200) {
  185 + return result;
  186 + }
216 187
217 - href = helpers.urlFormat(baseUri, extQs, ssubValue.brand_domain); 188 + // 品牌list A-Z 0-9
  189 + if (res.data && res.data.all_list) {
  190 +
  191 + _.forEach(res.data.all_list, (subValue, key) => {
  192 + let listTmp = [];
  193 +
  194 + _.forEach(subValue, ssubValue => {
  195 + let extQs = {};
  196 + let baseUri = '';
  197 +
  198 + // 为品牌名称
  199 + let href;
  200 +
  201 + if (switchParams.channelType === 1) {
  202 + Object.assign(extQs, {gender: '1,3'});
  203 + } else if (switchParams.channelType === 2) {
  204 + Object.assign(extQs, {gender: '2,3'});
  205 + }
  206 + let shopInfo, shopId;
  207 +
  208 + switch (ssubValue.type * 1) {
  209 + case 1:
  210 + extQs = {
  211 + query: ssubValue.brand_name,
  212 + brand: ssubValue.id
  213 + };
  214 + ssubValue.brand_domain = 'search';
  215 + break;
  216 + case 2:
  217 + shopInfo = _.get(ssubValue, 'shop_info.yoho_shop_list[0]', {});
  218 + shopId = shopInfo.shop_id || ssubValue.shop_id;
  219 +
  220 + ssubValue.brand_domain = shopInfo.shop_domain || ssubValue.brand_domain;
  221 + if (shopId) {
  222 + Object.assign(extQs, {shopId: shopId});
  223 + }
  224 + break;
  225 + case 3:
  226 + Object.assign(extQs, {brand: ssubValue.global_brand_id});
  227 + ssubValue.brand_domain = '';
  228 + baseUri = GLOBAL_BASE_URI;
  229 + break;
  230 + default:
  231 + break;
  232 + }
  233 +
  234 + href = helpers.urlFormat(baseUri, extQs, ssubValue.brand_domain);
  235 +
  236 + let brandItem = {
  237 + name: ssubValue.brand_name,
  238 + key: ssubValue.id,
  239 + href: href
  240 + };
  241 +
  242 + if (ssubValue.is_hot === 'Y') {
  243 + brandItem.hot = 'hot';
  244 + }
  245 + listTmp.push(brandItem);
218 246
219 - let brandItem = {  
220 - name: ssubValue.brand_name,  
221 - key: ssubValue.id,  
222 - href: href  
223 - }; 247 + });
224 248
225 - if (ssubValue.is_hot === 'Y') {  
226 - brandItem.hot = 'hot'; 249 + if (key.match(/\d+/g)) {
  250 + numResult = {// 把0-9提出来
  251 + key: key,
  252 + val: _.sortBy(listTmp, 'name')// 对name排序
  253 + };
  254 + } else {
  255 + result.push({
  256 + key: key,
  257 + val: _.sortBy(listTmp, 'name')// 对name排序
  258 + });
227 } 259 }
228 - listTmp.push(brandItem);  
229 -  
230 }); 260 });
231 261
232 - if (key.match(/\d+/g)) {  
233 - numResult = {// 把0-9提出来  
234 - key: key,  
235 - val: _.sortBy(listTmp, 'name')// 对name排序  
236 - };  
237 - } else {  
238 - result.push({  
239 - key: key,  
240 - val: _.sortBy(listTmp, 'name')// 对name排序  
241 - });  
242 - }  
243 - });  
244 -  
245 - }  
246 -  
247 - // 只取部分数据  
248 - let begin;  
249 -  
250 - if (start) {  
251 - begin = (start - 1) ? (start - 1) : 0;  
252 - begin = (begin > 0) ? begin : 0;  
253 - result = length ? result.slice(begin, length + begin) : result.slice(begin);  
254 - } 262 + }
255 263
256 - result = _.sortBy(result, 'key');// A-Z排序  
257 - result.push(numResult); // 0-9放到最后  
258 - result.navigation = _.map(result, 'key');  
259 - return result;  
260 - })();  
261 -}; 264 + // 只取部分数据
  265 + let begin;
262 266
263 -/**  
264 - * 获取单个广告浮窗内容  
265 - *  
266 - * @param int $brandId  
267 - * @param int $uid  
268 - * @return array  
269 - */  
270 -const getBrandInfo = (brandId, uid) => {  
271 - return co(function*() {  
272 - let data = {},  
273 - imgs = [];  
274 -  
275 - // 获取品牌简介  
276 - let res = yield brandApi.getBrandIntro(brandId, uid); 267 + if (start) {
  268 + begin = (start - 1) ? (start - 1) : 0;
  269 + begin = (begin > 0) ? begin : 0;
  270 + result = length ? result.slice(begin, length + begin) : result.slice(begin);
  271 + }
277 272
278 - if (!res || res.code !== 200) {  
279 - return data;  
280 - }  
281 - if (res.data) {  
282 - // 获取品牌下的产品信息  
283 - let proInfo = yield brandApi.getProductByBrand(brandId, 3); 273 + result = _.sortBy(result, 'key');// A-Z排序
  274 + result.push(numResult); // 0-9放到最后
  275 + result.navigation = _.map(result, 'key');
  276 + return result;
  277 + })();
  278 + }
284 279
285 - if (!proInfo || proInfo.code !== 200) { 280 + /**
  281 + * 获取单个广告浮窗内容
  282 + *
  283 + * @param int $brandId
  284 + * @param int $uid
  285 + * @return array
  286 + */
  287 + getBrandInfo(brandId, uid) {
  288 + let that = this;
  289 + let brandData = new BrandApi(that.ctx);
  290 +
  291 + return co(function*() {
  292 + let data = {},
  293 + imgs = [];
  294 +
  295 + // 获取品牌简介
  296 + let res = yield brandData.getBrandIntro(brandId, uid);
  297 +
  298 + if (!res || res.code !== 200) {
286 return data; 299 return data;
287 } 300 }
288 - let proInfoTmp = proInfo.data.product_list ? proInfo.data.product_list : []; 301 + if (res.data) {
  302 + // 获取品牌下的产品信息
  303 + let proInfo = yield brandData.getProductByBrand(brandId, 3);
289 304
290 - if (!_.isEmpty(proInfoTmp)) {  
291 - _.forEach(proInfoTmp, subValue => {  
292 - imgs.push({  
293 - src: helpers.image(subValue.default_images, 80, 100, 3) 305 + if (!proInfo || proInfo.code !== 200) {
  306 + return data;
  307 + }
  308 + let proInfoTmp = proInfo.data.product_list ? proInfo.data.product_list : [];
  309 +
  310 + if (!_.isEmpty(proInfoTmp)) {
  311 + _.forEach(proInfoTmp, subValue => {
  312 + imgs.push({
  313 + src: helpers.image(subValue.default_images, 80, 100, 3)
  314 + });
294 }); 315 });
295 - }); 316 + }
  317 +
  318 + // 整合
  319 + data = {
  320 + key: res.data.brand_id,
  321 + icon: helpers.image(res.data.brand_ico, 80, 50, 3),
  322 + title: res.data.brand_name,
  323 + content: res.data.brand_intro,
  324 + subtitle: 'FEATURED ITEMS',
  325 + imgs: imgs
  326 + };
296 } 327 }
  328 + return data;
  329 + })();
  330 + }
297 331
298 - // 整合  
299 - data = {  
300 - key: res.data.brand_id,  
301 - icon: helpers.image(res.data.brand_ico, 80, 50, 3),  
302 - title: res.data.brand_name,  
303 - content: res.data.brand_intro,  
304 - subtitle: 'FEATURED ITEMS',  
305 - imgs: imgs  
306 - };  
307 - }  
308 - return data;  
309 - })();  
310 -}; 332 + /**
  333 + * 多个品牌ID获取品牌信息
  334 + *
  335 + * @param array $brandIds
  336 + * @return array
  337 + */
  338 + getBrandInfoByIds(brandIds) {
  339 + let that = this;
  340 + let brandData = new BrandApi(that.ctx);
311 341
312 -/**  
313 - * 多个品牌ID获取品牌信息  
314 - *  
315 - * @param array $brandIds  
316 - * @return array  
317 - */  
318 -const getBrandInfoByIds = (brandIds) => {  
319 - return co(function*() {  
320 - let res = yield brandApi.getBrandInfoByIds(brandIds); 342 + return co(function*() {
  343 + let res = yield brandData.getBrandInfoByIds(brandIds);
321 344
322 - let brandsInfo = {}; 345 + let brandsInfo = {};
323 346
324 - if (!res || res.code !== 200) {  
325 - return brandsInfo;  
326 - }  
327 - if (res.data && res.code === 200) {  
328 - _.forEach(res.data, (subValue, k) => {  
329 - subValue.desc = _.trim(subValue.brand_intro.replace(/(\t)|(\n)|(\r)|( )/g, '') 347 + if (!res || res.code !== 200) {
  348 + return brandsInfo;
  349 + }
  350 + if (res.data && res.code === 200) {
  351 + _.forEach(res.data, (subValue, k) => {
  352 + subValue.desc = _.trim(subValue.brand_intro.replace(/(\t)|(\n)|(\r)|( )/g, '')
330 .replace(/<.*?>/ig, '')); 353 .replace(/<.*?>/ig, ''));
331 - subValue.url = subValue.brand_domain;  
332 - delete subValue.brand_intro;  
333 - brandsInfo[k] = subValue;  
334 - });  
335 - } 354 + subValue.url = subValue.brand_domain;
  355 + delete subValue.brand_intro;
  356 + brandsInfo[k] = subValue;
  357 + });
  358 + }
336 359
337 - return brandsInfo;  
338 - })();  
339 -}; 360 + return brandsInfo;
  361 + })();
  362 + }
340 363
341 -/**  
342 - * 获取plusstar品牌列表项目  
343 - *  
344 - * @param string $channel  
345 - * @return array  
346 - */  
347 -const getPlusstarBrandListItem = (channel) => {  
348 - return co(function*() {  
349 - let code = channel === 'girls' ? channelCode.brand_plusstar_banner_girls :  
350 - channelCode.brand_plusstar_banner_boys; 364 + /**
  365 + * 获取plusstar品牌列表项目
  366 + *
  367 + * @param string $channel
  368 + * @return array
  369 + */
  370 + getPlusstarBrandListItem(channel) {
  371 + let that = this;
  372 + let brandData = new BrandApi(that.ctx);
351 373
352 - // 资源位数据  
353 - let resource = yield serviceApi.get('operations/api/v5/resource/get', {content_code: code}, {cache: 3600}); 374 + return co(function*() {
  375 + let code = channel === 'girls' ? channelCode.brand_plusstar_banner_girls :
  376 + channelCode.brand_plusstar_banner_boys;
354 377
355 - let items = []; 378 + // 资源位数据
  379 + let resource = yield brandData.getPlusstarBrandListItem(code);
356 380
357 - if (!resource || resource.code !== 200) {  
358 - return items;  
359 - }  
360 - if (resource.data && resource.code === 200) {  
361 - items[0] = {name: '所有品牌', src: '', url: helpers.urlFormat('/brands', {channel: channel}), brandType: ''};  
362 - items[1] = {name: '设计新潮', src: '', url: '', brandType: 4};  
363 - items[2] = {name: '潮流经典', src: '', url: '', brandType: 1};  
364 - items[3] = {name: '明星潮牌', src: '', url: '', brandType: 2};  
365 - items[4] = {name: '原创潮牌', src: '', url: '', brandType: 3};  
366 -  
367 - let resourceData = resource.data,  
368 - pos = 0;  
369 -  
370 - _.forEach(items, (subValue, k) => {  
371 - if (_.isEmpty(subValue.url)) {  
372 - subValue.url = helpers.urlFormat('/brands/plusstar', {id: k, channel: channel});  
373 - } 381 + let items = [];
374 382
375 - if (pos in resourceData[0].data) {  
376 - subValue.src = helpers.image(resourceData[0].data[pos].src, 222, 180, 1);  
377 - subValue.name = resourceData[0].data[pos].title;  
378 - }  
379 - pos++;  
380 - });  
381 - }  
382 -  
383 - return items;  
384 - })();  
385 -};  
386 -  
387 -/**  
388 - * 获取Plustar列表  
389 - *  
390 - * @param string $brandType  
391 - * @param string $gender  
392 - * @return array  
393 - */  
394 -const getPlustarList = (brandType, gender) => {  
395 - return co(function*() {  
396 - let list = yield brandApi.getPlusstarList(brandType, gender); 383 + if (!resource || resource.code !== 200) {
  384 + return items;
  385 + }
  386 + if (resource.data && resource.code === 200) {
  387 + items[0] = {name: '所有品牌', src: '', url: helpers.urlFormat('/brands',
  388 + {channel: channel}), brandType: ''};
  389 + items[1] = {name: '设计新潮', src: '', url: '', brandType: 4};
  390 + items[2] = {name: '潮流经典', src: '', url: '', brandType: 1};
  391 + items[3] = {name: '明星潮牌', src: '', url: '', brandType: 2};
  392 + items[4] = {name: '原创潮牌', src: '', url: '', brandType: 3};
  393 +
  394 + let resourceData = resource.data,
  395 + pos = 0;
  396 +
  397 + _.forEach(items, (subValue, k) => {
  398 + if (_.isEmpty(subValue.url)) {
  399 + subValue.url = helpers.urlFormat('/brands/plusstar', {id: k, channel: channel});
  400 + }
397 401
398 - let brandList = {},  
399 - data = {},  
400 - brandsIds = [],  
401 - result = {brandsIds: [], data: {}}; 402 + if (pos in resourceData[0].data) {
  403 + subValue.src = helpers.image(resourceData[0].data[pos].src, 222, 180, 1);
  404 + subValue.name = resourceData[0].data[pos].title;
  405 + }
  406 + pos++;
  407 + });
  408 + }
402 409
403 - if (!list || list.code !== 200) {  
404 - return result;  
405 - }  
406 - if (list.data && list.data.data && list.data.data.list) {  
407 - brandList = list.data.data.list[0];  
408 - }  
409 - if (brandList.data) {  
410 - _.forEach(brandList.data, brand => {  
411 - let src = ''; 410 + return items;
  411 + })();
  412 + }
412 413
413 - if (brand.data[0]) {  
414 - src = helpers.image(brand.data[0].src, 320, 160, 1);  
415 - }  
416 - data[brand.brand_id] = {  
417 - brand_id: brand.brand_id,  
418 - name: brand.brand_name,  
419 - sort_id: brand.sort_id,  
420 - src: src,  
421 - desc: '',  
422 - url: ''  
423 - };  
424 - brandsIds.push(brand.brand_id);  
425 - }); 414 + /**
  415 + * 获取Plustar列表
  416 + *
  417 + * @param string $brandType
  418 + * @param string $gender
  419 + * @return array
  420 + */
  421 + getPlustarList(brandType, gender) {
  422 + let that = this;
  423 + let brandData = new BrandApi(that.ctx);
  424 +
  425 + return co(function*() {
  426 + let list = yield brandData.getPlusstarList(brandType, gender);
  427 +
  428 + let brandList = {},
  429 + data = {},
  430 + brandsIds = [],
  431 + result = {brandsIds: [], data: {}};
  432 +
  433 + if (!list || list.code !== 200) {
  434 + return result;
  435 + }
  436 + if (list.data && list.data.data && list.data.data.list) {
  437 + brandList = list.data.data.list[0];
  438 + }
  439 + if (brandList.data) {
  440 + _.forEach(brandList.data, brand => {
  441 + let src = '';
426 442
427 - result.brandsIds = brandsIds;  
428 - result.data = data;  
429 - } 443 + if (brand.data[0]) {
  444 + src = helpers.image(brand.data[0].src, 320, 160, 1);
  445 + }
  446 + data[brand.brand_id] = {
  447 + brand_id: brand.brand_id,
  448 + name: brand.brand_name,
  449 + sort_id: brand.sort_id,
  450 + src: src,
  451 + desc: '',
  452 + url: ''
  453 + };
  454 + brandsIds.push(brand.brand_id);
  455 + });
430 456
431 - return result;  
432 - })();  
433 -}; 457 + result.brandsIds = brandsIds;
  458 + result.data = data;
  459 + }
434 460
435 -module.exports = {  
436 - getBrandViewTop,  
437 - getBrandViewList,  
438 - getBrandInfo,  
439 - getBrandInfoByIds,  
440 - getPlusstarBrandListItem,  
441 - getPlustarList 461 + return result;
  462 + })();
  463 + }
442 }; 464 };
@@ -9,7 +9,7 @@ const Promise = require('bluebird'); @@ -9,7 +9,7 @@ const Promise = require('bluebird');
9 const co = Promise.coroutine; 9 const co = Promise.coroutine;
10 const api = global.yoho.API; 10 const api = global.yoho.API;
11 const headerModel = require('../../../doraemon/models/header'); 11 const headerModel = require('../../../doraemon/models/header');
12 -const brandsModel = require('./brands-model'); 12 +const BrandsModel = require('./brands-model');
13 const _ = require('lodash'); 13 const _ = require('lodash');
14 const helpers = global.yoho.helpers; 14 const helpers = global.yoho.helpers;
15 const pager = require(`${global.utils}/pager`).setPager; 15 const pager = require(`${global.utils}/pager`).setPager;
@@ -20,294 +20,314 @@ const KIDS = 'kids'; @@ -20,294 +20,314 @@ const KIDS = 'kids';
20 const LIFESTYLE = 'lifestyle'; 20 const LIFESTYLE = 'lifestyle';
21 const queryString = require('querystring'); 21 const queryString = require('querystring');
22 22
23 -/**  
24 - * 获取品牌一览资源位&channelType  
25 - *  
26 - * @param string $channelStr  
27 - * @return array  
28 - */  
29 -const getGenderByChannel = channel => {  
30 - let gender = '';  
31 -  
32 - switch (channel) {  
33 -  
34 - case BOYS:  
35 - gender = '1,3';  
36 - break;  
37 - case GIRLS:  
38 - gender = '2,3';  
39 - break;  
40 - default:  
41 - gender = '1,2,3';  
42 - break; 23 +module.exports = class extends global.yoho.BaseModel {
  24 + constructor(ctx) {
  25 + super(ctx);
43 } 26 }
44 - return gender;  
45 -};  
46 27
47 -const getHomeurlByChannel = channel => {  
48 - let home;  
49 -  
50 - switch (channel) {  
51 - case GIRLS:  
52 - home = helpers.urlFormat('/woman', {}, 'new');  
53 - break;  
54 - case LIFESTYLE:  
55 - home = helpers.urlFormat('/lifestyle', {}, 'new');  
56 - break;  
57 - case KIDS:  
58 - home = helpers.urlFormat('/kids', {}, 'new');  
59 - break;  
60 - default:  
61 - home = helpers.urlFormat('');  
62 - break; 28 + /**
  29 + * 获取品牌一览资源位&channelType
  30 + *
  31 + * @param string $channelStr
  32 + * @return array
  33 + */
  34 + getGenderByChannel(channel) {
  35 + let gender = '';
  36 +
  37 + switch (channel) {
  38 +
  39 + case BOYS:
  40 + gender = '1,3';
  41 + break;
  42 + case GIRLS:
  43 + gender = '2,3';
  44 + break;
  45 + default:
  46 + gender = '1,2,3';
  47 + break;
  48 + }
  49 + return gender;
63 } 50 }
64 - return home;  
65 -};  
66 51
67 -// 添加网站的SEO  
68 -const seoMap = {  
69 - boys: {  
70 - title: '品牌一览|男装品牌排行榜,男装品牌大全|YOHO!BUY 有货 100%正品保证',  
71 - keywords: '品牌一览,男装品牌,男装品牌排行榜,男装品牌大全,YOHO!BUY 有货',  
72 - description: 'YOHO!BUY 有货男装品牌一览汇集国内国际各大男装品牌大全,为广大爱好时尚的男士青年提供品牌男装、' +  
73 - '休闲男装、商务男装.YOHO!BUY 有货,100%正品保证'  
74 - },  
75 - girls: {  
76 - title: '品牌一览|女装品牌排行榜,女装品牌大全|YOHO!BUY 有货 100%正品保证',  
77 - keywords: '品牌一览,女装品牌,女装品牌排行榜,女装品牌大全,YOHO!BUY 有货',  
78 - description: 'YOHO!BUY 有货女装品牌一览汇集国内国际各大女装品牌,为广大爱美女生提供品牌女装、休闲女装、' +  
79 - '商务女装.买品牌女装就上YOHO!BUY 有货,100%正品保证'  
80 - },  
81 - kids: {  
82 - title: '品牌一览|童装童鞋品牌,儿童鞋包配饰排行榜,潮童品牌大全|YOHO!BUY 有货 100%正品保证',  
83 - keywords: '童装品牌,童装童鞋排行榜,儿童鞋包配饰排行榜,潮童品牌大全,品牌一览,YOHO!BUY 有货',  
84 - description: 'YOHO!BUY 有货童装品牌一览汇集国内国际各大童装品牌大全,为广大爱好潮流的儿童提供品牌童装、童鞋,' +  
85 - '儿童鞋包配饰.YOHO!BUY 有货,100%正品保证'  
86 - },  
87 - lifestyle: {  
88 - title: '品牌一览|数码3c,居家,玩具娱乐,文具,美妆品牌|YOHO!BUY 有货 100%正品保证',  
89 - keywords: '数码3c品牌,居家品牌,玩具娱乐品牌,文具品牌,美妆品牌',  
90 - description: 'YOHO!BUY 有货女装品牌一览汇集国内国际各大数码3c品牌,居家品牌,玩具娱乐品牌,文具品牌,' +  
91 - '美妆品牌.买创意生活家居就上YOHO!BUY 有货,100%正品保证'  
92 - },  
93 - 'boys-plusstar': {  
94 - title: '品牌plusstar,男装潮流品牌简介|YOHO!BUY有货',  
95 - keywords: '品牌plusstar,男装潮流品牌简介',  
96 - description: 'YOHO!BUY 有货男装品牌一览汇集国内国际各大男装品牌,为广大爱美男生提供品牌男装、' +  
97 - '休闲男装、商务男装.买品牌男装就上YOHO!BUY 有货,100%正品保证'  
98 - },  
99 - 'girls-plusstar': {  
100 - title: '品牌plusstar,女装潮流品牌简介|YOHO!BUY有货',  
101 - keywords: '品牌plusstar,女装潮流品牌简介',  
102 - description: 'YOHO!BUY 有货女装品牌一览汇集国内国际各大女装品牌,为广大爱美女生提供品牌女装、' +  
103 - '休闲女装、商务女装.买品牌女装就上YOHO!BUY 有货,100%正品保证' 52 + getHomeurlByChannel(channel) {
  53 + let home;
  54 +
  55 + switch (channel) {
  56 + case GIRLS:
  57 + home = helpers.urlFormat('/woman', {}, 'new');
  58 + break;
  59 + case LIFESTYLE:
  60 + home = helpers.urlFormat('/lifestyle', {}, 'new');
  61 + break;
  62 + case KIDS:
  63 + home = helpers.urlFormat('/kids', {}, 'new');
  64 + break;
  65 + default:
  66 + home = helpers.urlFormat('');
  67 + break;
  68 + }
  69 + return home;
104 } 70 }
105 -};  
106 71
107 -/**  
108 - * plusstar 分页链接伪静态  
109 - * @param string uri  
110 - * @param string originUrl 动态地址  
111 - */  
112 -const staticUrl = (uri, originUrl) => {  
113 - originUrl = queryString.parse(_.split(originUrl, '?')[1]);  
114 - return `${uri}id${originUrl.id || 0}-p${originUrl.page || 1}/`;  
115 -};  
116 -  
117 -/**  
118 - * 获取品牌一览list  
119 - * @param string $channel 频道名称  
120 - * @param int start 开始位置 1 开始  
121 - * @param int length 取数长度 0 取到最后  
122 - */  
123 -exports.getBrandViewList = (channel) => {  
124 - let apiMethod = [  
125 - headerModel.requestHeaderData(channel),  
126 - brandsModel.getBrandViewTop(channel),  
127 - brandsModel.getBrandViewList(channel) // 分屏加载  
128 - ];  
129 -  
130 - return api.all(apiMethod).then(result => {  
131 - let responseData = {  
132 - module: 'brands',  
133 - page: 'brands',  
134 - noCashe: false 72 + // 添加网站的SEO
  73 + seoMap() {
  74 + return {
  75 + boys: {
  76 + title: '品牌一览|男装品牌排行榜,男装品牌大全|YOHO!BUY 有货 100%正品保证',
  77 + keywords: '品牌一览,男装品牌,男装品牌排行榜,男装品牌大全,YOHO!BUY 有货',
  78 + description: 'YOHO!BUY 有货男装品牌一览汇集国内国际各大男装品牌大全,为广大爱好时尚的男士青年提供品牌男装、' +
  79 + '休闲男装、商务男装.YOHO!BUY 有货,100%正品保证'
  80 + },
  81 + girls: {
  82 + title: '品牌一览|女装品牌排行榜,女装品牌大全|YOHO!BUY 有货 100%正品保证',
  83 + keywords: '品牌一览,女装品牌,女装品牌排行榜,女装品牌大全,YOHO!BUY 有货',
  84 + description: 'YOHO!BUY 有货女装品牌一览汇集国内国际各大女装品牌,为广大爱美女生提供品牌女装、休闲女装、' +
  85 + '商务女装.买品牌女装就上YOHO!BUY 有货,100%正品保证'
  86 + },
  87 + kids: {
  88 + title: '品牌一览|童装童鞋品牌,儿童鞋包配饰排行榜,潮童品牌大全|YOHO!BUY 有货 100%正品保证',
  89 + keywords: '童装品牌,童装童鞋排行榜,儿童鞋包配饰排行榜,潮童品牌大全,品牌一览,YOHO!BUY 有货',
  90 + description: 'YOHO!BUY 有货童装品牌一览汇集国内国际各大童装品牌大全,为广大爱好潮流的儿童提供品牌童装、童鞋,' +
  91 + '儿童鞋包配饰.YOHO!BUY 有货,100%正品保证'
  92 + },
  93 + lifestyle: {
  94 + title: '品牌一览|数码3c,居家,玩具娱乐,文具,美妆品牌|YOHO!BUY 有货 100%正品保证',
  95 + keywords: '数码3c品牌,居家品牌,玩具娱乐品牌,文具品牌,美妆品牌',
  96 + description: 'YOHO!BUY 有货女装品牌一览汇集国内国际各大数码3c品牌,居家品牌,玩具娱乐品牌,文具品牌,' +
  97 + '美妆品牌.买创意生活家居就上YOHO!BUY 有货,100%正品保证'
  98 + },
  99 + 'boys-plusstar': {
  100 + title: '品牌plusstar,男装潮流品牌简介|YOHO!BUY有货',
  101 + keywords: '品牌plusstar,男装潮流品牌简介',
  102 + description: 'YOHO!BUY 有货男装品牌一览汇集国内国际各大男装品牌,为广大爱美男生提供品牌男装、' +
  103 + '休闲男装、商务男装.买品牌男装就上YOHO!BUY 有货,100%正品保证'
  104 + },
  105 + 'girls-plusstar': {
  106 + title: '品牌plusstar,女装潮流品牌简介|YOHO!BUY有货',
  107 + keywords: '品牌plusstar,女装潮流品牌简介',
  108 + description: 'YOHO!BUY 有货女装品牌一览汇集国内国际各大女装品牌,为广大爱美女生提供品牌女装、' +
  109 + '休闲女装、商务女装.买品牌女装就上YOHO!BUY 有货,100%正品保证'
  110 + }
135 }; 111 };
  112 + }
136 113
137 - // 头部数据  
138 - Object.assign(responseData, result[0]);  
139 -  
140 - // 品牌一览列表  
141 - responseData.brands = result[1];  
142 - responseData.brands.navigation = result[2].navigation;  
143 - responseData.brands.category = result[2]; 114 + /**
  115 + * plusstar 分页链接伪静态
  116 + * @param string uri
  117 + * @param string originUrl 动态地址
  118 + */
  119 + staticUrl(uri, originUrl) {
  120 + originUrl = queryString.parse(_.split(originUrl, '?')[1]);
  121 + return `${uri}id${originUrl.id || 0}-p${originUrl.page || 1}/`;
  122 + }
144 123
145 - // 导航pathNav  
146 - responseData.brands.pathNav = [  
147 - {  
148 - href: getHomeurlByChannel(channel),  
149 - name: `${_.toUpper(channel)}首页`,  
150 - pathTitle: 'YOHO!BUY 有货'  
151 - },  
152 - {  
153 - href: helpers.urlFormat('/brands'),  
154 - name: '品牌一览',  
155 - pathTitle: '品牌一览'  
156 - } 124 + /**
  125 + * 获取品牌一览list
  126 + * @param string $channel 频道名称
  127 + * @param int start 开始位置 1 开始
  128 + * @param int length 取数长度 0 取到最后
  129 + */
  130 + getBrandViewList(channel) {
  131 + let that = this;
  132 + let brandsModelCtx = new BrandsModel(that.ctx);
  133 +
  134 + let apiMethod = [
  135 + headerModel.requestHeaderData(channel),
  136 + brandsModelCtx.getBrandViewTop(channel),
  137 + brandsModelCtx.getBrandViewList(channel) // 分屏加载
157 ]; 138 ];
158 139
159 - // SEO  
160 - Object.assign(responseData, seoMap[channel]);  
161 -  
162 - // 数据出错不cashe  
163 - if (_.isEmpty(result[0].headerData) || _.isEmpty(result[1]) || _.isEmpty(result[2])) {  
164 - responseData.noCashe = true;  
165 - }  
166 - return responseData;  
167 - });  
168 -}; 140 + return api.all(apiMethod).then(result => {
  141 + let responseData = {
  142 + module: 'brands',
  143 + page: 'brands',
  144 + noCashe: false
  145 + };
  146 +
  147 + // 头部数据
  148 + Object.assign(responseData, result[0]);
  149 +
  150 + // 品牌一览列表
  151 + responseData.brands = result[1];
  152 + responseData.brands.navigation = result[2].navigation;
  153 + responseData.brands.category = result[2];
  154 +
  155 + // 导航pathNav
  156 + responseData.brands.pathNav = [
  157 + {
  158 + href: that.getHomeurlByChannel(channel),
  159 + name: `${_.toUpper(channel)}首页`,
  160 + pathTitle: 'YOHO!BUY 有货'
  161 + },
  162 + {
  163 + href: helpers.urlFormat('/brands'),
  164 + name: '品牌一览',
  165 + pathTitle: '品牌一览'
  166 + }
  167 + ];
169 168
170 -/**  
171 - * brandList-Ajax调用  
172 - */  
173 -exports.getBrandList = (channel, start) => {  
174 - let apiMethod = [  
175 - brandsModel.getBrandViewList(channel, start)  
176 - ];  
177 -  
178 - return api.all(apiMethod).then(result => {  
179 - let responseData = {};  
180 -  
181 - // 品牌一览列表  
182 - responseData.category = result[0];  
183 - return responseData;  
184 - });  
185 -}; 169 + // SEO
  170 + Object.assign(responseData, that.seoMap[channel]);
186 171
187 -/**  
188 - * 品牌接口数据  
189 - *  
190 - * @param string brandId 获取品牌ID  
191 - * @return json  
192 - */  
193 -exports.brandInfo = (brandId, uid) => {  
194 - let apiMethod = [  
195 - brandsModel.getBrandInfo(brandId, uid)  
196 - ];  
197 -  
198 - return api.all(apiMethod).then(result => {  
199 - let responseData = {  
200 - code: _.isEmpty(result[0]) ? 400 : 200,  
201 - brand: _.isEmpty(result[0]) ? '' : result[0],  
202 - noCashe: false  
203 - };  
204 -  
205 - // 数据出错不cashe  
206 - if (_.isEmpty(result[0])) {  
207 - responseData.noCashe = true;  
208 - }  
209 - return responseData;  
210 - });  
211 -}; 172 + // 数据出错不cashe
  173 + if (_.isEmpty(result[0].headerData) || _.isEmpty(result[1]) || _.isEmpty(result[2])) {
  174 + responseData.noCashe = true;
  175 + }
  176 + return responseData;
  177 + });
  178 + }
212 179
213 -/**  
214 - * 多个品牌ID获取品牌信息  
215 - *  
216 - * @param array $brandIds  
217 - * @return array  
218 - */  
219 -exports.plusstarList = (channel, req) => {  
220 - return co(function*() {  
221 - let headerData = yield headerModel.requestHeaderData(channel);  
222 -  
223 - let responseData = {  
224 - module: 'brands',  
225 - page: 'brands',  
226 - brandsHomePage: true,  
227 - noCashe: false  
228 - }; 180 + /**
  181 + * brandList-Ajax调用
  182 + */
  183 + getBrandList(channel, start) {
  184 + let that = this;
  185 + let brandsModelCtx = new BrandsModel(that.ctx);
229 186
230 - let id = req.query.id || '',  
231 - gender = req.query.gender || getGenderByChannel(channel),  
232 - limit = 20,  
233 - page = parseInt(req.query.page, 10) || 1; 187 + let apiMethod = [
  188 + brandsModelCtx.getBrandViewList(channel, start)
  189 + ];
234 190
235 - let items = yield brandsModel.getPlusstarBrandListItem(channel); 191 + return api.all(apiMethod).then(result => {
  192 + let responseData = {};
236 193
237 - let brandType = 1; 194 + // 品牌一览列表
  195 + responseData.category = result[0];
  196 + return responseData;
  197 + });
  198 + }
238 199
239 - if (+id !== 0 && items[id]) {  
240 - brandType = items[id].brandType;  
241 - }  
242 - let plustarList = yield brandsModel.getPlustarList(brandType, gender); 200 + /**
  201 + * 品牌接口数据
  202 + *
  203 + * @param string brandId 获取品牌ID
  204 + * @return json
  205 + */
  206 + brandInfo(brandId, uid) {
  207 + let that = this;
  208 + let brandsModelCtx = new BrandsModel(that.ctx);
  209 +
  210 + let apiMethod = [
  211 + brandsModelCtx.getBrandInfo(brandId, uid)
  212 + ];
243 213
244 - let list = plustarList.data; 214 + return api.all(apiMethod).then(result => {
  215 + let responseData = {
  216 + code: _.isEmpty(result[0]) ? 400 : 200,
  217 + brand: _.isEmpty(result[0]) ? '' : result[0],
  218 + noCashe: false
  219 + };
245 220
246 - // 数据出错不cashe  
247 - if (_.isEmpty(headerData.headerData) || _.isEmpty(items) || _.isEmpty(list)) {  
248 - responseData.noCashe = true;  
249 - }  
250 - let brandIds = [],  
251 - brands = [],  
252 - pageList = {};  
253 -  
254 - brandIds = plustarList.brandsIds.slice((page - 1) * limit, page * limit);  
255 - if (plustarList.brandsIds.length > limit) {  
256 - pageList = pager(Math.ceil(plustarList.brandsIds.length / limit), {  
257 - page: page,  
258 - id: id  
259 - });  
260 -  
261 - // url 伪静态  
262 - _.forEach(pageList.pages, (val) => {  
263 - val.url = staticUrl(`/${channel}-brands/plusstar/`, val.url);  
264 - });  
265 - if (pageList.nextPage) {  
266 - pageList.nextPage.url = staticUrl(`/${channel}-brands/plusstar/`, pageList.nextPage.url);  
267 - }  
268 - if (pageList.prePage) {  
269 - pageList.prePage.url = staticUrl(`/${channel}-brands/plusstar/`, pageList.prePage.url); 221 + // 数据出错不cashe
  222 + if (_.isEmpty(result[0])) {
  223 + responseData.noCashe = true;
270 } 224 }
271 - } 225 + return responseData;
  226 + });
  227 + }
272 228
273 - if (brandIds.length > 0) {  
274 - // 获取品牌信息  
275 - let brandsInfo = yield brandsModel.getBrandInfoByIds(brandIds); 229 + /**
  230 + * 多个品牌ID获取品牌信息
  231 + *
  232 + * @param array $brandIds
  233 + * @return array
  234 + */
  235 + plusstarList(channel, req) {
  236 + let that = this;
  237 + let brandsModelCtx = new BrandsModel(that.ctx);
  238 +
  239 + return co(function*() {
  240 + let headerData = yield headerModel.requestHeaderData(channel);
  241 +
  242 + let responseData = {
  243 + module: 'brands',
  244 + page: 'brands',
  245 + brandsHomePage: true,
  246 + noCashe: false
  247 + };
  248 +
  249 + let id = req.query.id || '',
  250 + gender = req.query.gender || that.getGenderByChannel(channel),
  251 + limit = 20,
  252 + page = parseInt(req.query.page, 10) || 1;
  253 +
  254 + let items = yield brandsModelCtx.getPlusstarBrandListItem(channel);
  255 +
  256 + let brandType = 1;
  257 +
  258 + if (+id !== 0 && items[id]) {
  259 + brandType = items[id].brandType;
  260 + }
  261 + let plustarList = yield brandsModelCtx.getPlustarList(brandType, gender);
276 262
277 - _.forEach(brandIds, brandId => {  
278 - if (brandsInfo[brandId]) {  
279 - list[brandId].desc = brandsInfo[brandId].desc;  
280 - list[brandId].url = helpers.urlFormat('', {gender: gender}, brandsInfo[brandId].url);  
281 - }  
282 - brands.push(list[brandId]);  
283 - }); 263 + let list = plustarList.data;
284 264
285 // 数据出错不cashe 265 // 数据出错不cashe
286 - if (_.isEmpty(brandsInfo)) { 266 + if (_.isEmpty(headerData.headerData) || _.isEmpty(items) || _.isEmpty(list)) {
287 responseData.noCashe = true; 267 responseData.noCashe = true;
288 } 268 }
289 - }  
290 - let data = {  
291 - brandsHomePage: true,  
292 - brands: {  
293 - items: brands,  
294 - tabs: items 269 + let brandIds = [],
  270 + brands = [],
  271 + pageList = {};
  272 +
  273 + brandIds = plustarList.brandsIds.slice((page - 1) * limit, page * limit);
  274 + if (plustarList.brandsIds.length > limit) {
  275 + pageList = pager(Math.ceil(plustarList.brandsIds.length / limit), {
  276 + page: page,
  277 + id: id
  278 + });
  279 +
  280 + // url 伪静态
  281 + _.forEach(pageList.pages, (val) => {
  282 + val.url = that.staticUrl(`/${channel}-brands/plusstar/`, val.url);
  283 + });
  284 + if (pageList.nextPage) {
  285 + pageList.nextPage.url = that.staticUrl(`/${channel}-brands/plusstar/`, pageList.nextPage.url);
  286 + }
  287 + if (pageList.prePage) {
  288 + pageList.prePage.url = that.staticUrl(`/${channel}-brands/plusstar/`, pageList.prePage.url);
  289 + }
  290 + }
295 291
  292 + if (brandIds.length > 0) {
  293 + // 获取品牌信息
  294 + let brandsInfo = yield brandsModelCtx.getBrandInfoByIds(brandIds);
  295 +
  296 + _.forEach(brandIds, brandId => {
  297 + if (brandsInfo[brandId]) {
  298 + list[brandId].desc = brandsInfo[brandId].desc;
  299 + list[brandId].url = helpers.urlFormat('', {gender: gender}, brandsInfo[brandId].url);
  300 + }
  301 + brands.push(list[brandId]);
  302 + });
  303 +
  304 + // 数据出错不cashe
  305 + if (_.isEmpty(brandsInfo)) {
  306 + responseData.noCashe = true;
  307 + }
296 } 308 }
297 - }; 309 + let data = {
  310 + brandsHomePage: true,
  311 + brands: {
  312 + items: brands,
  313 + tabs: items
  314 +
  315 + }
  316 + };
298 317
299 - // 头部数据  
300 - Object.assign(responseData, headerData); 318 + // 头部数据
  319 + Object.assign(responseData, headerData);
301 320
302 - // 产品信息  
303 - Object.assign(responseData, data); 321 + // 产品信息
  322 + Object.assign(responseData, data);
304 323
305 - // 页码  
306 - Object.assign(responseData, pageList); 324 + // 页码
  325 + Object.assign(responseData, pageList);
307 326
308 - // SEO  
309 - Object.assign(responseData, seoMap[`${channel}-plusstar`] || {});  
310 - return responseData;  
311 - })(); 327 + // SEO
  328 + Object.assign(responseData, that.seoMap[`${channel}-plusstar`] || {});
  329 + return responseData;
  330 + })();
312 331
  332 + }
313 }; 333 };
@@ -36,7 +36,7 @@ @@ -36,7 +36,7 @@
36 <div class="brands-logo clearfix"> 36 <div class="brands-logo clearfix">
37 {{#each logos}} 37 {{#each logos}}
38 <a href="{{url}}" title="{{name}}" target="_blank"> 38 <a href="{{url}}" title="{{name}}" target="_blank">
39 - <img class="lazy" data-original="{{image2 src}}"> 39 + <img class="lazy" src="{{image2 src w=136 h=57}}">
40 </a> 40 </a>
41 {{/each}} 41 {{/each}}
42 </div> 42 </div>
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 const headerModel = require('../../../doraemon/models/simple-header'); 8 const headerModel = require('../../../doraemon/models/simple-header');
9 const ticketService = require('../models/ticket-service'); 9 const ticketService = require('../models/ticket-service');
10 const _ = require('lodash'); 10 const _ = require('lodash');
  11 +const helpers = global.yoho.helpers;
11 12
12 const stepper = [ 13 const stepper = [
13 { name: '填写订单', focus: true }, 14 { name: '填写订单', focus: true },
@@ -16,14 +17,19 @@ const stepper = [ @@ -16,14 +17,19 @@ const stepper = [
16 17
17 const ticketEnsure = (req, res, next) => { 18 const ticketEnsure = (req, res, next) => {
18 let uid = req.user.uid; 19 let uid = req.user.uid;
19 - let sku = req.body.productSku || 0;  
20 - let buyNumber = req.body.buyNumber || 0; 20 + let sku = req.query.productSku || 0;
  21 + let buyNumber = req.query.buyNumber || 0;
  22 + let skn = req.query.productSkn || 0;
21 23
22 ticketService.addTicket(uid, sku, buyNumber).then(result => { 24 ticketService.addTicket(uid, sku, buyNumber).then(result => {
23 let header = headerModel.setSimpleHeaderData() || {}; 25 let header = headerModel.setSimpleHeaderData() || {};
24 26
25 result.stepper = stepper; 27 result.stepper = stepper;
26 28
  29 + if (result.error) {
  30 + result.productUrl = helpers.getUrlBySkc(skn);
  31 + }
  32 +
27 res.render('ticket-ensure', { 33 res.render('ticket-ensure', {
28 title: '填写订单 | ' + (res.locals.title || ''), 34 title: '填写订单 | ' + (res.locals.title || ''),
29 page: 'ticket', 35 page: 'ticket',
@@ -39,7 +45,7 @@ const ticketSubmit = (req, res, next) => { @@ -39,7 +45,7 @@ const ticketSubmit = (req, res, next) => {
39 let sku = req.body.sku || 0; 45 let sku = req.body.sku || 0;
40 let count = req.body.count || 0; 46 let count = req.body.count || 0;
41 let mobile = req.body.mobile || 0; 47 let mobile = req.body.mobile || 0;
42 - let yohoCoin = req.body.yohoCoin || 0; 48 + let yohoCoin = req.body.coin || 0;
43 49
44 if (!sku || !count || !mobile) { 50 if (!sku || !count || !mobile) {
45 return res.json({ 51 return res.json({
@@ -17,7 +17,8 @@ const PROMOTION_TYPE_TAG_MAP = { @@ -17,7 +17,8 @@ const PROMOTION_TYPE_TAG_MAP = {
17 Needpaygift: '加价购', 17 Needpaygift: '加价购',
18 SpecifiedAmount: '满减', // X件X元 18 SpecifiedAmount: '满减', // X件X元
19 FreeShippingCost: '免运费', 19 FreeShippingCost: '免运费',
20 - VipFreeShippingCost: '免运费' 20 + VipFreeShippingCost: '免运费',
  21 + Payment: '折扣' // apple pay
21 }; 22 };
22 23
23 const GOODS_TYPE_TAG_MAP = { 24 const GOODS_TYPE_TAG_MAP = {
@@ -26,9 +26,13 @@ const addTicket = co(function * (uid, sku, count, yohoCoin) { @@ -26,9 +26,13 @@ const addTicket = co(function * (uid, sku, count, yohoCoin) {
26 let result = {}; 26 let result = {};
27 27
28 if (ticketInfo.code !== 200) { 28 if (ticketInfo.code !== 200) {
29 - return result; 29 + return {
  30 + last_order_amount: 0,
  31 + error: ticketInfo.message
  32 + };
30 } 33 }
31 34
  35 + result.virtualGood = true;
32 result.goodsList = _handleGoodsList(_.get(ticketInfo, 'data.goods_list', [])); 36 result.goodsList = _handleGoodsList(_.get(ticketInfo, 'data.goods_list', []));
33 result.last_order_amount = _handleAmount(ticketInfo); 37 result.last_order_amount = _handleAmount(ticketInfo);
34 Object.assign(result, _handleUseYhoCoin(_.get(ticketInfo, 'data.shopping_cart_data', {}))); 38 Object.assign(result, _handleUseYhoCoin(_.get(ticketInfo, 'data.shopping_cart_data', {})));
@@ -37,7 +37,7 @@ router.get('/easypay', auth, easypay.index); // 限购商品快捷结算页 @@ -37,7 +37,7 @@ router.get('/easypay', auth, easypay.index); // 限购商品快捷结算页
37 router.post('/easypay/compute', auth, easypay.compute); // 价格重新计算 37 router.post('/easypay/compute', auth, easypay.compute); // 价格重新计算
38 router.post('/easypay/submit', auth, easypay.submit); // 限购商品订单提交 38 router.post('/easypay/submit', auth, easypay.submit); // 限购商品订单提交
39 39
40 -router.post('/ticketEnsure', auth, ticket.ticketEnsure); 40 +router.get('/ticketEnsure', auth, ticket.ticketEnsure);
41 router.post('/ticketSubmit', auth, ticket.ticketSubmit); 41 router.post('/ticketSubmit', auth, ticket.ticketSubmit);
42 router.post('/ticketCompute', auth, ticket.ticketCompute); 42 router.post('/ticketCompute', auth, ticket.ticketCompute);
43 43
@@ -32,7 +32,7 @@ @@ -32,7 +32,7 @@
32 <tr> 32 <tr>
33 <th width="3%"></th> 33 <th width="3%"></th>
34 <th class="aline-left" width="46%">商品信息</th> 34 <th class="aline-left" width="46%">商品信息</th>
35 - <th>颜色/尺码</th> 35 + <th>时间</th>
36 <th width="18%">单价</th> 36 <th width="18%">单价</th>
37 <th width="6%">数量</th> 37 <th width="6%">数量</th>
38 <th width="3%"></th> 38 <th width="3%"></th>
@@ -44,16 +44,18 @@ @@ -44,16 +44,18 @@
44 data-price="{{last_price}}" data-num="{{buy_number}}"> 44 data-price="{{last_price}}" data-num="{{buy_number}}">
45 <td{{#if @first}} class="border-top"{{/if}}></td> 45 <td{{#if @first}} class="border-top"{{/if}}></td>
46 <td class="border-top aline-left"> 46 <td class="border-top aline-left">
47 - <a class="image" href="{{linkToGoods}}">  
48 - <img src="{{image2 goods_images w=64 h=85}}" class="thumb">  
49 - <p class="name"> 47 + <a class="image ticket-cover" href="{{linkToGoods}}">
  48 + <span class="ticket-image">
  49 + <img src="{{image2 goods_images w=64 h=85}}" class="thumb">
  50 + <span class="ticket-image-tag">虚拟商品</span>
  51 + </span>
  52 + <p class="ticket-name">
50 {{product_name}} 53 {{product_name}}
51 </p> 54 </p>
52 </a> 55 </a>
53 </td> 56 </td>
54 <td class="border-top color-size"> 57 <td class="border-top color-size">
55 - 颜色:<span class="color">{{color_name}}</span>  
56 - 尺码:<span class="size">{{size_name}}</span> 58 + <span>{{color_name}}</span>
57 </td> 59 </td>
58 <td class="border-top price"> 60 <td class="border-top price">
59 <p class="red">¥ {{round productPrice 2}}</p> 61 <p class="red">¥ {{round productPrice 2}}</p>
@@ -103,5 +105,12 @@ @@ -103,5 +105,12 @@
103 应付金额:<span id="order-price" class="price">¥ {{round last_order_amount 2}}</span> 105 应付金额:<span id="order-price" class="price">¥ {{round last_order_amount 2}}</span>
104 <button id="order-submit">提交订单</button> 106 <button id="order-submit">提交订单</button>
105 </div> 107 </div>
  108 +
  109 + {{#if error}}
  110 + <div class="error hide">
  111 + <span class="info">{{error}}</span>
  112 + <span class="url">{{productUrl}}</span>
  113 + </div>
  114 + {{/if}}
106 {{/ content}} 115 {{/ content}}
107 </div> 116 </div>
@@ -12,36 +12,14 @@ const helpers = global.yoho.helpers; @@ -12,36 +12,14 @@ const helpers = global.yoho.helpers;
12 exports.QRcode = (req, res, next) => { 12 exports.QRcode = (req, res, next) => {
13 let id = req.query.orderCode || 0; 13 let id = req.query.orderCode || 0;
14 14
15 - let bg = {  
16 - '16-1': '//img13.static.yhbimg.com/yhb-img02/2016/08/04/14/02004edaf02b52363c27cea0e2cbbe9b59.jpg',  
17 - '17-1': '//img12.static.yhbimg.com/yhb-img02/2016/08/04/14/023d0470ffc2b0efe89bfdd1c6b73ab894.jpg',  
18 - '16-2': '//img12.static.yhbimg.com/yhb-img02/2016/08/04/14/02fcb3d6cdd6be244c836c520a0d034fed.jpg',  
19 - '17-2': '//img12.static.yhbimg.com/yhb-img02/2016/08/04/14/02ed77b564211c3246ab7be81794ed17cd.jpg'  
20 - };  
21 -  
22 - let bgkey = '16-1', ticktypeName = '展览票';  
23 -  
24 QRcodeModel.getQRcodeData(id, req.user.uid).then((result)=>{ 15 QRcodeModel.getQRcodeData(id, req.user.uid).then((result)=>{
25 - if (result) {  
26 - result.ticks = result.ticks.map(item=>{  
27 - if (+item.ticket_type === 2) {  
28 - item.isgroup = true;  
29 - }  
30 - return item;  
31 - });  
32 - if (result.ticks.length) {  
33 - bgkey = [/月(\d+)/g.exec(result.ticks[0].entrance_time)[1], result.ticks[0].ticket_type].join('-');  
34 - ticktypeName = result.ticks[0].ticket_type === '2' ? '套票' : '展览票';  
35 - }  
36 - }  
37 -  
38 let vm = { 16 let vm = {
39 path: [{href: helpers.urlFormat('/'), name: 'YOHO!BUY 有货首页'}, 17 path: [{href: helpers.urlFormat('/'), name: 'YOHO!BUY 有货首页'},
40 {name: '个人中心'}, {name: '订单中心'}, {name: '查看二维码'}], 18 {name: '个人中心'}, {name: '订单中心'}, {name: '查看二维码'}],
41 qrcodeData: result, 19 qrcodeData: result,
  20 + onlyOne: result.ticks.length === 1,
42 code: id, 21 code: id,
43 - bgsrc: bg[bgkey],  
44 - ticktypeName: ticktypeName, 22 + ticktypeName: result.title,
45 returnOrder: helpers.urlFormat('/home/orders') 23 returnOrder: helpers.urlFormat('/home/orders')
46 }; 24 };
47 25
@@ -31,7 +31,7 @@ const _homeNav = (switcher) => { @@ -31,7 +31,7 @@ const _homeNav = (switcher) => {
31 {name: '我的评论', href: '/home/comment'}, 31 {name: '我的评论', href: '/home/comment'},
32 32
33 // {name: '我的投诉', href: '/home/complaints'}, 33 // {name: '我的投诉', href: '/home/complaints'},
34 - {name: '我的推广', href: '/home/spread'}, 34 + {name: '我的邀请好友', href: '/home/spread'},
35 {name: '我的信息', href: '/home/message', count: 0}, 35 {name: '我的信息', href: '/home/message', count: 0},
36 { 36 {
37 name: '在线客服', 37 name: '在线客服',
@@ -225,7 +225,7 @@ const _getGoodsTag = (attribute, goodsType) => { @@ -225,7 +225,7 @@ const _getGoodsTag = (attribute, goodsType) => {
225 225
226 // 电子 226 // 电子
227 case 'ticket': 227 case 'ticket':
228 - goodsTagName = ''; 228 + goodsTagName = 'virtualGood';
229 break; 229 break;
230 default: 230 default:
231 break; 231 break;
@@ -235,6 +235,7 @@ const _getGoodsTag = (attribute, goodsType) => { @@ -235,6 +235,7 @@ const _getGoodsTag = (attribute, goodsType) => {
235 if (attribute === 3) { 235 if (attribute === 3) {
236 goodsTagName = 'virtualGood'; 236 goodsTagName = 'virtualGood';
237 } 237 }
  238 +
238 return goodsTagName; 239 return goodsTagName;
239 }; 240 };
240 241
@@ -737,13 +738,13 @@ const _getOrderDetail = co(function * (uid, orderId) { @@ -737,13 +738,13 @@ const _getOrderDetail = co(function * (uid, orderId) {
737 738
738 // 虚拟商品 739 // 虚拟商品
739 if (+orderDetail.attribute === 3) { 740 if (+orderDetail.attribute === 3) {
740 - detail.virtualGoods = true; 741 + detail.virtualGood = true;
741 detail.virtualPayMode = { 742 detail.virtualPayMode = {
742 payMode: ChannelConfig.payType[orderDetail.payment_type], 743 payMode: ChannelConfig.payType[orderDetail.payment_type],
743 phone: _.fill(orderDetail.mobile.split(''), '*', 3, 4).join('') 744 phone: _.fill(orderDetail.mobile.split(''), '*', 3, 4).join('')
744 }; 745 };
745 } else { 746 } else {
746 - detail.virtualGoods = false; 747 + detail.virtualGood = false;
747 detail.noramlPayMode = { 748 detail.noramlPayMode = {
748 payMode: ChannelConfig.payType[orderDetail.payment_type], 749 payMode: ChannelConfig.payType[orderDetail.payment_type],
749 payWay: orderDetail.payment_name, 750 payWay: orderDetail.payment_name,
@@ -798,7 +799,7 @@ const _getOrderDetail = co(function * (uid, orderId) { @@ -798,7 +799,7 @@ const _getOrderDetail = co(function * (uid, orderId) {
798 num: good.buy_number, 799 num: good.buy_number,
799 sum: good.goods_amount, 800 sum: good.goods_amount,
800 sku: good.product_sku, 801 sku: good.product_sku,
801 - [_getGoodsTag(+good.attribute, good.goods_type)]: true 802 + [_getGoodsTag(+orderDetail.attribute, good.goods_type)]: true
802 }; 803 };
803 804
804 // 划线的价格 805 // 划线的价格
@@ -218,6 +218,7 @@ const getOrderRefund = (orderCode, uid) => { @@ -218,6 +218,7 @@ const getOrderRefund = (orderCode, uid) => {
218 218
219 // tar note 为每个特殊商品都添加标识 219 // tar note 为每个特殊商品都添加标识
220 if (value.is_limit_skn === 'Y') { 220 if (value.is_limit_skn === 'Y') {
  221 + item.isLimitSkn = true;
221 item.specialNoticeBo = { 222 item.specialNoticeBo = {
222 title: _.get(result, 'data.special_notice.title', ''), 223 title: _.get(result, 'data.special_notice.title', ''),
223 remark1: remarks[0] || '', 224 remark1: remarks[0] || '',
@@ -568,6 +569,7 @@ const getOrderExchange = (orderCode, uid) => { @@ -568,6 +569,7 @@ const getOrderExchange = (orderCode, uid) => {
568 569
569 // tar note 为每个特殊商品都添加标识 570 // tar note 为每个特殊商品都添加标识
570 if (value.is_limit_skn === 'Y') { 571 if (value.is_limit_skn === 'Y') {
  572 + item.isLimitSkn = true;
571 item.specialNoticeBo = { 573 item.specialNoticeBo = {
572 title: _.get(result, 'data.specialNoticeBo.title', ''), 574 title: _.get(result, 'data.specialNoticeBo.title', ''),
573 remark1: remarks[0] || '', 575 remark1: remarks[0] || '',
@@ -31,6 +31,8 @@ module.exports = class extends global.yoho.BaseModel { @@ -31,6 +31,8 @@ module.exports = class extends global.yoho.BaseModel {
31 if (resList.code === 200) { 31 if (resList.code === 200) {
32 let list = _.get(resList, 'data.data', []); 32 let list = _.get(resList, 'data.data', []);
33 33
  34 + resData.rules = _.get(resList, 'data.activityRuleDesc', '');
  35 +
34 if (!_.isEmpty(list)) { 36 if (!_.isEmpty(list)) {
35 resData.list = list; 37 resData.list = list;
36 } 38 }
@@ -6,16 +6,16 @@ @@ -6,16 +6,16 @@
6 <h2 class="title"> 6 <h2 class="title">
7 </h2> 7 </h2>
8 <div class='subtitle'> 8 <div class='subtitle'>
9 - <h2>虚拟商品 <span class='pad20'>2016 YO'HOOD</span> {{ticktypeName}} <i id="qrid"></i></h2> 9 + <h2>虚拟商品 <span class='pad20'>{{ticktypeName}}</span><i id="qrid"></i></h2>
10 <a class='r-go' href="{{returnOrder}}">返回我的订单</a> 10 <a class='r-go' href="{{returnOrder}}">返回我的订单</a>
11 </div> 11 </div>
12 {{#qrcodeData}} 12 {{#qrcodeData}}
13 <div class='qrcmain'> 13 <div class='qrcmain'>
14 <div class="qrcmain-switch"> 14 <div class="qrcmain-switch">
15 - <a class="prev gray" href="javascript:;"> 15 + <a class="prev gray {{#if ../onlyOne}}hide{{/if}}" href="javascript:;">
16 <span class="iconfont">&#xe60e;</span> 16 <span class="iconfont">&#xe60e;</span>
17 </a> 17 </a>
18 - <a class="next" href="javascript:;"> 18 + <a class="next {{#if ../onlyOne}}hide{{/if}}" href="javascript:;">
19 <span class="iconfont">&#xe60c;</span> 19 <span class="iconfont">&#xe60c;</span>
20 </a> 20 </a>
21 </div> 21 </div>
@@ -27,9 +27,6 @@ @@ -27,9 +27,6 @@
27 <div class='center'> 27 <div class='center'>
28 <img src='{{image2 qr_image}}'> 28 <img src='{{image2 qr_image}}'>
29 <p class='bianhao'><label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;号:</label><i>{{ticket_code}}</i></p> 29 <p class='bianhao'><label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;号:</label><i>{{ticket_code}}</i></p>
30 - {{#if isgroup}}  
31 - <p class='zuoweihao'><label>&nbsp;&nbsp;&nbsp;&nbsp;号:</label>{{seat_no}}</p>  
32 - {{/if}}  
33 <p><label>进场时间:</label>{{entrance_time}}</p> 30 <p><label>进场时间:</label>{{entrance_time}}</p>
34 </div> 31 </div>
35 </li> 32 </li>
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 {{!--防诈骗提示--}} 10 {{!--防诈骗提示--}}
11 {{> swindle-info}} 11 {{> swindle-info}}
12 12
13 - <div class="detail-info{{#if virtualGoods}} virtual-detail{{/if}} {{#if offlineBySelf}}offline-self{{/if}}"> 13 + <div class="detail-info{{#if virtualGood}} virtual-detail{{/if}} {{#if offlineBySelf}}offline-self{{/if}}">
14 <div class="status"> 14 <div class="status">
15 <p> 15 <p>
16 订单编号: 16 订单编号:
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 {{#if operation.goPay}} 21 {{#if operation.goPay}}
22 <a class="go-pay oo-btn" href="{{operation.goPay}}">立即付款</a> 22 <a class="go-pay oo-btn" href="{{operation.goPay}}">立即付款</a>
23 {{/if}} 23 {{/if}}
24 - {{#unless virtualGoods}} 24 + {{#unless virtualGood}}
25 <!--虚拟商品--> 25 <!--虚拟商品-->
26 {{#if changeable}} 26 {{#if changeable}}
27 <span class="edit-order oo-btn">修改地址</span> 27 <span class="edit-order oo-btn">修改地址</span>
@@ -165,6 +165,8 @@ @@ -165,6 +165,8 @@
165 </p> 165 </p>
166 <div class="content"> 166 <div class="content">
167 <span>付款方式:{{payMode}}</span> 167 <span>付款方式:{{payMode}}</span>
  168 + <br />
  169 + <br />
168 <span>电话号码:{{phone}}</span> 170 <span>电话号码:{{phone}}</span>
169 </div> 171 </div>
170 </div> 172 </div>
@@ -236,13 +238,10 @@ @@ -236,13 +238,10 @@
236 </a> 238 </a>
237 <p class="name-color-size"> 239 <p class="name-color-size">
238 <a class="name" href="{{url}}" target="_blank">{{name}}</a> 240 <a class="name" href="{{url}}" target="_blank">{{name}}</a>
239 - {{#if virtualGood}} 241 + {{#if ../virtualGood}}
240 {{#if color}} 242 {{#if color}}
241 日期:{{color}} 243 日期:{{color}}
242 {{/if}} 244 {{/if}}
243 - {{#if size}}  
244 - 区域:{{size}}  
245 - {{/if}}  
246 {{else}} 245 {{else}}
247 {{#if color}} 246 {{#if color}}
248 <b title="{{color}}">颜色:{{color}}</b> 247 <b title="{{color}}">颜色:{{color}}</b>
@@ -35,7 +35,7 @@ @@ -35,7 +35,7 @@
35 <input type="hidden" value="{{sku}}" name="sku"> 35 <input type="hidden" value="{{sku}}" name="sku">
36 <input type="hidden" value="{{price}}" name="price"> 36 <input type="hidden" value="{{price}}" name="price">
37 <input type="hidden" value="{{goods_type_id}}" name="typeid"> 37 <input type="hidden" value="{{goods_type_id}}" name="typeid">
38 - <input type="checkbox" checked="true"> 38 + {{#unless isLimitSkn}}<input type="checkbox" checked="true">{{/unless}}
39 {{/unless}} 39 {{/unless}}
40 </td> 40 </td>
41 <td width="60"> 41 <td width="60">
@@ -89,7 +89,7 @@ @@ -89,7 +89,7 @@
89 </td> 89 </td>
90 {{^}} 90 {{^}}
91 <td class="return-reason-wrap"> 91 <td class="return-reason-wrap">
92 - <select class="return-reason"> 92 + <select class="return-reason" {{#if isLimitSkn}}disabled{{/if}}>
93 <option value="0">请选择换货原因</option> 93 <option value="0">请选择换货原因</option>
94 {{# reason}} 94 {{# reason}}
95 <option value="{{id}}" {{#if inactive}}disabled{{/if}}>{{name}}</option> 95 <option value="{{id}}" {{#if inactive}}disabled{{/if}}>{{name}}</option>
@@ -235,7 +235,7 @@ @@ -235,7 +235,7 @@
235 {{#if banMsg}} 235 {{#if banMsg}}
236 <label>{{banMsg}}</label> 236 <label>{{banMsg}}</label>
237 {{^}} 237 {{^}}
238 - <select class="return-reason"> 238 + <select class="return-reason" {{#if isLimitSkn}}disabled{{/if}}>
239 <option value="0">请选择退货原因</option> 239 <option value="0">请选择退货原因</option>
240 {{# reason}} 240 {{# reason}}
241 <option value="{{id}}">{{name}}</option> 241 <option value="{{id}}">{{name}}</option>
@@ -7,21 +7,21 @@ @@ -7,21 +7,21 @@
7 {{# spread}} 7 {{# spread}}
8 <div class="spread-wrap clearfix"> 8 <div class="spread-wrap clearfix">
9 <div class="item-card"> 9 <div class="item-card">
10 - <span class="tag">邀请二维码</span> 10 + <span class="tag">方法一:扫描邀请二维码</span>
11 <div class="card-main"> 11 <div class="card-main">
12 <div class="spread-code" data-url="{{url}}"></div> 12 <div class="spread-code" data-url="{{url}}"></div>
13 </div> 13 </div>
14 <p>{{{activityDescribe}}}</p> 14 <p>{{{activityDescribe}}}</p>
15 </div> 15 </div>
16 <div class="item-card"> 16 <div class="item-card">
17 - <span class="tag">邀请码</span> 17 + <span class="tag">方法二:使用邀请码</span>
18 <div class="card-main"> 18 <div class="card-main">
19 <p class="spread-id">{{inviteCode}}</p> 19 <p class="spread-id">{{inviteCode}}</p>
20 </div> 20 </div>
21 <p>1.复制您的邀请码<br>2.粘贴给您的朋友</p> 21 <p>1.复制您的邀请码<br>2.粘贴给您的朋友</p>
22 </div> 22 </div>
23 <div class="item-card"> 23 <div class="item-card">
24 - <span class="tag">邀请链接</span> 24 + <span class="tag">方法三:使用邀请链接</span>
25 <div class="card-main"> 25 <div class="card-main">
26 <div class="spread-url"> 26 <div class="spread-url">
27 <input type="text" value="{{url}}" class 27 <input type="text" value="{{url}}" class
@@ -32,6 +32,10 @@ @@ -32,6 +32,10 @@
32 <p>1.复制您的邀请链接<br>2.选择您的社交平台<br>3.粘贴给您的朋友</p> 32 <p>1.复制您的邀请链接<br>2.选择您的社交平台<br>3.粘贴给您的朋友</p>
33 </div> 33 </div>
34 </div> 34 </div>
  35 + <div class="spread-wrap clearfix spread-rules">
  36 + <h2>活动细则</h2>
  37 + <p>{{{rules}}}</p>
  38 + </div>
35 <div class="my-spread-list"> 39 <div class="my-spread-list">
36 <table> 40 <table>
37 <thead> 41 <thead>
@@ -39,7 +43,6 @@ @@ -39,7 +43,6 @@
39 <th>我邀请的好友</th> 43 <th>我邀请的好友</th>
40 <th>注册时间</th> 44 <th>注册时间</th>
41 <th>首单购物金额</th> 45 <th>首单购物金额</th>
42 - <th>订单状态</th>  
43 <th>我的奖励</th> 46 <th>我的奖励</th>
44 <th>奖励状态</th> 47 <th>奖励状态</th>
45 <th>发放时间</th> 48 <th>发放时间</th>
@@ -51,9 +54,15 @@ @@ -51,9 +54,15 @@
51 <td>{{nickName}}</td> 54 <td>{{nickName}}</td>
52 <td>{{registerTimeDis}}</td> 55 <td>{{registerTimeDis}}</td>
53 <td>{{orderAmountDis}}</td> 56 <td>{{orderAmountDis}}</td>
54 - <td>{{paymentStatusDesc}}</td>  
55 <td>{{couponName}}</td> 57 <td>{{couponName}}</td>
56 - <td>{{couponStatusDesc}}</td> 58 + <td class="coupon-status">{{couponStatusDesc}}
  59 + {{#if paymentStatusDesc}}
  60 + <i class="help-icon"></i>
  61 + <div class="coin-tip-help">
  62 + <p>{{paymentStatusDesc}}</p>
  63 + </div>
  64 + {{/if}}
  65 + </td>
57 <td>{{couponSendTimeDis}}</td> 66 <td>{{couponSendTimeDis}}</td>
58 </tr> 67 </tr>
59 {{/ list}} 68 {{/ list}}
@@ -41,9 +41,6 @@ @@ -41,9 +41,6 @@
41 {{#if color}} 41 {{#if color}}
42 日期:{{color}}&nbsp;&nbsp; 42 日期:{{color}}&nbsp;&nbsp;
43 {{/if}} 43 {{/if}}
44 - {{#if size}}  
45 - 区域:{{size}}  
46 - {{/if}}  
47 {{else}} 44 {{else}}
48 {{#if color}} 45 {{#if color}}
49 <b title="{{color}}">颜色:{{color}}&nbsp;&nbsp;</b> 46 <b title="{{color}}">颜色:{{color}}&nbsp;&nbsp;</b>
@@ -9,4 +9,4 @@ @@ -9,4 +9,4 @@
9 {{/if}} 9 {{/if}}
10 {{#if preSaleGood}} 10 {{#if preSaleGood}}
11 <span class="presall-tag">预售</span> 11 <span class="presall-tag">预售</span>
12 -{{/if}}  
  12 +{{/if}}
@@ -38,7 +38,7 @@ @@ -38,7 +38,7 @@
38 </li> 38 </li>
39 39
40 <li class="clearfix" data-index="3"> 40 <li class="clearfix" data-index="3">
41 - <input id="invite-code" class="input invite-code" name="inviteCode" placeholder="邀请码" autocomplete="off" maxlength="20" type="text"> 41 + <input id="invite-code" class="input invite-code" name="inviteCode" placeholder="邀请码(非必填)" autocomplete="off" maxlength="20" type="text">
42 </li> 42 </li>
43 43
44 <li class="items-container clearfix"> 44 <li class="items-container clearfix">
@@ -200,6 +200,35 @@ const keyword = (req, res, next) => { @@ -200,6 +200,35 @@ const keyword = (req, res, next) => {
200 }).catch(next); 200 }).catch(next);
201 }; 201 };
202 202
  203 +/**
  204 + * 搜索推荐列表页
  205 + * @param {[type]} req [description]
  206 + * @param {[type]} res [description]
  207 + * @return {[type]} [description]
  208 + */
  209 +const keyId = (req, res, next) => {
  210 + let params = req.query;
  211 + let id = req.params.id;
  212 +
  213 + return search.getSearchKeywordDataById(id, params, req.yoho.channel).then(result => {
  214 + let query = result.queryKey;
  215 +
  216 + Object.assign(result, {
  217 + pageNoFollow: true,
  218 + title: `${query}价格_图片_品牌_怎么样-YOHO!BUY有货`,
  219 + keywords: `${query},${query}价格,${query}图片,${query}怎么样,${query}品牌,YOHO!BUY有货`,
  220 + description: `YOHO!BUY有货网yohobuy.com是国内专业的${query}网上潮流购物商城,为您找到${_.get(result,
  221 + 'search.totalCount', 0)}${query}、产品的详细参数,实时报价,价格行情,图片、评价、品牌等信息。买${query},就上YOHO!BUY有货`
  222 + });
  223 +
  224 + if (!_.get(result, 'search.goods') || !_.get(result, 'search.goods').length) {
  225 + _.set(result, 'search.keyWord', query);
  226 + return res.render('search/no-result', result);
  227 + }
  228 + res.render('search/index', result);
  229 + }).catch(next);
  230 +};
  231 +
203 module.exports = { 232 module.exports = {
204 index, 233 index,
205 suggest, 234 suggest,
@@ -207,6 +236,7 @@ module.exports = { @@ -207,6 +236,7 @@ module.exports = {
207 searchFilterBrands, 236 searchFilterBrands,
208 searchHistory, // 搜索历史记录 237 searchHistory, // 搜索历史记录
209 searchLessRecommend, 238 searchLessRecommend,
210 - keyword 239 + keyword,
  240 + keyId
211 }; 241 };
212 242
@@ -737,7 +737,7 @@ exports.handleFilterData = (origin, params, total) => { @@ -737,7 +737,7 @@ exports.handleFilterData = (origin, params, total) => {
737 }]; 737 }];
738 738
739 // 尺码处理 739 // 尺码处理
740 - if (!_.isEmpty(origin.size) && ((params.msort && !_.includes(params.msort, ',')) || params.misort || params.sort)) { 740 + if (!_.isEmpty(origin.size) && params.category_id) {
741 741
742 dest.size = []; 742 dest.size = [];
743 743
@@ -1788,7 +1788,11 @@ exports.handleSuggestData = (origin, query) => { @@ -1788,7 +1788,11 @@ exports.handleSuggestData = (origin, query) => {
1788 }); 1788 });
1789 }); 1789 });
1790 1790
1791 - leftContent.allSuggest = {all: all, list: list}; 1791 + leftContent.allSuggest = {
  1792 + all: all,
  1793 + title: '相关推荐',
  1794 + list: list
  1795 + };
1792 1796
1793 return leftContent; 1797 return leftContent;
1794 }; 1798 };
@@ -10,6 +10,7 @@ const api = global.yoho.API; @@ -10,6 +10,7 @@ const api = global.yoho.API;
10 const Promise = require('bluebird'); 10 const Promise = require('bluebird');
11 const co = Promise.coroutine; 11 const co = Promise.coroutine;
12 const helpers = global.yoho.helpers; 12 const helpers = global.yoho.helpers;
  13 +const redis = global.yoho.redis;
13 const saleApi = require('./sale-api'); 14 const saleApi = require('./sale-api');
14 const searchApi = require('./search-api'); 15 const searchApi = require('./search-api');
15 const headerModel = require('../../../doraemon/models/header'); 16 const headerModel = require('../../../doraemon/models/header');
@@ -401,3 +402,50 @@ exports.getSearchKeywordData = (params, channel) => { @@ -401,3 +402,50 @@ exports.getSearchKeywordData = (params, channel) => {
401 return setSearchKeywordData(result, params, channel); 402 return setSearchKeywordData(result, params, channel);
402 }); 403 });
403 }; 404 };
  405 +
  406 +/**
  407 + * 获取搜索建议数据
  408 + * @id {[number]} origin [description]
  409 + * @param {[object]} origin [description]
  410 + * @channel {[string]} origin [description]
  411 + * @return {[object]} [description]
  412 + */
  413 +exports.getSearchKeywordDataById = (id, params, channel) => {
  414 + let that = this;
  415 +
  416 + return co(function * () {
  417 + let redisData = yield redis.all([
  418 + ['get', `golobal:yoho:seo:keywords:id:${id}`]
  419 + ]);
  420 +
  421 + if (!redisData[0]) {
  422 + return Promise.reject('get redis canpin keywords by id error!' +
  423 + `key: golobal:yoho:seo:keywords:id:${id} value: ${redisData[0]}`);
  424 + }
  425 +
  426 + redisData = JSON.parse(redisData[0]);
  427 +
  428 + params.query = redisData.name;
  429 +
  430 + let resData = yield that.getSearchKeywordData(params, channel);
  431 +
  432 + resData.queryKey = params.query;
  433 +
  434 + if (!_.isEmpty(redisData.data)) {
  435 + _.forEach(redisData.data, value => {
  436 + if (!value) {
  437 + return;
  438 + }
  439 +
  440 + Object.assign(value, {
  441 + name: value.keyword,
  442 + href: helpers.urlFormat(`/chanpin/${value.id}.html`, null, 'www')
  443 + });
  444 + });
  445 +
  446 + _.set(resData, 'search.leftContent.allSuggest.list', redisData.data);
  447 + }
  448 +
  449 + return resData;
  450 + })();
  451 +};
@@ -103,6 +103,7 @@ router.get('/api/suggest', search.suggest4Old); @@ -103,6 +103,7 @@ router.get('/api/suggest', search.suggest4Old);
103 router.get('/search/history', search.searchHistory); // 搜索历史提示 103 router.get('/search/history', search.searchHistory); // 搜索历史提示
104 router.get('/search/less/recommend', search.searchLessRecommend);// 搜索少或无 有可能喜欢 104 router.get('/search/less/recommend', search.searchLessRecommend);// 搜索少或无 有可能喜欢
105 router.get('/search/keyword/:id', search.keyword); 105 router.get('/search/keyword/:id', search.keyword);
  106 +router.get('/search/chanpin/:id', search.keyId);
106 107
107 // 商品分类列表页 108 // 商品分类列表页
108 router.get('/list/index', gbk2utf, list.index); 109 router.get('/list/index', gbk2utf, list.index);
@@ -131,9 +131,7 @@ @@ -131,9 +131,7 @@
131 {{#if virtualGoods}} 131 {{#if virtualGoods}}
132 {{!-- 电子门票按钮 --}} 132 {{!-- 电子门票按钮 --}}
133 {{#if isVirtualBtn}} 133 {{#if isVirtualBtn}}
134 - <form name="ticket-form" action="{{buyNowBase}}" method="POST"  
135 - class="hide"></form>  
136 - <span id="buy-ticket" class="buy-ticket buy-now item-buy{{#if dis}} dis{{/if}}">立即购买</span> 134 + <span id="buy-ticket" class="buy-ticket buy-now item-buy{{#if dis}} dis{{/if}}" data-base="{{buyNowBase}}">立即购买</span>
137 {{/if}} 135 {{/if}}
138 {{else}} 136 {{else}}
139 {{!-- 各颜色下所有尺码均售罄则只显示售罄按钮 --}} 137 {{!-- 各颜色下所有尺码均售罄则只显示售罄按钮 --}}
@@ -10,7 +10,10 @@ @@ -10,7 +10,10 @@
10 10
11 <span class="bundle {{#if_cond bundle.type "!=" 2}}hide{{/if_cond}}"> 11 <span class="bundle {{#if_cond bundle.type "!=" 2}}hide{{/if_cond}}">
12 {{bundle.count}}件起购{{#if bundle.discount}}{{bundle.discount}}折优惠{{/if}} 12 {{bundle.count}}件起购{{#if bundle.discount}}{{bundle.discount}}折优惠{{/if}}
  13 +</span>
13 14
  15 +<span class="bundle {{#unless isTicket}}hide{{/unless}}" >
  16 + 限购4件
14 </span> 17 </span>
15 18
16 <span class="few-sold hide"> 19 <span class="few-sold hide">
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 </ul> 10 </ul>
11 </div> 11 </div>
12 12
13 -<div class="chose-size row clearfix {{#unless isTicket}} hide {{/unless}}"> 13 +<div class="chose-size row clearfix hide">
14 <input type="hidden" name="isTicket" value="{{isTicket}}"/> 14 <input type="hidden" name="isTicket" value="{{isTicket}}"/>
15 <span class="title pull-left"> 15 <span class="title pull-left">
16 选区域: 16 选区域:
@@ -17,12 +17,12 @@ module.exports = { @@ -17,12 +17,12 @@ module.exports = {
17 cookieDomain: '.yohobuy.com', 17 cookieDomain: '.yohobuy.com',
18 domains: { 18 domains: {
19 // test3 19 // test3
20 - // singleApi: 'http://api-test3.yohops.com:9999/',  
21 - // api: 'http://api-test3.yohops.com:9999/',  
22 - // service: 'http://service-test3.yohops.com:9999/',  
23 - // serviceNotify: 'http://service-test3.yohops.com:9999/',  
24 - // global: 'http://global-test-soa.yohops.com:9999/',  
25 - // platformApi: 'http://192.168.102.48:8088/', 20 + singleApi: 'http://api-test3.yohops.com:9999/',
  21 + api: 'http://api-test3.yohops.com:9999/',
  22 + service: 'http://service-test3.yohops.com:9999/',
  23 + serviceNotify: 'http://service-test3.yohops.com:9999/',
  24 + global: 'http://global-test-soa.yohops.com:9999/',
  25 + platformApi: 'http://192.168.102.48:8088/',
26 26
27 // test2 27 // test2
28 // singleApi: 'http://api-test2.yohops.com:9999/', 28 // singleApi: 'http://api-test2.yohops.com:9999/',
@@ -47,11 +47,11 @@ module.exports = { @@ -47,11 +47,11 @@ module.exports = {
47 // platformApi: 'http://172.16.6.210:8088/', 47 // platformApi: 'http://172.16.6.210:8088/',
48 48
49 // dev 49 // dev
50 - api: 'http://dev-api.yohops.com:9999/',  
51 - service: 'http://dev-service.yohops.com:9999/',  
52 - serviceNotify: 'http://dev-service.yohops.com:9999/',  
53 - singleApi: 'http://dev-api.yohops.com:9999/',  
54 - platformApi: 'http://192.168.102.48:8088/', 50 + // api: 'http://dev-api.yohops.com:9999/',
  51 + // service: 'http://dev-service.yohops.com:9999/',
  52 + // serviceNotify: 'http://dev-service.yohops.com:9999/',
  53 + // singleApi: 'http://dev-api.yohops.com:9999/',
  54 + // platformApi: 'http://192.168.102.48:8088/',,
55 55
56 imSocket: 'ws://socket.yohobuy.com:10240', 56 imSocket: 'ws://socket.yohobuy.com:10240',
57 imCs: 'http://im.yohobuy.com/api', 57 imCs: 'http://im.yohobuy.com/api',
@@ -77,6 +77,13 @@ module.exports = [ @@ -77,6 +77,13 @@ module.exports = [
77 target: (req, match, p1) => `/product/search/keyword/${p1}` 77 target: (req, match, p1) => `/product/search/keyword/${p1}`
78 }, 78 },
79 79
  80 + // 推荐词id列表页
  81 + {
  82 + type: TYPE.rewrite,
  83 + origin: /^\/chanpin\/(.*)\.html(.*)/,
  84 + target: (req, match, p1) => `/product/search/chanpin/${p1}`
  85 + },
  86 +
80 // erp2good 87 // erp2good
81 { 88 {
82 type: TYPE.rewrite, 89 type: TYPE.rewrite,
  1 +
  2 +const _ = require('lodash');
1 const redis = require('redis'); 3 const redis = require('redis');
2 const bluebird = require('bluebird'); 4 const bluebird = require('bluebird');
3 const config = require('../../config/common'); 5 const config = require('../../config/common');
@@ -9,6 +11,18 @@ try { @@ -9,6 +11,18 @@ try {
9 bluebird.promisifyAll(redis.RedisClient.prototype); 11 bluebird.promisifyAll(redis.RedisClient.prototype);
10 bluebird.promisifyAll(redis.Multi.prototype); 12 bluebird.promisifyAll(redis.Multi.prototype);
11 13
  14 + client.all = args => {
  15 + if (!client.ready) {
  16 + if (Array.isArray(args)) {
  17 + return Promise.resolve(_.fill(args, false));
  18 + } else {
  19 + return Promise.resolve(false);
  20 + }
  21 + }
  22 +
  23 + return client.multi.call(client, args).execAsync();
  24 + };
  25 +
12 client.on('error', function() { 26 client.on('error', function() {
13 global.yoho.redis = ''; 27 global.yoho.redis = '';
14 }); 28 });
@@ -20,6 +34,4 @@ try { @@ -20,6 +34,4 @@ try {
20 global.yoho.redis = ''; 34 global.yoho.redis = '';
21 } 35 }
22 36
23 -  
24 -  
25 module.exports = client; 37 module.exports = client;
@@ -287,5 +287,6 @@ @@ -287,5 +287,6 @@
287 <div class="code-down-box"> 287 <div class="code-down-box">
288 <div class="code-img"></div> 288 <div class="code-img"></div>
289 <h5 class="code-title">下载手机客户端</h5> 289 <h5 class="code-title">下载手机客户端</h5>
  290 + <i class="iconfont icon-del"></i>
290 </div> 291 </div>
291 {{/ headerData}} 292 {{/ headerData}}
@@ -36,7 +36,7 @@ @@ -36,7 +36,7 @@
36 </div> 36 </div>
37 <div class="good-detail-img"> 37 <div class="good-detail-img">
38 <a class="good-thumb" href="{{url}}" target="_blank"> 38 <a class="good-thumb" href="{{url}}" target="_blank">
39 - <img class="lazy" data-original="{{image2 thumb w=280 h=382}}"> 39 + <img class="lazy" data-original="{{image2 thumb w=280 h=382}}">
40 </a> 40 </a>
41 {{# is_few}} 41 {{# is_few}}
42 <p class="few-tag">即将售罄</p> 42 <p class="few-tag">即将售罄</p>
@@ -89,6 +89,9 @@ @@ -89,6 +89,9 @@
89 {{!-- 搜索推荐--}} 89 {{!-- 搜索推荐--}}
90 {{# allSuggest}} 90 {{# allSuggest}}
91 <div class="sort-container"> 91 <div class="sort-container">
  92 + {{# title}}
  93 + <h2 class="nav-pic-title">{{.}}</h2>
  94 + {{/ title}}
92 <ul class="sort-child-list suggest-list"> 95 <ul class="sort-child-list suggest-list">
93 {{#each list}} 96 {{#each list}}
94 <li> 97 <li>
@@ -140,4 +143,4 @@ @@ -140,4 +143,4 @@
140 {{/each}} 143 {{/each}}
141 </ul> 144 </ul>
142 </div> 145 </div>
143 -{{/signboard}}  
  146 +{{/signboard}}
1 { 1 {
2 "name": "yohobuy-node", 2 "name": "yohobuy-node",
3 - "version": "5.8.7", 3 + "version": "5.9.0",
4 "private": true, 4 "private": true,
5 "description": "A New Yohobuy Project With Express", 5 "description": "A New Yohobuy Project With Express",
6 "repository": { 6 "repository": {

5.55 KB | W: | H:

5.85 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
@@ -17,6 +17,28 @@ var submitting = false; @@ -17,6 +17,28 @@ var submitting = false;
17 require('../common'); 17 require('../common');
18 require('../simple-header'); 18 require('../simple-header');
19 19
  20 +function errorInfo(info, url) {
  21 + new dialog.Dialog({
  22 + content: info,
  23 + className: 'ensure-back-alert',
  24 + btns: [{
  25 + id: 'back-sure',
  26 + btnClass: ['back-sure'],
  27 + name: '返回商品详情页',
  28 + cb: function() {
  29 + window.jumpUrl(url);
  30 + }
  31 + }]
  32 + }).show();
  33 +}
  34 +
  35 +if ($('.error').length === 1) {
  36 + errorInfo(
  37 + $('.error').find('.info').text(),
  38 + $('.error').find('.url').text()
  39 + );
  40 +}
  41 +
20 function validateUserInfo(info) { 42 function validateUserInfo(info) {
21 var errTip = ''; 43 var errTip = '';
22 44
@@ -24,6 +46,10 @@ function validateUserInfo(info) { @@ -24,6 +46,10 @@ function validateUserInfo(info) {
24 errTip = '您还没有填写手机号'; 46 errTip = '您还没有填写手机号';
25 } 47 }
26 48
  49 + if (!errTip && !/^\d{11}$/ig.test(info.mobile)) {
  50 + errTip = '手机号只能是11位数字';
  51 + }
  52 +
27 if (errTip) { 53 if (errTip) {
28 new dialog.Alert((errTip)).show(); 54 new dialog.Alert((errTip)).show();
29 return false; 55 return false;
@@ -987,21 +987,8 @@ function searchSuggestHistory() { @@ -987,21 +987,8 @@ function searchSuggestHistory() {
987 } 987 }
988 988
989 $(function() { 989 $(function() {
990 - var windowWidth = document.documentElement.clientWidth;  
991 -  
992 - if (windowWidth <= 1440) { 990 + $('.code-down-box').bind('click', '.icon-del', function() {
993 $('.code-down-box').hide(); 991 $('.code-down-box').hide();
994 - }  
995 -  
996 - $(window).resize(function() {  
997 - var innerWindowWidth = window.innerWidth;  
998 -  
999 - if (innerWindowWidth > 1440 && innerWindowWidth <= windowWidth) {  
1000 - $('.code-down-box').show();  
1001 -  
1002 - } else {  
1003 - $('.code-down-box').hide();  
1004 - }  
1005 }); 992 });
1006 }); 993 });
1007 994
@@ -942,13 +942,13 @@ bindEvent.add(function() { @@ -942,13 +942,13 @@ bindEvent.add(function() {
942 sku = $('.size:not(.hide) li.focus').data('sku'); 942 sku = $('.size:not(.hide) li.focus').data('sku');
943 buyNumber = getNum(); 943 buyNumber = getNum();
944 944
945 - var $ticketForm = $('form[name="ticket-form"]'); // eslint-disable-line  
946 -  
947 - $ticketForm.html(  
948 - '<input name="productSku" value="' + sku + '" />' +  
949 - '<input name="buyNumber" value="' + buyNumber + '" />'  
950 - );  
951 - $ticketForm.submit(); 945 + window.jumpUrl(
  946 + [
  947 + $(this).data('base'),
  948 + '?productSku=', sku,
  949 + '&buyNumber=', buyNumber,
  950 + '&productSkn=', skn
  951 + ].join(''));
952 }); 952 });
953 953
954 // 立即购买 954 // 立即购买
@@ -917,6 +917,38 @@ @@ -917,6 +917,38 @@
917 } 917 }
918 } 918 }
919 919
  920 + .ticket-cover {
  921 + .ticket-image {
  922 + display: inline-block;
  923 + position: relative;
  924 + }
  925 +
  926 + .ticket-image-tag {
  927 + display: block;
  928 + position: absolute;
  929 + bottom: 0;
  930 + left: 0;
  931 + right: 0;
  932 + height: 15px;
  933 + line-height: 16px;
  934 + text-align: center;
  935 + color: #fff;
  936 + background: #333;
  937 + }
  938 +
  939 + .ticket-name {
  940 + display: inline-block;
  941 + width: 280px;
  942 + max-height: 68px;
  943 + font-size: 15px;
  944 + padding-left: 20px;
  945 + line-height: 1.5;
  946 + overflow: hidden;
  947 + word-break: break-all;
  948 + vertical-align: top;
  949 + }
  950 + }
  951 +
920 .use-coupons { 952 .use-coupons {
921 .tip-box { 953 .tip-box {
922 width: 60%; 954 width: 60%;
@@ -1494,7 +1494,7 @@ @@ -1494,7 +1494,7 @@
1494 border: none; 1494 border: none;
1495 background-color: transparent; 1495 background-color: transparent;
1496 z-index: 990; 1496 z-index: 990;
1497 - display: none; 1497 + display: block;
1498 1498
1499 .code-img { 1499 .code-img {
1500 width: 117px; 1500 width: 117px;
@@ -1511,10 +1511,17 @@ @@ -1511,10 +1511,17 @@
1511 line-height: 20px; 1511 line-height: 20px;
1512 text-align: center; 1512 text-align: center;
1513 } 1513 }
1514 -}  
1515 1514
1516 -@media screen and (min-width: 1440px) {  
1517 - .code-down-box {  
1518 - display: block; 1515 + .icon-del {
  1516 + position: absolute;
  1517 + top: -13px;
  1518 + right: -10px;
  1519 + display: inline-block;
  1520 + font-size: 30px;
  1521 + cursor: pointer;
  1522 +
  1523 + &:before {
  1524 + content: "\e60d";
  1525 + }
1519 } 1526 }
1520 } 1527 }
@@ -28,9 +28,10 @@ @@ -28,9 +28,10 @@
28 } 28 }
29 29
30 .tag { 30 .tag {
31 - width: 76px;  
32 - height: 24px;  
33 - line-height: 24px; 31 + width: 252px;
  32 + margin-left: -1px;
  33 + height: 25px;
  34 + line-height: 25px;
34 background-color: #000; 35 background-color: #000;
35 color: #fff; 36 color: #fff;
36 text-align: center; 37 text-align: center;
@@ -112,5 +113,67 @@ @@ -112,5 +113,67 @@
112 padding: 14px 0; 113 padding: 14px 0;
113 text-align: center; 114 text-align: center;
114 } 115 }
  116 +
  117 + .coupon-status {
  118 + position: relative;
  119 + }
  120 +
  121 + .help-icon {
  122 + display: block;
  123 + width: 16px;
  124 + height: 16px;
  125 + background: url(/cart/help-mark.png);
  126 + position: absolute;
  127 + right: 3%;
  128 + top: 50%;
  129 + margin-top: -8px;
  130 + cursor: pointer;
  131 +
  132 + &:hover + .coin-tip-help {
  133 + display: block;
  134 + }
  135 + }
  136 +
  137 + .coin-tip-help {
  138 + width: 200px;
  139 + padding: 6px 10px;
  140 + line-height: 2;
  141 + border: 1px solid #000;
  142 + background-color: #fff;
  143 + text-align: center;
  144 + position: absolute;
  145 + top: 38px;
  146 + right: -100px;
  147 + display: none;
  148 + z-index: 1000;
  149 + }
  150 +
  151 + .coin-tip-help:before {
  152 + content: "";
  153 + width: 12px;
  154 + height: 6px;
  155 + background-image: url(../img/sprite.cart.png);
  156 + background-position: -325px -76px;
  157 + display: block;
  158 + position: absolute;
  159 + top: -6px;
  160 + right: 106px;
  161 + }
  162 + }
  163 +
  164 + .spread-rules {
  165 + border: 1px solid #dedede;
  166 + padding: 10px 20px;
  167 + width: 736px;
  168 + margin: 0 auto;
  169 +
  170 + h2 {
  171 + font-size: 14px;
  172 + font-weight: 600;
  173 + }
  174 +
  175 + p {
  176 + line-height: 18px;
  177 + }
115 } 178 }
116 } 179 }
@@ -84,6 +84,10 @@ @@ -84,6 +84,10 @@
84 padding-left: 5px; 84 padding-left: 5px;
85 color: #bbb; 85 color: #bbb;
86 } 86 }
  87 +
  88 + &:first-child {
  89 + margin-top: 4px;
  90 + }
87 } 91 }
88 92
89 a { 93 a {
@@ -93,9 +97,13 @@ @@ -93,9 +97,13 @@
93 white-space: nowrap; 97 white-space: nowrap;
94 display: block; 98 display: block;
95 color: #666; 99 color: #666;
96 - padding-left: 10px;  
97 height: 22px; 100 height: 22px;
98 line-height: 22px; 101 line-height: 22px;
  102 + margin-left: 10px;
  103 + }
  104 +
  105 + &.suggest-list a {
  106 + margin-left: 0;
99 } 107 }
100 } 108 }
101 109