Authored by ityuany

Merge branch 'master' into feature/0813/yuany

... ... @@ -33,6 +33,12 @@ export default {
if (res === 'N') {
this.SET_STATUS_BAR_STATUS({status: false});
}
});
this.$yoho.setWebview({
bounces: false,
clearCacheWhenDestroy: false
});
});
... ...
const getAppPath = () => {
let appPath = document.getElementById('main-wrap').dataset.apppath || 'yohobuy://yohobuy.com/goapp?openby:yohobuy={"action":"go.home","params":{"gender":"1","channel":"2"}}';
return appPath;
};
const u = navigator.userAgent;
const isFromYOHO = /m\.yohobuy\.com/i.test(document.referrer);
const isApp = /yoho/i.test(u) ||
!!window.yohoInterface ||
/app_version=/i.test(location.search) ||
/openrefer=/i.test(location.search);
const isiOS = /(iPhone|iPad|iPod|iOS)/i.test(u); // ios终端
const isAndroid = /Android/i.test(u); // android终端
const isWechatDevtool = /wechatdevtools/i.test(u); // 微信开发者工具
const nodownload = document.getElementById('no-download'); // 页面不需要下载
const getIOSVersion = () => {
const verion = navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/);
return verion ? parseInt(verion[1], 10) : 0;
};
const ua = navigator.userAgent;
const isOriginalChrome = /chrome\/[\d.]+ Mobile Safari\/[\d.]+/i.test(ua) &&
isAndroid &&
ua.indexOf('Version') < 0;
const getFallUrl = (schemeUrl) => {
const appPath = (schemeUrl || '').replace('yohobuy://yohobuy.com/goapp?', '') || 'openby:yohobuy={"action":"go.home","params":{"gender":"1","channel":"2"}}';
return `https://union.yoho.cn/union/app-downloads.html?${appPath}`;
};
const checkOpenFall = (url, callFunc, noFall) => {
callFunc();
const fallUrl = getFallUrl(url);
if (noFall) {
return;
}
window.location.href = fallUrl;
};
const callIframe = (url, noFall) => {
checkOpenFall(url, () => {
window.location.href = url;
}, noFall);
};
const callUrl = (url, noFall) => {
checkOpenFall(url, () => {
}, noFall);
};
const callA = (url, noFall) => {
checkOpenFall(url, () => {
const ca = document.createElement('a');
ca.setAttribute('href', url);
ca.style.display = 'none';
document.body.appendChild(ca);
ca.click();
}, noFall);
};
const toAppPage = (appUrl, noFall) => {
if (isOriginalChrome) {
callA(appUrl, noFall);
} else if (isiOS) {
if (getIOSVersion() < 9) {
callIframe(appUrl, noFall);
} else {
callUrl(appUrl, noFall);
}
} else {
callIframe(appUrl, noFall);
}
};
const canOpenApp = () => {
if (isWechatDevtool || isApp || isFromYOHO || nodownload) {
return false;
}
return isAndroid || isiOS;
};
export default () => {
if (canOpenApp()) {
let appPath = getAppPath();
toAppPage(appPath, false);
}
};
... ...
// 只在客户端进行处理的组件
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
];
... ...
... ... @@ -12,9 +12,12 @@ import {get, find} from 'lodash';
import yoho from 'common/yoho';
import sdk from 'common/sdk';
import links from 'utils/links';
import openApp from 'common/open-app';
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';
... ... @@ -44,6 +47,8 @@ Vue.prop('auth', function() {
return true;
});
Vue.prop('openApp', openApp);
Vue.prop('bus', bus());
Vue.use(Prompt);
Vue.use(Toast);
... ...
<template>
<Layout class="article-detail">
<ArticleDetailHeader ref="header" class="article-detail-header" :data="articleInfo" :step="headerAnimateStep" :title-step="headerTitleAnimateStep">
<ArticleDetailHeader ref="header" class="article-detail-header" v-if="!share" :data="articleInfo" :step="headerAnimateStep" :title-step="headerTitleAnimateStep">
<div v-if="articleInfo.articleId && !articleInfo.empty" class="title-main">
<div class="title-info" :style="`transform: translate3d(0, ${viewMoreArticles ? '-50%' : '0'}, 0)`">
<ArticleItemHeader class="title-info-author" :share="share" :data="authorData" :more="false" @on-follow="onFollowAuthor"></ArticleItemHeader>
... ... @@ -10,9 +8,11 @@
</div>
</div>
</ArticleDetailHeader>
<RecycleScrollReveal :size="10" ref="scroll" :class="{'preview-page': previewPage}" @scroll="onScroll" :offset="2000" :on-fetch="onFetch" :manual-init="true">
<template v-slot:eternalTop>
<ClientOnly>
<Download v-if="share"></Download>
</ClientOnly>
<ArticleDeatilLong
v-if="articleInfo.sort == 2"
ref="detailLong"
... ... @@ -55,6 +55,8 @@
</template>
</RecycleScrollReveal>
<DownloadBottom v-if="share" :class="{'scroll-opacity': scrolling}"></DownloadBottom>
<ReplaceToHome :scrolling="scrolling" class="back-to-home"></ReplaceToHome>
<ArticleDetailFooter ref="footer" class="detail-fixed-footer" :style="`transform: translate3d(0, ${viewMoreArticles ? '100%' : '0'}, 0)`" v-bind="footerData" @on-comment-click="onComment">
<template v-if="articleInfo.sort != 2" v-slot:before>
... ... @@ -94,6 +96,8 @@ import ArticleDeatilLong from './components/detail/article-long';
import ArticleDeatilNote from './components/detail/article-note';
import ArticleItem2 from './components/article/article-item2';
import ArticleDetailFooter from './components/detail/article-footer';
import Download from './components/download-top';
import DownloadBottom from './components/download-bottom';
import MoreActionSheet from './components/detail/more-action-sheet';
import {mapState as mapYohoState, mapMutations as mapYohoMutations, createNamespacedHelpers} from 'vuex';
import ReplaceToHome from 'components/replace-to-home/replace-to-home';
... ... @@ -101,9 +105,6 @@ const {mapState, mapActions, mapMutations} = createNamespacedHelpers('article');
export default {
name: 'ArticleDetailPage',
props: {
share: Boolean
},
data() {
return {
toHomeHref: '',
... ... @@ -115,7 +116,8 @@ export default {
colWidthForTwo: 370,
posId: YAS.scene.newsDetail,
previewPage: false,
articleProducts: []
articleProducts: [],
share: false
};
},
async created() {
... ... @@ -155,6 +157,7 @@ export default {
mounted() {
this.colWidthForTwo = Math.floor(this.$el.offsetWidth / 2);
this.loadPreData(+this.$route.params.id);
this.share = !this.$yoho.isApp;
},
computed: {
...mapYohoState(['yoho']),
... ... @@ -458,6 +461,9 @@ export default {
}
}
});
},
toDownloadPage() {
this.$links.toDownloadApp();
}
},
components: {
... ... @@ -468,7 +474,9 @@ export default {
ArticleDeatilNote,
ArticleItem2,
MoreActionSheet,
ArticleDetailFooter
ArticleDetailFooter,
Download,
DownloadBottom
}
};
</script>
... ...
... ... @@ -231,7 +231,6 @@ export default {
font-size: 24px;
line-height: 36px;
max-height: 72px;
word-break: break-all;
/* stylelint-disable */
text-overflow: -o-ellipsis-lastline;
text-overflow: ellipsis;
... ...
<template>
<div class="article-detail-long">
<div class="header-cover"></div>
<div class="header-cover" v-if="!share"></div>
<ArticleItemSlideImage ref="coverFigure" class="cover-figure" :data="coverImage" :thumb-size="coverSize" :style="`transform: translate3d(0, ${coverTranslateY}px, 0)`">
</ArticleItemSlideImage>
<div ref="authorBlock" class="author-block">
... ... @@ -43,6 +43,7 @@ import ArticleItemTopics from '../article/article-item-topics';
import ArticleDetailFooter from './article-footer';
import ArticleItemSlideImage from '../article/article-item-slide-image';
import ArticleDetailHeader from './article-header';
import YAS from 'utils/yas-constants';
import {mapState, mapMutations, createNamespacedHelpers} from 'vuex';
const {mapState: mapArticleState} = createNamespacedHelpers('article');
... ... @@ -77,7 +78,7 @@ export default {
this.downgrade = true;
}
this.handleRechText();
this.handleRichText();
},
computed: {
...mapState(['yoho']),
... ... @@ -141,7 +142,7 @@ export default {
},
watch: {
'data.richText': function() {
this.handleRechText();
this.handleRichText();
}
},
methods: {
... ... @@ -168,11 +169,25 @@ export default {
},
onActionComment() {
},
handleRechText() {
handleRichText() {
let vm = this;
this.$nextTick(() => {
this.$refs.richText && this.$refs.richText.querySelectorAll('a').forEach(ele => {
if (ele.querySelector('img')) {
ele.classList.add('yoho-img-link');
ele.addEventListener('click', function() {
vm.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.articleImageClick,
param: {
ARTICLE_ID: vm.data.articleId,
URL: ele.getAttribute('href')
}
}
});
});
}
});
});
... ...
<template>
<a class="openapp-btn hover-opacity" href="javascript:;" @click="toDownloadPage">
<span class="avatar-block">
<div class="avatar"></div>
</span>
在App中查看
<i class="iconfont mg">&#xe7b0;</i>
</a>
</template>
<script>
export default {
methods: {
toDownloadPage() {
this.$openApp();
}
}
};
</script>
<style lang="scss" scoped>
.openapp-btn {
width: 320px;
height: 80px;
border-radius: 10px;
font-size: 30px;
color: #fff;
background: #d0021b;
position: absolute;
bottom: 120px;
left: calc(50% - 160px);
z-index: 100;
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%;
background-image: url("~statics/image/common/app.png");
background-size: 100% 100%;
}
.mg {
margin-left: 10px;
font-size: 30px;
}
}
</style>
... ...
<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;
switch (target.className.toLowerCase()) {
case 'download-close': {
// 点击关闭
vm.$emit('close');
vm.visible = false;
break;
}
case 'download-go': {
// 尝试打开app
vm.$openApp();
e.stopPropagation();
e.preventDefault();
break;
}
case 'download-go-wechat': {
// 尝试打开app
vm.$openApp();
e.stopPropagation();
e.preventDefault();
break;
}
default: {
// pass
}
}
});
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 class="article">
<TopicHeader ref="header" :title="topicTitle" :step="headerAnimateStep" :data="topicSimpleInfo" :share="share" @on-follow="onFollowTopic">
<Layout ref="layout" class="article">
<TopicHeader ref="header" :title="topicTitle" v-if="!share" :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>
<TopicTabBlock :active-type="activeTopicListType" @on-change-tab="onChangeTab"></TopicTabBlock>
</template>
</TopicHeader>
<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 +40,8 @@
</span>
立即参与
</a>
<DownloadBottom v-else :class="{'scroll-opacity': scrolling}"></DownloadBottom>
</Layout>
</div>
</template>
... ... @@ -50,6 +55,8 @@ 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 DownloadBottom from './components/download-bottom';
import {mapState as mapYohoState, mapActions as mapYohoActions, mapMutations as mapYohoMutations, createNamespacedHelpers} from 'vuex';
import ReplaceToHome from 'components/replace-to-home/replace-to-home';
const {mapState, mapMutations, mapActions} = createNamespacedHelpers('article');
... ... @@ -69,7 +76,9 @@ export default {
scrollTop: 0,
activeTopicListType: 2,
colWidthForTwo: 0,
scrolling: false
scrolling: false,
page: 1,
fetching: false
};
},
created() {
... ... @@ -105,13 +114,7 @@ export default {
}
},
mounted() {
if (this.$route.name === 'topic.share') {
this.share = true;
if (!this.$yoho.isApp) {
Share.init();
}
}
this.share = !this.$yoho.isApp;
this.scrollEvent = throttle(this.onDounceScroll.bind(this), throttleTime);
this.colWidthForTwo = Math.floor(this.$el.offsetWidth / 2);
... ... @@ -194,7 +197,7 @@ export default {
return;
}
this._headerHeight = this._headerHeight || this.$refs.header.$el.offsetHeight;
this._headerHeight = this._headerHeight || (this.$refs.header && this.$refs.header.$el.offsetHeight);
this._topicHeaderHeight = this._topicHeaderHeight || this.$refs.topicBanner.$el.offsetHeight;
let step = Math.round((scrollTop - 4) / (this._topicHeaderHeight - this._headerHeight - 10) * 100);
... ... @@ -359,14 +362,16 @@ export default {
}
});
}
}
},
},
components: {
ReplaceToHome,
ArticleItem2,
TopicHeader,
TopicBanner,
TopicTabBlock
TopicTabBlock,
Download,
DownloadBottom
}
};
</script>
... ...
... ... @@ -193,7 +193,6 @@ export default {
padding: 10px 20px;
> p {
word-break: break-all;
/* stylelint-disable */
text-overflow: -o-ellipsis-lastline;
text-overflow: ellipsis;
... ...
.top-downloadbar {
//position: absolute !important;
//z-index: 100;
padding: 0 0 !important;
height: 110px !important;
border-bottom: 0.5PX solid #efefef;
.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;
}
}
... ...
import VConsole from 'vconsole';
export default new VConsole();
... ...
... ... @@ -38,7 +38,7 @@ const getDetailShareData = (article) => {
return {
title: `@${article.authorName} 在有货社区上发了一篇内容,快点开看看!`,
imgUrl: handleProtocol(get(shareImage.split('?'), '[0]') || DEFAULT_SHARE_IMAGE),
link: handleProtocol(`${window ? window.location.origin : ''}/grass/article/${article.articleId}`),
link: handleProtocol(`${window ? window.location.origin : ''}/grass/article/${article.articleId}?share=true`),
desc,
hideType: ['7', '8', '9']
};
... ... @@ -48,7 +48,7 @@ const getTopicShareData = (topic) => {
return {
title: topic.topicName,
imgUrl: handleProtocol(topic.topicImageUrl),
link: handleProtocol(`${location.origin}/grass/topic/${topic.topicId}`),
link: handleProtocol(`${location.origin}/grass/topic/${topic.topicId}?share=true`),
desc: '我在有货的社区发现一个热门话题。' + topic.topicDesc,
hideType: ['7', '8', '9']
};
... ... @@ -58,7 +58,7 @@ const getAuthorShareData = (author) => {
return {
title: `@${author.nickName} YO!社区,一起来玩潮流!`,
imgUrl: handleProtocol(get(author, 'headIco', '').split('?')[0] || DEFAULT_SHARE_IMAGE),
link: handleProtocol(`${location.origin}/grass/author/${author.authorType}/${author.authorUid}`),
link: handleProtocol(`${location.origin}/grass/author/${author.authorType}/${author.authorUid}?share=true`),
desc: author.signature || '',
hideType: ['7', '8', '9']
};
... ...
... ... @@ -21,6 +21,7 @@ export default {
productFav: 'YB_STROLL_ARC_RLT_PRD_COL_C',
labelClick: 'YB_STROLL_ACT_LBL_C',
topicFollow: 'YB_STROLL_TOPIC_ATT_C',
detailShow: 'YB_STROLL_CONT'
detailShow: 'YB_STROLL_CONT',
articleImageClick: 'YB_ARTICLE_IMAGE_CLICK'
}
};
... ...
... ... @@ -8,7 +8,7 @@ const pkg = require('../../package.json');
const routes = require('../../config/ssr-routes');
const redis = require('../../utils/redis');
const routeEncode = require('../../utils/route-encode');
const { createBundleRenderer } = require('vue-server-renderer');
const {createBundleRenderer} = require('vue-server-renderer');
const Handlebars = require('handlebars');
const logger = global.yoho.logger;
const config = global.yoho.config;
... ... @@ -16,23 +16,16 @@ const config = global.yoho.config;
const isDev = process.env.NODE_ENV === 'development' || !process.env.NODE_ENV;
let renderer;
let serverBundle;
let degradeHtml;
const hbs = fs.readFileSync(
path.join(__dirname, '../views/index.hbs'),
'utf-8',
);
const hbs = fs.readFileSync(path.join(__dirname, '../views/index.hbs'), 'utf-8');
const template = Handlebars.compile(hbs);
if (!isDev) {
degradeHtml = fs.readFileSync(
path.join(__dirname, `../../degrade-${pkg.version}.html`),
'utf-8',
);
degradeHtml = fs.readFileSync(path.join(__dirname, `../../degrade-${pkg.version}.html`), 'utf-8');
serverBundle = require('../../manifest.server.json');
const clientManifest = require('../../manifest.json');
... ... @@ -40,27 +33,27 @@ if (!isDev) {
renderer = createBundleRenderer(serverBundle, {
runInNewContext: false,
clientManifest,
inject: false,
inject: false
});
}
const REG_SCRIPT = /src="([^"]+)"/g;
const asyncLoadScripts = renderScripts => {
const asyncLoadScripts = (renderScripts) => {
let match;
const scripts = [];
while ((match = REG_SCRIPT.exec(renderScripts))) {
scripts.push({
src: match[1],
index: scripts.length,
index: scripts.length
});
}
return scripts;
};
const getContext = req => {
const getContext = (req) => {
return {
url: req.url,
title: req.query.share_title || '',
... ... @@ -80,10 +73,23 @@ const getContext = req => {
hostname: os.hostname(),
route: `[${req.method}]${_.get(req, 'route.path', '')}`, // 请求路由
udid: _.get(req, 'cookies.udid', 'yoho'),
path: `[${req.method}]${routeEncode.getRouter(req)}`,
path: `[${req.method}]${routeEncode.getRouter(req)}`
};
};
function getAppPath(req) {
let appPathUrl = req.originalUrl.split('?')[0] || '';
const query = Object.assign(req.query, {
headerid: -1
});
let appPath = 'yohobuy://yohobuy.com/goapp?openby:yohobuy={"action":"go.h5",' +
'"params":{"url":"http://m.yohobuy.com' + appPathUrl +
'","param":' + JSON.stringify(query) + '}}';
return encodeURI(appPath);
}
const handlerError = (err = {}, req, res, next) => {
if (err.code === 404) {
return res.redirect('/grass/error/404');
... ... @@ -93,7 +99,7 @@ const handlerError = (err = {}, req, res, next) => {
return next(err);
};
const getChannel = yoho => {
const getChannel = (yoho) => {
if (yoho.isYohoApp && yoho.isiOS) {
return 'ios';
} else if (yoho.isYohoApp && yoho.isAndroid) {
... ... @@ -107,15 +113,12 @@ const getChannel = yoho => {
const getCacheKey = (req, route) => {
const urlObj = url.parse(req.url);
let ck = urlObj.pathname;
if (route.query) {
const qks = Object.keys(route.query);
ck += `?${qks
.map(qk => `${qk}=${(req.query && req.query[qk]) || ''}`)
.join('&')}`;
ck += `?${qks.map(qk => `${qk}=${req.query && req.query[qk] || ''}`).join('&')}`;
}
ck += `|${getChannel(req.yoho)}|${pkg.version}`;
... ... @@ -123,15 +126,11 @@ const getCacheKey = (req, route) => {
return md5(ck);
};
const render = route => {
const render = (route) => {
return async(req, res, next) => {
try {
res.setHeader('X-YOHO-Version', pkg.version);
const isDegrade = _.get(
req.app.locals.wap,
`webapp.${config.appName}-degrade`,
false,
);
const isDegrade = _.get(req.app.locals.wap, `webapp.${config.appName}-degrade`, false);
if (isDegrade) {
return res.send(degradeHtml);
... ... @@ -143,7 +142,7 @@ const render = route => {
const html = await redis.getAsync(ck);
res.set({
'Cache-Control': 'max-age=' + route.cacheTime || 60,
'Cache-Control': 'max-age=' + route.cacheTime || 60
});
if (html) {
logger.debug(`cached ${req.url}`);
... ... @@ -158,7 +157,7 @@ const render = route => {
res.set({
'Cache-Control': 'no-cache',
Pragma: 'no-cache',
Expires: new Date(1900, 0, 1, 0, 0, 0, 0).toUTCString(),
Expires: (new Date(1900, 0, 1, 0, 0, 0, 0)).toUTCString()
});
}
let context = getContext(req);
... ... @@ -168,16 +167,12 @@ const render = route => {
return handlerError(err, req, res, next);
}
let styles = context.renderStyles();
let scripts = context.renderScripts();
let resources = context.renderResourceHints();
const states = context.renderState();
let asyncScripts;
let zk = {
asyncJs: _.get(req.app.locals.wap, 'webapp.ios-async-js', true),
asyncJs: _.get(req.app.locals.wap, 'webapp.ios-async-js', true)
};
if (process.env.NODE_ENV === 'production') {
... ... @@ -199,7 +194,9 @@ const render = route => {
resources,
states,
zk,
download: req.query.share ? true : false,
routeHash: routeEncode.getRouter(req),
appPath: getAppPath(req)
});
if (config.useCache && route.cache && ck) {
... ... @@ -212,28 +209,24 @@ const render = route => {
}
};
};
const devRender = route => {
const devRender = (route) => {
return async(req, res, next) => {
try {
res.setHeader('X-YOHO-Version', pkg.version);
const ck = getCacheKey(req, route);
const isDegrade = _.get(
req.app.locals.wap,
`webapp.${config.appName}-degrade`,
false,
);
const isDegrade = _.get(req.app.locals.wap, `webapp.${config.appName}-degrade`, false);
if (isDegrade) {
return require('request-promise')({
url: 'http://m.yohobuy.com:6005/degrade.html',
url: 'http://m.yohobuy.com:6005/degrade.html'
}).pipe(res);
}
if (config.useCache && route.cache && ck) {
const html = await redis.getAsync(ck);
res.set({
'Cache-Control': 'max-age=' + route.cacheTime || 60,
'Cache-Control': 'max-age=' + route.cacheTime || 60
});
if (html) {
logger.debug(`cached ${req.url}`);
... ... @@ -245,12 +238,12 @@ const devRender = route => {
res.set({
'Cache-Control': 'no-cache',
Pragma: 'no-cache',
Expires: new Date(1900, 0, 1, 0, 0, 0, 0).toUTCString(),
Expires: (new Date(1900, 0, 1, 0, 0, 0, 0)).toUTCString()
});
}
let context = getContext(req);
process.send({ action: 'ssr_request', context });
process.send({action: 'ssr_request', context});
let event = msg => {
process.removeListener('message', event);
if (msg.action === 'ssr_request') {
... ... @@ -262,7 +255,7 @@ const devRender = route => {
} catch (error) {} // eslint-disable-line
return handlerError(err, req, res, next);
}
let { styles, scripts, resources, states, html } = msg;
let {styles, scripts, resources, states, html} = msg;
scripts = scripts.replace(/defer/g, 'defer crossorigin="anonymous"');
... ... @@ -274,6 +267,8 @@ const devRender = route => {
resources,
states,
routeHash: routeEncode.getRouter(req),
download: req.query.share ? true : false,
appPath: getAppPath(req)
});
if (config.useCache && route.cache && ck) {
... ...
... ... @@ -28,10 +28,15 @@
(function (d) {function vtn(e){var t,a=0,n=e.split(".").map(e=>Number(e));for(t=0;t<3;t++)a+=(n[t]||0)*Math.pow(100,2-t);return a}function gav(e,t){var a=e.match(new RegExp("(^|)app_version=([^"+t+"]*)("+t+"|$)"));return a&&a.length?a[2]:""}var appv=gav(d.cookie,";")||gav(location.href,"&");if(/YohoBuy/i.test(navigator.userAgent||"")&&/\(i[^;]+;( U;)? CPU.+Mac OS X/i.test(navigator.userAgent||"")&&appv&&vtn(appv)>=vtn("6.9.2")){var e=d.documentElement,n=e.clientHeight/e.clientWidth>2.1?"-high":"";d.getElementsByTagName("body")[0].className="immerse-body"+n}})(document);
</script>
{{{html}}}
<div id="degrade-app"></div>
<div id="main-wrap">
<div id="main-wrap" data-apppath='{{{appPath}}}'>
{{#unless download}}
<div id="no-download"></div>
{{/unless}}
</div>
{{{states}}}
{{#if zk.webperf}}
... ... @@ -76,7 +81,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 +125,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() {
... ...
{
"name": "yoho-community-web",
"version": "6.9.8-beta24",
"version": "6.9.8-beta39",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ... @@ -131,6 +131,7 @@
"stylus-loader": "^3.0.2",
"uglifyjs-webpack-plugin": "^2.0.1",
"url-loader": "^1.1.2",
"vconsole": "^3.3.2",
"webpack": "4.16.5",
"webpack-bundle-analyzer": "^3.0.3",
"webpack-cli": "^3.1.2",
... ...
... ... @@ -8856,6 +8856,11 @@ vary@^1, vary@~1.1.2:
version "1.1.2"
resolved "http://npm.yohops.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
vconsole@^3.3.2:
version "3.3.2"
resolved "http://npm.yohops.com/vconsole/-/vconsole-3.3.2.tgz#07424f8de2e5e2586c504042093948435ed2de06"
integrity sha1-B0JPjeLl4lhsUEBCCTlIQ17S3gY=
vendors@^1.0.0:
version "1.0.2"
resolved "http://npm.yohops.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801"
... ...