实现项目和文档锁定功能

dev
Minho 2018-04-09 16:56:29 +08:00
parent 7a05cdfea4
commit de5f7301f0
8 changed files with 312 additions and 70 deletions

View File

@ -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 + "<span class='lock-text'> [锁定]</span>"
}
}
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 {

View File

@ -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
}

View File

@ -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 {

View File

@ -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")

View File

@ -198,3 +198,8 @@
line-height: 30px;
height: 30px;
}
.jstree .lock-text{
color: #c00;
font-size: 12px;
}

View File

@ -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('<span')[0] : '';
var parentId = $node && $node.parent !== '#' ? $node.parent : 0;
$then.find("input[name='doc_id']").val(doc_id);
@ -152,6 +152,55 @@ function pushVueLists($lists) {
}
}
/**
*
* @param $node
*/
function lockDocumentAction($node) {
var index = layer.load(1, {
shade: [0.1, '#fff'] // 0.1 透明度的白色背景
});
$.post(window.lockURL,{"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 + "<span class='lock-text'> [锁定]</span>";
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})
});
}
/**
*
*/

View File

@ -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 + "<span class='lock-text'> [锁定]</span>";
// 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 + "<span class='lock-text'> [锁定]</span>";
}
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();

View File

@ -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}}";
</script>
<!-- Bootstrap -->
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet">