Vue 3、Go、MySQL でユーザー登録ログイン、コメント、分類、タグ機能を備えた個人ブログ システムを作成

目次

ユーザー登録とログインを実装する

コメント機能を実現

分類およびラベル付け機能を実装する

ユーザー登録とログインのフロントエンド処理

コメントのフロントエンド処理

分類およびラベル付け機能のフロントエンド処理


ユーザー登録とログインを実装する

まず、MySQL に新しい users テーブルを作成します。

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 コードでは、ユーザー登録を処理するルートとユーザー ログインを処理するルートの 2 つの新しいルートを作成します。

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

次に、registerと のloginユーザーが登録すると、セキュリティを強化するためにユーザーのパスワードがハッシュ化され、データベースに保存されます。ユーザーがログインすると、ユーザーが入力したパスワードとデータベースに保存されているハッシュ化されたパスワードが比較され、それらが一致する場合、ログインは成功します。

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 コードでは、ユーザー登録とログイン用の 2 つの新しいコンポーネントを作成できます。ユーザー登録とログインのためのフォーム送信時に、POST リクエストがバックエンドに送信されます。リクエストが成功すると、ユーザー認証と権限制御を実装するため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 にカテゴリとタグを保存する 2 つの新しいテーブルを作成します。

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 コードに新しいルートを作成して、カテゴリとタグを取得および作成するリクエストと、カテゴリとタグで記事をフィルタリングするリクエストを処理します。

ユーザー登録とログインのフロントエンド処理

フロントエンドでは、まずサインアップおよびログイン機能用の 2 つの新しい Vue コンポーネント、Register.vueおよびを作成する必要がありますLogin.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"、フォームのデフォルトの送信動作を防止し、registerまたはloginメソッドを呼び出すために使用されます。

コメントのフロントエンド処理

コメント機能については、記事詳細ページにコメントフォームとコメント一覧を追加する必要があります。

まず、次のコードを記事の詳細コンポーネント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