跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
TypeScriptNode.js大前端

苍穹外卖前端开发实战:Vue + TypeScript + ElementUI

基于 Vue 3 与 TypeScript 技术栈,结合 ElementUI 组件库完成苍穹外卖系统的前端模块开发。内容涵盖员工管理与套餐管理两大核心功能,包括分页查询、状态变更、新增修改及批量删除等 CRUD 操作。通过封装 Axios 请求、配置路由守卫及表单校验规则,实现了前后端数据的高效交互与界面动态渲染。文章详细梳理了从环境搭建到具体业务逻辑实现的完整流程,适合希望掌握企业级中后台管理系统开发的开发者参考。

ArchDesign发布于 2026/4/8更新于 2026/9/874 浏览
苍穹外卖前端开发实战:Vue + TypeScript + ElementUI

前端环境搭建

技术选型

本项目采用 Node.js 作为运行环境,核心框架选用 Vue,配合 ElementUI 组件库、Axios 请求拦截器、Vuex 状态管理、Vue-Router 路由以及 TypeScript 类型系统构建。

代码结构

项目核心目录与文件说明如下:

目录 / 文件说明
api封装 Ajax 请求的文件目录
components公共组件存放目录
views视图组件存放目录
App.vue项目主组件、页面入口文件
main.ts整个项目的入口文件
router.ts路由配置文件

环境准备

安装依赖包(生成 node_modules 目录):

npm install

启动前端项目(需同时启动后端 Java 服务):

npm run serve

员工管理

分页查询

功能需求

实现员工列表的分页展示,支持按姓名筛选,并在表格中显示账号状态及操作按钮。

页面头部构建

使用 ElementUI 的 Input 和 Button 组件制作搜索栏。输入框与按钮均基于官方文档组件进行配置。

<div>
  <label>员工姓名:</label>
  <el-input placeholder="请输入员工姓名" />
  <el-button type="primary">查询</el-button>
  <el-button type="primary">+ 添加员工</el-button>
</div>
前后端数据交互

为查询按钮绑定 @click="pageQuery()" 事件。在 methods 中定义 pageQuery 方法,验证逻辑执行。

<script lang="ts">
export default {
  methods: {
    // 分页查询
    pageQuery() {
      // 验证当前方法能否成功执行
      console.log('Query triggered')
    }
  }
}
</script>

封装 API 请求:在 src/api/employee.ts 中定义 getEmployeeList 方法,用于发送 Ajax 请求获取分页数据。

// 分页查询
export const getEmployeeList = (params: any) => {
  return request({ url: '/employee/page', method: 'get', params })
}

导入 API 并定义模型数据:在员工管理组件中导入 getEmployeeList,并在 data() 中定义分页相关的模型数据。

import { getEmployeeList } from '@/api/employee'
export default {
  data() {
    return {
      name: '',       // 员工姓名
      page: 1,        // 页码
      pageSize: 10,   // 每页记录数
      total: 0,       // 总记录数
      records: []     // 当前页要展示的数据集合
    }
  }
}

双向绑定输入框:将 name 属性与员工姓名输入框进行双向绑定。

<el-input v-model="name" placeholder="请输入员工姓名" clearable />

完善查询方法:在 pageQuery 方法中调用 getEmployeeList,处理返回数据。

pageQuery() {
  const params = { page: this.page, pageSize: this.pageSize, name: this.name }
  getEmployeeList(params)
    .then((res) => {
      if (res.data.code === 1) {
        this.records = res.data.data.records
        this.total = res.data.data.total
      }
    })
    .catch((err) => {
      this.$message.error('请求出错了:' + err.message)
    })
}
自动加载数据

利用 Vue 的 created 生命周期钩子,在组件加载后自动发送 Ajax 请求,查询第一页数据。

created() {
  this.pageQuery()
}
表格展示

使用 ElementUI 的 Table 组件展示后端返回的员工数据。注意状态列的样式处理。

<el-table :data="records" stripe>
  <el-table-column prop="name" label="员工姓名" />
  <el-table-column prop="username" label="账号" />
  <el-table-column prop="phone" label="手机号" />
  <el-table-column prop="status" label="账号状态">
    <template slot-scope="scope">
      <span :class="scope.row.status === 0 ? 'stopUse' : 'activeUse'">
        {{ scope.row.status === 0 ? '禁用' : '启用' }}
      </span>
    </template>
  </el-table-column>
  <el-table-column prop="updateTime" label="最后操作时间" />
  <el-table-column prop="操作" label="操作">
    <template slot-scope="scope">
      <el-button size="small" type="text">修改</el-button>
      <el-button size="small" type="text">
        {{ scope.row.status === 1 ? '禁用' : '启用' }}
      </el-button>
      <el-button size="small" type="text">删除</el-button>
    </template>
  </el-table-column>
