Vue 3, Go y MySQL crean un sistema de blog personal con funciones de inicio de sesión de registro de usuario, comentarios, clasificación y etiquetas

Tabla de contenido

Implementar registro de usuario e inicio de sesión

Darse cuenta de la función de comentario

Implementar funciones de clasificación y etiquetado.

Procesamiento front-end del registro e inicio de sesión del usuario

Procesamiento front-end para comentarios

Procesamiento frontal para funciones de clasificación y etiquetado


Implementar registro de usuario e inicio de sesión

Primero, crearemos una nueva tabla de usuarios en 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
);

En el código Go de backend, crearemos dos rutas nuevas, una para gestionar el registro de usuarios y otra para gestionar el inicio de sesión de los usuarios:

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

A continuación, implementaremos registerlas loginfunciones y respectivamente. Cuando un usuario se registra, codificamos la contraseña del usuario y la almacenamos en la base de datos para mayor seguridad. Cuando el usuario inicia sesión, comparamos la contraseña ingresada por el usuario con la contraseña cifrada almacenada en la base de datos y, si coinciden, el inicio de sesión es exitoso:

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

En el código front-end de Vue 3, podemos crear dos nuevos componentes para el registro y el inicio de sesión del usuario. En el envío del formulario para el registro e inicio de sesión del usuario, enviamos una solicitud POST al backend. Si la solicitud tiene éxito, almacenamos la identificación del localStorageusuario para implementar la autenticación del usuario y el control de permisos.

Darse cuenta de la función de comentario

Primero, creamos una nueva tabla de comentarios en 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)
);

Luego, creamos una nueva ruta en el código Go de backend para manejar las solicitudes para obtener y crear comentarios:

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

En el código frontal de Vue 3, podemos agregar una lista de comentarios y un formulario de comentarios debajo de la página de detalles del artículo. Al cargar la página, enviamos una solicitud GET al backend para obtener la lista de comentarios. Al enviar el formulario, enviamos una solicitud POST al backend para crear un nuevo comentario.

Implementar funciones de clasificación y etiquetado.

Primero, creamos dos nuevas tablas en MySQL para almacenar categorías y etiquetas:

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

Luego, creamos nuevas rutas en el código de back-end Go para manejar las solicitudes para obtener y crear categorías y etiquetas, así como las solicitudes para filtrar artículos por categorías y etiquetas.

Procesamiento front-end del registro e inicio de sesión del usuario

En la interfaz, primero debemos crear dos nuevos componentes de Vue para la funcionalidad de registro e inicio de sesión: Register.vuey Login.vue.

Register.vueEl código del componente es el siguiente:

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

De manera similar, Login.vue el código para el componente es el siguiente:

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

La parte de la plantilla de ambos componentes contiene un formulario que acepta la entrada del usuario para un nombre de usuario y una contraseña. @submit.prevent="register"y @submit.prevent="login"se utilizan para evitar el comportamiento de envío predeterminado del formulario y llamar registeral loginmétodo .

Procesamiento front-end para comentarios

Para la función de comentarios, debemos agregar un formulario de comentarios y una lista de comentarios en la página de detalles del artículo.

Primero, necesitamos agregar el siguiente código Article.vueal :

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

Procesamiento frontal para funciones de clasificación y etiquetado

Para la función de categoría y etiqueta, podemos agregar una barra lateral a la página de lista de artículos para mostrar todas las categorías y etiquetas. Los usuarios pueden hacer clic en una categoría o etiqueta para ver artículos relacionados.

Primero, necesitamos agregar el siguiente código Articles.vueal :

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

Eso es todo para el registro e inicio de sesión de usuarios, comentarios, categorías y etiquetas usando Vue 3, Go y MySQL. Estas funciones son muy importantes para un sistema de blogs y pueden mejorar en gran medida la experiencia del usuario. Espero que este blog le sea útil, si tiene alguna pregunta o sugerencia, deje un mensaje en el área de comentarios.

Supongo que te gusta

Origin blog.csdn.net/m0_68036862/article/details/131156960
Recomendado
Clasificación