Vue + spring MVC is developed separately from the front end and back end (making a simple background user management interface)

previously on

  • The previous section explained how to use oauth2 in the front end, how to modify user status and write authentication logic to adapt to oauth2
  • This section will explain how to make a simple background management page

What is the background management page?

  • The essence of background management is CRUD of database records
  • It is used to visualize the pages needed for database maintenance and management
  • The user background management page is used to manage user information. It should have not only the basic information of the user, but also the information related to the user, such as user permission, group and group permission

Manage in the form of form

  • Table is a neat and intuitive way to express. In addition, vuetify has provided a portable api to create qualified tables, so tables are preferred
  • Create a folder called admin in views, and the background related files are written here
  • Then create a user Vue file is used to manage the basic information of users. The code is as follows (the code is very long, please read and understand it by yourself)
<template>
  <v-container fluid>
    <v-row>
      <v-col cols="12">
        <v-data-table :headers="headers" :items="users" class="elevation-1">
          <template v-slot:top>
            <v-toolbar flat>
              <v-toolbar-title>User information management</v-toolbar-title>
              <v-divider class="mx-4" inset vertical></v-divider>
              <v-spacer></v-spacer>
              <!--Dialog box for modifying or creating new-->
              <v-dialog v-model="dialog" max-width="600px">
                <template v-slot:activator="{ on, attrs }">
                  <!--When you click this button, the status will be switched to create-->
                  <v-btn color="primary" dark class="mb-2" v-bind="attrs" v-on="on" @click="state.create=true">
                    New User
                  </v-btn>
                </template>
                <v-card>
                  <v-card-title>
                    <span class="headline">{{ formTitle }}</span>
                  </v-card-title>
                  <v-card-text>
                    <v-form ref="userForm" v-model="valid" lazy-validation autocomplete="off">
                      <!--User name and password-->
                      <v-row>
                        <v-col cols="12" sm="6">
                          <v-text-field v-model="editedItem.username" :rules="rules.usernameRules" label="Username"></v-text-field>
                        </v-col>
                        <v-col cols="12" sm="6">
                          <v-text-field type="password" v-model="editedItem.password" :rules="rules.passwordRules" label="Password"></v-text-field>
                        </v-col>
                      </v-row>
                      <!--Status of the user to disable the user-->
                      <v-row>
                        <v-col cols="12" sm="6">
                          <v-switch v-model="editedItem.enabled" :label="`Enabled: ${editedItem.enabled}`"></v-switch>
                        </v-col>
                        <!--phone number-->
                        <v-col cols="12" sm="6">
                          <v-text-field v-model="editedItem.phone" label="Phone"></v-text-field>
                        </v-col>
                      </v-row>
                      <!--User gender-->
                      <v-row>
                        <v-col cols="12">
                          <v-radio-group v-model="editedItem.gender" row>
                            <v-radio label="Unknown" color="orange" :value="0"></v-radio>
                            <v-radio label="Male" color="primary" :value="1"></v-radio>
                            <v-radio label="Female" color="pink" :value="2"></v-radio>
                          </v-radio-group>
                        </v-col>
                      </v-row>
                      <!--User mailbox-->
                      <v-row>
                        <v-col cols="12">
                          <v-text-field v-model="editedItem.email" :rules="rules.emailRules" label="Email"></v-text-field>
                        </v-col>
                      </v-row>
                      <!--User's birthday and joining date-->
                      <v-row>
                        <v-col cols="12" sm="6">
                          <v-text-field type="date" v-model="editedItem.birthday" label="birthday"></v-text-field>
                        </v-col>
                        <v-col cols="12" sm="6">
                          <v-text-field type="date" v-model="editedItem.joinedDate" label="joined date"></v-text-field>
                        </v-col>
                      </v-row>
                    </v-form>
                  </v-card-text>
                  <v-card-actions>
                    <v-spacer></v-spacer>
                    <v-btn color="blue darken-1" text @click="close">Cancel</v-btn>
                    <!--Determine whether to create or delete-->
                    <v-btn v-if="state.create" :disabled="!valid" color="blue darken-1" text @click="create">Create</v-btn>
                    <v-btn v-if="state.update" :disabled="!valid" color="blue darken-1" text @click="update">Update</v-btn>
                  </v-card-actions>
                </v-card>
              </v-dialog>
              <!--Delete dialog box to confirm again-->
              <v-dialog v-model="dialogDelete" max-width="500px">
                <v-card>
                  <v-card-title class="headline">Are you sure you want to delete this item?</v-card-title>
                  <v-card-actions>
                    <v-spacer></v-spacer>
                    <v-btn color="blue darken-1" text @click="closeDelete()">Cancel</v-btn>
                    <v-btn color="blue darken-1" text @click="deleteItemConfirm()">OK</v-btn>
                    <v-spacer></v-spacer>
                  </v-card-actions>
                </v-card>
              </v-dialog>
            </v-toolbar>
          </template>
          <template v-slot:item.actions="{ item }">
            <v-icon small class="mr-2" @click="editItem(item)">
              mdi-pencil
            </v-icon>
            <v-icon small @click="deleteItem(item)">
              mdi-delete
            </v-icon>
          </template>
          <template v-slot:no-data>
            <v-btn color="primary" @click="initialize">
              Reset
            </v-btn>
          </template>
        </v-data-table>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: 'UserAdmin',
  data: () => ({
    state: {
      create: false,
      update: false
    },
    valid: true,
    dialog: false,
    dialogDelete: false,
    headers: [
      {
        text: 'Username',
        align: 'start',
        sortable: false,
        value: 'username'
      },
      {
        text: 'Email',
        sortable: false,
        value: 'email'
      },
      {
        text: 'Enabled',
        value: 'enabled'
      },
      {
        text: 'Joined Date',
        value: 'joinedDate'
      },
      {
        text: 'Actions',
        value: 'actions',
        sortable: false
      }
    ],
    users: [],
    editedIndex: -1,
    editedItem: {
      username: '',
      password: '',
      enabled: true,
      gender: '0',
      phone: '',
      email: '',
      icon: null,
      birthday: new Date().toISOString().substr(0, 10),
      joinedDate: new Date().toISOString().substr(0, 10)
    },
    defaultItem: {
      username: '',
      password: '',
      enabled: true,
      gender: 0,
      phone: '',
      email: '',
      icon: null,
      birthday: new Date().toISOString().substr(0, 10),
      joinedDate: new Date().toISOString().substr(0, 10)
    },
    rules: {
      usernameRules: [
        v => !!v || 'Username is none!',
        v => (v.length >= 1 && v.length <= 20) || 'Username must be 1-20 characters!'
      ],
      passwordRules: [
        v => !!v || 'Password is none!',
        v => (v.length >= 6 && v.length <= 30) || 'Password must be 6-30 characters!'
      ],
      emailRules: [
        v => !!v || 'Email is none!',
        v => /(\w+)@(\w+)\.(\w+)/.test(v) || 'Email is not valid!'
      ]
    }
  }),
  computed: {
    formTitle () {
      return this.editedIndex === -1 ? 'New User' : 'Edit User'
    }
  },
  watch: {
    dialog (val) {
      val || this.close()
    },
    dialogDelete (val) {
      val || this.closeDelete()
    }
  },
  methods: {
    initialize () {
      // Get all users (10 pages by default)
      this.axios.get('http://127.0.0.1:9001/api/users')
        .then(response => {
          console.log(response)
          // Set user list
          const data = response.data._embedded.users
          for (var i = 0; i < data.length; ++i) {
            data[i].birthday = data[i].birthday ? data[i].birthday.substr(0, 10) : null
            data[i].joinedDate = data[i].joinedDate ? data[i].joinedDate.substr(0, 10) : null
          }
          this.users = data
        }).catch(error => {
          console.log(error)
        })
    },
    editItem (item) {
      this.editedIndex = this.users.indexOf(item)
      this.editedItem = Object.assign({}, item)
      this.dialog = true
      this.state.update = true
    },
    deleteItem (item) {
      this.editedIndex = this.users.indexOf(item)
      this.editedItem = Object.assign({}, item)
      this.dialogDelete = true
    },
    deleteItemConfirm () {
      const user = this.users[this.editedIndex]
      this.axios.delete(user._links.self.href)
        .then(response => {
          console.log(response)
        }).catch(error => {
          console.log(error)
        })
      this.users.splice(this.editedIndex, 1)
      this.closeDelete()
    },
    close () {
      this.dialog = false
      this.$nextTick(() => {
        this.editedItem = Object.assign({}, this.defaultItem)
        this.editedIndex = -1
      })
      this.state.create = false
      this.state.update = false
    },
    closeDelete () {
      this.dialogDelete = false
      this.$nextTick(() => {
        this.editedItem = Object.assign({}, this.defaultItem)
        this.editedIndex = -1
      })
    },
    create () {
      const valid = this.$refs.userForm.validate()
      if (valid) {
        this.axios.post('http://127.0.0.1:9001/api/users', {
          username: this.editedItem.username,
          password: this.editedItem.password,
          enabled: this.editedItem.enabled,
          gender: parseInt(this.editedItem.gender),
          phone: this.editedItem.phone,
          email: this.editedItem.email,
          icon: this.editedItem.icon,
          birthday: this.editedItem.birthday ? this.editedItem.birthday : new Date().toISOString().substr(0, 10),
          joinedDate: this.editedItem.joinedDate ? this.editedItem.joinedDate : new Date().toISOString().substr(0, 10)
        }
        ).then(response => {
          console.log(response)
          this.initialize()
        }).catch(error => {
          console.log(error)
        })
        this.close()
      }
    },
    update () {
      const valid = this.$refs.userForm.validate()
      if (valid) {
        const user = this.users[this.editedIndex]
        this.axios.patch(user._links.self.href, {
          username: this.editedItem.username,
          password: this.editedItem.password,
          enabled: this.editedItem.enabled,
          gender: parseInt(this.editedItem.gender),
          phone: this.editedItem.phone,
          email: this.editedItem.email,
          icon: this.editItem.icon,
          birthday: this.editedItem.birthday ? this.editedItem.birthday : new Date().toISOString().substr(0, 10),
          joinedDate: this.editedItem.joinedDate ? this.editedItem.joinedDate : new Date().toISOString().substr(0, 10)
        }
        ).then(response => {
          console.log(response)
          this.initialize()
        }).catch(error => {
          console.log(error)
        })
        this.close()
      }
    }
  },
  created () {
    this.initialize()
  }
}
</script>

