新闻发布与列表

新闻发布与列表

学习目标

  • 前端实现发布新闻页面,调用 /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(加载新闻列表)

替换templatescript的内容,保留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

701

目录结构:

702

  • 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 } }
    

    注意加上逗号,添加位置如下:

703

结束时的项目状态

  • 首页显示新闻列表(分页)。
  • 点击发布新闻,填写表单提交,成功后跳转首页,列表自动刷新。
posted @ 2026-06-25 13:38  睡醒再说  阅读(2)  评论(0)    收藏  举报