Authored by 郭成尧

Merge branch 'feature/search' into 'release/6.5'

Feature/search



See merge request !1237
@@ -27,7 +27,7 @@ @@ -27,7 +27,7 @@
27 "request": "launch", 27 "request": "launch",
28 "name": "Node", 28 "name": "Node",
29 "program": "${workspaceFolder}/app.js", 29 "program": "${workspaceFolder}/app.js",
30 - "console":"integratedTerminal" 30 + "console": "integratedTerminal"
31 } 31 }
32 ] 32 ]
33 } 33 }
@@ -108,7 +108,7 @@ const baseShopFav = (req, res) => { @@ -108,7 +108,7 @@ const baseShopFav = (req, res) => {
108 108
109 /** 109 /**
110 * 店铺首页 110 * 店铺首页
111 - * @return int 111 + * TODO 弃用
112 */ 112 */
113 const _shop = (req, res, shopId) => { 113 const _shop = (req, res, shopId) => {
114 let isApp = req.query.app_version || req.query.appVersion || false; 114 let isApp = req.query.app_version || req.query.appVersion || false;
@@ -216,7 +216,10 @@ const shopFav = (req, res) => { @@ -216,7 +216,10 @@ const shopFav = (req, res) => {
216 }); 216 });
217 }; 217 };
218 218
219 -// 品类落地页 219 +/**
  220 + * 旧版品类落地页
  221 + * TODO 已重构为 listNew 待删除
  222 + */
