瀏覽代碼

1、优化文档缓存逻辑
2、新增标签管理功能
3、优化部分页面显示效果

Minho 7 年之前
父節點
當前提交
b93052cc09

+ 9 - 1
controllers/base.go

@@ -123,7 +123,15 @@ func (c *BaseController) BaseUrl() string {
 //显示错误信息页面.
 func (c *BaseController) ShowErrorPage(errCode int, errMsg string) {
 	c.TplName = "errors/error.tpl"
+
 	c.Data["ErrorMessage"] = errMsg
 	c.Data["ErrorCode"] = errCode
-	c.StopRun()
+
+	var buf bytes.Buffer
+
+	if err := beego.ExecuteViewPathTemplate(&buf, "document/export.tpl", beego.BConfig.WebConfig.ViewsPath, map[string]interface{}{"ErrorMessage": errMsg, "errCode": errCode, "BaseUrl": conf.BaseUrl}); err != nil {
+		c.Abort("500")
+	}
+
+	c.CustomAbort(200,buf.String())
 }

+ 16 - 6
controllers/book.go

@@ -42,6 +42,10 @@ func (c *BookController) Index() {
 		c.Abort("500")
 	}
 
+	for i,book := range books {
+		books[i].Description = utils.StripTags(string(blackfriday.MarkdownBasic([]byte(book.Description))))
+	}
+
 	if totalCount > 0 {
 		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize)
 		c.Data["PageHtml"] = pager.HtmlPages()
@@ -135,6 +139,7 @@ func (c *BookController) SaveBook() {
 	autoRelease := strings.TrimSpace(c.GetString("auto_release")) == "on"
 	publisher := strings.TrimSpace(c.GetString("publisher"))
 	historyCount,_ := c.GetInt("history_count",0)
+	isDownload := strings.TrimSpace(c.GetString("is_download")) == "on"
 
 	if strings.Count(description, "") > 500 {
 		c.JsonResult(6004, "项目描述不能大于500字")
@@ -159,13 +164,18 @@ func (c *BookController) SaveBook() {
 	book.Label = tag
 	book.Editor = editor
 	book.HistoryCount = historyCount
+	book.IsDownload = 0
 
 	if autoRelease {
 		book.AutoRelease = 1
 	} else {
 		book.AutoRelease = 0
 	}
-
+	if isDownload {
+		book.IsDownload = 0
+	}else{
+		book.IsDownload = 1
+	}
 	if err := book.Update(); err != nil {
 		c.JsonResult(6006, "保存失败")
 	}
@@ -395,7 +405,7 @@ func (c *BookController) Create() {
 		book_name := strings.TrimSpace(c.GetString("book_name", ""))
 		identify := strings.TrimSpace(c.GetString("identify", ""))
 		description := strings.TrimSpace(c.GetString("description", ""))
-		privately_owned, _ := strconv.Atoi(c.GetString("privately_owned"))
+		privatelyOwned, _ := strconv.Atoi(c.GetString("privately_owned"))
 		comment_status := c.GetString("comment_status")
 
 		if book_name == "" {
@@ -413,8 +423,8 @@ func (c *BookController) Create() {
 		if strings.Count(description, "") > 500 {
 			c.JsonResult(6004, "项目描述不能大于500字")
 		}
-		if privately_owned != 0 && privately_owned != 1 {
-			privately_owned = 1
+		if privatelyOwned != 0 && privatelyOwned != 1 {
+			privatelyOwned = 1
 		}
 		if comment_status != "open" && comment_status != "closed" && comment_status != "group_only" && comment_status != "registered_only" {
 			comment_status = "closed"
@@ -460,7 +470,7 @@ func (c *BookController) Create() {
 		book.BookName = book_name
 		book.Description = description
 		book.CommentCount = 0
-		book.PrivatelyOwned = privately_owned
+		book.PrivatelyOwned = privatelyOwned
 		book.CommentStatus = comment_status
 		book.Identify = identify
 		book.DocCount = 0
@@ -487,7 +497,7 @@ func (c *BookController) Create() {
 	}
 	c.JsonResult(6001, "error")
 }
-
+//导入
 func (c *BookController) Import() {
 
 	file, moreFile, err := c.GetFile("import-file")

+ 24 - 19
controllers/document.go

@@ -169,13 +169,13 @@ func (c *DocumentController) Read() {
 	doc := models.NewDocument()
 
 	if doc_id, err := strconv.Atoi(id); err == nil {
-		doc, err = doc.Find(doc_id)
+		doc, err = doc.FromCacheById(doc_id)
 		if err != nil {
 			beego.Error(err)
 			c.Abort("500")
 		}
 	} else {
-		doc, err = doc.FindByFieldFirst("identify", id)
+		doc, err = doc.FromCacheByIdentify(id)
 		if err != nil {
 			beego.Error(err)
 			c.Abort("500")
@@ -723,14 +723,14 @@ func (c *DocumentController) Content() {
 	c.Prepare()
 
 	identify := c.Ctx.Input.Param(":key")
-	doc_id, err := c.GetInt("doc_id")
+	docId, err := c.GetInt("doc_id")
 
 	if err != nil {
-		doc_id, _ = strconv.Atoi(c.Ctx.Input.Param(":id"))
+		docId, _ = strconv.Atoi(c.Ctx.Input.Param(":id"))
 	}
 
-	book_id := 0
-	auto_release := false
+	bookId := 0
+	autoRelease := false
 
 	// 如果是超级管理员,则忽略权限
 	if c.Member.IsAdministrator() {
@@ -739,8 +739,8 @@ func (c *DocumentController) Content() {
 			c.JsonResult(6002, "项目不存在或权限不足")
 		}
 
-		book_id = book.BookId
-		auto_release = book.AutoRelease == 1
+		bookId = book.BookId
+		autoRelease = book.AutoRelease == 1
 	} else {
 		bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId)
 
@@ -749,11 +749,11 @@ func (c *DocumentController) Content() {
 			c.JsonResult(6002, "项目不存在或权限不足")
 		}
 
-		book_id = bookResult.BookId
-		auto_release = bookResult.AutoRelease
+		bookId = bookResult.BookId
+		autoRelease = bookResult.AutoRelease
 	}
 
-	if doc_id <= 0 {
+	if docId <= 0 {
 		c.JsonResult(6001, "参数错误")
 	}
 
@@ -761,25 +761,25 @@ func (c *DocumentController) Content() {
 		markdown := strings.TrimSpace(c.GetString("markdown", ""))
 		content := c.GetString("html")
 		version, _ := c.GetInt64("version", 0)
-		is_cover := c.GetString("cover")
+		isCover := c.GetString("cover")
 
-		doc, err := models.NewDocument().Find(doc_id)
+		doc, err := models.NewDocument().Find(docId)
 
 		if err != nil {
 			c.JsonResult(6003, "读取文档错误")
 		}
 
-		if doc.BookId != book_id {
+		if doc.BookId != bookId {
 			c.JsonResult(6004, "保存的文档不属于指定项目")
 		}
 
-		if doc.Version != version && !strings.EqualFold(is_cover, "yes") {
+		if doc.Version != version && !strings.EqualFold(isCover, "yes") {
 			beego.Info("%d|", version, doc.Version)
 			c.JsonResult(6005, "文档已被修改确定要覆盖吗?")
 		}
 
 		history := models.NewDocumentHistory()
-		history.DocumentId = doc_id
+		history.DocumentId = docId
 		history.Content = doc.Content
 		history.Markdown = doc.Markdown
 		history.DocumentName = doc.DocumentName
@@ -812,9 +812,9 @@ func (c *DocumentController) Content() {
 			}
 		}
 		//如果启用了自动发布
-		if auto_release {
+		if autoRelease {
 			go func(identify string) {
-				models.NewDocument().ReleaseContent(book_id)
+				models.NewDocument().ReleaseContent(bookId)
 
 			}(identify)
 		}
@@ -822,7 +822,7 @@ func (c *DocumentController) Content() {
 		c.JsonResult(0, "ok", doc)
 	}
 
-	doc, err := models.NewDocument().Find(doc_id)
+	doc, err := models.NewDocument().Find(docId)
 	if err != nil {
 		c.JsonResult(6003, "文档不存在")
 	}
@@ -883,6 +883,9 @@ func (c *DocumentController) Export() {
 	} else {
 		bookResult = isReadable(identify, token, c)
 	}
+	if !bookResult.IsDownload {
+		c.ShowErrorPage(200,"当前项目没有开启导出功能")
+	}
 
 	if !strings.HasPrefix(bookResult.Cover, "http:://") && !strings.HasPrefix(bookResult.Cover, "https:://") {
 		bookResult.Cover = c.BaseUrl() + bookResult.Cover
@@ -911,6 +914,8 @@ func (c *DocumentController) Export() {
 		c.Ctx.Output.Download(eBookResult.WordPath, bookResult.BookName+".docx")
 
 		c.Abort("200")
+	}else{
+		c.ShowErrorPage(200,"不支持的文件格式")
 	}
 
 	c.Abort("404")

+ 2 - 2
controllers/label.go

@@ -47,7 +47,7 @@ func (c *LabelController) Index() {
 	if c.Member != nil {
 		member_id = c.Member.MemberId
 	}
-	search_result, totalCount, err := models.NewBook().FindForLabelToPager(labelName, pageIndex, conf.PageSize, member_id)
+	searchResult, totalCount, err := models.NewBook().FindForLabelToPager(labelName, pageIndex, conf.PageSize, member_id)
 
 	if err != nil {
 		beego.Error(err)
@@ -59,7 +59,7 @@ func (c *LabelController) Index() {
 	} else {
 		c.Data["PageHtml"] = ""
 	}
-	c.Data["Lists"] = search_result
+	c.Data["Lists"] = searchResult
 
 	c.Data["LabelName"] = labelName
 }

+ 64 - 0
controllers/manager.go

@@ -15,6 +15,7 @@ import (
 	"path/filepath"
 	"strconv"
 	"github.com/lifei6671/mindoc/utils/pagination"
+	"math"
 )
 
 type ManagerController struct {
@@ -633,3 +634,66 @@ func (c *ManagerController) AttachDelete() {
 	}
 	c.JsonResult(0, "ok")
 }
+
+//标签列表
+func (c *ManagerController) LabelList(){
+	c.Prepare()
+	c.TplName = "manager/label_list.tpl"
+
+	pageIndex, _ := c.GetInt("page", 1)
+
+	labels, totalCount, err := models.NewLabel().FindToPager(pageIndex, conf.PageSize)
+
+	if err != nil {
+		c.ShowErrorPage(50001, err.Error())
+	}
+	if totalCount > 0 {
+		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize)
+		c.Data["PageHtml"] = pager.HtmlPages()
+	} else {
+		c.Data["PageHtml"] = ""
+	}
+	c.Data["TotalPages"] = int(math.Ceil(float64(totalCount) / float64(conf.PageSize)))
+
+	c.Data["Lists"] = labels
+}
+//删除标签
+func (c *ManagerController) LabelDelete(){
+	labelId,err := strconv.Atoi(c.Ctx.Input.Param(":id"))
+
+	if err != nil {
+		beego.Error("获取删除标签参数时出错:",err)
+		c.JsonResult(50001,"参数错误")
+	}
+	if labelId <= 0 {
+		c.JsonResult(50001,"参数错误")
+	}
+
+	label,err := models.NewLabel().FindFirst("label_id",labelId)
+	if err != nil {
+		beego.Error("查询标签时出错:",err)
+		c.JsonResult(50001,"查询标签时出错:" + err.Error())
+	}
+	if err := label.Delete();err != nil {
+		c.JsonResult(50002,"删除失败:" + err.Error())
+	}else{
+		c.JsonResult(0,"ok")
+	}
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 14 - 34
controllers/search.go

@@ -4,8 +4,8 @@ import (
 	"github.com/astaxie/beego"
 	"github.com/lifei6671/mindoc/conf"
 	"github.com/lifei6671/mindoc/models"
+	"github.com/lifei6671/mindoc/utils"
 	"github.com/lifei6671/mindoc/utils/pagination"
-	"regexp"
 	"strconv"
 	"strings"
 )
@@ -13,6 +13,7 @@ import (
 type SearchController struct {
 	BaseController
 }
+
 //搜索首页
 func (c *SearchController) Index() {
 	c.Prepare()
@@ -42,7 +43,7 @@ func (c *SearchController) Index() {
 			return
 		}
 		if totalCount > 0 {
-			pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize)
+			pager := pagination.NewPagination(c.Ctx.Request, totalCount, conf.PageSize)
 			c.Data["PageHtml"] = pager.HtmlPages()
 		} else {
 			c.Data["PageHtml"] = ""
@@ -54,27 +55,7 @@ func (c *SearchController) Index() {
 				if item.Description != "" {
 					src := item.Description
 
-					//将HTML标签全转换成小写
-					re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
-					src = re.ReplaceAllStringFunc(src, strings.ToLower)
-
-					//去除STYLE
-					re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
-					src = re.ReplaceAllString(src, "")
-
-					//去除SCRIPT
-					re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
-					src = re.ReplaceAllString(src, "")
-
-					//去除所有尖括号内的HTML代码,并换成换行符
-					re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
-					src = re.ReplaceAllString(src, "\n")
-
-					//去除连续的换行符
-					re, _ = regexp.Compile("\\s{2,}")
-					src = re.ReplaceAllString(src, "\n")
-
-					r := []rune(src)
+					r := []rune(utils.StripTags(item.Description))
 
 					if len(r) > 100 {
 						src = string(r[:100])
@@ -101,35 +82,34 @@ func (c *SearchController) User() {
 	c.Prepare()
 	key := c.Ctx.Input.Param(":key")
 	keyword := strings.TrimSpace(c.GetString("q"))
-	if key == "" || keyword == ""{
-		c.JsonResult(404,"参数错误")
+	if key == "" || keyword == "" {
+		c.JsonResult(404, "参数错误")
 	}
 
 	book, err := models.NewBookResult().FindByIdentify(key, c.Member.MemberId)
 	if err != nil {
 		if err == models.ErrPermissionDenied {
-			c.JsonResult(403,"没有权限")
+			c.JsonResult(403, "没有权限")
 		}
-		c.JsonResult(500,"项目不存在")
+		c.JsonResult(500, "项目不存在")
 	}
 
-	members,err := models.NewMemberRelationshipResult().FindNotJoinUsersByAccount(book.BookId,10,"%"+keyword+"%")
+	members, err := models.NewMemberRelationshipResult().FindNotJoinUsersByAccount(book.BookId, 10, "%"+keyword+"%")
 	if err != nil {
 		beego.Error("查询用户列表出错:" + err.Error())
-		c.JsonResult(500,err.Error())
+		c.JsonResult(500, err.Error())
 	}
 	result := models.SelectMemberResult{}
-	items := make([]models.KeyValueItem,0)
+	items := make([]models.KeyValueItem, 0)
 
-	for _,member := range members {
+	for _, member := range members {
 		item := models.KeyValueItem{}
 		item.Id = member.MemberId
 		item.Text = member.Account
-		items = append(items,item)
+		items = append(items, item)
 	}
 
 	result.Result = items
 
-	c.JsonResult(0,"OK", result)
+	c.JsonResult(0, "OK", result)
 }
-

+ 10 - 8
models/book.go

@@ -22,6 +22,8 @@ type Book struct {
 	Identify string `orm:"column(identify);size(100);unique" json:"identify"`
 	//是否是自动发布 0 否/1 是
 	AutoRelease int `orm:"column(auto_release);type(int);default(0)" json:"auto_release"`
+	//是否开启下载功能 0 是/1 否
+	IsDownload int `orm:"column(is_download);type(int);default(0)" json:"is_download"`
 	OrderIndex  int `orm:"column(order_index);type(int);default(0)" json:"order_index"`
 	// Description 项目描述.
 	Description string `orm:"column(description);size(2000)" json:"description"`
@@ -129,7 +131,7 @@ func (m *Book) Update(cols ...string) error {
 		return err
 	}
 
-	if (m.Label + temp.Label) != "" {
+	if m.Label != "" || temp.Label != ""{
 
 		go NewLabel().InsertOrUpdateMulti(m.Label + "," + temp.Label)
 	}
@@ -314,16 +316,16 @@ func (m *Book) FindForHomeToPager(pageIndex, pageSize, member_id int) (books []*
 }
 
 //分页全局搜索.
-func (m *Book) FindForLabelToPager(keyword string, pageIndex, pageSize, member_id int) (books []*BookResult, totalCount int, err error) {
+func (m *Book) FindForLabelToPager(keyword string, pageIndex, pageSize, memberId int) (books []*BookResult, totalCount int, err error) {
 	o := orm.NewOrm()
 
 	keyword = "%" + keyword + "%"
 	offset := (pageIndex - 1) * pageSize
 	//如果是登录用户
-	if member_id > 0 {
+	if memberId > 0 {
 		sql1 := "SELECT COUNT(*) FROM md_books AS book LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.member_id = ? WHERE (relationship_id > 0 OR book.privately_owned = 0) AND book.label LIKE ?"
 
-		err = o.Raw(sql1, member_id, keyword).QueryRow(&totalCount)
+		err = o.Raw(sql1, memberId, keyword).QueryRow(&totalCount)
 		if err != nil {
 			return
 		}
@@ -333,7 +335,7 @@ func (m *Book) FindForLabelToPager(keyword string, pageIndex, pageSize, member_i
 			LEFT JOIN md_members AS member ON rel1.member_id = member.member_id
 			WHERE (rel.relationship_id > 0 OR book.privately_owned = 0) AND book.label LIKE ? ORDER BY order_index DESC ,book.book_id DESC LIMIT ?,?`
 
-		_, err = o.Raw(sql2, member_id, keyword, offset, pageSize).QueryRows(&books)
+		_, err = o.Raw(sql2, memberId, keyword, offset, pageSize).QueryRows(&books)
 
 		return
 
@@ -359,12 +361,12 @@ func (m *Book) FindForLabelToPager(keyword string, pageIndex, pageSize, member_i
 }
 
 //重置文档数量
-func (m *Book) ResetDocumentNumber(book_id int) {
+func (m *Book) ResetDocumentNumber(bookId int) {
 	o := orm.NewOrm()
 
-	totalCount, err := o.QueryTable(NewDocument().TableNameWithPrefix()).Filter("book_id", book_id).Count()
+	totalCount, err := o.QueryTable(NewDocument().TableNameWithPrefix()).Filter("book_id", bookId).Count()
 	if err == nil {
-		o.Raw("UPDATE md_books SET doc_count = ? WHERE book_id = ?", int(totalCount), book_id).Exec()
+		o.Raw("UPDATE md_books SET doc_count = ? WHERE book_id = ?", int(totalCount), bookId).Exec()
 	} else {
 		beego.Error(err)
 	}

+ 2 - 0
models/book_result.go

@@ -51,6 +51,7 @@ type BookResult struct {
 
 	LastModifyText   string `json:"last_modify_text"`
 	IsDisplayComment bool   `json:"is_display_comment"`
+	IsDownload bool			`json:"is_download"`
 }
 
 func NewBookResult() *BookResult {
@@ -174,6 +175,7 @@ func (m *BookResult) ToBookResult(book Book) *BookResult {
 	m.AutoRelease = book.AutoRelease == 1
 	m.Publisher = book.Publisher
 	m.HistoryCount = book.HistoryCount
+	m.IsDownload = book.IsDownload == 0
 
 	if book.Theme == "" {
 		m.Theme = "default"

+ 38 - 40
models/document.go

@@ -14,7 +14,6 @@ import (
 	"github.com/PuerkitoBio/goquery"
 	"github.com/lifei6671/mindoc/cache"
 	"encoding/json"
-	"qiniupkg.com/x/errors.v7"
 )
 
 // Document struct.
@@ -65,9 +64,7 @@ func (m *Document) Find(id int) (*Document, error) {
 	if id <= 0 {
 		return m, ErrInvalidParameter
 	}
-	if m,err := m.FromCacheById(id); err == nil {
-		return m,nil
-	}
+
 	o := orm.NewOrm()
 
 	err := o.QueryTable(m.TableNameWithPrefix()).Filter("document_id", id).One(m)
@@ -75,7 +72,7 @@ func (m *Document) Find(id int) (*Document, error) {
 	if err == orm.ErrNoRows {
 		return m, ErrDataNotExist
 	}
-	m.PutToCache()
+
 	return m, nil
 }
 
@@ -93,36 +90,16 @@ func (m *Document) InsertOrUpdate(cols ...string) error {
 		return err
 	}
 
-	m.PutToCache()
-
 	return nil
 }
 
 //根据指定字段查询一条文档.
 func (m *Document) FindByFieldFirst(field string, v interface{}) (*Document, error) {
 
-	if field == "identify" {
-		if identify,ok := v.(string);ok {
-			if m,err := m.FromCacheByIdentify(identify);err == nil{
-				return m,nil
-			}
-		}
-	}else if field == "document_id" {
-		if id,ok := v.(int); ok && id > 0 {
-			if m,err := m.FromCacheById(id);err == nil{
-				return m,nil
-			}
-		}
-	}
-
 	o := orm.NewOrm()
 
 	err := o.QueryTable(m.TableNameWithPrefix()).Filter(field, v).One(m)
 
-	if err == nil {
-		m.PutToCache()
-	}
-
 	return m, err
 }
 
@@ -165,7 +142,7 @@ func (m *Document) ReleaseContent(bookId int) {
 	o := orm.NewOrm()
 
 	var docs []*Document
-	_, err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id", bookId).All(&docs, "document_id", "content")
+	_, err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id", bookId).All(&docs, "document_id","identify", "content")
 
 	if err != nil {
 		beego.Error("发布失败 => ", err)
@@ -214,7 +191,12 @@ func (m *Document) ReleaseContent(bookId int) {
 			beego.Error(fmt.Sprintf("发布失败 => %+v", item), err)
 		}else {
 			//当文档发布后,需要清除已缓存的转换文档和文档缓存
-			item.PutToCache()
+			if doc,err := NewDocument().Find(item.DocumentId); err == nil {
+				doc.PutToCache()
+			}else{
+				doc.RemoveCache()
+			}
+
 			os.RemoveAll(filepath.Join(conf.WorkingDirectory,"uploads","books",strconv.Itoa(bookId)))
 		}
 	}
@@ -222,38 +204,54 @@ func (m *Document) ReleaseContent(bookId int) {
 
 //将文档写入缓存
 func (m *Document) PutToCache(){
-	if v,err := json.Marshal(m);err == nil {
-		if m.Identify == "" {
-			if err := cache.Put("Document.Id."+strconv.Itoa(m.DocumentId), v, time.Second*3600); err != nil {
-				beego.Info("文档缓存失败:", m)
-			}
-		}else{
-			if err := cache.Put("Document.Identify."+ m.Identify, v, time.Second*3600); err != nil {
-				beego.Info("文档缓存失败:", m)
+	go func(m Document) {
+		if v,err := json.Marshal(&m);err == nil {
+			if m.Identify == "" {
+
+				if err := cache.Put("Document.Id." + strconv.Itoa(m.DocumentId), v, time.Second*3600); err != nil {
+					beego.Info("文档缓存失败:", m.DocumentId)
+				}
+			}else{
+				if err := cache.Put("Document.Identify."+ m.Identify, v, time.Second*3600); err != nil {
+					beego.Info("文档缓存失败:", m.DocumentId)
+				}
 			}
 		}
-	}
+	}(*m)
+}
+//清除缓存
+func (m *Document) RemoveCache() {
+	go func(m Document) {
+		cache.Put("Document.Id." + strconv.Itoa(m.DocumentId), m, time.Second*3600);
+
+		if m.Identify != "" {
+			cache.Put("Document.Identify."+ m.Identify, m, time.Second*3600);
+		}
+	}(*m)
 }
+
 //从缓存获取
 func (m *Document) FromCacheById(id int) (*Document,error) {
 	b := cache.Get("Document.Id." + strconv.Itoa(id))
 	if v,ok := b.([]byte); ok {
-		beego.Info("从缓存中获取文档信息成功")
+
 		if err := json.Unmarshal(v,m);err == nil{
+			beego.Info("从缓存中获取文档信息成功",m.DocumentId)
 			return m,nil
 		}
 	}
-	return nil,errors.New("Cache not exists")
+	return m.Find(id)
 }
+//根据文档标识从缓存中查询文档
 func (m *Document) FromCacheByIdentify(identify string) (*Document,error) {
 	b := cache.Get("Document.Identify." + identify)
 	if v,ok := b.([]byte); ok {
-		beego.Info("从缓存中获取文档信息成功")
 		if err := json.Unmarshal(v,m);err == nil{
+			beego.Info("从缓存中获取文档信息成功",m.DocumentId)
 			return m,nil
 		}
 	}
-	return nil,errors.New("Cache not exists")
+	return m.FindByFieldFirst("identify",identify)
 }
 
 //根据项目ID查询文档列表.

+ 14 - 0
models/label.go

@@ -72,6 +72,16 @@ func (m *Label) InsertOrUpdateMulti(labels string) {
 		}
 	}
 }
+//删除标签
+func (m *Label) Delete() error {
+	o := orm.NewOrm()
+	_,err := o.Raw("DELETE FROM " + m.TableNameWithPrefix() + " WHERE label_id= ?",m.LabelId).Exec()
+
+	if err != nil {
+		return err
+	}
+	return nil
+}
 
 //分页查找标签.
 func (m *Label) FindToPager(pageIndex, pageSize int) (labels []*Label, totalCount int, err error) {
@@ -90,3 +100,7 @@ func (m *Label) FindToPager(pageIndex, pageSize int) (labels []*Label, totalCoun
 
 	return
 }
+
+
+
+

+ 2 - 0
models/member_result.go

@@ -9,6 +9,7 @@ import (
 type MemberRelationshipResult struct {
 	MemberId       int       `json:"member_id"`
 	Account        string    `json:"account"`
+	RealName 	   string    `json:"real_name"`
 	Description    string    `json:"description"`
 	Email          string    `json:"email"`
 	Phone          string    `json:"phone"`
@@ -47,6 +48,7 @@ func (m *MemberRelationshipResult) FromMember(member *Member) *MemberRelationshi
 	m.Status = member.Status
 	m.CreateTime = member.CreateTime
 	m.CreateAt = member.CreateAt
+	m.RealName = member.RealName
 
 	return m
 }

+ 2 - 0
routers/router.go

@@ -33,6 +33,8 @@ func init() {
 	beego.Router("/manager/attach/list", &controllers.ManagerController{}, "*:AttachList")
 	beego.Router("/manager/attach/detailed/:id", &controllers.ManagerController{}, "*:AttachDetailed")
 	beego.Router("/manager/attach/delete", &controllers.ManagerController{}, "post:AttachDelete")
+	beego.Router("/manager/label/list", &controllers.ManagerController{},"get:LabelList")
+	beego.Router("/manager/label/delete/:id", &controllers.ManagerController{},"post:LabelDelete")
 
 	beego.Router("/setting", &controllers.SettingController{}, "*:Index")
 	beego.Router("/setting/password", &controllers.SettingController{}, "*:Password")

+ 31 - 0
utils/html.go

@@ -0,0 +1,31 @@
+package utils
+
+import (
+	"regexp"
+	"strings"
+)
+
+func StripTags(s string) string  {
+
+	//将HTML标签全转换成小写
+	re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
+	src := re.ReplaceAllStringFunc(s, strings.ToLower)
+
+	//去除STYLE
+	re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
+	src = re.ReplaceAllString(src, "")
+
+	//去除SCRIPT
+	re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
+	src = re.ReplaceAllString(src, "")
+
+	//去除所有尖括号内的HTML代码,并换成换行符
+	re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
+	src = re.ReplaceAllString(src, "\n")
+
+	//去除连续的换行符
+	re, _ = regexp.Compile("\\s{2,}")
+	src = re.ReplaceAllString(src, "\n")
+
+	return src
+}

+ 9 - 0
views/book/setting.tpl

@@ -137,6 +137,14 @@
                         </div>
                     </div>
                 </div>
+                <div class="form-group">
+                    <label for="autoRelease">开启导出</label>
+                    <div class="controls">
+                        <div class="switch switch-small" data-on="primary" data-off="info">
+                            <input type="checkbox" id="isDownload" name="is_download"{{if .Model.IsDownload }} checked{{end}} data-size="small">
+                        </div>
+                    </div>
+                </div>
                 <div class="form-group">
                     <button type="submit" id="btnSaveBookInfo" class="btn btn-success" data-loading-text="保存中...">保存修改</button>
                     <span id="form-error-message" class="error-message"></span>
@@ -301,6 +309,7 @@
             window.modalHtml = $("#upload-logo-panel").find(".modal-body").html();
         });
         $("#autoRelease").bootstrapSwitch();
+        $("#isDownload").bootstrapSwitch();
 
         $('input[name="label"]').tagsinput({
             confirmKeys: [13,44],

+ 1 - 0
views/book/users.tpl

@@ -52,6 +52,7 @@
                             <div class="list-item" v-for="item in lists">
                                 <img :src="item.avatar" onerror="this.src='/static/images/middle.gif'" class="img-circle" width="34" height="34">
                                 <span>${item.account}</span>
+                                <span style="font-size: 12px;color: #484848" v-if="item.real_name != ''">[${item.real_name}]</span>
                                 <div class="operate">
                                     <template v-if="item.role_id == 0">
                                         创始人

+ 2 - 1
views/document/default_read.tpl

@@ -64,6 +64,7 @@
                     <button type="button" class="btn btn-success" data-toggle="modal" data-target="#shareProject"><i class="fa fa-share-alt" aria-hidden="true"></i> 分享</button>
                 {{end}}
                 </div>
+                {{if .Model.IsDownload}}
                 <div class="dropdown pull-right" style="margin-right: 10px;">
                     <button type="button" class="btn btn-primary" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                         <i class="fa fa-cloud-download" aria-hidden="true"></i> 下载 <span class="caret"></span>
@@ -75,7 +76,7 @@
                         <li><a href="{{urlfor "DocumentController.Export" ":key" .Model.Identify "output" "docx"}}" target="_blank">Word</a> </li>
                     </ul>
                 </div>
-
+                {{end}}
             </div>
         </div>
     </header>

+ 1 - 0
views/manager/attach_detailed.tpl

@@ -31,6 +31,7 @@
                     <li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
                     <li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
                     <li class="active"><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
+                    <li><a href="{{urlfor "ManagerController.LabelList" }}" class="item"><i class="fa fa-bookmark" aria-hidden="true"></i> 标签管理</a> </li>
                 </ul>
             </div>
             <div class="page-right">

+ 1 - 0
views/manager/attach_list.tpl

@@ -32,6 +32,7 @@
                     {{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
                     <li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
                     <li class="active"><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
+                    <li><a href="{{urlfor "ManagerController.LabelList" }}" class="item"><i class="fa fa-bookmark" aria-hidden="true"></i> 标签管理</a> </li>
                 </ul>
             </div>
             <div class="page-right">

+ 1 - 0
views/manager/books.tpl

@@ -32,6 +32,7 @@
                     {{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
                     <li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
                     <li><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
+                    <li><a href="{{urlfor "ManagerController.LabelList" }}" class="item"><i class="fa fa-bookmark" aria-hidden="true"></i> 标签管理</a> </li>
                 </ul>
             </div>
             <div class="page-right">

+ 1 - 0
views/manager/edit_book.tpl

@@ -33,6 +33,7 @@
                     {{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
                     <li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
                     <li><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
+                    <li><a href="{{urlfor "ManagerController.LabelList" }}" class="item"><i class="fa fa-bookmark" aria-hidden="true"></i> 标签管理</a> </li>
                 </ul>
             </div>
             <div class="page-right">

+ 1 - 0
views/manager/edit_users.tpl

@@ -31,6 +31,7 @@
                     {{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
                     <li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
                     <li><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
+                    <li><a href="{{urlfor "ManagerController.LabelList" }}" class="item"><i class="fa fa-bookmark" aria-hidden="true"></i> 标签管理</a> </li>
                 </ul>
             </div>
             <div class="page-right">

+ 1 - 0
views/manager/index.tpl

@@ -32,6 +32,7 @@
                     {{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
                     <li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
                     <li><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
+                    <li><a href="{{urlfor "ManagerController.LabelList" }}" class="item"><i class="fa fa-bookmark" aria-hidden="true"></i> 标签管理</a> </li>
 
                 </ul>
             </div>

+ 116 - 0
views/manager/label_list.tpl

@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+
+    <title>标签管理 - Powered by MinDoc</title>
+
+    <!-- Bootstrap -->
+    <link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet" type="text/css">
+    <link href="{{cdncss "/static/font-awesome/css/font-awesome.min.css"}}" rel="stylesheet" type="text/css">
+
+    <link href="{{cdncss "/static/css/main.css"}}" rel="stylesheet">
+    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
+    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+    <!--[if lt IE 9]>
+    <script src="{{cdnjs "/static/html5shiv/3.7.3/html5shiv.min.js"}}"></script>
+    <script src="{{cdnjs "/static/respond.js/1.4.2/respond.min.js" }}"></script>
+    <![endif]-->
+</head>
+<body>
+<div class="manual-reader">
+{{template "widgets/header.tpl" .}}
+    <div class="container manual-body">
+        <div class="row">
+            <div class="page-left">
+                <ul class="menu">
+                    <li><a href="{{urlfor "ManagerController.Index"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 仪表盘</a> </li>
+                    <li><a href="{{urlfor "ManagerController.Users" }}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 用户管理</a> </li>
+                    <li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
+                {{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
+                    <li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
+                    <li><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
+                    <li class="active"><a href="{{urlfor "ManagerController.LabelList" }}" class="item"><i class="fa fa-bookmark" aria-hidden="true"></i> 标签管理</a> </li>
+
+                </ul>
+            </div>
+            <div class="page-right">
+                <div class="m-box">
+                    <div class="box-head">
+                        <strong class="box-title">附件管理</strong>
+                    </div>
+                </div>
+                <div class="box-body">
+                    <div class="attach-list" id="attachList">
+                        <table class="table">
+                            <thead>
+                            <tr>
+                                <th width="10%">#</th>
+                                <th width="55%">标签名称</th>
+                                <th width="20%">使用数量</th>
+                                <th>操作</th>
+                            </tr>
+                            </thead>
+                            <tbody>
+                            {{range $index,$item := .Lists}}
+                            <tr>
+                                <td>{{$item.LabelId}}</td>
+                                <td>{{$item.LabelName}}</td>
+                                <td>{{$item.BookNumber}}</td>
+                                <td>
+                                    <button type="button" data-method="delete" class="btn btn-danger btn-sm" data-id="{{$item.LabelId}}" data-loading-text="删除中...">删除</button>
+                                    <a href="{{urlfor "LabelController.Index" ":key" $item.LabelName}}" class="btn btn-success btn-sm" target="_blank">详情</a>
+
+                                </td>
+                            </tr>
+                            {{else}}
+                            <tr><td class="text-center" colspan="6">暂无数据</td></tr>
+                            {{end}}
+                            </tbody>
+                        </table>
+                        <nav class="pagination-container">
+                        {{.PageHtml}}
+                        </nav>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+{{template "widgets/footer.tpl" .}}
+</div>
+
+<script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}"></script>
+<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}"></script>
+<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
+<script src="{{cdnjs "/static/layer/layer.js" }}" type="text/javascript"></script>
+<script type="text/javascript">
+    $(function () {
+        $("#attachList").on("click","button[data-method='delete']",function () {
+            var id = $(this).attr("data-id");
+            var $this = $(this);
+            $(this).button("loading");
+            $.ajax({
+                url : "{{urlfor "ManagerController.LabelDelete" ":id" ""}}" + id,
+                type : "post",
+                dataType : "json",
+                success : function (res) {
+                    if(res.errcode === 0){
+                        $this.closest("tr").remove().empty();
+                    }else {
+                        layer.msg(res.message);
+                    }
+                },
+                error : function () {
+                    layer.msg("服务器异常");
+                },
+                complete : function () {
+                    $this.button("reset");
+                }
+            });
+        });
+    });
+</script>
+</body>
+</html>

+ 1 - 0
views/manager/setting.tpl

@@ -31,6 +31,7 @@
                     {{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
                     <li class="active"><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
                     <li><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
+                    <li><a href="{{urlfor "ManagerController.LabelList" }}" class="item"><i class="fa fa-bookmark" aria-hidden="true"></i> 标签管理</a> </li>
 
                 </ul>
             </div>

+ 2 - 0
views/manager/users.tpl

@@ -35,6 +35,8 @@
                     {{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
                     <li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
                     <li><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
+                    <li><a href="{{urlfor "ManagerController.LabelList" }}" class="item"><i class="fa fa-bookmark" aria-hidden="true"></i> 标签管理</a> </li>
+
                 </ul>
 
             </div>