</el-table>
分页条实现

使用 Pagination 组件实现翻页效果。监听 size-change 和 current-change 事件以刷新数据。

<el-pagination
  :page-sizes="[10, 20, 30, 40, 50]"
  :page-size="pageSize"
  layout="total, sizes, prev, pager, next, jumper"
  :total="total"
  @size-change="handleSizeChange"
  @current-change="handleCurrentChange"
/>

事件处理函数:

// pageSize 改变时触发
handleSizeChange(pageSize) {
  this.pageSize = pageSize
  this.pageQuery()
},
// currentPage 改变时触发
handleCurrentChange(currentPage) {
  this.page = currentPage
  this.pageQuery()
}

启用禁用员工账号

功能需求

支持在列表中直接切换员工账号状态,管理员账号除外。

按钮交互

为表格中的'启用/禁用'按钮绑定 handleStartOrStop 事件,并根据当前状态动态显示文字。

<el-button type="text" size="small" @click="handleStartOrStop(scope.row)">
  {{ scope.row.status == '1' ? '禁用' : '启用' }}
</el-button>
状态变更逻辑

在 methods 中定义 handleStartOrStop 方法,结合 ElementUI 的确认弹窗 confirm 确保操作安全。

handleStartOrStop(row) {
  // 管理员保护逻辑
  if (row.username === 'admin') {
    this.$message.error('admin 为管理员账号,不能更改账号状态!')
    return
  }
  this.$confirm('确认调整该账号的状态?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    enableOrDisableEmployee({ id: row.id, status: !row.status ? 1 : 0 })
      .then((res) => {
        if (res.status === 200) {
          this.$message.success('账号状态更改成功!')
          this.pageQuery() // 刷新数据
        }
      })
      .catch((err) => {
        this.$message.error('请求出错了:' + err.message)
      })
  })
}

封装 API 请求:在 src/api/employee.ts 中定义 enableOrDisableEmployee 方法。

export const enableOrDisableEmployee = (params: any) => {
  return request({
    url: `/employee/status/${params.status}`,
    method: 'post',
    params: { id: params.id }
  })
}

新增员工

功能需求

通过表单录入员工信息,包含账号、姓名、手机、性别、身份证号等字段,并进行校验。

路由跳转

点击'添加员工'按钮,跳转到新增页面组件。

handleAddEmp() {
  this.$router.push('/employee/add')
}

路由配置示例:

{ path: "/employee/add", component: () => import("@/views/employee/addEmployee.vue"), meta: { title: "添加/修改员工", hidden: true } }
表单元素开发

使用 Form 组件构建表单,设置 rules 进行校验。

<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="180px">
  <el-form-item label="账号" prop="username">
    <el-input v-model="ruleForm.username"></el-input>
  </el-form-item>
  <el-form-item label="员工姓名" prop="name">
    <el-input v-model="ruleForm.name"></el-input>
  </el-form-item>
  <el-form-item label="手机号" prop="phone">
    <el-input v-model="ruleForm.phone"></el-input>
  </el-form-item>
  <el-form-item label="性别" prop="sex">
    <el-radio v-model="ruleForm.sex" label="1">男</el-radio>
    <el-radio v-model="ruleForm.sex" label="2">女</el-radio>
  </el-form-item>
  <el-form-item label="身份证号" prop="idNumber">
    <el-input v-model="ruleForm.idNumber"></el-input>
  </el-form-item>
  <div>
    <el-button type="primary" @click="submitForm('ruleForm',false)">保存</el-button>
    <el-button type="primary" @click="submitForm('ruleForm',true)">保存并继续添加员工</el-button>
    <el-button @click="() => this.$router.push('/employee')">返回</el-button>
  </div>
</el-form>
表单校验规则

定义正则表达式校验手机号和身份证号格式。

rules: {
  phone: [
    {
      required: true,
      trigger: 'blur',
      validator: (rule, value, callback) => {
        if (value === '' || !(/^1[3|4|5|6|7|8]\d{9}$/.test(value))) {
          callback(new Error('请输入正确的手机号'))
        } else {
          callback()
        }
      }
    }
  ],
  idNumber: [
    {
      required: true,
      trigger: 'blur',
      validator: (rule, value, callback) => {
        if (value === '' || !(/(\d{15}$)|(\d{18}$)|(\d{17}(\d|X|x)$)/.test(value))) {
          callback(new Error('请输入正确的身份证号'))
        } else {
          callback()
        }
      }
    }
  ]
}
提交逻辑

