diff --git a/controllers/BookController.go b/controllers/BookController.go index 0851a13d..f13faf79 100644 --- a/controllers/BookController.go +++ b/controllers/BookController.go @@ -198,7 +198,7 @@ func (c *BookController) SaveBook() { bookResult.CommentStatus = commentStatus bookResult.Label = tag - beego.Info("用户 [",c.Member.Account ,"] 修改了项目 ->",book) + beego.Info("用户 [", c.Member.Account, "] 修改了项目 ->", book) c.JsonResult(0, "ok", bookResult) } @@ -241,7 +241,7 @@ func (c *BookController) PrivatelyOwned() { logs.Error("PrivatelyOwned => ", err) c.JsonResult(6004, "保存失败") } - beego.Info("用户 【",c.Member.Account,"]修改了项目权限 ->", state) + beego.Info("用户 【", c.Member.Account, "]修改了项目权限 ->", state) c.JsonResult(0, "ok") } @@ -296,12 +296,12 @@ func (c *BookController) UploadCover() { } file, moreFile, err := c.GetFile("image-file") - defer file.Close() if err != nil { - logs.Error("", err.Error()) + logs.Error("获取上传文件失败 ->", err.Error()) c.JsonResult(500, "读取文件异常") } + defer file.Close() ext := filepath.Ext(moreFile.Filename) @@ -321,7 +321,8 @@ func (c *BookController) UploadCover() { fileName := "cover_" + strconv.FormatInt(time.Now().UnixNano(), 16) - filePath := filepath.Join("uploads", time.Now().Format("200601"), fileName+ext) + //附件路径按照项目组织 + filePath := filepath.Join("uploads", book.Identify,"images", fileName+ext) path := filepath.Dir(filePath) @@ -372,7 +373,7 @@ func (c *BookController) UploadCover() { if oldCover != conf.GetDefaultCover() { os.Remove("." + oldCover) } - beego.Info("用户[",c.Member.Account,"]上传了项目封面 ->",book.BookName,book.BookId,book.Cover) + beego.Info("用户[", c.Member.Account, "]上传了项目封面 ->", book.BookName, book.BookId, book.Cover) c.JsonResult(0, "ok", url) } @@ -510,7 +511,7 @@ func (c *BookController) Create() { beego.Error(err) } - beego.Info("用户[",c.Member.Account,"]创建了项目 ->",book) + beego.Info("用户[", c.Member.Account, "]创建了项目 ->", book) c.JsonResult(0, "ok", bookResult) } c.JsonResult(6001, "error") @@ -611,7 +612,7 @@ func (c *BookController) Import() { go book.ImportBook(tempPath) - beego.Info("用户[",c.Member.Account,"]导入了项目 ->",book) + beego.Info("用户[", c.Member.Account, "]导入了项目 ->", book) c.JsonResult(0, "项目正在后台转换中,请稍后查看") } @@ -648,7 +649,7 @@ func (c *BookController) CreateToken() { logs.Error("生成阅读令牌失败 => ", err) c.JsonResult(6003, "生成阅读令牌失败") } - beego.Info("用户[",c.Member.Account,"]创建项目令牌 ->",book.PrivateToken) + beego.Info("用户[", c.Member.Account, "]创建项目令牌 ->", book.PrivateToken) c.JsonResult(0, "ok", conf.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken)) } else { book.PrivateToken = "" @@ -656,7 +657,7 @@ func (c *BookController) CreateToken() { logs.Error("CreateToken => ", err) c.JsonResult(6004, "删除令牌失败") } - beego.Info("用户[",c.Member.Account,"]创建项目令牌 ->",book.PrivateToken) + beego.Info("用户[", c.Member.Account, "]创建项目令牌 ->", book.PrivateToken) c.JsonResult(0, "ok", "") } } @@ -683,7 +684,7 @@ func (c *BookController) Delete() { logs.Error("删除项目 => ", err) c.JsonResult(6003, "删除失败") } - beego.Info("用户[",c.Member.Account,"]删除了项目 ->",bookResult) + beego.Info("用户[", c.Member.Account, "]删除了项目 ->", bookResult) c.JsonResult(0, "ok") } diff --git a/controllers/DocumentController.go b/controllers/DocumentController.go index 5d236a8a..c7bc008d 100644 --- a/controllers/DocumentController.go +++ b/controllers/DocumentController.go @@ -13,7 +13,7 @@ import ( "time" "net/url" "image/png" - + "fmt" "bytes" "github.com/PuerkitoBio/goquery" @@ -27,7 +27,6 @@ import ( "github.com/lifei6671/mindoc/utils/pagination" "gopkg.in/russross/blackfriday.v2" "github.com/lifei6671/mindoc/utils/cryptil" - "fmt" "github.com/lifei6671/mindoc/utils/filetil" "github.com/lifei6671/mindoc/utils/gopool" "github.com/astaxie/beego/logs" @@ -46,7 +45,7 @@ func (c *DocumentController) Index() { token := c.GetString("token") if identify == "" { - c.ShowErrorPage(404,"项目不存在或已删除") + c.ShowErrorPage(404, "项目不存在或已删除") } // 如果没有开启匿名访问则跳转到登录 @@ -62,7 +61,7 @@ func (c *DocumentController) Index() { selected := 0 if bookResult.IsUseFirstDocument { - doc,err := bookResult.FindFirstDocumentByBookId(bookResult.BookId) + doc, err := bookResult.FindFirstDocumentByBookId(bookResult.BookId) if err == nil { if strings.TrimSpace(doc.Release) != "" { doc.Release += "
文档更新时间: " + doc.ModifyTime.Local().Format("2006-01-02 15:04") + "
"; @@ -71,9 +70,9 @@ func (c *DocumentController) Index() { c.Data["Title"] = doc.DocumentName c.Data["Content"] = template.HTML(doc.Release) - c.Data["Description"] = utils.AutoSummary(doc.Release,120) + c.Data["Description"] = utils.AutoSummary(doc.Release, 120) } - }else { + } else { c.Data["Title"] = "概要" c.Data["Content"] = template.HTML(blackfriday.Run([]byte(bookResult.Description))) } @@ -82,10 +81,10 @@ func (c *DocumentController) Index() { if err != nil { if err == orm.ErrNoRows { - c.ShowErrorPage(404,"生成项目文档树时出错") + c.ShowErrorPage(404, "生成项目文档树时出错") } else { - beego.Error("生成项目文档树时出错 -> ",err) - c.ShowErrorPage(500,"生成项目文档树时出错") + beego.Error("生成项目文档树时出错 -> ", err) + c.ShowErrorPage(500, "生成项目文档树时出错") } } c.Data["Model"] = bookResult @@ -104,7 +103,7 @@ func (c *DocumentController) Read() { c.Data["DocumentId"] = id if identify == "" || id == "" { - c.ShowErrorPage(404,"项目不存或已删除") + c.ShowErrorPage(404, "项目不存或已删除") } // 如果没有开启匿名访问则跳转到登录 @@ -115,30 +114,30 @@ func (c *DocumentController) Read() { bookResult := isReadable(identify, token, c) - c.TplName = fmt.Sprintf("document/%s_read.tpl",bookResult.Theme) + c.TplName = fmt.Sprintf("document/%s_read.tpl", bookResult.Theme) doc := models.NewDocument() if docId, err := strconv.Atoi(id); err == nil { doc, err = doc.FromCacheById(docId) if err != nil { - beego.Error("从缓存中读取文档时失败 ->",err) - c.ShowErrorPage(500,"文档不存在或已删除") + beego.Error("从缓存中读取文档时失败 ->", err) + c.ShowErrorPage(500, "文档不存在或已删除") } } else { - doc, err = doc.FromCacheByIdentify(id,bookResult.BookId) + doc, err = doc.FromCacheByIdentify(id, bookResult.BookId) if err != nil { if err == orm.ErrNoRows { - c.ShowErrorPage(404,"文档不存在或已删除") - }else{ - beego.Error("从缓存查询文档时出错 ->" ,err) - c.ShowErrorPage(500,"未知异常") + c.ShowErrorPage(404, "文档不存在或已删除") + } else { + beego.Error("从缓存查询文档时出错 ->", err) + c.ShowErrorPage(500, "未知异常") } } } if doc.BookId != bookResult.BookId { - c.ShowErrorPage(404,"文档不存在或已删除") + c.ShowErrorPage(404, "文档不存在或已删除") } attach, err := models.NewAttachment().FindListByDocumentId(doc.DocumentId) @@ -181,11 +180,11 @@ func (c *DocumentController) Read() { docInfo += ";更新于 " docInfo += doc.ModifyTime.Local().Format("2006-01-02 15:04") if strings.TrimSpace(doc.Release) != "" { - doc.Release += "
文档更新时间: " + doc.ModifyTime.Local().Format("2006-01-02 15:04") +"   作者:"; + doc.Release += "
文档更新时间: " + doc.ModifyTime.Local().Format("2006-01-02 15:04") + "   作者:"; if docCreator != nil { if docCreator.RealName != "" { doc.Release += docCreator.RealName - }else{ + } else { doc.Release += docCreator.Account } } @@ -193,8 +192,6 @@ func (c *DocumentController) Read() { } } - - if c.IsAjax() { var data struct { DocTitle string `json:"doc_title"` @@ -213,14 +210,12 @@ func (c *DocumentController) Read() { tree, err := models.NewDocument().CreateDocumentTreeForHtml(bookResult.BookId, doc.DocumentId) if err != nil && err != orm.ErrNoRows { - beego.Error("生成项目文档树时出错 ->",err) + beego.Error("生成项目文档树时出错 ->", err) - c.ShowErrorPage(500,"生成项目文档树时出错") + c.ShowErrorPage(500, "生成项目文档树时出错") } - - c.Data["Description"] = utils.AutoSummary(doc.Release,120) - + c.Data["Description"] = utils.AutoSummary(doc.Release, 120) c.Data["Model"] = bookResult c.Data["Result"] = template.HTML(tree) @@ -235,7 +230,7 @@ func (c *DocumentController) Edit() { identify := c.Ctx.Input.Param(":key") if identify == "" { - c.ShowErrorPage(404,"无法解析项目标识") + c.ShowErrorPage(404, "无法解析项目标识") } bookResult := models.NewBookResult() @@ -255,9 +250,9 @@ func (c *DocumentController) Edit() { if err != nil { if err == orm.ErrNoRows { c.ShowErrorPage(403, "项目不存在或没有权限") - }else{ + } else { beego.Error("查询项目时出错 -> ", err) - c.ShowErrorPage(500,"查询项目时出错") + c.ShowErrorPage(500, "查询项目时出错") } } if bookResult.RoleId == conf.BookObserver { @@ -315,7 +310,6 @@ func (c *DocumentController) Create() { c.JsonResult(6004, "文档名称不能为空") } - bookId := 0 // 如果是超级管理员则不判断权限 @@ -343,7 +337,7 @@ func (c *DocumentController) Create() { c.JsonResult(6003, "文档标识只能包含小写字母、数字,以及“-”、“.”和“_”符号") } - d, _ := models.NewDocument().FindByIdentityFirst(docIdentify,bookId) + d, _ := models.NewDocument().FindByIdentityFirst(docIdentify, bookId) if d.DocumentId > 0 && d.DocumentId != docId { c.JsonResult(6006, "文档标识已被使用") } @@ -377,8 +371,8 @@ func (c *DocumentController) Create() { // 上传附件或图片 func (c *DocumentController) Upload() { identify := c.GetString("identify") - doc_id, _ := c.GetInt("doc_id") - is_attach := true + docId, _ := c.GetInt("doc_id") + isAttach := true if identify == "" { c.JsonResult(6001, "参数错误") @@ -452,8 +446,8 @@ func (c *DocumentController) Upload() { 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, "文档不存在") } @@ -463,9 +457,15 @@ func (c *DocumentController) Upload() { } } - fileName := "attach_" + strconv.FormatInt(time.Now().UnixNano(), 16) + fileName := "m_" + cryptil.UniqueId() + "_r" + filePath := filepath.Join(conf.WorkingDirectory, "uploads", identify) - filePath := filepath.Join(conf.WorkingDirectory, "uploads", time.Now().Format("200601"),identify, fileName+ext) + //将图片和文件分开存放 + if strings.EqualFold(ext, ".jpg") || strings.EqualFold(ext, ".jpeg") || strings.EqualFold(ext, ".png") || strings.EqualFold(ext, ".gif") { + filePath = filepath.Join(filePath, "images", fileName+ext) + } else { + filePath = filepath.Join(filePath, "files", fileName+ext) + } path := filepath.Dir(filePath) @@ -474,7 +474,7 @@ func (c *DocumentController) Upload() { err = c.SaveToFile(name, filePath) if err != nil { - beego.Error("SaveToFile => ", err) + beego.Error("保存文件失败 -> ", err) c.JsonResult(6005, "保存文件失败") } @@ -484,14 +484,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") { @@ -500,7 +500,7 @@ func (c *DocumentController) Upload() { attachment.HttpPath = conf.URLForWithCdnImage(string(attachment.HttpPath[1:])) } - is_attach = false + isAttach = false } err = attachment.Insert() @@ -526,7 +526,7 @@ func (c *DocumentController) Upload() { "message": "ok", "url": attachment.HttpPath, "alt": attachment.FileName, - "is_attach": is_attach, + "is_attach": isAttach, "attach": attachment, } @@ -558,10 +558,10 @@ func (c *DocumentController) DownloadAttachment() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { if err == orm.ErrNoRows { - c.ShowErrorPage(404,"项目不存在或已删除") - }else{ - beego.Error("查找项目时出错 ->",err) - c.ShowErrorPage(500,"系统错误") + c.ShowErrorPage(404, "项目不存在或已删除") + } else { + beego.Error("查找项目时出错 ->", err) + c.ShowErrorPage(500, "系统错误") } } @@ -569,7 +569,7 @@ func (c *DocumentController) DownloadAttachment() { if c.Member == nil || c.Member.Role != conf.MemberSuperRole { // 如果项目是私有的,并且 token 不正确 if (book.PrivatelyOwned == 1 && token == "") || (book.PrivatelyOwned == 1 && book.PrivateToken != token) { - c.ShowErrorPage(403,"权限不足") + c.ShowErrorPage(403, "权限不足") } } @@ -584,14 +584,14 @@ func (c *DocumentController) DownloadAttachment() { if err != nil { beego.Error("查找附件时出错 -> ", err) if err == orm.ErrNoRows { - c.ShowErrorPage(404,"附件不存在或已删除") + c.ShowErrorPage(404, "附件不存在或已删除") } else { - c.ShowErrorPage(500,"查找附件时出错") + c.ShowErrorPage(500, "查找附件时出错") } } if attachment.BookId != bookId { - c.ShowErrorPage(404,"附件不存在或已删除") + c.ShowErrorPage(404, "附件不存在或已删除") } c.Ctx.Output.Download(filepath.Join(conf.WorkingDirectory, attachment.FilePath), attachment.FileName) @@ -649,9 +649,9 @@ func (c *DocumentController) Delete() { c.Prepare() identify := c.GetString("identify") - doc_id, err := c.GetInt("doc_id", 0) + docId, err := c.GetInt("doc_id", 0) - book_id := 0 + bookId := 0 // 如果是超级管理员则忽略权限判断 if c.Member.IsAdministrator() { @@ -661,7 +661,7 @@ func (c *DocumentController) Delete() { c.JsonResult(6002, "项目不存在或权限不足") } - book_id = book.BookId + bookId = book.BookId } else { bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) @@ -670,21 +670,21 @@ func (c *DocumentController) Delete() { c.JsonResult(6002, "项目不存在或权限不足") } - book_id = bookResult.BookId + bookId = bookResult.BookId } - if doc_id <= 0 { + if docId <= 0 { c.JsonResult(6001, "参数错误") } - doc, err := models.NewDocument().Find(doc_id) + doc, err := models.NewDocument().Find(docId) if err != nil { beego.Error("Delete => ", err) c.JsonResult(6003, "删除失败") } // 如果文档所属项目错误 - if doc.BookId != book_id { + if doc.BookId != bookId { c.JsonResult(6004, "参数错误") } @@ -801,7 +801,7 @@ func (c *DocumentController) Content() { go func() { err := doc.ReleaseContent() if err == nil { - logs.Informational("文档自动发布成功 -> document_id=%d;document_name=%s",doc.DocumentId, doc.DocumentName) + logs.Informational("文档自动发布成功 -> document_id=%d;document_name=%s", doc.DocumentId, doc.DocumentName) } }() } @@ -821,6 +821,7 @@ func (c *DocumentController) Content() { c.JsonResult(0, "ok", doc) } + // //func (c *DocumentController) GetDocumentById(id string) (doc *models.Document, err error) { // doc = models.NewDocument() @@ -845,7 +846,7 @@ func (c *DocumentController) Export() { identify := c.Ctx.Input.Param(":key") if identify == "" { - c.ShowErrorPage(500,"参数错误") + c.ShowErrorPage(500, "参数错误") } output := c.GetString("output") @@ -857,7 +858,7 @@ func (c *DocumentController) Export() { return } if !conf.GetEnableExport() { - c.ShowErrorPage(500,"系统没有开启导出功能") + c.ShowErrorPage(500, "系统没有开启导出功能") } bookResult := models.NewBookResult() @@ -865,10 +866,10 @@ func (c *DocumentController) Export() { book, err := models.NewBook().FindByIdentify(identify) if err != nil { if err == orm.ErrNoRows { - c.ShowErrorPage(404,"项目不存在") + c.ShowErrorPage(404, "项目不存在") } else { - beego.Error("查找项目时出错 ->",err) - c.ShowErrorPage(500,"查找项目时出错") + beego.Error("查找项目时出错 ->", err) + c.ShowErrorPage(500, "查找项目时出错") } } bookResult = models.NewBookResult().ToBookResult(*book) @@ -876,7 +877,7 @@ func (c *DocumentController) Export() { bookResult = isReadable(identify, token, c) } if !bookResult.IsDownload { - c.ShowErrorPage(200,"当前项目没有开启导出功能") + c.ShowErrorPage(200, "当前项目没有开启导出功能") } if !strings.HasPrefix(bookResult.Cover, "http:://") && !strings.HasPrefix(bookResult.Cover, "https:://") { @@ -884,13 +885,13 @@ func (c *DocumentController) Export() { } if output == "markdown" { - if bookResult.Editor != "markdown"{ - c.ShowErrorPage(500,"当前项目不支持Markdown编辑器") + if bookResult.Editor != "markdown" { + c.ShowErrorPage(500, "当前项目不支持Markdown编辑器") } - p,err := bookResult.ExportMarkdown(c.CruSession.SessionID()) + p, err := bookResult.ExportMarkdown(c.CruSession.SessionID()) if err != nil { - c.ShowErrorPage(500,"导出文档失败") + c.ShowErrorPage(500, "导出文档失败") } c.Ctx.Output.Download(p, bookResult.BookName+".zip") @@ -905,10 +906,10 @@ func (c *DocumentController) Export() { mobipath := filepath.Join(outputPath, "book.mobi") docxpath := filepath.Join(outputPath, "book.docx") - if output == "pdf" && filetil.FileExists(pdfpath){ + if output == "pdf" && filetil.FileExists(pdfpath) { c.Ctx.Output.Download(pdfpath, bookResult.BookName+".pdf") c.Abort("200") - } else if output == "epub" && filetil.FileExists(epubpath){ + } else if output == "epub" && filetil.FileExists(epubpath) { c.Ctx.Output.Download(epubpath, bookResult.BookName+".epub") c.Abort("200") @@ -916,22 +917,22 @@ func (c *DocumentController) Export() { c.Ctx.Output.Download(mobipath, bookResult.BookName+".mobi") c.Abort("200") - } else if output == "docx" && filetil.FileExists(docxpath){ + } else if output == "docx" && filetil.FileExists(docxpath) { c.Ctx.Output.Download(docxpath, bookResult.BookName+".docx") c.Abort("200") - }else if output == "pdf" || output == "epub" || output == "docx" || output == "mobi"{ - if err := models.BackgroupConvert(c.CruSession.SessionID(),bookResult);err != nil && err != gopool.ErrHandlerIsExist{ - c.ShowErrorPage(500,"导出失败,请查看系统日志") + } else if output == "pdf" || output == "epub" || output == "docx" || output == "mobi" { + if err := models.BackgroupConvert(c.CruSession.SessionID(), bookResult); err != nil && err != gopool.ErrHandlerIsExist { + c.ShowErrorPage(500, "导出失败,请查看系统日志") } - c.ShowErrorPage(200,"文档正在后台转换,请稍后再下载") - }else{ - c.ShowErrorPage(200,"不支持的文件格式") + c.ShowErrorPage(200, "文档正在后台转换,请稍后再下载") + } else { + c.ShowErrorPage(200, "不支持的文件格式") } - c.ShowErrorPage(404,"项目没有导出文件") + c.ShowErrorPage(404, "项目没有导出文件") } // 生成项目访问的二维码 @@ -942,20 +943,20 @@ func (c *DocumentController) QrCode() { book, err := models.NewBook().FindByIdentify(identify) if err != nil || book.BookId <= 0 { - c.ShowErrorPage(404,"项目不存在") + c.ShowErrorPage(404, "项目不存在") } uri := conf.URLFor("DocumentController.Index", ":key", identify) code, err := qr.Encode(uri, qr.L, qr.Unicode) if err != nil { - beego.Error("生成二维码失败 ->",err) - c.ShowErrorPage(500,"生成二维码失败") + beego.Error("生成二维码失败 ->", err) + c.ShowErrorPage(500, "生成二维码失败") } code, err = barcode.Scale(code, 150, 150) if err != nil { - beego.Error("生成二维码失败 ->",err) - c.ShowErrorPage(500,"生成二维码失败") + beego.Error("生成二维码失败 ->", err) + c.ShowErrorPage(500, "生成二维码失败") } c.Ctx.ResponseWriter.Header().Set("Content-Type", "image/png") @@ -964,8 +965,8 @@ func (c *DocumentController) QrCode() { err = png.Encode(c.Ctx.ResponseWriter, code) if err != nil { - beego.Error("生成二维码失败 ->",err) - c.ShowErrorPage(500,"生成二维码失败") + beego.Error("生成二维码失败 ->", err) + c.ShowErrorPage(500, "生成二维码失败") } } @@ -1018,7 +1019,7 @@ func (c *DocumentController) History() { docId, err := c.GetInt("doc_id", 0) pageIndex, _ := c.GetInt("page", 1) - book_id := 0 + bookId := 0 // 如果是超级管理员则忽略权限判断 if c.Member.IsAdministrator() { @@ -1029,7 +1030,7 @@ func (c *DocumentController) History() { return } - book_id = book.BookId + bookId = book.BookId c.Data["Model"] = book } else { bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) @@ -1039,7 +1040,7 @@ func (c *DocumentController) History() { return } - book_id = bookResult.BookId + bookId = bookResult.BookId c.Data["Model"] = bookResult } @@ -1056,19 +1057,19 @@ func (c *DocumentController) History() { } // 如果文档所属项目错误 - if doc.BookId != book_id { + if doc.BookId != bookId { c.Data["ErrorMessage"] = "参数错误" return } - historis, totalCount, err := models.NewDocumentHistory().FindToPager(docId, pageIndex, conf.PageSize) + histories, totalCount, err := models.NewDocumentHistory().FindToPager(docId, pageIndex, conf.PageSize) if err != nil { beego.Error("分页查找文档历史失败 ->", err) c.Data["ErrorMessage"] = "获取历史失败" return } - c.Data["List"] = historis + c.Data["List"] = histories c.Data["PageHtml"] = "" c.Data["Document"] = doc @@ -1135,6 +1136,7 @@ func (c *DocumentController) DeleteHistory() { c.JsonResult(0, "ok") } + //通过文档历史恢复文档 func (c *DocumentController) RestoreHistory() { c.Prepare() @@ -1209,7 +1211,7 @@ func (c *DocumentController) Compare() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { beego.Error("DocumentController.Compare => ", err) - c.ShowErrorPage(403,"权限不足") + c.ShowErrorPage(403, "权限不足") return } @@ -1220,7 +1222,7 @@ func (c *DocumentController) Compare() { bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil || bookResult.RoleId == conf.BookObserver { beego.Error("FindByIdentify => ", err) - c.ShowErrorPage(403,"权限不足") + c.ShowErrorPage(403, "权限不足") return } @@ -1281,14 +1283,14 @@ func EachFun(prefix, dpath string, c *DocumentController, book *models.BookResul f, err := os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0777) if err != nil { beego.Error(err) - c.ShowErrorPage(500,"系统错误") + c.ShowErrorPage(500, "系统错误") } html, err := c.ExecuteViewPathTemplate("document/export.tpl", map[string]interface{}{"Model": book, "Lists": item, "BaseUrl": c.BaseUrl()}) if err != nil { f.Close() beego.Error(err) - c.ShowErrorPage(500,"系统错误") + c.ShowErrorPage(500, "系统错误") } buf := bytes.NewReader([]byte(html)) @@ -1303,7 +1305,7 @@ func EachFun(prefix, dpath string, c *DocumentController, book *models.BookResul if err != nil { f.Close() beego.Error(err) - c.ShowErrorPage(500,"系统错误") + c.ShowErrorPage(500, "系统错误") } // html = strings.Replace(html, " 0 { + t,err := template.Find(templateId); + if err != nil { + c.JsonResult(500,"模板不存在") + } + + template = t + template.ModifyAt = c.Member.MemberId + } + + template.TemplateId = templateId template.BookId = c.BookId template.TemplateContent = content - template.MemberId = c.Member.MemberId + template.TemplateName = templateName - if templateId > 0 { - template.ModifyAt = c.Member.MemberId - } //只有管理员才能设置全局模板 if c.Member.IsAdministrator() { template.IsGlobal = isGlobal }else{ template.IsGlobal = 0 + //如果不是管理员需要判断是否有项目权限 + rel,err := models.NewRelationship().FindByBookIdAndMemberId(c.BookId,c.Member.MemberId) + if err != nil || rel.RoleId == conf.BookObserver { + c.JsonResult(403,"没有权限") + } + //如果修改的模板不是本人创建的,并且又不是项目创建者则禁止修改 + if template.MemberId > 0 && template.MemberId != c.Member.MemberId && rel.RoleId != conf.BookFounder { + c.JsonResult(403,"没有权限") + } } + template.MemberId = c.Member.MemberId var cols []string @@ -104,20 +145,40 @@ func (c *TemplateController) Add() { c.JsonResult(0,"OK",template) } +//删除模板 func (c *TemplateController) Delete() { if err := c.isPermission() ; err != nil { c.JsonResult(500,err.Error()) } templateId, _ := c.GetInt("template_id",0) + template,err := models.NewTemplate().Find(templateId) + + if err != nil { + c.JsonResult(404,"模板不存在") + } + if c.Member.IsAdministrator() { err := models.NewTemplate().Delete(templateId,0) if err != nil { c.JsonResult(500,"删除失败") } }else{ - err := models.NewTemplate().Delete(templateId,c.Member.MemberId) - if err != nil { + //如果不是管理员需要判断是否有项目权限 + rel,err := models.NewRelationship().FindByBookIdAndMemberId(template.BookId,c.Member.MemberId) + if err != nil || rel.RoleId == conf.BookObserver { + c.JsonResult(403,"没有权限") + } + + //如果是创始人或管理者可以直接删除模板 + if rel.RoleId == conf.BookFounder || rel.RoleId == conf.BookAdmin { + err := models.NewTemplate().Delete(templateId,0) + if err != nil { + c.JsonResult(500,"删除失败") + } + } + + if err := models.NewTemplate().Delete(templateId,c.Member.MemberId);err != nil { c.JsonResult(500,"删除失败") } } diff --git a/models/BookModel.go b/models/BookModel.go index 795859f6..74d61e35 100644 --- a/models/BookModel.go +++ b/models/BookModel.go @@ -72,8 +72,8 @@ type Book struct { IsUseFirstDocument int `orm:"column(is_use_first_document);type(int);default(0)" json:"is_use_first_document"` } -func (b *Book) String() string { - ret, err := json.Marshal(*b) +func (book *Book) String() string { + ret, err := json.Marshal(*book) if err != nil { return "" @@ -136,13 +136,13 @@ func (book *Book) Insert() error { return err } -func (book *Book) Find(id int) (*Book, error) { +func (book *Book) Find(id int,cols ...string) (*Book, error) { if id <= 0 { return book, ErrInvalidParameter } o := orm.NewOrm() - err := o.QueryTable(book.TableNameWithPrefix()).Filter("book_id", id).One(book) + err := o.QueryTable(book.TableNameWithPrefix()).Filter("book_id", id).One(book,cols...) return book, err } @@ -221,7 +221,7 @@ func (book *Book) Copy(identify string) error { return err } 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) o.Rollback() return err @@ -371,31 +371,41 @@ func (book *Book) ThoroughDeleteBook(id int) error { } o.Begin() - sql2 := "DELETE FROM " + NewDocument().TableNameWithPrefix() + " WHERE book_id = ?" + //删除附件,这里没有删除实际物理文件 + _,err = o.Raw("DELETE FROM " + NewAttachment().TableNameWithPrefix() + " WHERE book_id=?").Exec() + if err != nil { + o.Rollback() + return err + } - _, err = o.Raw(sql2, book.BookId).Exec() + //删除文档 + _, err = o.Raw( "DELETE FROM " + NewDocument().TableNameWithPrefix() + " WHERE book_id = ?", book.BookId).Exec() if err != nil { o.Rollback() return err } - sql3 := "DELETE FROM " + book.TableNameWithPrefix() + " WHERE book_id = ?" - - _, err = o.Raw(sql3, book.BookId).Exec() + //删除项目 + _, err = o.Raw("DELETE FROM " + book.TableNameWithPrefix() + " WHERE book_id = ?", book.BookId).Exec() if err != nil { o.Rollback() return err } - sql4 := "DELETE FROM " + NewRelationship().TableNameWithPrefix() + " WHERE book_id = ?" - - _, err = o.Raw(sql4, book.BookId).Exec() + //删除关系 + _, err = o.Raw("DELETE FROM " + NewRelationship().TableNameWithPrefix() + " WHERE book_id = ?", book.BookId).Exec() if err != nil { o.Rollback() - return err } + //删除模板 + _,err = o.Raw("DELETE FROM " + NewTemplate().TableNameWithPrefix() + " WHERE book_id = ?",book.BookId).Exec() + if err != nil { + o.Rollback() + return err + } + if book.Label != "" { NewLabel().InsertOrUpdateMulti(book.Label) @@ -821,7 +831,7 @@ func (book *Book) ImportBook(zipPath string) error { beego.Error("导入项目异常 => ", err) book.Description = "【项目导入存在错误:" + err.Error() + "】" } - beego.Info("项目导入完毕 => ",book.BookName) + beego.Info("项目导入完毕 => ", book.BookName) book.ReleaseContent(book.BookId) return err } diff --git a/models/Member.go b/models/Member.go index 56f86629..90f543c8 100644 --- a/models/Member.go +++ b/models/Member.go @@ -204,11 +204,10 @@ func (m *Member) Update(cols ...string) error { return nil } -func (m *Member) Find(id int) (*Member, error) { +func (m *Member) Find(id int,cols ...string) (*Member, error) { o := orm.NewOrm() - m.MemberId = id - if err := o.Read(m); err != nil { + if err := o.QueryTable(m.TableNameWithPrefix()).Filter("member_id",id).One(m,cols...); err != nil { return m, err } m.ResolveRoleName() @@ -408,6 +407,18 @@ func (m *Member) Delete(oldId int, newId int) error { o.Rollback() return err } + + _, err = o.Raw("UPDATE md_templates SET modify_at = ? WHERE modify_at = ?", newId, oldId).Exec() + if err != nil { + o.Rollback() + return err + } + + _, err = o.Raw("UPDATE md_templates SET member_id = ? WHERE member_id = ?", newId, oldId).Exec() + if err != nil { + o.Rollback() + return err + } //_,err = o.Raw("UPDATE md_relationship SET member_id = ? WHERE member_id = ?",newId,oldId).Exec() //if err != nil { // diff --git a/models/Template.go b/models/Template.go index 7c49c1ab..49a5325b 100644 --- a/models/Template.go +++ b/models/Template.go @@ -14,12 +14,15 @@ type Template struct { TemplateName string `orm:"column(template_name);size(500);" json:"template_name"` MemberId int `orm:"column(member_id);index" json:"member_id"` BookId int `orm:"column(book_id);index" json:"book_id"` + BookName string `orm:"-" json:"book_name"` //是否是全局模板:0 否/1 是; 全局模板在所有项目中都可以使用;否则只能在创建模板的项目中使用 IsGlobal int `orm:"column(is_global);default(0)" json:"is_global"` TemplateContent string `orm:"column(template_content);type(text);null" json:"template_content"` CreateTime time.Time `orm:"column(create_time);type(datetime);auto_now_add" json:"create_time"` + CreateName string `orm:"-" json:"create_name"` ModifyTime time.Time `orm:"column(modify_time);type(datetime);auto_now" json:"modify_time"` ModifyAt int `orm:"column(modify_at);type(int)" json:"-"` + ModifyName string `orm:"-" json:"modify_name"` Version int64 `orm:"type(bigint);column(version)" json:"version"` } @@ -125,14 +128,15 @@ func (t *Template) Save(cols ...string) (err error) { } o := orm.NewOrm() - if !o.QueryTable(NewBook()).Filter("book_id",t.BookId).Exist() { + if !o.QueryTable(NewBook().TableNameWithPrefix()).Filter("book_id",t.BookId).Exist() { return errors.New("项目不存在") } - if !o.QueryTable(NewMember()).Filter("member_id",t.MemberId).Filter("status",0).Exist() { + if !o.QueryTable(NewMember().TableNameWithPrefix()).Filter("member_id",t.MemberId).Filter("status",0).Exist() { return errors.New("用户已被禁用") } + t.Version = time.Now().Unix() + if t.TemplateId > 0 { - t.Version = time.Now().Unix() t.ModifyTime = time.Now() _,err = o.Update(t,cols...) }else{ @@ -143,8 +147,38 @@ func (t *Template) Save(cols ...string) (err error) { return } - - +//预加载一些数据 +func (t *Template) Preload() *Template { + if t != nil { + if t.MemberId > 0 { + m,err := NewMember().Find(t.MemberId,"account","real_name"); + if err == nil { + if m.RealName != "" { + t.CreateName = m.RealName + }else{ + t.CreateName = m.Account + } + }else{ + beego.Error("加载模板所有者失败 ->",err) + } + } + if t.ModifyAt > 0 { + if m,err := NewMember().Find(t.ModifyAt,"account","real_name"); err == nil { + if m.RealName != "" { + t.ModifyName = m.RealName + }else{ + t.ModifyName = m.Account + } + } + } + if t.BookId > 0 { + if b,err := NewBook().Find(t.BookId,"book_name");err == nil { + t.BookName = b.BookName + } + } + } + return t +} diff --git a/routers/router.go b/routers/router.go index 0b9c8ac6..ec7bd21a 100644 --- a/routers/router.go +++ b/routers/router.go @@ -78,6 +78,7 @@ func init() { beego.Router("/blog-:id([0-9]+).html",&controllers.BlogController{}, "*:Index") //模板相关接口 + beego.Router("/api/template/get", &controllers.TemplateController{},"get:Get") beego.Router("/api/template/list", &controllers.TemplateController{},"post:List") beego.Router("/api/template/add", &controllers.TemplateController{},"post:Add") beego.Router("/api/template/remove", &controllers.TemplateController{},"post:Delete") diff --git a/static/js/markdown.js b/static/js/markdown.js index 32b3e392..9cfe8277 100644 --- a/static/js/markdown.js +++ b/static/js/markdown.js @@ -86,7 +86,9 @@ $(function () { saveDocument(false); } else if (name === "template") { $("#documentTemplateModal").modal("show"); - } else if (name === "sidebar") { + } else if(name === "save-template"){ + $("#saveTemplateModal").modal("show"); + }else if (name === "sidebar") { $("#manualCategory").toggle(0, "swing", function () { var $then = $("#manualEditorContainer"); var left = parseInt($then.css("left")); @@ -380,7 +382,9 @@ $(function () { } $("#documentTemplateModal").modal('hide'); }); - + /** + * 展示自定义模板列表 + */ $("#displayCustomsTemplateModal").on("show.bs.modal",function () { window.sessionStorage.setItem("displayCustomsTemplateList",$("#displayCustomsTemplateList").html()); @@ -392,12 +396,12 @@ $(function () { url : window.template.listUrl, data: {"identify":window.book.identify}, type: "POST", - dataType: "json", + dataType: "html", success: function ($res) { - + $("#displayCustomsTemplateList").html($res); }, error : function () { - + layer.msg("加载失败请重试"); }, complete : function () { layer.close(index); @@ -408,4 +412,91 @@ $(function () { var cache = window.sessionStorage.getItem("displayCustomsTemplateList"); $("#displayCustomsTemplateList").html(cache); }); + /** + * 添加模板 + */ + $("#saveTemplateForm").ajaxForm({ + beforeSubmit: function () { + var doc_name = $.trim($("#templateName").val()); + if (doc_name === "") { + return showError("模板名称不能为空", "#saveTemplateForm .show-error-message"); + } + var content = $("#saveTemplateForm").find("input[name='content']").val(); + if (content === ""){ + return showError("模板内容不能为空", "#saveTemplateForm .show-error-message"); + } + + $("#btnSaveTemplate").button("loading"); + + return true; + }, + success: function ($res) { + if($res.errcode === 0){ + $("#saveTemplateModal").modal("hide"); + layer.msg("保存成功"); + }else{ + return showError($res.message, "#saveTemplateForm .show-error-message"); + } + }, + complete : function () { + $("#btnSaveTemplate").button("reset"); + } + }); + + $("#saveTemplateModal").on("show.bs.modal",function () { + window.sessionStorage.setItem("saveTemplateModal",$(this).find(".modal-body").html()); + var content = window.editor.getMarkdown(); + $("#saveTemplateForm").find("input[name='content']").val(content); + }).on("hidden.bs.modal",function () { + $(this).find(".modal-body").html(window.sessionStorage.getItem("saveTemplateModal")); + }); + + $("#displayCustomsTemplateList").on("click",".btn-insert",function () { + var templateId = $(this).attr("data-id"); + + $.ajax({ + url: window.template.getUrl, + data :{"identify": window.book.identify, "template_id": templateId}, + dataType: "json", + type: "get", + success : function ($res) { + if ($res.errcode !== 0){ + layer.msg($res.message); + return; + } + window.isLoad = true; + window.editor.clear(); + window.editor.insertValue($res.data.template_content); + window.editor.setCursor({ line: 0, ch: 0 }); + resetEditorChanged(true); + $("#displayCustomsTemplateModal").modal("hide"); + },error : function () { + layer.msg("服务器异常"); + } + }); + }).on("click",".btn-delete",function () { + var $then = $(this); + var templateId = $then.attr("data-id"); + $then.button("loading"); + + $.ajax({ + url : window.template.deleteUrl, + data: {"identify": window.book.identify, "template_id": templateId}, + dataType: "json", + type: "post", + success: function ($res) { + if($res.errcode !== 0){ + layer.msg($res.message); + }else{ + $then.parents("tr").empty().remove(); + } + },error : function () { + layer.msg("服务器异常"); + }, + complete: function () { + $then.button("reset"); + } + }) + }); + }); \ No newline at end of file diff --git a/utils/cryptil/cryptil.go b/utils/cryptil/cryptil.go index 8e6fe84b..6df493b6 100644 --- a/utils/cryptil/cryptil.go +++ b/utils/cryptil/cryptil.go @@ -9,6 +9,8 @@ import ( "strconv" "strings" "time" + "io" + "crypto/rand" ) //对称加密与解密之加密【从Beego中提取出来的】 @@ -68,3 +70,14 @@ func Sha1Crypt(str string, salt ...interface{}) (CryptStr string) { } return fmt.Sprintf("%x", sha1.Sum([]byte(str))) } + + +//生成Guid字串 +func UniqueId() string { + b := make([]byte, 48) + + if _, err := io.ReadFull(rand.Reader, b); err != nil { + return "" + } + return Md5Crypt(base64.URLEncoding.EncodeToString(b)) +} \ No newline at end of file diff --git a/utils/filetil/filetil.go b/utils/filetil/filetil.go index e7df8080..db13671f 100644 --- a/utils/filetil/filetil.go +++ b/utils/filetil/filetil.go @@ -241,21 +241,4 @@ func ReadFileAndIgnoreUTF8BOM(filename string) ([]byte,error) { return data,nil - - //fd, err := os.Open(filename) - // - //if err != nil { - // return nil,err - //} - //bom := [3]byte{} - // - //_, err = io.ReadFull(fd, bom[:]) - //if err != nil { - // return nil,err - //} - //if bom[0] != 0xef || bom[1] != 0xbb || bom[2] != 0xbf { - // _, err = fd.Seek(0, 0) - //} - // - //return ioutil.ReadAll(fd) -} \ No newline at end of file +} diff --git a/views/book/dashboard.tpl b/views/book/dashboard.tpl index d49c0127..c7c2e3bc 100644 --- a/views/book/dashboard.tpl +++ b/views/book/dashboard.tpl @@ -59,7 +59,7 @@
- +
diff --git a/views/document/markdown_edit_template.tpl b/views/document/markdown_edit_template.tpl index 2c8bfff8..d2d22ea8 100644 --- a/views/document/markdown_edit_template.tpl +++ b/views/document/markdown_edit_template.tpl @@ -23,24 +23,31 @@ window.historyURL = "{{urlfor "DocumentController.History"}}"; window.removeAttachURL = "{{urlfor "DocumentController.RemoveAttachment"}}"; window.highlightStyle = "{{.HighlightStyle}}"; - window.template = { "listUrl" : "{{urlfor "TemplateController.List"}}", "deleteUrl" : "{{urlfor "TemplateController.Delete"}}", "saveUrl" :"{{urlfor "TemplateController.Add"}}"} + window.template = { "getUrl":"{{urlfor "TemplateController.Get"}}", "listUrl" : "{{urlfor "TemplateController.List"}}", "deleteUrl" : "{{urlfor "TemplateController.Delete"}}", "saveUrl" :"{{urlfor "TemplateController.Add"}}"} - + - - + + + @@ -50,7 +57,8 @@
- + +
@@ -163,6 +171,8 @@
+ + - + - +