feat:实现项目团队管理功能

This commit is contained in:
lifei6671 2018-11-13 17:33:13 +08:00
parent 0f705f0249
commit c666fcbed8
8 changed files with 220 additions and 172 deletions

View File

@ -1284,19 +1284,21 @@ func isReadable(identify, token string, c *DocumentController) *models.BookResul
beego.Error(err) beego.Error(err)
c.ShowErrorPage(500, "项目不存在") c.ShowErrorPage(500, "项目不存在")
} }
bookResult := models.NewBookResult().ToBookResult(*book)
isOk := false
if c.Member != nil {
roleId, err := models.NewBook().FindForRoleId(book.BookId, c.Member.MemberId)
if err == nil {
isOk = true
bookResult.MemberId = c.Member.MemberId
bookResult.RoleId = roleId
}
}
// 如果文档是私有的 // 如果文档是私有的
if book.PrivatelyOwned == 1 && !c.Member.IsAdministrator() { if book.PrivatelyOwned == 1 && !c.Member.IsAdministrator() {
is_ok := false
if c.Member != nil { if book.PrivateToken != "" && !isOk {
_, err := models.NewRelationship().FindForRoleId(book.BookId, c.Member.MemberId)
if err == nil {
is_ok = true
}
}
if book.PrivateToken != "" && !is_ok {
// 如果有访问的 Token并且该项目设置了访问 Token并且和用户提供的相匹配则记录到 Session 中。 // 如果有访问的 Token并且该项目设置了访问 Token并且和用户提供的相匹配则记录到 Session 中。
// 如果用户未提供 Token 且用户登录了,则判断用户是否参与了该项目。 // 如果用户未提供 Token 且用户登录了,则判断用户是否参与了该项目。
// 如果用户未登录,则从 Session 中读取 Token。 // 如果用户未登录,则从 Session 中读取 Token。
@ -1305,36 +1307,21 @@ func isReadable(identify, token string, c *DocumentController) *models.BookResul
} else if token, ok := c.GetSession(identify).(string); !ok || !strings.EqualFold(token, book.PrivateToken) { } else if token, ok := c.GetSession(identify).(string); !ok || !strings.EqualFold(token, book.PrivateToken) {
c.ShowErrorPage(403, "权限不足") c.ShowErrorPage(403, "权限不足")
} }
} else if !is_ok { } else if !isOk {
c.ShowErrorPage(403, "权限不足") c.ShowErrorPage(403, "权限不足")
} }
} }
bookResult := models.NewBookResult().ToBookResult(*book) //// 判断是否需要显示评论框
//if bookResult.CommentStatus == "closed" {
if c.Member != nil { // bookResult.IsDisplayComment = false
rel, err := models.NewRelationship().FindByBookIdAndMemberId(bookResult.BookId, c.Member.MemberId) //} else if bookResult.CommentStatus == "open" {
// bookResult.IsDisplayComment = true
if err == nil { //} else if bookResult.CommentStatus == "group_only" {
bookResult.MemberId = rel.MemberId // bookResult.IsDisplayComment = bookResult.RelationshipId > 0
bookResult.RoleId = rel.RoleId //} else if bookResult.CommentStatus == "registered_only" {
bookResult.RelationshipId = rel.RelationshipId // bookResult.IsDisplayComment = true
} else { //}
//TODO 团队权限
}
}
// 判断是否需要显示评论框
if bookResult.CommentStatus == "closed" {
bookResult.IsDisplayComment = false
} else if bookResult.CommentStatus == "open" {
bookResult.IsDisplayComment = true
} else if bookResult.CommentStatus == "group_only" {
bookResult.IsDisplayComment = bookResult.RelationshipId > 0
} else if bookResult.CommentStatus == "registered_only" {
bookResult.IsDisplayComment = true
}
return bookResult return bookResult
} }

View File

