mirror of https://github.com/mindoc-org/mindoc.git
parent
96ba414dd8
commit
86637ef581
|
@ -3,6 +3,16 @@ package controllers
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
"github.com/lifei6671/mindoc/models"
|
"github.com/lifei6671/mindoc/models"
|
||||||
|
"time"
|
||||||
|
"github.com/astaxie/beego"
|
||||||
|
"github.com/lifei6671/mindoc/conf"
|
||||||
|
"github.com/lifei6671/mindoc/utils/pagination"
|
||||||
|
"strconv"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
|
"github.com/astaxie/beego/orm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BlogController struct{
|
type BlogController struct{
|
||||||
|
@ -25,6 +35,24 @@ func (c *BlogController) List() {
|
||||||
func (c *BlogController) ManageList() {
|
func (c *BlogController) ManageList() {
|
||||||
c.Prepare()
|
c.Prepare()
|
||||||
c.TplName = "blog/manage_list.tpl"
|
c.TplName = "blog/manage_list.tpl"
|
||||||
|
|
||||||
|
pageIndex, _ := c.GetInt("page", 1)
|
||||||
|
|
||||||
|
blogList,totalCount,err := models.NewBlog().FindToPager(pageIndex,conf.PageSize,c.Member.MemberId,"")
|
||||||
|
|
||||||
|
beego.Info(totalCount)
|
||||||
|
if err != nil {
|
||||||
|
c.ShowErrorPage(500,err.Error())
|
||||||
|
}
|
||||||
|
if totalCount > 0 {
|
||||||
|
pager := pagination.NewPagination(c.Ctx.Request, totalCount, conf.PageSize, c.BaseUrl())
|
||||||
|
c.Data["PageHtml"] = pager.HtmlPages()
|
||||||
|
} else {
|
||||||
|
c.Data["PageHtml"] = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["ModelList"] = blogList
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//文章设置
|
//文章设置
|
||||||
|
@ -39,10 +67,21 @@ func (c *BlogController) ManageSetting() {
|
||||||
orderIndex,_ := c.GetInt("order_index",0)
|
orderIndex,_ := c.GetInt("order_index",0)
|
||||||
blogType,_ := c.GetInt("blog_type",0)
|
blogType,_ := c.GetInt("blog_type",0)
|
||||||
documentId,_ := c.GetInt("document_id",0)
|
documentId,_ := c.GetInt("document_id",0)
|
||||||
|
blogExcerpt := c.GetString("excerpt","")
|
||||||
|
blogStatus := c.GetString("status","publish")
|
||||||
|
blogPassword := c.GetString("password","")
|
||||||
if blogTitle == "" {
|
if blogTitle == "" {
|
||||||
c.JsonResult(6001,"文章标题不能为空")
|
c.JsonResult(6001,"文章标题不能为空")
|
||||||
}
|
}
|
||||||
|
if strings.Count(blogExcerpt,"") > 100 {
|
||||||
|
c.JsonResult(6008,"文章摘要必须小于500字符")
|
||||||
|
}
|
||||||
|
if blogStatus != "public" && blogStatus != "password" && blogStatus != "draft" {
|
||||||
|
blogStatus = "public"
|
||||||
|
}
|
||||||
|
if blogStatus == "password" && blogPassword == "" {
|
||||||
|
c.JsonResult(6010,"加密文章请设置密码")
|
||||||
|
}
|
||||||
if blogType != 0 && blogType != 1 {
|
if blogType != 0 && blogType != 1 {
|
||||||
c.JsonResult(6005,"未知的文章类型")
|
c.JsonResult(6005,"未知的文章类型")
|
||||||
}else if documentId <= 0 && blogType == 1 {
|
}else if documentId <= 0 && blogType == 1 {
|
||||||
|
@ -73,6 +112,8 @@ func (c *BlogController) ManageSetting() {
|
||||||
c.JsonResult(6004,"文章标识已存在")
|
c.JsonResult(6004,"文章标识已存在")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
blog.Modified = time.Now()
|
||||||
|
blog.ModifyAt = c.Member.MemberId
|
||||||
}else{
|
}else{
|
||||||
//如果设置了文章标识
|
//如果设置了文章标识
|
||||||
if blogIdentify != "" {
|
if blogIdentify != "" {
|
||||||
|
@ -83,17 +124,47 @@ func (c *BlogController) ManageSetting() {
|
||||||
|
|
||||||
blog = models.NewBlog()
|
blog = models.NewBlog()
|
||||||
blog.MemberId = c.Member.MemberId
|
blog.MemberId = c.Member.MemberId
|
||||||
|
blog.Created = time.Now()
|
||||||
|
}
|
||||||
|
if blogIdentify == "" {
|
||||||
|
blog.BlogIdentify = fmt.Sprintf("%s-%d","post",time.Now().UnixNano())
|
||||||
|
}else{
|
||||||
|
blog.BlogIdentify = blogIdentify
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
blog.BlogTitle = blogTitle
|
blog.BlogTitle = blogTitle
|
||||||
blog.BlogIdentify = blogIdentify
|
|
||||||
blog.OrderIndex = orderIndex
|
blog.OrderIndex = orderIndex
|
||||||
blog.BlogType = blogType
|
blog.BlogType = blogType
|
||||||
if blogType == 1 {
|
if blogType == 1 {
|
||||||
blog.DocumentId = documentId
|
blog.DocumentId = documentId
|
||||||
}
|
}
|
||||||
|
blog.BlogExcerpt = blogExcerpt
|
||||||
|
blog.BlogStatus = blogStatus
|
||||||
|
blog.Password = blogPassword
|
||||||
|
|
||||||
|
if err := blog.Save();err != nil {
|
||||||
|
beego.Error("保存文章失败 -> ",err)
|
||||||
|
c.JsonResult(6011,"保存文章失败")
|
||||||
|
}else{
|
||||||
|
c.JsonResult(0,"ok",blog)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.Ctx.Input.Referer() == "" {
|
||||||
|
c.Data["Referer"] = "javascript:history.back();"
|
||||||
|
}else{
|
||||||
|
c.Data["Referer"] = c.Ctx.Input.Referer()
|
||||||
|
}
|
||||||
|
blogId,err := strconv.Atoi(c.Ctx.Input.Param(":id"))
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
blog,err := models.NewBlog().FindByIdAndMemberId(blogId,c.Member.MemberId)
|
||||||
|
if err != nil {
|
||||||
|
c.ShowErrorPage(500,err.Error())
|
||||||
|
}
|
||||||
|
c.Data["Model"] = blog
|
||||||
|
}else{
|
||||||
|
c.Data["Model"] = models.NewBlog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,4 +172,316 @@ func (c *BlogController) ManageSetting() {
|
||||||
func (c *BlogController) ManageEdit() {
|
func (c *BlogController) ManageEdit() {
|
||||||
c.Prepare()
|
c.Prepare()
|
||||||
c.TplName = "blog/manage_edit.tpl"
|
c.TplName = "blog/manage_edit.tpl"
|
||||||
|
|
||||||
|
if c.Ctx.Input.IsPost() {
|
||||||
|
blogId,_ := c.GetInt("blogId",0)
|
||||||
|
|
||||||
|
if blogId <= 0 {
|
||||||
|
c.JsonResult(6001,"文章参数错误")
|
||||||
|
}
|
||||||
|
blogContent := c.GetString("content","")
|
||||||
|
blogHtml := c.GetString("htmlContent","")
|
||||||
|
version,_ := c.GetInt64("version",0)
|
||||||
|
cover := c.GetString("cover")
|
||||||
|
|
||||||
|
var blog *models.Blog
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if c.Member.IsAdministrator() {
|
||||||
|
blog,err = models.NewBlog().Find(blogId)
|
||||||
|
}else{
|
||||||
|
blog,err = models.NewBlog().FindByIdAndMemberId(blogId,c.Member.MemberId)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
beego.Error("查询文章失败 ->",err)
|
||||||
|
c.JsonResult(6002,"查询文章失败")
|
||||||
|
}
|
||||||
|
if version > 0 && blog.Version != version && cover != "yes"{
|
||||||
|
c.JsonResult(6005,"文章已被修改")
|
||||||
|
}
|
||||||
|
if blog.BlogType == 1 {
|
||||||
|
doc,err := models.NewDocument().Find(blog.DocumentId)
|
||||||
|
if err != nil {
|
||||||
|
beego.Error("查询关联项目文档时出错 ->", err)
|
||||||
|
c.JsonResult(6003,"查询关联项目文档时出错")
|
||||||
|
}
|
||||||
|
doc.Markdown = blogContent
|
||||||
|
doc.Release = blogHtml
|
||||||
|
doc.Content = blogHtml
|
||||||
|
doc.ModifyTime = time.Now()
|
||||||
|
doc.ModifyAt = c.Member.MemberId
|
||||||
|
if err := doc.InsertOrUpdate("markdown","release","content","modify_time","modify_at");err != nil {
|
||||||
|
beego.Error("保存关联文档时出错 ->",err)
|
||||||
|
c.JsonResult(6004,"保存关联文档时出错")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blog.BlogContent = blogContent
|
||||||
|
blog.BlogRelease = blogHtml
|
||||||
|
blog.ModifyAt = c.Member.MemberId
|
||||||
|
blog.Modified = time.Now()
|
||||||
|
|
||||||
|
|
||||||
|
if err := blog.Save("blog_content","blog_release","modify_at","modify_time","version");err != nil {
|
||||||
|
beego.Error("保存文章失败 -> ",err)
|
||||||
|
c.JsonResult(6011,"保存文章失败")
|
||||||
|
}else{
|
||||||
|
c.JsonResult(0,"ok",blog)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blogId,_ := strconv.Atoi(c.Ctx.Input.Param(":id"))
|
||||||
|
|
||||||
|
if blogId <= 0 {
|
||||||
|
c.ShowErrorPage(500,"参数错误")
|
||||||
|
}
|
||||||
|
var blog *models.Blog
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if c.Member.IsAdministrator() {
|
||||||
|
blog,err = models.NewBlog().Find(blogId)
|
||||||
|
}else{
|
||||||
|
blog,err = models.NewBlog().FindByIdAndMemberId(blogId,c.Member.MemberId)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
c.ShowErrorPage(404,"文章不存在或已删除")
|
||||||
|
}
|
||||||
|
c.Data["Model"] = blog
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除文章
|
||||||
|
func (c *BlogController) ManageDelete() {
|
||||||
|
c.Prepare()
|
||||||
|
blogId,_ := c.GetInt("blog_id",0)
|
||||||
|
|
||||||
|
if blogId <= 0 {
|
||||||
|
c.JsonResult(6001,"参数错误")
|
||||||
|
}
|
||||||
|
var blog *models.Blog
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if c.Member.IsAdministrator() {
|
||||||
|
blog,err = models.NewBlog().Find(blogId)
|
||||||
|
}else{
|
||||||
|
blog,err = models.NewBlog().FindByIdAndMemberId(blogId,c.Member.MemberId)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
c.JsonResult(6002,"文章不存在或已删除")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := blog.Delete(blogId); err != nil {
|
||||||
|
c.JsonResult(6003,"删除失败")
|
||||||
|
}else{
|
||||||
|
c.JsonResult(0,"删除成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传附件或图片
|
||||||
|
func (c *BlogController) Upload() {
|
||||||
|
|
||||||
|
blogId, _ := c.GetInt("blogId")
|
||||||
|
|
||||||
|
if blogId <= 0 {
|
||||||
|
c.JsonResult(6001, "参数错误")
|
||||||
|
}
|
||||||
|
|
||||||
|
name := "editormd-file-file"
|
||||||
|
|
||||||
|
file, moreFile, err := c.GetFile(name)
|
||||||
|
if err == http.ErrMissingFile {
|
||||||
|
name = "editormd-image-file"
|
||||||
|
file, moreFile, err = c.GetFile(name)
|
||||||
|
if err == http.ErrMissingFile {
|
||||||
|
c.JsonResult(6003, "没有发现需要上传的图片")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.JsonResult(6002, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
type Size interface {
|
||||||
|
Size() int64
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.GetUploadFileSize() > 0 && moreFile.Size > conf.GetUploadFileSize() {
|
||||||
|
c.JsonResult(6009, "查过文件允许的上传最大值")
|
||||||
|
}
|
||||||
|
|
||||||
|
ext := filepath.Ext(moreFile.Filename)
|
||||||
|
|
||||||
|
if ext == "" {
|
||||||
|
c.JsonResult(6003, "无法解析文件的格式")
|
||||||
|
}
|
||||||
|
//如果文件类型设置为 * 标识不限制文件类型
|
||||||
|
if beego.AppConfig.DefaultString("upload_file_ext", "") != "*" {
|
||||||
|
if !conf.IsAllowUploadFileExt(ext) {
|
||||||
|
c.JsonResult(6004, "不允许的文件类型")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是超级管理员,则不判断权限
|
||||||
|
if c.Member.IsAdministrator() {
|
||||||
|
_, err := models.NewBlog().Find(blogId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.JsonResult(6006, "文档不存在或权限不足")
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_, err := models.NewBlog().FindByIdAndMemberId(blogId, c.Member.MemberId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
beego.Error("查询文章时出错 -> ", err)
|
||||||
|
if err == orm.ErrNoRows {
|
||||||
|
c.JsonResult(6006, "权限不足")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JsonResult(6001, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName := "attach_" + strconv.FormatInt(time.Now().UnixNano(), 16)
|
||||||
|
|
||||||
|
filePath := filepath.Join(conf.WorkingDirectory, "uploads", "blog", time.Now().Format("200601"), fileName+ext)
|
||||||
|
|
||||||
|
path := filepath.Dir(filePath)
|
||||||
|
|
||||||
|
os.MkdirAll(path, os.ModePerm)
|
||||||
|
|
||||||
|
err = c.SaveToFile(name, filePath)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
beego.Error("SaveToFile => ", err)
|
||||||
|
c.JsonResult(6005, "保存文件失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
var httpPath string
|
||||||
|
result := make(map[string]interface{})
|
||||||
|
|
||||||
|
if strings.EqualFold(ext, ".jpg") || strings.EqualFold(ext, ".jpeg") || strings.EqualFold(ext, ".png") || strings.EqualFold(ext, ".gif") {
|
||||||
|
httpPath = "/" + strings.Replace(strings.TrimPrefix(filePath, conf.WorkingDirectory), "\\", "/", -1)
|
||||||
|
if strings.HasPrefix(httpPath, "//") {
|
||||||
|
httpPath = conf.URLForWithCdnImage(string(httpPath[1:]))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
attachment := models.NewAttachment()
|
||||||
|
attachment.BookId = 0
|
||||||
|
attachment.FileName = moreFile.Filename
|
||||||
|
attachment.CreateAt = c.Member.MemberId
|
||||||
|
attachment.FileExt = ext
|
||||||
|
attachment.FilePath = strings.TrimPrefix(filePath, conf.WorkingDirectory)
|
||||||
|
attachment.DocumentId = blogId
|
||||||
|
|
||||||
|
if fileInfo, err := os.Stat(filePath); err == nil {
|
||||||
|
attachment.FileSize = float64(fileInfo.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
attachment.HttpPath = httpPath
|
||||||
|
|
||||||
|
if err := attachment.Insert(); err != nil {
|
||||||
|
os.Remove(filePath)
|
||||||
|
beego.Error("保存文件附件失败 => ", err)
|
||||||
|
c.JsonResult(6006, "文件保存失败")
|
||||||
|
}
|
||||||
|
if attachment.HttpPath == "" {
|
||||||
|
attachment.HttpPath = conf.URLFor("BlogController.Download", ":id", blogId, ":attach_id", attachment.AttachmentId)
|
||||||
|
|
||||||
|
if err := attachment.Update(); err != nil {
|
||||||
|
beego.Error("SaveToFile => ", err)
|
||||||
|
c.JsonResult(6005, "保存文件失败")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result["attach"] = attachment
|
||||||
|
}
|
||||||
|
|
||||||
|
result["errcode"] = 0
|
||||||
|
result["success"] = 1
|
||||||
|
result["message"] = "ok"
|
||||||
|
result["url"] = httpPath
|
||||||
|
result["alt"] = fileName
|
||||||
|
|
||||||
|
|
||||||
|
c.Ctx.Output.JSON(result, true, false)
|
||||||
|
c.StopRun()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除附件
|
||||||
|
func (c *BlogController) RemoveAttachment() {
|
||||||
|
c.Prepare()
|
||||||
|
attachId, _ := c.GetInt("attach_id")
|
||||||
|
|
||||||
|
if attachId <= 0 {
|
||||||
|
c.JsonResult(6001, "参数错误")
|
||||||
|
}
|
||||||
|
|
||||||
|
attach, err := models.NewAttachment().Find(attachId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
beego.Error(err)
|
||||||
|
c.JsonResult(6002, "附件不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.Member.IsAdministrator() {
|
||||||
|
_, err := models.NewBlog().FindByIdAndMemberId(attach.DocumentId,c.Member.MemberId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
beego.Error(err)
|
||||||
|
c.JsonResult(6003, "文档不存在")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if err := attach.Delete();err != nil {
|
||||||
|
beego.Error(err)
|
||||||
|
c.JsonResult(6005, "删除失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Remove(filepath.Join(conf.WorkingDirectory, attach.FilePath))
|
||||||
|
|
||||||
|
c.JsonResult(0, "ok", attach)
|
||||||
|
}
|
||||||
|
|
||||||
|
//下载附件
|
||||||
|
func (c *BlogController) Download() {
|
||||||
|
c.Prepare()
|
||||||
|
|
||||||
|
blogId, _ := strconv.Atoi(c.Ctx.Input.Param(":id"))
|
||||||
|
attachId, _ := strconv.Atoi(c.Ctx.Input.Param(":attach_id"))
|
||||||
|
password := c.GetString("password")
|
||||||
|
|
||||||
|
blog, err := models.NewBlog().Find(blogId)
|
||||||
|
if err != nil {
|
||||||
|
if err == orm.ErrNoRows {
|
||||||
|
c.ShowErrorPage(500, "文档不存在")
|
||||||
|
} else {
|
||||||
|
c.ShowErrorPage(500, "查询文章时异常")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.Member != nil && !c.Member.IsAdministrator()) || ( blog.BlogStatus == "password" && password != blog.Password) {
|
||||||
|
c.ShowErrorPage(403, "没有下载权限")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找附件
|
||||||
|
attachment, err := models.NewAttachment().Find(attachId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
beego.Error("DownloadAttachment => ", err)
|
||||||
|
if err == orm.ErrNoRows {
|
||||||
|
c.ShowErrorPage(404,"附件不存在")
|
||||||
|
} else {
|
||||||
|
c.ShowErrorPage(500,"查询附件时出现异常")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if attachment.BookId !=0 || attachment.DocumentId != blogId {
|
||||||
|
c.ShowErrorPage(404,"附件不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Ctx.Output.Download(filepath.Join(conf.WorkingDirectory, attachment.FilePath), attachment.FileName)
|
||||||
|
c.StopRun()
|
||||||
}
|
}
|
||||||
|
|
|
@ -579,13 +579,13 @@ func (c *DocumentController) DownloadAttachment() {
|
||||||
// 删除附件
|
// 删除附件
|
||||||
func (c *DocumentController) RemoveAttachment() {
|
func (c *DocumentController) RemoveAttachment() {
|
||||||
c.Prepare()
|
c.Prepare()
|
||||||
attach_id, _ := c.GetInt("attach_id")
|
attachId, _ := c.GetInt("attach_id")
|
||||||
|
|
||||||
if attach_id <= 0 {
|
if attachId <= 0 {
|
||||||
c.JsonResult(6001, "参数错误")
|
c.JsonResult(6001, "参数错误")
|
||||||
}
|
}
|
||||||
|
|
||||||
attach, err := models.NewAttachment().Find(attach_id)
|
attach, err := models.NewAttachment().Find(attachId)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beego.Error(err)
|
beego.Error(err)
|
||||||
|
|
|
@ -657,17 +657,19 @@ func (c *ManagerController) AttachDetailed() {
|
||||||
//删除附件.
|
//删除附件.
|
||||||
func (c *ManagerController) AttachDelete() {
|
func (c *ManagerController) AttachDelete() {
|
||||||
c.Prepare()
|
c.Prepare()
|
||||||
attach_id, _ := c.GetInt("attach_id")
|
attachId, _ := c.GetInt("attach_id")
|
||||||
|
|
||||||
if attach_id <= 0 {
|
if attachId <= 0 {
|
||||||
c.Abort("404")
|
c.Abort("404")
|
||||||
}
|
}
|
||||||
attach, err := models.NewAttachment().Find(attach_id)
|
attach, err := models.NewAttachment().Find(attachId)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beego.Error("AttachDelete => ", err)
|
beego.Error("AttachDelete => ", err)
|
||||||
c.JsonResult(6001, err.Error())
|
c.JsonResult(6001, err.Error())
|
||||||
}
|
}
|
||||||
|
attach.FilePath = filepath.Join(conf.WorkingDirectory,attach.FilePath)
|
||||||
|
|
||||||
if err := attach.Delete(); err != nil {
|
if err := attach.Delete(); err != nil {
|
||||||
beego.Error("AttachDelete => ", err)
|
beego.Error("AttachDelete => ", err)
|
||||||
c.JsonResult(6002, err.Error())
|
c.JsonResult(6002, err.Error())
|
||||||
|
|
|
@ -82,11 +82,11 @@ func (m *Attachment) Find(id int) (*Attachment, error) {
|
||||||
|
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
//查询指定文档的附件列表
|
||||||
func (m *Attachment) FindListByDocumentId(doc_id int) (attaches []*Attachment, err error) {
|
func (m *Attachment) FindListByDocumentId(docId int) (attaches []*Attachment, err error) {
|
||||||
o := orm.NewOrm()
|
o := orm.NewOrm()
|
||||||
|
|
||||||
_, err = o.QueryTable(m.TableNameWithPrefix()).Filter("document_id", doc_id).OrderBy("-attachment_id").All(&attaches)
|
_, err = o.QueryTable(m.TableNameWithPrefix()).Filter("document_id", docId).Filter("book_id__gt",0).OrderBy("-attachment_id").All(&attaches)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,20 +115,31 @@ func (m *Attachment) FindToPager(pageIndex, pageSize int) (attachList []*Attachm
|
||||||
attach := &AttachmentResult{}
|
attach := &AttachmentResult{}
|
||||||
attach.Attachment = *item
|
attach.Attachment = *item
|
||||||
attach.FileShortSize = filetil.FormatBytes(int64(attach.FileSize))
|
attach.FileShortSize = filetil.FormatBytes(int64(attach.FileSize))
|
||||||
|
//当项目ID为0标识是文章的附件
|
||||||
|
if item.BookId == 0 && item.DocumentId > 0 {
|
||||||
|
blog := NewBlog()
|
||||||
|
if err := o.QueryTable(blog.TableNameWithPrefix()).Filter("blog_id",item.DocumentId).One(blog,"blog_title");err == nil {
|
||||||
|
attach.BookName = blog.BlogTitle
|
||||||
|
}else{
|
||||||
|
attach.BookName = "[文章不存在]"
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
book := NewBook()
|
||||||
|
|
||||||
book := NewBook()
|
if e := o.QueryTable(book.TableNameWithPrefix()).Filter("book_id", item.BookId).One(book, "book_name"); e == nil {
|
||||||
|
attach.BookName = book.BookName
|
||||||
|
|
||||||
if e := o.QueryTable(book.TableNameWithPrefix()).Filter("book_id", item.BookId).One(book, "book_name"); e == nil {
|
doc := NewDocument()
|
||||||
attach.BookName = book.BookName
|
|
||||||
} else {
|
|
||||||
attach.BookName = "[不存在]"
|
|
||||||
}
|
|
||||||
doc := NewDocument()
|
|
||||||
|
|
||||||
if e := o.QueryTable(doc.TableNameWithPrefix()).Filter("document_id", item.DocumentId).One(doc, "document_name"); e == nil {
|
if e := o.QueryTable(doc.TableNameWithPrefix()).Filter("document_id", item.DocumentId).One(doc, "document_name"); e == nil {
|
||||||
attach.DocumentName = doc.DocumentName
|
attach.DocumentName = doc.DocumentName
|
||||||
} else {
|
} else {
|
||||||
attach.DocumentName = "[不存在]"
|
attach.DocumentName = "[文档不存在]"
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
attach.BookName = "[项目不存在]"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
attach.LocalHttpPath = strings.Replace(item.FilePath, "\\", "/", -1)
|
attach.LocalHttpPath = strings.Replace(item.FilePath, "\\", "/", -1)
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,12 @@ type Blog struct {
|
||||||
//链接到的项目中的文档ID
|
//链接到的项目中的文档ID
|
||||||
DocumentId int `orm:"column(document_id);type(int);default(0)" json:"document_id"`
|
DocumentId int `orm:"column(document_id);type(int);default(0)" json:"document_id"`
|
||||||
//文章摘要
|
//文章摘要
|
||||||
BlogExcerpt string `orm:"column(blog_excerpt);size(1500);unique" json:"blog_excerpt"`
|
BlogExcerpt string `orm:"column(blog_excerpt);size(1500)" json:"blog_excerpt"`
|
||||||
//文章内容
|
//文章内容
|
||||||
BlogContent string `orm:"column(blog_content);type(text);null" json:"blog_content"`
|
BlogContent string `orm:"column(blog_content);type(text);null" json:"blog_content"`
|
||||||
//发布后的文章内容
|
//发布后的文章内容
|
||||||
BlogRelease string `orm:"column(blog_release);type(text);null" json:"blog_release"`
|
BlogRelease string `orm:"column(blog_release);type(text);null" json:"blog_release"`
|
||||||
//文章当前的状态,枚举enum(’publish’,’draft’,’private’,’static’,’object’)值,publish为已 发表,draft为草稿,private为私人内容(不会被公开) ,static(不详),object(不详)。默认为publish。
|
//文章当前的状态,枚举enum(’publish’,’draft’,’password’)值,publish为已 发表,draft为草稿,password 为私人内容(不会被公开) 。默认为publish。
|
||||||
BlogStatus string `orm:"column(blog_status);size(100);default(publish)" json:"blog_status"`
|
BlogStatus string `orm:"column(blog_status);size(100);default(publish)" json:"blog_status"`
|
||||||
//文章密码,varchar(100)值。文章编辑才可为文章设定一个密码,凭这个密码才能对文章进行重新强加或修改。
|
//文章密码,varchar(100)值。文章编辑才可为文章设定一个密码,凭这个密码才能对文章进行重新强加或修改。
|
||||||
Password string `orm:"column(password);size(100)" json:"-"`
|
Password string `orm:"column(password);size(100)" json:"-"`
|
||||||
|
@ -36,9 +36,12 @@ type Blog struct {
|
||||||
Modified time.Time `orm:"column(modify_time);type(datetime);auto_now" json:"modify_time"`
|
Modified time.Time `orm:"column(modify_time);type(datetime);auto_now" json:"modify_time"`
|
||||||
//修改人id
|
//修改人id
|
||||||
ModifyAt int `orm:"column(modify_at);type(int)" json:"-"`
|
ModifyAt int `orm:"column(modify_at);type(int)" json:"-"`
|
||||||
|
ModifyRealName string `orm:"-" json:"modify_real_name"`
|
||||||
//创建时间
|
//创建时间
|
||||||
Created time.Time `orm:"column(create_time);type(datetime);auto_now_add" json:"create_time"`
|
Created time.Time `orm:"column(create_time);type(datetime);auto_now_add" json:"create_time"`
|
||||||
Version int64 `orm:"type(bigint);column(version)" json:"version"`
|
CreateName string `orm:"-" json:"create_name"`
|
||||||
|
//版本号
|
||||||
|
Version int64 `orm:"type(bigint);column(version)" json:"version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 多字段唯一键
|
// 多字段唯一键
|
||||||
|
@ -64,7 +67,7 @@ func (m *Blog) TableNameWithPrefix() string {
|
||||||
|
|
||||||
func NewBlog() *Blog {
|
func NewBlog() *Blog {
|
||||||
return &Blog{
|
return &Blog{
|
||||||
Version: time.Now().Unix(),
|
BlogStatus: "public",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +112,7 @@ func (b *Blog)Link() (*Blog,error) {
|
||||||
//如果是链接文章,则需要从链接的项目中查找文章内容
|
//如果是链接文章,则需要从链接的项目中查找文章内容
|
||||||
if b.BlogType == 1 && b.DocumentId > 0{
|
if b.BlogType == 1 && b.DocumentId > 0{
|
||||||
doc := NewDocument()
|
doc := NewDocument()
|
||||||
if err := o.QueryTable(doc.TableNameWithPrefix()).Filter("document_id",b.DocumentId).One(doc,"");err != nil {
|
if err := o.QueryTable(doc.TableNameWithPrefix()).Filter("document_id",b.DocumentId).One(doc,"release","markdown");err != nil {
|
||||||
beego.Error("查询文章链接对象时出错 -> ",err)
|
beego.Error("查询文章链接对象时出错 -> ",err)
|
||||||
}else{
|
}else{
|
||||||
b.BlogRelease = doc.Release
|
b.BlogRelease = doc.Release
|
||||||
|
@ -127,7 +130,79 @@ func (b *Blog) IsExist(identify string) bool {
|
||||||
|
|
||||||
return o.QueryTable(b.TableNameWithPrefix()).Filter("blog_identify",identify).Exist()
|
return o.QueryTable(b.TableNameWithPrefix()).Filter("blog_identify",identify).Exist()
|
||||||
}
|
}
|
||||||
|
//保存文章
|
||||||
|
func (b *Blog) Save(cols ...string) error {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
func (b *Blog) FindToPager() {
|
if b.OrderIndex == 0 {
|
||||||
|
blog := NewBlog()
|
||||||
|
if err :=o.QueryTable(b.TableNameWithPrefix()).OrderBy("-blog_id").One(blog,"blog_id");err == nil{
|
||||||
|
b.OrderIndex = b.BlogId + 1;
|
||||||
|
}else{
|
||||||
|
c,_ := o.QueryTable(b.TableNameWithPrefix()).Count()
|
||||||
|
b.OrderIndex = int(c) + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
b.Version = time.Now().Unix()
|
||||||
|
if b.BlogId > 0 {
|
||||||
|
b.Modified = time.Now()
|
||||||
|
_,err = o.Update(b,cols...)
|
||||||
|
}else{
|
||||||
|
b.Created = time.Now()
|
||||||
|
_,err = o.Insert(b)
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
//分页查询文章列表
|
||||||
|
func (b *Blog) FindToPager(pageIndex, pageSize int,memberId int,status string) (blogList []*Blog, totalCount int, err error) {
|
||||||
|
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
offset := (pageIndex - 1) * pageSize
|
||||||
|
|
||||||
|
query := o.QueryTable(b.TableNameWithPrefix());
|
||||||
|
|
||||||
|
if memberId > 0 {
|
||||||
|
query = query.Filter("member_id",memberId)
|
||||||
|
}
|
||||||
|
if status != "" {
|
||||||
|
query = query.Filter("blog_status",status)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_,err = query.OrderBy("-order_index").Offset(offset).Limit(pageSize).All(&blogList)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if err == orm.ErrNoRows {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
beego.Error("获取文章列表时出错 ->",err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
count,err := query.Count()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
beego.Error("获取文章数量时出错 ->",err)
|
||||||
|
return nil,0,err
|
||||||
|
}
|
||||||
|
totalCount = int(count)
|
||||||
|
for _,blog := range blogList {
|
||||||
|
if blog.BlogType == 1 {
|
||||||
|
blog.Link()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除文章
|
||||||
|
func (b *Blog) Delete(blogId int) error {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
_,err := o.QueryTable(b.TableNameWithPrefix()).Filter("blog_id",blogId).Delete()
|
||||||
|
if err != nil {
|
||||||
|
beego.Error("删除文章失败 ->",err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
|
@ -34,27 +34,36 @@ func (m *AttachmentResult) Find(id int) (*AttachmentResult, error) {
|
||||||
|
|
||||||
m.Attachment = *attach
|
m.Attachment = *attach
|
||||||
|
|
||||||
book := NewBook()
|
if attach.BookId == 0 && attach.DocumentId > 0 {
|
||||||
|
blog := NewBlog()
|
||||||
if e := o.QueryTable(book.TableNameWithPrefix()).Filter("book_id", attach.BookId).One(book, "book_name"); e == nil {
|
if err := o.QueryTable(blog.TableNameWithPrefix()).Filter("blog_id",attach.DocumentId).One(blog,"blog_title");err == nil {
|
||||||
m.BookName = book.BookName
|
m.BookName = blog.BlogTitle
|
||||||
|
}else{
|
||||||
|
m.BookName = "[文章不存在]"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
m.BookName = "[不存在]"
|
book := NewBook()
|
||||||
}
|
|
||||||
doc := NewDocument()
|
|
||||||
|
|
||||||
if e := o.QueryTable(doc.TableNameWithPrefix()).Filter("document_id", attach.DocumentId).One(doc, "document_name"); e == nil {
|
if e := o.QueryTable(book.TableNameWithPrefix()).Filter("book_id", attach.BookId).One(book, "book_name"); e == nil {
|
||||||
m.DocumentName = doc.DocumentName
|
m.BookName = book.BookName
|
||||||
} else {
|
} else {
|
||||||
m.DocumentName = "[不存在]"
|
m.BookName = "[不存在]"
|
||||||
}
|
}
|
||||||
|
doc := NewDocument()
|
||||||
|
|
||||||
|
if e := o.QueryTable(doc.TableNameWithPrefix()).Filter("document_id", attach.DocumentId).One(doc, "document_name"); e == nil {
|
||||||
|
m.DocumentName = doc.DocumentName
|
||||||
|
} else {
|
||||||
|
m.DocumentName = "[不存在]"
|
||||||
|
}
|
||||||
|
}
|
||||||
if attach.CreateAt > 0 {
|
if attach.CreateAt > 0 {
|
||||||
member := NewMember()
|
member := NewMember()
|
||||||
if e := o.QueryTable(member.TableNameWithPrefix()).Filter("member_id", attach.CreateAt).One(member, "account"); e == nil {
|
if e := o.QueryTable(member.TableNameWithPrefix()).Filter("member_id", attach.CreateAt).One(member, "account"); e == nil {
|
||||||
m.Account = member.Account
|
m.Account = member.Account
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m.FileShortSize = filetil.FormatBytes(int64(attach.FileSize))
|
m.FileShortSize = filetil.FormatBytes(int64(attach.FileSize))
|
||||||
m.LocalHttpPath = strings.Replace(m.FilePath, "\\", "/", -1)
|
m.LocalHttpPath = strings.Replace(m.FilePath, "\\", "/", -1)
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@ func init() {
|
||||||
beego.InsertFilter("/book", beego.BeforeRouter, FilterUser)
|
beego.InsertFilter("/book", beego.BeforeRouter, FilterUser)
|
||||||
beego.InsertFilter("/book/*", beego.BeforeRouter, FilterUser)
|
beego.InsertFilter("/book/*", beego.BeforeRouter, FilterUser)
|
||||||
beego.InsertFilter("/api/*", beego.BeforeRouter, FilterUser)
|
beego.InsertFilter("/api/*", beego.BeforeRouter, FilterUser)
|
||||||
|
beego.InsertFilter("/blogs", beego.BeforeRouter,FilterUser)
|
||||||
|
beego.InsertFilter("/blogs/*", beego.BeforeRouter,FilterUser)
|
||||||
|
|
||||||
var FinishRouter = func(ctx *context.Context) {
|
var FinishRouter = func(ctx *context.Context) {
|
||||||
ctx.ResponseWriter.Header().Add("MinDoc-Version", conf.VERSION)
|
ctx.ResponseWriter.Header().Add("MinDoc-Version", conf.VERSION)
|
||||||
|
|
|
@ -65,11 +65,14 @@ func init() {
|
||||||
|
|
||||||
//管理文章的路由
|
//管理文章的路由
|
||||||
beego.Router("/blogs", &controllers.BlogController{},"*:ManageList")
|
beego.Router("/blogs", &controllers.BlogController{},"*:ManageList")
|
||||||
beego.Router("/blogs/setting/:id", &controllers.BlogController{}, "*:ManageSetting")
|
beego.Router("/blogs/setting/?:id", &controllers.BlogController{}, "*:ManageSetting")
|
||||||
beego.Router("/blogs/edit/:id",&controllers.BlogController{}, "*:ManageEdit")
|
beego.Router("/blogs/edit/?:id",&controllers.BlogController{}, "*:ManageEdit")
|
||||||
|
beego.Router("/blogs/delete",&controllers.BlogController{}, "post:ManageDelete")
|
||||||
|
beego.Router("/blogs/upload",&controllers.BlogController{}, "post:Upload")
|
||||||
|
|
||||||
//读文章的路由
|
//读文章的路由
|
||||||
beego.Router("/blog", &controllers.BlogController{}, "*:List")
|
beego.Router("/blog", &controllers.BlogController{}, "*:List")
|
||||||
|
beego.Router("/blog/attach/:id:int/:attach_id:int", &controllers.BlogController{},"get:Download")
|
||||||
beego.Router("/blog/:id",&controllers.BlogController{}, "*:Index")
|
beego.Router("/blog/:id",&controllers.BlogController{}, "*:Index")
|
||||||
|
|
||||||
beego.Router("/api/attach/remove/", &controllers.DocumentController{}, "post:RemoveAttachment")
|
beego.Router("/api/attach/remove/", &controllers.DocumentController{}, "post:RemoveAttachment")
|
||||||
|
|
|
@ -602,6 +602,346 @@ textarea{
|
||||||
.pagination-container .pagination>.active>a, .pagination>.active>a:focus, .pagination>.active>a:hover, .pagination>.active>span, .pagination>.active>span:focus, .pagination>.active>span:hover{
|
.pagination-container .pagination>.active>a, .pagination>.active>a:focus, .pagination>.active>a:hover, .pagination>.active>span, .pagination>.active>span:focus, .pagination>.active>span:hover{
|
||||||
color: #272727;
|
color: #272727;
|
||||||
}
|
}
|
||||||
|
/*************文章相关样式**********/
|
||||||
|
.ui.items>.item>.content>.header {
|
||||||
|
display: inline-block;
|
||||||
|
margin: -.21425em 0 0;
|
||||||
|
font-family: 'PingFang SC','Helvetica Neue','Microsoft YaHei UI','Microsoft YaHei','Noto Sans CJK SC',Sathu,EucrosiaUPC,Arial,Helvetica,sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
color: rgba(0,0,0,.85)
|
||||||
|
}
|
||||||
|
.ui.items>.item {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
margin: 1em 0;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
background: 0 0;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
-webkit-transition: -webkit-box-shadow .1s ease;
|
||||||
|
transition: -webkit-box-shadow .1s ease;
|
||||||
|
transition: box-shadow .1s ease;
|
||||||
|
transition: box-shadow .1s ease,-webkit-box-shadow .1s ease;
|
||||||
|
z-index: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item a {
|
||||||
|
cursor: pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items {
|
||||||
|
margin: 1.5em 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items:first-child {
|
||||||
|
margin-top: 0!important
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items:last-child {
|
||||||
|
margin-bottom: 0!important
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item:after {
|
||||||
|
display: block;
|
||||||
|
content: ' ';
|
||||||
|
height: 0;
|
||||||
|
clear: both;
|
||||||
|
overflow: hidden;
|
||||||
|
visibility: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item:first-child {
|
||||||
|
margin-top: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item:last-child {
|
||||||
|
margin-bottom: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.image {
|
||||||
|
position: relative;
|
||||||
|
-webkit-box-flex: 0;
|
||||||
|
-ms-flex: 0 0 auto;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
display: block;
|
||||||
|
float: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
max-height: '';
|
||||||
|
-ms-flex-item-align: top;
|
||||||
|
align-self: top
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.image>img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
border-radius: .125rem;
|
||||||
|
border: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.image:only-child>img {
|
||||||
|
border-radius: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content {
|
||||||
|
display: block;
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-ms-flex: 1 1 auto;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
background: 0 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
font-size: 1em;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content:after {
|
||||||
|
display: block;
|
||||||
|
content: ' ';
|
||||||
|
height: 0;
|
||||||
|
clear: both;
|
||||||
|
overflow: hidden;
|
||||||
|
visibility: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.image+.content {
|
||||||
|
min-width: 0;
|
||||||
|
width: auto;
|
||||||
|
display: block;
|
||||||
|
margin-left: 0;
|
||||||
|
-ms-flex-item-align: top;
|
||||||
|
align-self: top;
|
||||||
|
padding-left: 1.5em
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content>.header {
|
||||||
|
display: inline-block;
|
||||||
|
margin: -.21425em 0 0;
|
||||||
|
font-family: 'PingFang SC','Helvetica Neue','Microsoft YaHei UI','Microsoft YaHei','Noto Sans CJK SC',Sathu,EucrosiaUPC,Arial,Helvetica,sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
color: rgba(0,0,0,.85)
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content>.header:not(.ui) {
|
||||||
|
font-size: 1.14285714em
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item [class*="left floated"] {
|
||||||
|
float: left
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item [class*="right floated"] {
|
||||||
|
float: right
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item .content img {
|
||||||
|
-ms-flex-item-align: middle;
|
||||||
|
align-self: middle;
|
||||||
|
width: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item .avatar img,.ui.items>.item img.avatar {
|
||||||
|
width: '';
|
||||||
|
height: '';
|
||||||
|
border-radius: 500rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content>.description {
|
||||||
|
margin-top: .6em;
|
||||||
|
max-width: auto;
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: 1.4285em;
|
||||||
|
color: rgba(0,0,0,.87);
|
||||||
|
min-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content p {
|
||||||
|
margin: 0 0 .5em
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content p:last-child {
|
||||||
|
margin-bottom: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item .meta {
|
||||||
|
margin: .5em 0 .5em;
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: 1em;
|
||||||
|
color: rgba(0,0,0,.6)
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item .meta * {
|
||||||
|
margin-right: .3em
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item .meta :last-child {
|
||||||
|
margin-right: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item .meta [class*="right floated"] {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: .3em
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content a:not(.ui) {
|
||||||
|
color: '';
|
||||||
|
-webkit-transition: color .1s ease;
|
||||||
|
transition: color .1s ease
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content a:not(.ui):hover {
|
||||||
|
color: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content>a.header {
|
||||||
|
color: rgba(0,0,0,.85)
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content>a.header:hover {
|
||||||
|
color: #1e70bf
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item .meta>a:not(.ui) {
|
||||||
|
color: rgba(0,0,0,.4)
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item .meta>a:not(.ui):hover {
|
||||||
|
color: rgba(0,0,0,.87)
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content .favorite.icon {
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: .75;
|
||||||
|
-webkit-transition: color .1s ease;
|
||||||
|
transition: color .1s ease
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content .favorite.icon:hover {
|
||||||
|
opacity: 1;
|
||||||
|
color: #ffb70a
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content .active.favorite.icon {
|
||||||
|
color: #ffe623
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content .like.icon {
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: .75;
|
||||||
|
-webkit-transition: color .1s ease;
|
||||||
|
transition: color .1s ease
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content .like.icon:hover {
|
||||||
|
opacity: 1;
|
||||||
|
color: #ff2733
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.content .active.like.icon {
|
||||||
|
color: #ff2733
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item .extra {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
background: 0 0;
|
||||||
|
margin: .5rem 0 0;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 0 0;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
color: rgba(0,0,0,.4);
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
-webkit-transition: color .1s ease;
|
||||||
|
transition: color .1s ease;
|
||||||
|
border-top: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item .extra>* {
|
||||||
|
margin: .25rem .5rem .25rem 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item .extra>[class*="right floated"] {
|
||||||
|
margin: .25rem 0 .25rem .5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item .extra:after {
|
||||||
|
display: block;
|
||||||
|
content: ' ';
|
||||||
|
height: 0;
|
||||||
|
clear: both;
|
||||||
|
overflow: hidden;
|
||||||
|
visibility: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.items>.item>.image:not(.ui) {
|
||||||
|
width: 175px
|
||||||
|
}
|
||||||
|
.ui.horizontal.list {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.horizontal.list>.item {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 1em;
|
||||||
|
font-size: 1rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.horizontal.list:not(.celled)>.item:first-child {
|
||||||
|
margin-left: 0!important;
|
||||||
|
padding-left: 0!important
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.horizontal.list .list {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-bottom: 0
|
||||||
|
}
|
||||||
|
.ui.horizontal.list a{
|
||||||
|
color: rgba(0,0,0,.4);
|
||||||
|
}
|
||||||
|
.ui.horizontal.list a:hover {
|
||||||
|
color: rgba(0,0,0,.87)
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.horizontal.list .list>.item>.content,.ui.horizontal.list .list>.item>.icon,.ui.horizontal.list .list>.item>.image,.ui.horizontal.list>.item>.content,.ui.horizontal.list>.item>.icon,.ui.horizontal.list>.item>.image {
|
||||||
|
vertical-align: middle
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.horizontal.list>.item:first-child,.ui.horizontal.list>.item:last-child {
|
||||||
|
padding-top: .21428571em;
|
||||||
|
padding-bottom: .21428571em
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.horizontal.list>.item>i.icon {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 .25em 0 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.horizontal.list>.item>.icon,.ui.horizontal.list>.item>.icon+.content {
|
||||||
|
float: none;
|
||||||
|
display: inline-block
|
||||||
|
}
|
||||||
|
.ui.teal.label {
|
||||||
|
background-color: #00b5ad!important;
|
||||||
|
border-color: #00b5ad!important;
|
||||||
|
color: #fff!important
|
||||||
|
}
|
||||||
|
.ui.items>.item {
|
||||||
|
border-bottom: 1px solid #efefef;
|
||||||
|
margin: 0;
|
||||||
|
padding: 1em 0
|
||||||
|
}
|
||||||
|
|
||||||
/**************网站底部样式*************************/
|
/**************网站底部样式*************************/
|
||||||
.footer{
|
.footer{
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
$(function () {
|
||||||
|
editormd.katexURL = {
|
||||||
|
js : window.baseUrl + "/static/katex/katex",
|
||||||
|
css : window.baseUrl + "/static/katex/katex"
|
||||||
|
};
|
||||||
|
window.editor = editormd("docEditor", {
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
path: window.baseUrl + "/static/editor.md/lib/",
|
||||||
|
toolbar: true,
|
||||||
|
placeholder: "本编辑器支持 Markdown 编辑,左边编写,右边预览。",
|
||||||
|
imageUpload: true,
|
||||||
|
imageFormats: ["jpg", "jpeg", "gif", "png", "JPG", "JPEG", "GIF", "PNG"],
|
||||||
|
imageUploadURL: window.imageUploadURL,
|
||||||
|
toolbarModes: "full",
|
||||||
|
fileUpload: true,
|
||||||
|
fileUploadURL: window.fileUploadURL,
|
||||||
|
taskList: true,
|
||||||
|
flowChart: true,
|
||||||
|
htmlDecode: "style,script,iframe,title,onmouseover,onmouseout,style",
|
||||||
|
lineNumbers: false,
|
||||||
|
sequenceDiagram: true,
|
||||||
|
tocStartLevel: 1,
|
||||||
|
tocm: true,
|
||||||
|
tex:true,
|
||||||
|
saveHTMLToTextarea: true,
|
||||||
|
|
||||||
|
onload: function() {
|
||||||
|
this.hideToolbar();
|
||||||
|
var keyMap = {
|
||||||
|
"Ctrl-S": function(cm) {
|
||||||
|
saveBlog(false);
|
||||||
|
},
|
||||||
|
"Cmd-S": function(cm){
|
||||||
|
saveBlog(false);
|
||||||
|
},
|
||||||
|
"Ctrl-A": function(cm) {
|
||||||
|
cm.execCommand("selectAll");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.addKeyMap(keyMap);
|
||||||
|
|
||||||
|
|
||||||
|
uploadImage("docEditor", function ($state, $res) {
|
||||||
|
if ($state === "before") {
|
||||||
|
return layer.load(1, {
|
||||||
|
shade: [0.1, '#fff'] // 0.1 透明度的白色背景
|
||||||
|
});
|
||||||
|
} else if ($state === "success") {
|
||||||
|
if ($res.errcode === 0) {
|
||||||
|
var value = '![](' + $res.url + ')';
|
||||||
|
window.editor.insertValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onchange: function () {
|
||||||
|
resetEditorChanged(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
* 实现标题栏操作
|
||||||
|
*/
|
||||||
|
$("#editormd-tools").on("click", "a[class!='disabled']", function () {
|
||||||
|
var name = $(this).find("i").attr("name");
|
||||||
|
if (name === "attachment") {
|
||||||
|
$("#uploadAttachModal").modal("show");
|
||||||
|
}else if (name === "save") {
|
||||||
|
saveBlog(false);
|
||||||
|
} else if (name === "template") {
|
||||||
|
$("#documentTemplateModal").modal("show");
|
||||||
|
} else if (name === "tasks") {
|
||||||
|
// 插入 GFM 任务列表
|
||||||
|
var cm = window.editor.cm;
|
||||||
|
var selection = cm.getSelection();
|
||||||
|
|
||||||
|
if (selection === "") {
|
||||||
|
cm.replaceSelection("- [x] " + selection);
|
||||||
|
} else {
|
||||||
|
var selectionText = selection.split("\n");
|
||||||
|
|
||||||
|
for (var i = 0, len = selectionText.length; i < len; i++) {
|
||||||
|
selectionText[i] = (selectionText[i] === "") ? "" : "- [x] " + selectionText[i];
|
||||||
|
}
|
||||||
|
cm.replaceSelection(selectionText.join("\n"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var action = window.editor.toolbarHandlers[name];
|
||||||
|
|
||||||
|
if (action !== "undefined") {
|
||||||
|
$.proxy(action, window.editor)();
|
||||||
|
window.editor.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存文章
|
||||||
|
* @param $is_cover
|
||||||
|
*/
|
||||||
|
function saveBlog($is_cover) {
|
||||||
|
var content = window.editor.getMarkdown();
|
||||||
|
var html = window.editor.getPreviewedHTML();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
beforeSend: function () {
|
||||||
|
index = layer.load(1, { shade: [0.1, '#fff'] });
|
||||||
|
},
|
||||||
|
url: window.editURL,
|
||||||
|
data: { "blogId": window.blogId,"content": content,"htmlContent": html, "cover": $is_cover ? "yes" : "no","version" : window.blogVersion},
|
||||||
|
type: "post",
|
||||||
|
timeout : 30000,
|
||||||
|
dataType: "json",
|
||||||
|
success: function ($res) {
|
||||||
|
layer.close(index);
|
||||||
|
if ($res.errcode === 0) {
|
||||||
|
resetEditorChanged(false);
|
||||||
|
window.blogVersion = $res.data.version;
|
||||||
|
console.log(window.blogVersion);
|
||||||
|
} else if($res.errcode === 6005) {
|
||||||
|
var confirmIndex = layer.confirm('文档已被其他人修改确定覆盖已存在的文档吗?', {
|
||||||
|
btn: ['确定', '取消'] // 按钮
|
||||||
|
}, function() {
|
||||||
|
layer.close(confirmIndex);
|
||||||
|
saveBlog(true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
layer.msg(res.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error : function (XMLHttpRequest, textStatus, errorThrown) {
|
||||||
|
layer.close(index);
|
||||||
|
layer.msg("服务器错误:" + errorThrown);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 设置编辑器变更状态
|
||||||
|
* @param $is_change
|
||||||
|
*/
|
||||||
|
function resetEditorChanged($is_change) {
|
||||||
|
if ($is_change && !window.isLoad) {
|
||||||
|
$("#markdown-save").removeClass('disabled').addClass('change');
|
||||||
|
} else {
|
||||||
|
$("#markdown-save").removeClass('change').addClass('disabled');
|
||||||
|
}
|
||||||
|
window.isLoad = false;
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,301 @@
|
||||||
|
<!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>
|
||||||
|
<script type="text/javascript">
|
||||||
|
window.baseUrl = "{{.BaseUrl}}";
|
||||||
|
window.editor = null;
|
||||||
|
window.editURL = "{{urlfor "BlogController.ManageEdit" "blogId" .Model.BlogId}}";
|
||||||
|
window.imageUploadURL = "{{urlfor "BlogController.Upload" "blogId" .Model.BlogId}}";
|
||||||
|
window.fileUploadURL = "";
|
||||||
|
window.blogId = {{.Model.BlogId}};
|
||||||
|
window.blogVersion = {{.Model.Version}};
|
||||||
|
window.removeAttachURL = "{{urlfor "DocumentController.RemoveAttachment"}}";
|
||||||
|
</script>
|
||||||
|
<!-- Bootstrap -->
|
||||||
|
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet">
|
||||||
|
<link href="{{cdncss "/static/font-awesome/css/font-awesome.min.css"}}" rel="stylesheet">
|
||||||
|
<link href="{{cdncss "/static/jstree/3.3.4/themes/default/style.min.css"}}" rel="stylesheet">
|
||||||
|
<link href="{{cdncss "/static/editor.md/css/editormd.css"}}" rel="stylesheet">
|
||||||
|
|
||||||
|
<link href="{{cdncss "/static/css/jstree.css"}}" rel="stylesheet">
|
||||||
|
<link href="{{cdncss "/static/highlight/styles/vs.css"}}" rel="stylesheet">
|
||||||
|
<link href="{{cdncss "/static/webuploader/webuploader.css"}}" rel="stylesheet">
|
||||||
|
<link href="{{cdncss "/static/css/markdown.css"}}" rel="stylesheet">
|
||||||
|
<link href="{{cdncss "/static/prettify/themes/prettify.css"}}" rel="stylesheet">
|
||||||
|
<link href="{{cdncss "/static/css/markdown.preview.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="/static/html5shiv/3.7.3/html5shiv.min.js"></script>
|
||||||
|
<script src="/static/respond.js/1.4.2/respond.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="m-manual manual-editor">
|
||||||
|
<div class="manual-head" id="editormd-tools" style="min-width: 1200px; position:absolute;">
|
||||||
|
<div class="editormd-group">
|
||||||
|
<a href="{{urlfor "BlogController.ManageList"}}" data-toggle="tooltip" data-title="返回"><i class="fa fa-chevron-left" aria-hidden="true"></i></a>
|
||||||
|
</div>
|
||||||
|
<div class="editormd-group">
|
||||||
|
<a href="javascript:;" id="markdown-save" data-toggle="tooltip" data-title="保存" class="disabled save"><i class="fa fa-save" aria-hidden="true" name="save"></i></a>
|
||||||
|
</div>
|
||||||
|
<div class="editormd-group">
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="撤销 (Ctrl-Z)"><i class="fa fa-undo first" name="undo" unselectable="on"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="重做 (Ctrl-Y)"><i class="fa fa-repeat last" name="redo" unselectable="on"></i></a>
|
||||||
|
</div>
|
||||||
|
<div class="editormd-group">
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="粗体"><i class="fa fa-bold first" name="bold" unselectable="on"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="斜体"><i class="fa fa-italic item" name="italic" unselectable="on"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="删除线"><i class="fa fa-strikethrough last" name="del" unselectable="on"></i></a>
|
||||||
|
</div>
|
||||||
|
<div class="editormd-group">
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="标题一"><i class="fa editormd-bold first" name="h1" unselectable="on">H1</i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="标题二"><i class="fa editormd-bold item" name="h2" unselectable="on">H2</i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="标题三"><i class="fa editormd-bold item" name="h3" unselectable="on">H3</i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="标题四"><i class="fa editormd-bold item" name="h4" unselectable="on">H4</i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="标题五"><i class="fa editormd-bold item" name="h5" unselectable="on">H5</i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="标题六"><i class="fa editormd-bold last" name="h6" unselectable="on">H6</i></a>
|
||||||
|
</div>
|
||||||
|
<div class="editormd-group">
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="无序列表"><i class="fa fa-list-ul first" name="list-ul" unselectable="on"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="有序列表"><i class="fa fa-list-ol item" name="list-ol" unselectable="on"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="横线"><i class="fa fa-minus last" name="hr" unselectable="on"></i></a>
|
||||||
|
</div>
|
||||||
|
<div class="editormd-group">
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="链接"><i class="fa fa-link first" name="link" unselectable="on"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="引用链接"><i class="fa fa-anchor item" name="reference-link" unselectable="on"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="添加图片"><i class="fa fa-picture-o item" name="image" unselectable="on"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="行内代码"><i class="fa fa-code item" name="code" unselectable="on"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="代码块" unselectable="on"><i class="fa fa-file-code-o item" name="code-block" unselectable="on"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="添加表格"><i class="fa fa-table item" name="table" unselectable="on"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="引用"><i class="fa fa-quote-right item" name="quote" unselectable="on"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="GFM 任务列表"><i class="fa fa-tasks item" name="tasks" aria-hidden="true"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="附件"><i class="fa fa-paperclip item" aria-hidden="true" name="attachment"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="模板"><i class="fa fa-tachometer last" name="template"></i></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="editormd-group pull-right">
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="关闭实时预览"><i class="fa fa-eye-slash first" name="watch" unselectable="on"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="使用帮助"><i class="fa fa-question-circle-o last" aria-hidden="true" name="help"></i></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="editormd-group">
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title=""></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title=""></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
</div>
|
||||||
|
<div class="manual-body">
|
||||||
|
<div class="manual-editor-container" id="manualEditorContainer" style="min-width: 920px;left: 0;">
|
||||||
|
<div class="manual-editormd">
|
||||||
|
<div id="docEditor" class="manual-editormd-active"><textarea style="display:none;">{{.Model.BlogContent}}</textarea></div>
|
||||||
|
</div>
|
||||||
|
<div class="manual-editor-status">
|
||||||
|
<div id="attachInfo" class="item">0 个附件</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Modal -->
|
||||||
|
|
||||||
|
<div class="modal fade" id="uploadAttachModal" tabindex="-1" role="dialog" aria-labelledby="uploadAttachModalLabel">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<form method="post" id="uploadAttachModalForm" class="form-horizontal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
|
<h4 class="modal-title" id="myModalLabel">上传附件</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="attach-drop-panel">
|
||||||
|
<div class="upload-container" id="filePicker"><i class="fa fa-upload" aria-hidden="true"></i></div>
|
||||||
|
</div>
|
||||||
|
<div class="attach-list" id="attachList">
|
||||||
|
<template v-for="item in lists">
|
||||||
|
<div class="attach-item" :id="item.attachment_id">
|
||||||
|
<template v-if="item.state == 'wait'">
|
||||||
|
<div class="progress">
|
||||||
|
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100">
|
||||||
|
<span class="sr-only">0% Complete (success)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="item.state == 'error'">
|
||||||
|
<span class="error-message">${item.message}</span>
|
||||||
|
<button type="button" class="btn btn-sm close" @click="removeAttach(item.attachment_id)">
|
||||||
|
<i class="fa fa-remove" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<a :href="item.http_path" target="_blank" :title="item.file_name">${item.file_name}</a>
|
||||||
|
<span class="text">(${ formatBytes(item.file_size) })</span>
|
||||||
|
<span class="error-message">${item.message}</span>
|
||||||
|
<button type="button" class="btn btn-sm close" @click="removeAttach(item.attachment_id)">
|
||||||
|
<i class="fa fa-remove" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<span id="add-error-message" class="error-message"></span>
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||||||
|
<button type="button" class="btn btn-primary" id="btnUploadAttachFile" data-dismiss="modal">确定</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Modal -->
|
||||||
|
|
||||||
|
|
||||||
|
<div class="modal fade" id="documentTemplateModal" tabindex="-1" role="dialog" aria-labelledby="请选择模板类型" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title" id="modal-title">请选择模板类型</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body template-list">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section">
|
||||||
|
<a data-type="normal" href="javascript:;"><i class="fa fa-file-o"></i></a>
|
||||||
|
<h3><a data-type="normal" href="javascript:;">普通文档</a></h3>
|
||||||
|
<ul>
|
||||||
|
<li>默认类型</li>
|
||||||
|
<li>简单的文本文档</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="section">
|
||||||
|
<a data-type="api" href="javascript:;"><i class="fa fa-file-code-o"></i></a>
|
||||||
|
<h3><a data-type="api" href="javascript:;">API文档</a></h3>
|
||||||
|
<ul>
|
||||||
|
<li>用于API文档速写</li>
|
||||||
|
<li>支持代码高亮</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="section">
|
||||||
|
<a data-type="code" href="javascript:;"><i class="fa fa-book"></i></a>
|
||||||
|
|
||||||
|
<h3><a data-type="code" href="javascript:;">数据字典</a></h3>
|
||||||
|
<ul>
|
||||||
|
<li>用于数据字典显示</li>
|
||||||
|
<li>表格支持</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template id="template-normal">
|
||||||
|
{{template "document/template_normal.tpl"}}
|
||||||
|
</template>
|
||||||
|
<template id="template-api">
|
||||||
|
{{template "document/template_api.tpl"}}
|
||||||
|
</template>
|
||||||
|
<template id="template-code">
|
||||||
|
{{template "document/template_code.tpl"}}
|
||||||
|
</template>
|
||||||
|
<script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}"></script>
|
||||||
|
<script src="{{cdnjs "/static/vuejs/vue.min.js"}}" type="text/javascript"></script>
|
||||||
|
<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}"></script>
|
||||||
|
<script src="{{cdnjs "/static/webuploader/webuploader.min.js"}}" type="text/javascript"></script>
|
||||||
|
<script src="{{cdnjs "/static/jstree/3.3.4/jstree.min.js"}}" type="text/javascript"></script>
|
||||||
|
<script src="{{cdnjs "/static/editor.md/editormd.js"}}" type="text/javascript"></script>
|
||||||
|
<script src="{{cdnjs "/static/layer/layer.js"}}" type="text/javascript" ></script>
|
||||||
|
<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
|
||||||
|
<script src="{{cdnjs "/static/js/editor.js"}}" type="text/javascript"></script>
|
||||||
|
<script src="{{cdnjs "/static/js/blog.js"}}" type="text/javascript"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function () {
|
||||||
|
|
||||||
|
$("#attachInfo").on("click",function () {
|
||||||
|
$("#uploadAttachModal").modal("show");
|
||||||
|
});
|
||||||
|
window.uploader = null;
|
||||||
|
|
||||||
|
$("#uploadAttachModal").on("shown.bs.modal",function () {
|
||||||
|
if(window.uploader === null){
|
||||||
|
try {
|
||||||
|
window.uploader = WebUploader.create({
|
||||||
|
auto: true,
|
||||||
|
dnd : true,
|
||||||
|
swf: '{{.BaseUrl}}/static/webuploader/Uploader.swf',
|
||||||
|
server: '{{urlfor "BlogController.Upload"}}',
|
||||||
|
formData : { "blogId" : {{.Model.BlogId}}},
|
||||||
|
pick: "#filePicker",
|
||||||
|
fileVal : "editormd-file-file",
|
||||||
|
fileNumLimit : 1,
|
||||||
|
compress : false
|
||||||
|
}).on("beforeFileQueued",function (file) {
|
||||||
|
uploader.reset();
|
||||||
|
}).on( 'fileQueued', function( file ) {
|
||||||
|
var item = {
|
||||||
|
state : "wait",
|
||||||
|
attachment_id : file.id,
|
||||||
|
file_size : file.size,
|
||||||
|
file_name : file.name,
|
||||||
|
message : "正在上传"
|
||||||
|
};
|
||||||
|
window.vueApp.lists.splice(0,0,item);
|
||||||
|
|
||||||
|
}).on("uploadError",function (file,reason) {
|
||||||
|
for(var i in window.vueApp.lists){
|
||||||
|
var item = window.vueApp.lists[i];
|
||||||
|
if(item.attachment_id == file.id){
|
||||||
|
item.state = "error";
|
||||||
|
item.message = "上传失败";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}).on("uploadSuccess",function (file, res) {
|
||||||
|
|
||||||
|
for(var index in window.vueApp.lists){
|
||||||
|
var item = window.vueApp.lists[index];
|
||||||
|
if(item.attachment_id === file.id){
|
||||||
|
if(res.errcode === 0) {
|
||||||
|
window.vueApp.lists.splice(index, 1, res.attach);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
item.message = res.message;
|
||||||
|
item.state = "error";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}).on("beforeFileQueued",function (file) {
|
||||||
|
|
||||||
|
}).on("uploadComplete",function () {
|
||||||
|
|
||||||
|
}).on("uploadProgress",function (file, percentage) {
|
||||||
|
var $li = $( '#'+file.id ),
|
||||||
|
$percent = $li.find('.progress .progress-bar');
|
||||||
|
|
||||||
|
$percent.css( 'width', percentage * 100 + '%' );
|
||||||
|
});
|
||||||
|
}catch(e){
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -36,167 +36,69 @@
|
||||||
<div class="box-head">
|
<div class="box-head">
|
||||||
<strong class="box-title">文章列表</strong>
|
<strong class="box-title">文章列表</strong>
|
||||||
|
|
||||||
<button type="button" data-toggle="modal" data-target="#addBlogDialogModal" class="btn btn-success btn-sm pull-right">添加文章</button>
|
<a href="{{urlfor "BlogController.ManageSetting"}}" class="btn btn-success btn-sm pull-right">添加文章</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body" id="bookList">
|
<div class="box-body" id="blogList">
|
||||||
<div class="book-list">
|
<div class="ui items">
|
||||||
<template v-if="lists.length <= 0">
|
{{range $index,$item := .ModelList}}
|
||||||
<div class="text-center">暂无数据</div>
|
<div class="item blog-item">
|
||||||
</template>
|
<div class="content">
|
||||||
<template v-else>
|
<a class="header" href="{{urlfor "BlogController.Index" ":id" $item.BlogId}}" target="_blank">
|
||||||
|
{{if eq $item.BlogStatus "password"}}
|
||||||
<div class="list-item" v-for="item in lists">
|
<div class="ui teal label horizontal" data-tooltip="加密">密</div>
|
||||||
<div class="book-title">
|
{{end}}
|
||||||
<div class="pull-left">
|
{{$item.BlogTitle}}
|
||||||
<a :href="'{{.BaseUrl}}/book/' + item.identify + '/dashboard'" title="项目概要" data-toggle="tooltip">
|
</a>
|
||||||
<template v-if="item.privately_owned == 0">
|
<div class="description">
|
||||||
<i class="fa fa-unlock" aria-hidden="true"></i>
|
<p class="line-clamp">{{$item.BlogExcerpt}} </p>
|
||||||
</template>
|
|
||||||
<template v-else-if="item.privately_owned == 1">
|
|
||||||
<i class="fa fa-lock" aria-hidden="true"></i>
|
|
||||||
</template>
|
|
||||||
${item.book_name}
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="pull-right">
|
<div class="extra">
|
||||||
<div class="btn-group">
|
<div>
|
||||||
<a :href="'{{.BaseUrl}}/book/' + item.identify + '/dashboard'" class="btn btn-default">设置</a>
|
<div class="ui horizontal small list">
|
||||||
|
<div class="item"><i class="fa fa-clock-o"></i> {{date $item.Modified "Y-m-d H:i:s"}}</div>
|
||||||
<a href="javascript:;" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<div class="item"><a href="{{urlfor "BlogController.ManageEdit" ":id" $item.BlogId}}" title="文章编辑"><i class="fa fa-edit"></i> 编辑</a></div>
|
||||||
<span class="caret"></span>
|
<div class="item"><a class="delete-btn" title="删除文章" data-id="{{$item.BlogId}}"><i class="fa fa-trash"></i> 删除</a></div>
|
||||||
<span class="sr-only">Toggle Dropdown</span>
|
<div class="item"><a href="{{urlfor "BlogController.ManageSetting" ":id" $item.BlogId}}" title="文章设置" class="setting-btn"><i class="fa fa-gear"></i> 设置</a></div>
|
||||||
</a>
|
</div>
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<li><a :href="'{{urlfor "DocumentController.Index" ":key" ""}}' + item.identify" target="_blank">阅读</a></li>
|
|
||||||
<template v-if="item.role_id != 3">
|
|
||||||
<li><a :href="'{{.BaseUrl}}/api/' + item.identify + '/edit'" target="_blank">编辑</a></li>
|
|
||||||
</template>
|
|
||||||
<template v-if="item.role_id == 0">
|
|
||||||
<li><a :href="'javascript:deleteBook(\''+item.identify+'\');'">删除</a></li>
|
|
||||||
<li><a :href="'javascript:copyBook(\''+item.identify+'\');'">复制</a></li>
|
|
||||||
</template>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{/*<a :href="'{{urlfor "DocumentController.Index" ":key" ""}}' + item.identify" title="查看文档" data-toggle="tooltip" target="_blank"><i class="fa fa-eye"></i> 查看文档</a>*/}}
|
|
||||||
{{/*<template v-if="item.role_id != 3">*/}}
|
|
||||||
{{/*<a :href="'/api/' + item.identify + '/edit'" title="编辑文档" data-toggle="tooltip" target="_blank"><i class="fa fa-edit" aria-hidden="true"></i> 编辑文档</a>*/}}
|
|
||||||
{{/*</template>*/}}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfix"></div>
|
|
||||||
</div>
|
|
||||||
<div class="desc-text">
|
|
||||||
<template v-if="item.description === ''">
|
|
||||||
|
|
||||||
</template>
|
|
||||||
<template v-else="">
|
|
||||||
<a :href="'{{.BaseUrl}}/book/' + item.identify + '/dashboard'" title="项目概要" style="font-size: 12px;">
|
|
||||||
${item.description}
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
<span title="创建时间" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-clock-o"></i>
|
|
||||||
${(new Date(item.create_time)).format("yyyy-MM-dd hh:mm:ss")}
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<span title="创建者" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-user"></i> ${item.create_name}</span>
|
|
||||||
<span title="文档数量" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pie-chart"></i> ${item.doc_count}</span>
|
|
||||||
<span title="项目角色" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-user-secret"></i> ${item.role_name}</span>
|
|
||||||
<template v-if="item.last_modify_text !== ''">
|
|
||||||
<span title="最后编辑" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pencil"></i> 最后编辑: ${item.last_modify_text}</span>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
{{else}}
|
||||||
|
<div class="text-center">暂无文章</div>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<template v-if="lists.length >= 0">
|
<nav class="pagination-container">
|
||||||
<nav class="pagination-container">
|
|
||||||
{{.PageHtml}}
|
{{.PageHtml}}
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{template "widgets/footer.tpl" .}}
|
{{template "widgets/footer.tpl" .}}
|
||||||
</div>
|
</div>
|
||||||
<!-- Modal -->
|
|
||||||
<div class="modal fade" id="addBlogDialogModal" tabindex="-1" role="dialog" aria-labelledby="addBlogDialogModalLabel">
|
|
||||||
<div class="modal-dialog modal-lg" role="document" style="min-width: 900px;">
|
|
||||||
<form method="post" autocomplete="off" action="{{urlfor "BookController.Create"}}" id="addBookDialogForm" enctype="multipart/form-data">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
|
||||||
<h4 class="modal-title" id="myModalLabel">添加文章</h4>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="pull-left">
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="text" class="form-control" placeholder="标题(不超过100字)" name="book_name" id="bookName">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="pull-left" style="padding: 7px 5px 6px 0">
|
|
||||||
{{urlfor "DocumentController.Index" ":key" ""}}
|
|
||||||
</div>
|
|
||||||
<input type="text" class="form-control pull-left" style="width: 410px;vertical-align: middle" placeholder="项目唯一标识(不超过50字)" name="identify" id="identify">
|
|
||||||
<div class="clearfix"></div>
|
|
||||||
<p class="text" style="font-size: 12px;color: #999;margin-top: 6px;">文档标识只能包含小写字母、数字,以及“-”、“.”和“_”符号.</p>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<textarea name="description" id="description" class="form-control" placeholder="描述信息不超过500个字符" style="height: 90px;"></textarea>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<label>
|
|
||||||
<input type="radio" name="privately_owned" value="0" checked> 公开<span class="text">(任何人都可以访问)</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<label>
|
|
||||||
<input type="radio" name="privately_owned" value="1"> 私有<span class="text">(只要参与者或使用令牌才能访问)</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="clearfix"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="clearfix"></div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<span id="form-error-message"></span>
|
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
|
||||||
<button type="button" class="btn btn-success" id="btnSaveDocument" data-loading-text="保存中...">保存</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!--END Modal-->
|
|
||||||
|
|
||||||
<!-- Delete Book Modal -->
|
<!-- Delete Book Modal -->
|
||||||
<div class="modal fade" id="deleteBookModal" tabindex="-1" role="dialog" aria-labelledby="deleteBookModalLabel">
|
<div class="modal fade" id="deleteBlogModal" tabindex="-1" role="dialog" aria-labelledby="deleteBlogModalLabel">
|
||||||
<div class="modal-dialog" role="document">
|
<div class="modal-dialog" role="document">
|
||||||
<form method="post" id="deleteBookForm" action="{{urlfor "BookController.Delete"}}">
|
<form method="post" id="deleteBlogForm" action="{{urlfor "BlogController.ManageDelete"}}">
|
||||||
<input type="hidden" name="identify" value="">
|
<input type="hidden" name="blog_id" value="">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
<h4 class="modal-title">删除项目</h4>
|
<h4 class="modal-title">删除文章</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<span style="font-size: 14px;font-weight: 400;">确定删除项目吗?</span>
|
<span style="font-size: 14px;font-weight: 400;">确定删除文章吗?</span>
|
||||||
<p></p>
|
<p></p>
|
||||||
<p class="text error-message">删除项目后将无法找回。</p>
|
<p class="text error-message">删除文章后将无法找回。</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<span id="form-error-message2" class="error-message"></span>
|
<span id="form-error-message2" class="error-message"></span>
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||||||
<button type="submit" id="btnDeleteBook" class="btn btn-primary" data-loading-text="删除中...">确定删除</button>
|
<button type="submit" id="btnDeleteBlog" class="btn btn-primary" data-loading-text="删除中...">确定删除</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -212,98 +114,13 @@
|
||||||
<script src="{{cdnjs "/static/layer/layer.js"}}" type="text/javascript" ></script>
|
<script src="{{cdnjs "/static/layer/layer.js"}}" type="text/javascript" ></script>
|
||||||
<script src="{{cdnjs "/static/js/main.js"}}" type="text/javascript"></script>
|
<script src="{{cdnjs "/static/js/main.js"}}" type="text/javascript"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
/**
|
|
||||||
* 绘制项目封面
|
|
||||||
* @param $id
|
|
||||||
* @param $font
|
|
||||||
*/
|
|
||||||
function drawBookCover($id,$font) {
|
|
||||||
var draw = document.getElementById($id);
|
|
||||||
//确认浏览器是否支持<canvas>元素
|
|
||||||
if (draw.getContext) {
|
|
||||||
var context = draw.getContext('2d');
|
|
||||||
|
|
||||||
//绘制红色矩形,绿色描边
|
|
||||||
context.fillStyle = '#eee';
|
|
||||||
context.strokeStyle = '#d4d4d5';
|
|
||||||
context.strokeRect(0,0,170,230);
|
|
||||||
context.fillRect(0,0,170,230);
|
|
||||||
|
|
||||||
//设置字体样式
|
|
||||||
context.font = "bold 20px SimSun";
|
|
||||||
context.textAlign = "left";
|
|
||||||
//设置字体填充颜色
|
|
||||||
context.fillStyle = "#3E403E";
|
|
||||||
|
|
||||||
var font = $font;
|
|
||||||
|
|
||||||
var lineWidth = 0; //当前行的绘制的宽度
|
|
||||||
var lastTextIndex = 0; //已经绘制上canvas最后的一个字符的下标
|
|
||||||
var drawWidth = 155,lineHeight = 25,drawStartX = 15,drawStartY=65;
|
|
||||||
//由于改变canvas 的高度会导致绘制的纹理被清空,所以,不预先绘制,先放入到一个数组当中
|
|
||||||
var arr = [];
|
|
||||||
for(var i = 0; i<font.length; i++){
|
|
||||||
//获取当前的截取的字符串的宽度
|
|
||||||
lineWidth = context.measureText(font.substr(lastTextIndex,i-lastTextIndex)).width;
|
|
||||||
|
|
||||||
if(lineWidth > drawWidth){
|
|
||||||
//判断最后一位是否是标点符号
|
|
||||||
if(judgePunctuationMarks(font[i-1])){
|
|
||||||
arr.push(font.substr(lastTextIndex,i-lastTextIndex));
|
|
||||||
lastTextIndex = i;
|
|
||||||
}else{
|
|
||||||
arr.push(font.substr(lastTextIndex,i-lastTextIndex-1));
|
|
||||||
lastTextIndex = i-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//将最后多余的一部分添加到数组
|
|
||||||
if(i === font.length - 1){
|
|
||||||
arr.push(font.substr(lastTextIndex,i-lastTextIndex+1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(var i =0; i<arr.length; i++){
|
|
||||||
context.fillText(arr[i],drawStartX,drawStartY+i*lineHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
//判断是否是需要避开的标签符号
|
|
||||||
function judgePunctuationMarks(value) {
|
|
||||||
var arr = [".",",",";","?","!",":","\"",",","。","?","!",";",":","、"];
|
|
||||||
for(var i = 0; i< arr.length; i++){
|
|
||||||
if(value === arr[i]){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}else{
|
|
||||||
console.log("浏览器不支持")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将base64格式的图片转换为二进制
|
|
||||||
* @param dataURI
|
|
||||||
* @returns {Blob}
|
|
||||||
*/
|
|
||||||
function dataURItoBlob(dataURI) {
|
|
||||||
var byteString = atob(dataURI.split(',')[1]);
|
|
||||||
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
|
|
||||||
var ab = new ArrayBuffer(byteString.length);
|
|
||||||
var ia = new Uint8Array(ab);
|
|
||||||
for (var i = 0; i < byteString.length; i++) {
|
|
||||||
ia[i] = byteString.charCodeAt(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Blob([ab], {type: mimeString});
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* 删除项目
|
* 删除项目
|
||||||
*/
|
*/
|
||||||
function deleteBook($id) {
|
function deleteBlog($id) {
|
||||||
$("#deleteBookModal").find("input[name='identify']").val($id);
|
$("#deleteBlogModal").find("input[name='blog_id']").val($id);
|
||||||
$("#deleteBookModal").modal("show");
|
$("#deleteBlogModal").modal("show");
|
||||||
}
|
}
|
||||||
function copyBook($id){
|
function copyBook($id){
|
||||||
var index = layer.load()
|
var index = layer.load()
|
||||||
|
@ -329,181 +146,30 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
$("#addBookDialogModal").on("show.bs.modal",function () {
|
|
||||||
window.bookDialogModal = $(this).find("#addBookDialogForm").html();
|
|
||||||
drawBookCover("bookCover","默认封面");
|
|
||||||
}).on("hidden.bs.modal",function () {
|
|
||||||
$(this).find("#addBookDialogForm").html(window.bookDialogModal);
|
|
||||||
});
|
|
||||||
/**
|
|
||||||
* 创建项目
|
|
||||||
*/
|
|
||||||
$("body").on("click","#btnSaveDocument",function () {
|
|
||||||
var $this = $(this);
|
|
||||||
|
|
||||||
|
$("#blogList .delete-btn").click(function () {
|
||||||
var bookName = $.trim($("#bookName").val());
|
deleteBlog($(this).attr("data-id"));
|
||||||
if (bookName === "") {
|
|
||||||
return showError("项目标题不能为空")
|
|
||||||
}
|
|
||||||
if (bookName.length > 100) {
|
|
||||||
return showError("项目标题必须小于100字符");
|
|
||||||
}
|
|
||||||
|
|
||||||
var identify = $.trim($("#identify").val());
|
|
||||||
if (identify === "") {
|
|
||||||
return showError("项目标识不能为空");
|
|
||||||
}
|
|
||||||
if (identify.length > 50) {
|
|
||||||
return showError("项目标识必须小于50字符");
|
|
||||||
}
|
|
||||||
var description = $.trim($("#description").val());
|
|
||||||
|
|
||||||
if (description.length > 500) {
|
|
||||||
return showError("描述信息不超过500个字符");
|
|
||||||
}
|
|
||||||
|
|
||||||
$this.button("loading");
|
|
||||||
|
|
||||||
var draw = document.getElementById("bookCover");
|
|
||||||
var form = document.getElementById("addBookDialogForm");
|
|
||||||
var fd = new FormData(form);
|
|
||||||
if (draw.getContext) {
|
|
||||||
var dataURL = draw.toDataURL("png", 100);
|
|
||||||
|
|
||||||
var blob = dataURItoBlob(dataURL);
|
|
||||||
|
|
||||||
fd.append('image-file', blob,(new Date()).valueOf() + ".png");
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url : "{{urlfor "BookController.Create"}}",
|
|
||||||
data: fd,
|
|
||||||
type: "POST",
|
|
||||||
dataType :"json",
|
|
||||||
processData: false,
|
|
||||||
contentType: false
|
|
||||||
}).success(function (res) {
|
|
||||||
$this.button("reset");
|
|
||||||
if (res.errcode === 0) {
|
|
||||||
window.app.lists.splice(0, 0, res.data);
|
|
||||||
$("#addBookDialogModal").modal("hide");
|
|
||||||
} else {
|
|
||||||
showError(res.message);
|
|
||||||
}
|
|
||||||
$this.button("reset");
|
|
||||||
}).error(function () {
|
|
||||||
$this.button("reset");
|
|
||||||
return showError("服务器异常");
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
/**
|
|
||||||
* 当填写项目标题后,绘制项目封面
|
|
||||||
*/
|
|
||||||
$("#bookName").on("blur",function () {
|
|
||||||
var txt = $(this).val();
|
|
||||||
if(txt !== ""){
|
|
||||||
drawBookCover("bookCover",txt);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
/**
|
/**
|
||||||
* 删除项目
|
* 删除项目
|
||||||
*/
|
*/
|
||||||
$("#deleteBookForm").ajaxForm({
|
$("#deleteBookForm").ajaxForm({
|
||||||
beforeSubmit : function () {
|
beforeSubmit : function () {
|
||||||
$("#btnDeleteBook").button("loading");
|
$("#btnDeleteBlog").button("loading");
|
||||||
},
|
},
|
||||||
success : function (res) {
|
success : function ($res) {
|
||||||
if(res.errcode === 0){
|
if($res.errcode === 0){
|
||||||
window.location = window.location.href;
|
window.location = window.location.href;
|
||||||
}else{
|
}else{
|
||||||
showError(res.message,"#form-error-message2");
|
showError(res.message,"#form-error-message2");
|
||||||
}
|
}
|
||||||
$("#btnDeleteBook").button("reset");
|
$("#btnDeleteBlog").button("reset");
|
||||||
},
|
},
|
||||||
error : function () {
|
error : function () {
|
||||||
showError("服务器异常","#form-error-message2");
|
showError("服务器异常","#form-error-message2");
|
||||||
$("#btnDeleteBook").button("reset");
|
$("#btnDeleteBlog").button("reset");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#btnImportBook").on("click",function () {
|
|
||||||
var $this = $(this);
|
|
||||||
var $then = $(this).parents("#importBookDialogForm");
|
|
||||||
|
|
||||||
|
|
||||||
var bookName = $.trim($then.find("input[name='book_name']").val());
|
|
||||||
|
|
||||||
if (bookName === "") {
|
|
||||||
return showError("项目标题不能为空","#import-book-form-error-message");
|
|
||||||
}
|
|
||||||
if (bookName.length > 100) {
|
|
||||||
return showError("项目标题必须小于100字符","#import-book-form-error-message");
|
|
||||||
}
|
|
||||||
|
|
||||||
var identify = $.trim($then.find("input[name='identify']").val());
|
|
||||||
if (identify === "") {
|
|
||||||
return showError("项目标识不能为空","#import-book-form-error-message");
|
|
||||||
}
|
|
||||||
var description = $.trim($then.find('textarea[name="description"]').val());
|
|
||||||
if (description.length > 500) {
|
|
||||||
return showError("描述信息不超过500个字符","#import-book-form-error-message");
|
|
||||||
}
|
|
||||||
var filesCount = $('#import-book-upload').fileinput('getFilesCount');
|
|
||||||
console.log(filesCount)
|
|
||||||
if (filesCount <= 0) {
|
|
||||||
return showError("请选择需要上传的文件","#import-book-form-error-message");
|
|
||||||
}
|
|
||||||
//$("#importBookDialogForm").submit();
|
|
||||||
$("#btnImportBook").button("loading");
|
|
||||||
$('#import-book-upload').fileinput('upload');
|
|
||||||
|
|
||||||
});
|
|
||||||
window.app = new Vue({
|
|
||||||
el : "#bookList",
|
|
||||||
data : {
|
|
||||||
lists : {{.Result}}
|
|
||||||
},
|
|
||||||
delimiters : ['${','}'],
|
|
||||||
methods : {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Vue.nextTick(function () {
|
|
||||||
$("[data-toggle='tooltip']").tooltip();
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#import-book-upload").fileinput({
|
|
||||||
'uploadUrl':"{{urlfor "BookController.Import"}}",
|
|
||||||
'theme': 'fa',
|
|
||||||
'showPreview': false,
|
|
||||||
'showUpload' : false,
|
|
||||||
'required': true,
|
|
||||||
'validateInitialCount': true,
|
|
||||||
"language" : "zh",
|
|
||||||
'allowedFileExtensions': ['zip'],
|
|
||||||
'msgPlaceholder' : '请选择Zip文件',
|
|
||||||
'elErrorContainer' : "#import-book-form-error-message",
|
|
||||||
'uploadExtraData' : function () {
|
|
||||||
var book = {};
|
|
||||||
var $then = $("#importBookDialogForm");
|
|
||||||
book.book_name = $then.find("input[name='book_name']").val();
|
|
||||||
book.identify = $then.find("input[name='identify']").val();
|
|
||||||
book.description = $then.find('textarea[name="description"]').val()
|
|
||||||
|
|
||||||
return book;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$("#import-book-upload").on("fileuploaded",function (event, data, previewId, index){
|
|
||||||
|
|
||||||
if(data.response.errcode === 0 || data.response.errcode === '0'){
|
|
||||||
showSuccess(data.response.message,"#import-book-form-error-message");
|
|
||||||
}else{
|
|
||||||
showError(data.response.message,"#import-book-form-error-message");
|
|
||||||
}
|
|
||||||
$("#btnImportBook").button("reset");
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
<!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">
|
||||||
|
<link href="{{cdncss "/static/font-awesome/css/font-awesome.min.css"}}" rel="stylesheet">
|
||||||
|
<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="/static/html5shiv/3.7.3/html5shiv.min.js"></script>
|
||||||
|
<script src="/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 {{if eq .ControllerName "BookController"}}class="active"{{end}}><a href="{{urlfor "BookController.Index"}}" class="item"><i class="fa fa-sitemap" aria-hidden="true"></i> 我的项目</a> </li>
|
||||||
|
<li {{if eq .ControllerName "BlogController"}}class="active"{{end}}><a href="{{urlfor "BlogController.ManageList"}}" class="item"><i class="fa fa-file" 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">
|
||||||
|
<form method="post" id="gloablEditForm" action="{{urlfor "BlogController.ManageSetting"}}">
|
||||||
|
<input type="hidden" name="id" id="blogId" value="{{.Model.BlogId}}">
|
||||||
|
<input type="hidden" name="identify" value="{{.Model.BlogIdentify}}">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>文章标题</label>
|
||||||
|
<input type="text" class="form-control" name="title" id="title" placeholder="文章标题" value="{{.Model.BlogTitle}}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>文章类型</label>
|
||||||
|
<div class="radio">
|
||||||
|
<label class="radio-inline">
|
||||||
|
<input type="radio" {{if eq .Model.BlogType 0}}checked{{end}} name="blog_type" value="0">普通文章<span class="text"></span>
|
||||||
|
</label>
|
||||||
|
<label class="radio-inline">
|
||||||
|
<input type="radio" {{if eq .Model.BlogType 1}}checked{{end}} name="blog_type" value="1">链接文章<span class="text"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" id="blogLinkDocument"{{if ne .Model.BlogType 1}} style="display: none;" {{end}}>
|
||||||
|
<label>关联文档</label>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="text" class="form-control" placeholder="请选择项目">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="text" class="form-control" placeholder="请选择文档">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>文章状态</label>
|
||||||
|
<div class="radio">
|
||||||
|
<label class="radio-inline">
|
||||||
|
<input type="radio" {{if eq .Model.BlogStatus "public"}}checked{{end}} name="status" value="public">公开<span class="text"></span>
|
||||||
|
</label>
|
||||||
|
<label class="radio-inline">
|
||||||
|
<input type="radio" {{if eq .Model.BlogStatus "password"}}checked{{end}} name="status" value="password">加密<span class="text"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group"{{if eq .Model.BlogStatus "public"}} style="display: none;"{{end}} id="blogPassword">
|
||||||
|
<label>文章密码</label>
|
||||||
|
<input type="password" class="form-control" name="password" id="password" placeholder="文章密码" value="{{.Model.Password}}" maxlength="20">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>文章摘要</label>
|
||||||
|
<textarea rows="3" class="form-control" name="excerpt" style="height: 90px" placeholder="项目描述">{{.Model.BlogExcerpt}}</textarea>
|
||||||
|
<p class="text">文章摘要不超过500个字符</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" id="btnSaveBlogInfo" class="btn btn-success" data-loading-text="保存中...">保存</button>
|
||||||
|
<a href="{{.Referer}}" title="返回" class="btn btn-info">返回</a>
|
||||||
|
<span id="form-error-message" class="error-message"></span>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{template "widgets/footer.tpl" .}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}" type="text/javascript"></script>
|
||||||
|
<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}" type="text/javascript"></script>
|
||||||
|
<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
|
||||||
|
<script src="{{cdnjs "/static/js/main.js"}}" type="text/javascript"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function () {
|
||||||
|
$("#gloablEditForm").ajaxForm({
|
||||||
|
beforeSubmit : function () {
|
||||||
|
var title = $.trim($("#title").val());
|
||||||
|
|
||||||
|
if (title === ""){
|
||||||
|
return showError("文章标题不能为空");
|
||||||
|
}
|
||||||
|
$("#btnSaveBlogInfo").button("loading");
|
||||||
|
},success : function ($res) {
|
||||||
|
if($res.errcode === 0) {
|
||||||
|
showSuccess("保存成功");
|
||||||
|
$("#blogId").val($res.data.blog_id);
|
||||||
|
}else{
|
||||||
|
showError($res.message);
|
||||||
|
}
|
||||||
|
$("#btnSaveBlogInfo").button("reset");
|
||||||
|
}, error : function () {
|
||||||
|
showError("服务器异常.");
|
||||||
|
$("#btnSaveBlogInfo").button("reset");
|
||||||
|
}
|
||||||
|
}).find("input[name='status']").change(function () {
|
||||||
|
var $status = $(this).val();
|
||||||
|
if($status === "password"){
|
||||||
|
$("#blogPassword").show();
|
||||||
|
}else{
|
||||||
|
$("#blogPassword").hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$("#gloablEditForm").find("input[name='blog_type']").change(function () {
|
||||||
|
var $link = $(this).val();
|
||||||
|
if($link == 1){
|
||||||
|
$("#blogLinkDocument").show();
|
||||||
|
}else{
|
||||||
|
$("#blogLinkDocument").hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -55,13 +55,15 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>项目名称</label>
|
<label>项目/文章名称</label>
|
||||||
<input type="text" value="{{.Model.BookName}}" class="form-control input-readonly" readonly placeholder="项目名称">
|
<input type="text" value="{{.Model.BookName}}" class="form-control input-readonly" readonly placeholder="项目名称">
|
||||||
</div>
|
</div>
|
||||||
|
{{if ne .Model.BookId 0}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>文档名称</label>
|
<label>文档名称</label>
|
||||||
<input type="text" value="{{.Model.DocumentName}}" class="form-control input-readonly" readonly placeholder="文档名称">
|
<input type="text" value="{{.Model.DocumentName}}" class="form-control input-readonly" readonly placeholder="文档名称">
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>文件路径</label>
|
<label>文件路径</label>
|
||||||
<input type="text" value="{{.Model.FilePath}}" class="form-control input-readonly" readonly placeholder="文件路径">
|
<input type="text" value="{{.Model.FilePath}}" class="form-control input-readonly" readonly placeholder="文件路径">
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th>#</th>
|
<th>#</th>
|
||||||
<th>附件名称</th>
|
<th>附件名称</th>
|
||||||
<th>项目名称</th>
|
<th>项目/文章名称</th>
|
||||||
<th>文件大小</th>
|
<th>文件大小</th>
|
||||||
<th>是否存在</th>
|
<th>是否存在</th>
|
||||||
<th>操作</th>
|
<th>操作</th>
|
||||||
|
|
Loading…
Reference in New Issue