day05项目【讲师管理模块前端开发】

改造登录到本地接口


一、跨域配置

1、什么是跨域

浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域 。前后端分离开发中,需要考虑ajax跨域的问题。

这里我们可以从服务端解决这个问题

2、配置

在Controller类上添加注解

@CrossOrigin//跨域


01-项目中的路由

一、后台系统路由实现分析

1、入口文件中调用路由

src/main.js

......

import router from './router'//引入路由模块

......

newVue({

    el:'#app',

    router,//挂载路由

    store,

    render:h=>h(App)

})

2、路由模块中定义路由

src/router/index.js

......

export const constantRouterMap=[

    ......

]

export default new Router({

    ......

    routes:constantRouterMap

})

二、路由定义

1、复制icon图标

将vue-element-admin/src/icons/svg 中的图标复制到 guli-admin项目中

2、修改路由

修改 src/router/index.js 文件,重新定义constantRouterMap

注意:每个路由的name不能相同

{

    path: '/teacher',

    component: Layout,

    redirect: '/teacher/table',

    name: '讲师管理',

    meta: { title: '讲师管理', icon: 'example' },

    children: [

      {

        path: 'table',

        name: '讲师列表',

        component: () => import('@/views/edu/teacher/list'),

        meta: { title: '讲师列表', icon: 'table' }

      },

      {

        path: 'tree',

        name: '添加讲师',

        component: () => import('@/views/edu/teacher/save'),

        meta: { title: '添加讲师', icon: 'tree' }

      }

    ]

  },

3、创建vue组件

在src/views文件夹下创建以下文件夹和文件

list.vue

<template>

    <div class="app-container">

        讲师列表

    </div>

</template>

save.vue

<template>

    <div class="app-container">

        讲师添加

    </div>

</template>


02-使用nginx配置后台多服务器api

一、项目中的Easy Mock

config/dev.env.js 中BASE_API 为项目的easymock地址,目前具有模拟登录、登出、获取用户信息的功能

BASE_API:'"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"',

登录:/user/login

获取用户信息:/user/info?token=admin

登出:/user/logout

config/dev.env.js,只有一个api地址的配置位置,而我们实际的后端有很多微服务,所以接口地址有很多,

我们可以使用nginx反向代理让不同的api路径分发到不同的api服务器中

二、配置nginx反向代理

1、安装window版的nginx

将nginx-1.12.0.zip解压到开发目录中

如:E:\development\nginx-1.12.0-guli-api

双击nginx.exe运行nginx

访问:localhost

2、配置nginx代理

在Nginx中配置对应的微服务服务器地址即可

注意:最好修改默认的 80端口到81

3、重启nginx

nginx -s reload

4、测试

http://localhost:9001/eduservice/teacher/pageTeacherCondition/1/10

三、配置开发环境

1、修改config/dev.env.js

BASE_API:'"http://127.0.0.1:9001"'

2、重启前端程序

修改配置文件后,需要手动重启前端程序



03-讲师管理列表组件

一、分页列表

1、定义api

创建文件 src/api/edu/teacher.js

import request from '@/utils/request'

export default{

    //1 讲师列表(条件查询分页)

    //current当前页,limit每页记录数,teacherQuery条件对象

    getTeacherPageList(current,limit,teacherQuery){

        return request({

            // url:'/eduservice/teacher/pageTeacherCondition/'+current+'/'+limit,

            url:`/eduservice/teacher/pageTeacherCondition/${current}/${limit}`,

            method:'post',

            //data表示把对象转换为json进行传递到接口里面

            //data表示把对象转换json进行传递到接口里面

            data:teacherQuery

        })

    }

}

2、初始化vue组件

src/views/edu/teacher/list.vue

<template>

    <div class="app-container">

        讲师列表

    </div>

</template>

<script>

    // 引入调用teacher.js文件

    import teacher from '@/api/edu/teacher'

    export default {

        //写核心代码位置

        // data:{

        // },

        data(){ //定义变量和初始值

            return {}

        },

        created(){ //页面渲染之前执行,一般调用method定义的方法

            this.getList()

        },

        methods:{ //创建具体的方法,调用teacher.js定义的方法

            //讲师列表的方法

            getList(){

            }

        }

    }

