资料
资料地址
后台管理系统目录 前台展示系统目录
1 - 构建工程篇 7 - 渲染前台篇
2 - 前后交互篇 8 - 前台登录篇
3 - 文件上传篇 9 - 前台课程篇
4 - 课程管理篇 10 - 前台支付篇
5 - 章节管理篇 11 - 统计分析篇
6 - 微服务治理 12 - 项目完结篇

目录

  • 一、搭建前端工程
    • 1.1、测试启动
    • 1.2、目录结构
    • 1.3、配置环境
  • 二、后台系统登录功能
    • 2.1、分析登录流程代码
    • 2.2、编写接口
  • 三、讲师模块的前端实现
    • 3.1、路由视图及测试讲师列表接口
    • 3.2、渲染讲师列表
    • 3.3、分页功能实现
    • 3.4、多条件查询功能
    • 3.5、讲师删除
    • 3.6、讲师添加
    • 3.7、讲师修改-回显数据
    • 3.8、讲师修改
    • 3.9、bug解决

一、搭建前端工程

1.1、测试启动

1、从资料中解压 vue-element-admin 修改为 gulicollege_ui

2、安装依赖 npm install (安装太慢了直接放弃)

2、从资料中拷贝 node_modules 文件夹到项目中 并执行如下安装依赖

npm install node-sassnpm i node-sass -Dnpm install --save element-ui

3、启动 npm run dev


1.2、目录结构

.
├── build   // 构建脚本
├── config  // 全局配置
├── node_modules // 项目依赖模块
├── src     //项目源代码
├── static  // 静态资源
└── package.jspon // 项目信息和依赖配置
src
├── api         // 各种接口
├── assets      // 图片等资源
├── components  // 各种公共组件,非公共组件在各自view下维护
├── icons       //svg icon
├── router      // 路由表
├── store       // 存储
├── styles      // 各种样式
├── utils       // 公共工具,非公共工具,在各自view下维护
├── views       // 各种layout
├── App.vue     //***项目顶层组件***
├── main.js     //***项目入口文件***
└── permission.js //认证入口

1.3、配置环境

1、package.json

{"name": "gulicollege_ui","version": "3.8.0","license": "MIT","description": "谷粒学院后台管理系统","author": "Laptoy",
}

2、config/index.js 配置端口号

port: 9528

3、config/index.js 关闭语法检查

useEslint: false

4、config/dev.env.js 修改为访问后台端口

BASE_API: '"http://localhost:8001"',

二、后台系统登录功能

2.1、分析登录流程代码

1、src/views/login/index.vue

