express+Vue2进行项目实战-景点后台管理系统(中篇)

前言

近期在完善博客内容,发现关于【景点后台管理系统】的项目内容没有更新完,所以接下来会找时间完善一下。

上篇:项目介绍以及准备、初始化工作

中篇:前端页面开发

下篇:后端接口开发+调试+项目完结

express+Vue2进行项目实战-景点后台管理系统(上篇)_express vue项目实战-优快云博客文章浏览阅读1.8k次,点赞46次,收藏20次。本项目做一个景点后台管理系统,采用前后端分离,前端使用Vue2进行开发,后端使用express搭建本地服务器,数据库用mysql。背景:前面做了一个express专栏,从入门:搭建简单的服务器,再到进阶:使用数据库集成(增删改查)操作。然后就结束专栏内容。后期考虑可以补充项目实战,做一个大家都能从0到1上手的项目实战,于是这次的项目实战来了!_express vue项目实战 https://blog.youkuaiyun.com/orbit4/article/details/145596061?utm_source%20=%20uc_fansmsg

本文是【中篇】,我们将实现前端页面内容。

一、实现效果

首先看一下实现效果。

登录页(vue-admin-template后台模板已实现)

景点管理列表

具体的展示内容,可以看express+Vue2进行项目实战-景点后台管理系统(上篇)_express vue项目实战-优快云博客

这里有详细介绍。

二、开发内容

接下来正式进入到开发环节

1、登录页

vue-admin-template后台模板已经实现登录页面样式以及登录功能。

登录逻辑

    handleLogin() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true
          this.$store.dispatch('user/login', this.loginForm).then(() => {
            this.$router.push({ path: this.redirect || '/' })
            this.loading = false
          }).catch(() => {
            this.loading = false
          })
        } else {
          console.log('error submit!!')
          return false
        }
      })
    }

这段代码实现了一个完整的登录流程控制,包括表单验证、加载状态管理、登录请求触发、以及登录成功 / 失败后的相应处理,是 Vue 项目中常见的登录功能实现方式。

2、首页

登录成功后,会跳转到首页

首页位置:src\views\dashboard

可以添加代码,丰富首页的内容。

3、如何添加层次菜单?

代码位置:src\router\index.js

建议:参考模版提供的写法

这里演示手动配置定义 "景点管理" 的路由模块。

  {
    path: '/scenery',
    component: Layout,
    redirect: '/scenery/sceneryListManager',
    name: 'Scenery',
    meta: {
      title: '景点管理',
      icon: 'el-icon-s-help'
    },
    children: [
      {
        path: 'sceneryListManager',
        name: 'sceneryListManager',
        component: () => import('@/views/sceneryListManager/index'),
        meta: {
          title: '景点大全',
          icon: 'table'
        }
      },
      {
        path: 'tree',
        name: 'Tree',
        component: () => import('@/views/tree/index'),
        meta: {
          title: 'Tree',
          icon: 'tree'
        }
      }
    ]
  },

路由基本配置

  • path: '/scenery':定义路由路径,访问时使用 /scenery
  • component: Layout:指定该路由使用的布局组件(通常是包含侧边栏、顶部导航的公共布局)
  • redirect: '/scenery/sceneryListManager':设置重定向,当访问 /scenery 时自动跳转到其第一个子路由
  • name: 'Scenery':路由名称,用于标识路由(需唯一)

子路由配置(children)

这是一个嵌套路由数组,表示 /scenery 下的子页面:

  • 第一个子路由:

    {
      path: 'sceneryListManager',
      name: 'sceneryListManager',
      component: () => import('@/views/sceneryListManager/index'),
      meta: {
        title: '景点大全',
        icon: 'table'
      }
    }
    
     
    • 完整访问路径为 /scenery/sceneryListManager
    • 使用懒加载方式导入组件 @/views/sceneryListManager/index
    • 菜单显示文本为 "景点大全",图标为表格图标
  • 第二个子路由:

    {
      path: 'tree',
      name: 'Tree',
      component: () => import('@/views/tree/index'),
      meta: {
        title: 'Tree',
        icon: 'tree'
      }
    }
    
     
    • 完整访问路径为 /scenery/tree
    • 对应组件为 @/views/tree/index
    • 菜单显示文本为 "Tree",图标为树形图标

