feat: 实现前后端数据交互功能
- 添加axios API服务模块,封装所有后端接口调用 - 修改各视图组件,移除模拟数据,改为从后端API获取真实数据 - 更新文章、留言板等页面,支持后端数据渲染 - 添加README_API.md文档,说明API调用方式 - 升级axios依赖版本至1.12.2
This commit is contained in:
407
README_API.md
Normal file
407
README_API.md
Normal file
@@ -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
|
||||||
|
<template>
|
||||||
|
<Index/>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import Index from './index.vue';
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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 // 回复列表
|
||||||
|
}
|
||||||
|
```
|
||||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -10,7 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ant-design-vue": "^4.2.6",
|
"ant-design-vue": "^4.2.6",
|
||||||
"antd": "^5.27.3",
|
"antd": "^5.27.3",
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.12.2",
|
||||||
"element-plus": "^2.11.2",
|
"element-plus": "^2.11.2",
|
||||||
"vue": "^3.5.18",
|
"vue": "^3.5.18",
|
||||||
"vue-router": "^4.5.1"
|
"vue-router": "^4.5.1"
|
||||||
@@ -2647,9 +2647,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.11.0",
|
"version": "1.12.2",
|
||||||
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.11.0.tgz",
|
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.12.2.tgz",
|
||||||
"integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
|
"integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.6",
|
"follow-redirects": "^1.15.6",
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ant-design-vue": "^4.2.6",
|
"ant-design-vue": "^4.2.6",
|
||||||
"antd": "^5.27.3",
|
"antd": "^5.27.3",
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.12.2",
|
||||||
"element-plus": "^2.11.2",
|
"element-plus": "^2.11.2",
|
||||||
"vue": "^3.5.18",
|
"vue": "^3.5.18",
|
||||||
"vue-router": "^4.5.1"
|
"vue-router": "^4.5.1"
|
||||||
|
|||||||
86
src/axios/api.js
Normal file
86
src/axios/api.js
Normal file
@@ -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
|
||||||
@@ -105,10 +105,7 @@ const handleSelect = (key: string) => {
|
|||||||
*/
|
*/
|
||||||
const updatePageState = (url: string) => {
|
const updatePageState = (url: string) => {
|
||||||
classhero.value = url !== '/:type';
|
classhero.value = url !== '/:type';
|
||||||
console.log("当前路径是:"+url);
|
|
||||||
classnonsenset.value = url == '/nonsense';
|
classnonsenset.value = url == '/nonsense';
|
||||||
console.log( classnonsenset.value);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,14 +151,12 @@ const handleScroll = () => {
|
|||||||
isconts.value = true;
|
isconts.value = true;
|
||||||
isScrollingleftmodlue.value = true;
|
isScrollingleftmodlue.value = true;
|
||||||
}
|
}
|
||||||
console.log("好耶滚动了");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加滚动监听
|
* 添加滚动监听
|
||||||
*/
|
*/
|
||||||
const addScrollListener = () => {
|
const addScrollListener = () => {
|
||||||
console.log("添加滚动监听");
|
|
||||||
window.addEventListener('scroll', handleScroll);
|
window.addEventListener('scroll', handleScroll);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -169,7 +164,6 @@ const addScrollListener = () => {
|
|||||||
* 移除滚动监听
|
* 移除滚动监听
|
||||||
*/
|
*/
|
||||||
const removeScrollListener = () => {
|
const removeScrollListener = () => {
|
||||||
console.log("移除滚动监听");
|
|
||||||
window.removeEventListener('scroll', handleScroll);
|
window.removeEventListener('scroll', handleScroll);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -184,7 +178,6 @@ const handleResize = () => {
|
|||||||
isScrollingleftmodlue.value = true;
|
isScrollingleftmodlue.value = true;
|
||||||
classnonsenset.value = false;
|
classnonsenset.value = false;
|
||||||
isconts.value = true;
|
isconts.value = true;
|
||||||
// removeScrollListener();
|
|
||||||
} else {
|
} else {
|
||||||
windowwidth.value = true;
|
windowwidth.value = true;
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="post_content">
|
<div class="post_content">
|
||||||
<div v-for="(items, index) in datas" style=" padding: 20px;">
|
<div v-for="(items, index) in datas" style=" padding: 20px;">
|
||||||
<h2>{{ items[index].title }}</h2>
|
<h2>{{ items[index] }}</h2>
|
||||||
<span class="badge badge-primary">共{{ contentsum(items) }}篇</span>
|
<span class="badge badge-primary">共{{ contentsum(items) }}篇</span>
|
||||||
<ul class="pcont_ul">
|
<ul class="pcont_ul">
|
||||||
<li class="pcont_li" v-for="item in items">
|
<li class="pcont_li" v-for="item in items">
|
||||||
<a class="btn" @click="btnonclick(item.contentid)"><kbd>{{ item.content }}</kbd></a> — —({{ item.sum }})
|
<a class="btn" @click="btnonclick(item.typeid)"><kbd>{{ item.content }}</kbd></a> — —({{ item.sum }})
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -18,12 +18,26 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
import { articleAPI } from '@/axios/api'
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const btnonclick = (contentid) => {
|
const datas = ref([])
|
||||||
|
console.log("获取文章列表")
|
||||||
|
onMounted(() => {
|
||||||
|
articleAPI.getAllArticles().then(res => {
|
||||||
|
datas.value = res.data
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(err)
|
||||||
|
}).finally(() => {
|
||||||
|
console.log("finally")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const btnonclick = (typeid) => {
|
||||||
router.push({
|
router.push({
|
||||||
path: '/:type',
|
path: '/:type',
|
||||||
query: {
|
query: {
|
||||||
type: contentid
|
type: typeid
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -34,59 +48,6 @@ const contentsum = (items) => {
|
|||||||
}
|
}
|
||||||
return nums
|
return nums
|
||||||
}
|
}
|
||||||
const datas = [
|
|
||||||
// 学习模块
|
|
||||||
[
|
|
||||||
{
|
|
||||||
title: '学习',
|
|
||||||
contentid: '1',
|
|
||||||
content: '算法',
|
|
||||||
sum: 1,
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '学习',
|
|
||||||
contentid: '2',
|
|
||||||
content: '前端',
|
|
||||||
sum: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '学习',
|
|
||||||
contentid: '3',
|
|
||||||
content: '后端',
|
|
||||||
sum: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '学习',
|
|
||||||
contentid: '4',
|
|
||||||
content: 'Java',
|
|
||||||
sum: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
// 生活模块
|
|
||||||
[
|
|
||||||
{
|
|
||||||
title: '生活',
|
|
||||||
contentid: '1',
|
|
||||||
content: '生活',
|
|
||||||
sum: 1,
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '生活',
|
|
||||||
contentid: '2',
|
|
||||||
content: '书',
|
|
||||||
sum: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '生活',
|
|
||||||
contentid: '2',
|
|
||||||
content: '书',
|
|
||||||
sum: 1,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
]
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
.header {
|
.header {
|
||||||
|
|||||||
@@ -1,15 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="allstyle">
|
<div id="allstyle">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h1>文章内容页面</h1>
|
<h1>{{ article.title }}</h1>
|
||||||
|
</div>
|
||||||
|
<div class="article-content">
|
||||||
|
<p>{{ article.content }}</p>
|
||||||
</div>
|
</div>
|
||||||
<p>通过传来的{{ urls }}向服务器发送请求获取相关文章的链接</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
import { articleAPI } from '@/axios/api'
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
const article = ref({})
|
||||||
const urls = useRoute().query
|
const urls = useRoute().query
|
||||||
|
// 从后端获取文章详情
|
||||||
|
onMounted(() => {
|
||||||
|
articleAPI.getArticleById(urls.articleid).then(res => {
|
||||||
|
article.value = res.data
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(err)
|
||||||
|
}).finally(() => {
|
||||||
|
console.log("finally")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
</style>
|
</style>
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
class="article-card"
|
class="article-card"
|
||||||
v-for="item in datas"
|
v-for="item in datas"
|
||||||
:key="item.title + item.publishedAt"
|
:key="item.title + item.publishedAt"
|
||||||
@click="aericleClick(item.aur)"
|
@click="aericleClick(item.articleid)"
|
||||||
>
|
>
|
||||||
<h2>{{ item.title }}</h2>
|
<h2>{{ item.title }}</h2>
|
||||||
<el-text class="mx-1">{{ item.author }}</el-text>
|
<el-text class="mx-1">{{ item.author }}</el-text>
|
||||||
@@ -18,8 +18,21 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
import { articleAPI } from '@/axios/api'
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const datas = ref([])
|
||||||
|
console.log("获取文章列表")
|
||||||
|
onMounted(() => {
|
||||||
|
articleAPI.getAllArticles().then(res => {
|
||||||
|
datas.value = res.data
|
||||||
|
console.log(res.data)
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(err)
|
||||||
|
}).finally(() => {
|
||||||
|
console.log("finally")
|
||||||
|
})
|
||||||
|
})
|
||||||
// 跳转到文章详情
|
// 跳转到文章详情
|
||||||
const aericleClick = (aur) => {
|
const aericleClick = (aur) => {
|
||||||
router.push({
|
router.push({
|
||||||
@@ -27,104 +40,6 @@ const aericleClick = (aur) => {
|
|||||||
query: { url: aur }
|
query: { url: aur }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 文章数据
|
|
||||||
const datas = [
|
|
||||||
{
|
|
||||||
title: '测试1',
|
|
||||||
author: '这是文章模块测试',
|
|
||||||
aur: '链接',
|
|
||||||
mg: '11',
|
|
||||||
publishedAt: '2016-04-10'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '测试2',
|
|
||||||
author: '这是img模块测试',
|
|
||||||
aur: '链接',
|
|
||||||
mg: '',
|
|
||||||
mg_b: '',
|
|
||||||
publishedAt: '2016-04-12'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '测试2',
|
|
||||||
author: '这是img模块测试',
|
|
||||||
aur: '链接',
|
|
||||||
mg: '',
|
|
||||||
publishedAt: '2016-04-12'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '测试2',
|
|
||||||
author: '这是img模块测试',
|
|
||||||
aur: '链接',
|
|
||||||
mg: '',
|
|
||||||
mg_b: '',
|
|
||||||
publishedAt: '2016-04-12'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '测试2',
|
|
||||||
author: '这是img模块测试',
|
|
||||||
aur: '链接',
|
|
||||||
mg: '',
|
|
||||||
mg_b: '',
|
|
||||||
publishedAt: '2016-04-12'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '测试2',
|
|
||||||
author: '这是img模块测试',
|
|
||||||
aur: '链接',
|
|
||||||
mg: '',
|
|
||||||
mg_b: '',
|
|
||||||
publishedAt: '2016-04-12'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '测试2',
|
|
||||||
author: '这是img模块测试',
|
|
||||||
aur: '链接',
|
|
||||||
mg: '',
|
|
||||||
mg_b: '',
|
|
||||||
publishedAt: '2016-04-12'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '测试2',
|
|
||||||
author: '这是img模块测试',
|
|
||||||
aur: '链接',
|
|
||||||
mg: '',
|
|
||||||
mg_b: '',
|
|
||||||
publishedAt: '2016-04-12'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '测试2',
|
|
||||||
author: '这是img模块测试',
|
|
||||||
aur: '链接',
|
|
||||||
mg: '',
|
|
||||||
mg_b: '',
|
|
||||||
publishedAt: '2016-04-12'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '测试2',
|
|
||||||
author: '这是img模块测试',
|
|
||||||
aur: '链接',
|
|
||||||
mg: '',
|
|
||||||
mg_b: '',
|
|
||||||
publishedAt: '2016-04-12'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '测试2',
|
|
||||||
author: '这是img模块测试',
|
|
||||||
aur: '链接',
|
|
||||||
mg: '',
|
|
||||||
mg_b: '',
|
|
||||||
publishedAt: '2016-04-12'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '测试2',
|
|
||||||
author: '这是img模块测试',
|
|
||||||
aur: '链接',
|
|
||||||
mg: '',
|
|
||||||
mg_b: '',
|
|
||||||
publishedAt: '2016-04-12'
|
|
||||||
},
|
|
||||||
]
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<!-- 评论内容 -->
|
<!-- 评论内容 -->
|
||||||
<div class="message-item-top">
|
<div class="message-item-top">
|
||||||
<div class="message-nickname">{{ msg.nickname }}</div>
|
<div class="message-nickname">{{ msg.nickname }}</div>
|
||||||
<div class="message-time">{{ msg.time }}</div>
|
<div class="message-time">{{ msg.createdAt }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="message-content">{{ msg.content }}</div>
|
<div class="message-content">{{ msg.content }}</div>
|
||||||
<!-- 回复按钮 -->
|
<!-- 回复按钮 -->
|
||||||
@@ -86,39 +86,21 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, ref } from 'vue'
|
import { reactive, ref, onMounted } from 'vue'
|
||||||
|
import { messageAPI } from '@/axios/api'
|
||||||
const message_all = ref({})
|
const message_all = ref({})
|
||||||
const hoverId = ref(null)
|
const hoverId = ref(null)
|
||||||
const messages = ref([
|
const messages = ref([])
|
||||||
{
|
// 从后端获取留言列表
|
||||||
id: 1,
|
onMounted(() => {
|
||||||
nickname: 'A',
|
messageAPI.getAllMessages().then(res => {
|
||||||
content: '这里是A!',
|
messages.value = res.data
|
||||||
time: '2025-09-26 10:00',
|
}).catch(err => {
|
||||||
replies: [
|
console.log(err)
|
||||||
{
|
}).finally(() => {
|
||||||
id: 4,
|
console.log("finally")
|
||||||
nickname: 'B',
|
})
|
||||||
content: 'A,我来回复你!',
|
})
|
||||||
time: '2025-09-26 10:20'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
nickname: 'B',
|
|
||||||
content: '这里是B!',
|
|
||||||
time: '2025-09-26 10:05',
|
|
||||||
replies: []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
nickname: 'C',
|
|
||||||
content: '这里是C!',
|
|
||||||
time: '2025-09-26 10:10',
|
|
||||||
replies: []
|
|
||||||
}
|
|
||||||
])
|
|
||||||
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
replyid: null,
|
replyid: null,
|
||||||
|
|||||||
Reference in New Issue
Block a user