Showing
10 changed files
with
239 additions
and
44 deletions
@@ -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 | } |
public/vue/product/css/image-carousel.css
0 → 100644
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 | }; |
-
Please register or login to post a comment