封装 addEmployee 方法,根据 isContinue 参数决定是否保留表单或跳转。

submitForm(formName, isContinue) {
  this.$refs[formName].validate((valid) => {
    if (valid) {
      addEmployee(this.ruleForm)
        .then((res: any) => {
          if (res.data.code === 1) {
            this.$message.success('员工添加成功!')
            if (isContinue) {
              this.$router.push({ path: '/employee/add' })
            } else {
              this.ruleForm = { username: '', name: '', phone: '', sex: '1', idNumber: '' }
            }
          } else {
            this.$message.error(res.data.msg)
          }
        })
    }
  })
}

修改员工

功能需求

复用新增页面组件,通过路由参数区分新增与修改模式,支持数据回显。

路由传参

点击'修改'按钮时,携带 ID 参数跳转。

handleUpdateEmp(row) {
  if (row.username === 'admin') {
    this.$message.error('admin 为管理员账号,不能修改!')
    return
  }
  this.$router.push({ path: '/employee/add', query: { id: row.id } })
}
组件内判断

在 addEmployee.vue 中通过 optType 区分操作类型,并在 created 中根据路由参数初始化。

created() {
  this.optType = this.$route.query.id ? 'update' : 'add'
  if (this.optType === 'update') {
    queryEmployeeById(this.$route.query.id).then((res) => {
      if (res.data.code === 1) {
        this.ruleForm = res.data.data
      }
    })
  }
}
接口区分

封装 queryEmployeeById 和 updateEmployee 方法,分别对应 GET 和 PUT 请求。

export const queryEmployeeById = (id: number) => {
  return request({ url: `/employee/${id}`, method: 'get' })
}

export const updateEmployee = (params: any) => {
  return request({ url: '/employee', method: 'put', data: params })
}
按钮控制

仅在新增模式下显示'保存并继续添加员工'按钮。

<el-button v-if="this.optType === 'add'" type="primary" @click="submitForm('ruleForm',true)">
  保存并继续添加员工
</el-button>

套餐管理

套餐分页查询

功能需求

支持按套餐名称、分类、售卖状态筛选,展示图片、价格及操作选项。

页面头部构建

增加下拉选择框以支持分类和状态筛选。

<div>
  <label>套餐名称:</label>
  <el-input v-model="name" clearable />
  <label>套餐分类:</label>
  <el-select v-model="categoryId" placeholder="请选择">
    <el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id" />
  </el-select>
  <label>售卖状态:</label>
  <el-select v-model="status" placeholder="请选择" clearable>
    <el-option v-for="item in statusArr" :key="item.value" :label="item.label" :value="item.value" />
  </el-select>
  <el-button type="primary">查询</el-button>
  <div>
    <el-button type="danger">批量删除</el-button>
    <el-button type="info">+ 新建套餐</el-button>
  </div>
</div>
动态填充分类数据

在 created 生命周期中调用分类接口,填充下拉框选项。

import { getCategoryByType } from '@/api/category'
created() {
  getCategoryByType({type: 2}).then((res) => {
    if (res.data.code === 1) {
      this.options = res.data.data
    }
  })
}
表格展示

使用 Image 组件展示套餐图片,状态列根据数值渲染文本。

<el-table :data="records" stripe>
  <el-table-column prop="image" label="图片">
    <template slot-scope="scope">
      <el-image :src="scope.row.image"></el-image>
    </template>
  </el-table-column>
  <el-table-column prop="name" label="套餐名称" />
  <el-table-column prop="price" label="套餐价" />
  <el-table-column prop="categoryName" label="套餐分类" />
  <el-table-column label="售卖状态">
    <template slot-scope="scope">
      <div :class="scope.row.status === 0 ? 'stopUse' : 'activeUse'">
        {{ scope.row.status === 0 ? '停售' : '启售' }}
      </div>
    </template>
  </el-table-column>
  <el-table-column label="操作">
    <template slot-scope="scope">
      <el-button type="text" size="small">修改</el-button>
      <el-button type="text" size="small">
        {{ scope.row.status === 1 ? '停售' : '启售' }}
      </el-button>
      <el-button type="text" size="small">删除</el-button>
    </template>
  </el-table-column>
</el-table>

启售停售套餐

功能需求

允许运营人员快速切换套餐的售卖状态。

状态切换逻辑

