Authored by zhangwenxue

商品详情:添加购买

... ... @@ -7,7 +7,7 @@
:z-index="100"
v-show="isVisible"
@mask-click="maskClick">
<transition name="cube-action-sheet-move">
<transition :name="transtion">
<div class="cube-action-sheet-panel" v-show="isVisible" @click.stop>
<slot></slot>
</div>
... ... @@ -21,11 +21,22 @@ import { Popup } from 'cube-ui';
export default {
name: 'ActionSheet',
props: {
position: {
type: String,
defaut: 'bottom',
},
},
data() {
return {
isVisible: false,
};
},
computed: {
transtion() {
return `cube-action-sheet-${this.position}`;
},
},
methods: {
show(fn) {
this.isVisible = true;
... ... @@ -69,16 +80,20 @@ export default {
background: #fff;
}
.cube-action-sheet-move-enter, .cube-action-sheet-move-leave-active {
.cube-action-sheet-bottom-enter, .cube-action-sheet-bottom-leave-active {
transform: translate3d(0, 100%, 0);
}
.cube-action-sheet-move-enter-active, .cube-action-sheet-move-leave-active {
.cube-action-sheet-right-enter, .cube-action-sheet-right-leave-active {
transform: translate3d(100%, 0, 0);
}
.cube-action-sheet-bottom-enter-active, .cube-action-sheet-bottom-leave-active,
.cube-action-sheet-right-enter-active, .cube-action-sheet-right-leave-active {
transition: all 0.3s ease-in-out;
}
/deep/ .cube-popup-mask {
opacity: 0.2;
}
</style>
... ...
<template>
<action-sheet @hidden="onActivitySheetHidden" ref="popup">
<action-sheet @hidden="onHidden" ref="popup">
<div class="activity-sheet">
<h3>活动详情</h3>
<div class="list" >
... ... @@ -38,7 +38,7 @@ export default {
});
},
methods: {
onActivitySheetHidden() {
onHidden() {
this.$emit('hidden');
},
}
... ...
<template>
<action-sheet @hidden="onHidden" position="right" ref="popup">
<div class="buy-sheet">
<div class="header">
<div class="back-wrapper flex" @touchend="onBack">
<div class="back"></div>
</div>
</div>
<div class="title">
<img-size class="title-thumbnail" :src="imageUrl" :width="300" :height="300"/>
<div>{{productDetail.product_name}} {{goodsName}}</div>
</div>
<div class="size-list">
<cube-scroll>
<ul>
<li :class="['size-item', item.available ? '': 'disable']" v-for="(item, idx) in sizeViewList" :key="idx" @click="buy(item)">
<div class="size"><span>{{item.name}}</span><span v-if="item.subName">{{item.subName}}</span></div>
<div class="price">¥ {{item.price}} <i class="cubeic-arrow"></i></div>
</li>
</ul>
</cube-scroll>
</div>
</div>
</action-sheet>
</template>
<script>
import { Scroll } from 'cube-ui';
import { get } from 'lodash';
import { createNamespacedHelpers } from 'vuex';
import ImgSize from '../../../components/img-size';
import ActionSheet from './action-sheet';
const { mapActions, mapGetters } = createNamespacedHelpers('product');
export default {
name: 'BuySheet',
components: {
ImgSize,
ActionSheet,
'cube-scroll': Scroll,
},
computed: {
...mapGetters(['productDetail']),
sizeList() {
return get(this.productDetail, 'goods_list_tabs.goods_list[0].size_list', []);
},
sizeViewList() {
return this.sizeList.map(info => {
let price;
if (info.least_price > 0) {
price = `${info.least_price}`;
} else {
price = '-';
}
const name = info.size_name.split(/\s+/);
return {
size_id: info.size_id,
name: name[0],
subName: name[1],
price,
store_id: info.storage_id,
available: info.storage_num > 0 && price !== '-',
};
});
},
imageUrl() {
return get(this.productDetail, 'goods_list[0].image_list[0].image_url', '');
},
goodsName() {
return get(this.productDetail, 'goods_list[0].goods_name', '');
},
},
mounted() {
this.$refs.popup.show();
},
methods: {
...mapActions(['updateTradeInfo']),
onHidden() {
this.$emit('hidden');
},
buy(product) {
if (!product.available) {
return;
}
this.onBack();
this.updateTradeInfo({
productId: this.productDetail.product_id,
sizeInfo: product,
}).then((data) => {
this.$router.push({
name: 'OrderBuyConfirm',
query: data,
});
});
},
onBack() {
this.$refs.popup.hide();
},
},
};
</script>
<style lang="scss" scoped>
@import "../product-detail";
.buy-sheet {
height: 100vh;
display: flex;
flex-direction: column;
position: relative;
.size-list {
flex: 1;
padding: 10px 40px;
overflow: scroll;
}
}
.title-thumbnail {
width: 140px;
height: 140px;
margin: 0 auto;
display: block;
}
.header {
width: 100%;
height: 90px;
padding-left: 40px;
padding-right: 40px;
display: flex;
justify-content: flex-end;
align-items: stretch;
box-sizing: border-box;
position: absolute;
top: 0;
.flex {
display: flex;
align-items: center;
}
.back-wrapper {
height: 100%;
}
.back {
width: 48px;
height: 48px;
background: url(~statics/image/address/close.png) no-repeat;
background-size: cover;
}
}
.title {
padding: 20px 40px 80px;
text-align: center;
font-weight: bold;
font-size: 0.9em;
border-bottom: 1px solid #ddd;
}
.size-item {
display: flex;
justify-content: space-between;
align-items: center;
color: #000;
font-size: 32px;
padding: 40px;
margin-bottom: 40px;
border-bottom: 1px solid #ddd;
.size {
line-height: 1.8;
display: flex;
font-size: 1.3em;
font-weight: bold;
align-items: baseline;
span:nth-child(2) {
font-size: 0.8em;
margin-left: 10px;
display: inline-block;
}
}
.price {
display: flex;
align-items: center;
i {
display: inline-block;
margin-left: 5px;
color: #999;
}
}
&.disable {
.size, .price {
color: #999;
}
}
}
</style>
... ...
<template>
<div class="size-list">
<cube-scroll ref="sizeselectScroll">
<ul>
<li v-for="(info, idx) in viewList"
:key="idx"
@click="toggle(info)"
:class="{selected: isSelected(info), disabled: !info.available}">
<div class="size-item">
<div class="size">
<div class="size-info"><span>{{info.name}}</span><span v-if="info.subName">{{info.subName}}</span></div>
<div class="size-price" v-if="!simplePrice">¥ {{info.price}}</div>
</div>
</div>
</li>
<li class="add-new" v-if="addSize" @click="add">
<div class="size-item">
<div class="size">
<div class="size-info"><i class="cubeic-close"></i></div>
<div class="size-price">添加尺码</div>
</div>
</div>
</li>
</ul>
</cube-scroll>
</div>
</template>
<script>
import { Scroll } from 'cube-ui';
import { sortby } from 'lodash';
export default {
name: 'size-list',
props: {
list: {
type: Array,
required: true,
},
addSize: {
type: Boolean,
default: false,
},
multiple: {
type: Boolean,
default: false,
},
selected: {
type: [Array, Object],
},
simplePrice: {
type: Boolean,
default: false,
}
},
components: {
'cube-scroll': Scroll,
},
data() {
return {
collection: {},
};
},
computed: {
viewList() {
if (!this.list || this.list.length === 0) {
return this.list || [];
}
if (!this.simplePrice) {
const list = sortby(this.list, 'order_by').reverse();
return list.map(this.priceMap);
}
return this.list.map(this.simplePriceMap);
},
},
mounted() {
this.$watch('list', () => {
this.refreshScroll();
}, {
immediate: true,
});
},
methods: {
priceMap(info) {
let price;
if (info.least_price > 0) {
price = `${info.least_price}`;
} else {
price = '-';
}
const name = info.size_name.split(/\s+/);
return {
size_id: info.size_id,
name: name[0],
subName: name[1],
price,
store_id: info.storage_id,
available: info.storage_num > 0 && price !== '-',
};
},
simplePriceMap(info) {
const name = info.text.split(/\s+/);
return {
size_id: info.id,
name: name[0],
subName: name[1],
available: info.text !== '-',
};
},
refreshScroll() {
this.$nextTick(() => {
this.$refs.sizeselectScroll.refresh();
});
},
isSelected(item) {
if (!this.multiple) {
return item.size_id === this.selected.size_id;
}
return !!this.selected && this.selected.includes(item);
},
toggle(item) {
if (!item.available) {
return;
}
let selected;
const hasSelected = this.isSelected(item);
if (!this.multiple) {
selected = hasSelected ? null : item;
} else {
if (hasSelected) {
selected = this.selected.filter(e => e !== item);
} else {
selected = [...this.selected, item];
}
}
this.$emit('select', {selected, item, isNew: !hasSelected});
},
add() {
this.$emit('add');
}
}
};
</script>
<style lang="scss" scoped>
@import "../product-detail";
.size-list {
overflow: auto;
ul {
padding-bottom: 1px;
overflow: auto;
}
}
li {
box-sizing: border-box;
width: 25%;
float: left;
border: 1px solid #999;
margin-right: -1px;
margin-bottom: -1px;
&.selected {
background: $primary-color;
.size-info {
color: #fff;
}
.size-price {
color: $sub-color;
}
}
&.disabled {
.size-info,
.size-price {
color: #ccc;
}
}
}
.size-item {
height: 0;
padding-bottom: 100%;
position: relative;
}
.size {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.size-info {
color: #000;
font-weight: bold;
font-size: 1.5em;
display: inline-block;
vertical-align: baseline;
span:not(:only-child):last-child {
font-size: 0.6em;
}
span + span {
margin-left: 10px;
}
}
.size-price {
color: #aaa;
font-size: 0.9em;
margin-top: 5px;
}
.add-new {
color: #999;
.cubeic-close {
display: inline-block;
transform: rotate(45deg);
font-weight: bold;
color: #333;
font-size: 1.2em;
}
.size-price {
font-size: 0.8em;
}
}
</style>
... ...
<template>
<action-sheet @hidden="onHidden" position="right" ref="popup">
<div class="buy-sheet">
<div class="header">
<div class="back-wrapper flex" @touchend="onBack">
<div class="back"></div>
</div>
</div>
<div class="title">
<h1>添加尺码</h1>
<h3>请选择希望添加的尺码</h3>
</div>
<size-list :list="unusedSizeList"
:multiple="true"
:simple-price="true"
:selected="selected"
@select="onSelected" />
<cube-button :disabled="!canRequest"
@click="_requestSize"><cube-loading v-if="loading"></cube-loading>提交申请</cube-button>
</div>
</action-sheet>
</template>
<script>
import { Button, Loading } from 'cube-ui';
import { get } from 'lodash';
import { createNamespacedHelpers } from 'vuex';
import LayoutApp from '../../../components/layout/layout-app';
import SizeList from './size-list';
import ActionSheet from './action-sheet';
const { mapActions, mapGetters } = createNamespacedHelpers('product');
export default {
name: 'SizeRequest',
components: {
LayoutApp,
SizeList,
ActionSheet,
'cube-button': Button,
'cube-loading': Loading,
},
data() {
return {
selected: [],
loading: false,
};
},
computed: {
...mapGetters(['productDetail']),
sizeList() {
return get(this.productDetail, 'goods_list[0].size_list', null);
},
otherSizeList() {
return get(this.productDetail, 'goods_list[0].otherSizeList', null);
},
unusedSizeList() {
return this.otherSizeList;
},
canRequest() {
return this.selected.length !== 0 && !this.loading;
},
},
mounted() {
this.$refs.popup.show();
},
methods: {
...mapActions(['requestSize']),
onHidden() {
this.$emit('hidden');
},
_requestSize() {
const sizeIds = this.selected.map(item => item.size_id).join(',');
this.requestSize({sizeIds}).then(() => {
this.$createDialog({
type: 'alert',
content: '您的尺码添加申请已提交,我们会尽快审核并通知您,请耐心等待',
confirmBtn: {
text: '我知道了'
},
onConfirm: () => {
this.onBack();
},
}).show();
this.loading = false;
}).catch(() => {
this.loading = false;
});
},
onSelected({selected}) {
this.selected = selected;
},
onBack() {
this.$refs.popup.hide();
},
},
};
</script>
<style lang="scss" scoped>
@import "../product-detail";
.buy-sheet {
height: 100vh;
display: flex;
flex-direction: column;
.size-list {
flex: 1;
padding: 10px 40px;
}
}
.header {
width: 100%;
height: 90px;
padding-left: 40px;
padding-right: 40px;
background-color: #fff;
display: flex;
align-items: stretch;
box-sizing: border-box;
.flex {
display: flex;
align-items: center;
}
.back-wrapper {
height: 100%;
width: 120px;
}
.back {
width: 48px;
height: 48px;
background: url(~statics/image/address/close.png) no-repeat;
background-size: cover;
}
}
.title {
padding: 20px 40px;
h1, h3 {
margin: 0;
font-weight: normal;
}
h1 {
font-size: 64px;
color: #000;
letter-spacing: 0.82px;
line-height: 82px;
}
h3 {
font-size: 28px;
color: #999;
letter-spacing: 0;
}
}
.cube-btn {
box-sizing: border-box;
border-radius: 0;
padding: 0;
line-height: 60px;
font-size: 14px;
background: #002b47;
&.cube-btn_disabled {
background: #999;
}
}
</style>
... ...
<template>
<action-sheet @hidden="onActivitySheetHidden" ref="popup">
<action-sheet @hidden="onHidden" ref="popup">
<div class="size-select-sheet">
<div class="select-info">
<img-size class="title-thumbnail" :src="imageList[0] && imageList[0].image_url" :width="70" :height="70"/>
<div class="product">
<div>¥{{product.least_price||''}}</div>
<div>{{goods_name}}<template v-if="goods_name && sizeName">, </template>{{sizeName}}</div>
<div class="select-size" v-if="type === 'size'">
<div class="selected-info">
<img-size class="title-thumbnail" :src="imageList[0] && imageList[0].image_url" :width="70" :height="70"/>
<div class="product">
<div>¥{{product.least_price||''}}</div>
<div>
{{goods_name}}
<template v-if="goods_name && sizeName">,</template>
{{sizeName}}
</div>
</div>
</div>
<size-list class="select-content size-list" :list="list" :addSize="canAddSize" :selected="selectedSize"
@select="onSelectSize"
@add="onAdd"></size-list>
</div>
<div class="size-select-list" >
<cube-scroll ref="sizeselectScroll">
<ul>
<li v-for="(info, idx) in viewList"
:key="idx"
@click="toggle(info)"
:class="{selected: collection[info.size_id], disabled: !info.available}">
<div class="size-item">
<div class="size">
<div class="size-info"><span>{{info.name}}</span><span v-if="info.subName">{{info.subName}}</span></div>
<div class="size-price">¥{{info.price}}</div>
<div class="select-type" v-else>
<div class="info">
<div class="back" @click="goBack"></div>
<h2>请选择出售方式</h2>
<div class="sub-title">
{{goods_name}}
<template v-if="goods_name && sizeName">,</template>
{{sizeName}}
</div>
</div>
<div class="select-content type-list">
<cube-scroll>
<div class="type-wrap" @click="selectType">
<div class="trade-type">
<div class="title">
<div class="type">现货</div>
<div class="desc">现货好价, 36小时发货</div>
</div>
</div>
</li>
<li class="add-new">
<div class="size-item" @click="add">
<div class="size">
<div class="size-info"><i class="cubeic-close"></i></div>
<div class="size-price">添加尺码</div>
<div class="price">
¥{{selectedSize.least_price}}
<i class="cubeic-arrow"></i>
</div>
</div>
</li>
</ul>
</cube-scroll>
</div>
</cube-scroll>
</div>
</div>
</div>
</action-sheet>
... ... @@ -39,9 +50,14 @@
<script>
import { Scroll } from 'cube-ui';
import { sortby, get } from 'lodash';
import { get } from 'lodash';
import { createNamespacedHelpers } from 'vuex';
import ActionSheet from './action-sheet';
import ImgSize from '../../../components/img-size';
import SizeList from './size-list';
const { mapActions, mapGetters } = createNamespacedHelpers('product');
export default {
name: 'SizeSelectSheet',
... ... @@ -57,224 +73,175 @@ export default {
product: { // 获取productId, goods_name
type: Object,
required: true,
},
multiple: {
type: Boolean,
default: false,
}
},
components: {
SizeList,
ImgSize,
'cube-scroll': Scroll,
'action-sheet': ActionSheet,
},
data() {
return {
selected: {},
collection: {
},
selectedType: {},
type: 'size',
};
},
computed: {
viewList() {
if (!this.list || this.list.length === 0) {
return this.list || [];
}
const list = sortby(this.list, 'order_by').reverse();
return list.map(info => {
let price;
if (info.least_price > 0) {
price = `¥${info.least_price}`;
} else {
price = '-';
}
const name = info.size_name.split(/\s+/);
return {
size_id: info.size_id,
name: name[0],
subName: name[1],
price,
available: info.storage_num > 0 && price !== '-',
};
});
},
...mapGetters(['selectedSize']),
goods_name() {
return get(this.product, 'goods_list[0].goods_name', '');
},
sizeName() {
if (this.selected && this.selected.name) {
return this.selected.name + '码';
if (this.selectedSize && this.selectedSize.name) {
return this.selectedSize.name + '码';
}
return null;
},
canAddSize() {
return get(this.product, 'goods_list[0].canAddSize', false);
}
},
mounted() {
this.$refs.popup.show(() => {
this.$refs.sizeselectScroll.refresh();
});
this.$refs.popup.show();
},
methods: {
onActivitySheetHidden() {
...mapActions(['updateTradeInfo']),
onHidden() {
this.$emit('hidden');
},
toggle(info) {
if (!info.available) {
return;
}
if (!this.multiple) {
if (this.collection[info.size_id]) {
this.collection = {};
this.selected = null;
} else {
this.collection = {[info.size_id]: info};
this.selected = info;
}
return;
}
if (this.collection[info.size_id]) {
// eslint-disable-next-line no-unused-vars
const {[info.size_id]: tmp, ...remain} = this.collection;
this.collection = remain;
} else {
this.collection = {...this.collection, [info.size_id]: info};
}
onSelectSize({selected: sizeInfo}) {
this.updateTradeInfo({
productId: this.product.product_id,
sizeInfo,
}).then(() => {
this.type = 'type';
});
},
add() {
onAdd() {
this.$emit('add');
}
}
},
goBack() {
this.type = 'size';
},
selectType() {
this.updateTradeInfo({
productId: this.product.product_id,
tradeTypeInfo: {tradeTypeId: 1},
}).then((data) => {
this.$emit('select', data);
});
},
},
};
</script>
<style lang="scss" scoped>
@import "../product-detail";
.size-select-sheet {
.select-size, .select-type {
display: flex;
flex-direction: column;
max-height: 60vh;
}
.size-select-list {
flex: 1;
overflow: auto;
padding: 20px;
ul {
padding-bottom: 1px;
overflow: auto;
}
height: 60vh;
padding: 0 40px;
}
li {
box-sizing: border-box;
width: 25%;
float: left;
border: 1px solid #999;
margin-right: -1px;
margin-bottom: -1px;
&.selected {
background: $primary-color;
.selected-info {
display: flex;
padding: 20px 0;
.size-info {
color: #fff;
}
.product {
margin-left: 40px;
display: flex;
flex-direction: column;
justify-content: space-evenly;
.size-price {
color: $sub-color;
div {
font-size: 24px;
color: #999;
}
}
&.disabled {
.size-info,
.size-price {
color: #ccc;
div:first-child {
font-size: 32px;
color: #000;
}
}
}
.size-item {
height: 0;
padding-bottom: 100%;
position: relative;
.title-thumbnail {
width: 140px;
height: 140px;
}
.size {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.select-content {
flex: 1;
overflow: auto;
}
.size-info {
color: #000;
font-weight: bold;
font-size: 1.5em;
display: inline-block;
vertical-align: baseline;
.select-type {
overflow: scroll;
span:last-child {
font-size: 0.6em;
.info {
position: relative;
padding: 20px 40px 40px;
text-align: center;
}
span + span {
margin-left: 10px;
.back {
position: absolute;
top: 20px;
left: 0px;
width: 48px;
height: 48px;
background: url(~statics/image/order/back@3x.png) no-repeat;
background-size: cover;
}
}
.size-price {
color: #aaa;
font-size: 0.9em;
margin-top: 5px;
}
.add-new {
color: #999;
.cubeic-close {
display: inline-block;
transform: rotate(45deg);
font-weight: bold;
color: #333;
font-size: 1.2em;
h2 {
font-size: 32px;
}
.size-price {
font-size: 0.8em;
.sub-title {
font-size: 24px;
color: #ccc;
line-height: 1.8;
}
}
.title-thumbnail {
width: 140px;
height: 140px;
}
.select-info {
.trade-type {
background: $primary-color;
display: flex;
.product {
line-height: 34px;
margin-left: 40px;
justify-content: space-between;
align-items: center;
color: #fff;
font-size: 32px;
padding: 40px;
margin-bottom: 40px;
.title {
line-height: 1.8;
}
.desc {
font-size: 24px;
color: #999;
}
.price {
display: flex;
flex-direction: column;
justify-content: space-evenly;
div {
font-size: 24px;
align-items: center;
color: $sub-color;
i {
display: inline-block;
margin-left: 5px;
color: #999;
}
div:first-child {
font-size: 32px;
color: #000;
}
}
}
.type-wrap {
overflow: scroll;
}
</style>
... ...
... ... @@ -42,15 +42,13 @@
<div class="info">
<div class="info-price">¥{{productDetail.least_price||''}}</div>
<div class="info-name">{{productDetail.product_name}}</div>
<!-- <a class="banner" :href="resource.url">-->
<!-- <img-size :src="sizeImg(resource.src)" :width="300" :height="60"/>-->
<!-- </a>-->
<a class="banner" v-if="resource" :href="resource.url">
<img-size :src="sizeImg(resource.src)" :width="300" :height="60"/>
</a>
<div class="info-list">
<div class="info-list-item">
<div class="info-list-item" v-if="activity && activity.length !== 0">
<div class="info-list-name">促销</div>
<div class="info-list-value info-promote"
v-if="activity && activity.length !== 0"
@click="showActivity"
<div class="info-list-value info-promote" @click="showActivity"
>
<span>{{activity[0].promotionTypeStr}}</span>
<i class="cubeic-arrow"></i>
... ... @@ -71,7 +69,15 @@
<cube-button class="buy" @click="buy">购买 <span>¥{{ productDetail.least_price || '-' }}</span></cube-button>
</div>
<activity-list-sheet v-if="showActivitySheet" :list="activity" @hidden="onActivitySheetHidden"/>
<size-select-sheet v-if="showSizeSelectSheet" :list="sizeList" :product="productDetail" :image-list="imageList" @hidden="onSizeSelecctSheetHidden"/>
<size-select-sheet v-if="showSizeSelectSheet"
:list="sizeList"
:product="productDetail"
:image-list="imageList"
@hidden="onSizeSelectSheetHidden"
@select="onSelectTradeProduct"
@add="onRequestSize"/>
<size-request-sheet v-if="showSizeRequestSheet" @hidden="onSizeRequestHidden"/>
<buy-sheet v-if="showBuySheet" @hidden="onBuyHidden"/>
</div>
</template>
... ... @@ -87,6 +93,8 @@ import ActivityListSheet from './components/activity-list-sheet';
import prdDetailTip from '../../statics/image/product/prdDetailTip.png';
import prdDetailImage from '../../statics/image/product/prdDetailImage.png';
import SizeSelectSheet from './components/size-select-sheet';
import SizeRequestSheet from './components/size-request-sheet';
import BuySheet from './components/buy-sheet';
const { mapActions, mapGetters } = createNamespacedHelpers('product');
... ... @@ -95,6 +103,8 @@ export default {
components: {
SizeSelectSheet,
ActivityListSheet,
SizeRequestSheet,
BuySheet,
ImgSize,
'cube-button': Button,
'cube-slide': Slide,
... ... @@ -115,6 +125,8 @@ export default {
showActivitySheet: false,
showSizeSelectSheet: false,
showSizeRequestSheet: false,
showBuySheet: false,
};
},
computed: {
... ... @@ -158,7 +170,7 @@ export default {
this.imageHideThreadhold = -window.innerWidth * 0.8;
},
methods: {
...mapActions(['fetchProductInfo', 'toggleFav']),
...mapActions(['fetchProductInfo', 'toggleFav', 'updateTradeInfo', 'getSelectedTradeProduct']),
handleScroll(e) {
this.headThumbnailVisible = e.y < this.imageHideThreadhold;
},
... ... @@ -197,17 +209,35 @@ export default {
onActivitySheetHidden() {
this.showActivitySheet = false;
},
onSizeSelecctSheetHidden() {
onSizeSelectSheetHidden() {
this.showSizeSelectSheet = false;
},
gotoProduction(productId) {
this.$router.push({name: this.$route.name, params: {productId}});
},
buy() {
this.showBuySheet = true;
},
onBuyHidden() {
this.showBuySheet = false;
},
sell() {
this.showSizeSelectSheet = true;
},
onSelectTradeProduct(tradeProduct) {
this.$router.push({
name: 'OrderSellConfirm',
query: tradeProduct
});
},
onRequestSize() {
this.showSizeSelectSheet = false;
this.showSizeRequestSheet = true;
},
onSizeRequestHidden() {
this.showSizeRequestSheet = false;
},
},
};
</script>
... ...
... ... @@ -22,30 +22,47 @@ export default {
}));
},
async toggleFav({commit}, {productId, isFav}) {
const result = await this.$api.get(`/api/ufo/product/${isFav ? 'add' : 'cancel'}`, {productId});
const result = await this.$api.get(`/api/ufo/product/${isFav ? 'add' : 'cancel'}`, {product_id: productId});
if (result.code === 200) {
if (result && result.code === 200) {
commit(Types.UPDATE_PRODUCT_FAV, {productId, isFav});
} else {
throw new Error('更新收藏失败!');
}
},
async requestSize(ctx, {productId, sizeList}) {
const result = await this.$api.get('/api/ufo/product/suggestsize', {productId, sizeList});
async updateTradeInfo({commit, state}, {productId, sizeInfo, tradeTypeInfo}) {
if (sizeInfo) {
commit(Types.UPDATE_SELECTED_RPODUCT_SIZE, {productId, sizeId: sizeInfo.size_id});
}
if (result.code !== 200) {
throw new Error('"建议请求"发送失败!');
if (tradeTypeInfo) {
commit(Types.UPDATE_SELECTED_TRADE_TYPE, {productId, tradeTypeId: tradeTypeInfo.tradeTypeId});
}
return {
productId,
sizeId: state.selectedProductInfo.sizeId,
tradeTypeId: state.selectedProductInfo.tradeTypeId,
};
},
async getSelectedTradeProduct({state, commit, dispatch}, {productId, sizeId, tradeTypeId}) {
if (state.selectedProductInfo && state.selectedProductInfo.productId === productId ||
state.products.byId[productId]) {
commit(Types.UPDATE_SELECTED_RPODUCT_SIZE, {productId, sizeId});
commit(Types.UPDATE_SELECTED_TRADE_TYPE, {productId, tradeTypeId});
return state.selectedProductInfo;
if (!(state.selectedProductInfo && state.selectedProductInfo.productId === productId ||
state.products.byId[productId])) {
await dispatch('fetchProductInfo', {productId});
}
await dispatch('fetchProductInfo', {productId});
commit(Types.UPDATE_SELECTED_RPODUCT_SIZE, {productId, sizeId});
commit(Types.UPDATE_SELECTED_TRADE_TYPE, {productId, tradeTypeId});
return state.selectedProductInfo;
},
async requestSize({state}, { sizeIds }) {
const selectedProduct = state.selectedProductInfo;
await this.$api.get('/api/ufo/product/addsize', {
product_id: selectedProduct.productId,
goods_id: get(selectedProduct.product, 'goods_list[0].goods_id'),
size_ids: sizeIds
});
// 忽略错误
},
};
... ...
... ... @@ -20,7 +20,14 @@ export default function() {
* tradeTypeId: 交易类型id
* tradeType: 交易类型
*/
selectedProductInfo: null,
selectedProductInfo: {
productId: null,
product: {},
sizeId: null,
size: {},
tradeTypeId: null,
tradeType: {},
},
},
mutations,
actions,
... ... @@ -36,6 +43,9 @@ export default function() {
},
activity(state, getters) {
return get(getters.productDetail, 'activity', []);
},
selectedSize(state) {
return state.selectedProductInfo.size;
}
}
};
... ...
... ... @@ -3,7 +3,14 @@ import {get, find } from 'lodash';
function ensureSelectedProduct(state, productId) {
if (!state.selectedProductInfo || state.selectedProductInfo.productId !== productId) {
state.selectedProductInfo = {productId, product: state.products.byId[productId]};
state.selectedProductInfo = {
productId,
product: state.products.byId[productId],
sizeId: null,
size: {},
tradeTypeId: null,
tradeType: {}
};
}
}
... ... @@ -12,6 +19,7 @@ export default {
state.products.byId[state.currentId] = null;
state.currentId = payload.product_id;
state.products.byId[state.currentId] = payload;
ensureSelectedProduct(state, state.currentId);
},
[Types.UPDATE_PRODUCT_FAV](state, { productId, isFav}) {
if (state.products.byId[productId]) {
... ... @@ -23,12 +31,12 @@ export default {
state.selectedProductInfo.sizeId = sizeId;
const sizeList = get(state.selectedProductInfo.product, 'goods_list[0].size_list', []);
state.selectedProductInfo.size = find(sizeList, (size) => size.size_id === sizeId);
state.selectedProductInfo.size = find(sizeList, (size) => size.size_id === sizeId) || {};
},
[Types.UPDATE_SELECTED_TRADE_TYPE](state, { productId, tradeTypeId}) {
ensureSelectedProduct(state, productId);
state.selectedProductInfo.tradeTypeId = tradeTypeId;
state.selectedProductInfo.tradeType = {}; // FIXME: 查询交易类型
}
},
};
... ...
... ... @@ -2,5 +2,6 @@ export const UPDATE_PRODUCT_DETAIL = 'UPDATE_PRODUCT_DETAIL';
export const UPDATE_PRODUCT_FAV = 'UPDATE_PRODUCT_FAV';
export const UPDATE_SELECTED_RPODUCT_SIZE = 'UPDATE_SELECTED_RPODUCT_SIZE';
export const UPDATE_SELECTED_TRADE_TYPE = 'UPDATE_SELECTED_TRADE_TYPE';
export const PRODUCT_REQUEST_SIZE = 'PRODUCT_REQUEST_SIZE';
... ...
... ... @@ -88,7 +88,7 @@ module.exports = {
params: {
product_id: {type: Number}, // 商品id
goods_id: {type: Number}, // 商品id
size_ids: {type: Array}, // 建议尺码id
size_ids: {type: String}, // 建议尺码id
},
},
... ...