Authored by 姜枫

handle merge

@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
5 */ 5 */
6 'use strict'; 6 'use strict';
7 7
  8 +const _ = require('lodash');
8 const Item = require('../models/item'); 9 const Item = require('../models/item');
9 10
10 const index = (req, res, next) => { 11 const index = (req, res, next) => {
@@ -241,6 +242,9 @@ const index = (req, res, next) => { @@ -241,6 +242,9 @@ const index = (req, res, next) => {
241 // }; 242 // };
242 243
243 Item.getProductItemData(req.params).then(result => { 244 Item.getProductItemData(req.params).then(result => {
  245 + if (_.isEmpty(result)) {
  246 + return next();
  247 + }
244 res.display('item', result); 248 res.display('item', result);
245 }).catch(next); 249 }).catch(next);
246 }; 250 };
@@ -31,7 +31,7 @@ const getsizeInfoAsync = (skn) => { @@ -31,7 +31,7 @@ const getsizeInfoAsync = (skn) => {
31 }, { cache: true }); 31 }, { cache: true });
32 }; 32 };
33 33
34 -const getProductComfort = productId => { 34 +const getComfortAsync = productId => {
35 return api.get('', { 35 return api.get('', {
36 method: 'web.productComfort.data', 36 method: 'web.productComfort.data',
37 product_id: productId 37 product_id: productId
@@ -42,8 +42,19 @@ const getProductComfort = productId => { @@ -42,8 +42,19 @@ const getProductComfort = productId => {
42 42
43 }; 43 };
44 44
  45 +const getModelTryAsync = skn => {
  46 + return api.get('', {
  47 + method: 'web.productModelTry.data',
  48 + product_skn: skn
  49 + }, {
  50 + cache: true,
  51 + code: 200
  52 + });
  53 +};
  54 +
45 module.exports = { 55 module.exports = {
46 getProductBaseAsync, 56 getProductBaseAsync,
47 getsizeInfoAsync, 57 getsizeInfoAsync,
48 - getProductComfort 58 + getComfortAsync,
  59 + getModelTryAsync
49 }; 60 };
@@ -9,13 +9,91 @@ const _ = require('lodash'); @@ -9,13 +9,91 @@ const _ = require('lodash');
9 const helpers = global.yoho.helpers; 9 const helpers = global.yoho.helpers;
10 10
11 /** 11 /**
  12 + * 使sizeBoList id以 sizeAttributeBos id顺序一样
  13 + * @param sizeInfoBo
  14 + */
  15 +const _sizeInfoBoSort = sizeInfoBo => {
  16 + if (!sizeInfoBo.sizeBoList || !sizeInfoBo.sizeAttributeBos) {
  17 + return {};
  18 + }
  19 +
  20 + // TODO: 这里的排序代码很乱
  21 +
  22 + _.forEach(sizeInfoBo.sizeBoList, (sizeBoList, sizek)=> {
  23 + let sortAttr = {};
  24 +
  25 + _.forEach(sizeBoList.sortAttributes, sortAttributes => {
  26 + sortAttr[sortAttributes.id] = sortAttributes;
  27 + });
  28 +
  29 + sizeInfoBo.sizeBoList[sizek].sortAttributes = sortAttr;
  30 + });
  31 +
  32 +
  33 + _.forEach(sizeInfoBo.sizeBoList, (sizeBoList, sizek)=> {
  34 + let sortAttr = [];
  35 +
  36 + _.forEach(sizeInfoBo.sizeAttributeBos, val => {
  37 + sortAttr.push(sizeBoList.sortAttributes[val.id]);
  38 + });
  39 +
  40 + sizeInfoBo.sizeBoList[sizek].sortAttributes = sortAttr;
  41 +
  42 + });
  43 +
  44 + return sizeInfoBo;
  45 +};
  46 +
  47 +const setPathNav = (data, name) => {
  48 + let resData = {};
  49 +
  50 + if (!_.isEmpty(data)) {
  51 + let navs = [];
  52 + let sort = data.sort[0];
  53 +
  54 + navs.push({
  55 + link: helpers.urlFormat('/list', {
  56 + msort: sort.sort_id
  57 +
  58 + // gender: '' // 待处理
  59 + }),
  60 + name: sort.sort_name,
  61 + pathTitle: sort.sort_name
  62 + });
  63 +
  64 + // 二级分类
  65 + if (!_.isEmpty(sort.sub)) {
  66 + navs.push({
  67 + link: helpers.urlFormat('/list', {
  68 + msort: sort.sort_id,
  69 + misort: sort.sub.sort_id
  70 +
  71 + // gender: '' // 待处理
  72 + }),
  73 + name: sort.sub[0].sort_name,
  74 + pathTitle: sort.sub[0].sort_name
  75 + });
  76 + }
  77 +
  78 + navs.push({
  79 + name: name,
  80 + pathTitle: name
  81 + });
  82 +
  83 + resData.nav = navs;
  84 + }
  85 +
  86 + return resData;
  87 +};
  88 +
  89 +/**
12 * 设置品牌banner数据 90 * 设置品牌banner数据
13 * @param brand 品牌相关数据 91 * @param brand 品牌相关数据
14 * @return Object 92 * @return Object
15 */ 93 */
16 const setBrandBanner = brand => { 94 const setBrandBanner = brand => {
17 let data = { 95 let data = {
18 - bgColor: '#93897d', 96 + bgColor: '#000',
19 brandLogo: { 97 brandLogo: {
20 link: `#${brand.brandDomain}`, // 品牌跳转链接 -- 待处理 98 link: `#${brand.brandDomain}`, // 品牌跳转链接 -- 待处理
21 img: brand.brandIco 99 img: brand.brandIco
@@ -166,10 +244,11 @@ const setBrandIntro = brand => { @@ -166,10 +244,11 @@ const setBrandIntro = brand => {
166 244
167 /** 245 /**
168 * 设置商品描述 246 * 设置商品描述
169 - * @param brand 品牌相关数据 247 + * @param sizeInfo
  248 + * @param comfortInfo
170 * @return Object 249 * @return Object
171 */ 250 */
172 -const setDescriptionInfo = (sizeInfo, comfortInfo) => { 251 +const setDescriptionData = (sizeInfo, comfortInfo) => {
173 let resData = {}; 252 let resData = {};
174 253
175 if (_.has(sizeInfo, 'productDescBo.erpProductId')) { 254 if (_.has(sizeInfo, 'productDescBo.erpProductId')) {
@@ -198,7 +277,7 @@ const setDescriptionInfo = (sizeInfo, comfortInfo) => { @@ -198,7 +277,7 @@ const setDescriptionInfo = (sizeInfo, comfortInfo) => {
198 ]; 277 ];
199 278
200 if (_.isArray(sizeInfo.productDescBo.standardBos)) { 279 if (_.isArray(sizeInfo.productDescBo.standardBos)) {
201 - _.forEach(sizeInfo.productDescBo.standardBos, function(value) { 280 + _.forEach(sizeInfo.productDescBo.standardBos, value => {
202 basic.push({ 281 basic.push({
203 key: value.standardName, 282 key: value.standardName,
204 value: value.standardVal 283 value: value.standardVal
@@ -211,7 +290,7 @@ const setDescriptionInfo = (sizeInfo, comfortInfo) => { @@ -211,7 +290,7 @@ const setDescriptionInfo = (sizeInfo, comfortInfo) => {
211 if (comfortInfo) { 290 if (comfortInfo) {
212 let comfort = []; 291 let comfort = [];
213 292
214 - _.forEach(comfortInfo, function(value) { 293 + _.forEach(comfortInfo, value => {
215 let i = 1; 294 let i = 1;
216 let blocks = []; 295 let blocks = [];
217 let flag = false; 296 let flag = false;
@@ -249,9 +328,243 @@ const setDescriptionInfo = (sizeInfo, comfortInfo) => { @@ -249,9 +328,243 @@ const setDescriptionInfo = (sizeInfo, comfortInfo) => {
249 return resData; 328 return resData;
250 }; 329 };
251 330
  331 +/**
  332 + * 设置洗涤材质信息
  333 + * @param sizeInfo
  334 + * @return Object
  335 + */
  336 +const setMaterialData = sizeInfo => {
  337 + let resData = {};
  338 + let material = {};
  339 +
  340 + // 洗涤提示
  341 + if (sizeInfo.washTipsBoList) {
  342 + let wash = [];
  343 +
  344 + _.forEach(sizeInfo.washTipsBoList, value => {
  345 + wash.push({
  346 + name: value.caption,
  347 + img: value.img
  348 + });
  349 + });
  350 +
  351 + if (!_.isEmpty(wash)) {
  352 + material.wash = wash;
  353 + }
  354 + }
  355 +
  356 + // 商品材质[洗涤说明]
  357 + if (sizeInfo.productMaterialList) {
  358 + let detail = [];
  359 +
  360 + _.forEach(sizeInfo.productMaterialList, value => {
  361 + detail.push({
  362 + img: value.imageUrl,
  363 + name: value.caption,
  364 + enName: value.encaption,
  365 + text: value.remark
  366 + });
  367 + });
  368 +
  369 + if (!_.isEmpty(detail)) {
  370 + material.detail = detail;
  371 + }
  372 + }
  373 +
  374 + if (!_.isEmpty(material)) {
  375 + Object.assign(material, {
  376 + titleEn: 'MATERIALS',
  377 + titleCn: '材料洗涤'
  378 + });
  379 +
  380 + resData.material = material;
  381 + }
  382 + return resData;
  383 +};
  384 +
  385 +/**
  386 + * 设置尺寸信息
  387 + * @param sizeInfo
  388 + * @return Object
  389 + */
  390 +const setSizeData = (sizeInfo) => {
  391 + let resData = {};
  392 +
  393 + if (sizeInfo.sizeInfoBo) {
  394 + let referenceName,
  395 + boyReference,
  396 + girlReference,
  397 + gender;
  398 + let size = {
  399 + titleEn: 'SIZEINFO',
  400 + titleCn: '尺码信息'
  401 + };
  402 +
  403 + sizeInfo.sizeInfoBo = _sizeInfoBoSort(sizeInfo.sizeInfoBo);
  404 +
  405 + // 参考尺码
  406 + if (_.has(sizeInfo, 'productExtra')) {
  407 + boyReference = sizeInfo.productExtra.boyReference;
  408 + girlReference = sizeInfo.productExtra.girlReference;
  409 + }
  410 +
  411 + gender = _.has(sizeInfo, 'productDescBo.gender') ? sizeInfo.productDescBo.gender : 3;
  412 + if (gender === 3 && boyReference) {
  413 + referenceName = '参考尺码(男)';
  414 + } else if (gender === 3 && girlReference) {
  415 + referenceName = '参考尺码(女)';
  416 + } else {
  417 + referenceName = '参考尺码';
  418 + }
  419 +
  420 + // 判断是否显示参考尺码
  421 + let showReference = (boyReference && _.get(sizeInfo.sizeInfoBo, 'sizeBoList[0].boyReferSize', false)) ||
  422 + (girlReference && _.get(sizeInfo.sizeInfoBo, 'sizeBoList[0].girlReferSize', false));
  423 +
  424 + if (sizeInfo.sizeInfoBo.sizeAttributeBos) {
  425 + let sizeTable = {};
  426 +
  427 + // 尺码信息头部
  428 + sizeTable.thead = [{name: '吊牌尺码', id: '', width: 126}];
  429 +
  430 + // 显示参考尺码
  431 + if (showReference) {
  432 + sizeTable.thead.push({name: referenceName, id: '', width: 126});
  433 + }
  434 +
  435 + _.forEach(sizeInfo.sizeInfoBo.sizeAttributeBos, value => {
  436 + sizeTable.thead.push({
  437 + name: value.attributeName || ' ',
  438 + id: value.id,
  439 + width: 126
  440 + });
  441 + });
  442 +
  443 + sizeTable.tbody = [];
  444 + _.forEach(sizeInfo.sizeInfoBo.sizeBoList, value => {
  445 + let sizes = [];
  446 +
  447 + // 吊牌尺码
  448 + sizes.push(value.sizeName);
  449 +
  450 + // 判断是否显示参考尺码
  451 + if (boyReference && (gender === 1 || gender === 3) && showReference) {
  452 + sizes.push(value.boyReferSize.referenceName || ' ');
  453 + } else if (girlReference && (gender === 2 || gender === 3) && showReference) {
  454 + sizes.push(value.girlReferSize.referenceName || ' ');
  455 + } else {
  456 + if (sizeTable.thead[1] && showReference) {
  457 + sizeTable.thead[1] = {};
  458 + }
  459 + }
  460 +
  461 + // 其他尺码信息
  462 + value.sortAttributes.forEach(attr => {
  463 + sizes.push((attr.sizeValue || ' '));
  464 + });
  465 +
  466 + // 尺码信息
  467 + sizeTable.tbody.push(sizes);
  468 + });
  469 +
  470 + // 参考尺码为空
  471 + if (_.isEmpty(sizeTable.thead[1]) && showReference) {
  472 + // 移除这个值
  473 + sizeTable.thead.splice(1, 1);
  474 + }
  475 +
  476 + size.param = sizeTable;
  477 + }
  478 +
  479 + if (!_.isEmpty(sizeInfo.modelBos)) {
  480 + let tasteTable = {};
  481 +
  482 + tasteTable.thead = [
  483 + {name: '模特', width: 170},
  484 + {name: '身高', width: 126},
  485 + {name: '体重', width: 126},
  486 + {name: '三围', width: 126},
  487 + {name: '吊牌尺码', width: 126},
  488 + {name: '试穿描述', width: 126}
  489 + ];
  490 +
  491 + tasteTable.tbody = [];
  492 + _.forEach(sizeInfo.modelBos, value => {
  493 + let modelInfo = [
  494 + value.avatar, value.modelName, value.height,
  495 + value.weight, value.vitalStatistics, value.fitModelBo.fit_size,
  496 + value.fitModelBo.feel
  497 + ];
  498 +
  499 + // 是否有备注
  500 + if (_.get(value, 'fitModelBo.fit_remark', false)) {
  501 + modelInfo.push(value.fitModelBo.fit_remark);
  502 + tasteTable.thead[7] = {name: '备注', width: 170};
  503 + }
  504 + tasteTable.tbody.push(modelInfo);
  505 + });
  506 +
  507 + size.taste = tasteTable;
  508 + }
  509 +
  510 + resData.sizeInfo = size;
  511 + }
  512 + return resData;
  513 +};
  514 +
  515 +/**
  516 + * 设置商品详情页介绍
  517 + *
  518 + * @param array sizeInfo
  519 + * @return string
  520 + */
  521 +const setDetailData = sizeInfo => {
  522 + let resData = {};
  523 +
  524 + // 详情配图
  525 + if (_.has(sizeInfo, 'productIntroBo.productIntro')) {
  526 + let details = {
  527 + titleEn: 'DETAILS',
  528 + titleCn: '商品详情'
  529 + };
  530 +
  531 + if (sizeInfo.productDescBo && sizeInfo.productDescBo.phrase) {
  532 + details.content = `${sizeInfo.productDescBo.phrase}<br/>`;
  533 + }
  534 +
  535 + // 图片换规则
  536 + const replacePairs = [
  537 + {
  538 + reg: /<img src=/g,
  539 + str: '<img class="lazy" src="data:image/gif;base64,R0lGODlhAQABAJEAAAAAAP///93d3f' +
  540 + '///yH5BAEAAAMALAAAAAABAAEAAAICVAEAOw==" data-original='
  541 + },
  542 + {
  543 + reg: /<img border="0" src=/g,
  544 + str: '<img border="0" class="lazy" src="data:image/gif;base64,R0lGODlhAQABAJEAAAAAAP' +
  545 + '///93d3f///yH5BAEAAAMALAAAAAABAAEAAAICVAEAOw==" data-original='
  546 + }
  547 + ];
  548 + let content = sizeInfo.productIntroBo.productIntro;
  549 +
  550 + // 图片换成懒加载方式
  551 + _.forEach(replacePairs, value => {
  552 + content = _.replace(content, value.reg, value.str);
  553 + });
  554 + details.content += content;
  555 +
  556 + resData.details = details;
  557 + }
  558 + return resData;
  559 +};
  560 +
252 module.exports = { 561 module.exports = {
253 setBrandBanner, 562 setBrandBanner,
  563 + setPathNav,
254 setProductData, 564 setProductData,
255 setBrandIntro, 565 setBrandIntro,
256 - setDescriptionInfo 566 + setDescriptionData,
  567 + setMaterialData,
  568 + setSizeData,
  569 + setDetailData
257 }; 570 };
@@ -8,6 +8,8 @@ @@ -8,6 +8,8 @@
8 const itemAPI = require('./item-api'); 8 const itemAPI = require('./item-api');
9 const itemFUN = require('./item-handler'); 9 const itemFUN = require('./item-handler');
10 10
  11 +const search = require('./search-api');
  12 +
11 const _getMultiResourceByBaseInfo = (base, uid) => { 13 const _getMultiResourceByBaseInfo = (base, uid) => {
12 let productId = base.id; 14 let productId = base.id;
13 let skn = base.erpProductId; 15 let skn = base.erpProductId;
@@ -17,7 +19,9 @@ const _getMultiResourceByBaseInfo = (base, uid) => { @@ -17,7 +19,9 @@ const _getMultiResourceByBaseInfo = (base, uid) => {
17 // 获取相关数据 19 // 获取相关数据
18 let promiseData = [ 20 let promiseData = [
19 itemAPI.getsizeInfoAsync(skn), 21 itemAPI.getsizeInfoAsync(skn),
20 - itemAPI.getProductComfort(productId) 22 + itemAPI.getComfortAsync(productId),
  23 + itemAPI.getModelTryAsync(skn),
  24 + search.getSortAsync({sort: base.smallSortId})
21 ]; 25 ];
22 26
23 if (uid) { 27 if (uid) {
@@ -29,7 +33,9 @@ const _getMultiResourceByBaseInfo = (base, uid) => { @@ -29,7 +33,9 @@ const _getMultiResourceByBaseInfo = (base, uid) => {
29 return Promise.all(promiseData).then(result => { 33 return Promise.all(promiseData).then(result => {
30 return { 34 return {
31 sizeInfo: result[0], 35 sizeInfo: result[0],
32 - comfort: result[1].data 36 + comfort: result[1].data,
  37 + modelTry: result[2].data,
  38 + sort: result[3].data
33 }; 39 };
34 }); 40 });
35 }; 41 };
@@ -49,9 +55,7 @@ let getProductItemData = (params) => { @@ -49,9 +55,7 @@ let getProductItemData = (params) => {
49 } 55 }
50 56
51 // 商品基本信息 57 // 商品基本信息
52 - Object.assign(data, {  
53 - goodInfo: itemFUN.setProductData(result)  
54 - }); 58 + data.goodInfo = itemFUN.setProductData(result);
55 59
56 if (result.brand) { 60 if (result.brand) {
57 Object.assign(data, itemFUN.setBrandBanner(result.brand)); 61 Object.assign(data, itemFUN.setBrandBanner(result.brand));
@@ -61,9 +65,20 @@ let getProductItemData = (params) => { @@ -61,9 +65,20 @@ let getProductItemData = (params) => {
61 } 65 }
62 66
63 return _getMultiResourceByBaseInfo(result).then(mulRes => { 67 return _getMultiResourceByBaseInfo(result).then(mulRes => {
64 - // 设置商品描述  
65 - Object.assign(data, itemFUN.setDescriptionInfo(mulRes.sizeInfo, mulRes.comfort)); 68 + // 面包屑导航
  69 + Object.assign(data, itemFUN.setPathNav(mulRes.sort, result.productName));
  70 +
  71 + // DESCRIPTION商品描述
  72 + Object.assign(data, itemFUN.setDescriptionData(mulRes.sizeInfo, mulRes.comfort));
  73 +
  74 + // MATERIALS材料洗涤
  75 + Object.assign(data, itemFUN.setMaterialData(mulRes.sizeInfo));
  76 +
  77 + // SIZEINFO尺码信息
  78 + Object.assign(data, itemFUN.setSizeData(mulRes.sizeInfo, mulRes.modelTry));
66 79
  80 + // DETAILS商品详情
  81 + Object.assign(data, itemFUN.setDetailData(mulRes.sizeInfo));
67 82
68 return data; 83 return data;
69 }); 84 });
  1 +// 由于目前没有相关java接口,暂时调search
  2 +'use strict';
  3 +
  4 +const api = global.yoho.SearchAPI;
  5 +
  6 +const getSortAsync = (condition) => {
  7 + return api.get('sortgroup.json', condition, {
  8 + code: 200
  9 + });
  10 +};
  11 +
  12 +module.exports = {
  13 + getSortAsync
  14 +};
@@ -19,8 +19,8 @@ module.exports = { @@ -19,8 +19,8 @@ module.exports = {
19 }, 19 },
20 cookieDomain: 'yohoblk.com', 20 cookieDomain: 'yohoblk.com',
21 domains: { 21 domains: {
22 - api: 'http://api.yoho.cn/', // devapi.yoho.cn:58078 testapi.yoho.cn:28078 devapi.yoho.cn:58078  
23 - service: 'http://service.yoho.cn/', // testservice.yoho.cn:28077 devservice.yoho.cn:58077 22 + api: 'http://testapi.yoho.cn:28078/', // devapi.yoho.cn:58078 testapi.yoho.cn:28078 devapi.yoho.cn:58078
  23 + service: 'http://testservice.yoho.cn:28077/', // testservice.yoho.cn:28077 devservice.yoho.cn:58077
24 search: 'http://192.168.102.216:8080/yohosearch/' 24 search: 'http://192.168.102.216:8080/yohosearch/'
25 }, 25 },
26 useOneapm: false, 26 useOneapm: false,
@@ -270,6 +270,10 @@ @@ -270,6 +270,10 @@
270 margin-left: 20px; 270 margin-left: 20px;
271 } 271 }
272 } 272 }
  273 +
  274 + .detail-content {
  275 + text-align: center;
  276 + }
273 } 277 }
274 278
275 .info-block { 279 .info-block {