diff --git a/controllers/DocumentController.go b/controllers/DocumentController.go index cef65fb9..338d3b11 100644 --- a/controllers/DocumentController.go +++ b/controllers/DocumentController.go @@ -54,7 +54,7 @@ func (c *DocumentController) Index() { bookResult := isReadable(identify, token, c) - c.TplName = "document/" + bookResult.Theme + "_read.tpl" + c.TplName = fmt.Sprintf("document/%s_read.tpl",bookResult.Theme) selected := 0 @@ -243,7 +243,7 @@ func (c *DocumentController) Edit() { } else if bookResult.Editor == "html" { c.TplName = "document/new_html_edit_template.tpl" } else { - c.TplName = "document/" + bookResult.Editor + "_edit_template.tpl" + c.TplName = fmt.Sprintf("document/%s_edit_template.tpl", bookResult.Editor) } c.Data["Model"] = bookResult @@ -260,6 +260,11 @@ func (c *DocumentController) Edit() { beego.Error("FindDocumentTree => ", err) } else { if len(trees) > 0 { + for _,tree := range trees { + if tree.Type == "lock" { + tree.DocumentName = tree.DocumentName + " [锁定]" + } + } if jtree, err := json.Marshal(trees); err == nil { c.Data["Result"] = template.JS(string(jtree)) } @@ -297,6 +302,9 @@ func (c *DocumentController) Create() { beego.Error(err) c.JsonResult(6002, "项目不存在或权限不足") } + if book.IsLock == 1 { + c.JsonResult(6004,"已锁定的项目不能创建文档") + } bookId = book.BookId } else { @@ -306,7 +314,9 @@ func (c *DocumentController) Create() { beego.Error("FindByIdentify => ", err) c.JsonResult(6002, "项目不存在或权限不足") } - + if bookResult.IsLock { + c.JsonResult(6004,"已锁定的项目不能创建文档") + } bookId = bookResult.BookId } @@ -349,7 +359,7 @@ func (c *DocumentController) Create() { // 上传附件或图片 func (c *DocumentController) Upload() { identify := c.GetString("identify") - doc_id, _ := c.GetInt("doc_id") + docId, _ := c.GetInt("doc_id") is_attach := true if identify == "" { @@ -402,6 +412,9 @@ func (c *DocumentController) Upload() { if err != nil { c.JsonResult(6006, "文档不存在或权限不足") } + if book.IsLock == 1 { + c.JsonResult(6004,"已锁定的项目不能上传文件") + } bookId = book.BookId } else { @@ -421,11 +434,14 @@ func (c *DocumentController) Upload() { c.JsonResult(6006, "权限不足") } + if book.IsLock { + c.JsonResult(6004,"已锁定的项目不能上传文件") + } bookId = book.BookId } - if doc_id > 0 { - doc, err := models.NewDocument().Find(doc_id) + if docId > 0 { + doc, err := models.NewDocument().Find(docId) if err != nil { c.JsonResult(6007, "文档不存在") } @@ -433,6 +449,9 @@ func (c *DocumentController) Upload() { if doc.BookId != bookId { c.JsonResult(6008, "文档不属于指定的项目") } + if doc.IsLock == 1 { + c.JsonResult(6004,"已锁定的文档不能上传文件") + } } fileName := "attach_" + strconv.FormatInt(time.Now().UnixNano(), 16) @@ -456,14 +475,14 @@ func (c *DocumentController) Upload() { attachment.CreateAt = c.Member.MemberId attachment.FileExt = ext attachment.FilePath = strings.TrimPrefix(filePath, conf.WorkingDirectory) - attachment.DocumentId = doc_id + attachment.DocumentId = docId if fileInfo, err := os.Stat(filePath); err == nil { attachment.FileSize = float64(fileInfo.Size()) } - if doc_id > 0 { - attachment.DocumentId = doc_id + if docId > 0 { + attachment.DocumentId = docId } if strings.EqualFold(ext, ".jpg") || strings.EqualFold(ext, ".jpeg") || strings.EqualFold(ext, ".png") || strings.EqualFold(ext, ".gif") { @@ -568,13 +587,13 @@ func (c *DocumentController) DownloadAttachment() { // 删除附件 func (c *DocumentController) RemoveAttachment() { c.Prepare() - attach_id, _ := c.GetInt("attach_id") + attachId, _ := c.GetInt("attach_id") - if attach_id <= 0 { + if attachId <= 0 { c.JsonResult(6001, "参数错误") } - attach, err := models.NewAttachment().Find(attach_id) + attach, err := models.NewAttachment().Find(attachId) if err != nil { beego.Error(err) @@ -587,8 +606,11 @@ func (c *DocumentController) RemoveAttachment() { beego.Error(err) c.JsonResult(6003, "文档不存在") } + if document.IsLockBook(document.DocumentId) { + c.JsonResult(6004,"已锁定的项目不能删除附件") + } if document.IsLock == 1 { - c.JsonResult(6004,"不能编辑已锁定的文档") + c.JsonResult(6004,"已锁定的文档不能删除附件") } if c.Member.Role != conf.MemberSuperRole { rel, err := models.NewRelationship().FindByBookIdAndMemberId(document.BookId, c.Member.MemberId) @@ -737,6 +759,9 @@ func (c *DocumentController) Content() { beego.Info("%d|", version, doc.Version) c.JsonResult(6005, "文档已被修改确定要覆盖吗?") } + if doc.IsLock == 1 { + c.JsonResult(6003,"锁定的项目不能编辑") + } history := models.NewDocumentHistory() history.DocumentId = docId @@ -798,23 +823,6 @@ func (c *DocumentController) Content() { c.JsonResult(0, "ok", doc) } -// -//func (c *DocumentController) GetDocumentById(id string) (doc *models.Document, err error) { -// doc = models.NewDocument() -// if doc_id, err := strconv.Atoi(id); err == nil { -// doc, err = doc.Find(doc_id) -// if err != nil { -// return nil, err -// } -// } else { -// doc, err = doc.FindByFieldFirst("identify", id) -// if err != nil { -// return nil, err -// } -// } -// -// return doc, nil -//} // 导出 func (c *DocumentController) Export() { @@ -1043,6 +1051,7 @@ func (c *DocumentController) History() { } } +//删除文档历史 func (c *DocumentController) DeleteHistory() { c.Prepare() @@ -1101,6 +1110,7 @@ func (c *DocumentController) DeleteHistory() { c.JsonResult(0, "ok") } +//重置文档历史 func (c *DocumentController) RestoreHistory() { c.Prepare() @@ -1158,6 +1168,7 @@ func (c *DocumentController) RestoreHistory() { c.JsonResult(0, "ok", doc) } +//比较文档 func (c *DocumentController) Compare() { c.Prepare() @@ -1221,6 +1232,92 @@ func (c *DocumentController) Compare() { } } +//锁定文档 +func (c *DocumentController) Lock() { + docId, _ := c.GetInt("doc_id", 0) + identify := c.GetString("identify") + // 如果是超级管理员则不判断权限 + if c.Member.IsAdministrator() { + book, err := models.NewBook().FindByFieldFirst("identify", identify) + if err != nil { + beego.Error(err) + c.JsonResult(6002, "项目不存在或权限不足") + } + + if book.IsLock == 1 { + c.JsonResult(6001,"项目已锁定") + } + } else { + bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) + + if err != nil || bookResult.RoleId == conf.BookObserver { + beego.Error("FindByIdentify => ", err) + c.JsonResult(6002, "项目不存在或权限不足") + } + if bookResult.IsLock { + c.JsonResult(6001,"项目已锁定") + } + } + document, err := models.NewDocument().Find(docId) + + if err != nil { + beego.Error("获取文档失败 =>",err) + c.JsonResult(6004,"文档不存在") + } + if document.IsLock == 1 { + c.JsonResult(6005,"文档已锁定") + } + document.IsLock = 1 + if err := document.InsertOrUpdate();err != nil { + beego.Error("锁定文档失败 =>",err) + c.JsonResult(6006,"锁定文档失败") + } + c.JsonResult(0, "文档已锁定", document) +} + +// 解锁文档 +func (c *DocumentController) UnLock() { + docId, _ := c.GetInt("doc_id", 0) + identify := c.GetString("identify") + // 如果是超级管理员则不判断权限 + if c.Member.IsAdministrator() { + book, err := models.NewBook().FindByFieldFirst("identify", identify) + if err != nil { + beego.Error(err) + c.JsonResult(6002, "项目不存在或权限不足") + } + + if book.IsLock == 1 { + c.JsonResult(6001,"项目已锁定") + } + } else { + bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) + + if err != nil || bookResult.RoleId == conf.BookObserver { + beego.Error("FindByIdentify => ", err) + c.JsonResult(6002, "项目不存在或权限不足") + } + if bookResult.IsLock { + c.JsonResult(6001,"项目已锁定") + } + } + document, err := models.NewDocument().Find(docId) + + if err != nil { + beego.Error("获取文档失败 =>",err) + c.JsonResult(6004,"文档不存在") + } + if document.IsLock == 1 { + document.IsLock = 0 + if err := document.InsertOrUpdate();err != nil { + beego.Error("文档解锁失败 =>",err) + c.JsonResult(6006,"文档解锁失败") + } + } + + c.JsonResult(0, "文档已解锁", document) +} + // 递归生成文档序列数组 func RecursiveFun(parentId int, prefix, dpath string, c *DocumentController, book *models.BookResult, docs []*models.Document, paths *list.List) { for _, item := range docs { diff --git a/models/document.go b/models/document.go index 3a261898..0174ab9d 100644 --- a/models/document.go +++ b/models/document.go @@ -216,3 +216,25 @@ func (m *Document) FindListByBookId(bookId int) (docs []*Document, err error) { return } + +//判断项目是否锁定 +func (m *Document) IsLockBook(docId int) bool { + document := NewDocument() + book := NewBook() + + o := orm.NewOrm() + + err := o.QueryTable(m.TableNameWithPrefix()).Filter("document_id",docId).One(document,"book_id") + if err != nil { + beego.Error("查询文档失败 =>",err) + return false + } + err = o.QueryTable(book.TableNameWithPrefix()).Filter("book_id",document.BookId).One(book,"is_lock") + + if err != nil { + beego.Error("查询项目失败 =>",err) + return false + } + + return book.IsLock == 1 +} \ No newline at end of file diff --git a/models/document_tree.go b/models/document_tree.go index 39e8d7cd..ddc198a2 100644 --- a/models/document_tree.go +++ b/models/document_tree.go @@ -18,6 +18,7 @@ type DocumentTree struct { BookIdentify string `json:"-"` Version int64 `json:"version"` State *DocumentSelected `json:"state,omitempty"` + Type string `json:"type"` } type DocumentSelected struct { Selected bool `json:"selected"` @@ -32,7 +33,7 @@ func (m *Document) FindDocumentTree(book_id int) ([]*DocumentTree, error) { var docs []*Document - count, err := o.QueryTable(m).Filter("book_id", book_id).OrderBy("order_sort", "document_id").Limit(math.MaxInt32).All(&docs, "document_id", "version", "document_name", "parent_id", "identify") + count, err := o.QueryTable(m).Filter("book_id", book_id).OrderBy("order_sort", "document_id").Limit(math.MaxInt32).All(&docs, "document_id", "version", "document_name", "parent_id", "identify","is_lock") if err != nil { return trees, err @@ -50,6 +51,11 @@ func (m *Document) FindDocumentTree(book_id int) ([]*DocumentTree, error) { tree.Identify = item.Identify tree.Version = item.Version tree.BookIdentify = book.Identify + if item.IsLock == 1 { + tree.Type = "lock" + }else{ + tree.Type = "unlock" + } if item.ParentId > 0 { tree.ParentId = item.ParentId } else { diff --git a/routers/router.go b/routers/router.go index 3f2368e5..b31ec54e 100644 --- a/routers/router.go +++ b/routers/router.go @@ -68,6 +68,8 @@ func init() { beego.Router("/api/:key/content/?:id", &controllers.DocumentController{}, "*:Content") beego.Router("/api/:key/compare/:id", &controllers.DocumentController{}, "*:Compare") beego.Router("/api/search/user/:key", &controllers.SearchController{}, "*:User") + beego.Router("/api/:key/lock", &controllers.DocumentController{}, "*:Lock") + beego.Router("/api/:key/unlock", &controllers.DocumentController{}, "*:UnLock") beego.Router("/history/get", &controllers.DocumentController{}, "get:History") beego.Router("/history/delete", &controllers.DocumentController{}, "*:DeleteHistory") diff --git a/static/css/jstree.css b/static/css/jstree.css index 6a02dc76..3387f19f 100644 --- a/static/css/jstree.css +++ b/static/css/jstree.css @@ -198,3 +198,8 @@ line-height: 30px; height: 30px; } + +.jstree .lock-text{ + color: #c00; + font-size: 12px; +} \ No newline at end of file diff --git a/static/js/editor.js b/static/js/editor.js index 070763c7..1b084dd8 100644 --- a/static/js/editor.js +++ b/static/js/editor.js @@ -106,7 +106,7 @@ function openDeleteDocumentDialog($node) { function openEditCatalogDialog($node) { var $then = $("#addDocumentModal"); var doc_id = parseInt($node ? $node.id : 0); - var text = $node ? $node.text : ''; + var text = $node ? $node.text.split(' [锁定]"; + window.treeCatalog.rename_node(node, name); + window.treeCatalog.set_type(node,"lock"); + }else{ + layer.msg(res.message,{icon : 2}) + } + }).fail(function () { + layer.close(index); + layer.msg("锁定失败",{icon : 2}) + }); +} +/** + * 解锁文档 + * @param $node + */ +function unLockDocumentAction($node) { + var index = layer.load(1, { + shade: [0.1, '#fff'] // 0.1 透明度的白色背景 + }); + + $.post(window.unLockURL,{"identify" : window.book.identify,"doc_id" : $node.id}).done(function (res) { + layer.close(index); + if(res.errcode === 0){ + var node = {"id":$node.id}; + var name = res.data.doc_name; + window.treeCatalog.rename_node(node,name); + window.treeCatalog.set_type(node,"unlock"); + }else{ + layer.msg("解锁失败",{icon : 2}) + } + }).fail(function () { + layer.close(index); + layer.msg("解锁失败",{icon : 2}) + }); +} + /** * 发布项目 */ diff --git a/static/js/markdown.js b/static/js/markdown.js index b2c9db51..3eab5150 100644 --- a/static/js/markdown.js +++ b/static/js/markdown.js @@ -75,6 +75,9 @@ $(function () { * 实现标题栏操作 */ $("#editormd-tools").on("click", "a[class!='disabled']", function () { + if($(this).hasClass('disabled')){ + return false; + } var name = $(this).find("i").attr("name"); if (name === "attachment") { $("#uploadAttachModal").modal("show"); @@ -148,6 +151,15 @@ $(function () { layer.close(index); if (res.errcode === 0) { + var node = { "id": res.data.doc_id, 'parent': res.data.parent_id === 0 ? '#' : res.data.parent_id, "text": res.data.doc_name, "identify": res.data.identify, "version": res.data.version }; + if(res.data.is_lock){ + node.type = "lock"; + node.text = node.text + " [锁定]"; + // window.editor.config('readOnly',true); + }else{ + node.type = "unlock"; + window.editor.config('readOnly',false); + } window.isLoad = true; try { window.editor.clear(); @@ -156,10 +168,11 @@ $(function () { }catch(e){ console.log(e); } - var node = { "id": res.data.doc_id, 'parent': res.data.parent_id === 0 ? '#' : res.data.parent_id, "text": res.data.doc_name, "identify": res.data.identify, "version": res.data.version }; + pushDocumentCategory(node); window.selectNode = node; pushVueLists(res.data.attach); + } else { layer.msg("文档加载失败"); } @@ -244,6 +257,10 @@ $(function () { */ function resetEditorChanged($is_change) { if ($is_change && !window.isLoad) { + var type = window.treeCatalog.get_type(window.selectNode); + if(type === "lock"){ + return; + } $("#markdown-save").removeClass('disabled').addClass('change'); } else { $("#markdown-save").removeClass('change').addClass('disabled'); @@ -265,8 +282,11 @@ $(function () { }, success: function (res) { if (res.errcode === 0) { - var data = { "id": res.data.doc_id, 'parent': res.data.parent_id === 0 ? '#' : res.data.parent_id , "text": res.data.doc_name, "identify": res.data.identify, "version": res.data.version }; + var data = { "id": res.data.doc_id, 'parent': res.data.parent_id === 0 ? '#' : res.data.parent_id , "text": res.data.doc_name, "identify": res.data.identify, "version": res.data.version ,"type": res.data.is_lock ? "lock" : "unlock"}; + if(res.data.is_lock){ + data.text = data.text + " [锁定]"; + } var node = window.treeCatalog.get_node(data.id); if (node) { window.treeCatalog.rename_node({ "id": data.id }, data.text); @@ -293,6 +313,12 @@ $(function () { "types": { "default": { "icon": false // 删除默认图标 + }, + "lock" : { + "icon" : false + }, + "unlock" : { + "icon" : false } }, 'core': { @@ -304,45 +330,78 @@ $(function () { "contextmenu": { show_at_node: false, select_node: false, - "items": { - "添加文档": { - "separator_before": false, - "separator_after": true, - "_disabled": false, - "label": "添加文档", - "icon": "fa fa-plus", - "action": function (data) { - var inst = $.jstree.reference(data.reference), - node = inst.get_node(data.reference); + 'items' : function(node) { + var items = { + "添加文档": { + "separator_before": false, + "separator_after": true, + "_disabled": false, + "label": "添加文档", + "icon": "fa fa-plus", + "action": function (data) { + var inst = $.jstree.reference(data.reference), + node = inst.get_node(data.reference); - openCreateCatalogDialog(node); - } - }, - "编辑": { - "separator_before": false, - "separator_after": true, - "_disabled": false, - "label": "编辑", - "icon": "fa fa-edit", - "action": function (data) { - var inst = $.jstree.reference(data.reference); - var node = inst.get_node(data.reference); - openEditCatalogDialog(node); - } - }, - "删除": { - "separator_before": false, - "separator_after": true, - "_disabled": false, - "label": "删除", - "icon": "fa fa-trash-o", - "action": function (data) { - var inst = $.jstree.reference(data.reference); - var node = inst.get_node(data.reference); - openDeleteDocumentDialog(node); + openCreateCatalogDialog(node); + } + }, + "编辑": { + "separator_before": false, + "separator_after": true, + "_disabled": false, + "label": "编辑", + "icon": "fa fa-edit", + "action": function (data) { + var inst = $.jstree.reference(data.reference); + var node = inst.get_node(data.reference); + openEditCatalogDialog(node); + } + }, + "删除": { + "separator_before": false, + "separator_after": true, + "_disabled": false, + "label": "删除", + "icon": "fa fa-trash-o", + "action": function (data) { + var inst = $.jstree.reference(data.reference); + var node = inst.get_node(data.reference); + openDeleteDocumentDialog(node); + } + }, + "unlock" : { + "separator_before": false, + "separator_after": true, + "_disabled": false, + "label": "解锁", + "icon": "fa fa-unlock", + "action": function (data) { + var inst = $.jstree.reference(data.reference); + var node = inst.get_node(data.reference); + unLockDocumentAction(node); + } + }, + "lock" : { + "separator_before": false, + "separator_after": true, + "_disabled": false, + "label": "锁定", + "icon": "fa fa-lock", + "action": function (data) { + var inst = $.jstree.reference(data.reference); + var node = inst.get_node(data.reference); + lockDocumentAction(node); + } } + }; + console.log(this.get_type(node)); + if(this.get_type(node) === "lock") { + delete items.lock; + }else{ + delete items.unlock; } - } + return items; + }, } }).on('loaded.jstree', function () { window.treeCatalog = $(this).jstree(); diff --git a/views/document/markdown_edit_template.tpl b/views/document/markdown_edit_template.tpl index 5d8d7e80..7d2a99b0 100644 --- a/views/document/markdown_edit_template.tpl +++ b/views/document/markdown_edit_template.tpl @@ -20,6 +20,8 @@ window.sortURL = "{{urlfor "BookController.SaveSort" ":key" .Model.Identify}}"; window.historyURL = "{{urlfor "DocumentController.History"}}"; window.removeAttachURL = "{{urlfor "DocumentController.RemoveAttachment"}}"; + window.lockURL = "{{urlfor "DocumentController.Lock" ":key" .Model.Identify}}"; + window.unLockURL = "{{urlfor "DocumentController.UnLock" ":key" .Model.Identify}}";