From c514d0bc1c54dfe1d4f34e1b58e81eba6c353a00 Mon Sep 17 00:00:00 2001 From: life <lifephp@gmail.com> Date: Thu, 8 Jan 2015 21:15:56 +0800 Subject: [PATCH] =?UTF-8?q?Ace=20&=20Markdown=E5=85=A8=E6=96=B0=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=99=A8=20&=20others?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 邀请注册 共享后图片可见问题 fileService::getFile() 笔记历史记录问题 共享后得到被共享者列表问题 shareService themeService 博客主题新建问题, 模板循环引用问题 markdown编辑器双屏大小不能保存问题 --- app/controllers/AttachController.go | 14 +- app/controllers/AuthController.go | 7 +- app/controllers/BaseController.go | 7 +- app/controllers/BlogController.go | 5 +- app/controllers/FileController.go | 92 ++------- app/controllers/PreviewController.go | 2 + .../member/MemberBlogController.go | 187 +++++++++--------- app/controllers/member/init.go | 3 +- app/db/Mgo.go | 15 +- app/lea/Debug.go | 13 +- app/release/release.go | 34 +++- app/service/AuthService.go | 11 +- app/service/FileService.go | 10 + app/service/NoteContentHistoryService.go | 5 +- app/service/ShareService.go | 3 +- app/service/ThemeService.go | 135 ++++++++++++- app/service/UserService.go | 2 +- app/views/errors/500-blog.html | 63 ++++++ app/views/home/register.html | 4 +- app/views/member/blog/add_single.html | 4 +- app/views/member/blog/base.html | 2 +- app/views/member/blog/single.html | 4 +- app/views/member/blog/theme.html | 30 ++- app/views/member/blog/update_theme.html | 2 +- app/views/note/note-dev.html | 158 +++++++++++++-- app/views/note/note.html | 161 +++++++++++++-- 26 files changed, 719 insertions(+), 254 deletions(-) create mode 100644 app/views/errors/500-blog.html diff --git a/app/controllers/AttachController.go b/app/controllers/AttachController.go index 90246d7..d7f2134 100644 --- a/app/controllers/AttachController.go +++ b/app/controllers/AttachController.go @@ -62,7 +62,7 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) { maxFileSize = 1000 } if(float64(len(data)) > maxFileSize * float64(1024*1024)) { - resultMsg = fmt.Sprintf("附件大于%vM", maxFileSize) + resultMsg = fmt.Sprintf("The file's size is bigger than %vM", maxFileSize) return re } @@ -100,11 +100,15 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) { id := bson.NewObjectId(); fileInfo.AttachId = id fileId = id.Hex() - Ok = attachService.AddAttach(fileInfo) + Ok, resultMsg = attachService.AddAttach(fileInfo) + if resultMsg != "" { + resultMsg = c.Message(resultMsg) + } fileInfo.Path = ""; // 不要返回 - resultMsg = "success" - + if Ok { + resultMsg = "success" + } return re } @@ -212,4 +216,4 @@ func (c Attach) DownloadAll(noteId string) revel.Result { // file, _ := os.Open(dir + "/" + filename) // fw.Seek(0, 0) return c.RenderBinary(fw, filename, revel.Attachment, time.Now()) // revel.Attachment -} \ No newline at end of file +} diff --git a/app/controllers/AuthController.go b/app/controllers/AuthController.go index 3814668..8cd0d5b 100644 --- a/app/controllers/AuthController.go +++ b/app/controllers/AuthController.go @@ -91,18 +91,19 @@ func (c Auth) Demo() revel.Result { //-------- // 注册 -func (c Auth) Register(from string) revel.Result { +func (c Auth) Register(from, iu string) revel.Result { if !configService.IsOpenRegister() { return c.Redirect("/index") } c.SetLocale() c.RenderArgs["from"] = from + c.RenderArgs["iu"] = iu c.RenderArgs["title"] = c.Message("register") c.RenderArgs["subTitle"] = c.Message("register") return c.RenderTemplate("home/register.html") } -func (c Auth) DoRegister(email, pwd string) revel.Result { +func (c Auth) DoRegister(email, pwd, iu string) revel.Result { if !configService.IsOpenRegister() { return c.Redirect("/index") } @@ -117,7 +118,7 @@ func (c Auth) DoRegister(email, pwd string) revel.Result { } // 注册 - re.Ok, re.Msg = authService.Register(email, pwd) + re.Ok, re.Msg = authService.Register(email, pwd, iu) // 注册成功, 则立即登录之 if re.Ok { diff --git a/app/controllers/BaseController.go b/app/controllers/BaseController.go index fcef661..e82be4a 100644 --- a/app/controllers/BaseController.go +++ b/app/controllers/BaseController.go @@ -193,12 +193,13 @@ func (c BaseController) SetLocale() string { } // 设置userInfo -func (c BaseController) SetUserInfo() { +func (c BaseController) SetUserInfo() info.User { userInfo := c.GetUserInfo() c.RenderArgs["userInfo"] = userInfo if(userInfo.Username == configService.GetAdminUsername()) { c.RenderArgs["isAdmin"] = true } + return userInfo } // life @@ -224,6 +225,7 @@ func (c BaseController) RenderTemplateStr(templatePath string) string { // 为了msg // msg-v1-v2-v3 func (c BaseController) RenderRe(re info.Re) revel.Result { + oldMsg := re.Msg if re.Msg != "" { if(strings.Contains(re.Msg, "-")) { msgAndValues := strings.Split(re.Msg, "-") @@ -241,5 +243,8 @@ func (c BaseController) RenderRe(re info.Re) revel.Result { re.Msg = c.Message(re.Msg) } } + if strings.HasPrefix(re.Msg, "???") { + re.Msg = oldMsg + } return c.RenderJson(re) } diff --git a/app/controllers/BlogController.go b/app/controllers/BlogController.go index 088ddf8..98c6c36 100644 --- a/app/controllers/BlogController.go +++ b/app/controllers/BlogController.go @@ -57,6 +57,9 @@ func (c Blog) render(templateName string, themePath string) revel.Result { isPreview = true themePath = themePath2.(string) c.setPreviewUrl() + + // 因为common的themeInfo是从UserBlog.ThemeId来取的, 所以这里要fugai下 + c.RenderArgs["themeInfo"] = c.RenderArgs["themeInfoPreview"]; } return blog.RenderTemplate(templateName, c.RenderArgs, revel.BasePath+"/"+themePath, isPreview) } @@ -846,4 +849,4 @@ func (c Blog) ListCateLatest(notebookId, callback string) revel.Result { re.Ok = true re.List = blogs return c.RenderJsonP(callback, re) -} \ No newline at end of file +} diff --git a/app/controllers/FileController.go b/app/controllers/FileController.go index 7e4a4b7..49f4d1e 100644 --- a/app/controllers/FileController.go +++ b/app/controllers/FileController.go @@ -10,7 +10,7 @@ import ( "io/ioutil" "os" "fmt" - "strconv" +// "strconv" "strings" ) @@ -85,7 +85,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) { var fileUrlPath = "" var fileId = "" var resultCode = 0 // 1表示正常 - var resultMsg = "内部错误" // 错误信息 + var resultMsg = "error" // 错误信息 var Ok = false defer func() { @@ -120,7 +120,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) { } else { _, ext = SplitFilename(filename) if(ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg") { - resultMsg = "不是图片" + resultMsg = "Please upload image" return re } } @@ -147,7 +147,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) { // > 2M? if(float64(len(data)) > maxFileSize * float64(1024*1024)) { resultCode = 0 - resultMsg = fmt.Sprintf("图片大于%vM", maxFileSize) + resultMsg = fmt.Sprintf("The file Size is bigger than %vM", maxFileSize) return re } @@ -163,7 +163,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) { filesize := GetFilesize(toPathGif) fileUrlPath += "/" + filename resultCode = 1 - resultMsg = "上传成功!" + resultMsg = "Upload Success!" // File fileInfo := info.File{Name: filename, @@ -178,7 +178,8 @@ func (c File) uploadImage(from, albumId string) (re info.Re) { fileId = "public/upload/" + c.GetUserId() + "/images/logo/" + filename } - Ok = fileService.AddImage(fileInfo, albumId, c.GetUserId()) + Ok, resultMsg = fileService.AddImage(fileInfo, albumId, c.GetUserId(), from == "" || from == "pasteImage") + resultMsg = c.Message(resultMsg) fileInfo.Path = ""; // 不要返回 re.Item = fileInfo @@ -203,55 +204,6 @@ func (c File) DeleteImage(fileId string) revel.Result { re.Ok, re.Msg = fileService.DeleteImage(c.GetUserId(), fileId) return c.RenderJson(re) } - -// update image uploader to leaui image, -// scan all user's images and insert into db -func (c File) UpgradeLeauiImage() revel.Result { - re := info.NewRe() - - if ok, _ := revel.Config.Bool("upgradeLeauiImage"); !ok { - re.Msg = "Not allowed" - return c.RenderJson(re) - } - - uploadPath := revel.BasePath + "/public/upload"; - userIds := ListDir(uploadPath) - if userIds == nil { - re.Msg = "no user" - return c.RenderJson(re) - } - - msg := ""; - - for _, userId := range userIds { - dirPath := uploadPath + "/" + userId + "/images" - images := ListDir(dirPath) - if images == nil { - msg += userId + " no images " - continue; - } - - hadImages := fileService.GetAllImageNamesMap(userId) - - i := 0 - for _, filename := range images { - if _, ok := hadImages[filename]; !ok { - fileUrlPath := "/upload/" + userId + "/images/" + filename - fileInfo := info.File{Name: filename, - Title: filename, - Path: fileUrlPath, - Size: GetFilesize(dirPath + "/" + filename)} - fileService.AddImage(fileInfo, "", userId) - i++ - } - } - msg += userId + ": " + strconv.Itoa(len(images)) + " -- " + strconv.Itoa(i) + " images " - } - - re.Msg = msg - return c.RenderJson(re) -} - //----------- // 输出image @@ -267,15 +219,15 @@ func (c File) OutputImage(noteId, fileId string) revel.Result { } // 协作时复制图片到owner +// 需要计算对方大小 func (c File) CopyImage(userId, fileId, toUserId string) revel.Result { re := info.NewRe() - re.Ok, re.Id = fileService.CopyImage(userId, fileId, toUserId) - return c.RenderJson(re) } // 复制外网的图片, 成公共图片 放在/upload下 +// 都要好好的计算大小 func (c File) CopyHttpImage(src string) revel.Result { re := info.NewRe() fileUrlPath := "upload/" + c.GetUserId() + "/images" @@ -302,29 +254,7 @@ func (c File) CopyHttpImage(src string) revel.Result { re.Id = id.Hex() re.Item = fileInfo.Path - re.Ok = fileService.AddImage(fileInfo, "", c.GetUserId()) + re.Ok, re.Msg = fileService.AddImage(fileInfo, "", c.GetUserId(), true) return c.RenderJson(re) -} - -//------------ -// 过时 已弃用! -func (c File) UploadImage(renderHtml string) revel.Result { - if renderHtml == "" { - renderHtml = "file/image.html" - } - - re := c.uploadImage("", ""); - - c.RenderArgs["fileUrlPath"] = configService.GetSiteUrl() + re.Id - c.RenderArgs["resultCode"] = re.Code - c.RenderArgs["resultMsg"] = re.Msg - - return c.RenderTemplate(renderHtml) -} - -// 已弃用 -func (c File) UploadImageJson(from, noteId string) revel.Result { - re := c.uploadImage(from, ""); - return c.RenderJson(re) -} +} \ No newline at end of file diff --git a/app/controllers/PreviewController.go b/app/controllers/PreviewController.go index 03cfca9..f24afa8 100644 --- a/app/controllers/PreviewController.go +++ b/app/controllers/PreviewController.go @@ -33,6 +33,8 @@ func (c Preview) getPreviewThemeAbsolutePath(themeId string) bool { theme := themeService.GetTheme(c.GetUserId(), themeId) c.RenderArgs["isPreview"] = true + c.RenderArgs["themeId"] = themeId + c.RenderArgs["themeInfoPreview"] = theme.Info c.RenderArgs["themePath"] = theme.Path if theme.Path == "" { return false diff --git a/app/controllers/member/MemberBlogController.go b/app/controllers/member/MemberBlogController.go index 97359b1..2ae4c3e 100644 --- a/app/controllers/member/MemberBlogController.go +++ b/app/controllers/member/MemberBlogController.go @@ -1,15 +1,15 @@ package member import ( - "github.com/revel/revel" - . "github.com/leanote/leanote/app/lea" - "github.com/leanote/leanote/app/info" - "os" - "io/ioutil" - "time" "fmt" + "github.com/leanote/leanote/app/info" + . "github.com/leanote/leanote/app/lea" + "github.com/revel/revel" + "io/ioutil" + "os" "strings" -// "github.com/leanote/leanote/app/lea/blog" + "time" + // "github.com/leanote/leanote/app/lea/blog" ) // 博客管理 @@ -28,35 +28,34 @@ func (c MemberBlog) common() info.UserBlog { userBlog := blogService.GetUserBlog(userId) c.RenderArgs["userBlog"] = userBlog - + c.SetUserInfo() c.SetLocale() return userBlog } - // 得到sorterField 和 isAsc // okSorter = ['email', 'username'] -func (c MemberBlog) getSorter(sorterField string, isAsc bool, okSorter []string) (string, bool){ +func (c MemberBlog) getSorter(sorterField string, isAsc bool, okSorter []string) (string, bool) { sorter := "" c.Params.Bind(&sorter, "sorter") if sorter == "" { - return sorterField, isAsc; + return sorterField, isAsc } - + // sorter形式 email-up, email-down s2 := strings.Split(sorter, "-") if len(s2) != 2 { - return sorterField, isAsc; + return sorterField, isAsc } - + // 必须是可用的sorter if okSorter != nil && len(okSorter) > 0 { if !InArray(okSorter, s2[0]) { - return sorterField, isAsc; + return sorterField, isAsc } } - + sorterField = strings.Title(s2[0]) if s2[1] == "up" { isAsc = true @@ -64,28 +63,29 @@ func (c MemberBlog) getSorter(sorterField string, isAsc bool, okSorter []string) isAsc = false } c.RenderArgs["sorter"] = sorter - return sorterField, isAsc; + return sorterField, isAsc } // 博客列表 var userPageSize = 15 + func (c MemberBlog) Index(sorter, keywords string) revel.Result { userId := c.GetUserId() userInfo := userService.GetUserInfo(userId) c.RenderArgs["userInfo"] = userInfo - + c.RenderArgs["title"] = "Posts" pageNumber := c.GetPage() - sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "urlTitle", "updatedTime", "publicTime", "createdTime"}); - pageInfo, blogs := blogService.ListAllBlogs(c.GetUserId(), "", keywords, false, pageNumber, userPageSize, sorterField, isAsc); + sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "urlTitle", "updatedTime", "publicTime", "createdTime"}) + pageInfo, blogs := blogService.ListAllBlogs(c.GetUserId(), "", keywords, false, pageNumber, userPageSize, sorterField, isAsc) c.RenderArgs["pageInfo"] = pageInfo c.RenderArgs["blogs"] = blogs c.RenderArgs["keywords"] = keywords - + userAndBlog := userService.GetUserAndBlog(c.GetUserId()) c.RenderArgs["userAndBlog"] = userAndBlog - - return c.RenderTemplate("member/blog/list.html"); + + return c.RenderTemplate("member/blog/list.html") } // 修改笔记的urlTitle @@ -95,17 +95,16 @@ func (c MemberBlog) UpdateBlogUrlTitle(noteId, urlTitle string) revel.Result { return c.RenderJson(re) } - // 修改笔记的urlTitle func (c MemberBlog) UpdateBlogAbstract(noteId string) revel.Result { c.RenderArgs["title"] = "Update Post Abstract" - note := noteService.GetNoteAndContent(noteId, c.GetUserId()); + note := noteService.GetNoteAndContent(noteId, c.GetUserId()) if !note.Note.IsBlog { - return c.E404(); + return c.E404() } c.RenderArgs["note"] = note c.RenderArgs["noteId"] = noteId - return c.RenderTemplate("member/blog/update_abstract.html"); + return c.RenderTemplate("member/blog/update_abstract.html") } func (c MemberBlog) DoUpdateBlogAbstract(noteId, imgSrc, desc, abstract string) revel.Result { @@ -118,38 +117,33 @@ func (c MemberBlog) DoUpdateBlogAbstract(noteId, imgSrc, desc, abstract string) func (c MemberBlog) Base() revel.Result { c.common() c.RenderArgs["title"] = "Blog Base Info" - return c.RenderTemplate("member/blog/base.html"); + return c.RenderTemplate("member/blog/base.html") } func (c MemberBlog) Comment() revel.Result { c.common() c.RenderArgs["title"] = "Comment" - return c.RenderTemplate("member/blog/comment.html"); -} -func (c MemberBlog) Domain() revel.Result { - c.common() - c.RenderArgs["title"] = "Domain" - return c.RenderTemplate("member/blog/domain.html"); + return c.RenderTemplate("member/blog/comment.html") } func (c MemberBlog) Paging() revel.Result { c.common() c.RenderArgs["title"] = "Paging" - return c.RenderTemplate("member/blog/paging.html"); + return c.RenderTemplate("member/blog/paging.html") } func (c MemberBlog) Cate() revel.Result { userBlog := c.common() c.RenderArgs["title"] = "Cate" - + notebooks := blogService.ListBlogNotebooks(c.GetUserId()) notebooksMap := map[string]info.Notebook{} for _, each := range notebooks { notebooksMap[each.NotebookId.Hex()] = each } - - var i = 0; + + var i = 0 notebooks2 := make([]info.Notebook, len(notebooks)) - + // 先要保证已有的是正确的排序 cateIds := userBlog.CateIds has := map[string]bool{} // cateIds中有的 @@ -171,8 +165,8 @@ func (c MemberBlog) Cate() revel.Result { } } c.RenderArgs["notebooks"] = notebooks2 - - return c.RenderTemplate("member/blog/cate.html"); + + return c.RenderTemplate("member/blog/cate.html") } // 修改分类排序 @@ -199,9 +193,10 @@ func (c MemberBlog) AddOrUpdateSingle(singleId string) revel.Result { c.RenderArgs["title"] = "Add Single" c.RenderArgs["singleId"] = singleId if singleId != "" { + c.RenderArgs["title"] = "Update Single" c.RenderArgs["single"] = blogService.GetSingle(singleId) } - return c.RenderTemplate("member/blog/add_single.html"); + return c.RenderTemplate("member/blog/add_single.html") } func (c MemberBlog) SortSingles(singleIds []string) revel.Result { re := info.NewRe() @@ -226,8 +221,8 @@ func (c MemberBlog) Single() revel.Result { c.common() c.RenderArgs["title"] = "Cate" c.RenderArgs["singles"] = blogService.GetSingles(c.GetUserId()) - - return c.RenderTemplate("member/blog/single.html"); + + return c.RenderTemplate("member/blog/single.html") } // 主题 @@ -236,15 +231,16 @@ func (c MemberBlog) Theme() revel.Result { activeTheme, otherThemes := themeService.GetUserThemes(c.GetUserId()) c.RenderArgs["activeTheme"] = activeTheme c.RenderArgs["otherThemes"] = otherThemes - + c.RenderArgs["optionThemes"] = themeService.GetDefaultThemes() - + c.RenderArgs["title"] = "Theme" - return c.RenderTemplate("member/blog/theme.html"); + return c.RenderTemplate("member/blog/theme.html") } // 编辑主题 var baseTpls = []string{"header.html", "footer.html", "index.html", "cate.html", "search.html", "post.html", "single.html", "tags.html", "tag_posts.html", "archive.html", "share_comment.html", "404.html", "theme.json", "style.css", "blog.js"} + func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result { // 查看用户是否有该theme, 若没有则复制default之 // 得到主题的文件列表 @@ -253,22 +249,25 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result { _, themeId = themeService.NewThemeForFirst(userBlog) return c.Redirect("/member/blog/updateTheme?themeId=" + themeId) } - + c.common() c.RenderArgs["title"] = "Upate Theme" c.RenderArgs["isNew"] = isNew - + // 先复制之 c.RenderArgs["themeId"] = themeId - + // 得到脚本目录 userId := c.GetUserId() - - theme := themeService.GetTheme(userId, themeId) + + theme := themeService.GetTheme(userId, themeId) + if theme.ThemeId == "" { + return c.E404() + } c.RenderArgs["theme"] = theme - + path := revel.BasePath + "/" + theme.Path - + tpls := ListDir(path) myTpls := make([]string, len(baseTpls)) tplMap := map[string]bool{} @@ -279,16 +278,16 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result { // 得到没有的tpls for _, t := range tpls { if t == "images" { - continue; + continue } if !tplMap[t] { myTpls = append(myTpls, t) } } - + c.RenderArgs["myTpls"] = myTpls - - return c.RenderTemplate("member/blog/update_theme.html"); + + return c.RenderTemplate("member/blog/update_theme.html") } // 得到文件内容 @@ -296,13 +295,13 @@ func (c MemberBlog) GetTplContent(themeId string, filename string) revel.Result re := info.NewRe() re.Ok = true re.Item = themeService.GetTplContent(c.GetUserId(), themeId, filename) - + return c.RenderJson(re) } func (c MemberBlog) UpdateTplContent(themeId, filename, content string) revel.Result { re := info.NewRe() re.Ok, re.Msg = themeService.UpdateTplContent(c.GetUserId(), themeId, filename, content) - return c.RenderJson(re) + return c.RenderRe(re) } func (c MemberBlog) DeleteTpl(themeId, filename string) revel.Result { @@ -331,7 +330,7 @@ func (c MemberBlog) DeleteThemeImage(themeId, filename string) revel.Result { // 上传主题图片 func (c MemberBlog) UploadThemeImage(themeId string) revel.Result { - re := c.uploadImage(themeId); + re := c.uploadImage(themeId) c.RenderArgs["fileUrlPath"] = re.Id c.RenderArgs["resultCode"] = re.Code c.RenderArgs["resultMsg"] = re.Msg @@ -339,17 +338,17 @@ func (c MemberBlog) UploadThemeImage(themeId string) revel.Result { } func (c MemberBlog) uploadImage(themeId string) (re info.Re) { var fileId = "" - var resultCode = 0 // 1表示正常 + var resultCode = 0 // 1表示正常 var resultMsg = "内部错误" // 错误信息 var Ok = false - + defer func() { re.Id = fileId // 只是id, 没有其它信息 re.Code = resultCode re.Msg = resultMsg re.Ok = Ok }() - + file, handel, err := c.Request.FormFile("file") if err != nil { return re @@ -363,11 +362,11 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) { } // 生成新的文件名 filename := handel.Filename - - var ext string; - + + var ext string + _, ext = SplitFilename(filename) - if(ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg") { + if ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg" { resultMsg = "不是图片" return re } @@ -378,15 +377,15 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) { LogJ(err) return re } - + // > 2M? - if(len(data) > 5 * 1024 * 1024) { + if len(data) > 5*1024*1024 { resultCode = 0 resultMsg = "图片大于2M" return re } - - toPath := dir + "/" + filename; + + toPath := dir + "/" + filename err = ioutil.WriteFile(toPath, data, 0777) if err != nil { LogJ(err) @@ -395,7 +394,7 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) { TransToGif(toPath, 0, true) resultCode = 1 resultMsg = "上传成功!" - + return re } @@ -406,18 +405,21 @@ func (c MemberBlog) ActiveTheme(themeId string) revel.Result { re.Ok = themeService.ActiveTheme(c.GetUserId(), themeId) return c.RenderJson(re) } + // 删除主题 func (c MemberBlog) DeleteTheme(themeId string) revel.Result { re := info.NewRe() re.Ok = themeService.DeleteTheme(c.GetUserId(), themeId) return c.RenderJson(re) } + // 管理员公开主题 func (c MemberBlog) PublicTheme(themeId string) revel.Result { re := info.NewRe() re.Ok = themeService.PublicTheme(c.GetUserId(), themeId) return c.RenderJson(re) } + // 导出 func (c MemberBlog) ExportTheme(themeId string) revel.Result { re := info.NewRe() @@ -427,21 +429,21 @@ func (c MemberBlog) ExportTheme(themeId string) revel.Result { return c.RenderText("error...") } fw, err := os.Open(path) - if err != nil { + if err != nil { return c.RenderText("error") - } - return c.RenderBinary(fw, GetFilename(path), revel.Attachment, time.Now()) // revel.Attachment + } + return c.RenderBinary(fw, GetFilename(path), revel.Attachment, time.Now()) // revel.Attachment } // 导入主题 func (c MemberBlog) ImportTheme() revel.Result { re := info.NewRe() - + file, handel, err := c.Request.FormFile("file") if err != nil { re.Msg = fmt.Sprintf("%v", err) return c.RenderJson(re) - + } defer file.Close() // 生成上传路径 @@ -454,10 +456,10 @@ func (c MemberBlog) ImportTheme() revel.Result { } // 生成新的文件名 filename := handel.Filename - - var ext string; + + var ext string _, ext = SplitFilename(filename) - if(ext != ".zip") { + if ext != ".zip" { re.Msg = "请上传zip文件" return c.RenderJson(re) } @@ -467,40 +469,40 @@ func (c MemberBlog) ImportTheme() revel.Result { if err != nil { return c.RenderJson(re) } - + // > 10M? - if(len(data) > 10 * 1024 * 1024) { + if len(data) > 10*1024*1024 { re.Msg = "文件大于10M" return c.RenderJson(re) } - - toPath := dir + "/" + filename; + + toPath := dir + "/" + filename err = ioutil.WriteFile(toPath, data, 0777) if err != nil { re.Msg = fmt.Sprintf("%v", err) return c.RenderJson(re) } - + // 上传好后, 增加之 - themeService.ImportTheme(c.GetUserId(), toPath) - - re.Ok = true - return c.RenderJson(re) + re.Ok, re.Msg = themeService.ImportTheme(c.GetUserId(), toPath) + return c.RenderRe(re) } - + // 安装 func (c MemberBlog) InstallTheme(themeId string) revel.Result { re := info.NewRe() re.Ok = themeService.InstallTheme(c.GetUserId(), themeId) return c.RenderJson(re) } + // 新建主题 func (c MemberBlog) NewTheme() revel.Result { _, themeId := themeService.NewTheme(c.GetUserId()) return c.Redirect("/member/blog/updateTheme?isNew=1&themeId=" + themeId) } + //----------- -// +// func (c MemberBlog) SetUserBlogBase(userBlog info.UserBlogBase) revel.Result { re := info.NewRe() re.Ok = blogService.UpdateUserBlogBase(c.GetUserId(), userBlog) @@ -516,6 +518,7 @@ func (c MemberBlog) SetUserBlogStyle(userBlog info.UserBlogStyle) revel.Result { re.Ok = blogService.UpdateUserBlogStyle(c.GetUserId(), userBlog) return c.RenderJson(re) } + func (c MemberBlog) SetUserBlogPaging(perPageSize int, sortField string, isAsc bool) revel.Result { re := info.NewRe() re.Ok, re.Msg = blogService.UpdateUserBlogPaging(c.GetUserId(), perPageSize, sortField, isAsc) diff --git a/app/controllers/member/init.go b/app/controllers/member/init.go index d891db2..b52edb0 100644 --- a/app/controllers/member/init.go +++ b/app/controllers/member/init.go @@ -128,6 +128,7 @@ func init() { revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberIndex{}) revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberUser{}) revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberBlog{}) + revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberGroup{}) revel.OnAppStart(func() { }) -} +} \ No newline at end of file diff --git a/app/db/Mgo.go b/app/db/Mgo.go index 37b0bdb..684ae10 100644 --- a/app/db/Mgo.go +++ b/app/db/Mgo.go @@ -3,6 +3,7 @@ package db import ( "fmt" "github.com/revel/revel" + . "github.com/leanote/leanote/app/lea" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" ) @@ -56,12 +57,15 @@ var Themes *mgo.Collection var Sessions *mgo.Collection // 初始化时连接数据库 -func Init() { - var url string - var ok bool +func Init(url, dbname string) { + ok := true config := revel.Config - url, ok = config.String("db.url") - dbname, _ := config.String("db.dbname") + if url == "" { + url, ok = config.String("db.url") + } + if dbname == "" { + dbname, _ = config.String("db.dbname") + } if !ok { host, _ := revel.Config.String("db.host") port, _ := revel.Config.String("db.port") @@ -73,6 +77,7 @@ func Init() { } url = "mongodb://" + usernameAndPassword + host + ":" + port + "/" + dbname } + Log(url) // [mongodb://][user:pass@]host1[:port1][,host2[:port2],...][/database][?options] // mongodb://myuser:mypass@localhost:40001,otherhost:40001/mydb diff --git a/app/lea/Debug.go b/app/lea/Debug.go index ce8bb02..7684521 100644 --- a/app/lea/Debug.go +++ b/app/lea/Debug.go @@ -3,6 +3,7 @@ package lea import ( "encoding/json" "github.com/revel/revel" + "fmt" ) func Log(i interface{}) { @@ -12,4 +13,14 @@ func Log(i interface{}) { func LogJ(i interface{}) { b, _ := json.MarshalIndent(i, "", " ") revel.INFO.Println(string(b)) -} \ No newline at end of file +} + +// 为test用 +func L(i interface{}) { + fmt.Println(i) +} + +func LJ(i interface{}) { + b, _ := json.MarshalIndent(i, "", " ") + fmt.Println(string(b)) +} diff --git a/app/release/release.go b/app/release/release.go index 05c0d2b..dfe4019 100644 --- a/app/release/release.go +++ b/app/release/release.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "strings" ) + /* 用golang exec 总是说找不到uglifyjs命令, 需要全部路径 而且node, npm要在/usr/bin下, 已建ln @@ -33,8 +34,8 @@ var jss = []string{"js/jquery-cookie", "js/bootstrap", "js/common", "js/app/note", "js/app/tag", "js/app/notebook", "js/app/share", "js/object_id", "js/ZeroClipboard/ZeroClipboard"} -var base1 = "/Users/life/Documents/Go/package2/src/github.com/leanote/leanote/" -var base = "/Users/life/Documents/Go/package2/src/github.com/leanote/leanote/public/" +var base1 = "/Users/life/Documents/Go/package1/src/github.com/leanote/leanote/" +var base = "/Users/life/Documents/Go/package1/src/github.com/leanote/leanote/public/" var cmdPath = "/usr/local/bin/uglifyjs" func cmdError(err error) { @@ -52,7 +53,7 @@ func compressJs(filename string) { to := base + filename + "-min.js" cmd := exec.Command(cmdPath, source, "-o", to) _, err := cmd.CombinedOutput() - + fmt.Println(source); cmdError(err) } @@ -80,7 +81,10 @@ func combineJs() { // 改note-dev->note func dev() { // 即替换note.js->note-min.js - m := map[string]string{"note.js": "note-min.js", + m := map[string]string{"tinymce.dev.js": "tinymce.min.js", + "tinymce.js": "tinymce.min.js", + "jquery.ztree.all-3.5.js": "jquery.ztree.all-3.5-min.js", + "note.js": "note-min.js", "app.js": "app-min.js", "page.js": "page-min.js", "common.js": "common-min.js", @@ -88,6 +92,7 @@ func dev() { "share.js": "share-min.js", "tag.js": "tag-min.js", "main.js": "main-min.js", + "jquery.slimscroll.js": "jquery.slimscroll-min.js", "jquery.contextmenu.js": "jquery.contextmenu-min.js", "editor/editor.js": "editor/editor-min.js", "/public/mdeditor/editor/scrollLink.js": "/public/mdeditor/editor/scrollLink-min.js", @@ -111,12 +116,21 @@ func tinymce() { // cmd := exec.Command("/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master/node_modules/jake/bin/cli.js", "minify", "bundle[themes:modern,plugins:table,paste,advlist,autolink,link,image,lists,charmap,hr,searchreplace,visualblocks,visualchars,code,nav,tabfocus,contextmenu,directionality,codemirror,codesyntax,textcolor,fullpage]") cmd := exec.Command("/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master/node_modules/jake/bin/cli.js", "minify") cmd.Dir = "/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master" - c, err := cmd.CombinedOutput() + + // 必须要先删除 + cmd2 := exec.Command("/bin/sh", "-c", "rm " + cmd.Dir + "/js/tinymce/tinymce.dev.js") + cmd2.CombinedOutput() + cmd2 = exec.Command("/bin/sh", "-c", "rm " + cmd.Dir + "/js/tinymce/tinymce.jquery.dev.js") + c, _ := cmd2.CombinedOutput() + fmt.Println(string(c)) + c, _ = cmd.CombinedOutput() fmt.Println(string(c)) - cmdError(err) } func main() { + // 压缩tinymce + tinymce() + dev(); // 其它零散的需要压缩的js @@ -133,6 +147,10 @@ func main() { "mdeditor/editor/underscore", "mdeditor/editor/mathJax", "js/jQuery-slimScroll-1.3.0/jquery.slimscroll", + "js/app/editor_drop_paste", + "js/app/attachment_upload", + "js/jquery.ztree.all-3.5", + "js/jQuery-slimScroll-1.3.0/jquery.slimscroll", } for _, js := range otherJss { @@ -141,7 +159,5 @@ func main() { // 先压缩后合并 combineJs() - - // 压缩tinymce - tinymce() + } diff --git a/app/service/AuthService.go b/app/service/AuthService.go index 6e4fd24..3937741 100644 --- a/app/service/AuthService.go +++ b/app/service/AuthService.go @@ -5,6 +5,7 @@ import ( // "github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/info" // "github.com/revel/revel" + "strings" . "github.com/leanote/leanote/app/lea" "fmt" "strconv" @@ -17,6 +18,8 @@ type AuthService struct { // pwd已md5了 func (this *AuthService) Login(emailOrUsername, pwd string) info.User { + emailOrUsername = strings.Trim(emailOrUsername, " ") +// pwd = strings.Trim(pwd, " ") userInfo := userService.LoginGetUserInfo(emailOrUsername, Md5(pwd)) return userInfo } @@ -32,12 +35,16 @@ func (this *AuthService) Login(emailOrUsername, pwd string) info.User { // 1. 添加用户 // 2. 将leanote共享给我 // [ok] -func (this *AuthService) Register(email, pwd string) (bool, string) { +func (this *AuthService) Register(email, pwd, fromUserId string) (bool, string) { // 用户是否已存在 if userService.IsExistsUser(email) { return false, "userHasBeenRegistered-" + email } user := info.User{UserId: bson.NewObjectId(), Email: email, Username: email, Pwd: Md5(pwd)} + if fromUserId != "" && IsObjectId(fromUserId) { + user.FromUserId = bson.ObjectIdHex(fromUserId) + } + LogJ(user) return this.register(user) } @@ -129,4 +136,4 @@ func (this *AuthService) ThirdRegister(thirdType, thirdUserId, thirdUsername str } _, _ = this.register(userInfo) return -} \ No newline at end of file +} diff --git a/app/service/FileService.go b/app/service/FileService.go index 21a2e5e..6a403ae 100644 --- a/app/service/FileService.go +++ b/app/service/FileService.go @@ -147,7 +147,16 @@ func (this *FileService) GetFile(userId, fileId string) string { return path } + // 2014/12/28 修复, 如果是分享给用户组, 那就不行, 这里可以实现 + for _, noteId := range noteIds { + note := noteService.GetNoteById(noteId.Hex()) + if shareService.HasReadPerm(note.UserId.Hex(), userId, noteId.Hex()) { + return path; + } + } + /* // 若有共享给我的笔记? + // 对该笔记可读? if db.Has(db.ShareNotes, bson.M{"ToUserId": bson.ObjectIdHex(userId), "NoteId": bson.M{"$in": noteIds}}) { return path } @@ -166,6 +175,7 @@ func (this *FileService) GetFile(userId, fileId string) string { return path } } + */ } // 可能是刚复制到owner上, 但内容又没有保存, 所以没有note->imageId的映射, 此时看是否有fromFileId diff --git a/app/service/NoteContentHistoryService.go b/app/service/NoteContentHistoryService.go index 4b67c31..803feb6 100644 --- a/app/service/NoteContentHistoryService.go +++ b/app/service/NoteContentHistoryService.go @@ -33,7 +33,8 @@ func (this *NoteContentHistoryService) AddHistory(noteId, userId string, eachHis // TODO l := len(history.Histories) if l >= maxSize { - history.Histories = history.Histories[l-maxSize:] + // history.Histories = history.Histories[l-maxSize:] // BUG, 致使都是以前的 + history.Histories = history.Histories[:maxSize] } newHistory := []info.EachHistory{eachHistory} newHistory = append(newHistory, history.Histories...) // 在开头加了, 最近的在最前 @@ -61,4 +62,4 @@ func (this *NoteContentHistoryService) ListHistories(noteId, userId string) []in histories := info.NoteContentHistory{} db.GetByIdAndUserId(db.NoteContentHistories, noteId, userId, &histories) return histories.Histories -} \ No newline at end of file +} diff --git a/app/service/ShareService.go b/app/service/ShareService.go index 40219b3..d1c05bb 100644 --- a/app/service/ShareService.go +++ b/app/service/ShareService.go @@ -49,6 +49,7 @@ func (this *ShareService) getOrQ(userId string) bson.M { return q } +// 得到共享给我的笔记本和用户(谁共享给了我) func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksByUser, []info.User) { // 得到共享给我的用户s信息 // 得到我参与的组织 @@ -60,7 +61,7 @@ func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksB db.Distinct(db.ShareNotes, q, "UserId", &userIds1) userIds2 := []bson.ObjectId{} - db.Distinct(db.ShareNotebooks, q, "UserId", &userIds1) + db.Distinct(db.ShareNotebooks, q, "UserId", &userIds2) // BUG之前是userId1, 2014/12/29 userIds := append(userIds1, userIds2...) userInfos := userService.GetUserInfosOrderBySeq(userIds); diff --git a/app/service/ThemeService.go b/app/service/ThemeService.go index 95577a7..0867299 100644 --- a/app/service/ThemeService.go +++ b/app/service/ThemeService.go @@ -13,6 +13,7 @@ import ( "fmt" "html/template" "regexp" + "io/ioutil" "encoding/json" ) @@ -127,7 +128,8 @@ func (this *ThemeService) CopyDefaultTheme(userBlog info.UserBlog) (ok bool, the // 设为active true func (this *ThemeService) NewThemeForFirst(userBlog info.UserBlog) (ok bool, themeId string) { ok, themeId = this.CopyDefaultTheme(userBlog) - db.UpdateByQField(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId)}, "IsActive", true) + this.ActiveTheme(userBlog.UserId.Hex(), themeId) + // db.UpdateByQField(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId)}, "IsActive", true) return } @@ -285,11 +287,15 @@ func (this *ThemeService) GetThemePath(userId, themeId string) string { } // 更新模板内容 func (this *ThemeService) UpdateTplContent(userId, themeId, filename, content string) (ok bool, msg string) { - path := this.GetThemeAbsolutePath(userId, themeId) + "/" + filename + basePath := this.GetThemeAbsolutePath(userId, themeId) + path := basePath + "/" + filename if strings.Contains(filename, ".html") { - // 模板 - if ok, msg = this.mustTpl(filename, content); ok { - ok = PutFileStrContent(path, content) + Log(">>") + if ok, msg = this.ValidateTheme(basePath, filename, content); ok { + // 模板 + if ok, msg = this.mustTpl(filename, content); ok { + ok = PutFileStrContent(path, content) + } } return } else if filename == "theme.json" { @@ -410,6 +416,11 @@ func (this *ThemeService) ImportTheme(userId, path string) (ok bool, msg string) DeleteFile(targetPath) return } + // 主题验证 + if ok, msg = this.ValidateTheme(targetPath, "", ""); !ok { + DeleteFile(targetPath) + return + } // 解压成功, 那么新建之 // 保存到数据库中 theme, _ := this.getThemeConfig(targetPath) @@ -505,5 +516,119 @@ func (this *ThemeService) InstallTheme(userId, themeId string) (ok bool) { ok = db.Insert(db.Themes, theme) + // 激活之 + this.ActiveTheme(userId, themeId); + return ok } + +// 验证主题是否全法, 存在循环引用? +// filename, newContent 表示在修改模板时要判断模板修改时是否有错误 +func (this *ThemeService) ValidateTheme(path string, filename, newContent string) (ok bool, msg string) { + Log("theme Path") + Log(path) + // 建立一个有向图 + // 将该path下的所有文件提出, 得到文件的引用情况 + files := ListDir(path) + LogJ(files); + size := len(files) + if(size > 100) { + ok = false; + msg = "tooManyFiles" + return + } + /* + 111111111 + 111000000 + */ + vector := make([][]int, size) + for i := 0; i < size; i++ { + vector[i] = make([]int, size) + } + fileIndexMap := map[string]int{} // fileName => index + fileContent := map[string]string{} // fileName => content + index := 0 + // 得到文件内容, 和建立索引, 每个文件都有一个index, 对应数组位置 + for _, t := range files { + if !strings.Contains(t, ".html") { + continue; + } + if t != filename { + fileBytes, err := ioutil.ReadFile(path + "/" + t) + if err != nil { + continue + } + + fileIndexMap[t] = index; + // html内容 + fileStr := string(fileBytes) + fileContent[t] = fileStr + } else { + fileIndexMap[t] = index + fileContent[t] = newContent + } + index++ + } + // 分析文件内容, 建立有向图 + reg, _ := regexp.Compile("{{ *template \"(.+?\\.html)\".*}}") + for filename, content := range fileContent { + thisIndex := fileIndexMap[filename] + finds := reg.FindAllStringSubmatch(content, -1) // 子匹配 + LogJ(finds) +// Log(content) + if finds != nil && len(finds) > 0 { + for _, includes := range finds { + include := includes[1] + includeIndex, has := fileIndexMap[include] + Log(includeIndex) + Log("??") + Log(has) + if has { + vector[thisIndex][includeIndex] = 1 + } + } + } + } + + LogJ(vector) + LogJ(fileIndexMap) + // 建立图后, 判断是否有环 + if this.hasRound(vector, index) { + ok = false + msg = "themeValidHasRoundInclude" + } else { + ok = true + } + return; +} + +// 检测有向图是否有环, DFS +func (this *ThemeService) hasRound(vector [][]int, size int) (ok bool) { + for i := 0; i < size; i++ { + visited := make([]int, size) + if this.hasRoundEach(vector, i, size, visited) { + Log(">>") + Log(i); + return true; + } + } + return false +} + +// 从每个节点出发, 判断是否有环 +func (this *ThemeService) hasRoundEach(vector [][]int, index int, size int, visited []int) (ok bool) { + if visited[index] > 0 { + Log("<") + Log(index) + return true + } + visited[index] = 1; + // 遍历它的孩子 + for i := 0; i < size; i++ { + if vector[index][i] > 0 { + return this.hasRoundEach(vector, i, size, visited); + } + } + visited[index] = 0; + return false; +} diff --git a/app/service/UserService.go b/app/service/UserService.go index cea7c79..9577a6b 100644 --- a/app/service/UserService.go +++ b/app/service/UserService.go @@ -369,7 +369,7 @@ func (this *UserService) ThirdAddUser(userId, email, pwd string) (ok bool, msg s // 宽度 func (this *UserService)UpdateColumnWidth(userId string, notebookWidth, noteListWidth, mdEditorWidth int) bool { return db.UpdateByQMap(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, - bson.M{"NotebookWidth": notebookWidth, "NoteListWidth": noteListWidth, "mdEditorWidth": mdEditorWidth}) + bson.M{"NotebookWidth": notebookWidth, "NoteListWidth": noteListWidth, "MdEditorWidth": mdEditorWidth}) } // 左侧是否隐藏 func (this *UserService)UpdateLeftIsMin(userId string, leftIsMin bool) bool { diff --git a/app/views/errors/500-blog.html b/app/views/errors/500-blog.html new file mode 100644 index 0000000..b15d4d4 --- /dev/null +++ b/app/views/errors/500-blog.html @@ -0,0 +1,63 @@ +{{template "home/header_box.html" .}} + +<section id="box"> + <div> + <div> + <h1 class="h text-white animated fadeInDownBig">ERROR!</h1> + </div> + <div id="errorBox"> + <p class="error-info"> + Sorry, you(not we) got an error. This error is just showing in blog preview for test. + </p> + + <div class="list-group m-b-sm bg-white m-b-lg"> + + {{with .Error}} + <div id="header" class="block"> + <h1> + {{.Title}} + </h1> + <p> + {{if .SourceType}} + The {{.SourceType}} <strong>{{.Path}}</strong> does not compile: <strong>{{.Description}}</strong> + {{else}} + {{.Description}} + {{end}} + </p> + </div> + {{if .Path}} + <div id="source" class="block"> + <h2>In {{.Path}} + {{if .Line}} + (around {{if .Line}}line {{.Line}}{{end}}{{if .Column}} column {{.Column}}{{end}}) + {{end}} + </h2> + {{range .ContextSource}} + <div class="line {{if .IsError}}error{{end}}"> + <span class="lineNumber">{{.Line}}:</span> + <pre>{{.Source}}</pre> + </div> + {{end}} + </div> + {{end}} + {{if .MetaError}} + <div id="source" class="block"> + <h2>Additionally, an error occurred while handling this error.</h2> + <div class="line error"> + {{.MetaError}} + </div> + </div> + {{end}} + {{end}} + + </div> + </div> + </div> +</section> +<div id="boxFooter"> + <p> + <a href="/index">leanote</a> © 2014 + </p> +</div> +</body> +</html> \ No newline at end of file diff --git a/app/views/home/register.html b/app/views/home/register.html index c8f9038..520eea0 100644 --- a/app/views/home/register.html +++ b/app/views/home/register.html @@ -100,7 +100,9 @@ $(function() { $("#registerBtn").html("{{msg . "ing"}}...").addClass("disabled"); // hideMsg(); - $.post("/doRegister", {email: email, pwd: pwd}, function(e) { + var iu = "{{.iu}}"; + + $.post("/doRegister", {email: email, pwd: pwd, iu: iu}, function(e) { $("#registerBtn").html("{{msg . "register"}}").removeClass("disabled"); if(e.Ok) { $("#registerBtn").html("{{msg . "registerSuccessAndRdirectToNote"}}"); diff --git a/app/views/member/blog/add_single.html b/app/views/member/blog/add_single.html index 6446d71..a60c742 100644 --- a/app/views/member/blog/add_single.html +++ b/app/views/member/blog/add_single.html @@ -1,6 +1,6 @@ {{template "member/top.html" .}} <div class="m-b-md"> <h3 class="m-b-none"> -{{if .page}} +{{if .single}} {{msg . "updateSingle"}} {{else}} {{msg . "addSingle"}} @@ -41,7 +41,7 @@ </div> {{template "member/footer.html" .}} -<script type="text/javascript" src="/tinymce/tinymce.min.js"></script> +<script type="text/javascript" src="/tinymce/tinymce.js"></script> <script> var urlPrefix = "{{.siteUrl}}"; $(function() { diff --git a/app/views/member/blog/base.html b/app/views/member/blog/base.html index 999c86e..97798dd 100644 --- a/app/views/member/blog/base.html +++ b/app/views/member/blog/base.html @@ -20,7 +20,7 @@ <label for="logo">{{msg . "blogLogo"}}</label> <input type="hidden" name="Logo" id="Logo" value="{{.userBlog.Logo}}" /> - <form id="formLogo" action="{{$.siteUrl}}/file/uploadBlogLogo" method="post" + <form id="formLogo" action="/file/uploadBlogLogo" method="post" enctype="multipart/form-data" target="logoTarget"> <input type="file" class="form-control" id="logo2" name="file" onChange='$("#formLogo").submit();' /> diff --git a/app/views/member/blog/single.html b/app/views/member/blog/single.html index 869e3b3..23aa5bf 100644 --- a/app/views/member/blog/single.html +++ b/app/views/member/blog/single.html @@ -37,7 +37,7 @@ </div> {{template "member/footer.html" .}} -<script type="text/javascript" src="{{.siteUrl}}/public/member/js/jquery.sortable.js"></script> +<script type="text/javascript" src="/public/member/js/jquery.sortable.js"></script> <script> $(function() { $("#baseBtn").click(function(){ @@ -79,7 +79,7 @@ $(function() { art.alert(re.Msg || "error"); } }); - }); + }); }); </script> diff --git a/app/views/member/blog/theme.html b/app/views/member/blog/theme.html index e05f384..7c62b29 100644 --- a/app/views/member/blog/theme.html +++ b/app/views/member/blog/theme.html @@ -8,6 +8,7 @@ </small> </h3> </div> + <div class="row"> <div class="col-sm-12 theme-container"> <section class="panel panel-default"> @@ -27,8 +28,8 @@ <p> {{msg . "currentTheme"}}: </p> - <ul class="themes"> - <li class="theme"> + <div class="themes clearfix"> + <div class="theme pull-left"> <a class="choose-theme" data-method="put" href="#" rel="nofollow"> <div class="theme-thumb thumb active-theme"> <img src="/{{.activeTheme.Path}}/images/screenshot.png" alt="preview"> @@ -41,12 +42,21 @@ <div class="theme-btns"> <div class="btn-group" data-id="{{.activeTheme.ThemeId.Hex}}"> <a class="btn btn-default btn-sm btn-export"><span class="fa fa-download"></span> {{msg $ "export"}}</a> - <a class="btn btn-default btn-sm" href="{{$.siteUrl}}/preview?themeId={{.activeTheme.ThemeId.Hex}}" target="_blank"><span class="fa fa-eye"></span> {{msg $ "preview"}}</a> + <!-- 必须是自己的主题 --> + {{if .activeTheme.ThemeId}} + <a class="btn btn-default btn-sm" href="{{$.siteUrl}}/preview?themeId={{.activeTheme.ThemeId.Hex}}" target="_blank"><span class="fa fa-eye"></span> {{msg $ "preview"}}</a> + {{end}} <a class="btn btn-primary btn-sm" target="_blank" href="/member/blog/updateTheme?themeId={{if .activeTheme.ThemeId}}{{.activeTheme.ThemeId.Hex}}{{end}}"><span class="fa fa-pencil"></span> {{msg $ "edit"}}</a> </div> </div> - </li> - </ul> + </div> + {{if .activeTheme.Info.Desc}} + <!-- 描述 --> + <div class="pull-left theme-desc"> + {{.activeTheme.Info.Desc|raw}} + </div> + {{end}} + </div> <hr /> <p> @@ -59,6 +69,11 @@ <a class="choose-theme" data-method="put" href="#" rel="nofollow"> <div class="theme-thumb thumb"> <img src="/{{.Path}}/images/screenshot.png" alt="preview"> + {{if .Info.Desc}} + <div class="theme-desc-mask"> + {{.Info.Desc|raw}} + </div> + {{end}} </div> <span class="theme-title">{{.Name}}</span> </a> @@ -100,6 +115,11 @@ <a class="choose-theme" data-method="put" href="#" rel="nofollow"> <div class="theme-thumb thumb"> <img src="/{{.Path}}/images/screenshot.png" alt="preview"> + {{if .Info.Desc}} + <div class="theme-desc-mask"> + {{.Info.Desc|raw}} + </div> + {{end}} </div> <span class="theme-title">{{.Name}}</span> </a> diff --git a/app/views/member/blog/update_theme.html b/app/views/member/blog/update_theme.html index fa0cbca..fd69d0d 100644 --- a/app/views/member/blog/update_theme.html +++ b/app/views/member/blog/update_theme.html @@ -107,7 +107,7 @@ </div> {{template "member/footer.html" .}} -<script src="/public/member/js/ace/ace.js" type="text/javascript"></script> +<script src="/public/libs/ace/ace.js" type="text/javascript"></script> <script> var editor = ace.edit("tplContent"); editor.setTheme("ace/theme/tomorrow"); diff --git a/app/views/note/note-dev.html b/app/views/note/note-dev.html index 9aeb1ea..8fce04d 100644 --- a/app/views/note/note-dev.html +++ b/app/views/note/note-dev.html @@ -13,10 +13,12 @@ <link href="/css/bootstrap.css" rel="stylesheet" /> <!-- 先加载, 没有样式, 宽度不定 --> <link rel="stylesheet" href="/tinymce/skins/custom/skin.min.css" rel="stylesheet"/> - <!-- leanote css --> <link href="/css/font-awesome-4.2.0/css/font-awesome.css" rel="stylesheet" /> <link href="/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" /> +<!-- mdeditor --> +<link href="/public/dist/themes/default.css" rel="stylesheet" /> + <script> var hash = location.hash; if(hash.indexOf("writing") >= 0) { @@ -169,7 +171,7 @@ function log(o) { {{if .isAdmin}} <li role="presentation" class="divider"></li> <li role="presentation"> - <a target="_blank" title="{{msg . "amdin"}}" href="/admin/index"> + <a target="_blank" title="{{msg . "admin"}}" href="/admin/index"> <i class="fa fa-dashboard"></i> <span>{{msg . "admin"}}</span> </a> @@ -184,13 +186,11 @@ function log(o) { </div> </div> - <!-- <div class="pull-right top-nav writting-hide lea-blog"> <a target="_blank" href="http://lea.leanote.com"> lea++ </a> </div> - --> <div class="pull-right top-nav writting-hide" id="myBlog"> <a target="_blank" href="{{$.blogUrl}}/{{.userInfo.Username}}"> @@ -557,12 +557,12 @@ function log(o) { </a> </div> <div class="editorBg"></div> - <div id="leanoteNav"> + <div id="leanoteNav" class="leanoteNav"> <h1> - <i class="fa fa-align-justify" title="文档导航"></i> + <i class="fa fa-align-justify" title="{{msg . "nav"}}"></i> <span>{{msg . "nav"}}</span> </h1> - <div id="leanoteNavContent"> + <div id="leanoteNavContent" class="leanoteNavContent"> </div> </div> @@ -583,9 +583,85 @@ function log(o) { </div> <div id="mdEditor"> + + + <div class="layout-wrapper-l1"> + <div class="layout-wrapper-l2"> + <div class="navbar navbar-default"> + <div class="navbar-inner" id="wmd-button-bar"> + <ul class="nav left-buttons"> + <li class="wmd-button-group1 btn-group"></li> + </ul> + <ul class="nav left-buttons"> + <li class="wmd-button-group2 btn-group"></li> + </ul> + <ul class="nav left-buttons"> + <li class="wmd-button-group3 btn-group"></li> + </ul> + <ul class="nav left-buttons"> + <li class="wmd-button-group5 btn-group"></li> + </ul> + <!-- 帮助 --> + <ul class="nav left-buttons"> + <li class="wmd-button-group6 btn-group"> + <li class="wmd-button btn btn-success" id="wmd-help-button" title="Markdown syntax" style="left: 0px; display: none;"><span style="display: none; background-position: 0px 0px;"></span><i class="fa fa-question-circle"></i></li> + </li> + </ul> + + <!-- + <ul class="nav pull-right right-buttons"> + <li class="offline-status hide"> + <div class="text-danger"> + <i class="icon-attention-circled"></i>offline + </div> + </li> + <li class="extension-buttons"></li> + </ul> + <ul class="nav pull-right title-container"> + <li><div class="working-indicator"></div></li> + <li><a class="btn btn-success file-title-navbar" href="#" + title="Rename document"> </a></li> + <li><div class="input-file-title-container"><input type="text" + class="col-sm-4 form-control hide input-file-title" + placeholder="Document title" /></div></li> + </ul> + --> + </div> + <div class="editorBg"></div> + </div> + <div class="layout-wrapper-l3"> + <div id="left-column"> + <pre id="wmd-input" class="form-control"><div class="editor-content mousetrap" contenteditable=true></div><div class="editor-margin"></div></pre> + </div> + <div id="right-column"> + <div class="preview-panel panel-open" id="preview-panel"> + <div id="mdSplitter2" class="layout-resizer layout-resizer-preview open" style="-webkit-user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); touch-action: none;"></div> + <div class="layout-toggler layout-toggler-preview btn btn-info open" title="Toggle preview" data-open="1"><i class="fa fa-angle-right"></i></div> + <div class="preview-container"> + <div id="preview-contents"> + <div id="wmd-preview" class="preview-content"></div> + </div> + </div> + </div> + </div> + </div> + <div class="extension-preview-buttons"> + <div id="leanoteNavMd" class="leanoteNav"> + <h1> + <i class="fa fa-align-justify" title="{{msg . "nav"}}"></i> + <span>{{msg . "nav"}}</span> + </h1> + <div id="leanoteNavContentMd" class="leanoteNavContent table-of-contents"> + </div> + </div> + </div> + </div> + <div id="wmd-button-bar" class="hide"></div> + </div> + + <!-- <div id="wmd-button-bar" id="mdBar"></div> <div class="editorBg"></div> - <!-- 为了scroll --> <div class="clearfix" id="mdEditorPreview"> <div id="left-column"> @@ -601,11 +677,59 @@ function log(o) { </div> </div> <textarea id="md-section-helper"></textarea> + --> </div> </div> </div> <!-- mdEditor --> + <!-- v2 --> + <div class="modal fade modal-insert-link"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" + aria-hidden="true">×</button> + <h4 class="modal-title">Hyperlink</h4> + </div> + <div class="modal-body"> + <p>Please provide the link URL and an optional title:</p> + <div class="input-group"> + <span class="input-group-addon"><i class="icon-globe"></i></span><input + id="input-insert-link" type="text" class="col-sm-5 form-control" + placeholder='http://example.com/ "optional title"' /> + </div> + </div> + <div class="modal-footer"> + <a href="#" class="btn btn-default" data-dismiss="modal">Cancel</a> + <a href="#" class="btn btn-primary action-insert-link" + data-dismiss="modal">OK</a> + </div> + </div> + </div> + </div> + + <!-- 插入图片 --> + <div class="modal fade modal-insert-image"> + <div class="modal-dialog" style="width: 840px"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" + aria-hidden="true">×</button> + <h4 class="modal-title">Image</h4> + </div> + <div class="modal-body" style="padding-top: 0; padding-bottom: 0"> + <iframe name="mdImageManager" style="width: 100%; height: 350px" scrolling="no" id="leauiIfrForMD" src="" frameborder="0"></iframe> + </div> + <div class="modal-footer"> + <a href="#" class="btn btn-default" + data-dismiss="modal">Cancel</a> <a href="#" + class="btn btn-primary action-insert-image" data-dismiss="modal">Insert Image</a> + </div> + </div> + </div> + </div> + <!-- v1 --> <!-- Hidden Popup Modal --> <div class="modal fade bs-modal-sm" id="editorDialog" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true"> <div class="modal-dialog modal-sm"> @@ -774,28 +898,32 @@ var GlobalConfigs = {{.globalConfigs|jsonJs}}; // 2014/11/9 beta2 <!-- 渲染view --> <script src="/tinymce/tinymce.js"></script> +<script src="/public/libs/ace/ace.js"></script> <script src="/js/app/page.js"></script> <script src="/js/jQuery-slimScroll-1.3.0/jquery.slimscroll.js"></script> <script src="/js/contextmenu/jquery.contextmenu.js"></script> -<script src="/js/jquery-cookie.js"></script> <script src="/js/bootstrap-min.js"></script> <script src="/js/app/note.js"></script> <script src="/js/app/tag.js"></script> <script src="/js/app/notebook.js"></script> <script src="/js/app/share.js"></script> <script src="/js/object_id-min.js"></script> -<script src="/js/ZeroClipboard/ZeroClipboard-min.js"></script> <script> initPage(); </script> - + <!-- context-menu --> <link rel="stylesheet" href="/js/contextmenu/css/contextmenu.css" type="text/css" /> -<!-- code --> -<link href="/public/mdeditor/editor/google-code-prettify/prettify.css" rel="stylesheet" /> -<!-- js version 2.0 use require.js --> + +<!-- v2 use require.js, mdeditor --> +<script> +window.baseDir = '/public/dist'; +window.require = { + baseUrl: window.baseDir, + deps: ['main'] +}; +</script> <script src="/js/require.js"></script> -<script src="/js/main.js"></script> </script> </body> </html> \ No newline at end of file diff --git a/app/views/note/note.html b/app/views/note/note.html index 2dfc97c..43492db 100644 --- a/app/views/note/note.html +++ b/app/views/note/note.html @@ -17,6 +17,9 @@ <!-- leanote css --> <link href="/css/font-awesome-4.2.0/css/font-awesome.css" rel="stylesheet" /> <link href="/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" /> + +<link href="/public/res-min/themes/default.css" rel="stylesheet" /> + <script> var hash = location.hash; if(hash.indexOf("writing") >= 0) { @@ -169,7 +172,7 @@ function log(o) { {{if .isAdmin}} <li role="presentation" class="divider"></li> <li role="presentation"> - <a target="_blank" title="{{msg . "amdin"}}" href="/admin/index"> + <a target="_blank" title="{{msg . "admin"}}" href="/admin/index"> <i class="fa fa-dashboard"></i> <span>{{msg . "admin"}}</span> </a> @@ -184,13 +187,11 @@ function log(o) { </div> </div> - <!-- <div class="pull-right top-nav writting-hide lea-blog"> <a target="_blank" href="http://lea.leanote.com"> lea++ </a> </div> - --> <div class="pull-right top-nav writting-hide" id="myBlog"> <a target="_blank" href="{{$.blogUrl}}/{{.userInfo.Username}}"> @@ -557,12 +558,12 @@ function log(o) { </a> </div> <div class="editorBg"></div> - <div id="leanoteNav"> + <div id="leanoteNav" class="leanoteNav"> <h1> - <i class="fa fa-align-justify" title="文档导航"></i> + <i class="fa fa-align-justify" title="{{msg . "nav"}}"></i> <span>{{msg . "nav"}}</span> </h1> - <div id="leanoteNavContent"> + <div id="leanoteNavContent" class="leanoteNavContent"> </div> </div> @@ -583,9 +584,85 @@ function log(o) { </div> <div id="mdEditor"> + + + <div class="layout-wrapper-l1"> + <div class="layout-wrapper-l2"> + <div class="navbar navbar-default"> + <div class="navbar-inner" id="wmd-button-bar"> + <ul class="nav left-buttons"> + <li class="wmd-button-group1 btn-group"></li> + </ul> + <ul class="nav left-buttons"> + <li class="wmd-button-group2 btn-group"></li> + </ul> + <ul class="nav left-buttons"> + <li class="wmd-button-group3 btn-group"></li> + </ul> + <ul class="nav left-buttons"> + <li class="wmd-button-group5 btn-group"></li> + </ul> + <!-- 帮助 --> + <ul class="nav left-buttons"> + <li class="wmd-button-group6 btn-group"> + <li class="wmd-button btn btn-success" id="wmd-help-button" title="Markdown syntax" style="left: 0px; display: none;"><span style="display: none; background-position: 0px 0px;"></span><i class="fa fa-question-circle"></i></li> + </li> + </ul> + + <!-- + <ul class="nav pull-right right-buttons"> + <li class="offline-status hide"> + <div class="text-danger"> + <i class="icon-attention-circled"></i>offline + </div> + </li> + <li class="extension-buttons"></li> + </ul> + <ul class="nav pull-right title-container"> + <li><div class="working-indicator"></div></li> + <li><a class="btn btn-success file-title-navbar" href="#" + title="Rename document"> </a></li> + <li><div class="input-file-title-container"><input type="text" + class="col-sm-4 form-control hide input-file-title" + placeholder="Document title" /></div></li> + </ul> + --> + </div> + <div class="editorBg"></div> + </div> + <div class="layout-wrapper-l3"> + <div id="left-column"> + <pre id="wmd-input" class="form-control"><div class="editor-content mousetrap" contenteditable=true></div><div class="editor-margin"></div></pre> + </div> + <div id="right-column"> + <div class="preview-panel panel-open" id="preview-panel"> + <div id="mdSplitter2" class="layout-resizer layout-resizer-preview open" style="-webkit-user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); touch-action: none;"></div> + <div class="layout-toggler layout-toggler-preview btn btn-info open" title="Toggle preview" data-open="1"><i class="fa fa-angle-right"></i></div> + <div class="preview-container"> + <div id="preview-contents"> + <div id="wmd-preview" class="preview-content"></div> + </div> + </div> + </div> + </div> + </div> + <div class="extension-preview-buttons"> + <div id="leanoteNavMd" class="leanoteNav"> + <h1> + <i class="fa fa-align-justify" title="{{msg . "nav"}}"></i> + <span>{{msg . "nav"}}</span> + </h1> + <div id="leanoteNavContentMd" class="leanoteNavContent table-of-contents"> + </div> + </div> + </div> + </div> + <div id="wmd-button-bar" class="hide"></div> + </div> + + <!-- <div id="wmd-button-bar" id="mdBar"></div> <div class="editorBg"></div> - <!-- 为了scroll --> <div class="clearfix" id="mdEditorPreview"> <div id="left-column"> @@ -601,11 +678,59 @@ function log(o) { </div> </div> <textarea id="md-section-helper"></textarea> + --> </div> </div> </div> <!-- mdEditor --> + <!-- v2 --> + <div class="modal fade modal-insert-link"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" + aria-hidden="true">×</button> + <h4 class="modal-title">Hyperlink</h4> + </div> + <div class="modal-body"> + <p>Please provide the link URL and an optional title:</p> + <div class="input-group"> + <span class="input-group-addon"><i class="icon-globe"></i></span><input + id="input-insert-link" type="text" class="col-sm-5 form-control" + placeholder='http://example.com/ "optional title"' /> + </div> + </div> + <div class="modal-footer"> + <a href="#" class="btn btn-default" data-dismiss="modal">Cancel</a> + <a href="#" class="btn btn-primary action-insert-link" + data-dismiss="modal">OK</a> + </div> + </div> + </div> + </div> + + <!-- 插入图片 --> + <div class="modal fade modal-insert-image"> + <div class="modal-dialog" style="width: 840px"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" + aria-hidden="true">×</button> + <h4 class="modal-title">Image</h4> + </div> + <div class="modal-body" style="padding-top: 0; padding-bottom: 0"> + <iframe name="mdImageManager" style="width: 100%; height: 350px" scrolling="no" id="leauiIfrForMD" src="" frameborder="0"></iframe> + </div> + <div class="modal-footer"> + <a href="#" class="btn btn-default" + data-dismiss="modal">Cancel</a> <a href="#" + class="btn btn-primary action-insert-image" data-dismiss="modal">Insert Image</a> + </div> + </div> + </div> + </div> + <!-- v1 --> <!-- Hidden Popup Modal --> <div class="modal fade bs-modal-sm" id="editorDialog" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true"> <div class="modal-dialog modal-sm"> @@ -751,7 +876,7 @@ function log(o) { </div> </div> <script src="/js/jquery-1.9.0.min.js"></script> -<script src="/js/jquery.ztree.all-3.5.js"></script> +<script src="/js/jquery.ztree.all-3.5-min.js"></script> <script src="/js/i18n/msg.{{.locale}}.js"></script> <script src="/js/common-min.js"></script> <script> @@ -773,29 +898,31 @@ var GlobalConfigs = {{.globalConfigs|jsonJs}}; // 2014/11/9 beta2 </script> <!-- 渲染view --> -<script src="/tinymce/tinymce.js"></script> +<script src="/tinymce/tinymce.min.js"></script> +<script src="/js/ace/ace.js"></script> <script src="/js/app/page-min.js"></script> -<script src="/js/jQuery-slimScroll-1.3.0/jquery.slimscroll.js"></script> +<script src="/js/jQuery-slimScroll-1.3.0/jquery.slimscroll-min.js"></script> <script src="/js/contextmenu/jquery.contextmenu-min.js"></script> -<script src="/js/jquery-cookie.js"></script> <script src="/js/bootstrap-min.js"></script> <script src="/js/app/note-min.js"></script> <script src="/js/app/tag-min.js"></script> <script src="/js/app/notebook-min.js"></script> <script src="/js/app/share-min.js"></script> <script src="/js/object_id-min.js"></script> -<script src="/js/ZeroClipboard/ZeroClipboard-min.js"></script> <script> initPage(); </script> - + <!-- context-menu --> <link rel="stylesheet" href="/js/contextmenu/css/contextmenu.css" type="text/css" /> -<!-- code --> -<link href="/public/mdeditor/editor/google-code-prettify/prettify.css" rel="stylesheet" /> -<!-- js version 2.0 use require.js --> +<script> +window.baseDir = '/public/res-min'; +window.require = { + baseUrl: window.baseDir, + deps: ['main'] +}; +</script> <script src="/js/require.js"></script> -<script src="/js/main-min.js"></script> </script> </body> </html> \ No newline at end of file