前台页面
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"></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(¬e).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