beego搭建個人部落格(二)

lightTrace發表於2018-03-29

今天基於 beego搭建個人部落格(一)把部落格的後臺管理的部分完成了,然後我的邏輯不一定是最合適的,可能寫的比較亂,大家可以根據原始碼分支https://github.com/lightTrace/beego-blog/tree/blog-dev1來自己搭建

後臺效果:
這裡寫圖片描述

一 models

分類model,category .go

package models

import "time"

type Category struct {
    Id int
    Name string
    Created time.Time
    Updated time.Time
}

func (m *Category) TableName() string {
    return TableName("category")
}

配置model,cofig.go:

package models

type Config struct {
    Id    int
    Name  string
    Value string
}

func (m *Config) TableName() string {
    return TableName("config")
}

文章model,post.go:

package models

import "time"

type Post struct {
    Id int
    UserId int
    Title string
    Url string
    Content string
    Tags string
    Views int
    IsTop int8
    Created time.Time
    Updated time.Time
    CategoryId int
    Status int8
    Types int8
    Info string
    Image string
}

func (m *Post) TableName() string {
    return TableName("post")
}

首先在controller資料夾中完善admin.go檔案:
–首先新增登出邏輯:

func (c *AdminController) logout {
    c.DestroySession();
    c.History("退出登入","/admin/login.html")
}

–然後部落格配置資訊邏輯:

//配置資訊
func (c *AdminController) Config()  {
    var result []*models.Config
    c.o.QueryTable(new(models.Config).TableName()).All(&result)
    options := make(map[string]string)
    mp := make(map[string]*models.Config)
    for _, v := range result {
        options[v.Name] = v.Value
        mp[v.Name] = v
    }
    if c.Ctx.Request.Method == "POST" {
        keys := []string{"url", "title",  "keywords", "description", "email", "start", "qq"}
        for _, key := range keys {
            val := c.GetString(key)
            if _, ok := mp[key]; !ok {
                options[key] = val
                c.o.Insert(&models.Config{Name:key, Value:val})
            } else {
                opt := mp[key]
                if _, err := c.o.Update(&models.Config{Id:opt.Id, Name:opt.Name, Value:val}); err != nil {
                    continue;
                }
            }
        }
        c.History("設定資料成功","")
    }
    c.Data["config"] = options
    c.TplName = c.controllerName + "/config.html"
}

配置資訊頁面config.html:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>配置</title>
    <link rel="stylesheet" href="/static/plug/layui/css/layui.css">
</head>
<body>

<script type="text/javascript" src="/static/plug/layui/layui.js"></script>

<form class="layui-form" action="/admin/config.html" style="margin:20px" method="post">
    <div class="layui-form-item">
        <label class="layui-form-label">標題:</label>
        <div class="layui-input-block">
            <input name="title" lay-verify="required"  value="{{.config.title}}" class="layui-input" title="網站名稱" type="text" />
        </div>
    </div>

    <div class="layui-form-item">
        <label class="layui-form-label">網址:</label>
        <div class="layui-input-block">
            <input name="url"   lay-verify="required|url" class="layui-input"  value="{{.config.url}}"  title="網址" type="text" />
        </div>
    </div>

    <div class="layui-form-item">
        <label class="layui-form-label">關鍵字:</label>
        <div class="layui-input-block">
            <input name="keywords"  class="layui-input" value="{{.config.keywords}}" title="關鍵字" type="text" />
        </div>
    </div>

    <div class="layui-form-item">
        <label class="layui-form-label">描述:</label>
        <div class="layui-input-block">
            <input name="description"  class="layui-input" value="{{.config.description}}"  title="描述" type="text" />
        </div>
    </div>

    <div class="layui-form-item">
        <label class="layui-form-label">郵箱:</label>
        <div class="layui-input-block">
            <input name="email"  lay-verify="email"  class="layui-input" value="{{.config.email}}" class="input-xlarge" title="郵箱" type="text" />
        </div>
    </div>

    <div class="layui-form-item">
        <label class="layui-form-label">qq:</label>
        <div class="layui-input-block">
            <input name="qq" lay-verify="number"  class="layui-input" value="{{.config.qq}}" class="input-xlarge" title="qq" type="text" />
        </div>
    </div>

    <div class="layui-form-item">
        <label class="layui-form-label">開關:</label>
        <div class="layui-input-block">
            <input type="checkbox" name="start" {{if .config.start}} checked {{end}} value="1" title="開關" >
        </div>
    </div>

    <div class="layui-form-item">
        <div class="layui-input-block">
            <button class="layui-btn" lay-submit lay-filter="formDemo">提交</button>
            <button type="reset" class="layui-btn layui-btn-primary">重置</button>
        </div>
    </div>