</script>

3、定义data

  data(){ //定义变量和初始值

            return {

                list:null,//查询之后接口返回集合

                page:1,//当前页

                limit:10,//每页记录数

                total:0,//总记录数

                teacherQuery:{}//条件封装对象

            }

        },

4、定义methods

methods:{ //创建具体的方法,调用teacher.js定义的方法

            //讲师列表的方法

            getList(){

                teacher.getTeacherPageList(this.page,this.limit,this.teacherQuery)

                    .then(response => {//请求成功

                        //response接口返回数据

                        // console.log(response)

                        this.list = response.data.rows

                        this.total = response.data.total

                        console.log(this.list)

                        console.log(this.total)

                    })

                    .catch(error =>{//请求失败

                        console.log(error)

                    })

            }

        }

5、表格渲染

<template>

    <div class="app-container">

        讲师列表

        <!-- 表格 -->

        <el-table

            :data="list"

            border

            fit

            highlight-current-row>

            <el-table-column

                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>

6、分页组件

<!-- 分页 -->

        <el-pagination

        :current-page="page"

        :page-size="limit"

        :total="total"

        style="padding: 30px 0; text-align: center;"

        layout="total, prev, pager, next, jumper"

        @current-change="getList"

        />

7、顶部查询表单

注意:

element-ui的 date-picker组件默认绑定的时间值是默认世界标准时间,和中国时间差8小时

设置value-format="yyyy-MM-dd HH:mm:ss" 改变绑定的值

     <!-- :inline="true"表示在一行显示 -->

        <!--查询表单-->

        <el-form :inline="true" class="demo-form-inline">

            <el-form-item>

                <el-input v-model="teacherQuery.name" placeholder="讲师名"/>

            </el-form-item>

            <el-form-item>

                <el-select v-model="teacherQuery.level" clearable placeholder="讲师头衔">

                <el-option :value="1" label="高级讲师"/>

                <el-option :value="2" label="首席讲师"/>

                </el-select>

            </el-form-item>

            <el-form-item label="添加时间">

                <el-date-picker

                v-model="teacherQuery.begin"

                type="datetime"

                placeholder="选择开始时间"

                value-format="yyyy-MM-dd HH:mm:ss"

                default-time="00:00:00"

                />

            </el-form-item>

            <el-form-item>

                <el-date-picker

                v-model="teacherQuery.end"

                type="datetime"

                placeholder="选择截止时间"

                value-format="yyyy-MM-dd HH:mm:ss"

                default-time="00:00:00"

                />

            </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>

清空方法:

 resetData(){//清空方法

                //表单输入项数据清空

                this.teacherQuery = {}

                //查询所有讲师数据

                this.getList()

            }

8、测试

二、删除

1、定义api

src/api/edu/teacher.js

    removeById(id){

        return request({

            url:`/eduservice/teacher/${id}`,

            method:'delete'

        })

    }

2、定义methods

src/views/edu/teacher/list.vue

使用MessageBox 弹框组件

        removeDataById(id){

                // debugger

                // console.log(memberId)

                this.$confirm('此操作将永久删除该记录, 是否继续?', '提示', {

                    confirmButtonText: '确定',

                    cancelButtonText: '取消',

                    type: 'warning'

                }).then(() => {//点击确定,执行then方法

                    //调用删除的方法

                    teacher.removeById(id)

                        .then( response => {//删除成功            

                        //提示信息

                        this.$message({

                            type: 'success',

                            message: '删除成功!'

                        })

                        //回到列表页面

                        this.getList()                    

                    })

                })//点击取消,执行catch方法

            }


04-讲师管理表单组件

一、新增

1、定义api

 src/api/edu/teacher.js

      //添加讲师

    addTeacher(teacher){

        return request({

            url:`/eduservice/teacher/addTeacher`,

            method:'post',

            data:teacher

        })

    }

2、初始化组件

src/views/edu/teacher/save.vue

html

<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="请选择">

                <!--

                    数据类型一定要和取出的json中的一致,否则没法回填

                    因此,这里value使用动态绑定的值,保证其数据类型是number

                -->

                <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"/>

            </el-form-item>

            <el-form-item label="讲师简介">

                <el-input v-model="teacher.intro" :rows="10" 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>

