Authored by yyq

Merge branch 'feature/scroll' into develop

Showing 45 changed files with 429 additions and 185 deletions
<template>
<CubeScroll v-if="dialogEnable" class="third-bind-wrapper">
<div v-if="dialogEnable" class="third-bind-wrapper">
<div class="bind-dialog">
<p class="bind-title">为了提供有效服务<br>请关联手机号</p>
<div class="under-row">
... ... @@ -20,12 +20,12 @@
<CubeButton class="bind-btn" :disabled="submitDisable" @click="bindSubmit">登录</CubeButton>
</div>
</div>
</CubeScroll>
</div>
</template>
<script>
import { Button, Scroll, Input } from 'cube-ui';
import { Button, Input } from 'cube-ui';
import { mapActions, mapState, mapMutations } from 'vuex';
export default {
... ... @@ -140,7 +140,6 @@ export default {
}
},
components: {
CubeScroll: Scroll,
CubeInput: Input,
CubeButton: Button
}
... ...
import LayoutApp from './layout/layout-app';
import LayoutHeader from './layout/layout-header';
import LayoutLink from './layout/layout-link';
import LayoutScroll from './layout/layout-scroll';
import Images from './images';
import YohoButton from './button';
import CountCircle from './count-circle';
... ... @@ -9,6 +10,7 @@ export default [
LayoutApp,
LayoutHeader,
LayoutLink,
LayoutScroll,
...Images,
YohoButton,
...CountCircle
... ...
<template>
<div ref="layout" class="layout">
<div
ref="layout"
class="layout"
@touchstart="webviewScrollStart"
@touchmove="webviewScrollMove"
@touchend="webviewScrollEnd">
<slot name="header">
<LayoutHeader
v-if="!hideHeader"
... ... @@ -60,14 +65,15 @@ export default {
this.touchStartY = e.changedTouches[0].pageY;
},
webviewScrollMove(e) {
if (this.isTouchStart && !this.isStop) {
if (this.isTouchStart && this.isStop) {
let scrollTop = this.$refs.layout.scrollTop;
this.touchMoveY = e.changedTouches[0].pageY;
if (scrollTop <= 0 && this.touchMoveY > this.touchStartY) {
e.stopPropagation();
e.preventDefault();
e.stopPropagation && e.stopPropagation();
e.preventDefault && e.preventDefault();
}
}
... ...
<template>
<div class="layout-scroll">
<div class="layout-scroll-main" ref="scroll">
<slot></slot>
<div v-if="loading && !loading.hide" class="loading">
<p v-if="loading.noMore" class="load-text">没有更多了</p>
<Loading v-else :size="20"></Loading>
</div>
</div>
</div>
</template>
<script>
import {throttle} from 'lodash';
import {Loading} from 'cube-ui';
const EVENT_SCROLL = 'scroll';
export default {
name: 'LayoutScroll',
data() {
return {
noMore: false
};
},
props: {
loading: Object
},
mounted() {
this._forceUpdate = throttle(this.forceUpdate.bind(this), 500);
this._onPullingUp = throttle(this.onPullingUp.bind(this), 1000);
let supportsPassive = false;
try {
const opts = Object.defineProperty({}, 'passive', {
get() {
supportsPassive = true;
return true;
}
});
window.addEventListener('test', null, opts);
} catch (e) {} //eslint-disable-line
this.$el.addEventListener(EVENT_SCROLL, this.onScroll, supportsPassive ? { passive: true } : false);
},
beforeDestroy() {
this.$el.removeEventListener(EVENT_SCROLL, this.onScroll);
},
methods: {
scrollTo() {
let top = arguments[1] || arguments[0];
this.$el.scrollTop = Math.abs(top);
},
onScroll() {
let top = this.$el.scrollTop;
if (this.lastTop === top) {
return;
}
this._forceUpdate();
this.lastTop = top;
this.$emit('scroll', {y: -top});
this.scrollTimer && clearTimeout(this.scrollTimer);
this.scrollTimer = setTimeout(this.onScrollEnd.bind(this), 400);
if (this.scrollHeight - top < this.$el.offsetHeight * 2) {
this._onPullingUp();
}
},
onScrollEnd() {
this.$emit('scroll-end', {y: -this.$el.scrollTop});
},
onPullingUp() {
this.$emit('pulling-up');
},
forceUpdate() {
this.scrollHeight = this.$refs.scroll.offsetHeight;
}
},
components: {
Loading
}
};
</script>
<style lang="scss" scoped>
.layout-scroll {
height: 100%;
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
position: relative;
z-index: 0;
}
.layout-scroll-main {
min-height: 100%;
}
.loading {
padding: 20px 0;
line-height: 40px;
text-align: center;
/deep/ .cube-loading-spinners {
margin: auto;
}
}
</style>
... ...
... ... @@ -2,7 +2,7 @@
<div class="address-select-component">
<div class="address-select-box">
<div class="component-title">
<span class="title">所在地区</span>
<span class="title">选择地区</span>
<span class="icon-close close" @click="closeAddBox"></span>
</div>
... ... @@ -35,6 +35,7 @@
<li
v-for="(pprovince, index) in provinces"
:key="index"
:class="{active: pprovince.id === province.id}"
@click="switchAddress(pprovince.id, pprovince.caption)"
>
{{pprovince.caption}}
... ... @@ -45,6 +46,7 @@
<li
v-for="(pcity, index) in citys"
:key="index"
:class="{active: pcity.id === city.id}"
@click="switchAddress(pcity.id, pcity.caption)"
>
{{pcity.caption}}
... ... @@ -55,6 +57,7 @@
<li
v-for="(parea, index) in areas"
:key="index"
:class="{active: parea.id === area.id}"
@click="switchAddress(parea.id, parea.caption)"
>
{{parea.caption}}
... ... @@ -65,6 +68,7 @@
<li
v-for="(pstreet, index) in streets"
:key="index"
:class="{active: pstreet.id === street.id}"
@click="switchAddress(pstreet.id, pstreet.caption)"
>
{{pstreet.caption}}
... ... @@ -417,9 +421,10 @@ export default {
.component-title {
text-align: center;
line-height: 80px;
font-size: 32px;
color: #ccc;
line-height: 88px;
font-size: 34px;
font-weight: bold;
color: #000;
padding: 0 30px;
.close {
... ... @@ -429,26 +434,26 @@ export default {
.icon-close {
height: 40px;
width: 40px;
margin-top: 20px;
margin-top: 24px;
background: url("~statics/image/address/close.png");
background-size: cover;
}
}
.head-address-ul {
margin: 0 0 0 30px;
padding: 0;
margin: 0 0 0 30px;
list-style: none;
overflow: hidden;
background-color: white;
font-size: 24px;
color: #444;
font-size: 28px;
color: #999;
li {
display: block;
float: left;
height: 40px;
line-height: 40px;
height: 60px;
font-size: 28px;
line-height: 60px;
position: relative;
margin-right: 70px;
}
... ... @@ -458,13 +463,12 @@ export default {
}
.head-address-li {
color: #f23030;
color: #000;
}
.head-address-li:after {
width: 100%;
height: 1px;
border-bottom: 2px solid #f23030;
border-bottom: 4px solid #000;
position: absolute;
bottom: 0;
left: 0;
... ... @@ -472,24 +476,12 @@ export default {
}
}
.head-address-ul:after {
content: "";
width: 100%;
height: 1px;
position: absolute;
border-bottom: 1px solid #e3e5e9;
left: 0;
bottom: 0;
transform: scaleY(0.5);
-webkit-transform: scaleY(0.5);
}
.address-container {
margin: 0;
overflow: hidden;
height: 100%;
width: 100%;
border-top: solid 1px #ccc;
border-top: solid 1px #eee;
.address-content {
transform: translate(0, 0) translateZ(0);
... ... @@ -503,8 +495,8 @@ export default {
list-style: none;
height: 100%;
overflow: auto;
font-size: 24px;
color: #232326;
font-size: 28px;
color: #999;
justify-content: center;
li {
... ... @@ -516,6 +508,12 @@ export default {
display: flex;
align-items: center;
&.active {
font-size: 36px;
color: #000;
font-weight: bold;
}
.icon-check {
display: inline-block;
margin-left: 18px;
... ... @@ -526,17 +524,6 @@ export default {
background-size: 100% 100%;
}
}
li:after {
content: "";
width: 100%;
height: 1px;
position: absolute;
left: 0;
bottom: 0;
transform: scaleY(0.5);
-webkit-transform: scaleY(0.5);
}
}
}
}
... ...
... ... @@ -140,6 +140,8 @@ export default {
<style lang="scss" scoped>
.input-label {
font-size: 36px;
color: #000;
font-family: 'PingFang-SC-Regular';
display: inline-block;
font-weight: bold;
}
... ... @@ -150,7 +152,9 @@ export default {
.wrapper-input {
font-size: 28px;
color: #000;
width: 100%;
font-family: 'SFProText-Regular';
/*line-height: 1;*/
line-height: normal;
}
... ...
<template>
<LayoutApp class="yohoufo-channel-page" :show-back="true" :hide-header="hideHeader" :title="title">
<div class="fixed-nav scroll-nav-wrap" v-if="isShow && navList.length">
<ScrollNav :list="navList" :current="active" @transfer="getIndex" style="background: #f2f2f2;"></ScrollNav>
<LayoutApp class="yohoufo-channel-page" :show-back="true" :hide-header="hideHeader" :title="title" :isStop="isStop">
<div class="fixed-nav scroll-nav-wrap" v-if="navList.length" v-show="isShow">
<ScrollNav :list="navList" :current="active" @transfer="getIndex"></ScrollNav>
</div>
<Scroll
<LayoutScroll
ref="scroll"
class="channel-scroll"
:scroll-events="scrollEvents"
@scroll="scrollHandler"
@scroll-end="scrollEndHandler"
:options="options"
@pulling-up="onPullingUp"
:data="productList.list">
@pulling-up="onPullingUp" >
<div class="channel-body" ref="body">
<div ref="topSource" class="channel-html">
<div class="search-header middle" @click="goSearch">
... ... @@ -25,15 +22,15 @@
<TwoBanner :list="item.data" :ref="index" :PAGE_URL="PAGE_URL" :key="index" v-if="item.template_name == 'twoPicture'"/>
</template>
</div>
<div ref="scrollNav" class="scroll-nav-wrap" v-if="!isShow && navList.length">
<div ref="scrollNav" class="scroll-nav-wrap" v-if="navList.length">
<ScrollNav :list="navList" :current="active" @transfer="getIndex"></ScrollNav>
</div>
<div class="list-wrap" :style="{minHeight: total + 'px'}">
<div class="list-wrap">
<ProductList ref="product" :list="productList.list" :yasParams="listYasParams" v-if="productList.list.length > 0"></ProductList>
<UfoNoItem class="channel-no-item" :tip="`暂无数据`" v-else></UfoNoItem>
</div>
</div>
</Scroll>
</LayoutScroll>
</LayoutApp>
</template>
... ... @@ -106,13 +103,18 @@ export default {
page: null, // 当前页号
coupon_token: null, // 优惠券token
},
selectedCategory: {}
selectedCategory: {},
height: 0,
isA: false,
};
},
computed: {
...mapState(['channelList']),
navList() {
return get(find(this.channelList.list, ['template_name', 'guessLike']), 'data') || [];
},
isStop() {
return this.scrollY < 10;
}
},
watch: {
... ... @@ -126,10 +128,13 @@ export default {
}
},
activated() {
this.$refs.scroll && this.scrollY && this.$refs.scroll.scrollTo(this.scrollY);
if (!this.channelList.list || !this.channelList.list.length) {
this.fetchChannelList();
}
this.init();
this.PAGE_URL = window.location.href;
// 首页进入上报
this.$store.dispatch('reportYas', {
... ... @@ -249,7 +254,7 @@ export default {
this.selectedCategory = params;
this.setYasParam({index,...params});
this.active = Number(index);
this.$refs.scroll.scrollTo(0, -this.navTop, 300);
this.isShow && this.$refs.scroll.scrollTo(0, -this.navTop, 300);
},
scrollEndHandler({y}) {
let scrollHeight = Math.abs(y)
... ... @@ -257,15 +262,15 @@ export default {
this.$refs.product && this.$refs.product.yasShowEvent(scrollHeight+this.navTop);
},
scrollHandler({ y }) {
this.scrollY = -y;
if (this.navTop) {
let scrollY = -y;
// console.log(parseInt(scrollY));
// console.log(this.navTop);
if (scrollY >= this.navTop) {
if (this.scrollY >= this.navTop) {
this.isShow = true;
// this.isA = false;
} else {
this.isShow = false;
// this.isA = true;
}
}
},
... ... @@ -354,11 +359,6 @@ export default {
name: 'Search',
});
},
// getParams(params) {
// this.reportParams = params;
// console.log(this.reportParams);
// }
},
components: {
Swiper,
... ... @@ -401,10 +401,6 @@ export default {
background-color: #fefefe;
overflow: hidden;
}
&.fixed-nav:after {
display: none;
}
}
.channel-scroll {
... ... @@ -508,4 +504,7 @@ input::-webkit-input-placeholder {
background: url(~statics/image/list/searchPage_icon@3x.png) no-repeat;
background-size: cover;
}
.class-a {
padding-top: 104px;
}
</style>
... ...
... ... @@ -19,7 +19,7 @@ export default {
return {
isUnionType: false,
shareUrl:
"https://activity.yoho.cn/feature/5475.html?share_id=8169&title=新人礼遇"
"https://activity.yoho.cn/feature/5475.html?share_id=8169&title=新人礼遇&nodownload=1"
};
},
mounted() {
... ...
... ... @@ -11,10 +11,9 @@
@click="onChangeList('overtime')">已失效{{overtime.total && '('+ overtime.total + ')' || null}}
</div>
</div>
<Scroll ref="couponlist"
<LayoutScroll ref="couponlist"
class="coupon-list"
:options="scrollOptions"
:data="list"
:loading="loadingOptions"
@pulling-up="onPullingUp" v-show="!showEmpty">
<div class="item" v-for="(item,index) in list">
<div :class="type === 'unused' ? 'item-bg' : 'item-gray-bg'">
... ... @@ -48,7 +47,7 @@
</div>
</div>
</div>
</Scroll>
</LayoutScroll>
<div
class="empty-wrapper"
v-show="showEmpty"
... ... @@ -61,7 +60,6 @@
<script>
import {Scroll} from 'cube-ui';
import {createNamespacedHelpers} from 'vuex';
import EmptyList from '../../../components/ufo-no-item';
... ... @@ -69,7 +67,7 @@ const {mapState, mapActions} = createNamespacedHelpers('home/coupon');
export default {
name: 'Coupon',
components: {Scroll, EmptyList},
components: {EmptyList},
activated: function() {
this.type = 'unused';
this.fetchCouponList({type: 'unused', isReset: true}).then(r=>{
... ... @@ -90,7 +88,7 @@ export default {
},
type: 'unused',
list: [],
showEmpty: false,
showEmpty: false
};
},
methods: {
... ... @@ -132,6 +130,14 @@ export default {
},
computed: {
...mapState(['unused', 'used', 'overtime']),
loadingOptions() {
let info = this[this.type];
return {
hide: !this.list || !this.list.length,
noMore: info && info.reachedEnd
}
}
},
};
</script>
... ...
... ... @@ -43,7 +43,6 @@ export default {
</script>
<style lang="scss" scoped>
@import "../../../../statics/scss/variable";
.assets-record-container {
display: flex;
margin: 0 40px;
... ...
<template>
<div v-if="validStatus !== 1" class="">
<div @click="goBind" class="bind-alipay">绑定支付宝</div>
<p class="bind-tip">请先设置支付宝账号作为货款和补偿款的收款户,
<p class="bind-tip">请先设置支付宝账号作为货款和补偿款的收款户,
绑定完成在我的收入中展示支付宝绑定账户</p>
</div>
</template>
... ... @@ -20,7 +20,7 @@ export default {
},
data() {
return {
};
},
computed: {
... ...
... ... @@ -43,7 +43,6 @@ export default {
</script>
<style lang="scss" scoped>
@import "../../../../statics/scss/variable";
.orders {
display: flex;
... ...
... ... @@ -87,7 +87,6 @@ export default {
</script>
<style lang="scss" scoped>
@import "../../../../statics/scss/variable";
.tab-item {
display: flex;
... ...
<template>
<LayoutApp :show-back="true" :hideHeader="hideHeader">
<div class="scroll-list-wrap">
<Scroll
<LayoutScroll
ref="scroll"
:options="options"
:loading="loadingOptions"
@pulling-up="onPullingUp"
:data="newsList.list">
<div class="news-content">
... ... @@ -11,7 +12,7 @@
<List v-if="newsList.list && newsList.list.length > 0" isTitle :list="newsList.list || []"></List>
<UfoNoItem v-else :tip="`暂无数据`" style="margin-top: 60px"></UfoNoItem>
</div>
</Scroll>
</LayoutScroll>
</div>
</LayoutApp>
</template>
... ... @@ -68,6 +69,12 @@ export default {
return {
pullUpLoad: this.newsList.list.length > 0 ? true : false,
}
},
loadingOptions() {
return {
hide: !this.newsList.list || this.newsList.list.length === 0,
noMore: !this.newsList.isMoreData
}
}
},
created() {
... ...
... ... @@ -39,7 +39,6 @@ export default {
</script>
<style lang="scss" scoped>
@import "../../../../statics/scss/variable";
.income-header-wrapper {
position: relative;
}
... ...
<template>
<LayoutApp :show-back="true" title="我的收入">
<div class="body" ref="body">
<Scroll
ref="scroll"
:data="incomeData.list"
:options="options"
@pulling-down="onPullingDown"
@pulling-up="onPullingUp">
<incomeHeader :data="getAssetSummary"></incomeHeader>
<payAccount></payAccount>
<incomeDetail :data="incomeData">
<template v-for="(item,index) in incomeData.list">
<incomeItem :data="item" :key="index"></incomeItem>
</template>
</incomeDetail>
<LayoutScroll
ref="scroll"
:loading="loadingOptions"
@pulling-up="onPullingUp">
<incomeHeader :data="getAssetSummary"></incomeHeader>
<payAccount></payAccount>
<incomeDetail :data="incomeData">
<template v-for="(item,index) in incomeData.list">
<incomeItem :data="item" :key="index"></incomeItem>
</template>
</incomeDetail>
<!-- 自定义下拉刷新内容 -->
<!-- <template v-if="customPullDown" slot="pulldown" slot-scope="props">
<pullDown :propsData="props" :pullDownRefreshThreshold="pullDownRefreshThreshold"></pullDown>
</template> -->
</Scroll>
</LayoutScroll>
</div>
</LayoutApp>
</template>
... ... @@ -38,20 +36,26 @@ export default {
mixins: [scrollMixin],
data() {
return {
page: 0,
totalPage: 0
}
},
computed:{
...mapGetters(['getAssetSummary']),
...mapState({
incomeData: (state) => state.assetData
}),
...mapState({
incomeData: (state) => state.assetData
}),
loadingOptions() {
return {
hide: !this.totalPage,
noMore: this.page > this.totalPage
};
}
},
created() {
},
activated() {
this.fetchAssets(true)
this.fetchAssetsAsync(true)
},
watch: {
"incomeData.list": function(val) {
... ... @@ -66,15 +70,22 @@ export default {
},
methods: {
...mapActions(['fetchAssets']),
onPullingDown() {
this.fetchAssets(true)
},
onPullingUp() {
if(!this.incomeData.endReached) {
this.fetchAssets(false)
this.fetchAssetsAsync(false)
} else {
this.$refs.scroll.forceUpdate()
}
},
fetchAssetsAsync(reFetch) {
return this.fetchAssets(reFetch).then(res => {
if (res.code === 200) {
let { page, pagetotal } = res.data || {};
this.page = page || 0;
this.pageTotal = pagetotal || 0;
}
});
}
},
components: {
... ... @@ -83,8 +94,7 @@ export default {
incomeItem,
pullDown,
payAccount,
Style,
Scroll
Style
}
};
</script>
... ...
... ... @@ -172,7 +172,7 @@ export default {
}
.bg {
padding: 24px;
padding: 24px 24px 8px;
display: flex;
flex-wrap: wrap;
}
... ...
... ... @@ -72,9 +72,9 @@ export default {
if (this.yoho.direction === 'forword') {
Object.assign(this.$data, this.$options.data());
!params.order && (params.order = 'sale_desc');
this.fetchData(params);
}
!params.order && (params.order = 'sale_desc');
this.fetchData(params);
},
computed: {
... ... @@ -163,7 +163,7 @@ export default {
this.yasParams.ENT_NAME = ENT_NAME.toString();
params.isReset = true;
this.yas(this.yasParams)
this.yas(this.yasParams);
this.$parent.fetchList(params);
this.$parent.$refs.scroll.scrollTo(0, 0, 300);
this.hide();
... ...
<template>
<div>
<LayoutApp :show-back="true" :title="title">
<LayoutApp :show-back="true" :title="title" :isStop="isStop">
<div class="filter">
<div class="filter-tab">
<div class="tab-item" :class="selectedType === 2 && 'selected-tab'" @click="pressType(2)">人气</div>
... ... @@ -18,14 +18,16 @@
<div class="search-img" @click="goSearch()"></div>
</div>
</div>
<Scroll ref="scroll" class="product-list" v-show="!productList.isEmpty"
:scroll-events="['scroll-end']"
:options="scrollOptions"
:data="productList.list"
@scroll-end="scrollHandler"
@pulling-up="onPullingUp">
<LayoutScroll ref="scroll" class="product-list" v-show="!productList.isEmpty"
:loading="loadingOption"
:scroll-events="['scroll', 'scroll-end']"
:options="scrollOptions"
:data="productList.list"
@scroll="scrollHandler"
@scroll-end="scrollEndHandler"
@pulling-up="onPullingUp">
<ProductList ref="product" :list="productList.list" :yasParams="yasParams"></ProductList>
</Scroll>
</LayoutScroll>
<EmptyList class="empty-wrapper product-list" :tip="`暂无数据`" v-show="productList.isEmpty">
</EmptyList>
</LayoutApp>
... ... @@ -65,6 +67,7 @@ export default {
priceDesc: true,
arrowImage: '',
title: '',
scrollY: 0,
yasParams: {P_NAME: 'XY_UFOSearchList', TYPE_ID: 1},
productList: {
showErrorPage: false,
... ... @@ -99,24 +102,34 @@ export default {
if (this.yoho.direction === 'forword') {
this.$refs.filtrate.hide();
Object.assign(this.$data, this.$options.data());
}
this.changeArrow();
let params = {...this.$route.query};
this.changeArrow();
let params = {...this.$route.query};
if (params.title) {
this.title = params.title;
delete params.title;
if (params.title) {
this.title = params.title;
delete params.title;
} else {
this.title = '商品列表';
}
this.setYasParam({param: params, tab: {index: 1, name: '人气'}});
!params.order && (params.order = 'sale_desc');
await this.fetchList({...params, isReset: true});
} else {
this.title = '商品列表';
this.scrollY && this.$refs.scroll.scrollTo(this.scrollY);
}
this.setYasParam({param: params, tab: {index: 1, name: '人气'}});
!params.order && (params.order = 'sale_desc');
await this.fetchList({...params, isReset: true});
this.yasShowPage();
},
computed: {
...mapState(['yoho'])
...mapState(['yoho']),
loadingOption() {
return {
noMore: this.productList && this.productList.endReached
};
},
isStop() {
return this.scrollY < 10;
}
},
methods: {
... ... @@ -128,6 +141,10 @@ export default {
},
scrollHandler({y}) {
this.scrollY = -y;
},
scrollEndHandler({y}) {
let height = -y;
this.$refs.product.yasShowEvent(height);
... ... @@ -371,6 +388,7 @@ export default {
.product-list {
background: #f5f5f5;
height: calc(100% - 120px);
}
.search-img {
... ...
... ... @@ -36,7 +36,6 @@ export default {
</script>
<style lang="scss" scoped>
@import "../../../../statics/scss/variable";
.price-item {
display: flex;
... ...
... ... @@ -25,7 +25,6 @@ export default {
</script>
<style lang="scss" scoped>
@import "../../../../statics/scss/variable";
.product-wrapper {
height: 180px;
... ...
<template>
<div class="fee-detail">
<div class="item">
<div>平台用费:<i class="iconfont iconquestion icon-class" @click="onClick"></i></div>
<div>平台费用:<i class="iconfont iconquestion icon-class" @click="onClick"></i></div>
<div>{{data.platformFee.amount || '¥0'}}</div>
</div>
<div class="item">
... ...
... ... @@ -67,7 +67,6 @@ export default {
</script>
<style lang="scss" scoped>
@import "../../../statics/scss/variable";
.count-down-wrapper {
display: flex;
... ...
... ... @@ -17,7 +17,7 @@ export default {
methods: {
onClick() {
this.$yoho.goNewPage({
url: 'https://activity.yoho.cn/feature/5729.html?title=活动规则&openby:yohobuy={"action":"go.h5","params":{"title":"活动规则","url":"https://activity.yoho.cn/feature/5729.html"}}'
url: 'https://activity.yoho.cn/feature/5729.html?nodownload=1&title=活动规则&openby:yohobuy={"action":"go.h5","params":{"title":"活动规则","url":"https://activity.yoho.cn/feature/5729.html"}}'
});
}
}
... ...
... ... @@ -18,7 +18,7 @@ export default {
data() {
return {
isUnionType: false,
shareUrl: 'https://activity.yoho.cn/feature/5475.html?share_id=8169&title=新人礼遇'
shareUrl: 'https://activity.yoho.cn/feature/5475.html?share_id=8169&title=新人礼遇&nodownload=1'
};
},
mounted() {
... ...
... ... @@ -50,7 +50,7 @@
></i>
<span>我已阅读并同意</span>
<LayoutLink
href="//activity.yoho.cn/feature/4049.html?share_id=6729&title=UFO卖家商品质检标准"
href="//activity.yoho.cn/feature/4049.html?share_id=6729&title=卖家商品质检标准"
>《卖家商品质检标准》</LayoutLink
>
</div>
... ... @@ -173,7 +173,7 @@ export default {
"dg-notice-content-title": true
}
},
isChanged ? "UFO仓库调整公告" : title
isChanged ? "仓库调整公告" : title
),
...info.map(val => {
return createElement(
... ...
... ... @@ -232,7 +232,10 @@ export default {
extra: JSON.stringify({
forward: {
name: isDetail ? 'buyOrderDetail' : 'OrderList',
params: this.$route.params,
params: isDetail ? {
owner: this.$route.params.owner,
code: bidData.orderCode,//改为新订单号
} : this.$route.params,
},
reportType: 'buy',
}),
... ...
... ... @@ -146,7 +146,7 @@ export default {
return {
title: '调价',
agreementURL:
'https://activity.yoho.cn/feature/3187.html?share_id=5851&title=ufo-%E5%8D%96%E5%AE%B6%E5%8D%8F%E8%AE%AE',
'https://activity.yoho.cn/feature/3187.html?share_id=5851&title=ufo-%E5%8D%96%E5%AE%B6%E5%8D%8F%E8%AE%AE&nodownload=1',
platformFeeModalVisible: false,
platformFee: {
amount: '-¥0',
... ...
... ... @@ -73,7 +73,7 @@ export default {
error: false,
agreeDesc: '有货卖家协议',
url:
'https://activity.yoho.cn/feature/6773.html?share_id=9479&title=%E9%97%B2%E9%B1%BC%E6%BD%AE%E5%8D%96%E5%AE%B6%E5%8D%8F%E8%AE%AE',
'https://activity.yoho.cn/feature/6773.html?share_id=9479&title=%E9%97%B2%E9%B1%BC%E6%BD%AE%E5%8D%96%E5%AE%B6%E5%8D%8F%E8%AE%AE&nodownload=1',
superSell: false,
addNumError: false,
scrollOption: {
... ... @@ -81,7 +81,7 @@ export default {
click: true
},
tipUrl:
'https://activity.yoho.cn/feature/6773.html?share_id=9479&title=%E9%97%B2%E9%B1%BC%E6%BD%AE%E5%8D%96%E5%AE%B6%E5%8D%8F%E8%AE%AE'
'https://activity.yoho.cn/feature/6773.html?share_id=9479&title=%E9%97%B2%E9%B1%BC%E6%BD%AE%E5%8D%96%E5%AE%B6%E5%8D%8F%E8%AE%AE&nodownload=1'
};
},
activated() {
... ... @@ -455,7 +455,6 @@ export default {
</script>
<style lang="scss" scoped>
@import "~statics/scss/variable";
.body {
height: 100%;
... ...
<template>
<LayoutApp class="yohoufo-real-auth-page" title="实名认证">
<div class="auth-content">
<p class="auth-sub-title">UFO平台将严格保密您的认证信息,请按照种类分别填写以下信息,保证上传的图片文字清晰可见。</p>
<p class="auth-sub-title">平台将严格保密您的认证信息,请按照种类分别填写以下信息,保证上传的图片文字清晰可见。</p>
<div class="auth-form">
<p class="form-title">姓名</p>
<div class="form-input-block">
... ...
... ... @@ -215,7 +215,7 @@ export default {
align-items: baseline;
font-size: 40px;
letter-spacing: 0;
font-family: $num-font;
@include num;
span:nth-child(2) {
font-size: 0.8em;
... ...
... ... @@ -220,7 +220,7 @@ export default {
.size-info,
.size-price {
font-family: $num-font;
@include num;
}
&.selected {
background: $primary-color;
... ... @@ -259,7 +259,8 @@ export default {
.size-info {
color: #000;
font-family: $num-font;
@include num;
font-weight: bold;
font-size: 40px;
display: inline-block;
... ...
... ... @@ -221,7 +221,6 @@ export default {
<style lang="scss" scoped>
@import "../product-detail";
@import "../../../statics/scss/variable";
.title {
font-size: 40px;
... ... @@ -343,7 +342,7 @@ export default {
}
.crash-info {
font-family: $num-font;
@include num;
}
.footer {
... ...
... ... @@ -106,7 +106,8 @@ export default {
}
.price {
font-family: $num-font;
@include num;
font-weight: bold;
font-size: 32px;
line-height: 38px;
... ...
$primary-color : #08304b;
$sub-color : #64ad88;
$num-font: "DINAlternate-Bold", "din alternate", "PingFang SC", "HiraginoSansGB-W3", "SanFranciscoText-Regular", Helvetica, Roboto, "Heiti SC", "黑体", Arial;
@mixin cube-ufo-btn {
[type="button"] {
... ...
... ... @@ -27,7 +27,7 @@
<div class="info-name"><div>{{productDetail.product_name}}</div></div>
</div>
<a class="banner" v-if="resource" @click.prevent="gotoNewPage(resource.url)">
<img-size :src="sizeImg(resource.src)"/>
<img-size ref="resourceImg" :src="sizeImg(resource.src)"/>
</a>
<div class="info">
<transition-group name="info-list" tag="div" class="info-list">
... ... @@ -50,7 +50,7 @@
<img class="ref-img" v-lazy="prdDetailImage" />
<div class="recommend" v-if="recommend"><h2>相关推荐</h2>
<product-list :list="recommend" priceKey="price"/>
<product-list ref="recommendList" :list="recommend" priceKey="price" :yas-params="recommendYasParams"/>
</div>
</div>
<div class="footer">
... ... @@ -97,7 +97,7 @@ import TopList from './components/top-list';
import SquareImg from './components/square-img';
import stateShortCutsMixins from './mixins';
const { mapActions } = createNamespacedHelpers('product');
const { mapActions, mapState } = createNamespacedHelpers('product');
export default {
name: 'ProductDetail',
... ... @@ -133,10 +133,23 @@ export default {
showSizeSelectSheet: false,
showSizeRequestSheet: false,
selectSizeConfig: {},
/**
* 商品详情页-推荐商品曝光时
* XY_UFO_SHOW_EVENT
* 1.P_NAME:页面名称,UFOProductDetail_LIST;
* 2.P_PARAM:页面参数;
* 3.I_INDEX:曝光顺序;
* 4.PRD_SKN:商品id;
*/
recommendYasParams: {
P_NAME: 'UFOProductDetail_LIST',
},
};
},
computed: {
...mapGetters(['isQiugouEnabled']),
...mapState(['resourceContentCode']),
productDec() {
const goods = get(this.productDetail, 'goods_list[0]', {});
... ... @@ -198,6 +211,31 @@ export default {
this.loadData(this.productId);
this.refresh();
if (this._resourceImgWatcher) {
this._resourceImgWatcher();
}
if (this.resource && this.resource.url) {
this.yasResourceVisible();
} else {
this._resourceImgWatcher = this.$watch(() => {
return this.resource && this.resource.url;
}, (url) => {
if (url) {
this._resourceImgWatcher && this._resourceImgWatcher();
this.yasResourceVisible();
}
}, {
immediate: true,
});
}
},
deactivated() {
if (this._resourceImgWatcher) {
this._resourceImgWatcher();
this._resourceImgWatcher = null;
}
},
beforeRouteUpdate(to, from ,next) {
if (this.historyBackGuard() === false) {
... ... @@ -228,6 +266,31 @@ export default {
refresh() {
this.$refs.slide && this.$refs.slide.refresh && this.$refs.slide.refresh();
},
yasResourceVisible() {
/**
* 商品详情页中的资源位曝光
* XY_UFO_SHOW_EVENT
* 1.P_NAME:当前页面名称,XY_UFOProductDetail;
* 2.P_PARAM:当前页面资源位code;
* 3.PRD_ID:商品ID;
* 4.ACTION_URL:资源位跳转URL;
*/
this.$store.dispatch('reportYas', {
params: {
appop: 'XY_UFO_SHOW_EVENT',
param: {
P_NAME: 'XY_UFOProductDetail',
P_PARAM: this.resourceContentCode,
PRD_ID: this.productId,
ACTION_URL: this.resource.url,
},
}
});
if (this._resourceImgWatcher) {
this._resourceImgWatcher();
this._resourceImgWatcher = null;
}
},
sizeImg(src, width = 360, height = 72) {
if (src) {
return getImgUrl(src, width, height);
... ... @@ -344,19 +407,23 @@ export default {
// 选择出售或购买
async onSelectTradeProduct(tradeProduct) {
/**
* 数据埋点
* 商品详情页点击出售/购买/求购按钮
* event: XY_UFO_PRD_DT_SALE_C
* params: 1.TAB_ID:1-出售,2-购买,3-求购;
* 2.PRD_ID:商品ID;
*/
this.$store.dispatch('reportYas', {
params: {
appop: 'XY_UFO_PRD_DT_BUY_SEL_C',
param: {
TAB_ID: this.selectSizeConfig.type === 'buy' ? 2 : 1,
PRD_ID: tradeProduct.productId
},
}
});
if (this.selectSizeConfig.type === 'buy') {
//数据埋点
this.$store.dispatch('reportYas', {
params: {
appop: 'XY_UFO_PRD_DT_BUY_SEL_C',
param: {
PRD_ID: tradeProduct.productId,
PRD_SKU: tradeProduct.skup,
PRD_SIZE: tradeProduct.size_name,
},
}
});
try {
const info = await this.payment({
skup: tradeProduct.skup,
... ... @@ -423,6 +490,15 @@ export default {
// 打开求购列表
qiugou() {
this.showBidSheet = true;
this.$store.dispatch('reportYas', {
params: {
appop: 'XY_UFO_PRD_DT_SALE_C',
param: {
TAB_ID: 3,
PRD_ID: this.productId,
},
}
});
},
// 购买
... ... @@ -432,6 +508,21 @@ export default {
// 资源位
gotoNewPage(url) {
/**
* 商品详情页中的资源位点击
* XY_UFO_GDS_DT_BANNER_C
* 1.PRD_ID:商品ID
* 2.ACTION_URL:跳转的URL
*/
this.$store.dispatch('reportYas', {
params: {
appop: 'XY_UFO_GDS_DT_BANNER_C',
param: {
PRD_ID: this.productId,
ACTION_URL: url,
},
}
});
this.$xianyu.goXianyuNewPage({url});
},
},
... ... @@ -550,7 +641,8 @@ export default {
.info-price {
color: #d0021b;
font-size: 48px;
font-family: $num-font;
@include num;
font-weight: bold;
line-height: 56px;
height: 56px;
... ...
... ... @@ -17,7 +17,8 @@ export default function() {
validStatus
} = data;
state.alipayAccount = maskAccount(alipayAccount);
// state.alipayAccount = maskAccount(alipayAccount);
state.alipayAccount = alipayAccount;
state.nickName = nickName || '';
state.certName = certName;
state.validStatus = validStatus;
... ...
... ... @@ -106,7 +106,7 @@ export default function() {
page: 'tradeIncome',
}, // 原交易收入 tradeIncome, 余额 income
buyOrder: {
title: '我的订单',
title: '我的购买订单',
num: state.buyNum,
page: 'OrderList',
params: { owner: ownType.BUY, status: 1 },
... ... @@ -408,6 +408,8 @@ export default function() {
assetData.list = newList;
commit('addAssets', assetData);
}
return result;
},
async fetchWallet(
... ...
... ... @@ -6,13 +6,13 @@ export default {
ensureProduct({ commit }, { productId }) {
commit(Types.ENSURE_PRODUCT_DETAIL, { productId });
},
async fetchProductInfo({ commit }, { productId }) {
async fetchProductInfo({ commit, state }, { productId }) {
const queryTasks = ['', '/resource', '/activity', '/recommend'].map(path => {
let params = { product_id: productId };
if (path === '/resource') {
params = {
content_code: '05e4f5782dfc3a5e10d39b8f04a7dcb9',
content_code: state.resourceContentCode,
};
}
return this.$api.post(`/api/ufo/product${path}`, params).then(result => {
... ...
... ... @@ -50,7 +50,7 @@ export function defaultProduct() {
export function defaultState() {
return {
products: {},
resourceContentCode: '05e4f5782dfc3a5e10d39b8f04a7dcb9', // 资源位code,当前只有一个固定的code
/**
1: 当前商品对应品牌系统的推荐
2: 商品详情页面取前3
... ...
... ... @@ -26,6 +26,7 @@ const webpackConfig = {
alias: {
vue$: 'vue/dist/vue.runtime.esm.js',
'lottie-web': 'lottie-web/build/player/lottie_light.min.js',
'@': resolve('apps')
},
modules: [path.join(__dirname, '../apps'), 'node_modules'],
},
... ...
... ... @@ -76,7 +76,7 @@ const webpackConfig = merge(baseConfig, {
loader: 'sass-loader',
options: {
sourceMap: isProd,
// data: '@import "variables";',
data: '@import "@/statics/scss/variable.scss";',
},
},
],
... ...
... ... @@ -191,7 +191,7 @@ const devRender = (route) => {
const ck = getCacheKey(req, route);
if (route.accessLog) {
logger.info(`${req.yoho.clientIp} | ${req.url} | uid:${req.user.uid} | ${new Date()}`);
logger.info(`[page access] ${req.yoho.clientIp} | ${req.url} | uid:${req.user.uid} | ${new Date()}`);
}
// return require('request-promise')({
... ...
... ... @@ -64,7 +64,8 @@ module.exports = (app) => {
},
cookie: {
domain: 'yohobuy.com',
httpOnly: true
httpOnly: true,
maxAge: 1000 * 60 * 60 * 24 * 7 // 7天
},
store: new RedisStore(Object.assign(config.redis.session, {
logErrors: (e) => {
... ...