Toggle navigation
Toggle navigation
This project
Loading...
Sign in
fe
/
yoho-blk
·
Commits
Go to a project
GitLab
Go to group
Project
Activity
Files
Commits
Pipelines
0
Builds
0
Graphs
Milestones
Issues
0
Merge Requests
1
Members
Labels
Wiki
Forks
Network
Create a new issue
Download as
Email Patches
Plain Diff
Browse Files
Authored by
王水玲
8 years ago
Commit
73e02dca966877e5f62c2034af5df8c17bd2ecb5
1 parent
76b8a7d7
店铺推荐 为您优选
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
464 additions
and
110 deletions
apps/product/controllers/item.js
apps/product/controllers/recommend.js
apps/product/models/item-handler.js
apps/product/models/recommend.js
apps/product/router.js
config/common.js
package.json
public/helper/https.js
public/js/product/item.page.js
public/js/product/item/recommend-product.js
public/scss/product/_index.css
public/scss/product/_item.css
public/scss/product/_recommend-product.css
public/tpl/product/recommend-product.hbs
public/tpl/product/recommend-templet.hbs
apps/product/controllers/item.js
View file @
73e02dc
...
...
@@ -8,6 +8,18 @@
const
_
=
require
(
'lodash'
);
const
item
=
require
(
'../models/item'
);
// 保存在 gids 和 skns ,最近流览功能
const
saveRecentGoodInCookies
=
(
oldSkns
,
res
,
addSkns
)
=>
{
oldSkns
=
oldSkns
?
oldSkns
.
split
(
','
)
:
[];
oldSkns
=
_
.
reject
(
oldSkns
,
old
=>
old
===
String
(
addSkns
)
?
true
:
false
);
oldSkns
.
unshift
(
addSkns
);
res
.
cookie
(
'_browseskn'
,
oldSkns
.
splice
(
0
,
30
).
join
(
','
),
{
maxAge
:
2000000000
,
domain
:
'.yohoblk.com'
});
};
/**
* 商品详情页
* @function index
...
...
@@ -18,6 +30,12 @@ const index = (req, res, next) => {
if
(
_
.
isEmpty
(
result
))
{
return
next
();
}
// 最近浏览存储cookies
if
(
!
_
.
has
(
result
.
content
.
goodInfo
,
'fashionTopGoods'
))
{
saveRecentGoodInCookies
(
req
.
cookies
.
_browseskn
,
res
,
result
.
content
.
goodInfo
.
productSkn
);
}
result
.
page
=
'item'
;
result
.
title
+=
`
|
$
{
res
.
locals
.
title
}
`
;
res
.
display
(
'item'
,
result
);
...
...
apps/product/controllers/recommend.js
View file @
73e02dc
...
...
@@ -5,15 +5,112 @@
*/
'use strict'
;
const
_
=
require
(
'lodash'
);
const
recommend
=
require
(
'../models/recommend'
);
const
_
=
require
(
'lodash'
);
const
md5
=
require
(
'md5'
);
const
requestIp
=
require
(
'request-ip'
);
const
_channel
=
(
channel
)
=>
{
let
yhChannel
=
1
;
switch
(
channel
)
{
case
'men'
:
yhChannel
=
1
;
break
;
case
'women'
:
yhChannel
=
2
;
break
;
case
'lifestyle'
:
yhChannel
=
4
;
break
;
default
:
break
;
}
return
yhChannel
;
};
/**
* 获取客户端唯一标识
* @return string
*/
const
getUdid
=
(
req
,
res
)
=>
{
let
udid
=
req
.
cookies
.
udid
;
if
(
!
udid
)
{
udid
=
md5
(
req
.
ip
||
requestIp
.
getClientIp
(
req
));
if
(
res
&&
res
.
cookie
)
{
res
.
cookie
(
'udid'
,
udid
);
}
}
return
udid
;
};
/**
* 为您优选
* @param req
* @param res
* @param next
*/
const
getRecommendProduct
=
(
req
,
res
,
next
)
=>
{
recommend
.
getRecommendProduct
().
then
((
result
)
=>
{
let
params
=
{
yh_channel
:
_channel
(
req
.
query
.
channel
||
req
.
cookies
.
_Channel
||
'men'
),
udid
:
getUdid
(
req
,
res
)
};
recommend
.
getRecommendProduct
(
params
).
then
((
result
)
=>
{
res
.
json
(
result
);
});
}).
catch
(
next
);
};
/**
* 店铺推荐
* @param req
* @param res
* @param next
*/
const
getRecommendShop
=
(
req
,
res
,
next
)
=>
{
recommend
.
getRecommendShop
(
req
.
query
.
productSkn
).
then
((
result
)
=>
{
res
.
json
(
result
);
}).
catch
(
next
);
};
/**
* 最近浏览
* @param req
* @param res
* @param next
*/
const
recentPreview
=
(
req
,
res
,
next
)
=>
{
let
browserSkn
=
req
.
cookies
.
_browseskn
;
let
limit
=
req
.
query
.
limit
;
// 拆解skn
let
skn
=
browserSkn
?
decodeURIComponent
(
browserSkn
).
replace
(
/
\-(\d)
+
(\,){0,1}
/g
,
','
)
:
''
;
// 去除skn字符串的最后一个多余的,
if
(
skn
&&
skn
.
lastIndexOf
(
','
)
===
skn
.
length
-
1
)
{
skn
=
skn
.
slice
(
0
,
-
1
);
}
if
(
!
skn
)
{
res
.
jsonp
({
code
:
200
,
data
:
[],
message
:
'User info'
});
}
else
{
skn
=
_
.
slice
(
_
.
uniq
(
skn
.
split
(
','
)),
0
,
limit
).
join
(
','
);
// 去重+截取
recommend
.
recentPreview
(
skn
,
limit
).
then
(
data
=>
{
res
.
jsonp
(
data
);
}).
catch
(
next
);
}
};
module
.
exports
=
{
getRecommendProduct
getRecommendProduct
,
getRecommendShop
,
recentPreview
};
...
...
apps/product/models/item-handler.js
View file @
73e02dc
...
...
@@ -320,6 +320,7 @@ const setBrandBanner = (base, brand, shop) => {
const
setProductData
=
base
=>
{
let
resData
=
{
id
:
base
.
product_id
,
productSkn
:
base
.
product_skn
,
name
:
base
.
product_name
,
brandName
:
_
.
has
(
base
,
'brand_info.brand_name'
)
?
base
.
brand_info
.
brand_name
:
''
,
intro
:
base
.
sales_phrase
,
...
...
apps/product/models/recommend.js
View file @
73e02dc
...
...
@@ -6,29 +6,96 @@
'use strict'
;
const
_
=
require
(
'lodash'
);
const
api
=
global
.
yoho
.
API
;
const
logger
=
global
.
yoho
.
logger
;
const
_
=
require
(
'lodash'
);
const
config
=
global
.
yoho
.
config
;
const
getRecommendProduct
=
(
params
)
=>
{
params
=
{
yh_channel
:
4
,
udid
:
'0f528764d624db129b32c21fbca0cb8d6'
,
limit
:
5
,
rec_pos
:
100003
};
return
api
.
get
(
'app.home.newPreference'
,
params
).
then
((
data
)
=>
{
if
(
data
.
code
===
200
&&
data
.
data
.
length
>
0
)
{
console
.
log
(
data
);
return
data
.
data
;
}
else
{
logger
.
error
(
'get recommend product data code is not 200'
);
return
[];
/**
* 根据性别来决定 默认图片获取字段 如果是 2、3
*
* 则优先从cover_2 --》 cover_1 -- 》 images_url
* 否则优先从cover_1 --》 cover_2 -- 》 images_url
*
*/
const
_procProductImg
=
(
product
)
=>
{
if
(
product
.
gender
===
'2,3'
||
product
.
gender
===
'2'
||
product
.
gender
===
'3'
)
{
return
product
.
cover_2
||
product
.
images_url
||
product
.
cover_1
||
''
;
}
return
product
.
cover_1
||
product
.
images_url
||
product
.
cover_2
||
''
;
};
const
_processProduct
=
(
list
)
=>
{
let
newRes
=
[];
list
=
list
||
[];
list
.
forEach
(
item
=>
{
let
defaultGoods
=
_
.
find
(
item
.
goods_list
,
{
is_default
:
'Y'
});
// 无默认商品取商品列表第一个
if
(
!
defaultGoods
)
{
defaultGoods
=
item
.
goods_list
[
0
];
}
item
.
default_images
=
_procProductImg
(
defaultGoods
);
item
.
goodsUrl
=
`
$
{
config
.
siteUrl
}
/product/
pro_$
{
item
.
product_id
}
_$
{
defaultGoods
.
goods_id
}
/${item.cn_alphabet}.html`; // eslint-disable-lin
e
});
_
.
chunk
(
list
,
5
).
forEach
(
item
=>
{
newRes
.
push
({
list
:
item
});
});
return
newRes
;
};
const
getRecommendProduct
=
(
params
,
uid
)
=>
{
if
(
uid
!==
0
&&
uid
!==
null
)
{
params
.
uid
=
uid
;
}
return
api
.
get
(
''
,
_
.
assign
({
method
:
'app.home.newPreference'
,
limit
:
20
,
page
:
1
,
rec_pos
:
100003
},
params
),
{
code
:
200
,
catch
:
true
}).
then
(
data
=>
{
return
_processProduct
(
data
.
data
.
product_list
);
});
};
const
getRecommendShop
=
(
productSkn
)
=>
{
return
api
.
get
(
''
,
{
method
:
'web.product.shopRecommend'
,
limit
:
20
,
page
:
1
,
product_skn
:
productSkn
},
{
code
:
200
}).
then
(
data
=>
{
return
_processProduct
(
data
.
data
.
product_list
);
});
};
const
recentPreview
=
(
skn
,
limit
)
=>
{
return
api
.
get
(
''
,
{
method
:
'h5.product.batch'
,
productSkn
:
skn
,
limit
:
limit
,
page
:
1
},
{
code
:
200
}).
then
(
data
=>
{
return
_processProduct
(
data
.
data
.
product_list
);
});
};
module
.
exports
=
{
getRecommendProduct
getRecommendProduct
,
getRecommendShop
,
recentPreview
};
...
...
apps/product/router.js
View file @
73e02dc
...
...
@@ -33,5 +33,7 @@ router.post('/brand/togglecollect', auth, fav.brand);
router
.
get
(
'/query'
,
query
.
index
);
router
.
get
(
'/getRecommendProduct'
,
recommend
.
getRecommendProduct
);
router
.
get
(
'/getRecommendShop'
,
recommend
.
getRecommendShop
);
router
.
get
(
'/recentPreview'
,
recommend
.
recentPreview
);
module
.
exports
=
router
;
...
...
config/common.js
View file @
73e02dc
...
...
@@ -26,6 +26,11 @@ module.exports = {
api
:
'http://api.yoho.yohoops.org/'
,
service
:
'http://service.yoho.yohoops.org/'
,
search
:
'http://search.yohoops.org/yohosearch/'
// api: 'http://api-test3.yohops.com:9999/',
// service: 'http://service-test3.yohops.com:9999/',
// liveApi: 'http://testapi.live.yohops.com:9999/',
// singleApi: 'http://api-test3.yohops.com:9999/'
},
useOneapm
:
false
,
useCache
:
false
,
...
...
package.json
View file @
73e02dc
...
...
@@ -95,6 +95,7 @@
"postcss-sprites"
:
"^3.1.2"
,
"postcss-use"
:
"^2.0.2"
,
"precss"
:
"^1.4.0"
,
"request-ip"
:
"^1.2.3"
,
"rewire"
:
"^2.5.1"
,
"shelljs"
:
"^0.7.0"
,
"stylelint"
:
"^7.1.0"
,
...
...
public/helper/https.js
0 → 100644
View file @
73e02dc
/**
* 链接改成自适应链接
* @return {[type]}
*/
module
.
exports
=
function
(
url
)
{
return
url
.
replace
(
'http:'
,
''
);
};
...
...
public/js/product/item.page.js
View file @
73e02dc
...
...
@@ -49,8 +49,12 @@ require('../plugins/share');
lazyload
(
$
(
'img.lazy'
));
recProduct
.
init
({
url
:
'/product/getRecommendShop'
,
dom
:
'.recommend-product'
,
isGoodsDetail
:
true
isGoodsDetail
:
true
,
params
:
{
productSkn
:
'51085370'
}
});
function
changeThumb
(
$dom
)
{
...
...
public/js/product/item/recommend-product.js
View file @
73e02dc
...
...
@@ -3,37 +3,112 @@
* @author: wsl<shuiling.wang@yoho.cn>
* @date: 2016/11/21
*/
var
recProduct
=
require
(
'../../../tpl/product/recommend-product.hbs'
);
var
recTemplet
=
require
(
'../../../tpl/product/recommend-templet.hbs'
);
var
recProduct
=
require
(
'../../../tpl/product/recommend-product.hbs'
),
recTemplet
=
require
(
'../../../tpl/product/recommend-templet.hbs'
);
var
recommmendProduct
=
{
init
:
function
(
params
)
{
var
_this
=
this
;
var
obj
=
{
isGoodsDetail
:
false
};
recommendPage
:
0
,
recentPreviewPage
:
0
,
init
:
function
(
obj
)
{
var
_this
=
this
,
params
=
obj
.
params
||
{},
$dom
=
$
(
obj
.
dom
),
url
=
obj
.
url
||
'/product/getRecommendProduct'
;
if
(
params
.
isGoodsDetail
)
{
obj
.
isGoodsDetail
=
true
;
}
$dom
.
append
(
recTemplet
({
isGoodsDetail
:
obj
.
isGoodsDetail
?
true
:
false
}));
$
.
extend
(
_this
,
{
$changeBtn
:
$dom
.
find
(
'.change-btn'
),
$dom
:
$dom
});
_this
.
getProducts
({
url
:
url
,
index
:
0
,
params
:
params
});
$dom
.
find
(
'.head-tab'
).
on
(
'click'
,
function
()
{
var
index
=
$
(
this
).
index
(),
$tabCont
=
$
(
'.tab-cont-'
+
index
);
$
(
'.head-tab'
).
removeClass
(
'active'
);
$
(
this
).
addClass
(
'active'
);
if
(
$tabCont
.
find
(
'.goods-group'
).
length
===
0
&&
index
===
1
)
{
_this
.
getProducts
({
url
:
'/product/recentPreview'
,
index
:
index
,
params
:
{
limit
:
20
}
});
}
_this
.
isShowChangeBtn
(
$tabCont
.
find
(
'.goods-group'
).
length
);
$tabCont
.
removeClass
(
'hide'
).
siblings
().
addClass
(
'hide'
);
});
_this
.
$changeBtn
.
on
(
'click'
,
function
()
{
var
index
=
$
(
'.recommend-header .active'
).
index
(),
$goodsGroup
=
$
(
'.tab-cont-'
+
index
).
find
(
'.goods-group'
),
currPage
=
0
;
$
(
params
.
dom
).
append
(
recTemplet
(
obj
));
if
(
$goodsGroup
.
length
>
1
)
{
if
(
index
===
1
)
{
currPage
=
_this
.
countPage
(
_this
.
recentPreviewPage
,
$goodsGroup
);
_this
.
recentPreviewPage
=
currPage
;
}
else
{
currPage
=
_this
.
countPage
(
_this
.
recommendPage
,
$goodsGroup
);
_this
.
recommendPage
=
currPage
;
}
}
_this
.
getRecommendProduct
({
page
:
1
,
dom
:
params
.
dom
$goodsGroup
.
eq
(
currPage
).
show
().
siblings
().
hide
();
_this
.
lazyImage
();
});
},
getRecommendProduct
:
function
(
params
)
{
$
.
get
(
'/product/getRecommendProduct'
,
{
page
:
params
.
page
},
function
(
data
)
{
if
(
data
)
{
$
(
params
.
dom
).
find
(
'.goods-area'
).
html
(
recProduct
(
data
));
countPage
:
function
(
page
,
$goodsGroup
)
{
var
currPage
=
0
;
page
++
;
if
(
page
>
$goodsGroup
.
length
-
1
)
{
currPage
=
0
;
}
else
{
currPage
=
page
;
}
return
currPage
;
},
getProducts
:
function
(
obj
)
{
var
_this
=
this
;
$
.
get
(
obj
.
url
,
obj
.
params
,
function
(
result
)
{
if
(
result
)
{
_this
.
$dom
.
find
(
'.tab-cont-'
+
obj
.
index
).
html
(
recProduct
({
result
:
result
}));
_this
.
lazyImage
();
_this
.
isShowChangeBtn
(
result
.
length
);
}
});
},
isShowChangeBtn
:
function
(
currGoodsLen
)
{
if
(
currGoodsLen
<=
1
)
{
this
.
$changeBtn
.
hide
();
}
else
{
this
.
$changeBtn
.
show
();
}
},
lazyImage
:
function
()
{
$
(
'img.lazy'
).
lazyload
({
effect
:
'fadeIn'
});
}
};
require
(
'yoho-jquery-lazyload'
);
module
.
exports
=
recommmendProduct
;
...
...
public/scss/product/_index.css
View file @
73e02dc
@import
'list'
;
@import
'item'
;
@import
'_shop.css'
;
@import
"list"
;
@import
"item"
;
@import
"_shop.css"
;
/* 组件 */
@import
'brand-banner'
;
@import
"brand-banner"
;
@import
"recommend-product"
;
...
...
public/scss/product/_item.css
View file @
73e02dc
...
...
@@ -478,55 +478,6 @@
}
}
.recommend-product
{
width
:
100%
;
margin-bottom
:
55px
;
.recommend-header
{
height
:
40px
;
border-bottom
:
1px
solid
#ddd
;
}
.head-tab
{
width
:
140px
;
height
:
40px
;
line-height
:
42px
;
font-size
:
14px
;
text-align
:
center
;
float
:
left
;
cursor
:
pointer
;
&.active
{
font-weight
:
bold
;
border
:
1px
solid
#ddd
;
border-bottom-color
:
#fff
;
box-sizing
:
border-box
;
}
}
.change-btn
{
float
:
right
;
font-size
:
14px
;
font-weight
:
bold
;
line-height
:
42px
;
.iconfont
{
font-size
:
18px
;
position
:
relative
;
top
:
2px
;
margin-left
:
5px
;
}
}
.product-area
{
img
{
width
:
214px
;
height
:
288px
;
background
:
#f5f7f6
;
}
}
}
.info-block
{
border
:
1px
solid
#f3f3f3
;
padding
:
40px
130px
;
...
...
public/scss/product/_recommend-product.css
0 → 100644
View file @
73e02dc
.recommend-product
{
width
:
100%
;
margin-bottom
:
55px
;
.recommend-header
{
height
:
40px
;
border-bottom
:
1px
solid
#ddd
;
}
.head-tab
{
width
:
140px
;
height
:
40px
;
line-height
:
42px
;
font-size
:
14px
;
text-align
:
center
;
float
:
left
;
cursor
:
pointer
;
&.active
{
font-weight
:
bold
;
border
:
1px
solid
#ddd
;
border-bottom-color
:
#fff
;
box-sizing
:
border-box
;
}
}
.change-btn
{
float
:
right
;
font-size
:
14px
;
font-weight
:
bold
;
line-height
:
42px
;
cursor
:
pointer
;
.iconfont
{
font-size
:
18px
;
position
:
relative
;
top
:
2px
;
margin-left
:
5px
;
}
}
.product-area
{
img
{
width
:
214px
;
height
:
288px
;
background
:
#f5f7f6
;
}
}
.recommend-goods
{
width
:
100%
;
margin
:
0
auto
;
.goods-group
{
display
:
none
;
&:first-child
{
display
:
block
;
}
}
.goods
{
width
:
214px
;
float
:
left
;
margin
:
20px
0
0
20px
;
&:first-child
{
margin-left
:
0
;
}
.goods-img
,
img
{
width
:
214px
;
height
:
288px
;
}
.goods-brand
{
font-size
:
14px
;
font-weight
:
bold
;
text-align
:
center
;
padding
:
15px
0
;
width
:
214px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.goods-name
{
font-size
:
12px
;
text-align
:
center
;
width
:
214px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.goods-price
{
font-size
:
16px
;
font-weight
:
bold
;
text-align
:
center
;
padding
:
15px
0
;
b
{
font-size
:
12px
;
color
:
#878787
;
margin-left
:
15px
;
text-decoration
:
line-through
;
}
}
}
}
}
...
...
public/tpl/product/recommend-product.hbs
View file @
73e02dc
{{#
each
products
}}
<div
class=
"goods"
data-id=
"
{{
productId
}}
"
data-url=
"
{{
url
}}
"
>
<div
class=
"goods-img"
>
<a
href=
"
{{
https
url
}}
"
target=
"_blank"
>
<img
class=
"lazy"
data-original=
"
{{
image
defaultImages
263
351
}}
"
width=
"263"
height=
"351"
alt=
""
>
</a>
</div>
<div
class=
"goods-brand"
>
{{
brandName
}}
</div>
<div
class=
"goods-name"
>
{{
productName
}}
</div>
<div
class=
"goods-price"
>
<span>
¥
{{
round
salesPrice
}}
</span>
</div>
{{#
each
result
}}
<div
class=
"goods-group"
>
{{#
list
}}
<div
class=
"goods"
>
<a
href=
"
{{
goodsUrl
}}
"
target=
"_blank"
>
<div
class=
"goods-img"
>
<img
class=
"lazy"
src=
""
data-original=
"
{{
image
default_images
214
288
}}
"
width=
"214"
height=
"288"
alt=
""
>
</div>
<div
class=
"goods-brand"
>
{{
brand_name
}}
</div>
<div
class=
"goods-name"
>
{{
product_name
}}
</div>
<div
class=
"goods-price"
>
<span>
¥
{{
round
sales_price
}}
</span>
{{#if
market_price
}}
<b>
¥
{{
round
market_price
}}
</b>
{{/if}}
</div>
</a>
</div>
{{/
list
}}
</div>
{{/
each
}}
...
...
public/tpl/product/recommend-templet.hbs
View file @
73e02dc
...
...
@@ -3,4 +3,7 @@
<span
class=
"head-tab"
>
最近浏览
</span>
<span
class=
"change-btn"
>
换一批
<i
class=
"iconfont"
>

</i></span>
</div>
<div
class=
"goods-area clearfix"
></div>
<div
class=
"recommend-goods clearfix"
>
<div
class=
"tab-cont-0"
></div>
<div
class=
"tab-cont-1 hide"
></div>
</div>
...
...
Please
register
or
login
to post a comment