
背景:想在自己的vps上搭建一个个人博客系统,之前自己用宝塔+WordPress 搭建过一个不过 

还是想自己用golang做个真正属于自己的博客系统,于是就有了标题所述....

下面是组件部分:
- 导航:
- <template>
- <div class="app-bar">
- <div class="left-links">
- <router-link v-for="link in activeLinks" :key="link.name" :to="link.to" class="app-bar-item">
- {{ link.name }}
- </router-link>
- </div>
- <div class="right-links ">
- <router-link class="app-bar-item" href="#" v-if="!loggedIn" @click.prevent :to="{ name: 'Login' }">LOGIN</router-link>
- <a class="app-bar-item" href="#" v-if="loggedIn" @click.prevent="logoutButtonClicked">LOGOUT</a>
- </div>
- </div>
- </template>
-
- <script>
- import { mapActions, mapGetters } from "vuex";
- export default {
- data() {
- return {
- links: [
- {
- visibleIfLoggedOut: true,
- name: "Posts",
- to: {name: "Posts"}
- },
- {
- visibleIfLoggedOut: false,
- name: "User",
- to: {
- name: "User",
- params: {
- userid: this.$store.getters["auth/currentUser"].username
- }
- }
- }
- ]
- };
- },
- methods: {
- ...mapActions({
- login: "auth/login", // map `this.login()` to `this.$store.dispatch('auth/login')`
- logout: "auth/logout"
- }),
- logoutButtonClicked() {
- this.logout().then(() => {
- this.$router.push({name: "Login"});
- });
- }
- },
- computed: {
- ...mapGetters({loggedIn: "auth/isLoggedIn"}),
- activeLinks() {
- return this.links.filter(
- link => link.visibleIfLoggedOut || this.loggedIn
- );
- }
- }
- };
- </script>
-
- <style scoped>
- .app-bar {
- height: 5vh;
- width: 100%;
- position: fixed;
- z-index: 1;
- top: 0;
- left: 0;
- background-color: burlywood;
- overflow: hidden;
- display: block;
- justify-content: space-between;
- }
- .left-links {
- padding-left: 10%;
- }
- .left-links a {
- float: left;
- }
-
- a {
- float: left;
- display: block;
- color: #f2f2f2;
- text-align: center;
- padding: 14px 16px;
- text-decoration: none;
- font-size: 17px;
- }
- .right-links {
- float: right;
- }
- </style>
添加文章或者评论:
- <template>
- <form>
- <label v-if="showLabel" :for="'text' + this._uid">{{ textRequest }}</label>
- <input
- :id="'text' + this._uid"
- type="text"
- :placeholder="textRequest"
- v-model="textValue"
- />
- <button @click.prevent="submitted">submit</button>
- </form>
- </template>
-
- <script>
- export default {
- data() {
- return {
- textValue: ""
- };
- },
- props: {
- textRequest: { type: String, default: "" },
- showLabel: { type: Boolean, default: false }
- },
- methods: {
- submitted() {
- this.$emit("text-added", this.textValue);
- this.textValue = "";
- }
- },
- emits: ["text-added"]
- };
- </script>
-
- <style scoped>
- label {
- padding-right: 1rem;
- display: block;
- }
- button {
- margin-top: 1rem;
- width: 10%;
- border-top-right-radius: 8px;
- border-bottom-right-radius: 8px;
- background-color: darksalmon;
- padding: 8px;
- }
- input {
- box-sizing: border-box;
- border-top-left-radius: 8px;
- border-bottom-left-radius: 8px;
- width: 80%;
- padding: 8px 20px;
- }
- input:focus {
- outline: 0;
- background-color: wheat;
- }
- </style>
博文列表
- <template>
- <div>
- <h1>{{ title }}</h1>
- <div class="post-list" v-if="showPosts">
- <single-post v-for="post in posts" :key="post.id" :post="post">
- </single-post>
- </div>
- </div>
- </template>
-
- <script>
- import SinglePost from "@/components/SinglePost";
- export default {
- components: { SinglePost },
- props: ["posts", "title"],
- computed: {
- showPosts() {
- return this.posts && this.posts.length > 0;
- }
- }
- };
- </script>
- <style></style>
单个帖子
- <template>
- <base-card :expandable="post.comments && post.comments.length > 0">
- <template v-slot:header>
- <h3>
- <router-link :to="linkUser(post.username)">{{postTitle(post) }}</router-link>
- </h3>
- <button class="delete-button" @click.prevent="deletePost">Delete</button>
- </template>
- <div class="text-wrapper">Say:{{post.post }}</div>
- <template v-slot:footer>
- <base-card v-for="comment in post.comments" :key="comment.id" :expandable="false">
- <template v-slot:header>
- <h3>
- <router-link :to="linkUser(comment.username)">{{postTitle(comment)}}</router-link>
- </h3>
- </template>
- {{ comment.post }}
- </base-card>
- </template>
- <template v-if="loggedIn" v-slot:actions>
- <add-text-form textRequest="Add comment" :showLabel="false" @text-added="text => addComment(text, post)"></add-text-form>
- </template>
- </base-card>
- </template>
-
- <script>
- import {mapGetters} from "vuex";
- import BaseCard from "@/components/UI/BaseCard";
- import AddTextForm from "@/components/AddTextForm";
- export default {
- components: { BaseCard, AddTextForm },
- props: ["post"],
- name: "SinglePost",
- computed: {
- ...mapGetters({
- loggedIn: "auth/isLoggedIn",
- currentUser: "auth/currentUser"
- })
- },
- methods: {
- postTitle(post) {
- return post.username + "@" + post.date;
- },
- linkUser(username) {
- return {
- name: "User",
- params: {
- userid: username
- }
- };
- },
- addComment(text, post) {
- this.$store.dispatch("posts/addComment", {
- postId: post.id,
- comment: {
- username: this.currentUser.userid,
- post: text
- }
- });
- },
- deletePost() {
- this.$store.dispatch("posts/deletePost", {post: this.post});
- }
- }
- };
- </script>
- <style>
- .text-wrapper {
- white-space: pre-wrap;
- }
- </style>
...
后端代码:
- package endpoints
-
- import (
- "encoding/json"
- "github.com/gorilla/mux"
- "log"
- "net/http"
- )
-
- //AddRouterEndpoints add the actual endpoints for api
- func AddRouterEndpoints(r *mux.Router) *mux.Router {
- r.HandleFunc("/api/posts", getPosts).Methods("GET")
- r.HandleFunc("/api/posts", addPost).Methods("POST")
- r.HandleFunc("/api/posts/{POST_ID}", deletePost).Methods("DELETE")
- r.HandleFunc("/api/posts/{POST_ID}/comments", addComment).Methods("POST")
- return r
- }
-
- func sendJSONResponse(w http.ResponseWriter, data interface{}) {
- body, err := json.Marshal(data)
- if err != nil {
- log.Printf("Failed to encode a JSON response: %v", err)
- w.WriteHeader(http.StatusInternalServerError)
- return
- }
- w.Header().Set("Content-Type", "application/json; charset=UTF-8")
- w.WriteHeader(http.StatusOK)
- _, err = w.Write(body)
- if err != nil {
- log.Printf("Failed to write the response body: %v", err)
- return
- }
- }
...
完整的代码请留言...