4、景点管理页面

这里可以分为两个模块:信息查询(暂时忽略【添加按钮】)、列表展示

4.1、搜索模块
<el-row :gutter="20" type="flex" align="bottom" class-name="topSerachBox">
      <el-col :span="6">
        <el-select v-model="searchField" placeholder="请选择搜索字段">
          <el-option label="名称" value="name" />
          <el-option label="类型" value="type" />
          <el-option label="内容" value="content" />
        </el-select>
      </el-col>
      <el-col :span="8">
        <el-input v-model="searchKeyword" placeholder="请输入搜索内容" clearable @change="handleClear" />
      </el-col>
      <el-col :span="2">
        <el-button type="primary" @click="handleSearch">搜索</el-button>
      </el-col>
      <el-col :span="2">
        <el-button type="success" @click="handleReset">重置</el-button>
      </el-col>
    </el-row>

在data中添加变量

searchField: '', // 搜索类型
searchKeyword: '', // 搜索关键词

函数方法

// 搜索功能
    handleSearch() {
      if (!this.searchField || !this.searchKeyword) {
        this.$message({
          type: 'warning',
          message: '搜索字段或值不能为空!'
        })
        return
      }
      console.log('选择的搜索字段是>>>,', this.searchField, '对应的值是>>>', this.searchKeyword)
      // 发送接口
      const params = {
        fieldName: this.searchField,
        fieldValue: this.searchKeyword
      }
     //xxx后续【下篇】补充获取景点数据的接口
    },    
// 重置
    handleReset() {
      this.searchField = ''
      this.searchKeyword = ''
    },

这段代码实现了一个包含 "搜索字段选择"、"搜索内容输入"、"搜索按钮" 和 "重置按钮" 的完整搜索区域,采用栅格布局确保各元素排列整齐,是后台管理系统中查询功能的常见实现方式。

4.2、列表模块
    <el-row>
      <el-col :span="24">
        <el-table :data="dataList" style="width: 100%">
          <el-table-column prop="id" label="ID" width="150" align="center" />
          <el-table-column prop="name" label="景点名称" width="100" align="center" />

          <el-table-column prop="type" label="景点类型" width="150" align="center" />
          <el-table-column prop="title" label="景点简介" width="200" class-name="dateColumn" />
          <el-table-column label="景点图片" width="200" align="center">
            <template slot-scope="scope">
              <img :src="Array.isArray(scope.row.pic)?scope.row.pic[0]:scope.row.pic" class="table-pic">
            </template>
          </el-table-column>
          <el-table-column prop="content" label="文本介绍" width="300" class-name="dateColumn" />
          <el-table-column prop="latitude" label="经度" width="150" align="center" />
          <el-table-column prop="longitude" label="维度" width="150" align="center" />
          <el-table-column prop="address" label="所在地" align="center" />
          <!-- 操作栏 -->
          <!-- 固定操作列在右侧 -->
          <el-table-column label="操作" fixed="right" width="200" align="center">
            <template slot-scope="scope">
              <el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
              <el-button type="primary" size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-col>
    </el-row>

这段代码实现了一个功能完整的景点信息表格,展示了 ID、名称、类型、简介、图片等多种数据类型,并提供了编辑和删除的操作入口,是后台管理系统中数据展示的典型实现方式。

4.3、弹窗模块(添加/编辑)

添加弹窗和编辑弹窗用的是同一个,逻辑不同而已,添加 新数据,编辑 旧数据。

点击【添加】按钮,弹窗出现

//html代码
      <el-col :span="2">
        <el-button type="success" @click="showAddModal(1)">添加</el-button>
      </el-col>

//js代码
    showAddModal() {
      this.editDialogVisible = true
      console.log('打开新增状态下的表单,当前存储的表单数据是>>>>', this.currentEditItem)
      this.addFlag = true
    },

