Vue 3, Go and MySQL create a personal blog system with user registration login, comment, classification and tag functions

Table of contents

Implement user registration and login

Realize the comment function

Implement classification and labeling functions

Front-end processing of user registration and login

Front-end processing for comments

Front-end processing of classification and labeling functions


Implement user registration and login

First, we'll create a new users table in MySQL:

CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(50) NOT NULL UNIQUE,
  password VARCHAR(255) NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

In the backend Go code, we'll create two new routes, one to handle user registration and one to handle user login:

 
 
func main() {
  // other code
  r.POST("/register", register)
  r.POST("/login", login)
  // other code
}

Next, we will implement registerthe and loginfunctions respectively. When a user registers, we hash the user's password and store it in the database for added security. When the user logs in, we compare the password entered by the user with the hashed password stored in the database, and if they match, the login is successful:

import (
  "github.com/gin-gonic/gin"
  "golang.org/x/crypto/bcrypt"
)

type User struct {
  ID       int    `json:"id"`
  Username string `json:"username" binding:"required"`
  Password string `json:"password" binding:"required"`
}

func register(c *gin.Context) {
  // Parse and validate the request body
  var user User
  if err := c.ShouldBindJSON(&user); err != nil {
    c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    return
  }

  // Hash the password
  hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
  if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
    return
  }

  // Insert the user into the database
  res, err := db.Exec("INSERT INTO users (username, password) VALUES (?, ?)", user.Username, hash)
  if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
    return
  }

  // Return the user ID
  id, err := res.LastInsertId()
  if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
    return
  }
  c.JSON(http.StatusOK, gin.H{"id": id})
}

func login(c *gin.Context) {
  // Parse and validate the request body
  var user User
  if err := c.ShouldBindJSON(&user); err != nil {
    c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    return
  }

  // Get the user from the database
  var dbUser User
  err := db.QueryRow("SELECT * FROM users WHERE username = ?", user.Username).Scan(&dbUser.ID, &dbUser.Username, &dbUser.Password)
  if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
    return
  }

  // Compare the passwords
  if err := bcrypt.CompareHashAndPassword([]byte(dbUser.Password), []byte(user.Password)); err != nil {
    c.JSON(http.StatusUnauthorized, gin.H{"error": "Incorrect password"})
    return
  }

  // Return the user ID
  c.JSON(http.StatusOK, gin.H{"id": dbUser.ID})
}

In the front-end Vue 3 code, we can create two new components for user registration and login. On form submission for user registration and login, we send a POST request to the backend. If the request is successful, we store the user's ID localStoragein to implement user authentication and permission control.

Realize the comment function

First, we create a new comments table in MySQL:

CREATE TABLE comments (
  id INT AUTO_INCREMENT PRIMARY KEY,
  article_id INT NOT NULL,
  user_id INT NOT NULL,
  content TEXT NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (article_id) REFERENCES articles(id),
  FOREIGN KEY (user_id) REFERENCES users(id)
);

Then, we create a new route in the backend Go code to handle requests to get and create comments:

 
 
func main() {
  // other code
  r.GET("/articles/:id/comments", getComments)
  r.POST("/articles/:id/comments", createComment)
  // other code
}

In the front-end Vue 3 code, we can add a comment list and a comment form below the article details page. On page load, we send a GET request to the backend to get the list of comments. On form submission, we send a POST request to the backend to create a new comment.

Implement classification and labeling functions

First, we create two new tables in MySQL to store categories and tags:

CREATE TABLE categories (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50) NOT NULL UNIQUE
);

CREATE TABLE tags (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50) NOT NULL UNIQUE
);

CREATE TABLE article_categories (
  article_id INT NOT NULL,
  category_id INT NOT NULL,
  PRIMARY KEY (article_id, category_id),
  FOREIGN KEY (article_id) REFERENCES articles(id),
  FOREIGN KEY (category_id) REFERENCES categories(id)
);

CREATE TABLE article_tags (
  article_id INT NOT NULL,
  tag_id INT NOT NULL,
  PRIMARY KEY (article_id, tag_id),
  FOREIGN KEY (article_id) REFERENCES articles(id),
  FOREIGN KEY (tag_id) REFERENCES tags(id)
);

We then create new routes in the backend Go code to handle requests to get and create categories and tags, and requests to filter articles by categories and tags.

Front-end processing of user registration and login

On the front end, we first need to create two new Vue components for the signup and login functionality: Register.vueand Login.vue.

Register.vueThe code of the component is as follows:

