Skip to content
本页目录

vue3新闻管理系统

时间预计:30分钟

技术: vue3, vuex, elementplus, json-server

数据来源: json-server提供接口

作业要求:

image-20240611231020976

项目运行

node版本>= 18.18.0

1.在当前项目目录的命令行启动json-server,一定要带上版本,最新的json-server功能有问题

shell
npm install -g json-server@0.17.4    # NPM
yarn global add json-server@0.17.4   # Yarn
pnpm add -g json-server@0.17.4       # PNPM
shell
npm run mock  # NPM
yarn run mock # Yarn

image-20240611231959919

  1. 启动vue项目

    shell
    yarn run dev # Yarn
    npm run dev # NPM
    

    image-20240611232328421

项目截图

01-登陆页面

image-20240611232412869

02-首页

image-20240611232427203

03-新闻管理页面

image-20240611232517575

04-用户管理页面

image-20240611232549620

05-个人中心页面

image-20240611232610457

06-404页面

image-20240612003843785

重点代码解析

1.封装element-plus的表格组件为SimpleTable,简化操作

2.新闻的增删改查逻辑

新闻表格 NewsList.vue

新建文件src/view/newsManage/NewsList.vue

vue
<template>
  <el-card>
    <template #header>
      <div>
        <span>新闻列表</span>
 
        <el-button class="button"
          size="small"
          @click="onAdd()"
          type="primary">
          创建新闻
        </el-button>
        <!-- 搜索功能 -->
        <div class="inputArea">
          <el-input v-model="keyWords.k" placeholder="请输入" clearable :style="{ width: '200px'}" @clear="clearFn"/>
          <el-button
          type="primary"
          @click="searchFn">
              <el-icon><Search /></el-icon>
              搜索
          </el-button>
        </div>
      </div>
    </template>
    <div class="table-container">
      <simple-table
      :columns="columns"
      :tableData="state.list"
      optionWidth="200"
      @handleEdit="onEdit"
      @handleDelete="onDelete"
    >
    <template #currentStatus="scope">
        <div>
          <el-tag type="success"  v-if="scope.row.currentStatus == '0'">发布</el-tag>
          <el-tag type="info" v-else>未发布</el-tag>
        </div>
      </template>
    </simple-table>
     
    </div>
    <!--注册/修改用户对话框-->
    <NewsModal ref="userModal" @add="addFetch" @edit="editFetch" :modalConfig="modalConfig"></NewsModal>
  </el-card>
</template>
<script setup>
//注意:vue3.x组合式api,需要在<script>里面使用setup
import {ref,reactive,onMounted} from "vue";
import { ElMessage } from 'element-plus';
import NewsModal from './NewsModal.vue';
import SimpleTable from '@/components/base/Table/SimpleTable.vue'

//导入axios实例(从封装的http.js中导入)
import http from "@/util/http.js";

// 获取弹窗的dom
const userModal = ref(null)
const modalConfig = reactive({
  title: '创建新闻',
  option: 'add'
})

// 定义表格列
const columns = reactive([
  { prop: "title", label: "新闻标题", minWidth: 120 },
  { prop: "intro", label: "内容", minWidth: 120 },
  { prop: "author", label: "作者", minWidth: 120 },
  { prop: "currentStatus", label: "状态", minWidth: 120,isSlot:true },
]);

//使用一个reactive方法定义响应式对象
const state = reactive({
//数据列表
  list:[],
  listSearchBefore:[],
//临时保存选中的行索引
  selectedIndex:-1,
})
//生命周期钩子
onMounted(() =>{
  initTable()
})
const initTable = ()=>{
  http.get("/news").then(res=>{
    if(res.status === 200 || res.status === 201){
//更新表格
      state.list = res.data;
      state.listSearchBefore = res.data
    }
  }).catch(err=>{
    console.log(err)
    ElMessage.error('获取数据失败');
  })
}
//响应注册按钮,打开注册对话框
const onAdd = ()=>{
  modalConfig.title = "创建新闻"
  modalConfig.option = "add"
  userModal.value.open()
}
// 新增操作
const addFetch = async (formData)=>{
  let res = await http.post("/news",formData)
      if(res.status === 200 || res.status ===201 ){
        // 操作成功
        ElMessage({
          message: "保存成功!",
          type: "success"
        });
        //更新表格
        state.list.push(formData);
      }
}
// 编辑操作
const onEdit = ({index})=>{
  modalConfig.title = "修改新闻"
  modalConfig.option = "edit"
//获得要修改用户的信息
  let user = state.list[index];

  modalConfig.formData = user
  userModal.value.open()

  //临时保存选中的索引
  state.selectedIndex = index;
}

