Authored by htoooth

fix htaccess

@@ -149,6 +149,7 @@ const logger = global.yoho.logger; @@ -149,6 +149,7 @@ const logger = global.yoho.logger;
149 149
150 // dispatcher 150 // dispatcher
151 try { 151 try {
  152 + const htaccess = require('./doraemon/middleware/htaccess');
152 const subDomain = require('./doraemon/middleware/sub-domain'); 153 const subDomain = require('./doraemon/middleware/sub-domain');
153 const mobileRefer = require('./doraemon/middleware/mobile-refer'); 154 const mobileRefer = require('./doraemon/middleware/mobile-refer');
154 const mobileCheck = require('./doraemon/middleware/mobile-check'); 155 const mobileCheck = require('./doraemon/middleware/mobile-check');
@@ -162,6 +163,7 @@ try { @@ -162,6 +163,7 @@ try {
162 const devtool = require('./doraemon/middleware/devtools'); 163 const devtool = require('./doraemon/middleware/devtools');
163 164
164 // YOHO 前置中间件 165 // YOHO 前置中间件
  166 + app.use(htaccess());
165 app.use(subDomain()); 167 app.use(subDomain());
166 app.use(mobileRefer()); 168 app.use(mobileRefer());
167 app.use(mobileCheck()); 169 app.use(mobileCheck());
@@ -58,7 +58,7 @@ exports.index = (req, res, next) => { @@ -58,7 +58,7 @@ exports.index = (req, res, next) => {
58 pageSize: pageSize, 58 pageSize: pageSize,
59 type: type, 59 type: type,
60 pathNav: pathNav, 60 pathNav: pathNav,
61 - baseUrl: `?${querystring.stringify(req.query)}`, 61 + baseUrl: helpers.urlFormat('/' + channel + `-t${type}`, null, 'guang'),
62 page: page, 62 page: page,
63 total: (ret[2] && ret[2].total) || 0 63 total: (ret[2] && ret[2].total) || 0
64 }, 64 },
@@ -169,7 +169,7 @@ exports.editor = (req, res, next) => { @@ -169,7 +169,7 @@ exports.editor = (req, res, next) => {
169 exRecos: ret[4], 169 exRecos: ret[4],
170 170
171 gender: gender, 171 gender: gender,
172 - baseUrl: `?${querystring.stringify(req.query)}`, 172 + baseUrl: helpers.urlFormat('/' + channel + `-author-i${authorId}`, null, 'guang'),
173 pageSize: pageSize, 173 pageSize: pageSize,
174 pathNav: pathNav, 174 pathNav: pathNav,
175 page: page, 175 page: page,
  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.spager = 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 += '-' + (options.hash.pageSize ? (pageSizeVar + pageSize + '-') : '') + pageVar;
  48 +
  49 + console.log(base);
  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 +};
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 layoutsDir: doraemon, 24 layoutsDir: doraemon,
25 partialsDir: [path.join(__dirname, 'views/partial')], 25 partialsDir: [path.join(__dirname, 'views/partial')],
26 views: path.join(__dirname, 'views/action'), 26 views: path.join(__dirname, 'views/action'),
27 - helpers: Object.assign(require('./helpers/pager'), global.yoho.helpers) 27 + helpers: Object.assign(require('./helpers/pager'), require('./helpers/pager-seo'), global.yoho.helpers)
28 })); 28 }));
29 29
30 // require('./helpers/json'); 30 // require('./helpers/json');
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 const _ = require('lodash'); 8 const _ = require('lodash');
9 const moment = require('moment'); 9 const moment = require('moment');
10 const ghelper = require('./guang-helper'); 10 const ghelper = require('./guang-helper');
  11 +const urlHelper = require('./urlHelper');
