# guli-admin **Repository Path**: strive_chen/guli-admin ## Basic Information - **Project Name**: guli-admin - **Description**: guli教育项目--前端 - **Primary Language**: JavaScript - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-11-06 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # guli-admin # 前端环境搭建 [vue-element-admin](https://panjiachen.github.io/vue-element-admin-site/zh/) ## 介绍 [vue-element-admin](http://panjiachen.github.io/vue-element-admin) 是一个后台前端解决方案,它基于 [vue](https://github.com/vuejs/vue) 和 [element-ui](https://github.com/ElemeFE/element)实现。它使用了最新的前端技术栈,内置了 i18 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。 建议 本项目的定位是后台集成方案,不太适合当基础模板来进行二次开发。因为本项目集成了很多你可能用不到的功能,会造成不少的代码冗余。如果你的项目不关注这方面的问题,也可以直接基于它进行二次开发。 - 集成方案: [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) - 基础模板: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template) - 桌面终端: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin) - Typescript 版: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (鸣谢: [@Armour](https://github.com/Armour)) - Others: [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312) ## 功能 ```text - 登录 / 注销 - 权限验证 - 页面权限 - 指令权限 - 权限配置 - 二步登录 - 多环境发布 - dev sit stage prod - 全局功能 - 国际化多语言 - 多种动态换肤 - 动态侧边栏(支持多级路由嵌套) - 动态面包屑 - 快捷导航(标签页) - Svg Sprite 图标 - 本地/后端 mock 数据 - Screenfull全屏 - 自适应收缩侧边栏 - 编辑器 - 富文本 - Markdown - JSON 等多格式 - Excel - 导出excel - 导入excel - 前端可视化excel - 导出zip - 表格 - 动态表格 - 拖拽表格 - 内联编辑 - 错误页面 - 401 - 404 - 組件 - 头像上传 - 返回顶部 - 拖拽Dialog - 拖拽Select - 拖拽看板 - 列表拖拽 - SplitPane - Dropzone - Sticky - CountTo - 综合实例 - 错误日志 - Dashboard - 引导页 - ECharts 图表 - Clipboard(剪贴复制) - Markdown2html ``` ## [#](https://panjiachen.github.io/vue-element-admin-site/zh/guide/#前序准备)前序准备 你需要在本地安装 [node](http://nodejs.org/) 和 [git](https://git-scm.com/)。本项目技术栈基于 [ES2015+](http://es6.ruanyifeng.com/)、[vue](https://cn.vuejs.org/index.html)、[vuex](https://vuex.vuejs.org/zh-cn/)、[vue-router](https://router.vuejs.org/zh-cn/) 、[vue-cli](https://github.com/vuejs/vue-cli) 、[axios](https://github.com/axios/axios) 和 [element-ui](https://github.com/ElemeFE/element),所有的请求数据都使用[Mock.js](https://github.com/nuysoft/Mock)进行模拟,提前了解和学习这些知识会对使用本项目有很大的帮助。 同时配套一个系列的教程文章,如何从零构建一个完整的管理后台项目,建议大家先看完这些文章再来实践本项目。 - [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2) - [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac) - [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35) - [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板)](https://juejin.im/post/595b4d776fb9a06bbe7dba56) - [手摸手,带你用 vue 撸后台 系列五(v4.0 新版本)](https://juejin.im/post/5c92ff94f265da6128275a85) - [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836) - [手摸手,带你优雅的使用 icon](https://juejin.im/post/59bb864b5188257e7a427c09) - [手摸手,带你用合理的姿势使用 webpack4(上)](https://juejin.im/post/5b56909a518825195f499806) - [手摸手,带你用合理的姿势使用 webpack4(下)](https://juejin.im/post/5b5d6d6f6fb9a04fea58aabc) **本项目不支持低版本浏览器(如 ie),有需求请自行添加 polyfill [详情](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)** ## [#](https://panjiachen.github.io/vue-element-admin-site/zh/guide/#目录结构)目录结构 本项目已经为你生成了一个完整的开发框架,提供了涵盖中后台开发的各类功能和坑位,下面是整个项目的目录结构。 ```bash ├── build # 构建相关 ├── mock # 项目mock 模拟数据 ├── plop-templates # 基本模板 ├── public # 静态资源 │ │── favicon.ico # favicon图标 │ └── index.html # html模板 ├── src # 源代码 │ ├── api # 所有请求 │ ├── assets # 主题 字体等静态资源 │ ├── components # 全局公用组件 │ ├── directive # 全局指令 │ ├── filters # 全局 filter │ ├── icons # 项目所有 svg icons │ ├── lang # 国际化 language │ ├── layout # 全局 layout │ ├── router # 路由 │ ├── store # 全局 store管理 │ ├── styles # 全局样式 │ ├── utils # 全局公用方法 │ ├── vendor # 公用vendor │ ├── views # views 所有页面 │ ├── App.vue # 入口页面 │ ├── main.js # 入口文件 加载组件 初始化等 │ └── permission.js # 权限管理 ├── tests # 测试 ├── .env.xxx # 环境变量配置 ├── .eslintrc.js # eslint 配置项 ├── .babelrc # babel-loader 配置 ├── .travis.yml # 自动化CI配置 ├── vue.config.js # vue-cli 配置 ├── postcss.config.js # postcss 配置 └── package.json # package.json ``` ## [#](https://panjiachen.github.io/vue-element-admin-site/zh/guide/#安装)安装 ```bash # 克隆项目 git clone https://github.com/PanJiaChen/vue-element-admin.git # 进入项目目录 cd vue-element-admin # 安装依赖 npm install # 建议不要用 cnpm 安装 会有各种诡异的bug 可以通过如下操作解决 npm 下载速度慢的问题 npm install --registry=https://registry.npm.taobao.org # 本地开发 启动项目 npm run dev ``` TIP 强烈建议不要用直接使用 cnpm 安装,会有各种诡异的 bug,可以通过重新指定 registry 来解决 npm 安装速度慢的问题。若还是不行,可使用 [yarn](https://github.com/yarnpkg/yarn) 替代 `npm`。 Windows 用户若安装不成功,很大概率是`node-sass`安装失败,[解决方案](https://github.com/PanJiaChen/vue-element-admin/issues/24)。 另外因为 `node-sass` 是依赖 `python`环境的,如果你之前没有安装和配置过的话,需要自行查看一下相关安装教程。 启动完成后会自动打开浏览器访问 [http://localhost:9527](http://localhost:9527/), 你看到下面的页面就代表操作成功了。 ![img](https://panjiachen.gitee.io/gitee-cdn/vue-element-admin-site/1bc334a6-32a8-4f29-a037-ac3f5ce32588.png) 接下来你可以修改代码进行业务开发了,本项目内建了典型业务模板、常用业务组件、模拟数据、HMR 实时预览、状态管理、国际化、全局路由等等各种实用的功能来辅助开发,你可以继续阅读和探索左侧的其它文档。 建议 你可以把 `vue-element-admin`当做工具箱或者集成方案仓库,在 `vue-admin-template` 的基础上进行二次开发,想要什么功能或者组件就去 `vue-element-admin` 那里复制过来。 # **一、前端登录问题** 默认情况下,前端项目已经实现了登录功能,后端连接到远程Mock平台的模拟数据接口进行登录,而Mock平台地址不稳定,导致有时模拟登录无法执行 ​ ![0](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/D2D2A252238F40F4BA277658EB631720/14379) # **二、Mock登录接口** 我们暂时将请求切换到本地Mock数据的接口中,使系统可以进行模拟登录,以便进行后续的开发工作 **1、修改前端接口配置** 我们暂时将请求切换到本地Mock数据的接口中,使系统可以进行模拟登录,以便进行后续的开发工作 ## 1、修改前端接口配置 在根目录vue.config.js 中修改devServer 注意:这个文件修改后需要重启前端服务器 ```javascript //修改前 devServer: { port: 8100, open: true, overlay: { warnings: false, errors: true }, before: require('./mock/mock-server.js') }, //修改后 devServer: { proxy: 'http://localhost:8110' }, ``` 在根目录.env.development修改 ```js # base api VUE_APP_BASE_API = '/' ``` ## 2、前端登录接口文件 src/api/login.js,可以在这个文件中分析后端Mock数据的接口的url地址: - 登录:/user/login - 登出:/user/logout - 获取用户信息:/user/info ## 3、后端接口文件 暂时在service_edu微服务中创建LoginController,模拟上面三个接口 ```java package com.bangdao; @CrossOrigin //跨域 @RestController @RequestMapping("/user") public class LoginController { /** * 登录 * @return */ @PostMapping("login") public R login() { return R.ok().data("token","admin"); } /** * 获取用户信息 * @return */ @GetMapping("info") public R info() { return R.ok() .data("roles","[admin]") .data("name","admin") .data("avatar","https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg"); } /** * 退出 * @return */ @PostMapping("logout") public R logout(){ return R.ok(); } } ``` # 三、axios响应拦截器 修改src/utils/request.js ## **1、关于响应码** code!==20000的响应会被拦截,并转到 error=>{} 处理 ```JavaScript if (res.code !== 20000) { Message({ message: res.message, type: 'error', duration: 5 * 1000 }) ...... return Promise.reject('error') } ``` ## 2、关于response code===20000时放行,前端页面接收到response.data的值,而不是response ```JavaScript if (res.code !== 20000) { ...... } else { return response.data } ``` ## 3、关于error 统一处理错误结果,显示错误消息 ```JavaScript error => { console.log('err' + error) // for debug Message({ message: error.message, type: 'error', duration: 5 * 1000 }) return Promise.reject(error) } ``` # 四、前端项目路由配置 ## **一、组件定义** ### 1、创建vue组件 在src/views文件夹下创建以下文件夹和文件 ![img](file:///D:/ProgramFiles/WizNote/笔记/temp/72dc4f61-da0a-453c-8f62-c5d50cac55c5/128/index_files/aee0810b-e6f2-4dae-a8b1-8fa43c1823a7.png) ### 2、form.vue ```javascript ``` ### 3、list.vue ```javascript ``` ## **二、路由定义** 修改 src/router/index.js 文件,重新定义constantRouterMap **注意:**每个路由的name不能相同 ```javascript export const constantRouterMap = [ { path: '/login', component: () => import('@/views/login/index'), hidden: true }, { path: '/404', component: () => import('@/views/404'), hidden: true }, { path: '/', component: Layout, redirect: '/dashboard', name: 'Dashboard', hidden: true, children: [{ path: 'dashboard', component: () => import('@/views/dashboard/index') }] }, // 讲师管理 { path: '/teacher', component: Layout, redirect: '/teacher/list', name: 'Teacher', meta: { title: '讲师管理' }, children: [ { path: 'list', name: 'TeacherList', component: () => import('@/views/teacher/list'), meta: { title: '讲师列表' } }, { path: 'create', name: 'TeacherCreate', component: () => import('@/views/teacher/form'), meta: { title: '添加讲师' } }, { path: 'edit/:id', name: 'TeacherEdit', component: () => import('@/views/teacher/form'), meta: { title: '编辑讲师' }, hidden: true } ] }, { path: '*', redirect: '/404', hidden: true } ] ``` ## 三、其他 ### 1、端口号 在 config/index.js中修改 ``` port: 9528, ``` ### 2、国际化设置 src/main.js,第7行,修改语言为 zh-CN,使用中文语言环境,例如:日期时间组件 ```javascript import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n ``` ### 3、入口页面 index.html ``` 谷粒学院后台管理系统 ``` ### **4、登录页** src/views/login/index.vue,第4行 ```javascript

