新闻发布与列表

任务清单
前端实现发布新闻页面,调用 /news/add 接口。
前端首页调用 /news/page 分页接口,展示表格。
操作步骤
主要修改前端工程,后端工程已有相应的功能
步骤1:修改 api/news.js
全部替换为如下内容:

import request from '../utils/request'

export const getNewsPage = (page, size) => {
  return request.get('/news/page', { params: { page, size } })
}

export const publishNews = (data) => {
  return request.post('/news/add', data)
}

export const getNewsDetail = (id) => {
  return request.get(`/news/${id}`)
}

export const updateNews = (id, data) => {
  return request.put(`/news/${id}`, data)
}

export const deleteNews = (id) => {
  return request.delete(`/news/${id}`)
}

export const likeNews = (id, likes) => request.patch(`/news/${id}`, { likes })

步骤2:修改 Home.vue(加载新闻列表)
替换template和script的内容,保留style中的内容,替换的内容如下:

<!-- src/views/Home.vue -->
<template>
    <div class="home-container">
        <!-- 固定头部 -->
        <div class="header">
            <h2>微头条首页</h2>
            <div>欢迎,{{ userStore.username }}</div>
            <button @click="logout">退出登录</button>
        </div>

        <!-- 可滚动的内容区域(发布区 + 新闻列表) -->
        <div class="scroll-area">
            <div class="content-wrapper">
                <!-- 发布区域 -->
                <div class="publish-area">
                    <button @click="goToPublish">+ 发布微头条</button>
                </div>

                <!-- 新闻列表 -->
                <div class="news-list">
                    <div v-if="newsList.length === 0" class="empty">
                        暂无新闻,快去发布一条吧
                    </div>
                    <div v-for="item in newsList" :key="item.id" class="news-item">
                        <h3>{{ item.title }}</h3>
                        <div class="time">{{ item.time }}</div>
                        <div class="content">{{ item.content }}</div>
                        <div class="actions">
                            <button @click="homeViewDetail(item.id)">📚 查看详情</button>
                            <button @click="homeDeleteNews(item.id)">🗑 删除</button>
                            <button @click="homeLikeNews(item.id, item.likes)">💗 点赞 {{ item.likes }}</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <el-pagination v-model:current-page="pageNum" v-model:page-size="pageSize" :total="total"
            @current-change="loadNews" layout="prev, pager, next" />
    </div>
</template>

<script setup>
import { useRouter } from 'vue-router'
import { ref, onMounted, onUnmounted } from 'vue'
import { useUserStore } from '../stores/user'
import { getNewsPage, publishNews, getNewsDetail, updateNews, deleteNews, likeNews } from '../api/news'
import { ElMessage } from 'element-plus'

const router = useRouter()
const userStore = useUserStore()

const newsList = ref([])
const newTitle = ref('')
const newContent = ref('')
const loading = ref(false)
const pageNum = ref(1)
const pageSize = ref(10)
const total = ref(0)    

const loadNews = async () => {
    loading.value = true
    try {
        const res = await getNewsPage(pageNum.value, pageSize.value)
        if (res.code === 200) {
            newsList.value = res.data.records
            total.value = res.data.total
        }
    } finally {
        loading.value = false
    }
}

const addNews = async () => {
    if (!newTitle.value.trim() || !newContent.value.trim()) {
        ElMessage.warning('标题和内容不能为空')
        return
    }
    const newNews = {
        title: newTitle.value,
        content: newContent.value,
        time: new Date().toLocaleString(),
        likes: 0,
        userId: 1
    }
    try {
        await publishNews(newNews)
        ElMessage.success('发布成功')
        newTitle.value = ''
        newContent.value = ''
        loadNews()
    } catch {
        ElMessage.error('发布失败')
    }
}

const homeDeleteNews = async (id) => {
    try {
        await deleteNews(id)
        ElMessage.success('删除成功')
        loadNews()
    } catch {
        ElMessage.error('删除失败')
    }
}

const homeLikeNews = async (id, currentLikes) => {
    try {
        await likeNews(id, currentLikes + 1)
        loadNews()
    } catch {
        ElMessage.error('点赞失败')
    }
}

const homeViewDetail = (id) => {
    router.push(`/detail/${id}`)
}

const goToPublish = () => {
    router.push('/publish')
}

const logout = () => {
    userStore.logout()
    router.push('/login')
}

onMounted(() => {
    loadNews()
    document.body.style.overflow = 'hidden'
})

onUnmounted(() => {
    document.body.style.overflow = ''
})
</script>

步骤3:创建发布新闻页面
右键views文件夹,新建Publish.vue
目录结构:
Publish.vue中的代码:

<!-- src/views/Publish.vue -->
<template>
  <div class="publish-container">
    <el-card>
      <h2>发布微头条</h2>
      <el-form :model="form" :rules="rules" ref="formRef" label-width="80px">
        <el-form-item label="标题" prop="title">
          <el-input v-model="form.title" placeholder="请输入标题" />
        </el-form-item>
        <el-form-item label="内容" prop="content">
          <el-input v-model="form.content" type="textarea" rows="8" placeholder="请输入内容" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handlePublish" :loading="submitting">发布</el-button>
          <el-button @click="$router.back()">取消</el-button>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script setup>
import { reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { publishNews } from '../api/news'
import { ElMessage } from 'element-plus'

const router = useRouter()
const formRef = ref(null)
const submitting = ref(false)
const form = reactive({ title: '', content: '' })

const rules = {
  title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
  content: [{ required: true, message: '请输入内容', trigger: 'blur' }]
}

const handlePublish = async () => {
  if (!formRef.value) return
  await formRef.value.validate(async (valid) => {
    if (valid) {
      submitting.value = true
      try {
        const res = await publishNews(form)
        if (res.code === 200) {
          ElMessage.success('发布成功')
          router.push('/home')
        } else {
          ElMessage.error(res.message)
        }
      } finally {
        submitting.value = false
      }
    }
  })
}
</script>

<style scoped>
.publish-container { max-width: 800px; margin: 40px auto; }
</style>

步骤4:添加路由
在src/router/index.js 添加

import Publish from '../views/Publish.vue'
{ path: '/publish', component: Publish, meta: { requiresAuth: true } }

注意加上逗号
首页显示新闻列表(分页)。
点击发布新闻,填写表单提交,成功后跳转首页,列表自动刷新。

posted on 2026-06-24 10:58  爱我的果果吖  阅读(2)  评论(0)    收藏  举报