11 12
12 const helpers = global.yoho.helpers; 13 const helpers = global.yoho.helpers;
13 const serviceApi = global.yoho.ServiceAPI; 14 const serviceApi = global.yoho.ServiceAPI;
@@ -166,15 +167,7 @@ const _formatArticle = (articleData, showTag, showAuthor, channel) => { @@ -166,15 +167,7 @@ const _formatArticle = (articleData, showTag, showAuthor, channel) => {
166 let authorId = articleData.author.author_id; 167 let authorId = articleData.author.author_id;
167 168
168 if (authorId) { 169 if (authorId) {
169 -  
170 - let aparam = {  
171 - author_id: authorId  
172 - };  
173 -  
174 - if (channel) {  
175 - aparam.channel = channel;  
176 - }  
177 - result.editorUrl = helpers.urlFormat('/Index/editor', aparam, 'guang'); 170 + result.editorUrl = urlHelper.editorUrl(channel, authorId);
178 } 171 }
179 172
180 let tags = []; 173 let tags = [];
@@ -439,7 +432,7 @@ const getCategory = (currentSortId, channel) => { @@ -439,7 +432,7 @@ const getCategory = (currentSortId, channel) => {
439 typeId: cat.id, 432 typeId: cat.id,
440 type: cat.name, 433 type: cat.name,
441 isActive: String(cat.id) === String(currentSortId), 434 isActive: String(cat.id) === String(currentSortId),
442 - navUrl: helpers.urlFormat('/index/index', param, 'guang') 435 + navUrl: urlHelper.listUrl(channel, cat.id)
443 }); 436 });
444 } 437 }
445 } 438 }
  1 +/**
  2 + * Created by TaoHuang on 2017/2/21.
  3 + */
  4 +
  5 +'use strict';
  6 +
  7 +const helpers = global.yoho.helpers;
  8 +
  9 +module.exports.editorUrl = function(channel, authorId) {
  10 + return helpers.urlFormat(`/${channel}-author-i${authorId}/`, null, 'guang');
  11 +};
  12 +
  13 +module.exports.listUrl = function(channel, type) {
  14 + return helpers.urlFormat(`/${channel}-t${type}/`, null, 'guang');
  15 +};
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 {{/ msgs}} 20 {{/ msgs}}
21 </div> 21 </div>
22 <div class="msg-pager pager"> 22 <div class="msg-pager pager">
23 - {{gpager baseUrl totalRecords=total page=page type="ellipsis" theme="msg-pager"}} 23 + {{spager baseUrl totalRecords=total page=page pageVar="p" type="ellipsis" theme="msg-pager"}}
24 </div> 24 </div>
25 </div> 25 </div>
26 <div class="right-side"> 26 <div class="right-side">
@@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
30 {{> msg}} 30 {{> msg}}
31 {{/ msgs}} 31 {{/ msgs}}
32 </div> 32 </div>
33 - {{gpager baseUrl totalRecords=total page=page type="ellipsis" theme="msg-pager"}} 33 + {{spager baseUrl totalRecords=total page=page pageVar="p" type="ellipsis" theme="msg-pager"}}
34 </div> 34 </div>
35 </div> 35 </div>
36 <div class="right-side"> 36 <div class="right-side">
  1 +/**
  2 + * Created by TaoHuang on 2017/2/21.
  3 + */
  4 +
  5 +'use strict';
  6 +
  7 +/**
  8 + * url
  9 + * @type {*[]}
  10 + */
  11 +
  12 +module.exports = [
  13 + // 首页
  14 + {
  15 + type: 'rewrite',
  16 + origin: /^\/(boys|girls|kids|lifestyle)$/,
  17 + target: (req, match, p1) => {
  18 + req.query.channel = p1;
  19 + return `/?chanel=${p1}`;
  20 + }
  21 + },
  22 +
  23 + // 首页 + 类型
  24 + {
  25 + type: 'rewrite',
  26 + origin: /^\/(boys|girls|kids|lifestyle)-t([\d]+)\/$/,
  27 + target: (req, match, p1, p2) => {
  28 + req.query.channel = p1;
  29 + req.query.type = p2;
  30 + return `/?chanel=${p1}&type=${p2}`;
  31 + }
  32 + },
  33 +
  34 + // 列表页 + 类型 + 翻页
  35 + {
  36 + type: 'rewrite',
  37 + origin: /^\/(boys|girls|kids|lifestyle)-t([\d]+)-p([\d]+)\/$/,
  38 + target: (req, match, p1, p2, p3) => {
  39 + req.query.channel = p1;
  40 + req.query.type = p2;
  41 + req.query.page = p3;
  42 + return `/index/index/?type=${p2}&channel=${p3}`;
  43 + }
  44 + },
  45 +
  46 + // 编缉首页
  47 + {
  48 + type: 'rewrite',
  49 + origin: /^\/(boys|girls|kids|lifestyle)-author-i([\d]+)\/$/,
  50 + target: (req, match, p1, p2) => {
  51 + req.query.channel = p1;
  52 + req.query.author_id = p2;
  53 + return `/index/editor?channel=${p1}&author_id=${p2}`;
  54 + }
  55 + },
  56 +
  57 + // 编缉首页 + 翻页
  58 + {
  59 + type: 'rewrite',
  60 + origin: /^\/(boys|girls|kids|lifestyle)-author-i([\d]+)-p([\d]+)\/$/,
  61 + target: (req, match, p1, p2, p3) => {
  62 + req.query.channel = p1;
  63 + req.query.author_id = p2;
  64 + req.query.page = p3;
  65 + return `/index/editor?channel=${p1}&author_id=${p2}&page=${p3}`;
  66 + }
  67 + }
  68 +
  69 +];
  1 +/**
  2 + * Created by TaoHuang on 2017/2/21.
  3 + */
  4 +
  5 +'use strict';
  6 +
  7 +const fs = require('fs');
  8 +const _ = require('lodash');
  9 +const path = require('path');
  10 +
  11 +const curDir = __dirname;
  12 +const files = fs.readdirSync(curDir);
  13 +
  14 +let domainRules = {};
  15 +
  16 +files.forEach((file) => {
  17 + let info = fs.statSync(path.resolve(curDir, file));
  18 +
  19 + if (info.isDirectory() && file !== '.git') {
  20 + domainRules[file] = require(path.resolve(curDir, file));
  21 + }
  22 +});
  23 +
  24 +module.exports = () => {
  25 + return (req, res, next) => {
  26 + let curDomainRules = domainRules[req.subdomains[0]];
  27 +
  28 + if (!curDomainRules) {
  29 + return next();
  30 + }
  31 +
  32 + for (let i = 0; i < curDomainRules.length; i++) {
  33 + let rule = curDomainRules[i];
  34 +
  35 + if (
  36 + (_.isRegExp(rule.origin) && !_.isEmpty(rule.origin.exec(req.url))) ||
  37 + (_.isFunction(rule.origin) && rule.origin(req))
  38 + ) {
  39 + let newUrl = req.url;
  40 +
  41 + if (_.isRegExp(rule.origin)) {
  42 + if (_.isFunction(rule.target)) {
  43 + newUrl = req.url.replace(rule.origin, _.partial(rule.target, req));
  44 + } else if (_.isString(rule.target)) {
  45 + newUrl = req.url.replace(rule.origin, req.target);
  46 + }
  47 + } else if (_.isFunction(rule.origin)) {
  48 + if (_.isFunction(rule.target)) {
  49 + newUrl = rule.target(req);
  50 + } else if (_.isString(rule.target)) {
  51 + newUrl = rule.target;
  52 + }
  53 + }
  54 +
  55 + if (rule.type === '301') {
  56 + return res.redirect(301, newUrl);
  57 + } else if (rule.type === 'rewrite') {
  58 + req.url = newUrl;
  59 + return next();
  60 + }
  61 +
  62 + break;
  63 + }
  64 + }
  65 +
  66 + return next();
  67 + };
  68 +};
  1 +/**
  2 + * Created by TaoHuang on 2017/2/21.
  3 + */
  4 +'use strict;'
  5 +
  6 +module.exports = [
  7 + { // 商品详情页老链接
  8 + type: '301',
  9 + origin: /^\/product\/pro_([\d]+)_([\d]+)\/(.*).html(.*)/,
  10 + target: (req, match, p1, p2, p3, p4) => `/p${p1}.html${p4}`
  11 + },
  12 + { // 商品详情页新链接
  13 + type: 'rewrite',
  14 + origin: /^\/p([\d]+)/,
  15 + target: req => `/product${req.url}`
  16 + }
  17 +];
  1 +/**
  2 + * Created by TaoHuang on 2017/2/21.
  3 + */
  4 +
  5 +'use strict';
  6 +const helpers = global.yoho.helpers;
  7 +
  8 +module.exports = [
  9 + {
  10 + type: '301',
  11 + origin: /.*/,
  12 + target: req => helpers.urlFormat(req.url, null, 'www')
  13 + }
  14 +];
  1 +/**
  2 + * Created by TaoHuang on 2017/2/22.
  3 + */
  4 +
  5 +'use strict';
  6 +
  7 +const helpers = global.yoho.helpers;
  8 +
  9 +module.exports = [
  10 + { // 商品详情页老链接
  11 + type: '301',
  12 + origin: /^\/product\/pro_([\d]+)_([\d]+)\/(.*).html(.*)/,
  13 + target: (req, match, p1, p2, p3, p4) => helpers.urlFormat(`/p${p1}.html${p4}`, null, 'item')
  14 + },
  15 + { // 商品详情页新链接
  16 + type: '301',
  17 + origin: /\/p([\d]+)(.*)/,
  18 + target: req => helpers.urlFormat(req.url, null, 'item')
  19 + }
  20 +];
