Skip to content

Commit c3ead74

Browse files
committed
updated:adapt mobile device
1 parent b305680 commit c3ead74

1 file changed

Lines changed: 181 additions & 52 deletions

File tree

frontend/src/views/Home.vue

Lines changed: 181 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
<template>
22
<div class="home">
3-
<el-container>
4-
<el-aside width="220px">
3+
<el-container :class="['home-container', { 'is-mobile': isMobile }]">
4+
<el-aside
5+
v-if="!isMobile"
6+
width="220px"
7+
class="sidebar"
8+
>
59
<div class="user-profile">
610
<el-avatar :size="100" :src="avatarUrl"></el-avatar>
711
<h3>{{ signature }}</h3>
@@ -10,19 +14,35 @@
1014
<h4 class="cat-title">分类</h4>
1115
<el-tag
1216
:type="selectedCategories.length === 0 ? 'success' : 'info'"
13-
size="small" class="cat-item" effect="light"
14-
@click="clearCategories">全部</el-tag>
17+
size="small"
18+
class="cat-item"
19+
effect="light"
20+
@click="clearCategories"
21+
>全部</el-tag>
1522
<el-tag
16-
v-for="c in categories" :key="c"
23+
v-for="c in categories"
24+
:key="c"
1725
:type="isActive(c) ? 'success' : 'info'"
18-
size="small" class="cat-item" @click="toggleCategory(c)"
19-
effect="light">
26+
size="small"
27+
class="cat-item"
28+
effect="light"
29+
@click="toggleCategory(c)"
30+
>
2031
{{ c || '未分类' }}
2132
</el-tag>
2233
</div>
2334
</el-aside>
24-
<el-main>
35+
<el-main :class="{ 'mobile-main': isMobile }">
2536
<div class="toolbar">
37+
<el-button
38+
v-if="isMobile"
39+
class="sidebar-toggle"
40+
type="primary"
41+
text
42+
@click="drawerVisible = true"
43+
>
44+
<el-icon><Menu /></el-icon>
45+
</el-button>
2646
<el-input
2747
v-model="keyword"
2848
placeholder="搜索标题或摘要..."
@@ -74,48 +94,84 @@
7494
</el-pagination>
7595
</el-main>
7696
</el-container>
97+
<el-drawer
98+
v-if="isMobile"
99+
v-model="drawerVisible"
100+
:with-header="false"
101+
direction="ltr"
102+
size="260px"
103+
class="sidebar-drawer"
104+
>
105+
<div class="sidebar">
106+
<div class="user-profile">
107+
<el-avatar :size="100" :src="avatarUrl"></el-avatar>
108+
<h3>{{ signature }}</h3>
109+
</div>
110+
<div class="category-panel">
111+
<h4 class="cat-title">分类</h4>
112+
<el-tag
113+
:type="selectedCategories.length === 0 ? 'success' : 'info'"
114+
size="small"
115+
class="cat-item"
116+
effect="light"
117+
@click="clearCategories"
118+
>全部</el-tag>
119+
<el-tag
120+
v-for="c in categories"
121+
:key="c"
122+
:type="isActive(c) ? 'success' : 'info'"
123+
size="small"
124+
class="cat-item"
125+
effect="light"
126+
@click="toggleCategory(c)"
127+
>
128+
{{ c || '未分类' }}
129+
</el-tag>
130+
</div>
131+
</div>
132+
</el-drawer>
77133
</div>
78134
</template>
79135