js

<script>

export default {

    data(){

        return {

            teacher:{

                name: '',

                sort: 0,

                level: 1,

                career: '',

                intro: '',

                avatar: ''

            },

            saveBtnDisabled: false // 保存按钮是否禁用,

        }

    },

    created(){

    },

    methods:{

        saveOrUpdate(){

            //添加

            this.saveTeacher()

        },

        //添加讲师的方法

        saveTeacher(){

        }

    }

}

</script>

3、实现新增功能

引入teacher api模块

import teacherApi from '@/api/edu/teacher'

完善save方法

         //添加讲师的方法

        saveTeacher(){

            teacherApi.addTeacher(this.teacher)

                .then(response =>{

                    //提示信息

                    this.$message({

                        type:'success',

                        message:'添加成功!'

                    });

                    //回到列表页面 路由跳转

                    this.$router.push({path:'/teacher/table'})

                })

        }

修改讲师信息:通过隐藏路由传递讲师id

index.js

    {

        path: 'edit/:id',

        name: 'EduTeacherEdit',

        component: () => import('@/views/edu/teacher/save'),

        meta: { title: '编辑讲师', noCache:true },

        hidden:true

      }

二、回显

1、定义api 

 src/api/edu/teacher.js

getTeacherInfo(id){

        return request({

            url:`/eduservice/teacher/getTeacher/${id}`,

            method:'get'

        })

    }

2、组件中调用api

save.vue中的methods中定义getInfo

        //根据讲师id查询的方法

        getInfo(id){

            teacherApi.getTeacherInfo(id)

                .then(response => {

                    this.teacher = response.data.teacher

                })

        },

3、页面渲染前调用fetchDataById

save.vue

created(){//页面渲染之前执行

        //判断路径是否有id值

        if (this.$route.params && this.$route.params.id) {

            //从路径获取id值

            const id = this.$route.params.id

            //调用根据id查询的方法

            this.getInfo(id)

        }

    },

三、更新

1、定义api

teacher.js

    //修改讲师

    updateById(teacher){

        return request({

            url:`/eduservice/teacher/updateTeacher`,

            method:'post',

            data:teacher

        })

    }

2、组件中调用api

methods中定义updateData

    //修改讲师的方法

        updateData(){

            this.saveBtnDisabled = true

            teacherApi.updateById(this.teacher)

                .then(response => {

                    //提示信息

                    this.$message({

                        type:'success',

                        message:'修改成功!'

                    });

                    //回到列表页面 路由跳转

                    this.$router.push({path:'/teacher/table'})

                })

        }

3、完善saveOrUpdate方法

    saveOrUpdate(){

            this.saveBtnDisabled = true

            //判断修改还是添加

            //根据teacher是否有id

            if(!this.teacher.id){

                //添加

                this.saveTeacher()

            }else{

                //修改

                this.updateData()

            }

        },

四、存在问题

vue-router导航切换 时,如果两个路由都渲染同个组件,组件会重(chong)用,

组件的生命周期钩子(created)不会再被调用, 使得组件的一些数据无法根据 path的改变得到更新

因此:

1、我们可以在watch中监听路由的变化,当路由变化时,重新调用created中的内容

2、在init方法中我们判断路由的变化,如果是修改路由,则从api获取表单数据,

      如果是新增路由,则重新初始化表单数据

<script>

import teacherApi from '@/api/edu/teacher'

export default {

    data(){

        return {

            teacher:{

                name: '',

                sort: 0,

                level: 1,

                career: '',

                intro: '',

                avatar: ''

            },

            saveBtnDisabled: false // 保存按钮是否禁用,

        }

    },

    created(){//页面渲染之前执行

        this.init()

    },

    watch: {//监听

        $route(to,from) { //路由变化方式,路由发生变化,方法就会执行

        this.init()

       }

    },

    methods:{

        init(){

            //判断路径是否有id值

            if (this.$route.params && this.$route.params.id) {

                //从路径获取id值

                const id = this.$route.params.id

                //调用根据id查询的方法

                this.getInfo(id)

            }else{//路径中没有id值,做添加

                //清空表单

                this.teacher = {}

            }

        },

.......

}

</script>


05-后端业务的灵活优化

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342