手记

beego开发轻博客——第五讲 文章录入

前台页面

1. 我们采用“ wangeditor”作为 富文本编辑器 编辑器

wangEditor 是一款 轻量级 web 富文本编辑器。配置方便,使用简单。支持 IE10+ 浏览器。

2 新增 views->note_new.html 文件,核心代码如下
<body class="lay-blog">
        ...
    <form class="layui-form layui-form-pane" action="">        <div class="layui-form-item">
            <label class="layui-form-label">标题</label>
            <div class="layui-input-block">
                <input type="text" name="title" required=""
                        value=""
                        lay-verify="required" placeholder="请输入标题"
                        autocomplete="off" class="layui-input">
            </div>
        </div>

        <div class="layui-form-item layui-form-text">
            <label class="layui-form-label">内容</label>
            <div class="layui-input-block">
                <div id="edit"></div>
            </div>
        </div>
        <div class="layui-form-item">
            <button class="layui-btn" lay-submit=""
                    lay-filter="save">提交            </button>
        </div>
    </form>
       ...



页面效果如下:

image.png

3. wangEditor使用

我们只需要引入wangEditor.min.js 文件,调用window.wangEditor("元素id").create() 就可 初始化富文本页面 。我继续修改views->note_new.html 文件。

<body>...<form>... <div id="edit"><div> ...</form>...
{{template "comm/footer.html" .}}<script type="text/javascript" src="/static/lib/wangEditor/wangEditor.min.js"></script><script>
    layui.use([...], function () {
        ...        // 初始化 wangEditor
        var E = window.wangEditor;        var editor = new E('#edit');      // 图片不采用上传模式,直接保存到数据库
        editor.customConfig.uploadImgShowBase64 = true;
        editor.customConfig.pasteFilterStyle = false;
        editor.customConfig.zIndex = 1;
        editor.create();
    });</script>

定义数据库表

新增models->note.go 定义文章表,代码如下
type Note struct {
    gorm.Model
    Key     string `gorm:"unique_index;not null;"` //文章唯一标示
    UserID  int // 用户id
    User    User  //用户
    Title   string //文章标题
    Summary string `gorm:"type:text"` //概要
    Content string `gorm:"type:text"` //文章内容
    Visit   int    `gorm:"default:0"` //浏览次数
    Praise  int    `gorm:"default:0"` // 点赞次数}

新增文章的页面显示

1.  我们需要为文章新增页面添加路由路径,以此我们新增一个新的NoteController控制器。新增 controllers->note.go文件添加如下代码
type NoteController struct {
    BaseController
}// @router /new [get]func (ctx *NoteController) NewPage() {
    ctx.Data["key"] = uuid.NewUUID().String()
    ctx.TplName = "note_new.html"}

上面代码中有个ctx.Data["key"] = uuid.NewUUID().String()。试想如果用户打开新增文章页面后,维护好数据,当点击保存按钮时候,不小心多点几次,难道系统就会多新增几个重复的文章记录?因此,我们添加了ctx.Data["key"] = uuid.NewUUID().String() 使每打开新增文章页面都会有一个唯一的key 在当前页面上。当点击保存时,会将页面key传回到后台,这样后台可以更具key开判断用户是新增还是修改!刚才说的情况用户多次点击,第一次是新增,之后都是修改。

2. 与文章调整相关的功能,必须是登陆的用户,且登陆的用户的必须是管理员。我们修改 NoteController控制器,添加NestPrepare方法。每次发送的请求,当路由到NoteController控制器相应的方法时,都会去调用NestPrepare方法,用来添加判断用户必须登陆且为管理员。修改controllers->note.go,代码如下
func (ctx *NoteController) NestPrepare() {
    ctx.MustLogin()//用户必须登陆,没有登陆就返回错误
    if ctx.User.Role != 0 {//不是管理员,之前返回错误
        ctx.Abort500(syserrors.NewError("您没有权限修改文章", nil))
    }
}
3. 我们采用的beego的注解路由,我需要将NoteController控制器 注入beego的Include上。修改routers->router.go文件,修改如下:
func init() {
    ...
    beego.AddNamespace(
        beego.NewNamespace(            "note",
            beego.NSInclude(&controllers.NoteController{}),
        ),
    )
}

到此,新增文章的路由路径为:note/new

