Authored by 郭成尧

Merge remote-tracking branch 'remotes/origin/develop' into feature/brand

... ... @@ -4,6 +4,7 @@
* @date: 2016/07/18
*/
'use strict';
const homeModel = require('../models/index');
const _ = require('lodash');
const helpers = global.yoho.helpers;
... ... @@ -12,20 +13,95 @@ const helpers = global.yoho.helpers;
*/
const component = {
index: (req, res, next) => {
var testData = {
isLogin: false,
head_ico: '',
profile_name: 'XXX',
signinUrl: '/home',
wait_pay_num: 1,
wait_cargo_num: 2,
send_cargo_num: 3
let uid = req.user.uid;
if (!uid && req.xhr) {
return res.json({
code: 400,
message: '抱歉,您暂未登录!'
});
}
homeModel.getUserHomeData(uid).then(data => {
let result = {
module: 'home',
page: 'index',
head_ico: uid ? '' : '',
profile_name: uid ? 'James Sen' : '登录/注册',
userinfourl: uid ? '/home/mydetails' : helpers.urlFormat('/signin.html', {
refer: req.originalUrl
}),
};
res.render('index', _.merge(result, data[1]));
}).catch(next);
},
help: (req, res, next) => {
homeModel.getHelpInfo().then(helpList => {
res.render('help', {
module: 'home',
page: 'help',
helpList: helpList
});
}).catch(next);
},
helpDetail: (req, res, next) => {
var helpDetailPara = {
code: req.query.code,
caption: req.query.caption
};
res.render('index', _.merge({
homeModel.getHelpDetail(helpDetailPara).then(helpDetail => {
res.render('help-detail', {
module: 'home',
page: 'help',
helpDetail: helpDetail
});
}).catch(next);
},
favorite: (req, res, next) => {
let tab = req.query.tab;
let testData = {
brandUrl: helpers.urlFormat('/product/new'),
productUrl: helpers.urlFormat('/product/new')
}
res.render('favorite', _.merge({
module: 'home',
page: 'index'
page: 'favorite',
}, testData));
},
favpaging: (req, res, next) => {
let tab = req.query.tab;
let page = req.query.page;
console.log("page: " + page);
if (tab === 'brand') {
}
if (page > 3) return res.json([]);
let testData = []
for (var i = 1; i <= 9; i++) {
testData.push({
fav_id: Number(page + i),
title: "商品名测试测试测试测试测试测试测试测试" + Number(page + i),
invalidGoods: true,
discountPrice: '¥' + 900,
price: '¥' + 990
})
}
return res.json(testData);
},
favdel: (req, res, next) => {
let id = req.body.id;
return res.json({
code: 200
});
}
};
module.exports = component;
module.exports = component;
\ No newline at end of file
... ...
'use strict';
const api = global.yoho.API;
const Promise = require('bluebird');
const co = Promise.coroutine;
const _ = require('lodash');
const helpers = global.yoho.helpers;
/**
* 处理用户个人详情数据
*
* @param int uid 用户ID
* @return Object 处理之后的个人详情数据
*/
const _getUserProfileData = (uid) => {
return co(function*() {
// 调用接口获取个人详情
const data = {};
return data;
// return api.get('operations/api/v5/resource/get', {
// uid: uid
// }, {
// cache: true,
// code: 200
// });
})();
};
/**
* 处理个人中心页面优惠券,收藏的商品等的数目数据
*
* @param int uid 用户ID
* @return Object 处理之后的个人中心页面收藏的商品等的数目数据
*/
const _getInfoNumData = (uid) => {
return co(function*() {
const data = {
wait_pay_num: 1,
wait_cargo_num: 2,
send_cargo_num: 3,
address_num: 4,
product_favorite_total: 5,
brand_favorite_total: 6,
yoho_coin_num: 7
};
return data;
})();
};
exports.getUserHomeData = (uid) => {
return Promise.all([_getUserProfileData(uid), _getInfoNumData(uid)]);
};
const helpListDataProc = (helpData) => {
const formatData = [];
helpData = helpData || [];
_.forEach(helpData, (item) => {
formatData.push({
name: item.caption,
code: item.code,
url: helpers.urlFormat('/home/helpDetail', {
code: item.code,
caption: item.caption,
})
});
});
return formatData;
};
/**
* 帮助中心列表页
*
* @param data
*
*/
exports.getHelpInfo = (data) => {
var defaultParam = {
method: 'app.help.li'
},
infoData = Object.assign(defaultParam, data);
return api.get('', infoData).then(result => {
return helpListDataProc(result.data);
});
};
/**
* 帮助中心详情页
*
* @param data
*/
exports.getHelpDetail = (data) => {
var defaultParam = {
method: 'app.help.detail',
return_type: 'html'
},
detailData = Object.assign(defaultParam, data);
return api.get('', detailData).then(result => {
return result;
});
};
... ...
... ... @@ -13,4 +13,12 @@ const home = require(cRoot);
// Your controller here
router.get('/', home.index); // 个人中心主页
module.exports = router;
router.get('/help', home.help); // 帮助中心列表页
router.get('/helpDetail', home.helpDetail); // 帮助中心详情页
router.get('/favorite', home.favorite); // 个人中心 - 收藏
router.get('/favorite/favpaging', home.favpaging); // 个人中心 - 收藏商品/品牌(翻页)
router.post('/favorite/favdel', home.favdel); // 个人中心 - 收藏商品/品牌(刪除)
module.exports = router;
\ No newline at end of file
... ...
<div class="yoho-favorite-page yoho-page">
<div class="fav-content" id="fav-content">
<fav-product-list product-url={{productUrl}}></fav-product-list>
</div>
</div>
\ No newline at end of file
... ...
<div class="help">
<ul>
{{# helpList}}
<li><a href="{{url}}"><span>{{ name}}</span><i class="icon num">&#xe607;</i></a></li>
{{/ helpList}}
</ul>
</div>
... ...
<div class="my-page yoho-page">
<div class="my-header">
{{#isLogin}}
<a class="user-info" href="/home/mydetails">
<a class="user-info" href={{userinfourl}}>
<span class="user-avatar" data-avatar="{{head_ico}}"></span>
<br><span class="username">{{profile_name}}</span>
</a>
{{/isLogin}}
{{^isLogin}}
<div class="user-info">
<a class="login-btn" href="{{signinUrl}}">
登录/注册
</a>
</div>
{{/isLogin}}
</div>
<div class="my-order">
<a class="order-title" href="/home/orders">
我的订单
<span>
<span class="read-order">
查看全部订单 <span class="icon icon-right"></span>
</span>
</a>
... ... @@ -55,23 +46,23 @@
<div class="group-list">
<a class="list-item" href="/home/address">
地址管理
<span class="num">3 <span class="icon icon-right"></span></span>
<span class="num">{{address_num}} <span class="icon icon-right"></span></span>
</a>
</div>
<div class="group-list">
<a class="list-item" href="/home/favorite">
收藏的商品
<span class="num">120 <span class="icon icon-right"></span></span>
<span class="num">{{product_favorite_total}} <span class="icon icon-right"></span></span>
</a>
<a class="list-item" href="/home/favorite?tab=brand">
收藏的品牌
<span class="num">100 <span class="icon icon-right"></span></span>
<span class="num">{{brand_favorite_total}} <span class="icon icon-right"></span></span>
</a>
</div>
<div class="group-list">
<a class="list-item" href="/home/mycurrency">
YOHO 币
<span class="num">100 <span class="icon icon-right"></span></span>
<span class="num">{{yoho_coin_num}} <span class="icon icon-right"></span></span>
</a>
</div>
<div class="group-list">
... ...
<div id="product-list">
<Sort></Sort>
<List url="/product/list" :query='{a:1}'></List>
<Sort :config.once="sortConfig" :val="sort">
</Sort>
<List :data="productList"></List>
<Drawer>
<Filter></Filter>
</Drawer>
</div>
\ No newline at end of file
</div>
<script>
var sortConfig = [
{txt: '默认', val: 1 },
{txt: '最新', val: 2 },
{type: 'updown', txt: '价格', val: [3, 4] }, //[up, down]
{type: 'updown', txt: '折扣', val: [5, 6] }
];
</script>
\ No newline at end of file
... ...
... ... @@ -16,7 +16,7 @@ module.exports = {
siteUrl: '//m.yohobuy.com',
domains: {
api: 'http://devapi.yoho.cn:58078/',
service: 'http://172.16.6.247:8085/gateway/'
service: 'http://192.168.102.202:8080/gateway/'
},
subDomains: {
host: '.m.yohobuy.com',
... ...
... ... @@ -4,7 +4,7 @@ const qs = require('yoho-qs');
const contentCode = require('content-code');
const tab = require('channel/tab.vue');
const resources = require('channel/resources.vue');
const resources = require('component/resources/index.vue');
require('common/vue-filter');
... ...
const Vue = require('yoho-vue');
const infiniteScroll = require('yoho-vue-infinite-scroll');
const ProductList = require('home/fav-product-list.vue');
Vue.use(infiniteScroll)
new Vue({
el: '#fav-content',
components: {
'fav-product-list': ProductList
}
});
\ No newline at end of file
... ...
const Vue = require('yoho-vue');
const lazyload = require('yoho-vue-lazyload');
const infinitScroll = require('yoho-vue-infinite-scroll');
const bus = require('common/vue-bus');
const sort = require('product/sort.vue');
const list = require('product/list.vue');
const drawer = require('product/drawer.vue');
... ... @@ -11,9 +12,104 @@ Vue.use(infinitScroll);
require('common/vue-filter');
new Vue({
const app = new Vue({
el: '#product-list',
data: function() {
return {
sortConfig: global.sortConfig,
filterConfig: [],
// query
url: 'list',
sort: 3,
filter: [],
page: 0, // page= 0 未搜索, 1 并且productList.length =0 没有数据, page = page_total 全部加载完
totalPage: 0,
// 产品列表
productList: [],
// state:
inSearching: false
};
},
components: {
list, sort, filter, drawer
list,
sort,
filter,
drawer
},
methods: {
search: function() {
if (this.inSearching) {
return;
}
const self = this;
this.inSearching = true;
$.post(this.url, {
sort: this.sort,
filter: this.filter,
page: this.page
})
.done(res => {
self.$set('productList', self.productList.concat(res.data.productList));
})
.fail(error => {
self.page--;
})
.always(()=>{
self.inSearching = false;
});
},
pageState: function() {
},
/**
*
*/
research: function() {
}
},
watch: {
/* sort 和 filter 改变 都会触发 重新搜索 (想象成清空所有分页) */
sort: function() {
this.page = 0;
},
filter: function() {
this.page = 0;
},
page: function(newVal, oldVal) {
if (newVal === 0) {
// when research
this.$set('productList', []);
this.search();
} else if (newVal > oldVal && newVal > this.totalPage) {
// when fetch
this.search();
}
}
},
created: function() {
this.search();
}
});
bus.$on('list.paging', function() {
app.page++;
});
bus.$on('sort.change', function({ val}) {
console.log(val);
app.sort = val;
});
bus.$on('filter.change', function({ val}) {
console.log(val);
app.filter = val;
});
... ...
@use postcss-clearfix ;
@use postcss-clearfix;
.clearfix {
clear: fix;
... ... @@ -15,7 +15,7 @@ html,
body {
width: 100%;
font-size: 24px;
font-family: helvetica, Arial, "黑体";
font-family: Helvetica, Roboto, "Heiti SC", "黑体", Arial;
line-height: 1.4;
}
... ... @@ -29,14 +29,6 @@ a {
outline: none;
}
.hide {
display: none;
}
.overflow-hidden {
overflow: hidden;
}
.main-wrap {
position: relative;
margin-right: auto;
... ... @@ -44,6 +36,15 @@ a {
max-width: 750px;
width: 100%;
}
.text-center {
text-align: center;
}
.overflow-hidden {
overflow: hidden;
}
.right {
float: right;
}
... ... @@ -51,6 +52,7 @@ a {
.left {
float: right;
}
.text-center {
text-align: center;
.hide {
display: none;
}
... ...
.yoho-favorite-page {
width: 100%;
height: auto;
.fav-content {
.fav-type {
display: none;
}
.show {
display: block;
}
.fav-null {
font-size: 22px;
color: #444;
display: block;
margin-top: 100px;
text-align: center;
&:before {
content: '';
display: block;
width: 188px;
height: 171px;
background: resolve("home/fav/fav-null.png");
background-size: 100% 100%;
margin: 0 auto 45px auto;
}
}
.go-shopping {
width: 472px;
height: 88px;
line-height: 88px;
margin: 80px auto 0 auto;
background: #444;
text-align: center;
color: #fff;
display: block;
font-size: 26px;
border-radius:.2rem;
}
.fav-product-list {
list-style: none;
li {
height: auto;
overflow: hidden;
margin-top: 20px;
}
.fav-del {
float: left;
background: resolve("home/fav/fav-del.png");
display: none;
}
.show {
display: block;
}
.delhide {
display: block;
}
.fav-img-box {
width: 152px;
height: 203px;
float: left;
margin-right: 24px;
img {
display: block;
overflow: hidden;
width: 100%;
height: 100%;
}
}
.fav-info-list {
color: #444;
font-size: 24px;
border-bottom: 1px solid #e0e0e0;
padding-bottom: 20px;
margin-right: 5px;
height: 203px;
overflow: hidden;
position: relative;
.title {
width: 430px;
text-overflow: ellipsis;
font-size: 28px;
margin: 0;
}
.fav-price {
margin-top: 20px;
.new-price {
color: #d1021c;
font-size: 24px;
}
.price-underline {
text-decoration: line-through;
margin-left: 15px;
color: #b0b0b0;
font-size: 24px;
}
}
.save-price {
position: absolute;
bottom: 20px;
left: 0;
width: 100%;
min-height: 24px;
span {
&.sell-out {
float: right;
padding: 5px 18px;
color: #b0b0b0;
border-radius: 20px;
font-size: 22px;
}
}
}
}
}
}
}
\ No newline at end of file
... ...
.help {
width: 100%;
height: auto;
overflow: hidden;
ul {
width: 100%;
height: auto;
overflow: hidden;
display: block;
border-top: 1px solid #e0e0e0;
padding-left: 0;
margin: 0;
li {
width: 100%;
height: 80px;
line-height: 84px;
overflow: hidden;
font-size: 28px;
border-bottom: 1px solid #e0e0e0;
float: right;
color: #444;
list-style: none;
&:last-of-type {
border-bottom: none;
}
a:visited {
color: #444;
}
span {
width: 90%;
height: 100%;
overflow: hidden;
float: left;
padding-left: 5%;
}
i {
color: #e0e0e0;
}
}
}
.iconfont {
color: #fff;
}
}
... ...
.my-page {
color: #444;
background: #f0f0f0;
a {
color: #000;
}
.user-info {
display: block;
position: relative;
padding: 0 30px;
color: #000;
font-size: 34px;
line-height: 138px;
height: 469px;
background-size: cover;
background: resolve("home/header-bg.png");
text-align: center;
.user-avatar {
display: inline-block;
position: relative;
top: 90px;
width: 200px;
height: 200px;
border-radius: 50%;
border: 6px solid #a7a8a9;
background: resolve("home/user-icon.png");
background-size: 100%;
}
.username {
display: inline-block;
padding: 0 16px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
font-size: 32px;
max-width: 260px;
}
}
.login-btn {
display: inline-block;
top: 40px;
left: 194px;
width: 244px;
height: 82px;
line-height: 82px;
color: #fff;
border: 4px solid #fff;
margin: 150px auto;
}
.my-order {
margin-bottom: 30px;
border-top: 1px solid #e0e0e0;
border-bottom: 1px solid #e0e0e0;
background: #fff;
.order-title {
display: block;
padding: 0 29px;
font-size: 34px;
line-height: 88px;
span {
color: #e0e0e0;
float: right;
}
&.highlight {
background: #eee;
}
.read-order {
font-size: 30px;
}
}
.order-type {
padding: 20px 30px;
text-align: center;
border-top: 1px solid #e0e0e0;
.type-item {
position: relative;
float: left;
color: #444;
font-size: 24px;
line-height: 1.5;
width: 170px;
&.highlight {
background: #eee;
}
.num {
position: absolute;
top: -24px;
right: 36px;
width: 72px;
height: 72px;
font-size: 34px;
line-height: 72px;
color: #fff;
background: #f03d35;
text-align: center;
border-radius: 50%;
transform: scale(0.5);
}
}
}
}
.group-list {
margin-bottom: 30px;
border-top: 1px solid #e0e0e0;
border-bottom: 1px solid #e0e0e0;
background: #fff;
.list-item {
display: block;
position: relative;
padding: 0 30px;
font-size: 34px;
line-height: 90px;
overflow: hidden;
&.highlight {
background: #eee;
}
&:after {
content: "";
position: absolute;
right: 0;
bottom: 0;
width: 100%;
height: 0;
border-top: 1px solid #f0f0f0;
}
&:last-child:after {
content: none;
}
}
.icon {
margin-right: 5px;
font-size: 34px;
vertical-align: top;
}
.num {
color: #b0b0b0;
float: right;
}
}
}
... ...
.my-page {
color: #444;
background: #f0f0f0;
a {
color: #444;
}
.user-info {
display: block;
position: relative;
padding: 0 30px;
color: #fff;
font-size: 34px;
line-height: 138px;
height: 449px;
background-size: cover;
background: #444;
/*background: resolve("home/header-bg.jpg"); */
text-align: center;
.user-avatar {
display: inline-block;
position: relative;
top: 88px;
width: 200px;
height: 200px;
border-radius: 50%;
border: 6px solid #a7a8a9;
background: #a7a8a9;
background-size: 100%;
}
.username {
display: inline-block;
padding: 0 16px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
max-width: 260px;
}
}
.login-btn {
display: inline-block;
top: 40px;
left: 194px;
width: 244px;
height: 82px;
line-height: 82px;
color: #fff;
border: 4px solid #fff;
margin: 120px auto;
}
.my-order {
margin-bottom: 30px;
border-top: 1px solid #e0e0e0;
border-bottom: 1px solid #e0e0e0;
background: #fff;
.order-title {
display: block;
padding: 0 30px;
font-size: 16PX;
line-height: 88px;
span {
color: #e0e0e0;
float: right;
}
&.highlight {
background: #eee;
}
}
.order-type {
padding: 20px 30px;
text-align: center;
border-top: 1px solid #e0e0e0;
.type-item {
position: relative;
float: left;
color: #444;
font-size: 14PX;
line-height: 1.5;
width: 170px;
&.highlight {
background: #eee;
}
.num {
position: absolute;
top: -24px;
right: 36px;
width: 72px;
height: 72px;
font-size: 40px;
line-height: 72px;
color: #fff;
background: #f03d35;
text-align: center;
border-radius: 50%;
transform: scale(0.5);
}
}
}
}
.group-list {
margin-bottom: 30px;
border-top: 1px solid #e0e0e0;
border-bottom: 1px solid #e0e0e0;
background: #fff;
.list-item {
display: block;
position: relative;
padding: 0 30px;
font-size: 16PX;
line-height: 90px;
&.highlight {
background: #eee;
}
&:after {
content: '';
position: absolute;
right: 0;
bottom: 0;
width: 100%;
height: 0;
border-top: 1px solid #f0f0f0;
}
&:last-child:after {
content: none;
}
}
.icon {
margin-right: 5px;
font-size: 30px;
vertical-align: top;
}
.num {
color: #e0e0e0;
float: right;
}
}
}
@import "home";
@import "help";
@import "fav";
... ...
... ... @@ -55,6 +55,7 @@
height: 8px;
background: #ccc;
opacity: 1;
vertical-align: middle;
&.active {
width: 12px;
... ...
... ... @@ -29,12 +29,12 @@
const bus = require('common/vue-bus');
const contentCode = require('content-code');
const focus = require('component/resources/focus.vue');
const focusLeftRight = require('component/resources/focus-left-right.vue');
const titleImage = require('component/resources/title-image.vue');
const titleFloor = require('component/resources/title-floor.vue');
const recommendContentFive = require('component/resources/recommend-content-five.vue');
const goods = require('component/resources/goods.vue');
const focus = require('./focus.vue');
const focusLeftRight = require('./focus-left-right.vue');
const titleImage = require('./title-image.vue');
const titleFloor = require('./title-floor.vue');
const recommendContentFive = require('./recommend-content-five.vue');
const goods = require('./goods.vue');
const dataCache = {};
... ...
<template>
<div class="fav-type show" v-infinite-scroll="loadMore()" infinite-scroll-disabled="busy" infinite-scroll-distance="10">
<ul class="fav-product-list">
<li v-for="item in productData" track-by="fav_id">
<div class="fav-del {{editmodel ? 'show': ''}}">
<button @click="delProduct($index, item.fav_id)">删除</button>
</div>
<a :href="item.link">
<div class="fav-img-box">
<img :src="item.imgUrl" alt=""/>
</div>
<div class="fav-info-list">
<span class="title">{{item.title}}</span>
<br/>
<div class="fav-price">
<span class="new-price" v-if="item.discountPrice">{{item.discountPrice}}</span>
<span class="fav-price {{ item.discountPrice ? 'price-underline' : ''}}">{{item.price}}</span>
</div>
<br/>
<div class="save-price">
<span class="sell-out" v-if="item.sellOut || item.invalidGoods">{{item.sellOut ? '已售罄' : '已下架'}}</span>
</div>
</div>
</a>
</li>
</ul>
<div class="fav-null-box {{ nullbox }}">
<span class="fav-null">您暂无收藏任何商品}}</span>
<a slot="go-shopping" class="go-shopping" :href="productUrl">随便逛逛</a>
</div>
</div>
</template>
<script>
const $ = require('yoho-jquery');
const tip = require('common/tip');
const Loading = require('common/loading');
const modal = require('common/modal');
const loading = new Loading();
module.exports = {
props: ['productUrl'],
data() {
return {
nullbox : 'hide',
busy: false,
editmodel: false,
page: 0,
productData: []
};
},
methods: {
loadMore: function() {
loading.show();
let _this = this;
this.busy = true;
$.ajax({
url: '/home/favorite/favpaging',
data: {
page : ++_this.page
}
}).then(result => {
if (result.length) {
result.forEach(function(o){
_this.productData.push(o);
});
_this.busy = false;
} else {
_this.busy = true;
}
_this.nullbox = _this.productData.length ? "hide" : "";
loading.hide();
}).fail(() => {
tip('网络错误');
});
},
editProduct(action) {
this.editmodel = action;
},
delProduct(index, id) {
let _this = this;
$.modal.confirm('', '确定刪除该收藏吗?', function() {
this.hide();
$.ajax({
method: 'post',
url: '/home/favorite/favdel',
data: {
id: id
}
}).then(function(data) {
if (data.code === 200) {
_this.productData.splice(index, 1);
} else if (data.code === 400) {
$.modal.alert(data.message, '出错了!');
} else {
$.modal.alert('', '取消收藏失败');
}
}).fail(function() {
$.modal.alert('', '网络错误');
});
});
}
}
};
</script>
... ...
<template>
<div class="goods-box" v-infinite-scroll="fetch()" infinite-scroll-disable="disableFetch">
<ul class="cardlist card-large clearfix">
<li class="card" v-for="item in products">
<li class="card" v-for="item in data">
<div class="card-pic">
<a href="">
<img v-lazy="item.goodsList[0].imagesUrl | resize 372 499" alt="{{item.productName}}">
... ... @@ -21,75 +21,21 @@
</div>
</template>
<script>
let $ = require('yoho-jquery');
/**
* @example
* <List url='' :query='{}' disable-fetch></List>
* <List :init-data='{}'></List>
*/
let bus = require('common/vue-bus');
module.exports = {
props: {
/* 请求地址 */
url: {
type: String,
required: true
},
/* 初始数据, 应该只单次绑定, 然后fetch数据全靠url */
initData: Array,
/* 请求参数 */
query: Object,
/* 开启滚动加载 */
disableFetch: Boolean
},
data: function() {
return {
state: {
curPage: 0,
totalPage: 10
},
products: [],
inLoading: false,
atEnd: false
};
disableFetch: Boolean,
//数据
data: Array
},
methods: {
fetch: function() {
if (this.atEnd) {
return;
}
let self = this;
this.state.curPage++;
this.inLoading = true;
$.ajax({
url: this.url,
type: 'POST',
})
.done(result => {
self.$set('products', self.products.concat(result.data.productList));
})
.always(() => {
self.inLoading = false;
self.atEnd = self.state.curPage === self.state.totalPage;
});
}
},
created: function() {
// 有初始数据,用初始数据
if (this.initData) {
this.$set('products', this.products.concat(this.initData));
this.atEnd = true;
} else if (this.url) {
this.fetch();
bus.$emit('list.paging');
}
},
}
};
</script>
<style>
... ...
<template>
<ul class="sort-navs clearfix">
<li class="sort-item active"><span>默认</span></li>
<li class="sort-item">
<span class="sort-name">最新</span>
<span class="sort-icon">
<i class="icon icon-sort-asc"></i>
<i class="icon icon-sort-desc"></i>
</span>
</li>
<li class="sort-item">
<span class="sort-name">价格</span>
</li>
<li class="sort-item">
<span class="sort-name">折扣</span>
<span class="sort-icon">
<i class="icon icon-sort-asc"></i>
<i class="icon icon-sort-desc"></i>
</span>
</li>
<template v-for="item in config">
<simple v-if="(item.type || 'simple') === 'simple'" :txt="item.txt" :val="item.val">
</simple>
<updown v-if="item.type === 'updown'" :txt="item.txt" :vals="item.val">
</updown>
</template>
</ul>
</template>
<script>
const $ = require('yoho-jquery');
const bus = require('common/vue-bus');
const simple = require('./sort/simple.vue');
const updown = require('./sort/updown.vue');
module.exports = {
props: {
/**
* sort 配置
* @type {Array} [{type, txt, val}]
* type: 类型 simple, updown
* txt: 文字,
* val: 值
*/
config: Array,
//初始值 可以进行双向绑定
val: Number
},
components: {
simple,
updown
},
methods: {},
watch: {
'val': function(newVal, oldVal) {
bus.$emit('sort.change', {
val: newVal,
ref: this._uid
});
}
}
};
</script>
<style>
... ... @@ -41,7 +59,6 @@ module.exports = {
width: 25%;
float: left;
text-align: center;
&:after {
content: "|";
position: absolute;
... ... @@ -52,15 +69,12 @@ module.exports = {
&:last-of-type:after {
display: none;
}
.sort-name {
font-size: 28px;
}
.sort-icon {
position: relative;
margin-left: 10px;
.icon-sort-asc,
.icon-sort-desc {
position: absolute;
... ... @@ -68,7 +82,6 @@ module.exports = {
top: 0;
}
}
&.active {
color: $black;
}
... ...
<template>
<li class="sort-item" :class="active" @click="click">
<span class="sort-name">{{txt}}</span>
</li>
</template>
<script>
module.exports = {
props: ['txt', 'val'],
computed: {
active: function() {
if (this.val === this.$parent.val) {
return 'active';
}
}
},
methods: {
click: function() {
this.$parent.val = this.val;
}
}
};
</script>
... ...
<template>
<li class="sort-item" :class="active" @click="clickHandler">
<span class="sort-name">{{txt}}</span>
<span class="sort-icon">
<i class="icon icon-sort-asc" :class="{active: $parent.val === vals[0]}"></i>
<i class="icon icon-sort-desc" :class="{active: $parent.val === vals[1]}"></i>
</span>
</li>
</template>
<style>
.sort-item .icon {
color: #b0b0b0;
&.active {
color: #000;
}
}
</style>
<script>
module.exports = {
props: {
txt: String,
vals: Array //[asc, desc]
},
data: function() {
return {};
},
computed: {
active: function() {
const index = this.vals.indexOf(this.$parent.val);
if (index >= 0) {
return {
'active': true,
};
}
}
},
methods: {
clickHandler: function() {
let index = this.vals.indexOf(this.$parent.val);
if (index === -1) {
this.$parent.val = this.vals[0];
} else {
index = index === 0 ? 1 : 0;
this.$parent.val = this.vals[index];
}
}
}
};
</script>
... ...