Authored by 郭成尧

Merge branch 'develop' of git.yoho.cn:fe/yohoblk-wap into develop

@@ -10,3 +10,6 @@ @@ -10,3 +10,6 @@
10 <hr> 10 <hr>
11 Cookies:<br> 11 Cookies:<br>
12 {{{cookies}}} 12 {{{cookies}}}
  13 +
  14 +<hr>
  15 +<input type="date">
@@ -39,6 +39,12 @@ const component = { @@ -39,6 +39,12 @@ const component = {
39 res.render('index', _.merge(result, data[1])); 39 res.render('index', _.merge(result, data[1]));
40 }).catch(next); 40 }).catch(next);
41 }, 41 },
  42 + mydetails: (req, res) => {
  43 + res.render('mydetails', {
  44 + module: 'home',
  45 + page: 'mydetails'
  46 + });
  47 + },
42 help: (req, res, next) => { 48 help: (req, res, next) => {
43 homeModel.getHelpInfo().then(helpList => { 49 homeModel.getHelpInfo().then(helpList => {
44 res.render('help', { 50 res.render('help', {
@@ -104,8 +110,6 @@ const component = { @@ -104,8 +110,6 @@ const component = {
104 } 110 }
105 }).catch(next); 111 }).catch(next);
106 }, 112 },
107 -  
108 - // 关于我们  
109 aboutUs: (req, res) => { 113 aboutUs: (req, res) => {
110 res.render('about-us', { 114 res.render('about-us', {
111 module: 'home', 115 module: 'home',
@@ -33,7 +33,7 @@ const refund = { @@ -33,7 +33,7 @@ const refund = {
33 res.render('logistics', { 33 res.render('logistics', {
34 module: 'home', 34 module: 'home',
35 page: 'logistics', 35 page: 'logistics',
36 - company_list: result ? JSON.stringify(result.data) : "" 36 + company_list: result ? JSON.stringify(result.data) : ''
37 }); 37 });
38 }).catch(next); 38 }).catch(next);
39 }, 39 },
@@ -50,6 +50,7 @@ router.get('/exchange', exchange.exchange); @@ -50,6 +50,7 @@ router.get('/exchange', exchange.exchange);
50 router.get('/exchange/order', exchange.order); // AJAX 获取订单 商品 50 router.get('/exchange/order', exchange.order); // AJAX 获取订单 商品
51 router.get('/exchange/delivery', exchange.delivery); // AJAX 获取 退货方式 51 router.get('/exchange/delivery', exchange.delivery); // AJAX 获取 退货方式
52 52
  53 +router.get('/mydetails', home.mydetails); // 个人信息设置
53 router.get('/about-us', home.aboutUs); // 个人中心 - 关于我们 54 router.get('/about-us', home.aboutUs); // 个人中心 - 关于我们
54 55
55 56
  1 +<div class="personal-details" id="details">
  2 + <mydetails gender="women" birthday="1990.07.17"></mydetails>
  3 +</div>
@@ -52,7 +52,7 @@ exports.fetchFilters = (req, res, next) => { @@ -52,7 +52,7 @@ exports.fetchFilters = (req, res, next) => {
52 .then(result => { 52 .then(result => {
53 let filterConfig = {}; 53 let filterConfig = {};
54 54
55 - if (result.code === 200) { 55 + if (result.code === 200 || !result.hasOwnProperty('code')) {
56 prettyFilter(result.data.filter); 56 prettyFilter(result.data.filter);
57 filterConfig = camelCase(result.data.filter); 57 filterConfig = camelCase(result.data.filter);
58 } 58 }
  1 +/**
  2 + * 产品搜索 controller
  3 + * @author 陈轩 <xuan.chen@yoho.cn>
  4 + */
  5 +'use strict';
  6 +
  7 +const newModel = require('../models/new');
  8 +
  9 +/* 最新商品 页面 */
  10 +exports.index = (req, res) => {
  11 + const view = {
  12 + module: 'product',
  13 + page: 'new'
  14 + };
  15 +
  16 + res.render('new', view);
  17 +};
  18 +
  19 +/* 获取 筛选配置 */
  20 +exports.fetchFilters = (req, res, next) => {
  21 + const params = Object.assign({
  22 + uid: req.user.uid,
  23 + page: 1,
  24 + order: 1,
  25 + yh_channel: 'all',
  26 + channel: 'all',
  27 + }, req.query);
  28 +
  29 + newModel.getNewData(params).then(result => {
  30 + res.json(result);
  31 + }).catch(next);
  32 +};
  33 +
  34 +/* 查询 产品列表 */
  35 +exports.fetchProducts = (req, res, next) => {
  36 + const params = Object.assign({
  37 + uid: req.user.uid,
  38 + page: 1,
  39 + order: 1
  40 + }, req.query);
  41 +
  42 + newModel.getNewData(params).catch(next);
  43 +};
  1 +const api = global.yoho.API;
  2 +const camelCase = global.yoho.camelCase;
  3 +const prettyFilter = require(`${global.utils}/beautify/filters`);
  4 +const processProductList = require(`${global.utils}/beautify/product`);
  5 +
  6 +/* 查询最新产品列表 */
  7 +exports.getNewData = (params) => {
  8 + params = Object.assign({
  9 + method: 'app.search.newProduct',
  10 + }, params);
  11 +
  12 + api.post('', params, {
  13 + cache: true,
  14 + code: 200
  15 + }).then(result => {
  16 + if (result.data) {
  17 + result.data.productList = processProductList(result.data.productList);
  18 + result = camelCase(result);
  19 + }
  20 +
  21 + return result;
  22 + });
  23 +};
  24 +
  25 +/* 查询最新产品筛选条件 */
  26 +exports.getNewFilterData = (params) => {
  27 + params = Object.assign({
  28 + method: 'app.search.newProduct',
  29 + }, params);
  30 +
  31 + api.post('', params, {
  32 + cache: true,
  33 + code: 200
  34 + }).then(result => {
  35 + let filterConfig = {};
  36 +
  37 + if (result.data) {
  38 + prettyFilter(result.data.filter);
  39 + filterConfig = camelCase(result.data.filter);
  40 + }
  41 +
  42 + return {
  43 + code: result.code,
  44 + data: filterConfig
  45 + };
  46 + });
  47 +};
@@ -17,12 +17,14 @@ const search = require(`${cRoot}/search`); @@ -17,12 +17,14 @@ const search = require(`${cRoot}/search`);
17 router.get('/search', search.index); 17 router.get('/search', search.index);
18 router.get('/search.json', search.fetchProducts); // ajax 18 router.get('/search.json', search.fetchProducts); // ajax
19 19
  20 +router.get('/new', search.index);
  21 +router.get('/new.json', search.fetchProducts);
20 22
21 // 产品 列表页 23 // 产品 列表页
22 const productList = require(`${cRoot}/list`); 24 const productList = require(`${cRoot}/list`);
23 25
24 router.get('/list', productList.index); 26 router.get('/list', productList.index);
25 -router.post('/list', productList.fetchProducts); 27 +router.get('/list.json', productList.fetchProducts);
26 router.get('/filter', productList.subFilter); 28 router.get('/filter', productList.subFilter);
27 router.get('/filters.json', productList.fetchFilters); 29 router.get('/filters.json', productList.fetchFilters);
28 30
1 {{! 筛选的 二级菜单}} 1 {{! 筛选的 二级菜单}}
2 <div id="filter-sub"> 2 <div id="filter-sub">
3 - <filter-sub :data="data" :val="val" type="color"><filter-sub> 3 + <filter-sub :data="data" :val="val" :type="type"><filter-sub>
4 </div> 4 </div>
  1 +<div id="product-new"></div>
@@ -15,8 +15,8 @@ module.exports = { @@ -15,8 +15,8 @@ module.exports = {
15 port: 6004, 15 port: 6004,
16 siteUrl: '//m.yohoblk.com', 16 siteUrl: '//m.yohoblk.com',
17 domains: { 17 domains: {
18 - api: 'http://192.168.102.205:8080/gateway/',  
19 - service: 'http://192.168.102.205:8080/gateway/' 18 + api: 'http://devapi.yoho.cn:58078/',
  19 + service: 'http://devservice.yoho.cn:58077/'
20 }, 20 },
21 subDomains: { 21 subDomains: {
22 host: '.m.yohoblk.com', 22 host: '.m.yohoblk.com',
@@ -7,9 +7,7 @@ require('common/vue-filter'); @@ -7,9 +7,7 @@ require('common/vue-filter');
7 7
8 Vue.use(lazyload); 8 Vue.use(lazyload);
9 9
10 -new Vue({  
11 - el: '#exchange',  
12 - components: {  
13 - exchange  
14 - }  
15 -}); 10 +new Vue(exchange);
  11 +
  12 +// Global variable: 全局常量 只允许读, 不允许写!!!!!!! exchange created的时候设置
  13 +global.store = {};
  1 +const Vue = require('yoho-vue');
  2 +const Mydetails = require('home/mydetails.vue');
  3 +
  4 +new Vue({
  5 + el: '#details',
  6 + components: {
  7 + Mydetails
  8 + }
  9 +});
@@ -3,12 +3,291 @@ const filterSub = require('component/product/filter/filter-sub.vue'); @@ -3,12 +3,291 @@ const filterSub = require('component/product/filter/filter-sub.vue');
3 3
4 // TODO: 该mock数据 应该有 上级页面传过来 4 // TODO: 该mock数据 应该有 上级页面传过来
5 const page = { 5 const page = {
6 - type: 'brand', // 二级筛选的 类型  
7 - data: [ // 二级筛选的 数据  
8 - { id: 1, name: '红色' },  
9 - { id: 2, name: '红色' },  
10 - { id: 3, name: '红色' }  
11 - ], 6 +
  7 + // 二级筛选的 类型
  8 + type: 'brand',
  9 +
  10 + // data: [ // 二级筛选的 数据
  11 + // { id: 1, name: '红色' },
  12 + // { id: 2, name: '红色' },
  13 + // { id: 3, name: '红色' }
  14 + // ],
  15 + data: [{
  16 + domain: 'converse',
  17 + alif: 'C',
  18 + ico: 'http://img12.static.yhbimg.com/brandLogo/2015/12/09/14/02752d2839e7001a09ecf71dcc9a996387.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  19 + name: 'converse',
  20 + keyword: 'converse,街头,摇滚,百搭,朋克,简约,个性,自然,潮流,环保',
  21 + id: 27,
  22 + hotKeyword: 'converse',
  23 + isHot: 'Y',
  24 + nameEn: 'converse',
  25 + nameCn: '匡威'
  26 + }, {
  27 + domain: 'eightguys',
  28 + alif: 'E',
  29 + ico: 'http://img11.static.yhbimg.com/brandLogo/2013/07/02/19/01959c3b33245e16e786bda6b1e91234be.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  30 + name: 'Eight Guys',
  31 + keyword: '8Guys,八个男人',
  32 + id: 396,
  33 + hotKeyword: '',
  34 + isHot: 'Y',
  35 + nameEn: 'eight guys',
  36 + nameCn: 'Eight Guys'
  37 + }, {
  38 + domain: 'soulandsole',
  39 + alif: 'S',
  40 + ico: 'http://img13.static.yhbimg.com/brandLogo/2014/01/27/11/02cfe4044dfb82230c1868211b814d6192.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  41 + name: 'SOUL&SOLE',
  42 + keyword: '',
  43 + id: 335,
  44 + hotKeyword: '',
  45 + isHot: '',
  46 + nameEn: 'SOUL&SOLE ',
  47 + nameCn: 'SOUL&SOLE '
  48 + }, {
  49 + domain: 'thething',
  50 + alif: 'T',
  51 + ico: 'http://img11.static.yhbimg.com/brandLogo/2015/12/09/16/018d25bf4481ed2998bf33b294673a8535.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  52 + name: 'THETHING',
  53 + keyword: 'thething,tee,polo,衬衫,裤类,包类,配件类',
  54 + id: 138,
  55 + hotKeyword: 'thething',
  56 + isHot: 'Y',
  57 + nameEn: 'THETHING',
  58 + nameCn: 'THETHING'
  59 + }, {
  60 + domain: 'roxy',
  61 + alif: 'R',
  62 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  63 + name: 'Roxy',
  64 + keyword: 'roxy',
  65 + id: 273,
  66 + hotKeyword: '',
  67 + isHot: '',
  68 + nameEn: 'Roxy',
  69 + nameCn: 'Roxy'
  70 + }, {
  71 + domain: 'roxy',
  72 + alif: 'R',
  73 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  74 + name: 'Roxy',
  75 + keyword: 'roxy',
  76 + id: 273,
  77 + hotKeyword: '',
  78 + isHot: '',
  79 + nameEn: 'Roxy',
  80 + nameCn: 'Roxy'
  81 + }, {
  82 + domain: 'roxy',
  83 + alif: 'R',
  84 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  85 + name: 'Roxy',
  86 + keyword: 'roxy',
  87 + id: 273,
  88 + hotKeyword: '',
  89 + isHot: '',
  90 + nameEn: 'Roxy',
  91 + nameCn: 'Roxy'
  92 + }, {
  93 + domain: 'roxy',
  94 + alif: 'R',
  95 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  96 + name: 'Roxy',
  97 + keyword: 'roxy',
  98 + id: 273,
  99 + hotKeyword: '',
  100 + isHot: '',
  101 + nameEn: 'Roxy',
  102 + nameCn: 'Roxy'
  103 + }, {
  104 + domain: 'roxy',
  105 + alif: 'R',
  106 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  107 + name: 'Roxy',
  108 + keyword: 'roxy',
  109 + id: 273,
  110 + hotKeyword: '',
  111 + isHot: '',
  112 + nameEn: 'Roxy',
  113 + nameCn: 'Roxy'
  114 + }, {
  115 + domain: 'roxy',
  116 + alif: 'R',
  117 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  118 + name: 'Roxy',
  119 + keyword: 'roxy',
  120 + id: 273,
  121 + hotKeyword: '',
  122 + isHot: '',
  123 + nameEn: 'Roxy',
  124 + nameCn: 'Roxy'
  125 + }, {
  126 + domain: 'roxy',
  127 + alif: 'R',
  128 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  129 + name: 'Roxy',
  130 + keyword: 'roxy',
  131 + id: 273,
  132 + hotKeyword: '',
  133 + isHot: '',
  134 + nameEn: 'Roxy',
  135 + nameCn: 'Roxy'
  136 + }, {
  137 + domain: 'roxy',
  138 + alif: 'R',
  139 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  140 + name: 'Roxy',
  141 + keyword: 'roxy',
  142 + id: 273,
  143 + hotKeyword: '',
  144 + isHot: '',
  145 + nameEn: 'Roxy',
  146 + nameCn: 'Roxy'
  147 + }, {
  148 + domain: 'roxy',
  149 + alif: 'R',
  150 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  151 + name: 'Roxy',
  152 + keyword: 'roxy',
  153 + id: 273,
  154 + hotKeyword: '',
  155 + isHot: '',
  156 + nameEn: 'Roxy',
  157 + nameCn: 'Roxy'
  158 + }, {
  159 + domain: 'roxy',
  160 + alif: 'R',
  161 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  162 + name: 'Roxy',
  163 + keyword: 'roxy',
  164 + id: 273,
  165 + hotKeyword: '',
  166 + isHot: '',
  167 + nameEn: 'Roxy',
  168 + nameCn: 'Roxy'
  169 + }, {
  170 + domain: 'roxy',
  171 + alif: 'R',
  172 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  173 + name: 'Roxy',
  174 + keyword: 'roxy',
  175 + id: 273,
  176 + hotKeyword: '',
  177 + isHot: '',
  178 + nameEn: 'Roxy',
  179 + nameCn: 'Roxy'
  180 + }, {
  181 + domain: 'roxy',
  182 + alif: 'R',
  183 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  184 + name: 'Roxy',
  185 + keyword: 'roxy',
  186 + id: 273,
  187 + hotKeyword: '',
  188 + isHot: '',
  189 + nameEn: 'Roxy',
  190 + nameCn: 'Roxy'
  191 + }, {
  192 + domain: 'roxy',
  193 + alif: 'R',
  194 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  195 + name: 'Roxy',
  196 + keyword: 'roxy',
  197 + id: 273,
  198 + hotKeyword: '',
  199 + isHot: '',
  200 + nameEn: 'Roxy',
  201 + nameCn: 'Roxy'
  202 + }, {
  203 + domain: 'roxy',
  204 + alif: 'R',
  205 + ico: 'http://img12.static.yhbimg.com/brandLogo/2012/05/28/13/0242bc746fa4ddbc9519c14c3b769b6774.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  206 + name: 'Roxy',
  207 + keyword: 'roxy',
  208 + id: 273,
  209 + hotKeyword: '',
  210 + isHot: '',
  211 + nameEn: 'Roxy',
  212 + nameCn: 'Roxy'
  213 + }, {
  214 + domain: 'natkiel',
  215 + alif: 'N',
  216 + ico: 'http://img11.static.yhbimg.com/brandLogo/2015/11/17/10/01032e9fba6bc0770077f2c645bad46127.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  217 + name: 'Natkiel',
  218 + keyword: '奈凯儿',
  219 + id: 393,
  220 + hotKeyword: '',
  221 + isHot: 'N',
  222 + nameEn: 'Natkiel',
  223 + nameCn: 'Natkiel'
  224 + }, {
  225 + domain: 'natkiel',
  226 + alif: 'N',
  227 + ico: 'http://img11.static.yhbimg.com/brandLogo/2015/11/17/10/01032e9fba6bc0770077f2c645bad46127.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  228 + name: 'Natkiel',
  229 + keyword: '奈凯儿',
  230 + id: 393,
  231 + hotKeyword: '',
  232 + isHot: 'N',
  233 + nameEn: 'Natkiel',
  234 + nameCn: 'Natkiel'
  235 + }, {
  236 + domain: 'natkiel',
  237 + alif: 'N',
  238 + ico: 'http://img11.static.yhbimg.com/brandLogo/2015/11/17/10/01032e9fba6bc0770077f2c645bad46127.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  239 + name: 'Natkiel',
  240 + keyword: '奈凯儿',
  241 + id: 393,
  242 + hotKeyword: '',
  243 + isHot: 'N',
  244 + nameEn: 'Natkiel',
  245 + nameCn: 'Natkiel'
  246 + }, {
  247 + domain: 'natkiel',
  248 + alif: 'N',
  249 + ico: 'http://img11.static.yhbimg.com/brandLogo/2015/11/17/10/01032e9fba6bc0770077f2c645bad46127.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  250 + name: 'Natkiel',
  251 + keyword: '奈凯儿',
  252 + id: 393,
  253 + hotKeyword: '',
  254 + isHot: 'N',
  255 + nameEn: 'Natkiel',
  256 + nameCn: 'Natkiel'
  257 + }, {
  258 + domain: 'natkiel',
  259 + alif: 'N',
  260 + ico: 'http://img11.static.yhbimg.com/brandLogo/2015/11/17/10/01032e9fba6bc0770077f2c645bad46127.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  261 + name: 'Natkiel',
  262 + keyword: '奈凯儿',
  263 + id: 393,
  264 + hotKeyword: '',
  265 + isHot: 'N',
  266 + nameEn: 'Natkiel',
  267 + nameCn: 'Natkiel'
  268 + }, {
  269 + domain: 'natkiel',
  270 + alif: 'N',
  271 + ico: 'http://img11.static.yhbimg.com/brandLogo/2015/11/17/10/01032e9fba6bc0770077f2c645bad46127.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  272 + name: 'Natkiel',
  273 + keyword: '奈凯儿',
  274 + id: 393,
  275 + hotKeyword: '',
  276 + isHot: 'N',
  277 + nameEn: 'Natkiel',
  278 + nameCn: 'Natkiel'
  279 + }, {
  280 + domain: 'natkiel',
  281 + alif: 'N',
  282 + ico: 'http://img11.static.yhbimg.com/brandLogo/2015/11/17/10/01032e9fba6bc0770077f2c645bad46127.jpg?imageMogr2/thumbnail/{width}x{height}/extent/{width}x{height}/background/d2hpdGU=/position/center/quality/80',
  283 + name: 'Natkiel',
  284 + keyword: '奈凯儿',
  285 + id: 393,
  286 + hotKeyword: '',
  287 + isHot: 'N',
  288 + nameEn: 'Natkiel',
  289 + nameCn: 'Natkiel'
  290 + }],
12 val: 3 // 二级筛选 的值 291 val: 3 // 二级筛选 的值
13 }; 292 };
14 293
@@ -25,5 +304,3 @@ new Vue({ @@ -25,5 +304,3 @@ new Vue({
25 filterSub 304 filterSub
26 } 305 }
27 }); 306 });
28 -  
29 -  
  1 +const Vue = require('yoho-vue');
  2 +const search = require('product/search/index.vue');
  3 +
  4 +new Vue(search);
  1 +.personal-details {
  2 + width: 100%;
  3 + height: auto;
  4 + overflow: hidden;
  5 + margin-top: 20px;
  6 + background-color: #fff;
  7 +
  8 + ul {
  9 + width: 95%;
  10 + height: auto;
  11 + overflow: hidden;
  12 + float: right;
  13 +
  14 + li {
  15 + &:first-of-type {
  16 + height: 100px;
  17 + line-height: 100px;
  18 + }
  19 +
  20 + height: 80px;
  21 + border-bottom: 1px solid #e0e0e0;
  22 +
  23 + .details-icon {
  24 + float: right;
  25 + height: 90px;
  26 + margin-right: 15px;
  27 +
  28 + .icon {
  29 + vertical-align: middle;
  30 + color: #b0b0b0;
  31 + }
  32 + }
  33 +
  34 + .user-avatar {
  35 + display: inline-block;
  36 + width: 100%;
  37 + height: 100%;
  38 + background-image: resolve("home/user-icon.png");
  39 + background-size: 100%;
  40 + }
  41 +
  42 + .head-portrait {
  43 + width: 90px;
  44 + height: 90px;
  45 + overflow: hidden;
  46 + border-radius: 50%;
  47 + border: 1px solid #eee;
  48 + vertical-align: middle;
  49 + }
  50 +
  51 + > label {
  52 + width: 100%;
  53 + height: 100%;
  54 + line-height: 80px;
  55 + font-size: 32px;
  56 + margin-right: 8%;
  57 + text-overflow: ellipsis;
  58 + white-space: nowrap;
  59 + overflow: hidden;
  60 + display: inline-block;
  61 +
  62 + .details-nickname,
  63 + .details-gender,
  64 + .details-birthday {
  65 + text-align: right;
  66 + float: right;
  67 + margin-right: 40px;
  68 + color: #b0b0b0;
  69 + }
  70 + }
  71 + }
  72 + }
  73 +}
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 @import "help"; 2 @import "help";
3 @import "feedback"; 3 @import "feedback";
4 @import "fav"; 4 @import "fav";
  5 +@import "details";
5 @import "about-us"; 6 @import "about-us";
6 @import "coin"; 7 @import "coin";
7 @import "logistics"; 8 @import "logistics";
@@ -36,7 +36,7 @@ @@ -36,7 +36,7 @@
36 $.ajax({ 36 $.ajax({
37 url: '/channel/channel.json' 37 url: '/channel/channel.json'
38 }).then(res => { 38 }).then(res => {
39 - if (res.data.length) { 39 + if (res.data && res.data.length) {
40 const channel = []; 40 const channel = [];
41 41
42 res.data.forEach(c => { 42 res.data.forEach(c => {
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 <feature-options name="size" :options="sizes" :selection="selection.size"></feature-options> 22 <feature-options name="size" :options="sizes" :selection="selection.size"></feature-options>
23 </section> 23 </section>
24 <button @click="addToCart()" 24 <button @click="addToCart()"
25 - class="button button-solid add-to-cart">加入购物袋 25 + class="button button-solid add-to-cart">{{config.btnTxt || '加入购物袋'}}
26 </button> 26 </button>
27 </div> 27 </div>
28 </div> 28 </div>
@@ -139,7 +139,9 @@ @@ -139,7 +139,9 @@
139 * 139 *
140 * @param result 后端返回的数据 140 * @param result 后端返回的数据
141 */ 141 */
142 - onAddToCart: Function 142 + onAddToCart: Function,
  143 +
  144 + config: Object
143 }, 145 },
144 watch: { 146 watch: {
145 isVisible() { 147 isVisible() {
@@ -283,7 +285,6 @@ @@ -283,7 +285,6 @@
283 */ 285 */
284 addToCart() { 286 addToCart() {
285 // console.log(`${this.selection.color}:${this.selection.size}`); 287 // console.log(`${this.selection.color}:${this.selection.size}`);
286 - const sku = this.selection.size;  
287 288
288 if (!this.selection.color) { 289 if (!this.selection.color) {
289 tip('请选择颜色'); 290 tip('请选择颜色');
@@ -295,12 +296,7 @@ @@ -295,12 +296,7 @@
295 return; 296 return;
296 } 297 }
297 298
298 - $.post('/product/cart.json', {  
299 - productSku: sku,  
300 - buyNumber: 1  
301 - }).then((result)=> {  
302 - this.onAddToCart(result);  
303 - }); 299 + this.onAddToCart(this.selection, this.entity.pid);
304 } 300 }
305 } 301 }
306 }; 302 };
@@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
9 <div class="item-inner">{{brand.name}}</div> 9 <div class="item-inner">{{brand.name}}</div>
10 </dd> 10 </dd>
11 </dl> 11 </dl>
  12 + <index-list :index-list="indexList"></index-list>
12 </div> 13 </div>
13 </template> 14 </template>
14 <script> 15 <script>
@@ -20,6 +21,7 @@ @@ -20,6 +21,7 @@
20 * } 21 * }
21 */ 22 */
22 const $ = require('yoho-jquery'); 23 const $ = require('yoho-jquery');
  24 + const indexList = require('component/tool/index-list.vue');
23 25
24 module.exports = { 26 module.exports = {
25 props: { 27 props: {
@@ -29,7 +31,7 @@ @@ -29,7 +31,7 @@
29 // 以brand.alif 分组 31 // 以brand.alif 分组
30 const res = {}; 32 const res = {};
31 33
32 - $.each(data, brand => { 34 + $.each(data, (index, brand) => {
33 let groupName = brand.alif; 35 let groupName = brand.alif;
34 36
35 if (!res.hasOwnProperty(groupName)) { 37 if (!res.hasOwnProperty(groupName)) {
@@ -38,6 +40,8 @@ @@ -38,6 +40,8 @@
38 res[groupName].push(brand); 40 res[groupName].push(brand);
39 41
40 }); 42 });
  43 +
  44 + return res;
41 } 45 }
42 } 46 }
43 }, 47 },
@@ -45,6 +49,22 @@ @@ -45,6 +49,22 @@
45 select: function(val) { 49 select: function(val) {
46 this.val = val; 50 this.val = val;
47 } 51 }
  52 + },
  53 + computed: {
  54 + indexList() {
  55 + var arr = [];
  56 +
  57 + $.each(this.data, (key, val) => {
  58 + arr.push({
  59 + index: key,
  60 + name: key
  61 + });
  62 + });
  63 + return arr;
  64 + }
  65 + },
  66 + components: {
  67 + indexList
48 } 68 }
49 }; 69 };
50 70
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 <div> 2 <div>
3 <brand-filter v-if="type === 'brand'" :data="data" :val.sync="val"></brand-filter> 3 <brand-filter v-if="type === 'brand'" :data="data" :val.sync="val"></brand-filter>
4 <normal-filter v-else :data="data" :val.sync="val"> 4 <normal-filter v-else :data="data" :val.sync="val">
  5 +
5 </normal-filter> 6 </normal-filter>
6 </div> 7 </div>
7 </template> 8 </template>
1 <template> 1 <template>
2 <div class="refund"> 2 <div class="refund">
3 <div class="title">请选择换货商品</div> 3 <div class="title">请选择换货商品</div>
4 - <!--商品列表-->  
5 - <product-list v-bind:list="goods" v-bind:data="exchangeData"></product-list> 4 + <div>
  5 + <exchange-item v-for="good in selectedGoods" :product="good"></exchange-item>
  6 + </div>
  7 + <div>
  8 + <product-list v-bind:list="goods" v-bind:data="exchangeData" type="exchange"></product-list>
  9 + </div>
6 <!--换货信息--> 10 <!--换货信息-->
7 <div class="list exchange-info"> 11 <div class="list exchange-info">
8 <!--address--> 12 <!--address-->
@@ -23,19 +27,34 @@ @@ -23,19 +27,34 @@
23 </select> 27 </select>
24 </div> 28 </div>
25 </div> 29 </div>
  30 + <feature-selector
  31 + :is-visible="showFeatureSelector"
  32 + :entity="entity"
  33 + :on-add-to-cart="whenFeatureChange"
  34 + :config="{btnTxt:'确定'}">
  35 + </feature-selector>
26 </div> 36 </div>
27 </template> 37 </template>
28 38
29 <script> 39 <script>
30 const $ = require('yoho-jquery'); 40 const $ = require('yoho-jquery');
31 const qs = require('yoho-qs'); 41 const qs = require('yoho-qs');
  42 + const bus = require('common/vue-bus');
32 43
33 - const productList = require('home/refund/product-list.vue'); 44 + const productList = require('home/return/list.vue');
  45 + const exchangeItem = require('home/exchange/item.vue');
  46 + const featureSelector = require('component/product/feature-selector.vue');
34 47
35 module.exports = { 48 module.exports = {
  49 + el: '#exchange',
36 data() { 50 data() {
37 return { 51 return {
38 title: '请选择换货商品', 52 title: '请选择换货商品',
  53 + page: 'exchange',
  54 + showFeatureSelector: false,
  55 + entity: {},
  56 + exchangeData: {},
  57 +
39 goods: [], 58 goods: [],
40 address: {}, 59 address: {},
41 delivery: [], 60 delivery: [],
@@ -57,7 +76,19 @@ @@ -57,7 +76,19 @@
57 }); 76 });
58 } 77 }
59 }, 78 },
  79 + events: {
  80 + 'feature.close': function() {
  81 + this.showFeatureSelector = false;
  82 + }
  83 + },
60 created() { 84 created() {
  85 + // 打开 更换 颜色尺码
  86 + bus.$on('open.featureSelector', msg => {
  87 + this.showFeatureSelector = true;
  88 + this.queryProductFeature(msg.pid);
  89 + });
  90 +
  91 + // 获取 换货商品
61 $.ajax({ 92 $.ajax({
62 url: '/home/exchange/order', 93 url: '/home/exchange/order',
63 data: { 94 data: {
@@ -68,7 +99,6 @@ @@ -68,7 +99,6 @@
68 99
69 if (res.data && res.data.goodsList) { 100 if (res.data && res.data.goodsList) {
70 res.data.goodsList.forEach((product, index) => { 101 res.data.goodsList.forEach((product, index) => {
71 - product.checked = false;  
72 product.reason = { 102 product.reason = {
73 id: 0 103 id: 0
74 }; 104 };
@@ -78,15 +108,45 @@ @@ -78,15 +108,45 @@
78 }); 108 });
79 109
80 this.goods = res.data.goodsList; 110 this.goods = res.data.goodsList;
81 - this.exchangeData = res.data; 111 + this.$set('exchangeData', res.data);
82 this.$set('address', res.data.address); 112 this.$set('address', res.data.address);
  113 +
  114 + // 全局只读变量 放入 全局对象
  115 + const arr = [];
  116 +
  117 + res.data.specialExchangeReason.forEach(obj => arr.push(obj.id));
  118 + global.store.reasons = [{
  119 + id: 0,
  120 + name: '请选择'
  121 + }].concat(res.data.exchangeReason);
  122 + global.store.specialReasons = arr;
  123 + global.store.specialNotice = res.data.specialNoticeBo;
83 } 124 }
84 }); 125 });
85 }, 126 },
86 methods: { 127 methods: {
87 - changeAddress: function() { 128 + changeAddress() {
88 alert('TODO:更换地址'); 129 alert('TODO:更换地址');
89 }, 130 },
  131 +
  132 + // 商品 feature改变
  133 + whenFeatureChange(selection, pid) {
  134 + const index = this.indexMap[pid];
  135 +
  136 + this.showFeatureSelector = false;
  137 + this.goods[index]._change = {
  138 +
  139 + };
  140 + },
  141 +
  142 + // 查询 商品 feature
  143 + queryProductFeature(pid) {
  144 + $.get(`/product/product_${pid}.json`).then(result => {
  145 + this.entity = result;
  146 + this.entity.id = pid;
  147 + return result;
  148 + });
  149 + },
90 submit() { 150 submit() {
91 if (!this.checkSubmitData()) { 151 if (!this.checkSubmitData()) {
92 alert('请填写完整退换货信息'); 152 alert('请填写完整退换货信息');
@@ -108,23 +168,26 @@ @@ -108,23 +168,26 @@
108 // area code 改变,重新获取 换货方式 168 // area code 改变,重新获取 换货方式
109 'address.areaCode': function(newVal, oldVal) { 169 'address.areaCode': function(newVal, oldVal) {
110 const self = this; 170 const self = this;
  171 +
111 $.get('/home/exchange/delivery', { 172 $.get('/home/exchange/delivery', {
112 - areaCode: newVal  
113 - })  
114 - .then(result => {  
115 - $.each(result.data, (index, obj) => {  
116 - if (obj.isDefault === 'Y') {  
117 - self.$set('deliveryType', obj.id);  
118 - return false;  
119 - }  
120 - });  
121 -  
122 - self.$set('delivery', result.data); 173 + areaCode: newVal
  174 + })
  175 + .then(result => {
  176 + $.each(result.data, (index, obj) => {
  177 + if (obj.isDefault === 'Y') {
  178 + self.$set('deliveryType', obj.id);
  179 + return false;
  180 + }
123 }); 181 });
  182 +
  183 + self.$set('delivery', result.data);
  184 + });
124 } 185 }
125 }, 186 },
126 components: { 187 components: {
127 - productList 188 + productList,
  189 + exchangeItem,
  190 + featureSelector
128 } 191 }
129 }; 192 };
130 193
  1 +<template>
  2 + <div class="return-form exchange-form">
  3 + <product :product="product"></product>
  4 + <div class="field" @click="openFeatureSelector(product.productId)">
  5 + 换货的颜色尺码
  6 + <div class="right">
  7 + <span></span>
  8 + <i class="icon icon-right"></i>
  9 + </div>
  10 + </div>
  11 + <reason :product="product">
  12 + <span slot="type">换货原因</span>
  13 + </reason>
  14 + </div>
  15 +</template>
  16 +<script>
  17 + /**
  18 + * exchange form
  19 + * 1. 产品信息
  20 + * 2. 更换产品 款式
  21 + * 3. 换货 原因
  22 + */
  23 + const product = require('home/return/item.vue');
  24 + const reason = require('home/return/reason.vue');
  25 + const bus = require('common/vue-bus');
  26 +
  27 + module.exports = {
  28 + props: {
  29 + product: Object,
  30 + readyonly: Boolean,
  31 + reasons: Array,
  32 + specialReason: Array
  33 + },
  34 + components: {
  35 + product,
  36 + reason
  37 + },
  38 + methods: {
  39 + openFeatureSelector(pid) {
  40 + bus.$emit('open.featureSelector', {
  41 + pid,
  42 + uid: this._uid
  43 + });
  44 + }
  45 + }
  46 + };
  47 +
  48 +</script>
  49 +<style>
  50 + .return-form {
  51 + .field {
  52 + position: relative;
  53 + height: 90px;
  54 + line-height: 90px;
  55 + padding: 0 30px;
  56 + background-color: #fff;
  57 + font-size: 32px;
  58 + &:after {
  59 + position: absolute;
  60 + z-index: 1;
  61 + content: "";
  62 + display: block;
  63 + right: 30px;
  64 + bottom: -1px;
  65 + left: 30px;
  66 + border-bottom: 1px solid #eee;
  67 + }
  68 + }
  69 + .field .right {
  70 + color: #b0b0b0;
  71 + }
  72 + }
  73 +
  74 +</style>
@@ -36,7 +36,7 @@ @@ -36,7 +36,7 @@
36 props: ['brandUrl'], 36 props: ['brandUrl'],
37 data() { 37 data() {
38 return { 38 return {
39 - nullbox : 'hide', 39 + nullbox: 'hide',
40 busy: false, 40 busy: false,
41 editmodel: false, 41 editmodel: false,
42 page: 0, 42 page: 0,
@@ -46,13 +46,13 @@ @@ -46,13 +46,13 @@
46 methods: { 46 methods: {
47 loadMore: function() { 47 loadMore: function() {
48 let _this = this; 48 let _this = this;
49 - this.busy = true;  
50 49
  50 + this.busy = true;
51 $.ajax({ 51 $.ajax({
52 url: '/home/favorite/favpaging', 52 url: '/home/favorite/favpaging',
53 data: { 53 data: {
54 - page : ++_this.page,  
55 - tab : "brand" 54 + page: ++_this.page,
  55 + tab: 'brand'
56 } 56 }
57 }).then(result => { 57 }).then(result => {
58 if (result.isend) { 58 if (result.isend) {
@@ -62,12 +62,12 @@ @@ -62,12 +62,12 @@
62 } 62 }
63 63
64 if (result.list.length) { 64 if (result.list.length) {
65 - result.list.forEach(function(o){ 65 + result.list.forEach(function(o) {
66 _this.brandData.push(o); 66 _this.brandData.push(o);
67 }); 67 });
68 } 68 }
69 69
70 - _this.nullbox = _this.brandData.length ? "hide" : ""; 70 + _this.nullbox = _this.brandData.length ? 'hide' : '';
71 }).fail(() => { 71 }).fail(() => {
72 tip('网络错误'); 72 tip('网络错误');
73 }); 73 });
@@ -80,17 +80,19 @@ @@ -80,17 +80,19 @@
80 }, 80 },
81 showDelBtn(index) { 81 showDelBtn(index) {
82 this.hideDelBth(); 82 this.hideDelBth();
83 - var delBtn = $("#del-" + index);  
84 - var width = delBtn.width();  
85 - $("#li-" + index).css("transform","translateX(-" + width + "px)"); 83 + let delBtn = $('#del-' + index);
  84 + let width = delBtn.width();
  85 +
  86 + $('#li-' + index).css('transform', 'translateX(-' + width + 'px)');
86 }, 87 },
87 hideDelBth() { 88 hideDelBth() {
88 - this.brandData.forEach(function(d, index){  
89 - $("#li-" + index).css("transform","translateX(0px)");  
90 - }) 89 + this.brandData.forEach(function(d, index) {
  90 + $('#li-' + index).css('transform', 'translateX(0px)');
  91 + });
91 }, 92 },
92 delItem(index, id) { 93 delItem(index, id) {
93 let _this = this; 94 let _this = this;
  95 +
94 $.ajax({ 96 $.ajax({
95 method: 'POST', 97 method: 'POST',
96 url: '/home/del-favdel', 98 url: '/home/del-favdel',
@@ -44,7 +44,7 @@ @@ -44,7 +44,7 @@
44 props: ['productUrl'], 44 props: ['productUrl'],
45 data() { 45 data() {
46 return { 46 return {
47 - nullbox : 'hide', 47 + nullbox: 'hide',
48 busy: false, 48 busy: false,
49 editmodel: false, 49 editmodel: false,
50 page: 0, 50 page: 0,
@@ -54,12 +54,12 @@ @@ -54,12 +54,12 @@
54 methods: { 54 methods: {
55 loadMore: function() { 55 loadMore: function() {
56 let _this = this; 56 let _this = this;
57 - this.busy = true;  
58 57
  58 + this.busy = true;
59 $.ajax({ 59 $.ajax({
60 url: '/home/favorite/favpaging', 60 url: '/home/favorite/favpaging',
61 data: { 61 data: {
62 - page : ++_this.page 62 + page: ++_this.page
63 } 63 }
64 }).then(result => { 64 }).then(result => {
65 if (result.isend) { 65 if (result.isend) {
@@ -69,12 +69,12 @@ @@ -69,12 +69,12 @@
69 } 69 }
70 70
71 if (result.list.length) { 71 if (result.list.length) {
72 - result.list.forEach(function(o){ 72 + result.list.forEach(function(o) {
73 _this.productData.push(o); 73 _this.productData.push(o);
74 }); 74 });
75 } 75 }
76 76
77 - _this.nullbox = _this.productData.length ? "hide" : ""; 77 + _this.nullbox = _this.productData.length ? 'hide' : '';
78 }).fail(() => { 78 }).fail(() => {
79 tip('网络错误'); 79 tip('网络错误');
80 }); 80 });
@@ -87,17 +87,19 @@ @@ -87,17 +87,19 @@
87 }, 87 },
88 showDelBtn(index) { 88 showDelBtn(index) {
89 this.hideDelBth(); 89 this.hideDelBth();
90 - var delBtn = $("#del-" + index);  
91 - var width = delBtn.width();  
92 - $("#li-" + index).css("transform","translateX(-" + width + "px)"); 90 + let delBtn = $('#del-' + index);
  91 + let width = delBtn.width();
  92 +
  93 + $('#li-' + index).css('transform', 'translateX(-' + width + 'px)');
93 }, 94 },
94 hideDelBth() { 95 hideDelBth() {
95 - this.productData.forEach(function(d, index){  
96 - $("#li-" + index).css("transform","translateX(0px)");  
97 - }) 96 + this.productData.forEach(function(d, index) {
  97 + $('#li-' + index).css('transform', 'translateX(0px)');
  98 + });
98 }, 99 },
99 delItem(index, id) { 100 delItem(index, id) {
100 let _this = this; 101 let _this = this;
  102 +
101 $.ajax({ 103 $.ajax({
102 method: 'POST', 104 method: 'POST',
103 url: '/home/del-favdel', 105 url: '/home/del-favdel',
  1 +<template>
  2 + <ul>
  3 + <li>
  4 + <label>头像
  5 + <span class="details-icon">
  6 + <span class="head-portrait user-avatar" data-avatar="{{head_ico}}"></span>
  7 + <span class="icon icon-right"></span>
  8 + </span>
  9 + </label>
  10 + </li>
  11 + <li>
  12 + <label>昵称<input class="details-nickname" v-model='nickname'></label>
  13 + </li>
  14 + <li>
  15 + <label>性别<span class="details-gender">{{ gender }}</span></label>
  16 + </li>
  17 + <li>
  18 + <label>生日<span class="details-birthday">{{ birthday }}</span></label>
  19 + </li>
  20 + </ul>
  21 +</template>
  22 +
  23 +<script>
  24 + module.exports = {
  25 + props: ['head_ico', 'nickname', 'gender', 'birthday'],
  26 + data() {
  27 + return {
  28 + };
  29 + }
  30 + };
  31 +</script>
1 <template> 1 <template>
2 <div class="refund"> 2 <div class="refund">
3 <div class="title">请选择退货商品</div> 3 <div class="title">请选择退货商品</div>
4 - <product-list v-bind:list="list" v-bind:refund-data="refundData"></product-list> 4 + <product-list v-bind:list="list" v-bind:data="refundData"></product-list>
5 <div class="return-amount"> 5 <div class="return-amount">
6 <!-- TODO:退货信息优化为组件 --> 6 <!-- TODO:退货信息优化为组件 -->
7 <div class="return-amount-item"> 7 <div class="return-amount-item">
@@ -110,7 +110,7 @@ @@ -110,7 +110,7 @@
110 } 110 }
111 }); 111 });
112 this.list = res.data.goodsList; 112 this.list = res.data.goodsList;
113 - this.refundData = res.data; 113 + this.$set('refundData', res.data);
114 } 114 }
115 }); 115 });
116 }, 116 },
@@ -14,7 +14,6 @@ @@ -14,7 +14,6 @@
14 </template> 14 </template>
15 15
16 <script> 16 <script>
17 - const $ = require('yoho-jquery');  
18 const indexList = require('component/tool/index-list.vue'); 17 const indexList = require('component/tool/index-list.vue');
19 18
20 module.exports = { 19 module.exports = {
@@ -31,28 +30,32 @@ @@ -31,28 +30,32 @@
31 }, 30 },
32 methods: { 31 methods: {
33 search: function() { 32 search: function() {
34 - var inputname = this.inputname; 33 + let inputname = this.inputname;
  34 +
35 if (!inputname) { 35 if (!inputname) {
36 this.showData = this.company_list; 36 this.showData = this.company_list;
37 return; 37 return;
38 } 38 }
39 39
40 - var filter = {};  
41 - for (var k in this.company_list) {  
42 - this.company_list[k].forEach(function(d){ 40 + let filter = {};
  41 +
  42 + for (let k in this.company_list) {
  43 + this.company_list[k].forEach(function(d) {
43 if (d.company_name.indexOf(inputname) > -1) { 44 if (d.company_name.indexOf(inputname) > -1) {
44 - if (!filter[k]) filter[k] = []; 45 + if (!filter[k]) {
  46 + filter[k] = [];
  47 + }
45 filter[k].push(d); 48 filter[k].push(d);
46 } 49 }
47 - }) 50 + });
48 } 51 }
49 this.showData = filter; 52 this.showData = filter;
50 }, 53 },
51 - select: function(company_id, company_name) { 54 + select: function(companyId, companyName) {
52 this.$dispatch('changeView', { 55 this.$dispatch('changeView', {
53 view: 'logistics', 56 view: 'logistics',
54 - company_id: company_id,  
55 - company_name: company_name 57 + company_id: companyId,
  58 + company_name: companyName
56 }); 59 });
57 60
58 // 重置列表 61 // 重置列表
@@ -26,19 +26,19 @@ @@ -26,19 +26,19 @@
26 }; 26 };
27 }, 27 },
28 methods: { 28 methods: {
29 - companylist: function(){ 29 + companylist: function() {
30 this.$dispatch('changeView', { 30 this.$dispatch('changeView', {
31 view: 'logisticsCompany' 31 view: 'logisticsCompany'
32 }); 32 });
33 }, 33 },
34 - submit: function(){ 34 + submit: function() {
35 if (!this.company_name) { 35 if (!this.company_name) {
36 - tip("请选择快递公司"); 36 + tip('请选择快递公司');
37 return false; 37 return false;
38 } 38 }
39 if (!this.num || !/^[0-9]*$/.test(this.num)) { 39 if (!this.num || !/^[0-9]*$/.test(this.num)) {
40 - tip("请输入正确的快递单号");  
41 - return false; 40 + tip('请输入正确的快递单号');
  41 + return false;
42 } 42 }
43 43
44 $.ajax({ 44 $.ajax({
@@ -50,7 +50,7 @@ @@ -50,7 +50,7 @@
50 num: this.num 50 num: this.num
51 } 51 }
52 }).then(function(res) { 52 }).then(function(res) {
53 - if ($.type(res) !== 'object') { 53 + if ($.type(res) !== 'object') {
54 res = {}; 54 res = {};
55 } 55 }
56 if (res.code !== 200) { 56 if (res.code !== 200) {
@@ -67,4 +67,4 @@ @@ -67,4 +67,4 @@
67 } 67 }
68 }; 68 };
69 69
70 -</script>  
  70 +</script>
@@ -139,7 +139,7 @@ @@ -139,7 +139,7 @@
139 border-bottom: 1px solid #eee; 139 border-bottom: 1px solid #eee;
140 } 140 }
141 141
142 - span, 142 + .icon,
143 select { 143 select {
144 direction: rtl; 144 direction: rtl;
145 float: right; 145 float: right;
  1 +<template>
  2 + <div>
  3 + <product></product>
  4 + </div>
  5 +</template>
  1 +# 退换货 业务组件的 公用组件
  2 +* item.vue
  3 +* list.vue 退换货 申请的中间部分
  4 +* reason.vue 退换货 原因
  1 +<template>
  2 + <div class="product clearfix">
  3 + <div class="checkbox">
  4 + <input type="checkbox" v-model="product.checked" id="checkbox-{{product.goodsId}}">
  5 + <label for="checkbox-{{product.goodsId}}"></label>
  6 + </div>
  7 + <img class="image" v-bind:src="product.goodsImage | resize 100 130">
  8 + <div class="info">
  9 + <div class="p-title">
  10 + {{product.productName}}{{product.productName}}{{product.productName}}{{product.productName}}
  11 + </div>
  12 + <div class="meta">
  13 + <span class="color">颜色: {{product.colorName}}</span>
  14 + <span class="size">尺码: {{product.sizeName}}</span>
  15 + </div>
  16 + </div>
  17 + <div class="price">
  18 + &yen;{{product.lastPrice}}
  19 + <p class="num">
  20 + x1
  21 + </p>
  22 + </div>
  23 + </div>
  24 +</template>
  25 +
  26 +<script>
  27 + const reason = require('home/refund/reason.vue');
  28 +
  29 + module.exports = {
  30 + props: {
  31 + product: Object
  32 + },
  33 + components: {
  34 + reason
  35 + },
  36 +
  37 + created() {
  38 + // 经过该组件, 给product 添加 checked属性
  39 + if (!this.product.hasOwnProperty('checked')) {
  40 + this.$set('product.checked', false);
  41 + }
  42 + }
  43 + };
  44 +
  45 +</script>
  46 +
  47 +<style>
  48 + .product {
  49 + position: relative;
  50 + padding: 0 30px;
  51 + height: 170px;
  52 + font-size: 24px;
  53 + line-height: 1.5;
  54 + background: #fff;
  55 + &:after {
  56 + content: "";
  57 + position: absolute;
  58 + left: 30px;
  59 + bottom: -1px;
  60 + width: 690px;
  61 + height: 0;
  62 + border-bottom: 1px solid #eee;
  63 + z-index: 1;
  64 + }
  65 + .checkbox {
  66 + float: left;
  67 + margin-top: 67px;
  68 + label:before {
  69 + border-radius: 100%;
  70 + }
  71 + }
  72 + .image {
  73 + float: left;
  74 + margin: 20px;
  75 + width: 100px;
  76 + height: 130px;
  77 + }
  78 + .info {
  79 + padding: 15px 0;
  80 + width: 520px;
  81 + .p-title {
  82 + color: #000;
  83 + font-size: 24px;
  84 + height: 72px;
  85 + overflow: hidden;
  86 + }
  87 + .meta {
  88 + margin-top: 10px;
  89 + color: #b0b0b0;
  90 + }
  91 + .color {
  92 + margin-right: 30px;
  93 + }
  94 + }
  95 + .price {
  96 + position: absolute;
  97 + top: 15px;
  98 + right: 30px;
  99 + text-align: right;
  100 + .num {
  101 + color: #b0b0b0;
  102 + }
  103 + }
  104 + }
  105 +
  106 +</style>
  1 +<template>
  2 + <div>
  3 + <div v-show="checkedList.length" class="product-list product-list-checked">
  4 + <div v-for="product in list" v-if="product.checked">
  5 + <component :is = 'selectView' v-for="product in list" v-if="product.checked" v-bind:product="product" v-bind:data="data"></component>
  6 + </div>
  7 + </div>
  8 + <div v-show="checkedList.length !== list.length" class="product-list">
  9 + <pruduct v-for="product in list" v-if="!product.checked" v-bind:product="product" v-bind:data="data"></pruduct>
  10 + </div>
  11 + </div>
  12 +</template>
  13 +
  14 +<script>
  15 + const pruduct = require('home/return/item.vue');
  16 + const exchangeItem = require('home/exchange/item.vue');
  17 + const refundItem = require('home/refund/product-list.vue');
  18 +
  19 + module.exports = {
  20 + props: ['list', 'data', 'type'],
  21 + data() {
  22 + return {};
  23 + },
  24 + computed: {
  25 + selectedView() {
  26 + return this.type === 'exchange' ? 'exchange-item' : 'refund-item';
  27 + },
  28 + checkedList() {
  29 + return this.list.filter(product => {
  30 + return product.checked;
  31 + });
  32 + }
  33 + },
  34 + components: {
  35 + pruduct,
  36 + exchangeItem,
  37 + refundItem
  38 + }
  39 + };
  40 +
  41 +</script>
  42 +
  43 +<style>
  44 + .title {
  45 + padding: 30px 30px 0;
  46 + color: #b0b0b0;
  47 + font-size: 28px;
  48 + line-height: 60px;
  49 + }
  50 +
  51 + .product-list {
  52 + margin-top: -4px;
  53 + border-top: 1px solid #eee;
  54 + border-bottom: 1px solid #eee;
  55 + }
  56 +
  57 +</style>
  1 +<template>
  2 + <div v-if="product.checked" class="reason">
  3 + <div v-if="product.isLimitSkn === 'Y'" v-on:click="showTip" class="tip">
  4 + <span class="icon icon-love"></span>
  5 + {{specialNotice.title}}
  6 + </div>
  7 + <div class="select-reason">
  8 + <slot name="type">退货原因</slot>
  9 +
  10 + <span class="icon icon-right"></span>
  11 + <select v-model="product.reason.id" name="reason">
  12 + <option v-for="reason in reasons" v-bind:value="reason.id" selected="{{reason.id === product.reason.id}}">{{reason.name}}</option>
  13 + </select>
  14 + </div>
  15 + <div class="remark">
  16 + <textarea v-model="product.remark" rows="3" max-length="100" placeholder="原因说明"></textarea>
  17 + </div>
  18 + <div v-show="specialReasons.indexOf(product.reason.id) !== -1" class="image-list clearfix">
  19 + <div class="image-item" v-for="image in imageListForShow">
  20 + <span v-on:click="deleteImage(image.index)" class="icon icon-close"></span>
  21 + <img v-bind:src="image.path">
  22 + </div>
  23 + <upload v-show="imageListForShow.length < 4" class="image-item" v-bind:image-list="product.imageList"></upload>
  24 + </div>
  25 + </div>
  26 +</template>
  27 +
  28 +<script>
  29 + const upload = require('component/tool/upload.vue');
  30 +
  31 + const getImgHost = function(url) {
  32 + let urlArr = url.split('/'),
  33 + num = urlArr[urlArr.length - 1].substr(1, 1),
  34 + domain = 'static.yhbimg.com/goodsimg';
  35 +
  36 + url = domain + url;
  37 + if (num === '1') {
  38 + return '//img11.' + url;
  39 + } else {
  40 + return '//img12.' + url;
  41 + }
  42 + };
  43 +
  44 + module.exports = {
  45 + props: ['product', 'data'],
  46 + data() {
  47 + return {
  48 + reasons: [],
  49 + specialReasons: [],
  50 + specialNoticeBo: {}
  51 + };
  52 + },
  53 + computed: {
  54 + imageListForShow() {
  55 + const list = [];
  56 +
  57 + this.product.imageList.forEach((path, index) => {
  58 + list.push({
  59 + index: index,
  60 + path: getImgHost(path) + '?imageView2/2/w/160/h/160'
  61 + });
  62 + });
  63 +
  64 + return list;
  65 + }
  66 + },
  67 + methods: {
  68 + showTip() {
  69 + alert(this.specialNotice.remark);
  70 + },
  71 + deleteImage(index) {
  72 + this.product.imageList.splice(index, 1);
  73 + }
  74 + },
  75 + components: {
  76 + upload
  77 + },
  78 +
  79 + created() {
  80 + this.$set('reasons', global.store.reasons);
  81 + this.$set('specialReasons', global.store.specialReasons);
  82 + this.$set('specialNoticeBo', global.store.specialNoticeBo);
  83 + }
  84 + };
  85 +
  86 +</script>
  87 +
  88 +<style>
  89 + .reason {
  90 + font-size: 32px;
  91 + line-height: 90px;
  92 + background: #f6f6f6;
  93 + &:after {
  94 + content: "";
  95 + display: block;
  96 + width: 100%;
  97 + height: 30px;
  98 + border-top: 1px solid #eee;
  99 + border-bottom: 1px solid #eee;
  100 + }
  101 + .tip {
  102 + position: relative;
  103 + padding: 0 30px;
  104 + font-size: 26px;
  105 + background: #fff;
  106 + .icon {
  107 + margin-right: 5px;
  108 + }
  109 + &:after {
  110 + content: "";
  111 + position: absolute;
  112 + left: 0;
  113 + bottom: -1px;
  114 + width: 690px;
  115 + height: 0;
  116 + border-bottom: 1px solid #eee;
  117 + }
  118 + }
  119 + .select-reason {
  120 + position: relative;
  121 + padding: 0 30px;
  122 + width: 100%;
  123 + height: 90px;
  124 + background: #fff;
  125 + &:after {
  126 + content: "";
  127 + position: absolute;
  128 + left: 0;
  129 + bottom: -1px;
  130 + width: 690px;
  131 + height: 0;
  132 + border-bottom: 1px solid #eee;
  133 + }
  134 + .icon,
  135 + select {
  136 + direction: rtl;
  137 + float: right;
  138 + height: 90px;
  139 + line-height: 90px;
  140 + color: #b0b0b0;
  141 + }
  142 + }
  143 + .remark {
  144 + margin-top: 20px;
  145 + padding: 0 30px;
  146 + background: #fff;
  147 + border-top: 1px solid #eee;
  148 + textarea {
  149 + margin-top: 30px;
  150 + width: 100%;
  151 + font-size: 24px;
  152 + line-height: 40px;
  153 + resize: none;
  154 + border: 0;
  155 + }
  156 + }
  157 + .image-list {
  158 + padding: 30px;
  159 + background: #fff;
  160 + .image-item {
  161 + position: relative;
  162 + float: left;
  163 + margin-right: 20px;
  164 + width: 150px;
  165 + height: 150px;
  166 + &:last-child {
  167 + margin-right: 0;
  168 + }
  169 + .icon-close {
  170 + position: absolute;
  171 + right: -20px;
  172 + top: -20px;
  173 + font-size: 40px;
  174 + color: #fff;
  175 + background: #b0b0b0;
  176 + border-radius: 100%;
  177 + z-index: 2;
  178 + }
  179 + img {
  180 + width: 100%;
  181 + height: 100%;
  182 + }
  183 + }
  184 + .label-input {
  185 + position: relative;
  186 + width: 150px;
  187 + height: 150px;
  188 + font-size: 150px;
  189 + &:before {
  190 + content: "\e604";
  191 + }
  192 + input {
  193 + position: absolute;
  194 + left: 0;
  195 + top: 0;
  196 + width: 0;
  197 + height: 0;
  198 + opacity: 0;
  199 + }
  200 + }
  201 + }
  202 + }
  203 +
  204 +</style>
@@ -412,16 +412,21 @@ @@ -412,16 +412,21 @@
412 * 412 *
413 * @param result 413 * @param result
414 */ 414 */
415 - onAddToCart: (result)=> {  
416 - // TODO: 库存不足 后台暂未实现  
417 - // TODO: 商品已下架 后台暂未实现  
418 - if (result.code === 200) {  
419 - this.cartCount = result.data.goods_count;  
420 - this.showFeatureSelector = false;  
421 - } else {  
422 - this.showFeatureSelector = false;  
423 - tip('系统异常,请稍后重试');  
424 - } 415 + onAddToCart: (selection)=> {
  416 + $.post('/product/cart.json', {
  417 + productSku: selection.size,
  418 + buyNumber: 1
  419 + }).then((result)=> {
  420 + // TODO: 库存不足 后台暂未实现
  421 + // TODO: 商品已下架 后台暂未实现
  422 + if (result.code === 200) {
  423 + this.cartCount = result.data.goods_count;
  424 + this.showFeatureSelector = false;
  425 + } else {
  426 + this.showFeatureSelector = false;
  427 + tip('系统异常,请稍后重试');
  428 + }
  429 + });
425 } 430 }
426 }; 431 };
427 }, 432 },
@@ -32,7 +32,7 @@ @@ -32,7 +32,7 @@
32 filterConfig: global.filterConfig, 32 filterConfig: global.filterConfig,
33 33
34 // query 34 // query
35 - url: 'search', 35 + url: '/product/list.json',
36 sort: null, 36 sort: null,
37 filter: {}, 37 filter: {},
38 page: 0, // 未搜索 page=0; 全部加载完 page = totalPage; 无数据: page !=0 && productList.length=0 38 page: 0, // 未搜索 page=0; 全部加载完 page = totalPage; 无数据: page !=0 && productList.length=0
@@ -67,7 +67,7 @@ @@ -67,7 +67,7 @@
67 67
68 this.inSearching = true; 68 this.inSearching = true;
69 console.log(nextPage); 69 console.log(nextPage);
70 - $.post(this.url, { 70 + $.get(this.url, {
71 sort: this.sort, 71 sort: this.sort,
72 filter: this.filter, 72 filter: this.filter,
73 page: nextPage 73 page: nextPage
@@ -118,8 +118,11 @@ @@ -118,8 +118,11 @@
118 self.search(); 118 self.search();
119 }); 119 });
120 120
121 - bus.$on('sort.change', function({ val }) {  
122 - console.log(val); self.sort = val; 121 + bus.$on('sort.change', function({
  122 + val
  123 + }) {
  124 + console.log(val);
  125 + self.sort = val;
123 }); 126 });
124 127
125 /** 128 /**
@@ -140,7 +143,9 @@ @@ -140,7 +143,9 @@
140 * 1. 打开view 143 * 1. 打开view
141 * 2. 监听 router.back ,重新设置 筛选值 144 * 2. 监听 router.back ,重新设置 筛选值
142 */ 145 */
143 - bus.$on('filter.sub.show', function({val}) { 146 + bus.$on('filter.sub.show', function({
  147 + val
  148 + }) {
144 self.openFilterSub(val); 149 self.openFilterSub(val);
145 }); 150 });
146 151
@@ -150,4 +155,6 @@ @@ -150,4 +155,6 @@
150 155
151 </script> 156 </script>
152 <style> 157 <style>
  158 +
  159 +
153 </style> 160 </style>
  1 +<template>
  2 + <div>
  3 + <template v-if="productList.length">
  4 + <Sort :config="sortConfig" :val="sort">
  5 + </Sort>
  6 + <List :data="productList"></List>
  7 + </template>
  8 + <div class="empty-tip" v-if="empty">
  9 + <i class="icon icon-search"></i>
  10 + <p class="empty-tip-cn">未找到相关商品</p>
  11 + <p class="empty-tip-en">Did not find the relevant goods</p>
  12 + </div>
  13 + </div>
  14 +</template>
  15 +<script>
  16 + const Vue = require('yoho-vue');
  17 + const lazyload = require('yoho-vue-lazyload');
  18 + const infinitScroll = require('yoho-vue-infinite-scroll');
  19 +
  20 + const qs = require('yoho-qs');
  21 + const bus = require('common/vue-bus');
  22 + const tip = require('common/tip');
  23 +
  24 + const sort = require('component/product/sort.vue');
  25 + const list = require('component/product/list.vue');
  26 +
  27 + Vue.use(lazyload);
  28 + Vue.use(infinitScroll);
  29 +
  30 + require('common/vue-filter');
  31 +
  32 + module.exports = {
  33 + el: '#product-new',
  34 + data: function() {
  35 + return {
  36 + sortConfig: global.sortConfig,
  37 + filterConfig: global.filterConfig,
  38 +
  39 + // query
  40 + url: '/product/search.json',
  41 + sort: null,
  42 + query: qs.query,
  43 + page: 0, // 未搜索 page=0; 全部加载完 page = totalPage; 无数据: page !=0 && productList.length=0
  44 + totalPage: null,
  45 +
  46 + // 产品列表
  47 + productList: [],
  48 +
  49 + // state
  50 + inSearching: false // 请求中
  51 + };
  52 + },
  53 + computed: {
  54 + // 无数据
  55 + empty: function() {
  56 + return this.page !== 0 && !this.productList.length;
  57 + }
  58 + },
  59 + components: {
  60 + list,
  61 + sort
  62 + },
  63 + methods: {
  64 + search: function() {
  65 + const self = this;
  66 + const nextPage = this.page + 1;
  67 +
  68 + if (this.inSearching) {
  69 + return;
  70 + }
  71 +
  72 + // page = 0, 始终执行搜索
  73 + if (this.page && nextPage > this.totalPage) {
  74 + return;
  75 + }
  76 +
  77 + this.inSearching = true;
  78 + console.log(nextPage);
  79 + $.get(this.url, {
  80 + order: this.sort, // 排序 信息
  81 + query: this.query,
  82 + page: nextPage
  83 + })
  84 + .done(res => {
  85 + if (res.code === 200) {
  86 + self.page = res.data.page;
  87 + self.totalPage = res.data.pageTotal;
  88 + self.$set('productList', self.productList.concat(res.data.productList));
  89 + }
  90 + })
  91 + .fail(() => {
  92 + tip('网络出错~');
  93 + })
  94 + .always(() => {
  95 + self.inSearching = false;
  96 + });
  97 + },
  98 +
  99 + /**
  100 + * 清空数据(page=0) 重新搜索
  101 + */
  102 + research: function() {
  103 + this.page = 0;
  104 + this.$set('productList', []);
  105 + this.search();
  106 + }
  107 + },
  108 + watch: {
  109 + /* sort 改变 都会触发 重新搜索 */
  110 + sort: function() {
  111 + this.research();
  112 + }
  113 + },
  114 +
  115 + created: function() {
  116 + const self = this;
  117 +
  118 +
  119 + bus.$on('list.paging', function() {
  120 + self.search();
  121 + });
  122 +
  123 + bus.$on('sort.change', function({
  124 + val
  125 + }) {
  126 + self.sort = val;
  127 + });
  128 +
  129 + this.search();
  130 + }
  131 + };
  132 +
  133 +</script>
  134 +<style>
  135 + .empty-tip {
  136 + margin-top: 380px;
  137 + color: #b0b0b0;
  138 + text-align: center;
  139 + .icon-search {
  140 + display: inline-block;
  141 + font-size: 200px;
  142 + margin-bottom: 56px;
  143 + }
  144 + }
  145 +
  146 + .empty-tip-cn {
  147 + font-size: 34px;
  148 + margin-bottom: 30px;
  149 + }
  150 +
  151 + .empty-tip-en {
  152 + font-size: 20px;
  153 + }
  154 +
  155 +</style>