diff --git a/controllers/DocumentController.go b/controllers/DocumentController.go index 4483ddcac..777df65a4 100644 --- a/controllers/DocumentController.go +++ b/controllers/DocumentController.go @@ -36,6 +36,16 @@ type DocumentController struct { BaseController } +// Document prev&next +type DocumentTreeFlatten struct { + DocumentId int `json:"id"` + DocumentName string `json:"text"` + // ParentId interface{} `json:"parent"` + Identify string `json:"identify"` + // BookIdentify string `json:"-"` + // Version int64 `json:"version"` +} + // 文档首页 func (c *DocumentController) Index() { c.Prepare() @@ -98,7 +108,6 @@ func (c *DocumentController) Index() { c.Data["IS_DOCUMENT_INDEX"] = true c.Data["Model"] = bookResult c.Data["Result"] = template.HTML(tree) - } // CheckPassword : Handles password verification for private documents, @@ -186,6 +195,41 @@ func (c *DocumentController) Read() { doc.AttachList = attach } + // prev,next + treeJson, err := models.NewDocument().FindDocumentTree2(bookResult.BookId) + if err != nil { + logs.Error("生成项目文档树时出错 ->", err) + } + + res := getTreeRecursive(treeJson, 0) + flat := make([]DocumentTreeFlatten, 0) + Flatten(res, &flat) + var index int + for i, v := range flat { + if v.Identify == id { + index = i + } + } + var PrevName, PrevPath, NextName, NextPath string + if index == 0 { + c.Data["PrevName"] = "没有了" + PrevName = "没有了" + } else { + c.Data["PrevPath"] = identify + "/" + flat[index-1].Identify + c.Data["PrevName"] = flat[index-1].DocumentName + PrevPath = identify + "/" + flat[index-1].Identify + PrevName = flat[index-1].DocumentName + } + if index == len(flat)-1 { + c.Data["NextName"] = "没有了" + NextName = "没有了" + } else { + c.Data["NextPath"] = identify + "/" + flat[index+1].Identify + c.Data["NextName"] = flat[index+1].DocumentName + NextPath = identify + "/" + flat[index+1].Identify + NextName = flat[index+1].DocumentName + } + doc.IncrViewCount(doc.DocumentId) doc.ViewCount = doc.ViewCount + 1 doc.PutToCache() @@ -205,7 +249,7 @@ func (c *DocumentController) Read() { data.DocId = doc.DocumentId data.DocIdentify = doc.Identify data.DocTitle = doc.DocumentName - data.Body = doc.Release + data.Body = doc.Release + "
上一篇:
下一篇:
" data.Title = doc.DocumentName + " - Powered by MinDoc" data.Version = doc.Version data.ViewCount = doc.ViewCount @@ -229,7 +273,6 @@ func (c *DocumentController) Read() { if err != nil && err != orm.ErrNoRows { logs.Error("生成项目文档树时出错 ->", err) - c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.build_doc_tree_error")) } @@ -238,7 +281,7 @@ func (c *DocumentController) Read() { c.Data["Model"] = bookResult c.Data["Result"] = template.HTML(tree) c.Data["Title"] = doc.DocumentName - c.Data["Content"] = template.HTML(doc.Release) + c.Data["Content"] = template.HTML(doc.Release + "
上一篇:
下一篇:
") c.Data["ViewCount"] = doc.ViewCount c.Data["FoldSetting"] = "closed" if bookResult.Editor == EditorCherryMarkdown { @@ -251,6 +294,34 @@ func (c *DocumentController) Read() { } } +// 递归得到树状结构体 +func getTreeRecursive(list []*models.DocumentTree, parentId int) (res []*models.DocumentTree) { + for _, v := range list { + if v.ParentId == parentId { + v.Children = getTreeRecursive(list, v.DocumentId) + res = append(res, v) + } + } + return res +} + +// 递归将树状结构体转换为扁平结构体数组 +// func Flatten(list []*models.DocumentTree, flattened *[]DocumentTreeFlatten) (flatten *[]DocumentTreeFlatten) { +func Flatten(list []*models.DocumentTree, flattened *[]DocumentTreeFlatten) { + // Treeslice := make([]*DocumentTreeFlatten, 0) + for _, v := range list { + tree := make([]DocumentTreeFlatten, 1) + tree[0].DocumentId = v.DocumentId + tree[0].DocumentName = v.DocumentName + tree[0].Identify = v.Identify + *flattened = append(*flattened, tree...) + if len(v.Children) > 0 { + Flatten(v.Children, flattened) + } + } + return +} + // 编辑文档 func (c *DocumentController) Edit() { c.Prepare() @@ -868,24 +939,30 @@ func (c *DocumentController) Export() { c.Prepare() identify := c.Ctx.Input.Param(":key") + if identify == "" { c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.param_error")) } output := c.GetString("output") token := c.GetString("token") - + logs.Info(identify) + logs.Info(output) + logs.Info(token) // 如果没有开启匿名访问则跳转到登录 if !c.EnableAnonymous && !c.isUserLoggedIn() { + logs.Info(output) promptUserToLogIn(c) return } if !conf.GetEnableExport() { + logs.Info(output) c.ShowErrorPage(500, i18n.Tr(c.Lang, "export_func_disable")) } bookResult := models.NewBookResult() if c.Member != nil && c.Member.IsAdministrator() { + logs.Info(output) book, err := models.NewBook().FindByIdentify(identify) if err != nil { if err == orm.ErrNoRows { @@ -897,17 +974,21 @@ func (c *DocumentController) Export() { } bookResult = models.NewBookResult().ToBookResult(*book) } else { + logs.Info(output) bookResult = c.isReadable(identify, token) } if !bookResult.IsDownload { + logs.Info(output) c.ShowErrorPage(200, i18n.Tr(c.Lang, "message.cur_project_export_func_disable")) } if !strings.HasPrefix(bookResult.Cover, "http:://") && !strings.HasPrefix(bookResult.Cover, "https:://") { + logs.Info(output) bookResult.Cover = conf.URLForWithCdnImage(bookResult.Cover) } - + logs.Info(Markdown) if output == Markdown { + logs.Info("hah") if bookResult.Editor != EditorMarkdown && bookResult.Editor != EditorCherryMarkdown { c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.cur_project_not_support_md")) } diff --git a/go.mod b/go.mod index d1698fdeb..c757c2a37 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/lib/pq v1.10.5 github.com/lifei6671/gocaptcha v0.2.0 github.com/mattn/go-runewidth v0.0.13 - github.com/mattn/go-sqlite3 v1.14.15 + github.com/mattn/go-sqlite3 v1.14.17 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/russross/blackfriday/v2 v2.1.0 ) @@ -32,6 +32,8 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/gomodule/redigo v2.0.0+incompatible // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -50,4 +52,6 @@ require ( google.golang.org/protobuf v1.28.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + gorm.io/driver/sqlite v1.5.5 // indirect + gorm.io/gorm v1.25.9 // indirect ) diff --git a/go.sum b/go.sum index 524b4168b..a51b33ad6 100644 --- a/go.sum +++ b/go.sum @@ -165,6 +165,10 @@ github.com/howeyc/fsnotify v0.9.0/go.mod h1:41HzSPxBGeFRQKEEwgh49TRw/nKBsYZ2cF1O github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -195,6 +199,8 @@ github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= +github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -575,6 +581,12 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/sqlite v1.5.5 h1:7MDMtUZhV065SilG62E0MquljeArQZNfJnjd9i9gx3E= +gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE= +gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde h1:9DShaph9qhkIYw7QF91I/ynrr4cOO2PZra2PFD7Mfeg= +gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8= +gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/models/AttachmentModel.go b/models/AttachmentModel.go index 5de9fb319..0d382159e 100644 --- a/models/AttachmentModel.go +++ b/models/AttachmentModel.go @@ -1,4 +1,4 @@ -//数据库模型. +// 数据库模型. package models import ( @@ -12,8 +12,15 @@ import ( "github.com/beego/beego/v2/core/logs" "github.com/mindoc-org/mindoc/conf" "github.com/mindoc-org/mindoc/utils/filetil" + // "gorm.io/driver/sqlite" + // "gorm.io/gorm" + // "gorm.io/gorm/logger" + // "gorm.io/gorm/schema" ) +// 定义全局的db对象,我们执行数据库操作主要通过他实现。 +// var _db *gorm.DB + // Attachment struct . type Attachment struct { AttachmentId int `orm:"column(attachment_id);pk;auto;unique" json:"attachment_id"` @@ -83,7 +90,7 @@ func (m *Attachment) Find(id int) (*Attachment, error) { return m, err } -//查询指定文档的附件列表 +// 查询指定文档的附件列表 func (m *Attachment) FindListByDocumentId(docId int) (attaches []*Attachment, err error) { o := orm.NewOrm() @@ -91,7 +98,7 @@ func (m *Attachment) FindListByDocumentId(docId int) (attaches []*Attachment, er return } -//分页查询附件 +// 分页查询附件 func (m *Attachment) FindToPager(pageIndex, pageSize int) (attachList []*AttachmentResult, totalCount int, err error) { o := orm.NewOrm() diff --git a/models/DocumentTree.go b/models/DocumentTree.go index 7a0c8dccc..11020dd75 100644 --- a/models/DocumentTree.go +++ b/models/DocumentTree.go @@ -8,6 +8,8 @@ import ( "github.com/beego/beego/v2/client/orm" "github.com/mindoc-org/mindoc/conf" + // "gorm.io/driver/sqlite" + // "gorm.io/gorm" ) type DocumentTree struct { @@ -19,14 +21,24 @@ type DocumentTree struct { Version int64 `json:"version"` State *DocumentSelected `json:"-"` AAttrs map[string]interface{} `json:"a_attr"` + Children []*DocumentTree `json:"children"` } + +// type DocumentTreeJson struct { +// gorm.Model +// DocumentId int `json:"id"` +// DocumentName string `json:"text"` +// ParentId interface{} `json:"parent"` +// Children []*DocumentTreeJson `json:"children" gorm:"-"` +// } + type DocumentSelected struct { Selected bool `json:"selected"` Opened bool `json:"opened"` Disabled bool `json:"disabled"` } -//获取项目的文档树状结构 +// 获取项目的文档树状结构 func (item *Document) FindDocumentTree(bookId int) ([]*DocumentTree, error) { o := orm.NewOrm() @@ -79,6 +91,59 @@ func (item *Document) FindDocumentTree(bookId int) ([]*DocumentTree, error) { return trees, nil } +// 获取项目的文档树状结构2 +func (item *Document) FindDocumentTree2(bookId int) ([]*DocumentTree, error) { + o := orm.NewOrm() + + trees := make([]*DocumentTree, 0) + + var docs []*Document + + count, err := o.QueryTable(item).Filter("book_id", bookId). + OrderBy("order_sort", "document_id"). + Limit(math.MaxInt32). + All(&docs, "document_id", "version", "document_name", "parent_id", "identify", "is_open") + + if err != nil { + return trees, err + } + book, _ := NewBook().Find(bookId) + + trees = make([]*DocumentTree, count) + + for index, item := range docs { + tree := &DocumentTree{ + AAttrs: map[string]interface{}{"is_open": false, "opened": 0}, + } + if index == 0 { + tree.State = &DocumentSelected{Selected: true, Opened: true} + tree.AAttrs = map[string]interface{}{"is_open": true, "opened": 1} + } else if item.IsOpen == 1 { + tree.State = &DocumentSelected{Selected: false, Opened: true} + tree.AAttrs = map[string]interface{}{"is_open": true, "opened": 1} + } + if item.IsOpen == 2 { + tree.State = &DocumentSelected{Selected: false, Opened: false, Disabled: true} + tree.AAttrs = map[string]interface{}{"disabled": true, "opened": 2} + } + tree.DocumentId = item.DocumentId + tree.Identify = item.Identify + tree.Version = item.Version + tree.BookIdentify = book.Identify + // if item.ParentId > 0 { + tree.ParentId = item.ParentId + // } else { + // tree.ParentId = "#" + // } + + tree.DocumentName = item.DocumentName + + trees[index] = tree + } + + return trees, nil +} + func (item *Document) CreateDocumentTreeForHtml(bookId, selectedId int) (string, error) { trees, err := item.FindDocumentTree(bookId) if err != nil { @@ -94,7 +159,7 @@ func (item *Document) CreateDocumentTreeForHtml(bookId, selectedId int) (string, } -//使用递归的方式获取指定ID的顶级ID +// 使用递归的方式获取指定ID的顶级ID func getSelectedNode(array []*DocumentTree, parent_id int) int { for _, item := range array { diff --git a/static/css/kancloud.css b/static/css/kancloud.css index d6f35a445..2c1f1ebf0 100644 --- a/static/css/kancloud.css +++ b/static/css/kancloud.css @@ -576,6 +576,17 @@ table>tbody>tr:hover { padding: 5px; } +.manual-article .wiki-bottom-left { + border-top: 1px solid #E5E5E5; + line-height: 25px; + color: #333; + text-align: left; + font-size: 12px; + margin-bottom: 20px; + margin-top: 30px; + padding: 5px; +} + .manual-article .jump-top .view-backtop { position: fixed; bottom: -30px; diff --git a/uploads/.gitignore b/uploads/.gitignore deleted file mode 100644 index bfa6a22a5..000000000 --- a/uploads/.gitignore +++ /dev/null @@ -1 +0,0 @@ -# Created by .ignore support plugin (hsz.mobi) diff --git a/uploads/20170501203542.png b/uploads/20170501203542.png deleted file mode 100644 index b44b3e876..000000000 Binary files a/uploads/20170501203542.png and /dev/null differ diff --git a/uploads/20170501203619.png b/uploads/20170501203619.png deleted file mode 100644 index 15d3df3f2..000000000 Binary files a/uploads/20170501203619.png and /dev/null differ diff --git a/uploads/20170501203637.png b/uploads/20170501203637.png deleted file mode 100644 index 47234af3d..000000000 Binary files a/uploads/20170501203637.png and /dev/null differ diff --git a/uploads/20170501203656.png b/uploads/20170501203656.png deleted file mode 100644 index 0828f04bd..000000000 Binary files a/uploads/20170501203656.png and /dev/null differ diff --git a/uploads/20170501203854.png b/uploads/20170501203854.png deleted file mode 100644 index 57a214e61..000000000 Binary files a/uploads/20170501203854.png and /dev/null differ diff --git a/uploads/20170501204438.png b/uploads/20170501204438.png deleted file mode 100644 index 22310ef29..000000000 Binary files a/uploads/20170501204438.png and /dev/null differ diff --git a/uploads/20170501204609.png b/uploads/20170501204609.png deleted file mode 100644 index 4942f2b1a..000000000 Binary files a/uploads/20170501204609.png and /dev/null differ diff --git a/uploads/20170501204651.png b/uploads/20170501204651.png deleted file mode 100644 index f94571f2a..000000000 Binary files a/uploads/20170501204651.png and /dev/null differ diff --git a/uploads/20170501204710.png b/uploads/20170501204710.png deleted file mode 100644 index 37e987b3e..000000000 Binary files a/uploads/20170501204710.png and /dev/null differ