Authored by ccbikai

Merge branch 'develop' into feature/channel

1 <div id="channel"> 1 <div id="channel">
2 - <tab v-bind:page="page"></tab>  
3 - <resources v-bind:content-code.sync="contentCode"></resources> 2 + <channel></channel>
4 </div> 3 </div>
@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 * @date: 2016/07/18 4 * @date: 2016/07/18
5 */ 5 */
6 'use strict'; 6 'use strict';
  7 +const homeModel = require('../models/index');
7 const _ = require('lodash'); 8 const _ = require('lodash');
8 const helpers = global.yoho.helpers; 9 const helpers = global.yoho.helpers;
9 10
@@ -12,20 +13,95 @@ const helpers = global.yoho.helpers; @@ -12,20 +13,95 @@ const helpers = global.yoho.helpers;
12 */ 13 */
13 const component = { 14 const component = {
14 index: (req, res, next) => { 15 index: (req, res, next) => {
15 - var testData = {  
16 - isLogin: false,  
17 - head_ico: '',  
18 - profile_name: 'XXX',  
19 - signinUrl: '/home',  
20 - wait_pay_num: 1,  
21 - wait_cargo_num: 2,  
22 - send_cargo_num: 3 16 + let uid = req.user.uid;
  17 + if (!uid && req.xhr) {
  18 + return res.json({
  19 + code: 400,
  20 + message: '抱歉,您暂未登录!'
  21 + });
  22 + }
  23 +
  24 + homeModel.getUserHomeData(uid).then(data => {
  25 + let result = {
  26 + module: 'home',
  27 + page: 'index',
  28 + head_ico: uid ? '' : '',
  29 + profile_name: uid ? 'James Sen' : '登录/注册',
  30 + userinfourl: uid ? '/home/mydetails' : helpers.urlFormat('/signin.html', {
  31 + refer: req.originalUrl
  32 + }),
  33 + };
  34 +
  35 + res.render('index', _.merge(result, data[1]));
  36 + }).catch(next);
  37 + },
  38 + help: (req, res, next) => {
  39 + homeModel.getHelpInfo().then(helpList => {
  40 + res.render('help', {
  41 + module: 'home',
  42 + page: 'help',
  43 + helpList: helpList
  44 + });
  45 + }).catch(next);
  46 + },
  47 +
  48 + helpDetail: (req, res, next) => {
  49 + var helpDetailPara = {
  50 + code: req.query.code,
  51 + caption: req.query.caption
23 }; 52 };
24 - res.render('index', _.merge({ 53 +
  54 + homeModel.getHelpDetail(helpDetailPara).then(helpDetail => {
  55 + res.render('help-detail', {
  56 + module: 'home',
  57 + page: 'help',
  58 + helpDetail: helpDetail
  59 + });
  60 + }).catch(next);
  61 + },
  62 + favorite: (req, res, next) => {
  63 + let tab = req.query.tab;
  64 + let testData = {
  65 + brandUrl: helpers.urlFormat('/product/new'),
  66 + productUrl: helpers.urlFormat('/product/new')
  67 + }
  68 + res.render('favorite', _.merge({
25 module: 'home', 69 module: 'home',
26 - page: 'index' 70 + page: 'favorite',
27 }, testData)); 71 }, testData));
  72 + },
  73 + favpaging: (req, res, next) => {
  74 + let tab = req.query.tab;
  75 + let page = req.query.page;
  76 +
  77 + console.log("page: " + page);
  78 +
  79 + if (tab === 'brand') {
  80 +
  81 + }
  82 +
  83 + if (page > 3) return res.json([]);
  84 +
  85 + let testData = []
  86 + for (var i = 1; i <= 9; i++) {
  87 + testData.push({
  88 + fav_id: Number(page + i),
  89 + title: "商品名测试测试测试测试测试测试测试测试" + Number(page + i),
  90 + invalidGoods: true,
  91 + discountPrice: '¥' + 900,
  92 + price: '¥' + 990
  93 + })
  94 + }
  95 +
  96 + return res.json(testData);
  97 + },
  98 + favdel: (req, res, next) => {
  99 + let id = req.body.id;
  100 +
  101 + return res.json({
  102 + code: 200
  103 + });
28 } 104 }
29 }; 105 };
30 106
31 -module.exports = component; 107 +module.exports = component;
  1 +'use strict';
  2 +const api = global.yoho.API;
  3 +const Promise = require('bluebird');
  4 +const co = Promise.coroutine;
  5 +const _ = require('lodash');
  6 +const helpers = global.yoho.helpers;
  7 +
  8 +/**
  9 + * 处理用户个人详情数据
  10 + *
  11 + * @param int uid 用户ID
  12 + * @return Object 处理之后的个人详情数据
  13 + */
  14 +const _getUserProfileData = (uid) => {
  15 + return co(function*() {
  16 + // 调用接口获取个人详情
  17 + const data = {};
  18 + return data;
  19 +
  20 + // return api.get('operations/api/v5/resource/get', {
  21 + // uid: uid
  22 + // }, {
  23 + // cache: true,
  24 + // code: 200
  25 + // });
  26 + })();
  27 +};
  28 +
  29 +/**
  30 + * 处理个人中心页面优惠券,收藏的商品等的数目数据
  31 + *
  32 + * @param int uid 用户ID
  33 + * @return Object 处理之后的个人中心页面收藏的商品等的数目数据
  34 + */
  35 +const _getInfoNumData = (uid) => {
  36 + return co(function*() {
  37 + const data = {
  38 + wait_pay_num: 1,
  39 + wait_cargo_num: 2,
  40 + send_cargo_num: 3,
  41 + address_num: 4,
  42 + product_favorite_total: 5,
  43 + brand_favorite_total: 6,
  44 + yoho_coin_num: 7
  45 + };
  46 + return data;
  47 + })();
  48 +
  49 +};
  50 +
  51 +exports.getUserHomeData = (uid) => {
  52 + return Promise.all([_getUserProfileData(uid), _getInfoNumData(uid)]);
  53 +};
  54 +
  55 +const helpListDataProc = (helpData) => {
  56 + const formatData = [];
  57 +
  58 + helpData = helpData || [];
  59 + _.forEach(helpData, (item) => {
  60 + formatData.push({
  61 + name: item.caption,
  62 + code: item.code,
  63 + url: helpers.urlFormat('/home/helpDetail', {
  64 + code: item.code,
  65 + caption: item.caption,
  66 + })
  67 + });
  68 + });
  69 + return formatData;
  70 +};
  71 +
  72 +
  73 +
  74 +/**
  75 + * 帮助中心列表页
  76 + *
  77 + * @param data
  78 + *
  79 + */
  80 +exports.getHelpInfo = (data) => {
  81 + var defaultParam = {
  82 + method: 'app.help.li'
  83 + },
  84 + infoData = Object.assign(defaultParam, data);
  85 +
  86 + return api.get('', infoData).then(result => {
  87 +
  88 + return helpListDataProc(result.data);
  89 + });
  90 +};
  91 +
  92 +/**
  93 + * 帮助中心详情页
  94 + *
  95 + * @param data
  96 + */
  97 +exports.getHelpDetail = (data) => {
  98 + var defaultParam = {
  99 + method: 'app.help.detail',
  100 + return_type: 'html'
  101 + },
  102 + detailData = Object.assign(defaultParam, data);
  103 +
  104 + return api.get('', detailData).then(result => {
  105 + return result;
  106 + });
  107 +};
  108 +