<template>
  <form @submit.prevent="register">
    <label>
      用户名:
      <input v-model="username" type="text" required>
    </label>
    <label>
      密码:
      <input v-model="password" type="password" required>
    </label>
    <button type="submit">注册</button>
  </form>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      username: '',
      password: ''
    };
  },
  methods: {
    async register() {
      try {
        const res = await axios.post('/register', {
          username: this.username,
          password: this.password
        });
        localStorage.setItem('userId', res.data.id);
        this.$router.push('/');
      } catch (error) {
        console.error(error);
      }
    }
  }
};
</script>

Similarly, Login.vue the code for the component is as follows:

 
 
<template>
  <form @submit.prevent="login">
    <label>
      用户名:
      <input v-model="username" type="text" required>
    </label>
    <label>
      密码:
      <input v-model="password" type="password" required>
    </label>
    <button type="submit">登录</button>
  </form>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      username: '',
      password: ''
    };
  },
  methods: {
    async login() {
      try {
        const res = await axios.post('/login', {
          username: this.username,
          password: this.password
        });
        localStorage.setItem('userId', res.data.id);
        this.$router.push('/');
      } catch (error) {
        console.error(error);
      }
    }
  }
};
</script>

The template portion of both components contains a form that accepts user input for a username and password. @submit.prevent="register"and @submit.prevent="login"are used to prevent the form's default submit behavior and call registerthe or loginmethod .

Front-end processing for comments

For the comment function, we need to add a comment form and a comment list under the article details page.

First, we need to add the following code Article.vueto :

<template>
  <!-- other code -->
  <section>
    <form @submit.prevent="submitComment">
      <label>
        评论:
        <textarea v-model="commentContent" required></textarea>
      </label>
      <button type="submit">提交评论</button>
    </form>
    <div v-for="comment in comments" :key="comment.id">
      <h3>{
   
   { comment.user.username }}</h3>
      <p>{
   
   { comment.content }}</p>
    </div>
  </section>
</template>

<script>
import axios from 'axios';

export default {
  // other code
  data() {
    return {
      comments: [],
      commentContent: ''
    };
  },
  async created() {
    try {
      const res = await axios.get(`/articles/${this.id}/comments`);
      this.comments = res.data;
    } catch (error) {
      console.error(error);
    }
  },
  methods: {
    async submitComment() {
      try {
        const res = await axios.post(`/articles/${this.id}/comments`, {
          content: this.commentContent,
          user_id: localStorage.getItem('userId')
        });
        this.comments.push(res.data);
        this.commentContent = '';
      } catch (error) {
        console.error(error);
      }
    }
  }
};
</script>

Front-end processing of classification and labeling functions

For the category and label function, we can add a sidebar to the article list page to display all categories and labels. Users can click on a category or tag to view related articles.

First, we need to add the following code Articles.vueto :

<template>
  <!-- other code -->
  <aside>
    <section>
      <h2>分类</h2>
      <ul>
        <li v-for="category in categories" :key="category.id">
          <a @click="filterByCategory(category.id)">{
   
   { category.name }}</a>
        </li>
      </ul>
    </section>
    <section>
      <h2>标签</h2>
      <ul>
        <li v-for="tag in tags" :key="tag.id">
          <a @click="filterByTag(tag.id)">{
   
   { tag.name }}</a>
        </li>
      </ul>
    </section>
  </aside>
</template>

<script>
import axios from 'axios';

export default {
  // other code
  data() {
    return {
      categories: [],
      tags: [],
      articles: []
    };
  },
  async created() {
    try {
      const [categoriesRes, tagsRes, articlesRes] = await Promise.all([
        axios.get('/categories'),
        axios.get('/tags'),
        axios.get('/articles')
      ]);
      this.categories = categoriesRes.data;
      this.tags = tagsRes.data;
      this.articles = articlesRes.data;
    } catch (error) {
      console.error(error);
    }
  },
  methods: {
    async filterByCategory(id) {
      try {
        const res = await axios.get(`/articles?category=${id}`);
        this.articles = res.data;
      } catch (error) {
        console.error(error);
      }
    },
    async filterByTag(id) {
      try {
        const res = await axios.get(`/articles?tag=${id}`);
        this.articles = res.data;
      } catch (error) {
        console.error(error);
      }
    }
  }
};
</script>

That's all for user registration and login, comments, categories and tags using Vue 3, Go and MySQL. These functions are very important for a blog system and can greatly improve user experience. I hope this blog is helpful to you, if you have any questions or suggestions, please leave a message in the comment area.

Guess you like

Origin blog.csdn.net/m0_68036862/article/details/131156960