From 07d3159b08e38d5796f281020a638662f5f0336f Mon Sep 17 00:00:00 2001 From: qingfeng1121 Date: Sat, 11 Oct 2025 13:32:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E5=89=8D=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E6=95=B0=E6=8D=AE=E4=BA=A4=E4=BA=92=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加axios API服务模块,封装所有后端接口调用 - 修改各视图组件,移除模拟数据,改为从后端API获取真实数据 - 更新文章、留言板等页面,支持后端数据渲染 - 添加README_API.md文档,说明API调用方式 - 升级axios依赖版本至1.12.2 --- README_API.md | 407 ++++++++++++++++++++++++++++++++++ package-lock.json | 8 +- package.json | 2 +- src/axios/api.js | 86 +++++++ src/index.vue | 7 - src/views/aericle.vue | 75 ++----- src/views/articlecontents.vue | 20 +- src/views/home.vue | 115 ++-------- src/views/messageboard.vue | 46 ++-- 9 files changed, 563 insertions(+), 203 deletions(-) create mode 100644 README_API.md create mode 100644 src/axios/api.js diff --git a/README_API.md b/README_API.md new file mode 100644 index 0000000..515b1c8 --- /dev/null +++ b/README_API.md @@ -0,0 +1,407 @@ +# 前端调用文档 + +## 项目概述 + +这是一个基于Vue 3的博客前端项目,提供文章展示、分类浏览、留言板等功能。项目使用Vue 3 Composition API进行开发,集成了Vue Router进行路由管理,并使用Element Plus等UI库提供用户界面。 + +## 技术栈 + +- **前端框架**: Vue 3 +- **构建工具**: Vite +- **路由管理**: Vue Router 4 +- **UI组件库**: Element Plus、Ant Design Vue +- **HTTP客户端**: Axios +- **编程语言**: JavaScript/TypeScript + +## 项目结构 + +``` +src/ +├── App.vue # 应用根组件 +├── assets/ # 静态资源 +│ └── index.css # 全局样式 +├── img/ # 图片资源 +├── index.vue # 首页主组件 +├── main.js # 应用入口文件 +├── router/ # 路由配置 +│ └── Router.js # 路由定义 +└── views/ # 视图组件 + ├── aboutme.vue # 关于页面 + ├── aericle.vue # 文章分类目录页面 + ├── articlecontents.vue # 文章内容页面 + ├── home.vue # 首页内容组件 + ├── leftmodlue.vue # 左侧边栏组件 + ├── messageboard.vue # 留言板页面 + └── nonsense.vue # 疯言疯语页面 +``` + +## 路由配置 + +路由配置位于 `src/router/Router.js`,定义了应用的所有路由映射关系: + +| 路由路径 | 组件 | 功能描述 | +|---------|------|---------| +| `/` | home.vue | 默认路由,重定向到首页 | +| `/:type` | home.vue | 首页,可根据type参数筛选文章 | +| `/aericle` | aericle.vue | 文章分类目录页面 | +| `/nonsense` | nonsense.vue | 疯言疯语页面 | +| `/message` | messageboard.vue | 留言板页面 | +| `/about` | aboutme.vue | 关于页面 | +| `/articlecontents/:url` | articlecontents.vue | 文章内容详情页 | + +## 主要组件说明 + +### 1. App.vue + +应用根组件,负责渲染主页面组件。 + +```vue + + +``` + +### 2. index.vue + +主页面组件,包含顶部导航栏、Hero区域和内容展示区。 + +主要功能: +- 响应式布局,适配不同屏幕宽度 +- 导航菜单切换不同页面 +- 打字机效果展示欢迎语 + +### 3. home.vue + +首页文章列表组件,用于展示文章卡片列表。 + +主要功能: +- 展示文章标题、作者、发布时间等信息 +- 点击文章卡片跳转到文章详情页 +- 支持文章筛选功能 + +### 4. aericle.vue + +文章分类目录组件,展示文章的分类结构。 + +主要功能: +- 展示不同分类下的文章数量 +- 点击分类项可以跳转到对应的文章列表 + +### 5. articlecontents.vue + +文章内容详情组件,用于展示单篇文章的完整内容。 + +主要功能: +- 获取URL参数并展示对应文章内容 +- 支持通过参数向服务器请求相关文章 + +### 6. messageboard.vue + +留言板组件,支持用户发表评论和回复。 + +主要功能: +- 展示留言列表和回复 +- 支持发表新留言 +- 支持回复他人留言 + +### 7. nonsense.vue + +疯言疯语组件,展示一些非正式的简短内容。 + +## 后端API接口 + +项目后端基于Spring Boot开发,提供了以下主要API接口: + +### 文章管理API + +#### 1. 获取文章列表 + +``` +GET /api/articles +``` + +**功能**: 获取所有文章列表 + +**返回**: 包含文章列表的ResponseMessage对象 + +#### 2. 获取单篇文章 + +``` +GET /api/articles/{id} +``` + +**功能**: 根据ID获取单篇文章详情 + +**参数**: id - 文章ID + +**返回**: 包含文章信息的ResponseMessage对象 + +#### 3. 根据分类获取文章 + +``` +GET /api/articles/category/{categoryId} +``` + +**功能**: 获取指定分类下的所有文章 + +**参数**: categoryId - 分类ID + +**返回**: 包含文章列表的ResponseMessage对象 + +#### 4. 获取热门文章 + +``` +GET /api/articles/popular +``` + +**功能**: 获取浏览量最高的文章列表 + +**返回**: 包含热门文章列表的ResponseMessage对象 + +#### 5. 创建文章 (需要认证) + +``` +POST /api/articles +``` + +**功能**: 创建新文章 + +**权限**: 需要AUTHOR角色 + +**参数**: ArticleDto对象 (JSON格式) + +**返回**: 包含新创建文章信息的ResponseMessage对象 + +#### 6. 更新文章 (需要认证) + +``` +PUT /api/articles/{id} +``` + +**功能**: 更新现有文章 + +**权限**: 需要AUTHOR或ADMIN角色 + +**参数**: +- id - 文章ID +- ArticleDto对象 (JSON格式) + +**返回**: 包含更新后文章信息的ResponseMessage对象 + +#### 7. 删除文章 (需要认证) + +``` +DELETE /api/articles/{id} +``` + +**功能**: 删除指定文章 + +**权限**: 需要AUTHOR或ADMIN角色 + +**参数**: id - 文章ID + +**返回**: 包含被删除文章信息的ResponseMessage对象 + +### 留言管理API + +#### 1. 获取所有留言 + +``` +GET /api/messages +``` + +**功能**: 获取所有留言列表 + +**返回**: 包含留言列表的ResponseMessage对象 + +#### 2. 获取单条留言 + +``` +GET /api/messages/{id} +``` + +**功能**: 根据ID获取单条留言详情 + +**参数**: id - 留言ID + +**返回**: 包含留言信息的ResponseMessage对象 + +#### 3. 保存留言 + +``` +POST /api/messages +``` + +**功能**: 保存新留言 + +**参数**: MessageDto对象 (JSON格式) + +**返回**: 包含保存后留言信息的ResponseMessage对象 + +#### 4. 删除留言 + +``` +DELETE /api/messages/{id} +``` + +**功能**: 删除指定留言 + +**参数**: id - 留言ID + +**返回**: 包含删除结果的ResponseMessage对象 + +## 前端API调用说明 + +项目中使用Axios进行HTTP请求,推荐创建统一的API服务模块来封装所有后端API调用。以下是一个示例: + +```javascript +import axios from 'axios'; + +// 创建axios实例 +const api = axios.create({ + baseURL: 'http://localhost:8080/api', // 后端API基础URL + timeout: 10000, // 请求超时时间 + headers: { + 'Content-Type': 'application/json' + } +}); + +// 请求拦截器 +api.interceptors.request.use( + config => { + // 可以在这里添加token等认证信息 + const token = localStorage.getItem('token'); + if (token) { + config.headers.Authorization = `Bearer ${token}`; + } + return config; + }, + error => { + return Promise.reject(error); + } +); + +// 响应拦截器 +api.interceptors.response.use( + response => { + return response.data; + }, + error => { + // 统一错误处理 + console.error('API请求错误:', error); + return Promise.reject(error); + } +); + +// 文章相关API +export const articleAPI = { + // 获取所有文章 + getAllArticles: () => api.get('/articles'), + // 获取单篇文章 + getArticleById: (id) => api.get(`/articles/${id}`), + // 根据分类获取文章 + getArticlesByCategory: (categoryId) => api.get(`/articles/category/${categoryId}`), + // 获取热门文章 + getPopularArticles: () => api.get('/articles/popular'), + // 创建文章 + createArticle: (articleData) => api.post('/articles', articleData), + // 更新文章 + updateArticle: (id, articleData) => api.put(`/articles/${id}`, articleData), + // 删除文章 + deleteArticle: (id) => api.delete(`/articles/${id}`) +}; + +// 留言相关API +export const messageAPI = { + // 获取所有留言 + getAllMessages: () => api.get('/messages'), + // 获取单条留言 + getMessageById: (id) => api.get(`/messages/${id}`), + // 保存留言 + saveMessage: (messageData) => api.post('/messages', messageData), + // 删除留言 + deleteMessage: (id) => api.delete(`/messages/${id}`) +}; + +// 导出默认的api对象 +export default api; +``` + +## 开发指南 + +### 安装依赖 + +```bash +npm install +``` + +### 启动开发服务器 + +```bash +npm run dev +``` + +开发服务器将在 http://localhost:3000 启动 + +### 构建生产版本 + +```bash +npm run build +``` + +构建后的文件将生成在 `dist` 目录中 + +### 预览生产版本 + +```bash +npm run preview +``` + +## 部署说明 + +1. 确保后端服务已部署并运行在正确的端口上 +2. 修改前端API请求的基础URL指向实际的后端服务地址 +3. 构建生产版本并部署到Web服务器 +4. 配置Web服务器以支持单页应用路由 (SPA fallback) + +## 注意事项 + +1. 项目使用了Element Plus和Ant Design Vue两个UI库,请注意组件的正确引入和使用方式 +2. 后端服务默认端口为8080,前端开发服务器端口为3000 +3. 确保CORS配置正确,允许前端域名访问后端API +4. 对于需要认证的API,需要在请求头中添加正确的认证信息 + +## 附录:数据模型 + +### 文章数据模型 (Article) + +```javascript +{ + articleid: Number, // 文章ID + title: String, // 文章标题 + content: String, // 文章内容 + author: String, // 作者 + authorid: Number, // 作者ID + typeid: Number, // 分类ID + publishedAt: String, // 发布时间 + viewCount: Number, // 浏览次数 + status: Number, // 状态 (1表示已发布) + img: String // 文章图片 +} +``` + +### 留言数据模型 (Message) + +```javascript +{ + id: Number, // 留言ID + nickname: String, // 昵称 + email: String, // 邮箱 + content: String, // 留言内容 + time: String, // 留言时间 + replies: Array // 回复列表 +} +``` \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c26a5df..a330f84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "ant-design-vue": "^4.2.6", "antd": "^5.27.3", - "axios": "^1.11.0", + "axios": "^1.12.2", "element-plus": "^2.11.2", "vue": "^3.5.18", "vue-router": "^4.5.1" @@ -2647,9 +2647,9 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.11.0", - "resolved": "https://registry.npmmirror.com/axios/-/axios-1.11.0.tgz", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "version": "1.12.2", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.12.2.tgz", + "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", diff --git a/package.json b/package.json index 4d07dd0..1067cf0 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "dependencies": { "ant-design-vue": "^4.2.6", "antd": "^5.27.3", - "axios": "^1.11.0", + "axios": "^1.12.2", "element-plus": "^2.11.2", "vue": "^3.5.18", "vue-router": "^4.5.1" diff --git a/src/axios/api.js b/src/axios/api.js new file mode 100644 index 0000000..06023f3 --- /dev/null +++ b/src/axios/api.js @@ -0,0 +1,86 @@ +import axios from 'axios' + +// 创建axios实例 +const service = axios.create({ + baseURL: 'http://localhost:8080/api', // api的base_url + timeout: 3000, // 请求超时时间 + headers: { + 'Content-Type': 'application/json' + } + // withCredentials: true, // 跨域请求时是否需要使用凭证 +}) + +// 请求拦截器 - 添加认证token +service.interceptors.request.use( + config => { + const token = localStorage.getItem('token') + if (token) { + config.headers.Authorization = `Bearer ${token}` + } + return config + }, + error => { + return Promise.reject(error) + } +) + +// 响应拦截器 - 统一处理响应 +service.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) + } +) + +// 文章相关API +export const articleAPI = { + // 获取所有文章 + getAllArticles: () => service.get('/articles'), + // 获取单篇文章 + getArticleById: (id) => service.get(`/articles/${id}`), + // 根据分类获取文章 + getArticlesByCategory: (categoryId) => service.get(`/articles/category/${categoryId}`), + // 获取热门文章 + getPopularArticles: () => service.get('/articles/popular'), + // 创建文章 + createArticle: (articleData) => service.post('/articles', articleData), + // 更新文章 + updateArticle: (id, articleData) => service.put(`/articles/${id}`, articleData), + // 删除文章 + deleteArticle: (id) => service.delete(`/articles/${id}`) +} + +// 留言相关API +export const messageAPI = { + // 获取所有留言 + getAllMessages: () => service.get('/messages'), + // 获取单条留言 + getMessageById: (id) => service.get(`/messages/${id}`), + // 根据文章ID获取留言 + getMessagesByArticleId: (articleId) => service.get(`/messages/article/${articleId}`), + // 获取根留言 + getRootMessages: () => service.get('/messages/root'), + // 根据父留言ID获取回复 + getRepliesByParentId: (parentId) => service.get(`/messages/parent/${parentId}`), + // 根据昵称搜索留言 + searchMessagesByNickname: (nickname) => service.get(`/messages/search?nickname=${nickname}`), + // 获取文章评论数量 + getMessageCountByArticleId: (articleId) => service.get(`/messages/count/${articleId}`), + // 创建留言 + saveMessage: (messageData) => service.post('/messages', messageData), + // 删除留言 + deleteMessage: (id) => service.delete(`/messages/${id}`) +} + +export default service \ No newline at end of file diff --git a/src/index.vue b/src/index.vue index d836378..cb5e5fd 100644 --- a/src/index.vue +++ b/src/index.vue @@ -105,10 +105,7 @@ const handleSelect = (key: string) => { */ const updatePageState = (url: string) => { classhero.value = url !== '/:type'; - console.log("当前路径是:"+url); classnonsenset.value = url == '/nonsense'; - console.log( classnonsenset.value); - }; /** @@ -154,14 +151,12 @@ const handleScroll = () => { isconts.value = true; isScrollingleftmodlue.value = true; } - console.log("好耶滚动了"); }; /** * 添加滚动监听 */ const addScrollListener = () => { - console.log("添加滚动监听"); window.addEventListener('scroll', handleScroll); }; @@ -169,7 +164,6 @@ const addScrollListener = () => { * 移除滚动监听 */ const removeScrollListener = () => { - console.log("移除滚动监听"); window.removeEventListener('scroll', handleScroll); }; @@ -184,7 +178,6 @@ const handleResize = () => { isScrollingleftmodlue.value = true; classnonsenset.value = false; isconts.value = true; - // removeScrollListener(); } else { windowwidth.value = true; diff --git a/src/views/aericle.vue b/src/views/aericle.vue index 9261b7f..6298aba 100644 --- a/src/views/aericle.vue +++ b/src/views/aericle.vue @@ -5,11 +5,11 @@
-

{{ items[index].title }}

+

{{ items[index] }}

共{{ contentsum(items) }}篇
@@ -18,12 +18,26 @@ \ No newline at end of file diff --git a/src/views/home.vue b/src/views/home.vue index f0a84c9..37b0db0 100644 --- a/src/views/home.vue +++ b/src/views/home.vue @@ -5,7 +5,7 @@ class="article-card" v-for="item in datas" :key="item.title + item.publishedAt" - @click="aericleClick(item.aur)" + @click="aericleClick(item.articleid)" >

{{ item.title }}

{{ item.author }} @@ -18,8 +18,21 @@