DocumentTree.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. package models
  2. import (
  3. "bytes"
  4. "fmt"
  5. "html/template"
  6. "math"
  7. "github.com/beego/beego/v2/client/orm"
  8. "github.com/mindoc-org/mindoc/conf"
  9. // "gorm.io/driver/sqlite"
  10. // "gorm.io/gorm"
  11. )
  12. type DocumentTree struct {
  13. DocumentId int `json:"id"`
  14. DocumentName string `json:"text"`
  15. ParentId interface{} `json:"parent"`
  16. Identify string `json:"identify"`
  17. BookIdentify string `json:"-"`
  18. Version int64 `json:"version"`
  19. State *DocumentSelected `json:"-"`
  20. AAttrs map[string]interface{} `json:"a_attr"`
  21. Children []*DocumentTree `json:"children"`
  22. }
  23. // type DocumentTreeJson struct {
  24. // gorm.Model
  25. // DocumentId int `json:"id"`
  26. // DocumentName string `json:"text"`
  27. // ParentId interface{} `json:"parent"`
  28. // Children []*DocumentTreeJson `json:"children" gorm:"-"`
  29. // }
  30. type DocumentSelected struct {
  31. Selected bool `json:"selected"`
  32. Opened bool `json:"opened"`
  33. Disabled bool `json:"disabled"`
  34. }
  35. // 获取项目的文档树状结构
  36. func (item *Document) FindDocumentTree(bookId int) ([]*DocumentTree, error) {
  37. o := orm.NewOrm()
  38. trees := make([]*DocumentTree, 0)
  39. var docs []*Document
  40. count, err := o.QueryTable(item).Filter("book_id", bookId).
  41. OrderBy("order_sort", "document_id").
  42. Limit(math.MaxInt32).
  43. All(&docs, "document_id", "version", "document_name", "parent_id", "identify", "is_open")
  44. if err != nil {
  45. return trees, err
  46. }
  47. book, _ := NewBook().Find(bookId)
  48. trees = make([]*DocumentTree, count)
  49. for index, item := range docs {
  50. tree := &DocumentTree{
  51. AAttrs: map[string]interface{}{"is_open": false, "opened": 0},
  52. }
  53. if index == 0 {
  54. tree.State = &DocumentSelected{Selected: true, Opened: true}
  55. tree.AAttrs = map[string]interface{}{"is_open": true, "opened": 1}
  56. } else if item.IsOpen == 1 {
  57. tree.State = &DocumentSelected{Selected: false, Opened: true}
  58. tree.AAttrs = map[string]interface{}{"is_open": true, "opened": 1}
  59. }
  60. if item.IsOpen == 2 {
  61. tree.State = &DocumentSelected{Selected: false, Opened: false, Disabled: true}
  62. tree.AAttrs = map[string]interface{}{"disabled": true, "opened": 2}
  63. }
  64. tree.DocumentId = item.DocumentId
  65. tree.Identify = item.Identify
  66. tree.Version = item.Version
  67. tree.BookIdentify = book.Identify
  68. if item.ParentId > 0 {
  69. tree.ParentId = item.ParentId
  70. } else {
  71. tree.ParentId = "#"
  72. }
  73. tree.DocumentName = item.DocumentName
  74. trees[index] = tree
  75. }
  76. return trees, nil
  77. }
  78. // 获取项目的文档树状结构2
  79. func (item *Document) FindDocumentTree2(bookId int) ([]*DocumentTree, error) {
  80. o := orm.NewOrm()
  81. trees := make([]*DocumentTree, 0)
  82. var docs []*Document
  83. count, err := o.QueryTable(item).Filter("book_id", bookId).
  84. OrderBy("order_sort", "document_id").
  85. Limit(math.MaxInt32).
  86. All(&docs, "document_id", "version", "document_name", "parent_id", "identify", "is_open")
  87. if err != nil {
  88. return trees, err
  89. }
  90. book, _ := NewBook().Find(bookId)
  91. trees = make([]*DocumentTree, count)
  92. for index, item := range docs {
  93. tree := &DocumentTree{
  94. AAttrs: map[string]interface{}{"is_open": false, "opened": 0},
  95. }
  96. if index == 0 {
  97. tree.State = &DocumentSelected{Selected: true, Opened: true}
  98. tree.AAttrs = map[string]interface{}{"is_open": true, "opened": 1}
  99. } else if item.IsOpen == 1 {
  100. tree.State = &DocumentSelected{Selected: false, Opened: true}
  101. tree.AAttrs = map[string]interface{}{"is_open": true, "opened": 1}
  102. }
  103. if item.IsOpen == 2 {
  104. tree.State = &DocumentSelected{Selected: false, Opened: false, Disabled: true}
  105. tree.AAttrs = map[string]interface{}{"disabled": true, "opened": 2}
  106. }
  107. tree.DocumentId = item.DocumentId
  108. tree.Identify = item.Identify
  109. tree.Version = item.Version
  110. tree.BookIdentify = book.Identify
  111. // if item.ParentId > 0 {
  112. tree.ParentId = item.ParentId
  113. // } else {
  114. // tree.ParentId = "#"
  115. // }
  116. tree.DocumentName = item.DocumentName
  117. trees[index] = tree
  118. }
  119. return trees, nil
  120. }
  121. func (item *Document) CreateDocumentTreeForHtml(bookId, selectedId int) (string, error) {
  122. trees, err := item.FindDocumentTree(bookId)
  123. if err != nil {
  124. return "", err
  125. }
  126. parentId := getSelectedNode(trees, selectedId)
  127. buf := bytes.NewBufferString("")
  128. getDocumentTree(trees, 0, selectedId, parentId, buf)
  129. return buf.String(), nil
  130. }
  131. // 使用递归的方式获取指定ID的顶级ID
  132. func getSelectedNode(array []*DocumentTree, parent_id int) int {
  133. for _, item := range array {
  134. if _, ok := item.ParentId.(string); ok && item.DocumentId == parent_id {
  135. return item.DocumentId
  136. } else if pid, ok := item.ParentId.(int); ok && item.DocumentId == parent_id {
  137. return getSelectedNode(array, pid)
  138. }
  139. }
  140. return 0
  141. }
  142. func getDocumentTree(array []*DocumentTree, parentId int, selectedId int, selectedParentId int, buf *bytes.Buffer) {
  143. buf.WriteString("<ul>")
  144. for _, item := range array {
  145. pid := 0
  146. if p, ok := item.ParentId.(int); ok {
  147. pid = p
  148. }
  149. if pid == parentId {
  150. selected := ""
  151. if item.DocumentId == selectedId {
  152. selected = ` class="jstree-clicked"`
  153. }
  154. selectedLi := ""
  155. if item.DocumentId == selectedParentId || (item.State != nil && item.State.Opened) {
  156. selectedLi = ` class="jstree-open"`
  157. }
  158. buf.WriteString(fmt.Sprintf("<li id=\"%d\"%s><a href=\"", item.DocumentId, selectedLi))
  159. if item.Identify != "" {
  160. uri := conf.URLFor("DocumentController.Read", ":key", item.BookIdentify, ":id", item.Identify)
  161. buf.WriteString(uri)
  162. } else {
  163. uri := conf.URLFor("DocumentController.Read", ":key", item.BookIdentify, ":id", item.DocumentId)
  164. buf.WriteString(uri)
  165. }
  166. buf.WriteString(fmt.Sprintf("\" title=\"%s\"", template.HTMLEscapeString(item.DocumentName)))
  167. if item.State != nil && item.State.Disabled {
  168. buf.WriteString(" disabled=\"true\"")
  169. }
  170. buf.WriteString(fmt.Sprintf(" data-version=\"%d\"%s>%s</a>", item.Version, selected, template.HTMLEscapeString(item.DocumentName)))
  171. for _, sub := range array {
  172. if p, ok := sub.ParentId.(int); ok && p == item.DocumentId {
  173. getDocumentTree(array, p, selectedId, selectedParentId, buf)
  174. break
  175. }
  176. }
  177. buf.WriteString("</li>")
  178. }
  179. }
  180. buf.WriteString("</ul>")
  181. }