@@ -13,4 +13,12 @@ const home = require(cRoot); @@ -13,4 +13,12 @@ const home = require(cRoot);
13 // Your controller here 13 // Your controller here
14 router.get('/', home.index); // 个人中心主页 14 router.get('/', home.index); // 个人中心主页
15 15
16 -module.exports = router; 16 +router.get('/help', home.help); // 帮助中心列表页
  17 +router.get('/helpDetail', home.helpDetail); // 帮助中心详情页
  18 +
  19 +
  20 +router.get('/favorite', home.favorite); // 个人中心 - 收藏
  21 +router.get('/favorite/favpaging', home.favpaging); // 个人中心 - 收藏商品/品牌(翻页)
  22 +router.post('/favorite/favdel', home.favdel); // 个人中心 - 收藏商品/品牌(刪除)
  23 +
  24 +module.exports = router;
  1 +<div class="yoho-favorite-page yoho-page">
  2 + <div class="fav-content" id="fav-content">
  3 + <fav-product-list product-url={{productUrl}}></fav-product-list>
  4 + </div>
  5 +</div>
  1 +<div class="help">
  2 + <ul>
  3 + {{# helpList}}
  4 + <li><a href="{{url}}"><span>{{ name}}</span><i class="icon num">&#xe607;</i></a></li>
  5 + {{/ helpList}}
  6 + </ul>
  7 +</div>
1 <div class="my-page yoho-page"> 1 <div class="my-page yoho-page">
2 <div class="my-header"> 2 <div class="my-header">
3 - {{#isLogin}}  
4 - <a class="user-info" href="/home/mydetails"> 3 + <a class="user-info" href={{userinfourl}}>
5 <span class="user-avatar" data-avatar="{{head_ico}}"></span> 4 <span class="user-avatar" data-avatar="{{head_ico}}"></span>
6 <br><span class="username">{{profile_name}}</span> 5 <br><span class="username">{{profile_name}}</span>
7 </a> 6 </a>
8 - {{/isLogin}}  
9 - {{^isLogin}}  
10 - <div class="user-info">  
11 - <a class="login-btn" href="{{signinUrl}}">  
12 - 登录/注册  
13 - </a>  
14 - </div>  
15 - {{/isLogin}}  
16 </div> 7 </div>
17 <div class="my-order"> 8 <div class="my-order">
18 <a class="order-title" href="/home/orders"> 9 <a class="order-title" href="/home/orders">
19 我的订单 10 我的订单
20 - <span> 11 + <span class="read-order">
21 查看全部订单 <span class="icon icon-right"></span> 12 查看全部订单 <span class="icon icon-right"></span>
22 </span> 13 </span>
23 </a> 14 </a>
@@ -55,23 +46,23 @@ @@ -55,23 +46,23 @@
55 <div class="group-list"> 46 <div class="group-list">
56 <a class="list-item" href="/home/address"> 47 <a class="list-item" href="/home/address">
57 地址管理 48 地址管理
58 - <span class="num">3 <span class="icon icon-right"></span></span> 49 + <span class="num">{{address_num}} <span class="icon icon-right"></span></span>
59 </a> 50 </a>
60 </div> 51 </div>
61 <div class="group-list"> 52 <div class="group-list">
62 <a class="list-item" href="/home/favorite"> 53 <a class="list-item" href="/home/favorite">
63 收藏的商品 54 收藏的商品
64 - <span class="num">120 <span class="icon icon-right"></span></span> 55 + <span class="num">{{product_favorite_total}} <span class="icon icon-right"></span></span>
65 </a> 56 </a>
66 <a class="list-item" href="/home/favorite?tab=brand"> 57 <a class="list-item" href="/home/favorite?tab=brand">
67 收藏的品牌 58 收藏的品牌
68 - <span class="num">100 <span class="icon icon-right"></span></span> 59 + <span class="num">{{brand_favorite_total}} <span class="icon icon-right"></span></span>
69 </a> 60 </a>
70 </div> 61 </div>
71 <div class="group-list"> 62 <div class="group-list">
72 <a class="list-item" href="/home/mycurrency"> 63 <a class="list-item" href="/home/mycurrency">
73 YOHO 币 64 YOHO 币
74 - <span class="num">100 <span class="icon icon-right"></span></span> 65 + <span class="num">{{yoho_coin_num}} <span class="icon icon-right"></span></span>
75 </a> 66 </a>
76 </div> 67 </div>
77 <div class="group-list"> 68 <div class="group-list">
1 <div id="product-list"> 1 <div id="product-list">
2 - <Sort></Sort>  
3 - <List url="/product/list" :query='{a:1}'></List> 2 + <Sort :config.once="sortConfig" :val="sort">
  3 + </Sort>
  4 + <List :data="productList"></List>
4 <Drawer> 5 <Drawer>
5 <Filter></Filter> 6 <Filter></Filter>
6 </Drawer> 7 </Drawer>
7 -</div>  
  8 +</div>
  9 +<script>
  10 + var sortConfig = [
  11 + {txt: '默认', val: 1 },
  12 + {txt: '最新', val: 2 },
  13 + {type: 'updown', txt: '价格', val: [3, 4] }, //[up, down]
  14 + {type: 'updown', txt: '折扣', val: [5, 6] }
  15 +];
  16 +</script>
1 const Vue = require('yoho-vue'); 1 const Vue = require('yoho-vue');
2 const lazyload = require('yoho-vue-lazyload'); 2 const lazyload = require('yoho-vue-lazyload');
3 -const qs = require('yoho-qs');  
4 -const contentCode = require('content-code');  
5 3
6 -const tab = require('channel/tab.vue');  
7 -const resources = require('component/resources/index.vue'); 4 +const channel = require('channel/index.vue');
8 5
9 require('common/vue-filter'); 6 require('common/vue-filter');
10 7
@@ -12,14 +9,7 @@ Vue.use(lazyload); @@ -12,14 +9,7 @@ Vue.use(lazyload);
12 9
13 new Vue({ 10 new Vue({
14 el: '#channel', 11 el: '#channel',
15 - data() {  
16 - return {  
17 - page: 'channel',  
18 - contentCode: contentCode.channel[qs.channel || 'men']  
19 - };  
20 - },  
21 components: { 12 components: {
22 - tab: tab,  
23 - resources: resources 13 + channel
24 } 14 }
25 }); 15 });
  1 +const Vue = require('yoho-vue');
  2 +const infiniteScroll = require('yoho-vue-infinite-scroll');
  3 +const ProductList = require('home/fav-product-list.vue');
  4 +
  5 +Vue.use(infiniteScroll)
  6 +
  7 +new Vue({
  8 + el: '#fav-content',
  9 + components: {
  10 + 'fav-product-list': ProductList
  11 + }
  12 +});
1 const Vue = require('yoho-vue'); 1 const Vue = require('yoho-vue');
2 const lazyload = require('yoho-vue-lazyload'); 2 const lazyload = require('yoho-vue-lazyload');
3 const infinitScroll = require('yoho-vue-infinite-scroll'); 3 const infinitScroll = require('yoho-vue-infinite-scroll');
  4 +const bus = require('common/vue-bus');
4 const sort = require('product/sort.vue'); 5 const sort = require('product/sort.vue');
5 const list = require('product/list.vue'); 6 const list = require('product/list.vue');
6 const drawer = require('product/drawer.vue'); 7 const drawer = require('product/drawer.vue');
@@ -11,9 +12,104 @@ Vue.use(infinitScroll); @@ -11,9 +12,104 @@ Vue.use(infinitScroll);
11 12
12 require('common/vue-filter'); 13 require('common/vue-filter');
13 14
14 -new Vue({ 15 +const app = new Vue({
15 el: '#product-list', 16 el: '#product-list',
  17 + data: function() {
  18 + return {
  19 + sortConfig: global.sortConfig,
  20 + filterConfig: [],
  21 +
  22 + // query
  23 + url: 'list',
  24 + sort: 3,
  25 + filter: [],
  26 + page: 0, // page= 0 未搜索, 1 并且productList.length =0 没有数据, page = page_total 全部加载完
  27 + totalPage: 0,
  28 +
  29 + // 产品列表
  30 + productList: [],
  31 +
  32 + // state:
  33 + inSearching: false
  34 + };
  35 + },
16 components: { 36 components: {
17 - list, sort, filter, drawer 37 + list,
  38 + sort,
  39 + filter,
  40 + drawer
  41 + },
  42 + methods: {
  43 + search: function() {
  44 + if (this.inSearching) {
  45 + return;
  46 + }
  47 + const self = this;
  48 +
  49 + this.inSearching = true;
  50 + $.post(this.url, {
  51 + sort: this.sort,
  52 + filter: this.filter,
  53 + page: this.page
  54 + })
  55 + .done(res => {
  56 + self.$set('productList', self.productList.concat(res.data.productList));
  57 + })
  58 + .fail(error => {
  59 + self.page--;
  60 + })
  61 + .always(()=>{
  62 + self.inSearching = false;
  63 + });
  64 + },
  65 +
  66 + pageState: function() {
  67 +
  68 + },
  69 +
  70 + /**
  71 + *
  72 + */
  73 + research: function() {
  74 +
  75 + }
  76 + },
  77 + watch: {
  78 + /* sort 和 filter 改变 都会触发 重新搜索 (想象成清空所有分页) */
  79 + sort: function() {
  80 + this.page = 0;
  81 + },
  82 + filter: function() {
  83 + this.page = 0;
  84 + },
  85 +
  86 + page: function(newVal, oldVal) {
  87 + if (newVal === 0) {
  88 + // when research
  89 + this.$set('productList', []);
  90 + this.search();
  91 + } else if (newVal > oldVal && newVal > this.totalPage) {
  92 + // when fetch
  93 + this.search();
  94 + }
  95 + }
  96 + },
  97 +
  98 + created: function() {
  99 + this.search();
18 } 100 }
19 }); 101 });
  102 +
  103 +bus.$on('list.paging', function() {
  104 + app.page++;
  105 +});
  106 +
  107 +bus.$on('sort.change', function({ val}) {
  108 + console.log(val);
  109 + app.sort = val;
  110 +});
  111 +
  112 +bus.$on('filter.change', function({ val}) {
  113 + console.log(val);
  114 + app.filter = val;
  115 +});
  1 +.yoho-favorite-page {
  2 + width: 100%;
  3 + height: auto;
  4 +
  5 + .fav-content {
  6 + .fav-type {
  7 + display: none;
  8 + }
  9 + .show {
  10 + display: block;
  11 + }
  12 +
  13 + .fav-null {
  14 + font-size: 22px;
  15 + color: #444;
  16 + display: block;
  17 + margin-top: 100px;
  18 + text-align: center;
  19 +
  20 + &:before {
  21 + content: '';
  22 + display: block;
  23 + width: 188px;
  24 + height: 171px;
  25 + background: resolve("home/fav/fav-null.png");
  26 + background-size: 100% 100%;
  27 + margin: 0 auto 45px auto;
  28 + }
  29 + }
  30 +
  31 + .go-shopping {
  32 + width: 472px;
  33 + height: 88px;
  34 + line-height: 88px;
  35 + margin: 80px auto 0 auto;
  36 + background: #444;
  37 + text-align: center;
  38 + color: #fff;
  39 + display: block;
  40 + font-size: 26px;
  41 + border-radius:.2rem;
  42 + }
  43 +
  44 + .fav-product-list {
  45 + list-style: none;
  46 +
  47 + li {
  48 + height: auto;
  49 + overflow: hidden;
  50 + margin-top: 20px;
  51 + }
  52 +
  53 + .fav-del {
  54 + float: left;
  55 + background: resolve("home/fav/fav-del.png");
  56 + display: none;
  57 + }
  58 +
  59 + .show {
  60 + display: block;
  61 + }
  62 +
  63 + .delhide {
  64 + display: block;
  65 + }
  66 +
  67 + .fav-img-box {
  68 + width: 152px;
  69 + height: 203px;
  70 + float: left;
  71 + margin-right: 24px;
  72 +
  73 + img {
  74 + display: block;
  75 + overflow: hidden;
  76 + width: 100%;
  77 + height: 100%;
  78 + }
  79 + }
  80 +
  81 + .fav-info-list {
  82 + color: #444;
  83 + font-size: 24px;
  84 + border-bottom: 1px solid #e0e0e0;
  85 + padding-bottom: 20px;
  86 + margin-right: 5px;
  87 + height: 203px;
  88 + overflow: hidden;
  89 + position: relative;
  90 +
  91 + .title {
  92 + width: 430px;
  93 + text-overflow: ellipsis;
  94 + font-size: 28px;
  95 + margin: 0;
  96 + }
  97 +
  98 + .fav-price {
  99 + margin-top: 20px;
  100 +
  101 + .new-price {
  102 + color: #d1021c;
  103 + font-size: 24px;
  104 + }
  105 +
  106 + .price-underline {
  107 + text-decoration: line-through;
  108 + margin-left: 15px;
  109 + color: #b0b0b0;
  110 + font-size: 24px;
  111 + }
  112 + }
  113 +
  114 + .save-price {
  115 + position: absolute;
  116 + bottom: 20px;
  117 + left: 0;
  118 + width: 100%;
  119 + min-height: 24px;
  120 +
  121 + span {
  122 + &.sell-out {
  123 + float: right;
  124 + padding: 5px 18px;
  125 + color: #b0b0b0;
  126 + border-radius: 20px;
  127 + font-size: 22px;
  128 + }
  129 + }
  130 + }
  131 + }
  132 + }
  133 + }
  134 +}
  1 +.help {
  2 + width: 100%;
  3 + height: auto;
  4 + overflow: hidden;
  5 + ul {
  6 + width: 100%;
  7 + height: auto;
  8 + overflow: hidden;
  9 + display: block;
  10 + border-top: 1px solid #e0e0e0;
  11 + padding-left: 0;
  12 + margin: 0;
  13 + li {
  14 + width: 100%;
  15 + height: 80px;
  16 + line-height: 84px;
  17 + overflow: hidden;
  18 + font-size: 28px;
  19 + border-bottom: 1px solid #e0e0e0;
  20 + float: right;
  21 + color: #444;
  22 + list-style: none;
  23 + &:last-of-type {
  24 + border-bottom: none;
  25 + }
  26 + a:visited {
  27 + color: #444;
  28 + }
  29 + span {
  30 + width: 90%;
  31 + height: 100%;
  32 + overflow: hidden;
  33 + float: left;
  34 + padding-left: 5%;
  35 + }
  36 + i {
  37 + color: #e0e0e0;
  38 + }
  39 + }
  40 + }
  41 + .iconfont {
  42 + color: #fff;
  43 + }
  44 +
  45 +}
  1 +.my-page {
  2 + color: #444;
  3 + background: #f0f0f0;
  4 +
  5 + a {
  6 + color: #000;
  7 + }
  8 +
  9 + .user-info {
  10 + display: block;
  11 + position: relative;
  12 + padding: 0 30px;
  13 + color: #000;
  14 + font-size: 34px;
  15 + line-height: 138px;
  16 + height: 469px;
  17 + background-size: cover;
  18 + background: resolve("home/header-bg.png");
  19 + text-align: center;
  20 +
  21 + .user-avatar {
  22 + display: inline-block;
  23 + position: relative;
  24 + top: 90px;
  25 + width: 200px;
  26 + height: 200px;
  27 + border-radius: 50%;
  28 + border: 6px solid #a7a8a9;
  29 + background: resolve("home/user-icon.png");
  30 + background-size: 100%;
  31 + }
  32 +
  33 + .username {
  34 + display: inline-block;
  35 + padding: 0 16px;
  36 + text-overflow: ellipsis;
  37 + overflow: hidden;
  38 + white-space: nowrap;
  39 + font-size: 32px;
  40 + max-width: 260px;
  41 + }
  42 + }
  43 +
  44 + .login-btn {
  45 + display: inline-block;
  46 + top: 40px;
  47 + left: 194px;
  48 + width: 244px;
  49 + height: 82px;
  50 + line-height: 82px;
  51 + color: #fff;
  52 + border: 4px solid #fff;
  53 + margin: 150px auto;
  54 + }
  55 +
  56 + .my-order {
  57 + margin-bottom: 30px;
  58 + border-top: 1px solid #e0e0e0;
  59 + border-bottom: 1px solid #e0e0e0;
  60 + background: #fff;
  61 +
  62 + .order-title {
  63 + display: block;
  64 + padding: 0 29px;
  65 + font-size: 34px;
  66 + line-height: 88px;
  67 +
  68 + span {
  69 + color: #e0e0e0;
  70 + float: right;
  71 + }
  72 +
  73 + &.highlight {
  74 + background: #eee;
  75 + }
  76 +
  77 + .read-order {
  78 + font-size: 30px;
  79 + }
  80 + }
  81 +
  82 + .order-type {
  83 + padding: 20px 30px;
  84 + text-align: center;
  85 + border-top: 1px solid #e0e0e0;
  86 +
  87 + .type-item {
  88 + position: relative;
  89 + float: left;
  90 + color: #444;
  91 + font-size: 24px;
  92 + line-height: 1.5;
  93 + width: 170px;
  94 +
  95 + &.highlight {
  96 + background: #eee;
  97 + }
  98 +
  99 + .num {
  100 + position: absolute;
  101 + top: -24px;
  102 + right: 36px;
  103 + width: 72px;
  104 + height: 72px;
  105 + font-size: 34px;
  106 + line-height: 72px;
  107 + color: #fff;
  108 + background: #f03d35;
  109 + text-align: center;
  110 + border-radius: 50%;
  111 + transform: scale(0.5);
  112 + }
  113 + }
  114 + }
  115 + }
  116 +
  117 + .group-list {
  118 + margin-bottom: 30px;
  119 + border-top: 1px solid #e0e0e0;
  120 + border-bottom: 1px solid #e0e0e0;
  121 + background: #fff;
  122 +
  123 + .list-item {
  124 + display: block;
  125 + position: relative;
  126 + padding: 0 30px;
  127 + font-size: 34px;
  128 + line-height: 90px;
  129 + overflow: hidden;
  130 +
  131 + &.highlight {
  132 + background: #eee;
  133 + }
  134 +
  135 + &:after {
  136 + content: "";
  137 + position: absolute;
  138 + right: 0;
  139 + bottom: 0;
  140 + width: 100%;
  141 + height: 0;
  142 + border-top: 1px solid #f0f0f0;
  143 + }
  144 +
  145 + &:last-child:after {
  146 + content: none;
  147 + }
  148 + }
  149 +
  150 + .icon {
  151 + margin-right: 5px;
  152 + font-size: 34px;
  153 + vertical-align: top;
  154 + }
  155 +
  156 + .num {
  157 + color: #b0b0b0;
  158 + float: right;
  159 + }
  160 + }
  161 +}
1 -.my-page {  
2 - color: #444;  
3 - background: #f0f0f0;  
4 -  
5 - a {  
6 - color: #444;  
7 - }  
8 -  
9 - .user-info {  
10 - display: block;  
11 - position: relative;  
12 - padding: 0 30px;  
13 - color: #fff;  
14 - font-size: 34px;  
15 - line-height: 138px;  
16 - height: 449px;  
17 - background-size: cover;  
18 - background: #444;  
19 - /*background: resolve("home/header-bg.jpg"); */  
20 - text-align: center;  
21 -  
22 - .user-avatar {  
23 - display: inline-block;  
24 - position: relative;  
25 - top: 88px;  
26 - width: 200px;  
27 - height: 200px;  
28 - border-radius: 50%;  
29 - border: 6px solid #a7a8a9;  
30 - background: #a7a8a9;  
31 - background-size: 100%;  
32 - }  
33 -  
34 - .username {  
35 - display: inline-block;  
36 - padding: 0 16px;  
37 - text-overflow: ellipsis;  
38 - overflow: hidden;  
39 - white-space: nowrap;  
40 - max-width: 260px;  
41 - }  
42 - }  
43 -  
44 - .login-btn {  
45 - display: inline-block;  
46 - top: 40px;  
47 - left: 194px;  
48 - width: 244px;  
49 - height: 82px;  
50 - line-height: 82px;  
51 - color: #fff;  
52 - border: 4px solid #fff;  
53 - margin: 120px auto;  
54 - }  
55 -  
56 - .my-order {  
57 - margin-bottom: 30px;  
58 - border-top: 1px solid #e0e0e0;  
59 - border-bottom: 1px solid #e0e0e0;  
60 - background: #fff;  
61 -  
62 - .order-title {  
63 - display: block;  
64 - padding: 0 30px;  
65 - font-size: 16PX;  
66 - line-height: 88px;  
67 -  
68 - span {  
69 - color: #e0e0e0;  
70 - float: right;  
71 - }  
72 -  
73 - &.highlight {  
74 - background: #eee;  
75 - }  
76 - }  
77 -  
78 - .order-type {  
79 - padding: 20px 30px;  
80 - text-align: center;  
81 - border-top: 1px solid #e0e0e0;  
82 -  
83 - .type-item {  
84 - position: relative;  
85 - float: left;  
86 - color: #444;  
87 - font-size: 14PX;  
88 - line-height: 1.5;  
89 - width: 170px;  
90 -  
91 - &.highlight {  
92 - background: #eee;  
93 - }  
94 -  
95 - .num {  
96 - position: absolute;  
97 - top: -24px;  
98 - right: 36px;  
99 - width: 72px;  
100 - height: 72px;  
101 - font-size: 40px;  
102 - line-height: 72px;  
103 - color: #fff;  
104 - background: #f03d35;  
105 - text-align: center;  
106 - border-radius: 50%;  
107 - transform: scale(0.5);  
108 - }  
109 - }  
110 - }  
111 - }  
112 -  
113 - .group-list {  
114 - margin-bottom: 30px;  
115 - border-top: 1px solid #e0e0e0;  
116 - border-bottom: 1px solid #e0e0e0;  
117 - background: #fff;  
118 -  
119 - .list-item {  
120 - display: block;  
121 - position: relative;  
122 - padding: 0 30px;  
123 - font-size: 16PX;  
124 - line-height: 90px;  
125 -  
126 - &.highlight {  
127 - background: #eee;  
128 - }  
129 -  
130 - &:after {  
131 - content: '';  
132 - position: absolute;  
133 - right: 0;  
134 - bottom: 0;  
135 - width: 100%;  
136 - height: 0;  
137 - border-top: 1px solid #f0f0f0;  
138 - }  
139 -  
140 - &:last-child:after {  
141 - content: none;  
142 - }  
143 - }  
144 -  
145 - .icon {  
146 - margin-right: 5px;  
147 - font-size: 30px;  
148 - vertical-align: top;  
149 - }  
150 -  
151 - .num {  
152 - color: #e0e0e0;  
153 - float: right;  
154 - }  
155 - }  
156 -} 1 +@import "home";
  2 +@import "help";
  3 +@import "fav";
  1 +<template>
  2 + <tab v-bind:page="page"></tab>
  3 + <resources v-bind:content-code="contentCode"></resources>
  4 +</template>
  5 +
  6 +<script>
  7 + const qs = require('yoho-qs');
  8 + const contentCode = require('content-code');
  9 + const bus = require('common/vue-bus');
  10 +
  11 + const tab = require('channel/tab.vue');
  12 + const resources = require('component/resources/index.vue');
  13 +
  14 + module.exports = {
  15 + data() {
  16 + return {
  17 + page: 'channel',
  18 + contentCode: contentCode.channel[qs.channel || 'men']
  19 + };
  20 + },
  21 + components: {
  22 + tab: tab,
  23 + resources: resources
  24 + },
  25 + created() {
  26 + bus.$on('contentCode.change', (code) => {
  27 + this.contentCode = code;
  28 + });
  29 + }
  30 + };
  31 +</script>
  32 +
  33 +<style>
  34 +
  35 +</style>
@@ -37,7 +37,7 @@ @@ -37,7 +37,7 @@
37 methods: { 37 methods: {
38 changeChannel(index) { 38 changeChannel(index) {
39 this.current = index; 39 this.current = index;
40 - bus.$emit('changeChannel', this.page, this.channel[index].channel); 40 + bus.$emit('channel.change', this.page, this.channel[index].channel);
41 } 41 }
42 } 42 }
43 }; 43 };
@@ -61,6 +61,7 @@ @@ -61,6 +61,7 @@
61 watch: { 61 watch: {
62 contentCode() { 62 contentCode() {
63 this.getResourcesData(); 63 this.getResourcesData();
  64 + bus.$emit('contentCode.change', this.contentCode);
64 } 65 }
65 }, 66 },
66 methods: { 67 methods: {
@@ -94,7 +95,7 @@ @@ -94,7 +95,7 @@
94 }, 95 },
95 created() { 96 created() {
96 this.getResourcesData(); 97 this.getResourcesData();
97 - bus.$on('changeChannel', (page, channel) => { 98 + bus.$on('channel.change', (page, channel) => {
98 this.contentCode = contentCode[page][channel]; 99 this.contentCode = contentCode[page][channel];
99 }); 100 });
100 } 101 }
  1 +<template>
  2 + <div class="fav-type show" v-infinite-scroll="loadMore()" infinite-scroll-disabled="busy" infinite-scroll-distance="10">
  3 + <ul class="fav-product-list">
  4 + <li v-for="item in productData" track-by="fav_id">
  5 + <div class="fav-del {{editmodel ? 'show': ''}}">
  6 + <button @click="delProduct($index, item.fav_id)">删除</button>
  7 + </div>
  8 + <a :href="item.link">
  9 + <div class="fav-img-box">
  10 + <img :src="item.imgUrl" alt=""/>
  11 + </div>
  12 + <div class="fav-info-list">
  13 + <span class="title">{{item.title}}</span>
  14 + <br/>
  15 + <div class="fav-price">
  16 + <span class="new-price" v-if="item.discountPrice">{{item.discountPrice}}</span>
  17 + <span class="fav-price {{ item.discountPrice ? 'price-underline' : ''}}">{{item.price}}</span>
  18 + </div>
  19 + <br/>
  20 + <div class="save-price">
  21 + <span class="sell-out" v-if="item.sellOut || item.invalidGoods">{{item.sellOut ? '已售罄' : '已下架'}}</span>
  22 + </div>
  23 + </div>
  24 + </a>
  25 + </li>
  26 + </ul>
  27 + <div class="fav-null-box {{ nullbox }}">
  28 + <span class="fav-null">您暂无收藏任何商品}}</span>
  29 + <a slot="go-shopping" class="go-shopping" :href="productUrl">随便逛逛</a>
  30 + </div>
  31 + </div>
  32 +</template>
  33 +
  34 +<script>
  35 + const $ = require('yoho-jquery');
  36 + const tip = require('common/tip');
  37 + const Loading = require('common/loading');
  38 + const modal = require('common/modal');
  39 + const loading = new Loading();
  40 +
  41 + module.exports = {
  42 + props: ['productUrl'],
  43 + data() {
  44 + return {
  45 + nullbox : 'hide',
  46 + busy: false,
  47 + editmodel: false,
  48 + page: 0,
  49 + productData: []
  50 + };
  51 + },
  52 + methods: {
  53 + loadMore: function() {
  54 + loading.show();
  55 +
  56 + let _this = this;
  57 + this.busy = true;
  58 +
  59 + $.ajax({
  60 + url: '/home/favorite/favpaging',
  61 + data: {
  62 + page : ++_this.page
  63 + }
  64 + }).then(result => {
  65 + if (result.length) {
  66 + result.forEach(function(o){
  67 + _this.productData.push(o);
  68 + });
  69 + _this.busy = false;
  70 + } else {
  71 + _this.busy = true;
  72 + }
  73 +
  74 + _this.nullbox = _this.productData.length ? "hide" : "";
  75 + loading.hide();
  76 + }).fail(() => {
  77 + tip('网络错误');
  78 + });
  79 + },
  80 + editProduct(action) {
  81 + this.editmodel = action;
  82 + },
  83 + delProduct(index, id) {
  84 + let _this = this;
  85 + $.modal.confirm('', '确定刪除该收藏吗?', function() {
  86 + this.hide();
  87 + $.ajax({
  88 + method: 'post',
  89 + url: '/home/favorite/favdel',
  90 + data: {
  91 + id: id
  92 + }
  93 + }).then(function(data) {
  94 + if (data.code === 200) {
  95 + _this.productData.splice(index, 1);
  96 + } else if (data.code === 400) {
  97 + $.modal.alert(data.message, '出错了!');
  98 + } else {
  99 + $.modal.alert('', '取消收藏失败');
  100 + }
  101 + }).fail(function() {
  102 + $.modal.alert('', '网络错误');
  103 + });
  104 + });
  105 + }
  106 + }
  107 + };
  108 +</script>
  109 +