Add routes for user background management

  • In router / index JS, add a point to admin / user The routing code of Vue is as follows
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  },
  {
    // Login view
    path: '/login',
    name: 'Login',
    component: () => import('../views/Login.vue')
  },
  {
    // Register view
    path: '/register',
    name: 'Register',
    component: () => import('../views/Register.vue')
  },
  {
    // User basic information background management
    path: '/admin/users',
    name: 'UserAdmin',
    component: () => import('../views/admin/User.vue')
  }
]

const router = new VueRouter({
  routes
})

export default router

Test user management function

  • Considering the problem of permission, generally speaking, the background management of a website is invisible to ordinary users, and you need to enter the specified url to enter it (ordinary users will not be able to use it even if they enter it because of insufficient permission)
  • Enter in the url http://127.0.0.1:9001/admin/users Enter the background management page, and the effect diagram is as follows
  • First, test the function of creating a user, input information and click create

  • You can see that a new user is created successfully
  • Then test the function of modifying a user, click the small pen on the right to open the modification page and modify the information at random (here is the password saved in the ciphertext in the database, and there is corresponding logic at the back end to judge whether the submitted password needs to be modified, so it can not be changed here)

  • You can see that the Email of a new user has been successfully modified
  • Finally, test the deletion function, click the trash can button on the right to delete, and select OK to delete

  • You can see that the user has been deleted and the test is successful

Relevant details and design purpose

  • What the table sees is a list view, not a detailed view. Just mark the necessary information to judge a user on the table
  • vuetify's table has its own paging function, so there is no need to change the back-end interface and implement paging logic
  • Deleting a user is indeed deleted in the database, but in the front end, only one item of the list is deleted without re obtaining all users. This can reduce the burden on the back end, because obtaining users is very time-consuming
  • vuetify's table has automatic sorting function. For example, this table can sort joinedDate

So far, a simple background user management interface has been completed. The next section will set up the background user management interface in more detail and complete other management functions

Keywords: Database Vue

Added by mantona on Fri, 18 Feb 2022 19:50:15 +0200