document.go 20 KB

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