1 <template> 1 <template>
2 <div class="goods-box" v-infinite-scroll="fetch()" infinite-scroll-disable="disableFetch"> 2 <div class="goods-box" v-infinite-scroll="fetch()" infinite-scroll-disable="disableFetch">
3 <ul class="cardlist card-large clearfix"> 3 <ul class="cardlist card-large clearfix">
4 - <li class="card" v-for="item in products"> 4 + <li class="card" v-for="item in data">
5 <div class="card-pic"> 5 <div class="card-pic">
6 <a href=""> 6 <a href="">
7 <img v-lazy="item.goodsList[0].imagesUrl | resize 372 499" alt="{{item.productName}}"> 7 <img v-lazy="item.goodsList[0].imagesUrl | resize 372 499" alt="{{item.productName}}">
@@ -21,75 +21,21 @@ @@ -21,75 +21,21 @@
21 </div> 21 </div>
22 </template> 22 </template>
23 <script> 23 <script>
24 -let $ = require('yoho-jquery');  
25 -  
26 -/**  
27 - * @example  
28 - * <List url='' :query='{}' disable-fetch></List>  
29 - * <List :init-data='{}'></List>  
30 - */ 24 +let bus = require('common/vue-bus');
31 25
32 module.exports = { 26 module.exports = {
33 props: { 27 props: {
34 -  
35 - /* 请求地址 */  
36 - url: {  
37 - type: String,  
38 - required: true  
39 - },  
40 -  
41 - /* 初始数据, 应该只单次绑定, 然后fetch数据全靠url */  
42 - initData: Array,  
43 -  
44 - /* 请求参数 */  
45 - query: Object,  
46 -  
47 /* 开启滚动加载 */ 28 /* 开启滚动加载 */
48 - disableFetch: Boolean  
49 - },  
50 - data: function() {  
51 - return {  
52 - state: {  
53 - curPage: 0,  
54 - totalPage: 10  
55 - },  
56 - products: [],  
57 - inLoading: false,  
58 - atEnd: false  
59 - }; 29 + disableFetch: Boolean,
  30 +
  31 + //数据
  32 + data: Array
60 }, 33 },
61 methods: { 34 methods: {
62 fetch: function() { 35 fetch: function() {
63 - if (this.atEnd) {  
64 - return;  
65 - }  
66 - let self = this;  
67 -  
68 - this.state.curPage++;  
69 - this.inLoading = true;  
70 - $.ajax({  
71 - url: this.url,  
72 - type: 'POST',  
73 - })  
74 - .done(result => {  
75 - self.$set('products', self.products.concat(result.data.productList));  
76 - })  
77 - .always(() => {  
78 - self.inLoading = false;  
79 - self.atEnd = self.state.curPage === self.state.totalPage;  
80 - });  
81 -  
82 - }  
83 - },  
84 - created: function() {  
85 - // 有初始数据,用初始数据  
86 - if (this.initData) {  
87 - this.$set('products', this.products.concat(this.initData));  
88 - this.atEnd = true;  
89 - } else if (this.url) {  
90 - this.fetch(); 36 + bus.$emit('list.paging');
91 } 37 }
92 - }, 38 + }
93 }; 39 };
94 </script> 40 </script>
95 <style> 41 <style>
1 <template> 1 <template>
2 <ul class="sort-navs clearfix"> 2 <ul class="sort-navs clearfix">
3 - <li class="sort-item active"><span>默认</span></li>  
4 - <li class="sort-item">  
5 - <span class="sort-name">最新</span>  
6 - <span class="sort-icon">  
7 - <i class="icon icon-sort-asc"></i>  
8 - <i class="icon icon-sort-desc"></i>  
9 - </span>  
10 - </li>  
11 - <li class="sort-item">  
12 - <span class="sort-name">价格</span>  
13 - </li>  
14 - <li class="sort-item">  
15 - <span class="sort-name">折扣</span>  
16 - <span class="sort-icon">  
17 - <i class="icon icon-sort-asc"></i>  
18 - <i class="icon icon-sort-desc"></i>  
19 - </span>  
20 - </li> 3 + <template v-for="item in config">
  4 + <simple v-if="(item.type || 'simple') === 'simple'" :txt="item.txt" :val="item.val">
  5 + </simple>
  6 + <updown v-if="item.type === 'updown'" :txt="item.txt" :vals="item.val">
  7 + </updown>
  8 + </template>
