Authored by yyq

topic

1 <template> 1 <template>
2 - <div v-if="data.topicImageUrl" class="topic-head" :style="headStyle">  
3 - <div class="center">  
4 - <p class="desc">{{data.topicDesc}}</p>  
5 - <div v-if="showAttAmount" class="att-amount">  
6 - <label>{{data.attAmount}}人已关注</label>  
7 - </div>  
8 - <div v-if="+data.allowAttention" class="att-topic-btn" :class="attClass" @click="onClick">  
9 - <WidgetFollow v-if="!share" class="att-click-wrap" :topic-id="data.topicId" :follow="data.hasAttention" @on-follow="onFollow"></WidgetFollow>  
10 - <template v-if="data.hasAttention">  
11 - 已关注  
12 - </template>  
13 - <template v-else>  
14 - <span class="iconfont icon-plus"></span>  
15 - 关注话题  
16 - </template> 2 + <div class="topic-banner" :style="headStyle">
  3 + <div class="banner-main">
  4 + <div class="topic-name">{{data.topicName}}</div>
  5 + <p class="topic-desc">{{data.topicDesc}}</p>
  6 + <div class="topic-extra">
  7 + <label class="att-amount">{{data.articleAmount}}人参与讨论</label>
  8 + <WidgetFollow v-if="+data.allowAttention" class="att-click-wrap" :topic-id="data.topicId" :follow="data.hasAttention" :share="share" @on-follow="onFollow"></WidgetFollow>
