Paper Management System Based on Vue-Springboot

Table of Contents

Demo link: ECNU-2022Spring-DatabaseTermProject Group 4_Bilibili

About Login Information and Permission Display

Here, sessionStorage is used to store user information and permissions (ideally, they should be returned together as user information, but here they are stored separately). Subsequent access to the left Aside of the page can also be resolved based on the stored sessionStorage.

The sessionStorage property allows you to access a session Storage object. It is similar to localStorage, except that the data stored in localStorage has no expiration time set, while the data stored in sessionStorage is cleared when the page session ends. The page session lasts as long as the browser is open, and reloading or restoring the page retains the original page session. Opening a page in a new tab or window initializes a new session in the top-level browsing context, which is different from how session cookies work.

request.post("/api/login", this.form).then(res => {
  console.log(res)
  if (res.code === 0) {
    console.log(3333)
    this.$message({
      type: "success",
      message: "Login successful"
    })
    sessionStorage.setItem("user", JSON.stringify(res.data))  // Cache user information
    request.post("/api/permission?user_id=" + res.data.user_id).then(res1 => {
      console.log(res1)
      console.log("Permission obtained")
      sessionStorage.setItem("userPermission", JSON.stringify(res1))  // Cache user permissions
      let userStr = sessionStorage.getItem("userPermission") || "{}"
      this.permissionList = JSON.parse(userStr)
      activateRouter()
      this.$router.push("/")  // Redirect to the homepage after successful login
    })

  } else {
    this.$message({
      type: "error",
      message: res.msg
    })
  }
})

About Route Configuration

To prevent any user from accessing pages by changing the URL, consider not loading the route if the user does not have permission to access the page. Use a loop to register routes (addRoute).

Also, use foreach to control permissions.

A very concise way of writing:

function activateRouter() {
  const userStr = sessionStorage.getItem("userPermission")
  if (userStr) {
    const userPermission = JSON.parse(userStr)
    let root = {
      path: '/',
      name: 'Layout',
      component: Layout,
      redirect: "/home",
      children: []
    }
    userPermission.forEach(p => {
      let obj = {
        path: p.path,
        name: p.name,
        component: () => import("@/views/" + p.name)
      };
      root.children.push(obj)
    })
    if (router) {
      router.addRoute(root)
    }
  }
}

router.beforeEach((to, from, next) => {
  if (to.path === '/login' || to.path === '/register') {
    next()
    return
  }
  let userPermission = sessionStorage.getItem("userPermission") ? JSON.parse(sessionStorage.getItem("userPermission")) : {}
  if (!userPermission || !userPermission.length) {
    next('/login')
  } else if (!userPermission.find(p => p.path === to.path)) {
    next('/login')
  } else {
    next()
  }
})

About Frontend Pagination

Using elementUi here, pagination operations are very simple, just modify: data values, using the slice function of JavaScript.

(Not recommended to use frontend pagination. It is meaningless.)

<el-table
    v-loading="loading"
    :data="tableData.slice((currentPage-1)*pageSize,currentPage*pageSize)"
    border
    stripe
    style="width: 100%">
  <el-table-column
      prop="user_id"
      label="ID"
      sortable
  >

About Clearing Forms

A simple way to clear this.form

this.form = {brand_right: 0}

About Comment Loading

When posting a reply after commenting, the page needs to refresh in real-time, but the entire page cannot be refreshed directly. Found a clever way to do this.

First, register the reload method in app.vue

<template>
  <div id="app" class="body"></div>
  <el-config-provider :locale="locale">
    <router-view v-if="isRouterAlive"></router-view>
  </el-config-provider>
</template>

export default {
  name: "App",
  provide() {
    return {
      reload: this.reload
    }
  },
  components: {
    [ElConfigProvider.name]: ElConfigProvider,
  },
  data() {
    return {
      isRouterAlive: true,
      locale: zhCn,
    }
  },
  methods: {
    reload() {
      this.isRouterAlive = false
      this.$nextTick(function () {
        this.isRouterAlive = true
      })
    }
  }
}

Import inject where needed:

export default {
  name: 'Comment',
  props: {
    paperid: Number
  },
  inject: ['reload']
}

About Vuex:

When to use Vuex?

Vuex is a state management pattern + library for Vue.js applications. It uses a centralized store to manage the state of all components in an application, with rules ensuring that the state changes in a predictable manner.

In simple terms, it manages communication between components, allowing information to be stored globally without passing it between components.

Using login and recording user-related information as an example (though this scenario is not suitable because Vuex is reactive and will be lost upon refresh).

export default createStore({
  state: {
    user: {}
  },
  mutations: {
    SET_USER(state, user) {
      state.user = user
      console.log("set_user in mutation:")
      console.log(user)
    }
  },
  actions: {
    SET_USER(context, user) {
      console.log("set_user in actions:")
      context.commit('SET_USER', user)
    }
  },
  getters: {
    getUser(state) {
      return state.user
    },
    printUsername(state) {
      console.log("print through getters")
      console.log(state.user.username)
    },
  }
})

Store state using state

Trigger on login:

this.$store.state.user = res
this.$store.commit('SET_USER', res.data)
this.$store.dispatch('SET_USER', res.data)

The first line directly assigns a value, the second line calls the mutation method using a function, and the third line calls the getters method (asynchronous mutation).

Comparison of local storage and session storage:

  1. Difference: Vuex is stored in memory, localStorage (local storage) is stored locally as a file and is permanently saved (unless actively deleted, it will always exist); sessionStorage (session storage) is temporarily saved. localStorage and sessionStorage can only store string types, for complex objects, use JSON.stringify and JSON.parse provided by ECMAScript.

  2. Application scenarios: Vuex (reactive) is used for passing values between components, while localStorage and sessionStorage are mainly used for passing values between different pages (non-reactive, updated only on page refresh).

  3. Permanence: When refreshing the page (here, refreshing the page means pressing F5, which clears the memory), the values stored in Vuex will be lost. localStorage and sessionStorage are not affected by page refresh and store data. sessionStorage is cleared when the page is closed, while localStorage is not.

JSON and String Handling:

JSON is a serialized object or array, it is a string representation of a JS object, meaning JSON is essentially a string. JSON exists in the form of key-value pairs, where:

JSON keys must be enclosed in "" (double quotes) JSON values cannot be function/undefined/NaN No trailing commas are allowed in data JS Object

In contrast, JS objects do not have the above three restrictions, which is the main difference from JSON.

Conversion between JSON and JS objects

Convert JSON to JS object: use JSON.parse() method Convert JS object to JSON: use JSON.stringify() method Application scenarios

JSON can convert a set of data represented by a JavaScript object into a string, making it much easier to pass this string than passing a large set of data. It can then be restored to a supported data format when needed.

In Conclusion:

This is a project from a previous database course. I believe it was the only useful course in the second semester of my sophomore year at ECNU. I was mainly responsible for the frontend part. It was completed in June 2022, and I have forgotten most of it now… Recently, I wanted to find an internship, so I decided to organize and upload some of the content I had casually put together before. The part I was most satisfied with was the comprehensive analysis and implementation of project requirements. I spent a lot of time on the multi-level comment and deletion part, which I was quite satisfied with (although I have forgotten most of it now…). The rest of the time was spent debugging interfaces and fixing bugs. Demo link: