Authored by huzhiming

feat(二手): 添加同尺码筛选页和详情联调

<!--
* @description:
* @fileName: filter-bar.vue
* @author: huzhiming
* @date: 2019-11-22 15:34:39
* @后台人员:
* @version: v1.0.0
* @path: 页面访问路径及参数说明
!-->
<template>
<div class="filter">
<div class="filter-tab">
<div class="tab-item middle" @click="change({item,index})" v-for="(item, index) in filterDate" :key="index">
<span :class="selectIndex===index && 'selected-tab'">{{item.text}}</span>
<div v-if="item.allowSwitch" :class="!item.asc?'desc-arrow':'asc-arrow'"></div>
</div>
</div>
<div class="middle">
<div class="screen middle" @click="goFilter()">
<div class="screen-img"></div>
筛选
</div>
<div class="search-img" @click="goSearch()"></div>
</div>
</div>
</template>
<script>
// const filterDate = [{ key: '', text:'推荐', asc: null, allowSwitch: false },{ key: '', text:'价格', asc: true, allowSwitch: true }]
const filterDate = [{ key: '', text:'推荐', asc: null, allowSwitch: false },{ key: '', text:'价格', asc: true, allowSwitch: true }]
export default {
mixins: [],
props: {},
// 服务端渲染函数
async asyncData ({ isDev, route, store, env, params, query, req, res, redirect, error }) {
return {}
},
data() {
return {
selectIndex: 0,
filterDate
}
},
created() {},
mounted() {},
activated() {},
deactivated() {},
// beforeRouteEnter (to, from, next) {},
// beforeRouteUpdate(to, from, next) {},
// beforeRouteLeave(to, from, next) {},
destroyed() {},
methods: {
change({item, index}) {
this.$emit('change',item,index);
this.selectIndex=index;
item.allowSwitch!=false?item.asc=!item.asc: void 0;
// selectIndex!=index?
}
},
computed: {},
watch: {},
components: {}
};
</script>
<style rel='stylesheet/scss' lang='scss' scoped>
.filter {
width: 100%;
height: 120px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding-left: 42px;
padding-right: 38px;
z-index: 999;
background: #fff;
position: sticky;
top: 0;
}
.filter-tab {
display: flex;
flex-direction: row;
align-items: center;
font-size: 32px;
color: #999;
text-align: center;
}
.selected-tab {
color: #000;
font-weight: bold;
}
.tab-item {
margin-right: 60px;
}
.screen {
font-size: 32px;
color: #000;
letter-spacing: 0;
margin-right: 24px;
}
.middle {
display: flex;
align-items: center;
}
.asc-arrow {
width: 40px;
height: 40px;
background: url(~statics/image/list/asc_arrow@3x.png) no-repeat;
background-size: cover;
}
.desc-arrow {
width: 40px;
height: 40px;
background: url(~statics/image/list/desc_arrow@3x.png) no-repeat;
background-size: cover;
}
.price-arrow {
width: 40px;
height: 40px;
background: url(~statics/image/list/price_arrow@3x.png) no-repeat;
background-size: cover;
}
.screen-img {
width: 40px;
height: 40px;
background: url(~statics/image/list/filter@3x.png) no-repeat;
background-size: cover;
}
.product-list {
width: 100%;
background: #f5f5f5;
padding-top: 120px;
box-sizing: border-box;
position: absolute;
z-index: 0;
top: 0;
bottom: 0;
}
.search-img {
width: 40px;
height: 40px;
margin-left: 20px;
background: url(~statics/image/list/search_icon@3x.png) no-repeat;
background-size: cover;
}
.empty-wrapper {
margin: auto 0;
position: absolute;
top: 0;
bottom: 0;
}
</style>
... ...
... ... @@ -94,7 +94,7 @@ import { mapState, createNamespacedHelpers } from 'vuex';
const { mapActions } = createNamespacedHelpers('list');
import ImgSize from '../../components/img-size';
import ImgSize from '@/components/img-size';
import { Scroll } from 'cube-ui';
const filterData = [
... ...
... ... @@ -29,28 +29,27 @@
<p class="price">¥{{info.price}}</p>
<p class="size">{{info.sizeName}}</p>
</div>
<p class="name">{{info.describeInfo}}</p>
<p class="name">{{info.productName}} {{info.colorName}} {{info.describeInfo}}</p>
</div>
<div class="other-info">
<p>男款 Jordan brand</p>
<p>状况:氧化泛黄</p>
<p>{{info.gender}} {{info.brandName}}</p>
<p>状况:{{ info.shoeQualityDesc }}</p>
<p>鞋盒:{{ info.shoeBoxDesc }}</p>
<p>售出时间:{{ info.soldTime }}</p>
<p>{{ info.shoeQualityDesc }}</p>
<p>{{ info.describeInfo }}</p>
</div>
<div class="extra-card">
<img-size class='image' src="//upyun.h800.com.cn/goods/1522828276980.png!/sq/1000" :width="375" :height="375" />
<div class="middle">
<p class="name ellipsis">Air Jordan 1 Rebel 20 Chicago Air Jordan 1 Rebel 20 Chicago</p>
<p class="number ellipsis">货号 8764212-001</p>
<div class="extra-card" @click="$router.push({name: 'ProductDetail', params: { productId: info.productId } })">
<img-size class='image' :src="info.image" :width="70" :height="70" />
<div class="middle" @click="'productId'">
<p class="name ellipsis">{{ info.productName }}</p>
<p class="number ellipsis">货号 {{ info.productCode }}</p>
</div>
<span class="iconfont iconright"></span>
</div>
<div class="fixed-footer">
<cube-button class="buy active" @click="buy">购买 <span class="price">¥1209.00</span></cube-button>
</div>
</LayoutScroll>
<div class="fixed-footer">
<cube-button class="buy active" @click="buy">购买 <span class="price">¥1209.00</span></cube-button>
</div>
<Filtrate ref="filtrate" :yasParams="{P_NAME: 'XY_UFOSearchList', TYPE_ID: 1}"></Filtrate>
</LayoutApp>
</template>
... ... @@ -60,35 +59,35 @@ import { Button, Slide } from 'cube-ui';
import { mapState } from 'vuex'
import ImgSize from '@/components/img-size';
import Filtrate from './filtrate';
import Filtrate from './components/filter-list';
const info = {
"brandName": "NIKE",
"colorName": "黑色",
"describeInfo": "ggAir Jordan 4 Retro Motorsport Away BG AJ4 赛车白40839787-002g",
"gender": "男款",
"image": "",
"imageList": [
"http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/01f5f36a2ce3e935b7481a658466c574af.jpg",
"http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/0150f24aed5fe9f26df7516c9479ee39c8.jpg",
"http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/01f247d64097dfadd5d510621e9d69abc3.jpg",
"http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/01e758d028aeb48d40e656a708488844dc.jpg",
"http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/017d63f422ee227a6fa519d44d7aa27f7f.jpg",
"http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/01a15766233785ea70f2fda57e1e906ce4.jpg",
"http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/01701885a5ca6b7cf8cae2fca6c0e36795.jpg"
],
"price": "99.00",
"productCode": "TB-011-A-BLK-GLD-49",
"productId": 10014795,
"productName": "DXF测试商品",
"sechondHandTypeName": "二手",
"shoeBoxDesc": "完好",
"shoeQualityDesc": "该商品没有明显瑕疵",
"sizeName": "37 2/3码",
"soldTime": "2019.03.12",
"status": 1
}
// const info = {
// "brandName": "NIKE",
// "colorName": "黑色",
// "describeInfo": "ggAir Jordan 4 Retro Motorsport Away BG AJ4 赛车白40839787-002g",
// "gender": "男款",
// "image": "",
// "imageList": [
// "http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/01f5f36a2ce3e935b7481a658466c574af.jpg",
// "http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/0150f24aed5fe9f26df7516c9479ee39c8.jpg",
// "http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/01f247d64097dfadd5d510621e9d69abc3.jpg",
// "http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/01e758d028aeb48d40e656a708488844dc.jpg",
// "http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/017d63f422ee227a6fa519d44d7aa27f7f.jpg",
// "http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/01a15766233785ea70f2fda57e1e906ce4.jpg",
// "http://img11.static.yhbimg.com/goodsimg/2019/11/07/17/01701885a5ca6b7cf8cae2fca6c0e36795.jpg"
// ],
// "price": "99.00",
// "productCode": "TB-011-A-BLK-GLD-49",
// "productId": 10014795,
// "productName": "DXF测试商品",
// "sechondHandTypeName": "二手",
// "shoeBoxDesc": "完好",
// "shoeQualityDesc": "该商品没有明显瑕疵",
// "sizeName": "37 2/3码",
// "soldTime": "2019.03.12",
// "status": 1
// }
export default {
... ... @@ -99,6 +98,7 @@ export default {
},
// 服务端渲染函数
asyncData({store, router}) {
store.dispatch('second/fetchFilterData', { skup: router.params.skup });
return store.dispatch('second/fetchDetailById', { skup: router.params.skup });
},
data(){
... ... @@ -107,7 +107,7 @@ export default {
eventPassthrough: 'vertical'
},
info
// info
}
},
created() {},
... ... @@ -123,7 +123,7 @@ export default {
methods: {
// 购买
buy() {
this.$refs.filtrate.show();
// this.$refs.filtrate.show();
/**
* 数据埋点
... ... @@ -151,7 +151,7 @@ export default {
}
},
computed: {
// ...mapState('second', ['info'])
...mapState('second', ['info'])
},
watch: {},
components: {
... ... @@ -168,7 +168,9 @@ export default {
/* 定义局部样式,添加外围容器,scss嵌套尽量不要超过三层,会影响查找器性能 */
<style rel='stylesheet/scss' lang='scss' scoped>
@import '@/pages/product/product-detail.scss';
.second-detail-wrap {}
.second-detail-wrap {
}
.ellipsis {
white-space: nowrap;
... ... @@ -186,6 +188,8 @@ export default {
img {
display: flex;
height: 375px;
margin: 0 auto;
max-width: max-content;
}
}
.pole-dot-area {
... ... @@ -258,6 +262,8 @@ export default {
border: 1px solid #f2f2f2;
border-radius: 4px;
.image {
min-width: 140px;
min-height: 140px;
max-width: 140px;
max-height: 140px;
margin: 0 20px;
... ...
... ... @@ -12,12 +12,12 @@ export default [{
path: '/xianyu/second/list.html',
component: () => import(/* webpackChunkName: "second" */ './list')
}, {
name: 'SecondSellList',
name: 'SecondSellList', // 筛选页
path: '/xianyu/second/product/:id/selllist.html',
component: () => import(/* webpackChunkName: "second" */ './sell-list'),
props({params}) {
return {
productId: parseInt(params.productId, 10),
storageId: parseInt(params.id, 10),
};
},
}];
... ...
<!--
* @description: 同尺寸二手列表页
* @fileName: filter-list.vue
* @author: huzhiming
* @date: 2019-11-22 15:01:07
* @后台人员:
* @version: v1.0.0
* @path: 页面访问路径及参数说明 http://xianyu.yohobuy.com/xianyu/second/product/123/selllist.html
!-->
<template>
<LayoutApp :show-back="true" title="商品列表">
<LayoutApp :show-back="true" title="Nike AJ1 空军1号纯白经典休闲鞋…" class="second-filter-list-wrap">
<vFilterBar @change="filterChange" :data="filterDate"></vFilterBar>
<LayoutScroll
ref="scrolllist"
@pulling-up="fetchSkupList(isMore)"
v-if="skupList.list.length"
class="list-scroll-bg"
>
<SecondList :list="skupList.list"></SecondList>
</LayoutScroll>
</LayoutApp>
</template>
<script>
import { createNamespacedHelpers } from "vuex";
const { mapState, mapActions } = createNamespacedHelpers("second/skupList");
import SecondList from "./components/second-list";
import vFilterBar from './components/filter-bar'
const filterDate = [{ key: '', text:'推荐', asc: null, allowSwitch: false },{ key: '', text:'价格', asc: true, allowSwitch: true }]
export default {
name: 'UfoSecondSellListPage'
name: 'UfoSecondSellListPage',
watchQuery: [],
layouts: '',
head() {
return {
title: '',
meta: [{ hid: 'keywords', name: 'keywords', content: '' },{ hid: 'hid', name: 'description', content: '' }],
// link: [{ rel: 'stylesheet', href: '' }],
// script: [{ src: '' }]
}
},
mixins: [],
props: {
storageId: Number
},
// 服务端渲染函数
async asyncData ({ isDev, route, store, env, params, query, req, res, redirect, error }) {
return {}
},
data() {
return {
filterDate
}
},
created() {},
mounted() {},
activated() {
this.fetchSecondSkupList({ isReset: true });
},
deactivated() {},
// beforeRouteEnter (to, from, next) {},
// beforeRouteUpdate(to, from, next) {},
// beforeRouteLeave(to, from, next) {},
destroyed() {},
methods: {
...mapActions(["fetchSecondSkupList"]),
async fetchSkupList(isMore) {
if (this.isMore) {
await this.fetchSecondSkupList({ isReset: false });
}
},
filterChange(aa,ss) {
console.log(aa,ss);
}
},
computed: {
...mapState(["skupList", "isMore"])
},
watch: {},
components: {
vFilterBar,
SecondList
}
};
</script>
<style lang="scss" scoped>
/* 定义局部样式,添加外围容器,scss嵌套尽量不要超过三层,会影响查找器性能 */
<style rel='stylesheet/scss' lang='scss' scoped>
</style>
... ...
... ... @@ -3,10 +3,32 @@ import { get } from 'lodash';
import Vue from 'vue';
export default {
/*
* @ description: 获取商品详情
* @ author: huzhiming
* @ date: 2019-11-22 10:15:13
* @ version: v1.0.0
*/
async fetchDetailById({ commit, state }, { skup = null }) {
let { data: info = null } = await this.$api.post('/api/ufo/secondhand/productDetail', { skup });
let { data: info } = await this.$api.post('/api/ufo/secondhand/productDetail', { skup });
// console.log('[store/actions/fetchDetailById]:', info);
console.log('====', info);
commit(Types.UPDATE_PRODUCT_DETAIL, {info});
},
/*
* @ description: 获取筛选数据
* @ author: huzhiming
* @ date: 2019-11-22 14:32:46
* @ version: v1.0.0
*/
async fetchFilterData({ commit, state }, { storage_id = 10228909 }) {
let { data: { filter } } = await this.$api.post('/api/ufo/secondhand/filter', { storage_id });
console.log('[store/actions/fetchFilterData]:', JSON.stringify(filter));
commit(Types.UPDATE_PRODUCT_FILTER, { filter });
},
};
... ...
... ... @@ -8,7 +8,8 @@ export function defaultState () {
sizeName: '',
shoeBoxDesc: '',
}
},
filterList: [] // 筛选列表
};
}
import skupList from './skupList';
... ...
... ... @@ -4,5 +4,9 @@ import { find, set } from 'lodash';
export default {
[Types.UPDATE_PRODUCT_DETAIL](state, { info }) {
state.info = { ...state.info, ...info };
},
[Types.UPDATE_PRODUCT_FILTER](state, { filter }) {
state.filterList = { ...state.filterList, ...filter };
}
};
... ...
... ... @@ -49,7 +49,7 @@ export default function() {
}
let limit = 10;
const result = await this.$api.get('/api/ufo/secondhand/skupList', {page, limit});
const result = await this.$api.get('/api/ufo/secondhand/skupList', {page, limit, debug: 'XYZ'});
if (result.code === 200) {
let data = result.data;
... ...
export const UPDATE_PRODUCT_DETAIL = 'UPDATE_PRODUCT_DETAIL';
export const UPDATE_PRODUCT_FILTER = 'UPDATE_PRODUCT_FILTER';
... ...
... ... @@ -37,7 +37,7 @@ module.exports = {
assetUrl: '//m.yohobuy.com:5001/yohoapp-node/',
testCode: 'yoho4946abcdef#$%&!@',
domains,
// yohoVerifyUdid: 'ca5c462a-e28b-407d-8061-5e204398e3cc',
yohoVerifyUdid: 'ca5c462a-e28b-407d-8061-5e204398e3cc',
signExtend: {
business_line: 'yohobuy',
business_client: 'h5/xianyu',
... ...
... ... @@ -6,5 +6,15 @@ module.exports = {
params: {
skup: { type: Number } // 商品池id
},
}
},
'/api/ufo/secondhand/filter': {
ufo: true,
auth: false,
api: 'ufo.product.secondHand.list.filter',
params: {
storage_id: { type: Number }
},
},
};
... ...