Authored by 陈峰

vue 2.0 80%

Showing 79 changed files with 2767 additions and 788 deletions

Too many changes to show.

To preserve performance only 79 of 79+ files are displayed.

... ... @@ -19,4 +19,4 @@ router.post('/upload/image', auth, multipartMiddleware, uploadApi.uploadImg);
router.get('/wechat/share/token', wechat.shareToken);
module.exports = router;
\ No newline at end of file
module.exports = router;
... ...
... ... @@ -47,4 +47,4 @@ module.exports = {
cache: true
}));
}
};
\ No newline at end of file
};
... ...
... ... @@ -94,4 +94,4 @@ const model = {
}
};
module.exports = model;
\ No newline at end of file
module.exports = model;
... ...
... ... @@ -33,4 +33,4 @@ const editorialList = params => {
module.exports = {
editorialList
};
\ No newline at end of file
};
... ...
... ... @@ -25,4 +25,4 @@ router.get(/like_(\d+)\.json/, auth, detail.like);
router.get(/favorite_(\d+)\.json/, auth, detail.favorite);
router.get(/misc_(\d+)\.json/, detail.misc);
module.exports = router;
\ No newline at end of file
module.exports = router;
... ...
... ... @@ -295,6 +295,16 @@ const component = {
res.render('privilege', Object.assign(result, responseData));
}).catch(next);
},
favoriteNum(req, res, next) {
homeModel.favoriteNum(req.user.uid).then(result => {
res.json(result);
}).catch(next);
},
editorialNum(req, res) {
homeModel.editorialNum(req.user.uid).then(result => {
res.json(result);
});
}
};
... ...
... ... @@ -4,6 +4,8 @@ const serviceAPI = global.yoho.ServiceAPI;
const helpers = global.yoho.helpers;
const _ = require('lodash');
const config = global.yoho.config;
const singleAPI = global.yoho.SingleAPI;
/**
* 查询用户信息
... ... @@ -438,3 +440,23 @@ exports.getPreferential = (params) => {
});
};
// 商品收藏数量接口
exports.favoriteNum = (uid) => {
return singleAPI.get('favorite', {
method: 'app.favorite.getFavoriteCount',
uid: uid
}, {
code: 200
});
};
// 资讯收藏数量接口
exports.editorialNum = (uid) => {
return serviceAPI.post('guang/api/v2/favorite/getFavNum', {
uid: uid,
app_type: 1
}, {
code: 200
});
};
... ...
... ... @@ -92,4 +92,4 @@ const refund = {
}
};
module.exports = refund;
\ No newline at end of file
module.exports = refund;
... ...
... ... @@ -46,6 +46,7 @@ router.post('/me/save-feedback', auth, home.saveFeedback); // 个人中心-提
router.get('/me/collection', auth, favorite.favorite); // 个人中心 - 收藏
router.get('/me/collection/favpaging', auth, favorite.favpaging); // 个人中心 - 收藏商品/品牌/资讯(翻页)
router.post('/me/del-favdel', auth, favorite.deletefav); // 个人中心 - 收藏商品/品牌/资讯(刪除)
router.get('/me/favoriteNum', auth, home.favoriteNum);// 收藏个数
// 退换货
router.get('/me/return', auth, refund.refundOrders); // 退换货 - 订单列表
... ... @@ -96,4 +97,6 @@ router.get('/me/grade', auth, home.grade);
router.get('/me/gradeData', home.gradeData);
router.get('/me/privilege', auth, home.preferential);
router.get('/me/editorialNum', auth, home.editorialNum);
module.exports = router;
... ...
... ... @@ -10,6 +10,11 @@ const _ = require('lodash');
const model = require('../models/detail');
const searchModel = require('../models/search');
const GENDER = {
1: '1,3',
2: '2,3'
};
// 频道映射
const CHANNEL_MAP = {
men: 1,
... ... @@ -213,6 +218,19 @@ const component = {
},
/**
* 根据skn 搜索产品
*
* @param req
* @param res
* @param next
*/
searchSkn: (req, res, next) => {
searchModel.productInfoBySkns(req.query.ids).then(result => {
res.json(result);
}).catch(next);
},
/**
* 是否支持退换货
* @param req
* @param res
... ... @@ -229,26 +247,33 @@ const component = {
},
/**
* 为你优选
* 猜你喜欢
* @param req
* @param res
* @param next
*/
prefer: (req, res, next) => {
let udid = req.sessionID;
let channel = req.query.channel || req.cookies._Channel || 'men';
let params = {
udid,
mightLike: (req, res, next) => {
const channel = req.query.channel || req.cookies._Channel || 'men';
const params = {
uid: req.user.uid,
page: req.query.page || 1,
limit: 20,
gender: GENDER[CHANNEL_MAP[channel]],
udid: req.sessionID,
rec_pos: req.query.rec_pos || 100001,
yh_channel: CHANNEL_MAP[channel] || 1,
limit: 30,
page: 1,
rec_pos: 100003
client_id: req.cookies._yasvd || '1'
};
model.preferList(params)
.then((list) => {
res.json(list);
}).catch(next);
model.mightLike(params).then(result => {
if (result && result.code === 200) {
res.json({
code: 200,
data: result.data.product_list || [],
message: result.message
});
}
}).catch(next);
}
};
... ...
... ... @@ -16,21 +16,6 @@ exports.index = (req, res) => {
res.render('new', view);
};
// /* 获取 筛选配置 */
// exports.fetchFilters = (req, res, next) => {
// const params = Object.assign({
// uid: req.user.uid || 0,
// page: 1,
// order: 1,
// yh_channel: 'all',
// channel: 'all',
// }, req.query);
// newModel.getNewData(params).then(result => {
// res.json(result);
// }).catch(next);
// };
/* 查询 产品列表 */
exports.fetchProducts = (req, res, next) => {
const params = Object.assign({
... ...
... ... @@ -20,12 +20,9 @@ exports.index = (req, res) => {
/* 查询 产品列表 */
exports.fetchProducts = (req, res, next) => {
const params = {
page: req.query.page || 1,
order: req.query.order || 1,
query: (req.query.query || '').trim()
};
const params = req.query;
console.log('params', params);
model.products(params)
.then(result => res.json(result))
.catch(next);
... ...
... ... @@ -6,52 +6,6 @@
'use strict';
const api = global.yoho.API;
const _ = require('lodash');
/**
*
* @param product
* @returns {*|string}
* @private
*/
const _procProductImg = (product) => {
if (product.gender === '2,3' || product.gender === '2' || product.gender === '3') {
return product.cover_2 || product.images_url || product.cover_1 || '';
}
return product.cover_1 || product.images_url || product.cover_2 || '';
};
/**
*
* @param list
* @returns {Array}
* @private
*/
const _processProduct = (list) => {
let newRes = [];
list = list || [];
list.forEach(item => {
let defaultGoods = _.find(item.goods_list, {is_default: 'Y'});
// 无默认商品取商品列表第一个
if (!defaultGoods) {
defaultGoods = item.goods_list[0];
}
item.default_images = _procProductImg(defaultGoods);
item.goodsUrl = `${config.siteUrl}/product/pro_${item.product_id}_${defaultGoods.goods_id}/${item.cn_alphabet}.html`; // eslint-disable-line
});
_.chunk(list, 5).forEach(item => {
newRes.push({
list: item
});
});
return newRes;
};
/**
* 商品详情
... ... @@ -147,21 +101,13 @@ const model = {
},
/**
* 为你优选
* 猜你喜欢
* @param params
* @param uid
* @returns {Array}
*/
preferList(params, uid) {
if (uid !== 0 && uid !== null) {
params.uid = uid;
}
mightLike(params) {
return api.get('', Object.assign({
method: 'app.home.newPreference'
}, params)).then(data => {
return _processProduct(data.data.product_list);
});
method: 'app.search.newLast7day'
}, params));
}
};
... ...
... ... @@ -5,7 +5,7 @@ const prettyFilter = require(`${global.utils}/beautify/filters`);
const processProductList = require(`${global.utils}/beautify/product`);
// 排序转换
const getTypeCont = (type, order) => {
const getTypeCont = (type, order) => { // eslint-disable-line
switch (type) {
case 'price':
return order === '0' ? 's_p_desc' : 's_p_asc';
... ... @@ -37,12 +37,6 @@ exports.getNewData = (params) => {
delete params.priceRange;
}
if (params.order) {
params.order = getTypeCont(params.type || '', params.order);
} else {
params.order = 's_t_asc';
}
params = Object.assign({
method: 'app.search.newProduct',
limit: 20
... ... @@ -59,27 +53,3 @@ exports.getNewData = (params) => {
return result;
});
};
// /* 查询最新产品筛选条件 */
// exports.getNewFilterData = (params) => {
// params = Object.assign({
// method: 'app.search.newProduct',
// }, params);
// return api.post('', params, {
// cache: true,
// code: 200
// }).then(result => {
// let filterConfig = {};
// if (result.data) {
// prettyFilter(result.data.filter);
// filterConfig = camelCase(result.data.filter);
// }
// return {
// code: result.code,
// data: filterConfig
// };
// });
// };
... ...
... ... @@ -42,7 +42,34 @@ const search = {
}
return result;
});
},
/**
* [根据商品SKN获取商品的简要信息]
* @param {[array]} sknString [skns]
* @return {[type]}
*/
productInfoBySkns(sknString) {
let limit = sknString && sknString.split(',').length;
// 调用搜索接口
let param = {
method: 'app.search.recomandLi',
query: sknString,
order: 's_t_desc',
limit: limit || 1
};
return api.get('', param, {
cache: true
}).then(result => {
result = result || {};
if (result.data) {
result.data.product_list = processProductList(result.data.product_list);
}
return _.get(result, 'data.product_list', []);
});
}
};
module.exports = search;
\ No newline at end of file
module.exports = search;
... ...
... ... @@ -132,4 +132,4 @@ module.exports = {
}
return api.get('', finalParams);
}
};
\ No newline at end of file
};
... ...
... ... @@ -199,4 +199,4 @@ module.exports = {
getShopData,
getBrandShopGoodsData,
collectShopData
};
\ No newline at end of file
};
... ...
... ... @@ -47,11 +47,12 @@ router.get(/\/product\/pro_([\d]+)_([\d]+)\/(.*).html/, detail.index); // 商品
router.get(/\/product\/product_([\d]+)\.json/, detail.product);
router.get(/\/product\/intro_([\d]+)\.json/, detail.intro);
router.get('/product/refundExchange/:skn', detail.supportRefundExchange); // 是否支持7天无理由退换货
router.get('/product/prefer', detail.prefer); // 为你优选列表
router.get('/product/mightLike', detail.mightLike); // 猜你喜欢
router.post(/\product\/cart.json/, detail.addToCart);
router.post(/\product\/favorite.json/, auth, detail.favorite);
router.get(/\/product\/cart-count.json/, detail.getCartCount);
router.get(/\/product\/search_product\.json/, detail.search);
router.get(/\/product\/search_skn\.json/, detail.searchSkn);
// alias: TODO: 测试完成 删除一下router,并更新资源位
// router.get(/\/brand\/share\/(.*)/, shop.shopShare); // 品牌店铺分享页面
... ...
... ... @@ -2,34 +2,51 @@
<div id="ssr">
{{#product}}
<div class="ssr show-box first-box">
<div class="image-carousel">
<div class="swipe">
<div class="swipe-items-wrap">
{{#each goods_list}}
{{#if color_image}}
<div class="swipe-item {{#if @first}}active{{/if}}"> <img width="100%" alt="" src="{{image2 color_image w=750 h=1000 q=80}}/interlace/1"></div>
{{/if}}
{{/each}}
<div class="image-swipe">
<div class="swipe-wrap">
<div class="swiper-container swiper-container-horizontal">
<div class="swiper-wrapper">
{{#each goods_list}}
{{#if color_image}}
<div class="swiper-slide" style="width: 300px;" data-swiper-slide-index="0">
<img width="100%" src="{{image2 color_image w=580 h=770 q=80}}/interlace/1">
</div>
{{/if}}
{{/each}}
</div>
</div>
</div>
</div>
<div class="title-box">
<h1 class="line-clamp-2">{{product_name}}</h1>
</div>
{{#brandInfo}}
<div class="show-box zero-top-margin">
<div>
<ul class="item-action">
<li><a href="/product/shop/{{brand_domain}}"><i class="brand icon"></i><span class="action-text">
{{brand_name}}</span></a>
</li>
<li><i class="icon icon-focus"></i><span class="action-text">收藏</span></li>
<li><i class="icon icon-share2"></i><span class="action-text">分享</span></li>
</ul>
</div>
<hr>
{{#product}}
<div class="item-price">
<i class="price highlight">{{formatPrice}}</i>
{{#if isDiscount}}
<i class="price strike-through">{{format_market_price}}</i>
<i class="price line-through">{{format_market_price}}</i>
{{/if}}
<i class="price {{#if isDiscount}}highlight{{/if}}">{{formatPrice}}</i>
<p class="product-name">{{product_name}}</p>
</div>
</div>
{{#brandInfo}}
<div class="ssr show-box brand">
<img src="{{image2 brand_ico w=110 h=68 q=80}}">
<h2>{{brand_name}}</h2>
<div class="brand-go">
<span>进入店铺</span>
<span class="icon icon-right"></span>
{{/product}}
<div class="service">
<ul>
<li><i class="icon icon-real"></i>100%品牌正品</li>
<li class="return"><i class="icon icon-seven"></i>7天无理由退换货</li>
<li><i class="icon icon-onlineservice"></i>便捷在线客服</li>
</ul>
</div>
<a href="/product/shop/{{brand_domain}}"></a>
</div>
{{/brandInfo}}
{{/product}}
... ...
... ... @@ -2,7 +2,7 @@
<div class="blk-header-wrap" class="is-fixed">
<div class="blk-header">
<div class="blk-header-left">
<i class="icon icon-left go-back-btn"></i>
<i class="icon icon-back go-back-btn"></i>
</div>
<div class="blk-header-right">
</div>
... ... @@ -12,50 +12,33 @@
</div>
<div class="blk-header-gap"></div>
</div>
<ul class="order-navs clearfix">
<li class="order-item active">
<span class="order-name">默认</span>
</li>
<li class="order-item">
<span class="order-name">最新</span>
</li>
<li class="order-item">
<span class="order-name">价格</span>
<span class="order-icon">
<i class="icon icon-sort-up"></i>
<i class="icon icon-sort-down"></i>
</span>
</li>
<li class="order-item">
<span class="order-name">折扣</span>
<span class="order-icon">
<i class="icon icon-sort-up"></i>
<i class="icon icon-sort-down"></i>
</span>
</li>
</ul>
<div class="goods-box">
<div class="top-filter clearfix">
<div class="filter-content">
<ul class="filter-type">
<li class="type-item">推荐<i class="icon down icon-sort-down"></i></li>
<li class="type-item">筛选<i class="icon down icon-sort-down"></i></li>
</ul>
</div>
</div>
<div class="goods-box list-items">
<ul class="cardlist card-large clearfix">
{{#list}}
<li class="card">
<div class="card-pic">
<a href="{{goodsUrl this}}">
<img src="{{resizeImage default_images 372 499}}" alt="{{product_name}}">
<img src="{{resizeImage default_images 330 440}}" alt="{{product_name}}">
</a>
</div>
<div class="card-bd">
<h2 class="card-label">
<a href="{{goodsUrl this}}" class="line-clamp-2">{{product_name}}</a>
<a href="{{goodsUrl this}}" class="line-clamp-1">{{product_name}}</a>
</h2>
<span class="good-price {{#if market_price}}sale-price{{/if}}">¥ {{toFixed sales_price}}</span>
{{#if marketPrice}}
<span class="good-price" class="old-price">
¥ {{toFixed market_price}}
</span>
<span class="good-price" class="old-price">
¥ {{toFixed market_price}}
</span>
{{/if}}
<span class="good-price {{#if market_price}}sale-price{{/if}}">¥ {{toFixed sales_price}}</span>
</div>
</li>
{{/list}}
... ...
... ... @@ -19,19 +19,18 @@ module.exports = {
},
domains: {
// api: 'http://api-test3.yohops.com:9999/',
// service: 'http://service-test3.yohops.com:9999/'
// service: 'http://service-test3.yohops.com:9999/',
/* api: 'http://dev-api.yohops.com:9999/',
service: 'http://dev-service.yohops.com:9999/',*/
// api: 'http://api-test2.yohops.com:9999/',
// service: 'http://service-test2.yohops.com:9999/',
// api: 'http://dev-api.yohops.com:9999/',
// service: 'http://dev-service.yohops.com:9999/',
// singleApi: 'http://192.168.102.27:8092/'
api: 'http://api.yoho.cn/',
service: 'http://service.yoho.cn/',
singleApi: 'http://single.yoho.cn/'
// singleApi: 'http://192.168.102.205:8080/gateway/',//'http://single.yoho.cn/',
// api: 'http://192.168.102.205:8080/gateway/',//'http://api.yoho.cn/',
// service: 'http://192.168.102.205:8080/gateway/'//'http://service.yoho.cn/'
},
subDomains: {
host: '.m.yohoblk.com',
... ...
... ... @@ -36,6 +36,7 @@
"influxdb-winston": "^1.0.1",
"lodash": "^4.15.0",
"memcached": "^2.2.1",
"mint-ui": "^1.0.2",
"moment": "^2.14.1",
"morgan": "^1.7.0",
"oneapm": "^1.2.20",
... ... @@ -52,6 +53,7 @@
"serve-favicon": "^2.3.0",
"uuid": "^2.0.2",
"vue": "^2.4.2",
"vue-touch": "next",
"webpack-uglify-parallel": "^0.1.3",
"webpack-visualizer-plugin": "^0.1.11",
"winston": "^2.2.0",
... ... @@ -95,11 +97,13 @@
"postcss-sprites": "^4.2.1",
"postcss-use": "^2.2.0",
"precss": "^1.4.0",
"sass-loader": "^6.0.6",
"shelljs": "^0.7.3",
"style-loader": "^0.17.0",
"stylelint": "^7.1.0",
"stylelint-config-yoho": "^1.2.7",
"stylelint-processor-html": "^1.0.0",
"vue-awesome-swiper": "^2.5.4",
"vue-hot-reload-api": "^1.2.0",
"vue-html-loader": "^1.2.4",
"vue-infinite-scroll": "^2.0.1",
... ... @@ -108,7 +112,6 @@
"vue-style-loader": "^3.0.1",
"vue-swipe": "^2.0.3",
"vue-template-compiler": "^2.4.2",
"vue-touch": "^1.1.0",
"webpack": "3.3",
"webpack-bundle-analyzer": "^2.8.2",
"webpack-dashboard": "^0.1.8",
... ...
const postImport = require('postcss-import');
const precss = require('precss');
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
module.exports = () => {
return [
postImport({}),
precss(),
autoprefixer(),
cssnano()
];
};
... ...
... ... @@ -12,7 +12,7 @@ let base = require('./webpack.base.config');
if (process.env.NODE_ENV === 'performance') {
const Visualizer = require('webpack-visualizer-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
base = merge(base, {
plugins: [
new Visualizer({
... ...
No preview for this file type
This diff could not be displayed because it is too large.
No preview for this file type
No preview for this file type
... ... @@ -6,7 +6,5 @@ Vue.use(lazyload, { preLoad: 3 });
new Vue({
el: '#cate-resource',
components: {
'cate-res': cateRes
}
render: h => h(cateRes)
});
... ...
... ... @@ -3,7 +3,5 @@ import brandCateBox from 'channel/brand-cate-box.vue';
new Vue({
el: '#brand-cate-box',
components: {
'brand-cate-box': brandCateBox
}
render: h => h(brandCateBox)
});
... ...
... ... @@ -76,10 +76,11 @@ const defaultTitleMap = {
des: '商品',
action: origin + '/me/collection'
},
mtitle: {
des: '品牌',
action: origin + '/me/collection?tab=brand'
},
// mtitle: {
// des: '品牌',
// action: origin + '/me/collection?tab=brand'
// },
rtitle: {
des: '资讯',
action: origin + '/me/collection?tab=article'
... ... @@ -257,8 +258,6 @@ const intercept = (url) => {
let header = titleMap[5];
if (qs.tab === 'article') {
header.defaultSelectedIndex = '2';
} else if (qs.tab === 'brand') {
header.defaultSelectedIndex = '1';
} else {
header.defaultSelectedIndex = '0';
... ...
import yoho from 'yoho';
import interceptClick from 'common/intercept-click';
import Modal from 'common/modal';
import cookie from 'yoho-cookie';
const getImgHost = function(url, bucket = 'goodsimg') {
let urlArr = url.split('/'),
... ... @@ -84,9 +85,31 @@ const applySuccuss = function(type, applyId) {
modal.show();
};
const getChannel = function() {
let channel = [
{
id: 0,
en: 'men'
},
{
id: 1,
en: 'women'
}
];
yoho.ready(function() {
yoho.getChannel({}, function(val) {
val = val - 1;
cookie.set('_Channel', channel[val].en);
cookie.set('_ChannelIndex', val);
});
});
};
export default {
getImgHost,
getImgUrl,
applySuccuss,
visibilitychange
visibilitychange,
getChannel
};
... ...
... ... @@ -5,6 +5,100 @@
* @Last Modified time: 2016-08-02 17:42:26
*/
import util from 'common/util';
function ImgSrcBinding(el, binding) {
if (binding.value === binding.oldValue) {
return;
}
if (typeof binding.value === 'string') {
el.src = binding.value;
} else if (typeof binding.value === 'object') {
let {src, width, height, mode} = binding.value;
el.src = util.getImgUrl(src, width, height, mode);
}
}
function BrandHrefBinding(el, binding) {
if (binding.value === binding.oldValue) {
return;
}
if (binding.modifiers.shop) {
el.href = `/product/shop/favorite?id=${binding.value || ''}`;
} else {
el.href = `/product/shop/${binding.value}`;
}
}
function GoodHrefBinding(el, binding) {
if (binding.value === binding.oldValue) {
return;
}
let {product_id, goods_id, cn_alphabet} = binding.value;
if (!binding.modifiers.collect) {
goods_id = binding.value.goods_list.length ? binding.value.goods_list[0].goods_id : '';
}
el.href = `/product/pro_${product_id}_${goods_id}/${cn_alphabet}.html`;
}
function BlkHrefBinding(el, binding) {
let value = binding.value;
let protocol = value.match(/^(https?:)?\/\//);
protocol = protocol && protocol.length ? protocol[0] : '';
value = value.replace(protocol, '');
// 新品抢先看
let query = value.match(/^m\.yohobuy\.com\/product\/blknew(\?.*)?/);
if (query) {
query = query[1] || '';
return `${protocol}m.yohoblk.com/new${query}`;
}
// 全部品类
if (value === 'm.yohobuy.com/cate') {
return `${protocol}m.yohoblk.com/cate-all`;
}
// 全部品牌
if (value === 'm.yohobuy.com/brand' || value === 'm.yohobuy.com/brands') {
return `${protocol}m.yohoblk.com/brand`;
}
// 部分品牌
query = value.match(/^m\.yohobuy\.com\/product\/index\/brand\?(.*)?/);
query = query && query[1] || '';
if (query && query.indexOf('domain=') > -1) {
let domain = query.match(/domain=([^&]*)&?.*?/);
domain = domain[1] || '';
return `${protocol}m.yohoblk.com/product/shop/${domain}?${query}`;
}
let subDomain = value.match(/(.+)\.m\.yohobuy\.com/);
subDomain = subDomain ? subDomain[1] : '';
if (subDomain) {
if (subDomain === 'guang') {
// 逛
let editorialId = value.match(/guang\.m\.yohobuy\.com\/info\/index\?id=(\d{1,})/);
if (editorialId) {
editorialId = editorialId[1];
return `${protocol}m.yohoblk.com/editorial/${editorialId}.html`;
}
} else if (subDomain === 'list') {
// 品类
query = value.match(/\?.*/);
query = query ? query[0] : '';
return `${protocol}m.yohoblk.com/product/list${query}`;
} else {
// 品牌
query = value.match(/\?.*/);
query = query ? query[0] : '';
return `${protocol}m.yohoblk.com/product/shop/${subDomain}${query}`;
}
}
el.href = `${protocol}${value}`;
}
export default (Vue) => {
Vue.directive('lazy-html', {
... ... @@ -20,96 +114,19 @@ export default (Vue) => {
}
});
Vue.directive('img-src', {
bind(el, binding) {
if (typeof binding.value === 'string') {
el.src = binding.value;
} else if (typeof binding.value === 'object') {
let {src, width, height, mode} = binding.value;
el.src = util.getImgUrl(src, width, height, mode);
}
}
bind: ImgSrcBinding,
update: ImgSrcBinding
});
Vue.directive('brand-href', {
bind(el, binding) {
if (binding.modifiers.shop) {
el.href = `/product/shop/favorite?id=${binding.value || ''}`;
} else {
el.href = `/product/shop/${binding.value}`;
}
}
bind: BrandHrefBinding,
update: BrandHrefBinding
});
Vue.directive('good-href', {
bind(el, binding) {
let {product_id, goods_id, cn_alphabet} = binding.value;
if (!binding.modifiers.collect) {
goods_id = binding.value.goods_list.length ? binding.value.goods_list[0].goods_id : '';
}
el.href = `/product/pro_${product_id}_${goods_id}/${cn_alphabet}.html`;
}
bind: GoodHrefBinding,
update: GoodHrefBinding
});
Vue.directive('blk-href', {
bind(el, binding) {
let value = binding.value;
let protocol = value.match(/^(https?:)?\/\//);
protocol = protocol && protocol.length ? protocol[0] : '';
value = value.replace(protocol, '');
// 新品抢先看
let query = value.match(/^m\.yohobuy\.com\/product\/blknew(\?.*)?/);
if (query) {
query = query[1] || '';
return `${protocol}m.yohoblk.com/new${query}`;
}
// 全部品类
if (value === 'm.yohobuy.com/cate') {
return `${protocol}m.yohoblk.com/cate-all`;
}
// 全部品牌
if (value === 'm.yohobuy.com/brand' || value === 'm.yohobuy.com/brands') {
return `${protocol}m.yohoblk.com/brand`;
}
// 部分品牌
query = value.match(/^m\.yohobuy\.com\/product\/index\/brand\?(.*)?/);
query = query && query[1] || '';
if (query && query.indexOf('domain=') > -1) {
let domain = query.match(/domain=([^&]*)&?.*?/);
domain = domain[1] || '';
return `${protocol}m.yohoblk.com/product/shop/${domain}?${query}`;
}
let subDomain = value.match(/(.+)\.m\.yohobuy\.com/);
subDomain = subDomain ? subDomain[1] : '';
if (subDomain) {
if (subDomain === 'guang') {
// 逛
let editorialId = value.match(/guang\.m\.yohobuy\.com\/info\/index\?id=(\d{1,})/);
if (editorialId) {
editorialId = editorialId[1];
return `${protocol}m.yohoblk.com/editorial/${editorialId}.html`;
}
} else if (subDomain === 'list') {
// 品类
query = value.match(/\?.*/);
query = query ? query[0] : '';
return `${protocol}m.yohoblk.com/product/list${query}`;
} else {
// 品牌
query = value.match(/\?.*/);
query = query ? query[0] : '';
return `${protocol}m.yohoblk.com/product/shop/${subDomain}${query}`;
}
}
el.href = `${protocol}${value}`;
}
bind: BlkHrefBinding,
update: BlkHrefBinding
});
};
... ...
... ... @@ -24,6 +24,7 @@ import bus from 'common/vue-bus';
import FastClick from 'fastclick';
import directive from 'common/vue-directive';
import filter from 'common/vue-filter';
import VueTouch from 'vue-touch';
/**
* iOS 7 不支持 Promise, vue-lazyload 有用到,所以全局申明
... ... @@ -43,6 +44,7 @@ Vue.mixin({
});
directive(Vue);
filter(Vue);
Vue.use(VueTouch);
$(() => {
const $body = $('body');
... ... @@ -66,3 +68,5 @@ $(() => {
bus.$emit(eventName);
});
});
util.getChannel();
... ...
import Vue from 'vue';
import lazyload from 'vue-lazyload';
import exchange from 'me/exchange.vue';
import Component from 'me/exchange.vue';
Vue.use(lazyload, { preLoad: 3 });
new Vue(exchange);
new Vue({
el: '#exchange',
components: {
Component
}
});
... ...
import Vue from 'vue';
import infiniteScroll from 'vue-infinite-scroll';
import favArticleList from 'me/fav-article-list.vue';
import VueTouch from 'vue-touch';
import yoho from 'yoho';
Vue.use(VueTouch);
Vue.use(infiniteScroll);
yoho.ready(() => {
... ...
import Vue from 'vue';
import infiniteScroll from 'vue-infinite-scroll';
import favBrandList from 'me/fav-brand-list.vue';
import VueTouch from 'vue-touch';
import yoho from 'yoho';
Vue.use(VueTouch);
Vue.use(infiniteScroll);
yoho.ready(() => {
... ...
import Vue from 'vue';
import infiniteScroll from 'vue-infinite-scroll';
import favProductList from 'me/fav-product-list.vue';
import VueTouch from 'vue-touch';
import yoho from 'yoho';
Vue.use(VueTouch);
Vue.use(infiniteScroll);
yoho.ready(() => {
... ...
... ... @@ -2,6 +2,7 @@ import Vue from 'vue';
import home from 'me/home.vue';
import yoho from 'yoho';
yoho.ready(() => {
new Vue({
el: '#home',
... ...
import Vue from 'vue';
import prefers from 'me/prefers.vue';
import yoho from 'yoho';
import VueTouch from 'vue-touch';
Vue.use(VueTouch);
yoho.ready(() => {
new Vue({
... ...
... ... @@ -3,7 +3,6 @@ import records from 'me/records.vue';
import yoho from 'yoho';
import VueTouch from 'vue-touch';
Vue.use(VueTouch);
VueTouch.config.swipe = {
threshold: 10
};
... ...
import Vue from 'vue';
import $ from 'jquery';
import search from 'product/list/index.vue';
import Component from 'product/list/index.vue';
$(function() {
const buildOrder = function() {
return [
{
txt: '默认',
val: ''
}, {
txt: '最新',
val: 's_t_desc'
}, {
type: 'updown',
txt: '价格',
val: ['s_p_asc', 's_p_desc'] // [up, down]
},
{
type: 'updown',
txt: '折扣',
val: ['p_d_asc', 'p_d_desc']
}
];
};
let app = new Vue(search);
app.orderConfig = buildOrder();
new Vue({
el: '#product-list',
render: h => h(Component)
});
... ...
import Vue from 'vue';
import $ from 'jquery';
import search from 'product/search/index.vue';
import Component from 'product/search/index.vue';
$(function() {
const buildOrder = function() {
return [
{
txt: '默认',
val: ''
}, {
txt: '最新',
val: 's_t_desc'
}, {
type: 'updown',
txt: '价格',
val: ['s_p_asc', 's_p_desc'] // [up, down]
},
{
type: 'updown',
txt: '折扣',
val: ['p_d_asc', 'p_d_desc']
}
];
};
let app = new Vue(search);
app.$set('orderConfig', buildOrder());
new Vue({
el: '#product-search',
render: h => h(Component)
});
... ...
... ... @@ -7,13 +7,13 @@
import Vue from 'vue';
import lazyload from 'vue-lazyload';
import infinitScroll from 'vue-infinite-scroll';
import shopBox from 'product/shop/shop-box.vue';
Vue.use(lazyload, {
preLoad: 3
});
Vue.use(infinitScroll);
import shopBox from 'product/shop/shop-box.vue';
new Vue({
el: '#shop',
... ...
... ... @@ -232,6 +232,57 @@ const yoho = {
},
/**
* 联系电话
* @param args {""}
* @param success
* @param fail
*/
goTel(args, success, fail) {
if (this.isApp && window.yohoInterface) {
window.yohoInterface.triggerEvent(success || nullFun, fail || nullFun, {
method: 'go.tel',
arguments: args
});
} else {
tip(tipInfo);
}
},
/**
* 获取频道
* @param args {""}
* @param success
* @param fail
*/
getChannel(args, success, fail) {
if (this.isApp && window.yohoInterface) {
window.yohoInterface.triggerEvent(success || nullFun, fail || nullFun, {
method: 'get.channel',
arguments: args
});
} else {
}
},
/**
* 设置频道
* @param args {""}
* @param success
* @param fail
*/
setChannel(args, success, fail) {
if (this.isApp && window.yohoInterface) {
window.yohoInterface.triggerEvent(success || nullFun, fail || nullFun, {
method: 'set.channel',
arguments: args
});
} else {
tip(tipInfo);
}
},
/**
* 分享
* @param args {"title":"标题","des":"描述","img":"icon地址","url":"网页地址"}
* @param success
... ...
... ... @@ -21,302 +21,280 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-8:before {
content: "\e900";
@font-face {
font-family: "iconfont";
src: resolve("iconfont.eot?vqs6e2");
src: resolve("iconfont.eot?vqs6e2#iefix") format("embedded-opentype"), resolve("iconfont.ttf?vqs6e2") format("truetype"), resolve("iconfont.woff?vqs6e2") format("woff"), resolve("iconfont.svg?vqs6e2#iconfont") format("svg");
font-weight: normal;
font-style: normal;
}
.icon {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: "iconfont" !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-down:before {
content: "\e602";
}
.icon-check:before {
content: "\e603";
}
.icon-love:before {
content: "\e604";
}
.icon-close:before {
content: "\e605";
}
.icon-left:before {
content: "\e606";
}
.icon-right:before {
content: "\e607";
}
.icon-search:before {
content: "\e608";
}
.icon-love-solid:before {
content: "\e609";
}
.icon-focus:before {
content: "\e60c";
}
.icon-focused:before {
content: "\e60d";
}
.icon-share:before {
content: "\e60e";
}
.icon-blk:before {
content: "\e60f";
}
.icon-importedlayers:before {
content: "\e610";
}
.icon-up:before {
content: "\e617";
}
.icon-time-o:before {
content: "\e906";
}
.icon-see2:before {
content: "\e907";
}
.icon-8:before {
content: "\e908";
}
.icon-filter:before {
content: "\e901";
content: "\e909";
}
.icon-share2:before {
content: "\e902";
content: "\e90a";
}
.icon-liked:before {
content: "\e903";
content: "\e90b";
}
.icon-like:before {
content: "\e904";
content: "\e90c";
}
.icon-82:before {
content: "\e905";
content: "\e90d";
}
.icon-0:before {
content: "\e906";
content: "\e90e";
}
.icon-5:before {
content: "\e907";
content: "\e90f";
}
.icon-kuaisu:before {
content: "\e908";
content: "\e910";
}
.icon-niandu:before {
content: "\e909";
content: "\e911";
}
.icon-vip:before {
content: "\e90a";
content: "\e912";
}
.icon-youhui:before {
content: "\e90b";
content: "\e913";
}
.icon-zazhi:before {
content: "\e90c";
content: "\e914";
}
.icon-refund-exchange:before {
content: "\e90d";
content: "\e915";
}
.icon-wait-cargo:before {
content: "\e90e";
content: "\e916";
}
.icon-wait-pay:before {
content: "\e90f";
content: "\e917";
}
.icon-send-cargo:before {
content: "\e910";
content: "\e918";
}
.icon-msg:before {
content: "\e911";
content: "\e919";
}
.icon-bold-shopbag:before {
content: "\e912";
content: "\e91a";
}
.icon-notdef:before {
content: "\e913";
content: "\e91b";
}
.icon-sort-asc:before {
content: "\e914";
content: "\e91c";
}
.icon-sort-desc:before {
content: "\e915";
content: "\e91d";
}
.icon-x:before {
content: "\e916";
content: "\e91e";
}
.icon-edit-del:before {
content: "\e917";
content: "\e91f";
}
.icon-close-round:before {
content: "\e918";
content: "\e920";
}
.icon-help:before {
content: "\e919";
content: "\e921";
}
.icon-read:before {
content: "\e91a";
content: "\e922";
}
.icon-back:before {
content: "\e91b";
.icon-back2:before {
content: "\e923";
}
.icon-sort-up:before {
content: "\e91c";
content: "\e924";
}
.icon-sort-down:before {
content: "\e91d";
content: "\e925";
}
.icon-timeshare:before {
content: "\e91e";
content: "\e926";
}
.icon-more:before {
content: "\e91f";
content: "\e927";
}
.icon-noselect:before {
content: "\e920";
content: "\e928";
}
.icon-add:before {
content: "\e921";
content: "\e929";
}
.icon-message:before {
content: "\e924";
content: "\e92a";
}
.icon-delete:before {
content: "\e925";
content: "\e92b";
}
.icon-nav:before {
content: "\e926";
content: "\e92c";
}
.icon-setting:before {
content: "\e927";
content: "\e92d";
}
.icon-search2:before {
content: "\e928";
content: "\e92e";
}
.icon-email:before {
content: "\e929";
content: "\e92f";
}
.icon-battery:before {
content: "\e92a";
content: "\e930";
}
.icon-key:before {
content: "\e92b";
content: "\e931";
}
.icon-note:before {
content: "\e92c";
content: "\e932";
}
.icon-question:before {
content: "\e92d";
content: "\e933";
}
.icon-time:before {
content: "\e92e";
.icon-time2:before {
content: "\e934";
}
.icon-card:before {
content: "\e92f";
content: "\e935";
}
.icon-bag2:before {
content: "\e930";
content: "\e936";
}
.icon-logistics:before {
content: "\e931";
content: "\e937";
}
.icon-money:before {
content: "\e932";
content: "\e938";
}
.icon-document:before {
content: "\e933";
content: "\e939";
}
.icon-wifi:before {
content: "\e934";
content: "\e93a";
}
.icon-email2:before {
content: "\e935";
content: "\e93b";
}
.icon-focus2:before {
content: "\e936";
content: "\e93c";
}
.icon-shopbag:before {
content: "\e937";
content: "\e93d";
}
.icon-search3:before {
content: "\e938";
content: "\e93e";
}
.icon-position:before {
content: "\e939";
content: "\e93f";
}
.icon-onlineservice:before {
content: "\e93a";
content: "\e940";
}
.icon-seven:before {
content: "\e93b";
content: "\e941";
}
.icon-real:before {
content: "\e93c";
content: "\e942";
}
.icon-unsupport-seven:before {
content: "\e93d";
content: "\e943";
}
.icon-back-top1:before {
content: "\e93e";
content: "\e944";
}
.icon-see:before {
content: "\e945";
}
.icon-plus:before {
content: "\e900";
}
.icon-back:before {
content: "\e901";
}
.icon-choose:before {
content: "\e902";
}
.icon-minus:before {
content: "\e903";
}
.icon-brand:before {
content: "\e904";
}
.icon-shopping-bag:before {
content: "\e905";
color: #969595;
}
... ...
... ... @@ -31,7 +31,7 @@
export default {
data() {
const detaultChannel = qs.channel || cookie.get('_Channel') || 'men';
return {
category: [],
categoryResult: {},
... ... @@ -45,13 +45,12 @@
},
methods: {
getCateList() {
$.ajax({
url: '/cate/list.json'
}).then(result => {
if (result.code === 200 && result.data) {
this.$set('categoryResult', result.data);
this.$set('category', this.categoryResult[channelTrans[this.detaultChannel].key]);
this.categoryResult = result.data;
this.category = this.categoryResult[channelTrans[this.detaultChannel].key];
}
}).fail(() => {
tip('网络错误');
... ... @@ -59,12 +58,13 @@
}
},
created() {
console.log(this.getCateList)
this.getCateList();
bus.$on('channel.change', (page, channel) => {
this.$set('detaultChannel', channel || qs.channel || cookie.get('_Channel') || 'men');
this.$set('gender', channelTrans[this.detaultChannel].code);
this.$set('category', this.categoryResult[channelTrans[this.detaultChannel].key]);
this.detaultChannel = channel || qs.channel || cookie.get('_Channel') || 'men';
this.gender = channelTrans[this.detaultChannel].code;
this.category = this.categoryResult[channelTrans[this.detaultChannel].key];
});
}
};
... ...
... ... @@ -9,15 +9,25 @@
</ul>
<div class="sub-level-container">
<ul class="sub-level">
<li class="ellipsis">
<a v-if="jump" :href="`/product/list?sort=${rightAll.sortId || ''}&sort_name=全部${rightAll.categoryName || ''}&gender=${gender}`">全部{{rightAll.categoryName}}</a>
<a v-else @click="noJumpReturn(rightAll.sortId, '全部' + rightAll.categoryName)">全部{{rightAll.categoryName}}</a>
<li :class="{'sub-checked': rightAll.checked}">
<div class="block ellipsis">
<a v-if="jump" :href="`/product/list?sort=${rightAll.sortId || ''}&sort_name=全部${rightAll.categoryName || ''}&gender=${gender}`">全部{{rightAll.categoryName}}</a>
<a v-else @click="noJumpReturn(rightAll.sortId, '全部' + rightAll.categoryName, true)">全部{{rightAll.categoryName}}</a>
</div>
<div class="checked">
<i class="icon icon-check"></i>
</div>
</li>
</ul>
<ul class="sub-level">
<li v-for="sub in cateNavRightData" :key="sub.category_name" class="ellipsis">
<a v-if="jump" :href="`/product/list?sort=${sub.relation_parameter.sort}&sort_name=${sub.category_name}&gender=${gender}`">{{sub.category_name}}</a>
<a v-else @click="noJumpReturn(sub.relation_parameter.sort, sub.category_name)">{{sub.category_name}}</a>
<li v-for="(sub, index) in cateNavRightData" :key="index" :class="{'sub-checked': sub.checked}">
<div class="block ellipsis">
<a v-if="jump" :href="`/product/list?sort=${sub.relation_parameter.sort}&sort_name=${sub.category_name}&gender=${gender}`">{{sub.category_name}}</a>
<a v-else @click="noJumpReturn(sub.relation_parameter.sort, sub.category_name)">{{sub.category_name}}</a>
</div>
<div class="checked">
<i class="icon icon-check"></i>
</div>
</li>
</ul>
</div>
... ... @@ -184,30 +194,44 @@
line-height: 88px;
border-bottom: 1px solid #e6e6e6;
padding-left: 30px;
margin-right: 30px;
user-select: none;
white-space: nowrap;
overflow-y: auto;
display: flex;
&.highlight {
background: #eee;
}
&.sub-checked {
.icon {
display: inline !important;
}
}
&:hover {
background-color: #efefef;
}
}
a {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 20px;
display: inline;
color: #b0b0b0;
overflow: hidden;
text-overflow: ellipsis;
.block {
flex: 1;
}
.checked {
width: 100px;
text-align: center;
color: #000;
.icon {
display: none;
}
}
a {
color: #b0b0b0;
display: block;
width: 100%;
}
}
}
}
... ... @@ -225,6 +249,12 @@
},
gender: {
type: String
},
value: {
type: Array,
default() {
return [];
}
}
},
data() {
... ... @@ -232,11 +262,17 @@
cateNavLeftData: [], // 左侧分类数据
cateNavRightData: [], // 右侧分类数据
leftcurrent: 0, // 标记当前左侧选中条目
rightAll: {} // 全部XX
rightAll: {}, // 全部XX
currentValue: this.value
};
},
watch: {
value(val) {
this.currentValue = val;
this.categoryChangeHandler();
},
category() {
console.log('123')
this.categoryChangeHandler();
}
},
... ... @@ -244,17 +280,48 @@
cateNavLeftFun(index, categoryId, categoryName) {
this.leftcurrent = index;
this.cateNavRightData = this.cateNavLeftData[index].sub;
let allSorts = this.getAllSortId(this.cateNavRightData);
this.rightAll = {
sortId: categoryId ? categoryId : '',
categoryName: categoryName ? categoryName : ''
sortId: allSorts,
categoryName: categoryName ? categoryName : '',
checked: this.currentValue.some(cate => {
return cate.id.toString() === allSorts;
})
};
},
/* 筛选列表使用返回值 */
noJumpReturn(categoryId, categoryName) {
this.$dispatch('select', {
id: categoryId,
name: categoryName
noJumpReturn(categoryId, categoryName, isall) {
let cateIndex = this.currentValue.findIndex(cate => cate.id.toString() === categoryId);
if (cateIndex >= 0) {
this.currentValue.splice(cateIndex, 1);
} else {
this.currentValue.push({
id: categoryId,
name: categoryName
});
}
if (isall) {
this.cateNavRightData.forEach(cate => {
let cateRmIndex = this.currentValue
.findIndex(c => c.id.toString() === cate.relation_parameter.sort);
if (cateRmIndex >= 0) {
this.currentValue.splice(cateRmIndex, 1);
}
});
} else if (this.rightAll.checked) {
let cateRmIndex = this.currentValue.findIndex(c => c.id.toString() === this.rightAll.sortId);
if (cateRmIndex >= 0) {
this.currentValue.splice(cateRmIndex, 1);
}
}
this.$emit('select', {
value: this.currentValue,
subType: 'group_sort'
});
},
... ... @@ -262,17 +329,30 @@
if (!this.category || !this.category.length) {
return;
}
this.$set('cateNavLeftData', this.category);
this.$set('cateNavRightData', this.cateNavLeftData ? this.cateNavLeftData[0].sub : []);
let allSorts = this.cateNavLeftData[0].sub ?
this.cateNavLeftData[0].sub.map(sort=>sort.relation_parameter.sort).join(',') : '';
this.$set('rightAll', this.cateNavLeftData ? {
sortId: allSorts,
categoryName: this.cateNavLeftData[0].category_name
} : {});
this.cateNavLeftData = this.category;
let selectLeftCate = this.cateNavLeftData[this.leftcurrent] || {};
this.cateNavRightData = [];
this.$nextTick(() => {
this.cateNavRightData = selectLeftCate.sub;
this.cateNavRightData.forEach(cate => {
cate.checked = this.currentValue
.some(selCate =>
selCate.id.toString() === cate.relation_parameter.sort);
});
let allSorts = this.getAllSortId(this.cateNavRightData);
this.rightAll = this.cateNavLeftData ? {
sortId: allSorts,
categoryName: selectLeftCate.category_name,
checked: this.currentValue.some(cate => cate.id.toString() === allSorts)
} : {};
});
},
getAllSortId(sub) {
return sub.map(sort=>sort.relation_parameter.sort).join(',') + ',';
}
},
created() {
... ...
<template>
<div>
<!--<brand-search></brand-search>-->
<tab :page="page"></tab>
<brand-search></brand-search>
<resources :content-code.sync="contentCode"></resources>
<resources :content-code="contentCode"></resources>
<brand-list :channel="channel"></brand-list>
</div>
</template>
... ... @@ -37,6 +37,6 @@
<style>
#brand-list {
padding-top: 90px;
padding-top: 80px;
}
</style>
... ...
<template>
<div>
<div class="brand-list-box">
<div v-for="(item, index) in brandList" :key="index" class="per-brand-box">
<div class="index"><a :href="'#' + item.index" :name="item.index">{{item.index}}</a></div>
<div class="brand-big-box clearfix">
<div class="brand-box" v-for="brand in item.brands" :key="brand.name">
<a v-brand-href="brand.domain">
<div class="brand-logo">
<img v-img-src="{src: brand.logo, width: 136, height: 136}" :alt="brand.name">
</div>
<span class="brand-name">{{brand.name}}</span>
</a>
</div>
<div class="brand-list-box">
<div v-for="(item, index) in brandList" :key="index" class="per-brand-box">
<div class="index"><a :href="'#' + item.index" :name="item.index">{{item.index}}</a></div>
<div class="brand-big-box clearfix">
<div class="brand-box" v-for="brand in item.brands" :key="brand.name">
<a v-brand-href="brand.domain">
<span class="brand-name">{{brand.name}}</span>
</a>
</div>
</div>
</div>
... ... @@ -21,23 +16,32 @@
<style>
.brand-list-box {
width: 100%;
padding: 20px 0;
/* padding: 20px 0; */
background: #f6f6f6;
border-top: 1px solid #eee;
/* border-top: 1px solid #eee; */
.per-brand-box {
background: #fff;
padding: 0 30px;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
/* padding: 0 30px; */
/* border-top: 1px solid #eee; */
/* border-bottom: 1px solid #eee; */
&:not(:first-of-type) {
margin-top: 20px;
/* margin-top: 20px; */
}
.index {
height: 60px;
line-height: 60px;
background-color: #f6f6f6;
padding: 0 30px;
font-weight: bold;
a {
font-size: 32px;
... ... @@ -50,12 +54,16 @@
}
.brand-box {
width: 172px;
height: 162px;
float: left;
width: 100%;
height: 80px;
line-height: 80px;
border-bottom: 1px solid #f6f6f6;
/* float: left; */
overflow: hidden;
text-align: center;
margin-bottom: 20px;
/* text-align: center; */
.brand-logo {
margin: 0 auto;
... ... @@ -69,13 +77,24 @@
}
.brand-name {
width: 136px;
font-size: 18px;
color: #d0d0d0;
/* width: 136px; */
font-size: 24px;
color: #000;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
/* white-space: nowrap; */
/* text-overflow: ellipsis; */
display: inline-block;
padding: 0 30px;
}
a {
height: 100%;
display: inline-block;
font-weight: bold;
}
}
}
... ... @@ -95,18 +114,20 @@
data() {
return {
brandList: [],
indexList: []
indexList: [],
currentChannel: this.channel,
};
},
watch: {
channel() {
channel(val) {
this.currentChannel = val;
this.getBrandList();
}
},
methods: {
getBrandList() {
let data = {
channel: this.channel
channel: this.currentChannel
};
$.ajax({
... ... @@ -126,7 +147,8 @@
created() {
this.getBrandList();
bus.$on('channel.change', (page, channel) => {
this.channel = channel;
this.currentChannel = channel;
this.getBrandList();
});
}
};
... ...
... ... @@ -10,18 +10,22 @@
width: 100%;
height: 88px;
padding: 15px 16px;
background-color: #f6f6f6;
background-color: #fff;
text-align: center;
border-bottom: 1px solid #f6f6f6;
.input {
margin-left: auto;
margin-right: auto;
background-color: #fff;
background-color: #f6f6f6;
text-align: center;
color: #b0b0b0;
height: 56px;
line-height: 56px;
font-size: 28px;
padding: 5px 0;
/* padding: 5px 0; */
border-radius: 8px;
.search-text {
... ...
<template>
<div>
<div class="tab-top-fixed">
<tab :page="page"></tab>
</div>
<resources :content-code.sync="contentCode"></resources>
<div class="cate-res">
<brand-search></brand-search>
<tab :page="page"></tab>
<resources :content-code="contentCode"></resources>
</div>
</template>
<style>
.tab-top-fixed {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 99;
}
.resources {
margin-top: 90px;
.cate-res {
.channel-tab {
top: 88px;
}
.recommend-content-five {
margin-top: -1px;
.resources {
padding-top: 80px;
a {
height: 218px;
.recommend-content-five {
margin-top: 0;
}
}
}
... ... @@ -34,6 +27,8 @@
import tab from 'channel/tab.vue';
import resources from 'component/resources/index.vue';
import brandSearch from 'channel/brand-search.vue';
const detaultChannel = qs.channel || cookie.get('_Channel') || 'men';
... ... @@ -46,7 +41,8 @@
},
components: {
tab,
resources
resources,
brandSearch
}
};
</script>
... ...
<template>
<div v-if="channel.length" class="channel-tab">
<div class="channel ellipsis" v-for="(item, index) in channel" :key="index" :class="{focus: index === currentChannel}"
@click="changeChannel(index)" :style="{width: (1 / channel.length) * 100 + '%'}">
<span class="name">{{item.name.toUpperCase()}}</span>
@click="changeChannel(index, item.id)" :style="{width: (1 / channel.length) * 100 + '%'}">
<span class="name">{{item.name && item.name.toUpperCase()}}</span>
</div>
</div>
</template>
... ... @@ -12,12 +12,14 @@
import cookie from 'yoho-cookie';
import qs from 'yoho-qs';
import bus from 'common/vue-bus';
import yoho from 'yoho';
const channelMap = {
301: 'men',
302: 'women',
303: 'lifestyle'
};
export default {
props: {
... ... @@ -33,7 +35,7 @@
data() {
return {
channel: [],
currentChannel: this.current,
currentChannel: +cookie.get('_ChannelIndex') || 0,
};
},
created() {
... ... @@ -45,6 +47,7 @@
res.data.forEach((c, index) => {
channel.push({
id: c.channel_id,
name: c.channel_name,
channel: channelMap[c.channel_id] || ''
});
... ... @@ -60,7 +63,7 @@
});
},
methods: {
changeChannel(index) {
changeChannel(index, id) {
const objY = {};
objY[this.page + '_' + this.channel[this.current].channel] = window.scrollY;
... ... @@ -69,6 +72,10 @@
bus.$emit('channel.change', this.page, this.channel[index].channel, objY);
cookie.set('_Channel', this.channel[index].channel);
cookie.set('_ChannelIndex', index);
yoho.setChannel({
channel_id: id
});
}
},
watch: {
... ... @@ -92,7 +99,7 @@
text-align: center;
background: #fff;
transform: translate(-50%, 0);
border-bottom: 1px solid #eee;
border-bottom: 1px solid #f6f6f6;
font-family: "BrownStd", "PingFang SC", Helvetica, Roboto, "Heiti SC", "黑体", Arial;
.channel {
... ...
... ... @@ -132,7 +132,7 @@
.blk-header-left {
float: left;
font-size: 42px;
font-size: 64px;
}
.blk-header-right {
... ...
<template>
<div>
<div class="items"
<v-touch class="items"
v-if="item.show"
v-for="(item, index) in list"
:key="index"
v-touch:swipeleft="showbutton(index)"
v-touch:swiperight="hidebutton(index)"
@swipeleft="showbutton(index)"
@swiperight="hidebutton(index)"
:class="{showbtn:item.isshowbtn,xiajia:!item.status,shouwan:!item.storage}"
v-touch-options:swipe="{ direction: 'horizontal', threshold: 10}">
:swipe-options="{ direction: 'horizontal', threshold: 10}">
<div class="wrap">
<a :href="item.goodsUrl">
<img :src='item.image'>
... ... @@ -19,8 +19,8 @@
</div>
</a>
</div>
<div class="delete" v-touch:tap="deleteskn(index)"><span><i></i>删除</span></div>
</div>
<v-touch class="delete" @tap="deleteskn(index)"><span><i></i>删除</span></v-touch>
</v-touch>
</div>
</template>
<script>
... ...
<template>
<div class="add-cart" :class="cartClass">
<ul class="cart-detail">
<v-touch tag="li" @tap="pickColor">
<span class="color">{{colorName || '颜色'}}</span>
<i class="icon color" :class="sortClass('color')"></i>
</v-touch>
<v-touch tag="li" @tap="pickSize">
<span class="size">{{sizeName || '尺码'}}</span>
<i class="icon size" :class="sortClass('size')"></i>
</v-touch>
</ul>
<v-touch tag="a" class="add-btn" @tap="toCart">{{buttonText}}</v-touch>
<slide-select ref="slideSelect"
:slides="slideList"
:model="slideId"
:title="slideTitle"
:tag="slideTag"
@selected="slideSelect"
@hide="slideHide"></slide-select>
</div>
</template>
<script>
import yoho from 'yoho';
import slideSelect from './slide-select.vue';
import tip from 'common/tip';
export default {
name: 'add-to-cart',
props: {
value: {
type: Object,
default() {
return {};
}
}
},
data() {
return {
skuList: [],
slideList: [],
slideTitle: '',
slideId: 0,
slideTag: '',
colorName: '',
sizeName: '',
colorId: 0,
sizeId: 0,
sku: 0
};
},
computed: {
cartClass() {
if (this.value.storage_sum <= 0) {
return {'no-storage': true};
}
return {};
},
buttonText() {
if (this.value.storage_sum <= 0) {
return '已售罄';
}
return '加入购物车';
}
},
methods: {
sortClass(tag) {
if (this.slideTag === tag) {
return {'icon-sort-up': true};
}
if (this.slideTag === tag) {
return {'icon-sort-up': true};
}
return {'icon-sort-down': true};
},
pickColor() {
if (!yoho.isLogin()) {
return yoho.goLogin();
}
if (this.skuList.length && this.value.storage_sum > 0) {
let slides = [];
this.skuList.filter(sku => sku.storage).forEach(sku => {
if (!slides.some(slide => slide.id === sku.colorId)) {
slides.push({
text: sku.colorName,
id: sku.colorId
});
}
});
this.slideList = slides;
this.slideId = this.colorId;
this.slideTitle = '颜色';
this.slideTag = 'color';
this.$refs.slideselect.show();
}
},
pickSize() {
if (!yoho.isLogin()) {
return yoho.goLogin();
}
if (this.skuList.length && this.value.storage_sum > 0) {
let slides = [];
this.skuList.filter(sku => sku.storage).forEach(sku => {
if (!slides.some(slide => slide.id === sku.sizeId) &&
(!this.colorId || sku.colorId === this.colorId)) {
slides.push({
text: sku.sizeName,
id: sku.sizeId
});
}
});
this.slideList = slides;
this.slideId = this.sizeId;
this.slideTitle = '尺码';
this.slideTag = 'size';
this.$refs.slideselect.show();
}
},
slideSelect(params) {
if (params.tag === 'color') {
this.colorId = params.slide.id;
this.colorName = params.slide.text;
this.sizeId = 0;
this.sizeName = '';
} else {
this.sizeId = params.slide.id;
this.sizeName = params.slide.text;
}
},
processSku(goodsList) {
let skus = [];
goodsList.filter(color => color.status).forEach(color => {
color.size_list.filter(size => size.status).forEach(size => {
if (!skus.some(sku => sku.colorId === color.color_id && sku.sizeId === size.size_id)) {
skus.push({
colorId: color.color_id,
colorName: color.factory_goods_name,
sizeId: size.size_id,
sizeName: size.size_name,
sku: size.product_sku,
storage: size.storage_number,
});
}
});
});
return skus;
},
toCart() {
if (!yoho.isLogin()) {
return yoho.goLogin();
}
if (this.value.storage_sum <= 0) {
return;
}
if (!this.colorId) {
return tip('请选择颜色');
}
if (!this.sizeId) {
return tip('请选择尺码');
}
let sku = this.skuList.find(s => s.colorId === this.colorId && s.sizeId === this.sizeId);
if (sku) {
this.reset();
this.$emit('add-cart', sku);
}
},
slideHide() {
this.slideTag = '';
},
reset() {
this.colorName = '';
this.sizeName = '';
this.colorId = 0;
this.sizeId = 0;
},
},
watch: {
value(val) {
if (val) {
this.skuList = this.processSku(val.goods_list);
}
}
},
components: {slideSelect}
};
</script>
<style>
.add-cart {
&.no-storage {
.cart-detail {
color: #b0b0b0;
.icon {
display: none;
}
}
.add-btn {
background-color: #b0b0b0;
border-color: #b0b0b0;
}
}
.cart-detail {
font-size: 0;
height: 100px;
margin-bottom: 40px;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
display: flex;
li {
position: relative;
display: flex;
line-height: 100px;
height: 100px;
overflow: hidden;
font-size: 32px;
flex: 1 1 100%;
align-items: center;
justify-content: space-between;
.icon {
float: right;
font-weight: bold;
font-size: 40px;
&.icon-sort-down {
margin-top: -15px;
}
}
span {
display: block;
height: 40px;
line-height: 40px;
}
&:first-child {
padding-right: 30px;
}
&:last-child {
span {
padding-left: 30px;
border-left: solid 1px #e0e0e0;
}
}
}
}
.add-btn {
display: inline-block;
width: 100%;
height: 85px;
color: #fff;
font-size: 32px;
text-align: center;
line-height: 82px;
background-color: #000;
border: 1px solid #7a7a7a;
}
}
</style>
... ...
<template>
<div class="select-header">
<div class="title">{{title}}</div>
<a class="btn-sure" @click="selected">确定</a>
</div>
</template>
<script>
export default {
name: 'slide-select-header',
props: ['title'],
methods: {
selected() {
this.$emit('selected');
}
}
};
</script>
<style>
.select-header {
width: 100%;
height: 80px;
line-height: 80px;
border-bottom: 1px solid #e0e0e0;
font-size: 32px;
background-color: #000;
.title {
float: left;
padding-left: 25px;
color: #fff;
}
.btn-sure {
float: right;
display: block;
width: 100px;
color: #4a90e2;
text-align: center;
}
}
</style>
... ...
<template>
<v-touch class="select-swipe"
@panmove="panmove"
@panstart="panstart"
@panend="panend">
<div class="select-foucs"></div>
<ul class="select-ul"
:style="selectStyle">
<li class="item" :class="itemClass(size)" v-for="size in slides" :key="size.id">
<p>{{size.text}}</p>
</li>
</ul>
</v-touch>
</template>
<script>
export default {
name: 'slide-select-swipe',
props: {
slides: {
type: Array,
default() {
return [];
}
},
model: {
type: Number,
default: 0
}
},
data() {
return {
selectStyle: {
transform: 'translate(0, 0)',
},
transitionStyle: '',
translateY: 0,
currentIndex: 2,
itemHeight: 0,
};
},
methods: {
renderModel() {
if (this.model > 0) {
this.currentIndex = this.slides.findIndex(slide => slide.id === this.model);
} else {
if (this.slides.length > 3) {
this.currentIndex = 2;
} else {
this.currentIndex = 0;
}
}
this.$emit('change', this.slides[this.currentIndex].id);
this.$nextTick(() => {
this.itemHeight = document.querySelector('.select-ul .item').clientHeight;
this.translateY = 0 - this.currentIndex * this.itemHeight;
this.transform();
});
},
transform() {
this.selectStyle.transform = `translate(0px, ${this.translateY + this.itemHeight * 2}px)`;
this.selectStyle.transition = this.transitionStyle;
},
itemClass(slide) {
let cls = {};
let slideIndex = this.slides.findIndex(s => s === slide);
if (this.currentIndex === slideIndex) {
cls.current = true;
} else if (this.currentIndex - slideIndex === 1) {
cls['current-prev'] = true;
} else if (this.currentIndex - slideIndex === -1) {
cls['current-next'] = true;
} else if (this.currentIndex > slideIndex) {
cls.prev = true;
} else {
cls.next = true;
}
return cls;
},
panstart() {
this.originY = 0 - this.currentIndex * this.itemHeight;
this.transitionStyle = '';
this.selectStyle['will-change'] = 'transform';
this.transform();
},
panmove(e) {
this.translateY = e.deltaY / 1.5 + this.originY;
if (this.translateY > 0) {
this.currentIndex = 0;
} else {
this.currentIndex = Math.abs(Math.round(this.translateY / this.itemHeight));
if (this.currentIndex >= this.slides.length) {
this.currentIndex = this.slides.length - 1;
}
}
this.transform();
},
panend() {
this.translateY = 0 - this.currentIndex * this.itemHeight;
this.transitionStyle = 'transform 0.5s cubic-bezier(0.4, 0, 0.2, 1)';
delete this.selectStyle['will-change'];
this.$emit('change', this.slides[this.currentIndex].id);
this.transform();
},
},
watch: {
slides(val) {
this.slides = val;
this.renderModel();
}
},
};
</script>
<style>
$item-height: 68px;
.select-swipe {
width: 100%;
height: 340px;
margin-top: 46px;
position: relative;
overflow: hidden;
.select-foucs {
width: 100%;
height: $item-height;
margin-top: calc(2 * $item-height);
border-top: 1px solid #e0e0e0;
border-bottom: 1px solid #e0e0e0;
}
.select-ul {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
.item {
width: 100%;
float: left;
height: $item-height;
text-align: center;
p {
transition: transform 0.1s linear;
line-height: $item-height;
font-size: 32px;
}
&.current p {
transform: rotateX(0deg);
color: #000;
}
&.current-prev p {
transform: rotateX(10deg) translate(0, -5px);
color: #b0b0b0;
}
&.current-next p {
transform: rotateX(-10deg) translate(0, 5px);
color: #b0b0b0;
}
&.prev p {
transform: rotateX(25deg);
color: #d9d9d9;
}
&.next p {
transform: rotateX(-25deg);
color: #d9d9d9;
}
}
}
}
</style>
... ...
<template>
<div class="slide-select" :class="{active: active, 'slide-in': slideIn}">
<v-touch class="shadow" @tap="hide"></v-touch>
<div class="select-box">
<slide-select-header :title="title" @selected="selected"></slide-select-header>
<slide-select-swipe v-if="active"
:model="model"
:slides="currentSlides"
@change="slideChange"></slide-select-swipe>
</div>
</div>
</template>
<script>
import slideSelectHeader from './slide-select-header.vue';
import slideSelectSwipe from './slide-select-swipe.vue';
export default {
name: 'slide-select',
props: {
slides: {
type: Array,
default() {
return [];
}
},
model: {
type: Number,
default: 0
},
title: {
type: String,
},
tag: {
type: String,
}
},
data() {
return {
active: false,
slideIn: false,
currentSlides: this.slides,
currentModel: this.model
};
},
methods: {
show() {
this.active = true;
setTimeout(() => {
this.slideIn = true;
}, 0);
this.bodyElStyle = document.querySelector('body').style;
this.bodyElStyle.position = 'absolute';
this.bodyElStyle.top = 0;
this.bodyElStyle.left = 0;
this.bodyElStyle.right = 0;
this.bodyElStyle.bottom = 0;
this.bodyElStyle.overflow = 'hidden';
this.$emit('show', this.tag);
},
hide() {
this.slideIn = false;
setTimeout(() => {
this.active = false;
}, 200);
this.bodyElStyle.position = 'static';
this.bodyElStyle.overflow = 'auto';
this.$emit('hide', this.tag);
},
slideChange(model) {
this.currentModel = model;
},
selected() {
let currentSlide = this.currentSlides.find(slide => slide.id === this.currentModel);
this.hide();
this.$emit('selected', {slide: currentSlide, tag: this.tag });
}
},
beforeDestroy() {
this.bodyElStyle.position = 'static';
this.bodyElStyle.overflow = 'auto';
},
watch: {
slides(val) {
this.currentSlides = val;
},
model(val) {
this.model = val;
}
},
components: {
slideSelectHeader,
slideSelectSwipe,
}
};
</script>
<style>
$show-speed: 0.2s;
.slide-select {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 211;
display: none;
&.active {
display: block;
}
&.slide-in {
.shadow {
background-color: rgba(0, 0, 0, 0.2);
}
.select-box {
transform: translate(0, 0);
}
}
}
.shadow {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
background-color: rgba(0, 0, 0, 0);
transition: background-color $show-speed ease-in-out;
}
.select-box {
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 511px;
background-color: #fff;
z-index: 2;
transform: translate(0, 100%);
transition: transform $show-speed ease-in-out;
}
</style>
... ...
... ... @@ -64,7 +64,7 @@
this.overlay.show();
} else {
this.overlay.hide();
this.$set('params', {});
this.params = {};
}
}
},
... ... @@ -93,12 +93,12 @@
},
clearVals: function() {
// remove all value
this.$set('selected', {});
this.$set('params', {});
this.selected = {};
this.params = {};
},
okAction: function() {
this.$set('selected', Object.assign({}, this.selected, this.params));
this.selected = Object.assign({}, this.selected, this.params);
let filter = {};
... ...
<template>
<div class="filter-detail">
<div class="item" @click="select({id: ''})">
<div class="item-inner">所有品牌</div>
</div>
<dl v-for="key in orderKeys" :key="key">
<dt class="index" :id="key">{{key}}</dt>
<dd class="item" v-for="brand in data[key]" :key="brand.id" :class="{'active': brand.id === val}" @click="select(brand)">
<div class="filter-sub-detail">
<dl v-for="item in indexData" :key="item.index">
<dt class="index" :id="item.index">{{item.index}}</dt>
<dd class="item" v-for="brand in currentData[item.index]" :key="brand.id" :class="{'active': brand.checked}" @click="select(brand)">
<div class="item-inner">{{brand.name}}</div>
<div class="item-check">
<i class="icon icon-check"></i>
</div>
</dd>
</dl>
<index-list :index-list="indexList"></index-list>
<index-list class="filter-index-list" :index-list="indexData"></index-list>
</div>
</template>
<script>
... ... @@ -25,55 +25,82 @@
export default {
props: {
val: Number,
data: {
default: () => { return [];},
coerce(data) {
const res = {};
$.each(data, (index, brand) => {
let groupName = brand.alif;
if (!res.hasOwnProperty(groupName)) {
res[groupName] = [];
}
res[groupName].push(brand);
});
return res;
type: Array,
default() {
return [];
}
},
value: {
type: Array,
default() {
return [];
}
}
},
data() {
return {
indexList: []
indexData: [],
currentData: [],
currentValue: this.value
};
},
watch: {
},
methods: {
select: function(val) {
this.$dispatch('select', val);
value(val) {
this.currentValue = val;
this.renderData();
}
},
computed: {
orderKeys() {
let keys = [];
const self = this;
methods: {
renderData() {
const res = {};
$.each(this.data, (index, brand) => {
let groupName = brand.alif;
keys = Object.keys(this.data).sort();
self.$set('indexList', keys.map(k => {
if (!res.hasOwnProperty(groupName)) {
res[groupName] = [];
}
brand.checked = this.currentValue.some(b => b.id === brand.id);
res[groupName].push(brand);
});
this.currentData = res;
this.indexData = Object.keys(this.currentData).sort().map(k => {
return {
index: k,
name: k
};
}));
});
},
select: function(val) {
let brandIndex = this.currentValue.findIndex(brand => brand.id === val.id);
return keys;
if (brandIndex >= 0) {
this.currentValue.splice(brandIndex, 1);
} else {
this.currentValue.push({
id: val.id,
name: val.name
});
}
this.$emit('select', {
value: this.currentValue,
subType: 'brand'
});
}
},
created() {
this.renderData();
},
components: {
indexList
}
};
</script>
<style>
.filter-index-list {
top: calc(70 + 20 * 2 + 1)px;
}
</style>
... ...
<template>
<div class="ft-item">
<div class="title" @click="toggleExpand(name)">
<span class="t-text">{{name}}</span>
<i class="t-icon icon icon-add"></i>
<span class="t-val ellipsis">{{chosenVal}}</span>
</div>
<div class="choices" v-show="show">
<span v-for="(choice, index) in allChoices"
:key="index"
class="ellipsis choice" :class="{active: choice.isChosen}"
@click="toggleChoice(index, choice)">
{{name === '品类' ? choice.category_name : choice.name}}
</span>
<span v-if="showMore" class="choice more" @click="expandSub(name)">全部{{name
}}<i class="icon icon-right"></i></span>
</div>
</div>
</template>
<script>
import _ from 'lodash';
import bus from 'common/vue-bus';
const typeMap = {
品牌: 'brand',
品类: 'group_sort',
颜色: 'color',
尺寸: 'size',
价格: 'price',
折扣: 'discount'
};
export default {
props: {
name: String,
choices: Array
},
data(){
return {
chosenVal: '',
show: false,
chosen: {},
choiceName: '品牌',
showMore: false,
allChoices: [],
initialChoices: []
}
},
methods: {
toggleExpand() {
if (this.show) {
this.show = false;
return;
}
bus.$emit('expand.choice.only', this.name);
},
toggleChoice(index, choice) {
choice.isChosen = !choice.isChosen;
!choice.isChosen && (delete this.chosen[index]);
choice.isChosen && (this.chosen[index] = choice);
this.calcChosenVal();
bus.$emit('subChosen.change', typeMap[this.name], this.chosen);
},
calcChosenVal() {
let name;
let names = [];
let keys = Object.keys(this.chosen);
_.each(keys, key => {
name = this.name !== '品类' ?
this.chosen[key].name :
this.chosen[key].category_name;
names.push(name)
});
this.chosenVal = names.join(',');
},
expandSub(name){
bus.$emit('expand.subFilter', typeMap[name]);
},
setAllChoices(){
let isLimited = false;
const len = this.choices.length;
const overCut = ['品牌', '品类', '颜色', '尺寸'];
this.allChoices = this.choices.slice();
this.initialChoices = this.choices.slice();
isLimited = overCut.indexOf(this.name) > -1;
if (len > 11 && isLimited) {
this.showMore = true;
this.allChoices = this.choices.slice(0, 11);
this.initialChoices = this.choices.slice(0, 11);
}
},
clearChosenVal(){
this.show = false;
this.chosen = {};
this.chosenVal = '';
this.allChoices = this.initialChoices.slice();
bus.$emit('subChosen.change', this.name, this.chosen);
},
searchChosenVal() {
this.show = false;
},
foldExcept(name) {
this.show = this.name === name;
},
subFilterChange(sub) {
if (typeMap[this.name] === sub.subType) {
let names = [];
if (sub.value && sub.value.length) {
this.allChoices = this.initialChoices.slice();
_.each(sub.value, item => {
names.push(item.name);
_.each(this.allChoices, (choice, index) => {
const isSort = this.name === '品类';
const id = isSort ? choice.category_id : choice.id;
if (item.id === id) {
choice.isChosen = !choice.isChosen;
this.chosen[index] = choice;
}
});
});
this.show = false;
this.chosenVal = names.join(',');
}
}
}
},
created(){
this.setAllChoices();
bus.$on('chosenVal.clear', this.clearChosenVal);
bus.$on('chosenVal.search', this.searchChosenVal);
bus.$on('fold.choice.except', this.foldExcept);
bus.$on('subFilter.change', this.subFilterChange);
},
components: {}
};
</script>
<style>
@import "../../../../scss/common/_color.css";
.ft-item {
color: $black;
border-bottom: 1px solid #eee;
.title {
height: 89px;
padding: 0 30px;
font-size: 32px;
line-height: 89px;
}
.t-val {
float: right;
max-width: 280px;
font-size: 24px;
margin-right: 10px;
}
.t-text {
float: left;
}
.t-icon {
float: right;
margin-top: 28px;
font-size: 24px;
font-weight: bold;
}
.choices {
padding: 1px 30px 0!important;
overflow: hidden;
}
.choice {
position: relative;
float: left;
height: 50px;
width: 150px;
padding: 0 5px;
margin-left: 30px;
margin-bottom: 30px;
font-size: 24px;
line-height: 48px;
text-align: center;
border: 1px solid #000;
&:nth-child(4n+1) {
margin-left: 0;
}
&.active {
color: #fff;
background-color: #000;
&:after {
content: '';
width: 22px;
height: 22px;
top: 24px;
right: 0;
position: absolute;
display: inline-block;
background: resolve("product/active-mark.png");
background-size: cover;
}
}
&.more {
border: none!important;
.icon-right {
line-height: 1;
}
}
}
}
</style>
... ...
<template>
<div class="filter-sub" :class="{'filter-sub-open': isVisible}">
<c-header class="filter-sub-header" :title="type | filterCn('选择')">
<i class="icon icon-left" slot="left" @click="hide"></i>
<c-header class="filter-sub-header" :title="filterType">
<i class="icon icon-back" slot="left" @click="hide"></i>
<button class="btn-clear" slot="right" @click="clear">清空</button>
</c-header>
<div class="filter-sub-select">
<brand-filter v-if="type === 'brand'" :data="data" @select="selectItem"></brand-filter>
<normal-filter v-if="type !== 'brand' && type !== 'group_sort'" :data="data" :type="type" @select="selectItem"></normal-filter>
<sort-filter class="filter-detail filter-sort" v-if="type === 'group_sort'" :category="data" @select="selectItem"></sort-filter>
<brand-filter
v-if="subType === 'brand'"
:data="data"
:value="currentValue"
@select="selectItem"></brand-filter>
<normal-filter
v-if="subType && subType !== 'brand' && subType !== 'group_sort'"
:data="data"
:value="currentValue"
:type="subType"
@select="selectItem"></normal-filter>
<sort-filter class="filter-sub-detail filter-sort"
v-if="subType === 'group_sort'"
:value="currentValue"
:category="data"
@select="selectItem"></sort-filter>
</div>
</div>
</template>
... ... @@ -16,18 +30,75 @@
import normalFilter from './normal.vue';
import sortFilter from 'channel/brand-cate.vue';
const zhDict = {
color: '颜色',
gender: '性别',
size: '尺寸',
brand: '品牌',
priceRange: '价格',
group_sort: '品类',
discount: '折扣',
style: '风格',
ageLevel: '年龄'
};
export default {
components: {cHeader, brandFilter, normalFilter, sortFilter},
props: ['type', 'data'],
props: {
type: {
type: String,
},
data: {
type: Array,
default() {
return [];
}
},
value: {
type: Array,
default() {
return [];
}
},
},
data() {
return {
isVisible: false
isVisible: false,
subType: this.type,
currentValue: this.value,
currentData: this.data
};
},
computed: {
filterType() {
return zhDict[this.type];
}
},
watch: {
value(val) {
this.currentValue = val;
},
type(val) {
if (this.currentData.length) {
this.subType = val;
}
},
data(val) {
if (!this.subType) {
this.subType = this.type;
}
this.currentData = val;
},
},
methods: {
selectItem() {
this.hide();
return true;
selectItem(params) {
this.$emit('select', params);
},
clear() {
this.currentValue = [];
this.$emit('select', {
value: this.currentValue,
subType: this.type
});
},
hide() {
this.isVisible = false;
... ... @@ -55,43 +126,63 @@
&.filter-sub-open {
transform: translate3d(0, 0, 0);
box-shadow: 0 0 10px 0 #ccc;
}
.btn-clear {
font-size: 32px;
border: none;
width: 100px;
background-color: #fff;
}
}
.filter-detail {
$w: 30px;
list-style: none;
margin: 0;
padding: 0;
font-size: 40px;
color: $grey;
.filter-sub-detail {
-webkit-overflow-scrolling: touch;
overflow: scroll;
height: 100%;
.item,
.index {
margin-left: $w;
margin-right: $w;
border-bottom: 1px solid #eee;
color: #000;
font-size: 28px;
padding-left: 30px;
padding-right: 30px;
}
.index {
font-size: 32px;
font-weight: bold;
color: $black;
height: 60px;
line-height: 60px;
}
.item.active .item-inner {
color: $black;
height: 62px;
line-height: 62px;
background-color: #f6f6f6;
}
.item-inner {
margin-left: -$w;
margin-right: -$w;
padding: 0 $w;
font-size: 34px;
height: 102px;
line-height: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.item {
height: 82px;
line-height: 82px;
display: flex;
border-bottom: solid 1px #eee;
&.active {
.item-check {
display: block;
}
}
.item-inner {
flex: 1;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.item-check {
width: 62px;
display: none;
i {
font-weight: bold;
}
}
}
}
... ... @@ -107,22 +198,19 @@
}
}
.filter-detail {
height: 100%;
overflow: auto;
-webkit-overflow-scrolling : touch;
}
.filter-sort {
.cate-container {
margin-top: 0;
margin-top: 0 !important;
height: 100%;
}
.content {
height: 100% !important;
}
.sub-level-container {
overflow: auto;
}
}
</style>
\ No newline at end of file
</style>
... ...
<template>
<div class="top-filter clearfix" :class="{'search-page': searchPage}">
<v-touch class="filter-overlay" v-show="layFlag" @tap="close"></v-touch>
<div class="filter-content">
<ul class="filter-type">
<li class="type-item" @click="toggleRec">{{activeSort.text}}<i class="icon" :class="recClass"></i></li>
<li class="type-item" @click="toggleFilter">筛选<i class="icon" :class="filterClass"></i></li>
</ul>
<div class="rec-detail" v-show="!recDown">
<ul class="re-items">
<li v-for="(item, index) in recItems" :key="index" class="re-item"
:class="{active: activeSort.text === item.text}" @click="sortChange(item)">{{item.text}}</li>
</ul>
</div>
<div class="filter-detail" v-show="!filterDown">
<filter-item v-for="item in filterItems" :key="item.name" :name="item.name" :choices="item.choices"
v-if="item.choices.length"></filter-item>
<div class="action">
<p class="tip">您可以选择一个或多个筛选项进行筛选</p>
<v-touch tag="a" class="action-btn filter-btn" @tap="filterSearch">筛选</v-touch>
<v-touch tag="a" class="action-btn clear-btn" @tap="clearFilter">清空</v-touch>
</div>
</div>
</div>
<filter-sub :value="valueData" :type="subType"
:data="subFilterData" ref="filterSub" @select="subFilterChange"></filter-sub>
</div>
</template>
<script>
import $ from 'jquery';
import _ from 'lodash';
import bus from 'common/vue-bus';
import qs from 'yoho-qs/parse';
import FilterItem from './filter-item.vue';
import FilterSub from './filter-sub.vue';
let locationQuery = qs(decodeURIComponent(location.search.replace(/^\?/, '')));
const keyMap = {
品牌: 'brand',
品类: 'sort',
颜色: 'color',
尺寸: 'size',
价格: 'price',
折扣: 'discount'
};
const convertMap = {
brand: 'brand',
group_sort: 'sort',
color: 'color',
size: 'size',
price: 'price',
discount: 'discount',
};
export default {
props: {
val: String,
filter: Object,
searchPage: {
type: Boolean,
default: false
}
},
data(){
return {
chosen: {},
recDown: true,
filterDown: true,
recItems: [
{
text: '推荐',
val: ''
}, {
text: '新品',
val: 's_t_desc'
}, {
text: '价格从高到低',
val: 's_p_desc'
}, {
text: '价格从低到高',
val: 's_p_asc'
}
],
filterItems: [
{
name: '品牌',
choices: []
}, {
name: '品类',
choices: []
}, {
name: '颜色',
choices: []
}, {
name: '尺寸',
choices: []
}, {
name: '价格',
choices: []
}, {
name: '折扣',
choices: []
}
],
activeSort: {
text: '推荐',
order: ''
},
layFlag: false,
subType: '',
values: {
group_sort: [],
brand: [],
color: [],
size: []
},
valueData: [],
subFilterData: []
}
},
computed: {
recClass(){
return {
down: this.recDown,
'icon-sort-up': !this.recDown,
'icon-sort-down': this.recDown
}
},
filterClass(){
return {
down: this.filterDown,
'icon-sort-up': !this.filterDown,
'icon-sort-down': this.filterDown
}
}
},
methods: {
toggleRec(){
this.filterDown = true;
this.recDown = !this.recDown;
},
toggleFilter(){
this.recDown = true;
this.filterDown = !this.filterDown;
},
sortChange(item) {
const text = this.activeSort.text;
if (item.text === text) {
this.recDown = true;
return;
}
this.activeSort = item;
bus.$emit('order.change', {
val: item.val,
ref: this._uid
});
this.recDown = true;
},
showLay() {
this.bodyElStyle = document.querySelector('body').style;
this.bodyElStyle.position = 'absolute';
this.bodyElStyle.top = 0;
this.bodyElStyle.left = 0;
this.bodyElStyle.right = 0;
this.bodyElStyle.bottom = 0;
this.bodyElStyle.overflow = 'hidden';
this.layFlag = true;
},
hideLay() {
this.bodyElStyle.position = 'static';
this.bodyElStyle.overflow = 'auto';
this.layFlag = false;
},
filterSearch(){
let query;
let filter = {};
let ids = [];
let keys = [];
_.each(this.chosen, (val, key) => {
ids = [];
key = convertMap[key];
keys = Object.keys(val);
_.each(keys, v => {
if (key !== 'sort') {
ids.push(val[v].id);
} else {
ids.push(val[v].relation_parameter.sort);
}
});
if (ids.length) {
filter[key] = ids.join(',');
} else {
delete filter[key];
}
});
query = $.extend({}, locationQuery, filter);
query = $.param(query);
if (history.replaceState) {
history.replaceState({}, '', location.pathname + '?'+ query);
}
bus.$emit('fold.choice.except');
bus.$emit('filter.change', {
val: filter,
ref: this._uid
});
this.close();
},
clearFilter(){
this.chosen = {};
bus.$emit('chosenVal.clear');
},
close(){
this.layFlag = false;
this.toggleFilter();
this.bodyElStyle.position = 'static';
this.bodyElStyle.overflow = 'auto';
},
expandSub(type){
this.subType = type;
this.valueData = this.values && this.values[type];
this.subFilterData = this.filter ? this.filter[type] : {};
this.$refs.filterSub.isVisible = true;
},
subFilterChange(sub){
bus.$emit('subFilter.change', sub);
},
subChosenChange(name, chosen) {
let keyArr = Object.keys(chosen);
if (keyArr.length) {
let id, nm;
this.values[name] = [];
_.each(keyArr, key => {
id = name !== 'group_sort' ?
chosen[key].id :
chosen[key].relation_parameter.sort;
nm = name !== 'group_sort' ?
chosen[key].name :
chosen[key].category_name;
this.values[name].push({
id,
name: nm
});
});
this.chosen[name] = chosen;
} else {
this.values[name] = [];
delete this.chosen[name];
}
}
},
watch: {
recDown(val){
if (val) {
this.hideLay();
return;
} else {
this.showLay();
}
},
filterDown(val){
if (val) {
return this.hideLay();
}
this.showLay();
}
},
components: {
FilterItem,
FilterSub
},
created(){
let temp = [];
_.each(this.filter.group_sort, item => {
temp = temp.concat(item.sub);
});
this.filterItems[1].choices = temp;
this.filterItems[0].choices = this.filter.brand || [];
this.filterItems[2].choices = this.filter.color || [];
this.filterItems[3].choices = this.filter.size || [];
this.filterItems[4].choices = this.filter.priceRange || [];
this.filterItems[5].choices = this.filter.discount || [];
bus.$on('subChosen.change', this.subChosenChange);
bus.$on('expand.choice.only', name => {
bus.$emit('fold.choice.except', name);
});
bus.$on('expand.subFilter', this.expandSub);
}
};
</script>
<style>
@import "../../../../scss/common/_color.css";
.top-filter {
position: fixed;
top: 110px;
left: 0;
right: 0;
height: 81px;
z-index: 220;
border-top: 1px solid #eee;
&.search-page {
top: 0;
}
.filter-overlay {
position: fixed;
top: 121px;
left: 0;
right: 0;
bottom: 0;
opacity: .5;
background-color: #000;
}
.filter-content {
position: relative;
background-color: #fff;
}
.filter-type {
font-size: 0;
list-style: none;
height: 79px;
background-color: #fff;
padding: 16px 30px 0;
border-bottom: 1px solid #eee;
.type-item {
display: inline-block;
width: 344px;
font-size: 32px;
text-align: center;
font-weight: bold;
border-right: 1px solid $grey;
&:nth-child(2n) {
border-right: none;
}
}
.icon {
position: relative;
top: 14px;
left: 20px;
font-size: 40px;
font-weight: bold;
&.down {
top: -10px;
}
}
}
.rec-detail {
position: absolute;
top: 79px;
left: 0;
right: 0;
.re-item {
height: 90px;
color: $black;
font-size: 32px;
text-align: center;
line-height: 89px;
background-color: #fff;
border-bottom: 1px solid #eee;
&:last-child {
border-bottom: none;
}
&.active {
background: $grey;
}
}
}
.filter-detail {
position: absolute;
top: 79px;
left: 0;
right: 0;
height: auto;
max-height: 950px;
background-color: #fff;
.ft-item {
color: $black;
border-bottom: 1px solid #eee;
.title {
height: 89px;
padding: 0 30px;
font-size: 32px;
line-height: 89px;
}
.t-val {
float: right;
max-width: 280px;
font-size: 24px;
margin-right: 10px;
}
.t-text {
float: left;
}
.t-icon {
float: right;
margin-top: 28px;
font-size: 24px;
font-weight: bold;
}
.choices {
padding: 0 30px;
overflow: hidden;
}
.choice {
position: relative;
float: left;
height: 50px;
width: 150px;
padding: 0 5px;
margin-left: 30px;
margin-bottom: 30px;
font-size: 24px;
line-height: 48px;
text-align: center;
border: 1px solid #000;
&:nth-child(4n+1) {
margin-left: 0;
}
&.active {
color: #fff;
background-color: #000;
&:after {
content: '';
width: 22px;
height: 22px;
top: 24px;
right: 0;
position: absolute;
display: inline-block;
background: resolve("product/active-mark.png");
background-size: cover;
}
}
}
}
.action {
padding: 0 30px;
.tip {
padding-top: 65px;
color: #000;
font-size: 24px;
text-align: center;
}
}
.action-btn {
display: block;
font-size: 28px;
text-align: center;
&.filter-btn {
margin-top: 30px;
color: #fff;
line-height: 100px;
background-color: #000;
}
&.clear-btn {
margin: 50px auto 70px;
width: 140px;
color: #000;
line-height: 48px;
background-color: #fff;
border: 1px solid #000;
}
}
}
}
</style>
... ...
<template>
<div class="filter-detail">
<div class="item">
<div class="item-inner" @click="select({id:''})">{{type | filterCn('所有')}}</div>
</div>
<div class="item" v-for="item in data" :key="item.name" :class="{active: item.id === val}" @click="select(item)">
<div class="filter-sub-detail">
<div class="item" v-for="item in currentData" :key="item.id" :class="{active: item.checked}" @click="select(item)">
<div class="item-inner">
{{item.name}}
</div>
<div class="item-check">
<i class="icon icon-check"></i>
</div>
</div>
<slot></slot>
</div>
</template>
<script>
export default {
props: ['data', 'type', 'val'],
computed: {},
props: {
data: {
type: Array,
default() {
return [];
}
},
value: {
type: Array,
default() {
return [];
}
},
type: {
type: String
}
},
data() {
return {
currentData: [],
currentValue: this.value,
subType: this.type
};
},
created() {
this.renderData();
},
watch: {
value(val) {
this.currentValue = val;
this.renderData();
}
},
methods: {
select: function(val) {
this.$dispatch('select', val);
let itemIndex = this.currentValue.findIndex(item => item.id === val.id);
if (itemIndex >= 0) {
this.currentValue.splice(itemIndex, 1);
} else {
this.currentValue.push({
id: val.id,
name: val.name
});
}
this.$emit('select', {
value: this.currentValue,
subType: this.type
});
},
renderData() {
this.currentData = this.data.map(item => {
return {
id: item.id,
name: item.name,
checked: this.currentValue.some(val => val.id === item.id)
};
});
}
}
};
... ...
<template>
<div class="goods-box" v-infinite-scroll="fetch()" infinite-scroll-disable="disableFetch" infinite-scroll-distance="1200">
<div class="goods-box" v-infinite-scroll="fetch" infinite-scroll-disable="disableFetch" infinite-scroll-distance="1200">
<ul class="cardlist card-large clearfix">
<li class="card" v-for="(item, index) in data" :key="index">
<li class="card" v-for="(item, index) in data" :key="item.product_skn">
<div class="card-pic">
<a v-good-href="item">
<img v-img-src="{src: item.default_images, width: 372, height: 499}" :alt="item.product_name">
<img v-img-src="{src: item.default_images, width: 330, height: 440}" :alt="item.product_name">
</a>
</div>
<div class="card-bd">
<h2 class="card-label">
<a v-good-href="item" class="line-clamp-2">{{item.product_name}}</a>
<a v-good-href="item" class="line-clamp-1">{{item.product_name}}</a>
</h2>
<h2 class="card-label-desc" v-if="item.product_name1">
<a v-good-href="item" class="line-clamp-2">{{item.product_name}}</a>
<a v-good-href="item" class="line-clamp-1">{{item.product_name}}</a>
</h2>
<span class="good-price" :class="{'old-price': item.market_price}" v-if="item.market_price">¥ {{item.market_price | toFixed}}</span>
<span class="good-price" :class="{'sale-price': item.market_price}">¥ {{item.sales_price | toFixed}}</span>
<span class="good-price" :class="{'old-price': item.market_price}" v-if="item.market_price">¥ {{item.market_price | toFixed}}</span>
</div>
</li>
</ul>
... ... @@ -33,11 +33,11 @@
import Vue from 'vue';
import lazyload from 'vue-lazyload';
import infinitScroll from 'vue-infinite-scroll';
import bus from 'common/vue-bus';
Vue.use(lazyload, { preLoad: 3 });
Vue.use(infinitScroll);
import bus from 'common/vue-bus';
export default {
props: {
... ... @@ -82,17 +82,17 @@
.card {
float: left;
width: 374px;
margin-right: 2px;
width: 330px;
margin: 0 30px;
&:nth-child(2n) {
margin-right: 0;
margin: 0;
}
}
.card-pic {
width: 100%;
height: 499px;
width: 330px;
height: 440px;
a,
img {
... ... @@ -104,18 +104,14 @@
.card-bd {
min-height: 180px;
margin-left: 30px;
margin-right: 30px;
padding-top: 26px;
text-align: center;
padding-top: 40px;
font-size: 0;
}
.card-label {
margin: 0 0 14px;
margin: 0 0 30px;
font-size: 24px;
line-height: 1.4;
height: 67.1999999999px;
font-weight: normal;
}
... ... @@ -124,7 +120,7 @@
font-size: 20px;
line-height: 1.4;
height: 67.1999999999px;
font-weight: normal;
font-weight: normal;
a {
color: #888;
... ... @@ -133,7 +129,7 @@
}
.good-price {
color: #000;
color: #b0b0b0;
margin-right: 14px;
font-size: 24px;
... ... @@ -142,12 +138,13 @@
}
&.old-price {
text-decoration: line-through;
font-size: 18px;
color: #b0b0b0;
text-decoration: line-through;
}
&.sale-price {
color: #000;
color: #d0021b;
}
}
... ...
<template>
<div>
<div class='title-wrap'>{{title}}</div>
<div class="list-wrap">
<div class="item-list" v-for="item in list">
<a :href="item.goodsUrl">
<img :src="item.default_images">
<h3>{{item.product_name}}</h3>
<div class='title-wrap'>{{title}}</div>
<div class="list-wrap">
<div class="product-item" v-for="item in list" :key="item.url">
<a :href="item.url">
<a v-good-href="item">
<img v-img-src="{src: item.default_images, width: 250, height: 335}">
<p class="product-name">{{item.product_name}}</p>
</a>
<div class="price">
<span class="market" :class="{underline:item.sales_price}">¥{{item.market_price}}</span><span class="sales" v-if="item.sales_price">¥{{item.sales_price}}</span>
</div>
</a>
<div class="price">
<span class="discount" v-if="item.sales_price">¥{{item.sales_price}}</span>
<span class="market" :class="{'line-through': item.sales_price}">¥{{item.market_price}}</span>
</div>
</div>
</div>
</div>
</template>
<script>
... ... @@ -22,55 +25,59 @@
<style>
.title-wrap {
height: 80px;
font-size: 36px;
font-size: 32px;
color: #000;
text-align: center;
text-align: left;
line-height: 80px;
}
.list-wrap {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
width: 690px;
max-width: 690px;
overflow-y: hidden;
overflow-x: auto;
white-space: nowrap;
.item-list {
width: 50%;
box-sizing: border-box;
.product-item {
display: inline-block;
width: 250px;
padding: 0;
margin-right: 20px;
text-align: left;
img {
height: 500px;
width: 100%;
display: block;
}
h3 {
font-size: 26px;
margin: 26px 36px 0;
text-align: center;
.product-name {
margin-top: 20px;
max-width: 200px;
font-size: 22px;
color: #000;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
height: 75px;
}
.price {
margin-bottom: 60px;
margin-top: 5px;
text-align: center;
color: #b0b0b0;
font-size: 22px;
}
.sales {
.price .discount {
margin-top: 10px;
color: #f00;
font-size: 22px;
display: inline-block;
margin-left: 7px;
vertical-align: bottom;
}
.underline {
.price .market {
margin-left: 5px;
font-size: 18px;
margin-top: 10px;
color: #b0b0b0;
}
.line-through {
text-decoration: line-through;
}
}
... ...
<template>
<div class="shopping-bag" @click="yoho.goShopingCart()">
<div class="background"></div>
<div class="bag"></div>
<span v-if="cartCount > 0" class="number" :class="{over: cartCount > 99}">
{{cartCount > 99 ? '99+' : cartCount}}
</span>
</div>
</template>
<style>
.shopping-bag {
position: fixed;
bottom: 160px;
left: 30px;
text-align: center;
.background {
width: 108px;
height: 108px;
opacity: .3;
border-radius: 50%;
background-color: #000;
}
.bag {
position: absolute;
top: 50%;
left: 50%;
width: 48px;
height: 48px;
margin-left: -24px;
margin-top: -26px;
background: resolve("product/shopping-bag.png");
background-size: contain;
}
.number {
position: absolute;
width: 36px;
height: 36px;
top: 0;
right: 0;
color: #fff;
font-size: 20px;
line-height: 36px;
text-align: center;
border-radius: 50%;
background-color: #d0021b;
&.over {
font-size: 14px;
}
}
}
</style>
<script>
import yoho from 'yoho';
import tip from 'common/tip';
export default {
name: 'shopping-bag',
props: {
cartCount: [Number, String]
},
data() {
return {
yoho: yoho
};
}
};
</script>
... ...
... ... @@ -30,12 +30,12 @@
}
.swipe-1 {
.swipe-indicators {
.mint-swipe-indicators {
display: none;
}
}
.swipe-item {
.mint-swipe-item {
a {
display: block;
}
... ... @@ -46,13 +46,13 @@
}
}
.swipe-indicators {
.mint-swipe-indicators {
left: initial;
right: 30px;
transform: none;
}
.swipe-indicator {
.mint-swipe-indicator {
width: 16px;
height: 16px;
background: #ccc;
... ...
... ... @@ -4,9 +4,9 @@
<focus v-if="floor.focus && floor.focus_type === '1'" :floor="floor.data" :style="{height: '9.1rem'}">
<!-- 轮播图,通栏 -->
</focus>
<focus-left-right v-if="floor.focus && floor.focus_type === '2'" :floor="floor.data">
<!--<focus-left-right v-if="floor.focus && floor.focus_type === '2'" :floor="floor.data">-->
<!-- 轮播图,左右滑动 -->
</focus-left-right>
<!--</focus-left-right>-->
<title-image v-if="floor.titleImage" :floor="floor.data">
<!-- 标题图片 -->
</title-image>
... ... @@ -61,12 +61,6 @@
recommendContentFive,
goods
},
watch: {
contentCode(val) {
this.currentContentCode = val;
this.load();
}
},
methods: {
load() {
this.getResourcesData();
... ... @@ -102,7 +96,7 @@
$('#ssr').remove();
}, 1000);
}).fail(() => {
tip('网络错误');
tip('网络错误');
});
}
},
... ... @@ -124,6 +118,6 @@
<style>
.resources {
background: #f6f6f6;
background: #fff;
}
</style>
... ...
... ... @@ -19,13 +19,27 @@
a {
display: inline-block;
width: 50%;
height: 375px;
width: 46%;
/* height: 375px; */
margin-bottom: 20px;
&:nth-child(odd) {
margin-left: 2.6%;
margin-right: 1.3%;
}
&:nth-child(even) {
margin-left: 1.3%;
margin-right: 2.6%;
}
}
img {
width: 100%;
height: 100%;
/* height: 100%; */
}
}
</style>
... ...
<template>
<div class="bg" :style="bgStyle">
<div v-for="item in channel" :key="item.id" :class="item.en" @click="changeChannel(item.id)"><b>{{item.cn}}</b><span>{{item.en && item.en.toUpperCase()}}</span></div>
</div>
</template>
<style>
.bg {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
transition: all 0.6s ease 0s;
transform: translate(100%, 0);
background: resolve("me/channel_default_bg.jpg") no-repeat;
background-size: 100% 100%;
div {
font-family: "BrownStd-Bold", "PingFang SC", Helvetica, Roboto, "Heiti SC", "\9ED1\4F53", Arial;
color: #fff;
background: #000;
text-align: left;
width: 680px;
height: 105px;
line-height: 105px;
position: absolute;
left: 50%;
transform: translate(-50%, -50%);
border: none;
font-size: 38px;
padding-left: 240px;
span {
font-size: 26px;
margin-left: 20px;
}
}
}
.bg-animation {
transform: translate(0, 0);
}
.men {
width: 680px;
height: 105px;
position: absolute;
bottom: 260px;
left: 50%;
transform: translate(-50%, -50%);
border: none;
}
.women {
width: 680px;
height: 105px;
position: absolute;
bottom: 120px;
left: 50%;
transform: translate(-50%, -50%);
border: none;
}
</style>
<script>
'use strict';
import $ from 'jquery';
import util from 'common/util';
import cookie from 'yoho-cookie';
export default {
props: ['curChannel'],
data() {
return {
channel: [
{
id: 0,
cn: '男士',
en: 'men'
},
{
id: 1,
cn: '女士',
en: 'women'
}
],
bgStyle: {}
};
},
created() {
this.getResource();
},
methods: {
changeChannel(val) {
this.$emit('cv', val);
cookie.set('_Channel', this.channel[val].en);
cookie.set('_ChannelIndex', val);
},
bgChange(src) {
return `background: url(${src})`;
},
getResource() {
$.get('/channel/resources.json', {
contentCode: '5e673b5352171c1a32736ebedb3d077c'
}).then(ret => {
if (ret[0]) {
let data = ret[0].data;
let src = util.getImgUrl(data.list[0].src, data.imageWidth, data.imageHeight);
this.bgStyle = {
background: `url(${src}) no-repeat`,
backgroundSize: '100% 100%'
};
}
});
}
}
};
</script>
... ...
<template>
<ul class="list-box">
<li v-for="item in items" :key="item.index"><a class="no-intercept" :href="'#' + item.index">{{item.name}}</a></li>
<li v-for="item in items" :key="item.name"><a class="no-intercept" :href="'#' + item.index">{{item.name}}</a></li>
</ul>
</template>
<style>
... ... @@ -11,9 +11,10 @@
padding: 6px 0;
right: 0;
background: #fff;
opacity: 0.8;
opacity: 0.5;
top: 0;
overflow-y: auto;
z-index: 10;
li {
list-style: none;
... ... @@ -62,6 +63,8 @@
index: '0~9',
name: '#'
});
} else {
this.items = this.indexList;
}
}
};
... ...
<template>
<div>
<div v-if="block.text" class="text-block a" v-lazy-html="block.text.data.text">
<div>
<div v-if="block.text" class="text-block a" v-lazy-html="block.text.data.text">
</div>
<div v-if="block.singleImage">
<div v-for="(item, index) in block.singleImage.data" :key="index">
<img :title="item.title"
:alt="item.alt"
v-img-src="{src: item.src, width: 750, height: 469}"
width="375"/>
</div>
</div>
</div>
<div v-if="block.singleImage">
<div v-for="(item, index) in block.singleImage.data" :key="index">
<img :title="item.title"
:alt="item.alt"
v-img-src="{src: item.src, width: 750, height: 469}"
width="375"/>
<div v-if="block.goods" class="editor-goods-area">
<div class="editor-goods">
<ul>
<li v-for="(item, index) in block.goods.data" :key="index" v-if="item.product">
<a :href="item.product.url">
<img v-img-src="{src: item.src, width: 250, height: 334}">
<p class="title">{{item.product.product_name}}</p>
<div class="price">¥ {{item.product.sales_price | toFixed}}</div>
</a>
</li>
</ul>
</div>
</div>
</div>
</template>
<style></style>
<style>
.editor-goods-area {
position: relative;
.white-mask {
&:before {
content: "";
width: 30px;
position: absolute;
left: 0;
top: 0;
bottom: 0;
background: #fff;
z-index: 9;
}
&:after {
content: "";
width: 30px;
position: absolute;
right: 0;
top: 0;
bottom: 0;
background: #fff;
z-index: 9;
}
}
}
.editor-goods {
width: 750px;
padding: 0 30px;
box-sizing: border-box;
overflow: auto;
position: relative;
margin-bottom: 60px;
ul {
white-space: nowrap;
}
li {
width: 250px !important;
display: inline-block;
margin-right: 30px;
img {
width: 250px !important;
height: 334px;
}
.price {
width: 154px;
height: 43px;
border: 1px solid #000;
text-align: center;
line-height: 43px;
margin: 0 auto;
font-size: 24px;
}
.title {
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 24px;
line-height: 62px;
}
}
}
</style>
<script>
export default {
props: {
... ...