</form>

<script>
    //Demo
    layui.use('form', function(){


    });
</script>
</body>
</html>

–然後類別管理邏輯:

//類別
func (c *AdminController) Category() {
    categorys := [] *models.Category{}
    c.o.QueryTable(new(models.Category).TableName()).All(&categorys)//查詢所有類別
    c.Data["categorys"] = categorys
    c.TplName = c.controllerName+"/category.tpl"
}

類別頁面:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>類目列表</title>
    <link rel="stylesheet" href="/static/plug/layui/css/layui.css">
</head>
<body>
<div class=" layui-inline" style="float: right; margin: 10px;">
    <button class="layui-btn " onclick="add()">
        <i class="layui-icon">&#xe608;</i> 新增
    </button>
</div>

<table class="layui-table" lay-skin="row">
    <colgroup>
        <col >
        <col>
        <col>
    </colgroup>
    <thead>
    <tr>
        <th>名稱</th>
        <th>新增時間</th>
        <th>修改時間</th>
        <th>操作</th>
    </tr>
    </thead>
    <tbody>
    {{range $k, $v := .categorys}}
    <tr>
        <td>{{$v.Name}}</td>
        <td>{{$v.Created}}</td>
        <td>{{$v.Updated}}</td>
        <td>
            <a href="/admin/categoryadd.html?id={{$v.Id}}" >
                <i class="layui-icon">&#xe642;</i> 修改
            </a>
            <a href="javascript:void(0)" onclick="del({{$v.Id}})"  >
                <i class="layui-icon">&#x1006;</i> 刪除
            </a>
        </td>
        {{end}}
    </tr>
    </tbody>
</table>

<script type="text/javascript" src="/static/plug/layui/layui.js"></script>
</body>
<script>
    function add() {
        location.href = "/admin/categoryadd.html"
    }

    function del(id)
    {
        if(confirm("確定要刪除嗎?"))
        {
            var url = "/admin/categorydel.html?id="+id;
            window.location.href=url;
        }
    }
</script>
</html>

–類別新增跳轉:

//新增類別
func (c *AdminController) Categoryadd() {
    id := c.Input().Get("id")
    if id != "" {
        intId, _ := strconv.Atoi(id)
        cate := models.Category{Id: intId}//根據id回顯該類別資料
        c.o.Read(&cate)
        c.Data["cate"] = cate
    }
    c.TplName = c.controllerName + "/category_add.tpl"
}

新增類別頁面:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>新增類目</title>
    <link rel="stylesheet" href="/static/plug/layui/css/layui.css">
</head>
<body>
<script type="text/javascript" src="/static/plug/layui/layui.js"></script>
<form class="layui-form" action="/admin/categorysave.html" style="margin:20px" method="post">
    <div class="layui-form-item">
        <label class="layui-form-label">標題:</label>
        <div class="layui-input-block">
            <input name="id" type="hidden" value="{{.cate.Id}}">
            <input type="text" name="name" value="{{.cate.Name}}" required  lay-verify="required" placeholder="請輸入標題" autocomplete="off" class="layui-input">
        </div>
    </div>

    <div class="layui-form-item">
        <div class="layui-input-block">
            <button class="layui-btn" lay-submit lay-filter="formDemo">提交</button>
            <button type="reset" class="layui-btn layui-btn-primary">重置</button>
        </div>
    </div>
</form>
</body>
</html>

–插入、修改及刪除類別邏輯:

//處理插入資料的欄位
func (c *AdminController) CategorySave() {
    name := c.Input().Get("name");
    id := c.Input().Get("id")
    category := models.Category{}
    category.Name = name
    if id == "" {
        if _, err := c.o.Insert(&category); err != nil {
            c.History("插入資料錯誤", "")
        } else {
            c.History("插入資料成功", "/admin/category.html")
        }
    } else {
        intId, err := strconv.Atoi(id);
        if err != nil {
            c.History("引數錯誤", "")
        }
        category.Id = intId
        if _, err := c.o.Update(&category); err != nil {
            c.History("更新資料出錯", "")
        } else {
            c.History("插入資料成功", "/admin/category.html")
        }
    }
}