封装 enableOrDisableSetmeal 方法,结合确认弹窗防止误操作。

handleStartOrStop(row) {
  this.$confirm('确认调整该套餐的售卖状态?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    enableOrDisableSetmeal({ id: row.id, status: !row.status ? 1 : 0 })
      .then((res) => {
        if (res.status === 200) {
          this.$message.success('套餐售卖状态更改成功!')
          this.pageQuery()
        }
      })
      .catch((err) => {
        this.$message.error('请求出错了:' + err.message)
      })
  })
}

删除套餐

功能需求

支持单个删除与批量删除,需先勾选再操作。

批量删除实现

监听表格 selection-change 事件获取选中行 ID,拼接后发送给后端。

handleDelete(type: string, id: string) {
  let param
  if (type === 'B' && this.multipleSelection.length === 0) {
    this.$message('请选择需要删除的套餐!')
    return
  }
  this.$confirm('确定删除该套餐?', '确定删除', {
    confirmButtonText: '删除',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    if (type === 'S') {
      param = id
    } else {
      const arr = new Array()
      this.multipleSelection.forEach(element => {
        arr.push(element.id)
      })
      param = arr.join(',')
    }
    deleteSetmeal(param).then(res => {
      if (res.data.code === 1) {
        this.$message.success('删除成功!')
        this.pageQuery()
      } else {
        this.$message.error(res.data.msg)
      }
    })
  })
}

新增套餐

功能需求

创建新套餐,关联菜品分类,设置售卖状态。

路由与组件

点击'新建套餐'跳转至 /setmeal/add,复用类似员工管理的表单逻辑,但数据结构不同。

核心逻辑

主要涉及套餐数据的提交与分类数据的联动。具体表单结构与员工新增类似,重点在于 setMeal 相关 API 的调用。


本文档涵盖了苍穹外卖系统前端的核心业务模块实现细节,从基础环境搭建到复杂 CRUD 操作,展示了 Vue 生态在企业级应用中的典型用法。

目录

  1. 前端环境搭建
  2. 技术选型
  3. 代码结构
  4. 环境准备
  5. 员工管理
  6. 分页查询
  7. 功能需求
  8. 页面头部构建
  9. 前后端数据交互
  10. 自动加载数据
  11. 表格展示
  12. 分页条实现
  13. 启用禁用员工账号
  14. 功能需求
  15. 按钮交互
  16. 状态变更逻辑
  17. 新增员工
  18. 功能需求
  19. 路由跳转
  20. 表单元素开发
  21. 表单校验规则
  22. 提交逻辑
  23. 修改员工
  24. 功能需求
  25. 路由传参
  26. 组件内判断
  27. 接口区分
  28. 按钮控制
  29. 套餐管理
  30. 套餐分页查询
  31. 功能需求
  32. 页面头部构建
  33. 动态填充分类数据
  34. 表格展示
  35. 启售停售套餐
  36. 功能需求
  37. 状态切换逻辑
  38. 删除套餐
  39. 功能需求
  40. 批量删除实现
  41. 新增套餐
  42. 功能需求
  43. 路由与组件
  44. 核心逻辑

更多推荐文章

查看全部
  • Elasticsearch 聚合查询报错 Fielddata is disabled 解决方案
  • Visual C++ 运行库缺失修复指南
  • LIBERO 数据集:终身机器人学习与知识迁移基准
  • Git 常用操作命令速查手册
  • OpenClaw 大龙虾机器人:本地部署与飞书对接实战
  • OpenClaw 本地 AI 助手部署与使用指南
  • 基于 Web 的药品商城设计与实现
  • 基于 brpc+MinIO 的分布式文件存储架构设计与实战
  • C++11 核心新特性解析:列表初始化、声明优化与右值引用
  • Python 结合 Excel 进行高效数据分析与处理指南
  • 知网 AIGC 检测未通过?三款降重工具实测分析
  • Apache SkyWalking 主流中间件集成实战:Spring Cloud、Dubbo、RocketMQ
  • 零钱兑换:动态规划经典问题深度解析
  • Pico 4XVR 1.10.13 安装包下载与安装教程
  • Java 集成 AI 能力实战:云端 API 与本地模型双方案
  • Python 开发环境搭建指南:从安装到配置
  • Spring Boot 前后端分离教室信息管理系统
  • 基于 SpringBoot 的人脸识别课堂考勤系统
  • 春晚机器人背后的 AI 大模型风口与职业机会
  • OpenClaw 本地安装与 Web UI 使用指南(macOS)

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online