Authored by 刘传洋

guang begin

  1 +let _ = require('lodash');
  2 +
  3 +class Pagination {
  4 +
  5 + constructor(url, page, totalRecords, pageSize){
  6 +
  7 + let options = {};
  8 + let len = arguments.length;
  9 + let args = [].slice.call(arguments);
  10 + let _pageSize = 0;
  11 +
  12 + if(args.length && _.isPlainObject(args[len - 1])) {
  13 + options = args.pop();
  14 + }
  15 +
  16 + this.baseUrl = args.shift() || options.baseUrl;
  17 + this.page = args.shift() || 1;
  18 + this.totalRecords = args.shift() || 0;
  19 +
  20 + _pageSize = args.shift() || options.pageSize;
  21 +
  22 + this.pageSize = _pageSize || 10;
  23 + this.totalPages = options.totalPages || 0;
  24 + this.theme = options.theme || 'full';
  25 + this.pageVar = options.pageVar || 'page';
  26 + this.pageSizeVar = options.pageSizeVar || 'pageSize';
  27 +
  28 + if(!this.totalPages && this.totalRecords) {
  29 + this.totalPages = Math.ceil(this.totalRecords / this.pageSize);
  30 + }
  31 +
  32 + this.base = this.baseUrl + (this.baseUrl.indexOf('?') < 0 ? '?' : '&') +
  33 + (_pageSize ? (this.pageSizeVar + '=' + this.pageSize + '&') : '') +
  34 + this.pageVar + '=';
  35 + }
  36 +
  37 + hasNextPage() {
  38 + return this.page < this.totalPages;
  39 + }
  40 +
  41 + hasPrevPage() {
  42 + return this.page > 1;
  43 + }
  44 +
  45 + getUrl(page) {
  46 + return this.base + page || 1;
  47 + }
  48 +}
  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 channelModel = require('../models/index');
  12 +const HeaderModel = require('../../../doraemon/models/header');
  13 +
  14 +exports.index = (req, res, next) => {
  15 +
  16 + let channel = req.yoho.channel;
  17 + let page = req.query.page || 1;
  18 + let limit = req.query.limit || 20;
  19 + let type = req.query.type || 0;
  20 +
  21 + let pathNav = channelModel.getIndexNav(channel);
  22 +
  23 + /*Promise.all([
  24 + channelModel.getBanner(),
  25 + channelModel.getCategory(),
  26 + channelModel.getList(),
  27 + //page
  28 + channelModel.getHotTags(),
  29 + channelModel.getAds(),
  30 + channelModel.getExcellectRecos()
  31 + ]).then(ret => {
  32 + res.render('index', {
  33 + 'guang' : {
  34 + 'slider' : ret[0],
  35 + 'msgTypes' : ret[1],
  36 + 'msgs' : ret[2],
  37 + 'hotTags' : ret[6],
  38 + 'ads' : ret[3],
  39 + 'exRecos' : ret[5],
  40 + 'msgPager' : null,
  41 +
  42 + 'guangIndexPage' : true
  43 + }
  44 + });
  45 + }).catch(next);*/
  46 +
  47 + return res.render('index', {
  48 + pageName : 'guang-index',
  49 + world : {
  50 + aaa : 'AAA'
  51 + }
  52 + });
  53 +
  54 +}
  55 +
  56 +exports.detail = (req, res, next) => {
  57 + return res.render('detail', {
  58 + detailId : req.params.id
  59 + });
  60 +}
  61 +
  62 +exports.tags = (req, res, next) => {
  63 + return res.render('index', {
  64 +
  65 + });
  66 +}
  67 +
  68 +exports.editor = (req, res, next) => {
  69 + return res.render('index', {
  70 +
  71 + });
  72 +}
  1 +/**
  2 + * guang
  3 + * @author: lcy<chuanyang.liu@yoho.cn>
  4 + * @date: 2016/09/01
  5 + */
  6 +
  7 +'use strict';
  8 +
  9 +let fs = require('fs');
  10 + //exphbs = require('express-handlebars').create(),
  11 +
  12 + //app = express(),
  13 +function wrap(app, exphbs) {
  14 +
  15 + let vPath = app.get('views') || 'views/',
  16 + extName = app.get('view engine') || '.hbs',
  17 + Handlebars = exphbs.handlebars;
  18 +
  19 + Handlebars.registerHelper("include", function(partial, options){
  20 +
  21 + console.log('-------');
  22 + //console.log(exphbs);
  23 + console.log(exphbs);
  24 + console.log('==================');
  25 + console.log(Handlebars.partials);
  26 + let tmpl = Handlebars.partials[partial] || exphbs.partials[partial];
  27 + let encoding = options.hash['encoding'] || 'utf8';
  28 +
  29 + exphbs.getPartials().then(function(partials){
  30 + console.log(partials.length);
  31 + }).catch(function(){
  32 +
  33 + });
  34 + if(tmpl == null) {
  35 + var source = fs.readFileSync(`${vPath}/${partial}${extName}`, 'utf8');
  36 + if(source != null) {
  37 + Handlebars.registerPartial(partial, source);
  38 + tmpl = Handlebars.partials[partial];
  39 + } else {
  40 + new Error('partial is not found : ' + partial);
  41 + }
  42 + }
  43 + //options.fn(this);
  44 + var ctx = Object.create(this);
  45 + for(var i in options.hash) {
  46 + ctx[i] = options.hash[i];
  47 + }
  48 + if (typeof tmpl !== 'function') {
  49 + tmpl = Handlebars.compile(tmpl);
  50 + }
  51 + return new Handlebars.SafeString(tmpl(ctx, options));
  52 + });
  53 +}
  54 +
  55 +
  56 +module.exports = wrap;
  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 fs = require('fs'),
  10 + _ = require('lodash'),
  11 + exphbs = require('express-handlebars').create(),
  12 + Handlebars = exphbs.handlebars;/*,
  13 + Pagination = require('../common/pagination');
  14 +*/
  15 +
  16 +let ALL_TYPES= {
  17 + 'stand' : 'p-page-n',
  18 + 'mini' : 'p-n',
  19 + 'full' : 'f-p-page-n-l-info-input-gobtn',
  20 + 'fullellipsis' : 'f-p-pe-n-l-info-input-gobtn',
  21 + 'ellipsis' : 'p-pe-n'
  22 +};
  23 +
  24 +Handlebars.registerHelper("page", function(){
  25 + var options = arguments[arguments.length - 1];
  26 + var baseUrl = (arguments.length > 1 ? arguments[0] : null) || options.hash.baseUrl || '',
  27 + page = (options.hash.page || 1)*1,
  28 + showNum = (options.hash.showNum || 7)*1,
  29 + pageSize= options.hash.pageSize || 20,
  30 + totalPages = options.hash.totalPages,
  31 + totalRecords = options.hash.totalRecords,
  32 + theme = options.hash.theme || 'pager',
  33 + currentClass = options.hash.currentClass || 'cur',
  34 + type = options.hash.type || 'stand', //min full stand ellipsis or: f-首页, p-上一页, page-页码,n-下一页,l-最后一页,info-displayMsg,inout输入框,gobtn-goto Btn
  35 + pageVar = options.pageVar || 'page',
  36 + pageSizeVar = options.pageSizeVar || "pageSize",
  37 + base = baseUrl + (baseUrl.indexOf('?') < 0 ? '?' : '&')
  38 + + (options.hash.pageSize ? (pageSizeVar + '=' + pageSize + '&') : '')
  39 + + pageVar + '=';
  40 +
  41 + if(!totalPages) {
  42 + if(!totalRecords || !pageSize) {
  43 + return new Handlebars.SafeString("");
  44 + } else {
  45 + totalPages = Math.ceil(totalRecords / pageSize);
  46 + }
  47 + }
  48 +
  49 + var items = ALL_TYPES[type] ? ALL_TYPES[type] : type;
  50 + items = _.isArray(items) ? items : (items || ALL_TYPES.stand).split('-');
  51 +
  52 + var hasPage = false; //配置中如果配置了多次 page/pe 则将忽略,只第一次有效
  53 + var ret = `<div class="pager ${theme}">`;
  54 + items.forEach(function(val, index, arr){
  55 +
  56 + switch(val) {
  57 + case 'f' :
  58 + if(page > 1) {
  59 + ret += `<a href="${base}1" title="首页">首页</a>`;
  60 + }
  61 + break;
  62 + case 'p' :
  63 + if(page > 1) {
  64 + ret += `<a href="${base}` + (page - 1) + `" title="上一页">上一页</a>`;
  65 + }
  66 + break;
  67 + case 'n' :
  68 + if(page < totalPages) {
  69 + ret += `<a href="${base}` + (page + 1) + `" title="下一页">下一页</a>`;
  70 + }
  71 + break;
  72 + case 'l' :
  73 + if(page < totalPages) {
  74 + ret += `<a href="${base}${totalPages}" title="尾页">尾页</a>`;
  75 + }
  76 + break;
  77 + case 'info' :
  78 + ret += `共{totalRecords}/{totalPages}页`;
  79 + break;
  80 + case 'input' :
  81 + //input
  82 + //ret += '<span class="{cls}"><input value="{value}" type="text"></span>';
  83 + break;
  84 + case 'gobtn' :
  85 + //goto btn
  86 + break;
  87 + case 'page' :
  88 + if(!hasPage) ret += createStandItems();
  89 + hasPage = true;
  90 + break;
  91 + case 'pe' :
  92 + if(!hasPage) ret += createEllipsisItems();
  93 + hasPage = true;
  94 + break;
  95 + }
  96 + });
  97 +
  98 + function createStandItems(){
  99 + return renderItem(getPageNums());
  100 + }
  101 +
  102 + function createEllipsisItems(){
  103 + return renderItem(getPageNums('e'));
  104 + }
  105 +
  106 + function getPageNums(type){
  107 + var pageNums = [];
  108 + var num = showNum;
  109 + if(type == 'e') {
  110 + num = num - 2;
  111 + num = num > 2 ? num : 2;
  112 + }
  113 +
  114 + /** 分页展示页码个数begin 规则:展示最靠近当前页的指定个数 **/
  115 + var pageShowMax = num % 2 == 0 ? page - 1 : page;
  116 + var pageShowMin = page;
  117 +
  118 + for(var i = 0; i < Math.floor(num/2); i++) {
  119 + pageShowMax++;
  120 + pageShowMin--;
  121 + if(pageShowMax > totalPages) {
  122 + pageShowMax = totalPages;
  123 + if(pageShowMin > 1) {
  124 + pageShowMin--;
  125 + }
  126 + }
  127 + if(pageShowMin < 1) {
  128 + pageShowMin = 1;
  129 + if(pageShowMax < totalPages) {
  130 + pageShowMax++;
  131 + }
  132 + }
  133 + }
  134 +
  135 + for(var n = pageShowMin; n <= pageShowMax; n++) {
  136 + pageNums.push(n);
  137 + }
  138 +
  139 + if(type == 'e') {
  140 + if(pageShowMin > 3) {
  141 + pageNums.unshift(1, '.');
  142 + } else if(pageShowMin == 2){
  143 + pageNums.unshift(1);
  144 + } else if(pageShowMin == 3) {
  145 + pageNums.unshift(1, 2);
  146 + }
  147 +
  148 + if(pageShowMax < totalPages - 2) {
  149 + pageNums.push('.', totalPages);
  150 + } else {
  151 + for(var x = pageShowMax + 1; x <= totalPages; x++) {
  152 + pageNums.push(x);
  153 + }
  154 + }
  155 + }
  156 +
  157 + return pageNums;
  158 + }
  159 +
  160 + function renderItem(arr) {
  161 + /** 分页展示页码个数end **/
  162 + var ret = '';
  163 + if(_.isArray(arr) && arr.length) {
  164 +
  165 + arr.forEach((val, index, arrs) => {
  166 + if('.' == val) {
  167 + ret += '<a>...</a>';
  168 + } else {
  169 + ret += `<a href="${base}${val}" ` + (page === val ? `class="${currentClass}"` : '') + ` title="第${val}页">${val}</a>`;
  170 + }
  171 + });
  172 + }
  173 +
  174 + return ret;
  175 + }
  176 +
  177 + if(options.fn) {
  178 + ret += options.fn(options.context);
  179 + }
  180 + ret += '</div>';
  181 + return new Handlebars.SafeString(ret);
  182 +});
  183 +
  184 +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 exphbs = require('express-handlebars').create();
  10 +let Handlebars = exphbs.handlebars;
  11 +let fs = require('fs');
  12 +
  13 +Handlebars.registerHelper('tpl', function(id, file, options){
  14 +
  15 + if(options.fn) {
  16 +
  17 + }
  18 + var source = Handlebars.partials[file];
  19 + var tpl = '';
  20 + if(source == null) {
  21 + var source = fs.readFileSync('views/' + file + '.html', 'utf8');
  22 + if(!source) {
  23 + new Error('file is not found : ' + file);
  24 + }
  25 + }
  26 +
  27 + tpl += '<script id="' + id + '" type="text/x-handlebars" data-file="'+file+'">';
  28 + tpl += source;
  29 + tpl += '</script>';
  30 + return new Handlebars.SafeString(tpl);
  31 +});
  32 +
  33 +module.exports = Handlebars;
  1 +/**
  2 + * guang
  3 + * @author: lcy<chuanyang.liu@yoho.cn>
  4 + * @date: 2016/08/31
  5 + */
  6 +
  7 +var express = require('express'),
  8 + path = require('path'),
  9 + hbs = require('express-handlebars'),
  10 + glob = require("glob");
  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 +var mhbs = hbs.create({
  25 + extname: '.hbs',
  26 + defaultLayout: 'layout',
  27 + layoutsDir: doraemon,
  28 + partialsDir: [`${partials}/partial`, `${doraemon}/partial`],
  29 + helpers: global.yoho.helpers
  30 +});
  31 +
  32 +app.set('views', path.join(__dirname, 'views/action'));
  33 +app.engine('.hbs', mhbs.engine);
  34 +
  35 +//register helper
  36 +//var helpersDir = path.join(__dirname, 'helpers');
  37 +// glob.sync(helpersDir + '/**/*.+(js|coffee)').forEach(function(file) {
  38 +// console.log(file);
  39 +// require(file);
  40 +// })
  41 +//require('./helpers/include')(app, mhbs);
  42 +require('./helpers/json');
  43 +require('./helpers/page');
  44 +require('./helpers/tpl');
  45 +
  46 +// router
  47 +app.use(require('./router'));
  48 +
  49 +module.exports = app;
  50 +
  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 +
  10 +const dataMap = require('../../../config/data-map');
  11 +
  12 +const helpers = global.yoho.helpers;
  13 +
  14 +const processProduct = require(`${global.utils}/product-process`).processProduct;
  15 +
  16 +
  17 +const serviceApi = global.yoho.ServiceAPI;
  18 +const searchApi = global.yoho.SearchAPI;
  19 +
  20 +const headerModel = require('../../../doraemon/models/header');
  21 +
  22 +
  23 +
  24 +/**
  25 + * 获取首页频道nav
  26 + */
  27 +const getHomeChannelNav = (channel) => {
  28 + let home = null;
  29 +
  30 + switch (channel) {
  31 + case 'boys':
  32 + {
  33 + home = helpers.urlFormat('', '', 'default');
  34 + break;
  35 + }
  36 + case 'girls':
  37 + {
  38 + home = helpers.urlFormat('/woman', '', 'new');
  39 + break;
  40 + }
  41 + case 'lifestyle':
  42 + {
  43 + home = helpers.urlFormat('/lifestyle', '', 'new');
  44 + break;
  45 + }
  46 + case 'kids':
  47 + {
  48 + home = helpers.urlFormat('/kids', '', 'new');
  49 + break;
  50 + }
  51 + default:
  52 + {
  53 + home = helpers.urlFormat('', '', 'default');
  54 + }
  55 +
  56 + }
  57 +
  58 + return {
  59 + href: home,
  60 + name: `${channel.toUpperCase()}首页`,
  61 + pathTitle: 'YOHO!有货'
  62 + };
  63 +}
  64 +
  65 +const getIndexNav = (channelType) => {
  66 +
  67 + _.concat(
  68 + getHomeChannelNav(channelType),
  69 + [{
  70 + name: '逛',
  71 + pathTitle : '逛',
  72 + href : helpers.urlFormat('guang', '', 'guang')
  73 + }]
  74 + )
  75 +}
  76 +
  77 +/**
  78 + * 获取页文章数据
  79 + * @param {String} channelType 传入频道页类型,值可以是: boys, girls, kids, lifestyle
  80 + * @return {Object}
  81 + */
  82 +const getList = channelType => {
  83 +
  84 +}
  85 +
  86 +/**
  87 + * 获取热门标签数据
  88 + * @param {String} type 传入频道页类型,值可以是: boys, girls, kids, lifestyle
  89 + * @return {Object}
  90 + */
  91 +const getHotTags = (page, limit) => {
  92 +
  93 + let data = {
  94 + client_type: 'web',
  95 + page : page || 1,
  96 + limit : limit || 10
  97 + };
  98 +
  99 + return serviceApi.get('guang/api/v2/article/getTagTop', data, {
  100 + cache: true,
  101 + code: 200
  102 + }).then(res => {
  103 + let tags = (res && res.data) || [];
  104 + return _.map(tags, it => {
  105 + return {
  106 + tagName : it.tag_name,
  107 + url : helpers.urlFormat('/tags/', it.tag_name, 'guang')
  108 + }
  109 + });
  110 + });
  111 +}
  112 +
  113 +/**
  114 + * 获取广告数据
  115 + * @param {String} channelType 传入频道页类型,值可以是: boys, girls, kids, lifestyle
  116 + * @return {Object}
  117 + */
  118 +const getAds = channelType => {
  119 +
  120 +}
  121 +
  122 +/**
  123 + * 获取热门标签数据
  124 + * @param {String} type 传入频道页类型,值可以是: boys, girls, kids, lifestyle
  125 + * @return {Object}
  126 + */
  127 +const getBanner = channelType => {
  128 +
  129 +}
  130 +
  131 +const getCategory = channelType => {
  132 +
  133 +}
  134 +
  135 +const getExcellectRecos = (channelType, start, limit) => {
  136 +
  137 +}
  138 +
  139 +
  140 +module.exports = {
  141 + getList: getList,
  142 + getHotTags: getHotTags,
  143 + getAds: getAds,
  144 + getBanner: getBanner,
  145 + getCategory: getCategory,
  146 + getExcellectRecos: getExcellectRecos,
  147 + getIndexNav : getIndexNav
  148 +}
  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('/', guangController.index);
  15 +router.get('/detail/:id', guangController.detail);
  16 +router.get('/tags/index', guangController.tags);
  17 +router.get('/Index/editor', guangController.editor);
  18 +
  19 +// ajax
  20 +// router.get('/getbrandFloorDataAjax', guangController.getbrandFloorDataAjax);
  21 +// router.post('/common/getNewArrival', guangController.getNewArrival);
  22 +// router.get('/guide', guangController.getIndexGuide);
  23 +
  24 +module.exports = router;
  1 +<div class="home-page yoho-page {{pageType}}" data-page="{{pageType}}">
  2 + {{detailId}}<br/>
  3 + {{include "sub-tpl" name="LCY"}}
  4 +</div>
  1 +<div class="con"></div>
  2 +<div class="guide-box" spm-name="homepage_guide" style="top: 255.5px;">
  3 + <a class="close" href="javascript:void(0)">x</a>
  4 + <ul class="clear">
  5 + {{#list}}
  6 + <li class="{{channel}}" >
  7 + <dl>
  8 + <dt class="tag-img-warpper">
  9 + <a href="{{url}}" target="_self">
  10 + <img spm-name="homepage_guide_manimg" alt="YOHO!BOYS" src="{{image src 180 168}}"></a>
  11 + </dt>
  12 + <dd class="block-cn">{{sort_name}}</dd>
  13 + <dd class="block-en"> <b>{{sort_name_en}}</b>
  14 + </dd>
  15 + <dd class="block-line">
  16 + </dd>
  17 + <dd class="goods-num"> <b>{{num}}+ Items.</b>
  18 + </dd>
  19 + <dd>
  20 + <a class="go" href="{{url}}">
  21 + Enter
  22 + <span class="ifont">&gt;</span>
  23 + </a>
  24 + </dd>
  25 + </dl>
  26 + </li>
  27 + {{/list}}
  28 + </ul>
  29 +</div>
  1 +<div class="home-page yoho-page {{pageType}}" data-page="{{pageType}}">
  2 + hello, <br/>
  3 + {{world.aaa}}
  4 + {{json world}}
  5 +
  6 + {{page '/good' totalRecords=1000 page=6 type="ellipsis" }}
  7 +
  8 + {{lowerCase 'GGGGG'}}
  9 +</div>
  1 +<div class="floor-ad">
  2 + sub tpl my name is {{name}}
  3 +</div>
@@ -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 };