document.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868
  1. package controllers
  2. import (
  3. "container/list"
  4. "encoding/json"
  5. "html/template"
  6. "net/http"
  7. "os"
  8. "path/filepath"
  9. "regexp"
  10. "strconv"
  11. "strings"
  12. "time"
  13. "image/png"
  14. "github.com/astaxie/beego"
  15. "github.com/astaxie/beego/orm"
  16. "github.com/boombuler/barcode"
  17. "github.com/boombuler/barcode/qr"
  18. "github.com/lifei6671/godoc/conf"
  19. "github.com/lifei6671/godoc/models"
  20. "github.com/lifei6671/godoc/utils/wkhtmltopdf"
  21. )
  22. //DocumentController struct.
  23. type DocumentController struct {
  24. BaseController
  25. }
  26. //判断用户是否可以阅读文档.
  27. func isReadable(identify, token string, c *DocumentController) *models.BookResult {
  28. book, err := models.NewBook().FindByFieldFirst("identify", identify)
  29. if err != nil {
  30. beego.Error(err)
  31. c.Abort("500")
  32. }
  33. if c.Member != nil && c.Member.Role == conf.MemberSuperRole {
  34. bookResult := book.ToBookResult()
  35. return bookResult
  36. }
  37. //如果文档是私有的
  38. if book.PrivatelyOwned == 1 {
  39. is_ok := false
  40. if c.Member != nil {
  41. _, err := models.NewRelationship().FindForRoleId(book.BookId, c.Member.MemberId)
  42. if err == nil {
  43. is_ok = true
  44. }
  45. }
  46. if book.PrivateToken != "" && !is_ok {
  47. //如果有访问的Token,并且该项目设置了访问Token,并且和用户提供的相匹配,则记录到Session中.
  48. //如果用户未提供Token且用户登录了,则判断用户是否参与了该项目.
  49. //如果用户未登录,则从Session中读取Token.
  50. if token != "" && strings.EqualFold(token, book.PrivateToken) {
  51. c.SetSession(identify, token)
  52. } else if token, ok := c.GetSession(identify).(string); !ok || !strings.EqualFold(token, book.PrivateToken) {
  53. c.Abort("403")
  54. }
  55. } else if !is_ok {
  56. c.Abort("403")
  57. }
  58. }
  59. bookResult := book.ToBookResult()
  60. if c.Member != nil {
  61. rel, err := models.NewRelationship().FindByBookIdAndMemberId(bookResult.BookId, c.Member.MemberId)
  62. if err == nil {
  63. bookResult.MemberId = rel.MemberId
  64. bookResult.RoleId = rel.RoleId
  65. bookResult.RelationshipId = rel.RelationshipId
  66. }
  67. }
  68. //判断是否需要显示评论框
  69. if bookResult.CommentStatus == "closed" {
  70. bookResult.IsDisplayComment = false
  71. } else if bookResult.CommentStatus == "open" {
  72. bookResult.IsDisplayComment = true
  73. } else if bookResult.CommentStatus == "group_only" {
  74. bookResult.IsDisplayComment = bookResult.RelationshipId > 0
  75. } else if bookResult.CommentStatus == "registered_only" {
  76. bookResult.IsDisplayComment = true
  77. }
  78. return bookResult
  79. }
  80. //文档首页.
  81. func (c *DocumentController) Index() {
  82. c.Prepare()
  83. identify := c.Ctx.Input.Param(":key")
  84. token := c.GetString("token")
  85. if identify == "" {
  86. c.Abort("404")
  87. }
  88. //如果没有开启你们访问则跳转到登录
  89. if !c.EnableAnonymous && c.Member == nil {
  90. c.Redirect(beego.URLFor("AccountController.Login"), 302)
  91. return
  92. }
  93. bookResult := isReadable(identify, token, c)
  94. c.TplName = "document/" + bookResult.Theme + "_read.tpl"
  95. tree, err := models.NewDocument().CreateDocumentTreeForHtml(bookResult.BookId, 0)
  96. if err != nil {
  97. beego.Error(err)
  98. c.Abort("500")
  99. }
  100. c.Data["Model"] = bookResult
  101. c.Data["Result"] = template.HTML(tree)
  102. c.Data["Title"] = "概要"
  103. c.Data["Content"] = bookResult.Description
  104. }
  105. //阅读文档.
  106. func (c *DocumentController) Read() {
  107. c.Prepare()
  108. identify := c.Ctx.Input.Param(":key")
  109. token := c.GetString("token")
  110. id := c.GetString(":id")
  111. if identify == "" || id == "" {
  112. c.Abort("404")
  113. }
  114. //如果没有开启你们访问则跳转到登录
  115. if !c.EnableAnonymous && c.Member == nil {
  116. c.Redirect(beego.URLFor("AccountController.Login"), 302)
  117. return
  118. }
  119. bookResult := isReadable(identify, token, c)
  120. c.TplName = "document/" + bookResult.Theme + "_read.tpl"
  121. doc := models.NewDocument()
  122. if doc_id, err := strconv.Atoi(id); err == nil {
  123. doc, err = doc.Find(doc_id)
  124. if err != nil {
  125. beego.Error(err)
  126. c.Abort("500")
  127. }
  128. } else {
  129. doc, err = doc.FindByFieldFirst("identify", id)
  130. if err != nil {
  131. beego.Error(err)
  132. c.Abort("500")
  133. }
  134. }
  135. if doc.BookId != bookResult.BookId {
  136. c.Abort("403")
  137. }
  138. attach, err := models.NewAttachment().FindListByDocumentId(doc.DocumentId)
  139. if err == nil {
  140. doc.AttachList = attach
  141. }
  142. if c.IsAjax() {
  143. var data struct {
  144. DocTitle string `json:"doc_title"`
  145. Body string `json:"body"`
  146. Title string `json:"title"`
  147. }
  148. data.DocTitle = doc.DocumentName
  149. data.Body = doc.Release
  150. data.Title = doc.DocumentName + " - Powered by MinDoc"
  151. c.JsonResult(0, "ok", data)
  152. }
  153. tree, err := models.NewDocument().CreateDocumentTreeForHtml(bookResult.BookId, doc.DocumentId)
  154. if err != nil {
  155. beego.Error(err)
  156. c.Abort("500")
  157. }
  158. c.Data["Model"] = bookResult
  159. c.Data["Result"] = template.HTML(tree)
  160. c.Data["Title"] = doc.DocumentName
  161. c.Data["Content"] = template.HTML(doc.Release)
  162. }
  163. //编辑文档.
  164. func (c *DocumentController) Edit() {
  165. c.Prepare()
  166. identify := c.Ctx.Input.Param(":key")
  167. if identify == "" {
  168. c.Abort("404")
  169. }
  170. bookResult := models.NewBookResult()
  171. var err error
  172. //如果是超级管理者,则不判断权限
  173. if c.Member.Role == conf.MemberSuperRole {
  174. book, err := models.NewBook().FindByFieldFirst("identify", identify)
  175. if err != nil {
  176. c.JsonResult(6002, "项目不存在或权限不足")
  177. }
  178. bookResult = book.ToBookResult()
  179. } else {
  180. bookResult, err = models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
  181. if err != nil {
  182. beego.Error("DocumentController.Edit => ", err)
  183. c.Abort("403")
  184. }
  185. if bookResult.RoleId == conf.BookObserver {
  186. c.JsonResult(6002, "项目不存在或权限不足")
  187. }
  188. }
  189. //根据不同编辑器类型加载编辑器
  190. if bookResult.Editor == "markdown" {
  191. c.TplName = "document/markdown_edit_template.tpl"
  192. } else if bookResult.Editor == "html" {
  193. c.TplName = "document/html_edit_template.tpl"
  194. } else {
  195. c.TplName = "document/" + bookResult.Editor + "_edit_template.tpl"
  196. }
  197. c.Data["Model"] = bookResult
  198. r, _ := json.Marshal(bookResult)
  199. c.Data["ModelResult"] = template.JS(string(r))
  200. c.Data["Result"] = template.JS("[]")
  201. trees, err := models.NewDocument().FindDocumentTree(bookResult.BookId)
  202. if err != nil {
  203. beego.Error("FindDocumentTree => ", err)
  204. } else {
  205. if len(trees) > 0 {
  206. if jtree, err := json.Marshal(trees); err == nil {
  207. c.Data["Result"] = template.JS(string(jtree))
  208. }
  209. } else {
  210. c.Data["Result"] = template.JS("[]")
  211. }
  212. }
  213. c.Data["BaiDuMapKey"] = beego.AppConfig.DefaultString("baidumapkey", "")
  214. }
  215. //创建一个文档.
  216. func (c *DocumentController) Create() {
  217. identify := c.GetString("identify")
  218. doc_identify := c.GetString("doc_identify")
  219. doc_name := c.GetString("doc_name")
  220. parent_id, _ := c.GetInt("parent_id", 0)
  221. doc_id, _ := c.GetInt("doc_id", 0)
  222. if identify == "" {
  223. c.JsonResult(6001, "参数错误")
  224. }
  225. if doc_name == "" {
  226. c.JsonResult(6004, "文档名称不能为空")
  227. }
  228. if doc_identify != "" {
  229. if ok, err := regexp.MatchString(`^[a-z]+[a-zA-Z0-9_\-]*$`, doc_identify); !ok || err != nil {
  230. c.JsonResult(6003, "文档标识只能包含小写字母、数字,以及“-”和“_”符号,并且只能小写字母开头")
  231. }
  232. d, _ := models.NewDocument().FindByFieldFirst("identify", doc_identify)
  233. if d.DocumentId > 0 && d.DocumentId != doc_id {
  234. c.JsonResult(6006, "文档标识已被使用")
  235. }
  236. }
  237. book_id := 0
  238. //如果是超级管理员则不判断权限
  239. if c.Member.Role == conf.MemberSuperRole {
  240. book, err := models.NewBook().FindByFieldFirst("identify", identify)
  241. if err != nil {
  242. beego.Error(err)
  243. c.JsonResult(6002, "项目不存在或权限不足")
  244. }
  245. book_id = book.BookId
  246. } else {
  247. bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
  248. if err != nil || bookResult.RoleId == conf.BookObserver {
  249. beego.Error("FindByIdentify => ", err)
  250. c.JsonResult(6002, "项目不存在或权限不足")
  251. }
  252. book_id = bookResult.BookId
  253. }
  254. if parent_id > 0 {
  255. doc, err := models.NewDocument().Find(parent_id)
  256. if err != nil || doc.BookId != book_id {
  257. c.JsonResult(6003, "父分类不存在")
  258. }
  259. }
  260. document, _ := models.NewDocument().Find(doc_id)
  261. document.MemberId = c.Member.MemberId
  262. document.BookId = book_id
  263. if doc_identify != "" {
  264. document.Identify = doc_identify
  265. }
  266. document.Version = time.Now().Unix()
  267. document.DocumentName = doc_name
  268. document.ParentId = parent_id
  269. if err := document.InsertOrUpdate(); err != nil {
  270. beego.Error("InsertOrUpdate => ", err)
  271. c.JsonResult(6005, "保存失败")
  272. } else {
  273. c.JsonResult(0, "ok", document)
  274. }
  275. }
  276. //上传附件或图片.
  277. func (c *DocumentController) Upload() {
  278. identify := c.GetString("identify")
  279. doc_id, _ := c.GetInt("doc_id")
  280. is_attach := true
  281. if identify == "" {
  282. c.JsonResult(6001, "参数错误")
  283. }
  284. name := "editormd-file-file"
  285. file, moreFile, err := c.GetFile(name)
  286. if err == http.ErrMissingFile {
  287. name = "editormd-image-file"
  288. file, moreFile, err = c.GetFile(name)
  289. if err == http.ErrMissingFile {
  290. c.JsonResult(6003, "没有发现需要上传的文件")
  291. }
  292. }
  293. if err != nil {
  294. c.JsonResult(6002, err.Error())
  295. }
  296. defer file.Close()
  297. ext := filepath.Ext(moreFile.Filename)
  298. if ext == "" {
  299. c.JsonResult(6003, "无法解析文件的格式")
  300. }
  301. if !conf.IsAllowUploadFileExt(ext) {
  302. c.JsonResult(6004, "不允许的文件类型")
  303. }
  304. book_id := 0
  305. //如果是超级管理员,则不判断权限
  306. if c.Member.Role == conf.MemberSuperRole {
  307. book, err := models.NewBook().FindByFieldFirst("identify", identify)
  308. if err != nil {
  309. c.JsonResult(6006, "文档不存在或权限不足")
  310. }
  311. book_id = book.BookId
  312. } else {
  313. book, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
  314. if err != nil {
  315. beego.Error("DocumentController.Edit => ", err)
  316. if err == orm.ErrNoRows {
  317. c.JsonResult(6006, "权限不足")
  318. }
  319. c.JsonResult(6001, err.Error())
  320. }
  321. //如果没有编辑权限
  322. if book.RoleId != conf.BookEditor && book.RoleId != conf.BookAdmin && book.RoleId != conf.BookFounder {
  323. c.JsonResult(6006, "权限不足")
  324. }
  325. book_id = book.BookId
  326. }
  327. if doc_id > 0 {
  328. doc, err := models.NewDocument().Find(doc_id)
  329. if err != nil {
  330. c.JsonResult(6007, "文档不存在")
  331. }
  332. if doc.BookId != book_id {
  333. c.JsonResult(6008, "文档不属于指定的项目")
  334. }
  335. }
  336. fileName := "attach_" + strconv.FormatInt(time.Now().UnixNano(), 16)
  337. filePath := "uploads/" + time.Now().Format("200601") + "/" + fileName + ext
  338. path := filepath.Dir(filePath)
  339. os.MkdirAll(path, os.ModePerm)
  340. err = c.SaveToFile(name, filePath)
  341. if err != nil {
  342. beego.Error("SaveToFile => ", err)
  343. c.JsonResult(6005, "保存文件失败")
  344. }
  345. attachment := models.NewAttachment()
  346. attachment.BookId = book_id
  347. attachment.FileName = moreFile.Filename
  348. attachment.CreateAt = c.Member.MemberId
  349. attachment.FileExt = ext
  350. attachment.FilePath = filePath
  351. attachment.DocumentId = doc_id
  352. if fileInfo, err := os.Stat(filePath); err == nil {
  353. attachment.FileSize = float64(fileInfo.Size())
  354. }
  355. if doc_id > 0 {
  356. attachment.DocumentId = doc_id
  357. }
  358. if strings.EqualFold(ext, ".jpg") || strings.EqualFold(ext, ".jpeg") || strings.EqualFold(ext, "png") || strings.EqualFold(ext, "gif") {
  359. attachment.HttpPath = "/" + filePath
  360. is_attach = false
  361. }
  362. err = attachment.Insert()
  363. if err != nil {
  364. os.Remove(filePath)
  365. beego.Error("Attachment Insert => ", err)
  366. c.JsonResult(6006, "文件保存失败")
  367. }
  368. if attachment.HttpPath == "" {
  369. attachment.HttpPath = beego.URLFor("DocumentController.DownloadAttachment", ":key", identify, ":attach_id", attachment.AttachmentId)
  370. if err := attachment.Update(); err != nil {
  371. beego.Error("SaveToFile => ", err)
  372. c.JsonResult(6005, "保存文件失败")
  373. }
  374. }
  375. result := map[string]interface{}{
  376. "errcode": 0,
  377. "success": 1,
  378. "message": "ok",
  379. "url": attachment.HttpPath,
  380. "alt": attachment.FileName,
  381. "is_attach": is_attach,
  382. "attach": attachment,
  383. }
  384. //c.Data["json"] = result
  385. //c.ServeJSON(true)
  386. //c.StopRun()
  387. //
  388. //returnJSON, err := json.Marshal(result)
  389. //
  390. //if err != nil {
  391. // beego.Error(err)
  392. //}
  393. //
  394. //c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json; charset=utf-8")
  395. //fmt.Fprint(c.Ctx.ResponseWriter,string(returnJSON))
  396. c.Ctx.Output.JSON(result, true, false)
  397. c.StopRun()
  398. }
  399. //DownloadAttachment 下载附件.
  400. func (c *DocumentController) DownloadAttachment() {
  401. c.Prepare()
  402. identify := c.Ctx.Input.Param(":key")
  403. attach_id, _ := strconv.Atoi(c.Ctx.Input.Param(":attach_id"))
  404. token := c.GetString("token")
  405. member_id := 0
  406. if c.Member != nil {
  407. member_id = c.Member.MemberId
  408. }
  409. book_id := 0
  410. //判断用户是否参与了项目
  411. bookResult, err := models.NewBookResult().FindByIdentify(identify, member_id)
  412. if err != nil {
  413. //判断项目公开状态
  414. book, err := models.NewBook().FindByFieldFirst("identify", identify)
  415. if err != nil {
  416. c.Abort("404")
  417. }
  418. //如果不是超级管理员则判断权限
  419. if c.Member == nil || c.Member.Role != conf.MemberSuperRole {
  420. //如果项目是私有的,并且token不正确
  421. if (book.PrivatelyOwned == 1 && token == "") || (book.PrivatelyOwned == 1 && book.PrivateToken != token) {
  422. c.Abort("403")
  423. }
  424. }
  425. book_id = book.BookId
  426. } else {
  427. book_id = bookResult.BookId
  428. }
  429. //查找附件
  430. attachment, err := models.NewAttachment().Find(attach_id)
  431. if err != nil {
  432. beego.Error("DownloadAttachment => ", err)
  433. if err == orm.ErrNoRows {
  434. c.Abort("404")
  435. } else {
  436. c.Abort("500")
  437. }
  438. }
  439. if attachment.BookId != book_id {
  440. c.Abort("404")
  441. }
  442. c.Ctx.Output.Download(attachment.FilePath, attachment.FileName)
  443. c.StopRun()
  444. }
  445. //删除附件.
  446. func (c *DocumentController) RemoveAttachment() {
  447. c.Prepare()
  448. attach_id, _ := c.GetInt("attach_id")
  449. if attach_id <= 0 {
  450. c.JsonResult(6001, "参数错误")
  451. }
  452. attach, err := models.NewAttachment().Find(attach_id)
  453. if err != nil {
  454. beego.Error(err)
  455. c.JsonResult(6002, "附件不存在")
  456. }
  457. document, err := models.NewDocument().Find(attach.DocumentId)
  458. if err != nil {
  459. beego.Error(err)
  460. c.JsonResult(6003, "文档不存在")
  461. }
  462. if c.Member.Role != conf.MemberSuperRole {
  463. rel, err := models.NewRelationship().FindByBookIdAndMemberId(document.BookId, c.Member.MemberId)
  464. if err != nil {
  465. beego.Error(err)
  466. c.JsonResult(6004, "权限不足")
  467. }
  468. if rel.RoleId == conf.BookObserver {
  469. c.JsonResult(6004, "权限不足")
  470. }
  471. }
  472. err = attach.Delete()
  473. if err != nil {
  474. beego.Error(err)
  475. c.JsonResult(6005, "删除失败")
  476. }
  477. c.JsonResult(0, "ok", attach)
  478. }
  479. //删除文档.
  480. func (c *DocumentController) Delete() {
  481. c.Prepare()
  482. identify := c.GetString("identify")
  483. doc_id, err := c.GetInt("doc_id", 0)
  484. book_id := 0
  485. //如果是超级管理员则忽略权限判断
  486. if c.Member.Role == conf.MemberSuperRole {
  487. book, err := models.NewBook().FindByFieldFirst("identify", identify)
  488. if err != nil {
  489. beego.Error("FindByIdentify => ", err)
  490. c.JsonResult(6002, "项目不存在或权限不足")
  491. }
  492. book_id = book.BookId
  493. } else {
  494. bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
  495. if err != nil || bookResult.RoleId == conf.BookObserver {
  496. beego.Error("FindByIdentify => ", err)
  497. c.JsonResult(6002, "项目不存在或权限不足")
  498. }
  499. book_id = bookResult.BookId
  500. }
  501. if doc_id <= 0 {
  502. c.JsonResult(6001, "参数错误")
  503. }
  504. doc, err := models.NewDocument().Find(doc_id)
  505. if err != nil {
  506. beego.Error("Delete => ", err)
  507. c.JsonResult(6003, "删除失败")
  508. }
  509. //如果文档所属项目错误
  510. if doc.BookId != book_id {
  511. c.JsonResult(6004, "参数错误")
  512. }
  513. //递归删除项目下的文档以及子文档
  514. err = doc.RecursiveDocument(doc.DocumentId)
  515. if err != nil {
  516. c.JsonResult(6005, "删除失败")
  517. }
  518. //重置文档数量统计
  519. models.NewBook().ResetDocumentNumber(doc.BookId)
  520. c.JsonResult(0, "ok")
  521. }
  522. //获取文档内容.
  523. func (c *DocumentController) Content() {
  524. c.Prepare()
  525. identify := c.Ctx.Input.Param(":key")
  526. doc_id, err := c.GetInt("doc_id")
  527. if err != nil {
  528. doc_id, _ = strconv.Atoi(c.Ctx.Input.Param(":id"))
  529. }
  530. book_id := 0
  531. //如果是超级管理员,则忽略权限
  532. if c.Member.Role == conf.MemberSuperRole {
  533. book, err := models.NewBook().FindByFieldFirst("identify", identify)
  534. if err != nil {
  535. c.JsonResult(6002, "项目不存在或权限不足")
  536. }
  537. book_id = book.BookId
  538. } else {
  539. bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
  540. if err != nil || bookResult.RoleId == conf.BookObserver {
  541. beego.Error("FindByIdentify => ", err)
  542. c.JsonResult(6002, "项目不存在或权限不足")
  543. }
  544. book_id = bookResult.BookId
  545. }
  546. if doc_id <= 0 {
  547. c.JsonResult(6001, "参数错误")
  548. }
  549. if c.Ctx.Input.IsPost() {
  550. markdown := strings.TrimSpace(c.GetString("markdown", ""))
  551. content := c.GetString("html")
  552. version, _ := c.GetInt64("version", 0)
  553. is_cover := c.GetString("cover")
  554. doc, err := models.NewDocument().Find(doc_id)
  555. if err != nil {
  556. c.JsonResult(6003, "读取文档错误")
  557. }
  558. if doc.BookId != book_id {
  559. c.JsonResult(6004, "保存的文档不属于指定项目")
  560. }
  561. if doc.Version != version && !strings.EqualFold(is_cover, "yes") {
  562. beego.Info("%d|", version, doc.Version)
  563. c.JsonResult(6005, "文档已被修改确定要覆盖吗?")
  564. }
  565. if markdown == "" && content != "" {
  566. doc.Markdown = content
  567. } else {
  568. doc.Markdown = markdown
  569. }
  570. doc.Version = time.Now().Unix()
  571. doc.Content = content
  572. if err := doc.InsertOrUpdate(); err != nil {
  573. beego.Error("InsertOrUpdate => ", err)
  574. c.JsonResult(6006, "保存失败")
  575. }
  576. c.JsonResult(0, "ok", doc)
  577. }
  578. doc, err := models.NewDocument().Find(doc_id)
  579. if err != nil {
  580. c.JsonResult(6003, "文档不存在")
  581. }
  582. attach, err := models.NewAttachment().FindListByDocumentId(doc.DocumentId)
  583. if err == nil {
  584. doc.AttachList = attach
  585. }
  586. c.JsonResult(0, "ok", doc)
  587. }
  588. //导出文件
  589. func (c *DocumentController) Export() {
  590. c.Prepare()
  591. c.TplName = "document/export.tpl"
  592. identify := c.Ctx.Input.Param(":key")
  593. output := c.GetString("output")
  594. token := c.GetString("token")
  595. if identify == "" {
  596. c.Abort("404")
  597. }
  598. //如果没有开启你们访问则跳转到登录
  599. if !c.EnableAnonymous && c.Member == nil {
  600. c.Redirect(beego.URLFor("AccountController.Login"), 302)
  601. return
  602. }
  603. bookResult := models.NewBookResult()
  604. if c.Member != nil && c.Member.Role == conf.MemberSuperRole {
  605. book, err := models.NewBook().FindByIdentify(identify)
  606. if err != nil {
  607. beego.Error(err)
  608. c.Abort("500")
  609. }
  610. bookResult = book.ToBookResult()
  611. } else {
  612. bookResult = isReadable(identify, token, c)
  613. }
  614. docs, err := models.NewDocument().FindListByBookId(bookResult.BookId)
  615. if err != nil {
  616. beego.Error(err)
  617. c.Abort("500")
  618. }
  619. if output == "pdf" {
  620. exe := beego.AppConfig.String("wkhtmltopdf")
  621. if exe == "" {
  622. c.TplName = "errors/error.tpl"
  623. c.Data["ErrorMessage"] = "没有配置PDF导出程序"
  624. c.Data["ErrorCode"] = 50010
  625. return
  626. }
  627. dpath := "cache/" + bookResult.Identify
  628. os.MkdirAll(dpath, 0766)
  629. pathList := list.New()
  630. RecursiveFun(0, "", dpath, c, bookResult, docs, pathList)
  631. defer os.RemoveAll(dpath)
  632. os.MkdirAll("./cache", 0766)
  633. pdfpath := "cache/" + identify + "_" + c.CruSession.SessionID() + ".pdf"
  634. if _, err := os.Stat(pdfpath); os.IsNotExist(err) {
  635. wkhtmltopdf.SetPath(beego.AppConfig.String("wkhtmltopdf"))
  636. pdfg, err := wkhtmltopdf.NewPDFGenerator()
  637. pdfg.MarginBottom.Set(35)
  638. if err != nil {
  639. beego.Error(err)
  640. c.Abort("500")
  641. }
  642. for e := pathList.Front(); e != nil; e = e.Next() {
  643. if page, ok := e.Value.(string); ok {
  644. pdfg.AddPage(wkhtmltopdf.NewPage(page))
  645. }
  646. }
  647. err = pdfg.Create()
  648. if err != nil {
  649. beego.Error(err)
  650. c.Abort("500")
  651. }
  652. err = pdfg.WriteFile(pdfpath)
  653. if err != nil {
  654. beego.Error(err)
  655. }
  656. }
  657. c.Ctx.Output.Download(pdfpath, identify+".pdf")
  658. defer os.Remove(pdfpath)
  659. c.StopRun()
  660. }
  661. c.Abort("404")
  662. }
  663. //生成项目访问的二维码.
  664. func (c *DocumentController) QrCode() {
  665. c.Prepare()
  666. identify := c.GetString(":key")
  667. book, err := models.NewBook().FindByIdentify(identify)
  668. if err != nil || book.BookId <= 0 {
  669. c.Abort("404")
  670. }
  671. uri := c.BaseUrl() + beego.URLFor("DocumentController.Index", ":key", identify)
  672. code, err := qr.Encode(uri, qr.L, qr.Unicode)
  673. if err != nil {
  674. beego.Error(err)
  675. c.Abort("500")
  676. }
  677. code, err = barcode.Scale(code, 150, 150)
  678. if err != nil {
  679. beego.Error(err)
  680. c.Abort("500")
  681. }
  682. c.Ctx.ResponseWriter.Header().Set("Content-Type", "image/png")
  683. //imgpath := filepath.Join("cache","qrcode",identify + ".png")
  684. err = png.Encode(c.Ctx.ResponseWriter, code)
  685. if err != nil {
  686. beego.Error(err)
  687. c.Abort("500")
  688. }
  689. }
  690. //递归生成文档序列数组.
  691. func RecursiveFun(parent_id int, prefix, dpath string, c *DocumentController, book *models.BookResult, docs []*models.Document, paths *list.List) {
  692. for _, item := range docs {
  693. if item.ParentId == parent_id {
  694. name := prefix + strconv.Itoa(item.ParentId) + strconv.Itoa(item.OrderSort) + strconv.Itoa(item.DocumentId)
  695. fpath := dpath + "/" + name + ".html"
  696. paths.PushBack(fpath)
  697. f, err := os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0777)
  698. if err != nil {
  699. beego.Error(err)
  700. c.Abort("500")
  701. }
  702. html, err := c.ExecuteViewPathTemplate("document/export.tpl", map[string]interface{}{"Model": book, "Lists": item, "BaseUrl": c.BaseUrl()})
  703. if err != nil {
  704. f.Close()
  705. beego.Error(err)
  706. c.Abort("500")
  707. }
  708. //beego.Info(fpath,html)
  709. f.WriteString(html)
  710. f.Close()
  711. for _, sub := range docs {
  712. if sub.ParentId == item.DocumentId {
  713. RecursiveFun(item.DocumentId, name, dpath, c, book, docs, paths)
  714. break
  715. }
  716. }
  717. }
  718. }
  719. }