const editFetch = (formData)=>{
  http.put("/news/"+ formData.id,formData).then(res=>{
    if (res.status === 200 || res.status === 201){
      //操作成功
      ElMessage({
        message: "保存成功!",
        type: "success"
      });
      //更新表格
      state.list.splice(state.selectedIndex,1,res.data)
      //重置selectedIndex
      state.selectedIndex = -1;
      //关闭对话框  
    }
  })
} 



//响应删除按钮
const onDelete = async ({index}) =>{
//删除被选中的数据
  let id = state.list[index].id;
  let res = await http.delete("/news/" + id)
  if (res.status === 200 || res.status === 201){
    ElMessage("删除成功");
// 刷新表格,删除起始下标为1,长度为1的一个值
    state.list.splice(index, 1);
  }
}

// 搜索功能
const keyWords = reactive({
        k:""
    })
const searchFn  = ()=>{
  if(keyWords.k== ''){
     initTable();
    return 
  }
  console.log(state.list,state.listSearchBefore,keyWords.k)
  let itemData = state.listSearchBefore.filter((p) => {
        return p.title.indexOf(keyWords.k) !== -1
    })
    
  state.list = JSON.parse(JSON.stringify(itemData))
}
// 清除搜索条件
const clearFn = ()=>{
  initTable()
}
 
 
</script>
<style scoped>
.table-container{
  text-align: right;
}
</style>
新闻的新增与编辑弹窗 NewsModal.vue

新建文件src/view/newsManage/NewsModal.vue

vue
<template>
  <div>
    <el-dialog :title="modalConfig.title" v-model="dialogVisible">
      <el-form ref="elForm" :model="formData" :rules="rules" size="default" label-width="100px">
        <el-form-item label="新闻标题" prop="title">
          <el-input v-model="formData.title" placeholder="请输入新闻标题" :maxlength="20" show-word-limit clearable
            :style="{width: '100%'}"></el-input>
        </el-form-item>
        <el-form-item label="新闻内容" prop="intro">
          <el-input v-model="formData.intro" type="textarea" placeholder="请输入新闻内容" :maxlength="200"
            show-word-limit :autosize="{minRows: 4, maxRows: 4}" :style="{width: '100%'}"></el-input>
        </el-form-item>
        <el-form-item label="作者" prop="author">
          <el-input v-model="formData.author" placeholder="请输入作者" clearable :style="{width: '100%'}">
          </el-input>
        </el-form-item>
        <el-form-item label="发布状态" prop="currentStatus" required>
          <el-switch v-model="formData.currentStatus" :active-value='0' :inactive-value='1'></el-switch>
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button @click="close">取消</el-button>
        <el-button type="primary" @click="handelConfirm">确定</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
export default {
  props: {
    modalConfig:{
      type: Object,
      default: ()=>{
        return{
          title: '弹窗标题',
          option: 'add'
        }
      }
    }
  },
  data() {
    return {
      dialogVisible: false,
      formData: {
        title: undefined,
        intro: "",
        author: undefined,
        currentStatus: 1,
      },
      rules: {
        title: [{
          required: true,
          message: '请输入新闻标题',
          trigger: 'blur'
        }],
        intro: [{
          required: true,
          message: '请输入新闻内容',
          trigger: 'blur'
        }],
        author: [{
          required: true,
          message: '请输入作者',
          trigger: 'blur'
        }],
      },
    }
  },
  computed: {},
  watch: {},
  created() {},
  mounted() {},
  methods: {
   // 打开弹窗
   open() {
      this.dialogVisible = true
      // 编辑初始化
      if(this.modalConfig.option==='edit'){
        this.formData = this.modalConfig.formData
      }
      // 新增初始化
      if(this.modalConfig.option==='add'){
        // 初始化当前用户名
        const userInfo = JSON.parse(sessionStorage.getItem('userInfo'))

        this.formData =  {
          title: undefined,
          intro: "",
          author: userInfo.userName,
          currentStatus: 1,
        }
      }
    },
    close() {
      this.dialogVisible = false
    },
    handelConfirm() {
      this.$refs['elForm'].validate(valid => {
        if (!valid) return
        // 新增操作
        if(this.modalConfig.option==='add'){
          // 设置新增用户id
          this.formData.id =  (new Date()).valueOf()  + ''
          // 返回结果
          this.$emit('add', this.formData)
        }
        // 编辑操作
        if(this.modalConfig.option==='edit'){
          // 返回结果
          this.$emit('edit', this.formData)
        }
        this.close()
      })
    },
  }
}

</script>
<style>
</style>

3.404页面的路由匹配

极速大抄(获取源码)

直接拿项目源码

请关注微信公众号 技术成神

添加阿飞(微信号:jscsvip)

提供源码与技术支持,保证服务满意