Authored by TaoHuang

add download

// 只在客户端进行处理的组件
export default {
name: 'ClientOnly',
functional: true,
render(h, { parent, children }) {
if (parent._isMounted) {
return children;
} else {
parent.$once('hook:mounted', () => {
parent.$forceUpdate();
});
}
}
};
... ...
... ... @@ -5,6 +5,7 @@ import LayoutRecycleList from './layout-recycle-list';
import RecycleList from './recycle-list';
import AuthComponent from './auth-component';
import RecycleScrollReveal from './recycle-scroll-reveal';
import ClientOnly from './client-only';
export default [
Layout,
... ... @@ -13,5 +14,6 @@ export default [
LayoutRecycleList,
RecycleList,
AuthComponent,
RecycleScrollReveal
RecycleScrollReveal,
ClientOnly
];
... ...
... ... @@ -15,6 +15,7 @@ import links from 'utils/links';
import {initClient, getYohoState} from 'utils/init-client';
import 'statics/scss/common.scss';
import 'statics/scss/grass-prompt.scss';
import 'statics/scss/download-app.scss';
import 'statics/font/iconfont.css';
import 'statics/font/cube-icon.css';
import 'video.js/dist/video-js.css';
... ...
<template>
<div class="download" v-if="visible">
</div>
</template>
<script>
export default {
name: 'download',
data() {
return {
visible: true
};
},
mounted() {
this.getDownloadElem((elem) => {
const newElem = this.handleElem(elem.cloneNode(true));
elem.parentNode.removeChild(elem);
this.$el.appendChild(newElem);
});
},
methods: {
getDownloadElem(found) {
let vm = this;
function checkForDownload() {
vm.$download = document.getElementById('top-downloadbar');
if (vm.$download) {
found(vm.$download);
} else {
setTimeout(checkForDownload, 50);
}
}
checkForDownload();
},
handleElem(elem) {
const vm = this;
const miniElem = elem.querySelector('#mini-app-open');
if (miniElem) {
elem.removeChild(miniElem);
}
elem.addEventListener('click', function(e) {
let target = e.target;
// 点击关闭
if (target.className.toLowerCase() === 'download-close') {
vm.$emit('close');
vm.visible = false;
}
});
const downloadGo = elem.querySelector('#download-go');
if (downloadGo) {
downloadGo.innerText = '下载APP';
}
return elem;
}
}
};
</script>
<style lang="scss" scoped>
.download {
width: 100%;
height: 110px;
}
</style>
... ...
<template>
<div>
<Layout ref="layout" class="article" @touchstart.native="onTouchStart($event)" @touchmove.native="onTouchMove($event)" @touchend.native="onTouchEnd($event)">
<Layout ref="layout" class="article">
<TopicHeader ref="header" :title="topicTitle" :step="headerAnimateStep" :data="topicSimpleInfo" :share="share" @on-follow="onFollowTopic">
<template v-if="tabBlockSuctionTop" v-slot:suctionTop>
<TopicTabBlock :active-type="activeTopicListType" @on-change-tab="onChangeTab"></TopicTabBlock>
</template>
</TopicHeader>
<div ref="pullEle" class="pull">{{this.text.startPull}}</div>
<RecycleScrollReveal :size="5" :thumbs="thumbs" ref="scroll" @scroll="onScroll" :offset="800" :on-fetch="onFetch" :manual-init="true"
@on-inited="onInited">
<template v-slot:eternalTop>
<ClientOnly>
<Download v-if="share"></Download>
</ClientOnly>
<TopicBanner ref="topicBanner" :data="topicSimpleInfo" :share="share" @on-follow="onFollowTopic"></TopicBanner>
<TopicTabBlock ref="tabBlock" :active-type="activeTopicListType" @on-change-tab="onChangeTab"></TopicTabBlock>
</template>
... ... @@ -37,6 +38,14 @@
</span>
立即参与
</a>
<a v-else class="openapp-btn hover-opacity" :class="{'scroll-opacity': scrolling}" :href="publishUrl || 'javascript:;'" @click="toDownloadPage">
<span class="avatar-block">
<img class="avatar" src="~statics/image/common/app.png" alt="">
</span>
打开有货App
<i class="iconfont mg">&#xe7b0;</i>
</a>
</Layout>
</div>
</template>
... ... @@ -50,6 +59,7 @@ import ArticleItem2 from './components/article/article-item2';
import TopicHeader from './components/topic/header';
import TopicBanner from './components/topic/banner';
import TopicTabBlock from './components/topic/tab-block';
import Download from './components/download-top';
import {mapState as mapYohoState, mapActions as mapYohoActions, mapMutations as mapYohoMutations, createNamespacedHelpers} from 'vuex';
const {mapState, mapMutations, mapActions} = createNamespacedHelpers('article');
... ... @@ -70,17 +80,7 @@ export default {
colWidthForTwo: 0,
scrolling: false,
page: 1,
fetching: false,
startLength: 0,
pullLength: 0,
threshold: 50,
enable: false,
firstTouchStart: true,
text: {
startPull: '下拉刷新',
releasePull: '松开刷新',
refreshing: '刷新中'
}
fetching: false
};
},
created() {
... ... @@ -370,67 +370,13 @@ export default {
});
}
},
onTouchStart(e) {
if (this.scrollTop !== 0) {
this.enable = false;
return;
}
this.enable = true;
this.startLength = e.touches[0].pageY;
this.$refs.scroll.$el.style.transition = 'transform 0s';
this.$refs.pullEle.innerText = this.text.startPull;
},
onTouchMove(e) {
if (!this.enable) {
return;
}
this.pullLength = e.touches[0].pageY - this.startLength;
if (this.pullLength) {
this.pullElement(this.pullLength);
}
},
onTouchEnd() {
if (!this.enable) {
return;
}
if (this.pullLength > this.threshold) {
this.$refs.pullEle.innerText = this.text.refreshing;
this.onPull();
}
this.$refs.scroll.$el.style.transition = 'transform 0.6s ease';
this.$refs.scroll.$el.style.transform = 'translate(0, 0px)';
this.pullLength = 0;
this.startLength = 0;
this.enable = false;
},
pullElement(length) {
if (length <= 0) {
return;
}
if (length < this.$refs.pullEle.offsetHeight) {
this.$refs.scroll.$el.style.transform = `translate(0, ${length}px)`;
if (length > this.threshold) {
this.$refs.pullEle.innerText = this.text.releasePull;
}
}
},
async onPull() {
this.init();
}
},
components: {
ArticleItem2,
TopicHeader,
TopicBanner,
TopicTabBlock
TopicTabBlock,
Download
}
};
</script>
... ... @@ -496,4 +442,42 @@ export default {
height: 100%;
}
}
.openapp-btn {
width: 320px;
height: 80px;
border-radius: 10px;
font-size: 30px;
color: #fff;
background: #d0021b;
position: absolute;
bottom: 40px;
left: calc(50% - 160px);
z-index: 1;
display: flex;
align-items: center;
transition: all 600ms ease-in-out;
&.scroll-opacity {
opacity: 0.3;
}
.avatar-block {
width: 60px;
height: 60px;
margin: 10px 25px 10px 10px;
overflow: hidden;
}
.avatar {
display: block;
width: 100%;
height: 100%;
}
.mg {
margin-left: 10px;
font-size: 30px;
}
}
</style>
... ...
.top-downloadbar {
//position: absolute !important;
//z-index: 100;
padding: 0 0 !important;
height: 110px !important;
.download-go-wechat {
height: 72px !important;
width: 180px !important;
font-size: 32px !important;
line-height: 72px !important;
text-align: center;
border-radius: 10px !important;
right: 20px !important;
}
}
... ...
... ... @@ -181,6 +181,7 @@ const render = (route) => {
resources,
states,
zk,
download: req.query.download ? true : false,
routeHash: routeEncode.getRouter(req)
});
... ... @@ -251,7 +252,8 @@ const devRender = (route) => {
scripts,
resources,
states,
routeHash: routeEncode.getRouter(req)
routeHash: routeEncode.getRouter(req),
download: req.query.download ? true : false,
});
if (config.useCache && route.cache && ck) {
... ...
... ... @@ -29,9 +29,13 @@
</script>
{{{html}}}
<div id="degrade-app"></div>
<div id="main-wrap">
<div id="no-download"></div>
</div>
<div id="main-wrap">
{{#unless download}}
<div id="no-download"></div>
{{/unless}}
</div>
{{{states}}}
{{#if zk.webperf}}
... ... @@ -76,7 +80,7 @@
a.async = 1;
a.src = j;
m.parentNode.insertBefore(a, m);
}(window, document, 'script', (document.location.protocol === 'https:' ? 'https:' : 'http:') + '//cdn.yoho.cn/yas-jssdk/2.4.18/yas.js', '_yas'));
}(window, document, 'script', (document.location.protocol === 'https:' ? 'https:' : 'http:') + '//cdn.yoho.cn/yas-jssdk/2.4.22/yas.js', '_yas'));
var _hmt = _hmt || [];
... ... @@ -120,7 +124,7 @@
uid = uid === 0 ? '' : uid;
window._ozuid = uid; // 暴露ozuid
if (window._yas) {
window._yas(1 * new Date(), '2.4.16', 'yohoappweb', uid, '', '');
window._yas(1 * new Date(), '2.4.22', 'yohoappweb', uid, '', '');
}
(function() {
... ...