80136
<script>
81-
import { ref, onMounted } from 'vue';
137+
import { ref, onMounted, onUnmounted } from 'vue';
82138
import { useRouter } from 'vue-router';
83139
import api from '@/api';
84140
import { loadConfig } from '@/config';
141+
import { Menu } from '@element-plus/icons-vue';
85142
86143
export default {
87144
name: 'Home',
88145
setup() {
89-
const getAvatarUrl = () => {
90-
try {
91-
return new URL(`../assets/${config.avatarPath}`, import.meta.url).href;
92-
} catch (e) {
93-
console.error(e);
94-
return 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png';
95-
}
96-
};
97-
98-
const avatarUrl = ref('');
99-
const signature = ref('');
100-
const articles = ref([]);
101-
const keyword = ref('');
102-
const categories = ref([]);
103-
const selectedCategories = ref([]);
146+
const avatarUrl = ref('');
147+
const signature = ref('');
148+
const articles = ref([]);
149+
const keyword = ref('');
150+
const categories = ref([]);
151+
const selectedCategories = ref([]);
104152
const currentPage = ref(1);
105153
const pageSize = ref(5);
106154
const total = ref(0);
107-
const aboutContent = ref('');
155+
const isMobile = ref(false);
156+
const drawerVisible = ref(false);
157+
158+
const updateIsMobile = () => {
159+
isMobile.value = window.innerWidth <= 768;
160+
if (!isMobile.value) {
161+
drawerVisible.value = false;
162+
}
163+
};
108164
109-
const fetchArticles = async (page) => {
165+
const fetchArticles = async (page) => {
110166
try {
111-
const kw = keyword.value.trim();
112-
let response;
113-
if (kw) {
114-
// 全文搜索接口不支持分类过滤,清空分类以避免误导
115-
response = await api.searchArticles(kw, page, pageSize.value);
116-
} else {
117-
response = await api.getArticles(page, pageSize.value, selectedCategories.value);
118-
}
167+
const kw = keyword.value.trim();
168+
let response;
169+
if (kw) {
170+
// 全文搜索接口不支持分类过滤,清空分类以避免误导
171+
response = await api.searchArticles(kw, page, pageSize.value);
172+
} else {
173+
response = await api.getArticles(page, pageSize.value, selectedCategories.value);
174+
}
119175
articles.value = response.data.articles;
120176
total.value = response.data.total;
121177
} catch (error) {
@@ -143,11 +199,17 @@ export default {
143199
}
144200
currentPage.value = 1;
145201
fetchArticles(currentPage.value);
202+
if (isMobile.value) {
203+
drawerVisible.value = false;
204+
}
146205
};
147-
const clearCategories = () => {
206+
const clearCategories = () => {
148207
if (keyword.value.trim()) keyword.value = '';
149-
selectedCategories.value = [];
150-
fetchArticles(1);
208+
selectedCategories.value = [];
209+
fetchArticles(1);
210+
if (isMobile.value) {
211+
drawerVisible.value = false;
212+
}
151213
};
152214
const isActive = (c) => selectedCategories.value.includes(c);
153215
@@ -187,10 +249,11 @@ export default {
187249
};
188250
189251
onMounted(async () => {
252+
updateIsMobile();
253+
window.addEventListener('resize', updateIsMobile);
190254
try {
191255
const conf = await loadConfig();
192256
signature.value = conf.signature || '鼠鼠很懒,什么都没有留下';
193-
aboutContent.value = conf.about || '鼠鼠很懒,什么都没有留下';
194257
try {
195258
avatarUrl.value = new URL(`../assets/${conf.avatarPath}`, import.meta.url).href;
196259
} catch { avatarUrl.value = ''; }
@@ -199,6 +262,10 @@ export default {
199262
fetchArticles(currentPage.value);
200263
});
201264
265+
onUnmounted(() => {
266+
window.removeEventListener('resize', updateIsMobile);
267+
});
268+
202269
return {
203270
avatarUrl,
204271
signature,
@@ -207,18 +274,20 @@ export default {
207274
currentPage,
208275
pageSize,
209276
total,
210-
handlePageChange,
211-
categories,
212-
selectedCategories,
213-
toggleCategory,
214-
clearCategories,
215-
isActive,
216-
goDetail,
217-
splitTags,
218-
formatDate,
219-
doSearch,
220-
clearSearch,
221-
aboutContent,
277+
handlePageChange,
278+
categories,
279+
selectedCategories,
280+
toggleCategory,
281+
clearCategories,
282+
isActive,
283+
goDetail,
284+
splitTags,
285+
formatDate,
286+
doSearch,
287+
clearSearch,
288+
isMobile,
289+
drawerVisible,
290+
Menu,
222291
};
223292
},
224293
};
@@ -228,14 +297,52 @@ export default {
228297
.home {
229298
padding: 20px;
230299
}
300+
.home-container {
301+
min-height: calc(100vh - 80px);
302+
}
303+
.home-container.is-mobile {
304+
flex-direction: column;
305+
}
306+
.sidebar {
307+
display: flex;
308+
flex-direction: column;
309+
gap: 20px;
310+
}
231311
.user-profile {
232312
text-align: center;
233313
background-color: rgba(255, 255, 255, 0.7);
234314
padding: 20px;
235315
border-radius: 10px;
236316
}
237-
.toolbar { display:flex; justify-content:flex-end; margin-bottom:12px; }
238-
.search-input { max-width: 360px; }
317+
.toolbar {
318+
display: flex;
319+
align-items: center;
320+
gap: 12px;
321+
justify-content: flex-end;
322+
margin-bottom: 12px;
323+
}
324+
.sidebar-toggle {
325+
display: inline-flex;
326+
align-items: center;
327+
justify-content: center;
328+
padding: 4px 6px;
329+
border-radius: 6px;
330+
}
331+
.sidebar-toggle .el-icon {
332+
font-size: 20px;
333+
}
334+
.search-input {
335+
max-width: 360px;
336+
}
337+
.mobile-main {
338+
width: 100%;
339+
}
340+
.sidebar-drawer {
341+
padding: 0 12px 24px;
342+
}
343+
.sidebar-drawer .sidebar {
344+
gap: 16px;
345+
}
239346
.category-panel { margin-top:20px; background:rgba(255,255,255,.7); padding:12px 14px; border-radius:10px; }
240347
.cat-title { margin:0 0 8px; font-size:14px; color:#333; }
241348
.cat-item { margin: 4px 6px 4px 0; cursor:pointer; user-select:none; }
@@ -280,4 +387,26 @@ export default {
280387
color: #555;
281388
line-height: 1.6;
282389
}
390+
391+
@media (max-width: 768px) {
392+
.home {
393+
padding: 12px;
394+
}
395+
.toolbar {
396+
justify-content: space-between;
397+
}
398+
.search-input {
399+
max-width: none;
400+
flex: 1;
401+
}
402+
.blog-card {
403+
margin-bottom: 16px;
404+
}
405+
.user-profile {
406+
padding: 16px;
407+
}
408+
.category-panel {
409+
margin-top: 12px;
410+
}
411+
}
283412
</style>

0 commit comments

Comments
 (0)