diff --git a/jsconfig.json b/jsconfig.json
index 5a1f2d2..e0aad8a 100644
--- a/jsconfig.json
+++ b/jsconfig.json
@@ -1,4 +1,5 @@
{
+ "include": ["src/**/*"],
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
diff --git a/src/App.vue b/src/App.vue
index ef9468d..30b53e6 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,9 +1,24 @@
-
+
+
+
-
-
diff --git a/src/axios/api.js b/src/axios/api.js
index 06023f3..6c7fc45 100644
--- a/src/axios/api.js
+++ b/src/axios/api.js
@@ -83,4 +83,6 @@ export const messageAPI = {
deleteMessage: (id) => service.delete(`/messages/${id}`)
}
+
+
export default service
\ No newline at end of file
diff --git a/src/components/LeftModule.vue b/src/components/LeftModule.vue
new file mode 100644
index 0000000..c17d96d
--- /dev/null
+++ b/src/components/LeftModule.vue
@@ -0,0 +1,240 @@
+
+
+
+
+
+
小颠片刻
+
左眼右右眼左,四十五度成就美
+
+
+
+
+
+
+
+
+
+
+
+ 清疯不颠
+ 重度精神失常患者
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/index.vue b/src/index.vue
index cb5e5fd..76d2c28 100644
--- a/src/index.vue
+++ b/src/index.vue
@@ -54,7 +54,7 @@
+
+
\ No newline at end of file
diff --git a/src/main.js b/src/main.js
index a64334a..f7c133d 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,7 +1,11 @@
import { createApp } from 'vue'
import App from './App.vue'
import Router from './router/Router'
-import './assets/index.css'
+import ElementPlus from 'element-plus'
+import 'element-plus/dist/index.css'
+import './styles/MainLayout.css'
+
const app = createApp(App)
app.use(Router)
+app.use(ElementPlus)
app.mount('#app')
\ No newline at end of file
diff --git a/src/router/Router.js b/src/router/Router.js
index 132c692..65200e5 100644
--- a/src/router/Router.js
+++ b/src/router/Router.js
@@ -1,54 +1,93 @@
import { createWebHistory, createRouter } from 'vue-router'
-import Aericle from '../views/aericle.vue'
-import home from '../views/home.vue'
-import nonsense from '../views/nonsense.vue'
-import messageboard from '../views/messageboard.vue'
-import about from '../views/aboutme.vue'
-import articlecontents from '../views/articlecontents.vue'
+// 导入视图组件
+import ArticleList from '../views/aericle.vue'
+import HomePage from '../views/home.vue'
+import NonsensePage from '../views/nonsense.vue'
+import MessageBoardPage from '../views/messageboard.vue'
+import AboutMePage from '../views/aboutme.vue'
+import ArticleContentPage from '../views/articlecontents.vue'
+
+/**
+ * 路由配置数组
+ * 定义了应用的所有路由路径和对应的组件
+ */
const routes = [
{
path: '/',
- redirect: '/:type' // 默认跳转到首页
+ redirect: '/all' // 默认跳转到首页,显示所有文章
},
{
path: '/:type',
- // 如果type为空则是所有不为空查询相对应属性的文章
- name: '/home',
- component: home
+ name: 'home',
+ component: HomePage,
+ meta: {
+ title: '首页'
+ }
},
{
- path: '/aericle',
- name: 'Aericle',
- component: Aericle
+ path: '/article-list',
+ name: 'articleList',
+ component: ArticleList,
+ meta: {
+ title: '文章目录'
+ }
},
{
path: '/nonsense',
name: 'nonsense',
- component: nonsense
-
+ component: NonsensePage,
+ meta: {
+ title: '随笔'
+ }
},
{
path: '/message',
- name: 'messageboard',
- component: messageboard
-
+ name: 'messageBoard',
+ component: MessageBoardPage,
+ meta: {
+ title: '留言板'
+ }
},
{
path: '/about',
- name: 'about',
- component: about
-
+ name: 'aboutMe',
+ component: AboutMePage,
+ meta: {
+ title: '关于我'
+ }
},
{
- path: '/articlecontents/:url',
- name: 'articlecontents',
- component: articlecontents
+ path: '/article/:url',
+ name: 'articleContent',
+ component: ArticleContentPage,
+ meta: {
+ title: '文章详情'
+ }
}
]
+/**
+ * 创建路由实例
+ */
const router = createRouter({
history: createWebHistory(),
routes,
+ scrollBehavior() {
+ // 路由切换时滚动到页面顶部
+ return { top: 0 }
+ }
+})
+
+/**
+ * 全局路由守卫 - 处理页面标题
+ */
+router.beforeEach((to, from, next) => {
+ if (to.meta.title) {
+ document.title = to.meta.title + ' - 个人博客'
+ } else {
+ document.title = '个人博客'
+ }
+ next()
})
export default router;
\ No newline at end of file
diff --git a/src/services/apiService.js b/src/services/apiService.js
new file mode 100644
index 0000000..0fa017f
--- /dev/null
+++ b/src/services/apiService.js
@@ -0,0 +1,46 @@
+// 基础 API 服务配置
+import axios from 'axios'
+
+// 创建 axios 实例
+const apiService = axios.create({
+ baseURL: 'http://localhost:8080/api', // api的base_url
+ timeout: 10000, // 请求超时时间
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+})
+
+// 请求拦截器 - 添加认证token
+apiService.interceptors.request.use(
+ config => {
+ const token = localStorage.getItem('token')
+ if (token) {
+ config.headers.Authorization = `Bearer ${token}`
+ }
+ return config
+ },
+ error => {
+ return Promise.reject(error)
+ }
+)
+
+// 响应拦截器 - 统一处理响应
+apiService.interceptors.response.use(
+ response => {
+ // 检查响应是否成功
+ if (response.data && response.data.success) {
+ return response.data
+ } else {
+ // 处理业务错误
+ return Promise.reject(new Error(response.data?.message || '请求失败'))
+ }
+ },
+ error => {
+ // 处理HTTP错误
+ console.error('API请求错误:', error)
+ // 可以在这里添加全局错误处理,如显示错误提示
+ return Promise.reject(error)
+ }
+)
+
+export default apiService
\ No newline at end of file
diff --git a/src/services/articleService.js b/src/services/articleService.js
new file mode 100644
index 0000000..b84d9da
--- /dev/null
+++ b/src/services/articleService.js
@@ -0,0 +1,75 @@
+// 文章相关API服务
+import apiService from './apiService'
+
+/**
+ * 文章服务类
+ */
+class ArticleService {
+ /**
+ * 获取所有文章
+ * @param {Object} params - 查询参数
+ * @returns {Promise}
+ */
+ getAllArticles(params = {}) {
+ return apiService.get('/articles', { params })
+ }
+
+ /**
+ * 获取单篇文章
+ * @param {number} id - 文章ID
+ * @returns {Promise}
+ */
+ getArticleById(id) {
+ return apiService.get(`/articles/${id}`)
+ }
+
+
+
+ /**
+ * 获取热门文章
+ * @returns {Promise}
+ */
+ getPopularArticles() {
+ return apiService.get('/articles/popular')
+ }
+
+ /**
+ * 创建文章
+ * @param {Object} articleData - 文章数据
+ * @returns {Promise}
+ */
+ createArticle(articleData) {
+ return apiService.post('/articles', articleData)
+ }
+
+ /**
+ * 更新文章
+ * @param {number} id - 文章ID
+ * @param {Object} articleData - 文章数据
+ * @returns {Promise}
+ */
+ updateArticle(id, articleData) {
+ return apiService.put(`/articles/${id}`, articleData)
+ }
+
+ /**
+ * 删除文章
+ * @param {number} id - 文章ID
+ * @returns {Promise}
+ */
+ deleteArticle(id) {
+ return apiService.delete(`/articles/${id}`)
+ }
+
+ /**
+ * 增加文章浏览量
+ * @param {number} id - 文章ID
+ * @returns {Promise}
+ */
+ incrementArticleViews(id) {
+ return apiService.post(`/articles/${id}/views`)
+ }
+}
+
+// 导出文章服务实例
+export default new ArticleService()
\ No newline at end of file
diff --git a/src/services/index.js b/src/services/index.js
new file mode 100644
index 0000000..d555208
--- /dev/null
+++ b/src/services/index.js
@@ -0,0 +1,8 @@
+// 导出所有服务
+import articleService from './articleService'
+import messageService from './messageService'
+
+export {
+ articleService,
+ messageService
+}
\ No newline at end of file
diff --git a/src/services/messageService.js b/src/services/messageService.js
new file mode 100644
index 0000000..9f5464a
--- /dev/null
+++ b/src/services/messageService.js
@@ -0,0 +1,89 @@
+// 留言相关API服务
+import apiService from './apiService'
+
+/**
+ * 留言服务类
+ */
+class MessageService {
+ /**
+ * 获取所有留言
+ * @returns {Promise}
+ */
+ getAllMessages() {
+ return apiService.get('/messages')
+ }
+
+ /**
+ * 获取单条留言
+ * @param {number} id - 留言ID
+ * @returns {Promise}
+ */
+ getMessageById(id) {
+ return apiService.get(`/messages/${id}`)
+ }
+
+ /**
+ * 根据文章ID获取留言
+ * @param {number} articleId - 文章ID
+ * @returns {Promise}
+ */
+ getMessagesByArticleId(articleId) {
+ return apiService.get(`/messages/article/${articleId}`)
+ }
+
+ /**
+ * 获取根留言
+ * @returns {Promise}
+ */
+ getRootMessages() {
+ return apiService.get('/messages/root')
+ }
+
+ /**
+ * 根据父留言ID获取回复
+ * @param {number} parentId - 父留言ID
+ * @returns {Promise}
+ */
+ getRepliesByParentId(parentId) {
+ return apiService.get(`/messages/parent/${parentId}`)
+ }
+
+ /**
+ * 根据昵称搜索留言
+ * @param {string} nickname - 昵称
+ * @returns {Promise}
+ */
+ searchMessagesByNickname(nickname) {
+ return apiService.get(`/messages/search?nickname=${nickname}`)
+ }
+
+ /**
+ * 获取文章评论数量
+ * @param {number} articleId - 文章ID
+ * @returns {Promise}
+ */
+ getMessageCountByArticleId(articleId) {
+ return apiService.get(`/messages/count/${articleId}`)
+ }
+
+ /**
+ * 创建留言
+ * @param {Object} messageData - 留言数据
+ * @returns {Promise}
+ */
+ saveMessage(messageData) {
+ return apiService.post('/messages', messageData)
+ }
+
+ /**
+ * 删除留言
+ * @param {number} id - 留言ID
+ * @returns {Promise}
+ */
+ deleteMessage(id) {
+ return apiService.delete(`/messages/${id}`)
+ }
+}
+
+// 导出留言服务实例
+export default new MessageService()
\ No newline at end of file
diff --git a/src/assets/index.css b/src/styles/MainLayout.css
similarity index 92%
rename from src/assets/index.css
rename to src/styles/MainLayout.css
index c9d9ead..33c3e9d 100644
--- a/src/assets/index.css
+++ b/src/styles/MainLayout.css
@@ -122,6 +122,23 @@ p {
align-items: center;
}
+/* Logo文本样式 - 清疯不颠 */
+.logo-text {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ height: 100%;
+ font-family: 'Microsoft YaHei', 'Ma Shan Zheng', cursive;
+ font-size: 1rem;
+ font-weight: bold;
+ background: linear-gradient(94.75deg, rgb(60, 172, 247) 0%, rgb(131, 101, 253) 43.66%, rgb(255, 141, 112) 64.23%, rgb(247, 201, 102) 83.76%, rgb(172, 143, 100) 100%);
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
+}
+
/* 导航栏透明状态 */
.elrow-top.transparent {
background-color: var(--nav-bg-transparent);
@@ -143,8 +160,10 @@ p {
}
.grid-content.ep-bg-purple-dark {
+ display: flex;
align-items: center;
-
+ height: 60px;
+ width: 100%;
}
/* 菜单样式 */
@@ -343,6 +362,7 @@ p {
/* 水平居中 */
align-items: center;
/* 垂直居中 */
+
}
.el-menu--vertical:not(.el-menu--collapse):not(.el-menu--popup-container) .el-menu-item,
diff --git a/src/types/index.ts b/src/types/index.ts
new file mode 100644
index 0000000..7971516
--- /dev/null
+++ b/src/types/index.ts
@@ -0,0 +1,79 @@
+// 项目中使用的类型定义
+
+/**
+ * 文章类型接口
+ */
+export interface Article {
+ id: number
+ title: string
+ content: string
+ author: string
+ createTime: string
+ updateTime: string
+ categoryId: number
+ categoryName?: string
+ tags?: string
+ views?: number
+ commentCount?: number
+ articleid?: string
+ publishedAt?: string
+ mg?: string
+}
+
+/**
+ * 留言类型接口
+ */
+export interface Message {
+ id: number
+ content: string
+ nickname: string
+ email: string
+ articleId?: number
+ parentId?: number
+ createdAt: string
+ replies?: Message[]
+ time?: string
+}
+
+/**
+ * 分类类型接口
+ */
+export interface Category {
+ id: number
+ name: string
+ description?: string
+ articleCount?: number
+}
+
+/**
+ * API响应接口
+ */
+export interface ApiResponse {
+ success: boolean
+ code: number
+ message?: string
+ data?: T
+ total?: number
+}
+
+/**
+ * 分页参数接口
+ */
+export interface PaginationParams {
+ page?: number
+ size?: number
+ keyword?: string
+ [key: string]: any
+}
+
+/**
+ * 用户信息接口
+ */
+export interface User {
+ id?: number
+ username?: string
+ email?: string
+ avatar?: string
+ role?: string
+ token?: string
+}
\ No newline at end of file
diff --git a/src/utils/dateUtils.js b/src/utils/dateUtils.js
new file mode 100644
index 0000000..da1f02b
--- /dev/null
+++ b/src/utils/dateUtils.js
@@ -0,0 +1,90 @@
+// 日期格式化工具函数
+
+/**
+ * 格式化日期为指定格式
+ * @param {string|Date} date - 日期对象或日期字符串
+ * @param {string} format - 格式化模板,如 'YYYY-MM-DD HH:mm:ss'
+ * @returns {string} 格式化后的日期字符串
+ */
+export const formatDate = (date, format = 'YYYY-MM-DD HH:mm:ss') => {
+ if (!date) return ''
+
+ // 如果是字符串,转换为日期对象
+ const dateObj = typeof date === 'string' ? new Date(date) : date
+
+ // 检查日期对象是否有效
+ if (isNaN(dateObj.getTime())) return ''
+
+ const year = dateObj.getFullYear()
+ const month = String(dateObj.getMonth() + 1).padStart(2, '0')
+ const day = String(dateObj.getDate()).padStart(2, '0')
+ const hours = String(dateObj.getHours()).padStart(2, '0')
+ const minutes = String(dateObj.getMinutes()).padStart(2, '0')
+ const seconds = String(dateObj.getSeconds()).padStart(2, '0')
+
+ // 替换模板中的日期部分
+ return format
+ .replace('YYYY', year)
+ .replace('MM', month)
+ .replace('DD', day)
+ .replace('HH', hours)
+ .replace('mm', minutes)
+ .replace('ss', seconds)
+}
+
+/**
+ * 计算时间差,返回相对时间
+ * @param {string|Date} date - 日期对象或日期字符串
+ * @returns {string} 相对时间字符串
+ */
+export const formatRelativeTime = (date) => {
+ if (!date) return ''
+
+ const dateObj = typeof date === 'string' ? new Date(date) : date
+ const now = new Date()
+ const diff = now - dateObj
+
+ // 转换为秒
+ const seconds = Math.floor(diff / 1000)
+
+ if (seconds < 60) {
+ return `${seconds}秒前`
+ }
+
+ // 转换为分钟
+ const minutes = Math.floor(seconds / 60)
+ if (minutes < 60) {
+ return `${minutes}分钟前`
+ }
+
+ // 转换为小时
+ const hours = Math.floor(minutes / 60)
+ if (hours < 24) {
+ return `${hours}小时前`
+ }
+
+ // 转换为天
+ const days = Math.floor(hours / 24)
+ if (days < 30) {
+ return `${days}天前`
+ }
+
+ // 转换为月
+ const months = Math.floor(days / 30)
+ if (months < 12) {
+ return `${months}个月前`
+ }
+
+ // 转换为年
+ const years = Math.floor(months / 12)
+ return `${years}年前`
+}
+
+/**
+ * 获取当前日期
+ * @param {string} format - 格式化模板
+ * @returns {string} 当前日期字符串
+ */
+export const getCurrentDate = (format = 'YYYY-MM-DD HH:mm:ss') => {
+ return formatDate(new Date(), format)
+}
\ No newline at end of file
diff --git a/src/utils/stringUtils.js b/src/utils/stringUtils.js
new file mode 100644
index 0000000..c7c673e
--- /dev/null
+++ b/src/utils/stringUtils.js
@@ -0,0 +1,75 @@
+// 字符串处理工具函数
+
+/**
+ * 截断字符串并添加省略号
+ * @param {string} str - 原始字符串
+ * @param {number} length - 保留的长度
+ * @returns {string} 截断后的字符串
+ */
+export const truncateString = (str, length) => {
+ if (!str || typeof str !== 'string' || str.length <= length) {
+ return str
+ }
+ return str.substring(0, length) + '...'
+}
+
+/**
+ * 移除HTML标签
+ * @param {string} html - 包含HTML标签的字符串
+ * @returns {string} 纯文本字符串
+ */
+export const stripHtmlTags = (html) => {
+ if (!html || typeof html !== 'string') {
+ return html
+ }
+ return html.replace(/<[^>]*>/g, '')
+}
+
+/**
+ * 格式化内容预览
+ * @param {string} content - 原始内容
+ * @param {number} maxLength - 最大长度
+ * @returns {string} 格式化后的预览内容
+ */
+export const formatContentPreview = (content, maxLength = 200) => {
+ if (!content) return ''
+ // 先移除HTML标签
+ const plainText = stripHtmlTags(content)
+ // 再截断字符串
+ return truncateString(plainText, maxLength)
+}
+
+/**
+ * 转义HTML特殊字符
+ * @param {string} str - 原始字符串
+ * @returns {string} 转义后的字符串
+ */
+export const escapeHtml = (str) => {
+ if (!str || typeof str !== 'string') {
+ return str
+ }
+ const map = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": '''
+ }
+ return str.replace(/[&<>"']/g, (m) => map[m])
+}
+
+/**
+ * 解析URL查询参数
+ * @param {string} url - URL字符串
+ * @returns {Object} 查询参数对象
+ */
+export const parseQueryParams = (url) => {
+ const queryString = url.split('?')[1]
+ if (!queryString) return {}
+
+ return queryString.split('&').reduce((params, param) => {
+ const [key, value] = param.split('=')
+ params[decodeURIComponent(key)] = decodeURIComponent(value || '')
+ return params
+ }, {})
+}
\ No newline at end of file
diff --git a/src/views/aboutme.vue b/src/views/aboutme.vue
index e301f90..e6cee67 100644
--- a/src/views/aboutme.vue
+++ b/src/views/aboutme.vue
@@ -1,11 +1,213 @@
-
-