220 const category = (req, res, next) => { 223 const category = (req, res, next) => {
221 if (req.query) { 224 if (req.query) {
222 _.forEach(req.query, (perParam, index) => { 225 _.forEach(req.query, (perParam, index) => {
@@ -400,9 +403,7 @@ const getCategoryGoods = (req, res, next) => { @@ -400,9 +403,7 @@ const getCategoryGoods = (req, res, next) => {
400 403
401 /** 404 /**
402 * 品牌店铺的入口 405 * 品牌店铺的入口
403 - * @param req  
404 - * @param res  
405 - * @param next 406 + * TODO 弃用
406 */ 407 */
407 const brand = (req, res, next) => { 408 const brand = (req, res, next) => {
408 let params = Object.assign({}, req.query); 409 let params = Object.assign({}, req.query);
@@ -11,12 +11,54 @@ const headerModel = require('../../../doraemon/models/header'); @@ -11,12 +11,54 @@ const headerModel = require('../../../doraemon/models/header');
11 const searchModel = require(`${mRoot}/search`); 11 const searchModel = require(`${mRoot}/search`);
12 const _ = require('lodash'); 12 const _ = require('lodash');
13 const helpers = global.yoho.helpers; 13 const helpers = global.yoho.helpers;
  14 +const stringProcess = require(`${utils}/string-process`);
14 const searchProcess = require(`${utils}/search-process`); 15 const searchProcess = require(`${utils}/search-process`);
15 const productProcess = require(`${utils}/product-process`); 16 const productProcess = require(`${utils}/product-process`);
16 const listParamsProcess = require(`${utils}/list-params-process`); 17 const listParamsProcess = require(`${utils}/list-params-process`);
17 const co = require('bluebird').coroutine; 18 const co = require('bluebird').coroutine;
18 19
19 /** 20 /**
  21 + * 搜索主页
  22 + */
  23 +exports.index = (req, res, next) => {
  24 + let title = '搜索',
  25 + uid = req.user.uid || 0;
  26 +
  27 + ((render) => {
  28 + if (_.get(req, 'app.locals.wap.search.removeHotSearch', false)) {
  29 + render([]);
  30 + } else {
  31 +
  32 + req.ctx(searchModel).getSearchIndex({
  33 + gender: req.yoho.channel || 'boys',
  34 + uid: uid
  35 + }).then((result) => {
  36 + render(result);
  37 + }).catch(next);
  38 + }
  39 +
  40 + })((result) => {
  41 + res.render('search/index', Object.assign({
  42 + module: 'product',
  43 + page: 'search-index',
  44 + pageHeader: headerModel.setNav({
  45 + navTitle: title
  46 + }),
  47 + pageFooter: true,
  48 + width750: true,
  49 + search: {
  50 + defaultTerms: (result && result.defaultTerms && result.defaultTerms.length) ?
  51 + result.defaultTerms[0].content : '',
  52 + url: helpers.urlFormat('', null, 'search'),
  53 + hotTerms: result.hotTerms,
  54 + wantTerms: result.guessTerms
  55 + }
  56 +
  57 + }, searchProcess.getListSeoData()));
  58 + });
  59 +};
  60 +
  61 +/**
20 * 搜索落地页 62 * 搜索落地页
21 */ 63 */
22 exports.list = (req, res, next) => { 64 exports.list = (req, res, next) => {
@@ -27,8 +69,7 @@ exports.list = (req, res, next) => { @@ -27,8 +69,7 @@ exports.list = (req, res, next) => {
27 let title = ''; 69 let title = '';
28 let isQueryFirstClass = false; // 标识用户搜的是不是一级品类 70 let isQueryFirstClass = false; // 标识用户搜的是不是一级品类
29 let isQuerySecondClass = false; // 标识用户搜的是不是二级品类 71 let isQuerySecondClass = false; // 标识用户搜的是不是二级品类
30 - // let domain = null;  
31 - let uid = req.user.uid || 0; 72 + let uid = req.user.uid;
32 73
33 if (params.shop_id) { 74 if (params.shop_id) {
34 params.shopId = params.shop_id; 75 params.shopId = params.shop_id;
@@ -76,26 +117,6 @@ exports.list = (req, res, next) => { @@ -76,26 +117,6 @@ exports.list = (req, res, next) => {
76 } 117 }
77 118
78 if (params.query) { 119 if (params.query) {
79 - // domain = result[0];  
80 -  
81 - // 跳转到品牌商品列表页  
82 - // if (domain !== null && !params.shop_id) {  
83 - // let urlPro = {  
84 - // from: 'search',  
85 - // query: params.query  
86 - // };  
87 -  
88 - // if (req.query.app_type) {  
89 - // urlPro = _.assign(urlPro, {  
90 - // app_type: req.query.app_type  
91 - // });  
92 - // }  
93 -  
94 - // let url = helpers.urlFormat('', urlPro, domain);  
95 -  
96 - // return res.redirect(url);  
97 - // }  
98 -  
99 // 品类名称为空时跳出 120 // 品类名称为空时跳出
100 if (!result[1]) { 121 if (!result[1]) {
101 return; 122 return;
@@ -141,6 +162,7 @@ exports.list = (req, res, next) => { @@ -141,6 +162,7 @@ exports.list = (req, res, next) => {
141 _noLazy: true, 162 _noLazy: true,
142 module: 'product', 163 module: 'product',
143 page: 'search-list', 164 page: 'search-list',
  165 + localCss: true,
144 pageHeader: headerModel.setNav({ 166 pageHeader: headerModel.setNav({
145 navTitle: title 167 navTitle: title
146 }), 168 }),
@@ -157,47 +179,6 @@ exports.list = (req, res, next) => { @@ -157,47 +179,6 @@ exports.list = (req, res, next) => {
157 }; 179 };
158 180
159 /** 181 /**
160 - * 搜索主页  
161 - */  
162 -exports.index = (req, res, next) => {  
163 - let title = '搜索',  
164 - uid = req.user.uid || 0;  
165 -  
166 - ((render) => {  
167 - if (_.get(req, 'app.locals.wap.search.removeHotSearch', false)) {  
168 - render([]);  
169 - } else {  
170 -  
171 - req.ctx(searchModel).getSearchIndex({  
172 - gender: req.yoho.channel || 'boys',  
173 - uid: uid  
174 - }).then((result) => {  
175 - render(result);  
176 - }).catch(next);  
177 - }  
178 -  
179 - })((result) => {  
180 - res.render('search/index', Object.assign({  
181 - module: 'product',  
182 - page: 'search-index',  
183 - pageHeader: headerModel.setNav({  
184 - navTitle: title  
185 - }),  
186 - pageFooter: true,  
187 - width750: true,  
188 - search: {  
189 - defaultTerms: (result && result.defaultTerms && result.defaultTerms.length) ?  
190 - result.defaultTerms[0].content : '',  
191 - url: helpers.urlFormat('', null, 'search'),  
192 - hotTerms: result.hotTerms,  
193 - wantTerms: result.guessTerms  
194 - }  
195 -  
196 - }, searchProcess.getListSeoData()));  
197 - });  
198 -};  
199 -  
200 -/**  
201 * 联动搜索 182 * 联动搜索
202 */ 183 */
203 exports.fuzzyDatas = (req, res, next) => { 184 exports.fuzzyDatas = (req, res, next) => {
@@ -213,12 +194,6 @@ exports.fuzzyDatas = (req, res, next) => { @@ -213,12 +194,6 @@ exports.fuzzyDatas = (req, res, next) => {
213 * ajax 商品数据请求 194 * ajax 商品数据请求
214 */ 195 */
215 exports.search = (req, res, next) => { 196 exports.search = (req, res, next) => {
216 - let allowOrigin = _.get(req, 'headers.origin', null) ?  
217 - req.headers.origin : req.protocol + '://' + req.headers.host;  
218 -  
219 - res.setHeader('Access-Control-Allow-Origin', allowOrigin);  
220 - res.setHeader('Access-Control-Allow-Credentials', 'true');  
221 -  
222 let params = Object.assign({}, req.query); 197 let params = Object.assign({}, req.query);
223 let uid = req.user.uid || 0; 198 let uid = req.user.uid || 0;
224 199
@@ -226,8 +201,13 @@ exports.search = (req, res, next) => { @@ -226,8 +201,13 @@ exports.search = (req, res, next) => {
226 params.uid = uid; 201 params.uid = uid;
227 } 202 }
228 203
  204 + if (params.query) {
  205 + params.query = stringProcess.decodeURIComponent(params.query);
  206 + }
  207 +
229 params.isApp = req.yoho.isApp; 208 params.isApp = req.yoho.isApp;
230 params.limit = 24; 209 params.limit = 24;
  210 + params.physical_channel = req.yoho.channel && searchProcess.getChannelType(req.yoho.channel);
231 211
232 req.ctx(searchModel).getSearchData(params).then((result) => { 212 req.ctx(searchModel).getSearchData(params).then((result) => {
233 213
@@ -587,10 +587,7 @@ module.exports = class extends global.yoho.BaseModel { @@ -587,10 +587,7 @@ module.exports = class extends global.yoho.BaseModel {
587 587
588 /** 588 /**
589 * 使用经典模板的店铺首页 589 * 使用经典模板的店铺首页
590 - * @param {object} req  
591 - * @param {int} shopId 店铺id  
592 - * @param {int} uid 用户id  
593 - * @param {string} isApp app版本 590 + * TODO 弃用
594 */ 591 */
595 getShopData(req, shopId, uid, isApp) { 592 getShopData(req, shopId, uid, isApp) {
596 let shopData = {}; 593 let shopData = {};
@@ -94,109 +94,15 @@ module.exports = class extends global.yoho.BaseModel { @@ -94,109 +94,15 @@ module.exports = class extends global.yoho.BaseModel {
94 } 94 }
95 95
96 /** 96 /**
97 - * 商品搜索接口请求  
98 - * TODO 按接口拆分  
99 - * @param {[object]} params  
100 - * @return {[array]} 97 + * 新的搜索接口处理,替换 _searchGoods
101 */ 98 */
102 - _searchGoods(params) {  
103 - let method = 'app.search.li';  
104 -  
105 - if (_.isArray(params.query)) {  
106 - params.query = _.join(params.query, ',');  
107 - }  
108 -  
109 - // 排除基本筛选项默认值为0的对象  
110 - for (let str in params) {  
111 - if (str !== 'order' && params[str] === '0' || params[str] === null) {  
112 - delete params[str];  
113 - }  
114 - }  
115 -  
116 - /* tar add 160823 店铺销售类目 */  
117 - if (params.filter_poolId) {  
118 - method = 'app.search.pool';  
119 - Object.assign(params, {  
120 - productPool: params.filter_poolId  
121 - });  
122 - delete params.filter_poolId;  
123 - }  
124 -  
125 - if (params.shop_id && !params.productPool) {  
126 - method = 'app.search.li';  
127 - }  
128 -  
129 - if (params.channel) {  
130 - params.yh_channel = searchProcess.getChannelType(params.channel);  
131 - delete params.channel;  
132 - }  
133 -  
134 - if (params.query) {  
135 - params.query = params.query.replace(/\+/g, ',');  
136 - }  
137 -  
138 - if (params.app_type && params.app_type === '1') {  
139 - params.app_type = 1;  
140 - }  
141 -  
142 - params = _.assign({  
143 - limit: '24',  
144 - status: 1,  
145 - sales: 'Y',  
146 - stocknumber: 1,  
147 - attribute_not: 2  
148 - }, params);  
149 -  
150 - if (params.type === 'default') {  
151 - // 筛选 默认 不传order  
152 - delete params.order;  
153 - } else if (params.order) {  
154 - params.order = searchProcess.getTypeCont(params.type || '', params.order);  
155 - } else {  
156 - params.order = 's_t_asc';  
157 - }  
158 -  
159 - // 学生返币查询  
160 - if (params.coin) {  
161 - method = 'app.student.rebate';  
162 - delete params.filter_poolId;  
163 -  
164 - if (params.type === 'newest') {  
165 - delete params.order;  
166 - delete params.type;  
167 - }  
168 - }  
169 -  
170 - if (params.isblknew) {  
171 - method = 'app.search.newProduct';  
172 - params.app_type = 1;  
173 - if (params.type === 'default') {  
174 - params.order = 's_t_asc';  
175 - }  
176 - }  
177 -  
178 - if (params.promotion_id) {  
179 - method = 'app.search.promotion';  
180 - }  
181 -  
182 - if (params.students) {  
183 - method = 'app.student.discount';  
184 - }  
185 -  
186 - // 个人中心优惠券立即使用 - 商品列表  
187 - if (params.coupon_id || params.coupon_code) {  
188 - method = 'app.search.coupon';  
189 - }  
190 -  
191 - // 物料商品列表增加  
192 - if (params.material === 'true') {  
193 - method = 'app.search.recommendProduct';  
194 - } 99 + _queryGoods(params) {
  100 + let paramsForApi = searchProcess.getSearchParamsWithoutMethod(params);
195 101
196 return this.get({ 102 return this.get({
197 data: _.assign({ 103 data: _.assign({
198 - method: method  
199 - }, params), 104 + method: 'app.search.li'
  105 + }, paramsForApi),
200 param: { 106 param: {
201 cache: true 107 cache: true
202 } 108 }
@@ -246,7 +152,7 @@ module.exports = class extends global.yoho.BaseModel { @@ -246,7 +152,7 @@ module.exports = class extends global.yoho.BaseModel {
246 // client_type 全部赋值为h5 过滤掉嵌入APP页面是默认的client_type 152 // client_type 全部赋值为h5 过滤掉嵌入APP页面是默认的client_type
247 params.client_type = 'h5'; 153 params.client_type = 'h5';
248 154
249 - return this._searchGoods(params).then((result) => { 155 + return this._queryGoods(params).then((result) => {
250 if (result && result.code === 200) { 156 if (result && result.code === 200) {
251 let newList = {}; 157 let newList = {};
252 let suggestion = {}; 158 let suggestion = {};
@@ -426,10 +332,8 @@ module.exports = class extends global.yoho.BaseModel { @@ -426,10 +332,8 @@ module.exports = class extends global.yoho.BaseModel {
426 filterDataResult = yield self.getBrandGoods(params); 332 filterDataResult = yield self.getBrandGoods(params);
427 } else if (params.isShopList === 'Y') { // 无店铺有店铺 ID 的商品列表 333 } else if (params.isShopList === 'Y') { // 无店铺有店铺 ID 的商品列表
428 filterDataResult = yield self.getShopGoods(params); 334 filterDataResult = yield self.getShopGoods(params);
429 - } else if (params.isNewList === 'Y') { // 新的 SEO 友好的品类落地页 335 + } else { // 新的 SEO 友好的品类落地页
430 filterDataResult = yield self.getCategoryGoods(params); 336 filterDataResult = yield self.getCategoryGoods(params);
431 - } else {  
432 - filterDataResult = yield self._searchGoods(params);  
433 } 337 }
434 338
435 let filterData = _.get(filterDataResult, 'data.filter', []); 339 let filterData = _.get(filterDataResult, 'data.filter', []);
@@ -443,23 +347,6 @@ module.exports = class extends global.yoho.BaseModel { @@ -443,23 +347,6 @@ module.exports = class extends global.yoho.BaseModel {
443 } 347 }
444 348
445 /** 349 /**
446 - * 获取筛选数据  
447 - * @param {[object]} params  
448 - * @return {[array]}  
449 - * TODO 这个可能不用了,待确定  
450 - */  
451 - getFilterSearchData(params) {  
452 - return this._searchGoods(params).then((result) => {  
453 - if (result && result.code === 200) {  
454 - return result.data;  
455 - } else {  
456 - logger.error('get filter data api return code is not 200');  
457 - return [];  
458 - }  
459 - });  
460 - }  
461 -  
462 - /**  
463 * 获取所有的品类名称 350 * 获取所有的品类名称
464 **/ 351 **/
465 getClassNames() { 352 getClassNames() {
@@ -141,20 +141,23 @@ router.get('/seckill/list', seckill.indexData); @@ -141,20 +141,23 @@ router.get('/seckill/list', seckill.indexData);
141 router.post('/seckill/remind', seckill.remind); // only app; 秒杀提醒 141 router.post('/seckill/remind', seckill.remind); // only app; 秒杀提醒
142 router.get('/seckill/get-product-list', seckill.getProductList); // 秒杀列表根据活动id获取商品列表 142 router.get('/seckill/get-product-list', seckill.getProductList); // 秒杀列表根据活动id获取商品列表
143 143
144 -router.get('/search/index', search.index); // 搜索主页  
145 -router.get('/search/so/:query.html', rewrite.sortParams, chanpin.keyword); // 推广落地页  
146 -router.get('/search/chanpin/:id.html', rewrite.sortParams, chanpin.keyId);  
147 -router.get('/search/chanpin/goods', chanpin.searchGoods); // 搜索的商品  
148 -router.get('/search/list', rewrite.sortParams, search.list); // 搜索落地页 144 +router.get('/search', search.index); // 搜索主页
  145 +router.get('/search/list', search.list); // 搜索落地页
149 router.get('/search/filter', search.filter); // filter 146 router.get('/search/filter', search.filter); // filter
150 router.get('/search/fuzzyDatas', search.fuzzyDatas); // fuzzyDatas 147 router.get('/search/fuzzyDatas', search.fuzzyDatas); // fuzzyDatas
151 router.get('/search/search', search.search); // ajax 请求商品数据 148 router.get('/search/search', search.search); // ajax 请求商品数据
  149 +
  150 +router.get('/search/so/:query.html', rewrite.sortParams, chanpin.keyword); // 推广落地页
  151 +router.get('/search/chanpin/:id.html', rewrite.sortParams, chanpin.keyId);
  152 +router.get('/search/chanpin/goods', chanpin.searchGoods); // 搜索的商品
152 router.get('/search/brand/goods', search.searchBrandGoods); // 搜索品牌下的商品 153 router.get('/search/brand/goods', search.searchBrandGoods); // 搜索品牌下的商品
153 router.get('/search/shop/goods', search.searchShopGoods); // 搜索店铺下的商品 154 router.get('/search/shop/goods', search.searchShopGoods); // 搜索店铺下的商品
154 155
155 router.get('/list/global(/:pathParams)?', rewrite.resolvePathParams, globalPro.list); // 全球购路由重写 全球购列表页 156 router.get('/list/global(/:pathParams)?', rewrite.resolvePathParams, globalPro.list); // 全球购路由重写 全球购列表页
156 -router.get('/index/index', rewrite.sortParams, list.category); // 旧品类首页  
157 -router.get('/list/index', rewrite.sortParams, list.category); // 兼容 PC 的链接 157 +
  158 +// router.get('/index/index', rewrite.sortParams, list.category); // 旧 品类首页
  159 +// router.get('/list/index', rewrite.sortParams, list.category); // 旧 兼容 PC 的链接
  160 +
158 router.get('/list(/:pathParams)?', rewrite.resolvePathParams, list.listNew); // 列表新的 URL 161 router.get('/list(/:pathParams)?', rewrite.resolvePathParams, list.listNew); // 列表新的 URL
159 router.get('/search/category', 162 router.get('/search/category',
160 cors, 163 cors,
@@ -29,7 +29,7 @@ @@ -29,7 +29,7 @@
29 <div class="search-group history-search hide"> 29 <div class="search-group history-search hide">
30 <div class="search-content-title"> 30 <div class="search-content-title">
31 <h3 class="left">最近搜索</h3> 31 <h3 class="left">最近搜索</h3>
32 - <i id="clear-history" class="right ico-del hide"></i> 32 + <i id="clear-history" class="iconfont right ico-del hide">&#xe64c;</i>
33 </div> 33 </div>
34 <div class="search-content"> 34 <div class="search-content">
35 <ul class="history clearfix"></ul> 35 <ul class="history clearfix"></ul>
@@ -31,20 +31,12 @@ module.exports = () => { @@ -31,20 +31,12 @@ module.exports = () => {
31 case 'cdnsrclist':// CDN list 回源域名 31 case 'cdnsrclist':// CDN list 回源域名
32 return res.redirect(301, listParamsProcess.generatePathUrl(req.query)); 32 return res.redirect(301, listParamsProcess.generatePathUrl(req.query));
33 case 'search': // search 33 case 'search': // search
34 - if (req.path === '/') {  
35 -  
36 - // 有查询关键字  
37 - if (_.keys(req.query).length) {  
38 - req.url = `/product/search/list?${querystring.stringify(req.query)}`;  
39 - } else {  
40 - req.url = `/product/search/index?${querystring.stringify(req.query)}`;  
41 - }  
42 - }  
43 -  
44 - if (req.path === '/search') {  
45 - req.url = `/product/search/index?${querystring.stringify(req.query)}`; 34 + // 有查询关键字
  35 + if (_.keys(req.query).length) {
  36 + return res.redirect(301, listParamsProcess.generatePathUrl(req.query, 'search/list'));
  37 + } else {
  38 + return res.redirect(301, listParamsProcess.generatePathUrl(req.query, 'search'));
46 } 39 }
47 - break;  
48 40
49 // 已经废弃,只是对老页面做兼容 --start 41 // 已经废弃,只是对老页面做兼容 --start
50 case 'sale': // sale 跳转到 m.yohobuy.com/product/sale 42 case 'sale': // sale 跳转到 m.yohobuy.com/product/sale
@@ -73,8 +73,8 @@ module.exports = () => { @@ -73,8 +73,8 @@ module.exports = () => {
73 req.url = `/product${req.url}`; 73 req.url = `/product${req.url}`;
74 } 74 }
75 75
76 - if (/^\/sale/.test(req.url)) {  
77 - // 匹配 life-style-sale 76 + if (/^\/search/.test(req.url)) {
  77 + // 搜索
78 req.url = `/product${req.url}`; 78 req.url = `/product${req.url}`;
79 } 79 }
80 80
@@ -16,7 +16,8 @@ const loading = require('plugin/loading'); @@ -16,7 +16,8 @@ const loading = require('plugin/loading');
16 16
17 class ProductListWithFilter { 17 class ProductListWithFilter {
18 constructor(filterParams, searchUrl, extra) { 18 constructor(filterParams, searchUrl, extra) {
19 - this.scrollActived = true; // 是否激活滚动加载,默认激活 19 + this.scrollActived = extra && typeof extra.scrollActived !== 'undefined' ?
  20 + extra.scrollActived : true; // 是否激活滚动加载,默认激活
20 this.filterParams = filterParams; 21 this.filterParams = filterParams;
21 this.searchUrl = location.protocol + '//m.yohobuy.com/' + (searchUrl || 'product/search/search'); 22 this.searchUrl = location.protocol + '//m.yohobuy.com/' + (searchUrl || 'product/search/search');
22 this.filterUrl = location.protocol + '//m.yohobuy.com/product/search/filter'; 23 this.filterUrl = location.protocol + '//m.yohobuy.com/product/search/filter';
1 /** 1 /**
2 - * 搜索商品列表页  
3 - * @author: wsl<shuiling.wang@yoho.cn>  
4 - * @date: 2016/7/21 2 + * 商品列表页、品类落地页
5 */ 3 */
6 require('product/search/list.page.css'); 4 require('product/search/list.page.css');
7 5
1 /** 1 /**
2 * 搜索商品列表页 2 * 搜索商品列表页
3 - * @author: wsl<shuiling.wang@yoho.cn>  
4 - * @date: 2016/7/21  
5 */ 3 */
  4 +import 'product/search/list.page.css';
  5 +import Page from 'yoho-page';
  6 +import noResultHbs from 'product/search/no-result-new.hbs';
  7 +import ProductListWithFilter from './list/product-list-with-filter';
  8 +import qs from 'yoho-qs';
  9 +import SearchListExtra from './search/search-list-extra';
  10 +import 'common/footer';
6 11
7 -require('product/search/list.page.css'); 12 +class Search extends Page {
  13 + constructor() {
  14 + super();
8 15
9 -require('./search/list');  
10 -require('common/footer');  
11 -require('./shop/coupon'); 16 + this.selector = {
  17 + goodsContainer: $('#goods-container'),
  18 + defaultGoods: $('.default-goods')
  19 + };
  20 +
  21 + this.firstScreen = this.selector.defaultGoods.children().size() > 0;
  22 + if (!this.firstScreen) {
  23 + this.selector.goodsContainer.html(noResultHbs());
  24 + }
  25 +
  26 + let initParams = {
  27 + page: 2
  28 + };
  29 +
  30 + if (qs) {
  31 + $.extend(initParams, qs);
  32 + }
  33 +
  34 + new ProductListWithFilter(initParams, null, {
  35 + scrollActived: this.firstScreen
  36 + });
  37 +
  38 + new SearchListExtra();
  39 + }
  40 +}
  41 +
  42 +export default new Search();
  1 +import Page from 'yoho-page';
  2 +import Tip from 'plugin/tip';
  3 +import maybeLike from 'channel/maybe-like';
  4 +
  5 +class SearchListExtra extends Page {
  6 + constructor() {
  7 + super();
  8 +
  9 + this.selector = {
  10 + input: $('#search-input').find('input[name="query"]'),
  11 + clear: $('#search-input .clear-input'),
  12 + buriedpoint: $('.buriedpoint'),
  13 + search: $('#search')
  14 + };
  15 +
  16 + this.selector.clear.on('click', () => {
  17 + this.selector.input.val('').trigger('input');
  18 + });
  19 +
  20 + this.init();
  21 + }
  22 +
  23 + init() {
  24 + maybeLike({recpose: 100101, isExecute: true});
  25 + this.inputAction();
  26 + }
  27 +
  28 + /**
  29 + * 搜索输入联动
  30 + */
  31 + inputAction() {
  32 + let $searchAssociate = $('.search-associate');
  33 + let $icon = $('.search-icon');
  34 + let $searchItems = $('.search-items');
  35 +
  36 + this.selector.input.on('input', () => {
  37 + if (this.selector.input.val() === '') {
  38 + $icon.css('color', '#b2b2b2');
  39 + this.selector.clear.addClass('hide');
  40 + $searchAssociate.html('');
  41 + $searchItems.show();
  42 + $searchAssociate.hide();
  43 + } else {
  44 + $icon.css('color', '#666');
  45 + this.selector.clear.removeClass('hide');
  46 + $searchAssociate.show();
  47 + }
  48 +
  49 + // 联动搜索
  50 + $.ajax({
  51 + url: '/product/search/fuzzyDatas',
  52 + data: {
  53 + keyword: this.selector.input.val()
  54 + },
  55 + dataType: 'json',
  56 + success: (data) => {
  57 + let ajaxHtml = '';
  58 + let i;
  59 +
  60 + if (data.length > 0) {
  61 + for (i = 0; i < data.length; i++) {
  62 + ajaxHtml += '<li><span class="keyword">' + data[i].keyword + '</span><span class="count">' +
  63 + data[i].count + ' items<i class="iconfont">&#xe614;</i></span></li>';
  64 + }
  65 +
  66 + $searchAssociate.html(ajaxHtml);
  67 + $searchItems.hide();
  68 + } else {
  69 + $searchAssociate.html('');
  70 + }
  71 +
  72 + $searchAssociate.find('li').on('click', event => {
  73 + this.selector.buriedpoint.val($(event.currentTarget).find('.keyword').html());
  74 + this.selector.search.closest('form').submit();
  75 + });
  76 + },
  77 + error: () => {
  78 + Tip.show('网络断开连接了~');
  79 + }
  80 + });
  81 + });
  82 + }
  83 +}
  84 +
  85 +export default SearchListExtra;
@@ -43,7 +43,7 @@ @@ -43,7 +43,7 @@
43 43
44 .clear-input { 44 .clear-input {
45 position: absolute; 45 position: absolute;
46 - top: 10px; 46 + top: 4px;
47 right: 100px; 47 right: 100px;
48 } 48 }
49 49
@@ -171,7 +171,7 @@ @@ -171,7 +171,7 @@
171 width: 24px; 171 width: 24px;
172 height: 26px; 172 height: 26px;
173 display: inline-block; 173 display: inline-block;
174 - background: url("/search/del-ico.png") no-repeat; 174 + color: #b0b0b0;
175 } 175 }
176 176
177 .left { 177 .left {
@@ -335,6 +335,9 @@ const getSearchParamsWithoutMethod = (params) => { @@ -335,6 +335,9 @@ const getSearchParamsWithoutMethod = (params) => {
335 if (params.saleType) { 335 if (params.saleType) {
336 finalParams.saleType = params.saleType; 336 finalParams.saleType = params.saleType;
337 } 337 }
  338 + if (params.physical_channel) {
  339 + finalParams.physical_channel = params.physical_channel;
  340 + }
338 341
339 return finalParams; 342 return finalParams;
340 }; 343 };