在data中添加变量

    <el-dialog width="700px" height="300px" :visible.sync="editDialogVisible" :title="addFlag==true?'新增信息':'编辑信息'" @close="resetForm">
      <el-form ref="editForm" :model="currentEditItem" label-width="120px" :rules="rules">
        <el-form-item label="景点名称" prop="name">
          <el-input v-model="currentEditItem.name" clearable autocomplete="off" />
        </el-form-item>
        <el-form-item label="景点类型" prop="type">
          <el-input v-model="currentEditItem.type" clearable autocomplete="off" />
        </el-form-item>
        <el-form-item label="景点简介" prop="title">
          <el-input
            v-model="currentEditItem.title"
            clearable
            type="textarea"
            :autosize="{ minRows: 3, maxRows: 7 }"
            autocomplete="off"
          />
        </el-form-item>
        <el-form-item label="景点图片" prop="pic">
          <el-upload
            ref="upload"
            action="http://localhost:4000/api/upload"
            list-type="picture-card"
            :on-preview="handlePictureCardPreview"
            :on-remove="handleRemove"
            :file-list="fileList"
            :on-change="handleFileChange"
            :on-success="handleUploadSuccess"
            :on-error="handleUploadError"
            name="file"
          >
            <i class="el-icon-plus" />
          </el-upload>
          <!-- 预览区域 -->
          <el-dialog :visible.sync="dialogVisible">
            <img width="100%" :src="dialogImageUrl" alt="">
          </el-dialog>
          <image
            :src="currentEditItem.pic"
            mode="scaleToFill"
          />
        </el-form-item>
        <el-form-item label="文本内容" prop="content">
          <el-input
            v-model="currentEditItem.content"
            clearable
            type="textarea"
            :autosize="{ minRows: 3, maxRows: 6 }"
            autocomplete="off"
          />
        </el-form-item>
        <el-form-item label="经度" prop="latitude">
          <el-input v-model.number="currentEditItem.latitude" clearable autocomplete="off" />
        </el-form-item>
        <el-form-item label="维度" prop="longitude">
          <el-input v-model.number="currentEditItem.longitude" clearable autocomplete="off" />
        </el-form-item>
        <el-form-item label="所在地" prop="address">
          <el-input v-model="currentEditItem.address" clearable autocomplete="off" />
        </el-form-item>
        <el-form-item label="音频">
          <el-input v-model="currentEditItem.mp3" clearable autocomplete="off" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="handleCancle">取消</el-button>
        <el-button type="primary" @click="handleSubmitEdit">确定</el-button>
      </div>
    </el-dialog>
//图片放大预览
    <el-dialog :visible.sync="dialogVisible">
      <img width="100%" :src="dialogImageUrl" alt="">
    </el-dialog>
  1. 对话框基本设置

    • 固定宽度为 700px(注意:Element UI 的 el-dialog 本身没有 height 属性,该属性可能不生效)
    • 根据 addFlag 动态显示标题为 "新增信息" 或 "编辑信息"
    • 绑定 visible 状态为 editDialogVisible,关闭时触发 resetForm 方法
  2. 核心表单功能

    • 使用 el-form 组件,绑定数据模型 currentEditItem 和校验规则 rules
    • 包含多个表单项,涵盖景点名称、类型、简介、图片、文本内容、经纬度、所在地、音频等信息
    • 部分输入框使用 textarea 类型,并设置了自适应高度
  3. 图片上传与预览

    • 集成 el-upload 组件实现图片上传功能,配置了上传地址、预览、删除等回调
    • 包含图片预览对话框,点击预览时显示大图
  4. 底部操作按钮

    • 提供 "取消" 和 "确定" 按钮,分别绑定 handleCancle 和 handleSubmitEdit 方法

【确定】和【取消】按钮,本文不做数据层面上的处理,因此先统一关闭掉弹窗即可。

//点击弹窗的确定按钮
handleSubmitEdit() {
        this.editDialogVisible = false
    },    
//点击弹窗的取消按钮
handleCancle() {
        this.editDialogVisible = false
    },

三、本篇小结

因为本文提供的代码只是起到借鉴和引导作用,很多细节需要大家完善,比如组件/模块用到的变量,相关函数方法等,要确保每个模块的逻辑走得通,后续引入数据层面的内容,也就更好处理。

评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十八朵郁金香

感恩前行路上有你相伴

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值