@@ -20,20 +20,8 @@ module.exports = () => { @@ -20,20 +20,8 @@ module.exports = () => {
20 case 'www': // 主站 20 case 'www': // 主站
21 case 'cdnsrcwww': // 主站的回源地址 21 case 'cdnsrcwww': // 主站的回源地址
22 case 'shop': // 商家入驻 22 case 'shop': // 商家入驻
23 - break;  
24 case 'new': // 原新版 重定向到301 23 case 'new': // 原新版 重定向到301
25 - return res.redirect(301, helpers.urlFormat(req.url, null, 'www'));  
26 case 'item':// 商品详情页 24 case 'item':// 商品详情页
27 - if (/^\/p([\d]+)/.test(req.url)) { // new  
28 - req.url = `/product${req.url}`;  
29 - }  
30 -  
31 - if (/^\/product\/pro_/.test(req.url)) { // old  
32 - return res.redirect(301,  
33 - req.url.replace(/^\/product\/pro_([\d]+)_([\d]+)\/(.*).html(.*)/, '/p$1.html$4')  
34 - );  
35 - }  
36 -  
37 break; 25 break;
38 case 'guang': // 逛 26 case 'guang': // 逛
39 case 'cdnsrcguang': // 逛CDN回源解析 27 case 'cdnsrcguang': // 逛CDN回源解析