Merge branch 'develop'
admin [init ok] lea++ blog platform [ok]
This commit is contained in:
@@ -32,6 +32,7 @@ func (c Auth) DoLogin(email, pwd string) revel.Result {
|
||||
c.SetSession(userInfo)
|
||||
// 必须要redirect, 不然用户刷新会重复提交登录信息
|
||||
// return c.Redirect("/")
|
||||
configService.InitUserConfigs(userInfo.UserId.Hex())
|
||||
return c.RenderJson(info.Re{Ok: true})
|
||||
}
|
||||
// return c.RenderTemplate("login.html")
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"github.com/revel/revel"
|
||||
// "encoding/json"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
// . "leanote/app/lea"
|
||||
// . "github.com/leanote/leanote/app/lea"
|
||||
"github.com/leanote/leanote/app/info"
|
||||
// "github.com/leanote/leanote/app/types"
|
||||
// "io/ioutil"
|
||||
@@ -45,15 +45,14 @@ func (c Blog) SetNotebook2Blog(notebookId string, isBlog bool) revel.Result {
|
||||
//-----------------------------
|
||||
// 前台
|
||||
|
||||
// 默认是admin用户的博客
|
||||
// 列表
|
||||
// 这里还需要得到其它博客配置信息...
|
||||
// 配置信息可以放在users表中, 或添加一个user_options表(用户配置表)
|
||||
|
||||
// 进入某个用户的博客
|
||||
var blogPageSize = 5
|
||||
var searchBlogPageSize = 30
|
||||
func (c Blog) Index(userId string, notebookId string) revel.Result {
|
||||
// 用户id为空, 转至博客平台
|
||||
if userId == "" {
|
||||
userId = leanoteUserId
|
||||
userId = leanoteUserId;
|
||||
}
|
||||
|
||||
// userId可能是 username, email
|
||||
@@ -90,7 +89,7 @@ func (c Blog) Index(userId string, notebookId string) revel.Result {
|
||||
c.RenderArgs["page"] = page
|
||||
c.RenderArgs["pageSize"] = blogPageSize
|
||||
c.RenderArgs["count"] = count
|
||||
|
||||
|
||||
// 当前notebook
|
||||
c.RenderArgs["notebookId"] = notebookId
|
||||
c.RenderArgs["notebook"] = notebook
|
||||
|
||||
52
app/controllers/LeaController.go
Normal file
52
app/controllers/LeaController.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/revel/revel"
|
||||
// "encoding/json"
|
||||
. "github.com/leanote/leanote/app/lea"
|
||||
// "github.com/leanote/leanote/app/types"
|
||||
// "io/ioutil"
|
||||
// "math"
|
||||
// "os"
|
||||
// "path"
|
||||
)
|
||||
|
||||
// lea++博客平台
|
||||
type Lea struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// 进入某个用户的博客
|
||||
func (c Lea) Index(tag, keywords string) revel.Result {
|
||||
c.RenderArgs["nav"] = "recommend"
|
||||
return c.p(tag, keywords, true)
|
||||
}
|
||||
|
||||
func (c Lea) Latest(tag, keywords string) revel.Result {
|
||||
c.RenderArgs["nav"] = "latest"
|
||||
return c.p(tag, keywords, false);
|
||||
}
|
||||
|
||||
func (c Lea) p(tag, keywords string, recommend bool) revel.Result {
|
||||
var tags = []string{}
|
||||
if recommend {
|
||||
tags = configService.GetGlobalArrayConfig("recommendTags")
|
||||
} else {
|
||||
tags = configService.GetGlobalArrayConfig("newTags")
|
||||
}
|
||||
// 如果不在所在的tag就不能搜索
|
||||
if !InArray(tags, tag) {
|
||||
tag = ""
|
||||
}
|
||||
c.RenderArgs["tag"] = tag
|
||||
|
||||
page := c.GetPage()
|
||||
pageInfo, blogs := blogService.ListAllBlogs(tag, keywords, recommend, page, 10, "UpdatedTime", false)
|
||||
|
||||
c.RenderArgs["pageInfo"] = pageInfo
|
||||
c.RenderArgs["blogs"] = blogs
|
||||
c.RenderArgs["tags"] = tags
|
||||
c.RenderArgs["keywords"] = keywords
|
||||
|
||||
return c.RenderTemplate("lea/index.html");
|
||||
}
|
||||
51
app/controllers/admin/AdminBaseController.go
Normal file
51
app/controllers/admin/AdminBaseController.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
// "github.com/revel/revel"
|
||||
// "gopkg.in/mgo.v2/bson"
|
||||
// "encoding/json"
|
||||
. "github.com/leanote/leanote/app/lea"
|
||||
"github.com/leanote/leanote/app/controllers"
|
||||
// "io/ioutil"
|
||||
// "fmt"
|
||||
// "math"
|
||||
// "strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 公用Controller, 其它Controller继承它
|
||||
type AdminBaseController struct {
|
||||
controllers.BaseController // 不能用*BaseController
|
||||
}
|
||||
|
||||
// 得到sorterField 和 isAsc
|
||||
// okSorter = ['email', 'username']
|
||||
func (c AdminBaseController) getSorter(sorterField string, isAsc bool, okSorter []string) (string, bool){
|
||||
sorter := ""
|
||||
c.Params.Bind(&sorter, "sorter")
|
||||
if sorter == "" {
|
||||
return sorterField, isAsc;
|
||||
}
|
||||
|
||||
// sorter形式 email-up, email-down
|
||||
s2 := strings.Split(sorter, "-")
|
||||
if len(s2) != 2 {
|
||||
return sorterField, isAsc;
|
||||
}
|
||||
|
||||
// 必须是可用的sorter
|
||||
if okSorter != nil && len(okSorter) > 0 {
|
||||
if !InArray(okSorter, s2[0]) {
|
||||
return sorterField, isAsc;
|
||||
}
|
||||
}
|
||||
|
||||
sorterField = strings.Title(s2[0])
|
||||
if s2[1] == "up" {
|
||||
isAsc = true
|
||||
} else {
|
||||
isAsc = false
|
||||
}
|
||||
c.RenderArgs["sorter"] = sorter
|
||||
return sorterField, isAsc;
|
||||
}
|
||||
30
app/controllers/admin/AdminBlogController.go
Normal file
30
app/controllers/admin/AdminBlogController.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"github.com/revel/revel"
|
||||
// . "github.com/leanote/leanote/app/lea"
|
||||
"github.com/leanote/leanote/app/info"
|
||||
)
|
||||
|
||||
// admin 首页
|
||||
|
||||
type AdminBlog struct {
|
||||
AdminBaseController
|
||||
}
|
||||
|
||||
// admin 主页
|
||||
func (c AdminBlog) Index(sorter, keywords string) revel.Result {
|
||||
pageNumber := c.GetPage()
|
||||
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "userId", "isRecommed", "createdTime"});
|
||||
pageInfo, blogs := blogService.ListAllBlogs("", keywords, false, pageNumber, userPageSize, sorterField, isAsc);
|
||||
c.RenderArgs["pageInfo"] = pageInfo
|
||||
c.RenderArgs["blogs"] = blogs
|
||||
c.RenderArgs["keywords"] = keywords
|
||||
return c.RenderTemplate("admin/blog/list.html");
|
||||
}
|
||||
|
||||
func (c AdminBlog) SetRecommend(noteId string, recommend bool) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = blogService.SetRecommend(noteId, recommend);
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
25
app/controllers/admin/AdminController.go
Normal file
25
app/controllers/admin/AdminController.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"github.com/revel/revel"
|
||||
)
|
||||
|
||||
// admin 首页
|
||||
|
||||
type Admin struct {
|
||||
AdminBaseController
|
||||
}
|
||||
|
||||
// admin 主页
|
||||
func (c Admin) Index() revel.Result {
|
||||
c.SetUserInfo()
|
||||
|
||||
c.RenderArgs["title"] = "leanote"
|
||||
c.SetLocale()
|
||||
|
||||
return c.RenderTemplate("admin/index.html");
|
||||
}
|
||||
|
||||
func (c Admin) GetView(view string) revel.Result {
|
||||
return c.RenderTemplate("admin/" + view);
|
||||
}
|
||||
62
app/controllers/admin/AdminSettingController.go
Normal file
62
app/controllers/admin/AdminSettingController.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"github.com/revel/revel"
|
||||
// . "github.com/leanote/leanote/app/lea"
|
||||
"github.com/leanote/leanote/app/info"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// admin 首页
|
||||
|
||||
type AdminSetting struct {
|
||||
AdminBaseController
|
||||
}
|
||||
|
||||
// email配置
|
||||
func (c AdminSetting) Email() revel.Result {
|
||||
return nil
|
||||
}
|
||||
|
||||
// blog标签设置
|
||||
func (c AdminSetting) Blog() revel.Result {
|
||||
recommendTags := configService.GetGlobalArrayConfig("recommendTags")
|
||||
newTags := configService.GetGlobalArrayConfig("newTags")
|
||||
c.RenderArgs["recommendTags"] = strings.Join(recommendTags, ",")
|
||||
c.RenderArgs["newTags"] = strings.Join(newTags, ",")
|
||||
return c.RenderTemplate("admin/setting/blog.html");
|
||||
}
|
||||
func (c AdminSetting) DoBlogTag(recommendTags, newTags string) revel.Result {
|
||||
re := info.NewRe()
|
||||
|
||||
re.Ok = configService.UpdateUserArrayConfig(c.GetUserId(), "recommendTags", strings.Split(recommendTags, ","))
|
||||
re.Ok = configService.UpdateUserArrayConfig(c.GetUserId(), "newTags", strings.Split(newTags, ","))
|
||||
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
// demo
|
||||
// blog标签设置
|
||||
func (c AdminSetting) Demo() revel.Result {
|
||||
c.RenderArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername")
|
||||
c.RenderArgs["demoPassword"] = configService.GetGlobalStringConfig("demoPassword")
|
||||
return c.RenderTemplate("admin/setting/demo.html");
|
||||
}
|
||||
func (c AdminSetting) DoDemo(demoUsername, demoPassword string) revel.Result {
|
||||
re := info.NewRe()
|
||||
|
||||
userInfo := authService.Login(demoUsername, demoPassword)
|
||||
if userInfo.UserId == "" {
|
||||
re.Msg = "The User is Not Exists";
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
re.Ok = configService.UpdateUserStringConfig(c.GetUserId(), "demoUserId", userInfo.UserId.Hex())
|
||||
re.Ok = configService.UpdateUserStringConfig(c.GetUserId(), "demoUsername", demoUsername)
|
||||
re.Ok = configService.UpdateUserStringConfig(c.GetUserId(), "demoPassword", demoPassword)
|
||||
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
|
||||
|
||||
28
app/controllers/admin/AdminUserController.go
Normal file
28
app/controllers/admin/AdminUserController.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"github.com/revel/revel"
|
||||
// . "github.com/leanote/leanote/app/lea"
|
||||
)
|
||||
|
||||
// admin 首页
|
||||
|
||||
type AdminUser struct {
|
||||
AdminBaseController
|
||||
}
|
||||
|
||||
// admin 主页
|
||||
var userPageSize = 10
|
||||
func (c AdminUser) Index(sorter, keywords string) revel.Result {
|
||||
pageNumber := c.GetPage()
|
||||
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"email", "username", "verified", "createdTime"});
|
||||
pageInfo, users := userService.ListUsers(pageNumber, userPageSize, sorterField, isAsc, keywords);
|
||||
c.RenderArgs["pageInfo"] = pageInfo
|
||||
c.RenderArgs["users"] = users
|
||||
c.RenderArgs["keywords"] = keywords
|
||||
return c.RenderTemplate("admin/user/list.html");
|
||||
}
|
||||
|
||||
func (c AdminUser) Add() revel.Result {
|
||||
return c.RenderTemplate("admin/user/add.html");
|
||||
}
|
||||
127
app/controllers/admin/init.go
Normal file
127
app/controllers/admin/init.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"github.com/leanote/leanote/app/service"
|
||||
"github.com/leanote/leanote/app/info"
|
||||
// . "github.com/leanote/leanote/app/lea"
|
||||
"github.com/revel/revel"
|
||||
// "strings"
|
||||
)
|
||||
|
||||
var userService *service.UserService
|
||||
var noteService *service.NoteService
|
||||
var trashService *service.TrashService
|
||||
var notebookService *service.NotebookService
|
||||
var noteContentHistoryService *service.NoteContentHistoryService
|
||||
var authService *service.AuthService
|
||||
var shareService *service.ShareService
|
||||
var blogService *service.BlogService
|
||||
var tagService *service.TagService
|
||||
var pwdService *service.PwdService
|
||||
var tokenService *service.TokenService
|
||||
var suggestionService *service.SuggestionService
|
||||
var albumService *service.AlbumService
|
||||
var noteImageService *service.NoteImageService
|
||||
var fileService *service.FileService
|
||||
var attachService *service.AttachService
|
||||
var configService *service.ConfigService
|
||||
|
||||
var adminUsername = "admin"
|
||||
// 拦截器
|
||||
// 不需要拦截的url
|
||||
// Index 除了Note之外都不需要
|
||||
var commonUrl = map[string]map[string]bool{"Index": map[string]bool{"Index": true,
|
||||
"Login": true,
|
||||
"DoLogin": true,
|
||||
"Logout": true,
|
||||
"Register": true,
|
||||
"DoRegister": true,
|
||||
"FindPasswword": true,
|
||||
"DoFindPassword": true,
|
||||
"FindPassword2": true,
|
||||
"FindPasswordUpdate": true,
|
||||
"Suggestion": true,
|
||||
},
|
||||
"Blog": map[string]bool{"Index": true,
|
||||
"View": true,
|
||||
"AboutMe": true,
|
||||
"SearchBlog": true,
|
||||
},
|
||||
// 用户的激活与修改邮箱都不需要登录, 通过链接地址
|
||||
"User": map[string]bool{"UpdateEmail": true,
|
||||
"ActiveEmail":true,
|
||||
},
|
||||
"Oauth": map[string]bool{"GithubCallback": true},
|
||||
"File": map[string]bool{"OutputImage": true, "OutputFile": true},
|
||||
"Attach": map[string]bool{"Download": true, "DownloadAll": true},
|
||||
}
|
||||
func needValidate(controller, method string) bool {
|
||||
// 在里面
|
||||
if v, ok := commonUrl[controller]; ok {
|
||||
// 在commonUrl里
|
||||
if _, ok2 := v[method]; ok2 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
// controller不在这里的, 肯定要验证
|
||||
return true;
|
||||
}
|
||||
}
|
||||
func AuthInterceptor(c *revel.Controller) revel.Result {
|
||||
// 全部变成首字大写
|
||||
/*
|
||||
var controller = strings.Title(c.Name)
|
||||
var method = strings.Title(c.MethodName)
|
||||
// 是否需要验证?
|
||||
if !needValidate(controller, method) {
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
|
||||
// 验证是否已登录
|
||||
// 必须是管理员
|
||||
if username, ok := c.Session["Username"]; ok && username == adminUsername {
|
||||
return nil // 已登录
|
||||
}
|
||||
|
||||
// 没有登录, 判断是否是ajax操作
|
||||
if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" {
|
||||
re := info.NewRe()
|
||||
re.Msg = "NOTLOGIN"
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
return c.Redirect("/login")
|
||||
}
|
||||
|
||||
// 最外层init.go调用
|
||||
// 获取service, 单例
|
||||
func InitService() {
|
||||
notebookService = service.NotebookS
|
||||
noteService = service.NoteS
|
||||
noteContentHistoryService = service.NoteContentHistoryS
|
||||
trashService = service.TrashS
|
||||
shareService = service.ShareS
|
||||
userService = service.UserS
|
||||
tagService = service.TagS
|
||||
blogService = service.BlogS
|
||||
tokenService = service.TokenS
|
||||
noteImageService = service.NoteImageS
|
||||
fileService = service.FileS
|
||||
albumService= service.AlbumS
|
||||
attachService = service.AttachS
|
||||
pwdService = service.PwdS
|
||||
suggestionService = service.SuggestionS
|
||||
authService = service.AuthS
|
||||
configService = service.ConfigS
|
||||
}
|
||||
|
||||
func init() {
|
||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &Admin{})
|
||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminSetting{})
|
||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &AdminUser{})
|
||||
revel.OnAppStart(func() {
|
||||
adminUsername, _ = revel.Config.String("adminUsername")
|
||||
})
|
||||
}
|
||||
@@ -24,6 +24,7 @@ var albumService *service.AlbumService
|
||||
var noteImageService *service.NoteImageService
|
||||
var fileService *service.FileService
|
||||
var attachService *service.AttachService
|
||||
var configService *service.ConfigService
|
||||
|
||||
var pageSize = 1000
|
||||
var defaultSortField = "UpdatedTime"
|
||||
@@ -116,6 +117,7 @@ func InitService() {
|
||||
pwdService = service.PwdS
|
||||
suggestionService = service.SuggestionS
|
||||
authService = service.AuthS
|
||||
configService = service.ConfigS
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -39,6 +39,7 @@ var Files *mgo.Collection
|
||||
var Attachs *mgo.Collection
|
||||
|
||||
var NoteImages *mgo.Collection
|
||||
var Configs *mgo.Collection
|
||||
|
||||
// 初始化时连接数据库
|
||||
func Init() {
|
||||
@@ -110,6 +111,8 @@ func Init() {
|
||||
Attachs = Session.DB(dbname).C("attachs")
|
||||
|
||||
NoteImages = Session.DB(dbname).C("note_images")
|
||||
|
||||
Configs = Session.DB(dbname).C("configs")
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -10,6 +10,7 @@ type BlogItem struct {
|
||||
Note
|
||||
Content string // 可能是content的一部分, 截取. 点击more后就是整个信息了
|
||||
HasMore bool // 是否是否还有
|
||||
User User // 用户信息
|
||||
}
|
||||
|
||||
type UserBlogBase struct {
|
||||
|
||||
15
app/info/Configinfo.go
Normal file
15
app/info/Configinfo.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package info
|
||||
|
||||
import (
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 配置
|
||||
// 用户配置高于全局配置
|
||||
type Config struct {
|
||||
UserId bson.ObjectId `bson:"_id"`
|
||||
StringConfigs map[string]string `StringConfigs` // key => value
|
||||
ArrayConfigs map[string][]string `ArrayConfigs` // key => []value
|
||||
UpdatedTime time.Time `UpdatedTime`
|
||||
}
|
||||
@@ -17,9 +17,11 @@ type Note struct {
|
||||
|
||||
ImgSrc string `ImgSrc` // 图片, 第一张缩略图地址
|
||||
Tags []string `Tags,omitempty`
|
||||
|
||||
IsTrash bool `IsTrash` // 是否是trash, 默认是false
|
||||
|
||||
IsBlog bool `IsBlog,omitempty` // 是否设置成了blog 2013/12/29 新加
|
||||
IsRecommend bool `IsRecommend,omitempty` // 是否为推荐博客 2014/9/24新加
|
||||
IsTop bool `IsTop,omitempty` // blog是否置顶
|
||||
|
||||
IsMarkdown bool `IsMarkdown` // 是否是markdown笔记, 默认是false
|
||||
|
||||
@@ -20,6 +20,7 @@ type User struct {
|
||||
Pwd string `bson:"Pwd" json:"-"`
|
||||
CreatedTime time.Time `CreatedTime`
|
||||
|
||||
Logo string `Logo` // 9-24
|
||||
// 主题
|
||||
Theme string `Theme`
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package info
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
|
||||
@@ -10,4 +11,12 @@ type Page struct {
|
||||
TotalPage int // 总页
|
||||
Count int // 总记录数
|
||||
List interface{}
|
||||
}
|
||||
|
||||
func NewPage(page, perPageSize, count int, list interface{}) Page {
|
||||
totalPage := 0
|
||||
if count > 0 {
|
||||
totalPage = int(math.Ceil(float64(count) / float64(perPageSize)))
|
||||
}
|
||||
return Page{page, totalPage, count, list}
|
||||
}
|
||||
127
app/init.go
127
app/init.go
@@ -5,11 +5,13 @@ import (
|
||||
. "github.com/leanote/leanote/app/lea"
|
||||
"github.com/leanote/leanote/app/service"
|
||||
"github.com/leanote/leanote/app/controllers"
|
||||
"github.com/leanote/leanote/app/controllers/admin"
|
||||
_ "github.com/leanote/leanote/app/lea/binder"
|
||||
"reflect"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"math"
|
||||
"strings"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
@@ -38,9 +40,13 @@ func init() {
|
||||
revel.TemplateFuncs["raw"] = func(str string) template.HTML {
|
||||
return template.HTML(str)
|
||||
}
|
||||
revel.TemplateFuncs["add"] = func(i int) template.HTML {
|
||||
revel.TemplateFuncs["add"] = func(i int) string {
|
||||
i = i + 1;
|
||||
return template.HTML(fmt.Sprintf("%v", i))
|
||||
return fmt.Sprintf("%v", i)
|
||||
}
|
||||
revel.TemplateFuncs["sub"] = func(i int) int {
|
||||
i = i - 1;
|
||||
return i
|
||||
}
|
||||
revel.TemplateFuncs["concat"] = func(s1, s2 string) template.HTML {
|
||||
return template.HTML(s1 + s2)
|
||||
@@ -78,6 +84,76 @@ func init() {
|
||||
return template.HTML(tagStr)
|
||||
}
|
||||
|
||||
revel.TemplateFuncs["li"] = func(a string) string {
|
||||
Log(a)
|
||||
Log("life==")
|
||||
return ""
|
||||
}
|
||||
// str连接
|
||||
revel.TemplateFuncs["urlConcat"] = func(url string, v... interface{}) string {
|
||||
html := ""
|
||||
for i := 0; i < len(v); i = i + 2 {
|
||||
item := v[i]
|
||||
if i+1 == len(v) {
|
||||
break;
|
||||
}
|
||||
value := v[i+1]
|
||||
if item != nil && value != nil {
|
||||
keyStr, _ := item.(string)
|
||||
valueStr, err := value.(string)
|
||||
if !err {
|
||||
valueInt, _ := value.(int)
|
||||
valueStr = strconv.Itoa(valueInt)
|
||||
}
|
||||
if keyStr != "" && valueStr != "" {
|
||||
s := keyStr + "=" + valueStr
|
||||
if html != "" {
|
||||
html += "&" + s
|
||||
} else {
|
||||
html += s
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if html != "" {
|
||||
if strings.Index(url, "?") >= 0 {
|
||||
return url + "&" + html
|
||||
} else {
|
||||
return url + "?" + html
|
||||
}
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
revel.TemplateFuncs["urlCond"] = func(url string, sorterI, keyords interface{}) template.HTML {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 为后台管理sorter th使用
|
||||
// 必须要返回HTMLAttr, 返回html, golang 会执行安全检查返回ZgotmplZ
|
||||
// sorterI 可能是nil, 所以用interfalce{}来接收
|
||||
/*
|
||||
data-url="/adminUser/index"
|
||||
data-sorter="email"
|
||||
class="th-sortable {{if eq .sorter "email-up"}}th-sort-up{{else}}{{if eq .sorter "email-down"}}th-sort-down{{end}}{{end}}"
|
||||
*/
|
||||
revel.TemplateFuncs["sorterTh"] = func(url, sorterField string, sorterI interface{}) template.HTMLAttr {
|
||||
sorter := ""
|
||||
if sorterI != nil {
|
||||
sorter, _ = sorterI.(string)
|
||||
}
|
||||
html := "data-url=\"" + url + "\" data-sorter=\"" + sorterField + "\"";
|
||||
html += " class=\"th-sortable ";
|
||||
if sorter == sorterField + "-up" {
|
||||
html += "th-sort-up\"";
|
||||
} else if(sorter == sorterField + "-down") {
|
||||
html += "th-sort-down";
|
||||
}
|
||||
html += "\"";
|
||||
return template.HTMLAttr(html)
|
||||
}
|
||||
|
||||
// pagination
|
||||
revel.TemplateFuncs["page"] = func(userId, notebookId string, page, pageSize, count int) template.HTML {
|
||||
if count == 0 {
|
||||
@@ -114,6 +190,51 @@ func init() {
|
||||
}
|
||||
return template.HTML("<li class='" + preClass + "'><a href='" + preUrl + "'>Previous</a></li> <li class='" + nextClass + "'><a href='" + nextUrl + "'>Next</a></li>")
|
||||
}
|
||||
// life
|
||||
// https://groups.google.com/forum/#!topic/golang-nuts/OEdSDgEC7js
|
||||
// http://play.golang.org/p/snygrVpQva
|
||||
// http://grokbase.com/t/gg/golang-nuts/142a6dhfh3/go-nuts-text-template-using-comparison-operators-eq-gt-etc-on-non-existent-variable-causes-the-template-to-stop-outputting-but-with-no-error-correct-behaviour
|
||||
revel.TemplateFuncs["gt"] = func(a1, a2 interface{}) bool {
|
||||
switch a1.(type) {
|
||||
case string:
|
||||
switch a2.(type) {
|
||||
case string:
|
||||
return reflect.ValueOf(a1).String() > reflect.ValueOf(a2).String()
|
||||
}
|
||||
case int, int8, int16, int32, int64:
|
||||
switch a2.(type) {
|
||||
case int, int8, int16, int32, int64:
|
||||
return reflect.ValueOf(a1).Int() > reflect.ValueOf(a2).Int()
|
||||
}
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
switch a2.(type) {
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
return reflect.ValueOf(a1).Uint() > reflect.ValueOf(a2).Uint()
|
||||
}
|
||||
case float32, float64:
|
||||
switch a2.(type) {
|
||||
case float32, float64:
|
||||
return reflect.ValueOf(a1).Float() > reflect.ValueOf(a2).Float()
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/*
|
||||
{{range $i := N 1 10}}
|
||||
<div>{{$i}}</div>
|
||||
{{end}}
|
||||
*/
|
||||
revel.TemplateFuncs["N"] = func(start, end int) (stream chan int) {
|
||||
stream = make(chan int)
|
||||
go func() {
|
||||
for i := start; i <= end; i++ {
|
||||
stream <- i
|
||||
}
|
||||
close(stream)
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
// init Email
|
||||
revel.OnAppStart(func() {
|
||||
@@ -121,5 +242,7 @@ func init() {
|
||||
|
||||
service.InitService()
|
||||
controllers.InitService()
|
||||
admin.InitService()
|
||||
service.ConfigS.InitGlobalConfigs()
|
||||
})
|
||||
}
|
||||
@@ -40,7 +40,7 @@ func (this *BlogService) GetBlog(noteId string) (blog info.BlogItem) {
|
||||
noteContent := noteService.GetNoteContent(note.NoteId.Hex(), note.UserId.Hex())
|
||||
|
||||
// 组装成blogItem
|
||||
blog = info.BlogItem{note, noteContent.Content, false}
|
||||
blog = info.BlogItem{note, noteContent.Content, false, info.User{}}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func (this *BlogService) ListBlogs(userId, notebookId string, page, pageSize int
|
||||
if noteContent, ok := noteContentsMap[note.NoteId]; ok {
|
||||
content = noteContent.Abstract
|
||||
}
|
||||
blogs[i] = info.BlogItem{note, content, hasMore}
|
||||
blogs[i] = info.BlogItem{note, content, hasMore, info.User{}}
|
||||
}
|
||||
return count, blogs
|
||||
}
|
||||
@@ -119,11 +119,85 @@ func (this *BlogService) SearchBlog(key, userId string, page, pageSize int, sort
|
||||
if noteContent, ok := noteContentsMap[note.NoteId]; ok {
|
||||
content = noteContent.Abstract
|
||||
}
|
||||
blogs[i] = info.BlogItem{note, content, hasMore}
|
||||
blogs[i] = info.BlogItem{note, content, hasMore, info.User{}}
|
||||
}
|
||||
return count, blogs
|
||||
}
|
||||
|
||||
//-------
|
||||
// p
|
||||
// 平台 lea+
|
||||
// 博客列表
|
||||
func (this *BlogService) ListAllBlogs(tag string, keywords string, isRecommend bool, page, pageSize int, sorterField string, isAsc bool) (info.Page, []info.BlogItem) {
|
||||
pageInfo := info.Page{CurPage: page}
|
||||
notes := []info.Note{}
|
||||
|
||||
skipNum, sortFieldR := parsePageAndSort(page, pageSize, sorterField, isAsc)
|
||||
|
||||
// 不是trash的
|
||||
query := bson.M{"IsTrash": false, "IsBlog": true}
|
||||
if tag != "" {
|
||||
query["Tags"] = bson.M{"$in": []string{tag}}
|
||||
}
|
||||
if isRecommend {
|
||||
query["IsRecommend"] = isRecommend
|
||||
}
|
||||
if keywords != "" {
|
||||
query["Title"] = bson.M{"$regex": bson.RegEx{".*?" + keywords + ".*", "i"}}
|
||||
}
|
||||
q := db.Notes.Find(query);
|
||||
|
||||
// 总记录数
|
||||
count, _ := q.Count()
|
||||
|
||||
q.Sort(sortFieldR).
|
||||
Skip(skipNum).
|
||||
Limit(pageSize).
|
||||
All(¬es)
|
||||
|
||||
if(notes == nil || len(notes) == 0) {
|
||||
return pageInfo, nil
|
||||
}
|
||||
|
||||
// 得到content, 并且每个都要substring
|
||||
noteIds := make([]bson.ObjectId, len(notes))
|
||||
userIds := make([]bson.ObjectId, len(notes))
|
||||
for i, note := range notes {
|
||||
noteIds[i] = note.NoteId
|
||||
userIds[i] = note.UserId
|
||||
}
|
||||
|
||||
// 可以不要的
|
||||
// 直接得到noteContents表的abstract
|
||||
// 这里可能是乱序的
|
||||
/*
|
||||
noteContents := noteService.ListNoteAbstractsByNoteIds(noteIds) // 返回[info.NoteContent]
|
||||
noteContentsMap := make(map[bson.ObjectId]info.NoteContent, len(noteContents))
|
||||
for _, noteContent := range noteContents {
|
||||
noteContentsMap[noteContent.NoteId] = noteContent
|
||||
}
|
||||
*/
|
||||
|
||||
// 得到用户信息
|
||||
userMap := userService.MapUserInfoAndBlogInfosByUserIds(userIds)
|
||||
|
||||
// 组装成blogItem
|
||||
// 按照notes的顺序
|
||||
blogs := make([]info.BlogItem, len(noteIds))
|
||||
for i, note := range notes {
|
||||
hasMore := true
|
||||
var content string
|
||||
/*
|
||||
if noteContent, ok := noteContentsMap[note.NoteId]; ok {
|
||||
content = noteContent.Abstract
|
||||
}
|
||||
*/
|
||||
blogs[i] = info.BlogItem{note, content, hasMore, userMap[note.UserId]}
|
||||
}
|
||||
pageInfo = info.NewPage(page, pageSize, count, nil)
|
||||
|
||||
return pageInfo, blogs
|
||||
}
|
||||
|
||||
//------------------------
|
||||
// 博客设置
|
||||
@@ -152,4 +226,12 @@ func (this *BlogService) UpdateUserBlogComment(userId string, userBlog info.User
|
||||
}
|
||||
func (this *BlogService) UpdateUserBlogStyle(userId string, userBlog info.UserBlogStyle) bool {
|
||||
return db.UpdateByQMap(db.UserBlogs, bson.M{"_id": bson.ObjectIdHex(userId)}, userBlog)
|
||||
}
|
||||
|
||||
//------------
|
||||
// 后台管理
|
||||
|
||||
// 推荐博客
|
||||
func (this *BlogService) SetRecommend(noteId string, isRecommend bool) bool {
|
||||
return db.UpdateByQField(db.Notes, bson.M{"_id": bson.ObjectIdHex(noteId), "IsBlog": true}, "IsRecommend", isRecommend)
|
||||
}
|
||||
141
app/service/ConfigService.go
Normal file
141
app/service/ConfigService.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/leanote/leanote/app/info"
|
||||
// . "github.com/leanote/leanote/app/lea"
|
||||
"github.com/leanote/leanote/app/db"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
"github.com/revel/revel"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 配置服务
|
||||
type ConfigService struct {
|
||||
// 全局的
|
||||
GlobalStringConfigs map[string]string
|
||||
GlobalArrayConfigs map[string][]string
|
||||
|
||||
// 两种配置, 用户自己的
|
||||
UserStringConfigs map[string]string
|
||||
UserArrayConfigs map[string][]string
|
||||
|
||||
// 合并之后的
|
||||
AllStringConfigs map[string]string
|
||||
AllArrayConfigs map[string][]string
|
||||
}
|
||||
|
||||
var adminUserId = ""
|
||||
|
||||
// appStart时 将全局的配置从数据库中得到作为全局
|
||||
func (this *ConfigService) InitGlobalConfigs() bool {
|
||||
this.GlobalStringConfigs = map[string]string{}
|
||||
this.GlobalArrayConfigs = map[string][]string{}
|
||||
|
||||
this.UserStringConfigs = map[string]string{}
|
||||
this.UserArrayConfigs = map[string][]string{}
|
||||
|
||||
this.AllStringConfigs = map[string]string{}
|
||||
this.AllArrayConfigs = map[string][]string{}
|
||||
|
||||
adminUsername, _ := revel.Config.String("adminUsername")
|
||||
if adminUsername == "" {
|
||||
adminUsername = "admin"
|
||||
}
|
||||
|
||||
userInfo := userService.GetUserInfoByAny(adminUsername)
|
||||
if userInfo.UserId == "" {
|
||||
return false
|
||||
}
|
||||
adminUserId = userInfo.UserId.Hex()
|
||||
|
||||
configs := info.Config{}
|
||||
db.Get2(db.Configs, userInfo.UserId, &configs)
|
||||
|
||||
if configs.UserId == "" {
|
||||
db.Insert(db.Configs, info.Config{UserId: userInfo.UserId, StringConfigs: map[string]string{}, ArrayConfigs: map[string][]string{}})
|
||||
}
|
||||
|
||||
this.GlobalStringConfigs = configs.StringConfigs;
|
||||
this.GlobalArrayConfigs = configs.ArrayConfigs;
|
||||
|
||||
// 复制到所有配置上
|
||||
for key, value := range this.GlobalStringConfigs {
|
||||
this.AllStringConfigs[key] = value
|
||||
}
|
||||
for key, value := range this.GlobalArrayConfigs {
|
||||
this.AllArrayConfigs[key] = value
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 用户登录后获取用户自定义的配置, 并将所有的配置都用上
|
||||
func (this *ConfigService) InitUserConfigs(userId string) bool {
|
||||
configs := info.Config{}
|
||||
db.Get(db.Configs, userId, &configs)
|
||||
|
||||
if configs.UserId == "" {
|
||||
db.Insert(db.Configs, info.Config{UserId: bson.ObjectIdHex(userId), StringConfigs: map[string]string{}, ArrayConfigs: map[string][]string{}})
|
||||
}
|
||||
|
||||
this.UserStringConfigs = configs.StringConfigs;
|
||||
this.UserArrayConfigs = configs.ArrayConfigs;
|
||||
|
||||
// 合并配置
|
||||
for key, value := range this.UserStringConfigs {
|
||||
this.AllStringConfigs[key] = value
|
||||
}
|
||||
for key, value := range this.UserArrayConfigs {
|
||||
this.AllArrayConfigs[key] = value
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 获取配置
|
||||
func (this *ConfigService) GetStringConfig(key string) string {
|
||||
return this.AllStringConfigs[key]
|
||||
}
|
||||
func (this *ConfigService) GetArrayConfig(key string) []string {
|
||||
arr := this.AllArrayConfigs[key]
|
||||
if arr == nil {
|
||||
return []string{}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// 更新用户配置
|
||||
func (this *ConfigService) UpdateUserStringConfig(userId, key string, value string) bool {
|
||||
this.UserStringConfigs[key] = value
|
||||
this.AllStringConfigs[key] = value
|
||||
if userId == adminUserId {
|
||||
this.GlobalStringConfigs[key] = value
|
||||
}
|
||||
|
||||
// 保存到数据库中
|
||||
return db.UpdateByQMap(db.Configs, bson.M{"_id": bson.ObjectIdHex(userId)},
|
||||
bson.M{"StringConfigs": this.UserStringConfigs, "UpdatedTime": time.Now()})
|
||||
}
|
||||
func (this *ConfigService) UpdateUserArrayConfig(userId, key string, value []string) bool {
|
||||
this.UserArrayConfigs[key] = value
|
||||
this.AllArrayConfigs[key] = value
|
||||
if userId == adminUserId {
|
||||
this.GlobalArrayConfigs[key] = value
|
||||
}
|
||||
|
||||
// 保存到数据库中
|
||||
return db.UpdateByQMap(db.Configs, bson.M{"_id": bson.ObjectIdHex(userId)},
|
||||
bson.M{"ArrayConfigs": this.UserArrayConfigs, "UpdatedTime": time.Now()})
|
||||
}
|
||||
|
||||
// 获取全局配置, 博客平台使用
|
||||
func (this *ConfigService) GetGlobalStringConfig(key string) string {
|
||||
return this.GlobalStringConfigs[key]
|
||||
}
|
||||
func (this *ConfigService) GetGlobalArrayConfig(key string) []string {
|
||||
arr := this.GlobalArrayConfigs[key]
|
||||
if arr == nil {
|
||||
return []string{}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
@@ -99,6 +99,29 @@ func (this *UserService) ListUserInfosByUserIds(userIds []bson.ObjectId) []info.
|
||||
db.ListByQ(db.Users, bson.M{"_id": bson.M{"$in": userIds}}, &users)
|
||||
return users
|
||||
}
|
||||
// 用户信息和博客设置信息
|
||||
func (this *UserService) MapUserInfoAndBlogInfosByUserIds(userIds []bson.ObjectId) map[bson.ObjectId]info.User {
|
||||
users := []info.User{}
|
||||
db.ListByQ(db.Users, bson.M{"_id": bson.M{"$in": userIds}}, &users)
|
||||
|
||||
userBlogs := []info.UserBlog{}
|
||||
db.ListByQWithFields(db.UserBlogs, bson.M{"_id": bson.M{"$in": userIds}}, []string{"Logo"}, &userBlogs)
|
||||
|
||||
userBlogMap := make(map[bson.ObjectId]info.UserBlog, len(userBlogs))
|
||||
for _, user := range userBlogs {
|
||||
userBlogMap[user.UserId] = user
|
||||
}
|
||||
|
||||
userMap := make(map[bson.ObjectId]info.User, len(users))
|
||||
for _, user := range users {
|
||||
if userBlog, ok := userBlogMap[user.UserId]; ok {
|
||||
user.Logo = userBlog.Logo
|
||||
}
|
||||
userMap[user.UserId] = user
|
||||
}
|
||||
|
||||
return userMap
|
||||
}
|
||||
|
||||
// 通过ids得到users, 按id的顺序组织users
|
||||
func (this *UserService) GetUserInfosOrderBySeq(userIds []bson.ObjectId) []info.User {
|
||||
@@ -135,7 +158,7 @@ func (this *UserService) LoginGetUserInfo(emailOrUsername, md5Pwd string) info.U
|
||||
|
||||
// 更新username
|
||||
func (this *UserService) UpdateUsername(userId, username string) (bool, string) {
|
||||
if userId == "" || username == "" {
|
||||
if userId == "" || username == "" || username == "admin" { // admin用户是内置的, 不能设置
|
||||
return false, "用户已存在"
|
||||
}
|
||||
usernameRaw := username // 原先的, 可能是同一个, 但有大小写
|
||||
@@ -296,4 +319,25 @@ func (this *UserService)UpdateColumnWidth(userId string, notebookWidth, noteList
|
||||
// 左侧是否隐藏
|
||||
func (this *UserService)UpdateLeftIsMin(userId string, leftIsMin bool) bool {
|
||||
return db.UpdateByQMap(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, bson.M{"LeftIsMin": leftIsMin})
|
||||
}
|
||||
|
||||
//-------------
|
||||
// user admin
|
||||
func (this *UserService) ListUsers(pageNumber, pageSize int, sortField string, isAsc bool, email string) (page info.Page, users []info.User) {
|
||||
users = []info.User{}
|
||||
skipNum, sortFieldR := parsePageAndSort(pageNumber, pageSize, sortField, isAsc)
|
||||
query := bson.M{}
|
||||
if email != "" {
|
||||
query["Email"] = bson.M{"$regex": bson.RegEx{".*?" + email + ".*", "i"}}
|
||||
}
|
||||
q := db.Users.Find(query);
|
||||
// 总记录数
|
||||
count, _ := q.Count()
|
||||
// 列表
|
||||
q.Sort(sortFieldR).
|
||||
Skip(skipNum).
|
||||
Limit(pageSize).
|
||||
All(&users)
|
||||
page = info.NewPage(pageNumber, pageSize, count, nil)
|
||||
return
|
||||
}
|
||||
@@ -21,6 +21,7 @@ var noteImageService, NoteImageS *NoteImageService
|
||||
var fileService, FileS *FileService
|
||||
var albumService, AlbumS *AlbumService
|
||||
var attachService, AttachS *AttachService
|
||||
var configService, ConfigS *ConfigService
|
||||
var PwdS *PwdService
|
||||
var SuggestionS *SuggestionService
|
||||
var AuthS *AuthService
|
||||
@@ -40,6 +41,7 @@ func InitService() {
|
||||
FileS = &FileService{}
|
||||
AlbumS = &AlbumService{}
|
||||
AttachS = &AttachService{}
|
||||
ConfigS = &ConfigService{}
|
||||
PwdS = &PwdService{}
|
||||
SuggestionS = &SuggestionService{}
|
||||
AuthS = &AuthService{}
|
||||
@@ -57,4 +59,5 @@ func InitService() {
|
||||
fileService = FileS
|
||||
albumService = AlbumS
|
||||
attachService = AttachS
|
||||
configService = ConfigS
|
||||
}
|
||||
175
app/views/Admin/Blog/list.html
Normal file
175
app/views/Admin/Blog/list.html
Normal file
@@ -0,0 +1,175 @@
|
||||
{{template "admin/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">Blog</h3></div>
|
||||
|
||||
<section class="panel panel-default">
|
||||
<div class="row wrapper">
|
||||
<div class="col-sm-5 m-b-xs">
|
||||
<select class="input-sm form-control input-s-sm inline v-middle">
|
||||
<option value="0">
|
||||
Bulk action
|
||||
</option>
|
||||
<option value="1">
|
||||
Delete selected
|
||||
</option>
|
||||
<option value="2">
|
||||
Bulk edit
|
||||
</option>
|
||||
<option value="3">
|
||||
Export
|
||||
</option>
|
||||
</select>
|
||||
<button class="btn btn-sm btn-default">
|
||||
Apply
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-4 m-b-xs">
|
||||
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<div class="input-group search-group">
|
||||
<input type="text" class="input-sm form-control" placeholder="Title" id="keywords" value="{{.keywords}}" />
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-sm btn-default" type="button" data-url="/adminBlog/index">Search</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped b-t b-light">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="20">
|
||||
<input type="checkbox">
|
||||
</th>
|
||||
{{$url := urlConcat "/adminBlog/index" "keywords" .keywords}}
|
||||
<th
|
||||
{{sorterTh $url "title" .sorter}}
|
||||
>
|
||||
Title
|
||||
<span class="th-sort">
|
||||
<i class="fa fa-sort-down"></i>
|
||||
<i class="fa fa-sort-up"></i>
|
||||
<i class="fa fa-sort"></i>
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
{{sorterTh $url "userId" .sorter}}
|
||||
>
|
||||
Username
|
||||
<span class="th-sort">
|
||||
<i class="fa fa-sort-down"></i>
|
||||
<i class="fa fa-sort-up"></i>
|
||||
<i class="fa fa-sort"></i>
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
{{sorterTh $url "isRecommend" .sorter}}
|
||||
>
|
||||
isRecommend
|
||||
<span class="th-sort">
|
||||
<i class="fa fa-sort-down"></i>
|
||||
<i class="fa fa-sort-up"></i>
|
||||
<i class="fa fa-sort"></i>
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
{{sorterTh $url "createdTime" .sorter}}
|
||||
>
|
||||
Create Date
|
||||
<span class="th-sort">
|
||||
<i class="fa fa-sort-down"></i>
|
||||
<i class="fa fa-sort-up"></i>
|
||||
<i class="fa fa-sort"></i>
|
||||
</span>
|
||||
</th>
|
||||
<th width="30">
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .blogs}}
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" name="post[]" value="2">
|
||||
</td>
|
||||
<td>
|
||||
<a href="/blog/view/{{.NoteId.Hex}}" target="_blank">{{.Title|raw}}</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/blog/{{.UserId.Hex}}" target="_blank">
|
||||
{{.User.Username}}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<button data-loading-text="..." class="btn btn-default change-recommend" data-id="{{.NoteId.Hex}}" data-recommend="{{if .IsRecommend}}1{{else}}0{{end}}">
|
||||
{{if .IsRecommend}}
|
||||
Y
|
||||
{{else}}
|
||||
N
|
||||
{{end}}
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
{{.CreatedTime|datetime}}
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" class="btn btn-default">Send Email</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<footer class="panel-footer">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 hidden-xs">
|
||||
<select class="input-sm form-control input-s-sm inline v-middle">
|
||||
<option value="0">
|
||||
Bulk action
|
||||
</option>
|
||||
<option value="1">
|
||||
Delete selected
|
||||
</option>
|
||||
<option value="2">
|
||||
Bulk edit
|
||||
</option>
|
||||
<option value="3">
|
||||
Export
|
||||
</option>
|
||||
</select>
|
||||
<button class="btn btn-sm btn-default">
|
||||
Apply
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-4 text-center">
|
||||
<small class="text-muted inline m-t-sm m-b-sm">
|
||||
showing 20-30 of 50 items
|
||||
</small>
|
||||
</div>
|
||||
<div class="col-sm-4 text-right text-center-xs">
|
||||
{{set . "url" (urlConcat "/adminBlog/index" "sorter" .sorter "keywords" .keywords)}}
|
||||
{{template "admin/user/page.html" .}}
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</section>
|
||||
|
||||
{{template "admin/footer.html" .}}
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
$(".change-recommend").click(function() {
|
||||
var isRecommend = +$(this).data("recommend");
|
||||
var noteId = $(this).data("id");
|
||||
var t = this;
|
||||
$(t).button("loading");
|
||||
ajaxGet("/adminBlog/setRecommend", {noteId: noteId, recommend: !isRecommend}, function() {
|
||||
$(t).button("reset");
|
||||
$(t).text(isRecommend ? "N" : "Y");
|
||||
$(t).data("recommend", !isRecommend);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{{template "admin/end.html" .}}
|
||||
33
app/views/Admin/Blog/page.html
Normal file
33
app/views/Admin/Blog/page.html
Normal file
@@ -0,0 +1,33 @@
|
||||
{{if gt .pageInfo.TotalPage 1}}
|
||||
<ul class="pagination pagination-sm m-t-none m-b-none">
|
||||
<li class="{{if eq $.pageInfo.CurPage 1}}disabled{{end}}" >
|
||||
<a href="{{if eq $.pageInfo.CurPage 1}}javascript:;{{else}}{{sub $.pageInfo.CurPage | urlConcat $.url "page" }}{{end}}">
|
||||
<i class="fa fa-chevron-left">
|
||||
</i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{{range $i := N 1 .pageInfo.TotalPage}}
|
||||
{{if eq $i $.pageInfo.CurPage}}
|
||||
<li class="active">
|
||||
<a href="javascript:;">
|
||||
{{$i}}
|
||||
</a>
|
||||
</li>
|
||||
{{else}}
|
||||
<li class="">
|
||||
<a href="{{urlConcat $.url "page" $i}}">
|
||||
{{$i}}
|
||||
</a>
|
||||
</li>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
<li class="{{if eq .pageInfo.CurPage .pageInfo.TotalPage}}disabled{{end}}" >
|
||||
<a href="{{if eq .pageInfo.CurPage .pageInfo.TotalPage}}javascript:;{{else}}{{add $.pageInfo.CurPage | urlConcat $.url "page" }}{{end}}">
|
||||
<i class="fa fa-chevron-right">
|
||||
</i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{{end}}
|
||||
55
app/views/Admin/Setting/blog.html
Normal file
55
app/views/Admin/Setting/blog.html
Normal file
@@ -0,0 +1,55 @@
|
||||
{{template "admin/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">Blog</h3></div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-6">
|
||||
<form id="add_user_form">
|
||||
<section class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label>Recommend Tags</label>
|
||||
<input type="text" class="form-control" name="recommendTags" value="{{.recommendTags}}">
|
||||
Split by ','
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>New Tags</label>
|
||||
<input type="text" class="form-control" name="newTags" value="{{.newTags}}">
|
||||
Split by ','
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="panel-footer text-right bg-light lter">
|
||||
<button type="submit" id="submit" class="btn btn-success btn-s-xs">Submit</button>
|
||||
</footer>
|
||||
</section>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{template "admin/footer.html" .}}
|
||||
<script src="/public/admin/js/jquery-validation-1.13.0/jquery.validate.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
init_validator("#add_user_form");
|
||||
|
||||
$("#submit").click(function(e){
|
||||
e.preventDefault();
|
||||
var t = this;
|
||||
if($("#add_user_form").valid()) {
|
||||
$(t).button('loading');
|
||||
ajaxPost("/adminSetting/doBlogTag", getFormJsonData("add_user_form"), function(ret){
|
||||
$(t).button('reset')
|
||||
if(!ret.Ok) {
|
||||
art.alert(ret.Msg)
|
||||
} else {
|
||||
art.tips("Success");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{{template "admin/end.html" .}}
|
||||
52
app/views/Admin/Setting/demo.html
Normal file
52
app/views/Admin/Setting/demo.html
Normal file
@@ -0,0 +1,52 @@
|
||||
{{template "admin/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">Demo User</h3></div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-6">
|
||||
<form id="add_user_form">
|
||||
<section class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label>Demo Username</label>
|
||||
<input type="text" class="form-control" name="demoUsername" value="{{.demoUsername}}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Demo Password</label>
|
||||
<input type="text" class="form-control" name="demoPassword" value="{{.demoPassword}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="panel-footer text-right bg-light lter">
|
||||
<button type="submit" id="submit" class="btn btn-success btn-s-xs">Submit</button>
|
||||
</footer>
|
||||
</section>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{template "admin/footer.html" .}}
|
||||
<script src="/public/admin/js/jquery-validation-1.13.0/jquery.validate.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
init_validator("#add_user_form");
|
||||
$("#submit").click(function(e){
|
||||
e.preventDefault();
|
||||
var t = this;
|
||||
if($("#add_user_form").valid()) {
|
||||
$(t).button('loading');
|
||||
ajaxPost("/adminSetting/doDemo", getFormJsonData("add_user_form"), function(ret){
|
||||
$(t).button('reset')
|
||||
if(!ret.Ok) {
|
||||
art.alert(ret.Msg)
|
||||
} else {
|
||||
art.tips("Success");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{{template "admin/end.html" .}}
|
||||
58
app/views/Admin/User/add.html
Normal file
58
app/views/Admin/User/add.html
Normal file
@@ -0,0 +1,58 @@
|
||||
{{template "admin/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">Add User</h3></div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-6">
|
||||
<form id="add_user_form">
|
||||
<section class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label>Email</label>
|
||||
<input type="text" class="form-control" name="email" data-rule-required="true" data-rule-email="true">
|
||||
</div>
|
||||
<div class="form-group pull-in clearfix">
|
||||
<div class="col-sm-6">
|
||||
<label>Enter password</label>
|
||||
<input type="password" class="form-control" data-rule-required="true" id="pwd" name="pwd" data-rule-minlength="6">
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label>Confirm password</label>
|
||||
<input type="password" class="form-control parsley-validated" data-rule-equalto="#pwd" data-rule-required="true" name="password2">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="panel-footer text-right bg-light lter">
|
||||
<button type="submit" id="submit" class="btn btn-success btn-s-xs">Submit</button>
|
||||
</footer>
|
||||
</section>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{template "admin/footer.html" .}}
|
||||
<script src="/public/admin/js/jquery-validation-1.13.0/jquery.validate.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
init_validator("#add_user_form");
|
||||
|
||||
$("#submit").click(function(e){
|
||||
e.preventDefault();
|
||||
var t = this;
|
||||
if($("#add_user_form").valid()) {
|
||||
$(t).button('loading');
|
||||
ajaxPost("/auth/doRegister", getFormJsonData("add_user_form"), function(ret){
|
||||
$(t).button('reset')
|
||||
if(!ret.Ok) {
|
||||
art.alert(ret.Msg)
|
||||
} else {
|
||||
art.tips("Success");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{{template "admin/end.html" .}}
|
||||
163
app/views/Admin/User/list.html
Normal file
163
app/views/Admin/User/list.html
Normal file
@@ -0,0 +1,163 @@
|
||||
{{template "admin/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">User</h3></div>
|
||||
|
||||
<section class="panel panel-default">
|
||||
<div class="row wrapper">
|
||||
<div class="col-sm-5 m-b-xs">
|
||||
<select class="input-sm form-control input-s-sm inline v-middle">
|
||||
<option value="0">
|
||||
Bulk action
|
||||
</option>
|
||||
<option value="1">
|
||||
Delete selected
|
||||
</option>
|
||||
<option value="2">
|
||||
Bulk edit
|
||||
</option>
|
||||
<option value="3">
|
||||
Export
|
||||
</option>
|
||||
</select>
|
||||
<button class="btn btn-sm btn-default">
|
||||
Apply
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-4 m-b-xs">
|
||||
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<div class="input-group search-group">
|
||||
<input type="text" class="input-sm form-control" placeholder="Email" id="keywords" value="{{.keywords}}" />
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-sm btn-default" type="button" data-url="/adminUser/index">Search</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped b-t b-light">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="20">
|
||||
<input type="checkbox">
|
||||
</th>
|
||||
{{$url := urlConcat "/adminUser/index" "keywords" .keywords}}
|
||||
<th
|
||||
{{sorterTh $url "email" .sorter}}
|
||||
>
|
||||
Email
|
||||
<span class="th-sort">
|
||||
<i class="fa fa-sort-down"></i>
|
||||
<i class="fa fa-sort-up"></i>
|
||||
<i class="fa fa-sort"></i>
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
{{sorterTh $url "username" .sorter}}
|
||||
>
|
||||
Username
|
||||
<span class="th-sort">
|
||||
<i class="fa fa-sort-down"></i>
|
||||
<i class="fa fa-sort-up"></i>
|
||||
<i class="fa fa-sort"></i>
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
{{sorterTh $url "verified" .sorter}}
|
||||
>
|
||||
Verified
|
||||
<span class="th-sort">
|
||||
<i class="fa fa-sort-down"></i>
|
||||
<i class="fa fa-sort-up"></i>
|
||||
<i class="fa fa-sort"></i>
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
{{sorterTh $url "createdTime" .sorter}}
|
||||
>
|
||||
Register Date
|
||||
<span class="th-sort">
|
||||
<i class="fa fa-sort-down"></i>
|
||||
<i class="fa fa-sort-up"></i>
|
||||
<i class="fa fa-sort"></i>
|
||||
</span>
|
||||
</th>
|
||||
<th width="30">
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .users}}
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" name="post[]" value="2">
|
||||
</td>
|
||||
<td>
|
||||
{{.Email}}
|
||||
</td>
|
||||
<td>
|
||||
{{.Username}}
|
||||
</td>
|
||||
<td>
|
||||
{{.Verified}}
|
||||
</td>
|
||||
<td>
|
||||
{{.CreatedTime|datetime}}
|
||||
<a href="#" class="active" data-toggle="class">
|
||||
<i class="fa fa-check text-success text-active">
|
||||
</i>
|
||||
<i class="fa fa-times text-danger text">
|
||||
</i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" class="btn btn-default">Send Email</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<footer class="panel-footer">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 hidden-xs">
|
||||
<select class="input-sm form-control input-s-sm inline v-middle">
|
||||
<option value="0">
|
||||
Bulk action
|
||||
</option>
|
||||
<option value="1">
|
||||
Delete selected
|
||||
</option>
|
||||
<option value="2">
|
||||
Bulk edit
|
||||
</option>
|
||||
<option value="3">
|
||||
Export
|
||||
</option>
|
||||
</select>
|
||||
<button class="btn btn-sm btn-default">
|
||||
Apply
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-4 text-center">
|
||||
<small class="text-muted inline m-t-sm m-b-sm">
|
||||
showing 20-30 of 50 items
|
||||
</small>
|
||||
</div>
|
||||
<div class="col-sm-4 text-right text-center-xs">
|
||||
{{set . "url" (urlConcat "/adminUser/index" "sorter" .sorter "keywords" .keywords)}}
|
||||
{{template "admin/user/page.html" .}}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</section>
|
||||
|
||||
{{template "admin/footer.html" .}}
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
});
|
||||
</script>
|
||||
|
||||
{{template "admin/end.html" .}}
|
||||
33
app/views/Admin/User/page.html
Normal file
33
app/views/Admin/User/page.html
Normal file
@@ -0,0 +1,33 @@
|
||||
{{if gt .pageInfo.TotalPage 1}}
|
||||
<ul class="pagination pagination-sm m-t-none m-b-none">
|
||||
<li class="{{if eq $.pageInfo.CurPage 1}}disabled{{end}}" >
|
||||
<a href="{{if eq $.pageInfo.CurPage 1}}javascript:;{{else}}{{sub $.pageInfo.CurPage | urlConcat $.url "page" }}{{end}}">
|
||||
<i class="fa fa-chevron-left">
|
||||
</i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{{range $i := N 1 .pageInfo.TotalPage}}
|
||||
{{if eq $i $.pageInfo.CurPage}}
|
||||
<li class="active">
|
||||
<a href="javascript:;">
|
||||
{{$i}}
|
||||
</a>
|
||||
</li>
|
||||
{{else}}
|
||||
<li class="">
|
||||
<a href="{{urlConcat $.url "page" $i}}">
|
||||
{{$i}}
|
||||
</a>
|
||||
</li>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
<li class="{{if eq .pageInfo.CurPage .pageInfo.TotalPage}}disabled{{end}}" >
|
||||
<a href="{{if eq .pageInfo.CurPage .pageInfo.TotalPage}}javascript:;{{else}}{{add $.pageInfo.CurPage | urlConcat $.url "page" }}{{end}}">
|
||||
<i class="fa fa-chevron-right">
|
||||
</i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{{end}}
|
||||
639
app/views/Admin/button.html
Normal file
639
app/views/Admin/button.html
Normal file
@@ -0,0 +1,639 @@
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-6">
|
||||
<h4 class="m-t-xs">
|
||||
Button options
|
||||
</h4>
|
||||
<div class="doc-buttons">
|
||||
<a href="#" class="btn btn-s-md btn-default">
|
||||
Default
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-primary">
|
||||
Primary
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-success">
|
||||
Success
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-info">
|
||||
Info
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-warning">
|
||||
Warning
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-danger">
|
||||
Danger
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-dark">
|
||||
Dark
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-default disabled">
|
||||
Disabled
|
||||
</a>
|
||||
</div>
|
||||
<h4 class="m-t">
|
||||
Button size
|
||||
</h4>
|
||||
<p>
|
||||
<a href="#" class="btn btn-default btn-lg">
|
||||
Large button
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="#" class="btn btn-default">
|
||||
Default button
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="#" class="btn btn-default btn-sm">
|
||||
Small button
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="#" class="btn btn-default btn-xs">
|
||||
Extra small button
|
||||
</a>
|
||||
</p>
|
||||
<h4 class="m-t-lg">
|
||||
Button dropdowns
|
||||
</h4>
|
||||
<p class="text-muted">
|
||||
Single button dropdowns
|
||||
</p>
|
||||
<div class="m-b-sm">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
Action
|
||||
<span class="caret">
|
||||
</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="#">
|
||||
Action
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Another action
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Something else here
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider">
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Separated link
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-success dropdown-toggle" data-toggle="dropdown">
|
||||
Action
|
||||
<span class="caret">
|
||||
</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="#">
|
||||
Action
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Another action
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Something else here
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider">
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Separated link
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="m-b-sm">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
|
||||
Action
|
||||
<span class="caret">
|
||||
</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="#">
|
||||
Action
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Another action
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Something else here
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider">
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Separated link
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="m-b-sm">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown">
|
||||
Action
|
||||
<span class="caret">
|
||||
</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="#">
|
||||
Action
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Another action
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Something else here
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider">
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Separated link
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted">
|
||||
Split button dropdowns & variation
|
||||
</p>
|
||||
<div class="m-b-sm">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-default">
|
||||
Action
|
||||
</button>
|
||||
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="caret">
|
||||
</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="#">
|
||||
Action
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Another action
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Something else here
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider">
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Separated link
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group dropup">
|
||||
<button class="btn btn-default">
|
||||
Action
|
||||
</button>
|
||||
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="caret">
|
||||
</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="#">
|
||||
Action
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Another action
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Something else here
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider">
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Separated link
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="m-t-lg">
|
||||
Button with icon
|
||||
</h4>
|
||||
<p>
|
||||
<a href="#" class="btn btn-default">
|
||||
<i class="fa fa-html5">
|
||||
</i>
|
||||
Html5
|
||||
</a>
|
||||
<a href="#" class="btn btn-info">
|
||||
<i class="fa fa-css3">
|
||||
</i>
|
||||
CSS3
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="#" class="btn btn-default btn-lg btn-block">
|
||||
<i class="fa fa-bars pull-right">
|
||||
</i>
|
||||
Block button with icon
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="#" class="btn btn-default btn-block">
|
||||
<i class="fa fa-bars pull-left">
|
||||
</i>
|
||||
Block button with icon
|
||||
</a>
|
||||
</p>
|
||||
<h4 class="m-t-lg">
|
||||
Button icon
|
||||
</h4>
|
||||
<p id="social-buttons">
|
||||
<a href="#" class="btn btn-sm btn-icon btn-info">
|
||||
<i class="fa fa-twitter">
|
||||
</i>
|
||||
</a>
|
||||
<a href="#" class="btn btn-sm btn-icon btn-success">
|
||||
<i class="fa fa-facebook">
|
||||
</i>
|
||||
</a>
|
||||
<a href="#" class="btn btn-sm btn-icon btn-danger">
|
||||
<i class="fa fa-google-plus">
|
||||
</i>
|
||||
</a>
|
||||
</p>
|
||||
<h4 class="m-t-lg">
|
||||
Button icon rounded
|
||||
</h4>
|
||||
<p id="social-buttons">
|
||||
<a href="#" class="btn btn-rounded btn-sm btn-icon btn-default">
|
||||
<i class="fa fa-twitter">
|
||||
</i>
|
||||
</a>
|
||||
<a href="#" class="btn btn-rounded btn-sm btn-icon btn-default">
|
||||
<i class="fa fa-facebook">
|
||||
</i>
|
||||
</a>
|
||||
<a href="#" class="btn btn-rounded btn-sm btn-icon btn-default">
|
||||
<i class="fa fa-google-plus">
|
||||
</i>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h4 class="m-t-xs">
|
||||
Rounded button
|
||||
</h4>
|
||||
<div class="doc-buttons">
|
||||
<a href="#" class="btn btn-s-md btn-default btn-rounded">
|
||||
Default
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-primary btn-rounded">
|
||||
Primary
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-success btn-rounded">
|
||||
Success
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-info btn-rounded">
|
||||
Info
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-warning btn-rounded">
|
||||
Warning
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-danger btn-rounded">
|
||||
Danger
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-dark btn-rounded">
|
||||
Dark
|
||||
</a>
|
||||
<a href="#" class="btn btn-s-md btn-default btn-rounded disabled">
|
||||
Disabled
|
||||
</a>
|
||||
</div>
|
||||
<h4 class="m-t-lg">
|
||||
Button groups
|
||||
</h4>
|
||||
<div class="m-b-sm">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-default">
|
||||
Left
|
||||
</button>
|
||||
<button type="button" class="btn btn-default">
|
||||
Middle
|
||||
</button>
|
||||
<button type="button" class="btn btn-default">
|
||||
Right
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted">
|
||||
Vertical button groups
|
||||
</p>
|
||||
<div class="btn-group-vertical m-b-sm">
|
||||
<button type="button" class="btn btn-default">
|
||||
Top
|
||||
</button>
|
||||
<button type="button" class="btn btn-default">
|
||||
Middle
|
||||
</button>
|
||||
<button type="button" class="btn btn-default">
|
||||
Bottom
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-muted">
|
||||
Nested button groups
|
||||
</p>
|
||||
<div class="btn-group m-b-sm">
|
||||
<button type="button" class="btn btn-default">
|
||||
1
|
||||
</button>
|
||||
<button type="button" class="btn btn-success">
|
||||
2
|
||||
</button>
|
||||
<button type="button" class="btn btn-default">
|
||||
3
|
||||
</button>
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
Dropdown
|
||||
<span class="caret">
|
||||
</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="#">
|
||||
Dropdown link
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Dropdown link
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Dropdown link
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted">
|
||||
Justified button groups
|
||||
</p>
|
||||
<div class="m-b-sm">
|
||||
<div class="btn-group btn-group-justified">
|
||||
<a href="#" class="btn btn-primary">
|
||||
Left
|
||||
</a>
|
||||
<a href="#" class="btn btn-info">
|
||||
Middle
|
||||
</a>
|
||||
<a href="#" class="btn btn-success">
|
||||
Right
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted">
|
||||
Multiple button groups
|
||||
</p>
|
||||
<div class="btn-toolbar">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-default">
|
||||
1
|
||||
</button>
|
||||
<button type="button" class="btn btn-default active">
|
||||
2
|
||||
</button>
|
||||
<button type="button" class="btn btn-default">
|
||||
3
|
||||
</button>
|
||||
<button type="button" class="btn btn-default">
|
||||
4
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-default">
|
||||
5
|
||||
</button>
|
||||
<button type="button" class="btn btn-default">
|
||||
6
|
||||
</button>
|
||||
<button type="button" class="btn btn-default">
|
||||
7
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-default">
|
||||
8
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="m-t-lg">
|
||||
Button components
|
||||
</h4>
|
||||
<p class="text-muted">
|
||||
<span>
|
||||
There are a few easy ways to quickly get started with Bootstrap, each
|
||||
one ...
|
||||
</span>
|
||||
<span class="text-muted hide" id="moreless">
|
||||
appealing to a different skill level and use case. Read through to see
|
||||
what suits your particular needs.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<button href="#moreless" class="btn btn-sm btn-default" data-toggle="class:show">
|
||||
<i class="fa fa-plus text">
|
||||
</i>
|
||||
<span class="text">
|
||||
More
|
||||
</span>
|
||||
<i class="fa fa-minus text-active">
|
||||
</i>
|
||||
<span class="text-active">
|
||||
Less
|
||||
</span>
|
||||
</button>
|
||||
</p>
|
||||
<p>
|
||||
<button class="btn btn-default" id="btn-1" href="#btn-1" data-toggle="class:btn-success">
|
||||
<i class="fa fa-cloud-upload text">
|
||||
</i>
|
||||
<span class="text">
|
||||
Upload
|
||||
</span>
|
||||
<i class="fa fa-check text-active">
|
||||
</i>
|
||||
<span class="text-active">
|
||||
Success
|
||||
</span>
|
||||
</button>
|
||||
<button class="btn btn-default" data-toggle="button">
|
||||
<i class="fa fa-heart-o text">
|
||||
</i>
|
||||
<i class="fa fa-heart text-active text-danger">
|
||||
</i>
|
||||
</button>
|
||||
<button class="btn btn-default" data-toggle="button">
|
||||
<span class="text">
|
||||
<i class="fa fa-thumbs-up text-success">
|
||||
</i>
|
||||
25
|
||||
</span>
|
||||
<span class="text-active">
|
||||
<i class="fa fa-thumbs-down text-danger">
|
||||
</i>
|
||||
10
|
||||
</span>
|
||||
</button>
|
||||
<button class="btn btn-success" data-toggle="class:show inline" data-target="#spin"
|
||||
data-loading-text="Saving...">
|
||||
Save
|
||||
</button>
|
||||
<i class="fa fa-spin fa-spinner hide" id="spin">
|
||||
</i>
|
||||
</p>
|
||||
<div class="m-b-sm">
|
||||
<div class="btn-group" data-toggle="buttons">
|
||||
<label class="btn btn-sm btn-info active">
|
||||
<input type="radio" name="options" id="option1">
|
||||
<i class="fa fa-check text-active">
|
||||
</i>
|
||||
Male
|
||||
</label>
|
||||
<label class="btn btn-sm btn-success">
|
||||
<input type="radio" name="options" id="option2">
|
||||
<i class="fa fa-check text-active">
|
||||
</i>
|
||||
Female
|
||||
</label>
|
||||
<label class="btn btn-sm btn-primary">
|
||||
<input type="radio" name="options" id="option3">
|
||||
<i class="fa fa-check text-active">
|
||||
</i>
|
||||
N/A
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="m-b-sm">
|
||||
<div class="btn-group" data-toggle="buttons">
|
||||
<label class="btn btn-sm btn-default">
|
||||
<input type="checkbox" name="options" id="option1">
|
||||
option1
|
||||
</label>
|
||||
<label class="btn btn-sm btn-default">
|
||||
<input type="checkbox" name="options" id="option2">
|
||||
option2
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<h5 class="m-t-lg">
|
||||
Select Button
|
||||
</h5>
|
||||
<div class="btn-group m-r">
|
||||
<button data-toggle="dropdown" class="btn btn-sm btn-default dropdown-toggle">
|
||||
<span class="dropdown-label">
|
||||
Option1
|
||||
</span>
|
||||
<span class="caret">
|
||||
</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-select">
|
||||
<li class="active">
|
||||
<a href="#">
|
||||
<input type="radio" name="d-s-r" checked="">
|
||||
Option1
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<input type="radio" name="d-s-r">
|
||||
Option2
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<input type="radio" name="d-s-r">
|
||||
Option3
|
||||
</a>
|
||||
</li>
|
||||
<li class="disabled">
|
||||
<a href="#">
|
||||
<input type="radio" name="d-s-r" disabled="">
|
||||
I'm disabled
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<h4 class="m-t-lg">
|
||||
<a href="#" class="pull-right text-sm" data-toggle="class:btn-rounded"
|
||||
data-target="#social-buttons a">
|
||||
Toggle
|
||||
</a>
|
||||
Social buttons
|
||||
</h4>
|
||||
<p id="social-buttons">
|
||||
<a href="#" class="btn btn-rounded btn-sm btn-twitter">
|
||||
<i class="fa fa-fw fa-twitter">
|
||||
</i>
|
||||
Twitter
|
||||
</a>
|
||||
<a href="#" class="btn btn-rounded btn-sm btn-facebook">
|
||||
<i class="fa fa-fw fa-facebook">
|
||||
</i>
|
||||
Facebook
|
||||
</a>
|
||||
<a href="#" class="btn btn-rounded btn-sm btn-gplus">
|
||||
<i class="fa fa-fw fa-google-plus">
|
||||
</i>
|
||||
Google+
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
3
app/views/Admin/end.html
Normal file
3
app/views/Admin/end.html
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
</body>
|
||||
</html>
|
||||
36
app/views/Admin/footer.html
Normal file
36
app/views/Admin/footer.html
Normal file
@@ -0,0 +1,36 @@
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<!-- Bootstrap -->
|
||||
<!-- App -->
|
||||
<script src="/js/jquery-1.9.0.min.js"></script>
|
||||
<script src="/js/bootstrap.js"></script>
|
||||
<script src="/public/admin/js/artDialog/jquery.artDialog.js?skin=default"></script>
|
||||
<script src="/public/js/common.js"></script>
|
||||
<script src="/public/admin/js/admin.js"></script>
|
||||
<script>
|
||||
$(function(){
|
||||
var pathname = location.pathname;
|
||||
var arr = pathname.split("/");
|
||||
if(arr.length == 0){
|
||||
return;
|
||||
}
|
||||
var controller = "";
|
||||
var action = "";
|
||||
if(arr[0] == "") {
|
||||
arr = arr.slice(1);
|
||||
}
|
||||
controller = arr[0];
|
||||
if(arr.length > 1) {
|
||||
action = arr[1];
|
||||
}
|
||||
$("#nav > li").removeClass("active");
|
||||
$("#" + controller + "Nav").addClass("active");
|
||||
|
||||
$('a[href="' + pathname + '"]').parent().addClass("active");
|
||||
});
|
||||
</script>
|
||||
37
app/views/Admin/header.html
Normal file
37
app/views/Admin/header.html
Normal file
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="keywords" content="leanote,leanote.com">
|
||||
<meta name="description" content="leanote, your own cloud note!">
|
||||
<meta name="author" content="leanote">
|
||||
<title>{{.title}}</title>
|
||||
|
||||
<link href="/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="/css/font-awesome-4.0.3/css/font-awesome.css" rel="stylesheet">
|
||||
<link href="/public/admin/css/admin.css" rel="stylesheet">
|
||||
<style>
|
||||
</style>
|
||||
|
||||
<script>
|
||||
function log(o) {
|
||||
if(window.console) {
|
||||
console.log(o);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="headerContainer" class="navbar-fixed-top">
|
||||
<div class="container" style="clearfix" id="header">
|
||||
<div class="pull-left">
|
||||
<h1 id="logo" class="clearfix">
|
||||
<a href="/admin/index"></a>
|
||||
<span>Admin</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
106
app/views/Admin/index.html
Normal file
106
app/views/Admin/index.html
Normal file
@@ -0,0 +1,106 @@
|
||||
{{template "admin/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">Workset</h3> <small>Welcome you!</small> </div>
|
||||
<section class="panel panel-default">
|
||||
<div class="row m-l-none m-r-none bg-light lter">
|
||||
<div class="col-sm-6 col-md-3 padder-v b-r b-light">
|
||||
<span class="fa-stack fa-2x pull-left m-r-sm">
|
||||
<i class="fa fa-circle fa-stack-2x text-info"></i>
|
||||
<i class="fa fa-male fa-stack-1x text-white"></i>
|
||||
</span>
|
||||
<a class="clear" href="#">
|
||||
<span class="h3 block m-t-xs"><strong>52,000</strong></span>
|
||||
<small class="text-muted text-uc">users</small>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 padder-v b-r b-light lt">
|
||||
<span class="fa-stack fa-2x pull-left m-r-sm">
|
||||
<i class="fa fa-circle fa-stack-2x text-warning"></i>
|
||||
<i class="fa fa-file-o fa-stack-1x text-white"></i>
|
||||
</span>
|
||||
<a class="clear" href="#">
|
||||
<span class="h3 block m-t-xs"><strong>1312,000</strong></span>
|
||||
<small class="text-muted text-uc">notes</small>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 最新动态 -->
|
||||
<section class="panel panel-default">
|
||||
<h4 class="font-thin padder">
|
||||
Leanote Events
|
||||
</h4>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<p>
|
||||
Wellcome
|
||||
<a href="#" class="text-info">
|
||||
@Drew Wllon
|
||||
</a>
|
||||
and play this web application template, have fun1
|
||||
</p>
|
||||
<small class="block text-muted">
|
||||
<i class="fa fa-clock-o">
|
||||
</i>
|
||||
2 minuts ago
|
||||
</small>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<p>
|
||||
Morbi nec
|
||||
<a href="#" class="text-info">
|
||||
@Jonathan George
|
||||
</a>
|
||||
nunc condimentum ipsum dolor sit amet, consectetur
|
||||
</p>
|
||||
<small class="block text-muted">
|
||||
<i class="fa fa-clock-o">
|
||||
</i>
|
||||
1 hour ago
|
||||
</small>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<p>
|
||||
<a href="#" class="text-info">
|
||||
@Josh Long
|
||||
</a>
|
||||
Vestibulum ullamcorper sodales nisi nec adipiscing elit.
|
||||
</p>
|
||||
<small class="block text-muted">
|
||||
<i class="fa fa-clock-o">
|
||||
</i>
|
||||
2 hours ago
|
||||
</small>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="panel panel-default">
|
||||
<form>
|
||||
<textarea class="form-control no-border" rows="3" placeholder="Suggestions to leanote"></textarea>
|
||||
</form>
|
||||
<footer class="panel-footer bg-light lter">
|
||||
<button class="btn btn-info pull-right btn-sm">
|
||||
POST
|
||||
</button>
|
||||
<ul class="nav nav-pills nav-sm">
|
||||
<!--
|
||||
<li>
|
||||
<a href="#">
|
||||
<i class="fa fa-camera text-muted">
|
||||
</i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<i class="fa fa-video-camera text-muted">
|
||||
</i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
-->
|
||||
</footer>
|
||||
</section>
|
||||
|
||||
{{template "admin/footer.html" .}}
|
||||
{{template "admin/end.html" .}}
|
||||
125
app/views/Admin/nav.html
Normal file
125
app/views/Admin/nav.html
Normal file
@@ -0,0 +1,125 @@
|
||||
<nav class="nav-primary hidden-xs">
|
||||
<ul class="nav" id="nav">
|
||||
|
||||
<li class="active" id="adminUserNav">
|
||||
<a href="index.html">
|
||||
<i class="fa fa-users icon">
|
||||
<b class="bg-danger">
|
||||
</b>
|
||||
</i>
|
||||
<span class="pull-right">
|
||||
<i class="fa fa-angle-down text">
|
||||
</i>
|
||||
<i class="fa fa-angle-up text-active">
|
||||
</i>
|
||||
</span>
|
||||
<span>
|
||||
User
|
||||
</span>
|
||||
</a>
|
||||
<!-- 导航列表 -->
|
||||
<ul class="nav lt">
|
||||
<li>
|
||||
<a href="/adminUser/index">
|
||||
<span>
|
||||
List
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/adminUser/add">
|
||||
<span>
|
||||
Add User
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/adminBlog/index">
|
||||
<i class="fa fa-file icon">
|
||||
<b class="bg-warning">
|
||||
</b>
|
||||
</i>
|
||||
<span>
|
||||
Blog
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li id="adminSettingNav">
|
||||
<a href="#layout">
|
||||
<i class="fa fa-cog icon">
|
||||
<b class="bg-warning">
|
||||
</b>
|
||||
</i>
|
||||
<span class="pull-right">
|
||||
<i class="fa fa-angle-down text">
|
||||
</i>
|
||||
<i class="fa fa-angle-up text-active">
|
||||
</i>
|
||||
</span>
|
||||
<span>
|
||||
Setting
|
||||
</span>
|
||||
</a>
|
||||
<ul class="nav lt">
|
||||
<li>
|
||||
<a href="layout-c.html">
|
||||
<span>
|
||||
Register
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="layout-c.html">
|
||||
<span>
|
||||
Login
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="layout-r.html">
|
||||
<span>
|
||||
Email
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="layout-h.html">
|
||||
<span>
|
||||
Share
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/adminSetting/blog">
|
||||
<span>
|
||||
Blog
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/adminSetting/demo">
|
||||
<span>
|
||||
Demo User
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#layout">
|
||||
<i class="fa fa-columns icon">
|
||||
<b class="bg-warning">
|
||||
</b>
|
||||
</i>
|
||||
<span>
|
||||
Others
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
106
app/views/Admin/top.html
Normal file
106
app/views/Admin/top.html
Normal file
@@ -0,0 +1,106 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="app">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>
|
||||
leanote admin
|
||||
</title>
|
||||
<meta name="description" content="leanote admin"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
|
||||
<link href="/css/font-awesome-4.0.3/css/font-awesome.css" rel="stylesheet">
|
||||
<link href="/public/admin/css/bootstrap.3.2.0.min.css" rel="stylesheet">
|
||||
<link href="/public/admin/css/admin.css" rel="stylesheet">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="/public/admin/js/ie/html5shiv.js"></script>
|
||||
<script src="/public/admin/js/ie/respond.min.js"></script>
|
||||
<script src="/public/admin/js/ie/excanvas.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body class="">
|
||||
<section class="vbox">
|
||||
<header class="bg-dark dk header navbar navbar-fixed-top-xs">
|
||||
<div class="navbar-header aside-md clearfix" id="logo">
|
||||
<a href="/admin/index" class="navbar-brand" data-toggle="fullscreen"></a>
|
||||
<div>Admin</div>
|
||||
</div>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right m-n hidden-xs nav-user">
|
||||
<li class="hidden-xs">
|
||||
<a href="/index" class="dk">
|
||||
Index
|
||||
</a>
|
||||
</li>
|
||||
<li class="hidden-xs">
|
||||
<a href="/note" class="dk">
|
||||
My Note
|
||||
</a>
|
||||
</li>
|
||||
<li class="hidden-xs">
|
||||
<a href="/blog/admin" class="dk">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="hidden-xs">
|
||||
<a href="/blog/admin" class="dk">
|
||||
Logout
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</header>
|
||||
<section>
|
||||
<section class="hbox stretch">
|
||||
<!-- .aside -->
|
||||
<aside class="bg-light lter b-r aside-md hidden-print hidden-xs" id="nav">
|
||||
<section class="vbox">
|
||||
<header class="header bg-primary lter text-center clearfix">
|
||||
<div class="btn-group">
|
||||
<div class="hidden-nav-xs">
|
||||
<a class="btn btn-sm btn-primary">
|
||||
Welcome, admin!
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<section class="w-f scrollable">
|
||||
<div class="slim-scroll" data-height="auto" data-disable-fade-out="true"
|
||||
data-distance="0" data-size="5px" data-color="#333333">
|
||||
<!-- nav -->
|
||||
{{template "admin/nav.html" .}}
|
||||
<!-- / nav -->
|
||||
</div>
|
||||
</section>
|
||||
<footer class="footer lt hidden-xs b-t b-light">
|
||||
<a href="#nav" data-toggle="class:nav-xs" class="pull-right btn btn-sm btn-default btn-icon">
|
||||
<i class="fa fa-angle-left text">
|
||||
</i>
|
||||
<i class="fa fa-angle-right text-active">
|
||||
</i>
|
||||
</a>
|
||||
|
||||
</footer>
|
||||
</section>
|
||||
</aside>
|
||||
<!-- /.aside -->
|
||||
<section id="content">
|
||||
<section class="vbox">
|
||||
<section class="scrollable padder">
|
||||
<!-- 导航 -->
|
||||
<ul class="breadcrumb no-border no-radius b-b b-light pull-in">
|
||||
<li>
|
||||
<a href="index.html">
|
||||
<i class="fa fa-home">
|
||||
</i>
|
||||
Home
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
Elements
|
||||
</a>
|
||||
</li>
|
||||
<li class="active">
|
||||
Components
|
||||
</li>
|
||||
</ul>
|
||||
<!-- 主要内容区 -->
|
||||
|
||||
7
app/views/Lea/footer.html
Normal file
7
app/views/Lea/footer.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<div id="footer">
|
||||
<a href="/lea/index">lea++</a>, leanote博客平台.
|
||||
<a href="/index">leanote</a> © 2014
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
48
app/views/Lea/header.html
Normal file
48
app/views/Lea/header.html
Normal file
@@ -0,0 +1,48 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="keywords" content="lea++, leanote,leanote.com">
|
||||
<meta name="description" content="lea++, leanote blog platform. leanote, your own cloud note!">
|
||||
<meta name="author" content="leanote">
|
||||
<link href="/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="/css/font-awesome-4.0.3/css/font-awesome.css" rel="stylesheet"/>
|
||||
<link href="/css/blog/p.css" rel="stylesheet">
|
||||
<title>lea++, leanote博客平台</title>
|
||||
<script>
|
||||
function log(o) {
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="header">
|
||||
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/lea/index">
|
||||
<span id="logo"></span>
|
||||
<span id="subTitle" title="lea++, leanote博客平台">lea++</span>
|
||||
</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<form class="navbar-form navbar-right">
|
||||
<input type="text" id="keywords" name="keywords" value="{{raw .keywords}}" class="form-control" placeholder="Search...">
|
||||
</form>
|
||||
<ul class="nav navbar-nav navbar-left">
|
||||
<li {{if eq .nav "recommend"}}class="active"{{end}}><a href="/lea/index">推荐</a></li>
|
||||
<li {{if eq .nav "latest"}}class="active"{{end}}><a href="/lea/latest">最新</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
68
app/views/Lea/index.html
Normal file
68
app/views/Lea/index.html
Normal file
@@ -0,0 +1,68 @@
|
||||
{{template "lea/header.html" .}}
|
||||
{{if eq .nav "recommend"}}
|
||||
{{set $ "baseUrl" "/lea/index" }}
|
||||
{{else}}
|
||||
{{set $ "baseUrl" "/lea/latest" }}
|
||||
{{end}}
|
||||
<div id="content">
|
||||
<!-- 分类 -->
|
||||
<ul class="clearfix sort-nav">
|
||||
<li {{if not .tag}}class="active"{{end}}>
|
||||
<a class="category" href="{{$.baseUrl}}">全部</a>
|
||||
</li>
|
||||
{{range $v := .tags}}
|
||||
<li {{if eq $v $.tag}}class="active"{{end}}>
|
||||
<a class="category" data-category-id="{{$v}}" href="{{$.baseUrl}}?tag={{$v}}">{{$v}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
<!-- 文章列表 -->
|
||||
<ul class="thumbnails">
|
||||
{{range .blogs}}
|
||||
<li>
|
||||
<div class="article">
|
||||
<a class="title" href="/blog/view/{{.NoteId.Hex}}" title="{{.Title}} {{msg $ "fullBlog"}}" target="_blank">{{.Title}}</a>
|
||||
<a class="avatar maleskine-author" href="/blog/{{.UserId.Hex}}" target="_blank" title="{{.User.Username}}">
|
||||
{{ if .User.Logo}}
|
||||
<img src="{{.User.Logo}}">
|
||||
{{else}}
|
||||
<img src="/images/blog/default_avatar.png">
|
||||
{{end}}
|
||||
</a>
|
||||
<div class="content">
|
||||
{{.Desc | raw}}
|
||||
</div>
|
||||
<div class="article-info">
|
||||
<a class="author" href="/blog/{{.User.Username}}">
|
||||
<span class="fa fa-user"></span>
|
||||
{{.User.Username}}
|
||||
</a>
|
||||
|
||||
<!--
|
||||
<span class="fa fa-comments-o"></span>9
|
||||
<span class="fa fa-heart-o"></span>6
|
||||
-->
|
||||
|
||||
<span class="fa fa-bookmark-o"></span>
|
||||
{{if .Tags}}
|
||||
{{blogTags .Tags}}
|
||||
{{else}}
|
||||
{{msg $ "noTag"}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
|
||||
<div id="pagination" class="clearfix">
|
||||
{{if eq .nav "recommend"}}
|
||||
{{set . "url" (urlConcat "/lea/index" "keywords" .keywords)}}
|
||||
{{else}}
|
||||
{{set . "url" (urlConcat "/lea/latest" "keywords" .keywords)}}
|
||||
{{end}}
|
||||
{{template "lea/page.html" .}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "lea/footer.html" .}}
|
||||
33
app/views/Lea/page.html
Normal file
33
app/views/Lea/page.html
Normal file
@@ -0,0 +1,33 @@
|
||||
{{if gt .pageInfo.TotalPage 1}}
|
||||
<ul class="pagination pagination-sm m-t-none m-b-none">
|
||||
<li class="{{if eq $.pageInfo.CurPage 1}}disabled{{end}}" >
|
||||
<a href="{{if eq $.pageInfo.CurPage 1}}javascript:;{{else}}{{sub $.pageInfo.CurPage | urlConcat $.url "page" }}{{end}}">
|
||||
<i class="fa fa-chevron-left">
|
||||
</i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{{range $i := N 1 .pageInfo.TotalPage}}
|
||||
{{if eq $i $.pageInfo.CurPage}}
|
||||
<li class="active">
|
||||
<a href="javascript:;">
|
||||
{{$i}}
|
||||
</a>
|
||||
</li>
|
||||
{{else}}
|
||||
<li class="">
|
||||
<a href="{{urlConcat $.url "page" $i}}">
|
||||
{{$i}}
|
||||
</a>
|
||||
</li>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
<li class="{{if eq .pageInfo.CurPage .pageInfo.TotalPage}}disabled{{end}}" >
|
||||
<a href="{{if eq .pageInfo.CurPage .pageInfo.TotalPage}}javascript:;{{else}}{{add $.pageInfo.CurPage | urlConcat $.url "page" }}{{end}}">
|
||||
<i class="fa fa-chevron-right">
|
||||
</i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user