Authored by Aiden Xu

商品详情

@@ -36,6 +36,17 @@ const component = { @@ -36,6 +36,17 @@ const component = {
36 api.get('', params).then(result => { 36 api.get('', params).then(result => {
37 res.json(result); 37 res.json(result);
38 }).catch(next); 38 }).catch(next);
  39 + },
  40 + intro: (req, res, next) => {
  41 + let params = {
  42 + method: 'h5.product.intro',
  43 + productskn: req.query.skn,
  44 + udid: 'f528764d624db129b32c21fbca0cb8d6'
  45 + };
  46 +
  47 + api.get('', params).then(result => {
  48 + res.json(result);
  49 + }).catch(next);
39 } 50 }
40 }; 51 };
41 52
@@ -7,11 +7,11 @@ @@ -7,11 +7,11 @@
7 7
8 'use strict'; 8 'use strict';
9 9
10 -const Router = require('express').Router; 10 +const expressRouter = require('express').Router;
11 const cRoot = './controllers'; 11 const cRoot = './controllers';
12 const productList = require(`${cRoot}/list`); 12 const productList = require(`${cRoot}/list`);
13 13
14 -const router = Router(); 14 +const router = expressRouter();
15 15
16 // 商品列表 16 // 商品列表
17 router.use('/list', (req, res, next) => { 17 router.use('/list', (req, res, next) => {
@@ -24,7 +24,9 @@ router.post('/list', productList.getProducts); @@ -24,7 +24,9 @@ router.post('/list', productList.getProducts);
24 24
25 // 商品详情controller 25 // 商品详情controller
26 const detail = require(`${cRoot}/detail`); 26 const detail = require(`${cRoot}/detail`);
  27 +
27 router.get(/\/pro_([\d]+)_([\d]+)\/(.*)/, detail.index); // 商品详情routers 28 router.get(/\/pro_([\d]+)_([\d]+)\/(.*)/, detail.index); // 商品详情routers
28 router.get(/\/product_([\d]+)_([\d]+)\.json/, detail.product); 29 router.get(/\/product_([\d]+)_([\d]+)\.json/, detail.product);
  30 +router.get(/\/intro\.json/, detail.intro);
29 31
30 module.exports = router; 32 module.exports = router;
@@ -15,8 +15,10 @@ module.exports = { @@ -15,8 +15,10 @@ module.exports = {
15 port: 6004, 15 port: 6004,
16 siteUrl: '//m.yohobuy.com', 16 siteUrl: '//m.yohobuy.com',
17 domains: { 17 domains: {
18 - api: 'http://devapi.yoho.cn:58078/',  
19 - service: 'http://123.206.1.104:28077/' 18 + // api: 'http://devapi.yoho.cn:58078/',
  19 + // service: 'http://123.206.1.104:28077/'
  20 + api: 'http://api.yoho.yohoops.org/',
  21 + service: 'http://service.yoho.yohoops.org/'
20 }, 22 },
21 subDomains: { 23 subDomains: {
22 host: '.m.yohobuy.com', 24 host: '.m.yohobuy.com',
@@ -57,7 +57,6 @@ @@ -57,7 +57,6 @@
57 "handlebars": "^4.0.5", 57 "handlebars": "^4.0.5",
58 "handlebars-loader": "^1.3.0", 58 "handlebars-loader": "^1.3.0",
59 "husky": "^0.11.4", 59 "husky": "^0.11.4",
60 - "node-sass": "^3.8.0",  
61 "nodemon": "1.9.2", 60 "nodemon": "1.9.2",
62 "postcss-assets": "^4.0.1", 61 "postcss-assets": "^4.0.1",
63 "postcss-cachebuster": "^0.1.3", 62 "postcss-cachebuster": "^0.1.3",
@@ -71,13 +70,11 @@ @@ -71,13 +70,11 @@
71 "postcss-sprites": "^3.1.2", 70 "postcss-sprites": "^3.1.2",
72 "postcss-use": "^2.2.0", 71 "postcss-use": "^2.2.0",
73 "precss": "^1.4.0", 72 "precss": "^1.4.0",
74 - "sass-loader": "^4.0.0",  
75 "shelljs": "^0.7.0", 73 "shelljs": "^0.7.0",
76 "style-loader": "^0.13.1", 74 "style-loader": "^0.13.1",
77 "stylelint": "^6.9.0", 75 "stylelint": "^6.9.0",
78 "stylelint-config-yoho": "1.2.5", 76 "stylelint-config-yoho": "1.2.5",
79 "vue-loader": "^8.5.3", 77 "vue-loader": "^8.5.3",
80 - "vue-swipe": "^0.2.6",  
81 "webpack": "^1.13.1", 78 "webpack": "^1.13.1",
82 "webpack-dev-server": "^1.14.1", 79 "webpack-dev-server": "^1.14.1",
83 "webpack-stream": "^3.1.0", 80 "webpack-stream": "^3.1.0",
@@ -21,7 +21,6 @@ @@ -21,7 +21,6 @@
21 display: inline-block; 21 display: inline-block;
22 vertical-align: middle; 22 vertical-align: middle;
23 } 23 }
24 -  
25 } 24 }
26 25
27 .separator { 26 .separator {
@@ -75,8 +74,15 @@ i.info { @@ -75,8 +74,15 @@ i.info {
75 font-size: 32px; 74 font-size: 32px;
76 font-weight: lighter; 75 font-weight: lighter;
77 font-style: normal; 76 font-style: normal;
  77 +
  78 + &.strike-through {
  79 + text-decoration: line-through;
78 } 80 }
79 81
  82 + &.highlight {
  83 + color: #d0021b;
  84 + }
  85 + }
80 } 86 }
81 87
82 .control-box { 88 .control-box {
@@ -123,10 +129,45 @@ i.info { @@ -123,10 +129,45 @@ i.info {
123 129
124 th, td { 130 th, td {
125 border: 1px solid #eeeeee; 131 border: 1px solid #eeeeee;
126 - min-width: 162px; 132 + min-width: 170px;
127 line-height: 66px; 133 line-height: 66px;
128 text-align: center; 134 text-align: center;
129 vertical-align: middle; 135 vertical-align: middle;
130 } 136 }
  137 +}
  138 +
  139 +.wash-condition {
  140 + display: flex;
  141 + justify-content: space-around;
  142 +}
  143 +
  144 +.wash-condition-item {
  145 + flex: 1;
  146 + text-align: center;
  147 +}
  148 +
  149 +.description {
  150 + font-size: 0;
  151 +
  152 + li {
  153 + font-size: 24px;
  154 + width: 325px;
  155 + line-height: 40px;
  156 + display: inline-block;
  157 + }
  158 +
  159 + .desc-caption {
  160 + color: #c7c7c7;
  161 + min-width: 100px;
  162 + }
  163 +}
  164 +
  165 +.model-avatar {
  166 + vertical-align: middle;
  167 + border-radius: 100%;
  168 +}
131 169
  170 +.model-name {
  171 + width: 100px;
  172 + display: inline-block;
132 } 173 }
  1 +.image-carousel {
  2 + width: 100%;
  3 + height: 1000px;
  4 +
  5 + .swipe {
  6 + height: 100%;
  7 + }
  8 +
  9 + .swipe-indicators {
  10 + left: auto;
  11 + right: 32px;
  12 + }
  13 +
  14 + .swipe-indicator {
  15 + width: 8px;
  16 + height: 8px;
  17 + line-height: 12px;
  18 + display: inline-block;
  19 +
  20 + &.active {
  21 + width: 12px;
  22 + height: 12px;
  23 + background: #000;
  24 + opacity: 0.6;
  25 + margin: -2px 5px;
  26 + }
  27 + }
  28 +}
@@ -5,6 +5,17 @@ @@ -5,6 +5,17 @@
5 border-bottom: 1px solid #eeeeee; 5 border-bottom: 1px solid #eeeeee;
6 padding: 30px; 6 padding: 30px;
7 7
  8 + img {
  9 + max-width: 100%;
  10 + height: auto !important;
  11 + }
  12 +
  13 + p {
  14 + color: #808080;
  15 + font-size: 24px;
  16 + line-height: 48px;
  17 + }
  18 +
8 hr { 19 hr {
9 border: none; 20 border: none;
10 border-bottom: 1px solid #eeeeee; 21 border-bottom: 1px solid #eeeeee;
@@ -27,6 +38,25 @@ @@ -27,6 +38,25 @@
27 } 38 }
28 } 39 }
29 40
  41 + ul {
  42 + list-style: none;
  43 + padding: 0;
  44 + }
  45 +
  46 + .image-box {
  47 + float: left;
  48 + }
  49 +
  50 + .text-box {
  51 + float: left;
  52 + margin-left: 20px;
  53 + text-align: center;
  54 + }
  55 +
  56 + .clear-fix {
  57 + clear: both;
  58 + }
  59 +
30 &.first-box { 60 &.first-box {
31 margin-top: 0; 61 margin-top: 0;
32 padding: 0; 62 padding: 0;
1 <template> 1 <template>
2 <show-box :is-first="true"> 2 <show-box :is-first="true">
3 - <div>  
4 - <image-carousel></image-carousel>  
5 - </div>  
6 - 3 + <image-carousel :goods="entity.goodsList"></image-carousel>
7 <div class="title-box"> 4 <div class="title-box">
8 <h1>{{entity.productName}}</h1> 5 <h1>{{entity.productName}}</h1>
9 - <i class="price">{{entity.productPriceBo.formatMarketPrice}}</i> 6 +
  7 + <i class="price" :class="{'strike-through': entity.productPriceBo.salesPrice > 0}">{{entity.productPriceBo.formatMarketPrice}}</i>
  8 +
  9 + <i v-if="entity.productPriceBo.salesPrice > 0" class="price highlight">
  10 + {{entity.productPriceBo.formatSalesPrice}}
  11 + </i>
10 </div> 12 </div>
11 </show-box> 13 </show-box>
12 14
13 <show-box> 15 <show-box>
14 <div class="brand"> 16 <div class="brand">
15 - <img src={{entity.brand.brandIco}} width="55" height="34"/> 17 + <img :src="entity.brand.brandIco | resize 110 68" width="55" height="34"/>
16 18
17 <h2>{{entity.brand.brandName}}</h2> 19 <h2>{{entity.brand.brandName}}</h2>
18 <a href="#"> 20 <a href="#">
@@ -22,26 +24,63 @@ @@ -22,26 +24,63 @@
22 </div> 24 </div>
23 </show-box> 25 </show-box>
24 26
25 - <div class="separator"><span>继续拖动,查看商品信息</span><hr/></div> 27 + <div class="separator"><span>继续拖动,查看商品信息</span>
  28 + <hr/>
  29 + </div>
26 30
27 - <show-box> 31 + <show-box v-if="intro.productDescBo">
28 <h2>商品信息</h2> 32 <h2>商品信息</h2>
29 <i>DESCRIPTION</i> 33 <i>DESCRIPTION</i>
30 <hr> 34 <hr>
  35 +
  36 + <ul class="description">
  37 + <li>
  38 + <span class="desc-caption">编号:</span>
  39 + <span>{{intro.productDescBo.erpProductId}}</span>
  40 + </li>
  41 + <li>
  42 + <span class="desc-caption">颜色:</span>
  43 + <span>{{intro.productDescBo.colorName}}</span>
  44 + </li>
  45 + <li>
  46 + <span class="desc-caption">性别:</span>
  47 + <span>{{intro.productDescBo.gender === 1 ? '男款' : '女款'}}</span>
  48 + </li>
  49 + <li v-for="item in intro.productDescBo.standardBos">
  50 + <span class="desc-caption">{{item.standardName}}:</span> <span>{{item.standardVal}}</span>
  51 + </li>
  52 + </ul>
31 </show-box> 53 </show-box>
32 54
33 55
34 - <show-box> 56 + <show-box v-if="intro.sizeInfoBo">
35 <h2>尺码信息</h2> 57 <h2>尺码信息</h2>
36 <i>SIZE INFO</i> 58 <i>SIZE INFO</i>
37 <hr> 59 <hr>
  60 + <div class="horizon-wrapper">
  61 + <table class="table">
  62 + <thead>
  63 + <th>吊牌尺码</th>
  64 + <th v-for="header in intro.sizeInfoBo.sizeAttributeBos">{{header.attributeName}}</th>
  65 + </thead>
  66 + <tbody>
  67 +
  68 + <tr v-for="size in intro.sizeInfoBo.sizeBoList">
  69 + <td>{{size.sizeName}}</td>
  70 + <td v-for="item in size.sortAttributes">{{item.sizeValue}}</td>
  71 + </tr>
  72 + </tbody>
  73 + </table>
  74 + </div>
  75 +
38 <i class="info">提示:左滑查看完整表格信息</i> 76 <i class="info">提示:左滑查看完整表格信息</i>
39 </show-box> 77 </show-box>
40 78
41 - <show-box> 79 + <show-box v-if="intro.sizeImage">
42 <h2>测量方式</h2> 80 <h2>测量方式</h2>
43 <i>MEASUREMENT METHOD</i> 81 <i>MEASUREMENT METHOD</i>
44 <hr> 82 <hr>
  83 + <img v-if="intro.sizeImage" :src="intro.sizeImage"/>
45 </show-box> 84 </show-box>
46 85
47 <show-box> 86 <show-box>
@@ -51,18 +90,27 @@ @@ -51,18 +90,27 @@
51 <div class="horizon-wrapper"> 90 <div class="horizon-wrapper">
52 <table class="table"> 91 <table class="table">
53 <thead> 92 <thead>
  93 + <tr>
54 <th>模特</th> 94 <th>模特</th>
55 <th>身高</th> 95 <th>身高</th>
56 <th>体重</th> 96 <th>体重</th>
57 <th>三围</th> 97 <th>三围</th>
58 - <th>三围</th> 98 + <th>吊牌尺码</th>
  99 + <th>试穿描述</th>
  100 + </tr>
59 </thead> 101 </thead>
60 <tbody> 102 <tbody>
61 - <td>Oliver</td>  
62 - <td>175</td>  
63 - <td>51</td>  
64 - <td>78/70/87</td>  
65 - <td>78/70/87</td> 103 + <tr v-for="item in intro.modelBos">
  104 + <td>
  105 + <img class="model-avatar" :src="item.avatar"/>
  106 + <span class="model-name">{{item.modelName}}</span>
  107 + </td>
  108 + <td>{{item.height}}</td>
  109 + <td>{{item.weight}}</td>
  110 + <td>{{item.vitalStatistics}}</td>
  111 + <td>{{item.fitModelBo.fit_size}}</td>
  112 + <td>{{item.fitModelBo.feel}}</td>
  113 + </tr>
66 </tbody> 114 </tbody>
67 </table> 115 </table>
68 </div> 116 </div>
@@ -70,26 +118,48 @@ @@ -70,26 +118,48 @@
70 </show-box> 118 </show-box>
71 119
72 <show-box> 120 <show-box>
  121 + <div v-if="intro.productMaterialList && intro.productMaterialList.length > 0">
73 <h2>商品材质</h2> 122 <h2>商品材质</h2>
74 <i>MATERIALS</i> 123 <i>MATERIALS</i>
75 <hr> 124 <hr>
  125 + </div>
  126 + <div v-if="intro.productMaterialList">
  127 + <ul v-for="item in intro.productMaterialList">
76 <div> 128 <div>
77 <div class="image-box"> 129 <div class="image-box">
78 - <img src="#" width="86" height="35"/> 130 + <img :src="item.imageUrl" width="86" height="35"/>
79 </div> 131 </div>
80 <div class="text-box"> 132 <div class="text-box">
81 - <div>涤纶</div>  
82 - <div>Terylene</div> 133 + <div>{{item.caption}}</div>
  134 + <div>{{item.encaption}}</div>
83 </div> 135 </div>
  136 + <div class="clear-fix"/>
84 </div> 137 </div>
85 <p> 138 <p>
86 - 用各种洗涤剂,可手洗机洗,但不宜氯漂,宜阴干,避免曝晒,以免深色衣物褪色,在日光下晾晒时,将里面朝外。浸泡时间不能太长,避免褪色。 139 + {{item.remark}}
87 </p> 140 </p>
  141 +
  142 + <hr/>
  143 + </ul>
  144 + </div>
  145 + <ul class="wash-condition">
  146 + <li class="wash-condition-item" v-for="item in intro.washTipsBoList">
  147 + <img :src="item.img" width="25" height="25"/>
  148 + <div>{{item.caption}}</div>
  149 + </li>
  150 + </ul>
88 </show-box> 151 </show-box>
89 152
90 <show-box :is-last="true"> 153 <show-box :is-last="true">
91 <h2>商品详情</h2> 154 <h2>商品详情</h2>
92 <i>DETAILS</i> 155 <i>DETAILS</i>
  156 + <p>
  157 + {{{entity.brand.brandIntro}}}
  158 + </p>
  159 +
  160 + <p v-if="intro.productIntroBo">
  161 + {{{intro.productIntroBo.productIntro}}}
  162 + </p>
93 </show-box> 163 </show-box>
94 164
95 <div class="control-box"> 165 <div class="control-box">
1 -<style>  
2 - .image-carousel {  
3 - width: 100%;  
4 - height: 1000px;  
5 - background-color: #efefef;  
6 - }  
7 -</style> 1 +<style src="./css/image-carousel.css"></style>
8 <template> 2 <template>
9 <div class="image-carousel"> 3 <div class="image-carousel">
10 - <img src="" alt=""> 4 + <swipe>
  5 + <swipe-item v-for="item in goods">
  6 + <a href="#" title="{{item.title}}">
  7 + <img :src="item.colorImage | resize 750 1000" width="375" height="500" alt="">
  8 + </a>
  9 + </swipe-item>
  10 + </swipe>
11 </div> 11 </div>
12 </template> 12 </template>
13 <script> 13 <script>
  14 + const swipe = require('vue-swipe');
  15 +
  16 + require('common/vue-filter');
  17 +
14 module.exports = { 18 module.exports = {
  19 + props: {
  20 + goods: [Object]
  21 + },
15 data() { 22 data() {
16 - return {  
17 - }; 23 + return {};
18 }, 24 },
19 components: { 25 components: {
20 - 26 + swipe: swipe.Swipe,
  27 + swipeItem: swipe.SwipeItem
21 } 28 }
22 }; 29 };
23 </script> 30 </script>
1 const app = $('#app'); 1 const app = $('#app');
2 2
  3 +require('vue-swipe/dist/vue-swipe.css');
  4 +
3 module.exports = { 5 module.exports = {
4 data() { 6 data() {
5 return { 7 return {
  8 + intro: {},
6 entity: { 9 entity: {
7 brand: { 10 brand: {
8 brandName: '', 11 brandName: '',
@@ -16,9 +19,9 @@ module.exports = { @@ -16,9 +19,9 @@ module.exports = {
16 }; 19 };
17 }, 20 },
18 components: { 21 components: {
19 - 'image-carousel': require('../image-carousel.vue'),  
20 - 'feature-selector': require('component/product/feature-selector.vue'),  
21 - 'show-box': require('../show-box.vue') 22 + imageCarousel: require('../image-carousel.vue'),
  23 + featureSelector: require('component/product/feature-selector.vue'),
  24 + showBox: require('../show-box.vue')
22 }, 25 },
23 methods: { 26 methods: {
24 showAddToCart: function() { 27 showAddToCart: function() {
@@ -33,8 +36,12 @@ module.exports = { @@ -33,8 +36,12 @@ module.exports = {
33 }); 36 });
34 37
35 $.get(`/product/product_${app.data('pid')}_${app.data('goodsId')}.json`).then(result=> { 38 $.get(`/product/product_${app.data('pid')}_${app.data('goodsId')}.json`).then(result=> {
36 - // console.log(result);  
37 this.entity = result; 39 this.entity = result;
  40 + return result;
  41 + }).then((result)=> {
  42 + return $.get('/product/product/intro.json', {skn: result.productPriceBo.productSkn});
  43 + }).then(result => {
  44 + this.intro = result;
38 }); 45 });
39 } 46 }
40 }; 47 };