|
|
<template>
|
|
|
<el-container class="home">
|
|
|
<!-- 头部 -->
|
|
|
<el-header class="header">
|
|
|
<el-row type="flex" justify="space-between" align="middle" style="width:100%;">
|
|
|
<el-col :span="6" class="logo-container">
|
|
|
<img src="@/assets/logo.png" alt="Logo" class="logo">
|
|
|
</el-col>
|
|
|
<el-col :span="12" class="search-col">
|
|
|
<el-input placeholder="搜索..." prefix-icon="el-icon-search" size="large" class="search-input"></el-input>
|
|
|
</el-col>
|
|
|
<el-col :span="6" class="auth-buttons">
|
|
|
<div class="auth-content">
|
|
|
<div v-if="!isLogin">
|
|
|
<el-button link @click="handleLogin" class="login-button">登录</el-button>
|
|
|
<el-button type="primary" @click="handleRegister" class="register-button">注册</el-button>
|
|
|
</div>
|
|
|
<div v-else>
|
|
|
<el-link type="primary" :underline="false" @click="gotoHome" class="username-link">
|
|
|
管理员
|
|
|
</el-link>
|
|
|
<el-link type="primary" :underline="false" @click="gotoHome2" class="username-link">
|
|
|
我
|
|
|
</el-link>
|
|
|
<el-button type="danger" @click="handleLogout" class="logout-button">退出登录</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
</el-header>
|
|
|
|
|
|
|
|
|
<!-- 轮播图 -->
|
|
|
<el-container>
|
|
|
<el-main>
|
|
|
<el-carousel trigger="click" height="400px" arrow="always" class="carousel">
|
|
|
<el-carousel-item v-for="(item, index) in images" :key="index">
|
|
|
<img :src="item" class="carousel-img" />
|
|
|
</el-carousel-item>
|
|
|
</el-carousel>
|
|
|
</el-main>
|
|
|
</el-container>
|
|
|
|
|
|
<!-- 文章内容部分 -->
|
|
|
<el-container class="content-container">
|
|
|
<el-aside width="400px" class="sidebar">
|
|
|
<h3 class="section-title">最新文章</h3>
|
|
|
<el-menu class="menu">
|
|
|
<el-menu-item v-for="post in latestPosts" :key="post.id">
|
|
|
<router-link :to="'/post/' + post.id" class="link-item">{{ post.title }}</router-link>
|
|
|
</el-menu-item>
|
|
|
</el-menu>
|
|
|
|
|
|
<h3 class="section-title">热门文章</h3>
|
|
|
<el-menu class="menu">
|
|
|
<el-menu-item v-for="post in popularPosts" :key="post.id">
|
|
|
<router-link :to="'/post/' + post.id" class="link-item">{{ post.title }}</router-link>
|
|
|
</el-menu-item>
|
|
|
</el-menu>
|
|
|
|
|
|
<h3 class="section-title">推荐文章</h3>
|
|
|
<el-menu class="menu">
|
|
|
<el-menu-item v-for="post in recommendedPosts" :key="post.id">
|
|
|
<router-link :to="'/post/' + post.id" class="link-item">{{ post.title }}</router-link>
|
|
|
</el-menu-item>
|
|
|
</el-menu>
|
|
|
<el-divider></el-divider>
|
|
|
|
|
|
</el-aside>
|
|
|
|
|
|
|
|
|
<el-main class="posts-container">
|
|
|
<div v-for="post in posts" :key="post.id" class="blog-post">
|
|
|
<router-link :to="'/post/' + post.id">
|
|
|
<h3>{{ post.title }}</h3>
|
|
|
</router-link>
|
|
|
<p><strong>Author:</strong> {{ post.author }} | <strong>Published:</strong> {{ post.date }}</p>
|
|
|
<p>{{ post.excerpt }}</p>
|
|
|
</div>
|
|
|
</el-main>
|
|
|
</el-container>
|
|
|
|
|
|
<!-- 底部 -->
|
|
|
<el-footer class="footer">
|
|
|
<span>© 2024 My Blog. All rights reserved.</span>
|
|
|
</el-footer>
|
|
|
</el-container>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
import { onMounted, reactive, ref } from 'vue';
|
|
|
import { useRouter } from 'vue-router';
|
|
|
import { useUserStore } from '../stores/user';
|
|
|
import { IUserInfo } from '../model/model';
|
|
|
import img1 from '@/assets/carousel/1.jpg';
|
|
|
import img2 from '@/assets/carousel/2.jpg';
|
|
|
import img3 from '@/assets/carousel/3.jpg';
|
|
|
import img4 from '@/assets/carousel/4.jpg';
|
|
|
import img5 from '@/assets/carousel/5.jpg';
|
|
|
import img6 from '@/assets/carousel/6.jpg';
|
|
|
|
|
|
const images = ref([img1, img2, img3, img4, img5, img6]);
|
|
|
|
|
|
const posts = ref([
|
|
|
{ id: 1, title: 'Vue 3 入门教程', author: 'John Doe', date: '2024-11-29', excerpt: '这是一篇关于 Vue 3 的入门教程,适合初学者阅读。' },
|
|
|
{ id: 2, title: 'Vue 3 响应式系统解析', author: 'Jane Doe', date: '2024-11-28', excerpt: '深入浅出地解析 Vue 3 中的响应式系统。' },
|
|
|
{ id: 3, title: 'Vue 3 性能优化技巧', author: 'Alice Smith', date: '2024-11-27', excerpt: '如何在 Vue 3 中实现性能优化,提升应用效率。' },
|
|
|
{ id: 4, title: 'Vue 3 Composition API 实战', author: 'Bob Brown', date: '2024-11-26', excerpt: '详细讲解 Vue 3 的 Composition API 并通过案例演示。' },
|
|
|
{ id: 5, title: 'Vue 3 路由详解', author: 'Carol White', date: '2024-11-25', excerpt: '讲解如何在 Vue 3 中配置和使用 Vue Router。' },
|
|
|
{ id: 6, title: 'Vue 3 状态管理:Pinia vs Vuex', author: 'Dave Black', date: '2024-11-24', excerpt: '比较 Vue 3 中的 Pinia 和 Vuex,帮助你选择最适合的状态管理工具。' },
|
|
|
{ id: 7, title: 'Vue 3 与 TypeScript 的完美结合', author: 'Eve Green', date: '2024-11-23', excerpt: '教你如何在 Vue 3 中使用 TypeScript 开发应用。' },
|
|
|
{ id: 8, title: 'Vue 3 表单验证最佳实践', author: 'Frank Blue', date: '2024-11-22', excerpt: '介绍如何在 Vue 3 中进行表单验证,提升用户体验。' },
|
|
|
{ id: 9, title: 'Vue 3 与 Webpack 配置优化', author: 'Grace Purple', date: '2024-11-21', excerpt: '讲解如何优化 Vue 3 与 Webpack 配合使用时的配置。' }
|
|
|
]);
|
|
|
|
|
|
const latestPosts = ref([
|
|
|
{ id: 1, title: '如何使用 Vue 3 构建高效的前端应用' },
|
|
|
{ id: 2, title: '深入浅出 Vue 3 响应式系统' },
|
|
|
{ id: 3, title: 'Vue 3 中的 Composition API 使用技巧' },
|
|
|
]);
|
|
|
|
|
|
const popularPosts = ref([
|
|
|
{ id: 4, title: 'Vue 3 性能优化实战' },
|
|
|
{ id: 5, title: '如何构建 Vue 3 + TypeScript 项目' },
|
|
|
{ id: 6, title: 'Vue 3 Router 动态路由实践' },
|
|
|
]);
|
|
|
|
|
|
const recommendedPosts = ref([
|
|
|
{ id: 7, title: 'Vue 3 状态管理:Pinia vs Vuex' },
|
|
|
{ id: 8, title: '如何在 Vue 3 中使用 Vue CLI' },
|
|
|
{ id: 9, title: '从 Vue 2 到 Vue 3:升级指南' },
|
|
|
]);
|
|
|
|
|
|
const router = useRouter();
|
|
|
const userStore = useUserStore();
|
|
|
const currentUser = reactive<IUserInfo>({ username: '', nickname: '', signature: '', phone: '', birthday: '', isAdmin: false, password: '' });
|
|
|
const isLogin = ref(false);
|
|
|
|
|
|
const init = () => {
|
|
|
const user = userStore.getCurrentUser();
|
|
|
if (user) {
|
|
|
currentUser.username = user.username || '';
|
|
|
currentUser.nickname = user.nickname || '';
|
|
|
currentUser.signature = user.signature || '';
|
|
|
currentUser.phone = user.phone || '';
|
|
|
currentUser.birthday = user.birthday || '';
|
|
|
currentUser.isAdmin = user.isAdmin || false;
|
|
|
currentUser.password = user.password || '';
|
|
|
isLogin.value = true;
|
|
|
} else {
|
|
|
isLogin.value = false;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
onMounted(() => {
|
|
|
init();
|
|
|
});
|
|
|
|
|
|
const handleLogin = () => {
|
|
|
router.push({ "name": "Login" });
|
|
|
};
|
|
|
|
|
|
const handleRegister = () => {
|
|
|
router.push("/register");
|
|
|
};
|
|
|
|
|
|
const handleLogout = () => {
|
|
|
userStore.logoutUser();
|
|
|
init();
|
|
|
router.push("/");
|
|
|
};
|
|
|
|
|
|
const gotoHome = () => {
|
|
|
//if panduan
|
|
|
router.push("/admin");
|
|
|
};
|
|
|
const gotoHome2 = () => {
|
|
|
//if panduan
|
|
|
router.push("/user");
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
/* 页面基础样式 */
|
|
|
.home {
|
|
|
height: 100%;
|
|
|
width: 100%;
|
|
|
font-family: 'Arial', sans-serif;
|
|
|
background-image: url('@/assets/bg1.jpg'); /* Path to your background image */
|
|
|
background-size: cover; /* Ensures the image covers the entire page */
|
|
|
background-position: center; /* Centers the image */
|
|
|
background-repeat: no-repeat;
|
|
|
/* 设置背景色 */
|
|
|
overflow-x: hidden;
|
|
|
/* 防止内容横向溢出 */
|
|
|
}
|
|
|
|
|
|
/* Header 样式 */
|
|
|
.header {
|
|
|
height: 100px;
|
|
|
background-color: rgba(255, 255, 255, 0.8);;
|
|
|
border-bottom: 1px solid #ddd;
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
padding: 0 20px;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: space-between;
|
|
|
/* 确保元素分布 */
|
|
|
overflow: hidden;
|
|
|
}
|
|
|
|
|
|
|
|
|
.logo {
|
|
|
height: 120px;
|
|
|
object-fit: contain;
|
|
|
overflow: hidden;
|
|
|
/* 防止 logo 超出容器 */
|
|
|
}
|
|
|
|
|
|
.search-input {
|
|
|
width: 100%;
|
|
|
border-radius: 20px;
|
|
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
|
|
padding: 10px 20px;
|
|
|
font-size: 16px;
|
|
|
}
|
|
|
|
|
|
/* 登录注册按钮 */
|
|
|
.auth-buttons {
|
|
|
display: flex;
|
|
|
justify-content: flex-end;
|
|
|
align-items: center;
|
|
|
}
|
|
|
|
|
|
.login-button,
|
|
|
.register-button,
|
|
|
.logout-button {
|
|
|
margin-left: 15px;
|
|
|
}
|
|
|
|
|
|
.username-link {
|
|
|
margin-right: 15px;
|
|
|
}
|
|
|
|
|
|
/* 轮播图样式 */
|
|
|
.carousel {
|
|
|
margin-bottom: 20px;
|
|
|
overflow: hidden;
|
|
|
/* 遮住轮播图超出的部分 */
|
|
|
}
|
|
|
|
|
|
.carousel-img {
|
|
|
width: 100%;
|
|
|
height: 400px;
|
|
|
object-fit: cover;
|
|
|
border-radius: 8px;
|
|
|
max-height: 100%;
|
|
|
/* 确保图片不会溢出容器 */
|
|
|
}
|
|
|
|
|
|
/* 内容容器 */
|
|
|
.content-container {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
margin-top: 20px;
|
|
|
padding: 0 20px;
|
|
|
}
|
|
|
|
|
|
.sidebar {
|
|
|
background-color: rgba(255, 255, 255, 0.8);;
|
|
|
padding: 20px;
|
|
|
border-radius: 8px;
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
width: 280px;
|
|
|
/* 控制侧边栏的宽度 */
|
|
|
overflow: hidden;
|
|
|
/* 遮住超出部分 */
|
|
|
}
|
|
|
|
|
|
.menu {
|
|
|
background-color: rgba(255, 255, 255, 0);;
|
|
|
margin-bottom: 15px;
|
|
|
}
|
|
|
|
|
|
.section-title {
|
|
|
font-size: 20px;
|
|
|
color: #333;
|
|
|
margin-bottom: 10px;
|
|
|
border-bottom: 2px solid #ddd;
|
|
|
padding-bottom: 10px;
|
|
|
font-weight: 600;
|
|
|
|
|
|
word-wrap: break-word;
|
|
|
/* 防止标题溢出 */
|
|
|
white-space: normal;
|
|
|
/* 保证标题文本正常换行 */
|
|
|
overflow: hidden;
|
|
|
/* 遮住超出部分 */
|
|
|
}
|
|
|
|
|
|
.link-item {
|
|
|
text-decoration: none;
|
|
|
color: #333;
|
|
|
font-size: 16px;
|
|
|
transition: color 0.3s ease, padding-left 0.3s ease;
|
|
|
display: block;
|
|
|
/* 使链接成为块级元素 */
|
|
|
padding: 8px 0;
|
|
|
/* 给链接增加上下内边距 */
|
|
|
overflow: hidden;
|
|
|
/* 遮住超出部分 */
|
|
|
}
|
|
|
|
|
|
.link-item:hover {
|
|
|
color: #1a73e8;
|
|
|
padding-left: 10px;
|
|
|
}
|
|
|
|
|
|
/* 帖子列表容器 */
|
|
|
.posts-container {
|
|
|
flex: 1;
|
|
|
padding: 20px;
|
|
|
background-color:rgba(255, 255, 255, 0.8);;
|
|
|
border-radius: 8px;
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
overflow: hidden;
|
|
|
/* 遮住超出部分 */
|
|
|
}
|
|
|
|
|
|
/* 博客文章样式 */
|
|
|
.blog-post {
|
|
|
margin-bottom: 20px;
|
|
|
padding-bottom: 20px;
|
|
|
border-bottom: 1px solid #ddd;
|
|
|
padding-left: 20px;
|
|
|
padding-right: 20px;
|
|
|
overflow: hidden;
|
|
|
/* 遮住超出部分 */
|
|
|
transition: background-color 0.3s ease, transform 0.2s ease;
|
|
|
}
|
|
|
|
|
|
.blog-post:hover {
|
|
|
background-color: #f9f9f9;
|
|
|
/* 鼠标悬浮时背景色变化 */
|
|
|
transform: translateY(-5px);
|
|
|
/* 鼠标悬浮时向上浮动 */
|
|
|
}
|
|
|
|
|
|
/* 文章标题样式 */
|
|
|
.blog-post h3 {
|
|
|
font-size: 22px;
|
|
|
color: #1a73e8;
|
|
|
margin-top: 10px;
|
|
|
margin-bottom: 10px;
|
|
|
transition: color 0.3s ease;
|
|
|
word-wrap: break-word;
|
|
|
/* 防止标题溢出 */
|
|
|
white-space: normal;
|
|
|
/* 保证标题文本正常换行 */
|
|
|
overflow: hidden;
|
|
|
/* 遮住超出部分 */
|
|
|
}
|
|
|
|
|
|
.blog-post h3:hover {
|
|
|
color: #0066cc;
|
|
|
/* 悬浮时标题颜色变化 */
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
|
|
|
/* 文章元数据样式 (作者和发布时间) */
|
|
|
.blog-post p {
|
|
|
color: #555;
|
|
|
font-size: 14px;
|
|
|
line-height: 1.6;
|
|
|
margin: 5px 0;
|
|
|
}
|
|
|
|
|
|
.blog-post p strong {
|
|
|
font-weight: 600;
|
|
|
color: #333;
|
|
|
}
|
|
|
|
|
|
/* 文章摘要样式 */
|
|
|
.blog-post .excerpt {
|
|
|
color: #666;
|
|
|
font-size: 16px;
|
|
|
line-height: 1.8;
|
|
|
margin-top: 10px;
|
|
|
display: -webkit-box;
|
|
|
-webkit-line-clamp: 3;
|
|
|
/* 限制显示的行数 */
|
|
|
-webkit-box-orient: vertical;
|
|
|
overflow: hidden;
|
|
|
/* 超出的部分隐藏 */
|
|
|
text-overflow: ellipsis;
|
|
|
/* 省略号 */
|
|
|
}
|
|
|
|
|
|
.blog-post .excerpt:hover {
|
|
|
text-decoration: underline;
|
|
|
/* 悬浮时摘要增加下划线 */
|
|
|
}
|
|
|
|
|
|
/* 响应式布局:适应小屏幕 */
|
|
|
@media (max-width: 768px) {
|
|
|
.posts-container {
|
|
|
padding: 10px;
|
|
|
}
|
|
|
|
|
|
.blog-post {
|
|
|
padding-left: 10px;
|
|
|
padding-right: 10px;
|
|
|
}
|
|
|
|
|
|
.blog-post h3 {
|
|
|
font-size: 20px;
|
|
|
}
|
|
|
|
|
|
.blog-post p {
|
|
|
font-size: 13px;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Footer 样式 */
|
|
|
.footer {
|
|
|
background-color: #ffffff;
|
|
|
height: 40px;
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
color: #333;
|
|
|
font-size: 14px;
|
|
|
border-top: 1px solid #ddd;
|
|
|
}
|
|
|
|
|
|
.footer span {
|
|
|
padding: 10px;
|
|
|
}
|
|
|
|
|
|
/* 响应式布局:适应小屏幕 */
|
|
|
@media (max-width: 768px) {
|
|
|
.header {
|
|
|
height: 80px;
|
|
|
}
|
|
|
|
|
|
.logo-container {
|
|
|
display: block;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.content-container {
|
|
|
flex-direction: column;
|
|
|
}
|
|
|
|
|
|
.sidebar {
|
|
|
width: 100%;
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.posts-container {
|
|
|
width: 100%;
|
|
|
}
|
|
|
|
|
|
.carousel-img {
|
|
|
height: 300px;
|
|
|
}
|
|
|
|
|
|
.menu {
|
|
|
padding: 0 10px;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
a {
|
|
|
text-decoration: none;
|
|
|
}
|
|
|
</style>
|