谷粒学院后台管理系统

``` # 五、前端项目开发流程 ## 一、项目开发流程 ![http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/70D771118DD24C0F9E0D6D8674352844/14446](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/70D771118DD24C0F9E0D6D8674352844/14446) ### 1、定义路由模块 src/router/index.js 配置讲师管理相关路由 ### 2、定义api模块 创建文件 src/api/teacher.js ```js // @ 符号在build/webpack.base.conf.js 中配置 表示 'src' 路径 import request from '@/utils/request' export default { list() { return request({ url: '/admin/edu/teacher/list', method: 'get' }) } } ``` ### **3、定义页面组件脚本** src/views/teacher/list.vue ```js ``` ### **4、定义页面组件模板** ```js ``` ## 二、项目执行流程 ### 1、页面加载流程 ![0](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/96416861CBD44F229F0C74F2090CF896/14444) ### **2、页面渲染流程** ​ ![0](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/A64E330055CC4754B01B28D996204009/14445) ### 3、**添加Vue.js devtools插件** 插件下载地址:https://wwx.lanzoux.com/iPvaHi4lb6f ![img](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/0DB74D069B294C5EA31317FBAA0DB04A/14493) ![http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/0F4543C7C61E4B10B27B4F41A506BF15/14506](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/0F4543C7C61E4B10B27B4F41A506BF15/14506) ![http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/6F929A48E71B4156A9CCD8A9A0E9BD6F/14513](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/6F929A48E71B4156A9CCD8A9A0E9BD6F/14513) ## 三、分页列表组件 ### 一、分页查询 #### 1、定义api模块 src/api/teacher.js ```js pageList(page, limit, searchObj) { return request({ url: `/admin/edu/teacher/list/${page}/${limit}`, method: 'get', params: searchObj }) } ``` #### 2、定义页面组件脚本 src/views/teacher/list.vue,完善data定义 ```js // 定义数据模型 data() { return { list: [], // 讲师列表 total: 0, // 总记录数 page: 1, // 页码 limit: 10, // 每页记录数 searchObj: {}// 查询条件 } } ``` 修改fetchData方法 ```js fetchData() { // 调用api teacherApi.pageList(this.page, this.limit, this.searchObj).then(response => { this.list = response.data.pageModel.records this.total = response.data.pageModel.total }) } ``` #### 3、定义页面组件模板 在list.vue/table组件下面添加分页组件 ```js ``` #### **4、改变每页条数** 为组件注册事件 ```js @size-change="changePageSize" ``` 定义事件脚本 ```js // 每页记录数改变,size:回调参数,表示当前选中的“每页条数” changePageSize(size) { this.limit = size this.fetchData() } ``` 5、翻页 为组件注册事件 ```js @current-change="changeCurrentPage" ``` 定义事件脚本 ```js // 改变页码,page:回调参数,表示当前选中的“页码” changeCurrentPage(page) { this.page = page this.fetchData() }, ``` 6、序号列 ```js ``` 7、查询表单 在table组件上面添加查询表单 ```js 查询 清空 ``` 重置表单脚本 ```js // 重置表单 resetData() { this.searchObj = {} this.fetchData() } ``` ### 二、数据删除 #### 1、定义api模块 src/api/teacher.js ```js removeById(id) { return request({ url: `/admin/edu/teacher/remove/${id}`, method: 'delete' }) } ``` #### 2、定义页面组件模板 在table组件中添加删除列 ```js ``` #### 3、定义页面组件脚本 ```js // 根据id删除数据 removeById(id) { this.$confirm('此操作将永久删除该记录, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { return teacherApi.removeById(id) }).then((response) => { this.fetchData() this.$message.success(response.message) }).catch(error => { console.log('error', error) // 当取消时会进入catch语句:error = 'cancel' // 当后端服务抛出异常时:error = 'error' if (error === 'cancel') { this.$message.info('取消删除') } }) } ``` # 六、新增讲师 ### 1、定义api模块 src/api/teacher.js ```js save(teacher) { return request({ url: '/admin/edu/teacher/save', method: 'post', data: teacher }) } ``` ### 2、定义页面组件脚本 src/views/teacher/form.vue,完善data定义 ```js ``` ### 3、定义页面组件模板 src/views/teacher/form.vue ```js 保存 ``` ### 4、实现新增功能 src/views/teacher/form.vue,引入teacher api模块: ```js import teacherApi from '@/api/teacher' ``` 定义保存方法 ```js methods: { saveOrUpdate() { // 禁用保存按钮 this.saveBtnDisabled = true this.saveData() }, // 新增讲师 saveData() { // debugger teacherApi.save(this.teacher).then(response => { this.$message({ type: 'success', message: response.message }) this.$router.push({ path: '/teacher' }) }) } } ``` ## 二、显示讲师信息 ### 1、定义api模块 src/api/teacher.js ```js getById(id) { return request({ url: `/admin/edu/teacher/get/${id}`, method: 'get' }) } ``` ### 2、定义页面组件脚本 src/views/teacher/form.vue,methods中定义回显方法 ```js // 根据id查询记录 fetchDataById(id) { teacherApi.getById(id).then(response => { this.teacher = response.data.item }) } ``` 页面渲染成功后获取数据 因为已在路由中定义如下内容:path: 'edit/:id',因此可以使用 this.$route.params.id 获取路由中的id ```js //页面渲染成功 created() { if (this.$route.params.id) { this.fetchDataById(this.$route.params.id) } } ``` ### 3、定义页面组件模板 src/views/teacher/list.vue,表格“操作”列中增加“修改”按钮 ```js 修改 ``` ## 三、更新讲师 ### 1、定义api模块 src/api/teacher.js ```js updateById(teacher) { return request({ url: '/admin/edu/teacher/update', method: 'put', data: teacher }) } ``` ### 2、定义页面组件脚本 src/views/teacher/form.vue,methods中定义updateData ```js // 根据id更新记录 updateData() { // teacher数据的获取 teacherApi.updateById(this.teacher).then(response => { this.$message({ type: 'success', message: response.message }) this.$router.push({ path: '/teacher' }) }) }, ``` 完善saveOrUpdate方法 ```js saveOrUpdate() { // 禁用保存按钮 this.saveBtnDisabled = true if (!this.teacher.id) { this.saveData() } else { this.updateData() } } ``` ## 四、组件重用问题 **问题:**vue-router导航切换 时,如果两个路由都渲染同个组件, 组件的生命周期方法(created或者mounted)不会再被调用, 组件会被重用,显示上一个路由渲染出来的自建 **解决方案:**可以简单的在 router-view上加上一个唯一的key,来保证路由切换时都会重新触发生命周期方法,确保组件被重新初始化。 修改 src/views/layout/components/AppMain.vue 文件如下: ```js ``` ```jsp computed: { key() { return this.$route.name !== undefined? this.$route.name + +new Date(): this.$route + +new Date() } } ``` # 七、关于Vue组件 ## **一、什么是组件** 组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用界面都可以抽象为一个组件树: ​ ![0](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/6BA2583E92614C719ACD6AC397F0B476/14487) ## **二、前端项目组件分析** **1、三要素** - 入口js:src/main.js - 入口页面:src/App.vue - 路由:src/router/index.js main.js 中引入了App.vue和 router/index.js,根据路由配置,App.vue中会显示相应的页面内容 **2、入口文件** src/main.js ​ ![0](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/41CC2CF898B848FAB875D374FA5683D5/14482) **3、主页面模块** src/App.vue ​ ![0](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/6C16172F2F444E5BB52A3064F1E4D8AA/14485) **4、路由模块** src/router/index.js ​ ![0](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/35D0C00201124635B8D388D7006FD06A/14480) **5、登录页面组件** ​ ![0](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/14114D9483B84443AE3176C08194693C/14488) ## **三、前端项目布局分析** **1、路由模块** src/router/index.js ​ ![0](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/F289EF36BAD24BE89EEC1D0B2C817618/14481) **2、布局模块** src/views/layout/Layout.vue ​ ![0](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/7772E8BEDFF142ECA5B34103A789C17F/14483) **3、核心内容区域** src/views/layout/components/AppMain.vue ​ ![0](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/E1E9E57BC12A4DA9A81E85BF44F4C91D/14486) **4、讲师列表页面组件** ​ ![0](http://note.youdao.com/yws/public/resource/059bd8aed0b8fef9bffd297532e98896/xmlnote/6AA79AAF4E2F4F0A8B52351F6E127204/14484) # 八-前端整合上传组件 ## **一、前端组件参考** https://element.eleme.cn/2.4/#/zh-CN/component/upload ![img](file:///D:/ProgramFiles/WizNote/笔记/temp/b00ad669-47cc-490a-b4d9-2334a2f6f50e/128/index_files/0f387b50-cd7e-4827-b28f-938903677607.png) ## **二、整合上传组件** ### 1、定义页面组件模板 src/views/teacher/form.vue:参考案例文档 ```js ``` css:参考案例文档 加上scoped,这样 css 就只会作用在当前组件内 ```js ``` ### 2、定义页面组件脚本 ```js // 上传成功回调 handleAvatarSuccess(res, file) { // console.log(res) this.teacher.avatar = res.data.url // 强制重新渲染 this.$forceUpdate() }, // 上传校验 beforeAvatarUpload(file) { const isJPG = file.type === 'image/jpeg' const isLt2M = file.size / 1024 / 1024 < 2 if (!isJPG) { this.$message.error('上传头像图片只能是 JPG 格式!') } if (!isLt2M) { this.$message.error('上传头像图片大小不能超过 2MB!') } return isJPG && isLt2M } ``` ## 三、自定义异常 ### **一、文件上传异常分析** #### 1、制造异常 将application.yml文件中的keyId改成错误的值,运行程序,执行上传阿里云sdk内部会抛出异常,并打印相关错误日志 #### 2、异常处理方案 方案1:异常处理器中捕获相关异常 方案2:自定义异常,异常处理器中捕获自定义异常 ### **二、自定义异常处理** #### 1、创建自定义异常类 service-base模块中创建com.atguigu.guli.service.base.exception包, 创建GuliException.java通用异常类 继承 RuntimeException,RuntimeException 对代码没有侵入性 ```java package com.bangdao.exception; @Data public class GuliException extends RuntimeException { //状态码 private Integer code; /** * 接受状态码和消息 * @param code * @param message */ public GuliException(Integer code, String message) { super(message); this.code=code; } /** * 接收枚举类型 * @param resultCodeEnum */ public GuliException(ResultCodeEnum resultCodeEnum) { super(resultCodeEnum.getMessage()); this.code = resultCodeEnum.getCode(); } } ``` #### 2、添加异常处理方法 GlobalExceptionHandler.java中添加 ```java @ExceptionHandler(GuliException.class) @ResponseBody public R error(GuliException e){ log.error(ExceptionUtils.getStackTrace(e)); return R.error().message(e.getMessage()).code(e.getCode()); } ``` #### 3、修改FileController 在类上添加日志注解 ```java @Slf4j ``` 业务中需要的位置抛出GuliException ```java public R upload(...) { try { ...... } catch (Exception e){ log.error(ExceptionUtils.getStackTrace(e)); throw new GuliException(ResultCodeEnum.FILE_UPLOAD_ERROR); } } ``` #### 4、打印完整的异常信息 GuliException类中重写toString方法 ```java @Override public String toString() { return "GuliException{" + "code=" + code + ", message=" + this.getMessage() + '}'; } ``` ### **三、****前端错误处理** #### 1、统一异常错误处理 ```json // 上传成功回调 handleAvatarSuccess(res, file) { console.log(res) if (res.success) { // console.log(res) this.teacher.avatar = res.data // 强制重新渲染 this.$forceUpdate() } else { this.$message.error('上传失败 (非0)') } }, ``` #### 2、http异常错误处理 注册事件 ```js ``` 事件函数 ```js // 错误处理 handleAvatarError() { console.log('error') this.$message.error('上传失败(http失败)') } ``` ## 四、批量删除 ### 一、后端接口 TeacherController ```java @ApiOperation("根据id列表删除讲师") @DeleteMapping("batch-remove") public R removeRows( @ApiParam(value = "讲师id列表", required = true) @RequestBody List idList){ boolean result = teacherService.removeByIds(idList); if(result){ return R.ok().message("删除成功"); }else{ return R.error().message("数据不存在"); } } ``` 测试Json列表数据格式 ![img](file:///D:/ProgramFiles/WizNote/笔记/temp/c1ecc881-b379-480e-b4f4-aa21496d39c7/128/index_files/f7eec65b-f6f2-4a1f-b46d-a91436b58fb9.png) ### 二、前端 #### 1、api teacher.js ```java batchRemove(idList) { return request({ url: '/admin/edu/teacher/batch-remove', method: 'delete', data: idList }) } ``` #### 2、添加删除复选框 views/teacher/list.vue ```js ``` #### 3、添加删除按钮 ```js
批量删除
``` #### 4、定义删除方法 ```js batchRemove() { } ``` #### 5、data中定义数据 ```js multipleSelection: []// 批量删除选中的记录列表 ``` #### 6、表格组件中添加事件 ```js @selection-change="handleSelectionChange" ``` #### 7、定义事件的回调函数 ```js // 当多选选项发生变化的时候调用 handleSelectionChange(selection) { console.log(selection) this.multipleSelection = selection } ``` #### 8、完善removeRows方法 ```js // 批量删除 batchRemove() { console.log('removeRows......') if (this.multipleSelection.length === 0) { this.$message.warning('请选择要删除的记录!') return } this.$confirm('此操作将永久删除该记录, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { // 点击确定,远程调用ajax // 遍历selection,将id取出放入id列表 var idList = [] this.multipleSelection.forEach(item => { idList.push(item.id) }) // 调用api return teacherApi.batchRemove(idList) }).then((response) => { this.fetchData() this.$message.success(response.message) }).catch(error => { if (error === 'cancel') { this.$message.info('取消删除') } }) } ``` ## 五、自动完成 ### 一、后端接口 #### 1、TeacherController ```java @ApiOperation("根据左关键字查询讲师名列表") @GetMapping("list/name/{key}") public R selectNameListByKey( @ApiParam(value = "查询关键字", required = true) @PathVariable String key){ List> nameList = teacherService.selectNameListByKey(key); return R.ok().data("nameList", nameList); } ``` #### 2、TeacherService 接口 ```java List> selectNameListByKey(String key); ``` 实现 ```java @Override public List> selectNameListByKey(String key) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.select("name"); queryWrapper.likeRight("name", key); List> list = baseMapper.selectMaps(queryWrapper);//返回值是Map列表 return list; } ``` ## 六、前端整合 ### 1、api teacher.js ```js selectNameListByKey(key) { return request({ url: `/admin/edu/teacher/list/name/${key}`, method: 'get' }) } ``` ### 2、组件 views/teacher/list.vue **注意: value-key="name" 的设置** ```js ``` 脚本 ```js querySearch(queryString, cb) { teacherApi.selectNameListByKey(queryString).then(response => { cb(response.data.nameList) }) } ```