@ -3,7 +3,7 @@ package controllers
import ( import (
"github.com/lifei6671/mindoc/models" "github.com/lifei6671/mindoc/models"
"github.com/astaxie/beego/orm" "github.com/astaxie/beego/orm"
"github.com/qiniu/x/errors.v7" "errors"
"strings" "strings"
"github.com/lifei6671/mindoc/conf" "github.com/lifei6671/mindoc/conf"
) )
@ -23,7 +23,7 @@ func (c *TemplateController) isPermission() (error) {
} }
if !c.Member.IsAdministrator() { if !c.Member.IsAdministrator() {
book, err := models.NewBookResult().FindByIdentify(bookIdentify, c.Member.MemberId, "book_id") book, err := models.NewBookResult().FindByIdentify(bookIdentify, c.Member.MemberId)
if err != nil { if err != nil {
if err == orm.ErrNoRows { if err == orm.ErrNoRows {
return errors.New("项目不存在或没有权限") return errors.New("项目不存在或没有权限")

View File

@ -72,10 +72,10 @@ type Book struct {
//是否使用第一篇文章项目为默认首页,0 否/1 是 //是否使用第一篇文章项目为默认首页,0 否/1 是
IsUseFirstDocument int `orm:"column(is_use_first_document);type(int);default(0)" json:"is_use_first_document"` IsUseFirstDocument int `orm:"column(is_use_first_document);type(int);default(0)" json:"is_use_first_document"`
//是否开启自动保存0 否/1 是 //是否开启自动保存0 否/1 是
AutoSave int `orm:"column(auto_save);type(tinyint);default(0)" json:"auto_save"` AutoSave int `orm:"column(auto_save);type(tinyint);default(0)" json:"auto_save"`
} }
func (book *Book) String() string { func (book *Book) String() string {
ret, err := json.Marshal(*book) ret, err := json.Marshal(*book)
if err != nil { if err != nil {
@ -97,7 +97,7 @@ func (book *Book) TableNameWithPrefix() string {
return conf.GetDatabasePrefix() + book.TableName() return conf.GetDatabasePrefix() + book.TableName()
} }
func (book *Book) QueryTable() orm.QuerySeter { func (book *Book) QueryTable() orm.QuerySeter {
return orm.NewOrm().QueryTable(book.TableNameWithPrefix()) return orm.NewOrm().QueryTable(book.TableNameWithPrefix())
} }
@ -143,13 +143,13 @@ func (book *Book) Insert() error {
return err return err
} }
func (book *Book) Find(id int,cols ...string) (*Book, error) { func (book *Book) Find(id int, cols ...string) (*Book, error) {
if id <= 0 { if id <= 0 {
return book, ErrInvalidParameter return book, ErrInvalidParameter
} }
o := orm.NewOrm() o := orm.NewOrm()
err := o.QueryTable(book.TableNameWithPrefix()).Filter("book_id", id).One(book,cols...) err := o.QueryTable(book.TableNameWithPrefix()).Filter("book_id", id).One(book, cols...)
return book, err return book, err
} }
@ -179,43 +179,43 @@ func (book *Book) Update(cols ...string) error {
func (book *Book) Copy(identify string) error { func (book *Book) Copy(identify string) error {
o := orm.NewOrm() o := orm.NewOrm()
err := o.QueryTable(book.TableNameWithPrefix()).Filter("identify",identify).One(book) err := o.QueryTable(book.TableNameWithPrefix()).Filter("identify", identify).One(book)
if err != nil { if err != nil {
beego.Error("查询项目时出错 -> ",err) beego.Error("查询项目时出错 -> ", err)
return err return err
} }
if err := o.Begin();err != nil { if err := o.Begin(); err != nil {
beego.Error("开启事物时出错 -> ",err) beego.Error("开启事物时出错 -> ", err)
return err return err
} }
bookId := book.BookId bookId := book.BookId
book.BookId = 0 book.BookId = 0
book.Identify = book.Identify + fmt.Sprintf("%s-%s",identify,strconv.FormatInt(time.Now().UnixNano(), 32)) book.Identify = book.Identify + fmt.Sprintf("%s-%s", identify, strconv.FormatInt(time.Now().UnixNano(), 32))
book.BookName = book.BookName + "[副本]" book.BookName = book.BookName + "[副本]"
book.CreateTime = time.Now() book.CreateTime = time.Now()
book.CommentCount = 0 book.CommentCount = 0
book.HistoryCount = 0 book.HistoryCount = 0
if _,err := o.Insert(book);err != nil { if _, err := o.Insert(book); err != nil {
beego.Error("复制项目时出错 -> ",err) beego.Error("复制项目时出错 -> ", err)
o.Rollback() o.Rollback()
return err return err
} }
var rels []*Relationship var rels []*Relationship
if _,err := o.QueryTable(NewRelationship().TableNameWithPrefix()).Filter("book_id",bookId).All(&rels); err != nil { if _, err := o.QueryTable(NewRelationship().TableNameWithPrefix()).Filter("book_id", bookId).All(&rels); err != nil {
beego.Error("复制项目关系时出错 -> ",err) beego.Error("复制项目关系时出错 -> ", err)
o.Rollback() o.Rollback()
return err return err
} }
for _,rel := range rels { for _, rel := range rels {
rel.BookId = book.BookId rel.BookId = book.BookId
rel.RelationshipId = 0 rel.RelationshipId = 0
if _,err := o.Insert(rel);err != nil { if _, err := o.Insert(rel); err != nil {
beego.Error("复制项目关系时出错 -> ",err) beego.Error("复制项目关系时出错 -> ", err)
o.Rollback() o.Rollback()
return err return err
} }
@ -223,14 +223,14 @@ func (book *Book) Copy(identify string) error {
var docs []*Document var docs []*Document
if _,err := o.QueryTable(NewDocument().TableNameWithPrefix()).Filter("book_id",bookId).Filter("parent_id",0).All(&docs);err != nil && err != orm.ErrNoRows { if _, err := o.QueryTable(NewDocument().TableNameWithPrefix()).Filter("book_id", bookId).Filter("parent_id", 0).All(&docs); err != nil && err != orm.ErrNoRows {
beego.Error("读取项目文档时出错 -> ",err) beego.Error("读取项目文档时出错 -> ", err)
o.Rollback() o.Rollback()
return err return err
} }
if len(docs) > 0 { if len(docs) > 0 {
if err := recursiveInsertDocument(docs,o, book.BookId,0);err != nil { if err := recursiveInsertDocument(docs, o, book.BookId, 0); err != nil {
beego.Error("复制项目时出错 -> ",err) beego.Error("复制项目时出错 -> ", err)
o.Rollback() o.Rollback()
return err return err
} }
@ -238,9 +238,10 @@ func (book *Book) Copy(identify string) error {
return o.Commit() return o.Commit()
} }
//递归的复制文档 //递归的复制文档
func recursiveInsertDocument(docs []*Document,o orm.Ormer,bookId int,parentId int) error { func recursiveInsertDocument(docs []*Document, o orm.Ormer, bookId int, parentId int) error {
for _,doc := range docs { for _, doc := range docs {
docId := doc.DocumentId docId := doc.DocumentId
doc.DocumentId = 0 doc.DocumentId = 0
@ -248,32 +249,32 @@ func recursiveInsertDocument(docs []*Document,o orm.Ormer,bookId int,parentId in
doc.BookId = bookId doc.BookId = bookId
doc.Version = time.Now().Unix() doc.Version = time.Now().Unix()
if _,err := o.Insert(doc);err != nil { if _, err := o.Insert(doc); err != nil {
beego.Error("插入项目时出错 -> ",err) beego.Error("插入项目时出错 -> ", err)
return err return err
} }
var attachList []*Attachment var attachList []*Attachment
//读取所有附件列表 //读取所有附件列表
if _,err := o.QueryTable(NewAttachment().TableNameWithPrefix()).Filter("document_id",docId).All(&attachList); err == nil { if _, err := o.QueryTable(NewAttachment().TableNameWithPrefix()).Filter("document_id", docId).All(&attachList); err == nil {
for _,attach := range attachList { for _, attach := range attachList {
attach.BookId = bookId attach.BookId = bookId
attach.DocumentId = doc.DocumentId attach.DocumentId = doc.DocumentId
attach.AttachmentId = 0 attach.AttachmentId = 0
if _,err := o.Insert(attach);err != nil { if _, err := o.Insert(attach); err != nil {
return err return err
} }
} }
} }
var subDocs []*Document var subDocs []*Document
if _,err := o.QueryTable(NewDocument().TableNameWithPrefix()).Filter("parent_id",docId).All(&subDocs);err != nil && err != orm.ErrNoRows { if _, err := o.QueryTable(NewDocument().TableNameWithPrefix()).Filter("parent_id", docId).All(&subDocs); err != nil && err != orm.ErrNoRows {
beego.Error("读取文档时出错 -> ",err) beego.Error("读取文档时出错 -> ", err)
return err return err
} }
if len(subDocs) > 0{ if len(subDocs) > 0 {
if err := recursiveInsertDocument(subDocs,o,bookId,doc.DocumentId);err != nil { if err := recursiveInsertDocument(subDocs, o, bookId, doc.DocumentId); err != nil {
return err return err
} }
} }
@ -282,11 +283,11 @@ func recursiveInsertDocument(docs []*Document,o orm.Ormer,bookId int,parentId in
} }
//根据指定字段查询结果集. //根据指定字段查询结果集.
func (book *Book) FindByField(field string, value interface{},cols ...string) ([]*Book, error) { func (book *Book) FindByField(field string, value interface{}, cols ...string) ([]*Book, error) {
o := orm.NewOrm() o := orm.NewOrm()
var books []*Book var books []*Book
_, err := o.QueryTable(book.TableNameWithPrefix()).Filter(field, value).All(&books,cols...) _, err := o.QueryTable(book.TableNameWithPrefix()).Filter(field, value).All(&books, cols...)
return books, err return books, err
} }
@ -302,10 +303,10 @@ func (book *Book) FindByFieldFirst(field string, value interface{}) (*Book, erro
} }
//根据项目标识查询项目 //根据项目标识查询项目
func (book *Book) FindByIdentify(identify string,cols ...string) (*Book, error) { func (book *Book) FindByIdentify(identify string, cols ...string) (*Book, error) {
o := orm.NewOrm() o := orm.NewOrm()
err := o.QueryTable(book.TableNameWithPrefix()).Filter("identify", identify).One(book,cols...) err := o.QueryTable(book.TableNameWithPrefix()).Filter("identify", identify).One(book, cols...)
return book, err return book, err
} }
@ -313,14 +314,23 @@ func (book *Book) FindByIdentify(identify string,cols ...string) (*Book, error)
//分页查询指定用户的项目 //分页查询指定用户的项目
func (book *Book) FindToPager(pageIndex, pageSize, memberId int) (books []*BookResult, totalCount int, err error) { func (book *Book) FindToPager(pageIndex, pageSize, memberId int) (books []*BookResult, totalCount int, err error) {
relationship := NewRelationship()
o := orm.NewOrm() o := orm.NewOrm()
sql1 := "SELECT COUNT(book.book_id) AS total_count FROM " + book.TableNameWithPrefix() + " AS book LEFT JOIN " + //sql1 := "SELECT COUNT(book.book_id) AS total_count FROM " + book.TableNameWithPrefix() + " AS book LEFT JOIN " +
relationship.TableNameWithPrefix() + " AS rel ON book.book_id=rel.book_id AND rel.member_id = ? WHERE rel.relationship_id > 0 " // relationship.TableNameWithPrefix() + " AS rel ON book.book_id=rel.book_id AND rel.member_id = ? WHERE rel.relationship_id > 0 "
err = o.Raw(sql1, memberId).QueryRow(&totalCount) sql1 := `SELECT
count(*) AS total_count
FROM md_books AS book
LEFT JOIN md_relationship AS rel ON book.book_id = rel.book_id AND rel.member_id = ?
left join (select *
from (select book_id,team_member_id,role_id
from md_team_relationship as mtr
left join md_team_member as mtm on mtm.team_id=mtr.team_id and mtm.member_id=? order by role_id desc )as t group by t.book_id)
as team on team.book_id=book.book_id
WHERE rel.relationship_id > 0 or team.team_member_id > 0`
err = o.Raw(sql1, memberId, memberId).QueryRow(&totalCount)
if err != nil { if err != nil {
return return
@ -328,13 +338,29 @@ func (book *Book) FindToPager(pageIndex, pageSize, memberId int) (books []*BookR
offset := (pageIndex - 1) * pageSize offset := (pageIndex - 1) * pageSize
sql2 := "SELECT book.*,rel.member_id,rel.role_id,m.account as create_name FROM " + book.TableNameWithPrefix() + " AS book" + //sql2 := "SELECT book.*,rel.member_id,rel.role_id,m.account as create_name FROM " + book.TableNameWithPrefix() + " AS book" +
" LEFT JOIN " + relationship.TableNameWithPrefix() + " AS rel ON book.book_id=rel.book_id AND rel.member_id = ?" + // " LEFT JOIN " + relationship.TableNameWithPrefix() + " AS rel ON book.book_id=rel.book_id AND rel.member_id = ?" +
" LEFT JOIN " + relationship.TableNameWithPrefix() + " AS rel1 ON book.book_id=rel1.book_id AND rel1.role_id=0" + // " LEFT JOIN " + relationship.TableNameWithPrefix() + " AS rel1 ON book.book_id=rel1.book_id AND rel1.role_id=0" +
" LEFT JOIN " + NewMember().TableNameWithPrefix() + " AS m ON rel1.member_id=m.member_id " + // " LEFT JOIN " + NewMember().TableNameWithPrefix() + " AS m ON rel1.member_id=m.member_id " +
" WHERE rel.relationship_id > 0 ORDER BY book.order_index DESC,book.book_id DESC LIMIT " + fmt.Sprintf("%d,%d", offset, pageSize) // " WHERE rel.relationship_id > 0 ORDER BY book.order_index DESC,book.book_id DESC LIMIT " + fmt.Sprintf("%d,%d", offset, pageSize)
_, err = o.Raw(sql2, memberId).QueryRows(&books) sql2 := `SELECT
book.*,
case when rel.relationship_id is null then team.role_id else rel.role_id end as role_id,
m.account as create_name
FROM md_books AS book
LEFT JOIN md_relationship AS rel ON book.book_id = rel.book_id AND rel.member_id = ?
left join (select *
from (select book_id,team_member_id,role_id
from md_team_relationship as mtr
left join md_team_member as mtm on mtm.team_id=mtr.team_id and mtm.member_id=? order by role_id desc )as t group by t.book_id) as team
on team.book_id=book.book_id
LEFT JOIN md_relationship AS rel1 ON book.book_id = rel1.book_id AND rel1.role_id = 0
LEFT JOIN md_members AS m ON rel1.member_id = m.member_id
WHERE rel.relationship_id > 0 or team.team_member_id > 0
ORDER BY book.order_index, book.book_id DESC limit ?,?`
_, err = o.Raw(sql2, memberId, memberId, offset, pageSize).QueryRows(&books)
if err != nil { if err != nil {
logs.Error("分页查询项目列表 => ", err) logs.Error("分页查询项目列表 => ", err)
return return
@ -380,21 +406,21 @@ func (book *Book) ThoroughDeleteBook(id int) error {
o.Begin() o.Begin()
//删除附件,这里没有删除实际物理文件 //删除附件,这里没有删除实际物理文件
_,err = o.Raw("DELETE FROM " + NewAttachment().TableNameWithPrefix() + " WHERE book_id=?",book.BookId).Exec() _, err = o.Raw("DELETE FROM "+NewAttachment().TableNameWithPrefix()+" WHERE book_id=?", book.BookId).Exec()
if err != nil { if err != nil {
o.Rollback() o.Rollback()
return err return err
} }
//删除文档 //删除文档
_, err = o.Raw( "DELETE FROM " + NewDocument().TableNameWithPrefix() + " WHERE book_id = ?", book.BookId).Exec() _, err = o.Raw("DELETE FROM "+NewDocument().TableNameWithPrefix()+" WHERE book_id = ?", book.BookId).Exec()
if err != nil { if err != nil {
o.Rollback() o.Rollback()
return err return err
} }
//删除项目 //删除项目
_, err = o.Raw("DELETE FROM " + book.TableNameWithPrefix() + " WHERE book_id = ?", book.BookId).Exec() _, err = o.Raw("DELETE FROM "+book.TableNameWithPrefix()+" WHERE book_id = ?", book.BookId).Exec()
if err != nil { if err != nil {
o.Rollback() o.Rollback()
@ -402,30 +428,29 @@ func (book *Book) ThoroughDeleteBook(id int) error {
} }
//删除关系 //删除关系
_, err = o.Raw("DELETE FROM " + NewRelationship().TableNameWithPrefix() + " WHERE book_id = ?", book.BookId).Exec() _, err = o.Raw("DELETE FROM "+NewRelationship().TableNameWithPrefix()+" WHERE book_id = ?", book.BookId).Exec()
if err != nil { if err != nil {
o.Rollback() o.Rollback()
return err return err
} }
//删除模板 //删除模板
_,err = o.Raw("DELETE FROM " + NewTemplate().TableNameWithPrefix() + " WHERE book_id = ?",book.BookId).Exec() _, err = o.Raw("DELETE FROM "+NewTemplate().TableNameWithPrefix()+" WHERE book_id = ?", book.BookId).Exec()
if err != nil { if err != nil {
o.Rollback() o.Rollback()
return err return err
} }
if book.Label != "" { if book.Label != "" {
NewLabel().InsertOrUpdateMulti(book.Label) NewLabel().InsertOrUpdateMulti(book.Label)
} }
//删除导出缓存 //删除导出缓存
if err := os.RemoveAll(filepath.Join(conf.GetExportOutputPath(), strconv.Itoa(id))); err != nil { if err := os.RemoveAll(filepath.Join(conf.GetExportOutputPath(), strconv.Itoa(id))); err != nil {
beego.Error("删除项目缓存失败 ->",err) beego.Error("删除项目缓存失败 ->", err)
} }
//删除附件和图片 //删除附件和图片
if err := os.RemoveAll(filepath.Join(conf.WorkingDirectory,"uploads",book.Identify)); err != nil { if err := os.RemoveAll(filepath.Join(conf.WorkingDirectory, "uploads", book.Identify)); err != nil {
beego.Error("删除项目附件和图片失败 ->",err) beego.Error("删除项目附件和图片失败 ->", err)
} }
return o.Commit() return o.Commit()
@ -433,25 +458,35 @@ func (book *Book) ThoroughDeleteBook(id int) error {
} }
//分页查找系统首页数据. //分页查找系统首页数据.
func (book *Book) FindForHomeToPager(pageIndex, pageSize, member_id int) (books []*BookResult, totalCount int, err error) { func (book *Book) FindForHomeToPager(pageIndex, pageSize, memberId int) (books []*BookResult, totalCount int, err error) {
o := orm.NewOrm() o := orm.NewOrm()
offset := (pageIndex - 1) * pageSize offset := (pageIndex - 1) * pageSize
//如果是登录用户 //如果是登录用户
if member_id > 0 { if memberId > 0 {
sql1 := "SELECT COUNT(*) FROM md_books AS book LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.member_id = ? WHERE relationship_id > 0 OR book.privately_owned = 0" sql1 := `SELECT COUNT(*)
FROM md_books AS book
err = o.Raw(sql1, member_id).QueryRow(&totalCount) LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.member_id = ?
left join (select *
from (select book_id,team_member_id,role_id
from md_team_relationship as mtr
left join md_team_member as mtm on mtm.team_id=mtr.team_id and mtm.member_id=? order by role_id desc )as t group by t.book_id) as team on team.book_id=book.book_id
WHERE relationship_id > 0 OR book.privately_owned = 0 or team.team_member_id > 0`
err = o.Raw(sql1, memberId, memberId).QueryRow(&totalCount)
if err != nil { if err != nil {
return return
} }
sql2 := `SELECT book.*,rel1.*,member.account AS create_name,member.real_name FROM md_books AS book sql2 := `SELECT book.*,rel1.*,member.account AS create_name,member.real_name FROM md_books AS book
LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.member_id = ? LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.member_id = ?
LEFT JOIN md_relationship AS rel1 ON rel1.book_id = book.book_id AND rel1.role_id = 0 left join (select *
LEFT JOIN md_members AS member ON rel1.member_id = member.member_id from (select book_id,team_member_id,role_id
WHERE rel.relationship_id > 0 OR book.privately_owned = 0 ORDER BY order_index DESC ,book.book_id DESC LIMIT ?,?` from md_team_relationship as mtr
left join md_team_member as mtm on mtm.team_id=mtr.team_id and mtm.member_id=? order by role_id desc )as t group by t.book_id) as team on team.book_id=book.book_id
LEFT JOIN md_relationship AS rel1 ON rel1.book_id = book.book_id AND rel1.role_id = 0
LEFT JOIN md_members AS member ON rel1.member_id = member.member_id
WHERE rel.relationship_id > 0 OR book.privately_owned = 0 or team.team_member_id > 0 ORDER BY order_index ,book.book_id DESC LIMIT ?,?`
_, err = o.Raw(sql2, member_id, offset, pageSize).QueryRows(&books) _, err = o.Raw(sql2, memberId, memberId, offset, pageSize).QueryRows(&books)
} else { } else {
count, err1 := o.QueryTable(book.TableNameWithPrefix()).Filter("privately_owned", 0).Count() count, err1 := o.QueryTable(book.TableNameWithPrefix()).Filter("privately_owned", 0).Count()
@ -470,9 +505,7 @@ func (book *Book) FindForHomeToPager(pageIndex, pageSize, member_id int) (books
_, err = o.Raw(sql, offset, pageSize).QueryRows(&books) _, err = o.Raw(sql, offset, pageSize).QueryRows(&books)
} }
return return
} }
//分页全局搜索. //分页全局搜索.
@ -483,19 +516,31 @@ func (book *Book) FindForLabelToPager(keyword string, pageIndex, pageSize, membe
offset := (pageIndex - 1) * pageSize offset := (pageIndex - 1) * pageSize
//如果是登录用户 //如果是登录用户
if memberId > 0 { if memberId > 0 {
sql1 := "SELECT COUNT(*) FROM md_books AS book LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.member_id = ? WHERE (relationship_id > 0 OR book.privately_owned = 0) AND book.label LIKE ?" sql1 := `SELECT COUNT(*)
FROM md_books AS book
LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.member_id = ?
left join (select *
from (select book_id,team_member_id,role_id
from md_team_relationship as mtr
left join md_team_member as mtm on mtm.team_id=mtr.team_id and mtm.member_id=? order by role_id desc )as t group by t.book_id) as team on team.book_id = book.book_id
WHERE (relationship_id > 0 OR book.privately_owned = 0 or team.team_member_id > 0) AND book.label LIKE ?`
err = o.Raw(sql1, memberId, keyword).QueryRow(&totalCount) err = o.Raw(sql1, memberId, memberId, keyword).QueryRow(&totalCount)
if err != nil { if err != nil {
return return
} }
sql2 := `SELECT book.*,rel1.*,member.account AS create_name FROM md_books AS book sql2 := `SELECT book.*,rel1.*,member.account AS create_name FROM md_books AS book
LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.member_id = ? LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.member_id = ?
left join (select * from (select book_id,team_member_id,role_id
from md_team_relationship as mtr
left join md_team_member as mtm on mtm.team_id=mtr.team_id and mtm.member_id=? order by role_id desc )as t group by t.book_id) as team
on team.book_id = book.book_id
LEFT JOIN md_relationship AS rel1 ON rel1.book_id = book.book_id AND rel1.role_id = 0 LEFT JOIN md_relationship AS rel1 ON rel1.book_id = book.book_id AND rel1.role_id = 0
LEFT JOIN md_members AS member ON rel1.member_id = member.member_id LEFT JOIN md_members AS member ON rel1.member_id = member.member_id
WHERE (rel.relationship_id > 0 OR book.privately_owned = 0) AND book.label LIKE ? ORDER BY order_index DESC ,book.book_id DESC LIMIT ?,?` WHERE (rel.relationship_id > 0 OR book.privately_owned = 0 or team.team_member_id > 0)
AND book.label LIKE ? ORDER BY order_index DESC ,book.book_id DESC LIMIT ?,?`
_, err = o.Raw(sql2, memberId, keyword, offset, pageSize).QueryRows(&books) _, err = o.Raw(sql2, memberId, memberId, keyword, offset, pageSize).QueryRows(&books)
return return
@ -529,7 +574,7 @@ func (book *Book) ReleaseContent(bookId int) {
_, err := o.QueryTable(NewDocument().TableNameWithPrefix()).Filter("book_id", bookId).All(&docs) _, err := o.QueryTable(NewDocument().TableNameWithPrefix()).Filter("book_id", bookId).All(&docs)
if err != nil { if err != nil {
beego.Error("发布失败 =>",bookId, err) beego.Error("发布失败 =>", bookId, err)
return return
} }
for _, item := range docs { for _, item := range docs {
@ -544,12 +589,12 @@ func (book *Book) ResetDocumentNumber(bookId int) {
totalCount, err := o.QueryTable(NewDocument().TableNameWithPrefix()).Filter("book_id", bookId).Count() totalCount, err := o.QueryTable(NewDocument().TableNameWithPrefix()).Filter("book_id", bookId).Count()
if err == nil { if err == nil {
_,err = o.Raw("UPDATE md_books SET doc_count = ? WHERE book_id = ?", int(totalCount), bookId).Exec() _, err = o.Raw("UPDATE md_books SET doc_count = ? WHERE book_id = ?", int(totalCount), bookId).Exec()
if err != nil { if err != nil {
beego.Error("重置文档数量失败 =>",bookId,err) beego.Error("重置文档数量失败 =>", bookId, err)
} }
} else { } else {
beego.Error("获取文档数量失败 =>",bookId,err) beego.Error("获取文档数量失败 =>", bookId, err)
} }
} }
@ -568,7 +613,7 @@ func (book *Book) ImportBook(zipPath string) error {
tempPath := filepath.Join(os.TempDir(), md5str) tempPath := filepath.Join(os.TempDir(), md5str)
if err := os.MkdirAll(tempPath, 0766); err != nil { if err := os.MkdirAll(tempPath, 0766); err != nil {
beego.Error("创建导入目录出错 => ",err) beego.Error("创建导入目录出错 => ", err)
} }
//如果加压缩失败 //如果加压缩失败
if err := ziptil.Unzip(zipPath, tempPath); err != nil { if err := ziptil.Unzip(zipPath, tempPath); err != nil {
@ -613,7 +658,7 @@ func (book *Book) ImportBook(zipPath string) error {
ext := filepath.Ext(info.Name()) ext := filepath.Ext(info.Name())
//如果是Markdown文件 //如果是Markdown文件
if strings.EqualFold(ext, ".md") || strings.EqualFold(ext, ".markdown") { if strings.EqualFold(ext, ".md") || strings.EqualFold(ext, ".markdown") {
beego.Info("正在处理 =>",path,info.Name()) beego.Info("正在处理 =>", path, info.Name())
doc := NewDocument() doc := NewDocument()
doc.BookId = book.BookId doc.BookId = book.BookId
doc.MemberId = book.MemberId doc.MemberId = book.MemberId
@ -644,9 +689,9 @@ func (book *Book) ImportBook(zipPath string) error {
//如果是本地路径,则需要将图片复制到项目目录 //如果是本地路径,则需要将图片复制到项目目录
if !strings.HasPrefix(imageUrl, "http://") && if !strings.HasPrefix(imageUrl, "http://") &&
!strings.HasPrefix(imageUrl, "https://") && !strings.HasPrefix(imageUrl, "https://") &&
!strings.HasPrefix(imageUrl,"ftp://") { !strings.HasPrefix(imageUrl, "ftp://") {
//如果路径中存在参数 //如果路径中存在参数
if l := strings.Index(imageUrl,"?"); l > 0 { if l := strings.Index(imageUrl, "?"); l > 0 {
imageUrl = imageUrl[:l] imageUrl = imageUrl[:l]
} }
@ -665,7 +710,7 @@ func (book *Book) ImportBook(zipPath string) error {
if filetil.FileExists(imageUrl) { if filetil.FileExists(imageUrl) {
filetil.CopyFile(imageUrl, dstFile) filetil.CopyFile(imageUrl, dstFile)
imageUrl = strings.TrimPrefix(strings.Replace(dstFile,"\\","/",-1), strings.Replace(conf.WorkingDirectory,"\\","/",-1)) imageUrl = strings.TrimPrefix(strings.Replace(dstFile, "\\", "/", -1), strings.Replace(conf.WorkingDirectory, "\\", "/", -1))
if !strings.HasPrefix(imageUrl, "/") && !strings.HasPrefix(imageUrl, "\\") { if !strings.HasPrefix(imageUrl, "/") && !strings.HasPrefix(imageUrl, "\\") {
imageUrl = "/" + imageUrl imageUrl = "/" + imageUrl
@ -685,7 +730,7 @@ func (book *Book) ImportBook(zipPath string) error {
} }
} }
imageUrl = strings.Replace(strings.TrimSuffix(image, originalImageUrl+")")+ conf.URLForWithCdnImage(imageUrl) +")", "\\", "/", -1) imageUrl = strings.Replace(strings.TrimSuffix(image, originalImageUrl+")")+conf.URLForWithCdnImage(imageUrl)+")", "\\", "/", -1)
return imageUrl return imageUrl
}) })
@ -697,18 +742,18 @@ func (book *Book) ImportBook(zipPath string) error {
originalLink := links[0][2] originalLink := links[0][2]
var linkPath string var linkPath string
var err error var err error
if strings.HasPrefix(originalLink,"<") { if strings.HasPrefix(originalLink, "<") {
originalLink = strings.TrimPrefix(originalLink,"<") originalLink = strings.TrimPrefix(originalLink, "<")
} }
if strings.HasSuffix(originalLink,">") { if strings.HasSuffix(originalLink, ">") {
originalLink = strings.TrimSuffix(originalLink,">") originalLink = strings.TrimSuffix(originalLink, ">")
} }
//如果是从根目录开始, //如果是从根目录开始,
if strings.HasPrefix(originalLink, "/") { if strings.HasPrefix(originalLink, "/") {
linkPath, err = filepath.Abs(filepath.Join(tempPath, originalLink)) linkPath, err = filepath.Abs(filepath.Join(tempPath, originalLink))
} else if strings.HasPrefix(originalLink, "./") { } else if strings.HasPrefix(originalLink, "./") {
linkPath, err = filepath.Abs(filepath.Join(filepath.Dir(path), originalLink[1:])) linkPath, err = filepath.Abs(filepath.Join(filepath.Dir(path), originalLink[1:]))
} else{ } else {
linkPath, err = filepath.Abs(filepath.Join(filepath.Dir(path), originalLink)) linkPath, err = filepath.Abs(filepath.Join(filepath.Dir(path), originalLink))
} }
@ -738,8 +783,8 @@ func (book *Book) ImportBook(zipPath string) error {
link = strings.TrimSuffix(link, originalLink+")") + tempLink + ")" link = strings.TrimSuffix(link, originalLink+")") + tempLink + ")"
} }
}else{ } else {
beego.Info("文件不存在 ->",linkPath) beego.Info("文件不存在 ->", linkPath)
} }
} }
@ -806,7 +851,7 @@ func (book *Book) ImportBook(zipPath string) error {
} else { } else {
//如果当前目录下存在Markdown文件则需要创建此节点 //如果当前目录下存在Markdown文件则需要创建此节点
if filetil.HasFileOfExt(path, []string{".md", ".markdown"}) { if filetil.HasFileOfExt(path, []string{".md", ".markdown"}) {
beego.Info("正在处理 =>",path,info.Name()) beego.Info("正在处理 =>", path, info.Name())
identify := strings.Replace(strings.Trim(strings.TrimPrefix(path, tempPath), "/"), "/", "-", -1) identify := strings.Replace(strings.Trim(strings.TrimPrefix(path, tempPath), "/"), "/", "-", -1)
if ok, err := regexp.MatchString(`[a-z]+[a-zA-Z0-9_.\-]*$`, identify); !ok || err != nil { if ok, err := regexp.MatchString(`[a-z]+[a-zA-Z0-9_.\-]*$`, identify); !ok || err != nil {
identify = "import-" + identify identify = "import-" + identify
@ -850,3 +895,31 @@ func (book *Book) ImportBook(zipPath string) error {
book.ReleaseContent(book.BookId) book.ReleaseContent(book.BookId)
return err return err
} }
func (book *Book) FindForRoleId(bookId, memberId int) (conf.BookRole, error) {
o := orm.NewOrm()
var relationship Relationship
err := NewRelationship().QueryTable().Filter("book_id", bookId).Filter("member_id", memberId).One(&relationship)
if err != nil && err != orm.ErrNoRows {
return 0, err
}
if err == nil {
return relationship.RoleId, nil
}
sql := `select role_id
from md_team_relationship as mtr
left join md_team_member as mtm using (team_id)
where mtr.book_id = ? and mtm.member_id = ? order by mtm.role_id asc limit 1;`
var roleId int
err = o.Raw(sql, bookId, memberId).QueryRow(&roleId)
if err != nil {
beego.Error("查询用户项目角色出错 -> book_id=", bookId, " member_id=", memberId, err)
return 0, nil
}
return conf.BookRole(roleId), nil
}

View File

@ -54,8 +54,8 @@ type BookResult struct {
AutoRelease bool `json:"auto_release"` AutoRelease bool `json:"auto_release"`
HistoryCount int `json:"history_count"` HistoryCount int `json:"history_count"`
RelationshipId int `json:"relationship_id"` //RelationshipId int `json:"relationship_id"`
TeamRelationshipId int `json:"team_relationship_id"` //TeamRelationshipId int `json:"team_relationship_id"`
RoleId conf.BookRole `json:"role_id"` RoleId conf.BookRole `json:"role_id"`
RoleName string `json:"role_name"` RoleName string `json:"role_name"`
Status int `json:"status"` Status int `json:"status"`
@ -82,7 +82,7 @@ func (m *BookResult) String() string {
} }
// 根据项目标识查询项目以及指定用户权限的信息. // 根据项目标识查询项目以及指定用户权限的信息.
func (m *BookResult) FindByIdentify(identify string, memberId int, cols ...string) (*BookResult, error) { func (m *BookResult) FindByIdentify(identify string, memberId int) (*BookResult, error) {
if identify == "" || memberId <= 0 { if identify == "" || memberId <= 0 {
return m, ErrInvalidParameter return m, ErrInvalidParameter
} }
@ -97,27 +97,15 @@ func (m *BookResult) FindByIdentify(identify string, memberId int, cols ...strin
return m, err return m, err
} }
var relationship Relationship roleId,err := NewBook().FindForRoleId(book.BookId,memberId)
var teamMember *TeamMember
err = NewRelationship().QueryTable().Filter("book_id", book.BookId).Filter("member_id", memberId).One(&relationship)
if err != nil { if err != nil {
if err == orm.ErrNoRows { return m, ErrPermissionDenied
//未查到项目参与者
teamMember,err = NewTeamMember().FindByBookIdAndMemberId(book.BookId,memberId)
if err != nil {
return m,err
}
err = nil
} else {
return m, err
}
} }
var relationship2 Relationship var relationship2 Relationship
//查找项目创始人 //查找项目创始人
err = o.QueryTable(relationship.TableNameWithPrefix()).Filter("book_id", book.BookId).Filter("role_id", 0).One(&relationship2) err = NewRelationship().QueryTable().Filter("book_id", book.BookId).Filter("role_id", 0).One(&relationship2)
if err != nil { if err != nil {
logs.Error("根据项目标识查询项目以及指定用户权限的信息 -> ", err) logs.Error("根据项目标识查询项目以及指定用户权限的信息 -> ", err)
@ -130,20 +118,15 @@ func (m *BookResult) FindByIdentify(identify string, memberId int, cols ...strin
} }
m.ToBookResult(book) m.ToBookResult(book)
m.RoleId = roleId
m.MemberId = memberId m.MemberId = memberId
m.CreateName = member.Account m.CreateName = member.Account
if member.RealName != "" { if member.RealName != "" {
m.RealName = member.RealName m.RealName = member.RealName
} }
if teamMember != nil {
m.RoleId = teamMember.RoleId
m.TeamRelationshipId = teamMember.TeamMemberId
} else {
m.RoleId = relationship.RoleId
m.RelationshipId = relationship.RelationshipId
}
if m.RoleId == conf.BookFounder { if m.RoleId == conf.BookFounder {
m.RoleName = "创始人" m.RoleName = "创始人"
} else if m.RoleId == conf.BookAdmin { } else if m.RoleId == conf.BookAdmin {

View File

@ -25,13 +25,13 @@ func NewDocumentSearchResult() *DocumentSearchResult {
} }
//分页全局搜索. //分页全局搜索.
func (m *DocumentSearchResult) FindToPager(keyword string, page_index, page_size, member_id int) (search_result []*DocumentSearchResult, total_count int, err error) { func (m *DocumentSearchResult) FindToPager(keyword string, pageIndex, pageSize, memberId int) (searchResult []*DocumentSearchResult, totalCount int, err error) {
o := orm.NewOrm() o := orm.NewOrm()
offset := (page_index - 1) * page_size offset := (pageIndex - 1) * pageSize
keyword = "%" + keyword + "%" keyword = "%" + keyword + "%"
if member_id <= 0 { if memberId <= 0 {
sql1 := `SELECT count(doc.document_id) as total_count FROM md_documents AS doc sql1 := `SELECT count(doc.document_id) as total_count FROM md_documents AS doc
LEFT JOIN md_books as book ON doc.book_id = book.book_id LEFT JOIN md_books as book ON doc.book_id = book.book_id
WHERE book.privately_owned = 0 AND (doc.document_name LIKE ? OR doc.release LIKE ?) ` WHERE book.privately_owned = 0 AND (doc.document_name LIKE ? OR doc.release LIKE ?) `
@ -43,11 +43,11 @@ WHERE book.privately_owned = 0 AND (doc.document_name LIKE ? OR doc.release LIKE
WHERE book.privately_owned = 0 AND (doc.document_name LIKE ? OR doc.release LIKE ?) WHERE book.privately_owned = 0 AND (doc.document_name LIKE ? OR doc.release LIKE ?)
ORDER BY doc.document_id DESC LIMIT ?,? ` ORDER BY doc.document_id DESC LIMIT ?,? `
err = o.Raw(sql1, keyword, keyword).QueryRow(&total_count) err = o.Raw(sql1, keyword, keyword).QueryRow(&totalCount)
if err != nil { if err != nil {
return return
} }
_, err = o.Raw(sql2, keyword, keyword, offset, page_size).QueryRows(&search_result) _, err = o.Raw(sql2, keyword, keyword, offset, pageSize).QueryRows(&searchResult)
if err != nil { if err != nil {
return return
} }
@ -56,21 +56,29 @@ WHERE book.privately_owned = 0 AND (doc.document_name LIKE ? OR doc.release LIKE
LEFT JOIN md_books as book ON doc.book_id = book.book_id LEFT JOIN md_books as book ON doc.book_id = book.book_id
LEFT JOIN md_relationship AS rel ON doc.book_id = rel.book_id AND rel.role_id = 0 LEFT JOIN md_relationship AS rel ON doc.book_id = rel.book_id AND rel.role_id = 0
LEFT JOIN md_relationship AS rel1 ON doc.book_id = rel1.book_id AND rel1.member_id = ? LEFT JOIN md_relationship AS rel1 ON doc.book_id = rel1.book_id AND rel1.member_id = ?
WHERE (book.privately_owned = 0 OR rel1.relationship_id > 0) AND (doc.document_name LIKE ? OR doc.release LIKE ?) ` left join (select * from (select book_id,team_member_id,role_id
from md_team_relationship as mtr
left join md_team_member as mtm on mtm.team_id=mtr.team_id and mtm.member_id=? order by role_id desc )as t group by t.book_id) as team
on team.book_id = book.book_id
WHERE (book.privately_owned = 0 OR rel1.relationship_id > 0 or team.team_member_id > 0) AND (doc.document_name LIKE ? OR doc.release LIKE ?) `
sql2 := `SELECT doc.document_id,doc.modify_time,doc.create_time,doc.document_name,doc.identify,doc.release as description,doc.modify_time,book.identify as book_identify,book.book_name,rel.member_id,member.account AS author FROM md_documents AS doc sql2 := `SELECT doc.document_id,doc.modify_time,doc.create_time,doc.document_name,doc.identify,doc.release as description,doc.modify_time,book.identify as book_identify,book.book_name,rel.member_id,member.account AS author FROM md_documents AS doc
LEFT JOIN md_books as book ON doc.book_id = book.book_id LEFT JOIN md_books as book ON doc.book_id = book.book_id
LEFT JOIN md_relationship AS rel ON book.book_id = rel.book_id AND rel.role_id = 0 LEFT JOIN md_relationship AS rel ON book.book_id = rel.book_id AND rel.role_id = 0
LEFT JOIN md_members as member ON rel.member_id = member.member_id LEFT JOIN md_members as member ON rel.member_id = member.member_id
LEFT JOIN md_relationship AS rel1 ON doc.book_id = rel1.book_id AND rel1.member_id = ? LEFT JOIN md_relationship AS rel1 ON doc.book_id = rel1.book_id AND rel1.member_id = ?
WHERE (book.privately_owned = 0 OR rel1.relationship_id > 0) AND (doc.document_name LIKE ? OR doc.release LIKE ?) left join (select * from (select book_id,team_member_id,role_id
from md_team_relationship as mtr
left join md_team_member as mtm on mtm.team_id=mtr.team_id and mtm.member_id=? order by role_id desc )as t group by t.book_id) as team
on team.book_id = book.book_id
WHERE (book.privately_owned = 0 OR rel1.relationship_id > 0 or team.team_member_id > 0) AND (doc.document_name LIKE ? OR doc.release LIKE ?)
ORDER BY doc.document_id DESC LIMIT ?,? ` ORDER BY doc.document_id DESC LIMIT ?,? `
err = o.Raw(sql1, member_id, keyword, keyword).QueryRow(&total_count) err = o.Raw(sql1, memberId, memberId, keyword, keyword).QueryRow(&totalCount)
if err != nil { if err != nil {
return return
} }
_, err = o.Raw(sql2, member_id, keyword, keyword, offset, page_size).QueryRows(&search_result) _, err = o.Raw(sql2, memberId, memberId, keyword, keyword, offset, pageSize).QueryRows(&searchResult)
if err != nil { if err != nil {
return return
} }

View File

@ -29,14 +29,14 @@ func (m *Relationship) TableEngine() string {
} }
// 联合唯一键 // 联合唯一键
func (u *Relationship) TableUnique() [][]string { func (m *Relationship) TableUnique() [][]string {
return [][]string{ return [][]string{
{"member_id", "book_id"}, {"member_id", "book_id"},
} }
} }
func (u *Relationship) QueryTable() orm.QuerySeter { func (m *Relationship) QueryTable() orm.QuerySeter {
return orm.NewOrm().QueryTable(u.TableNameWithPrefix()) return orm.NewOrm().QueryTable(m.TableNameWithPrefix())
} }
func NewRelationship() *Relationship { func NewRelationship() *Relationship {
return &Relationship{} return &Relationship{}
@ -91,12 +91,12 @@ func (m *Relationship) UpdateRoleId(bookId, memberId int, roleId conf.BookRole)
} }
func (m *Relationship) FindForRoleId(book_id, member_id int) (conf.BookRole, error) { func (m *Relationship) FindForRoleId(bookId, memberId int) (conf.BookRole, error) {
o := orm.NewOrm() o := orm.NewOrm()
relationship := NewRelationship() relationship := NewRelationship()
err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id", book_id).Filter("member_id", member_id).One(relationship) err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id", bookId).Filter("member_id", memberId).One(relationship)
if err != nil { if err != nil {

View File

@ -44,9 +44,8 @@
<div class="m-box"> <div class="m-box">
<div class="box-head"> <div class="box-head">
<strong class="box-title"> 团队管理</strong> <strong class="box-title"> 团队管理</strong>
{{if eq .Member.Role 0}} {{if eq .Model.RoleId 0}}
<button type="button" class="btn btn-success btn-sm pull-right" data-toggle="modal" <button type="button" class="btn btn-success btn-sm pull-right" data-toggle="modal" data-target="#addTeamDialogModal"><i class="fa fa-user-plus" aria-hidden="true"></i>
data-target="#addTeamDialogModal"><i class="fa fa-user-plus" aria-hidden="true"></i>
添加团队 添加团队
</button> </button>
{{end}} {{end}}

View File

@ -43,14 +43,12 @@
<div class="navbar-header pull-right manual-menu"> <div class="navbar-header pull-right manual-menu">
<a href="javascript:window.print();" id="printSinglePage" class="btn btn-default" style="margin-right: 10px;"><i class="fa fa-print"></i> 打印</a> <a href="javascript:window.print();" id="printSinglePage" class="btn btn-default" style="margin-right: 10px;"><i class="fa fa-print"></i> 打印</a>
{{if gt .Member.MemberId 0}} {{if gt .Member.MemberId 0}}
{{if gt .Model.RelationshipId 0}}
{{if eq .Model.RoleId 0 1 2}} {{if eq .Model.RoleId 0 1 2}}
<div class="dropdown pull-right"> <div class="dropdown pull-right">
<a href="{{urlfor "DocumentController.Edit" ":key" .Model.Identify ":id" ""}}" class="btn btn-default"><i class="fa fa-edit" aria-hidden="true"></i> 编辑</a> <a href="{{urlfor "DocumentController.Edit" ":key" .Model.Identify ":id" ""}}" class="btn btn-default"><i class="fa fa-edit" aria-hidden="true"></i> 编辑</a>
</div> </div>
{{end}} {{end}}
{{end}} {{end}}
{{end}}
<div class="dropdown pull-right" style="margin-right: 10px;"> <div class="dropdown pull-right" style="margin-right: 10px;">
<a href="{{urlfor "HomeController.Index"}}" class="btn btn-default"><i class="fa fa-home" aria-hidden="true"></i> 首页</a> <a href="{{urlfor "HomeController.Index"}}" class="btn btn-default"><i class="fa fa-home" aria-hidden="true"></i> 首页</a>
</div> </div>