1. 程式人生 > >golang(4)使用beego + ace admin 開發後臺系統 CRUD

golang(4)使用beego + ace admin 開發後臺系統 CRUD

1,關於ace admin

ace admin 是一個非常好的後臺系統ui。
集成了很多的好東西。非常的方便開發後天系統,而且能很漂亮。
上面有一堆的例子。非常的漂亮。
http://ace.jeka.by/

之前還是收費的。後來在github 上面放了一個專案。
但是沒有原始碼。是壓縮之後的程式碼。而且,付費地址也不再了。
是一個過期了的模板 3 年前的了。
github 地址:
https://github.com/bopoda/ace
專案已經沒有人維護了。也沒有原始碼了,原來的購買地址都沒有了。做公司的後天系統沒啥問題了。
比起其他的也沒感覺上不潮但比起原生的 bootstrap 要好看點。
已經不錯了,還要啥自行車呢。
我寫了一個 go-admin 的demo :
專案地址:

https://github.com/golangpkg/go-admin
程式碼都上傳上去了。

2,做一個 golang的後臺管理足夠了

專案使用beego 進行開發,使用beego開發還是非常的快速的。
將專案 ace 程式碼 assets 下面的 4個 資料夾拷貝到 beego 專案的 static 資料夾下面:

css
font-awesome
images
js

專案幾算匯入了。其他兩個資料夾不加也罷。

3,model 儲存物件

儲存物件一個使用者表的設計:

CREATE TABLE `user_info` (
    `id` bigint(20
) NOT NULL AUTO_INCREMENT, `user_name` varchar(200) DEFAULT NULL, `password` varchar(200) DEFAULT NULL, `name` varchar(200) DEFAULT NULL, `birth_date` varchar(200) DEFAULT NULL, `gender` int(1) DEFAULT NULL, `email` varchar(200) DEFAULT NULL, `phone` varchar(200) DEFAULT NULL, `status`
tinyint(1) NOT NULL , `create_time` datetime NOT NULL, `update_time` datetime NOT NULL, UNIQUE KEY `user_name` (`key`), PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

一個簡單的使用者表
對應的資料操作:

package models

import (
    "github.com/astaxie/beego/orm"
    "github.com/astaxie/beego/logs"
    "time"
)

type UserInfo struct {
    Id         int64  `orm:"auto"`
    UserName   string `orm:"size(255)"`    //登入名
    Password   string `orm:"size(255)"`    //密碼
    Name       string `orm:"size(255)"`    //使用者名稱
    BirthDate  string `orm:"size(255)"`    //生日
    Gender     int8       //性別
    Email      string `orm:"size(255)"`    //Email
    Phone      string `orm:"size(255)"`    //電話
    Status     int8     //狀態
    CreateTime time.Time //建立時間
    UpdateTime time.Time  //更新時間
}

func init() {
    orm.RegisterModel(new(UserInfo))
}

//建立&更新
func SaveUserInfoById(m *UserInfo) (err error) {
    o := orm.NewOrm()
    var num int64
    if m.Id == 0 {
        m.CreateTime = time.Now()
        m.UpdateTime = time.Now()
        if num, err = o.Insert(m); err == nil {
            logs.Info("Number of records insert in database:", num)
        }
    } else {
        var tmp *UserInfo
        tmp, err = GetUserInfoById(m.Id)

        if err == nil {

            //修改幾個引數的名稱。
            tmp.UserName = m.UserName
            tmp.Name = m.Name
            tmp.BirthDate = m.BirthDate
            tmp.Gender = m.Gender
            tmp.Email = m.Email
            tmp.Phone = m.Phone
            tmp.Status = m.Status
            tmp.UpdateTime = time.Now()

            if num, err = o.Update(tmp); err == nil {
                logs.Info("Number of records updated in database:", num)
            }
        }
    }
    return
}

//刪除
func DeleteUserInfo(id int64) (err error) {
    o := orm.NewOrm()
    v := UserInfo{Id: id}
    if err = o.Read(&v, "Id"); err == nil {
        if num, err := o.Delete(&UserInfo{Id: id}); err == nil {
            logs.Info("Number of records deleted in database:", num)
        }
    }
    return
}

//按id查詢
func GetUserInfoById(id int64) (v *UserInfo, err error) {
    o := orm.NewOrm()
    v = &UserInfo{Id: id}
    if err = o.Read(v, "Id"); err == nil {
        return v, nil
    }
    return nil, err
}

//查詢資料
func QueryAllUserInfo() (dataList []interface{}, err error) {
    var list []UserInfo
    o := orm.NewOrm()
    qs := o.QueryTable(new(UserInfo))
    //查詢
    //查詢資料
    if _, err = qs.All(&list); err == nil {
        for _, v := range list {
            dataList = append(dataList, v)
        }
        return dataList, nil
    }
    return nil, err
}

參考了bee go 自動生成的程式碼。但是發現beego 升級了之後模板變了。
其中特別要主要 := 的坑,如果稍不留神就會替換掉物件在一個作用域下,而且不會報錯呢。

4,controller 控制

package controllers

import (
    "github.com/astaxie/beego/logs"
    "github.com/astaxie/beego"
    "github.com/freewebsys/go-admin/models"
)

type UserInfoController struct {
    beego.Controller
}

//修改
func (c *UserInfoController) Edit() {
    //獲得id
    id, _ := c.GetInt64("Id", 0)
    userInfo, err := models.GetUserInfoById(id)
    if err == nil {
        c.Data["UserInfo"] = userInfo
    } else {
        tmpUserInfo := &models.UserInfo{}
        tmpUserInfo.Status = -1
        tmpUserInfo.Gender = -1
        c.Data["UserInfo"] = tmpUserInfo
    }
    c.TplName = "userInfo/edit.html"
}

//刪除
func (c *UserInfoController) Delete() {
    //獲得id
    id, _ := c.GetInt64("Id", 0)
    if err := models.DeleteUserInfo(id); err == nil {
        c.Data["json"] = "ok"
    } else {
        c.Data["json"] = "error"
    }
    c.ServeJSON()
}

//儲存
func (c *UserInfoController) Save() {
    //自動解析繫結到物件中
    userInfo := models.UserInfo{}
    if err := c.ParseForm(&userInfo); err == nil {
        if err := models.SaveUserInfoById(&userInfo); err == nil {
            c.Data["json"] = ""
        } else {
            c.Data["json"] = "error"
        }
    } else {
        c.Data["json"] = "error"
    }
    c.ServeJSON()
}

//返回全部資料
func (c *UserInfoController) List() {

    dataList, err := models.QueryAllUserInfo()
    if err == nil {
        c.Data["List"] = dataList
    }
    logs.Info("dataList :", dataList)
    c.TplName = "userInfo/list.html"

}

5,view 展示

<table id="simple-table" class="table  table-bordered table-hover">
                                    <tr>
                                        <th>Id</th>
                                        <th>姓名</th>
                                        <th>生日</th>
                                        <th>性別</th>
                                        <th>Email</th>
                                        <th>電話</th>
                                        <th>狀態</th>
                                        <th>建立時間</th>
                                        <th>更新時間</th>
                                        <th>操作</th>
                                    </tr>
                                    {{range .List}}
                                    <tr>

                                        <td>{{.Id}}</td>
                                        <td>{{.Name}}</td>
                                        <td>{{.BirthDate}}</td>
                                        <td>{{.Gender}}</td>
                                        <td>{{.Email}}</td>
                                        <td>{{.Phone}}</td>
                                        <td>{{.Status}}</td>
                                        <td>{{date .CreateTime "2006-01-02 15:04:05"}}</td>
                                        <td>{{date .UpdateTime "2006-01-02 15:04:05"}}</td>

                                        <td>
                                            <div class="hidden-sm hidden-xs btn-group">
                                                <button class="btn btn-xs btn-info" onclick="showEditWindow('{{.Id}}');">
                                                    <i class="ace-icon fa fa-pencil bigger-120"></i>
                                                </button>
                                                <button class="btn btn-xs btn-danger" onclick="deleteConfirm('{{.Id}}');">
                                                    <i class="ace-icon fa fa-trash-o bigger-120"></i>
                                                </button>
                                            </div>
                                        </td>
                                    </tr>
                                    {{end}}
                                </table>

特別注意對時間欄位的格式化:{{date .UpdateTime “2006-01-02 15:04:05”}} 不是java習慣的 yyyy-MM-dd
感覺上一點也不好記。是按照老外的習慣記住的 1 2 3 4 5 6 的規則命名的。

建立& 編輯:

將物件放到 data裡面,然後做展示編輯。

<div class="col-sm-9">
                        <input type="text" id="UserName" name="UserName" placeholder="登入名" class="col-xs-10 col-sm-5"
                               value="{{.UserInfo.UserName}}"/>
                    </div>
jQuery(function ($) {
        $('#saveForm').validate({
            errorElement: 'div',
            errorClass: 'help-block',
            focusInvalid: false,
            ignore: "",
            rules: {
                UserName: {
                    required: true,
                }
            },
            highlight: function (e) {
                $(e).closest('.form-group').removeClass('has-info').addClass('has-error');
            },
            success: function (e) {
                $(e).closest('.form-group').removeClass('has-error');//.addClass('has-info');
                $(e).remove();
            }
        });
    });
    //儲存,之前進行校驗
    function save() {
        if ($('#saveForm').valid()) {
            $.post("/admin/userInfo/save", $("#saveForm").serialize(),
                function (data) {
                    window.location.reload();
                });
        }
    }

7,攔截器

//增加攔截器。
    var filterAdmin = func(ctx *context.Context) {
        url := ctx.Input.URL()
        logs.Info("##### filter url : %s", url)
        //TODO 如果判斷使用者未登入。

    }
    beego.InsertFilter("/admin/*", beego.BeforeExec, filterAdmin)

可以針對 /admin/* 進行攔截

8,關閉防火牆

在 mac 上面發現總是要允許埠,開發比較討厭,請關閉防火牆:

這裡寫圖片描述

6,總結

beego 開發一個admin系統還是挺快的。
因為beego 可以自動檢查程式碼改的,自動重啟,開發速度還是很快的。
並且因為beego的編譯啟動還是非常的快速的。
所以開發速度還是挺快的。golang的程式碼還需要適應下。上手還是挺快的。1,2個星期就能開發一個小系統。
做個使用者許可權,登入啥的都非常方便。