Shangsi Valley grain college learning notes 4 - front end knowledge summary, lecturer list, front end implementation

Keywords: Javascript node.js Spring Boot Vue.js Project

es6 and vue basic knowledge points

es6 syntax new features blog link
vue basics blog link
axios blog link
npm, webpack blog link

vue-element-admin

Vue element admin is a background management system integration scheme based on element UI.

Function: https://panjiachen.github.io/vue-element-admin-site/zh/guide/# function

GitHub address: https://github.com/PanJiaChen/vue-element-admin

Project online preview: https://panjiachen.gitee.io/vue-element-admin

install

# Unzip the package
# Enter directory
cd vue-element-admin-master


# Installation dependency
npm install

# Start. After execution, the browser automatically pops up and accesses http://localhost:9527/
npm run dev

vue-admin-template

Ueadmin template is a set of basic templates (at least simplified version) of background management system based on Vue element admin, which can be used as a template for secondary development.

GitHub address: https://github.com/PanJiaChen/vue-admin-template

Suggestion: you can carry out secondary development on the basis of Vue admin template, take Vue element admin as a toolbox, and copy what functions or components you want from Vue element admin

# Unzip the package
# Enter directory
cd vue-admin-template-master

# Installation dependency
npm install

# Start. After execution, the browser automatically pops up and accesses http://localhost:9528/
npm run dev

Front end project creation and basic configuration

Rename Vue admin template master to Guli admin

Modify port number

Modify in config/index.js

port: 9528,

Turn off syntax checking

Modify in config/index.js

useEslint: false

Directory structure of the project

├── build // Build script
├── config // Global configuration 
├── node_modules // Project dependent module
├── src //Project source code
├── static // Static resources
└── package.jspon // Project information and dependency configuration
src 

├── api // Various interfaces 
├── assets // Pictures and other resources 
├── components // Various public components and non-public components are maintained under their own view s 
├── icons //svg icon 
├── router // Routing table 
├── store // storage 
├── styles // Various styles 
├── utils // Public tools and non-public tools are maintained under their own view s 
├── views // Various layout s
├── App.vue //***Project top-level components*** 
├── main.js //***Project entry file***
└── permission.js //Authentication entry

Run project

npm run dev

Modify simulated Login

front end

Base of dev.env.js under config_ Change the path of API to local

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  // BASE_API: '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"',

  BASE_API: '"http://localhost:8001"'
})

Replace the path of src/api/login.js with the path of the interface

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

export function getInfo(token) {
  return request({
    url: '/eduservice/user/info',
    method: 'get',
    params: { token }
  })
}

export function logout() {
  return request({
    url: '/eduservice/user/logout',
    method: 'post'
  })
}

back-end

EduLoginController

@RestController
@RequestMapping("/eduservice/user")
@Api(tags="Login management")
@CrossOrigin
public class EduLoginController {

    //login
    @PostMapping("/login")
    public ResultVo login(){
        return ResultVo.ok().data("token","admin");
    }
    //info
    @GetMapping("/info")
    public  ResultVo info(){
        return ResultVo.ok().data("roles","[admin]").data("name","admin").data("avatar","https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
    }
}

Start front end and back end

Cross domain problem

Solve cross domain problems

Add on the interface

@CrossOrigin

Front end implementation of instructor list

Create routing page

Create a new edu/teacher folder under src/views
And create a new list.vue save.vue

list.vue

<template>

  <div class="app-container">
    Instructor list
  </div>
</template>

add.vue

<template>

  <div class="app-container">
    Instructor add
  </div>
</template>

Add route

Add in src/router/index.js

{
    path: '/teacher',
    component: Layout,
    redirect: '/teacher/table',
    name: 'Instructor management',
    meta: { title: 'Instructor management', icon: 'example' },
    children: [
      {
        path: 'list',
        name: 'Instructor list',
        component: () => import('@/views/edu/teacher/list'),
        meta: { title: 'Instructor list', icon: 'table' }
      },
      {
        path: 'save',
        name: 'Add instructor',
        component: () => import('@/views/edu/teacher/save'),
        meta: { title: 'Add instructor', icon: 'tree' }
      }
    ]
  },

Define teacher.js

Create edu/teacher.js under src/api

import request from '@/utils/request'

export default{

  //Instructor list (condition query page)
  //Current current page limit records per page teacherQuery condition object
  getTeacherListPage(current,limit,teacherQuery){
    return request({
      url: `/eduservice/teacher/pageTeacherCondition/${current}/${limit}`, //The ` ` of es6 is used here, not a single quotation mark
      method: 'post',
      //teacherQuery condition object. The backend uses RequestBody to obtain data
      //data means that the object is transformed into json and passed to the interface
      data: teacherQuery
    })
  }

}

Initialize vue components

src/views/edu/teacher/list.vue

<template>