func (c *AdminController) CategoryDel() {
    id, err := strconv.Atoi(c.Input().Get("id"));
    if err != nil {
        c.History("引數錯誤", "")
    }else{
        if _,err := c.o.Delete(&models.Category{Id:id}); err !=nil{
            c.History("未能成功刪除", "")
        }else {
            c.History("刪除成功", "/admin/category.html")
        }
    }
}

–部落格列表邏輯

//後臺首頁
func (c *AdminController) Index() {
    categorys := [] *models.Category{}
    c.o.QueryTable( new(models.Category).TableName()).All(&categorys)
    c.Data["categorys"] = categorys
    var (
        page       int
        pagesize   int = 8
        offset     int
        list       []*models.Post
        keyword    string
        cateId int
    )
    keyword = c.GetString("title")
    cateId, _ = c.GetInt("cate_id")
    if page, _ = c.GetInt("page"); page < 1 {
        page = 1
    }
    offset = (page - 1) * pagesize
    //c.Ctx.WriteString(new(models.Post).TableName())
    query := c.o.QueryTable(new(models.Post).TableName())
    if keyword != "" {
        query = query.Filter("title__contains", keyword)
    }
    count, _ := query.Count()
    if count > 0 {
        query.OrderBy("-is_top", "-created").Limit(pagesize, offset).All(&list)
    }
    c.Data["keyword"] = keyword
    c.Data["count"] = count
    c.Data["list"] = list
    c.Data["cate_id"] = cateId
    c.Data["pagebar"] = util.NewPager(page, int(count), pagesize,
        fmt.Sprintf("/admin/index.html?keyword=%s", keyword), true).ToString()
    c.TplName = c.controllerName + "/list.tpl"
}

–部落格列表頁面list.tpl:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>個人部落格列表</title>
    <link rel="stylesheet" href="/static/plug/layui/css/layui.css">
</head>
<body>
<div class="layui-form" action="" style="margin: 5px; border: 1px silver">

    <div class="layui-inline">
        <label class="layui-form-label">選擇類別</label>
        <div class="layui-input-block">
            <select name="cate_id" lay-verify="required">
                {{range .categorys}}
                <option value="{{.Id}}" >{{.Name}}</option>
                {{end}}
            </select>
        </div>
    </div>

    <div class="layui-inline">
        <label class="layui-form-label">密碼</label>
        <div class="layui-input-block">
            <input type="text" name="title" placeholder="請輸入標題" autocomplete="on" class="layui-input">
        </div>
    </div>

    <div class=" layui-inline">
        <button class="layui-btn layui-btn-normal  ">
            搜尋
        </button>
    </div>

    <div class=" layui-inline" style="float: right">
        <button class="layui-btn " onclick="add()">
            <i class="layui-icon">&#xe608;</i> 新增
        </button>
    </div>

</div>

<table class="layui-table" lay-skin="row">
    <thead>
    <tr>
        <th>標題</th>
        <th>時間</th>
        <td>置頂</td>
        <th>點選量</th>
        <th>操作</th>
    </tr>
    </thead>
    <tbody>
    {{range .list}}
    <tr>
        <td>{{.Title}}</td>
        <td>{{.Created}}</td>
        <td>
            {{if .IsTop}}
            <i class="icon-arrow-up" title="置頂"> </i>
            {{else}}
                普通
            {{end}}
        </td>
        <td>
            {{.Views}}
        </td>
        <td>
            <a href="/admin/article?id={{.Id}}" >
                <i class="layui-icon">&#xe642;</i> 修改
            </a>
            <a href="javascript:void(0)" onclick="del({{.Id}})"  >
                <i class="layui-icon">&#x1006;</i> 刪除
            </a>
        </td>
    </tr>
    {{end}}
    </tbody>
</table>

<div class="layui-box layui-laypage layui-laypage-default" id="layui-laypage-0">
    {{str2html .pagebar}}
</div>
<script type="text/javascript" src="/static/plug/layui/layui.js"></script>
</body>

<script>

    //Demo
    layui.use('form', function () {
        var form = layui.form();
        var layer = layui.layer;
        //監聽提交
        form.on('submit(formDemo)', function (data) {
            layer.msg(JSON.stringify(data.field));
            return false;
        });
    });
    var add = function () {
        location.href = "/admin/article"
    }

    function del(id)
    {
        if(confirm("確定要刪除嗎?"))
        {
            var url = "/admin/delete.html?id="+id;
            window.location.href=url;
        }
    }

