Authored by 王水玲

帮助中心搜索

... ... @@ -6,54 +6,8 @@
'use strict';
const helpModel = require('../models/help');
const contentData = require('../models/content-data');
/**
* 根据id获取文章数据
* @param id
* @returns {*}
*/
const getData = (id)=> {
for (let i = 0; i < contentData.length; i++) {
if (contentData[i].id === id) {
return contentData[i];
}
}
};
/**
* 根据id获取当前所在位置,拼接面包屑
* @param id
*/
const getNav = (id)=> {
let menuData = helpModel.menuData().menuData;
for (let i = 0; i < menuData.length; i++) {
if (menuData[i].subsets) {
for (let j = 0; j < menuData[i].subsets.length; j++) {
if (menuData[i].subsets[j].id === id) {
return [
{
name: menuData[i].text
}, {
name: menuData[i].subsets[j].text
}
];
}
}
} else {
if (menuData[i].id === id) {
return [
{
name: menuData[i].text
}
];
}
}
}
};
const index = (req, res) => {
const index = (req, res, next) => {
let siteUrl = global.yoho.config.siteUrl;
helpModel.helpData().then(result => {
... ... @@ -73,17 +27,19 @@ const index = (req, res) => {
]
}, result)
});
});
}).catch(next);
};
/**
* 详情
*/
const detail = (req, res) => {
let id = +req.query.id || '1';
let contKey = +req.query.key || '';
let keyword = req.query.helpQuery || '';
//let data = Object.assign(getData(id), helpModel.menuData());
const detail = (req, res, next) => {
let q = req.query;
let params = {
id: parseInt(q.id || 1, 10),
contId: +req.query.contId || 0,
keywords: req.query.helpQuery
};
let nav = [
{
link: global.yoho.config.siteUrl,
... ... @@ -95,27 +51,37 @@ const detail = (req, res) => {
}
];
//data.qid = id;
//if (!(typeof (getNav(id)) === 'undefined')) {
// nav = nav.concat(getNav(id));
//}
helpModel.detailData(params).then(result => {
if (!(typeof (result.nav) === 'undefined')) {
nav = nav.concat(result.nav);
}
helpModel.detailData(keyword, {
id: id,
contKey: contKey
}).then(result => {
res.display('detail', {
module: 'help',
page: 'help',
content: Object.assign({nav}, result),
qid: id
content: Object.assign({nav}, result.data),
qid: params.id
});
});
}).catch(next);
};
// 帮助搜索功能
const search = (req, res, next) => {
helpModel.searchData(req.query).then(result => {
res.json(result);
}).catch(next);
};
// 获取在线客服的链接
const onlineService = (req, res, next) => {
helpModel.onlineService().then(url => {
res.json(url);
}).catch(next);
};
module.exports = {
index,
detail
detail,
search,
onlineService
};
... ...
... ... @@ -11,7 +11,7 @@ const api = global.yoho.API;
// 获取热词搜索
const getHotSearch = () => {
return api.get('', {
method: 'app.help.hotSearch',
method: 'app.helper.hotSearch',
showPlatform: 'yohobuy_pc'
}, {
code: 200
... ... @@ -21,7 +21,7 @@ const getHotSearch = () => {
// 获取首页帮助分类以及常见问题
const gethomeCategoryFaq = () => {
return api.get('', {
method: 'app.help.homeCategoryFaq',
method: 'app.helper.homeCategoryFaq',
showPlatform: 'yohobuy_pc'
}, {
code: 200,
... ... @@ -32,27 +32,48 @@ const gethomeCategoryFaq = () => {
// 获取自助服务
const getSelfService = () => {
return api.get('', {
method: 'app.help.selfService',
method: 'app.helper.selfService',
showPlatform: 'yohobuy_pc'
}, {
code: 200
});
};
const helpSearch = (keyword) => {
const helpSearch = (params) => {
return api.get('', {
method: 'app.help.search',
method: 'app.helper.search',
showPlatform: 'yohobuy_pc',
keyword: keyword,
keyword: params.keywords,
page: params.page,
viewNum: '15',
debug: 'XYZ'
}, {
code: 200
});
};
const allQA = () => {
return api.get('', {
method: 'app.helper.allQA',
showPlatform: 'yohobuy_pc'
}, {
code: 200
});
};
const onlineService = () => {
return api.get('', {
method: 'app.helper.getServiceOnline'
}, {
code: 200
});
};
module.exports = {
getHotSearch,
gethomeCategoryFaq,
getSelfService,
helpSearch
helpSearch,
allQA,
onlineService
};
... ...
... ... @@ -8,6 +8,60 @@
const _ = require('lodash');
const helpApi = require('./help-api');
/**
* 根据id获取当前所在位置,拼接面包屑
* @param id
* @param menuData
* @returns {*[]}
* @private
*/
const _getNav = (id, menuData)=> {
for (let i = 0; i < menuData.length; i++) {
if (menuData[i].subsets) {
for (let j = 0; j < menuData[i].subsets.length; j++) {
if (menuData[i].subsets[j].id === id) {
return [
{
link: ' ',
name: menuData[i].categoryName
}, {
name: menuData[i].subsets[j].categoryName
}
];
}
}
} else {
if (menuData[i].id === id) {
return [
{
name: menuData[i].categoryName
}
];
}
}
}
};
// 首页链接组装
const _processLink = (list, id) => {
let params = '';
list = list || [];
_.forEach(list, d => {
if (id) {
params = 'id=' + id + '&contId=' + d.id;
} else {
params = 'id=' + d.id;
}
d.jumpLink = global.yoho.config.siteUrl + '/help/detail?' + params;
});
return list;
};
// 首页模块内容处理
const _processHomeCategoryFaq = (list) => {
let result = {
other: []
... ... @@ -18,11 +72,21 @@ const _processHomeCategoryFaq = (list) => {
_.forEach(list.categorys, (item) => {
let newCont = [];
if (item.categoryItems) {
item.categoryItems = _processLink(item.categoryItems);
} else {
item.contentItems = _processLink(item.contentItems, item.id);
}
switch (item.categoryName) {
case '新手指南':
result.newGuide = item;
break;
case '公告':
_.forEach(item.contentItems, c => {
c.caption = c.caption.substring(0, 9);
});
_.chunk(item.contentItems, 2).forEach(data => {
newCont.push({
row: data
... ... @@ -77,14 +141,28 @@ const _processCountLength = (c) => {
}
};
const returnCont = (data, contKey) => {
const returnCont = (data, contId) => {
let curCont = {};
if (!data.contentItems) {
return;
}
_.forEach(data.contentItems, c => {
if (c.id === contId) {
curCont = c;
}
});
return {
isShowMenu: _processCountLength(data),
id: data.id,
title: data.categoryName,
list: data.contentItems,
contKey: contKey !== '' ? contKey : 0,
cont: contKey !== '' ? data.contentItems[contKey] : data.contentItems[0]
contId: contId ? contId : data.contentItems[0].id,
cont: contId ? curCont : data.contentItems[0]
};
};
... ... @@ -93,13 +171,13 @@ const _processDetailCont = (item, params) => {
let cont = false;
if (item.contentItems && item.id === params.id) {
return returnCont(item, params.contKey);
return returnCont(item, params.contId);
}
if (item.categoryItems) {
_.forEach(item.categoryItems, c => {
if (c.id === params.id) {
cont = returnCont(c, params.contKey);
cont = returnCont(c, params.contId);
}
});
return cont;
... ... @@ -107,10 +185,37 @@ const _processDetailCont = (item, params) => {
return false;
};
// 分类数据
const _processDetailData = (data, params) => {
// 处理搜索结果内容
const _processSearch = (list, params) => {
list = list || [];
if (list.total === 0) {
return {
error: true
};
} else {
list = _.assign({
paginationData: {
page: list.page,
limit: list.page_size || 10,
total: list.total,
pageTotal: list.page_total,
queryParams: {
page: params.page,
helpQuery: params.keywords
}
}
}, list);
}
return list;
};
// 详情内容及分类数据
const _processDetailData = (result, params) => {
let menuData = [];
let contData = false;
let data = result[1].data;
// 常见问题
if (data.faqs) {
... ... @@ -119,40 +224,46 @@ const _processDetailData = (data, params) => {
categoryName: '常见问题'
});
if (params.id === 1) {
if (params.id === 1 && !params.keywords) {
contData = {
isShowMenu: _processCountLength(data.faqs),
id: 1,
commonProblem: true,
faqs: data.faqs
faqs: data.faqs,
allQa: result[2].data
};
}
}
// 其它分类数据处理
_.forEach(data.categorys, item => {
let result;
let resCont;
menuData.push(_processMenuType(item));
if (contData) {
if (contData || params.keywords) {
return;
}
result = _processDetailCont(item, params);
resCont = _processDetailCont(item, params);
if (result) {
if (resCont) {
contData = _.assign({
helpDetail: true
}, result);
}, resCont);
}
});
return {
menuData: menuData,
contData: contData
nav: _getNav(params.id, menuData),
data: {
menuData: menuData,
contData: contData
}
};
};
// 首页
const helpData = () => {
return Promise.all([
helpApi.getHotSearch(),
... ... @@ -169,24 +280,44 @@ const helpData = () => {
});
};
const detailData = (keyword, params) => {
// 详情
const detailData = (params) => {
let promiseData = [
helpApi.getHotSearch(),
helpApi.gethomeCategoryFaq()
];
if (keyword) {
promiseData.push(helpApi.helpSearch(keyword));
if (params.id === 1) {
promiseData.push(helpApi.allQA());
}
return Promise.all(promiseData).then(result => {
let newData = _processDetailData(result, params);
newData.data.hotSearch = result[0].data;
return newData;
});
};
// 搜索
const searchData = (params) => {
return helpApi.helpSearch(params).then(result => {
return _.assign({
hotSearch: result[0].data
}, _processDetailData(result[1].data, params));
keywords: params.keywords
}, _processSearch(result.data.data, params));
});
};
// 在线客服
const onlineService = () => {
return helpApi.onlineService().then(result => {
return result.data.url;
});
};
module.exports = {
helpData,
detailData
detailData,
searchData,
onlineService
};
... ...
... ... @@ -16,8 +16,7 @@ const help = require(`${cRoot}/help`);
// 帮助中心
router.get('/index', help.index);
router.get('/detail', help.detail);
// router.get('/search', help.search);
router.get('/search', help.search);
router.get('/onlineService', help.onlineService);
module.exports = router;
... ...
... ... @@ -14,12 +14,7 @@
<div class="help-main left">
{{> search-form}}
<div class="detail-cont">
{{!--{{>help-detail}}--}}
{{#contData}}
{{#if search}}
{{> search-cont}}
{{/if}}
{{#if commonProblem}}
{{> common-problem}}
{{/if}}
... ...
... ... @@ -11,7 +11,7 @@
{{#each notice}}
<li>
{{#each row}}
<a class="notice-cont" href="{{url}}"><i class="dot-icon"></i> {{caption}}</a>
<a class="notice-cont" href="{{jumpLink}}"><i class="dot-icon"></i> {{caption}}</a>
{{/each}}
</li>
{{/each}}
... ... @@ -24,7 +24,7 @@
<ul class="menu-common new-guide">
{{#each categoryItems}}
<li>
<a href="{{jumpUrl}}"><img src="{{categoryIco}}" width="70" href="70"></a>
<a href="{{jumpLink}}"><img src="{{categoryIco}}" width="70" href="70"></a>
<p>{{categoryName}}</p>
</li>
{{/each}}
... ... @@ -58,7 +58,7 @@
<div class="list-box">
<div class="nav-list">
{{#categoryItems}}
<a href="{{url}}">{{categoryName}}</a>
<a href="{{jumpLink}}">{{categoryName}}</a>
{{/categoryItems}}
</div>
</div>
... ...
... ... @@ -7,12 +7,12 @@
</div>
<h2 class="all-problem-title">所有问题</h2>
<ul class="all-problem">
{{#faqs}}
{{#allQa}}
<li class="problem-li">
<p class="title">{{caption}}</p>
<p class="cont">{{{content}}}</p>
</li>
{{/faqs}}
{{/allQa}}
</ul>
</div>
... ...
... ... @@ -22,7 +22,7 @@
<h2>{{title}}</h2>
<div class="help-problem">
{{#list}}
<a href="/help/detail?id={{../id}}&key={{@index}}" class="{{#isEqual @index ../contKey}}active{{/isEqual}}"><i class="dot-icon"></i>{{caption}}</a>
<a href="/help/detail?id={{../id}}&contId={{id}}" class="{{#isEqual id ../contId}}active{{/isEqual}}"><i class="dot-icon"></i>{{caption}}</a>
{{/list}}
</div>
{{/if}}
... ...
{{#if error}}
<div class="search-result">很抱歉,关于“<span class="blue">有货制度</span></div>
<p class="result-error mt30">建议您:看看输入的文字是否有误/减少分类条件的限制/重新检索</p>
<p class="result-error">或 者:使用<a href="">在线客服</a>试试</p>
{{else}}
<div class="search-result">关于“<span class="blue">邮箱</span>”,共为您查询到<span class="blue">50</span>个答案</div>
<ul class="search-list">
<li class="problem-li">
<p class="title">送货要多长时间?</p>
<p class="cont">根据地域的不同,在您确认订购后的3-5天内我们会将<i class="keyword">邮箱</i>货品送到。如果在您订购完成后7天内商品仍没有送达,您可以直接与Yoho!Buy有货客服中心联系。需要说明的是:化妆品等液体商品,走的是陆运,会比普通商品晚2-3天左右,敬请谅解。</p>
</li>
<li class="article-li">
<p class="title">送货要多长时间?</p>
<p class="cont">根据地域的不同,在您确认订购后的3-5天内我们会将货品送到。如果在您订购完成后7天内商品仍没有送达,您可以直接与Yoho!Buy有货客服中心联系。需要说明的是:化妆品等液体商品,走的是陆运,会比普通商品晚2-3天左右,敬请谅解。</p>
</li>
</ul>
{{!-- 分页 --}}
{{{ pagination paginationData }}}
{{/if}}
... ... @@ -22,15 +22,15 @@ module.exports = {
},
cookieDomain: 'yohoblk.com',
domains: {
//singleApi: 'http://single.yoho.cn/',
//api: 'http://api.yoho.yohoops.org/',
//service: 'http://service.yoho.yohoops.org/',
//search: 'http://search.yohoops.org/yohosearch/'
// singleApi: 'http://single.yoho.cn/',
// api: 'http://api.yoho.yohoops.org/',
// service: 'http://service.yoho.yohoops.org/',
// search: 'http://search.yohoops.org/yohosearch/'
api: 'http://dev-api.yohops.com:9999/',
service: 'http://dev-service.yohops.com:9999/',
liveApi: 'http://testapi.live.yohops.com:9999/',
singleApi: 'http://api-test1.yohops.com:9999/',
api: 'http://dev-api.yohops.com:9999/',
service: 'http://dev-service.yohops.com:9999/',
liveApi: 'http://testapi.live.yohops.com:9999/',
singleApi: 'http://api-test1.yohops.com:9999/'
// api: 'http://api-test3.yohops.com:9999/',
... ...
/**
* 分页组件
* @author: djh<jinhu.dong@yoho.cn>
* @date: 2016/6/29
*/
'use strict';
// render pagination ellipse indicator
function _renderEllipse(templateStr) {
return templateStr + '<a>...</a>';
}
// render last page link
function _renderLastPage(templateStr, pageCount, queryParams) {
return templateStr + '<a href="?page=' + pageCount + queryParams + '">' + pageCount + '</a>';
}
/*
* Pagination Component
* @param { Object } pagination pagination constructor
* --- pagination ---
* @param { Integer } limit: per page records number
* @param { String } leftText: prev button text, default is iconfont
* @param { String } rightText: next button text, default is iconfont
* @param { String } paginationClass: pagination ul class, default is 'blk-pagination'
*/
module.exports = function(pagination, options) {
// default options
var limit = 9, // display links number
n, // page number ?page=n
queryParams = '', // paginate with query parameter
page = parseInt(pagination.page, 10), // current page number
leftText = '<i class="iconfont">&#xe607;</i>', // prev
rightText = '<i class="iconfont">&#xe61e;</i>', // next
paginationClass = 'blk-pagination'; // pagination <ul> default class
var pageCount,
key, // query params key
lastCharacterOfQueryParams;
var i, // iterator for each refresh page
leftCount, // left pagination link counts for current position
rightCount, // right pagination link counts for current position
start; // left first link number
var template;
if (!pagination || pagination.pageTotal === 1) {
return '';
}
// custome options
if (options.hash.limit) {
limit = +options.hash.limit;
}
if (options.hash.leftText) {
leftText = options.hash.leftText;
}
if (options.hash.rightText) {
rightText = options.hash.rightText;
}
if (options.hash.paginationClass) {
paginationClass = options.hash.paginationClass;
}
pageCount = Math.ceil(pagination.total / pagination.limit);
// query params
if (pagination.queryParams) {
queryParams = '&';
for (key in pagination.queryParams) {
if (pagination.queryParams.hasOwnProperty(key) && key !== 'page') {
queryParams += key + '=' + pagination.queryParams[key] + '&';
}
}
// lastCharacterOfQueryParams = queryParams.substring(queryParams.length, -1);
lastCharacterOfQueryParams = queryParams.slice(queryParams.length - 1);
if (lastCharacterOfQueryParams === '&') {
// trim off last & character
queryParams = queryParams.slice(0, queryParams.length - 1);
}
}
queryParams = encodeURI(queryParams);
template = '<div class="' + paginationClass + '">';
// ========= Previous Button ===============
if (page - 1) {
n = page - 1;
template = template + '<a class="pre-page" href="?page=' + n + queryParams + '">' + leftText + '</a>';
}
// ========= Page Numbers Middle ===============
// current is active, and make left page link count equal right link count
i = 0;
leftCount = Math.ceil(limit / 2) - 1;
rightCount = limit - leftCount - 1;
if (page + rightCount > pageCount) {
leftCount = limit - (pageCount - page) - 1;
}
if (page - leftCount < 1) {
leftCount = page - 1;
}
start = page - leftCount;
while (i < limit && i < pageCount) {
// start is every link
n = start;
if (start === page) {
template = template + '<a class="active" href="?page=' + n + queryParams + '">' + n + '</a>';
} else {
// generate left style
if (leftCount >= 4) {
if (i === 0) {
// first page
template = template + '<a href="?page=1' + queryParams + '">1</a>';
} else if (i === 1 || (i === 7 && start <= pageCount - 2)) {
// left and right ...
template = _renderEllipse(template);
} else if (i === 8 && start <= pageCount - 1) {
template = _renderLastPage(template, pageCount, queryParams);
} else {
// other links is normal
template = template +
'<a href="?page=' + n + queryParams + '">' +
n +
'</a>';
}
} else {
if (i === 7 && start <= pageCount - 2) {
// right ...
template = _renderEllipse(template);
} else if (i === 8 && start <= pageCount - 1) {
template = _renderLastPage(template, pageCount, queryParams);
} else {
template = template +
'<a href="?page=' + n + queryParams + '">' +
n +
'</a>';
}
}
}
start++;
i++;
}
// ========= Next page ===============
if (pageCount - page) {
n = page + 1;
template = template + '<a class="next-page" href="?page=' + n + queryParams + '">' + rightText + '</a>';
}
template = template + '</div>';
// html template
return template;
};
... ...
... ... @@ -10,12 +10,13 @@ var cutStr = function(params) {
var strLen = params.str.length || 0;
var i, curStr, addTxt;
params.type = '1';
params.str = params.str.replace(/<[^>]*>/g, '');
console.log(params.str)
if (params.type === '1') {
addTxt = '<span class="show-all">全部答案&gt;</span>';
if (params.type === '2') {
addTxt = '';
} else {
addTxt = '<a href="' + params.url + '" class="show-all">查看详情&gt;</a>';
addTxt = '<a href="' + params.url + '" class="show-all" target="_blank">查看详情&gt;</a>';
}
for (i = 0; i < strLen; i++) {
... ... @@ -46,5 +47,5 @@ var keywordLabel = function(str, key) {
return str.replace('www.yohobuy.com', '<a href="http://www.yohobuy.com" class="keyword">www.yohobuy.com</a>');
};
module.exports = cutStr;
module.exports = keywordLabel;
exports.cutStr = cutStr;
exports.keywordLabel = keywordLabel;
... ...
... ... @@ -23,6 +23,8 @@ $(function() {
}
});
new Scroller('notice', 30, 5);
setTimeout(function() {
new Scroller('notice', 30, 5);
}, 5000);
});
... ...
... ... @@ -13,12 +13,19 @@ var helpSearch = {
_this.searchDefaultVal();
$searchBtn.click(function() {
if (_this.$search.val() === '请输入您想知道的帮助信息') {
_this.$search.val('');
}
$helpSearchForm.submit();
});
_this.$search.keyup(function(e) {
var key = $(this).val();
if (key === '请输入您想知道的帮助信息') {
$(this).val('');
}
if (e.which === 13) {
if (key) {
$helpSearchForm.submit();
... ...
... ... @@ -7,20 +7,62 @@
var $subsets = $('.subsets');
var helpSearch = require('./help-search');
var problemBox = require('./problem-box');
var helper = require('./help-helper');
var comI = require('../common/index');
var queryId = comI.queryString().id;
var searchTemplet = require('../../tpl/help/search-cont.hbs');
var qs = comI.queryString();
var queryId = qs.id;
var page = qs.page || 1;
var keywords = qs.helpQuery;
var $cate = $('.cateId-' + queryId);// 当前分类
let parentID;
require('../common/header');
require('../common/return-top');
helpSearch.init();
problemBox();
require('../help/cutstr');
// 获取搜索的结果
if (keywords) {
$.get('/help/search', {
page: page,
keywords: keywords
}, function(result) {
var id,
$detailCont = $('.detail-cont');
if (result.helper_list) {
result.helper_list.forEach(function(s) {
if (s.helperType === '2') {
s.problem = true;
s.allCont = s.content;
}
helpSearch.init();
problemBox();
if (s.secendCategoryId === 0) {
id = s.firstCategoryId;
} else {
id = s.secendCategoryId;
}
s.content = helper.cutStr({
str: s.content,
len: 380,
type: s.helperType,
url: '/help/detail?id=' + id + '&contId=' + s.id
});
s.content = helper.keywordLabel(s.content, keywords);
});
$detailCont.html(searchTemplet(result));
} else {
$.get('/help/onlineService', {}, function(url) {
result.jumpUrl = url;
$detailCont.html(searchTemplet(result));
});
}
});
}
/**
* 目录切换
... ...
... ... @@ -68,6 +68,10 @@
padding-top: 45px;
}
.blk-pagination {
margin: 20px auto 0;
}
.normal-data,
.step-data {
padding: 2px;
... ... @@ -107,15 +111,22 @@
.blue {
color: #1ca1da;
padding: 0 5px;
}
}
.search-list {
width: 100%;
height: auto;
overflow: hidden;
.article-li {
float: left;
margin-top: 30px;
position: relative;
padding-left: 36px;
width: 100%;
box-sizing: border-box;
.title:before {
content: "";
... ... @@ -174,6 +185,7 @@
.show-all {
color: #1ea1da;
cursor: pointer;
}
.problem-li {
... ...
{{#if error}}
<div class="search-result">很抱歉,关于“<span class="blue">{{keywords}}</span></div>
<p class="result-error mt30">建议您:看看输入的文字是否有误/减少分类条件的限制/重新检索</p>
<p class="result-error">或 者:使用<a href="{{jumpUrl}}">在线客服</a>试试</p>
{{else}}
<div class="search-result">关于“<span class="blue">{{keywords}}</span>”,共为您查询到<span class="blue">{{total}}</span>个答案</div>
<ul class="search-list">
{{#helper_list}}
<li class="{{#if problem}}problem-li{{else}}article-li{{/if}}">
<p class="title">{{caption}}</p>
{{#if problem}}
<p class="cont">{{{allCont}}}</p>
{{else}}
<p class="cont">{{{content}}}</p>
{{/if}}
</li>
{{/helper_list}}
</ul>
{{!-- 分页 --}}
{{{ pagination paginationData }}}
{{/if}}
... ...