  <div class="app-container">
    Instructor list
  </div>
</template>

<script>

//Introducing teacher.js
import teacher from '@/api/edu/teacher'
export default {
    //Write core code
   data(){  //Define variables and initial values
     return{
       
     }
   },
   created(){//Before page rendering, the method defined by methods is generally called
     
   },
   methods:{//Create a specific method and call the method defined by teacher.js
       
   }
}
</script>

Define data

data(){  //Define variables and initial values
     return{
       list:null, //Collection returned by the interface after query
       page:1, //Current page
       limit:10, //Records per page
       total:0, //Total records
       teacherQuery:{} //Conditional encapsulation object

     }

Define methods

methods:{//Create a specific method and call the method defined by teacher.js
        //Instructor list method
        getList(){
          teacher.getTeacherListPage(this.page,this.limit,this.teacherQuery)
          .then(response =>{
              // console.log(response.data.rows)
              this.list=response.data.rows;
              this.total=response.data.total;
          })
          .catch(error => {
            console.log(error)//request was aborted
          })
        }

   }

Full version

<template>

  <div class="app-container">
    Instructor list
  </div>
</template>

<script>

//Introducing teacher.js
import teacher from '@/api/edu/teacher'
export default {
    //Write core code
   data(){  //Define variables and initial values
     return{
       list:null, //Collection returned by the interface after query
       page:1, //Current page
       limit:10, //Records per page
       total:0, //Total records
       teacherQuery:{} //Conditional encapsulation object

     }
   },
   created(){//Before page rendering, the method defined by methods is generally called
      this.getList()
   },
   methods:{//Create a specific method and call the method defined by teacher.js
        //Instructor list method
        getList(){
          teacher.getTeacherListPage(this.page,this.limit,this.teacherQuery)
          .then(response =>{
              // console.log(response.data.rows)
              this.list=response.data.rows;
              this.total=response.data.total;
          })
          .catch(error => {
            console.log(error)//request was aborted
          })
        }

   }
}
</script>

Table rendering

<!-- form -->
    <el-table
      :data="list"
      border
      fit
      highlight-current-row>

      <el-table-column
        label="Serial number"
        width="70"
        align="center">
        <template slot-scope="scope">
          {{ (page - 1) * limit + scope.$index + 1 }}
        </template>
      </el-table-column>

      <el-table-column prop="name" label="name" width="80" />

      <el-table-column label="title" width="80">
        <template slot-scope="scope">
          {{ scope.row.level===1?'Senior Lecturer':'Principal Lecturer ' }}
        </template>
      </el-table-column>

      <el-table-column prop="intro" label="Qualifications" />

      <el-table-column prop="gmtCreate" label="Add time" width="160"/>

      <el-table-column prop="sort" label="sort" width="60" />

      <el-table-column label="operation" width="200" align="center">
        <template slot-scope="scope">
          <router-link :to="'/teacher/edit/'+scope.row.id">
            <el-button type="primary" size="mini" icon="el-icon-edit">modify</el-button>
          </router-link>
          <el-button type="danger" size="mini" icon="el-icon-delete" @click="removeDataById(scope.row.id)">delete</el-button>
        </template>
      </el-table-column>
    </el-table>

paging

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

Modify getList method

Because the default current is 1, you can only check the first page,

methods:{//Create a specific method and call the method defined by teacher.js
        //Instructor list method
        getList(page=1){
          this.page = page
          teacher.getTeacherListPage(this.page,this.limit,this.teacherQuery)
          .then(response =>{
              // console.log(response.data.rows)
              this.list=response.data.rows;
              this.total=response.data.total;
          })
          .catch(error => {
            console.log(error)//request was aborted
          })
        }

   }

And @ current change = "getList" / > don't add parameters in it. If it's encapsulated, it will help you pass it

query form

be careful:
The default binding time value of the date picker component of the element UI is the default world standard time, which is 8 hours different from the Chinese time
Set value format = "yyyy MM DD HH: mm: SS" to change the bound value

  <!--query form -->
    <el-form :inline="true" class="demo-form-inline">
      <el-form-item>
        <el-input v-model="teacherQuery.name" placeholder="Lecturer name"/>
      </el-form-item>

      <el-form-item>
        <el-select v-model="teacherQuery.level" clearable placeholder="Lecturer title">
          <el-option :value="1" label="Senior Lecturer"/>
          <el-option :value="2" label="Principal Lecturer "/>
        </el-select>
      </el-form-item>

      <el-form-item label="Add time">
        <el-date-picker
          v-model="teacherQuery.begin"
          type="datetime"
          placeholder="Select start time"
          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="Select deadline"
          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()">query</el-button>
      <el-button type="default" @click="resetData()">empty</el-button>
    </el-form>

Emptying function

Empty form input condition data
Query all data

	resetData(){
          //Empty form entry data
          this.teacherQuery={}
          //Query all instructor data
          this.getList();
        }

Delete instructor

Define api

src/api/edu/teacher.js

 //Delete instructor
  deleteTeacherById(id){
    return request({
      url: `/eduservice/teacher/${id}`, 
      method: 'delete'
    })
  }

Define methods

src/views/edu/teacher/list.vue
Using the MessageBox bullet box component

removeDataById(id){
             
            this.$confirm('This operation will permanently delete the instructor record, Continue?', 'Tips', {
                confirmButtonText: 'determine',
                cancelButtonText: 'cancel',
                type: 'warning'
            }).then(() => {  //Click OK to execute the then method
                //Call the deleted method
               teacher.deleteTeacherById(id)
                    .then(response =>{//Delete succeeded
                    //Prompt information
                    this.$message({
                        type: 'success',
                        message: 'Delete succeeded!'
                    });
                    //Back to the list page
                    this.getList(this.page)
                })
            }) //Click Cancel to execute the catch method
        }

Add instructor

Define api

src/api/edu/teacher.js

//Add instructor
  addTeacher(teacher){
    return request({
      url:'/eduservice/teacher/addTeacher',
      method:'post',
      data: teacher
    })
  }

Initialize component

src/views/edu/teacher/save.vue

<template>
  <div class="app-container">
    Instructor add

    <el-form label-width="120px">
      <el-form-item label="Lecturer name">
        <el-input v-model="teacher.name" />
      </el-form-item>
      <el-form-item label="Lecturer ranking">
        <el-input-number
          v-model="teacher.sort"
          controls-position="right"
          :min="0"
        />
      </el-form-item>
      <el-form-item label="Lecturer title">
        <el-select v-model="teacher.level" clearable placeholder="Please select">
          <el-option :value="1" label="Senior Lecturer" />
          <el-option :value="2" label="Principal Lecturer " />
        </el-select>
      </el-form-item>
      <el-form-item label="Lecturer qualifications">
        <el-input v-model="teacher.career" />
      </el-form-item>
      <el-form-item label="Trainer Introduction ">
        <el-input v-model="teacher.intro" :rows="10" type="textarea" />
      </el-form-item>

      <!-- Instructor portrait: TODO -->

      <el-form-item>
        <el-button
          :disabled="saveBtnDisabled"
          type="primary"
          @click="saveOrUpdate"
          >preservation</el-button
        >
      </el-form-item>
    </el-form>
  </div>
</template>

js

<script>

import teacherApi from '@/api/edu/teacher'
export default {
  data(){
    return {
       teacher:{
        name: '',
        sort: 0,
        level: 1,
        career: '',
        intro: '',
        avatar: ''
       },
       saveBtnDisabled: false // Whether the Save button is disabled,
    }
  },
  created(){},

methods:{
     saveOrUpdate(){
       //add to
       this.saveTeacher()
     },
     //How to add an instructor
     saveTeacher(){
       teacherApi.addTeacher(this.teacher)
       .then((response) => {
         //Prompt information
          this.$message({
              type: 'success',
              message: 'Added successfully!'
          });

          //Return to the list page and route jump
          this.$router.push({path:'/teacher/list'})
       }).catch((err) => {
         
       });
     }
}
}
</script>

Modify instructor

Jump to the data echo page through the route, and then add the route from the route index page, which is a hidden route
Add and modify are the same page

Hide route

: id is a placeholder
hidden: true is hidden

{
        path: 'edit/:id',
        name: 'Modify instructor',
        component: () => import('@/views/edu/teacher/save'),
        meta: {
          title: 'Modify instructor',
          noCache: 'tree'
        },
        hidden: true
      }

Route jump

<router-link :to="'/teacher/edit/'+scope.row.id">
            <el-button type="primary" size="mini" icon="el-icon-edit">modify</el-button>
</router-link>

Data echo

Realize data echo on form page
In src/api/edu/teacher.js

getTeacherInfoById(id) {
    return request({
      url: `/eduservice/teacher/${id}`,
      method: 'get',

    })
  }

Page call echo

Because add and modify pages use the save page
The difference is whether to add or modify. The query data is echoed only when modifying

Judge whether there is an instructor id value in the path. If there is an id value modified, it can be added directly without an id value

The echo is determined according to whether the path has an id

 created() {
    //Judge that the path has id value and modify it
    if (this.$route.params && this.$route.params.id) {
      //Get id value from path
      const id = this.$route.params.id;
      
      this.getInfo(id);
    }
    
  },

Modify instructor

In src/api/edu/teacher.js

//Modify instructor
  updateTeacher(teacher) {
    return request({
      url: '/eduservice/teacher/updateTeacher',
      method: 'put',
      data: teacher
    })
  },
 updateTeacherInfo() {
      teacherApi
        .updateTeacher(this.teacher)
        .then((response) => {
          //Prompt information
          this.$message({
            type: "success",
            message: "Modified successfully!",
          });

          //Return to the list page and route jump
          this.$router.push({ path: "/teacher/list" });
        })
        .catch((err) => {});
    },

saveOrUpdate

saveOrUpdate() {
      //Determine whether to modify or add
      //According to whether the teacher has an id
      if (!this.teacher.id) {
        //add to
        this.saveTeacher();
      } else {
        //modify
        this.updateTeacherInfo();
      }
    }

Problem bug

If you click Modify in the instructor list first, and then click Add instructor, you will find that the data echo still exists
The form page is still used to modify the echoed data. The correct effect should be to empty the form data

During Vue router navigation switching, if both routes render the same component, the component will be reused,
The component life cycle hook (created) will not be called again, so that some data of the component cannot be updated according to the change of path
Therefore:
1. We can monitor the route change in the watch. When the route changes, we can call the content in created again
2. In the init method, we judge the change of the route. If the route is modified, we obtain the form data from the api,
If it is a new route, reinitialize the form data

Full version

<template>
  <div class="app-container">
    Instructor add

    <el-form label-width="120px">
      <el-form-item label="Lecturer name">
        <el-input v-model="teacher.name" />
      </el-form-item>
      <el-form-item label="Lecturer ranking">
        <el-input-number
          v-model="teacher.sort"
          controls-position="right"
          :min="0"
        />
      </el-form-item>
      <el-form-item label="Lecturer title">
        <el-select v-model="teacher.level" clearable placeholder="Please select">
          <el-option :value="1" label="Senior Lecturer" />
          <el-option :value="2" label="Principal Lecturer " />
        </el-select>
      </el-form-item>
      <el-form-item label="Lecturer qualifications">
        <el-input v-model="teacher.career" />
      </el-form-item>
      <el-form-item label="Trainer Introduction ">
        <el-input v-model="teacher.intro" :rows="10" type="textarea" />
      </el-form-item>

      <!-- Instructor portrait: TODO -->

      <el-form-item>
        <el-button
          :disabled="saveBtnDisabled"
          type="primary"
          @click="saveOrUpdate"
          >preservation</el-button
        >
      </el-form-item>
    </el-form>
  </div>
</template>


<script>
import teacherApi from "@/api/edu/teacher";
export default {
  data() {
    return {
      teacher: {
        name: "",
        sort: 0,
        level: 1,
        career: "",
        intro: "",
        avatar: "",
      },
      saveBtnDisabled: false, // Whether the Save button is disabled,
    };
  },

  watch: {
    $route(to, from) {
      this.init();
    },
  },
  created() {
    this.init();
  },

  methods: {
    init() {
      //Judge that the path has id value and modify it
      if (this.$route.params && this.$route.params.id) {
        //Get id value from path
        const id = this.$route.params.id;

        this.getInfo(id);
      } else {
        //The path has no id value. Please add it
        //Empty form
        this.teacher = {};
      }
    },

    //Query method based on instructor id
    getInfo(id) {
      teacherApi.getTeacherInfoById(id).then((response) => {
        this.teacher = response.data.teacher;
      });
    },
    saveOrUpdate() {
      //Determine whether to modify or add
      //According to whether the teacher has an id
      if (!this.teacher.id) {
        //add to
        this.saveTeacher();
      } else {
        //modify
        this.updateTeacherInfo();
      }
    },
    //How to add an instructor
    saveTeacher() {
      teacherApi
        .addTeacher(this.teacher)
        .then((response) => {
          //Prompt information
          this.$message({
            type: "success",
            message: "Added successfully!",
          });

          //Return to the list page and route jump
          this.$router.push({ path: "/teacher/list" });
        })
        .catch((err) => {});
    },

    updateTeacherInfo() {
      teacherApi
        .updateTeacher(this.teacher)
        .then((response) => {
          //Prompt information
          this.$message({
            type: "success",
            message: "Modified successfully!",
          });

          //Return to the list page and route jump
          this.$router.push({ path: "/teacher/list" });
        })
        .catch((err) => {});
    },
  },
};
</script>

Posted by Hafkas on Mon, 04 Oct 2021 17:36:26 -0700