methods: {handleLogin() {this.$refs.loginForm.validate(valid => {if (valid) {this.loading = true// 触发 store 的 Login事件this.$store.dispatch('Login', this.loginForm).then(() => {this.loading = falsethis.$router.push({ path: this.redirect || '/' })}).catch(() => {this.loading = false})} else {console.log('error submit!!')return false}})}
}

2、src/store/modules/user.js (这里没有使用 namespaces: true) 所以不需要通过命名空间调用

import { login, logout, getInfo } from '@/api/login'actions: {// 登录Login({ commit }, userInfo) {const username = userInfo.username.trim()return new Promise((resolve, reject) => {login(username, userInfo.password).then(response => {const data = response.datasetToken(data.token)commit('SET_TOKEN', data.token)resolve()}).catch(error => {reject(error)})})},
}

3、src/api/login.js (通过 axios 发送请求)

import request from '@/utils/request'export function login(username, password) {return request({url: '/user/login',method: 'post',data: {username,password}})
}

4、src/utils/request.js (封装 axios 调用)

import axios from 'axios'
import { Message, MessageBox } from 'element-ui'
import store from '../store'
import { getToken } from '@/utils/auth'// 创建axios实例
const service = axios.create({baseURL: process.env.BASE_API, // api 的 base_urltimeout: 5000 // 请求超时时间
})// request拦截器
service.interceptors.request.use(config => {if (store.getters.token) {config.headers['X-Token'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改}return config},error => {// Do something with request errorconsole.log(error) // for debugPromise.reject(error)}
)// response 拦截器
service.interceptors.response.use(response => {/*** code为非20000是抛错 可结合自己业务进行修改*/const res = response.dataif (res.code !== 20000) {Message({message: res.message,type: 'error',duration: 5 * 1000})// 50008:非法的token; 50012:其他客户端登录了;  50014:Token 过期了;if (res.code === 50008 || res.code === 50012 || res.code === 50014) {MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录','确定登出',{confirmButtonText: '重新登录',cancelButtonText: '取消',type: 'warning'}).then(() => {store.dispatch('FedLogOut').then(() => {location.reload() // 为了重新实例化vue-router对象 避免bug})})}return Promise.reject('error')} else {return response.data}},error => {console.log('err' + error) // for debugMessage({message: error.message,type: 'error',duration: 5 * 1000})return Promise.reject(error)}
)export default service

2.2、编写接口

根据前端代码分析

1、登录请求需要返回 token

2、获取用户信息请求需要返回 roles、name、avatar


1、EduLoginController (使用 @CrossOrigin 解决跨域问题

@Api(tags = "登录模块")
@RestController
@CrossOrigin //解决跨域问题
@RequestMapping("/eduservice/user")
public class EduLoginController {// 登录@PostMapping("/login")public R login() {return R.ok().data("token", "admin");}// 获取信息@GetMapping("/info")public R info() {return R.ok().data("roles", "admin").data("name", "Laptoy").data("avatar", "https://img-blog.csdnimg.cn/480b7a82bddb4f6a9b6942c88db18d85.png");}// 登出@PostMapping("/logout")public R logOut() {return R.ok();}
}

2、修改 src/api/login.js 匹配后端接口


三、讲师模块的前端实现

3.1、路由视图及测试讲师列表接口

1、添加路由 - src/router/index.js

// 讲师模块路由
{path: '/teacher',component: Layout,redirect: '/teacher/table',name: '讲师管理',meta: { title: '讲师管理', icon: 'example' },children: [{path: 'table',name: '讲师列表',component: () => import('@/views/edu/teacher/list.vue'),meta: { title: '讲师列表', icon: 'table' }},{path: 'save',name: '添加讲师',component: () => import('@/views/edu/teacher/save.vue'),meta: { title: '添加讲师', icon: 'tree' }}]
},

2、创建路由对应组件

  • 创建文件夹 src/views/edu/teacher
  • 创建 list.vuesave.vue 组件

3、定义访问的接口地址

在src/api文件创建 teacher/teacher.js 定义访问的接口地址

import request from '@/utils/request'export default {// 1、获取讲师列表(多条件分页查询)getTeacherListPage(page, limit, teacherQuery) {return request({url: `/eduservice/teacher/pageTeacherCondition/${page}/${limit}`,method: 'post',data: teacherQuery})}
}

4、组件页面调用定义接口方法 - list.vue

<template><div class="app-container">讲师列表</div>
</template><script>
import teacher from '@/api/teacher/teacher.js'export default {data() {return {list: null, // 查询之后给接口返回的数据装的集合page: 1, // 当前页limit: 5, // 每页显示记录数teacherQuery: {}, // 条件封装对象total: 0 // 总记录数}},created() {this.getList()},methods: {// 获取讲师列表getList() {teacher.getTeacherListPage(this.page, this.limit, this.teacherQuery).then((resp) => {this.list = resp.data.dataconsole.log(this.list)this.total = resp.data.totalconsole.log(this.total)}).catch((err) => {console.log(err)})}}
}
</script>

5、测试


3.2、渲染讲师列表

1、ui

<template><div><el-table :data="list" style="width: 100%" border fit highlight-current-row element-loading-text="数据加载中"><el-table-column prop="date" label="序号" width="70" align="center"><template slot-scope="scope">{{ (page - 1) * limit + scope.$index + 1 }}</template></el-table-column><el-table-column prop="name" label="名称" width="80" /><el-table-column label="头衔" width="80"><template slot-scope="scope">{{ scope.row.level === 1 ? "高级讲师" : "首席讲师" }}</template></el-table-column><el-table-column prop="intro" label="资历" /><el-table-column prop="gmtCreate" label="添加时间" width="160" /><el-table-column prop="sort" label="排序" width="60" /><el-table-column label="操作" width="200" align="center"><template slot-scope="scope"><router-link :to="'/edu/teacher/edit/' + scope.row.id"><el-button type="primary" size="mini" icon="el-icon-edit">修改</el-button></router-link><el-button type="danger" size="mini" icon="el-icon-delete" @click="removeDataById(scope.row.id)">删除</el-button></template></el-table-column></el-table></div>
</template>

2、展示


3.3、分页功能实现

1、ui

<div><el-table></el-table><el-pagination :total="total" :page-size="limit" :current-page="page" background layout="prev, pager, next,total,jumper" style="padding: 30px 0; text-align: center" @current-change="getList" />
</div>

2、方法

3、展示


3.4、多条件查询功能

1、ui

<!--多条件查询表单-->
<el-form :inline="true" class="demo-form-inline" style="margin-left: 20px; margin-top: 12px;"><el-form-item label="名称"><el-input v-model="teacherQuery.name" placeholder="请输入名称"></el-input></el-form-item><el-form-item label="级别"><el-select v-model="teacherQuery.level" placeholder="讲师头衔"><el-option label="高级讲师" :value="1"></el-option><el-option label="特级讲师" :value="2"></el-option></el-select></el-form-item><el-form-item label="添加时间"><el-time-picker placeholder="选择开始时间" v-model="teacherQuery.begin" value-format="yyyy-MM-dd HH:mm:ss" default-time="00:00:00" type="datetime"></el-time-picker</el-form-item><el-form-item><el-time-picker placeholder="选择截止时间" v-model="teacherQuery.end" value-format="yyyy-MM-dd HH:mm:ss" default-time="00:00:00" type="datetime"></el-time-picker></el-form-item><el-form-item><el-button type="primary" icon="el-icon-search" @click="getList()">查询</el-button><el-button type="default" @click="resetData()">清空</el-button></el-form-item>
</el-form>

2、方法

export default {methods: {// 清空查询栏resetData() {// 表单输入项数据清空this.teacherQuery = {};// 查询所有讲师数据this.getList();},}
}

3、展示


3.5、讲师删除

1、定义API - src/api/teacher/teacher.js

export default { ...// 2、根据id删除讲师removeById(id) {return request({url: `/eduservice/teacher/deleteTeacherById/${id}`,method: 'delete',})}
}

2、定义 methods

// 根据id删除讲师
removeDataById(id) {this.$confirm("此操作将永久删除该讲师记录, 是否继续?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {teacher.removeById(id).then((resp) => {this.$message({type: "success",message: "删除成功!",});//刷新页面this.getList();});});
}

3.6、讲师添加

1、定义API

// 添加讲师
saveTeacher(teacher) {return request({url: `/eduservice/teacher/save`,method: `post`,data: teacher})
}

2、初始化 save.vue 组件

<template><div class="app-container"><el-form label-width="120px"><el-form-item label="讲师名称"><el-input v-model="teacher.name" /></el-form-item><el-form-item label="讲师排序"><el-input-number v-model="teacher.sort" controls-position="right" :min="0" /></el-form-item><el-form-item label="讲师头衔"><el-select v-model="teacher.level" clearable placeholder="选择讲师头衔"><el-option :value="1" label="高级讲师" /><el-option :value="2" label="首席讲师" /></el-select></el-form-item><el-form-item label="讲师资历"><el-input v-model="teacher.career" placeholder="职业生涯、获得的证书、其他含金量的经历" /></el-form-item><el-form-item label="讲师简介"><el-input v-model="teacher.intro" :rows="3" type="textarea" /></el-form-item><!-- 讲师头像:TODO --><el-form-item><el-button :disabled="saveBtnDisabled" type="primary" @click="saveOrUpdate">保存</el-button></el-form-item></el-form></div>
</template><script>
//引入对应的新增api方法
import teacherApi from "@/api/teacher/teacher.js";export default {data() {return {teacher: {name: "",sort: 0,level: 1,career: "",intro: "",avatar: "",},saveBtnDisabled: false, // 保存按钮是否禁用,};},methods: {saveOrUpdate() {this.saveBtnDisabled = true; // 防止表单多次提交,保存后就禁用按钮this.saveData();},// 保存saveData() {teacherApi.saveTeacher(this.teacher).then((resp) => {//添加成功//提示信息this.$message({message: "添加讲师记录成功",type: "success",});//回到讲师列表 路由跳转this.$router.push({ path: '/teacher/table' })});},},
};
</script>

3、展示


3.7、讲师修改-回显数据

1、添加路由 - 实际上以保存组件作为模板跳转

// 讲师模块路由
{path: '/teacher',...children: [...{path: 'edit/:id',name: '修改讲师',component: () => import('@/views/edu/teacher/save.vue'),meta: { title: '修改讲师', noCache: true },hidden: true}]
},

2、list.vue - 通过路由携带id进行修改

3、定义API 根据id查询信息

//根据id查询讲师
updateById(id) {return request({url: `/eduservice/teacher/getById/${id}`,method: `get`,})
}

4、根据id回显信息 - save.vue

// 修改请求--根据id回显信息
getInfoById(id) {teacherApi.updateById(id).then(resp => {this.teacher = resp.data.data})
}

5、钩子函数添加判断

created() {// 判断路由跳转时是否携带参数if (this.$route.params && this.$route.params.id) {this.getInfoById(this.$route.params.id)}
}

6、展示 - 点击修改后数据回显


3.8、讲师修改

1、定义API

// 修改讲师信息
updateTeacherInfo(teacher) {return request({url: `/eduservice/teacher/updateById`,method: `post`,data: teacher})
}

2、修改方法 - save.vue

// 修改请求--修改讲师信息
updateTeacher() {teacherApi.updateTeacherInfo(this.teacher).then((resp) => {this.$message({message: "修改讲师记录成功",type: "success",});this.$router.push({ path: "/teacher/table" });});
}

3、区分新增或修改请求(通过路由跳转是否携带id进行判断)

saveOrUpdate() {if (!this.teacher.id) {//没有id值,做【新增操作】this.saveBtnDisabled = true; // 只能点击一次保存操作,防止表单多次保存this.saveData();} else {//有id值,做【修改操作】this.updateTeacher()}
},

3.9、bug解决

场景

  • 用户点击修改按钮后不想修改了反而想添加讲师
  • 点击添加讲师按钮,此时表单数据未清空

  1. 将 回显数据流程 封装为 init()方法(当路由中有id时回显数据,没有就清空表单)
  2. 通过 watch属性 观察路由是否发生变化,变化那就重新执行 init() 进行页面加载

旧代码

created() {// 判断路由跳转时是否携带参数if (this.$route.params && this.$route.params.id) {this.getInfoById(this.$route.params.id)}
}

优化后

methods: {...// 初始化页面init() {if (this.$route.params && this.$route.params.id) {this.getInfoById(this.$route.params.id)} else {this.teacher = {};}},
},
created() {this.init();
},
watch: {// 当路由发生变化时初始化页面$route(to, from) {this.init();}
}

2022年最新《谷粒学院开发教程》:2 - 前后端交互篇相关推荐

  1. 2022年最新《谷粒学院开发教程》:9 - 前台课程模块

    资料 资料地址 后台管理系统目录 前台展示系统目录 1 - 构建工程篇 7 - 渲染前台篇 2 - 前后交互篇 8 - 前台登录篇 3 - 文件上传篇 9 - 前台课程篇 4 - 课程管理篇 10 - ...

  2. 2022年最新《谷粒学院开发教程》:5 - 章节管理

    资料 资料地址 后台管理系统目录 前台展示系统目录 1 - 构建工程篇 7 - 渲染前台篇 2 - 前后交互篇 8 - 前台登录篇 3 - 文件上传篇 9 - 前台课程篇 4 - 课程管理篇 10 - ...

  3. 2022年最新《谷粒学院开发教程》:4 - 课程管理

    资料 资料地址 后台管理系统目录 前台展示系统目录 1 - 构建工程篇 7 - 渲染前台篇 2 - 前后交互篇 8 - 前台登录篇 3 - 文件上传篇 9 - 前台课程篇 4 - 课程管理篇 10 - ...

  4. 三维电子沙盘 三维数字虚拟沙盘 开发教程第39课 交互触摸查询面板的调用

    三维电子沙盘 三维数字虚拟沙盘 开发教程第39课 交互触摸查询面板的调用 查询面板调用: private void Button_Click_11(object sender, RoutedEvent ...

  5. 前后端解析_好程序员Web前端教程分享前后端分离接口

    随着互联网的高速发展以及IT开发技术的升级,前后端分离已成为互联网项目开发的业界标准使用方式.在实际工作中,前后端的接口联调对接工作量占Web前端人员日常工作的30%-50%,甚至会更高.接下来的好程 ...

  6. 运维开发笔记整理-前后端分离

    运维开发笔记整理-前后端分离 作者:尹正杰  版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.为什么要进行前后端分离 1>.pc, app, pad多端适应 2>.SPA开发式的流 ...

  7. 前后端混合开发模式和前后端分离开发模式

    前后端混合开发模式和前后端分离开发模式 一.前后端混合开发模式 二.前后端分离开发模式

  8. uniapp简单搞定支付传统的开发支付需要前后端做很多工作,各种参数的处理,签名,秘钥的验证校验等,尤其是涉及到多种不同的平台支付,更是繁琐;而且以往的支付是由后端主导的,如果后端是个菜鸡,那么做这

    uniapp简单搞定支付 传统的开发支付需要前后端做很多工作,各种参数的处理,签名,秘钥的验证校验等,尤其是涉及到多种不同的平台支付,更是繁琐:而且以往的支付是由后端主导的,如果后端是个菜鸡,那么做这 ...

  9. cbnertvirtual内部框架下载_快速开发,支持前后端分离,微服务框架

    JeecgBoot JeecgBoot是一款基于BPM的低代码平台,零代码开发!采用前后端分离架构,支持微服务: SpringBoot 2.x,Ant Design&Vue,Mybatis-p ...

  10. 【系】微信小程序云开发实战坚果商城-前后端交互之订单实现

    第 4-7 课:前后端交互之订单实现 目录 开篇 [系]微信小程序云开发实战坚果商城-开篇 基础篇 [系]微信小程序云开发实战坚果商城-弹性盒子 [系]微信小程序云开发实战坚果商城-ES6 简单入门 ...

最新文章

  1. jQuery框架学习第二天:jQuery中万能的选择器
  2. 问题解决:Apache: You don't have permission to access / on this server
  3. html层次选择器例题,JQuery 层次选择器的例子
  4. CodeForces - 850C Arpa and a game with Mojtaba(博弈+sg函数)
  5. php上传图片文件常用的几个方法
  6. LINUX下载编译ncurses
  7. python调用matlab
  8. Java实现两个文件夹之间的同步(改进版)
  9. 基于R语言的贝叶斯网络模型、现代贝叶斯统计学方法
  10. 【OS学习笔记】二 汇编语言和汇编软件
  11. Python 自动获取 Bing 壁纸
  12. Unity 游戏入门 九、 精灵动画 Sprite Animation
  13. 在顺丰的历史上,扩大规模的资金来源
  14. 局域网不能访问的问题
  15. Python数据分析练习:北京、广州PM2.5空气质量分析(2)
  16. 2015php网址导航源码,114啦网址导航源码评测 114啦网址导航下载
  17. Golang优秀开源项目汇总(持续更新。。。)
  18. python剪切文件
  19. Java+SSH人力资源管理系统(含源码+论文+答辩PPT等)
  20. WordPress自定义简码制作写法

热门文章

  1. hfss仿真软件入门教程
  2. MFC学习心得第一篇
  3. navicat for mysql 破解版 中文免费
  4. 一个贼简单的代码表白
  5. 【技术分享】H5小游戏开发入门指南
  6. C语言进制转换相关函数
  7. matlab程序转成可执行文件,matlab程序如何生成可执行文件
  8. java关闭窗口的6种方法
  9. 《Java语言程序设计》(基础篇原书第10版)第四章复习题答案
  10. 从零开始学习makefile(7) makefile的filter的作用