Authored by 毕凯

Merge remote-tracking branch 'origin/feature/news' into gray

... ... @@ -2,6 +2,7 @@
const api = global.yoho.API;
const serviceAPI = global.yoho.ServiceAPI;
const _ = require('lodash');
const rp = require('request-promise');
/* 微信相关 */
const wxCode = {
... ... @@ -315,30 +316,30 @@ const getWxUserInfo = (params) => {
params.code + '&grant_type=authorization_code';
let url2 = 'https://api.weixin.qq.com/sns/userinfo?lang=zh_CN';
return api._requestFromAPI({
return rp({
url: url1,
qs: {},
json: true,
gzip: true,
timeout: 3000
})
.then((result) => {
if (_.isEmpty(result.openid)) {
return false;
}
url2 = url2 + '&access_token=' + result.access_token +
}).then((result) => {
if (_.isEmpty(result.openid)) {
return false;
}
url2 = url2 + '&access_token=' + result.access_token +
'&openid=' + result.openid;
return api._requestFromAPI({
url: url2,
qs: {},
json: true,
gzip: true,
timeout: 3000
})
.then((result2) => {
return result2;
});
return rp({
url: url2,
qs: {},
json: true,
gzip: true,
timeout: 3000
}).then((result2) => {
return result2;
});
});
};
/**
... ...
/**
* guang controller
* @author: lcy<chuanyang.liu@yoho.cn>
* @date: 2016/08/31
*/
'use strict';
const headerModel = require('../../../doraemon/models/header'); // 头部model
const newsService = require('../models/news-service');
/**
* 首页文章列表 类型列表
*/
exports.index = (req, res, next) => {
let channel = req.yoho.channel;
req.ctx(newsService).getIndexList(channel, req.query).then(result => {
if (result.msgs.length <= 0) {
res.set('Cache-Control', 'no-cache');
}
return res.render('news-index', Object.assign({
title: '新闻 | ' + (res.locals.title || ''),
pageHeader: headerModel.setNav({
navTitle: '新闻'
}),
module: 'news',
localCss: true,
page: 'index'
}, result));
}).catch(next);
};
/**
* 文章详情
*/
exports.detail = (req, res, next) => {
let channel = req.yoho.channel;
let id = req.params[0] || 0;
let cid = req.params[1] || 0;
let query = {
channel: channel,
id: id,
cid: cid,
};
if (!id || !cid) {
return next();
}
req.ctx(newsService).detail(channel, query).then(result => {
return res.render('news-detail', Object.assign({
pageHeader: headerModel.setNav({
navTitle: result.header && result.header.title || '新闻详情页'
}),
module: 'news',
localCss: true,
page: 'detail'
}, result));
}).catch(next);
};
/**
* 文章详情
*/
exports.pageData = (req, res, next) => {
let channel = req.yoho.channel;
req.ctx(newsService).pageData(channel, req.query).then(result => {
return res.render('news-page', Object.assign({
layout: false
}, result));
}).catch(next);
};
... ...
/**
* news
* @author: xiaoxiao<xiaoxiao.hao@yoho.cn>
* @date: 2017/10/13
*/
'use strict';
var express = require('express'),
path = require('path'),
hbsEvent = require('../../config/hbsevent');
var app = express();
// set view engin
var doraemon = path.join(__dirname, '../../doraemon/views'); // parent view root
app.disable('x-powered-by');
app.on('mount', function(parent) {
delete parent.locals.settings; // 不继承父 App 的设置
Object.assign(app.locals, parent.locals);
});
app.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [path.join(__dirname, 'views/partial')],
views: path.join(__dirname, 'views/action'),
helpers: global.yoho.helpers,
cb: hbsEvent.cb
}));
// router
app.use(require('./router'));
module.exports = app;
... ...
'use strict';
module.exports = class extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
}
getPolymerizationList(params) {
return this.get({
url: 'yohonow/api/page/getPolymerizationList',
data: params,
param: {
cache: true
},
api: global.yoho.YohoNowApi
});
}
getContentDetail(params) {
return this.get({
url: 'yohoboyins/v5/channel/getContentDetail',
data: {parameters: JSON.stringify(params)},
param: {
cache: true
},
api: global.yoho.YohoNowApi
});
}
/**
* 推荐文章
*/
getRecoArticles(params) {
return this.get({
url: 'guang/api/v2/article/getArticleByViewsNum',
data: params,
param: {
cache: true
},
api: global.yoho.ServiceAPI
});
}
/**
* 获取广告数据
* @param {String} channelType 传入频道页类型,值可以是: boys, girls, kids, lifestyle
* @return {Object}
*/
getAds(params) {
if (params.isAdDegrade) {
return Promise.resolve({});
}
return this.get({
url: 'operations/api/v5/resource/get',
data: params,
param: {
cache: true
},
api: global.yoho.ServiceAPI
});
}
};
... ...
'use strict';
const _ = require('lodash');
const helpers = global.yoho.helpers;
const NewsAPi = require('./news-api');
const utils = require('./utils');
const moment = require('moment');
const ATYPE = 'yohobuy4008899646,yohogroup,YOHO_GIRL,mars-app';
module.exports = class extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
}
_formatArticle(rdata) {
let list = _.get(rdata, 'data.content', []);
let total = _.get(rdata, 'data.total', 0);
let lresult = {};
let width = 640;
let height = 275;
let result = _.map(list, (articleData) => {
articleData.image += '?imageView2/{mode}/w/{width}/h/{height}';
lresult = {
id: articleData.id,
url: helpers.urlFormat(`/news/${articleData.id}_${articleData.cid}.html`),
img: helpers.image(articleData.image, width, height, 1),
title: articleData.title,
publishTime: articleData.update_time && moment(articleData.update_time * 1000).format('MM月DD HH:mm'),
text: articleData.summary,
isVideo: articleData.videoUrl ? true : false
};
return lresult;
});
return {msgs: {info: result}, totalCount: total};
}
getIndexList(channel, param) {
let newsAPi = new NewsAPi(this.ctx);
let params = {
type: 'wechat',
limit: 20,
page: param.page || 1
};
return newsAPi.getPolymerizationList(Object.assign({}, params, {id: param.atype || ATYPE})).then(result => {
let responseData = {};
// 列表数据
Object.assign(responseData, this._formatArticle(result));
return responseData;
});
}
pageData(channel, param) {
let newsAPi = new NewsAPi(this.ctx);
let params = {
type: 'wechat',
limit: 20,
page: param.page || 1
};
return newsAPi.getPolymerizationList(Object.assign({}, params, {id: param.atype || ATYPE})).then(result => {
let responseData = {};
// 列表数据
Object.assign(responseData, this._formatArticle(result));
return responseData;
});
}
_formatDetail(rdata) {
let contents = _.get(rdata, 'data.contents', {});
let header = {
title: contents.title,
summary: contents.summary,
tag: contents.tag,
publishTime: contents.update_time && moment(contents.update_time * 1000).format('MM月DD HH:mm'),
};
let content = utils.filterPhtml(contents.content, [
'阅读原文',
'点击这里',
'点这里'
]);
return {header: header, content: utils.filterAhtml(content)};
}
detail(channel, param) {
let params = {
id: param.id,
cid: param.cid
};
let newsAPi = new NewsAPi(this.ctx);
return newsAPi.getContentDetail(params).then(result => {
let responseData = {};
// 详情页数据
Object.assign(responseData, this._formatDetail(result, params));
// seo
let title = _.get(responseData, 'header.title', '新闻详情页');
let keywords = [];
let tags = _.compact(_.get(responseData, 'header.tag', []).map(el => {
return el.tag_name;
}));
keywords.push(title, tags.slice(0, 3).join('、'), 'YOHO!BUY有货');
Object.assign(responseData, {
title: `${title} | YOHO!BUY有货`,
keywords: keywords.join('、'),
description: _.get(responseData, 'header.summary', _.get(this.ctx, 'res.locals.description'))
});
return responseData;
});
}
};
... ...
'use strict';
const _ = require('lodash');
const cheerio = require('cheerio');
const util = {
// 过滤指定字符的p标签
filterPhtml: (html, filters) => {
if (!html) {
return html;
}
let $ = cheerio.load(html, {decodeEntities: false});
_.each($('p'), (item) => {
let ele = $(item);
let phtml = ele.html();
_.each(filters, ft => {
if (phtml.indexOf(ft) >= 0) {
ele.remove();
}
});
});
return $.html();
},
// 过滤 a标签连接和删除html标签中的script和link脚本
filterAhtml: (html) => {
if (!html) {
return html;
}
let $ = cheerio.load(html, {decodeEntities: false});
$('a').attr('href', 'javascript:void(0);').css({cursor: 'text'});// eslint-disable-line
$('script,link').remove();
return $.html();
}
};
module.exports = util;
... ...
/**
* news
* @author: xiaoxiao<xiaoxiao.hao@yoho.cn>
* @date: 2017/10/13
*/
'use strict';
const router = require('express').Router(); // eslint-disable-line
const cRoot = './controllers';
const newsController = require(`${cRoot}/index`);
router.get(['/', '/index/index'], newsController.index);
router.get(/\/([\d]+)_([\d]+).html/, newsController.detail);
// ajax
router.get(['/', '/index/page'], newsController.pageData);
module.exports = router;
... ...
<div class="news-detail-page news-page yoho-page">
<div class="detail" data-id="{{id}}">
{{# header}}
<div class="post-title">
<p class="title">{{title}}</p>
{{> news-index/tvls}}
</div>
{{/header}}
<div class="post-content">
{{{content}}}
</div>
</div>
</div>
... ...
<div class="news-list-page news-page yoho-page">
{{# msgs}}
<div id="info-list" class="info-list-container">
<div class="info-list">
{{# info}}
{{> news-index/info}}
{{/ info}}
</div>
</div>
<div id="load-more-info" class="load-more-info">
<div class="loading status hide">
正在加载...
</div>
<span class="no-more status">没有更多啦</span>
</div>
{{/ msgs}}
</div>
{{> footer-tab}}
... ...
{{# msgs.info}}
{{> news-index/info}}
{{/ msgs.info}}
... ...
<div class="news-info" data-id="{{id}}">
{{# author}}
<a class="info-author clearfix"{{#if url}} href="{{url}}"{{/if}}>
<img class="lazy avatar" data-original="{{image2 avatar mode=2 q=60}}">
<span class="name">{{name}}</span>
{{#if minCategory}}
<span class="min-tag">#{{minCategory}}</span>
{{/if}}
</a>
{{/ author}}
<div class="info-img">
{{#if showTags}}
<a href="javascript:;" class="info-match hide">
{{# isTip}}
小贴士
<div class="info-tag tip"></div>
{{/ isTip}}
{{# isCollocation}}
搭配
<div class="info-tag collocation"></div>
{{/ isCollocation}}
{{# isFashionMan}}
潮人
<div class="info-tag fashion-man"></div>
{{/ isFashionMan}}
{{# isFashionGood}}
潮品
<div class="info-tag fashion-good"></div>
{{/ isFashionGood}}
{{# isTopic}}
话题
<div class="info-tag topic"></div>
{{/ isTopic}}
{{# isSpecialTopic}}
专题
<div class="info-tag special-topic"></div>
{{/ isSpecialTopic}}
{{# isVideo}}
视频
<div class="info-tag video"></div>
{{/ isVideo}}
{{# isShow}}
SHOW
<div class="info-tag show"></div>
{{/ isShow}}
</a>
{{/if}}
<a class="img-box"{{#unless isShow}} href="{{url}}"{{/unless}}>
{{#if @first}}
<img src="{{image2 img q=60}}" alt="{{alt}}">
{{^}}
<img class="lazy" data-original="{{image2 img q=60}}" alt="{{alt}}">
{{/if}}
{{#if isVideo}}
<div class="play"></div>
{{/if}}
</a>
</div>
<div class="info-deps">
<a class="info-title-container"{{#unless isShow}} href="{{url}}"{{/unless}}>
<div class="info-title">{{#if top}}<span class="top-tag">置顶</span>{{/if}}{{title}}</div>
</a>
<p class="info-text">{{text}}</p>
{{> news-index/tvls}}
</div>
{{#unless @root.isApp}}
{{#if productList}}
<div class="product-list-box">
<ul class="product-list">
{{#productList}}
{{> news-index/product-list}}
{{/productList}}
</ul>
</div>
{{/if}}
{{/unless}}
</div>
... ...
<li class="goods-box">
<div class="goods-img">
<a href="{{href}}">
<img class="lazy" data-original="{{image2 pic_url w=106 h=138}}" />
</a>
</div>
<div class="goods-info">
<a href="{{href}}">
<p class="title">{{product_name}}</p>
<p class="price">¥{{price}}</p>
</a>
</div>
</li>
\ No newline at end of file
... ...
<div class="time-view-like-share clearfix">
<i class="iconfont">&#xe603;</i>
{{publishTime}}&nbsp;&nbsp;&nbsp;&nbsp;
{{#if pageView}}
<i class="iconfont">&#xe602;</i>
<span class="page-view">{{pageView}}</span>
{{/if}}
<div class="like-share-container">
{{#like}}
<i class="iconfont like-btn{{#isLiked}} like{{/isLiked}}">&#xe601;</i>
<span class="like-count">{{count}}</span>
{{/ like}}
{{# collect}}
<i class="iconfont collect-btn{{#isCollected}} collected{{/isCollected}}">&#xe605;</i>
{{/ collect}}
{{# share}}
<a href="{{.}}" class="iconfont share-btn">&#xe600;</a>
{{/ share}}
</div>
</div>
... ...
... ... @@ -20,7 +20,8 @@ const domains = {
platformApi: 'http://192.168.102.48:8088/',
store: 'http://192.168.102.47:8080/portal-gateway/wechat/',
extstore: 'http://extstore-test1.yohops.com',
family: 'http://192.168.103.73:8096/uic/'
family: 'http://192.168.103.73:8096/uic/',
yohoNowApi: 'http://yohonow-test.yohops.com:9999/'
};
module.exports = {
... ... @@ -145,7 +146,8 @@ if (isProduction) {
imCs: 'https://imhttp.yohobuy.com/api',
platformApi: 'http://api.platform.yohoops.org',
extstore: 'http://extstore.yohobuy.com',
family: 'http://uic.yoho.cn/uic/'
family: 'http://uic.yoho.cn/uic/',
yohoNowApi: 'http://new.yohoboys.com/'
},
memcache: {
master: [
... ... @@ -231,7 +233,8 @@ if (isProduction) {
imCs: process.env.TEST_IM_CS || 'http://im.yohobuy.com/api',
platformApi: 'http://192.168.102.48:8088/',
extstore: 'http://extstore-test1.yohops.com',
family: 'http://192.168.103.73:8096/uic/'
family: 'http://192.168.103.73:8096/uic/',
yohoNowApi: process.env.YOHO_NOW_API || 'http://yohonow-test.yohops.com:9999/'
},
memcache: {
master: ['192.168.104.15:12111', '192.168.104.29:12111', '192.168.104.32:12111'],
... ...
... ... @@ -16,6 +16,7 @@ module.exports = app => {
// 业务模块
app.use('/product', require('./apps/product'));
app.use('/guang', require('./apps/guang'));
app.use('/news', require('./apps/news'));
app.use('/activity', require('./apps/activity'));
app.use('/cart', require('./apps/cart'));
... ...
{
"name": "m-yohobuy-node",
"version": "6.2.2",
"version": "6.2.3",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ...
/**
* 新闻列表
* @author: xiaoxiao<xiaoxiao.hao@yoho.cn>
* @date: 2017/10/18
*/
require('news/detail.page.css');
require('common');
... ...
/**
* 新闻列表
* @author: xiaoxiao<xiaoxiao.hao@yoho.cn>
* @date: 2017/10/20
*/
require('news/index.page.css');
const NewsIndexController = require('./news-index/controller');
new NewsIndexController();
... ...
'use strict';
import {
Controller
} from 'yoho-mvc';
import {
IndexView
} from './view';
class IndexController extends Controller {
constructor() {
super();
this.init();
}
init() {
new IndexView().init();
}
}
module.exports = IndexController;
... ...
let tip = require('plugin/tip');
let mvc = require('yoho-mvc');
export class IndexModel {
loadMoreAjax(option) {
return mvc.http(option).catch(() => {
tip.show('网络断开了~~');
});
}
}
... ...
import {
View
} from 'yoho-mvc';
import {
IndexModel
} from './model';
let lazyLoad = require('yoho-jquery-lazyload');
let ellipsis = require('yoho-mlellipsis');
export class IndexView extends View {
constructor() {
super();
}
init() {
let that = this;
let $loadMoreInfo = $('#load-more-info');
ellipsis.init();
this.indexModel = new IndexModel();
this.selector = {
searching: false,
$win: $(window),
$infoList: $('#info-list'),
$loading: $loadMoreInfo.children('.loading'),
$noMore: $loadMoreInfo.children('.no-more'),
$infos: $('#info-list').children('.info-list'),
};
this.navState = [{
page: 2,
end: false
}];
// srcoll to load more
$(document).scroll(function() {
window.requestAnimationFrame(function() {
that.scrollHandler.apply(that, []);
});
});
this.setLazyLoadAndMellipsis(this.selector.$infoList.children('.info-list').not('.hide').find('.news-info'));
}
scrollHandler() {
let $c = this.selector.$infos.not('.hide');
if (this.selector.$win.scrollTop() + this.selector.$win.height() >= $(document).height() - 0.25 * $c.height()) {
this.loadMore($c, 0);
}
}
loadMore($container, index) {
let that = this;
if (that.selector.searching || that.navState[index].end) {
return;
}
that.selector.searching = true;
that.selector.$noMore.addClass('hide');
that.selector.$loading.removeClass('hide');
this.indexModel.loadMoreAjax({
type: 'GET',
url: '/news/index/page',
dataType: 'html',
data: that.navState[index]
}).then(rdata => {
that.selector.$loading.addClass('hide');
if (rdata === '') {
that.navState[index].end = true;
that.selector.searching = false;
that.selector.$noMore.removeClass('hide');
return;
}
let $dataHtml = $(rdata);
$container.append($dataHtml);
that.setLazyLoadAndMellipsis($dataHtml.siblings('.news-info'));
that.navState[index].page++;
that.selector.searching = false;
}).catch(() => {
that.selector.searching = false;
});
}
setLazyLoadAndMellipsis($infos) {
lazyLoad($infos.find('img.lazy'));
$infos.each(function() {
let $this = $(this),
$title = $this.find('.info-title'),
$text = $this.find('.info-text');
$title[0].mlellipsis(2);
$text[0].mlellipsis(2);
});
}
}
... ...
@define-mixin relatedTitle {
background: #fff;
line-height: 104px;
font-size: 28px;
color: #444;
text-align: center;
}
$focus-size: 42px;
.news-detail-page {
.news-wrap {
position: relative;
}
#wrapper {
background: #f0f0f0;
}
#wrapper.ios {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: hidden;
&.has-head {
top: 90px;
+ .fixed-top {
top: 90px;
}
}
}
.author {
border-bottom: 1px solid #e0e0e0;
background: #fff;
> a {
display: block;
height: 100%;
}
.avatar {
float: left;
margin-top: 20px;
margin-left: 30px;
width: 50px;
height: 50px;
border-radius: 50%;
}
.name {
float: left;
font-size: 14PX;
color: #000;
padding: 30px 0;
margin-left: 30px;
}
.intro {
float: left;
font-size: 14PX;
color: #b0b0b0;
padding: 30px 0;
margin-left: 30px;
}
}
.post-title {
padding: 16px 0 26px 30px;
background: #fff;
.title {
line-height: 30PX;
font-size: 20PX;
color: #000;
font-weight: bold;
}
}
.post-content {
padding: 0 30px;
background-color: #fff;
img {
height: auto;
}
}
.text-block {
padding: 20px 0;
line-height: 23PX;
font-size: 14PX;
background: #fff;
color: #444;
word-break: break-word;
word-wrap: break-word;
}
.big-img-block {
padding-bottom: 5px;
background: #fff;
position: relative;
img {
width: 100%;
}
}
.big-img-block > .tag-list-box {
left: 0;
bottom: 0;
position: absolute;
padding: 20px;
.label-box {
font-size: 20px;
overflow: hidden;
margin-bottom: 10px;
.lable-focus {
float: left;
display: flex;
align-items: center;
line-height: 46px;
height: 46px;
margin-right: 32px;
.focus-big {
display: flex;
align-items: center;
width: $focus-size;
height: $focus-size;
border-radius: $focus-size;
border: 6px solid rgba(253, 157, 43, 0.5);
justify-content: center;
}
.focus-small {
width: $focus-size;
height: $focus-size;
border-radius: $focus-size;
background: rgba(253, 157, 43, 1);
transform: scale(0.5, 0.5);
margin: -$focus-size;
}
}
.lable-info-box {
background-color: rgba(0, 0, 0, 0.6);
color: #fff;
padding: 0 20px;
border-top-left-radius: 40px;
border-bottom-left-radius: 40px;
float: left;
line-height: 46px;
width: 250px;
height: 46px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.lable-infobox-borderadius {
width: 336px;
border-top-right-radius: 40px;
border-bottom-right-radius: 40px;
}
.lable-info-box > a {
color: #fff;
}
.lable-btn {
background-color: #000;
color: #fff;
padding: 0 20px;
border-top-right-radius: 40px;
border-bottom-right-radius: 40px;
float: left;
line-height: 46px;
height: 46px;
}
.lable-btn > .plus {
font-size: 16px;
}
}
}
.small-img-block {
padding-bottom: 8px;
background: #fff;
img {
float: right;
width: 50%;
&:first-child {
float: left;
}
}
}
.collocation-block {
background: #fff;
.good-info {
width: 260px;
height: 477px;
}
}
.thumb-container {
padding-top: 30px;
padding-left: 20px;
background: transparent resolve("guang/thumb-container-bg.png") no-repeat;
background-size: 200% 100%;
&.fixed-top {
position: fixed;
left: 0;
right: 0;
top: 0;
}
&.fixed-bottom {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.9);
}
&.absolute {
position: absolute;
left: 0;
right: 0;
}
&.static {
position: static;
}
&.hide {
display: none;
}
}
.clothe-type {
position: absolute;
right: 6px;
bottom: 34px;
width: 20px;
height: 20px;
border-radius: 50%;
&.bag {
background: url("/guang/clothes/bag.png");
background-color: #fff;
background-size: 100%;
}
&.cloth {
background: url("/guang/clothes/cloth.png");
background-color: #fff;
background-size: 100%;
}
&.dress {
background: url("/guang/clothes/dress.png");
background-color: #fff;
background-size: 100%;
}
&.headset {
background: url("/guang/clothes/headset.png");
background-color: #fff;
background-size: 100%;
}
&.lamp {
background: url("/guang/clothes/lamp.png");
background-color: #fff;
background-size: 100%;
}
&.pants {
background: url("/guang/clothes/pants.png");
background-color: #fff;
background-size: 100%;
}
&.shoe {
background: url("/guang/clothes/shoe.png");
background-color: #fff;
background-size: 100%;
}
&.swim-suit {
background: url("/guang/clothes/swim-suit.png");
background-color: #fff;
background-size: 100%;
}
&.under {
background: url("/guang/clothes/under.png");
background-color: #fff;
background-size: 100%;
}
&.watch {
background: url("/guang/clothes/watch.png");
background-color: #fff;
background-size: 100%;
}
}
.thumb {
display: inline-block;
position: relative;
margin-right: 22px;
padding-bottom: 30px;
&:last-child {
margin-right: 0;
}
&.focus .thumb-img {
border-color: #000;
}
.thumb-img {
height: 134px;
width: 96px;
border: 1px solid transparent;
}
}
.related-reco-block {
background: #fff;
.one-good {
background-color: #f0f0f0;
margin-bottom: 10px;
border: solid 1px #e0e0e0;
&:last-child {
margin-bottom: 0;
}
.thumb {
float: left;
height: 204px;
width: 152px;
margin: 0;
padding: 0;
}
.content-container {
width: 404px;
float: left;
font-size: 22px;
margin-left: 20px;
padding-right: 30px;
height: 206px;
position: relative;
span {
display: inline-block;
line-height: 24px;
}
.price {
line-height: 53px;
}
.go-detail {
color: #444;
position: absolute;
bottom: 20px;
right: 30px;
}
.detail-arr {
vertical-align: baseline;
}
.iconfont {
font-size: 18px;
}
}
.reco-name {
margin-top: 35px;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
height: 60px;
span {
line-height: 30px;
height: 60px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
.sale-price {
color: #d0021b;
line-height: 1.5;
}
.sale-price.no-price {
color: #000;
}
.market-price {
margin-left: 5px;
color: #b0b0b0;
text-decoration: line-through;
line-height: 1.5;
}
.check-detail {
display: block;
background-color: #444;
color: #fff;
border-radius: 20px;
height: 40px !important;
line-height: 40px !important;
text-align: center;
float: right;
width: 70px;
font-size: 28px;
span {
vertical-align: middle;
}
}
.check-detail > .plus {
font-size: 12px;
}
}
}
.related-reco-hide {
max-height: 860px;
overflow: hidden;
}
.related-reco {
padding-bottom: 10px;
}
.related-reco > .related-reco-more {
display: block;
width: 250px;
height: 40px;
line-height: 40px;
margin: 20px auto 0;
text-align: center;
font-size: 22px;
color: #fff;
background-color: #b0b0b0;
padding-left: 15px;
}
.link-block {
display: block;
height: 80px;
line-height: 80px;
padding: 0 30px;
font-size: 28px;
background: #fff;
border-top: 1px solid #e0e0e0;
border-bottom: 1px solid #e0e0e0;
.iconfont {
float: right;
color: #ccc;
}
}
.related-brand {
margin-top: 30px;
h2 {
@mixin relatedTitle ;
}
.brand-list {
padding: 30px 0;
background: #fff;
}
.brand {
float: left;
width: 158px;
height: 128px;
margin-bottom: 10px;
a {
display: block;
}
&:nth-child(4n) {
border-right: none;
}
}
.brand-logo {
display: table-cell;
width: 158px;
height: 94px;
vertical-align: middle;
img {
display: block;
max-width: 158px;
max-height: 94px;
vertical-align: middle;
margin: 0 auto;
}
}
.brand-name {
margin: 10px 0 0;
line-height: 24px;
font-size: 12PX;
color: #babac2;
text-align: center;
text-decoration: none;
border-bottom: none;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.related-tag {
position: relative;
padding-bottom: 30px;
border-top: 1px solid #e0e0e0;
border-bottom: 1px solid #e0e0e0;
background: #fff;
.tag-bg {
position: absolute;
height: 20PX;
width: 20PX;
background: resolve("guang/tag.png") no-repeat;
background-size: 100% 100%;
top: 35px;
left: 20px;
}
li {
float: left;
margin-top: 30px;
margin-left: 30px;
background-color: #444;
padding: 5px 11px;
}
a {
height: 40px;
font-size: 18px;
white-space: nowrap;
color: #fff;
}
}
.related-info {
margin-top: 30px;
h2 {
@mixin relatedTitle ;
}
.info-list {
background: #fff;
padding-bottom: 30px;
border-top: 1px solid #e0e0e0;
}
li {
padding-top: 30px;
margin-bottom: 10px;
a {
display: block;
}
img {
float: left;
margin-left: 30px;
width: 182px;
height: 114px;
&.square {
height: 182px;
}
}
}
.title,
.publish-time {
float: left;
width: 360px;
margin-left: 30px;
line-height: 20PX;
color: #444;
font-size: 14PX;
}
.title {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
word-break: break-all;
overflow: hidden;
}
.publish-time {
font-size: 12PX;
margin-top: 0;
color: #b0b0b0;
.iconfont {
font-size: 12PX;
}
}
}
.down-bottom {
height: 44PX;
background: #fff;
}
.weixin {
margin: 20px 0;
text-align: center;
padding: 0 20px;
.ems-cnpl {
width: 47.3%;
display: inline-block;
background: #ededed;
position: relative;
overflow: hidden;
.weixin-img {
width: 100%;
height: 100%;
}
}
a:nth-child(1) {
margin-right: 20px;
}
}
.float-layer-left {
p {
line-height: 22PX;
font-size: 24px;
span {
font-size: 32px;
}
}
}
.news-header {
height: 90px;
line-height: 90px;
background-image: linear-gradient(#323232, #414141);
overflow: hidden;
position: relative;
.iconfont {
color: #fff;
}
.nav-btn {
position: absolute;
left: 0;
top: 0;
bottom: 0;
z-index: 2;
width: 40px;
margin: 0 30px;
text-align: center;
max-height: 90px;
}
.logo {
display: block;
margin: 0 auto;
width: 208px;
height: 87px;
background: resolve("channel/yohologo02.png") no-repeat center center;
background-size: 100%;
}
}
.girls .news-header {
background: rgb(255, 136, 174);
}
.kids .news-header {
background: rgb(122, 217, 249);
}
.lifestyle .news-header {
background: rgb(79, 65, 56);
}
.kids .logo {
font-style: italic;
font-family: "helvetica", "Arial", "榛戜綋";
font-weight: bold;
color: #fff;
}
.overlay {
display: none;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #000;
z-index: 3;
transition: opacity 1s;
}
.share-code {
width: 100%;
background: #fff;
.share-word {
margin-top: 10px;
height: 154px;
line-height: 44px;
text-align: center;
color: #b3b3b3;
}
}
.recommend-products-box {
height: 264px;
margin: 30px 0;
overflow-x: scroll;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
}
.recommend-products-box > .recommend-products-content {
height: 264px;
overflow-y: hidden;
display: inline-flex;
background-color: #fff;
padding: 30px;
padding-right: 0;
.recommend-goods {
width: 152px;
height: 204px;
margin-right: 30px;
float: left;
position: relative;
overflow: hidden;
}
.recommend-goods > img {
width: 152px;
height: 204px;
}
.recommend-goods > .recommend-goods-cover {
width: 152px;
height: 30px;
line-height: 18px;
font-size: 18px;
color: #fff;
background-color: rgba(0, 0, 0, 0.6);
text-align: center;
position: absolute;
bottom: 0;
padding: 6px;
}
}
video {
width: 100%;
}
.related-reco.change-display {
.one-good {
width: 275px;
float: left;
margin-right: 30px;
margin-bottom: 25px;
&:nth-last-child(1) {
margin-bottom: 0;
}
&:nth-last-child(2) {
margin-bottom: 0;
}
.thumb {
width: 275px;
height: 365px;
}
&:nth-child(even) {
margin-right: 0;
}
.content-container {
position: relative;
width: 275px;
margin-left: 0;
height: 130px;
padding: 0 15px;
.price {
height: 50px;
}
.go-detail {
right: 15px;
bottom: 0;
line-height: 50px;
}
}
.reco-name {
margin-top: 20px;
height: 60px;
white-space: normal;
span {
line-height: 30px;
height: 60px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
.content-container > p {
position: absolute;
right: 15px;
bottom: 10px;
}
}
.related-reco-more {
display: none;
}
.related-reco-hide {
max-height: auto;
overflow: visible;
}
}
}
.news-detail-page.menu-open {
transform: translateX(540px);
}
... ...
.news-list-page {
.editor-header {
margin-bottom: 15PX;
padding-top: 18PX;
padding-bottom: 20PX;
background: #fff;
border-bottom: 1px solid #e0e0e0;
}
.avatar {
float: left;
margin-left: 30px;
img {
width: 50PX;
height: 50PX;
border-radius: 50%;
}
}
.text {
float: left;
margin-left: 32px;
width: 475px;
.name {
font-size: 16PX;
line-height: 20PX;
}
.info {
margin-top: 6px;
color: #bdbdbf;
font-size: 12PX;
line-height: 16PX;
}
}
.swiper-container {
width: 100%;
height: 310px;
img {
height: 100%;
width: 100%;
}
.swiper-pagination {
bottom: 0;
left: 0;
width: 100%;
}
.swiper-pagination-bullet-active {
background: #fff;
}
}
.news-nav {
background-color: #fff;
overflow: hidden;
width: 640px;
height: 80px;
display: flex;
justify-content: space-around;
}
.news-nav-item {
width: 20%;
color: #ccc;
font-size: 14PX;
text-align: center;
line-height: 80px;
&.focus {
color: #000;
}
}
.bytouch {
background: #eee;
}
.info-list-container {
overflow-x: hidden;
background: #f0f0f0;
}
.info-list.hide {
display: none;
}
.search-divide {
float: left;
height: 50px;
width: 100%;
padding: 10px 0;
color: #ccc;
text-align: center;
margin-bottom: 40px;
}
.load-more-info {
margin-bottom: 90px;
}
}
... ...
.news-info {
margin-bottom: 30px;
padding: 0 0 24px;
border-top: 1px solid #e0e0e0;
border-bottom: 1px solid #e0e0e0;
background: #fff;
.info-author {
display: block;
width: 100%;
.avatar {
float: left;
margin-top: 20px;
width: 50px;
height: 50px;
margin-left: 30px;
border-radius: 50%;
}
.name {
float: left;
margin-left: 30px;
padding: 30px 0;
font-size: 14PX;
color: #000;
}
.min-tag {
float: right;
min-width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
background-color: #f0f0f0;
font-size: 20px;
color: #b0b0b0;
margin-right: 30px;
margin-top: 25px;
padding: 0 10px;
}
}
&:last-child {
margin-bottom: 0;
}
.info-img {
position: relative;
width: 100%;
img {
display: block;
}
.play {
position: absolute;
width: 140px;
height: 140px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-image: url("/guang/play-btn.png");
}
}
.info-match {
position: absolute;
top: 0;
left: 0;
width: 130px;
height: 50px;
line-height: 50px;
font-size: 14PX;
color: #fff;
background: #000;
text-align: center;
text-decoration: none;
z-index: 1;
}
.info-tag {
position: absolute;
top: 0;
left: 105px;
height: 50px;
width: 50px;
&.collocation {
background-image: url("/guang/info/collocation.png");
}
&.fashion-good {
background-image: url("/guang/info/fashion-good.png");
}
&.fashion-man {
background-image: url("/guang/info/fashion-man.png");
}
&.tip,
&.special-topic {
background-image: url("/guang/info/tip.png");
}
&.topic {
background-image: url("/guang/info/topic.png");
}
&.video {
background-image: url("/guang/info/video.png");
}
&.show {
background-image: url("/guang/info/show.png");
}
}
.info-deps {
margin: 32px 0 0;
padding: 0 40px 0 30px;
.info-title-container {
text-decoration: none;
color: #000;
}
.info-title {
line-height: 44px;
color: #000;
font-size: 20PX;
font-weight: bold;
.top-tag {
font-size: 18px;
color: #d0021b;
padding: 4px 16px;
border: 1px solid #d0021b;
border-radius: 4px;
margin-right: 20px;
}
}
.info-text {
margin: 16px 0 0;
line-height: 46px;
font-size: 14PX;
color: #444;
}
.time-view-like-share {
margin-top: 16px;
}
}
}
... ...
.time-view-like-share {
color: #b0b0b0;
line-height: 38px;
height: 38px;
font-size: 12PX;
.iconfont {
margin-right: 4px;
font-size: 12PX;
color: #ccc;
}
.like-share-container {
display: inline-block;
float: right;
> * {
float: left;
}
.iconfont {
position: relative;
height: 60px;
line-height: 60px;
display: inline-block;
color: #b0b0b0;
width: 60px;
top: -14px;
font-size: 17PX;
text-align: center;
margin-right: 0;
outline: none;
}
.share-btn {
margin-left: 20px;
}
.like-btn.like {
color: #444;
}
.collect-btn {
margin-left: 20px;
&.collected {
color: #d62927;
}
}
}
}
... ...
@import "common/loading";
@import "detail";
@import "tvls";
... ...
@import "common/loading";
@import "info-list";
@import "info";
@import "tvls";
... ...