</script>


</html>

–指定部落格刪除邏輯:

func (c *AdminController) Delete() {
    id, err := strconv.Atoi(c.Input().Get("id"));
    if err != nil {
        c.History("引數錯誤", "")
    }else{
        if _,err := c.o.Delete(&models.Post{Id:id}); err !=nil{
            c.History("未能成功刪除", "")
        }else {
            c.History("刪除成功", "/admin/index.html")
        }
    }
}

–部落格新增邏輯

//文章
func (c *AdminController) Article() {
    categorys := [] *models.Category{}
    c.o.QueryTable( new(models.Category).TableName()).All(&categorys)
    id, _ := c.GetInt("id")
    if id != 0{
        post := models.Post{Id:id}
        c.o.Read(&post)
        c.Data["post"] = post
    }
    c.Data["categorys"] = categorys
    c.TplName = c.controllerName + "/_form.tpl"
}

部落格新增或者修改頁面_form.tpl:

//儲存
func (c * AdminController) Save()  {
    post := models.Post{}
    post.UserId = 1
    post.Title = c.Input().Get("title")
    post.Content = c.Input().Get("content")
    post.IsTop,_ = c.GetInt8("is_top")
    post.Types,_ = c.GetInt8("types")
    post.Tags = c.Input().Get("tags")
    post.Url = c.Input().Get("url")
    post.CategoryId, _ = c.GetInt("cate_id")
    post.Info = c.Input().Get("info")
    post.Image = c.Input().Get("image")
    post.Created = time.Now()
    post.Updated = time.Now()

    id ,_ := c.GetInt("id")
    if id == 0 {
        if _, err := c.o.Insert(&post); err != nil {
            c.History("插入資料錯誤"+err.Error(), "")
        } else {
            c.History("插入資料成功", "/admin/index.html")
        }
    }else {
        post.Id = id
        if _, err := c.o.Update(&post); err != nil {
            c.History("更新資料出錯"+err.Error(), "")
        } else {
            c.History("插入資料成功", "/admin/index.html")
        }
    }
}

–上傳照片邏輯:

//上傳介面
func (c *AdminController) Upload() {
    f, h, err := c.GetFile("uploadname")
    result := make(map[string]interface{})
    img := ""
    if err == nil {
        exStrArr := strings.Split(h.Filename, ".")
        exStr := strings.ToLower(exStrArr[len(exStrArr)-1])
        if exStr != "jpg" && exStr!="png" && exStr != "gif" {
            result["code"] = 1
            result["message"] = "上傳只能.jpg 或者png格式"
        }
        img = "/static/upload/" + util.UniqueId()+"."+exStr;
        c.SaveToFile("upFilename", img) // 儲存位置在 static/upload, 沒有資料夾要先建立
        result["code"] = 0
        result["message"] =img
    }else{
        result["code"] = 2
        result["message"] = "上傳異常"+err.Error()
    }
    defer f.Close()
    c.Data["json"] = result
    c.ServeJSON()
}

到這裡後臺管理功能大概完了,我們還有前臺給別人看的模組,把框架和前面一樣往上面套就行了,完整程式碼在另一個分支:https://github.com/lightTrace/beego-blog/tree/blog-dev2

就是有點不一樣的是,在前臺路由註冊中,我選擇了手動註冊,大家看看有什麼不同:

package routers

import (
    "github.com/Echosong/beego_blog/controllers"
    "github.com/astaxie/beego"
)

func init() {

    beego.Router("/", &controllers.BlogController{}, "*:Home")
    beego.Router("/home", &controllers.BlogController{}, "*:Home")
    beego.Router("/article", &controllers.BlogController{}, "*:Article")
    beego.Router("/detail", &controllers.BlogController{}, "*:Detail")
    beego.Router("/about", &controllers.BlogController{}, "*:About")
    beego.Router("/timeline", &controllers.BlogController{}, "*:Timeline")
    beego.Router("/resource", &controllers.BlogController{}, "*:Resource")
    beego.Router("/comment", &controllers.BlogController{}, "post:Comment")

    beego.AutoRouter(&controllers.AdminController{})
}

前臺效果:
這裡寫圖片描述

這裡順便帶一腳如何windows如何安裝zip版本的mysql,注意是5.6及以下,5.7以上的安裝方式會多一個initialize的步驟
安裝zip版本的mysql

相關文章