4. 添加新增文章的操作入口->修改用户管理页面(views->user.html) 添加按钮,点击跳转到文章新增页面。修改views->user.html文件,修改代码如下:
...
{{if .IsLogin}}
    ...
  {{if eq .User.Role 0}}    <h4 class="item-title">
        <p>
            <a href="/note/new"><i class="layui-icon layui-icon-add-1">&#xe654;</i><span>新增文章</span></a>
        </p>
    </h4>{{end}}
...

新增文章的页面保存功能

1. 我们新约定 文章新增的路由路径为:/note/save/:key
2. 添加页面逻辑,当保存时,我们将页面用户维护的文章数据用ajax发送post请求到后台服务,服务对于的路径为/note/save/:key,我们需要修改views->note_new.html文件,添加如下代码
...<script>
    layui.use(['form', 'jquery', 'layer', 'sysn'], function () {
        ...
      form.on('submit(save)', function (fromdata) {
        sysn.post("/note/save/{{.key}}", fdata)
            .success(function (data) {
               layer.msg("保存成功!");               if (data.action) {
                    setTimeout(function () {                         window.location.href = data.action;
                    }, 300)
               }
            }).run();
      }
}</script>...
3. 调整数据库

3.1 我们之前定义的文章的数据库中表结构中key是不能重复的,是作为文章的唯一标示。因此我们新增的时候都需要先判断 key是否存在,如果存在就更新不存在就新增。我们修改models->note.go 添加按key查询文章的方法。

func QueryNoteByKeyAndUserId(key string, userid int) (note Note, err error) {    return note, db.Model(&Note{}).Where("key = ? and user_id = ?", key, userid).Take(&note).Error
}

3.2 需要将文章的数据保存到数据库,因此我们要新增方法,用来保存文章数据。代码如下:

func SaveNote(n *Note) error {    return db.Save(n).Error
}
4. 调整控制器NoteController

4.1 将来我们需要将文章在首页列出来,我们不能将文章的所有的内容都显示在首页,因此我们需要截取文章前600个字作为文章的摘要保存到数据库。这里我们用到golang的第三方库github.com/PuerkitoBio/goquery,用来解析文章的html文档。修改controllers->note.go 添加截取文章摘要的方法,代码如下。

// 截取content摘要//content >文章 > html文档func getSummary(content string) (string, error) {   // bytes.Buffer,非常常用。
    var buf bytes.Buffer
    buf.Write([]byte(content))    // 用goquery来解析content
    doc, err := goquery.NewDocumentFromReader(&buf)    if err != nil {        return "", err
    }    // Text() 得到body元素下的文本内容(去掉html元素)
    str := doc.Find("body").Text()    // 截取字符串
    if len(str) > 600 {
        str = str[0:600] + "..."
    }    return str, nil
}

4.1 新增保存文章的方法 ,修改controllers->note.go ,代码如下

// @router /save/:key [post]func (ctx *NoteController) Save() {    //得到页面的传过来 key 
    key := ctx.Ctx.Input.Param(":key")    // 判空,为空就返回错误。
    title := ctx.GetMustString("title", "标题不能为空!")
    content := ctx.GetMustString("content", "内容不能为空!")    //获取文章摘要
    summary, _ := getSummary(content)    // 根据key查询文章
    note, err := ctx.Dao.QueryNoteByKeyAndUserId(key, int(ctx.User.ID))
    var n models.Note    if err != nil {        //存在错误,但是当错误不是查不到数据的错误,那就返回错误
        if err != gorm.ErrRecordNotFound {
            ctx.Abort500(syserrors.NewError("保存失败!", err))
        }       // 查不到数据,那就做新增文章操作
        n = models.Note{
            Key:     key,
            Summary: summary,
            Title:   title,
            Files:   files,
            Content: content,
            UserID:  int(ctx.User.ID),
        }
    } else {        //查询不报错,这存在文章,那就做更新文章操作
        n = note
        n.Title = title
        n.Content = content
        n.Summary = summary
        n.Files = files
        n.UpdatedAt = time.Now()
    }    //保存文章 SaveNote 是根据id来判断是更新还是新增,id存在就更新,不存在就新增。
   //上面更新操作是,从数据库查出来的文章记录,修改数据,所以是存在id的。
    if err := ctx.Dao.SaveNote(&n); err != nil {
        ctx.Abort500(syserrors.NewError("保存失败!", err))
    }
    ctx.JSONOk("成功")
}



作者:qq归位
链接:https://www.jianshu.com/p/fb0a69412c3d


0人推荐
随时随地看视频
慕课网APP