17 </div> 9 </div>
18 </div> 10 </div>
19 </div> 11 </div>
20 - <div v-else class="topic-head-empty" :style="headStyle"></div>  
21 </template> 12 </template>
22 13
23 <script> 14 <script>
@@ -44,22 +35,9 @@ export default { @@ -44,22 +35,9 @@ export default {
44 } 35 }
45 36
46 return style; 37 return style;
47 - },  
48 - showAttAmount() {  
49 - return this.data && +this.data.showAttAmount > 0;  
50 - },  
51 - attClass() {  
52 - return {  
53 - active: this.data.hasAttention  
54 - };  
55 } 38 }
56 }, 39 },
57 methods: { 40 methods: {
58 - onClick() {  
59 - if (this.share) {  
60 - return this.$links.toDownloadApp();  
61 - }  
62 - },  
63 onFollow(follow) { 41 onFollow(follow) {
64 this.$emit('on-follow', follow); 42 this.$emit('on-follow', follow);
65 }, 43 },
@@ -68,98 +46,70 @@ export default { @@ -68,98 +46,70 @@ export default {
68 </script> 46 </script>
69 47
70 <style scoped> 48 <style scoped>
71 -.topic-head {  
72 - min-height: 360px;  
73 - background-size: 100%;  
74 - box-sizing: border-box;  
75 - position: relative; 49 +.topic-banner {
76 background-size: cover; 50 background-size: cover;
77 - display: flex;  
78 - align-items: center; 51 + background-repeat: no-repeat;
  52 + background-color: #eee;
  53 + color: #fff;
  54 + position: relative;
79 55
80 - &:before {  
81 - content: "";  
82 - height: 1px;  
83 - position: absolute;  
84 - top: -1px;  
85 - left: 0;  
86 - right: 0;  
87 - z-index: 1;  
88 - box-shadow: 0 0 140px 40px #000; 56 + .banner-main {
  57 + height: 240px;
89 } 58 }
90 59
91 - .center {  
92 - width: 100%;  
93 - position: relative;  
94 - z-index: 2;  
95 - text-align: center;  
96 - padding: 40px 100px;  
97 - box-sizing: border-box; 60 + .topic-name {
  61 + height: 50px;
  62 + padding: 0 30px;
  63 + margin: 30px 0 18px;
  64 + font-size: 36px;
  65 + letter-spacing: 0.09PX;
  66 + font-weight: 800;
  67 + display: flex;
  68 + align-items: center;
98 } 69 }
99 70
100 - .desc { 71 + .topic-desc {
  72 + padding: 0 30px;
  73 + height: 60px;
101 font-size: 24px; 74 font-size: 24px;
102 - color: #fff;  
103 - line-height: 1.42;  
104 - word-break: break-all; 75 + font-weight: 300;
  76 + line-height: 30px;
  77 + overflow: hidden;
  78 + text-overflow: ellipsis;
  79 + display: -webkit-box;
  80 + -webkit-line-clamp: 2;
  81 + -webkit-box-orient: vertical;
105 } 82 }
106 83
107 - $attColor: #b0b0b0;  
108 -  
109 - .att-amount {  
110 - margin-top: 20px;  
111 - color: $attColor;  
112 - display: flex;  
113 - justify-content: center;  
114 -  
115 - label {  
116 - display: inline-block;  
117 - position: relative;  
118 - line-height: 1;  
119 -  
120 - &:before,  
121 - &:after {  
122 - content: "";  
123 - width: 60px;  
124 - height: 2px;  
125 - background-color: $attColor;  
126 - display: block;  
127 - position: absolute;  
128 - top: 50%;  
129 - margin-top: -1px;  
130 - }  
131 -  
132 - &:before {  
133 - right: calc(100% + 20px);  
134 - }  
135 -  
136 - &:after {  
137 - left: calc(100% + 20px);  
138 - }  
139 - }  
140 - }  
141 -  
142 - .att-topic-btn {  
143 - width: 200px;  
144 - height: 50px;  
145 - font-size: 26px;  
146 - border-radius: 28px;  
147 - line-height: 1; 84 + .topic-extra {
  85 + width: 100%;
  86 + height: 36px;
  87 + margin: 34px 0 40px;
148 display: flex; 88 display: flex;
149 align-items: center; 89 align-items: center;
150 - justify-content: center;  
151 - background-color: #d90025;  
152 - color: #fff;  
153 - margin: 36px auto 0;  
154 - position: relative; 90 + justify-content: space-between;
155 91
156 - .iconfont {  
157 - font-weight: bold;  
158 - margin-right: 10px; 92 + .att-amount {
  93 + font-size: 26px;
  94 + font-weight: 700px;
  95 + margin-left: 30px;
159 } 96 }
160 97
161 - &.active {  
162 - background-color: #e48a8a; 98 + .att-click-wrap {
  99 + width: 190px;
  100 + height: 60px;
  101 + padding-right: 36px;
  102 + margin-right: -32px;
  103 + border-radius: 31px;
  104 + border-color: #ff5660;
  105 + background-color: #ff5660;
  106 + color: #fff;
  107 + font-size: 32px;
  108 +
  109 + &.follow {
  110 + background: none;
  111 + border-color: #fff;
  112 + }
163 } 113 }
164 } 114 }
165 } 115 }
1 <template> 1 <template>
2 - <div class="fixed-header" :style="`background: rgba(64,64,64,${stepPercent});`"> 2 + <div class="fixed-header" :class="{'full-header': step >= 100}" :style="`background: rgba(255,255,255,${stepPercent});`">
3 <LayoutHeader theme="transparent"> 3 <LayoutHeader theme="transparent">
4 <template> 4 <template>
5 - <div ref="titleBlock" class="title-block">  
6 - <span :style="titleStyle">#{{title}}</span>  
7 - </div>  
8 - <div v-if="!share && +data.allowAttention" class="att-topic-btn" :class="attClass">  
9 - <WidgetFollow class="att-click-wrap" :topic-id="data.topicId" :follow="data.hasAttention" :share="share" @on-follow="onFollow"></WidgetFollow>  
10 - <span>{{data.hasAttention ? '已关注' : '关注'}}</span>  
11 - </div> 5 + <div ref="titleBlock" class="title-block" :style="titleStyle">#{{title}}</div>
12 </template> 6 </template>
13 <template v-slot:opts> 7 <template v-slot:opts>
14 <WidgetShare v-if="!share" class="topic-share" :option="shareOption" @click.native="onShare"></WidgetShare> 8 <WidgetShare v-if="!share" class="topic-share" :option="shareOption" @click.native="onShare"></WidgetShare>
15 </template> 9 </template>
16 </LayoutHeader> 10 </LayoutHeader>
  11 + <div class="suction-top-block">
  12 + <slot name="suctionTop"></slot>
  13 + </div>
17 </div> 14 </div>
18 </template> 15 </template>
19 16
@@ -39,41 +36,42 @@ export default { @@ -39,41 +36,42 @@ export default {
39 ], 36 ],
40 computed: { 37 computed: {
41 stepPercent() { 38 stepPercent() {
42 - return parseInt(this.step, 10) / 100; 39 + let percent = parseInt(this.step, 10) / 100;
  40 +
  41 + this.setIconColor(Math.floor((255 - 34) * (1 - percent) + 34));
  42 +
  43 + return percent;
43 }, 44 },
44 titleStyle() { 45 titleStyle() {
45 - let style = {};  
46 - let stepPercent = this.stepPercent;  
47 -  
48 - if (!this.offsetLeft) {  
49 - this.updateTitleOffset();  
50 - } 46 + const criticalPercent = 0.3;
  47 + const style = {
  48 + opacity: 0
  49 + };
51 50
52 - if (get(this, '$yoho.isiOS')) {  
53 - style.transform = `translate3d(${-stepPercent * this.offsetLeft}px, 0, 0)`;  
54 - } else {  
55 - style.transform = `translate3d(${this.stepPercent > 0.86 ? -this.offsetLeft : 0}px, 0, 0)`; 51 + if (this.stepPercent > criticalPercent) {
  52 + style.opacity = ((this.stepPercent - criticalPercent) / (1 - criticalPercent)).toFixed(2);
56 } 53 }
57 54
58 return style; 55 return style;
59 - },  
60 - attClass() {  
61 - return {  
62 - active: this.data.hasAttention,  
63 - show: this.stepPercent > 0.86  
64 - };  
65 } 56 }
66 }, 57 },
67 - watch: {  
68 - title() {  
69 - this.offsetLeft = 0;  
70 - } 58 + mounted() {
  59 + this._iconColor && this.setIconColor(this._iconColor);
71 }, 60 },
72 methods: { 61 methods: {
73 - updateTitleOffset() {  
74 - if (this.$refs && this.$refs.titleBlock) {  
75 - this.$nextTick(() => {  
76 - this.offsetLeft = this.$refs.titleBlock.offsetLeft + 40; 62 + setIconColor(color) {
  63 + if (!this.$el) {
  64 + this._iconColor = color;
  65 + return;
  66 + }
  67 +
  68 + if (!this.icons) {
  69 + this.icons = [...this.$el.querySelectorAll('.back .iconfont'), ...this.$el.querySelectorAll('.opts .iconfont')];
  70 + }
  71 +
  72 + if (this.icons && this.icons.length) {
  73 + this.icons.forEach(dom => {
  74 + dom.style.color = `rgb(${color},${color},${color})`;
77 }); 75 });
78 } 76 }
79 }, 77 },
@@ -89,30 +87,34 @@ export default { @@ -89,30 +87,34 @@ export default {
89 87
90 <style scoped> 88 <style scoped>
91 .fixed-header { 89 .fixed-header {
92 - position: fixed; 90 + position: absolute;
93 width: 100%; 91 width: 100%;
94 z-index: 10; 92 z-index: 10;
95 - transition: all 500ms; 93 + transition: background 50ms;
  94 +
  95 + &.full-header:after {
  96 + content: "";
  97 + background-color: #fff;
  98 + position: absolute;
  99 + left: 0;
  100 + right: 0;
  101 + top: 0;
  102 + bottom: 0;
  103 + z-index: -1;
  104 + }
96 105
97 /deep/ .title { 106 /deep/ .title {
98 overflow: visible!important; 107 overflow: visible!important;
99 } 108 }
100 109
101 .title-block { 110 .title-block {
102 - font-size: 0;  
103 -  
104 - > span {  
105 - max-width: 400px;  
106 - line-height: 1.2;  
107 - font-size: 36px;  
108 - display: inline-block;  
109 - vertical-align: super;  
110 - overflow: hidden;  
111 - text-overflow:ellipsis;  
112 - white-space: nowrap;  
113 - position: relative;  
114 - transition: all 116ms;  
115 - } 111 + color: #222;
  112 + line-height: 1.2;
  113 + font-size: 36px;
  114 + overflow: hidden;
  115 + text-overflow:ellipsis;
  116 + white-space: nowrap;
  117 + transition: opacity 100ms;
116 } 118 }
117 119
118 .att-topic-btn { 120 .att-topic-btn {
@@ -153,5 +155,11 @@ export default { @@ -153,5 +155,11 @@ export default {
153 .topic-share { 155 .topic-share {
154 margin-right: 26px; 156 margin-right: 26px;
155 } 157 }
  158 +
  159 + .suction-top-block {
  160 + width: 100%;
  161 + position: absolute;
  162 + top: 100%;
  163 + }
156 } 164 }
157 </style> 165 </style>
  1 +<template>
  2 + <div class="tab-block">
  3 + <div v-for="(tab, index) in tabList" :key="index" :ref="'tab-item' + index" class="tab-item" :class="{active: index == activeIndex}" @click="changeType(index)">
  4 + <div class="name">{{tab.name}}</div>
  5 + <div v-if="index == statusBlockIndex" ref="statusBlock" class="tab-status-block" :style="statusBlockStyle"></div>
  6 + </div>
  7 + </div>
  8 +</template>
  9 +
  10 +<script>
  11 +import {findIndex} from 'lodash';
  12 +
  13 +export default {
  14 + props: {
  15 + activeType: {
  16 + type: Number,
  17 + default: 0
  18 + }
  19 + },
  20 + data() {
  21 + let tabList = [
  22 + {name: '最新', type: 2},
  23 + {name: '热门', type: 1},
  24 + ];
  25 + let index = Math.max(findIndex(tabList, {type: this.activeType}), 0);
  26 +
  27 + return {
  28 + tabList,
  29 + statusBlockIndex: index,
  30 + activeIndex: index,
  31 + statusBlockStyle: {}
  32 + };
  33 + },
  34 + watch: {
  35 + activeType(val) {
  36 + let index = findIndex(this.tabList, {type: val});
  37 +
  38 + if (index > -1) {
  39 + this.activeIndex = index;
  40 + }
  41 + },
  42 + activeIndex() {
  43 + this.changeStatusBlockStyle();
  44 + }
  45 + },
  46 + methods: {
  47 + changeType(index) {
  48 + this.activeIndex = index;
  49 + this.$emit('on-change-tab', {...this.tabList[index]});
  50 + },
  51 + changeStatusBlockStyle() {
  52 + const baseDom = this.$refs['tab-item' + this.statusBlockIndex];
  53 +
  54 + if (baseDom) {
  55 + const baseLeft = baseDom[0].offsetLeft;
  56 + const {offsetLeft, offsetWidth} = this.$refs['tab-item' + this.activeIndex][0] || {};
  57 +
  58 + this.statusBlockStyle = {
  59 + transform: `translate3d(${offsetLeft - baseLeft}px, 0, 0)`,
  60 + width: offsetWidth + 'px'
  61 + };
  62 + }
  63 + }
  64 + }
  65 +};
  66 +</script>
  67 +
  68 +<style scoped>
  69 +.tab-block {
  70 + height: 100px;
  71 + background-color: #fff;
  72 + display: flex;
  73 + justify-content: center;
  74 + font-size: 32px;
  75 +
  76 + .tab-item {
  77 + margin: 0 38px;
  78 + padding-top: 20px;
  79 + color: #b0b0b0;
  80 + position: relative;
  81 +
  82 + &.active {
  83 + color: #222;
  84 + font-weight: 500;
  85 + }
  86 +
  87 + .name {
  88 + margin-bottom: 4px;
  89 + }
  90 + }
  91 +
  92 + .tab-status-block {
  93 + width: 100%;
  94 + height: 10px;
  95 + background: #d0021b;
  96 + box-shadow: 0 4px 8px 0 rgba(210,0,13,0.34);
  97 + position: absolute;
  98 + transition: all 500ms;
  99 + }
  100 +}
  101 +
  102 +</style>
1 <template> 1 <template>
2 <div> 2 <div>
3 <Layout class="article"> 3 <Layout class="article">
4 - <TopicHeader ref="header" :title="topicTitle" :step="headerAnimateStep" :data="topicSimpleInfo" :share="share" @on-follow="onFollowTopic"></TopicHeader> 4 + <TopicHeader ref="header" :title="topicTitle" :step="headerAnimateStep" :data="topicSimpleInfo" :share="share" @on-follow="onFollowTopic">
  5 + <template v-if="tabBlockSuctionTop" v-slot:suctionTop>
  6 + <TopicTabBlock :active-type="activeTopicListType" @on-change-tab="onChangeTab"></TopicTabBlock>
  7 + </template>
  8 + </TopicHeader>
5 9
6 <RecycleScrollReveal :size="5" :thumbs="thumbs" ref="scroll" @scroll="onScroll" :offset="800" :on-fetch="onFetch" :manual-init="true" 10 <RecycleScrollReveal :size="5" :thumbs="thumbs" ref="scroll" @scroll="onScroll" :offset="800" :on-fetch="onFetch" :manual-init="true"
7 @on-inited="onInited"> 11 @on-inited="onInited">
8 <template v-slot:eternalTop> 12 <template v-slot:eternalTop>
9 - <TopicBanner ref="topicHead" :data="topicSimpleInfo" :share="share" @on-follow="onFollowTopic"></TopicBanner> 13 + <TopicBanner ref="topicBanner" :data="topicSimpleInfo" :share="share" @on-follow="onFollowTopic"></TopicBanner>
  14 + <TopicTabBlock :active-type="activeTopicListType" @on-change-tab="onChangeTab"></TopicTabBlock>
10 </template> 15 </template>
11 <template class="article-item" #item="{ data }"> 16 <template class="article-item" #item="{ data }">
12 <ArticleItem2 17 <ArticleItem2
@@ -31,17 +36,6 @@ @@ -31,17 +36,6 @@
31 立即参与 36 立即参与
32 </a> 37 </a>
33 </Layout> 38 </Layout>
34 - <ArticleActionSheet v-if="showArticleDetailAction" ref="actionSheet"></ArticleActionSheet>  
35 - <YohoActionSheet transfer v-if="showCommentAction" ref="commentAction" :full="true">  
36 - <Comment ref="comment"  
37 - :destId="articleId"  
38 - :popup="true"  
39 - :article-id="articleId"  
40 - :pos-id="posId"  
41 - @on-close="onClose"  
42 - @on-comment="onActionComment"></Comment>  
43 - </YohoActionSheet>  
44 - <MoreActionSheet transfer ref="moreAction" @on-follow="onFollow" @on-delete="onDelete"></MoreActionSheet>  
45 </div> 39 </div>
46 </template> 40 </template>
47 41
@@ -55,6 +49,7 @@ import ArticleActionSheet from './components/detail/article-action-sheet'; @@ -55,6 +49,7 @@ import ArticleActionSheet from './components/detail/article-action-sheet';
55 import MoreActionSheet from './components/detail/more-action-sheet'; 49 import MoreActionSheet from './components/detail/more-action-sheet';
56 import TopicHeader from './components/topic/header'; 50 import TopicHeader from './components/topic/header';
57 import TopicBanner from './components/topic/banner'; 51 import TopicBanner from './components/topic/banner';
  52 +import TopicTabBlock from './components/topic/tab-block';
58 import {mapState as mapYohoState, mapActions as mapYohoActions, mapMutations as mapYohoMutations, createNamespacedHelpers} from 'vuex'; 53 import {mapState as mapYohoState, mapActions as mapYohoActions, mapMutations as mapYohoMutations, createNamespacedHelpers} from 'vuex';
59 const {mapState, mapMutations, mapActions} = createNamespacedHelpers('article'); 54 const {mapState, mapMutations, mapActions} = createNamespacedHelpers('article');
60 55
@@ -70,14 +65,8 @@ export default { @@ -70,14 +65,8 @@ export default {
70 topicId: 0, 65 topicId: 0,
71 topicName: '', 66 topicName: '',
72 headerAnimateStep: 0, 67 headerAnimateStep: 0,
73 - articleId: 0,  
74 - articleIndex: -1,  
75 - showCommentAction: false,  
76 - showCommentActioning: false,  
77 - showArticleDetailAction: false,  
78 - showMoreAction: true,  
79 scrollTop: 0, 68 scrollTop: 0,
80 - currentId: 0, 69 + activeTopicListType: 2,
81 colWidthForTwo: 0, 70 colWidthForTwo: 0,
82 scrolling: false 71 scrolling: false
83 }; 72 };
@@ -140,11 +129,25 @@ export default { @@ -140,11 +129,25 @@ export default {
140 return this.topicInfo[this.topicId] || {}; 129 return this.topicInfo[this.topicId] || {};
141 }, 130 },
142 publishUrl() { 131 publishUrl() {
143 - return this.topicId ? `?openby:yohobuy={"action":"go.grasspublish","params":{"topicId":"${this.topicId}","topicName":"${this.topicName}"}}` : ''; 132 + let params = {};
  133 +
  134 + if (this.topicId) {
  135 + params.topicId = this.topicId;
  136 + params.topicName = this.topicName;
  137 +
  138 + if (+this.topicSimpleInfo.isReward === 1) {
  139 + params.rewardNotice = this.topicSimpleInfo.rewardNotice;
  140 + }
  141 + }
  142 +
  143 + return `?openby:yohobuy={"action":"go.grasspublish","params":${JSON.stringify(params)}}`;
144 }, 144 },
145 topicTitle() { 145 topicTitle() {
146 return this.topicName || this.topicSimpleInfo.topicName || ''; 146 return this.topicName || this.topicSimpleInfo.topicName || '';
147 }, 147 },
  148 + tabBlockSuctionTop() {
  149 + return this.scrollTop >= (this._topicHeaderHeight - this._headerHeight);
  150 + },
148 headerBgOpacity() { 151 headerBgOpacity() {
149 return this.headerAnimateStep / 100; 152 return this.headerAnimateStep / 100;
150 } 153 }
@@ -152,78 +155,38 @@ export default { @@ -152,78 +155,38 @@ export default {
152 methods: { 155 methods: {
153 ...mapYohoActions(['fetchUserProfile']), 156 ...mapYohoActions(['fetchUserProfile']),
154 ...mapYohoMutations(['SET_STATUS_BAR_COLOR']), 157 ...mapYohoMutations(['SET_STATUS_BAR_COLOR']),
155 - ...mapActions(['fetchTopicSimpleInfo', 'fetchTopicRelatedArticles', 'fetchArticleProductFavs']),  
156 - ...mapMutations(['ASYNC_ARTICLE_COMMENT', 'CHANGE_AUTHOR_FOLLOW', 'CHANGE_TOPIC_FOLLOW']),  
157 - onShowComment({articleId, index}) {  
158 - this.articleId = articleId;  
159 - this.articleIndex = index;  
160 - this.showCommentAction = true;  
161 - this.$nextTick(() => {  
162 - if (this.showCommentActioning) {  
163 - return;  
164 - }  
165 - this.showCommentActioning = true;  
166 - this.$refs.comment.init();  
167 - this.$refs.commentAction.show();  
168 - setTimeout(() => {  
169 - this.showCommentActioning = false;  
170 - }, 300);  
171 - });  
172 - },  
173 - onShowMore({article, index}) {  
174 - this.$refs.moreAction.show(article, this.userUid, index);  
175 - },  
176 - onDelete(index) {  
177 - this.$refs.scroll.delete(index);  
178 - },  
179 - onPageReady({success}) {  
180 - if (success && this.showCommentAction) {  
181 - this.$refs.commentAction.show();  
182 - setTimeout(() => {  
183 - this.showCommentActioning = false;  
184 - }, 300);  
185 - } else {  
186 - this.showCommentActioning = false;  
187 - }  
188 - },  
189 - onUnlockHeight(params) {  
190 - this.$refs.scroll.unlockHight(params);  
191 - },  
192 - onClose() {  
193 - this.$refs.commentAction.hide();  
194 - },  
195 - onActionComment() {  
196 - this.ASYNC_ARTICLE_COMMENT({articleId: this.articleId, type: this.type});  
197 - this.onResize(this.articleIndex); 158 + ...mapActions(['fetchTopicSimpleInfo', 'fetchTopicRelatedArticles']),
  159 + ...mapMutations(['CHANGE_AUTHOR_FOLLOW', 'CHANGE_TOPIC_FOLLOW']),
  160 + onChangeTab({type}) {
  161 + this.page = 1;
  162 + this.activeTopicListType = type;
  163 + this.$refs.scroll && this.$refs.scroll.init();
198 }, 164 },
199 - onScroll(params) { 165 + onScroll({item, scrollTop, startIndex, items}) {
200 this.scrolling = true; 166 this.scrolling = true;
201 this._scTimer && clearTimeout(this._scTimer); 167 this._scTimer && clearTimeout(this._scTimer);
202 this._scTimer = setTimeout(() => { 168 this._scTimer = setTimeout(() => {
203 this.scrolling = false; 169 this.scrolling = false;
204 }, 400); 170 }, 400);
205 171
206 - this.scrollEvent(params);  
207 - this._ttTimer && clearTimeout(this._ttTimer);  
208 - this._ttTimer = setTimeout(() => {  
209 - this.scrollEvent(params);  
210 - }, throttleTime); 172 + this.updateHeadAnimateStep(scrollTop);
  173 + this.scrollTop = scrollTop || 0;
  174 + this.scrollEvent({item, scrollTop, startIndex, items});
211 }, 175 },
212 - onDounceScroll({item, scrollTop, startIndex, items}) { 176 + updateHeadAnimateStep(scrollTop) {
213 if (this.scrollTop === scrollTop) { 177 if (this.scrollTop === scrollTop) {
214 return; 178 return;
215 } 179 }
216 180
217 - this.scrollTop = scrollTop || 0;  
218 this._headerHeight = this._headerHeight || this.$refs.header.$el.offsetHeight; 181 this._headerHeight = this._headerHeight || this.$refs.header.$el.offsetHeight;
219 - this._topicHeaderHeight = this._topicHeaderHeight || this.$refs.topicHead.$el.offsetHeight;  
220 -  
221 - let step = Math.round((scrollTop - 10) / (this._topicHeaderHeight - this._headerHeight) * 100); 182 + this._topicHeaderHeight = this._topicHeaderHeight || this.$refs.topicBanner.$el.offsetHeight;
222 183
223 - if (step && this.topicSimpleInfo.topicImageUrl) { 184 + let step = Math.round((scrollTop - 4) / (this._topicHeaderHeight - this._headerHeight - 10) * 100);
  185 + if (step) {
224 this.headerAnimateStep = Math.max(Math.min(step, 100), 0); 186 this.headerAnimateStep = Math.max(Math.min(step, 100), 0);
225 } 187 }
226 - 188 + },
  189 + onDounceScroll({items}) {
227 this.reportArticleShow(items); 190 this.reportArticleShow(items);
228 }, 191 },
229 init() { 192 init() {
@@ -254,9 +217,13 @@ export default { @@ -254,9 +217,13 @@ export default {
254 this.headerAnimateStep = 100; 217 this.headerAnimateStep = 100;
255 } 218 }
256 }), 219 }),
257 - this.fetchTopicRelatedArticles({topicId: this.topicId, page: 1}).then(res => { 220 + this.fetchTopicRelatedArticles({
  221 + topicId: this.topicId,
  222 + type: this.activeTopicListType,
  223 + page: 1
  224 + }).then(res => {
258 if (res.code === 200) { 225 if (res.code === 200) {
259 - this.listPreCache[`${this.topicId}-1`] = res; 226 + this.listPreCache[`${this.topicId}-${this.activeTopicListType}-1`] = res;
260 } 227 }
261 }) 228 })
262 ]); 229 ]);
@@ -271,12 +238,15 @@ export default { @@ -271,12 +238,15 @@ export default {
271 this.fetching = true; 238 this.fetching = true;
272 this.page = this.page || 1; 239 this.page = this.page || 1;
273 240
274 - let result = get(this.listPreCache, `${this.topicId}-${this.page}`); 241 + let result = get(this.listPreCache, `${this.topicId}-${this.activeTopicListType}-${this.page}`);
275 242
276 - if (!result) { 243 + if (result) {
  244 + this.listPreCache = {};
  245 + } else {
277 result = await this.fetchTopicRelatedArticles({ 246 result = await this.fetchTopicRelatedArticles({
278 topicId, 247 topicId,
279 - page: this.page 248 + page: this.page,
  249 + type: this.activeTopicListType
280 }); 250 });
281 } 251 }
282 252
@@ -304,24 +274,10 @@ export default { @@ -304,24 +274,10 @@ export default {
304 onInited(items) { 274 onInited(items) {
305 this.reportArticleShow(items); 275 this.reportArticleShow(items);
306 }, 276 },
307 - onFollow(data, follow) {  
308 - this.CHANGE_AUTHOR_FOLLOW({authorUid: data.authorUid, authorType: data.authorType, follow, type: this.type});  
309 - },  
310 onFollowTopic(follow) { 277 onFollowTopic(follow) {
311 this.CHANGE_TOPIC_FOLLOW({topicId: this.topicId, follow}); 278 this.CHANGE_TOPIC_FOLLOW({topicId: this.topicId, follow});
312 follow && this.reportTopicFollow(); 279 follow && this.reportTopicFollow();
313 }, 280 },
314 - onResize(index) {  
315 - this.$nextTick(() => {  
316 - this.$refs.scroll.resize(index);  
317 - });  
318 - },  
319 - onShowGuang(params) {  
320 - this.showArticleDetailAction = true;  
321 - this.$nextTick(() => {  
322 - this.$refs.actionSheet.show(params);  
323 - });  
324 - },  
325 setPageShareInfo({topicName, topicImageUrl, topicDesc}) { 281 setPageShareInfo({topicName, topicImageUrl, topicDesc}) {
326 if (this.share) { 282 if (this.share) {
327 document && (document.title = topicName || '话题'); 283 document && (document.title = topicName || '话题');
@@ -392,75 +348,62 @@ export default { @@ -392,75 +348,62 @@ export default {
392 } 348 }
393 }, 349 },
394 components: { 350 components: {
395 - ArticleItem,  
396 ArticleItem2, 351 ArticleItem2,
397 - ArticleActionSheet,  
398 - MoreActionSheet,  
399 TopicHeader, 352 TopicHeader,
400 - TopicBanner 353 + TopicBanner,
  354 + TopicTabBlock
401 } 355 }
402 }; 356 };
403 </script> 357 </script>
404 358
405 <style scoped> 359 <style scoped>
406 - /deep/ .recycle-scroll-reveal-main {  
407 - background-color: #f7f7f7; 360 +/deep/ .recycle-scroll-reveal-main {
  361 + background-color: #f7f7f7;
408 362
409 - .scroll-reveal-list {  
410 - padding: 5px;  
411 - } 363 + .scroll-reveal-list {
  364 + padding: 5px;
412 } 365 }
  366 +}
413 367
414 - /deep/ .att-click-wrap {  
415 - opacity: 0;  
416 - position: absolute;  
417 - left: 0;  
418 - top: 0;  
419 - width: 100%;  
420 - height: 100%;  
421 - z-index: 1;  
422 - } 368 +/deep/ .cube-recycle-list-items {
  369 + padding-top: 54PX;
423 370
424 - /deep/ .cube-recycle-list-items {  
425 - padding-top: 54PX;  
426 -  
427 - .cube-recycle-list-item:first-child {  
428 - margin-top: -54PX;  
429 - } 371 + .cube-recycle-list-item:first-child {
  372 + margin-top: -54PX;
  373 + }
  374 +}
  375 +
  376 +.publish-btn {
  377 + width: 260px;
  378 + height: 80px;
  379 + border-radius: 42px;
  380 + font-size: 30px;
  381 + color: #fff;
  382 + background: #D0021B;
  383 + position: absolute;
  384 + bottom: 100px;
  385 + left: calc(50% - 130px);
  386 + z-index: 1;
  387 + display: flex;
  388 + align-items: center;
  389 + transition: all 600ms ease-in-out;
  390 +
  391 + &.scroll-opacity {
  392 + opacity: 0.3;
430 } 393 }
431 394
432 - .publish-btn {  
433 - width: 260px;  
434 - height: 80px;  
435 - border-radius: 42px;  
436 - font-size: 30px;  
437 - color: #fff;  
438 - background: #D0021B;  
439 - position: absolute;  
440 - bottom: 100px;  
441 - left: calc(50% - 130px);  
442 - z-index: 1;  
443 - display: flex;  
444 - align-items: center;  
445 - transition: all 600ms ease-in-out;  
446 -  
447 - &.scroll-opacity {  
448 - opacity: 0.3;  
449 - }  
450 -  
451 - .avatar-block {  
452 - width: 52px;  
453 - height: 52px;  
454 - margin: 14px 30px 14px 14px;  
455 - border-radius: 50%;  
456 - overflow: hidden;  
457 - }  
458 -  
459 - .avatar {  
460 - display: block;  
461 - width: 100%;  
462 - height: 100%;  
463 - } 395 + .avatar-block {
  396 + width: 52px;
  397 + height: 52px;
  398 + margin: 14px 30px 14px 14px;
  399 + border-radius: 50%;
  400 + overflow: hidden;
464 } 401 }
465 402
  403 + .avatar {
  404 + display: block;
  405 + width: 100%;
  406 + height: 100%;
  407 + }
  408 +}
466 </style> 409 </style>
@@ -302,11 +302,12 @@ export default { @@ -302,11 +302,12 @@ export default {
302 302
303 return result; 303 return result;
304 }, 304 },
305 - async fetchTopicRelatedArticles({ commit, state }, {topicId, page, lastedTime}) { 305 + async fetchTopicRelatedArticles({ commit, state }, {topicId, page, type}) {
306 commit(Types.FETCH_ARTICLE_TOPIC_REQUEST, { page }); 306 commit(Types.FETCH_ARTICLE_TOPIC_REQUEST, { page });
307 const result = await this.$api.post('/api/grass/topicRelatedArticles', { 307 const result = await this.$api.post('/api/grass/topicRelatedArticles', {
308 topicId, 308 topicId,
309 page, 309 page,
  310 + type,
310 limit: 6, 311 limit: 6,
311 lastedTime: state.articleLastedTimeByTopic || void 0 312 lastedTime: state.articleLastedTimeByTopic || void 0
312 }); 313 });
@@ -13,6 +13,7 @@ module.exports = { @@ -13,6 +13,7 @@ module.exports = {
13 topicId: {type: Number, require: true}, 13 topicId: {type: Number, require: true},
14 limit: {type: Number}, 14 limit: {type: Number},
15 page: {type: Number}, 15 page: {type: Number},
  16 + type: {type: Number},
16 lastedTime: {type: Number} 17 lastedTime: {type: Number}
17 } 18 }
18 }, 19 },