Vue 3、Go 和 MySQL 创建一个具有用户注册登录、评论、分类和标签功能的个人博客系统

目录

实现用户注册和登录

实现评论功能

实现分类和标签功能

用户注册和登录的前端处理

评论功能的前端处理

分类和标签功能的前端处理


实现用户注册和登录

首先,我们要在 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
);

在后端的 Go 代码中,我们将创建两个新的路由,一个用于处理用户注册,一个用于处理用户登录:

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

下面,我们将分别实现 registerlogin 函数。在用户注册时,我们将用户的密码哈希后存储在数据库中,以提高安全性。在用户登录时,我们将用户输入的密码和数据库中存储的哈希密码进行比较,如果匹配则登录成功:

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})
}

在前端的 Vue 3 代码中,我们可以为用户注册和登录创建两个新的组件。在用户注册和登录的表单提交时,我们向后端发送 POST 请求。如果请求成功,我们将用户的 ID 存储在 localStorage 中,以此实现用户认证和权限控制。

实现评论功能

首先,我们在 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)
);

然后,我们在后端的 Go 代码中创建一个新的路由来处理获取和创建评论的请求:

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

在前端的 Vue 3 代码中,我们可以在文章详情页面下方添加一个评论列表和一个评论表单。在页面加载时,我们向后端发送 GET 请求获取评论列表。在表单提交时,我们向后端发送 POST 请求创建新的评论。

实现分类和标签功能

首先,我们在 MySQL 中创建两个新的表来存储分类和标签:

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)
);

然后,我们在后端的 Go 代码中创建新的路由来处理获取和创建分类和标签的请求,以及按分类和标签过滤文章的请求。

用户注册和登录的前端处理

在前端部分,我们首先需要为注册和登录功能创建两个新的 Vue 组件:Register.vueLogin.vue

Register.vue 组件的代码如下:

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

同样,Login.vue 组件的代码如下:

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

这两个组件的模板部分都包含一个表单,用于接收用户输入的用户名和密码。@submit.prevent="register"@submit.prevent="login" 用于阻止表单的默认提交行为,并调用 registerlogin 方法。

评论功能的前端处理

对于评论功能,我们需要在文章详情页下面添加一个评论表单和一个评论列表。

首先,我们需要在文章详情组件 Article.vue 中添加以下代码:

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

分类和标签功能的前端处理

对于分类和标签功能,我们可以在文章列表页面添加一个侧边栏来显示所有的分类和标签。用户可以点击分类或标签来查看相关的文章。

首先,我们需要在文章列表组件 Articles.vue 中添加以下代码:

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

以上就是使用 Vue 3、Go 和 MySQL 实现用户注册和登录、评论、分类和标签功能的全部内容。这些功能对于一个博客系统来说都非常重要,可以极大地提高用户体验。我希望这篇博客对你有所帮助,如果你有任何问题或建议,欢迎在评论区留言。

猜你喜欢

转载自blog.csdn.net/m0_68036862/article/details/131156960