Authored by 周少峰

Merge branch 'master' into feature/couponcenter

Showing 71 changed files with 4139 additions and 95 deletions

Too many changes to show.

To preserve performance only 71 of 71+ files are displayed.

@@ -33,7 +33,7 @@ exports.getNewArrival = (req, res, next) => { @@ -33,7 +33,7 @@ exports.getNewArrival = (req, res, next) => {
33 let reqBody = req.body, 33 let reqBody = req.body,
34 pageIndex = reqBody.pageIndex, 34 pageIndex = reqBody.pageIndex,
35 pageCount = reqBody.pageCount, 35 pageCount = reqBody.pageCount,
36 - channel = reqBody.type, 36 + channel = reqBody.type || req.yoho.channel,
37 goods = [], 37 goods = [],
38 result = {}; 38 result = {};
39 39
  1 +/**
  2 + * guang controller
  3 + * @author: lcy<chuanyang.liu@yoho.cn>
  4 + * @date: 2016/08/31
  5 + */
  6 +
  7 +'use strict';
  8 +
  9 +let _ = require('lodash');
  10 +
  11 +class Pagination {
  12 +
  13 + constructor() { // url, page, totalRecords, pageSize
  14 +
  15 + let options = {};
  16 + let len = arguments.length;
  17 + let args = [].slice.call(arguments);
  18 + let _pageSize = 0;
  19 +
  20 + if (args.length && _.isPlainObject(args[len - 1])) {
  21 + options = args.pop();
  22 + }
  23 +
  24 + this.baseUrl = args.shift() || options.baseUrl;
  25 + this.page = args.shift() || 1;
  26 + this.totalRecords = args.shift() || 0;
  27 +
  28 + _pageSize = args.shift() || options.pageSize;
  29 +
  30 + this.pageSize = _pageSize || 10;
  31 + this.totalPages = options.totalPages || 0;
  32 + this.theme = options.theme || 'full';
  33 + this.pageVar = options.pageVar || 'page';
  34 + this.pageSizeVar = options.pageSizeVar || 'pageSize';
  35 +
  36 + if (!this.totalPages && this.totalRecords) {
  37 + this.totalPages = Math.ceil(this.totalRecords / this.pageSize);
  38 + }
  39 +
  40 + this.base = this.baseUrl + (this.baseUrl.indexOf('?') < 0 ? '?' : '&') +
  41 + (_pageSize ? (this.pageSizeVar + '=' + this.pageSize + '&') : '') +
  42 + this.pageVar + '=';
  43 + }
  44 +
  45 + hasNextPage() {
  46 + return this.page < this.totalPages;
  47 + }
  48 +
  49 + hasPrevPage() {
  50 + return this.page > 1;
  51 + }
  52 +
  53 + getUrl(page) {
  54 + return this.base + page || 1;
  55 + }
  56 +}
  57 +
  58 +module.exports = Pagination;
  1 +/**
  2 + * guang controller
  3 + * @author: lcy<chuanyang.liu@yoho.cn>
  4 + * @date: 2016/08/31
  5 + */
  6 +
  7 +'use strict';
  8 +
  9 +const _ = require('lodash');
  10 +
  11 +const guangModel = require('../models/index');
  12 +const headerModel = require('../../../doraemon/models/header');
  13 +const ghelper = require('../models/guang-helper');
  14 +const querystring = require('querystring');
  15 +
  16 +/**
  17 + * 首页文章列表 类型列表
  18 + */
  19 +exports.index = (req, res, next) => {
  20 + let channel = req.yoho.channel;
  21 + let page = req.query.page || 1;
  22 + let pageSize = req.query.pageSize || 20;
  23 + let type = req.query.type || 0;
  24 +
  25 + let pathNav = guangModel.getPathNav(channel);
  26 + let uid = req.user.uid;
  27 + let udid = ghelper.getUdid(req, res);
  28 + let gender = ghelper.getGenderByCookie(req);
  29 +
  30 + Promise.all([
  31 + guangModel.getBanner(channel),
  32 + guangModel.getCategory(type, channel),
  33 + guangModel.getArticleList(gender, type, uid, udid, page, '', '', pageSize, channel, true),
  34 + guangModel.getHotTags(page, pageSize, channel),
  35 + guangModel.getAds(channel),
  36 + guangModel.getRecoArticles(gender, 1, 10, channel),
  37 + headerModel.requestHeaderData(channel)
  38 + ]).then(ret => {
  39 + res.render('guang/index', {
  40 + title: '逛' + (res.locals.title || ''),
  41 + guang: {
  42 + slider: ret[0],
  43 + msgTypes: ret[1],
  44 + msgs: ret[2] && ret[2].msgs,
  45 + hotTags: ret[3],
  46 + ads: ret[4],
  47 + exRecos: ret[5],
  48 +
  49 + guangIndexPage: true,
  50 + pageSize: pageSize,
  51 + type: type,
  52 + pathNav: pathNav,
  53 + baseUrl: `?${querystring.stringify(req.query)}`,
  54 + page: page,
  55 + total: (ret[2] && ret[2].total) || 0
  56 + },
  57 + module: 'guang',
  58 + page: 'guang',
  59 + headerData: ret[6] && ret[6].headerData
  60 + });
  61 + }).catch(next);
  62 +
  63 +};
  64 +
  65 +/**
  66 + * 指定标签的文章列表
  67 + */
  68 +exports.tags = (req, res, next) => {
  69 +
  70 + let query = req.query.query;
  71 + let page = req.query.page || 1;
  72 + let pageSize = req.query.pageSize || 20;
  73 + let type = req.query.type || 0;
  74 +
  75 + let uid = req.user.uid;
  76 + let udid = ghelper.getUdid(req, res);
  77 + let gender = ghelper.getGenderByCookie(req);
  78 + let channel = req.yoho.channel;
  79 + let pathNav = guangModel.getPathNav(channel, query);
  80 +
  81 + Promise.all([
  82 + guangModel.getBanner(channel),
  83 +
  84 + guangModel.getArticleList(gender, 0, uid, udid, page, query, '', pageSize, channel, true),
  85 + guangModel.getHotTags(1, 20, channel),
  86 + guangModel.getAds(channel),
  87 + guangModel.getRecoArticles(gender, 1, 10, channel),
  88 + headerModel.requestHeaderData(channel)
  89 + ]).then(ret => {
  90 +
  91 + res.render('guang/tag', {
  92 + title: query + (res.locals.title || ''),
  93 + guang: {
  94 + slider: ret[0],
  95 + msgs: ret[1] && ret[1].msgs,
  96 + hotTags: ret[2],
  97 + ads: ret[3],
  98 + exRecos: ret[4],
  99 +
  100 + tag: query,
  101 + guangIndexPage: true,
  102 + baseUrl: `?${querystring.stringify(req.query)}`,
  103 + pageSize: pageSize,
  104 + type: type,
  105 + pathNav: pathNav,
  106 + page: page,
  107 + total: (ret[1] && ret[1].total) || 0
  108 + },
  109 + module: 'guang',
  110 + page: 'list',
  111 + headerData: ret[5] && ret[5].headerData
  112 + });
  113 + }).catch(next);
  114 +};
  115 +
  116 +/**
  117 + * 作者文章列表
  118 + */
  119 +exports.editor = (req, res, next) => {
  120 +
  121 + let authorId = req.query.author_id;
  122 + let channel = req.yoho.channel;
  123 + let gender = ghelper.getGenderByCookie(req);
  124 +
  125 + let uid = req.user.uid;
  126 + let udid = ghelper.getUdid(req, res);
  127 +
  128 + let pathNav = guangModel.getPathNav(channel);
  129 +
  130 + let page = req.query.page || 1;
  131 + let pageSize = req.query.pageSize || 20;
  132 +
  133 + Promise.all([
  134 + guangModel.getAuthor(authorId),
  135 + guangModel.getArticleList(gender, null, uid, udid, page, '', authorId, pageSize, channel, true),
  136 + guangModel.getHotTags(1, 20, channel),
  137 + guangModel.getAds(channel),
  138 + guangModel.getRecoArticles(gender, 1, 10, channel),
  139 + headerModel.requestHeaderData(channel)
  140 + ]).then(ret => {
  141 + res.render('guang/editor', {
  142 + title: _.get(ret[0], 'name', '') + (res.locals.title || ''),
  143 + guang: {
  144 + editor: ret[0],
  145 + msgs: ret[1] && ret[1].msgs,
  146 + hotTags: ret[2],
  147 + ads: ret[3],
  148 + exRecos: ret[4],
  149 +
  150 + gender: gender,
  151 + baseUrl: `?${querystring.stringify(req.query)}`,
  152 + pageSize: pageSize,
  153 + pathNav: pathNav,
  154 + page: page,
  155 + total: (ret[1] && ret[1].total) || 0
  156 + },
  157 + module: 'guang',
  158 + page: 'list',
  159 + headerData: ret[5] && ret[5].headerData
  160 + });
  161 + }).catch(next);
  162 +};
  163 +
  164 +/**
  165 + * 文章详情
  166 + */
  167 +exports.detail = (req, res, next) => {
  168 +
  169 + let id = req.params.id || req.query.id;
  170 + let page = req.query.page || 1;
  171 + let pageSize = req.query.pageSize || 10;
  172 + let col = req.query.col || 0;
  173 + let pjax = req.query._pjax;
  174 + let uid = req.user.uid;
  175 + let udid = ghelper.getUdid(req, res);
  176 + let gender = ghelper.getGenderByCookie(req);
  177 + let channel = req.yoho.channel;
  178 +
  179 + if (!_.isNumber(id)) {
  180 + id = parseInt(id);
  181 + }
  182 +
  183 + if (pjax) {
  184 + guangModel.getArticleComments(id, page, pageSize).then(ret => {
  185 +
  186 + res.render('guang/detail-comment', {
  187 + layout: false,
  188 + comment: ret
  189 + }, function(err, html) {
  190 + if (err) {
  191 + return res.send('');
  192 + }
  193 + return res.status(200).send(html);
  194 + });
  195 + });
  196 +
  197 + return;
  198 + }
  199 +
  200 + // 登陆后自动收藏
  201 + if (col === 1 && uid > 0) {
  202 + guangModel.collectArticle(id, uid);
  203 + }
  204 +
  205 + guangModel.getArticleInfo(id, channel).then(info => {
  206 +
  207 + // 判断参数是否有效, 无效会跳转到错误页面
  208 + if (!info || !info.title) {
  209 + return new Error('文章不存在');
  210 + }
  211 +
  212 + let promises = [
  213 + headerModel.requestHeaderData(channel),
  214 + guangModel.getArticleContent(id),
  215 + guangModel.getHotTags(1, 20, channel),
  216 + guangModel.getArticleComments(id, page, pageSize),
  217 + guangModel.getArticleBaseInfo(id, uid, udid),
  218 + guangModel.getArticleRelateBrand(id),
  219 + guangModel.getRecoArticles(gender, 1, 10, channel),
  220 + guangModel.getAds(channel)
  221 + ];
  222 +
  223 + if (info.authorId) {
  224 + promises.push(guangModel.getAuthor(info.authorId));
  225 + } else {
  226 + promises.push({});
  227 + }
  228 +
  229 + if (info.tag) {
  230 + promises.push(guangModel.getRelateArticleList(id, info.tag, 2, channel));
  231 + } else {
  232 + promises.push({});
  233 + }
  234 +
  235 + let pathNav = guangModel.getPathNav(channel, info.title);
  236 +
  237 + Promise.all(promises).then(ret => {
  238 +
  239 + res.render('guang/detail', Object.assign({
  240 + module: 'guang',
  241 + page: 'detail',
  242 + headerData: ret[0] && ret[0].headerData,
  243 + guang: {
  244 + pathNav: pathNav,
  245 +
  246 + id: id,
  247 + header: Object.assign({}, info, ret[8] || {},
  248 + { commentNum: _.get(ret[3], 'commentNum', 0) }),
  249 + content: ret[1],
  250 + hotTags: ret[2],
  251 + comment: ret[3],
  252 + commentInfo: req.session['comment_' + udid],
  253 + userInfo: ret[4],
  254 + brands: ret[5],
  255 +
  256 + tag: info.tags,
  257 + relatedPost: (ret[9] && ret[9].length) ? ret[9] : false,
  258 + exRecos: ret[6],
  259 + ads: ret[7],
  260 +
  261 + // 分享
  262 + shareImg: info.shareImg,
  263 + sharedTitle: info.title,
  264 + shareDesc: info.desc,
  265 + weixinUrl: info.weixinUrl
  266 + }
  267 + }, {
  268 + title: `${info.title} | YOHO!BUY有货 | 年轻人潮流购物中心,中国潮流购物风向标,官方授权正品保证`,
  269 + keywords: ['Yoho! 有货,潮流,时尚,流行,购物,B2C,正品,购物网站,网上购物,货到付款,品牌服饰,男士护肤,',
  270 + '黑框眼镜,匡威,板鞋,i.t,izzue,5cm,eastpak,vans,lylescott,g-shock,new balance,lacoste,melissa,',
  271 + 'casio,卡西欧手表,舒雅,jasonwood,odm,AAAA,香港购物,日本潮流'].join(''),
  272 + description: '潮流商品搜索,上衣,衬衫,TEE,卫衣,冲锋衣,风衣,羽绒服,裤子,休闲鞋,板鞋,配饰,复古眼镜',
  273 + webNavHeader: channel
  274 + }));
  275 + }).catch(next);
  276 + });
  277 +};
  278 +
  279 +/**
  280 + * 列表页(列表首页、标签列表页、作者列表页)动态数据,如:查看数,点赞数,评论数,是否点赞,是否回复
  281 + * @param req
  282 + * @param res
  283 + */
  284 +exports.listDynamicData = (req, res) => {
  285 + let ids = req.query.ids;
  286 +
  287 + let udid = ghelper.getUdid(req, res);
  288 +
  289 + let other = {};
  290 + let query = req.query.query,
  291 + type = req.query.type;
  292 +
  293 + if (req.user.uid) {
  294 + other.uid = req.user.uid;
  295 + }
  296 +
  297 + if (query) {
  298 + other.query = query;
  299 + }
  300 +
  301 + if (type) {
  302 + other.type = type;
  303 + }
  304 +
  305 + guangModel.getDynamicDataByIds(ids, udid, other).then(ret => {
  306 + res.send(ret);
  307 + });
  308 +};
  309 +
  310 +/**
  311 + * 详情页动态数据,如:评论数,回复数,是否点赞,是否收藏
  312 + * @param req
  313 + * @param res
  314 + */
  315 +exports.detailDynamicData = (req, res) => {
  316 + let id = req.query.id,
  317 + uid = req.user.uid,
  318 + udid = ghelper.getUdid(req, res);
  319 +
  320 + guangModel.getDynamicDataById(id, uid, udid).then((ret) => {
  321 + res.status(200).send(ret);
  322 + }).catch(() => {
  323 + res.status(400);
  324 + });
  325 +};
  326 +
  327 +/**
  328 + * 添加评论
  329 + */
  330 +exports.comment = (req, res) => {
  331 +
  332 + let id = req.body.id || req.query.id;
  333 + let uid = req.user.uid;
  334 + let udid = ghelper.getUdid(req, res);
  335 + let comment = req.body.comment;
  336 +
  337 + // let pageSize = req.query.pageSize || 20;
  338 +
  339 + if (!uid) {
  340 + req.session['comment_' + udid] = comment;
  341 + return res.send({
  342 + code: 401
  343 + });
  344 + }
  345 +
  346 + guangModel.addComment(id, uid, comment).then(() => {
  347 + if (req.session['comment_' + udid]) {
  348 + req.session['comment_' + udid] = null;
  349 + }
  350 +
  351 + return guangModel.getArticleComments(id, 1, 20);
  352 + }).then(commentInfo => {
  353 +
  354 + res.render('guang/detail-comment', {
  355 + comment: commentInfo,
  356 + layout: false
  357 + }, (err, content) => {
  358 +
  359 + if (err) {
  360 +
  361 + return res.send({
  362 + code: 401
  363 + });
  364 + }
  365 + return res.send({
  366 + code: 200,
  367 + data: {
  368 + count: commentInfo.commentNum,
  369 + content: content
  370 + }
  371 + });
  372 + });
  373 + }).catch(() => {
  374 + return res.send({
  375 + code: 400,
  376 + message: '评论失败'
  377 + });
  378 + });
  379 +};
  380 +
  381 +/**
  382 + * 赞
  383 + */
  384 +exports.praise = (req, res) => {
  385 +
  386 + let id = req.body.id || req.query.id;
  387 +
  388 + // let uid = req.user.uid;
  389 + let udid = ghelper.getUdid(req, res);
  390 +
  391 + guangModel.praise(id, udid).then(ret => {
  392 + res.send(ret);
  393 + }).catch(() => {
  394 + res.send({
  395 + code: 400
  396 + });
  397 + });
  398 +};
  399 +
  400 +/**
  401 + * 取消赞
  402 + */
  403 +exports.cancelPraise = (req, res) =>{
  404 + let id = req.body.id || req.query.id;
  405 + let udid = ghelper.getUdid(req, res);
  406 +
  407 + guangModel.cancelPraise(id, udid).then(ret => {
  408 + res.send(ret);
  409 + }).catch(() => {
  410 + res.send({
  411 + code: 400
  412 + });
  413 + });
  414 +};
  415 +
  416 +/**
  417 + * 收藏
  418 + */
  419 +exports.collect = (req, res) =>{
  420 + let id = req.body.id || req.query.id;
  421 + let uid = req.user.uid;
  422 +
  423 + if (!uid) {
  424 + return res.send({
  425 + code: 401
  426 + });
  427 + }
  428 +
  429 + guangModel.collect(id, uid).then(ret => {
  430 + res.send(ret);
  431 + }).catch(() => {
  432 + res.send({
  433 + code: 400,
  434 + message: '收藏失败'
  435 + });
  436 + });
  437 +};
  438 +
  439 +/**
  440 + * 取消收藏
  441 + */
  442 +exports.cancelCollect = (req, res) =>{
  443 + let id = req.body.id || req.query.id;
  444 + let uid = req.user.uid;
  445 +
  446 + if (!uid) {
  447 + return res.send({
  448 + code: 401
  449 + });
  450 + }
  451 +
  452 + guangModel.cancelCollect(id, uid).then(ret => {
  453 + res.send(ret);
  454 + }).catch(() => {
  455 + res.send({
  456 + code: 400,
  457 + message: '取消收藏失败'
  458 + });
  459 + });
  460 +};
  1 +/**
  2 + * guang
  3 + * @author: lcy<chuanyang.liu@yoho.cn>
  4 + * @date: 2016/09/01
  5 + */
  6 +
  7 +'use strict';
  8 +
  9 +let exphbs = require('express-handlebars').create(),
  10 + Handlebars = exphbs.handlebars;
  11 +
  12 +Handlebars.registerHelper('json', function(json) {
  13 + return new Handlebars.SafeString(JSON.stringify(json));
  14 +});
  15 +
  16 +module.exports = exphbs.handlebars;
  1 +/**
  2 + * guang
  3 + * @author: lcy<chuanyang.liu@yoho.cn>
  4 + * @date: 2016/09/01
  5 + */
  6 +
  7 +'use strict';
  8 +
  9 +let _ = require('lodash');
  10 +let Handlebars = require('handlebars');
  11 +
  12 +let ALL_TYPES = {
  13 + stand: 'p-page-n',
  14 + mini: 'p-n',
  15 + full: 'f-p-page-n-l-info-input-gobtn',
  16 + fullellipsis: 'f-p-pe-n-l-info-input-gobtn',
  17 + ellipsis: 'p-pe-n'
  18 +};
  19 +
  20 +exports.pager = function() {
  21 +
  22 + let options = arguments[arguments.length - 1];
  23 +
  24 + let baseUrl = (arguments.length > 1 ? arguments[0] : null) || options.hash.baseUrl || '',
  25 + page = (options.hash.page || 1) * 1,
  26 + showNum = (options.hash.showNum || 7) * 1,
  27 + pageSize = options.hash.pageSize || 20,
  28 + totalPages = options.hash.totalPages,
  29 + totalRecords = options.hash.totalRecords,
  30 + theme = options.hash.theme || 'pager',
  31 + currentClass = options.hash.currentClass || 'cur',
  32 +
  33 + // min full stand ellipsis or: f-首页, p-上一页, page-页码,n-下一页,l-最后一页,info-displayMsg,inout输入框,gobtn-goto Btn
  34 + type = options.hash.type || 'stand',
  35 + pageVar = options.hash.pageVar || 'page',
  36 + pageSizeVar = options.hash.pageSizeVar || 'pageSize';
  37 +
  38 + // 清除原来page(page=1&) 重新定义page
  39 + let clearPageReg = new RegExp(pageVar + '=[^&]*(&|$)'),
  40 + clearSizeReg = new RegExp(pageSizeVar + '=[^&]*(&|$)'),
  41 + base = baseUrl.replace(clearPageReg, '');
  42 +
  43 + if (options.hash.pageSize) {
  44 + base = base.replace(clearSizeReg, '');
  45 + }
  46 +
  47 + base += (base.indexOf('?') < 0 ? '?' : (base.charAt(base.length - 1) !== '?' ? '&' : '')) +
  48 + (options.hash.pageSize ? (pageSizeVar + '=' + pageSize + '&') : '') +
  49 + pageVar + '=';
  50 +
  51 + function getPageNums(ntype) {
  52 + var pageNums = [];
  53 + var num = showNum;
  54 +
  55 + if (ntype === 'e') {
  56 + num = num - 2;
  57 + num = num > 2 ? num : 2;
  58 + }
  59 +
  60 + /** 分页展示页码个数begin 规则:展示最靠近当前页的指定个数 **/
  61 + let pageShowMax = num % 2 === 0 ? page - 1 : page;
  62 + let pageShowMin = page;
  63 +
  64 + for (let i = 0; i < Math.floor(num / 2); i++) {
  65 + pageShowMax++;
  66 + pageShowMin--;
  67 + if (pageShowMax > totalPages) {
  68 + pageShowMax = totalPages;
  69 + if (pageShowMin > 1) {
  70 + pageShowMin--;
  71 + }
  72 + }
  73 + if (pageShowMin < 1) {
  74 + pageShowMin = 1;
  75 + if (pageShowMax < totalPages) {
  76 + pageShowMax++;
  77 + }
  78 + }
  79 + }
  80 +
  81 + for (let n = pageShowMin; n <= pageShowMax; n++) {
  82 + pageNums.push(n);
  83 + }
  84 +
  85 + if (ntype === 'e') {
  86 + if (pageShowMin > 3) {
  87 + pageNums.unshift(1, '.');
  88 + } else if (pageShowMin === 2) {
  89 + pageNums.unshift(1);
  90 + } else if (pageShowMin === 3) {
  91 + pageNums.unshift(1, 2);
  92 + }
  93 +
  94 + if (pageShowMax < totalPages - 2) {
  95 + pageNums.push('.', totalPages);
  96 + } else {
  97 + for (let x = pageShowMax + 1; x <= totalPages; x++) {
  98 + pageNums.push(x);
  99 + }
  100 + }
  101 + }
  102 +
  103 + return pageNums;
  104 + }
  105 +
  106 + function renderItem(arr) {
  107 + /** 分页展示页码个数end **/
  108 + let ret = '';
  109 +
  110 + if (_.isArray(arr) && arr.length) {
  111 +
  112 + arr.forEach((val) => {
  113 + if (val === '.') {
  114 + ret += '<a>...</a>';
  115 + } else {
  116 + ret += `<a href="${base}${val}" ` +
  117 + (page === val ? `class="${currentClass}"` : '') +
  118 + ` title="第${val}页">${val}</a>`;
  119 + }
  120 + });
  121 + }
  122 +
  123 + return ret;
  124 + }
  125 +
  126 + function createStandItems() {
  127 + return renderItem(getPageNums());
  128 + }
  129 +
  130 + function createEllipsisItems() {
  131 + return renderItem(getPageNums('e'));
  132 + }
  133 +
  134 + if (!totalPages) {
  135 + if (!totalRecords || !pageSize) {
  136 + return new Handlebars.SafeString('');
  137 + } else {
  138 + totalPages = Math.ceil(totalRecords / pageSize);
  139 + }
  140 + }
  141 +
  142 + let items = ALL_TYPES[type] ? ALL_TYPES[type] : type;
  143 +
  144 + items = _.isArray(items) ? items : (items || ALL_TYPES.stand).split('-');
  145 +
  146 + let hasPage = false; // 配置中如果配置了多次 page/pe 则将忽略,只第一次有效
  147 + let ret = `<div class="pager ${theme}">`;
  148 +
  149 + items.forEach(function(val) {
  150 +
  151 + switch (val) {
  152 + case 'f' :
  153 + if (page > 1) {
  154 + ret += `<a href="${base}1" title="首页">首页</a>`;
  155 + }
  156 + break;
  157 + case 'p' :
  158 + if (page > 1) {
  159 + ret += `<a href="${base}` + (page - 1) +
  160 + '" title="上一页"><span class="iconfont">&#xe60e;</span>上一页</a>';
  161 + }
  162 + break;
  163 + case 'n' :
  164 + if (page < totalPages) {
  165 + ret += `<a href="${base}` + (page + 1) +
  166 + '" title="下一页">下一页<span class="iconfont">&#xe60c;</span></a>';
  167 + }
  168 + break;
  169 + case 'l' :
  170 + if (page < totalPages) {
  171 + ret += `<a href="${base}${totalPages}" title="尾页">尾页</a>`;
  172 + }
  173 + break;
  174 + case 'info' :
  175 + ret += '共{totalRecords}条/{totalPages}页';
  176 + break;
  177 + case 'input' :
  178 + // input
  179 + // ret += '<span class="{cls}"><input value="{value}" type="text"></span>';
  180 + break;
  181 + case 'gobtn' :
  182 + // goto btn
  183 + break;
  184 + case 'page' :
  185 + if (!hasPage) {
  186 + ret += createStandItems();
  187 + }
  188 + hasPage = true;
  189 + break;
  190 + case 'pe' :
  191 + if (!hasPage) {
  192 + ret += createEllipsisItems();
  193 + }
  194 + hasPage = true;
  195 + break;
  196 + }
  197 + });
  198 +
  199 + if (options.fn) {
  200 + ret += options.fn(options.context);
  201 + }
  202 + ret += '</div>';
  203 + return new Handlebars.SafeString(ret);
  204 +};
  1 +/**
  2 + * guang
  3 + * @author: lcy<chuanyang.liu@yoho.cn>
  4 + * @date: 2016/08/31
  5 + */
  6 + 'use strict';
  7 +
  8 + var express = require('express'),
  9 + path = require('path'),
  10 + hbs = require('express-handlebars');
  11 +
  12 + var app = express();
  13 +
  14 +// set view engin
  15 + var doraemon = path.join(__dirname, '../../doraemon/views'); // parent view root
  16 + var partials = path.join(__dirname, './views'); // parent view root
  17 +
  18 +
  19 + app.on('mount', function(parent) {
  20 + delete parent.locals.settings; // 不继承父 App 的设置
  21 + Object.assign(app.locals, parent.locals);
  22 + });
  23 +
  24 + app.set('views', path.join(__dirname, 'views/action'));
  25 + app.engine('.hbs', hbs({
  26 + extname: '.hbs',
  27 + defaultLayout: 'layout',
  28 + layoutsDir: doraemon,
  29 + partialsDir: [`${partials}/partial`, `${doraemon}/partial`],
  30 + helpers: Object.assign(require('./helpers/pager'), global.yoho.helpers)
  31 + }));
  32 +
  33 + // require('./helpers/json');
  34 + // require('./helpers/page');
  35 +
  36 +// router
  37 + app.use(require('./router'));
  38 +
  39 + module.exports = app;
  40 +
  1 +/**
  2 + * 逛 model
  3 + * @author: lcy<chuanyang.liu@yoho.cn>
  4 + * @date: 2016/09/06
  5 + */
  6 +
  7 +'use strict';
  8 +
  9 +const md5 = require('md5');
  10 +const requestIp = require('request-ip');
  11 +const _ = require('lodash');
  12 +const helpers = global.yoho.helpers;
  13 +
  14 +/* COOKIE标识访问的是男生频道 */
  15 +// const COOKIE_NAME_BOYS = 'boys';
  16 +// const COOKIE_DOMAIN = '.yohobuy.com';
  17 +
  18 +const getGenderByCookie = (req) => {
  19 + let gender = null;
  20 + let channel = req.yoho.channel;
  21 +
  22 + switch (channel) {
  23 + case 'boys':
  24 + {
  25 + gender = '1,3';
  26 + break;
  27 + }
  28 + case 'girls':
  29 + {
  30 + gender = '2,3';
  31 + break;
  32 + }
  33 + default:
  34 + {
  35 + gender = '1,2,3';
  36 + }
  37 + }
  38 +
  39 + return gender;
  40 +};
  41 +
  42 +/**
  43 + * 获取客户端唯一标识
  44 + *
  45 + * @return string
  46 + */
  47 +const getUdid = (req, res) => {
  48 + let udid = req.cookies.udid;
  49 +
  50 + if (!udid) {
  51 + udid = md5(req.ip || requestIp.getClientIp(req));
  52 +
  53 + if (res && res.cookie) {
  54 + res.cookie('udid', udid);
  55 + }
  56 + }
  57 +
  58 + return udid;
  59 +};
  60 +
  61 +/**
  62 + * 获得文章 url
  63 + * @param type string url 后台返回的url
  64 + * @param type id 产品编号
  65 + * @return type url
  66 + */
  67 +const getArticleUrl = (url, id, channel) => {
  68 +
  69 + /* 格式由url:{url:'aaa'} 更改为 url: 'aaa'
  70 + try {
  71 + let urlObj = JSON.parse(url);
  72 +
  73 + if (urlObj && urlObj['url']) {
  74 + return urlObj['url'];
  75 + }
  76 + } catch (e) {}*/
  77 +
  78 + if (_.isString(url) && _.trim(url) !== '') {
  79 + return url;
  80 + }
  81 +
  82 + let param = {};
  83 +
  84 + if (channel) {
  85 + param.channel = channel;
  86 + }
  87 +
  88 + return helpers.urlFormat(`/${id}.html`, param, 'guang');
  89 +};
  90 +
  91 +module.exports = {
  92 + getGenderByCookie,
  93 + getUdid,
  94 + getArticleUrl
  95 +};
  96 +
  1 +/**
  2 + * 逛 model
  3 + * @author: lcy<chuanyang.liu@yoho.cn>
  4 + * @date: 2016/08/31
  5 + */
  6 +'use strict';
  7 +
  8 +const _ = require('lodash');
  9 +const moment = require('moment');
  10 +const ghelper = require('./guang-helper');
  11 +
  12 +const helpers = global.yoho.helpers;
  13 +const serviceApi = global.yoho.ServiceAPI;
  14 +const yohoApi = global.yoho.API;
  15 +
  16 +// const KEY_WEB_GUANG_BANNER_DATA = 'key_web_guang_banner_data';// 逛的首页banner
  17 +// const KEY_WEB_GUANG_ADS_DATA = 'key_web_guang_ads_data';// 逛的首页ads
  18 +const URL_OPERATIONS_RESOURCE_GET = 'operations/api/v5/resource/get';
  19 +
  20 +// guang banner code
  21 +const BANNER_CODE = {
  22 + boys: '15a288635c2ed9f6c807417be90f5d2d',
  23 + girls: 'e14e12e35af8626650979f7af8a0de2b',
  24 + lifestyle: '1d398e899f759c6d88971be680521a6f',
  25 + kids: 'ad14ee01ad048ce308aa3ca416133d2a'
  26 +};
  27 +
  28 +// 逛 ads code
  29 +const ADS_CODE = {
  30 + boys: '41777aa7ac86347692c5aa0d394b2f59',
  31 + girls: '722253573823ebb994e313e71b0a4fb9',
  32 + lifestyle: '02568b6042510e4be739cc688dc7d6ae',
  33 + kids: '1ffdd6ea22c58af52ee6408cd353c2d5'
  34 +};
  35 +
  36 +/**
  37 + * 获取首页频道nav
  38 + */
  39 +const getHomeChannelNav = (channel) => {
  40 + let home;
  41 +
  42 + switch (channel) {
  43 + case 'girls':
  44 + home = helpers.urlFormat('/woman', '', 'new');
  45 + break;
  46 + case 'lifestyle':
  47 + home = helpers.urlFormat('/lifestyle', '', 'new');
  48 + break;
  49 + case 'kids':
  50 + home = helpers.urlFormat('/kids', '', 'new');
  51 + break;
  52 + default:
  53 + home = helpers.urlFormat('', '', 'default');
  54 +
  55 + }
  56 +
  57 + return {
  58 + href: home,
  59 + name: `${channel.toUpperCase()}首页`,
  60 + pathTitle: 'YOHO!有货'
  61 + };
  62 +};
  63 +
  64 +const getPathNav = (channelType, query) => {
  65 +
  66 + let path = _.concat(
  67 + getHomeChannelNav(channelType),
  68 + [{
  69 + name: '逛',
  70 + pathTitle: '逛',
  71 + href: helpers.urlFormat('', '', 'guang')
  72 + }]
  73 + );
  74 +
  75 + return query ? _.concat(path, [{ name: query, pathTitle: query}]) : path;
  76 +};
  77 +
  78 +const _formatTag = (tagData, channel) => {
  79 + let name = tagData.name,
  80 + param = {
  81 + query: name
  82 + };
  83 +
  84 + if (channel) {
  85 + param.channel = channel;
  86 + }
  87 +
  88 + return {
  89 + tag: name,
  90 + name: name,
  91 + url: helpers.urlFormat('/tags/index', param, 'guang')
  92 + };
  93 +};
  94 +
  95 +/**
  96 + * 格式化资讯文章
  97 + *
  98 + * @param array $articleData 需要格式化的资讯数据
  99 + * @param bool $showTag 是否显示左上角标签
  100 + * @param bool $showAuthor 控制是否显示作者信息
  101 + * @return array | false
  102 + */
  103 +const _formatArticle = (articleData, showTag, showAuthor, channel) => {
  104 +
  105 + // 资讯ID不存在,则不显示
  106 + if (!articleData || !articleData.id) {
  107 + return false;
  108 + }
  109 +
  110 + let width = 360,
  111 + height = 360,
  112 + isSquareImage = true;
  113 +
  114 +
  115 + if (Number(articleData.conver_image_type) === 2) {
  116 + width = 360;
  117 + height = 240;
  118 + isSquareImage = false;
  119 + }
  120 +
  121 + let result = {
  122 + id: articleData.id,
  123 + classification: articleData.category_name,
  124 + isReco: articleData.is_recommended ? true : false,
  125 + url: ghelper.getArticleUrl(articleData.url, articleData.id, channel),
  126 + img: helpers.image(articleData.src, width, height, 1),
  127 + isSquareImg: isSquareImage,
  128 + title: articleData.title,
  129 + pTime: articleData.publish_time,
  130 + pView: articleData.views_num,
  131 + content: articleData.intro,
  132 + showTags: showTag,
  133 + comment: articleData.comment_num
  134 + };
  135 +
  136 + if (!articleData.author) {
  137 + articleData.author = {
  138 + name: '',
  139 + avatar: ''
  140 + };
  141 + }
  142 +
  143 + result.author = articleData.author.name;
  144 +
  145 + let authorId = articleData.author.author_id;
  146 +
  147 + if (authorId) {
  148 +
  149 + let aparam = {
  150 + author_id: authorId
  151 + };
  152 +
  153 + if (channel) {
  154 + aparam.channel = channel;
  155 + }
  156 + result.editorUrl = helpers.urlFormat('/Index/editor', aparam, 'guang');
  157 + }
  158 +
  159 + let tags = [];
  160 +
  161 + if (articleData.tags) {
  162 + let aTags = articleData.tags;
  163 +
  164 + for (let i = 0; i < aTags.length; i++) {
  165 + tags.push(_formatTag(aTags[i], channel));
  166 + }
  167 + }
  168 +
  169 + result.tags = tags;
  170 +
  171 + _.assign(result, {
  172 + tags: tags,
  173 + like: articleData.praise_num,
  174 + liked: articleData.isPraise === 'Y'
  175 + });
  176 +
  177 + // 判断是否显示作者信息
  178 + if (showAuthor && articleData.author) {
  179 + result.author = _.cloneDeep(articleData.author);
  180 + }
  181 +
  182 + // 模板中需要的标签标识
  183 + if (showTag && articleData.category_id) {
  184 + let categoryId = '' + articleData.category_id;
  185 +
  186 + switch (categoryId) {
  187 + case '1': // 话题
  188 + result.isTopic = true;
  189 + break;
  190 + case '2': // 搭配
  191 + result.isCollocation = true;
  192 + break;
  193 + case '3': // 潮人
  194 + result.isFashionMan = true;
  195 + break;
  196 + case '4': // 潮品
  197 + result.isFashionGood = true;
  198 + break;
  199 + case '5': // 小贴士
  200 + result.isTip = true;
  201 + break;
  202 + default:
  203 + result.isTopic = true;
  204 + }
  205 + }
  206 + return result;
  207 +};
  208 +
  209 +const _formatAd = (adData, channel) => {
  210 +
  211 + if (!adData) {
  212 + return null;
  213 + }
  214 +
  215 + let param = {
  216 + id: adData.id
  217 + };
  218 +
  219 + if (channel) {
  220 + param.channel = channel;
  221 + }
  222 +
  223 + return {
  224 + img: helpers.image(adData.src, 640, 640),
  225 + url: helpers.urlFormat('/info/index', param, 'guang'),
  226 + title: adData.title,
  227 + bgColor: adData.bgColor
  228 + };
  229 +};
  230 +
  231 +/**
  232 + * 获取页文章数据
  233 + * @param {String} channelType 传入频道页类型,值可以是: boys, girls, kids, lifestyle
  234 + * @return {Object}
  235 + */
  236 +const getArticleList = (gender, sortId, uid, udid, page, tag, authorId, limit, channel, useCache) => {
  237 +
  238 + uid = uid || 0;
  239 + udid = udid || '';
  240 + page = page || 1;
  241 + useCache = useCache || false;
  242 +
  243 + let param = {
  244 + gender: gender,
  245 + page: page,
  246 + uid: uid,
  247 + udid: udid,
  248 + client_type: 'web'
  249 + };
  250 +
  251 + if (sortId) {
  252 + param.sort_id = sortId;
  253 + }
  254 +
  255 + if (tag) {
  256 + param.tag = tag;
  257 + }
  258 +
  259 + if (authorId && Number(authorId)) {
  260 + param.author_id = authorId;
  261 + }
  262 +
  263 + if (limit) {
  264 + param.limit = limit;
  265 + }
  266 +
  267 + return serviceApi.get('guang/api/v2/article/getList', param, {
  268 + cache: useCache ? 300 : false
  269 + }).then(res => {
  270 +
  271 + if (res && res.data) {
  272 +
  273 + let artList,
  274 + adsList,
  275 + total = 0;
  276 +
  277 + if (res.data.total) {
  278 + total = _.parseInt(res.data.total);
  279 + }
  280 +
  281 + if (res.data.list) {
  282 + let list = res.data.list;
  283 +
  284 + if (list.artList) {
  285 + artList = _.map(list.artList, it => _formatArticle(it, true, false, channel));
  286 + }
  287 +
  288 + if (list.adlist) {
  289 + adsList = _.map(list.artList, it => _formatAd(it, channel));
  290 + }
  291 + }
  292 +
  293 + return {
  294 + msgs: artList,
  295 + ads: adsList,
  296 + total: total
  297 + };
  298 + }
  299 + return null;
  300 + });
  301 +};
  302 +
  303 +/**
  304 + * 获取热门标签数据
  305 + * @param {String} type 传入频道页类型,值可以是: boys, girls, kids, lifestyle
  306 + * @return {Object}
  307 + */
  308 +const getHotTags = (page, limit, channel) => {
  309 +
  310 + let data = {
  311 + client_type: 'web',
  312 + page: page || 1,
  313 + limit: limit || 10
  314 + };
  315 +
  316 + return serviceApi.get('guang/api/v2/article/getTagTop', data, {
  317 + cache: true
  318 + }).then(res => {
  319 + return _.map((res && res.data) || [], it => {
  320 + let param = {
  321 + query: it.tag_name
  322 + };
  323 +
  324 + if (channel) {
  325 + param.channel = channel;
  326 + }
  327 +
  328 + return {
  329 + tagName: it.tag_name,
  330 + url: helpers.urlFormat('/tags/index', param, 'guang')
  331 + };
  332 + });
  333 + });
  334 +};
  335 +
  336 +/**
  337 + * 获取广告数据
  338 + * @param {String} channelType 传入频道页类型,值可以是: boys, girls, kids, lifestyle
  339 + * @return {Object}
  340 + */
  341 +const getAds = channelType => {
  342 +
  343 + let contentCode = ADS_CODE[channelType] || ADS_CODE.boys;
  344 +
  345 + return serviceApi.get(URL_OPERATIONS_RESOURCE_GET, {
  346 + content_code: contentCode
  347 + }, {cache: true}).then(res => {
  348 + let list = [];
  349 +
  350 + if (res && res.code === 200 && res.data && res.data[0] && res.data[0].data) {
  351 + list = _.map(res.data[0].data, (it) => {
  352 + return {
  353 + img: helpers.image(it.src, 640, 640, 1),
  354 + url: it.url
  355 + };
  356 + });
  357 + }
  358 +
  359 + return list.length > 5 ? list.slice(0, 4) : list;
  360 + });
  361 +};
  362 +
  363 +/**
  364 + * 获取热门标签数据
  365 + * @param {String} type 传入频道页类型,值可以是: boys, girls, kids, lifestyle
  366 + * @return {Object}
  367 + */
  368 +const getBanner = channelType => {
  369 +
  370 + let contentCode = BANNER_CODE[channelType] || BANNER_CODE.boys;
  371 +
  372 + return serviceApi.get(URL_OPERATIONS_RESOURCE_GET, {
  373 + content_code: contentCode
  374 + }, {cache: true}).then(res => {
  375 +
  376 + let list = [];
  377 +
  378 + if (res && res.code === 200 && res.data && res.data[0] && res.data[0].data) {
  379 +
  380 + list = _.map(res.data[0].data, it => {
  381 + return {
  382 + img: helpers.image(it.src, 830, 327, 1),
  383 + url: it.url
  384 + };
  385 + });
  386 + }
  387 + return list;
  388 + });
  389 +};
  390 +
  391 +const getCategory = (currentSortId, channel) => {
  392 +
  393 + currentSortId = currentSortId || 0;
  394 + return serviceApi.get('guang/api/v1/category/get', {}, {
  395 + cache: true
  396 + }).then(res => {
  397 + let list = [];
  398 +
  399 + if (res && res.code === 200 && res.data) {
  400 + for (let cat of res.data) {
  401 + let param = {
  402 + type: cat.id
  403 + };
  404 +
  405 + if (channel) {
  406 + param.channel = channel;
  407 + }
  408 +
  409 + list.push({
  410 + typeId: cat.id,
  411 + type: cat.name,
  412 + isActive: String(cat.id) === String(currentSortId),
  413 + navUrl: helpers.urlFormat('/index/index', param, 'guang')
  414 + });
  415 + }
  416 + }
  417 +
  418 + return list;
  419 + });
  420 +};
  421 +
  422 +/**
  423 + * 推荐文章
  424 + */
  425 +const getRecoArticles = (gender, page, limit, channel) => {
  426 +
  427 + return serviceApi.get('guang/api/v2/article/getArticleByViewsNum', {
  428 + gender: gender,
  429 + page: page,
  430 + limit: limit
  431 + }, {cache: true}).then(res => {
  432 +
  433 + let list = [];
  434 +
  435 + if (res && res.data) {
  436 + for (let i = 0; i < res.data.length; i++) {
  437 + let it = res.data[i];
  438 +
  439 + let reco = {
  440 + url: ghelper.getArticleUrl(it.url, it.id, channel),
  441 + title: it.title
  442 + };
  443 +
  444 + if (it.src) {
  445 + reco.img = helpers.image(it.src, 90, 60, 1);
  446 + }
  447 +
  448 + list.push(reco);
  449 + }
  450 + }
  451 +
  452 + return list;
  453 + });
  454 +};
  455 +
  456 +/**
  457 + * 获取作者信息
  458 + */
  459 +const getAuthor = authorId => {
  460 +
  461 + return serviceApi.get('guang/service/v1/author/getAuthor', {
  462 + author_id: authorId
  463 + }, {
  464 + cache: 3600
  465 + }).then(res => {
  466 + if (res && res.data) {
  467 + let d = res.data;
  468 +
  469 + return {
  470 + authorId: authorId,
  471 + avatar: d.avatar,
  472 + name: d.name,
  473 + intro: d.author_desc,
  474 + authorUrl: d.name ? helpers.urlFormat('/Index/editor', {author_id: authorId }, 'guang') : ''
  475 + };
  476 + }
  477 + });
  478 +};
  479 +
  480 +/**
  481 + * 获取文章基本信息,文章标题(不含内容)
  482 + */
  483 +const getArticleInfo = (aid, channel) => {
  484 + return serviceApi.get('guang/service/v2/article/getArticle', {
  485 + article_id: aid
  486 + }, {cache: true}).then(res => {
  487 + if (res && res.code === 200 && res.data) {
  488 + let d = res.data;
  489 + let tags = [];
  490 +
  491 + if (d.tags) {
  492 + for (let i = 0; i < d.tags.length; i++) {
  493 + tags.push(_formatTag(d.tags[i], channel));
  494 + }
  495 + }
  496 +
  497 + return {
  498 + title: d.article_title,
  499 + time: moment(d.publish_time * 1000).format('YYYY年MM月DD HH:mm'),
  500 + click: d.pageViews,
  501 + shareImg: helpers.image(d.cover_image, 600, 600),
  502 + desc: d.article_summary,
  503 + authorId: d.author_id,
  504 + weixinUrl: d.url,
  505 + tag: d.tag, // tags 的字符串
  506 + tags: tags
  507 + };
  508 + }
  509 + });
  510 +};
  511 +
  512 +const _formatProduct = (products, arr) => {
  513 + let result = [];
  514 +
  515 + _.forEach(products, val => {
  516 +
  517 + let goods = {
  518 + thumb: helpers.image(val.default_images, 235, 314),
  519 + product_name: val.product_name,
  520 + sales_price: val.sales_price,
  521 + url: helpers.getUrlBySkc(val.product_id, val.goods_list[0].goods_id, val.cn_alphabet)
  522 + };
  523 +
  524 + if (val.market_price !== val.sales_price) {
  525 + goods.marketPrice = val.market_price;
  526 + }
  527 +
  528 + _.forEach(arr, (v, k) => {
  529 + if (Number(k) === Number(val.product_skn)) {
  530 + goods.thumb = helpers.image(v, 235, 314);
  531 + }
  532 + });
  533 +
  534 + result.push(goods);
  535 + });
  536 +
  537 + return result;
  538 +};
  539 +
  540 +/**
  541 + * 按照skn string 来查询 query=skn1,skn2,skn3
  542 + */
  543 +const getProductList = (params, arr) => {
  544 +
  545 + return yohoApi.get('', _.assign({
  546 + method: 'web.search.search',
  547 + order: 's_n_desc',
  548 + limit: 60
  549 + }, params), { cache: true }).then(ret => {
  550 + if (ret && ret.code === 200 && ret.data && ret.data.product_list) {
  551 + return _formatProduct(ret.data.product_list, arr);
  552 + }
  553 + });
  554 +};
  555 +
  556 +const _articleContentFormat = {
  557 + goods: goods => {
  558 +
  559 + let productSkn = [],
  560 + arr = {};
  561 +
  562 + _.forEach(goods, val => {
  563 + productSkn.push(val.id);
  564 + arr[val.id] = val.src;
  565 + });
  566 +
  567 + if (productSkn.length > 0) {
  568 +
  569 + return getProductList({
  570 + query: productSkn.join(',')
  571 + }, arr);
  572 +
  573 + }
  574 +
  575 + return null;
  576 + },
  577 + goodsGroup: goodsGroup => {
  578 +
  579 + let result = [];
  580 +
  581 + _.forEach(goodsGroup, val => {
  582 + if (val && val.list) {
  583 +
  584 + let productSkn = [];
  585 + let arr = {};
  586 +
  587 + for (let it of val.list) {
  588 + productSkn.push(it.id);
  589 + arr[it.id] = it.src;
  590 + }
  591 +
  592 + if (productSkn.length) {
  593 + // 包含多个对象,每对象里list都取数据,最终每个list只取前4个
  594 + result.push(getProductList({
  595 + query: productSkn.join(',')
  596 + }, arr).then(products => {
  597 +
  598 + let pl = [];
  599 +
  600 + if (products && _.isArray(products)) {
  601 + pl = products.slice(0, 4);
  602 + }
  603 +
  604 + return pl;
  605 + }));
  606 + }
  607 + }
  608 + });
  609 +
  610 + return result;
  611 + },
  612 + text: data => {
  613 + return data;
  614 + },
  615 + singleImage: data => {
  616 + if (data && data[0] && data[0].src) {
  617 + return {
  618 + pic: helpers.image(data[0].src, 640, 640)
  619 + };
  620 + }
  621 + return null;
  622 + },
  623 + smallPic: data => {
  624 + let result = {
  625 + smallPic: []
  626 + };
  627 +
  628 + _.forEach(data, (it, key) => {
  629 + if (key < 2) {
  630 + result.smallPic.push(helpers.image(it.src, 600, 600));
  631 + }
  632 + });
  633 + return result;
  634 + },
  635 + link: () => ({})
  636 +};
  637 +
  638 +/**
  639 + * 获取文章内容详情
  640 + */
  641 +const getArticleContent = aid => {
  642 +
  643 + let content = [],
  644 + index = 0;
  645 +
  646 + return serviceApi.get('guang/service/v2/article/getArticleContent', {
  647 + article_id: aid
  648 + }, {cache: true}).then(res => { // 内容内推荐的商品
  649 +
  650 + let gpromises = [], ggpromises = [];
  651 +
  652 + if (res && res.code === 200 && res.data) {
  653 + _.forEach(res.data, (it) => {
  654 +
  655 + _.forEach(it, (val, key) => {
  656 + if (key === 'goods') {
  657 + gpromises.push(_articleContentFormat.goods(val.data));
  658 + } else if (key === 'goodsGroup') {
  659 + // 可能包含多个list,则有多个promise
  660 + ggpromises = ggpromises.concat(_articleContentFormat.goodsGroup(val.data));
  661 + } else {
  662 + let other = _.isFunction(_articleContentFormat[key]) ?
  663 + _articleContentFormat[key](val.data) : '';
  664 +
  665 + content.push(other);
  666 + }
  667 + });
  668 + });
  669 + }
  670 +
  671 + index = gpromises.length;
  672 + return Promise.all(gpromises.concat(ggpromises));
  673 +
  674 + }).then(res => {
  675 +
  676 + let goods = _.filter(_.flatten(res.slice(0, index)), function(it) {
  677 + return it;
  678 + });
  679 +
  680 + let goodsGroup = _.filter(_.flatten(res.slice(index)), function(it) {
  681 + return it;
  682 + });
  683 +
  684 + if (goods.length > 0) {
  685 + content.push({
  686 + relatedReco: {
  687 + recos: goods
  688 + }
  689 + });
  690 + }
  691 +
  692 + if (goodsGroup.length > 0) {
  693 + content.push({
  694 + relatedReco: {
  695 + recos: goodsGroup
  696 + }
  697 + });
  698 + }
  699 +
  700 + return content;
  701 + });
  702 +};
  703 +
  704 +/**
  705 + * 判断用户是否收藏文章地址,应该是文章与用户关联的信息
  706 + * @param $articleId
  707 + * @param $uid
  708 + * @param $udid
  709 + * @param bool $onlyUrl
  710 + * @return mixed
  711 + */
  712 +const getArticleBaseInfo = (aid, uid, udid) => {
  713 + return serviceApi.get('guang/api/v1/article/getArticleBaseInfo', {
  714 + id: aid,
  715 + uid: uid,
  716 + udid: udid
  717 + }).then(res => ({
  718 + isLike: res && res.isPraise === 'Y',
  719 + likeNum: res.praise_num || 0,
  720 + isCollected: res && res.isFavor === 'Y'
  721 + }));
  722 +};
  723 +
  724 +/**
  725 + * 文章相关品牌
  726 + * @param $articleId
  727 + * @param bool $onlyUrl
  728 + * @return mixed
  729 + */
  730 +const getArticleRelateBrand = aid => {
  731 + return serviceApi.get('guang/service/v2/article/getBrand', {
  732 + article_id: aid
  733 + }, {cache: true}).then(res => {
  734 +
  735 + if (res && res.code === 200 && res.data) {
  736 + return _.map(res.data, it => {
  737 + it.thumb = it.thumb;
  738 + it.url = it.url;
  739 + return it;
  740 + });
  741 + }
  742 +
  743 + });
  744 +};
  745 +
  746 +/**
  747 + * 相关文章列表
  748 + * @param $articleId
  749 + * @param $tag
  750 + * @param int $limit
  751 + * @param bool $onlyUrl
  752 + * @return mixed
  753 + */
  754 +const getRelateArticleList = (aid, tag, size, channel) => {
  755 + size = size || 3;
  756 +
  757 + return serviceApi.get('guang/service/v2/article/getOtherArticle', {
  758 + article_id: aid,
  759 + tags: tag,
  760 + limit: size
  761 + }, {cache: true}).then(res => {
  762 + if (res && res.code === 200 && res.data) {
  763 + return _.map(res.data, it => {
  764 + it.thumb = helpers.image(it.thumb, 264, 173, 1);
  765 + it.url = ghelper.getArticleUrl(it.url, it.id, channel);
  766 + return it;
  767 + });
  768 + }
  769 + });
  770 +};
  771 +
  772 +/**
  773 + * 获取文章评论数据
  774 + */
  775 +const getArticleComments = (aid, page, pageSize) => {
  776 + page = page || 1;
  777 + pageSize = pageSize || 20;
  778 +
  779 + return serviceApi.get('guang/api/v1/comments/getList', {
  780 + article_id: aid,
  781 + page: page,
  782 + limit: pageSize
  783 + }).then(res => {
  784 +
  785 + let num = (res.data && res.data.total) || 0;
  786 + let list = [];
  787 +
  788 + if (num > 0 && res.data.list) {
  789 + let iList = res.data.list;
  790 +
  791 + for (let i = 0; i < iList.length; i++) {
  792 + let it = iList[i];
  793 +
  794 + list.push({
  795 + avatar: helpers.image(it.avator, 100, 100),
  796 + name: it.username,
  797 + content: it.content,
  798 + time: it.create_time
  799 + });
  800 + }
  801 + }
  802 +
  803 + return {
  804 + commentNum: num,
  805 + pageSize: pageSize,
  806 + page: page,
  807 + list: list,
  808 + baseUrl: helpers.urlFormat('/info/index', {
  809 + id: aid,
  810 + pageSize: pageSize
  811 + }, 'guang')
  812 + };
  813 + });
  814 +};
  815 +
  816 +/**
  817 + * 文章评论提交
  818 + * @param $id
  819 + * @param $uid
  820 + * @return mixed
  821 + */
  822 +const addComment = (aid, uid, content) => serviceApi.get('guang/api/v1/comments/add', {
  823 + article_id: aid,
  824 + uid: uid,
  825 + content: content
  826 +}).then(res => {
  827 + if (res && res.code === 200) {
  828 + return res.data;
  829 + } else {
  830 + return Promise.reject('评论失败');
  831 + }
  832 +});
  833 +
  834 +/**
  835 + * 文章点赞
  836 + * @param $id
  837 + * @param $uid
  838 + * @return mixed
  839 + */
  840 +const praise = (aid, udid) => serviceApi.get('guang/api/v2/praise/setPraise', {
  841 + article_id: aid,
  842 + udid: udid
  843 +});
  844 +
  845 +/**
  846 + * 文章点赞
  847 + * @param $id
  848 + * @param $uid
  849 + * @return mixed
  850 + */
  851 +const cancelPraise = (aid, udid) => serviceApi.get('guang/api/v2/praise/cancel', {
  852 + article_id: aid,
  853 + udid: udid
  854 +});
  855 +
  856 +/**
  857 + * 收藏文章
  858 + * @param $id
  859 + * @param $uid
  860 + * @return mixed
  861 + */
  862 +const collect = (aid, uid) => serviceApi.get('guang/api/v1/favorite/setFavorite', {
  863 + article_id: aid,
  864 + uid: uid
  865 +});
  866 +
  867 +/**
  868 + * 取消收藏文章
  869 + * @param $id
  870 + * @param $uid
  871 + * @return mixed
  872 + */
  873 +const cancelCollect = (aid, uid) => serviceApi.get('guang/api/v1/favorite/cancelFavorite', {
  874 + article_id: aid,
  875 + uid: uid
  876 +});
  877 +
  878 +/**
  879 + * 获取制指定文章的动态信息
  880 + * @param ids
  881 + * @returns {Promise.<T>|*}
  882 + */
  883 +const getDynamicDataById = (id, uid, udid) => {
  884 + return serviceApi.get('guang/api/*/article/getArticlePraiseAndFavor', {
  885 + id: id,
  886 + uid: uid,
  887 + udid: udid
  888 + });
  889 +};
  890 +
  891 +/**
  892 + * 获取制指定文章的动态信息
  893 + * @param ids
  894 + * @param udid
  895 + * @param other [Obejct] 包含uid,query,type等非必传参数
  896 + * @returns {Promise.<T>|*}
  897 + */
  898 +const getDynamicDataByIds = (ids, udid, other) => {
  899 + let params = {
  900 + articleIds: ids,
  901 + udid: udid
  902 + };
  903 +
  904 + if (other.uid) {
  905 + _.assign(params, {
  906 + uid: other.uid
  907 + });
  908 + }
  909 +
  910 + if (other.query) {
  911 + _.assign(params, {
  912 + query: other.query
  913 + });
  914 + }
  915 +
  916 + if (other.type) {
  917 + _.assign(params, {
  918 + type: other.type
  919 + });
  920 + }
  921 +
  922 + return serviceApi.get('guang/api/*/article/getSimpleArticleList', params, {cache: true});
  923 +};
  924 +
  925 +module.exports = {
  926 + getArticleList,
  927 + getHotTags,
  928 + getAds,
  929 + getBanner,
  930 + getCategory,
  931 + getRecoArticles,
  932 + getPathNav,
  933 + getAuthor,
  934 +
  935 + getArticleInfo,
  936 + getArticleContent,
  937 + getArticleBaseInfo,
  938 + getArticleRelateBrand,
  939 + getRelateArticleList,
  940 + getArticleComments,
  941 +
  942 + addComment,
  943 + praise,
  944 + cancelPraise,
  945 + collect,
  946 + cancelCollect,
  947 +
  948 + getDynamicDataById,
  949 + getDynamicDataByIds
  950 +};
  951 +
  952 +
  1 +/**
  2 + * router of guang
  3 + * @author: lcy<chuanyang.liu@yoho.cn>
  4 + * @date: 2016/08/31
  5 + */
  6 +
  7 +'use strict';
  8 +
  9 +const router = require('express').Router(); // eslint-disable-line
  10 +const cRoot = './controllers';
  11 +
  12 +const guangController = require(`${cRoot}/index`);
  13 +
  14 +router.get(['/', '/index/index'], guangController.index);
  15 +router.get(['/detail/:id', '/info/index'], guangController.detail); // guang/info/index
  16 +router.get('/tags/index', guangController.tags);
  17 +router.get('/Index/editor', guangController.editor);
  18 +
  19 +// ajax
  20 +router.post('/info/comment', guangController.comment); // 添加评论
  21 +router.get('/info/praise', guangController.praise); // 点赞
  22 +router.get('/info/cancelPraise', guangController.cancelPraise);
  23 +router.get('/info/collect', guangController.collect);
  24 +router.get('/info/cancelCollect', guangController.cancelCollect);
  25 +
  26 +router.get('/info/listData', guangController.listDynamicData);
  27 +router.get('/info/detailData', guangController.detailDynamicData);
  28 +
  29 +// router.get('/info/commentData', guangController.detailCommentData);
  30 +
  31 +module.exports = router;
  1 +<div class="guang-detail-page guang-page yoho-page clearfix">
  2 + {{# guang}}
  3 + {{> common/path-nav}}
  4 + <div class="left-side detail-body" data-id="{{id}}">
  5 + {{# header}}
  6 + <div class="detail-title">{{title}}</div>
  7 + <div class="article-info clearfix">
  8 + <div class="article-author">
  9 + <div class="author-avatar">
  10 + <a href="{{authorUrl}}" target="_blank">
  11 + <img src="{{avatar}}">
  12 + </a>
  13 + </div>
  14 + </div>
  15 + <div class="author-info">
  16 + <a class="author-name" href="{{authorUrl}}">{{name}}</a>
  17 + </div>
  18 + <div class="article-status clearfix">
  19 + <span class="article-time">{{time}}</span>
  20 + <span class="article-click">点击:<em>{{click}}</em></span>
  21 + <a href="#comment-info" id="article-comment" class="article-comment"><em class="comment-num">{{commentNum}}</em>条评论</a>
  22 + </div>
  23 + </div>
  24 + {{/ header}}
  25 +
  26 + <div class="article-main">
  27 + {{# content}}
  28 + {{# pic}}
  29 + <div class="article-pic block">
  30 + <img class="lazy" data-original="{{.}}">
  31 + </div>
  32 + {{/ pic}}
  33 + {{# text}}
  34 + <div class="article-text block">
  35 + <p>{{{.}}}</p>
  36 + </div>
  37 + {{/ text}}
  38 + {{#if smallPic}}
  39 + <div class="article-small-pic block clearfix">
  40 + {{# smallPic}}
  41 + <img class="lazy" data-original="{{.}}">
  42 + {{/ smallPic}}
  43 + </div>
  44 + {{/if}}
  45 + {{# relatedReco}}
  46 + <div class="related-reco block clearfix">
  47 + <div class="block-header">
  48 + 相关推荐
  49 + {{# moreReco}}
  50 + <a class="more-reco" href="{{.}}">MORE ></a>
  51 + {{/ moreReco}}
  52 + </div>
  53 + <div class="recos clearfix">
  54 + {{# recos}}
  55 + {{> product/good}}
  56 + {{/ recos}}
  57 + </div>
  58 + </div>
  59 + {{/ relatedReco}}
  60 + {{/ content}}
  61 + </div>
  62 + {{#if brands}}
  63 + <div class="related-brand block clearfix">
  64 + <div class="block-header">相关品牌</div>
  65 + <div class="brands">
  66 + {{# brands}}
  67 + <div class="brand">
  68 + <a class="thumb" href="{{url}}" target="_blank">
  69 + <img class="lazy" data-original="{{thumb}}">
  70 + </a>
  71 + <p class="brand-name">{{name}}</p>
  72 + </div>
  73 + {{/ brands}}
  74 + </div>
  75 + </div>
  76 + {{/if}}
  77 + {{# userInfo}}
  78 + <div class="user-handle">
  79 + <ul class="clearfix">
  80 + <li id="prise-btn" class="like-status{{#isLike}} liked{{/isLike}}">
  81 + <a href="javascript:;">
  82 + <i class="iconfont">&#xe626;</i>
  83 + <span class="like-num">{{likeNum}}</span>
  84 + </a>
  85 + </li>
  86 + <li id="collect-btn" class="sort-collect{{#isCollected}} collected{{/isCollected}}">
  87 + <a href="javascript:;">
  88 + <i class="iconfont">&#xe611;</i>
  89 + <span>收藏</span>
  90 + <span class="cancel-collect">取消收藏</span>
  91 + </a>
  92 + </li>
  93 + </ul>
  94 + </div>
  95 + {{/ userInfo}}
  96 + <div class="article-bottom-info clearfix">
  97 + {{#if tag}}
  98 + <div class="article-tag clearfix">
  99 + <i class="tag-icon iconfont">&#xe624;</i>
  100 + <ul class="clearfix">
  101 + {{# tag}}
  102 + <li>
  103 + <a href="{{url}}" target="_blank">{{name}}</a>
  104 + </li>
  105 + {{/ tag}}
  106 + </ul>
  107 + </div>
  108 + {{/if}}
  109 + <div class="article-share">
  110 + <span class="title pull-left">分享至:</span>
  111 + {{> share}}
  112 + </div>
  113 + </div>
  114 + {{#if relatedPost}}
  115 + <div class="detail-related-posts">
  116 + <ul class="clearfix">
  117 + {{# relatedPost}}
  118 + <li>
  119 + <a href="{{url}}" target="_blank">
  120 + <span class="bg-img">
  121 + <img src="{{thumb}}" alt="">
  122 + </span>
  123 + <div class="post-title">
  124 + <h2>{{title}}</h2>
  125 + </div>
  126 + </a>
  127 + </li>
  128 + {{/ relatedPost}}
  129 + </ul>
  130 + </div>
  131 + {{/if}}
  132 +
  133 + <div id="comment-area" class="comment-area">
  134 + <div class="comment-textarea">
  135 + <textarea id="comment-info" placeholder="我有话要说。。。">{{commentInfo}}</textarea>
  136 + </div>
  137 + <div class="comment-publish clearfix">
  138 + <span id="word-count-tip" class="word-count-tip"></span>
  139 + <a id="comment-btn" class="publish-btn disable">评论</a>
  140 + </div>
  141 + <div id="pjax-container" class="comments-wrap">
  142 + {{> comment}}
  143 + </div>
  144 + </div>
  145 + </div>
  146 + <div class="right-side detail-side">
  147 + {{> right-side}}
  148 + </div>
  149 + {{/ guang}}
  150 +</div>
  1 +<div class="guang-editor-page guang-page yoho-page clearfix">
  2 + {{# guang}}
  3 + {{> common/path-nav}}
  4 +
  5 + {{# editor}}
  6 + <div class="editor-info clearfix">
  7 + <div class="author-avatar">
  8 + <img src="{{avatar}}" alt="">
  9 + </div>
  10 + <div class="author-info">
  11 + <p class="author-name">{{name}}</p>
  12 + <p class="author-introduce">{{intro}}</p>
  13 + </div>
  14 + </div>
  15 + {{/ editor}}
  16 + <div class="left-side">
  17 + <div id="msg-list" class="msg-list">
  18 + {{# msgs}}
  19 + {{> msg}}
  20 + {{/ msgs}}
  21 + </div>
  22 + <div class="msg-pager pager">
  23 + {{pager baseUrl totalRecords=total page=page type="ellipsis" theme="msg-pager"}}
  24 + </div>
  25 + </div>
  26 + <div class="right-side">
  27 + {{> right-side}}
  28 + </div>
  29 + {{/ guang}}
  30 +</div>
  1 +<div class="guang-index-page guang-page yoho-page clearfix">
  2 + {{# guang}}
  3 + {{> common/path-nav}}
  4 + <div class="left-side">
  5 + <div id="slider" class="slider">
  6 + <ul class="slide-wrapper">
  7 + {{#each slider}}
  8 + <li>
  9 + <a href="{{url}}" target="_blank">
  10 + {{#if @first}}
  11 + <img src="{{img}}">
  12 + {{^}}
  13 + <img class="lazy" data-original="{{img}}">
  14 + {{/if}}
  15 + </a>
  16 + </li>
  17 + {{/each}}
  18 + </ul>
  19 + </div>
  20 + <div id="pjax-container" class="msg">
  21 + <ul class="msg-nav">
  22 + {{# msgTypes}}
  23 + <li data-type="{{typeId}}" {{#if isActive}}class="actived"{{/if}}>
  24 + <a class="pjax-link" href="{{navUrl}}">{{type}}</a>
  25 + </li>
  26 + {{/ msgTypes}}
  27 + </ul>
  28 + <div id="msg-list" class="msg-list">
  29 + {{# msgs}}
  30 + {{> msg}}
  31 + {{/ msgs}}
  32 + </div>
  33 + {{pager baseUrl totalRecords=total page=page type="ellipsis" theme="msg-pager"}}
  34 + </div>
  35 + </div>
  36 + <div class="right-side">
  37 + {{> right-side}}
  38 + </div>
  39 + {{/ guang}}
  40 +</div>
  1 +<div class="guang-list-page guang-page yoho-page clearfix">
  2 + {{# guang}}
  3 + {{> common/path-nav}}
  4 + <div class="left-side">
  5 + <div class="tag-header">
  6 + <span>{{tag}}</span>
  7 + 关联的文章
  8 + </div>
  9 + <div id="msg-list" class="msg-list">
  10 + {{# msgs}}
  11 + {{> msg}}
  12 + {{/ msgs}}
  13 + </div>
  14 +
  15 + {{pager baseUrl totalRecords=total page=page type="ellipsis" theme="msg-pager"}}
  16 + </div>
  17 + <div class="right-side">
  18 + {{> right-side}}
  19 + </div>
  20 + {{/ guang}}
  21 +</div>
  1 +{{# comment}}
  2 + <h4>
  3 + <span class="comment-num">{{commentNum}}</span>
  4 + 条评论 <i></i>
  5 + </h4>
  6 + <p class="comments-empty">还没有评论,快抢沙发吧</p>
  7 + <div class="commnets-resultwrapper">
  8 + <ul class="comments-list">
  9 + {{# list}}
  10 + <li class="clearfix">
  11 + <div class="avatar">
  12 + <img class="comment-user-avatar" src="{{avatar}}" alt=""></div>
  13 + <div class="comment-info">
  14 + <p class="comment-user-name">{{name}}</p>
  15 + <p class="comment-content">{{content}}</p>
  16 + <p class="comment-time">{{time}}</p>
  17 + </div>
  18 + </li>
  19 + {{/ list}}
  20 + </ul>
  21 + <div class="comment-pager pager">{{pager baseUrl totalRecords=commentNum page=page pageSize=pageSize type="ellipsis" theme="msg-pager"}}</div>
  22 + </div>
  23 +{{/ comment}}
  1 +<div class="msg-content clearfix" data-id="{{id}}">
  2 + <div class="msg-img">
  3 + <div class="classification">
  4 + {{classification}}
  5 + </div>
  6 + {{#if isReco}}
  7 + <div class="reco"></div>
  8 + {{/if}}
  9 + <a href="{{url}}" target="_blank">
  10 + <img class="lazy{{#if isSquareImg}} square{{/if}}" data-original="{{img}}">
  11 + </a>
  12 + </div>
  13 + <div class="msg-info">
  14 + <a class="msg-title" href="{{url}}" target="_blank">{{title}}</a>
  15 + <p class="msg-app">
  16 + <a href="{{editorUrl}}" target="_blank">
  17 + <span class="author">{{author}}</span>
  18 + </a>
  19 + <span class="publish-time">
  20 + <i class="iconfont">&#xe625;</i>
  21 + {{pTime}}
  22 + </span>
  23 + <span class="page-view">
  24 + <i class="iconfont">&#xe627;</i>
  25 + <em>{{pView}}</em>
  26 + </span>
  27 + </p>
  28 + <p class="content">{{content}}</p>
  29 + <div class="footer">
  30 + <div class="tags">
  31 + {{# tags}}
  32 + <a class="msg-tag" href="{{url}}" target="_blank">{{tag}}</a>
  33 + {{/ tags}}
  34 + </div>
  35 + <div class="like-comment">
  36 + <span class="like">
  37 + <i class="iconfont like-icon{{#if liked}} liked{{/if}}">&#xe626;</i>
  38 + {{#if like}}<b class="like-num">(<em class="num">{{like}}</em>)</b>{{/if}}
  39 + </span>
  40 + <span class="comment">
  41 + <i class="iconfont">&#xe624;</i>
  42 + {{# comment}}
  43 + (<em>{{.}}</em>)
  44 + {{/ comment}}
  45 + </span>
  46 + </div>
  47 + </div>
  48 + </div>
  49 +</div>
  1 +<div class="ex-reco">
  2 + <h1 class="ex-reco-title">精彩推荐</h1>
  3 + <div id="ex-reco-list" class="ex-reco-list">
  4 + {{# exRecos}}
  5 + <div class="ex-reco-item clearfix">
  6 + <a class="ex-reco-img" href="{{url}}" target="_blank">
  7 + <span class="bg-img" style="background-image:url({{img}})"></span>
  8 + </a>
  9 + <a href="{{url}}" target="_blank">
  10 + <p class="ex-reco-context">{{title}}</p>
  11 + </a>
  12 + </div>
  13 + {{/ exRecos}}
  14 + </div>
  15 +</div>
  16 +
  17 +<div class="hot">
  18 + <h1 class="hot-title">热门标签</h1>
  19 + <div class="hot-tag-list">
  20 + {{#hotTags}}
  21 + <a class="hot-tag" href="{{url}}" target="_blank">
  22 + {{tagName}}
  23 + </a>
  24 + {{/hotTags}}
  25 + </div>
  26 +</div>
  27 +
  28 +<div class="ads">
  29 + {{# ads}}
  30 + <a class="ad" href="{{url}}" target="_blank">
  31 + <img class="lazy" data-original="{{img}}">
  32 + </a>
  33 + {{/ ads}}
  34 +</div>
  1 +<div class="floor-ad">
  2 + sub tpl my name is {{name}}
  3 +</div>
@@ -15,7 +15,7 @@ const searchApi = require(`${mRoot}/search-api`); @@ -15,7 +15,7 @@ const searchApi = require(`${mRoot}/search-api`);
15 const shop = (shopId, req, res, next, brandInfo) => { 15 const shop = (shopId, req, res, next, brandInfo) => {
16 shopId = parseInt(shopId, 10); 16 shopId = parseInt(shopId, 10);
17 17
18 - list.getShopInfo(shopId, req.user.id).then(shopInfo => { 18 + list.getShopInfo(shopId, req.user.uid).then(shopInfo => {
19 if (+shopInfo.shopTemplateType === 2) { // 经典模板 19 if (+shopInfo.shopTemplateType === 2) { // 经典模板
20 let pjax = req.query._pjax; 20 let pjax = req.query._pjax;
21 21
@@ -83,7 +83,7 @@ exports.new = (req, res, next) => { @@ -83,7 +83,7 @@ exports.new = (req, res, next) => {
83 * @return {[type]} [description] 83 * @return {[type]} [description]
84 */ 84 */
85 exports.brand = (req, res, next) => { 85 exports.brand = (req, res, next) => {
86 - let brandDomain = req.params.brandDomain; 86 + let brandDomain = req.query.domain;
87 let shopId = req.query.shopId; 87 let shopId = req.query.shopId;
88 let resData = {}; 88 let resData = {};
89 89
@@ -158,7 +158,7 @@ exports.shopList = (req, res, next) => { @@ -158,7 +158,7 @@ exports.shopList = (req, res, next) => {
158 return next(); 158 return next();
159 } 159 }
160 160
161 - list.getShopListData(req.yoho.channel, req.query).then(result => { 161 + list.getShopListData(req.yoho.channel, req.query, req.user.uid).then(result => {
162 Object.assign(result, { 162 Object.assign(result, {
163 page: 'shop', 163 page: 'shop',
164 shopId: shopId 164 shopId: shopId
@@ -9,6 +9,8 @@ @@ -9,6 +9,8 @@
9 const mRoot = '../models'; 9 const mRoot = '../models';
10 const sale = require(`${mRoot}/sale`); // sale model 10 const sale = require(`${mRoot}/sale`); // sale model
11 11
  12 +const _ = require('lodash');
  13 +
12 /** 14 /**
13 * sale 首页 15 * sale 首页
14 * @param {[type]} req [description] 16 * @param {[type]} req [description]
@@ -16,7 +18,7 @@ const sale = require(`${mRoot}/sale`); // sale 页 model @@ -16,7 +18,7 @@ const sale = require(`${mRoot}/sale`); // sale 页 model
16 * @return {[type]} [description] 18 * @return {[type]} [description]
17 */ 19 */
18 exports.index = (req, res, next) => { 20 exports.index = (req, res, next) => {
19 - let channel = req.query.channel || req.cookies._Channel || 'boys'; 21 + let channel = req.query.channel || req.yoho.channel;
20 22
21 // 真实数据输出 23 // 真实数据输出
22 sale.getSaleIndexData(channel).then(result => { 24 sale.getSaleIndexData(channel).then(result => {
@@ -41,7 +43,7 @@ exports.discount = (req, res, next) => { @@ -41,7 +43,7 @@ exports.discount = (req, res, next) => {
41 saleType: '3' 43 saleType: '3'
42 }, req.query); 44 }, req.query);
43 45
44 - let channel = req.query.channel || req.cookies._Channel || 'boys'; 46 + let channel = req.query.channel || req.yoho.channel;
45 47
46 let responseData = { 48 let responseData = {
47 module: 'product', 49 module: 'product',
@@ -68,7 +70,7 @@ exports.vip = (req, res, next) => { @@ -68,7 +70,7 @@ exports.vip = (req, res, next) => {
68 saleType: '2' 70 saleType: '2'
69 }, req.query); 71 }, req.query);
70 72
71 - let channel = req.query.channel || req.cookies._Channel || 'boys'; 73 + let channel = req.query.channel || req.yoho.channel;
72 74
73 params.uid = req.user.uid || 0; 75 params.uid = req.user.uid || 0;
74 76
@@ -95,7 +97,7 @@ exports.newSale = (req, res, next) => { @@ -95,7 +97,7 @@ exports.newSale = (req, res, next) => {
95 order: 's_t_desc' 97 order: 's_t_desc'
96 }, req.query); 98 }, req.query);
97 99
98 - let channel = req.query.channel || req.cookies._Channel || 'boys'; 100 + let channel = req.query.channel || req.yoho.channel;
99 101
100 sale.getSaleOthersData(params, channel).then((result) => { 102 sale.getSaleOthersData(params, channel).then((result) => {
101 res.render('sale/other', Object.assign({ 103 res.render('sale/other', Object.assign({
@@ -119,7 +121,7 @@ exports.breakingYards = (req, res, next) => { @@ -119,7 +121,7 @@ exports.breakingYards = (req, res, next) => {
119 saleType: '5' 121 saleType: '5'
120 }, req.query); 122 }, req.query);
121 123
122 - let channel = req.query.channel || req.cookies._Channel || 'boys'; 124 + let channel = req.query.channel || req.yoho.channel;
123 125
124 let responseData = { 126 let responseData = {
125 module: 'product', 127 module: 'product',
@@ -150,6 +152,9 @@ exports.special = (req, res, next) => { @@ -150,6 +152,9 @@ exports.special = (req, res, next) => {
150 return next(); 152 return next();
151 } 153 }
152 154
  155 + _.omit(params, 'specialsale_id');
  156 + params.productPool = specialId;
  157 +
153 sale.getSaleSpecialData(specialId, params, req.yoho.channel).then(result => { 158 sale.getSaleSpecialData(specialId, params, req.yoho.channel).then(result => {
154 res.render('sale/special', result); 159 res.render('sale/special', result);
155 }).catch(next); 160 }).catch(next);
@@ -208,7 +208,7 @@ const _getBrandDataByProductBaseInfo = (data, additionalData) => { @@ -208,7 +208,7 @@ const _getBrandDataByProductBaseInfo = (data, additionalData) => {
208 return {}; 208 return {};
209 } 209 }
210 210
211 - let brandId = data.brand_info.id; 211 + let brandId = data.brand_info.brand_id;
212 let bgImg = ''; 212 let bgImg = '';
213 let logo = ''; 213 let logo = '';
214 let bannerInfo = null; 214 let bannerInfo = null;
@@ -373,7 +373,7 @@ const _getFashionTopGoodsStatus = (uid, showStatus, isBeginSale) => { @@ -373,7 +373,7 @@ const _getFashionTopGoodsStatus = (uid, showStatus, isBeginSale) => {
373 // dis //失效 373 // dis //失效
374 // buyNow //是否立即购买 374 // buyNow //是否立即购买
375 let result = { 375 let result = {
376 - getLimitedCode: true, 376 + getLimitedCode: false,
377 hadLimitedCode: false, 377 hadLimitedCode: false,
378 limitedCodeSoldOut: false, 378 limitedCodeSoldOut: false,
379 openSoon: false, 379 openSoon: false,
@@ -393,17 +393,16 @@ const _getFashionTopGoodsStatus = (uid, showStatus, isBeginSale) => { @@ -393,17 +393,16 @@ const _getFashionTopGoodsStatus = (uid, showStatus, isBeginSale) => {
393 result.openSoon = true; 393 result.openSoon = true;
394 result.hadLimitedCode = false; 394 result.hadLimitedCode = false;
395 } 395 }
  396 + result.getLimitedCode = true;
396 break; 397 break;
397 case 2: // 开售后,限购码已抢光(用户未领取限购码) 398 case 2: // 开售后,限购码已抢光(用户未领取限购码)
398 result.buyNow = true; 399 result.buyNow = true;
399 result.dis = true; 400 result.dis = true;
400 result.limitedCodeSoldOut = true; 401 result.limitedCodeSoldOut = true;
401 - result.getLimitedCode = false;  
402 result.hadLimitedCode = false; 402 result.hadLimitedCode = false;
403 break; 403 break;
404 case 3: // 开售后,商品已经售罄 404 case 3: // 开售后,商品已经售罄
405 result.soldOut = true; 405 result.soldOut = true;
406 - result.getLimitedCode = false;  
407 break; 406 break;
408 case 4:// 开售后,立即购买(用户已领取限购码) 407 case 4:// 开售后,立即购买(用户已领取限购码)
409 result.buyNow = true; 408 result.buyNow = true;
@@ -417,7 +416,6 @@ const _getFashionTopGoodsStatus = (uid, showStatus, isBeginSale) => { @@ -417,7 +416,6 @@ const _getFashionTopGoodsStatus = (uid, showStatus, isBeginSale) => {
417 result.openSoon = true; 416 result.openSoon = true;
418 result.hadLimitedCode = true; 417 result.hadLimitedCode = true;
419 result.limitedCodeSoldOut = true; 418 result.limitedCodeSoldOut = true;
420 - result.getLimitedCode = false;  
421 break; 419 break;
422 case 6: // 开售前,即将开售(用户已领取限购码) 420 case 6: // 开售前,即将开售(用户已领取限购码)
423 result.openSoon = true; 421 result.openSoon = true;
@@ -1102,21 +1100,22 @@ const _detailDataPkg = (origin, uid, vipLevel) => { @@ -1102,21 +1100,22 @@ const _detailDataPkg = (origin, uid, vipLevel) => {
1102 result.vipPrice = _getVipDataByProductBaseInfo(origin, vipLevel, uid); 1100 result.vipPrice = _getVipDataByProductBaseInfo(origin, vipLevel, uid);
1103 } 1101 }
1104 1102
1105 - // 促销活动banner,虚拟商品无促销 1103 + // 促销活动banner,虚拟商品无促销
1106 if (propOrigin('attribute') !== 3) { 1104 if (propOrigin('attribute') !== 3) {
1107 result.activity = _getActivityDataByProductBaseInfo(promotionData, additionalData); 1105 result.activity = _getActivityDataByProductBaseInfo(promotionData, additionalData);
1108 } 1106 }
1109 1107
1110 - const C_VALUE = {  
1111 - type: '返有货币',  
1112 - des: '每件返 ',  
1113 - rest: '个 有货币'  
1114 - }; 1108 + // 有货币
  1109 + if (!_.includes(['', '0'], propOrigin('yohoCoinNum'))) {
  1110 + const C_VALUE = {
  1111 + type: '返有货币',
  1112 + des: '每件返 ',
  1113 + rest: '个 有货币'
  1114 + };
1115 1115
1116 - if (propOrigin('yoho_coin_num', '0') !== '0') {  
1117 result.activity.push({ 1116 result.activity.push({
1118 type: C_VALUE.type, 1117 type: C_VALUE.type,
1119 - des: `${C_VALUE.des}${propOrigin('yoho_coin_num')}${C_VALUE.rest}` 1118 + des: `${C_VALUE.des}${propOrigin('yohoCoinNum')}${C_VALUE.rest}`
1120 }); 1119 });
1121 } 1120 }
1122 1121
@@ -1152,12 +1151,12 @@ const _detailDataPkg = (origin, uid, vipLevel) => { @@ -1152,12 +1151,12 @@ const _detailDataPkg = (origin, uid, vipLevel) => {
1152 // 是否收藏 1151 // 是否收藏
1153 result.isCollect = favoriteData.product; 1152 result.isCollect = favoriteData.product;
1154 1153
1155 - if (propOrigin('is_limit_buy', false)) { 1154 + if (propOrigin('isLimitBuy', false)) {
1156 // 是否开售 1155 // 是否开售
1157 - let isBeginSale = propOrigin('sale_status', 0) === 1; 1156 + let isBeginSale = propOrigin('saleStatus', 0) === 1;
1158 1157
1159 // 限购商品有关的展示状态 1158 // 限购商品有关的展示状态
1160 - let showStatus = propOrigin('show_status', 1); 1159 + let showStatus = propOrigin('showStatus', 1);
1161 1160
1162 let fashTopGoods = _getFashionTopGoodsStatus(uid, showStatus, isBeginSale); 1161 let fashTopGoods = _getFashionTopGoodsStatus(uid, showStatus, isBeginSale);
1163 1162
@@ -1237,8 +1236,13 @@ const _detailDataPkg = (origin, uid, vipLevel) => { @@ -1237,8 +1236,13 @@ const _detailDataPkg = (origin, uid, vipLevel) => {
1237 statGoodsInfo.productId = propOrigin('product_id'); 1236 statGoodsInfo.productId = propOrigin('product_id');
1238 statGoodsInfo.productName = result.name.replace('\'', '’'); 1237 statGoodsInfo.productName = result.name.replace('\'', '’');
1239 statGoodsInfo.brandName = (result.brandName || '').replace('\'', '’'); 1238 statGoodsInfo.brandName = (result.brandName || '').replace('\'', '’');
1240 - statGoodsInfo.marketPrice = result.marketPrice;  
1241 - statGoodsInfo.salePrice = result.salePrice ? result.salePrice : result.marketPrice; 1239 + statGoodsInfo.marketPrice = result.marketPrice.replace('¥', ''); // 数字
  1240 + statGoodsInfo.salePrice = (result.salePrice ? result.salePrice : result.marketPrice).replace('¥', ''); // 数字
  1241 + statGoodsInfo.imageUrl = 'http:' + result.img.split('?')[0];
  1242 + statGoodsInfo.productUrl = 'http:' +
  1243 + helpers.urlFormat(url.parse(propOrigin('product_url')).pathname, null, 'item');
  1244 + statGoodsInfo.smallSortId = result.smallSortId;
  1245 + statGoodsInfo.soldOut = soldOut ? 1 : 0;
1242 1246
1243 if (banner.brandId) { 1247 if (banner.brandId) {
1244 let domainBrand = yield brandService.getBrandByDomainAsync(banner.brandDomain); 1248 let domainBrand = yield brandService.getBrandByDomainAsync(banner.brandDomain);
@@ -1258,11 +1262,6 @@ const _detailDataPkg = (origin, uid, vipLevel) => { @@ -1258,11 +1262,6 @@ const _detailDataPkg = (origin, uid, vipLevel) => {
1258 } 1262 }
1259 } 1263 }
1260 1264
1261 - statGoodsInfo.imageUrl = 'http:' + result.img.split('?')[0];  
1262 - statGoodsInfo.productUrl = 'http:' +  
1263 - helpers.urlFormat(url.parse(propOrigin('product_url')).pathname, null, 'item');  
1264 - statGoodsInfo.smallSortId = result.smallSortId;  
1265 - statGoodsInfo.soldOut = soldOut ? 1 : 0;  
1266 1265
1267 // 获取商品尺寸相关 1266 // 获取商品尺寸相关
1268 let sizeInfo = _getSizeInfo(result, result.maxSortId, additionalData); 1267 let sizeInfo = _getSizeInfo(result, result.maxSortId, additionalData);
@@ -73,7 +73,7 @@ const getListData = (params, channel) => { @@ -73,7 +73,7 @@ const getListData = (params, channel) => {
73 ]; 73 ];
74 74
75 // 搜索分类介绍和广告 75 // 搜索分类介绍和广告
76 - if (params.msort && params.misort) { 76 + if (params.msort && params.misort && !isNaN(params.misort)) {
77 let IntroParams = { 77 let IntroParams = {
78 max_sort_id: params.msort, 78 max_sort_id: params.msort,
79 middle_sort_id: params.misort, 79 middle_sort_id: params.misort,
@@ -106,19 +106,27 @@ const getListData = (params, channel) => { @@ -106,19 +106,27 @@ const getListData = (params, channel) => {
106 106
107 finalResult.list = Object.assign( 107 finalResult.list = Object.assign(
108 searchHandler.handlePathNavData(result[1].data.sort, params, 'sort', channel), { 108 searchHandler.handlePathNavData(result[1].data.sort, params, 'sort', channel), {
109 - leftContent: searchHandler.handleSortData(result[1].data.sort, dps) 109 + leftContent: searchHandler.handleSortData(result[1].data.sort, dps, params)
110 }); 110 });
111 } 111 }
112 112
113 // 获取商品数据和顶部筛选条件 113 // 获取商品数据和顶部筛选条件
114 if (result[2].code === 200) { 114 if (result[2].code === 200) {
  115 + let filters = Object.assign(searchHandler.handleFilterDataAll(result[2].data, params),
  116 + finalResult.list.leftContent.sort);
  117 +
  118 + filters.checkedConditions.conditions = _.concat(filters.checkedConditions.conditions,
  119 + finalResult.list.leftContent.checked);
  120 +
115 Object.assign(finalResult.list, { 121 Object.assign(finalResult.list, {
116 - filters: searchHandler.handleFilterDataAll(result[2].data, params), 122 + filters: filters,
117 opts: searchHandler.handleOptsData(params, result[2].data.total, result[2].data.filter), 123 opts: searchHandler.handleOptsData(params, result[2].data.total, result[2].data.filter),
118 totalCount: result[2].data.total, 124 totalCount: result[2].data.total,
119 footPager: searchHandler.handlePagerData(result[2].data.total, params), 125 footPager: searchHandler.handlePagerData(result[2].data.total, params),
120 goods: productProcess.processProductList(result[2].data.product_list, 126 goods: productProcess.processProductList(result[2].data.product_list,
121 - Object.assign({showDiscount: false}, params)), 127 + Object.assign({showDiscount: false}, params, {
  128 + from: {type: 'list', params: params}
  129 + })),
122 hasNextPage: searchHandler.handleNextPage(params, result[2].data.total), 130 hasNextPage: searchHandler.handleNextPage(params, result[2].data.total),
123 131
124 // 最近浏览记录 132 // 最近浏览记录
@@ -182,19 +190,26 @@ const getListNewData = (params, channel) => { @@ -182,19 +190,26 @@ const getListNewData = (params, channel) => {
182 if (result[1].code === 200) { 190 if (result[1].code === 200) {
183 finalResult.list = Object.assign( 191 finalResult.list = Object.assign(
184 searchHandler.handlePathNavData(result[1].data.sort, params, 'new', channel), { 192 searchHandler.handlePathNavData(result[1].data.sort, params, 'new', channel), {
185 - leftContent: searchHandler.handleSortData(result[1].data.sort, dps) 193 + leftContent: searchHandler.handleSortData(result[1].data.sort, dps, params)
186 }); 194 });
187 } 195 }
188 196
189 // 获取商品数据和顶部筛选条件 197 // 获取商品数据和顶部筛选条件
190 if (result[2].code === 200) { 198 if (result[2].code === 200) {
  199 + let filters = Object.assign(searchHandler.handleFilterDataAll(result[2].data, params),
  200 + finalResult.list.leftContent.sort);
  201 +
  202 + filters.checkedConditions.conditions = _.concat(filters.checkedConditions.conditions,
  203 + finalResult.list.leftContent.checked);
  204 +
191 Object.assign(finalResult.list, { 205 Object.assign(finalResult.list, {
192 - filters: searchHandler.handleFilterDataAll(result[2].data, params), 206 + filters: filters,
193 opts: searchHandler.handleOptsData(params, result[2].data.total, result[2].data.filter), 207 opts: searchHandler.handleOptsData(params, result[2].data.total, result[2].data.filter),
194 totalCount: result[2].data.total, 208 totalCount: result[2].data.total,
195 footPager: searchHandler.handlePagerData(result[2].data.total, params), 209 footPager: searchHandler.handlePagerData(result[2].data.total, params),
196 goods: productProcess.processProductList(result[2].data.product_list, 210 goods: productProcess.processProductList(result[2].data.product_list,
197 - Object.assign({showDiscount: false, showNew: false}, params)), 211 + Object.assign({showDiscount: false, showNew: false,
  212 + from: {type: 'listNew', params: params}}, params)),
198 hasNextPage: searchHandler.handleNextPage(params, result[2].data.total), 213 hasNextPage: searchHandler.handleNextPage(params, result[2].data.total),
199 214
200 // 最近浏览记录 215 // 最近浏览记录
@@ -265,7 +280,7 @@ const getBrandData = (params, extra, channel) => { @@ -265,7 +280,7 @@ const getBrandData = (params, extra, channel) => {
265 let apiMethod = [ 280 let apiMethod = [
266 headerModel.requestHeaderData(channel), 281 headerModel.requestHeaderData(channel),
267 searchApi.getSortList(queryBase), 282 searchApi.getSortList(queryBase),
268 - searchApi.getProductList(Object.assign({order: order}, searchParams, queryBase)) 283 + searchApi.getProductList(Object.assign(searchParams, {order: order}, queryBase))
269 284
270 ]; 285 ];
271 286
@@ -292,28 +307,34 @@ const getBrandData = (params, extra, channel) => { @@ -292,28 +307,34 @@ const getBrandData = (params, extra, channel) => {
292 }); 307 });
293 308
294 Object.assign(finalResult.brand, { 309 Object.assign(finalResult.brand, {
295 - leftContent: searchHandler.handleSortData(result[1].data.sort, dps) 310 + leftContent: searchHandler.handleSortData(result[1].data.sort, dps, params)
296 }, searchHandler.handlePathNavData(extra, params, 'brand', channel)); 311 }, searchHandler.handlePathNavData(extra, params, 'brand', channel));
297 } 312 }
298 313
299 // 获取商品数据和顶部筛选条件 314 // 获取商品数据和顶部筛选条件
300 if (result[2].code === 200) { 315 if (result[2].code === 200) {
  316 + let filters = Object.assign(searchHandler.handleFilterDataAll(result[2].data, params),
  317 + finalResult.brand.leftContent.sort);
  318 +
  319 + filters.checkedConditions.conditions = _.concat(filters.checkedConditions.conditions,
  320 + finalResult.brand.leftContent.checked);
  321 +
301 Object.assign(finalResult.brand, { 322 Object.assign(finalResult.brand, {
302 - filters: searchHandler.handleFilterDataAll(result[2].data, params), 323 + filters: filters,
303 opts: searchHandler.handleOptsData(params, result[2].data.total, result[2].data.filter), 324 opts: searchHandler.handleOptsData(params, result[2].data.total, result[2].data.filter),
304 totalCount: result[2].data.total, 325 totalCount: result[2].data.total,
305 footPager: searchHandler.handlePagerData(result[2].data.total, params), 326 footPager: searchHandler.handlePagerData(result[2].data.total, params),
306 goods: productProcess.processProductList(result[2].data.product_list, 327 goods: productProcess.processProductList(result[2].data.product_list,
307 - Object.assign({showDiscount: false}, params)), 328 + Object.assign({showDiscount: false, from: {type: 'brand', params: params}}, params)),
308 hasNextPage: searchHandler.handleNextPage(params, result[2].data.total), 329 hasNextPage: searchHandler.handleNextPage(params, result[2].data.total),
309 330
310 // 最近浏览记录 331 // 最近浏览记录
311 latestWalk: 7 332 latestWalk: 7
312 }); 333 });
313 - }  
314 334
315 - // 品牌页不显示品牌筛选项  
316 - delete finalResult.brand.filters.brand; 335 + // 品牌页不显示品牌筛选项
  336 + _.unset(finalResult, 'brand.filters.brand');
  337 + }
317 338
318 finalResult.criteo = {skn: searchHandler.getCriteo(_.get(finalResult.brand, 'goods'))}; 339 finalResult.criteo = {skn: searchHandler.getCriteo(_.get(finalResult.brand, 'goods'))};
319 340
@@ -417,7 +438,7 @@ const getShopAbout = (shopId, uid, channel) => { @@ -417,7 +438,7 @@ const getShopAbout = (shopId, uid, channel) => {
417 438
418 if (result[1].code === 200) { 439 if (result[1].code === 200) {
419 let data = result[1].data || {}, 440 let data = result[1].data || {},
420 - decorator = shopHandler.getShopDecorator(data, {}, shopId); 441 + decorator = shopHandler.getShopDecorator(data, {}, shopId, true);
421 442
422 Object.assign(decorator.shopTopBannerBase, { 443 Object.assign(decorator.shopTopBannerBase, {
423 shopId: shopId, 444 shopId: shopId,
@@ -637,7 +658,8 @@ const getShopData = (shopId, channel, params, shopInfo) => { @@ -637,7 +658,8 @@ const getShopData = (shopId, channel, params, shopInfo) => {
637 finalResult.leftContent = searchHandler.handleSortData(groupSort, params); 658 finalResult.leftContent = searchHandler.handleSortData(groupSort, params);
638 659
639 if (finalResult.allGoods) { 660 if (finalResult.allGoods) {
640 - Object.assign(finalResult.allGoods, searchHandler.setShopSort(groupSort, params)); 661 + Object.assign(finalResult.allGoods, searchHandler.setShopSort(groupSort, Object.assign({},
  662 + params, {page: 1})));
641 } 663 }
642 } 664 }
643 665
@@ -652,7 +674,7 @@ const getShopData = (shopId, channel, params, shopInfo) => { @@ -652,7 +674,7 @@ const getShopData = (shopId, channel, params, shopInfo) => {
652 674
653 for (let i = 0; i < 3; i++) { 675 for (let i = 0; i < 3; i++) {
654 trendList.push({ 676 trendList.push({
655 - href: articleList[i].url, 677 + href: helpers.urlFormat(`/${articleList[i].id}.html`, '', 'guang'),
656 src: helpers.getForceSourceUrl(articleList[i].src) + 678 src: helpers.getForceSourceUrl(articleList[i].src) +
657 '?imageView/1/w/{width}/h/{height}', 679 '?imageView/1/w/{width}/h/{height}',
658 mainTitle: articleList[i].title, 680 mainTitle: articleList[i].title,
@@ -712,7 +734,8 @@ const getShopGoodsData = (shopId, channel, params) => { @@ -712,7 +734,8 @@ const getShopGoodsData = (shopId, channel, params) => {
712 if (subRes.code === 200) { 734 if (subRes.code === 200) {
713 let groupSort = _.get(subRes, 'data.sort', []); 735 let groupSort = _.get(subRes, 'data.sort', []);
714 736
715 - Object.assign(resData, searchHandler.setShopSort(groupSort, params)); 737 + Object.assign(resData, searchHandler.setShopSort(groupSort, Object.assign(params,
  738 + {page: 1})));
716 } 739 }
717 740
718 return resData; 741 return resData;
@@ -794,6 +817,9 @@ const getShopListData = (channel, params, uid) => { @@ -794,6 +817,9 @@ const getShopListData = (channel, params, uid) => {
794 }), 817 }),
795 footPager: {tip: tip} 818 footPager: {tip: tip}
796 }); 819 });
  820 +
  821 + _.set(finalResult, 'filters.checkedConditions.clearUrl',
  822 + `?navBar=${params.navBar}&shopId=${params.shopId}`);
797 } else { 823 } else {
798 finalResult.searchEmpty = true; 824 finalResult.searchEmpty = true;
799 825
@@ -886,6 +912,11 @@ const getBaseShopData = (params, extra, channel, shopId) => { @@ -886,6 +912,11 @@ const getBaseShopData = (params, extra, channel, shopId) => {
886 }); 912 });
887 } 913 }
888 914
  915 + // 临时删除seo信息
  916 + _.unset(resData, 'title');
  917 + _.unset(resData, 'keywords');
  918 + _.unset(resData, 'description');
  919 +
889 return resData; 920 return resData;
890 }); 921 });
891 }; 922 };
@@ -63,14 +63,14 @@ exports.getSalebreakingYardsSortList = (params) => { @@ -63,14 +63,14 @@ exports.getSalebreakingYardsSortList = (params) => {
63 * @return {[type]} [description] 63 * @return {[type]} [description]
64 */ 64 */
65 exports.getSaleActivityList = (params, channel) => { 65 exports.getSaleActivityList = (params, channel) => {
66 - let tempChannel = _.isEmpty(channel) ? 'boys' : channel; 66 + let tempChannel = yhChannel[channel] || yhChannel.boys;
67 67
68 return api.get('', { 68 return api.get('', {
69 id: params.id || null, 69 id: params.id || null,
70 method: 'app.activity.get', 70 method: 'app.activity.get',
71 sort: '2', 71 sort: '2',
72 plateform: '1', 72 plateform: '1',
73 - yh_channel: yhChannel[tempChannel].channel 73 + yh_channel: tempChannel.channel
74 }); 74 });
75 }; 75 };
76 76
@@ -379,7 +379,8 @@ exports.getSaleDiscountData = (params, channel) => { @@ -379,7 +379,8 @@ exports.getSaleDiscountData = (params, channel) => {
379 // 处理分页等筛选信息 379 // 处理分页等筛选信息
380 if (subResult[0].code === 200) { 380 if (subResult[0].code === 200) {
381 Object.assign(finalResult, { 381 Object.assign(finalResult, {
382 - leftContent: publicHandler.handleSaleSortData(subResult[0].data.filter.group_sort, params, 'discount'), 382 + leftContent: publicHandler.handleSaleSortData(subResult[0].data.filter.group_sort,
  383 + params, 'discount'),
383 saleList: { 384 saleList: {
384 footPager: publicHandler.handlePagerData(subResult[0].data.total, params), 385 footPager: publicHandler.handlePagerData(subResult[0].data.total, params),
385 opts: publicHandler.handleSaleOptsData(params, subResult[0].data.total, 'default') 386 opts: publicHandler.handleSaleOptsData(params, subResult[0].data.total, 'default')
@@ -528,7 +529,7 @@ exports.getSaleSpecialData = (id, params, channel) => { @@ -528,7 +529,7 @@ exports.getSaleSpecialData = (id, params, channel) => {
528 limit: limit, 529 limit: limit,
529 attribute_not: 2 530 attribute_not: 2
530 }); 531 });
531 - let banner = JSON.parse(data.banner_img) || []; 532 + let banner = data.banner_img ? JSON.parse(data.banner_img) : [];
532 533
533 Object.assign(resData, { 534 Object.assign(resData, {
534 mainBanner: { 535 mainBanner: {
@@ -580,7 +581,8 @@ exports.getSaleSpecialData = (id, params, channel) => { @@ -580,7 +581,8 @@ exports.getSaleSpecialData = (id, params, channel) => {
580 Object.assign(resData, { 581 Object.assign(resData, {
581 filters: searchHandler.handleFilterDataAll(_.get(result[2], 'data', {}), params), 582 filters: searchHandler.handleFilterDataAll(_.get(result[2], 'data', {}), params),
582 opts: searchHandler.handleOptsData(params, tip.total), 583 opts: searchHandler.handleOptsData(params, tip.total),
583 - goods: productProcess.processProductList(_.get(result[2], 'data.product_list', [])), 584 + goods: productProcess.processProductList(_.get(result[2], 'data.product_list', []),
  585 + {from: {type: 'saleSpecial', params: params}}),
584 footPager: {tip: tip} 586 footPager: {tip: tip}
585 }); 587 });
586 588
@@ -22,9 +22,6 @@ const getSortByConditionAsync = (condition) => { @@ -22,9 +22,6 @@ const getSortByConditionAsync = (condition) => {
22 return api.get('sortgroup.json', condition); 22 return api.get('sortgroup.json', condition);
23 }; 23 };
24 24
25 -// 获取list页广告  
26 -const adsUrl = '/shops/api/v1/ads/getList';  
27 -  
28 // 判断用户是否收藏品牌 25 // 判断用户是否收藏品牌
29 const isFavoriteBrandUrl = '/shops/service/v1/favorite/getUidBrandFav'; 26 const isFavoriteBrandUrl = '/shops/service/v1/favorite/getUidBrandFav';
30 27
@@ -175,7 +172,12 @@ const getSortIntro = (params) => { @@ -175,7 +172,12 @@ const getSortIntro = (params) => {
175 * @return 172 * @return
176 */ 173 */
177 const getSortAds = (params) => { 174 const getSortAds = (params) => {
178 - return serviceApi.get(adsUrl, params); 175 + let finalParams = {
  176 + method: 'app.ads.list'
  177 + };
  178 +
  179 + Object.assign(finalParams, params);
  180 + return yohoApi.get('', finalParams);
179 }; 181 };
180 182
181 /** 183 /**
@@ -39,7 +39,7 @@ const handleFilterUrl = (originParam, newParam, delParam) => { @@ -39,7 +39,7 @@ const handleFilterUrl = (originParam, newParam, delParam) => {
39 delete tempOriginParam.uid; 39 delete tempOriginParam.uid;
40 40
41 _.forEach(tempOriginParam, function(value, key) { 41 _.forEach(tempOriginParam, function(value, key) {
42 - if (!delParam[key]) { 42 + if (!delParam[key] && value) {
43 dest += `${key}=${value}&`; 43 dest += `${key}=${value}&`;
44 } 44 }
45 }); 45 });
@@ -311,7 +311,7 @@ exports.handleOptsData = (params, total, extra) => { @@ -311,7 +311,7 @@ exports.handleOptsData = (params, total, extra) => {
311 311
312 switch (i) { 312 switch (i) {
313 case 0: 313 case 0:
314 - opt.href = handleFilterUrl(params, {order: ''}, {page: true}); 314 + opt.href = handleFilterUrl(params, {}, {page: true, order: true});
315 if (extra === 'discont') { // 如果是折扣专场 315 if (extra === 'discont') { // 如果是折扣专场
316 opt.name = '全部'; 316 opt.name = '全部';
317 if (_.isEmpty(params.order) || params.order === 's_t_desc') { 317 if (_.isEmpty(params.order) || params.order === 's_t_desc') {
@@ -465,8 +465,12 @@ exports.handleOptsData = (params, total, extra) => { @@ -465,8 +465,12 @@ exports.handleOptsData = (params, total, extra) => {
465 * @param extra 可以任意传值用来处理特殊情况 465 * @param extra 可以任意传值用来处理特殊情况
466 * @returns {{}} 466 * @returns {{}}
467 */ 467 */
468 -exports.handleSortData = (origin, params) => {  
469 - let leftContent = {}; 468 +exports.handleSortData = (origin, params, originParams) => {
  469 + let leftContent = {
  470 + sort: {misort: []},
  471 + checked: []
  472 + };
  473 +
470 let list = [], 474 let list = [],
471 allCount = 0; 475 allCount = 0;
472 476
@@ -477,8 +481,6 @@ exports.handleSortData = (origin, params) => { @@ -477,8 +481,6 @@ exports.handleSortData = (origin, params) => {
477 href: handleFilterUrl(params, {}, {msort: true, misort: true}) 481 href: handleFilterUrl(params, {}, {msort: true, misort: true})
478 }]; 482 }];
479 483
480 - //  
481 -  
482 _.forEach(origin, value => { 484 _.forEach(origin, value => {
483 let category = { 485 let category = {
484 name: value.sort_name, 486 name: value.sort_name,
@@ -511,6 +513,25 @@ exports.handleSortData = (origin, params) => { @@ -511,6 +513,25 @@ exports.handleSortData = (origin, params) => {
511 category.active = true; 513 category.active = true;
512 } 514 }
513 515
  516 + if (subValue.sort_id === params.misort && subValue.sub && subValue.sub.length > 2) {
  517 + _.forEach(subValue.sub, smallSort => {
  518 +
  519 + leftContent.sort.misort.push({
  520 + id: smallSort.sort_id,
  521 + name: smallSort.sort_name,
  522 + checked: smallSort.sort_id === _.get(originParams, 'sort'),
  523 + href: handleFilterUrl(originParams, {sort: smallSort.sort_id})
  524 + });
  525 +
  526 + if (smallSort.sort_id === _.get(originParams, 'sort')) {
  527 + leftContent.checked.push({
  528 + name: smallSort.sort_name,
  529 + href: handleFilterUrl(originParams, {sort: ''})
  530 + });
  531 + }
  532 +
  533 + });
  534 + }
514 }); 535 });
515 536
516 list.push(category); 537 list.push(category);
@@ -582,6 +603,9 @@ exports.handleFilterData = (origin, params, total) => { @@ -582,6 +603,9 @@ exports.handleFilterData = (origin, params, total) => {
582 if (params.price === key) { 603 if (params.price === key) {
583 priceRangechecked = true; 604 priceRangechecked = true;
584 } 605 }
  606 + if (_.isString(value)) {
  607 + value = _.replace(value, '¥', '¥');
  608 + }
585 let price = { 609 let price = {
586 checked: params.price === key, 610 checked: params.price === key,
587 href: handleFilterUrl(params, {price: key}), 611 href: handleFilterUrl(params, {price: key}),
@@ -25,7 +25,7 @@ exports.getSearchData = (params, channel) => { @@ -25,7 +25,7 @@ exports.getSearchData = (params, channel) => {
25 // 调用接口 25 // 调用接口
26 let apiMethod = [ 26 let apiMethod = [
27 headerModel.requestHeaderData(channel), 27 headerModel.requestHeaderData(channel),
28 - searchApi.getSortList(Object.assign({}, searchParams, {msort: '', misort: ''})), 28 + searchApi.getSortList(Object.assign({}, searchParams, {msort: '', misort: '', sort: ''})),
29 searchApi.getProductList(searchParams), 29 searchApi.getProductList(searchParams),
30 searchApi.getShopList(params) 30 searchApi.getShopList(params)
31 ]; 31 ];
@@ -54,21 +54,28 @@ exports.getSearchData = (params, channel) => { @@ -54,21 +54,28 @@ exports.getSearchData = (params, channel) => {
54 }); 54 });
55 55
56 finalResult.search = { 56 finalResult.search = {
57 - leftContent: searchHandler.handleSortData(result[1].data.sort, dps) 57 + leftContent: searchHandler.handleSortData(result[1].data.sort, dps, params)
58 }; 58 };
59 } 59 }
60 60
61 // 获取商品数据和顶部筛选条件 61 // 获取商品数据和顶部筛选条件
62 if (result[2].code === 200) { 62 if (result[2].code === 200) {
  63 +
  64 + let filters = Object.assign(searchHandler.handleFilterDataAll(result[2].data, params),
  65 + finalResult.search.leftContent.sort);
  66 +
  67 + filters.checkedConditions.conditions = _.concat(filters.checkedConditions.conditions,
  68 + finalResult.search.leftContent.checked);
  69 +
63 Object.assign(finalResult.search, 70 Object.assign(finalResult.search,
64 searchHandler.handlePathNavData({total: result[2].data.total }, params, 'search', channel), 71 searchHandler.handlePathNavData({total: result[2].data.total }, params, 'search', channel),
65 { 72 {
66 - filters: searchHandler.handleFilterDataAll(result[2].data, params), 73 + filters: filters,
67 opts: searchHandler.handleOptsData(params, result[2].data.total, result[2].data.filter), 74 opts: searchHandler.handleOptsData(params, result[2].data.total, result[2].data.filter),
68 totalCount: result[2].data.total, 75 totalCount: result[2].data.total,
69 footPager: searchHandler.handlePagerData(result[2].data.total, params), 76 footPager: searchHandler.handlePagerData(result[2].data.total, params),
70 goods: productProcess.processProductList(result[2].data.product_list, 77 goods: productProcess.processProductList(result[2].data.product_list,
71 - Object.assign({showDiscount: false}, params)), 78 + Object.assign({showDiscount: false, from: {type: 'search', params: params}}, params)),
72 latestWalk: 6, 79 latestWalk: 6,
73 hasNextPage: searchHandler.handleNextPage(params, result[2].data.total), 80 hasNextPage: searchHandler.handleNextPage(params, result[2].data.total),
74 shopEntry: result[3] 81 shopEntry: result[3]
@@ -77,8 +77,8 @@ router.get('/list/index', list.index); @@ -77,8 +77,8 @@ router.get('/list/index', list.index);
77 router.get('/list/new', list.new); 77 router.get('/list/new', list.new);
78 78
79 // 品牌页 79 // 品牌页
80 -router.get('/brand/:brandDomain', list.brand);  
81 -router.get('/about/:brandDomain', list.brandAbout); 80 +router.get('/index/brand', list.brand);
  81 +router.get('/index/about', list.brandAbout);
82 82
83 router.get('/shoplist', list.shopList); // 店铺列表页 83 router.get('/shoplist', list.shopList); // 店铺列表页
84 router.post('/shop/togglecollect', favorite.collectShop); // 店铺收藏 84 router.post('/shop/togglecollect', favorite.collectShop); // 店铺收藏
@@ -16,8 +16,8 @@ module.exports = { @@ -16,8 +16,8 @@ module.exports = {
16 siteUrl: 'http://www.yohobuy.com', 16 siteUrl: 'http://www.yohobuy.com',
17 domains: { 17 domains: {
18 favApi: 'http://192.168.102.31:8092/brower', 18 favApi: 'http://192.168.102.31:8092/brower',
19 - api: 'http://api-test1.yohops.com:9999/',  
20 - service: 'http://service-test1.yohops.com:9999/', 19 + api: 'http://api.yoho.cn/',
  20 + service: 'http://service.yoho.cn/',
21 search: 'http://192.168.102.216:8080/yohosearch/' 21 search: 'http://192.168.102.216:8080/yohosearch/'
22 }, 22 },
23 subDomains: { 23 subDomains: {
@@ -14,4 +14,5 @@ module.exports = app => { @@ -14,4 +14,5 @@ module.exports = app => {
14 app.use('/product', require('./apps/product')); // 商品相关页面 14 app.use('/product', require('./apps/product')); // 商品相关页面
15 app.use(require('./apps/passport')); // 登录注册 15 app.use(require('./apps/passport')); // 登录注册
16 app.use('/home', require('./apps/home')); // 会员中心 16 app.use('/home', require('./apps/home')); // 会员中心
  17 + app.use('/guang', require('./apps/guang'));
17 }; 18 };
@@ -7,16 +7,24 @@ @@ -7,16 +7,24 @@
7 7
8 module.exports = () => { 8 module.exports = () => {
9 return (req, res, next) => { 9 return (req, res, next) => {
10 - let searchReg = /^\/product\//; 10 + let searchReg = /^\/product\//,
  11 + guangReg = /^\/guang/,
  12 + guangDetailReg = /.html$/;
11 13
12 if (req.subdomains.length) { 14 if (req.subdomains.length) {
13 switch (req.subdomains[0]) { 15 switch (req.subdomains[0]) {
14 case 'www': // 主站 16 case 'www': // 主站
15 case 'new': // 原新版 17 case 'new': // 原新版
16 - case 'guang': // 逛  
17 case 'shop': // 商家入驻 18 case 'shop': // 商家入驻
18 case 'item':// 商品详情页 19 case 'item':// 商品详情页
19 break; 20 break;
  21 + case 'guang': // 逛
  22 + if (guangDetailReg.test(req.path)) {
  23 + req.url = '/guang/detail' + req.url;
  24 + } else if (!guangReg.test(req.path)) {
  25 + req.url = '/guang' + req.url;
  26 + }
  27 + break;
20 case 'search': // 搜索 28 case 'search': // 搜索
21 if (!searchReg.test(req.path)) { 29 if (!searchReg.test(req.path)) {
22 if (req.path === '/api/suggest') { 30 if (req.path === '/api/suggest') {
@@ -40,9 +48,11 @@ module.exports = () => { @@ -40,9 +48,11 @@ module.exports = () => {
40 break; 48 break;
41 default: // 其它(识别为品牌) 49 default: // 其它(识别为品牌)
42 if (!req.path || req.path === '/') { 50 if (!req.path || req.path === '/') {
43 - req.url = `/product/brand/${req.subdomains[0]}`; 51 + req.url = `/product/index/brand?domain=${req.subdomains[0]}`;
  52 + req.query.domain = req.subdomains[0];
44 } else if (req.path === '/about') { 53 } else if (req.path === '/about') {
45 - req.url = `/product/about/${req.subdomains[0]}`; 54 + req.url = `/product/index/about?domain=${req.subdomains[0]}`;
  55 + req.query.domain = req.subdomains[0];
46 } 56 }
47 break; 57 break;
48 } 58 }
@@ -50,20 +50,6 @@ @@ -50,20 +50,6 @@
50 </div> 50 </div>
51 {{/if}} 51 {{/if}}
52 52
53 - {{#if ageLevel}}  
54 - <div class="channel section">  
55 - <span class="title">人群:</span>  
56 -  
57 - <div class="attr-content clearfix">  
58 - {{#each ageLevel}}  
59 - <a class="attr {{#if checked}}checked{{/if}}" href="{{href}}">  
60 - {{name}}  
61 - </a>  
62 - {{/each}}  
63 - </div>  
64 - </div>  
65 - {{/if}}  
66 -  
67 {{#if sort}} 53 {{#if sort}}
68 <div class="sort section"> 54 <div class="sort section">
69 <span class="title">分类:</span> 55 <span class="title">分类:</span>
@@ -143,6 +129,20 @@ @@ -143,6 +129,20 @@
143 {{> product/filter-brands}} 129 {{> product/filter-brands}}
144 </script> 130 </script>
145 131
  132 + {{#if ageLevel}}
  133 + <div class="channel section">
  134 + <span class="title">人群:</span>
  135 +
  136 + <div class="attr-content clearfix">
  137 + {{#each ageLevel}}
  138 + <a class="attr {{#if checked}}checked{{/if}}" href="{{href}}">
  139 + {{name}}
  140 + </a>
  141 + {{/each}}
  142 + </div>
  143 + </div>
  144 + {{/if}}
  145 +
146 {{#if price}} 146 {{#if price}}
147 <div class="price section"> 147 <div class="price section">
148 <span class="title">价格:</span> 148 <span class="title">价格:</span>
@@ -78,7 +78,7 @@ @@ -78,7 +78,7 @@
78 </p> 78 </p>
79 <div class="hideList hide"> 79 <div class="hideList hide">
80 {{#goods_list}} 80 {{#goods_list}}
81 - <li data-src="{{image images_url 280 374}}" data-url="{{../url}}" data-status="{{status}}"></li> 81 + <li data-src="{{image images_url 280 382}}" data-url="{{../url}}" data-status="{{status}}"></li>
82 {{/goods_list}} 82 {{/goods_list}}
83 </div> 83 </div>
84 </div> 84 </div>
  1 +<span class="share-wrapper share-to pull-left clearfix">
  2 + <i class="weibo" data-type="weibo" title="分享到新浪微博"></i>
  3 + <i class="weixin" data-type="weixin" title="分享到微信朋友圈"></i>
  4 + <i class="tweibo" data-type="tweibo" title="分享到腾讯微博"></i>
  5 + <i class="qzone" data-type="qzone" title="分享到QQ空间"></i>
  6 + <i class="qq" data-type="qq" title="分享到QQ好友"></i>
  7 + <i class="renren" data-type="renren" title="分享到人人"></i>
  8 + <i class="douban" data-type="douban" title="分享到豆瓣"></i>
  9 + <div class="weixin-share-box"></div>
  10 +</span>
  11 +<input id="share-img" type="hidden" value="{{shareImg}}">
  12 +<input id="share-desc" type="hidden" value="{{shareDesc}}">
  13 +<input id="weixin-url" type="hidden" value="{{weixinUrl}}">
1 { 1 {
2 "name": "yohobuy-node", 2 "name": "yohobuy-node",
3 - "version": "5.0.2", 3 + "version": "5.0.4",
4 "private": true, 4 "private": true,
5 "description": "A New Yohobuy Project With Express", 5 "description": "A New Yohobuy Project With Express",
6 "repository": { 6 "repository": {
@@ -37,6 +37,7 @@ @@ -37,6 +37,7 @@
37 "connect-memcached": "^0.2.0", 37 "connect-memcached": "^0.2.0",
38 "cookie-parser": "^1.4.3", 38 "cookie-parser": "^1.4.3",
39 "express": "^4.13.1", 39 "express": "^4.13.1",
  40 + "handlebars": "^4.0.5",
40 "express-handlebars": "^3.0.0", 41 "express-handlebars": "^3.0.0",
41 "influxdb-winston": "^1.0.1", 42 "influxdb-winston": "^1.0.1",
42 "lodash": "^4.13.1", 43 "lodash": "^4.13.1",
@@ -53,6 +54,7 @@ @@ -53,6 +54,7 @@
53 "passport-sina": "^0.1.0", 54 "passport-sina": "^0.1.0",
54 "passport-strategy": "1.x.x", 55 "passport-strategy": "1.x.x",
55 "passport-weixin": "^0.1.0", 56 "passport-weixin": "^0.1.0",
  57 + "request-ip": "^1.2.2",
56 "request-promise": "^3.0.0", 58 "request-promise": "^3.0.0",
57 "serve-favicon": "^2.3.0", 59 "serve-favicon": "^2.3.0",
58 "uuid": "^2.0.2", 60 "uuid": "^2.0.2",
@@ -103,7 +105,8 @@ @@ -103,7 +105,8 @@
103 "yoho-jquery-lazyload": "^1.9.7", 105 "yoho-jquery-lazyload": "^1.9.7",
104 "yoho-jquery-pjax": "0.0.1", 106 "yoho-jquery-pjax": "0.0.1",
105 "yoho-jquery-placeholder": "^2.3.1", 107 "yoho-jquery-placeholder": "^2.3.1",
106 - "yoho-jquery-qrcode": "^0.14.0",  
107 - "yoho-slider": "0.0.2" 108 + "yoho-slider": "0.0.2",
  109 + "yoho-jquery-dotdotdot": "0.0.1",
  110 + "yoho-jquery-qrcode": "^0.14.0"
108 } 111 }
109 } 112 }
  1 +*{margin: 0;padding: 0;list-style: none;}
  2 +/*
  3 +KISSY CSS Reset
  4 +理念:1. reset 的目的不是清除浏览器的默认样式,这仅是部分工作。清除和重置是紧密不可分的。
  5 +2. reset 的目的不是让默认样式在所有浏览器下一致,而是减少默认样式有可能带来的问题。
  6 +3. reset 期望提供一套普适通用的基础样式。但没有银弹,推荐根据具体需求,裁剪和修改后再使用。
  7 +特色:1. 适应中文;2. 基于最新主流浏览器。
  8 +维护:玉伯<lifesinger@gmail.com>, 正淳<ragecarrier@gmail.com>
  9 + */
  10 +
  11 +/** 清除内外边距 **/
  12 +body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 结构元素 */
  13 +dl, dt, dd, ul, ol, li, /* list elements 列表元素 */
  14 +pre, /* text formatting elements 文本格式元素 */
  15 +form, fieldset, legend, button, input, textarea, /* form elements 表单元素 */
  16 +th, td /* table elements 表格元素 */ {
  17 + margin: 0;
  18 + padding: 0;
  19 +}
  20 +
  21 +/** 设置默认字体 **/
  22 +body,
  23 +button, input, select, textarea /* for ie */ {
  24 + font: 12px/1.5 tahoma, arial, \5b8b\4f53, sans-serif;
  25 +}
  26 +h1, h2, h3, h4, h5, h6 { font-size: 100%; }
  27 +address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */
  28 +code, kbd, pre, samp { font-family: courier new, courier, monospace; } /* 统一等宽字体 */
  29 +small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */
  30 +
  31 +/** 重置列表元素 **/
  32 +ul, ol { list-style: none; }
  33 +
  34 +/** 重置文本格式元素 **/
  35 +a { text-decoration: none; }
  36 +a:hover { text-decoration: underline; }
  37 +
  38 +
  39 +/** 重置表单元素 **/
  40 +legend { color: #000; } /* for ie6 */
  41 +fieldset, img { border: 0; } /* img 搭车:让链接里的 img 无边框 */
  42 +button, input, select, textarea { font-size: 100%; } /* 使得表单元素在 ie 下能继承字体大小 */
  43 +/* 注:optgroup 无法扶正 */
  44 +
  45 +/** 重置表格元素 **/
  46 +table { border-collapse: collapse; border-spacing: 0; }
  47 +
  48 +/* 清除浮动 */
  49 +.ks-clear:after, .clear:after {
  50 + content: '\20';
  51 + display: block;
  52 + height: 0;
  53 + clear: both;
  54 +}
  55 +.ks-clear, .clear {
  56 + *zoom: 1;
  57 +}
  58 +
  59 +.main {padding: 30px 100px;}
  60 +.main h1{font-size:36px; color:#333; text-align:left;margin-bottom:30px; border-bottom: 1px solid #eee;}
  61 +
  62 +.helps{margin-top:40px;}
  63 +.helps pre{
  64 + padding:20px;
  65 + margin:10px 0;
  66 + border:solid 1px #e7e1cd;
  67 + background-color: #fffdef;
  68 + overflow: auto;
  69 +}
  70 +
  71 +.icon_lists li{
  72 + float:left;
  73 + width: 100px;
  74 + height:180px;
  75 + text-align: center;
  76 +}
  77 +.icon_lists .icon{
  78 + font-size: 42px;
  79 + line-height: 100px;
  80 + margin: 10px 0;
  81 + color:#333;
  82 + -webkit-transition: font-size 0.25s ease-out 0s;
  83 + -moz-transition: font-size 0.25s ease-out 0s;
  84 + transition: font-size 0.25s ease-out 0s;
  85 +
  86 +}
  87 +.icon_lists .icon:hover{
  88 + font-size: 100px;
  89 +}
  1 +
  2 +<!DOCTYPE html>
  3 +<html>
  4 +<head>
  5 + <meta charset="utf-8"/>
  6 + <title>IconFont</title>
  7 + <link rel="stylesheet" href="demo.css">
  8 + <link rel="stylesheet" href="iconfont.css">
  9 +</head>
  10 +<body>
  11 + <div class="main">
  12 + <h1>IconFont 图标</h1>
  13 + <ul class="icon_lists clear">
  14 +
  15 + <li>
  16 + <i class="icon iconfont">&#xe624;</i>
  17 + <div class="name">评论</div>
  18 + <div class="code">&amp;#xe624;</div>
  19 + <div class="fontclass">.pinglun</div>
  20 + </li>
  21 +
  22 + <li>
  23 + <i class="icon iconfont">&#xe618;</i>
  24 + <div class="name">左三角</div>
  25 + <div class="code">&amp;#xe618;</div>
  26 + <div class="fontclass">.zuosanjiao</div>
  27 + </li>
  28 +
  29 + <li>
  30 + <i class="icon iconfont">&#xe619;</i>
  31 + <div class="name">右三角</div>
  32 + <div class="code">&amp;#xe619;</div>
  33 + <div class="fontclass">.yousanjiao</div>
  34 + </li>
  35 +
  36 + <li>
  37 + <i class="icon iconfont">&#xe60b;</i>
  38 + <div class="name">向下</div>
  39 + <div class="code">&amp;#xe60b;</div>
  40 + <div class="fontclass">.chevron-down</div>
  41 + </li>
  42 +
  43 + <li>
  44 + <i class="icon iconfont">&#xe60c;</i>
  45 + <div class="name">向右</div>
  46 + <div class="code">&amp;#xe60c;</div>
  47 + <div class="fontclass">.chevron-right</div>
  48 + </li>
  49 +
  50 + <li>
  51 + <i class="icon iconfont">&#xe605;</i>
  52 + <div class="name">对号</div>
  53 + <div class="code">&amp;#xe605;</div>
  54 + <div class="fontclass">.duihao</div>
  55 + </li>
  56 +
  57 + <li>
  58 + <i class="icon iconfont">&#xe61b;</i>
  59 + <div class="name">购物车</div>
  60 + <div class="code">&amp;#xe61b;</div>
  61 + <div class="fontclass">.gouwuche</div>
  62 + </li>
  63 +
  64 + <li>
  65 + <i class="icon iconfont">&#xe60d;</i>
  66 + <div class="name"></div>
  67 + <div class="code">&amp;#xe60d;</div>
  68 + <div class="fontclass">.cha</div>
  69 + </li>
  70 +
  71 + <li>
  72 + <i class="icon iconfont">&#xe61c;</i>
  73 + <div class="name">forbid</div>
  74 + <div class="code">&amp;#xe61c;</div>
  75 + <div class="fontclass">.forbid</div>
  76 + </li>
  77 +
  78 + <li>
  79 + <i class="icon iconfont">&#xe60e;</i>
  80 + <div class="name">left</div>
  81 + <div class="code">&amp;#xe60e;</div>
  82 + <div class="fontclass">.left</div>
  83 + </li>
  84 +
  85 + <li>
  86 + <i class="icon iconfont">&#xe614;</i>
  87 + <div class="name">sort</div>
  88 + <div class="code">&amp;#xe614;</div>
  89 + <div class="fontclass">.sort</div>
  90 + </li>
  91 +
  92 + <li>
  93 + <i class="icon iconfont">&#xe625;</i>
  94 + <div class="name">时间</div>
  95 + <div class="code">&amp;#xe625;</div>
  96 + <div class="fontclass">.iconsj</div>
  97 + </li>
  98 +
  99 + <li>
  100 + <i class="icon iconfont">&#xe60f;</i>
  101 + <div class="name">search</div>
  102 + <div class="code">&amp;#xe60f;</div>
  103 + <div class="fontclass">.search</div>
  104 + </li>
  105 +
  106 + <li>
  107 + <i class="icon iconfont">&#xe615;</i>
  108 + <div class="name">三角2</div>
  109 + <div class="code">&amp;#xe615;</div>
  110 + <div class="fontclass">.sanjiao2</div>
  111 + </li>
  112 +
  113 + <li>
  114 + <i class="icon iconfont">&#xe610;</i>
  115 + <div class="name">三角1</div>
  116 + <div class="code">&amp;#xe610;</div>
  117 + <div class="fontclass">.sanjiao1</div>
  118 + </li>
  119 +
  120 + <li>
  121 + <i class="icon iconfont">&#xe608;</i>
  122 + <div class="name">向右</div>
  123 + <div class="code">&amp;#xe608;</div>
  124 + <div class="fontclass">.xiangyou</div>
  125 + </li>
  126 +
  127 + <li>
  128 + <i class="icon iconfont">&#xe609;</i>
  129 + <div class="name">向左</div>
  130 + <div class="code">&amp;#xe609;</div>
  131 + <div class="fontclass">.xiangzuo</div>
  132 + </li>
  133 +
  134 + <li>
  135 + <i class="icon iconfont">&#xe620;</i>
  136 + <div class="name">问号</div>
  137 + <div class="code">&amp;#xe620;</div>
  138 + <div class="fontclass">.wenhao</div>
  139 + </li>
  140 +
  141 + <li>
  142 + <i class="icon iconfont">&#xe61d;</i>
  143 + <div class="name">向下</div>
  144 + <div class="code">&amp;#xe61d;</div>
  145 + <div class="fontclass">.xiangxia</div>
  146 + </li>
  147 +
  148 + <li>
  149 + <i class="icon iconfont">&#xe621;</i>
  150 + <div class="name">电话</div>
  151 + <div class="code">&amp;#xe621;</div>
  152 + <div class="fontclass">.dianhua</div>
  153 + </li>
  154 +
  155 + <li>
  156 + <i class="icon iconfont">&#xe60a;</i>
  157 + <div class="name">time</div>
  158 + <div class="code">&amp;#xe60a;</div>
  159 + <div class="fontclass">.time</div>
  160 + </li>
  161 +
  162 + <li>
  163 + <i class="icon iconfont">&#xe626;</i>
  164 + <div class="name"></div>
  165 + <div class="code">&amp;#xe626;</div>
  166 + <div class="fontclass">.zan</div>
  167 + </li>
  168 +
  169 + <li>
  170 + <i class="icon iconfont">&#xe607;</i>
  171 + <div class="name">up</div>
  172 + <div class="code">&amp;#xe607;</div>
  173 + <div class="fontclass">.up</div>
  174 + </li>
  175 +
  176 + <li>
  177 + <i class="icon iconfont">&#xe611;</i>
  178 + <div class="name">Heart</div>
  179 + <div class="code">&amp;#xe611;</div>
  180 + <div class="fontclass">.heart</div>
  181 + </li>
  182 +
  183 + <li>
  184 + <i class="icon iconfont">&#xe616;</i>
  185 + <div class="name">login_check_button1</div>
  186 + <div class="code">&amp;#xe616;</div>
  187 + <div class="fontclass">.logincheckbutton1</div>
  188 + </li>
  189 +
  190 + <li>
  191 + <i class="icon iconfont">&#xe601;</i>
  192 + <div class="name">mail</div>
  193 + <div class="code">&amp;#xe601;</div>
  194 + <div class="fontclass">.aaa</div>
  195 + </li>
  196 +
  197 + <li>
  198 + <i class="icon iconfont">&#xe61e;</i>
  199 + <div class="name">评论</div>
  200 + <div class="code">&amp;#xe61e;</div>
  201 + <div class="fontclass">.pinglun1</div>
  202 + </li>
  203 +
  204 + <li>
  205 + <i class="icon iconfont">&#xe622;</i>
  206 + <div class="name">正确</div>
  207 + <div class="code">&amp;#xe622;</div>
  208 + <div class="fontclass">.zhengque</div>
  209 + </li>
  210 +
  211 + <li>
  212 + <i class="icon iconfont">&#xe606;</i>
  213 + <div class="name">circle</div>
  214 + <div class="code">&amp;#xe606;</div>
  215 + <div class="fontclass">.circle</div>
  216 + </li>
  217 +
  218 + <li>
  219 + <i class="icon iconfont">&#xe627;</i>
  220 + <div class="name">eye</div>
  221 + <div class="code">&amp;#xe627;</div>
  222 + <div class="fontclass">.eye</div>
  223 + </li>
  224 +
  225 + <li>
  226 + <i class="icon iconfont">&#xe61f;</i>
  227 + <div class="name">03-叹号</div>
  228 + <div class="code">&amp;#xe61f;</div>
  229 + <div class="fontclass">.03tanhao</div>
  230 + </li>
  231 +
  232 + <li>
  233 + <i class="icon iconfont">&#xe61a;</i>
  234 + <div class="name">home</div>
  235 + <div class="code">&amp;#xe61a;</div>
  236 + <div class="fontclass">.home</div>
  237 + </li>
  238 +
  239 + <li>
  240 + <i class="icon iconfont">&#xe600;</i>
  241 + <div class="name">shopping-card</div>
  242 + <div class="code">&amp;#xe600;</div>
  243 + <div class="fontclass">.shoppingcard</div>
  244 + </li>
  245 +
  246 + <li>
  247 + <i class="icon iconfont">&#xe617;</i>
  248 + <div class="name">checkbox-checked</div>
  249 + <div class="code">&amp;#xe617;</div>
  250 + <div class="fontclass">.checkboxchecked</div>
  251 + </li>
  252 +
  253 + <li>
  254 + <i class="icon iconfont">&#xe623;</i>
  255 + <div class="name">五角星</div>
  256 + <div class="code">&amp;#xe623;</div>
  257 + <div class="fontclass">.wujiaoxing</div>
  258 + </li>
  259 +
  260 + <li>
  261 + <i class="icon iconfont">&#xe612;</i>
  262 + <div class="name">select</div>
  263 + <div class="code">&amp;#xe612;</div>
  264 + <div class="fontclass">.zhengchang</div>
  265 + </li>
  266 +
  267 + <li>
  268 + <i class="icon iconfont">&#xe613;</i>
  269 + <div class="name">selected</div>
  270 + <div class="code">&amp;#xe613;</div>
  271 + <div class="fontclass">.weibiaoti7</div>
  272 + </li>
  273 +
  274 + <li>
  275 + <i class="icon iconfont">&#xe602;</i>
  276 + <div class="name">sya</div>
  277 + <div class="code">&amp;#xe602;</div>
  278 + <div class="fontclass">.say1</div>
  279 + </li>
  280 +
  281 + <li>
  282 + <i class="icon iconfont">&#xe603;</i>
  283 + <div class="name">7days</div>
  284 + <div class="code">&amp;#xe603;</div>
  285 + <div class="fontclass">.7t11</div>
  286 + </li>
  287 +
  288 + <li>
  289 + <i class="icon iconfont">&#xe604;</i>
  290 + <div class="name">zheng</div>
  291 + <div class="code">&amp;#xe604;</div>
  292 + <div class="fontclass">.z</div>
  293 + </li>
  294 +
  295 + </ul>
  296 +
  297 +
  298 + <div class="helps">
  299 + 第一步:使用font-face声明字体
  300 + <pre>
  301 +@font-face {font-family: 'iconfont';
  302 + src: url('iconfont.eot'); /* IE9*/
  303 + src: url('iconfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
  304 + url('iconfont.woff') format('woff'), /* chrome、firefox */
  305 + url('iconfont.ttf') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
  306 + url('iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */
  307 +}
  308 +</pre>
  309 +第二步:定义使用iconfont的样式
  310 + <pre>
  311 +.iconfont{
  312 + font-family:"iconfont" !important;
  313 + font-size:16px;font-style:normal;
  314 + -webkit-font-smoothing: antialiased;
  315 + -webkit-text-stroke-width: 0.2px;
  316 + -moz-osx-font-smoothing: grayscale;}
  317 +</pre>
  318 +第三步:挑选相应图标并获取字体编码,应用于页面
  319 +<pre>
  320 +&lt;i class="iconfont"&gt;&amp;#x33;&lt;/i&gt;
  321 +</pre>
  322 + </div>
  323 +
  324 + </div>
  325 +</body>
  326 +</html>
  1 +
  2 +@font-face {font-family: "iconfont";
  3 + src: url('iconfont.eot?t=1473148446'); /* IE9*/
  4 + src: url('iconfont.eot?t=1473148446#iefix') format('embedded-opentype'), /* IE6-IE8 */
  5 + url('iconfont.woff?t=1473148446') format('woff'), /* chrome, firefox */
  6 + url('iconfont.ttf?t=1473148446') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
  7 + url('iconfont.svg?t=1473148446#iconfont') format('svg'); /* iOS 4.1- */
  8 +}
  9 +
  10 +.iconfont {
  11 + font-family:"iconfont" !important;
  12 + font-size:16px;
  13 + font-style:normal;
  14 + -webkit-font-smoothing: antialiased;
  15 + -webkit-text-stroke-width: 0.2px;
  16 + -moz-osx-font-smoothing: grayscale;
  17 +}
  18 +.icon-pinglun:before { content: "\e624"; }
  19 +.icon-zuosanjiao:before { content: "\e618"; }
  20 +.icon-yousanjiao:before { content: "\e619"; }
  21 +.icon-chevron-down:before { content: "\e60b"; }
  22 +.icon-chevron-right:before { content: "\e60c"; }
  23 +.icon-duihao:before { content: "\e605"; }
  24 +.icon-gouwuche:before { content: "\e61b"; }
  25 +.icon-cha:before { content: "\e60d"; }
  26 +.icon-forbid:before { content: "\e61c"; }
  27 +.icon-left:before { content: "\e60e"; }
  28 +.icon-sort:before { content: "\e614"; }
  29 +.icon-iconsj:before { content: "\e625"; }
  30 +.icon-search:before { content: "\e60f"; }
  31 +.icon-sanjiao2:before { content: "\e615"; }
  32 +.icon-sanjiao1:before { content: "\e610"; }
  33 +.icon-xiangyou:before { content: "\e608"; }
  34 +.icon-xiangzuo:before { content: "\e609"; }
  35 +.icon-wenhao:before { content: "\e620"; }
  36 +.icon-xiangxia:before { content: "\e61d"; }
  37 +.icon-dianhua:before { content: "\e621"; }
  38 +.icon-time:before { content: "\e60a"; }
  39 +.icon-zan:before { content: "\e626"; }
  40 +.icon-up:before { content: "\e607"; }
  41 +.icon-heart:before { content: "\e611"; }
  42 +.icon-logincheckbutton1:before { content: "\e616"; }
  43 +.icon-aaa:before { content: "\e601"; }
  44 +.icon-pinglun1:before { content: "\e61e"; }
  45 +.icon-zhengque:before { content: "\e622"; }
  46 +.icon-circle:before { content: "\e606"; }
  47 +.icon-eye:before { content: "\e627"; }
  48 +.icon-03tanhao:before { content: "\e61f"; }
  49 +.icon-home:before { content: "\e61a"; }
  50 +.icon-shoppingcard:before { content: "\e600"; }
  51 +.icon-checkboxchecked:before { content: "\e617"; }
  52 +.icon-wujiaoxing:before { content: "\e623"; }
  53 +.icon-zhengchang:before { content: "\e612"; }
  54 +.icon-weibiaoti7:before { content: "\e613"; }
  55 +.icon-say1:before { content: "\e602"; }
  56 +.icon-7t11:before { content: "\e603"; }
  57 +.icon-z:before { content: "\e604"; }
No preview for this file type
@@ -2,7 +2,11 @@ @@ -2,7 +2,11 @@
2 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > 2 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
3 <svg xmlns="http://www.w3.org/2000/svg"> 3 <svg xmlns="http://www.w3.org/2000/svg">
4 <metadata> 4 <metadata>
  5 +<<<<<<< HEAD
  6 +Created by FontForge 20120731 at Tue Sep 6 15:54:06 2016
  7 +=======
5 Created by FontForge 20120731 at Wed Sep 21 17:18:20 2016 8 Created by FontForge 20120731 at Wed Sep 21 17:18:20 2016
  9 +>>>>>>> remotes/origin/master
6 By admin 10 By admin
7 </metadata> 11 </metadata>
8 <defs> 12 <defs>
@@ -19,7 +23,11 @@ Created by FontForge 20120731 at Wed Sep 21 17:18:20 2016 @@ -19,7 +23,11 @@ Created by FontForge 20120731 at Wed Sep 21 17:18:20 2016
19 bbox="0 -212 1158 896" 23 bbox="0 -212 1158 896"
20 underline-thickness="50" 24 underline-thickness="50"
21 underline-position="-100" 25 underline-position="-100"
  26 +<<<<<<< HEAD
  27 + unicode-range="U+0078-E627"
  28 +=======
22 unicode-range="U+0078-E62A" 29 unicode-range="U+0078-E62A"
  30 +>>>>>>> remotes/origin/master
23 /> 31 />
24 <missing-glyph horiz-adv-x="374" 32 <missing-glyph horiz-adv-x="374"
25 d="M34 0v682h272v-682h-272zM68 34h204v614h-204v-614z" /> 33 d="M34 0v682h272v-682h-272zM68 34h204v614h-204v-614z" />
@@ -141,6 +149,8 @@ q0 -28 20 -48.5t49 -20.5h137v518h-137q-29 0 -49 -20.5t-20 -48.5zM0 379z" /> @@ -141,6 +149,8 @@ q0 -28 20 -48.5t49 -20.5h137v518h-137q-29 0 -49 -20.5t-20 -48.5zM0 379z" />
141 <glyph glyph-name="uniE627" unicode="&#xe627;" horiz-adv-x="1025" 149 <glyph glyph-name="uniE627" unicode="&#xe627;" horiz-adv-x="1025"
142 d="M512 719q-167 0 -304.5 -89.5t-205.5 -236.5q-4 -9 0 -18q68 -147 205.5 -236.5t304.5 -89.5t304.5 89.5t205.5 236.5q4 9 0 18q-68 147 -205.5 236.5t-304.5 89.5zM512 153q-96 0 -163.5 67.5t-67.5 163.5t67.5 163.5t163.5 67.5t163.5 -67.5t67.5 -163.5t-67.5 -163.5 150 d="M512 719q-167 0 -304.5 -89.5t-205.5 -236.5q-4 -9 0 -18q68 -147 205.5 -236.5t304.5 -89.5t304.5 89.5t205.5 236.5q4 9 0 18q-68 147 -205.5 236.5t-304.5 89.5zM512 153q-96 0 -163.5 67.5t-67.5 163.5t67.5 163.5t163.5 67.5t163.5 -67.5t67.5 -163.5t-67.5 -163.5
143 t-163.5 -67.5zM512 384zM364 384q0 61 43.5 104.5t104.5 43.5t104.5 -43.5t43.5 -104.5t-43.5 -104.5t-104.5 -43.5t-104.5 43.5t-43.5 104.5z" /> 151 t-163.5 -67.5zM512 384zM364 384q0 61 43.5 104.5t104.5 43.5t104.5 -43.5t43.5 -104.5t-43.5 -104.5t-104.5 -43.5t-104.5 43.5t-43.5 104.5z" />
  152 +<<<<<<< HEAD
  153 +=======
144 <glyph glyph-name="uniE628" unicode="&#xe628;" 154 <glyph glyph-name="uniE628" unicode="&#xe628;"
145 d="M512 886q-102 0 -195 -39.5t-160.5 -107t-107 -160.5t-39.5 -195t39.5 -195t107 -160.5t160.5 -107t195 -39.5t195 39.5t160.5 107t107 160.5t39.5 195t-39.5 195t-107 160.5t-160.5 107t-195 39.5zM521 -15q-34 0 -58.5 24t-24.5 58.5t24.5 58.5t58.5 24t58 -24t24 -58 155 d="M512 886q-102 0 -195 -39.5t-160.5 -107t-107 -160.5t-39.5 -195t39.5 -195t107 -160.5t160.5 -107t195 -39.5t195 39.5t160.5 107t107 160.5t39.5 195t-39.5 195t-107 160.5t-160.5 107t-195 39.5zM521 -15q-34 0 -58.5 24t-24.5 58.5t24.5 58.5t58.5 24t58 -24t24 -58
146 q1 -34 -23.5 -58.5t-58.5 -24.5zM738 477q-17 -34 -67 -83q-45 -43 -60 -61q-12 -16 -17 -35q-6 -22 -6 -61l1 -31h-142v30q0 56 9 90q11 38 30 64q17 23 62 71q43 44 52 60q8 13 8 44q0 28 -20 51q-20 21 -61 21q-29 0 -48.5 -9.5t-28.5 -27.5t-12.5 -36t-3.5 -43v-30h-142 156 q1 -34 -23.5 -58.5t-58.5 -24.5zM738 477q-17 -34 -67 -83q-45 -43 -60 -61q-12 -16 -17 -35q-6 -22 -6 -61l1 -31h-142v30q0 56 9 90q11 38 30 64q17 23 62 71q43 44 52 60q8 13 8 44q0 28 -20 51q-20 21 -61 21q-29 0 -48.5 -9.5t-28.5 -27.5t-12.5 -36t-3.5 -43v-30h-142
@@ -150,5 +160,6 @@ d="M511 833q-91 0 -174 -36t-143 -96t-95.5 -143t-35.5 -174t35.5 -174t95.5 -143t14 @@ -150,5 +160,6 @@ d="M511 833q-91 0 -174 -36t-143 -96t-95.5 -143t-35.5 -174t35.5 -174t95.5 -143t14
150 t-34 14t-14 34t14 34l192 191l-192 192q-14 14 -14 34t14 34t34 14t34 -14l192 -192l192 192q14 14 33.5 14t34 -14t14.5 -34t-15 -34l-191 -192z" /> 160 t-34 14t-14 34t14 34l192 191l-192 192q-14 14 -14 34t14 34t34 14t34 -14l192 -192l192 192q14 14 33.5 14t34 -14t14.5 -34t-15 -34l-191 -192z" />
151 <glyph glyph-name="uniE62A" unicode="&#xe62a;" 161 <glyph glyph-name="uniE62A" unicode="&#xe62a;"
152 d="M799 456l127 127v313h-830v-609l421 -413l409 404v181l-414 -401l-288 284v426h575v-312zM671 518l-107 22l-53 100l-52 -100l-108 -22l75 -83l-14 -114l99 49l99 -49l-14 114z" /> 162 d="M799 456l127 127v313h-830v-609l421 -413l409 404v181l-414 -401l-288 284v426h575v-312zM671 518l-107 22l-53 100l-52 -100l-108 -22l75 -83l-14 -114l99 49l99 -49l-14 114z" />
  163 +>>>>>>> remotes/origin/master
153 </font> 164 </font>
154 </defs></svg> 165 </defs></svg>
No preview for this file type
No preview for this file type
  1 +/**
  2 + * 分享
  3 + * @author: xuqi<qi.xu@yoho.cn>
  4 + * @date: 2016/3/1
  5 + */
  6 +
  7 +var $ = require('yoho-jquery');
  8 +
  9 +function shareBase(options) {
  10 + var openUrl = '';
  11 + var defOption = {
  12 + title: '',
  13 + url: window.location.href,
  14 + weixinUrl: '',
  15 + image: '',
  16 + desc: '',
  17 + channel: ''
  18 + };
  19 + var shareChannels = ['weibo', 'tweibo', 'qzone', 'renren', 'qq', 'douban', 'weixin'];
  20 + var sharebox;
  21 + var shareCon = '<em><i></i></em>';
  22 +
  23 + defOption = $.extend(defOption, options);
  24 +
  25 + if (defOption.image && defOption.image.substr(0, 2) === '//') {
  26 + defOption.image = 'http:' + defOption.image;
  27 + }
  28 +
  29 + if (defOption.weixinUrl && defOption.weixinUrl.substr(0, 2) === '//') {
  30 + defOption.weixinUrl = 'http:' + defOption.weixinUrl;
  31 + }
  32 +
  33 + if (defOption.url && defOption.url.substr(0, 2) === '//') {
  34 + defOption.url = 'http:' + defOption.url;
  35 + }
  36 +
  37 + if ($.inArray(defOption.channel, shareChannels) === -1) {
  38 + alert('不存在的分享平台!');
  39 + return false;
  40 + }
  41 +
  42 + switch (defOption.channel) {
  43 + case 'weibo':
  44 + openUrl = 'http://service.weibo.com/share/share.php?url=' + defOption.url + '&title=' +
  45 + defOption.title + '&appkey=3739328910&searchPic=true&pic=' + defOption.image;
  46 + break;
  47 + case 'tweibo':
  48 + openUrl = 'http://share.v.t.qq.com/index.php?c=share&a=index&url=' + defOption.url + '&title=' +
  49 + defOption.title + '&appkey=c0af9c29e0900813028c2ccb42021792&pic=' + defOption.image;
  50 + break;
  51 + case 'qzone':
  52 + openUrl = 'http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=' + defOption.url + '&title=' +
  53 + defOption.title + '&desc=&summary=' + defOption.desc + '&site=YOHO!BUY 有货&pics=' + defOption.image;
  54 + break;
  55 + case 'renren':
  56 + openUrl = 'http://widget.renren.com/dialog/share?resourceUrl=' + defOption.url + '&srcUrl=' +
  57 + defOption.url + '&desc=' + defOption.desc + '&title=' + defOption.title + '&description=' +
  58 + defOption.desc + '&pic=' + defOption.image;
  59 + break;
  60 + case 'qq':
  61 + openUrl = 'http://connect.qq.com/widget/shareqq/index.html?url=' + defOption.url + '&desc=' +
  62 + defOption.desc + '&title=' + defOption.title.replace('%', '') + '&desc=&summary=' +
  63 + defOption.desc + '&site=YOHO!BUY 有货&pics=' + defOption.image;
  64 + break;
  65 + case 'weixin':
  66 + openUrl = 'http://s.jiathis.com/qrcode.php?url=' + defOption.weixinUrl + '&desc=' +
  67 + defOption.desc + '&title=' + defOption.title + '&description=' +
  68 + defOption.desc + '&pic=' + defOption.image;
  69 + break;
  70 + case 'douban':
  71 + openUrl = '//www.douban.com/share/service?href=' + defOption.url + '&text=' +
  72 + defOption.desc + '&image=' + defOption.image + '&title=' + defOption.title + '&comment=';
  73 + break;
  74 + }
  75 +
  76 + if (defOption.channel === 'weixin') {
  77 + if (!defOption.self) {
  78 + return;
  79 + }
  80 +
  81 + sharebox = defOption.self.closest('.share-to').find('.weixin-share-box');
  82 +
  83 + if (sharebox.length > 0) {
  84 + shareCon += '<div class="con"><h2>分享到微信朋友圈</h2><p class="pic">' +
  85 + '<img src="' + openUrl + '" /></p><p class="w">打开微信,点击底部得“发现”,使用<br/>“扫一扫“即可将网页分享到我的朋友圈。</p>' +
  86 + '<a href="javascript:void(0)" class="close">x</a></div>';
  87 + sharebox.find('div').length > 0 ? sharebox.show() : sharebox.html(shareCon).show();
  88 +
  89 + sharebox.find('.close').click(function() {
  90 + $(this).closest('.weixin-share-box').hide();
  91 + });
  92 + }
  93 + } else {
  94 + window.open(encodeURI(openUrl));
  95 + }
  96 +}
  97 +
  98 +function share(channel, self) {
  99 + var title = document.title.replace(/(^\s*)|(\s*$)/g, '');
  100 + var desc = $('#share-desc').val();
  101 + var image = $('#share-img').val();
  102 + var weixinUrl = $('#weixin-url').val();
  103 +
  104 +
  105 + if (channel === 'weibo' || channel === 'tqq') {
  106 + shareBase({
  107 + channel: channel,
  108 + title: title,
  109 + image: image
  110 + });
  111 + } else {
  112 + shareBase({
  113 + channel: channel,
  114 + title: title,
  115 + desc: desc,
  116 + image: image,
  117 + self: self,
  118 + weixinUrl: weixinUrl
  119 + });
  120 + }
  121 +}
  122 +
  123 +$('.share-wrapper').on('click', 'i', function() {
  124 + var $el = $(this),
  125 + type = $el.data('type'),
  126 + $weixinShareBox = $('.weixin-share-box');
  127 +
  128 + if (type === 'weixin') {
  129 + share(type, $el);
  130 + } else {
  131 + $weixinShareBox.hide();
  132 + share(type);
  133 + }
  134 +});
  1 +/**
  2 + * 动态获取页面数据
  3 + * @author liuchuanyang
  4 + * @date 2016/10/09
  5 + */
  6 +var $ = require('yoho-jquery');
  7 +
  8 +function getDynamicById(id) {
  9 + 'use strict';
  10 +
  11 + var param = {
  12 + id: id
  13 + };
  14 +
  15 +// //guang.yohobuy.com/guang/info/detailData
  16 + return $.getJSON('/guang/info/detailData', param);
  17 +}
  18 +
  19 +function renderData(data) {
  20 + 'use strict';
  21 +
  22 + var $favor = $('#collect-btn'),
  23 + $praise = $('#prise-btn');
  24 +
  25 + if (data && data.code === 200 && data.data) {
  26 +
  27 + if (data.data.isFavor === 'Y') {
  28 + $favor.addClass('collected');
  29 + } else {
  30 + $favor.removeClass('collected');
  31 + }
  32 +
  33 + if (data.data.isPraise === 'Y') {
  34 + $praise.addClass('liked');
  35 + } else {
  36 + $praise.removeClass('liked');
  37 + }
  38 +
  39 + $praise.find('.like-num').text(data.data.praiseNum || 0);
  40 + $('.detail-body .article-click em').text(data.data.browseNum || 0);
  41 + }
  42 +}
  43 +
  44 +function refreshData() {
  45 + 'use strict';
  46 +
  47 + var id = $('.detail-body').attr('data-id');
  48 +
  49 + getDynamicById(id).done(renderData);
  50 +}
  51 +
  52 +refreshData();
  1 +/**
  2 + * 逛详情页
  3 + * @author: liuyue<yue.liu@yoho.cn>
  4 + * @date: 2015/12/16
  5 + */
  6 +
  7 +var $ = require('yoho-jquery'),
  8 + lazyLoad = require('yoho-jquery-lazyload'),
  9 + $commentArea = $('#comment-area'),
  10 + articleId = $('.detail-body').data('id');
  11 +
  12 +var $commentList = $commentArea.find('.comments-wrap'),
  13 + $commentNum = $('#article-comment > .comment-num'),
  14 + commenting = false, // 评论请求尚未返回变量
  15 + locating = false, // 评论页面正在跳转
  16 + $commentBtn = $('#comment-btn'),
  17 + MAX_COMMENTS_WORDS = 100,
  18 + $wordCountTip = $('#word-count-tip');
  19 +
  20 +require('./right-side');
  21 +require('./img-blink');
  22 +
  23 +require('../common/share');
  24 +require('./detail-dynamic');
  25 +
  26 +// Pjax
  27 +require('yoho-jquery-pjax');
  28 +
  29 +lazyLoad({
  30 + failure_limit: 50
  31 +});
  32 +
  33 +// 点击评论滑到评论区
  34 +// $('#article-comment').click(function() {
  35 +// $('html, body').animate({
  36 +// scrollTop: $commentArea.offset().top - 20
  37 +// }, 800);
  38 +// });
  39 +
  40 +// 文章点赞与取消点赞
  41 +$('#prise-btn').click(function() {
  42 + var prising = false,
  43 + url,
  44 + $this = $(this);
  45 +
  46 + if (prising) {
  47 + return;
  48 + }
  49 + $this.toggleClass('liked');
  50 + if ($this.hasClass('liked')) {
  51 +
  52 + // 点赞
  53 + url = '/guang/info/praise';
  54 + } else {
  55 +
  56 + // 取消点赞
  57 + url = '/guang/info/cancelPraise';
  58 + }
  59 + prising = true;
  60 + $.ajax({
  61 + type: 'GET',
  62 + url: url,
  63 + data: {
  64 + id: articleId
  65 + }
  66 + }).then(function(data) {
  67 + if (data.code === 200) {
  68 + $this.find('.like-num').html(data.data);
  69 + }
  70 + prising = false;
  71 + });
  72 +}).bind('mouseenter mouseleave', function() {
  73 + $(this).toggleClass('hover');
  74 +});
  75 +
  76 +// 文章收藏与取消收藏
  77 +$('#collect-btn').click(function() {
  78 + var collecting = false,
  79 + url,
  80 + col,
  81 + $this = $(this);
  82 +
  83 + if (collecting) {
  84 + return;
  85 + }
  86 + if ($this.hasClass('collected')) {
  87 +
  88 + // 取消收藏
  89 + url = '/guang/info/cancelcollect';
  90 + col = 0;
  91 + } else {
  92 +
  93 + // 收藏
  94 + url = '/guang/info/collect';
  95 + col = 1;
  96 + }
  97 + collecting = true;
  98 + $.ajax({
  99 + type: 'GET',
  100 + url: url,
  101 + data: {
  102 + id: articleId
  103 + }
  104 + }).then(function(data) {
  105 + var hrefUrl;
  106 +
  107 + switch (data.code) {
  108 + case 401:
  109 +
  110 + // 防止从已有col的页面再次进行跳转后出错的情况
  111 + if (/\?col=(1|0)/.test(location.href)) {
  112 + hrefUrl = location.href.replace(/\?col=(1|0)/, '?col=' + col);
  113 + } else {
  114 + hrefUrl = location.href + '?col=' + col;
  115 + }
  116 + location.href = '//www.yohobuy.com/signin.html?refer=' + encodeURI(hrefUrl);
  117 + break;
  118 + case 400:
  119 +
  120 + // alert(data.message);
  121 + break;
  122 + case 200:
  123 + if (/\?col=(1|0)/.test(location.href)) {
  124 +
  125 + // 如果页面url中含有col,为了防止页面刷新时收藏或者取消收藏会根据col来的问题,进行页面跳转拿掉参数
  126 + location.href = location.href.replace(/\?col=(1|0)/, '');
  127 + } else {
  128 + $this.toggleClass('collected');
  129 + }
  130 + break;
  131 + }
  132 + collecting = false;
  133 + });
  134 +}).bind('mouseenter mouseleave', function() {
  135 + $(this).toggleClass('hover');
  136 +});
  137 +
  138 +function showComment() {
  139 + var commonlist = $('.comments-list').find('li').length;
  140 +
  141 + if (commonlist === 0) {
  142 + $('.commnets-resultwrapper').hide();
  143 + $('.comments-empty').show();
  144 + } else {
  145 + $('.commnets-resultwrapper').show();
  146 + $('.comments-empty').hide();
  147 + }
  148 +}
  149 +showComment();
  150 +
  151 +// 评论
  152 +function comment(id) {
  153 + var commentInfo = $('#comment-info').val();
  154 +
  155 + if (commentInfo === '') {
  156 + alert('评论不能为空');
  157 + return false;
  158 + }
  159 + commenting = true;
  160 + $.ajax({
  161 + url: '/guang/info/comment',
  162 + data: {
  163 + id: id,
  164 + comment: commentInfo
  165 + },
  166 + type: 'post',
  167 + success: function(data) {
  168 + switch (data.code) {
  169 + case 401:
  170 + locating = true;
  171 + location.href = '//www.yohobuy.com/signin.html?refer=' +
  172 + window.escape(location.href + '#comment-info');
  173 + break;
  174 + case 400:
  175 + alert(data.message);
  176 + break;
  177 + case 200:
  178 + if (data.data) {
  179 + $commentList.html(data.data.content);
  180 + $commentNum.html(data.data.count);
  181 + showComment();
  182 +
  183 + // clear comment-text
  184 + $('#comment-info').val('').keyup();
  185 + }
  186 + break;
  187 + }
  188 + commenting = false;
  189 + }
  190 + });
  191 +}
  192 +
  193 +$commentBtn.click(function(e) {
  194 +
  195 + // 页面正在跳转或者正在AJAX请求时评论无效
  196 + if (locating || commenting) {
  197 + return false;
  198 + }
  199 +
  200 + // 字数不符合要求
  201 + if ($('#comment-info').val().length - MAX_COMMENTS_WORDS > 0) {
  202 + return;
  203 + }
  204 + e.preventDefault();
  205 + comment(articleId);
  206 +});
  207 +
  208 +
  209 +// comment pager pjax
  210 +$(document).pjax('.comment-pager a', '#pjax-container', {
  211 + timeout: 5000
  212 +});
  213 +
  214 +// 分页后移动到评论框的位置
  215 +$(document).on('pjax:end', function() {
  216 + showComment();
  217 + $('html,body').scrollTop($('#comment-info').offset().top);
  218 +
  219 + // 设置头部评论数
  220 + $('#article-comment .comment-num').text($('#comment-area .comment-num').text());
  221 +});
  222 +
  223 +$('#comment-info').keyup(function() {
  224 + var len = $(this).val().length,
  225 + showTxt;
  226 +
  227 + if (len === 0) {
  228 + $wordCountTip.html('');
  229 + $commentBtn.addClass('disable');
  230 + } else {
  231 + if (len - MAX_COMMENTS_WORDS <= 0) {
  232 + showTxt = '还可以输入' + (MAX_COMMENTS_WORDS - len) + '字';
  233 + $commentBtn.removeClass('disable');
  234 + } else {
  235 + showTxt = '已超过<span class="exceed-count">' + (len - MAX_COMMENTS_WORDS) + '</span>字';
  236 + $commentBtn.addClass('disable');
  237 + }
  238 + }
  239 + $wordCountTip.html(showTxt);
  240 +});
  241 +
  242 +// init
  243 +$('#comment-info').trigger('keyup');
  1 +/**
  2 + * 逛首页
  3 + * @author: xuqi<qi.xu@yoho.cn>
  4 + * @date: 2015/12/15
  5 + */
  6 +
  7 +var $ = require('yoho-jquery');
  8 +
  9 +var msg = require('./msg');
  10 +
  11 +require('yoho-jquery-pjax');
  12 +require('../plugins/slider');
  13 +
  14 +require('./img-blink');
  15 +
  16 +require('./right-side');
  17 +
  18 +// page cache下更新点赞状态、点赞数、评论数、阅读数
  19 +require('./list-dynamic');
  20 +
  21 +$('#slider').slider(); // 初始化slider
  22 +
  23 +$(document).pjax('.pjax-link, .msg-pager a', '#pjax-container', {
  24 + timeout: 2000
  25 +});
  26 +
  27 +$(document).on('pjax:end', function() {
  28 + msg.dotLazy();
  29 +});
  1 +/**
  2 + * 图片移入闪动效果JS
  3 + * @auhor: xuqi<qi.xu@yoho.cn>
  4 + * @date: 2015/7/29
  5 + */
  6 +
  7 +var $ = require('yoho-jquery');
  8 +
  9 +$('.guang-page').on('mouseover', 'a img, a .bg-img', function(e) {
  10 + var $el = $(e.target);
  11 +
  12 + // slider中的图片不做此效果
  13 + if ($el.closest('.slider').length > 0) {
  14 + return;
  15 + }
  16 +
  17 + $el.addClass('blink');
  18 +
  19 + setTimeout(function() {
  20 + $el.removeClass('blink');
  21 + }, 100);
  22 +});
  1 +/**
  2 + * 动态获取页面数据
  3 + * @author liuchuanyang
  4 + * @date 2016/10/09
  5 + */
  6 +var $ = require('yoho-jquery');
  7 +
  8 +var $msgs = $('#msg-list');
  9 +
  10 +require('../common');
  11 +
  12 +function getDynamicByIds(ids) {
  13 + 'use strict';
  14 + var data = {
  15 + ids: ids
  16 + };
  17 +
  18 + var qs = window.queryString();
  19 +
  20 + if (qs.query) {
  21 +
  22 + // 标签列表
  23 + data.query = qs.query;
  24 + } else if (qs.type) {
  25 +
  26 + // 逛首页type
  27 + data.type = qs.type;
  28 + } else if (!qs.author_id) {
  29 +
  30 + // 非编辑页的情况下,为逛首页默认type=0
  31 + data.type = '0';
  32 + }
  33 +
  34 + return $.ajax({
  35 + type: 'GET',
  36 + url: '/guang/info/listData',
  37 + data: data
  38 + });
  39 +}
  40 +
  41 +function renderData(data) {
  42 + 'use strict';
  43 +
  44 + var i,
  45 + it,
  46 + $it;
  47 +
  48 + var list;
  49 +
  50 + if (data && data.code === 200 && (list = data.data.artList)) {
  51 + for (i = 0; i < list.length; i++) {
  52 + it = list[i];
  53 +
  54 + if (it && it.articleId) {
  55 + $it = $('.msg-content[data-id=' + it.articleId + ']', $msgs);
  56 +
  57 + // 浏览数目
  58 + $it.find('.page-view em').text(it.views_num);
  59 +
  60 + // 点赞状态
  61 + if (it.isPraise === 'Y') {
  62 + $it.find('.like-icon').addClass('liked');
  63 + } else {
  64 + $it.find('.like-icon').removeClass('liked');
  65 + }
  66 +
  67 + // 点赞数目
  68 + $it.find('.like .num').text(it.praise_num);
  69 +
  70 + // 评论数目
  71 + $it.find('.comment em').text(it.comment_num);
  72 + }
  73 + }
  74 + }
  75 +}
  76 +
  77 +(function() {
  78 + 'use strict';
  79 +
  80 + var idArr = [];
  81 +
  82 + $msgs.children('.msg-content').each(function() {
  83 + var id = $(this).data('id');
  84 +
  85 + if (id) {
  86 + idArr.push(id);
  87 + }
  88 + });
  89 +
  90 + getDynamicByIds(idArr.join(',')).then(renderData);
  91 +}());
  1 +/**
  2 + * 逛编辑页、列表页
  3 + * @author: xuqi<qi.xu@yoho.cn>
  4 + * @date: 2015/12/15
  5 + */
  6 +
  7 +require('./msg');
  8 +require('./img-blink');
  9 +require('./right-side');
  10 +
  11 +// page cache下更新点赞状态、点赞数、评论数、阅读数
  12 +require('./list-dynamic');
  1 +var $ = require('yoho-jquery'),
  2 + lazyLoad = require('yoho-jquery-lazyload');
  3 +
  4 +var prising;
  5 +
  6 +require('yoho-jquery-dotdotdot');
  7 +
  8 +// 资讯文字截取和lazyload
  9 +function dotLazy() {
  10 +
  11 + // 文字截取
  12 + $('.msg-title, .msg-content .content').dotdotdot({
  13 + wrap: 'letter'
  14 + });
  15 +
  16 + // Lazyload
  17 + lazyLoad($('#msg-list img.lazy'));
  18 +}
  19 +
  20 +// 资讯点赞
  21 +$('.guang-page').on('click', '.like-icon', function() {
  22 + var $this = $(this),
  23 + msgId = $this.closest('.msg-content').data('id'),
  24 + url;
  25 +
  26 + // 同一资讯多次点击归一处理
  27 + if (prising === msgId) {
  28 + return;
  29 + }
  30 +
  31 + prising = msgId;
  32 +
  33 + $this.toggleClass('liked');
  34 +
  35 + // 点赞或取消点赞
  36 + if ($this.hasClass('liked')) {
  37 + url = '/guang/info/praise';
  38 + } else {
  39 + url = '/guang/info/cancelPraise';
  40 + }
  41 + $.ajax({
  42 + type: 'GET',
  43 + url: url,
  44 + data: {
  45 + id: msgId,
  46 + time: new Date().getTime()
  47 + }
  48 + }).then(function(data) {
  49 + if (data.code === 200) {
  50 + if (data.data * 1 === 0) {
  51 + $this.next('b').addClass('num-0').children('.num').html('0'); // 隐藏数字显示
  52 + } else {
  53 + $this.next('b').removeClass('num-0').children('.num').html(data.data);
  54 + }
  55 + }
  56 + prising = false;
  57 + });
  58 +}).on('mouseenter mouseleave', '.like-icon', function() {
  59 + $(this).closest('.like').toggleClass('hover');
  60 +});
  61 +
  62 +dotLazy();
  63 +
  64 +exports.dotLazy = dotLazy;
  1 +/**
  2 + * 右侧栏文字截取js
  3 + */
  4 +var $ = require('yoho-jquery'),
  5 + lazyLoad = require('yoho-jquery-lazyload');
  6 +
  7 +require('yoho-jquery-dotdotdot');
  8 +
  9 +$('.ex-reco-context').dotdotdot({
  10 + wrap: 'letter'
  11 +});
  12 +
  13 +lazyLoad($('.ads img.lazy'));
  1 +@use postcss-crip;
  2 +@use postcss-short;
  3 +
  4 +.pager {
  5 + fz: 12px;
  6 +
  7 + a {
  8 + h: 24px;
  9 + p: 0 9px;
  10 + lh: 24px;
  11 + d: inline-block;
  12 + ta: center;
  13 + mr: 8px;
  14 + c: #222;
  15 +
  16 + &.cur {
  17 + c: #fff #222;
  18 + }
  19 +
  20 + &:first-child .iconfont {
  21 + right: auto;
  22 + left: -5px;
  23 + }
  24 + }
  25 +
  26 + .iconfont {
  27 + position: relative;
  28 + vertical-align: middle;
  29 + bottom: 1px;
  30 + right: -5px;
  31 + font-size: 14px;
  32 + }
  33 +}
  1 +.path-nav {
  2 + font-size: 12px;
  3 + padding: 15px 0;
  4 + height: 18px;
  5 + line-height: 18px;
  6 + /*border-bottom: 1px solid #eaeceb;*/
  7 + /*margin-bottom: 15px;*/
  8 + color: #666;
  9 +
  10 + a {
  11 + color: #666;
  12 + }
  13 +
  14 + .iconfont {
  15 + font-size: 12px;
  16 + }
  17 +
  18 + .last {
  19 + font-weight: bold;
  20 + }
  21 +}
  1 +.guang-detail-page {
  2 + width: 1150px;
  3 + margin: 0 auto 95px;
  4 +
  5 + b {
  6 + font-weight: bold;
  7 + }
  8 +
  9 + i {
  10 + font-style: italic;
  11 + }
  12 +
  13 + .block {
  14 + margin: 15px 0;
  15 + }
  16 +
  17 + .excellent-recommendation-title {
  18 + margin-top: 4px;
  19 + }
  20 +
  21 + .block-header {
  22 + position: relative;
  23 + border-bottom: 1px solid #c1c1c1;
  24 + font-size: 18px;
  25 + height: 38px;
  26 + line-height: 38px;
  27 + text-align: center;
  28 + margin-bottom: 24px;
  29 + color: #333;
  30 + .more-reco {
  31 + position: absolute;
  32 + right: 0;
  33 + color: #000;
  34 + font-size: 14px;
  35 + text-decoration: none;
  36 + }
  37 + }
  38 +
  39 + /*830+22:兼容IE8不认识:nth-child导致brand换行的问题*/
  40 + .related-brand .brands {
  41 + width:852px;
  42 + }
  43 +
  44 + .related-reco .recos {
  45 + width: 850px;
  46 + }
  47 +
  48 + .detail-title {
  49 + font-size: 28px;
  50 + line-height: 64px;
  51 + border-bottom: 1px dotted #c1c1c1;
  52 + word-wrap:break-word;
  53 + }
  54 +
  55 + .article-author {
  56 + float: left;
  57 + line-height: 64px;
  58 + .author-avatar {
  59 + clear: both;
  60 + width: 38px;
  61 + height: 64px;
  62 + img {
  63 + width: 38px;
  64 + height: 38px;
  65 + border-radius: 50%;
  66 + vertical-align: middle;
  67 + }
  68 + }
  69 + }
  70 + .author-info {
  71 + float: left;
  72 + margin-left: 10px;
  73 + font-size: 14px;
  74 + max-width: 447px;
  75 + .author-name {
  76 + display: block;
  77 + height: 64px;
  78 + line-height: 64px;
  79 + cursor: pointer;
  80 + color: #000;
  81 +
  82 + &:hover {
  83 + color: #cc3300;
  84 + }
  85 + }
  86 + .author-introduce {
  87 + color: #999;
  88 + }
  89 + }
  90 +
  91 + .article-status {
  92 + float: right;
  93 + height: 64px;
  94 + line-height: 64px;
  95 + color: #999;
  96 + font-size: 13px;
  97 + .article-click {
  98 + margin: 0 25px;
  99 + }
  100 + .article-comment {
  101 + color: #cc3300;
  102 + cursor: pointer;
  103 + }
  104 + }
  105 +
  106 + .article-main {
  107 + img {
  108 + display: block;
  109 + max-width: 100%;
  110 + margin:0 auto;
  111 + }
  112 + .article-text {
  113 + margin: 2px 0 20px;
  114 + line-height: 28px;
  115 + font-size: 14px;
  116 + }
  117 + .article-small-pic {
  118 + text-align: center;
  119 + font-size: 0;
  120 + img {
  121 + display: inline-block;
  122 + max-width: 412px;
  123 + &:first-child {
  124 + margin: 0 6px 0 0;
  125 + }
  126 + }
  127 + }
  128 +
  129 + .block:first-child {
  130 + margin-top: 10px;
  131 + }
  132 + }
  133 +
  134 + /*user handle*/
  135 + .user-handle {
  136 + margin: 30px 0 0 0;
  137 + text-align: center;
  138 + ul {
  139 + display: inline-block;
  140 + li {
  141 + float: left;
  142 + margin: 0 15px;
  143 + cursor: pointer;
  144 + a {
  145 + position: relative;
  146 + display: block;
  147 + padding: 0 10px;
  148 + height: 36px;
  149 + line-height: 36px;
  150 + color: #535353;
  151 + font-size: 0;
  152 + background: #efefef;
  153 + text-align: left;
  154 + i, span{
  155 + display: inline-block;
  156 + font-style: normal;
  157 + font-size: 14px;
  158 + }
  159 + i {
  160 + margin: 0 5px 0 0;
  161 + font-size: 18px;
  162 + opacity: 0.5;
  163 + }
  164 + .cancel-collect {
  165 + display: none;
  166 + }
  167 + }
  168 + }
  169 + .like-status.liked i,
  170 + .like-status.hover i{
  171 + opacity: 1;
  172 + }
  173 + .like-statis.hover .like-num {
  174 + color: #000;
  175 + }
  176 + .sort-collect a {
  177 + i {
  178 + width: 21px;
  179 + }
  180 + }
  181 + .sort-collect.collected a {
  182 + i {
  183 + opacity: 1;
  184 + }
  185 + span {
  186 + display: none;
  187 + }
  188 + .cancel-collect {
  189 + display: inline;
  190 + }
  191 + }
  192 + .sort-collect.hover i {
  193 + opacity: 1;
  194 + }
  195 + .sort-collect.hover span {
  196 + color: #000;
  197 + }
  198 + }
  199 + }
  200 +
  201 + .article-bottom-info {
  202 + margin: 44px 0 0 0;
  203 + padding: 0 0 10px;
  204 + border-bottom: 1px dotted #c1c1c1;
  205 + }
  206 +
  207 + .article-tag {
  208 + float: left;
  209 + width: 588px;
  210 + .tag-icon {
  211 + float: left;
  212 + margin: 0 12px 0 0;
  213 + font-size: 20px;
  214 + font-style: normal;
  215 + }
  216 + ul {
  217 + float: left;
  218 + max-width: 555px;
  219 + li {
  220 + float: left;
  221 + margin: 0 10px 10px 0;
  222 + a {
  223 + display: block;
  224 + padding: 0 15px;
  225 + height: 20px;
  226 + line-height: 20px;
  227 + font-size: 12px;
  228 + color: #fff;
  229 + font-weight: bold;
  230 + background: #c1c1c1;
  231 + }
  232 +
  233 + &:hover a {
  234 + background:#333;
  235 + }
  236 + }
  237 + li:first-child {
  238 + margin-left: 0;
  239 + }
  240 + }
  241 + }
  242 +
  243 +
  244 + .article-share {
  245 + float: right;
  246 +
  247 + .title {
  248 + font-size: 12px;
  249 + }
  250 + }
  251 +
  252 + .detail-related-posts {
  253 + margin: 14px 0 0 0;
  254 + li {
  255 + float: left;
  256 + width: 264px;
  257 + margin-left: 19px;
  258 + a {
  259 + display: block;
  260 + }
  261 + .bg-img {
  262 + display: block;
  263 + width: 100%;
  264 + height: 173px;
  265 + line-height: 173px;
  266 + text-align: center;
  267 + font-size: 0;
  268 +
  269 + img {
  270 + max-width: 100%;
  271 + max-height: 100%;
  272 + vertical-align: middle;
  273 + }
  274 + }
  275 + .post-title {
  276 + margin: 8px 0 0 0;
  277 + h2 {
  278 + line-height: 16px;
  279 + font-size: 14px;
  280 + color: #000;
  281 + overflow: hidden;
  282 + white-space: nowrap;
  283 + text-overflow: ellipsis;
  284 + }
  285 + }
  286 + .post-title:hover h2 {
  287 + color: #cc3300 !important;
  288 + }
  289 + }
  290 + li:first-child {
  291 + margin-left: 0;
  292 + }
  293 + }
  294 +
  295 + .comment-area {
  296 + margin: 58px 0 0 0;
  297 +
  298 + .comment-publish {
  299 + height: 48px;
  300 + }
  301 + }
  302 +
  303 + .comment-textarea {
  304 + textarea {
  305 + display: block;
  306 + width: 812px;
  307 + height: 86px;
  308 + padding: 12px 12px;
  309 + resize: none;
  310 + outline: none;
  311 + font-size: 14px;
  312 + line-height: 18px;
  313 + color: #535353;
  314 + font-family: "arial","helvetica","微软雅黑";
  315 + border: 1px solid #e7e7e7;
  316 + }
  317 + }
  318 +
  319 + .word-count-tip {
  320 + display: inline-block;
  321 + height: 48px;
  322 + line-height: 48px;
  323 +
  324 + font-size: 12px;
  325 + color: #c8c8c8;
  326 +
  327 + .exceed-count {
  328 + color: #f00;
  329 + }
  330 + }
  331 +
  332 + .publish-btn {
  333 + margin: 10px 0 0 0;
  334 + float: right;
  335 + width: 90px;
  336 + height: 33px;
  337 + line-height: 33px;
  338 + text-align: center;
  339 + color: #fff;
  340 + font-size: 14px;
  341 + background: #cb3a3e;
  342 + cursor: pointer;
  343 +
  344 + &:hover {
  345 + background: #c03234;
  346 + }
  347 +
  348 + &.disable {
  349 + background-color: #e79c9e;
  350 + }
  351 + }
  352 +
  353 + .comments-wrap {
  354 + h4 {
  355 + position: relative;
  356 + line-height: 32px;
  357 + border-bottom: 1px solid #e7e7e7;
  358 +
  359 + .comment-num {
  360 + margin-right: 5px;
  361 + color: #c11e00;
  362 + }
  363 +
  364 + i {
  365 + position: absolute;
  366 + width: 13px;
  367 + height: 7px;
  368 + left: 30px;
  369 + bottom: -7px;
  370 + background: resolve('guang/comment-icon.png') no-repeat;
  371 + }
  372 + }
  373 +
  374 + .comment-pager {
  375 + float: right;
  376 + margin: 20px 0;
  377 + }
  378 + }
  379 +
  380 + .comments-empty {
  381 + display: none;
  382 + color: #ccc;
  383 + margin: 20px 0;
  384 + font-size: 12px;
  385 + line-height: 12px;
  386 + text-align: center;
  387 + }
  388 +
  389 + .commnets-resultwrapper {
  390 + display: none;
  391 + }
  392 +
  393 + .comments-list{
  394 + li{
  395 + margin: 14px 0 0;
  396 + padding: 0 0 15px;
  397 + border-bottom: 1px dotted #e7e7e7;
  398 + .avatar{
  399 + float: left;
  400 + width: 40px;
  401 + height: 40px;
  402 + overflow: hidden;
  403 + img{
  404 + display: block;
  405 + width: 100%;
  406 + height: 100%;
  407 + border-radius: 50%;
  408 + }
  409 + }
  410 + .comment-info{
  411 + float: left;
  412 + width: 774px;
  413 + margin: 0 0 0 16px;
  414 + .comment-user-name{
  415 + color: #c11e00;
  416 + font-size: 15px;
  417 + line-height: 15px;
  418 + }
  419 + .comment-content{
  420 + margin-top: 10px;
  421 + line-height: 16px;
  422 + font-size: 12px;
  423 + word-wrap:break-word;
  424 + }
  425 + .comment-time{
  426 + margin: 10px 0 0 0;
  427 + color: #c8c8c8;
  428 + font-size: 12px;
  429 + line-height: 12px;
  430 + clear: both;
  431 + }
  432 + }
  433 +
  434 + }
  435 + }
  436 +
  437 +
  438 + .brand {
  439 + margin-right: 22px;
  440 + margin-bottom: 20px;
  441 + float: left;
  442 +
  443 + .thumb {
  444 + display: table-cell;
  445 + border: 1px solid #f5f5f5;
  446 + height: 120px;
  447 + width: 120px;
  448 + box-sizing: border-box;
  449 + text-align: center;
  450 + vertical-align: middle;
  451 +
  452 + img {
  453 + display: block;
  454 + max-width: 120px;
  455 + max-height: 120px;
  456 + margin: 0 auto;
  457 + }
  458 + }
  459 +
  460 + .brand-name {
  461 + width: 120px;
  462 + font-size: 13px;
  463 + line-height: 20px;
  464 + overflow: hidden;
  465 + white-space: nowrap;
  466 + text-overflow: ellipsis;
  467 + text-align: center;
  468 + color: #333;
  469 + }
  470 + }
  471 +
  472 + $commodityWidth: 192px;
  473 +
  474 + .tag-container,
  475 + .few-tag {
  476 + display: none;
  477 + }
  478 +
  479 + .good-info {
  480 + width: $commodityWidth;
  481 + margin-right: 20px;
  482 + margin-bottom: 12px;
  483 +
  484 + .good-detail-img {
  485 + height: auto;
  486 +
  487 + .good-thumb,
  488 + img.lazy {
  489 + height: 257px;
  490 + }
  491 + }
  492 +
  493 + .good-detail-text > a {
  494 + margin-top: 0;
  495 + line-height: 36px;
  496 + }
  497 +
  498 + .good-detail-text > .price {
  499 + margin-top: 0;
  500 + }
  501 + .good-detail-text .brand{
  502 + margin-right:0;
  503 + margin-bottom:0;
  504 + }
  505 + }
  506 +}
  507 +
  1 +.guang-index-page {
  2 + .msg-nav {
  3 + border-bottom: 1px solid #000;
  4 + margin-top: 24px;
  5 + height: 30px;
  6 + li {
  7 + float: left;
  8 + height: 30px;
  9 + line-height: 30px;
  10 + text-align: center;
  11 + font-size: 18px;
  12 + padding: 0 28px;
  13 +
  14 + a {
  15 + display: block;
  16 + height: 100%;
  17 + width: 100%;
  18 + color: #333;
  19 + }
  20 +
  21 + &.actived {
  22 + background-color: #111;
  23 +
  24 + a {
  25 + color: #fff;
  26 + }
  27 + }
  28 + }
  29 + }
  30 +
  31 + .msg-pager {
  32 + float: right;
  33 + margin: 20px 0;
  34 + }
  35 +}