21 </ul> 9 </ul>
22 </template> 10 </template>
23 <script> 11 <script>
  12 +const $ = require('yoho-jquery');
  13 +const bus = require('common/vue-bus');
  14 +const simple = require('./sort/simple.vue');
  15 +const updown = require('./sort/updown.vue');
  16 +
24 module.exports = { 17 module.exports = {
  18 + props: {
  19 + /**
  20 + * sort 配置
  21 + * @type {Array} [{type, txt, val}]
  22 + * type: 类型 simple, updown
  23 + * txt: 文字,
  24 + * val: 值
  25 + */
  26 + config: Array,
25 27
  28 + //初始值 可以进行双向绑定
  29 + val: Number
  30 + },
  31 + components: {
  32 + simple,
  33 + updown
  34 + },
  35 + methods: {},
  36 + watch: {
  37 + 'val': function(newVal, oldVal) {
  38 + bus.$emit('sort.change', {
  39 + val: newVal,
  40 + ref: this._uid
  41 + });
  42 + }
  43 + }
26 }; 44 };
27 </script> 45 </script>
28 <style> 46 <style>
@@ -41,7 +59,6 @@ module.exports = { @@ -41,7 +59,6 @@ module.exports = {
41 width: 25%; 59 width: 25%;
42 float: left; 60 float: left;
43 text-align: center; 61 text-align: center;
44 -  
45 &:after { 62 &:after {
46 content: "|"; 63 content: "|";
47 position: absolute; 64 position: absolute;
@@ -52,15 +69,12 @@ module.exports = { @@ -52,15 +69,12 @@ module.exports = {
52 &:last-of-type:after { 69 &:last-of-type:after {
53 display: none; 70 display: none;
54 } 71 }
55 -  
56 .sort-name { 72 .sort-name {
57 font-size: 28px; 73 font-size: 28px;
58 } 74 }
59 -  
60 .sort-icon { 75 .sort-icon {
61 position: relative; 76 position: relative;
62 margin-left: 10px; 77 margin-left: 10px;
63 -  
64 .icon-sort-asc, 78 .icon-sort-asc,
65 .icon-sort-desc { 79 .icon-sort-desc {
66 position: absolute; 80 position: absolute;
@@ -68,7 +82,6 @@ module.exports = { @@ -68,7 +82,6 @@ module.exports = {
68 top: 0; 82 top: 0;
69 } 83 }
70 } 84 }
71 -  
72 &.active { 85 &.active {
73 color: $black; 86 color: $black;
74 } 87 }
  1 +<template>
  2 + <li class="sort-item" :class="active" @click="click">
  3 + <span class="sort-name">{{txt}}</span>
  4 + </li>
  5 +</template>
  6 +<script>
  7 +module.exports = {
  8 + props: ['txt', 'val'],
  9 + computed: {
  10 + active: function() {
  11 + if (this.val === this.$parent.val) {
  12 + return 'active';
  13 + }
  14 + }
  15 + },
  16 + methods: {
  17 + click: function() {
  18 + this.$parent.val = this.val;
  19 + }
  20 + }
  21 +};
  22 +</script>
  1 +<template>
  2 + <li class="sort-item" :class="active" @click="clickHandler">
  3 + <span class="sort-name">{{txt}}</span>
  4 + <span class="sort-icon">
  5 + <i class="icon icon-sort-asc" :class="{active: $parent.val === vals[0]}"></i>
  6 + <i class="icon icon-sort-desc" :class="{active: $parent.val === vals[1]}"></i>
  7 + </span>
  8 + </li>
  9 +</template>
  10 +<style>
  11 +.sort-item .icon {
  12 + color: #b0b0b0;
  13 + &.active {
  14 + color: #000;
  15 + }
  16 +}
  17 +</style>
  18 +<script>
  19 +module.exports = {
  20 + props: {
  21 + txt: String,
  22 + vals: Array //[asc, desc]
  23 + },
  24 + data: function() {
  25 + return {};
  26 + },
  27 + computed: {
  28 + active: function() {
  29 + const index = this.vals.indexOf(this.$parent.val);
  30 +
  31 + if (index >= 0) {
  32 + return {
  33 + 'active': true,
  34 + };
  35 + }
  36 + }
  37 + },
  38 + methods: {
  39 + clickHandler: function() {
  40 + let index = this.vals.indexOf(this.$parent.val);
  41 +
  42 + if (index === -1) {
  43 + this.$parent.val = this.vals[0];
  44 + } else {
  45 + index = index === 0 ? 1 : 0;
  46 + this.$parent.val = this.vals[index];
  47 + }
  48 + }
  49 + }
  50 +};
  51 +</script>