Skip to content

Commit f835df0

Browse files
feat(views/HomePage): migrate home to HomePage
1 parent 5f26453 commit f835df0

File tree

13 files changed

+818
-15
lines changed

13 files changed

+818
-15
lines changed

babel.config.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
11
module.exports = {
22
presets: ['@vue/app'],
3-
plugins: ['transform-export-extensions'],
3+
plugins: [
4+
'@babel/plugin-proposal-export-default-from',
5+
[
6+
'import',
7+
{
8+
libraryName: 'vant',
9+
libraryDirectory: 'es',
10+
style: true,
11+
},
12+
'vant',
13+
],
14+
],
415
};

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,19 @@
99
"dependencies": {
1010
"axios": "^0.18.0",
1111
"mavon-editor": "^2.1.10",
12+
"vant": "^1.3.1",
1213
"vue": "^2.5.17",
1314
"vue-axios": "^2.1.3",
1415
"vue-router": "^3.0.1",
1516
"vuex": "^3.0.1"
1617
},
1718
"devDependencies": {
19+
"@babel/plugin-proposal-export-default-from": "^7.0.0",
1820
"@vue/cli-plugin-babel": "^3.0.2",
1921
"@vue/cli-plugin-eslint": "^3.0.2",
2022
"@vue/cli-service": "^3.0.2",
2123
"@vue/eslint-config-airbnb": "^3.0.2",
22-
"babel-plugin-transform-export-extensions": "^6.22.0",
24+
"babel-plugin-import": "^1.8.0",
2325
"node-sass": "^4.9.3",
2426
"sass-loader": "^7.1.0",
2527
"vue-template-compiler": "^2.5.17"
+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<template>
2+
<div class="article-card">
3+
<span v-if="!simpleMode">
4+
<span class="top" v-if="article.top">置顶</span><span v-if="article.top"> ·</span>
5+
<span class="good" v-if="article.good">精华</span><span v-if="article.good"> ·</span>
6+
<span class="tab">{{ this.tabTypes[article.tab] }}</span> ·
7+
</span>
8+
<span class="last-reply-time">{{ article.last_reply_at | timeFormat}}</span>
9+
<h1 class="title">
10+
<router-link :to="{ name: 'article', params: {id: article.id}}">{{ article.title }}</router-link>
11+
</h1>
12+
<div class="author" @click="toAuthorDetail">
13+
<img class="avatar" :src="article.author.avatar_url" alt="article.author.loginname">
14+
<p class="loginname">{{ article.author.loginname }}</p>
15+
</div>
16+
<div class="info" v-if="!simpleMode">
17+
<i class="iconfont icon-clickQuery"></i>
18+
<span class="visit-count">{{ article.visit_count }}</span>
19+
<i class="iconfont icon-pinglun"></i>
20+
<span class="reply-count">{{ article.reply_count }}</span>
21+
</div>
22+
</div>
23+
</template>
24+
25+
<script type="text/ecmascript-6">
26+
import timeFormat from '@/common/utils/timeFormat';
27+
28+
export default {
29+
data() {
30+
return {
31+
tabTypes: {
32+
good: '精华',
33+
share: '分享',
34+
ask: '问答',
35+
job: '招聘',
36+
dev: '客户端测试',
37+
},
38+
};
39+
},
40+
methods: {
41+
toAuthorDetail() {
42+
this.$router.push(`/user/${this.article.author.loginname}`);
43+
},
44+
},
45+
filters: {
46+
timeFormat,
47+
},
48+
props: {
49+
article: {
50+
type: Object,
51+
required: true,
52+
},
53+
simpleMode: {
54+
type: Boolean,
55+
default: false,
56+
},
57+
},
58+
};
59+
</script>
60+
61+
<style lang="scss" rel="stylesheet/scss">
62+
/*屏幕宽度小于450px的设备*/
63+
@media screen and (max-width: 1200px) {
64+
.article-card {
65+
width: 100%;
66+
}
67+
}
68+
69+
/*屏幕宽度大于1200px的设备*/
70+
@media screen and (min-width: 1200px) {
71+
.article-card {
72+
width: 1200px;
73+
}
74+
}
75+
76+
.article-card {
77+
margin: 0 auto;
78+
padding: 12px 24px;
79+
border-bottom: 1px solid #eff2f7;
80+
background-color: #ffffff;
81+
font-size: 10px;
82+
position: relative;
83+
min-height: 100px;
84+
&:hover {
85+
background-color: #f9fafc;
86+
}
87+
/*对置顶,精华,和类型分配颜色样式*/
88+
.top {
89+
color: #ff4949;
90+
}
91+
.good {
92+
color: #f7ba2a;
93+
}
94+
.tab {
95+
color: #20a0ff;
96+
}
97+
/*标题样式*/
98+
.title {
99+
font-size: 16px;
100+
padding: 10px 60px 10px 0;
101+
word-wrap: break-word;
102+
}
103+
/*用户头像及用户名*/
104+
.author {
105+
position: absolute;
106+
bottom: 50%;
107+
transform: translateY(50%);
108+
right: 20px;
109+
text-align: center;
110+
width: 48px;
111+
.avatar {
112+
width: 48px;
113+
height: 48px;
114+
border-radius: 50%;
115+
border: 1px solid #eff2f7;
116+
}
117+
.loginname {
118+
color: #475669;
119+
font-size: 10px;
120+
white-space: nowrap;
121+
overflow: hidden;
122+
text-overflow: ellipsis;
123+
}
124+
}
125+
.info {
126+
font-size: 12px;
127+
color: #475669;
128+
padding: 2px 5px;
129+
border-radius: 10px;
130+
border: 1px solid #e5e9f2;
131+
display: inline-block;
132+
.iconfont {
133+
font-size: 12px;
134+
}
135+
}
136+
}
137+
</style>

src/components/ArticleCard/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default from './ArticleCard.vue';

src/components/Page/Page.vue

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<template>
2+
<div :style="`padding-bottom: ${hasTabBar ? '60px' : '0'}`"
3+
ref="page">
4+
<slot></slot>
5+
</div>
6+
</template>
7+
8+
<script>
9+
export default {
10+
props: {
11+
title: {
12+
type: String,
13+
default: 'CNode中文社区',
14+
},
15+
hasTabBar: {
16+
type: Boolean,
17+
default: false,
18+
},
19+
watchScroll: {
20+
type: Boolean,
21+
default: false,
22+
},
23+
loading: {
24+
type: Boolean,
25+
default: false,
26+
},
27+
},
28+
watch: {
29+
title(val) {
30+
document.title = val;
31+
},
32+
},
33+
mounted() {
34+
document.title = this.title;
35+
if (this.watchScroll) {
36+
window.addEventListener('scroll', this.watchScrollHandler);
37+
}
38+
},
39+
destroyed() {
40+
if (this.watchScroll) {
41+
window.removeEventListener('scroll', this.watchScrollHandler);
42+
}
43+
},
44+
methods: {
45+
watchScrollHandler() {
46+
const bottomDistance =
47+
this.$refs.page.offsetHeight -
48+
window.scrollY -
49+
document.documentElement.clientHeight;
50+
51+
if (bottomDistance <= 0 && !this.loading) {
52+
// ios <= 75
53+
this.$emit('reach-bottom', bottomDistance);
54+
}
55+
},
56+
},
57+
};
58+
</script>

src/components/Page/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default from './Page.vue';

0 commit comments

Comments
 (0)