init
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
*.DS_Store
|
||||
imququ
|
||||
vendor
|
||||
*.exe
|
||||
eiblog
|
||||
conf/certs/*
|
||||
0
.travis.yml
Normal file
0
CHANGELOG.md
Normal file
13
Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM ubuntu:trusty
|
||||
MAINTAINER deepzz <deepzz.qi@gmail.com>
|
||||
|
||||
ADD conf /eiblog/conf
|
||||
ADD static /eiblog/static
|
||||
ADD views /eiblog/views
|
||||
ADD eiblog /eiblog/eiblog
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
WORKDIR /eiblog
|
||||
ENTRYPOINT ["./eiblog"]
|
||||
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Manuel Martínez-Almeida
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
390
api.go
Normal file
@@ -0,0 +1,390 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/EiBlog/eiblog/setting"
|
||||
"github.com/EiBlog/utils/logd"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
const (
|
||||
NOTICE_SUCCESS = "success"
|
||||
NOTICE_NOTICE = "notice"
|
||||
NOTICE_ERROR = "error"
|
||||
)
|
||||
|
||||
var APIs = make(map[string]func(c *gin.Context))
|
||||
|
||||
func init() {
|
||||
// 更新账号信息
|
||||
APIs["account"] = apiAccount
|
||||
// 更新博客信息
|
||||
APIs["blog"] = apiBlog
|
||||
// 更新密码
|
||||
APIs["password"] = apiPassword
|
||||
// 删除文章
|
||||
APIs["post-delete"] = apiPostDelete
|
||||
APIs["post-add"] = apiPostAdd
|
||||
// 专题
|
||||
APIs["serie-delete"] = apiSerieDelete
|
||||
APIs["serie-add"] = apiSerieAdd
|
||||
APIs["serie-sort"] = apiSerieSort
|
||||
// xx箱
|
||||
APIs["draft-delete"] = apiDraftDelete
|
||||
APIs["trash-delete"] = apiTrashDelete
|
||||
APIs["trash-recover"] = apiTrashRecover
|
||||
}
|
||||
|
||||
func apiAccount(c *gin.Context) {
|
||||
e := c.PostForm("email")
|
||||
pn := c.PostForm("phoneNumber")
|
||||
ad := c.PostForm("address")
|
||||
logd.Debug(e, pn, ad)
|
||||
if (e != "" && !CheckEmail(e)) || (pn != "" && !CheckSMS(pn)) {
|
||||
responseNotice(c, NOTICE_NOTICE, "参数错误", "")
|
||||
return
|
||||
}
|
||||
Ei.Email = e
|
||||
Ei.PhoneN = pn
|
||||
Ei.Address = ad
|
||||
err := UpdateAccountField(bson.M{"$set": bson.M{"email": e, "phonen": pn, "address": ad}})
|
||||
if err != nil {
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
responseNotice(c, NOTICE_SUCCESS, "更新成功", "")
|
||||
}
|
||||
|
||||
func apiBlog(c *gin.Context) {
|
||||
bn := c.PostForm("blogName")
|
||||
bt := c.PostForm("bTitle")
|
||||
ba := c.PostForm("beiAn")
|
||||
st := c.PostForm("subTitle")
|
||||
ss := c.PostForm("seriessay")
|
||||
as := c.PostForm("archivessay")
|
||||
if bn == "" || bt == "" {
|
||||
responseNotice(c, NOTICE_NOTICE, "参数错误", "")
|
||||
return
|
||||
}
|
||||
Ei.BlogName = bn
|
||||
Ei.BTitle = bt
|
||||
Ei.BeiAn = ba
|
||||
Ei.SubTitle = st
|
||||
Ei.SeriesSay = ss
|
||||
Ei.ArchivesSay = as
|
||||
err := UpdateAccountField(bson.M{"$set": bson.M{"blogger.blogname": bn, "blogger.btitle": bt, "blogger.beian": ba, "blogger.subtitle": st, "blogger.seriessay": ss, "blogger.archivessay": as}})
|
||||
if err != nil {
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
Ei.CH <- SERIES_MD
|
||||
Ei.CH <- ARCHIVE_MD
|
||||
responseNotice(c, NOTICE_SUCCESS, "更新成功", "")
|
||||
}
|
||||
|
||||
func apiPassword(c *gin.Context) {
|
||||
logd.Debug(c.Request.PostForm.Encode())
|
||||
od := c.PostForm("old")
|
||||
nw := c.PostForm("new")
|
||||
cf := c.PostForm("confirm")
|
||||
if nw != cf {
|
||||
responseNotice(c, NOTICE_NOTICE, "两次密码输入不一致", "")
|
||||
return
|
||||
}
|
||||
if !CheckPwd(nw) {
|
||||
responseNotice(c, NOTICE_NOTICE, "密码格式错误", "")
|
||||
return
|
||||
}
|
||||
if !VerifyPasswd(Ei.Password, Ei.BlogName, od) {
|
||||
responseNotice(c, NOTICE_NOTICE, "原始密码不正确", "")
|
||||
return
|
||||
}
|
||||
Ei.Password = EncryptPasswd(Ei.BlogName, nw)
|
||||
responseNotice(c, NOTICE_SUCCESS, "更改成功", "")
|
||||
}
|
||||
|
||||
func apiPostDelete(c *gin.Context) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
responseNotice(c, NOTICE_SUCCESS, "删除成功", "")
|
||||
}()
|
||||
err = c.Request.ParseForm()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var ids []int32
|
||||
var i int
|
||||
for _, v := range c.Request.PostForm["cid[]"] {
|
||||
i, err = strconv.Atoi(v)
|
||||
if err != nil || i < 1 {
|
||||
err = errors.New("参数错误")
|
||||
return
|
||||
}
|
||||
ids = append(ids, int32(i))
|
||||
}
|
||||
err = DelArticles(ids...)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// elasticsearch 删除索引
|
||||
err = ElasticDelIndex(ids)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func apiPostAdd(c *gin.Context) {
|
||||
var err error
|
||||
var publish bool
|
||||
var cid int
|
||||
defer func() {
|
||||
if !publish {
|
||||
// TODO 返回cid, success改为0
|
||||
// {"success":1,"time":"10:40:46 AM","cid":"4"}
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": FAIL, "time": time.Now().Format("15:04:05 PM"), "cid": cid})
|
||||
} else {
|
||||
c.JSON(http.StatusOK, gin.H{"success": SUCCESS, "time": time.Now().Format("15:04:05 PM"), "cid": cid})
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
|
||||
} else {
|
||||
c.Redirect(http.StatusFound, "/admin/posts")
|
||||
}
|
||||
}()
|
||||
do := c.PostForm("do") // save or publish
|
||||
slug := c.PostForm("slug")
|
||||
title := c.PostForm("title")
|
||||
text := c.PostForm("text")
|
||||
date := c.PostForm("date")
|
||||
serie := c.PostForm("serie")
|
||||
tag := c.PostForm("tags")
|
||||
if title == "" || text == "" || slug == "" {
|
||||
err = errors.New("参数错误")
|
||||
return
|
||||
}
|
||||
var tags []string
|
||||
if tag != "" {
|
||||
tags = strings.Split(tag, ",")
|
||||
}
|
||||
t := CheckDate(date)
|
||||
serieid := CheckSerieID(serie)
|
||||
publish = CheckPublish(do)
|
||||
if cid, err = strconv.Atoi(c.PostForm("cid")); err != nil || cid < 1 {
|
||||
artc := &Article{
|
||||
Title: title,
|
||||
Content: text,
|
||||
Slug: slug,
|
||||
CreateTime: t,
|
||||
IsDraft: !publish,
|
||||
Author: Ei.Username,
|
||||
SerieID: serieid,
|
||||
Tags: tags,
|
||||
}
|
||||
err = AddArticle(artc)
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
return
|
||||
}
|
||||
cid = int(artc.ID)
|
||||
if publish {
|
||||
ElasticIndex(artc)
|
||||
}
|
||||
} else {
|
||||
artc := QueryArticle(int32(cid))
|
||||
if artc == nil {
|
||||
err = errors.New("没有发现该文章")
|
||||
return
|
||||
}
|
||||
if publish {
|
||||
if Ei.MapArticles[artc.Slug] != nil {
|
||||
i, a := GetArticle(artc.ID)
|
||||
DelFromLinkedList(a)
|
||||
Ei.Articles[i] = artc
|
||||
if a.SerieID != serieid {
|
||||
ManageSeriesArticle(a, false, DELETE)
|
||||
}
|
||||
if strings.Join(a.Tags, ",") != tag {
|
||||
ManageTagsArticle(a, false, DELETE)
|
||||
}
|
||||
ManageArchivesArticle(a, false, DELETE)
|
||||
} else {
|
||||
Ei.Articles = append(Ei.Articles, artc)
|
||||
artc.IsDraft = false
|
||||
}
|
||||
Ei.MapArticles[artc.Slug] = artc
|
||||
}
|
||||
artc.Title = title
|
||||
artc.Slug = slug
|
||||
artc.Content = text
|
||||
artc.CreateTime = t
|
||||
artc.UpdateTime = time.Now()
|
||||
artc.SerieID = serieid
|
||||
artc.Tags = tags
|
||||
err = UpdateArticle(bson.M{"id": artc.ID}, artc)
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
return
|
||||
}
|
||||
if publish {
|
||||
sort.Sort(Ei.Articles)
|
||||
GenerateExcerptAndRender(artc)
|
||||
// elasticsearch 索引
|
||||
ElasticIndex(artc)
|
||||
if artc.ID >= setting.Conf.StartID {
|
||||
ManageTagsArticle(artc, true, ADD)
|
||||
ManageSeriesArticle(artc, true, ADD)
|
||||
ManageArchivesArticle(artc, true, ADD)
|
||||
AddToLinkedList(artc.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func apiSerieDelete(c *gin.Context) {
|
||||
err := c.Request.ParseForm()
|
||||
if err != nil {
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
// 只能逐一删除
|
||||
for _, v := range c.Request.PostForm["mid[]"] {
|
||||
id, err := strconv.Atoi(v)
|
||||
if err != nil || id < 1 {
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
err = DelSerie(int32(id))
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
}
|
||||
responseNotice(c, NOTICE_SUCCESS, "删除成功", "")
|
||||
}
|
||||
|
||||
func apiSerieAdd(c *gin.Context) {
|
||||
name := c.PostForm("name")
|
||||
slug := c.PostForm("slug")
|
||||
desc := c.PostForm("description")
|
||||
if name == "" || slug == "" || desc == "" {
|
||||
responseNotice(c, NOTICE_NOTICE, "参数错误", "")
|
||||
return
|
||||
}
|
||||
err := AddSerie(name, slug, desc)
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
responseNotice(c, NOTICE_SUCCESS, "添加成功", "")
|
||||
}
|
||||
|
||||
// 暂未启用
|
||||
func apiSerieSort(c *gin.Context) {
|
||||
err := c.Request.ParseForm()
|
||||
if err != nil {
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
v := c.Request.PostForm["mid[]"]
|
||||
logd.Debug(v)
|
||||
}
|
||||
|
||||
func apiDraftDelete(c *gin.Context) {
|
||||
err := c.Request.ParseForm()
|
||||
if err != nil {
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
for _, v := range c.Request.PostForm["mid[]"] {
|
||||
i, err := strconv.Atoi(v)
|
||||
if err != nil || i < 1 {
|
||||
responseNotice(c, NOTICE_NOTICE, "参数错误", "")
|
||||
return
|
||||
}
|
||||
err = RemoveArticle(int32(i))
|
||||
if err != nil {
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
}
|
||||
responseNotice(c, NOTICE_SUCCESS, "删除成功", "")
|
||||
}
|
||||
|
||||
func apiTrashDelete(c *gin.Context) {
|
||||
logd.Debug(c.PostForm("key"))
|
||||
logd.Debug(c.Request.PostForm)
|
||||
err := c.Request.ParseForm()
|
||||
if err != nil {
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
for _, v := range c.Request.PostForm["mid[]"] {
|
||||
i, err := strconv.Atoi(v)
|
||||
if err != nil || i < 1 {
|
||||
responseNotice(c, NOTICE_NOTICE, "参数错误", "")
|
||||
return
|
||||
}
|
||||
err = RemoveArticle(int32(i))
|
||||
if err != nil {
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
}
|
||||
c.JSON(http.StatusOK, nil)
|
||||
responseNotice(c, NOTICE_SUCCESS, "删除成功", "")
|
||||
}
|
||||
|
||||
func apiTrashRecover(c *gin.Context) {
|
||||
logd.Debug(c.PostForm("key"))
|
||||
logd.Debug(c.Request.PostForm)
|
||||
err := c.Request.ParseForm()
|
||||
if err != nil {
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
for _, v := range c.Request.PostForm["mid[]"] {
|
||||
i, err := strconv.Atoi(v)
|
||||
if err != nil || i < 1 {
|
||||
responseNotice(c, NOTICE_NOTICE, "参数错误", "")
|
||||
return
|
||||
|
||||
}
|
||||
err = RecoverArticle(int32(i))
|
||||
if err != nil {
|
||||
responseNotice(c, NOTICE_NOTICE, err.Error(), "")
|
||||
return
|
||||
}
|
||||
}
|
||||
responseNotice(c, NOTICE_SUCCESS, "恢复成功", "")
|
||||
}
|
||||
|
||||
func responseNotice(c *gin.Context, typ, content, hl string) {
|
||||
domain := runmode.Domain
|
||||
if i := strings.Index(domain, ":"); i > -1 {
|
||||
domain = domain[0:i]
|
||||
}
|
||||
if hl != "" {
|
||||
c.SetCookie("notice_highlight", hl, 86400, "/", domain, runmode.EnableHttps, false)
|
||||
}
|
||||
c.SetCookie("notice_type", typ, 86400, "/", domain, runmode.EnableHttps, false)
|
||||
c.SetCookie("notice", fmt.Sprintf("[\"%s\"]", content), 86400, "/", domain, runmode.EnableHttps, false)
|
||||
c.Redirect(http.StatusFound, c.Request.Referer())
|
||||
}
|
||||
277
back.go
Normal file
@@ -0,0 +1,277 @@
|
||||
// Package main provides ...
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/EiBlog/eiblog/setting"
|
||||
"github.com/EiBlog/utils/logd"
|
||||
"github.com/gin-gonic/contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
func AuthFilter() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// TODO 过滤登录
|
||||
session := sessions.Default(c)
|
||||
v := session.Get("username")
|
||||
if v == nil {
|
||||
c.Abort()
|
||||
c.Redirect(http.StatusFound, "/admin/login")
|
||||
return
|
||||
}
|
||||
if v.(string) != Ei.Username {
|
||||
c.Abort()
|
||||
c.Redirect(http.StatusFound, "/admin/login")
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// 登录界面
|
||||
func HandleLogin(c *gin.Context) {
|
||||
logout := c.Query("logout")
|
||||
if logout == "true" {
|
||||
session := sessions.Default(c)
|
||||
session.Delete("username")
|
||||
session.Save()
|
||||
}
|
||||
c.HTML(http.StatusOK, "login.html", gin.H{
|
||||
"BTitle": Ei.BTitle,
|
||||
})
|
||||
}
|
||||
|
||||
func HandleLoginPost(c *gin.Context) {
|
||||
user := c.PostForm("user")
|
||||
pwd := c.PostForm("password")
|
||||
// code := c.PostForm("code") // 二次验证
|
||||
if user == "" || pwd == "" {
|
||||
logd.Info("参数错误", user, pwd)
|
||||
c.Redirect(http.StatusFound, "/admin/login")
|
||||
return
|
||||
}
|
||||
if Ei.Username != user || !VerifyPasswd(Ei.Password, user, pwd) {
|
||||
logd.Info("账号或密码错误", user, pwd)
|
||||
c.Redirect(http.StatusFound, "/admin/login")
|
||||
return
|
||||
}
|
||||
session := sessions.Default(c)
|
||||
session.Set("username", user)
|
||||
session.Save()
|
||||
Ei.LoginIP = c.ClientIP()
|
||||
Ei.LoginTime = time.Now()
|
||||
UpdateAccountField(bson.M{"$set": bson.M{"loginip": Ei.LoginIP, "logintime": Ei.LoginTime}})
|
||||
c.Redirect(http.StatusFound, "/admin/profile")
|
||||
}
|
||||
|
||||
func GetBack() gin.H {
|
||||
return gin.H{"Author": Ei.Username}
|
||||
}
|
||||
|
||||
// 个人配置
|
||||
func HandleProfile(c *gin.Context) {
|
||||
h := GetBack()
|
||||
h["Console"] = true
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["Title"] = "个人配置 | " + Ei.BTitle
|
||||
h["Account"] = Ei
|
||||
h["Profile"] = true
|
||||
c.HTML(http.StatusOK, "backLayout.html", h)
|
||||
}
|
||||
|
||||
// 插件
|
||||
func HandlePlugins(c *gin.Context) {
|
||||
h := GetBack()
|
||||
h["Console"] = true
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["Title"] = "插件管理 | " + Ei.BTitle
|
||||
c.HTML(http.StatusOK, "backLayout.html", h)
|
||||
}
|
||||
|
||||
// 主题
|
||||
func HandleThemes(c *gin.Context) {
|
||||
h := GetBack()
|
||||
h["Console"] = true
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["Title"] = "主题管理 | " + Ei.BTitle
|
||||
c.HTML(http.StatusOK, "backLayout.html", h)
|
||||
}
|
||||
|
||||
// 写文章==>Write
|
||||
func HandlePost(c *gin.Context) {
|
||||
h := GetBack()
|
||||
id, err := strconv.Atoi(c.Query("cid"))
|
||||
if artc := QueryArticle(int32(id)); err == nil && id > 0 && artc != nil {
|
||||
h["Title"] = "编辑文章 | " + Ei.BTitle
|
||||
h["Edit"] = artc
|
||||
} else {
|
||||
h["Title"] = "撰写文章 | " + Ei.BTitle
|
||||
}
|
||||
h["Post"] = true
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["Title"] = "撰写文章 | " + Ei.BTitle
|
||||
h["Domain"] = runmode.Domain
|
||||
h["Series"] = Ei.Series
|
||||
c.HTML(http.StatusOK, "backLayout.html", h)
|
||||
}
|
||||
|
||||
func HandleDraftDelete(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Query("cid"))
|
||||
if err != nil || id < 1 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
|
||||
return
|
||||
}
|
||||
if err = RemoveArticle(int32(id)); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "删除错误"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, nil)
|
||||
}
|
||||
|
||||
// 文章管理==>Manage
|
||||
func HandlePosts(c *gin.Context) {
|
||||
kw := c.Query("keywords")
|
||||
tmp := c.Query("serie")
|
||||
se, err := strconv.Atoi(tmp)
|
||||
if err != nil || se < 1 {
|
||||
se = 0
|
||||
}
|
||||
pg, err := strconv.Atoi(c.Query("page"))
|
||||
if err != nil || pg < 1 {
|
||||
pg = 1
|
||||
}
|
||||
vals := c.Request.URL.Query()
|
||||
h := GetBack()
|
||||
h["Manage"] = true
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["Title"] = "文章管理 | " + Ei.BTitle
|
||||
h["Posts"] = true
|
||||
h["Series"] = Ei.Series
|
||||
h["Serie"] = se
|
||||
h["KW"] = kw
|
||||
var max int
|
||||
max, h["List"] = PageListBack(se, kw, false, false, pg, setting.Conf.PageSize)
|
||||
if pg < max {
|
||||
vals.Set("page", fmt.Sprint(pg+1))
|
||||
h["Next"] = vals.Encode()
|
||||
}
|
||||
if pg > 1 {
|
||||
vals.Set("page", fmt.Sprint(pg-1))
|
||||
h["Prev"] = vals.Encode()
|
||||
}
|
||||
h["PP"] = make(map[int]string, max)
|
||||
for i := 0; i < max; i++ {
|
||||
vals.Set("page", fmt.Sprint(i+1))
|
||||
h["PP"].(map[int]string)[i+1] = vals.Encode()
|
||||
}
|
||||
h["Cur"] = pg
|
||||
c.HTML(http.StatusOK, "backLayout.html", h)
|
||||
}
|
||||
|
||||
// 专题列表
|
||||
func HandleSeries(c *gin.Context) {
|
||||
h := GetBack()
|
||||
h["Manage"] = true
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["Title"] = "专题管理 | " + Ei.BTitle
|
||||
h["Series"] = true
|
||||
h["List"] = Ei.Series
|
||||
c.HTML(http.StatusOK, "backLayout.html", h)
|
||||
}
|
||||
|
||||
func HandleSerie(c *gin.Context) {
|
||||
h := GetBack()
|
||||
id, err := strconv.Atoi(c.Query("mid"))
|
||||
if serie := QuerySerie(int32(id)); err == nil && id > 0 && serie != nil {
|
||||
h["Title"] = "编辑专题 | " + Ei.BTitle
|
||||
h["Edit"] = serie
|
||||
} else {
|
||||
h["Title"] = "新增专题 | " + Ei.BTitle
|
||||
}
|
||||
h["Manage"] = true
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["Serie"] = true
|
||||
c.HTML(http.StatusOK, "backLayout.html", h)
|
||||
}
|
||||
|
||||
// 标签列表
|
||||
func HandleTags(c *gin.Context) {
|
||||
h := GetBack()
|
||||
h["Manage"] = true
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["Title"] = "标签管理 | " + Ei.BTitle
|
||||
h["Tags"] = true
|
||||
h["List"] = Ei.Tags
|
||||
c.HTML(http.StatusOK, "backLayout.html", h)
|
||||
}
|
||||
|
||||
// 草稿箱
|
||||
func HandleDraft(c *gin.Context) {
|
||||
h := GetBack()
|
||||
h["Manage"] = true
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["Title"] = "草稿箱 | " + Ei.BTitle
|
||||
h["Draft"] = true
|
||||
var err error
|
||||
h["List"], err = LoadDraft()
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
c.HTML(http.StatusBadRequest, "backLayout.html", h)
|
||||
return
|
||||
}
|
||||
c.HTML(http.StatusOK, "backLayout.html", h)
|
||||
}
|
||||
|
||||
// 回收箱
|
||||
func HandleTrash(c *gin.Context) {
|
||||
h := GetBack()
|
||||
h["Manage"] = true
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["Title"] = "回收箱 | " + Ei.BTitle
|
||||
h["Trash"] = true
|
||||
var err error
|
||||
h["List"], err = LoadTrash()
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
c.HTML(http.StatusBadRequest, "backLayout.html", h)
|
||||
return
|
||||
}
|
||||
c.HTML(http.StatusOK, "backLayout.html", h)
|
||||
}
|
||||
|
||||
// 基本设置==>Setting
|
||||
func HandleGeneral(c *gin.Context) {
|
||||
h := GetBack()
|
||||
h["Setting"] = true
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["Title"] = "基本设置 | " + Ei.BTitle
|
||||
h["General"] = true
|
||||
c.HTML(http.StatusOK, "backLayout.html", h)
|
||||
}
|
||||
|
||||
// 阅读设置
|
||||
func HandleDiscussion(c *gin.Context) {
|
||||
h := GetBack()
|
||||
h["Setting"] = true
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["Title"] = "阅读设置 | " + Ei.BTitle
|
||||
h["Discussion"] = true
|
||||
c.HTML(http.StatusOK, "backLayout.html", h)
|
||||
}
|
||||
|
||||
// api
|
||||
func HandleAPI(c *gin.Context) {
|
||||
action := c.Param("action")
|
||||
logd.Debug("action=======>", action)
|
||||
api := APIs[action]
|
||||
if api == nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Invalid API Request"})
|
||||
return
|
||||
}
|
||||
api(c)
|
||||
}
|
||||
18
build_docker.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
echo "go build..."
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build && \
|
||||
mkdir tmp && \
|
||||
cp -a conf tmp/conf && \
|
||||
cp -a static tmp/static && \
|
||||
cp -a views tmp/views && \
|
||||
cp eiblog tmp/eiblog && \
|
||||
cp Dockerfile tmp/Dockerfile && \
|
||||
cd tmp && \
|
||||
domain="registry.cn-hangzhou.aliyuncs.com" && \
|
||||
docker build -t $domain/deepzz/eiblog . && \
|
||||
read -p "是否上传到服务器(y/n):" word && \
|
||||
if [ $word = "y" ] ;then
|
||||
docker push $domain/deepzz/eiblog
|
||||
fi
|
||||
cd ..
|
||||
rm -rf tmp
|
||||
48
check.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func CheckEmail(e string) bool {
|
||||
reg := regexp.MustCompile(`^(\w)+([\.\-]\w+)*#(\w)+((\.\w+)+)$`)
|
||||
return reg.MatchString(e)
|
||||
}
|
||||
|
||||
func CheckDomain(domain string) bool {
|
||||
reg := regexp.MustCompile(`^(http://|https://)?[0-9a-zA-Z]+[0-9a-zA-Z\.-]*\.[a-zA-Z]{2,4}$`)
|
||||
return reg.MatchString(domain)
|
||||
}
|
||||
|
||||
func CheckSMS(sms string) bool {
|
||||
reg := regexp.MustCompile(`^\+\d+$`)
|
||||
return reg.MatchString(sms)
|
||||
}
|
||||
|
||||
func CheckPwd(pwd string) bool {
|
||||
return len(pwd) > 5 && len(pwd) < 19
|
||||
}
|
||||
|
||||
func CheckDate(date string) time.Time {
|
||||
if t, err := time.Parse("2006-01-02 15:04", date); err == nil {
|
||||
return t
|
||||
}
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
func CheckSerieID(sid string) int32 {
|
||||
if id, err := strconv.Atoi(sid); err == nil {
|
||||
return int32(id)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func CheckBool(str string) bool {
|
||||
return str == "true"
|
||||
}
|
||||
|
||||
func CheckPublish(do string) bool {
|
||||
return do == "publish"
|
||||
}
|
||||
29
check_test.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCheckEmail(t *testing.T) {
|
||||
e := "xx@email.com"
|
||||
e1 := "xxxxemail.com"
|
||||
e2 := "xxx#email.com"
|
||||
|
||||
t.Log(CheckEmail(e))
|
||||
t.Log(CheckEmail(e1))
|
||||
t.Log(CheckEmail(e2))
|
||||
}
|
||||
|
||||
func TestCheckDomain(t *testing.T) {
|
||||
d := "123.com"
|
||||
d1 := "http://123.com"
|
||||
d2 := "https://123.com"
|
||||
d3 := "123#.com"
|
||||
d4 := "123.coooom"
|
||||
|
||||
t.Log(CheckDomain(d))
|
||||
t.Log(CheckDomain(d1))
|
||||
t.Log(CheckDomain(d1))
|
||||
t.Log(CheckDomain(d1))
|
||||
t.Log(CheckDomain(d4))
|
||||
}
|
||||
76
conf/app.yml
Normal file
@@ -0,0 +1,76 @@
|
||||
# 静态文件版本
|
||||
staticversion: 2
|
||||
# 运行模式 dev or prod
|
||||
runmode: dev
|
||||
# 回收箱保留48小时
|
||||
trash: -48
|
||||
# 定时清理回收箱,%d小时
|
||||
clean: 12
|
||||
# 首页展示文章数量
|
||||
pagenum: 10
|
||||
# 管理界面
|
||||
pagesize: 20
|
||||
# 自动截取预览, 字符数
|
||||
length: 200
|
||||
# 截取预览标识
|
||||
identifier: <!-- more -->
|
||||
# favicon
|
||||
favicon: //st.deepzz.com/static/img/favicon.png
|
||||
# 起始ID,预留id不时之需, 不用管
|
||||
startid: 11
|
||||
# 静态文件地址, 后台js,css在用, cdn: //domain.com
|
||||
static: //127.0.0.1:8080
|
||||
# elasticsearch url
|
||||
searchurl: http://elasticsearch:9200
|
||||
# 评论相关
|
||||
disqus:
|
||||
shortname: deepzz
|
||||
publickey: wdSgxRm9rdGAlLKFcFdToBe3GT4SibmV7Y8EjJQ0r4GWXeKtxpopMAeIeoI2dTEg
|
||||
url: https://disqus.com/api/3.0/threads/set.json
|
||||
interval: 5
|
||||
# 运行模式
|
||||
modes:
|
||||
dev:
|
||||
# don't modify
|
||||
enablehttp: true
|
||||
httpport: 8080
|
||||
domain: 127.0.0.1:8080
|
||||
prod:
|
||||
# you can fix certfile, keyfile, domain
|
||||
enablehttp: true
|
||||
httpport: 80
|
||||
enablehttps: true
|
||||
httpsport: 443
|
||||
certfile: conf/certs/domain.pem
|
||||
keyfile: conf/certs/domain.key
|
||||
domain: deepzz.com
|
||||
# twitter地址: //twitter.com/chenqijing2
|
||||
twitter: //twitter.com/chenqijing2
|
||||
# rss地址
|
||||
rss: /rss.html
|
||||
# search地址
|
||||
search: /search.html
|
||||
|
||||
# 以下数据初始化用,可在后台修改
|
||||
account:
|
||||
# *后台登录用户名
|
||||
username: deepzz
|
||||
# *登录明文密码
|
||||
password: deepzz
|
||||
# 邮箱,用于通知: chenqijing2#163.com
|
||||
email: chenqijing2#163.com
|
||||
# 手机号, "+8615100000000"
|
||||
phonenumber: "+8615100000000"
|
||||
# 家庭住址
|
||||
address: ""
|
||||
blogger:
|
||||
# left显示名称: Deepzz
|
||||
blogname: Deepzz
|
||||
# 小标题: 不抛弃,不放弃
|
||||
subtitle: 不抛弃,不放弃
|
||||
# 备案号: 蜀 ICP 备 16021362 号
|
||||
beian: 蜀 ICP 备 16021362 号
|
||||
# footer显示名称及tab标题: Deepzz's Blog
|
||||
btitle: Deepzz's Blog
|
||||
# 版权声明: 本站使用「<a href="//creativecommons.org/licenses/by/4.0/">署名 4.0 国际</a>」创作共享协议,转载请注明作者及原网址。
|
||||
copyright: 本站使用「<a href="//creativecommons.org/licenses/by/4.0/">署名 4.0 国际</a>」创作共享协议,转载请注明作者及原网址。
|
||||
0
conf/blackip.yml
Normal file
3
conf/es/config/analysis/synonym.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
ua,user-agent,userAgent
|
||||
js,javascript
|
||||
谷歌=>google
|
||||
17
conf/es/config/elasticsearch.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
network.host: 0.0.0.0
|
||||
|
||||
index:
|
||||
analysis:
|
||||
analyzer:
|
||||
ik_syno:
|
||||
type: custom
|
||||
tokenizer: ik_max_word
|
||||
filter: [my_synonym_filter]
|
||||
ik_syno_smart:
|
||||
type: custom
|
||||
tokenizer: ik_smart
|
||||
filter: [my_synonym_filter]
|
||||
filter:
|
||||
my_synonym_filter:
|
||||
type: synonym
|
||||
synonyms_path: analysis/synonym.txt
|
||||
15
conf/es/config/logging.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
# you can override this using by setting a system property, for example -Des.logger.level=DEBUG
|
||||
es.logger.level: INFO
|
||||
rootLogger: ${es.logger.level}, console
|
||||
logger:
|
||||
# log action execution errors for easier debugging
|
||||
action: DEBUG
|
||||
# reduce the logging for aws, too much is logged under the default INFO
|
||||
com.amazonaws: WARN
|
||||
|
||||
appender:
|
||||
console:
|
||||
type: console
|
||||
layout:
|
||||
type: consolePattern
|
||||
conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n"
|
||||
BIN
conf/es/plugins/ik1.10.0/commons-codec-1.9.jar
Normal file
BIN
conf/es/plugins/ik1.10.0/commons-logging-1.2.jar
Normal file
13
conf/es/plugins/ik1.10.0/config/IKAnalyzer.cfg.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
|
||||
<properties>
|
||||
<comment>IK Analyzer 扩展配置</comment>
|
||||
<!--用户可以在这里配置自己的扩展字典 -->
|
||||
<entry key="ext_dict">custom/mydict.dic;custom/single_word_low_freq.dic</entry>
|
||||
<!--用户可以在这里配置自己的扩展停止词字典-->
|
||||
<entry key="ext_stopwords">custom/ext_stopword.dic</entry>
|
||||
<!--用户可以在这里配置远程扩展字典 -->
|
||||
<!-- <entry key="remote_ext_dict">words_location</entry> -->
|
||||
<!--用户可以在这里配置远程扩展停止词字典-->
|
||||
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
|
||||
</properties>
|
||||
31
conf/es/plugins/ik1.10.0/config/custom/ext_stopword.dic
Normal file
@@ -0,0 +1,31 @@
|
||||
也
|
||||
了
|
||||
仍
|
||||
从
|
||||
以
|
||||
使
|
||||
则
|
||||
却
|
||||
又
|
||||
及
|
||||
对
|
||||
就
|
||||
并
|
||||
很
|
||||
或
|
||||
把
|
||||
是
|
||||
的
|
||||
着
|
||||
给
|
||||
而
|
||||
被
|
||||
让
|
||||
在
|
||||
还
|
||||
比
|
||||
等
|
||||
当
|
||||
与
|
||||
于
|
||||
但
|
||||
14
conf/es/plugins/ik1.10.0/config/custom/mydict.dic
Normal file
@@ -0,0 +1,14 @@
|
||||
medcl
|
||||
elastic
|
||||
elasticsearch
|
||||
kogstash
|
||||
kibana
|
||||
marvel
|
||||
shield
|
||||
watcher
|
||||
beats
|
||||
packetbeat
|
||||
filebeat
|
||||
topbeat
|
||||
metrixbeat
|
||||
kimchy
|
||||
12638
conf/es/plugins/ik1.10.0/config/custom/single_word.dic
Normal file
12638
conf/es/plugins/ik1.10.0/config/custom/single_word_full.dic
Normal file
2714
conf/es/plugins/ik1.10.0/config/custom/single_word_low_freq.dic
Normal file
398716
conf/es/plugins/ik1.10.0/config/custom/sougou.dic
Normal file
275909
conf/es/plugins/ik1.10.0/config/main.dic
Normal file
25
conf/es/plugins/ik1.10.0/config/preposition.dic
Normal file
@@ -0,0 +1,25 @@
|
||||
不
|
||||
也
|
||||
了
|
||||
仍
|
||||
从
|
||||
以
|
||||
使
|
||||
则
|
||||
却
|
||||
又
|
||||
及
|
||||
对
|
||||
就
|
||||
并
|
||||
很
|
||||
或
|
||||
把
|
||||
是
|
||||
的
|
||||
着
|
||||
给
|
||||
而
|
||||
被
|
||||
让
|
||||
但
|
||||
316
conf/es/plugins/ik1.10.0/config/quantifier.dic
Normal file
@@ -0,0 +1,316 @@
|
||||
丈
|
||||
下
|
||||
世
|
||||
世纪
|
||||
两
|
||||
个
|
||||
中
|
||||
串
|
||||
亩
|
||||
人
|
||||
介
|
||||
付
|
||||
代
|
||||
件
|
||||
任
|
||||
份
|
||||
伏
|
||||
伙
|
||||
位
|
||||
位数
|
||||
例
|
||||
倍
|
||||
像素
|
||||
元
|
||||
克
|
||||
克拉
|
||||
公亩
|
||||
公克
|
||||
公分
|
||||
公升
|
||||
公尺
|
||||
公担
|
||||
公斤
|
||||
公里
|
||||
公顷
|
||||
具
|
||||
册
|
||||
出
|
||||
刀
|
||||
分
|
||||
分钟
|
||||
分米
|
||||
划
|
||||
列
|
||||
则
|
||||
刻
|
||||
剂
|
||||
剑
|
||||
副
|
||||
加仑
|
||||
勺
|
||||
包
|
||||
匙
|
||||
匹
|
||||
区
|
||||
千克
|
||||
千米
|
||||
升
|
||||
卷
|
||||
厅
|
||||
厘
|
||||
厘米
|
||||
双
|
||||
发
|
||||
口
|
||||
句
|
||||
只
|
||||
台
|
||||
叶
|
||||
号
|
||||
名
|
||||
吨
|
||||
听
|
||||
员
|
||||
周
|
||||
周年
|
||||
品
|
||||
回
|
||||
团
|
||||
圆
|
||||
圈
|
||||
地
|
||||
场
|
||||
块
|
||||
坪
|
||||
堆
|
||||
声
|
||||
壶
|
||||
处
|
||||
夜
|
||||
大
|
||||
天
|
||||
头
|
||||
套
|
||||
女
|
||||
孔
|
||||
字
|
||||
宗
|
||||
室
|
||||
家
|
||||
寸
|
||||
对
|
||||
封
|
||||
尊
|
||||
小时
|
||||
尺
|
||||
尾
|
||||
局
|
||||
层
|
||||
届
|
||||
岁
|
||||
师
|
||||
帧
|
||||
幅
|
||||
幕
|
||||
幢
|
||||
平方
|
||||
平方公尺
|
||||
平方公里
|
||||
平方分米
|
||||
平方厘米
|
||||
平方码
|
||||
平方米
|
||||
平方英寸
|
||||
平方英尺
|
||||
平方英里
|
||||
平米
|
||||
年
|
||||
年代
|
||||
年级
|
||||
度
|
||||
座
|
||||
式
|
||||
引
|
||||
张
|
||||
成
|
||||
战
|
||||
截
|
||||
户
|
||||
房
|
||||
所
|
||||
扇
|
||||
手
|
||||
打
|
||||
批
|
||||
把
|
||||
折
|
||||
担
|
||||
拍
|
||||
招
|
||||
拨
|
||||
拳
|
||||
指
|
||||
掌
|
||||
排
|
||||
撮
|
||||
支
|
||||
文
|
||||
斗
|
||||
斤
|
||||
方
|
||||
族
|
||||
日
|
||||
时
|
||||
曲
|
||||
月
|
||||
月份
|
||||
期
|
||||
本
|
||||
朵
|
||||
村
|
||||
束
|
||||
条
|
||||
来
|
||||
杯
|
||||
枚
|
||||
枝
|
||||
枪
|
||||
架
|
||||
柄
|
||||
柜
|
||||
栋
|
||||
栏
|
||||
株
|
||||
样
|
||||
根
|
||||
格
|
||||
案
|
||||
桌
|
||||
档
|
||||
桩
|
||||
桶
|
||||
梯
|
||||
棵
|
||||
楼
|
||||
次
|
||||
款
|
||||
步
|
||||
段
|
||||
毛
|
||||
毫
|
||||
毫升
|
||||
毫米
|
||||
毫克
|
||||
池
|
||||
洲
|
||||
派
|
||||
海里
|
||||
滴
|
||||
炮
|
||||
点
|
||||
点钟
|
||||
片
|
||||
版
|
||||
环
|
||||
班
|
||||
瓣
|
||||
瓶
|
||||
生
|
||||
男
|
||||
画
|
||||
界
|
||||
盆
|
||||
盎司
|
||||
盏
|
||||
盒
|
||||
盘
|
||||
相
|
||||
眼
|
||||
石
|
||||
码
|
||||
碗
|
||||
碟
|
||||
磅
|
||||
种
|
||||
科
|
||||
秒
|
||||
秒钟
|
||||
窝
|
||||
立方公尺
|
||||
立方分米
|
||||
立方厘米
|
||||
立方码
|
||||
立方米
|
||||
立方英寸
|
||||
立方英尺
|
||||
站
|
||||
章
|
||||
笔
|
||||
等
|
||||
筐
|
||||
筒
|
||||
箱
|
||||
篇
|
||||
篓
|
||||
篮
|
||||
簇
|
||||
米
|
||||
类
|
||||
粒
|
||||
级
|
||||
组
|
||||
维
|
||||
缕
|
||||
缸
|
||||
罐
|
||||
网
|
||||
群
|
||||
股
|
||||
脚
|
||||
船
|
||||
艇
|
||||
艘
|
||||
色
|
||||
节
|
||||
英亩
|
||||
英寸
|
||||
英尺
|
||||
英里
|
||||
行
|
||||
袋
|
||||
角
|
||||
言
|
||||
课
|
||||
起
|
||||
趟
|
||||
路
|
||||
车
|
||||
转
|
||||
轮
|
||||
辆
|
||||
辈
|
||||
连
|
||||
通
|
||||
遍
|
||||
部
|
||||
里
|
||||
重
|
||||
针
|
||||
钟
|
||||
钱
|
||||
锅
|
||||
门
|
||||
间
|
||||
队
|
||||
阶段
|
||||
隅
|
||||
集
|
||||
页
|
||||
顶
|
||||
顷
|
||||
项
|
||||
顿
|
||||
颗
|
||||
餐
|
||||
首
|
||||
33
conf/es/plugins/ik1.10.0/config/stopword.dic
Normal file
@@ -0,0 +1,33 @@
|
||||
a
|
||||
an
|
||||
and
|
||||
are
|
||||
as
|
||||
at
|
||||
be
|
||||
but
|
||||
by
|
||||
for
|
||||
if
|
||||
in
|
||||
into
|
||||
is
|
||||
it
|
||||
no
|
||||
not
|
||||
of
|
||||
on
|
||||
or
|
||||
such
|
||||
that
|
||||
the
|
||||
their
|
||||
then
|
||||
there
|
||||
these
|
||||
they
|
||||
this
|
||||
to
|
||||
was
|
||||
will
|
||||
with
|
||||
37
conf/es/plugins/ik1.10.0/config/suffix.dic
Normal file
@@ -0,0 +1,37 @@
|
||||
乡
|
||||
井
|
||||
亭
|
||||
党
|
||||
区
|
||||
厅
|
||||
县
|
||||
园
|
||||
塔
|
||||
家
|
||||
寺
|
||||
局
|
||||
巷
|
||||
市
|
||||
弄
|
||||
所
|
||||
斯基
|
||||
楼
|
||||
江
|
||||
河
|
||||
海
|
||||
湖
|
||||
省
|
||||
维奇
|
||||
署
|
||||
苑
|
||||
街
|
||||
觀
|
||||
观
|
||||
诺夫
|
||||
路
|
||||
部
|
||||
镇
|
||||
阁
|
||||
山
|
||||
子
|
||||
娃
|
||||
131
conf/es/plugins/ik1.10.0/config/surname.dic
Normal file
@@ -0,0 +1,131 @@
|
||||
丁
|
||||
万
|
||||
万俟
|
||||
上官
|
||||
东方
|
||||
乔
|
||||
于
|
||||
令狐
|
||||
仲孙
|
||||
任
|
||||
何
|
||||
余
|
||||
候
|
||||
傅
|
||||
公冶
|
||||
公孙
|
||||
公羊
|
||||
冯
|
||||
刘
|
||||
单
|
||||
单于
|
||||
卢
|
||||
史
|
||||
叶
|
||||
司徒
|
||||
司空
|
||||
司马
|
||||
吕
|
||||
吴
|
||||
周
|
||||
唐
|
||||
夏
|
||||
夏侯
|
||||
太叔
|
||||
姚
|
||||
姜
|
||||
孔
|
||||
孙
|
||||
孟
|
||||
宇文
|
||||
宋
|
||||
宗政
|
||||
尉迟
|
||||
尹
|
||||
崔
|
||||
常
|
||||
康
|
||||
廖
|
||||
张
|
||||
彭
|
||||
徐
|
||||
慕容
|
||||
戴
|
||||
文
|
||||
方
|
||||
易
|
||||
曹
|
||||
曾
|
||||
朱
|
||||
李
|
||||
杜
|
||||
杨
|
||||
林
|
||||
梁
|
||||
欧阳
|
||||
武
|
||||
段
|
||||
毛
|
||||
江
|
||||
汤
|
||||
沈
|
||||
淳于
|
||||
潘
|
||||
澹台
|
||||
濮阳
|
||||
熊
|
||||
王
|
||||
田
|
||||
申屠
|
||||
白
|
||||
皇甫
|
||||
石
|
||||
秦
|
||||
程
|
||||
罗
|
||||
肖
|
||||
胡
|
||||
苏
|
||||
范
|
||||
董
|
||||
蒋
|
||||
薛
|
||||
袁
|
||||
许
|
||||
诸葛
|
||||
谢
|
||||
谭
|
||||
贺
|
||||
贾
|
||||
赖
|
||||
赫连
|
||||
赵
|
||||
轩辕
|
||||
邓
|
||||
邱
|
||||
邵
|
||||
邹
|
||||
郑
|
||||
郝
|
||||
郭
|
||||
金
|
||||
钟
|
||||
钟离
|
||||
钱
|
||||
长孙
|
||||
闻人
|
||||
闾丘
|
||||
阎
|
||||
陆
|
||||
陈
|
||||
雷
|
||||
韩
|
||||
顾
|
||||
马
|
||||
高
|
||||
魏
|
||||
鲜于
|
||||
黄
|
||||
黎
|
||||
龙
|
||||
龚
|
||||
BIN
conf/es/plugins/ik1.10.0/elasticsearch-analysis-ik-1.10.0.jar
Normal file
BIN
conf/es/plugins/ik1.10.0/httpclient-4.5.2.jar
Normal file
BIN
conf/es/plugins/ik1.10.0/httpcore-4.4.4.jar
Normal file
80
conf/es/plugins/ik1.10.0/plugin-descriptor.properties
Normal file
@@ -0,0 +1,80 @@
|
||||
# Elasticsearch plugin descriptor file
|
||||
# This file must exist as 'plugin-descriptor.properties' at
|
||||
# the root directory of all plugins.
|
||||
#
|
||||
# A plugin can be 'site', 'jvm', or both.
|
||||
#
|
||||
### example site plugin for "foo":
|
||||
#
|
||||
# foo.zip <-- zip file for the plugin, with this structure:
|
||||
# _site/ <-- the contents that will be served
|
||||
# plugin-descriptor.properties <-- example contents below:
|
||||
#
|
||||
# site=true
|
||||
# description=My cool plugin
|
||||
# version=1.0
|
||||
#
|
||||
### example jvm plugin for "foo"
|
||||
#
|
||||
# foo.zip <-- zip file for the plugin, with this structure:
|
||||
# <arbitrary name1>.jar <-- classes, resources, dependencies
|
||||
# <arbitrary nameN>.jar <-- any number of jars
|
||||
# plugin-descriptor.properties <-- example contents below:
|
||||
#
|
||||
# jvm=true
|
||||
# classname=foo.bar.BazPlugin
|
||||
# description=My cool plugin
|
||||
# version=2.0.0-rc1
|
||||
# elasticsearch.version=2.0
|
||||
# java.version=1.7
|
||||
#
|
||||
### mandatory elements for all plugins:
|
||||
#
|
||||
# 'description': simple summary of the plugin
|
||||
description=IK Analyzer for Elasticsearch
|
||||
#
|
||||
# 'version': plugin's version
|
||||
version=1.10.0
|
||||
#
|
||||
# 'name': the plugin name
|
||||
name=analysis-ik
|
||||
|
||||
### mandatory elements for site plugins:
|
||||
#
|
||||
# 'site': set to true to indicate contents of the _site/
|
||||
# directory in the root of the plugin should be served.
|
||||
site=${elasticsearch.plugin.site}
|
||||
#
|
||||
### mandatory elements for jvm plugins :
|
||||
#
|
||||
# 'jvm': true if the 'classname' class should be loaded
|
||||
# from jar files in the root directory of the plugin.
|
||||
# Note that only jar files in the root directory are
|
||||
# added to the classpath for the plugin! If you need
|
||||
# other resources, package them into a resources jar.
|
||||
jvm=true
|
||||
#
|
||||
# 'classname': the name of the class to load, fully-qualified.
|
||||
classname=org.elasticsearch.plugin.analysis.ik.AnalysisIkPlugin
|
||||
#
|
||||
# 'java.version' version of java the code is built against
|
||||
# use the system property java.specification.version
|
||||
# version string must be a sequence of nonnegative decimal integers
|
||||
# separated by "."'s and may have leading zeros
|
||||
java.version=1.7
|
||||
#
|
||||
# 'elasticsearch.version' version of elasticsearch compiled against
|
||||
# You will have to release a new version of the plugin for each new
|
||||
# elasticsearch release. This version is checked when the plugin
|
||||
# is loaded so Elasticsearch will refuse to start in the presence of
|
||||
# plugins with the incorrect elasticsearch.version.
|
||||
elasticsearch.version=2.4.0
|
||||
#
|
||||
### deprecated elements for jvm plugins :
|
||||
#
|
||||
# 'isolated': true if the plugin should have its own classloader.
|
||||
# passing false is deprecated, and only intended to support plugins
|
||||
# that have hard dependencies against each other. If this is
|
||||
# not specified, then the plugin is isolated by default.
|
||||
isolated=${elasticsearch.plugin.isolated}
|
||||
#
|
||||
151
conf/nginx/eiblog.conf
Normal file
@@ -0,0 +1,151 @@
|
||||
server {
|
||||
listen 443 ssl http2 fastopen=3 reuseport;
|
||||
|
||||
server_name www.deepzz.com deepzz.com;
|
||||
server_tokens off;
|
||||
|
||||
include /data/eiblog/nginx/ip.blacklist;
|
||||
|
||||
# https://imququ.com/post/certificate-transparency.html#toc-2
|
||||
# ssl_ct on;
|
||||
# ssl_ct_static_scts /home/jerry/www/scts;
|
||||
|
||||
# 中间证书 + 站点证书
|
||||
ssl_certificate /data/eiblog/conf/certs/chained.pem;
|
||||
|
||||
# 创建 CSR 文件时用的密钥
|
||||
ssl_certificate_key /data/eiblog/conf/certs/domain.key;
|
||||
|
||||
# openssl dhparam -out dhparams.pem 2048
|
||||
# https://weakdh.org/sysadmin.html
|
||||
ssl_dhparam /data/eiblog/conf/ssl/dhparams.pem;
|
||||
|
||||
# https://github.com/cloudflare/sslconfig/blob/master/conf
|
||||
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
|
||||
|
||||
# 如果启用了 RSA + ECDSA 双证书,Cipher Suite 可以参考以下配置:
|
||||
# ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5;
|
||||
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
|
||||
ssl_session_cache shared:SSL:50m;
|
||||
ssl_session_timeout 1d;
|
||||
|
||||
ssl_session_tickets on;
|
||||
|
||||
# openssl rand 48 > session_ticket.key
|
||||
# 单机部署可以不指定 ssl_session_ticket_key
|
||||
ssl_session_ticket_key /data/eiblog/conf/ssl/session_ticket.key;
|
||||
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
|
||||
# 根证书 + 中间证书
|
||||
# https://imququ.com/post/why-can-not-turn-on-ocsp-stapling.html
|
||||
# ssl_trusted_certificate /home/jerry/www/ssl/full_chained.pem;
|
||||
|
||||
resolver 114.114.114.114 valid=300s;
|
||||
resolver_timeout 10s;
|
||||
|
||||
access_log /data/eiblog/log/nginx.log;
|
||||
|
||||
if ($request_method !~ ^(GET|HEAD|POST|OPTIONS)$ ) {
|
||||
return 444;
|
||||
}
|
||||
|
||||
if ($host != 'deepzz.com' ) {
|
||||
rewrite ^/(.*)$ https://deepzz.com/$1 permanent;
|
||||
}
|
||||
|
||||
location ~* (robots\.txt|favicon\.ico|crossdomain\.xml|google4c90d18e696bdcf8\.html|BingSiteAuth\.xml)$ {
|
||||
root /home/jerry/www/imququ.com/www/static;
|
||||
expires 1d;
|
||||
}
|
||||
|
||||
location ^~ /static/uploads/ {
|
||||
root /home/jerry/www/imququ.com/www;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
|
||||
set $expires_time max;
|
||||
|
||||
valid_referers blocked none server_names *.qgy18.com *.inoreader.com feedly.com *.feedly.com www.udpwork.com theoldreader.com digg.com *.feiworks.com *.newszeit.com r.mail.qq.com yuedu.163.com *.w3ctech.com;
|
||||
if ($invalid_referer) {
|
||||
set $expires_time -1;
|
||||
return 403;
|
||||
}
|
||||
|
||||
expires $expires_time;
|
||||
}
|
||||
|
||||
location ^~ /static/ {
|
||||
root /home/jerry/www/imququ.com/www;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
expires max;
|
||||
}
|
||||
|
||||
location ^~ /admin/ {
|
||||
proxy_http_version 1.1;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
|
||||
|
||||
# DENY 将完全不允许页面被嵌套,可能会导致一些异常。如果遇到这样的问题,建议改成 SAMEORIGIN
|
||||
# https://imququ.com/post/web-security-and-response-header.html#toc-1
|
||||
add_header X-Frame-Options DENY;
|
||||
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
|
||||
proxy_set_header X-Via QingDao.Aliyun;
|
||||
proxy_set_header Connection "";
|
||||
proxy_set_header Host imququ.com;
|
||||
proxy_set_header X-Real_IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
proxy_pass http://127.0.0.1:9095;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_http_version 1.1;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
|
||||
add_header X-Frame-Options deny;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header Content-Security-Policy "default-src 'none'; script-src 'unsafe-inline' 'unsafe-eval' blob: https:; img-src data: https: http://ip.qgy18.com; style-src 'unsafe-inline' https:; child-src https:; connect-src 'self' https://translate.googleapis.com; frame-src https://disqus.com https://www.slideshare.net";
|
||||
add_header Public-Key-Pins 'pin-sha256="YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg="; pin-sha256="aef6IF2UF6jNEwA2pNmP7kpgT6NFSdt7Tqf5HzaIGWI="; max-age=2592000; includeSubDomains';
|
||||
add_header Cache-Control no-cache;
|
||||
|
||||
proxy_ignore_headers Set-Cookie;
|
||||
|
||||
proxy_hide_header Vary;
|
||||
proxy_hide_header X-Powered-By;
|
||||
|
||||
proxy_set_header X-Via QingDao.Aliyun;
|
||||
proxy_set_header Connection "";
|
||||
proxy_set_header Host deepzz.com;
|
||||
proxy_set_header X-Real_IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
proxy_pass http://127.0.0.1:9095;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
server_name www.deepzz.com deepzz.com;
|
||||
server_tokens off;
|
||||
|
||||
access_log /dev/null;
|
||||
|
||||
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
|
||||
return 444;
|
||||
}
|
||||
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
alias /home/jerry/www/challenges/;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location / {
|
||||
rewrite ^/(.*)$ https://deepzz.com/$1 permanent;
|
||||
}
|
||||
}
|
||||
95
conf/nginx/nginx.conf
Normal file
@@ -0,0 +1,95 @@
|
||||
user www-data;
|
||||
worker_processes 4;
|
||||
pid /run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 768;
|
||||
# multi_accept on;
|
||||
}
|
||||
|
||||
http {
|
||||
|
||||
##
|
||||
# Basic Settings
|
||||
##
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
# server_tokens off;
|
||||
|
||||
# server_names_hash_bucket_size 64;
|
||||
# server_name_in_redirect off;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
##
|
||||
# Logging Settings
|
||||
##
|
||||
|
||||
access_log /var/log/nginx/access.log;
|
||||
error_log /var/log/nginx/error.log;
|
||||
|
||||
##
|
||||
# Gzip Settings
|
||||
##
|
||||
|
||||
gzip on;
|
||||
gzip_disable "msie6";
|
||||
|
||||
gzip_min_length 1000;
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_http_version 1.1;
|
||||
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;
|
||||
##
|
||||
# nginx-naxsi config
|
||||
##
|
||||
# Uncomment it if you installed nginx-naxsi
|
||||
##
|
||||
|
||||
#include /etc/nginx/naxsi_core.rules;
|
||||
|
||||
##
|
||||
# nginx-passenger config
|
||||
##
|
||||
# Uncomment it if you installed nginx-passenger
|
||||
##
|
||||
|
||||
#passenger_root /usr;
|
||||
#passenger_ruby /usr/bin/ruby;
|
||||
|
||||
##
|
||||
# Virtual Host Configs
|
||||
##
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
include /etc/nginx/sites-enabled/*;
|
||||
}
|
||||
|
||||
|
||||
#mail {
|
||||
# # See sample authentication script at:
|
||||
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
|
||||
#
|
||||
# # auth_http localhost/auth.php;
|
||||
# # pop3_capabilities "TOP" "USER";
|
||||
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
|
||||
#
|
||||
# server {
|
||||
# listen localhost:110;
|
||||
# protocol pop3;
|
||||
# proxy on;
|
||||
# }
|
||||
#
|
||||
# server {
|
||||
# listen localhost:143;
|
||||
# protocol imap;
|
||||
# proxy on;
|
||||
# }
|
||||
#}
|
||||
6
conf/robots.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
Sitemap: https://deepzz.com/sitemap.xml
|
||||
|
||||
User-agent: MJ12bot
|
||||
Disallow: /
|
||||
20
conf/tpl/feedTpl.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>{{.Title}}</title>
|
||||
<link>{{if .EnableHttps}}https://{{else}}http://{{end}}{{.Domain}}</link>
|
||||
<atom:link href="{{if .EnableHttps}}https://{{else}}http://{{end}}{{.Domain}}/feed" rel="self"/>
|
||||
<description>{{.SubTitle}}</description>
|
||||
<language>zh-CN</language>
|
||||
<lastBuildDate>{{.BuildDate}}</lastBuildDate>
|
||||
{{range .Artcs}}
|
||||
<item>
|
||||
<title>{{.Title}}</title>
|
||||
<link>{{if $.EnableHttps}}https://{{else}}http://{{end}}{{$.Domain}}/post/{{.Slug}}.html</link>
|
||||
<comments>{{if $.EnableHttps}}https://{{else}}http://{{end}}{{$.Domain}}/post/{{.Slug}}.html#comments</comments>
|
||||
<guid>{{if $.EnableHttps}}https://{{else}}http://{{end}}{{$.Domain}}/post/{{.Slug}}.html</guid>
|
||||
<description><![CDATA[<blockquote>{{.Content}}]]></description>
|
||||
</item>
|
||||
{{end}}
|
||||
</channel>
|
||||
</rss>
|
||||
10
conf/tpl/sitemapTpl.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
{{range .Artcs}}
|
||||
<url>
|
||||
<loc>{{if $.EnableHttps}}https{{else}}http{{end}}://{{$.Domain}}/post/{{.Slug}}.html</loc>
|
||||
<lastmod>{{dateformat .CreateTime "2006-01-02"}}</lastmod>
|
||||
<priority>0.6</priority>
|
||||
</url>
|
||||
{{end}}
|
||||
</urlset>
|
||||
591
db.go
Normal file
@@ -0,0 +1,591 @@
|
||||
// Package main provides ...
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
// "strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/EiBlog/blackfriday"
|
||||
"github.com/EiBlog/eiblog/helper"
|
||||
"github.com/EiBlog/eiblog/setting"
|
||||
"github.com/EiBlog/utils/logd"
|
||||
db "github.com/EiBlog/utils/mgo"
|
||||
"gopkg.in/mgo.v2"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
const (
|
||||
DB = "eiblog"
|
||||
COLLECTION_ACCOUNT = "account"
|
||||
COLLECTION_ARTICLE = "article"
|
||||
COUNTER_TAG = "tag"
|
||||
COUNTER_SERIE = "serie"
|
||||
COUNTER_ARTICLE = "article"
|
||||
SERIES_MD = "series_md"
|
||||
ARCHIVE_MD = "archive_md"
|
||||
ADD = "add"
|
||||
DELETE = "delete"
|
||||
)
|
||||
|
||||
const (
|
||||
commonHtmlFlags = 0 |
|
||||
blackfriday.HTML_TOC |
|
||||
blackfriday.HTML_USE_XHTML |
|
||||
blackfriday.HTML_USE_SMARTYPANTS |
|
||||
blackfriday.HTML_SMARTYPANTS_FRACTIONS |
|
||||
blackfriday.HTML_SMARTYPANTS_DASHES |
|
||||
blackfriday.HTML_SMARTYPANTS_LATEX_DASHES |
|
||||
blackfriday.HTML_NOFOLLOW_LINKS
|
||||
|
||||
commonExtensions = 0 |
|
||||
blackfriday.EXTENSION_NO_INTRA_EMPHASIS |
|
||||
blackfriday.EXTENSION_TABLES |
|
||||
blackfriday.EXTENSION_FENCED_CODE |
|
||||
blackfriday.EXTENSION_AUTOLINK |
|
||||
blackfriday.EXTENSION_STRIKETHROUGH |
|
||||
blackfriday.EXTENSION_SPACE_HEADERS |
|
||||
blackfriday.EXTENSION_HEADER_IDS |
|
||||
blackfriday.EXTENSION_BACKSLASH_LINE_BREAK |
|
||||
blackfriday.EXTENSION_DEFINITION_LISTS
|
||||
)
|
||||
|
||||
// Global Account
|
||||
var (
|
||||
Ei *Account
|
||||
lock sync.Mutex
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 数据库加索引
|
||||
ms, c := db.Connect(DB, COLLECTION_ACCOUNT)
|
||||
index := mgo.Index{
|
||||
Key: []string{"username"},
|
||||
Unique: true,
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
}
|
||||
if err := c.EnsureIndex(index); err != nil {
|
||||
logd.Fatal(err)
|
||||
}
|
||||
ms.Close()
|
||||
ms, c = db.Connect(DB, COLLECTION_ARTICLE)
|
||||
index = mgo.Index{
|
||||
Key: []string{"id", "slug"},
|
||||
Unique: true,
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
}
|
||||
if err := c.EnsureIndex(index); err != nil {
|
||||
logd.Fatal(err)
|
||||
}
|
||||
ms.Close()
|
||||
// 读取帐号信息
|
||||
Ei = loadAccount()
|
||||
// 获取文章
|
||||
Ei.Articles = loadArticles()
|
||||
// 生成markdown文档
|
||||
go generateMarkdown()
|
||||
// 启动定时器
|
||||
go timer()
|
||||
// 获取评论数量
|
||||
// go CommentsCount()
|
||||
}
|
||||
|
||||
// 读取或初始化帐号信息
|
||||
func loadAccount() (a *Account) {
|
||||
a = &Account{}
|
||||
err := db.FindOne(DB, COLLECTION_ACCOUNT, bson.M{"username": setting.Conf.Account.Username}, a)
|
||||
// 初始化用户数据
|
||||
if err == mgo.ErrNotFound {
|
||||
a = &Account{
|
||||
Username: setting.Conf.Account.Username,
|
||||
Password: helper.EncryptPasswd(setting.Conf.Account.Username, setting.Conf.Account.Password),
|
||||
Email: setting.Conf.Account.Email,
|
||||
PhoneN: setting.Conf.Account.PhoneNumber,
|
||||
Address: setting.Conf.Account.Address,
|
||||
CreateTime: time.Now(),
|
||||
}
|
||||
a.BlogName = setting.Conf.Blogger.BlogName
|
||||
a.SubTitle = setting.Conf.Blogger.SubTitle
|
||||
a.BeiAn = setting.Conf.Blogger.BeiAn
|
||||
a.BTitle = setting.Conf.Blogger.BTitle
|
||||
a.Copyright = setting.Conf.Blogger.Copyright
|
||||
err = db.Insert(DB, COLLECTION_ACCOUNT, a)
|
||||
generateTopic()
|
||||
} else if err != nil {
|
||||
logd.Fatal(err)
|
||||
}
|
||||
a.CH = make(chan string, 2)
|
||||
a.MapArticles = make(map[string]*Article)
|
||||
a.Tags = make(map[string]SortArticles)
|
||||
return
|
||||
}
|
||||
|
||||
func loadArticles() (artcs SortArticles) {
|
||||
err := db.FindAll(DB, COLLECTION_ARTICLE, bson.M{"isdraft": false, "deletetime": bson.M{"$eq": time.Time{}}}, &artcs)
|
||||
if err != nil {
|
||||
logd.Fatal(err)
|
||||
}
|
||||
sort.Sort(artcs)
|
||||
for i, v := range artcs {
|
||||
// 渲染文章
|
||||
GenerateExcerptAndRender(v)
|
||||
Ei.MapArticles[v.Slug] = v
|
||||
// 分析文章
|
||||
if v.ID < setting.Conf.StartID {
|
||||
continue
|
||||
}
|
||||
if i > 0 {
|
||||
v.Prev = artcs[i-1]
|
||||
}
|
||||
if artcs[i+1].ID >= setting.Conf.StartID {
|
||||
v.Next = artcs[i+1]
|
||||
}
|
||||
ManageTagsArticle(v, false, ADD)
|
||||
ManageSeriesArticle(v, false, ADD)
|
||||
ManageArchivesArticle(v, false, ADD)
|
||||
}
|
||||
Ei.CH <- SERIES_MD
|
||||
Ei.CH <- ARCHIVE_MD
|
||||
return
|
||||
}
|
||||
|
||||
// generate series,archive markdown
|
||||
func generateMarkdown() {
|
||||
for {
|
||||
|
||||
switch typ := <-Ei.CH; typ {
|
||||
case SERIES_MD:
|
||||
sort.Sort(Ei.Series)
|
||||
var buffer bytes.Buffer
|
||||
buffer.WriteString(Ei.SeriesSay)
|
||||
buffer.WriteString("\n\n")
|
||||
for _, serie := range Ei.Series {
|
||||
buffer.WriteString(fmt.Sprintf("### %s{#toc-%d}", serie.Name, serie.ID))
|
||||
buffer.WriteString("\n")
|
||||
buffer.WriteString(serie.Desc)
|
||||
buffer.WriteString("\n\n")
|
||||
for _, artc := range serie.Articles {
|
||||
// * [标题一](/post/hello-world.html) <span class="date">(Man 02, 2006)</span>
|
||||
buffer.WriteString("* [" + artc.Title + "](/post/" + artc.Slug + ".html) <span class=\"date\">(" + artc.CreateTime.Format("Jan 02, 2006") + ")</span>\n")
|
||||
}
|
||||
buffer.WriteByte('\n')
|
||||
}
|
||||
Ei.PageSeries = string(renderPage(buffer.Bytes()))
|
||||
case ARCHIVE_MD:
|
||||
sort.Sort(Ei.Archives)
|
||||
var buffer bytes.Buffer
|
||||
buffer.WriteString(Ei.ArchivesSay)
|
||||
buffer.WriteString("\n\n")
|
||||
for _, archive := range Ei.Archives {
|
||||
buffer.WriteString(fmt.Sprintf("### %s", archive.Time.Format("2006年01月")))
|
||||
buffer.WriteString("\n\n")
|
||||
for _, artc := range archive.Articles {
|
||||
buffer.WriteString("* [" + artc.Title + "](/post/" + artc.Slug + ".html) <span class=\"date\">(" + artc.CreateTime.Format("Jan 02, 2006") + ")</span>\n")
|
||||
}
|
||||
buffer.WriteByte('\n')
|
||||
}
|
||||
Ei.PageArchives = string(renderPage(buffer.Bytes()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// init account: generate blogroll and about page
|
||||
func generateTopic() {
|
||||
about := &Article{
|
||||
ID: db.NextVal(DB, COUNTER_ARTICLE),
|
||||
Author: setting.Conf.Account.Username,
|
||||
Title: "关于",
|
||||
Slug: "about",
|
||||
CreateTime: time.Now(),
|
||||
UpdateTime: time.Now(),
|
||||
}
|
||||
blogroll := &Article{
|
||||
ID: db.NextVal(DB, COUNTER_ARTICLE),
|
||||
Author: setting.Conf.Account.Username,
|
||||
Title: "友情链接",
|
||||
Slug: "blogroll",
|
||||
UpdateTime: time.Now(),
|
||||
CreateTime: time.Now(),
|
||||
}
|
||||
err := db.Insert(DB, COLLECTION_ARTICLE, blogroll)
|
||||
if err != nil {
|
||||
logd.Fatal(err)
|
||||
}
|
||||
err = db.Insert(DB, COLLECTION_ARTICLE, about)
|
||||
if err != nil {
|
||||
logd.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// render page
|
||||
func renderPage(md []byte) []byte {
|
||||
renderer := blackfriday.HtmlRenderer(commonHtmlFlags, "", "")
|
||||
return blackfriday.Markdown(md, renderer, commonExtensions)
|
||||
}
|
||||
|
||||
// 文章分页
|
||||
func PageList(p, n int) (prev int, next int, artcs []*Article) {
|
||||
var l int
|
||||
for l = len(Ei.Articles); l > 0; l-- {
|
||||
if Ei.Articles[l-1].ID >= setting.Conf.StartID {
|
||||
break
|
||||
}
|
||||
}
|
||||
if l == 0 {
|
||||
return 0, 0, nil
|
||||
}
|
||||
m := l / n
|
||||
if d := l % n; d > 0 {
|
||||
m++
|
||||
}
|
||||
if p > m {
|
||||
p = m
|
||||
}
|
||||
if p > 1 {
|
||||
prev = p - 1
|
||||
}
|
||||
if p < m {
|
||||
next = p + 1
|
||||
}
|
||||
s := (p - 1) * n
|
||||
e := p * n
|
||||
if e > l {
|
||||
e = l
|
||||
}
|
||||
artcs = Ei.Articles[s:e]
|
||||
return
|
||||
}
|
||||
|
||||
func ManageTagsArticle(artc *Article, s bool, dos ...string) {
|
||||
for _, do := range dos {
|
||||
switch do {
|
||||
case ADD:
|
||||
for _, tag := range artc.Tags {
|
||||
Ei.Tags[tag] = append(Ei.Tags[tag], artc)
|
||||
if s {
|
||||
sort.Sort(Ei.Tags[tag])
|
||||
}
|
||||
}
|
||||
case DELETE:
|
||||
for _, tag := range artc.Tags {
|
||||
for i, v := range Ei.Tags[tag] {
|
||||
if v == artc {
|
||||
Ei.Tags[tag] = append(Ei.Tags[tag][0:i], Ei.Tags[tag][i+1:]...)
|
||||
if len(Ei.Tags[tag]) == 0 {
|
||||
delete(Ei.Tags, tag)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ManageSeriesArticle(artc *Article, s bool, dos ...string) {
|
||||
for _, do := range dos {
|
||||
switch do {
|
||||
case ADD:
|
||||
if artc.SerieID != 0 {
|
||||
for i, serie := range Ei.Series {
|
||||
if serie.ID == artc.SerieID {
|
||||
Ei.Series[i].Articles = append(Ei.Series[i].Articles, artc)
|
||||
if s {
|
||||
sort.Sort(Ei.Series[i].Articles)
|
||||
Ei.CH <- SERIES_MD
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case DELETE:
|
||||
if artc.SerieID != 0 {
|
||||
for i, serie := range Ei.Series {
|
||||
if serie.ID == artc.SerieID {
|
||||
for j, v := range serie.Articles {
|
||||
if v == artc {
|
||||
Ei.Series[i].Articles = append(Ei.Series[i].Articles[0:j], Ei.Series[i].Articles[j+1:]...)
|
||||
Ei.CH <- SERIES_MD
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func ManageArchivesArticle(artc *Article, s bool, dos ...string) {
|
||||
for _, do := range dos {
|
||||
switch do {
|
||||
case ADD:
|
||||
add := false
|
||||
y, m, _ := artc.CreateTime.Date()
|
||||
for i, archive := range Ei.Archives {
|
||||
ay, am, _ := archive.Time.Date()
|
||||
if y == ay && m == am {
|
||||
add = true
|
||||
Ei.Archives[i].Articles = append(Ei.Archives[i].Articles, artc)
|
||||
if s {
|
||||
sort.Sort(Ei.Archives[i].Articles)
|
||||
Ei.CH <- ARCHIVE_MD
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !add {
|
||||
Ei.Archives = append(Ei.Archives, &Archive{Time: artc.CreateTime, Articles: SortArticles{artc}})
|
||||
}
|
||||
case DELETE:
|
||||
for i, archive := range Ei.Archives {
|
||||
ay, am, _ := archive.Time.Date()
|
||||
if y, m, _ := artc.CreateTime.Date(); ay == y && am == m {
|
||||
for j, v := range archive.Articles {
|
||||
if v == artc {
|
||||
Ei.Archives[i].Articles = append(Ei.Archives[i].Articles[0:j], Ei.Archives[i].Articles[j+1:]...)
|
||||
Ei.CH <- ARCHIVE_MD
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 渲染markdown操作和截取摘要操作
|
||||
var reg = regexp.MustCompile(setting.Conf.Identifier)
|
||||
|
||||
func GenerateExcerptAndRender(artc *Article) {
|
||||
index := reg.FindStringIndex(artc.Content)
|
||||
if len(index) > 0 {
|
||||
artc.Excerpt = artc.Content[0:index[0]]
|
||||
} else {
|
||||
uc := []rune(artc.Content)
|
||||
length := setting.Conf.Length
|
||||
if len(uc) < length {
|
||||
length = len(uc)
|
||||
}
|
||||
artc.Excerpt = string(uc[0:length])
|
||||
}
|
||||
artc.Content = string(renderPage([]byte(artc.Content)))
|
||||
}
|
||||
|
||||
// 读取草稿箱
|
||||
func LoadDraft() (artcs SortArticles, err error) {
|
||||
err = db.FindAll(DB, COLLECTION_ARTICLE, bson.M{"isdraft": true}, &artcs)
|
||||
sort.Sort(artcs)
|
||||
return
|
||||
}
|
||||
|
||||
// 读取回收箱
|
||||
func LoadTrash() (artcs SortArticles, err error) {
|
||||
err = db.FindAll(DB, COLLECTION_ARTICLE, bson.M{"deletetime": bson.M{"$ne": time.Time{}}}, &artcs)
|
||||
sort.Sort(artcs)
|
||||
return
|
||||
}
|
||||
|
||||
// 添加文章
|
||||
func AddArticle(artc *Article) error {
|
||||
// 分配ID, 占位至起始id
|
||||
for {
|
||||
if id := db.NextVal(DB, COUNTER_ARTICLE); id < setting.Conf.StartID {
|
||||
continue
|
||||
} else {
|
||||
artc.ID = id
|
||||
break
|
||||
}
|
||||
}
|
||||
if !artc.IsDraft {
|
||||
defer GenerateExcerptAndRender(artc)
|
||||
Ei.MapArticles[artc.Slug] = artc
|
||||
Ei.Articles = append([]*Article{artc}, Ei.Articles...)
|
||||
sort.Sort(Ei.Articles)
|
||||
AddToLinkedList(artc.ID)
|
||||
ManageTagsArticle(artc, true, ADD)
|
||||
ManageSeriesArticle(artc, true, ADD)
|
||||
ManageArchivesArticle(artc, true, ADD)
|
||||
Ei.CH <- ARCHIVE_MD
|
||||
if artc.SerieID > 0 {
|
||||
Ei.CH <- SERIES_MD
|
||||
}
|
||||
}
|
||||
return db.Insert(DB, COLLECTION_ARTICLE, artc)
|
||||
}
|
||||
|
||||
// 删除文章,移入回收箱
|
||||
func DelArticles(ids ...int32) error {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
for _, id := range ids {
|
||||
i, artc := GetArticle(id)
|
||||
DelFromLinkedList(artc)
|
||||
Ei.Articles = append(Ei.Articles[:i], Ei.Articles[i+1:]...)
|
||||
delete(Ei.MapArticles, artc.Slug)
|
||||
ManageTagsArticle(artc, false, DELETE)
|
||||
ManageSeriesArticle(artc, false, DELETE)
|
||||
ManageArchivesArticle(artc, false, DELETE)
|
||||
err := UpdateArticle(bson.M{"id": id}, bson.M{"$set": bson.M{"deletetime": time.Now()}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
Ei.CH <- ARCHIVE_MD
|
||||
Ei.CH <- SERIES_MD
|
||||
return nil
|
||||
}
|
||||
|
||||
func DelFromLinkedList(artc *Article) {
|
||||
if artc.Prev == nil && artc.Next != nil {
|
||||
artc.Next.Prev = nil
|
||||
} else if artc.Prev != nil && artc.Next == nil {
|
||||
artc.Prev.Next = nil
|
||||
} else if artc.Prev != nil && artc.Next != nil {
|
||||
artc.Prev.Next = artc.Next
|
||||
artc.Next.Prev = artc.Prev
|
||||
}
|
||||
}
|
||||
|
||||
func AddToLinkedList(id int32) {
|
||||
i, artc := GetArticle(id)
|
||||
if i == 0 && Ei.Articles[i+1].ID >= setting.Conf.StartID {
|
||||
artc.Next = Ei.Articles[i+1]
|
||||
Ei.Articles[i+1].Prev = artc
|
||||
} else if i > 0 && Ei.Articles[i-1].ID >= setting.Conf.StartID {
|
||||
artc.Prev = Ei.Articles[i-1]
|
||||
if Ei.Articles[i-1].Next != nil {
|
||||
artc.Next = Ei.Articles[i-1].Next
|
||||
}
|
||||
Ei.Articles[i-1].Next = artc
|
||||
}
|
||||
}
|
||||
|
||||
// 从缓存获取文章
|
||||
func GetArticle(id int32) (int, *Article) {
|
||||
for i, artc := range Ei.Articles {
|
||||
if id == artc.ID {
|
||||
return i, artc
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
// 定时清除回收箱文章
|
||||
func timer() {
|
||||
delT := time.NewTicker(time.Duration(setting.Conf.Clean) * time.Hour)
|
||||
for {
|
||||
<-delT.C
|
||||
db.Remove(DB, COLLECTION_ARTICLE, bson.M{"deletetime": bson.M{"$gt": time.Time{}, "$lt": time.Now().Add(time.Duration(setting.Conf.Trash) * time.Hour)}})
|
||||
}
|
||||
}
|
||||
|
||||
// 操作帐号字段
|
||||
func UpdateAccountField(M bson.M) error {
|
||||
return db.Update(DB, COLLECTION_ACCOUNT, bson.M{"username": Ei.Username}, M)
|
||||
}
|
||||
|
||||
// 删除草稿箱或回收箱,永久删除
|
||||
func RemoveArticle(id int32) error {
|
||||
return db.Remove(DB, COLLECTION_ARTICLE, bson.M{"id": id})
|
||||
}
|
||||
|
||||
// 恢复删除文章到草稿箱
|
||||
func RecoverArticle(id int32) error {
|
||||
return db.Update(DB, COLLECTION_ARTICLE, bson.M{"id": id}, bson.M{"$set": bson.M{"deletetime": time.Time{}, "isdraft": true}})
|
||||
}
|
||||
|
||||
// 更新文章
|
||||
func UpdateArticle(query, update interface{}) error {
|
||||
return db.Update(DB, COLLECTION_ARTICLE, query, update)
|
||||
}
|
||||
|
||||
// 编辑文档
|
||||
func QueryArticle(id int32) *Article {
|
||||
artc := &Article{}
|
||||
if err := db.FindOne(DB, COLLECTION_ARTICLE, bson.M{"id": id}, artc); err != nil {
|
||||
return nil
|
||||
}
|
||||
return artc
|
||||
}
|
||||
|
||||
// 添加专题
|
||||
func AddSerie(name, slug, desc string) error {
|
||||
serie := &Serie{db.NextVal(DB, COUNTER_SERIE), name, slug, desc, time.Now(), nil}
|
||||
Ei.Series = append(Ei.Series, serie)
|
||||
sort.Sort(Ei.Series)
|
||||
Ei.CH <- SERIES_MD
|
||||
return UpdateAccountField(bson.M{"$addToSet": bson.M{"blogger.series": serie}})
|
||||
}
|
||||
|
||||
// 删除专题
|
||||
func DelSerie(id int32) error {
|
||||
for i, serie := range Ei.Series {
|
||||
if id == serie.ID {
|
||||
if len(serie.Articles) > 0 {
|
||||
return fmt.Errorf("请删除该专题下的所有文章")
|
||||
}
|
||||
err := UpdateAccountField(bson.M{"$pull": bson.M{"blogger.series": bson.M{"id": id}}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
Ei.Series[i] = nil
|
||||
Ei.Series = append(Ei.Series[:i], Ei.Series[i+1:]...)
|
||||
Ei.CH <- SERIES_MD
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 查找专题
|
||||
func QuerySerie(id int32) *Serie {
|
||||
for _, serie := range Ei.Series {
|
||||
if serie.ID == id {
|
||||
return serie
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func PageListBack(se int, kw string, draft, del bool, p, n int) (max int, artcs []*Article) {
|
||||
M := bson.M{}
|
||||
if draft {
|
||||
M["isdraft"] = true
|
||||
} else if del {
|
||||
M["deletetime"] = bson.M{"$ne": time.Time{}}
|
||||
} else {
|
||||
M["isdraft"] = false
|
||||
M["deletetime"] = bson.M{"$eq": time.Time{}}
|
||||
if se > 0 {
|
||||
M["serieid"] = se
|
||||
}
|
||||
if kw != "" {
|
||||
M["title"] = bson.M{"$regex": kw, "$options": "$i"}
|
||||
}
|
||||
}
|
||||
ms, c := db.Connect(DB, COLLECTION_ARTICLE)
|
||||
defer ms.Close()
|
||||
err := c.Find(M).Select(bson.M{"content": 0}).Sort("-createtime").Limit(n).Skip((p - 1) * n).All(&artcs)
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
}
|
||||
count, err := c.Find(M).Count()
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
}
|
||||
max = count / n
|
||||
if count%n > 0 {
|
||||
max++
|
||||
}
|
||||
return
|
||||
}
|
||||
44
db_test.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPageListBack(t *testing.T) {
|
||||
_, artcs := PageListBack(0, "", false, false, 1, 20)
|
||||
for _, artc := range artcs {
|
||||
t.Log(*artc)
|
||||
}
|
||||
t.Log("------------------------------------------------------------")
|
||||
_, artcs = PageListBack(0, "", false, false, 2, 10)
|
||||
for _, artc := range artcs {
|
||||
t.Log(*artc)
|
||||
}
|
||||
t.Log("------------------------------------------------------------")
|
||||
_, artcs = PageListBack(3, "", false, false, 1, 20)
|
||||
for _, artc := range artcs {
|
||||
t.Log(*artc)
|
||||
}
|
||||
t.Log("------------------------------------------------------------")
|
||||
_, artcs = PageListBack(3, "19", false, false, 1, 20)
|
||||
for _, artc := range artcs {
|
||||
t.Log(*artc)
|
||||
}
|
||||
t.Log("------------------------------------------------------------")
|
||||
_, artcs = PageListBack(0, "", false, true, 1, 20)
|
||||
for _, artc := range artcs {
|
||||
t.Log(*artc)
|
||||
}
|
||||
t.Log("------------------------------------------------------------")
|
||||
_, artcs = PageListBack(0, "", true, false, 1, 20)
|
||||
for _, artc := range artcs {
|
||||
t.Log(*artc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddSerie(t *testing.T) {
|
||||
err := AddSerie("测试", "nothing", "这里是描述")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
75
disqus.go
Normal file
@@ -0,0 +1,75 @@
|
||||
// Package main provides ...
|
||||
// Get article' comments count
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/EiBlog/eiblog/setting"
|
||||
"github.com/EiBlog/utils/logd"
|
||||
)
|
||||
|
||||
type result struct {
|
||||
Code int
|
||||
Response []struct {
|
||||
Posts int
|
||||
Identifiers []string
|
||||
}
|
||||
}
|
||||
|
||||
func CommentsCount() {
|
||||
if setting.Conf.Disqus.URL == "" || setting.Conf.Disqus.PublicKey == "" || setting.Conf.Disqus.ShortName == "" {
|
||||
return
|
||||
}
|
||||
baseUrl := setting.Conf.Disqus.URL + "?api_key=" + setting.Conf.Disqus.PublicKey + "&forum=" + setting.Conf.Disqus.ShortName + "&"
|
||||
domain := "http:" + runmode.Domain
|
||||
if runmode.EnableHttps {
|
||||
domain = "https:" + runmode.Domain
|
||||
}
|
||||
var count, index int
|
||||
for index < len(Ei.Articles) {
|
||||
logd.Debugf("count=====%d, index=======%d, length=======%d, bool=========%t", count, index, len(Ei.Articles), index < len(Ei.Articles) && count < 10)
|
||||
var threads []string
|
||||
for ; index < len(Ei.Articles) && count < 20; index++ {
|
||||
artc := Ei.Articles[index]
|
||||
threads = append(threads, fmt.Sprintf("thread=link:%s/post/%s.html", domain, artc.Slug))
|
||||
count++
|
||||
}
|
||||
count = 0
|
||||
url := baseUrl + strings.Join(threads, "&")
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
break
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
break
|
||||
}
|
||||
rst := result{}
|
||||
err = json.Unmarshal(b, &rst)
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
break
|
||||
}
|
||||
if rst.Code != SUCCESS {
|
||||
logd.Error(rst.Code)
|
||||
break
|
||||
}
|
||||
for _, v := range rst.Response {
|
||||
i := strings.Index(v.Identifiers[0], "-")
|
||||
artc := Ei.MapArticles[v.Identifiers[0][i+1:]]
|
||||
if artc != nil {
|
||||
artc.Count = v.Posts
|
||||
}
|
||||
}
|
||||
}
|
||||
time.AfterFunc(time.Duration(setting.Conf.Disqus.Interval)*time.Hour, CommentsCount)
|
||||
}
|
||||
9
disqus_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDisqus(t *testing.T) {
|
||||
CommentsCount()
|
||||
}
|
||||
36
docker-compose.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
version: '2'
|
||||
services:
|
||||
mongodb:
|
||||
image: mongo:3.2
|
||||
container_name: eidb
|
||||
volumes:
|
||||
- /data/eiblog/db:/data/db
|
||||
restart: always
|
||||
elasticsearch:
|
||||
image: elasticsearch:2.4
|
||||
container_name: eisearch
|
||||
volumes:
|
||||
- /data/eiblog/conf/es/config:/usr/share/elasticsearch/config
|
||||
- /data/eiblog/conf/es/plugins:/usr/share/elasticsearch/plugins
|
||||
- /data/eiblog/conf/es/data:/usr/share/elasticsearch/data
|
||||
- /data/eiblog/conf/es/logs:/usr/share/elasticsearch/logs
|
||||
environment:
|
||||
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
|
||||
# 需注释掉
|
||||
ports:
|
||||
- "9200:9200"
|
||||
restart: always
|
||||
eiblog:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/deepzz/eiblog
|
||||
container_name: eiblog
|
||||
volumes:
|
||||
- /data/eiblog/logdata:/eiblog/logdata
|
||||
- /data/eiblog/conf:/eiblog/conf
|
||||
links:
|
||||
- elasticsearch
|
||||
- mongodb
|
||||
ports:
|
||||
- "443:443"
|
||||
- "80:80"
|
||||
- "8080:8080"
|
||||
restart: always
|
||||
344
elasticsearch.go
Normal file
@@ -0,0 +1,344 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/EiBlog/eiblog/setting"
|
||||
"github.com/EiBlog/utils/logd"
|
||||
)
|
||||
|
||||
const (
|
||||
INDEX = "eiblog"
|
||||
TYPE = "article"
|
||||
)
|
||||
|
||||
var es *ElasticService
|
||||
|
||||
func init() {
|
||||
es = &ElasticService{url: setting.Conf.SearchURL, c: new(http.Client)}
|
||||
initIndex()
|
||||
}
|
||||
|
||||
func initIndex() {
|
||||
mapping := map[string]interface{}{
|
||||
"mappings": map[string]interface{}{
|
||||
TYPE: map[string]interface{}{
|
||||
"properties": map[string]interface{}{
|
||||
"title": map[string]string{
|
||||
"type": "string",
|
||||
"term_vector": "with_positions_offsets",
|
||||
"analyzer": "ik_syno",
|
||||
"search_analyzer": "ik_syno",
|
||||
},
|
||||
"content": map[string]string{
|
||||
"type": "string",
|
||||
"term_vector": "with_positions_offsets",
|
||||
"analyzer": "ik_syno",
|
||||
"search_analyzer": "ik_syno",
|
||||
},
|
||||
"slug": map[string]string{
|
||||
"type": "string",
|
||||
},
|
||||
"tags": map[string]string{
|
||||
"type": "string",
|
||||
"index": "not_analyzed",
|
||||
},
|
||||
"create_time": map[string]string{
|
||||
"type": "date",
|
||||
"index": "not_analyzed",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
b, _ := json.Marshal(mapping)
|
||||
err := CreateIndexAndMappings(INDEX, TYPE, b)
|
||||
if err != nil {
|
||||
logd.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Elasticsearch(kw string, size, from int) *ESSearchResult {
|
||||
dsl := map[string]interface{}{
|
||||
"query": map[string]interface{}{
|
||||
"dis_max": map[string]interface{}{
|
||||
"queries": []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"match": map[string]interface{}{
|
||||
"title": map[string]interface{}{
|
||||
"query": kw,
|
||||
"minimum_should_match": "50%",
|
||||
"boost": 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"match": map[string]interface{}{
|
||||
"content": map[string]interface{}{
|
||||
"query": kw,
|
||||
"minimum_should_match": "75%",
|
||||
"boost": 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"match": map[string]interface{}{
|
||||
"tags": map[string]interface{}{
|
||||
"query": kw,
|
||||
"minimum_should_match": "100%",
|
||||
"boost": 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"match": map[string]interface{}{
|
||||
"slug": map[string]interface{}{
|
||||
"query": kw,
|
||||
"minimum_should_match": "100%",
|
||||
"boost": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"tie_breaker": 0.3,
|
||||
},
|
||||
},
|
||||
"highlight": map[string]interface{}{
|
||||
"pre_tags": []string{"<b>"},
|
||||
"post_tags": []string{"</b>"},
|
||||
"fields": map[string]interface{}{
|
||||
"title": map[string]string{},
|
||||
"content": map[string]string{
|
||||
// "fragment_size": 150,
|
||||
// "number_of_fragments": "3",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
b, _ := json.Marshal(dsl)
|
||||
docs, err := IndexQueryDSL(INDEX, TYPE, size, from, b)
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
return nil
|
||||
}
|
||||
return docs
|
||||
}
|
||||
|
||||
func ElasticsearchSimple(q string, size, from int) *ESSearchResult {
|
||||
docs, err := IndexQuerySimple(INDEX, TYPE, size, from, q)
|
||||
if err != nil {
|
||||
logd.Error(err)
|
||||
return nil
|
||||
}
|
||||
return docs
|
||||
}
|
||||
|
||||
func ElasticIndex(artc *Article) error {
|
||||
mapping := map[string]interface{}{
|
||||
"title": artc.Title,
|
||||
"content": artc.Content,
|
||||
"slug": artc.Slug,
|
||||
"tags": artc.Tags,
|
||||
"create_time": artc.CreateTime.Format("2006-01-02"),
|
||||
}
|
||||
b, _ := json.Marshal(mapping)
|
||||
return IndexOrUpdateDocument(INDEX, TYPE, artc.ID, b)
|
||||
}
|
||||
|
||||
func ElasticDelIndex(ids []int32) error {
|
||||
var target []string
|
||||
for _, id := range ids {
|
||||
target = append(target, fmt.Sprint(id))
|
||||
}
|
||||
return DeleteDocument(INDEX, TYPE, target)
|
||||
}
|
||||
|
||||
///////////////////////////// Elasticsearch api /////////////////////////////
|
||||
type ElasticService struct {
|
||||
c *http.Client
|
||||
url string
|
||||
}
|
||||
|
||||
type IndicesCreateResult struct {
|
||||
Acknowledged bool `json:"acknowledged"`
|
||||
}
|
||||
|
||||
func (s *ElasticService) ParseURL(format string, params ...interface{}) string {
|
||||
return fmt.Sprintf(s.url+format, params...)
|
||||
}
|
||||
|
||||
func (s *ElasticService) Do(req *http.Request) (interface{}, error) {
|
||||
resp, err := s.c.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
switch req.Method {
|
||||
case "POST":
|
||||
fallthrough
|
||||
case "DELETE":
|
||||
fallthrough
|
||||
case "PUT":
|
||||
fallthrough
|
||||
case "GET":
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
case "HEAD":
|
||||
return resp.StatusCode, nil
|
||||
|
||||
default:
|
||||
return nil, errors.New("unknown methods")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func CreateIndexAndMappings(index, typ string, mappings []byte) (err error) {
|
||||
req, err := http.NewRequest("HEAD", es.ParseURL("/%s/%s", index, typ), nil)
|
||||
code, err := es.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if code.(int) == http.StatusOK {
|
||||
return nil
|
||||
}
|
||||
req, err = http.NewRequest("PUT", es.ParseURL("/%s", index), bytes.NewReader(mappings))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := es.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var rst IndicesCreateResult
|
||||
err = json.Unmarshal(data.([]byte), &rst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !rst.Acknowledged {
|
||||
return errors.New(string(data.([]byte)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func IndexOrUpdateDocument(index, typ string, id int32, doc []byte) (err error) {
|
||||
req, err := http.NewRequest("PUT", es.ParseURL("/%s/%s/%d", index, typ, id), bytes.NewReader(doc))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := es.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(string(data.([]byte)))
|
||||
return nil
|
||||
}
|
||||
|
||||
type ESDeleteDocument struct {
|
||||
_Index string `json:"_index"`
|
||||
_Type string `json:"_type"`
|
||||
_ID string `json:"_id"`
|
||||
}
|
||||
|
||||
type ESDeleteResult struct {
|
||||
Errors bool `json:"errors"`
|
||||
Iterms []map[string]struct {
|
||||
Error string `json:"error"`
|
||||
} `json:"iterms"`
|
||||
}
|
||||
|
||||
func DeleteDocument(index, typ string, ids []string) error {
|
||||
var buff bytes.Buffer
|
||||
for _, id := range ids {
|
||||
dd := &ESDeleteDocument{_Index: index, _Type: typ, _ID: id}
|
||||
m := map[string]*ESDeleteDocument{"delete": dd}
|
||||
b, _ := json.Marshal(m)
|
||||
buff.Write(b)
|
||||
buff.WriteByte('\n')
|
||||
}
|
||||
req, err := http.NewRequest("POST", es.ParseURL("/_bulk"), bytes.NewReader(buff.Bytes()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := es.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var result ESDeleteResult
|
||||
err = json.Unmarshal(data.([]byte), &result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if result.Errors {
|
||||
for _, iterm := range result.Iterms {
|
||||
for _, s := range iterm {
|
||||
if s.Error != "" {
|
||||
return errors.New(s.Error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ESSearchResult struct {
|
||||
Took float32 `json:"took"`
|
||||
Hits struct {
|
||||
Total int `json:"total"`
|
||||
Hits []struct {
|
||||
ID string `json:"_id"`
|
||||
Source struct {
|
||||
Slug string `json:"slug"`
|
||||
Content string `json:"content"`
|
||||
CreateTime time.Time `json:"create_time"`
|
||||
Title string `json:"title"`
|
||||
} `json:"_source"`
|
||||
Highlight struct {
|
||||
Title []string `json:"title"`
|
||||
Content []string `json:"content"`
|
||||
} `json:"highlight"`
|
||||
} `json:"hits"`
|
||||
} `json:"hits"`
|
||||
}
|
||||
|
||||
func IndexQuerySimple(index, typ string, size, from int, q string) (*ESSearchResult, error) {
|
||||
req, err := http.NewRequest("GET", es.ParseURL("/%s/%s/_search?size=%d&from=%d&q=%s", index, typ, size, from, q), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := es.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := &ESSearchResult{}
|
||||
err = json.Unmarshal(data.([]byte), result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func IndexQueryDSL(index, typ string, size, from int, dsl []byte) (*ESSearchResult, error) {
|
||||
req, err := http.NewRequest("POST", es.ParseURL("/%s/%s/_search?size=%d&from=%d", index, typ, size, from), bytes.NewReader(dsl))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := es.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := &ESSearchResult{}
|
||||
err = json.Unmarshal(data.([]byte), result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
135
elasticsearch_test.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCreateIndexAndMappings(t *testing.T) {
|
||||
mapping := map[string]interface{}{
|
||||
"mappings": map[string]interface{}{
|
||||
"article": map[string]interface{}{
|
||||
"properties": map[string]interface{}{
|
||||
"title": map[string]string{
|
||||
"type": "string",
|
||||
"term_vector": "with_positions_offsets",
|
||||
"analyzer": "ik_syno",
|
||||
"search_analyzer": "ik_syno",
|
||||
},
|
||||
"content": map[string]string{
|
||||
"type": "string",
|
||||
"term_vector": "with_positions_offsets",
|
||||
"analyzer": "ik_syno",
|
||||
"search_analyzer": "ik_syno",
|
||||
},
|
||||
"slug": map[string]string{
|
||||
"type": "string",
|
||||
},
|
||||
"tags": map[string]string{
|
||||
"type": "string",
|
||||
"index": "not_analyzed",
|
||||
},
|
||||
"update_time": map[string]string{
|
||||
"type": "date",
|
||||
"index": "not_analyzed",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
b, _ := json.Marshal(mapping)
|
||||
err := CreateIndexAndMappings(INDEX, TYPE, b)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndexDocument(t *testing.T) {
|
||||
mapping := map[string]interface{}{
|
||||
"title": "简单到不知道为什么",
|
||||
"content": `最近有很多朋友邮件或者留言询问本博客服务端配置相关问题,基本都是关于 HTTPS 和 HTTP/2 的,其实我的 Nginx 配置在之前的文章中多次提到过,不过都比较分散。为了方便大家参考,本文贴出完整配置。本文内容会随时调整或更新,请大家不要把本文内容全文转载到第三方平台,以免给他人造成困扰或误导。另外限于篇幅,本文不会对配置做过多说明,如有疑问或不同意见,欢迎留言指出。
|
||||
`,
|
||||
"slug": "vim3",
|
||||
"tags": []string{"js", "javascript", "test"},
|
||||
"update_time": "2015-12-15T13:05:55Z",
|
||||
}
|
||||
b, _ := json.Marshal(mapping)
|
||||
err := IndexOrUpdateDocument(INDEX, TYPE, int32(11), b)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndexQuerySimple(t *testing.T) {
|
||||
_, err := IndexQuerySimple(INDEX, TYPE, "JS")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndexQueryDSL(t *testing.T) {
|
||||
kw := "实现访问限制"
|
||||
dsl := map[string]interface{}{
|
||||
"query": map[string]interface{}{
|
||||
"dis_max": map[string]interface{}{
|
||||
"queries": []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"match": map[string]interface{}{
|
||||
"title": map[string]interface{}{
|
||||
"query": kw,
|
||||
"minimum_should_match": "50%",
|
||||
"boost": 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"match": map[string]interface{}{
|
||||
"content": map[string]interface{}{
|
||||
"query": kw,
|
||||
"minimum_should_match": "75%",
|
||||
"boost": 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"match": map[string]interface{}{
|
||||
"tags": map[string]interface{}{
|
||||
"query": kw,
|
||||
"minimum_should_match": "100%",
|
||||
"boost": 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"match": map[string]interface{}{
|
||||
"slug": map[string]interface{}{
|
||||
"query": kw,
|
||||
"minimum_should_match": "100%",
|
||||
"boost": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"tie_breaker": 0.3,
|
||||
},
|
||||
},
|
||||
"highlight": map[string]interface{}{
|
||||
"pre_tags": []string{"<b>"},
|
||||
"post_tags": []string{"</b>"},
|
||||
"fields": map[string]interface{}{
|
||||
"title": map[string]string{},
|
||||
"content": map[string]string{
|
||||
// "fragment_size": 150,
|
||||
// "number_of_fragments": "3",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
b, _ := json.Marshal(dsl)
|
||||
fmt.Println(string(b))
|
||||
_, err := IndexQueryDSL(INDEX, TYPE, 10, 1, b)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
255
front.go
Normal file
@@ -0,0 +1,255 @@
|
||||
// Package main provides ...
|
||||
// 这里是前端页面展示相关接口
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/EiBlog/eiblog/setting"
|
||||
"github.com/EiBlog/utils/logd"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func Filter() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// 过滤黑名单
|
||||
BlackFilter(c)
|
||||
// 用户cookie,用于统计
|
||||
UserCookie(c)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// 用户识别
|
||||
func UserCookie(c *gin.Context) {
|
||||
cookie, err := c.Request.Cookie("u")
|
||||
if err != nil || cookie.Value == "" {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 黑名单过滤
|
||||
func BlackFilter(c *gin.Context) {
|
||||
ip := c.ClientIP()
|
||||
if setting.BlackIP[ip] {
|
||||
c.Abort()
|
||||
c.String(http.StatusForbidden, "Your IP is blacklisted.")
|
||||
}
|
||||
}
|
||||
|
||||
// 解析静态文件版本
|
||||
func StaticVersion(c *gin.Context) (version int) {
|
||||
cookie, err := c.Request.Cookie("v")
|
||||
if err != nil || cookie.Value != fmt.Sprint(setting.Conf.StaticVersion) {
|
||||
return setting.Conf.StaticVersion
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func HandleNotFound(c *gin.Context) {
|
||||
h := GetBase()
|
||||
h["Version"] = StaticVersion(c)
|
||||
h["Title"] = "Not Found"
|
||||
h["NotFoundPage"] = true
|
||||
h["Path"] = ""
|
||||
c.HTML(http.StatusNotFound, "homeLayout.html", h)
|
||||
}
|
||||
|
||||
func GetBase() gin.H {
|
||||
return gin.H{
|
||||
"Favicon": setting.Conf.Favicon,
|
||||
"BlogName": Ei.BlogName,
|
||||
"SubTitle": Ei.SubTitle,
|
||||
"Twitter": setting.Conf.Twitter,
|
||||
"RSS": setting.Conf.RSS,
|
||||
"Search": setting.Conf.Search,
|
||||
"CopyYear": time.Now().Year(),
|
||||
"BTitle": Ei.BTitle,
|
||||
"BeiAn": Ei.BeiAn,
|
||||
"Domain": runmode.Domain,
|
||||
"Static": setting.Conf.Static,
|
||||
}
|
||||
}
|
||||
|
||||
func HandleHomePage(c *gin.Context) {
|
||||
h := GetBase()
|
||||
h["Version"] = StaticVersion(c)
|
||||
h["Title"] = Ei.BTitle
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["HomePage"] = true
|
||||
h["CurrentPage"] = "blog-home"
|
||||
pn, err := strconv.Atoi(c.Query("pn"))
|
||||
if err != nil || pn < 1 {
|
||||
pn = 1
|
||||
}
|
||||
h["Prev"], h["Next"], h["List"] = PageList(pn, setting.Conf.PageNum)
|
||||
c.HTML(http.StatusOK, "homeLayout.html", h)
|
||||
}
|
||||
|
||||
func HandleSeriesPage(c *gin.Context) {
|
||||
h := GetBase()
|
||||
h["Version"] = StaticVersion(c)
|
||||
h["Title"] = "专题 | " + Ei.BTitle
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["SeriesPage"] = true
|
||||
h["CurrentPage"] = "series"
|
||||
h["Article"] = Ei.PageSeries
|
||||
c.HTML(http.StatusOK, "homeLayout.html", h)
|
||||
}
|
||||
|
||||
func HandleArchivesPage(c *gin.Context) {
|
||||
h := GetBase()
|
||||
h["Version"] = StaticVersion(c)
|
||||
h["Title"] = "归档 | " + Ei.BTitle
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["ArchivesPage"] = true
|
||||
h["CurrentPage"] = "archives"
|
||||
h["Article"] = Ei.PageArchives
|
||||
c.HTML(http.StatusOK, "homeLayout.html", h)
|
||||
}
|
||||
|
||||
func HandleArticlePage(c *gin.Context) {
|
||||
path := c.Param("slug")
|
||||
artc := Ei.MapArticles[path[0:strings.Index(path, ".")]]
|
||||
if artc == nil {
|
||||
HandleNotFound(c)
|
||||
return
|
||||
}
|
||||
h := GetBase()
|
||||
h["Version"] = StaticVersion(c)
|
||||
h["Title"] = artc.Title + " | " + Ei.BTitle
|
||||
h["Path"] = c.Request.URL.Path
|
||||
h["CurrentPage"] = "post-" + artc.Slug
|
||||
if path == "blogroll.html" {
|
||||
h["BlogrollPage"] = true
|
||||
} else if path == "about.html" {
|
||||
h["AboutPage"] = true
|
||||
} else {
|
||||
h["ArticlePage"] = true
|
||||
h["Copyright"] = Ei.Copyright
|
||||
if !artc.UpdateTime.IsZero() {
|
||||
h["Days"] = int(time.Now().Sub(artc.UpdateTime).Hours()) / 24
|
||||
}
|
||||
if artc.SerieID > 0 {
|
||||
h["Serie"] = QuerySerie(artc.SerieID)
|
||||
}
|
||||
}
|
||||
h["Article"] = artc
|
||||
h["EnableHttps"] = runmode.EnableHttps
|
||||
c.HTML(http.StatusOK, "homeLayout.html", h)
|
||||
}
|
||||
|
||||
type temp struct {
|
||||
Title string
|
||||
Slug string
|
||||
URL string
|
||||
Img string
|
||||
CreateTime time.Time
|
||||
}
|
||||
|
||||
func HandleSearchPage(c *gin.Context) {
|
||||
h := GetBase()
|
||||
h["Version"] = StaticVersion(c)
|
||||
h["Title"] = "站内搜索 | " + Ei.BTitle
|
||||
h["Path"] = ""
|
||||
h["SearchPage"] = true
|
||||
h["CurrentPage"] = "search-post"
|
||||
|
||||
q := c.Query("q")
|
||||
start, err := strconv.Atoi(c.Query("start"))
|
||||
if start < 1 || err != nil {
|
||||
start = 1
|
||||
}
|
||||
if q != "" {
|
||||
h["Word"] = q
|
||||
// TODO search
|
||||
var result *ESSearchResult
|
||||
vals := c.Request.URL.Query()
|
||||
reg := regexp.MustCompile(`^[a-z]+:\w+$`)
|
||||
logd.Debug(reg.MatchString(q))
|
||||
if reg.MatchString(q) {
|
||||
result = ElasticsearchSimple(q, setting.Conf.PageNum, start-1)
|
||||
} else {
|
||||
result = Elasticsearch(q, setting.Conf.PageNum, start-1)
|
||||
}
|
||||
if result != nil {
|
||||
result.Took /= 1000
|
||||
for i, v := range result.Hits.Hits {
|
||||
if artc := Ei.MapArticles[result.Hits.Hits[i].Source.Slug]; len(v.Highlight.Content) == 0 && artc != nil {
|
||||
result.Hits.Hits[i].Highlight.Content = []string{artc.Excerpt}
|
||||
}
|
||||
}
|
||||
h["SearchResult"] = result
|
||||
if start-setting.Conf.PageNum > 0 {
|
||||
vals.Set("start", fmt.Sprint(start-setting.Conf.PageNum))
|
||||
h["Prev"] = vals.Encode()
|
||||
}
|
||||
if result.Hits.Total >= start+setting.Conf.PageNum {
|
||||
vals.Set("start", fmt.Sprint(start+setting.Conf.PageNum))
|
||||
h["Next"] = vals.Encode()
|
||||
}
|
||||
}
|
||||
}
|
||||
c.HTML(http.StatusOK, "homeLayout.html", h)
|
||||
}
|
||||
|
||||
func HandleFeed(c *gin.Context) {
|
||||
http.ServeFile(c.Writer, c.Request, "conf/feed.xml")
|
||||
}
|
||||
|
||||
func HandleOpenSearch(c *gin.Context) {
|
||||
c.Header("Content-Type", "application/xml; charset=utf-8")
|
||||
c.Writer.WriteString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
|
||||
c.HTML(http.StatusOK, "opensearch.xml", gin.H{
|
||||
"BTitle": Ei.BTitle,
|
||||
"SubTitle": Ei.SubTitle,
|
||||
})
|
||||
}
|
||||
|
||||
func HandleRobots(c *gin.Context) {
|
||||
http.ServeFile(c.Writer, c.Request, "conf/robots.txt")
|
||||
}
|
||||
|
||||
func HandleSitemap(c *gin.Context) {
|
||||
http.ServeFile(c.Writer, c.Request, "conf/sitemap.xml")
|
||||
}
|
||||
|
||||
func HandleComments(c *gin.Context) {
|
||||
// TODO comments
|
||||
var ss = map[string]interface{}{
|
||||
"errno": 0,
|
||||
"errmsg": "",
|
||||
"data": map[string]interface{}{
|
||||
"next": "",
|
||||
"commentNum": 2,
|
||||
"comments": []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"id": "2361914870",
|
||||
"name": "Rekey Luo",
|
||||
"url": "https://disqus.com/by/rekeyluo/",
|
||||
"avatar": "//a.disquscdn.com/uploads/users/15860/7550/avatar92.jpg?1438917750",
|
||||
"createdAt": "2015-11-16T05:00:02",
|
||||
"createdAtStr": "9 months ago",
|
||||
"message": "你最近对 http2 ssl 相关关注好多啊。",
|
||||
"children": []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"id": "2361915528",
|
||||
"name": "Jerry Qu",
|
||||
"url": "https://disqus.com/by/JerryQu/",
|
||||
"avatar": "//a.disquscdn.com/uploads/users/1668/8837/avatar92.jpg?1472281172",
|
||||
"createdAt": "2015-11-16T05:01:05",
|
||||
"createdAtStr": "9 months ago",
|
||||
"message": "嗯,最近对 web 性能优化这一块研究得比较多。",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
c.JSON(http.StatusOK, ss)
|
||||
}
|
||||
18
glide.lock
generated
Normal file
@@ -0,0 +1,18 @@
|
||||
hash: 0da7cc4f8131804e7a030fd66408ea7b0d8796970eda67b7a18fa7e4f6ab5292
|
||||
updated: 2016-08-06T23:43:20.163798264+08:00
|
||||
imports:
|
||||
- name: github.com/EiBlog/utils
|
||||
version: 5a2bb8d46f95cd0d799a7eeebfb611431305eed3
|
||||
subpackages:
|
||||
- log
|
||||
- mgo
|
||||
- name: gopkg.in/ini.v1
|
||||
version: 9144852efba7c4daf409943ee90767da62d55438
|
||||
- name: gopkg.in/mgo.v2
|
||||
version: 01084657862d7b12d3b10ffd0394357abf8f8bc2
|
||||
subpackages:
|
||||
- bson
|
||||
- internal/json
|
||||
- internal/sasl
|
||||
- internal/scram
|
||||
testImports: []
|
||||
2
glide.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
package: github.com/EiBlog/eiblog
|
||||
import: []
|
||||
26
helper.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
const (
|
||||
SUCCESS = iota
|
||||
FAIL
|
||||
)
|
||||
|
||||
// encrypt password
|
||||
func EncryptPasswd(name, pass string) string {
|
||||
salt := "%$@w*)("
|
||||
h := sha256.New()
|
||||
io.WriteString(h, name)
|
||||
io.WriteString(h, salt)
|
||||
io.WriteString(h, pass)
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
||||
|
||||
func VerifyPasswd(origin, name, input string) bool {
|
||||
return origin == EncryptPasswd(name, input)
|
||||
}
|
||||
19
main.go
Normal file
@@ -0,0 +1,19 @@
|
||||
// Package main provides ...
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
|
||||
"github.com/EiBlog/utils/logd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// set log print level
|
||||
logd.SetLevel(logd.Ldebug)
|
||||
// pprof
|
||||
go func() {
|
||||
http.ListenAndServe(":6060", nil)
|
||||
}()
|
||||
Run()
|
||||
}
|
||||
126
model.go
Normal file
@@ -0,0 +1,126 @@
|
||||
// Package main provides ...
|
||||
package main
|
||||
|
||||
import "time"
|
||||
|
||||
type Account struct {
|
||||
// 账户名
|
||||
Username string
|
||||
// 账户密码
|
||||
Password string
|
||||
// 二次验证token
|
||||
Token string
|
||||
// 账户
|
||||
Email string
|
||||
// 手机号
|
||||
PhoneN string
|
||||
// 住址
|
||||
Address string
|
||||
// 创建时间
|
||||
CreateTime time.Time
|
||||
// 最后登录时间
|
||||
LoginTime time.Time
|
||||
// 登出时间
|
||||
LogoutTime time.Time
|
||||
// 最后登录ip
|
||||
LoginIP string
|
||||
// 博客信息
|
||||
Blogger
|
||||
}
|
||||
|
||||
type Blogger struct {
|
||||
// 博客名
|
||||
BlogName string
|
||||
// SubTitle
|
||||
SubTitle string
|
||||
// 备案号
|
||||
BeiAn string
|
||||
// 底部title
|
||||
BTitle string
|
||||
// 版权声明
|
||||
Copyright string
|
||||
// 专题,倒序
|
||||
SeriesSay string
|
||||
Series SortSeries
|
||||
// 归档描述
|
||||
ArchivesSay string
|
||||
Archives SortArchives
|
||||
// 忽略存储,前端界面全部缓存
|
||||
PageSeries string `bson:"-"` // 专题页面
|
||||
PageArchives string `bson:"-"` // 归档页面
|
||||
Tags map[string]SortArticles `bson:"-"` // 标签 name->tag
|
||||
Articles SortArticles `bson:"-"` // 所有文章
|
||||
MapArticles map[string]*Article `bson:"-"` // url->Article
|
||||
CH chan string `bson:"-"` // channel
|
||||
}
|
||||
|
||||
type Serie struct {
|
||||
// 自增id
|
||||
ID int32
|
||||
// 名称unique
|
||||
Name string
|
||||
// 缩略名
|
||||
Slug string
|
||||
// 专题描述
|
||||
Desc string
|
||||
// 创建时间
|
||||
CreateTime time.Time
|
||||
// 文章
|
||||
Articles SortArticles `bson:"-"`
|
||||
}
|
||||
|
||||
type SortSeries []*Serie
|
||||
|
||||
func (s SortSeries) Len() int { return len(s) }
|
||||
func (s SortSeries) Less(i, j int) bool { return s[i].ID > s[j].ID }
|
||||
func (s SortSeries) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
type Archive struct {
|
||||
Time time.Time
|
||||
Articles SortArticles `bson:"-"`
|
||||
}
|
||||
|
||||
type SortArchives []*Archive
|
||||
|
||||
func (s SortArchives) Len() int { return len(s) }
|
||||
func (s SortArchives) Less(i, j int) bool { return s[i].Time.After(s[j].Time) }
|
||||
func (s SortArchives) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
type Article struct {
|
||||
// 自增id
|
||||
ID int32
|
||||
// 作者名
|
||||
Author string
|
||||
// 标题
|
||||
Title string
|
||||
// 文章名: how-to-get-girlfriend
|
||||
Slug string
|
||||
// 评论数量
|
||||
Count int
|
||||
// markdown文档
|
||||
Content string
|
||||
// 归属专题
|
||||
SerieID int32
|
||||
// tagname
|
||||
Tags []string
|
||||
// 是否是草稿
|
||||
IsDraft bool
|
||||
// 创建时间
|
||||
CreateTime time.Time
|
||||
// 更新时间
|
||||
UpdateTime time.Time
|
||||
// 开始删除时间
|
||||
DeleteTime time.Time
|
||||
// 上篇文章
|
||||
Prev *Article `bson:"-"`
|
||||
// 下篇文章
|
||||
Next *Article `bson:"-"`
|
||||
// 预览信息
|
||||
Excerpt string `bson:"-"`
|
||||
}
|
||||
|
||||
type SortArticles []*Article
|
||||
|
||||
func (s SortArticles) Len() int { return len(s) }
|
||||
func (s SortArticles) Less(i, j int) bool { return s[i].CreateTime.After(s[j].CreateTime) }
|
||||
func (s SortArticles) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
112
router.go
Normal file
@@ -0,0 +1,112 @@
|
||||
// Package main provides ...
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"time"
|
||||
|
||||
"github.com/EiBlog/eiblog/setting"
|
||||
"github.com/EiBlog/utils/logd"
|
||||
"github.com/EiBlog/utils/tmpl"
|
||||
"github.com/gin-gonic/contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var router *gin.Engine
|
||||
var runmode = setting.Conf.Modes[setting.Conf.RunMode]
|
||||
|
||||
func init() {
|
||||
if setting.Conf.RunMode == setting.PROD {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
router = gin.Default()
|
||||
store := sessions.NewCookieStore([]byte("eiblog321"))
|
||||
store.Options(sessions.Options{
|
||||
MaxAge: 86400 * 999,
|
||||
Path: "/",
|
||||
Secure: runmode.EnableHttps,
|
||||
HttpOnly: true,
|
||||
})
|
||||
router.Use(sessions.Sessions("su", store))
|
||||
// 匹配模版
|
||||
//router.LoadHTMLGlob("views/*.html")
|
||||
if tmpl, err := template.New("").Funcs(tmpl.TplFuncMap).ParseGlob("views/*.*"); err == nil {
|
||||
tmpl, err = tmpl.ParseGlob("views/admin/*.html")
|
||||
if err != nil {
|
||||
logd.Fatal(err)
|
||||
}
|
||||
router.SetHTMLTemplate(tmpl)
|
||||
} else {
|
||||
logd.Fatal(err)
|
||||
}
|
||||
// 测试,开启静态文件
|
||||
router.Static("/static", "./static")
|
||||
router.Use(Filter())
|
||||
router.NoRoute(HandleNotFound)
|
||||
router.GET("/", HandleHomePage)
|
||||
router.GET("/post/:slug", HandleArticlePage)
|
||||
router.GET("/series.html", HandleSeriesPage)
|
||||
router.GET("/archives.html", HandleArchivesPage)
|
||||
router.GET("/search.html", HandleSearchPage)
|
||||
router.GET("/data/comment", HandleComments)
|
||||
router.GET("/feed", HandleFeed)
|
||||
router.GET("/opensearch.xml", HandleOpenSearch)
|
||||
router.GET("/sitemap.xml", HandleSitemap)
|
||||
router.GET("/robots.txt", HandleRobots)
|
||||
// 后台相关
|
||||
admin := router.Group("/admin")
|
||||
admin.GET("/login", HandleLogin)
|
||||
admin.POST("/login", HandleLoginPost)
|
||||
auth := admin.Use(AuthFilter())
|
||||
{
|
||||
// console
|
||||
auth.GET("/profile", HandleProfile)
|
||||
auth.GET("/plugins", HandlePlugins)
|
||||
auth.GET("/themes", HandleThemes)
|
||||
// write
|
||||
auth.GET("/write-post", HandlePost)
|
||||
// manage
|
||||
auth.GET("/manage-posts", HandlePosts)
|
||||
auth.GET("/manage-series", HandleSeries)
|
||||
auth.GET("/add-serie", HandleSerie)
|
||||
auth.GET("/manage-tags", HandleTags)
|
||||
auth.GET("/manage-draft", HandleDraft)
|
||||
auth.GET("/manage-trash", HandleTrash)
|
||||
auth.GET("/options-general", HandleGeneral)
|
||||
auth.GET("/options-discussion", HandleDiscussion)
|
||||
auth.GET("/draft-delete", HandleDraftDelete)
|
||||
// api
|
||||
auth.POST("/api/:action", HandleAPI)
|
||||
}
|
||||
}
|
||||
|
||||
func Run() {
|
||||
var (
|
||||
endRunning = make(chan bool, 1)
|
||||
err error
|
||||
)
|
||||
if runmode.EnableHttp {
|
||||
go func() {
|
||||
logd.Info(fmt.Sprintf("http server Running on %d", runmode.HttpPort))
|
||||
err = router.Run(fmt.Sprintf(":%d", runmode.HttpPort))
|
||||
if err != nil {
|
||||
logd.Info("ListenAndServe: ", err)
|
||||
time.Sleep(100 * time.Microsecond)
|
||||
endRunning <- true
|
||||
}
|
||||
}()
|
||||
}
|
||||
if runmode.EnableHttps {
|
||||
go func() {
|
||||
logd.Info(fmt.Sprintf("https server Running on %d", runmode.HttpsPort))
|
||||
err = router.RunTLS(fmt.Sprintf(":%d", runmode.HttpsPort), runmode.CertFile, runmode.KeyFile)
|
||||
if err != nil {
|
||||
logd.Info("ListenAndServe: ", err)
|
||||
time.Sleep(100 * time.Microsecond)
|
||||
endRunning <- true
|
||||
}
|
||||
}()
|
||||
}
|
||||
<-endRunning
|
||||
}
|
||||
91
setting/setting.go
Normal file
@@ -0,0 +1,91 @@
|
||||
// Package setting provides ...
|
||||
package setting
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/EiBlog/utils/logd"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
DEV = "dev"
|
||||
PROD = "prod"
|
||||
)
|
||||
|
||||
var (
|
||||
wd, _ = os.Getwd()
|
||||
Conf = new(Config)
|
||||
BlackIP = make(map[string]bool)
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
StaticVersion int
|
||||
RunMode string
|
||||
Trash int
|
||||
Clean int
|
||||
PageNum int
|
||||
PageSize int
|
||||
Length int
|
||||
Identifier string
|
||||
Favicon string
|
||||
StartID int32
|
||||
Static string
|
||||
SearchURL string
|
||||
Disqus struct {
|
||||
ShortName string
|
||||
PublicKey string
|
||||
URL string
|
||||
Interval int
|
||||
}
|
||||
Modes map[string]RunMode
|
||||
Twitter string
|
||||
RSS string
|
||||
Search string
|
||||
Blogger struct {
|
||||
BlogName string
|
||||
SubTitle string
|
||||
BeiAn string
|
||||
BTitle string
|
||||
Copyright string
|
||||
}
|
||||
Account struct {
|
||||
Username string
|
||||
Password string
|
||||
Email string
|
||||
PhoneNumber string
|
||||
Address string
|
||||
}
|
||||
}
|
||||
|
||||
type RunMode struct {
|
||||
EnableHttp bool
|
||||
HttpPort int
|
||||
EnableHttps bool
|
||||
HttpsPort int
|
||||
CertFile string
|
||||
KeyFile string
|
||||
Domain string
|
||||
}
|
||||
|
||||
func init() {
|
||||
// 初始化配置
|
||||
dir := wd + "/conf"
|
||||
data, err := ioutil.ReadFile(path.Join(dir, "app.yml"))
|
||||
checkError(err)
|
||||
err = yaml.Unmarshal(data, Conf)
|
||||
checkError(err)
|
||||
|
||||
data, err = ioutil.ReadFile(path.Join(dir, "blackip.yml"))
|
||||
checkError(err)
|
||||
err = yaml.Unmarshal(data, BlackIP)
|
||||
chekError(err)
|
||||
}
|
||||
|
||||
func checkError(err error) {
|
||||
if err != nil {
|
||||
logd.Fatal(err)
|
||||
}
|
||||
}
|
||||
12
setting/setting_test.go
Normal file
@@ -0,0 +1,12 @@
|
||||
// Package setting provides ...
|
||||
package setting
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestInit(t *testing.T) {
|
||||
init()
|
||||
fmt.Printf("%v\n", *Conf)
|
||||
}
|
||||
1
static/admin/background.css
Normal file
1
static/admin/diff.js
Normal file
16
static/admin/jquery-ui.js
vendored
Normal file
25
static/admin/jquery.js
vendored
Normal file
1
static/admin/moxie.js
Normal file
1
static/admin/pagedown.js
Normal file
1
static/admin/plupload.js
Normal file
1
static/admin/stmd.js
Normal file
1
static/admin/style.css
Normal file
4
static/admin/timepicker.js
Normal file
1
static/admin/tokeninput.js
Normal file
55
static/admin/typecho.js
Normal file
BIN
static/bg/bg01.jpg
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
static/bg/bg02.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
static/bg/bg03.jpg
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
static/bg/bg04.jpg
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
static/bg/bg05.jpg
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
static/bg/bg06.jpg
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
static/bg/bg07.jpg
Normal file
|
After Width: | Height: | Size: 22 KiB |
1
static/blog.css
Normal file
BIN
static/img/ajax-loader.gif
Normal file
|
After Width: | Height: | Size: 847 B |
BIN
static/img/editor.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
static/img/editor@2x.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
static/img/icons-2x-s481937020b.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
static/img/icons-s0c4f1c5ae6.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
static/img/noscreen.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
10
static/img/typecho-logo.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="110px" height="26px" viewBox="0 0 110 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<title>typecho-logo</title>
|
||||
<description>Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<path d="M34.75,5.288 C34.288,6.542 33.76,7.73 32.22,7.862 L32,9.468 L33.562,9.468 L33.562,15.342 C33.562,16.882 33.54,18.994 36.972,18.994 C38.006,18.994 39.106,18.686 39.766,18.224 L39.106,16.53 C38.754,16.75 38.204,16.992 37.61,16.992 C36.708,16.992 36.18,16.596 36.18,15.254 L36.18,9.468 L38.886,9.468 L39.106,7.62 L36.18,7.62 L36.18,5.288 L34.75,5.288 Z M48.258,18.268 C48.258,20.27 47.444,21.502 45.42,21.502 C44.76,21.502 44.276,21.436 43.858,21.282 C43.462,21.128 43.352,20.908 43.352,20.49 L43.352,19.434 L41.262,19.61 L41.262,22.668 C42.186,23.13 44.012,23.394 45.398,23.394 C48.676,23.394 50.502,21.898 50.502,18.268 L50.502,7.62 L46.63,7.62 L46.63,9.424 L47.334,9.468 C47.752,9.468 47.884,9.644 47.884,10.128 L47.884,14.11 C47.884,15.254 47.07,16.288 45.53,16.288 C44.122,16.288 43.902,15.276 43.902,13.934 L43.902,7.62 L40.03,7.62 L40.03,9.424 L40.734,9.468 C41.108,9.49 41.284,9.622 41.284,10.084 L41.284,14.506 C41.284,17.102 42.494,18.312 44.694,18.312 C46.146,18.312 47.488,17.696 48.258,16.596 L48.258,18.268 Z M54,20.776 C54,21.326 53.78,21.458 53.362,21.502 L52.636,21.568 L52.636,23.24 L58.312,23.24 L58.312,21.502 L56.53,21.414 L56.53,18.378 C57.102,18.73 58.026,19.016 58.884,19.016 C61.788,19.016 63.702,16.926 63.702,12.878 C63.702,8.94 62.162,7.29 59.72,7.29 C57.85,7.29 56.64,8.302 56.244,9.05 L56.244,7.62 L52.526,7.62 L52.526,9.402 L53.45,9.468 C53.868,9.468 54,9.644 54,10.128 L54,20.776 Z M60.974,13.098 C60.974,15.012 60.336,16.926 58.466,16.926 C57.894,16.926 57.102,16.75 56.53,16.376 L56.53,11.316 C56.53,10.304 57.498,9.424 58.752,9.424 C59.918,9.424 60.974,10.172 60.974,13.098 Z M70.786,7.29 C67.178,7.29 65.352,10.15 65.352,13.406 C65.352,16.684 66.804,18.972 70.544,18.972 C72.612,18.972 74.064,18.048 74.416,17.74 L73.58,15.958 C73.052,16.332 72.106,16.926 70.808,16.926 C68.938,16.926 68.19,15.76 68.102,14.33 C70.698,14.308 74.372,13.736 74.372,10.348 C74.372,8.39 72.942,7.29 70.786,7.29 Z M71.952,10.392 C71.952,12.086 69.642,12.46 68.014,12.482 C68.08,10.854 68.872,9.16 70.632,9.16 C71.424,9.16 71.952,9.578 71.952,10.392 Z M81.192,16.97 C79.234,16.97 78.354,15.43 78.354,13.032 C78.354,10.59 79.256,9.27 81.016,9.27 C81.346,9.27 81.61,9.314 81.874,9.402 C82.27,9.534 82.336,9.732 82.336,10.15 L82.336,11.206 L84.36,11.052 L84.36,8.192 C83.304,7.62 82.248,7.29 80.928,7.29 C78.442,7.29 75.692,8.83 75.692,13.296 C75.692,16.948 77.606,18.994 80.84,18.994 C82.468,18.994 83.81,18.422 84.668,17.718 L83.722,16.024 C82.82,16.684 82.05,16.97 81.192,16.97 Z M87.286,16.222 C87.286,16.772 87.066,16.904 86.648,16.948 L85.922,17.014 L85.922,18.686 L91.158,18.686 L91.158,16.926 L89.904,16.86 L89.904,11.536 C89.904,10.392 90.718,9.314 92.258,9.314 C93.666,9.314 93.974,10.348 93.974,11.69 L93.974,16.222 C93.974,16.772 93.754,16.904 93.336,16.948 L92.61,17.014 L92.61,18.686 L97.846,18.686 L97.846,16.926 L96.592,16.86 L96.592,11.118 C96.592,8.522 95.294,7.29 93.094,7.29 C91.642,7.29 90.542,7.972 89.882,8.918 L89.882,3 L85.966,3 L85.966,4.826 L86.736,4.87 C87.154,4.892 87.286,5.024 87.286,5.508 L87.286,16.222 Z M98.924,13.142 C98.924,17.124 100.86,19.016 103.808,19.016 C106.712,19.016 109.066,17.08 109.066,12.856 C109.066,7.796 105.788,7.29 104.16,7.29 C101.894,7.29 98.924,8.566 98.924,13.142 Z M103.984,17.08 C101.872,17.08 101.586,14.88 101.586,12.834 C101.586,10.722 102.29,9.226 104.028,9.226 C105.788,9.226 106.382,10.744 106.382,13.208 C106.382,15.496 105.7,17.08 103.984,17.08 Z" id="typecho" fill="#000000" sketch:type="MSShapeGroup"></path>
|
||||
<path d="M13,26 C3.36833333,26 0,22.631 0,13 C0,3.36866667 3.36833333,0 13,0 C22.6316667,0 26,3.36866667 26,13 C26,22.631 22.6316667,26 13,26 Z M6,9 L20,9 L20,7 L6,7 L6,9 Z M6,14 L16,14 L16,12 L6,12 L6,14 Z M6,19 L18,19 L18,17 L6,17 L6,19 Z" id="icon" fill="#000000" sketch:type="MSShapeGroup"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
6
static/opensearch.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
||||
<ShortName>Deepzz's Blog</ShortName>
|
||||
<Description>不抛弃,不放弃</Description>
|
||||
<Url type="text/html" template="https://deepzz.com/search.html?s={searchTerms}" />
|
||||
</OpenSearchDescription>
|
||||
1
views/404.html
Normal file
@@ -0,0 +1 @@
|
||||
{{define "notfound"}}<div id=content class=inner><article class="post post-404"><h1 class=title>404 - 什么也没有</h1><div class="entry-content"><p>你要找的东东不存在喔!</p><p>请检查 URL 拼写是否有误,或者通过<a href="/search.html"> 站内搜索 </a>搜一下吧~</p></div></article></div>{{end}}
|
||||
1
views/about.html
Normal file
@@ -0,0 +1 @@
|
||||
{{define "about"}}<div id=content class=inner>{{with .Article}}<article class="post post-{{.ID}}" itemscope itemtype="http://schema.org/Article"><h1 class=title itemprop=headline>{{.Title}}</h1><div class="entry-content" itemprop=articleBody>{{str2html .Content}}</div></article><section id=comments><h1 class=title>Comments<span id=switch_thread_mode></h1><div id=disqus_thread class=ds-thread data-identifier="post-{{.Slug}}" data-url="{{if $.EnableHttps}}https://{{else}}http://{{end}}{{$.Domain}}/post/{{.Slug}}.html"></div><div id=simple_thread data-id="golomb-coded-sets"></div></section>{{end}}</div>{{end}}
|
||||
178
views/admin/backLayout.html
Normal file
@@ -0,0 +1,178 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="zh-cn">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{.Title}}</title>
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<link rel="stylesheet" href="/static/admin/background.css">
|
||||
<link rel="stylesheet" href="/static/admin/style.css">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--[if lt IE 9]>
|
||||
<div class="alert alert-danger topframe" role="alert">你的浏览器实在<strong>太太太太太太旧了</strong>,放学别走,升级完浏览器再说 <a target="_blank" class="alert-link" href="http://browsehappy.com">立即升级</a></div>
|
||||
<![endif]-->
|
||||
<script src="/static/admin/jquery.js"></script>
|
||||
<script src="/static/admin/jquery-ui.js"></script>
|
||||
<script src="/static/admin/typecho.js"></script>
|
||||
<div class="typecho-head-nav clearfix" role="navigation">
|
||||
<nav id="typecho-nav-list">
|
||||
<ul class="root {{if .Console}}focus{{end}}">
|
||||
<li class="parent"><a target="_self" href="/admin/profile">控制台</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li {{if eq .Path "/admin/profile"}}class="focus" {{end}}><a target="_self" href="/admin/profile">个人设置</a></li>
|
||||
<li {{if eq .Path "/admin/plugins"}}class="focus" {{end}}><a target="_self" href="/admin/plugins">插件</a></li>
|
||||
<li class="last {{if eq .Path "/admin/themes"}}focus{{end}}"><a target="_self" href="/admin/themes">外观</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root {{if .Post}}focus{{end}}">
|
||||
<li class="parent"><a target="_self" href="/admin/write-post">撰写</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li class="last {{if eq .Path "/admin/write-post"}}focus{{end}}"><a target="_self" href="/admin/write-post">撰写文章</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root {{if .Manage}}focus{{end}}">
|
||||
<li class="parent"><a target="_self" href="/admin/manage-posts">管理</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li {{if eq .Path "/admin/manage-posts"}}class="focus" {{end}}><a target="_self" href="/admin/manage-posts">文章</a></li>
|
||||
<li {{if eq .Path "/admin/manage-series"}}class="focus" {{end}}><a target="_self" href="/admin/manage-series">专题</a></li>
|
||||
{{if eq .Path "/admin/add-serie"}}<li class="focus"><a target="_self" href="/admin/add-serie">{{if .Edit}}编辑专题{{else}}新增专题{{end}}</a></li>{{end}}
|
||||
<li class="last {{if eq .Path "/admin/manage-tags"}}focus{{end}}"><a target="_self" href="/admin/manage-tags">标签</a></li>
|
||||
<li class="last {{if eq .Path "/admin/manage-draft"}}focus{{end}}"><a target="_self" href="/admin/manage-draft">草稿箱</a></li>
|
||||
<li class="last {{if eq .Path "/admin/manage-trash"}}focus{{end}}"><a target="_self" href="/admin/manage-trash">回收箱</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root {{if .Setting}}focus{{end}}">
|
||||
<li class="parent"><a target="_self" href="/admin/options-general">设置</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li {{if eq .Path "/admin/options-general"}}class="focus" {{end}}><a target="_self" href="/admin/options-general">基本</a></li>
|
||||
<li class="last {{if eq .Path "/admin/options-discussion"}}focus{{end}}"><a target="_self" href="/admin/options-discussion">阅读</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="operate">
|
||||
<a target="_self" title="{{.LastLogin}}" href="/admin/profile" class="author">{{.Author}}</a><a class="exit" href="/admin/login?logout=true">登出</a><a target="_back" href="/">网站</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
{{if .Profile}}{{template "admin-profile" .}}{{else if .Post}}{{template "admin-post" .}}{{else if .Posts}}{{template "admin-posts" .}}{{else if .Series}}{{template "admin-series" .}}{{else if .Serie}}{{template "admin-serie" .}}{{else if .Tags}}{{template "admin-tags" .}}{{else if .General}}{{template "admin-general" .}}{{else if .Discussion}}{{template "admin-discussion" .}}{{else if .Draft}}{{template "admin-draft" .}}{{else if .Trash}}{{template "admin-trash" .}}{{end}}
|
||||
</div>
|
||||
<div class="typecho-foot" role="contentinfo">
|
||||
<div class="copyright">
|
||||
<a href="http://typecho.org" class="i-logo-s">Typecho</a>
|
||||
<p>由 <a href="http://typecho.org">Typecho</a> 提供皮肤, 版本 1.0 (14.10.10)</p>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
(function () {
|
||||
$(document).ready(function() {
|
||||
// 处理消息机制
|
||||
(function () {
|
||||
cookies = {
|
||||
notice : $.cookie( 'notice'),
|
||||
noticeType : $.cookie( 'notice_type'),
|
||||
highlight : $.cookie('notice_highlight')
|
||||
},
|
||||
path = '/';
|
||||
|
||||
if (!!cookies.notice && 'success|notice|error'.indexOf(cookies.noticeType) >= 0) {
|
||||
var head = $('.typecho-head-nav'),
|
||||
p = $('<div class="message popup ' + cookies.noticeType + '">'
|
||||
+ '<ul><li>' + $.parseJSON(cookies.notice).join('</li><li>')
|
||||
+ '</li></ul></div>'), offset = 0;
|
||||
|
||||
if (head.length > 0) {
|
||||
p.insertAfter(head);
|
||||
offset = head.outerHeight();
|
||||
} else {
|
||||
p.prependTo(document.body);
|
||||
}
|
||||
|
||||
function checkScroll () {
|
||||
if ($(window).scrollTop() >= offset) {
|
||||
p.css({
|
||||
'position' : 'fixed',
|
||||
'top' : 0
|
||||
});
|
||||
} else {
|
||||
p.css({
|
||||
'position' : 'absolute',
|
||||
'top' : offset
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(window).scroll(function () {
|
||||
checkScroll();
|
||||
});
|
||||
|
||||
checkScroll();
|
||||
|
||||
p.slideDown(function () {
|
||||
var t = $(this), color = '#C6D880';
|
||||
|
||||
if (t.hasClass('error')) {
|
||||
color = '#FBC2C4';
|
||||
} else if (t.hasClass('notice')) {
|
||||
color = '#FFD324';
|
||||
}
|
||||
|
||||
t.effect('highlight', {color : color})
|
||||
.delay(5000).slideUp(function () {
|
||||
$(this).remove();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$.cookie('notice', null, {path : path});
|
||||
$.cookie('notice_type', null, {path : path});
|
||||
}
|
||||
|
||||
if (cookies.highlight) {
|
||||
$('#' + cookies.highlight).effect('highlight', 1000);
|
||||
$.cookie('notice_highlight', null, {path : path});
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
// 导航菜单 tab 聚焦时展开下拉菜单
|
||||
(function () {
|
||||
$('#typecho-nav-list').find('.parent a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
$(this).parents('.root').find('.child').show();
|
||||
});
|
||||
$('.operate').find('a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
});
|
||||
})();
|
||||
|
||||
// if ($('.typecho-login').length == 0) {
|
||||
// $('a').each(function() {
|
||||
// var t = $(this),
|
||||
// href = t.attr('href');
|
||||
|
||||
// if ((href && href[0] == '#') || /^http\:\/\/localhost\/admin\/.*$/.exec(href)) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// t.attr('target', '_blank');
|
||||
// });
|
||||
// }
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
3
views/admin/discussion.html
Normal file
@@ -0,0 +1,3 @@
|
||||
{{define "admin-discussion"}}
|
||||
|
||||
{{end}}
|
||||
81
views/admin/draft.html
Normal file
@@ -0,0 +1,81 @@
|
||||
{{define "admin-draft"}}
|
||||
<div class="body container">
|
||||
<div class="typecho-page-title">
|
||||
<h2>草稿箱</h2>
|
||||
</div>
|
||||
<div class="row typecho-page-main manage-metas">
|
||||
<div class="col-mb-12" role="main">
|
||||
<form method="post" name="manage_draft" class="operate-form">
|
||||
<div class="typecho-list-operate clearfix">
|
||||
<div class="operate">
|
||||
<label><i class="sr-only">全选</i>
|
||||
<input type="checkbox" class="typecho-table-select-all" />
|
||||
</label>
|
||||
<div class="btn-group btn-drop">
|
||||
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only">操作</i>选中项 <i class="i-caret-down"></i></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a lang="此草稿箱下的所有内容将被永久删除, 你确认要删除这些文章吗?" href="/admin/api/draft-delete">删除</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search" role="search">
|
||||
</div>
|
||||
</div>
|
||||
<div class="typecho-table-wrap">
|
||||
<table class="typecho-list-table">
|
||||
<colgroup>
|
||||
<col width="20" />
|
||||
<col width="40%" />
|
||||
<col width="" />
|
||||
<col width="12%" />
|
||||
<col width="14%" />
|
||||
<col width="14%" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th>标题</th>
|
||||
<th>作者</th>
|
||||
<th>专题</th>
|
||||
<th>创建</th>
|
||||
<th>保存</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .List}}
|
||||
<tr id="mid-article-{{.ID}}">
|
||||
<td>
|
||||
<input type="checkbox" value="{{.ID}}" name="mid[]" />
|
||||
</td>
|
||||
<td><a href="/admin/write-post?cid={{.ID}}">{{.Title}}</a></td>
|
||||
<td>{{.Author}}</td>
|
||||
<td>{{if gt .SerieID 0}}专题ID:{{.SerieID}}{{else}}--{{end}}</td>
|
||||
<td>{{dateformat .CreateTime "2006/01/02 15:04"}}</td>
|
||||
<td>{{dateformat .UpdateTime "2006/01/02 15:04"}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
$('.typecho-list-table').tableSelectable({
|
||||
checkEl: 'input[type=checkbox]',
|
||||
rowEl: 'tr',
|
||||
selectAllEl: '.typecho-table-select-all',
|
||||
actionEl: '.dropdown-menu a,button.btn-operate'
|
||||
});
|
||||
|
||||
$('.btn-drop').dropdownMenu({
|
||||
btnEl: '.dropdown-toggle',
|
||||
menuEl: '.dropdown-menu'
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{{end}}
|
||||
3
views/admin/general.html
Normal file
@@ -0,0 +1,3 @@
|
||||
{{define "admin-general"}}
|
||||
|
||||
{{end}}
|
||||
38
views/admin/login.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<!Doctype html>
|
||||
<html lang="zh-cn">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" name=viewport>
|
||||
<meta name=robots content="noindex, nofollow">
|
||||
<title>Login | {{.BTitle}}</title>
|
||||
<link rel=stylesheet href="/static/admin/background.css">
|
||||
</head>
|
||||
|
||||
<body class="body-100">
|
||||
<div class="typecho-login-wrap">
|
||||
<div class="typecho-login">
|
||||
<h1><a href="/">{{.BTitle}}</a></h1>
|
||||
<form action="/admin/login" method=post>
|
||||
<p>
|
||||
<label for=user class="sr-only">用户名</label>
|
||||
<input type=text id=user name=user value="" placeholder="用户名" class="text-l w-100">
|
||||
</p>
|
||||
<p>
|
||||
<label for=password class="sr-only">密码</label>
|
||||
<input type=password id=password name=password class="text-l w-100" placeholder="密码">
|
||||
</p>
|
||||
<!-- <p>
|
||||
<label for=code class="sr-only">两步验证</label>
|
||||
<input type=text id=code name=code class="text-l w-100" placeholder="两步验证">
|
||||
</p> -->
|
||||
<p class=submit>
|
||||
<button type=submit class="btn btn-l w-100 primary">登录</button>
|
||||
</p>
|
||||
</form>
|
||||
<p class="more-link">管理后台皮肤来自于<a href="http://typecho.org" target=_blank>Typecho</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
328
views/admin/origin/articles.html
Normal file
@@ -0,0 +1,328 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="no-js">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>管理文章 - Hello World - Powered by Typecho</title>
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/normalize.css?v=14.10.10">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/grid.css?v=14.10.10">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/style.css?v=14.10.10">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://localhost/admin/js/html5shiv.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/respond.js?v=14.10.10"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--[if lt IE 9]>
|
||||
<div class="message error browsehappy" role="dialog">当前网页 <strong>不支持</strong> 你正在使用的浏览器. 为了正常的访问, 请 <a href="http://browsehappy.com/">升级你的浏览器</a>.</div>
|
||||
<![endif]-->
|
||||
<div class="typecho-head-nav clearfix" role="navigation">
|
||||
<nav id="typecho-nav-list">
|
||||
<ul class="root focus">
|
||||
<li class="parent"><a target="_self" href="/admin/home">控制台</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li target="_self" class="focus"><a href="/admin/home">概要</a></li>
|
||||
<li><a target="_self" href="/admin/profile">个人设置</a></li>
|
||||
<li><a target="_self" href="/admin/plugin">插件</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/theme">外观</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/write">撰写</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li class="last"><a target="_self" href="/admin/write">撰写文章</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/articles">管理</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/articles">文章</a></li>
|
||||
<li><a target="_self" href="/admin/categories">分类</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/tags">标签</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/setting">设置</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/setting">基本</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/reading">阅读</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="operate">
|
||||
<a target="_self" title="最后登录: 7小时前" href="/admin/profile" class="author">admin</a><a target="_self" class="exit" href="/admin/login?logout=true">登出</a><a href="/">网站</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
<div class="body container">
|
||||
<div class="typecho-page-title">
|
||||
<h2>管理文章<a href="http://localhost/admin/write-post.php">新增</a></h2>
|
||||
</div>
|
||||
<div class="row typecho-page-main" role="main">
|
||||
<div class="col-mb-12 typecho-list">
|
||||
<div class="typecho-list-operate clearfix">
|
||||
<form method="get">
|
||||
<div class="operate">
|
||||
<label><i class="sr-only">全选</i>
|
||||
<input type="checkbox" class="typecho-table-select-all" />
|
||||
</label>
|
||||
<div class="btn-group btn-drop">
|
||||
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only">操作</i>选中项 <i class="i-caret-down"></i></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a lang="你确认要删除这些文章吗?" href="http://localhost/index.php/action/contents-post-edit?do=delete&_=448a1ea454e9a1e7c93f8dd9b97b087a">删除</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search" role="search">
|
||||
<input type="text" class="text-s" placeholder="请输入关键字" value="" name="keywords" />
|
||||
<select name="category">
|
||||
<option value="">所有分类</option>
|
||||
<option value="1">默认分类</option>
|
||||
<option value="2">232</option>
|
||||
<option value="3">234</option>
|
||||
<option value="4">2</option>
|
||||
<option value="5">4</option>
|
||||
<option value="6">3</option>
|
||||
<option value="7">5</option>
|
||||
<option value="8">6</option>
|
||||
<option value="9">7</option>
|
||||
<option value="10">8</option>
|
||||
<option value="11">9</option>
|
||||
</select>
|
||||
<button type="submit" class="btn btn-s">筛选</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- end .typecho-list-operate -->
|
||||
<form method="post" name="manage_posts" class="operate-form">
|
||||
<div class="typecho-table-wrap">
|
||||
<table class="typecho-list-table">
|
||||
<colgroup>
|
||||
<col width="20" />
|
||||
<col width="6%" />
|
||||
<col width="45%" />
|
||||
<col width="" />
|
||||
<col width="18%" />
|
||||
<col width="16%" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>标题</th>
|
||||
<th>作者</th>
|
||||
<th>分类</th>
|
||||
<th>日期</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr id="post-3">
|
||||
<td>
|
||||
<input type="checkbox" value="3" name="cid[]" />
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/manage-comments.php?cid=3" class="balloon-button size-1">0</a></td>
|
||||
<td>
|
||||
<a href="http://localhost/admin/write-post.php?cid=3">未命名文档</a>
|
||||
<a href="http://localhost/index.php/archives/3/" title="浏览 未命名文档"><i class="i-exlink"></i></a>
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/manage-posts.php?uid=1">admin</a></td>
|
||||
<td> <a href="http://localhost/admin/manage-posts.php?category=1">默认分类</a> </td>
|
||||
<td>
|
||||
2天前 </td>
|
||||
</tr>
|
||||
<tr id="post-1">
|
||||
<td>
|
||||
<input type="checkbox" value="1" name="cid[]" />
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/manage-comments.php?cid=1" class="balloon-button size-10">1</a></td>
|
||||
<td>
|
||||
<a href="http://localhost/admin/write-post.php?cid=1">欢迎使用 Typecho</a>
|
||||
<a href="http://localhost/index.php/archives/1/" title="浏览 欢迎使用 Typecho"><i class="i-exlink"></i></a>
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/manage-posts.php?uid=1">admin</a></td>
|
||||
<td> <a href="http://localhost/admin/manage-posts.php?category=1">默认分类</a> </td>
|
||||
<td>
|
||||
4天前 </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
<!-- end .operate-form -->
|
||||
<div class="typecho-list-operate clearfix">
|
||||
<form method="get">
|
||||
<div class="operate">
|
||||
<label><i class="sr-only">全选</i>
|
||||
<input type="checkbox" class="typecho-table-select-all" />
|
||||
</label>
|
||||
<div class="btn-group btn-drop">
|
||||
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only">操作</i>选中项 <i class="i-caret-down"></i></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a lang="你确认要删除这些文章吗?" href="http://localhost/index.php/action/contents-post-edit?do=delete&_=448a1ea454e9a1e7c93f8dd9b97b087a">删除</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="typecho-pager">
|
||||
<li class="current"><a href="http://localhost/admin/manage-posts.php?page=1">1</a></li>
|
||||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
<!-- end .typecho-list-operate -->
|
||||
</div>
|
||||
<!-- end .typecho-list -->
|
||||
</div>
|
||||
<!-- end .typecho-page-main -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="typecho-foot" role="contentinfo">
|
||||
<div class="copyright">
|
||||
<a href="http://typecho.org" class="i-logo-s">Typecho</a>
|
||||
<p>由 <a href="http://typecho.org">Typecho</a> 强力驱动, 版本 1.0 (14.10.10)</p>
|
||||
</div>
|
||||
<nav class="resource">
|
||||
<a href="http://docs.typecho.org">帮助文档</a> •
|
||||
<a href="http://forum.typecho.org">支持论坛</a> •
|
||||
<a href="https://github.com/typecho/typecho/issues">报告错误</a> •
|
||||
<a href="http://extends.typecho.org">资源下载</a>
|
||||
</nav>
|
||||
</div>
|
||||
<script src="http://localhost/admin/js/jquery.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/jquery-ui.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/typecho.js?v=14.10.10"></script>
|
||||
<script>
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
// 处理消息机制
|
||||
(function() {
|
||||
var prefix = '86a9106ae65537651a8e456835b316ab',
|
||||
cookies = {
|
||||
notice: $.cookie(prefix + '__typecho_notice'),
|
||||
noticeType: $.cookie(prefix + '__typecho_notice_type'),
|
||||
highlight: $.cookie(prefix + '__typecho_notice_highlight')
|
||||
},
|
||||
path = '/';
|
||||
|
||||
if (!!cookies.notice && 'success|notice|error'.indexOf(cookies.noticeType) >= 0) {
|
||||
var head = $('.typecho-head-nav'),
|
||||
p = $('<div class="message popup ' + cookies.noticeType + '">' + '<ul><li>' + $.parseJSON(cookies.notice).join('</li><li>') + '</li></ul></div>'),
|
||||
offset = 0;
|
||||
|
||||
if (head.length > 0) {
|
||||
p.insertAfter(head);
|
||||
offset = head.outerHeight();
|
||||
} else {
|
||||
p.prependTo(document.body);
|
||||
}
|
||||
|
||||
function checkScroll() {
|
||||
if ($(window).scrollTop() >= offset) {
|
||||
p.css({
|
||||
'position': 'fixed',
|
||||
'top': 0
|
||||
});
|
||||
} else {
|
||||
p.css({
|
||||
'position': 'absolute',
|
||||
'top': offset
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(window).scroll(function() {
|
||||
checkScroll();
|
||||
});
|
||||
|
||||
checkScroll();
|
||||
|
||||
p.slideDown(function() {
|
||||
var t = $(this),
|
||||
color = '#C6D880';
|
||||
|
||||
if (t.hasClass('error')) {
|
||||
color = '#FBC2C4';
|
||||
} else if (t.hasClass('notice')) {
|
||||
color = '#FFD324';
|
||||
}
|
||||
|
||||
t.effect('highlight', {
|
||||
color: color
|
||||
})
|
||||
.delay(5000).slideUp(function() {
|
||||
$(this).remove();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$.cookie(prefix + '__typecho_notice', null, {
|
||||
path: path
|
||||
});
|
||||
$.cookie(prefix + '__typecho_notice_type', null, {
|
||||
path: path
|
||||
});
|
||||
}
|
||||
|
||||
if (cookies.highlight) {
|
||||
$('#' + cookies.highlight).effect('highlight', 1000);
|
||||
$.cookie(prefix + '__typecho_notice_highlight', null, {
|
||||
path: path
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
// 导航菜单 tab 聚焦时展开下拉菜单
|
||||
(function() {
|
||||
$('#typecho-nav-list').find('.parent a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
$(this).parents('.root').find('.child').show();
|
||||
});
|
||||
$('.operate').find('a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
if ($('.typecho-login').length == 0) {
|
||||
$('a').each(function() {
|
||||
var t = $(this),
|
||||
href = t.attr('href');
|
||||
|
||||
if ((href && href[0] == '#') || /^http\:\/\/localhost\/admin\/.*$/.exec(href) || /^http\:\/\/localhost\/index\.php\/action\/[_a-zA-Z0-9\/]+.*$/.exec(href)) {
|
||||
return;
|
||||
}
|
||||
|
||||
t.attr('target', '_blank');
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
$('.typecho-list-table').tableSelectable({
|
||||
checkEl: 'input[type=checkbox]',
|
||||
rowEl: 'tr',
|
||||
selectAllEl: '.typecho-table-select-all',
|
||||
actionEl: '.dropdown-menu a,button.btn-operate'
|
||||
});
|
||||
|
||||
$('.btn-drop').dropdownMenu({
|
||||
btnEl: '.dropdown-toggle',
|
||||
menuEl: '.dropdown-menu'
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
79
views/admin/origin/backLayout.html
Normal file
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="zh-cn">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{.Title}}</title>
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<link rel="stylesheet" href="/static/admin/background.css">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--[if lt IE 9]>
|
||||
<div class="alert alert-danger topframe" role="alert">你的浏览器实在<strong>太太太太太太旧了</strong>,放学别走,升级完浏览器再说 <a target="_blank" class="alert-link" href="http://browsehappy.com">立即升级</a></div>
|
||||
<![endif]-->
|
||||
<div class="typecho-head-nav clearfix" role="navigation">
|
||||
<nav id="typecho-nav-list">
|
||||
<ul class="root {{if .Console}}focus{{end}}">
|
||||
<li class="parent"><a target="_self" href="/admin/home">控制台</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li {{if eq .Path "/admin/home"}}class="focus"{{end}}><a target="_self" href="/admin/home">概要</a></li>
|
||||
<li {{if eq .Path "/admin/profile"}}class="focus"{{end}}><a target="_self" href="/admin/profile">个人设置</a></li>
|
||||
<li {{if eq .Path "/admin/plugin"}}class="focus"{{end}}><a target="_self" href="/admin/plugin">插件</a></li>
|
||||
<li class="last {{if eq .Path "/admin/theme"}}focus{{end}}"><a target="_self" href="/admin/theme">外观</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root {{if .Write}}focus{{end}}">
|
||||
<li class="parent"><a target="_self" href="/admin/write">撰写</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li class="last"><a target="_self" href="/admin/write">撰写文章</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root {{if .Manage}}focus{{end}}">
|
||||
<li class="parent"><a target="_self" href="/admin/articles">管理</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/articles">文章</a></li>
|
||||
<li><a target="_self" href="/admin/series">分类</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/tags">标签</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root {{if .Setting}}focus{{end}}">
|
||||
<li class="parent"><a target="_self" href="/admin/setting">设置</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/setting">基本</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/reading">阅读</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="operate">
|
||||
<a target="_self" title="{{.LastLogin}}" href="/admin/profile" class="author">admin</a><a target="_self" class="exit" href="/admin/login?logout=true">登出</a><a href="/">网站</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
</div>
|
||||
<div class="typecho-foot" role="contentinfo">
|
||||
<div class="copyright">
|
||||
<a href="http://typecho.org" class="i-logo-s">Typecho</a>
|
||||
<p>由 <a href="http://typecho.org">Typecho</a> 强力驱动, 版本 1.0 (14.10.10)</p>
|
||||
</div>
|
||||
<nav class="resource">
|
||||
<a href="http://docs.typecho.org">帮助文档</a> •
|
||||
<a href="http://forum.typecho.org">支持论坛</a> •
|
||||
<a href="https://github.com/typecho/typecho/issues">报告错误</a> •
|
||||
<a href="http://extends.typecho.org">资源下载</a>
|
||||
</nav>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
1
views/admin/origin/home.html
Normal file
@@ -0,0 +1 @@
|
||||
none
|
||||
38
views/admin/origin/login.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<!Doctype html>
|
||||
<html lang="zh-cn">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" name=viewport>
|
||||
<meta name=robots content="noindex, nofollow">
|
||||
<title>Login | {{.BTitle}}</title>
|
||||
<link rel=stylesheet href="/static/admin/background.css">
|
||||
</head>
|
||||
|
||||
<body class="body-100">
|
||||
<div class="typecho-login-wrap">
|
||||
<div class="typecho-login">
|
||||
<h1><a href="/">{{.BTitle}}</a></h1>
|
||||
<form action="/admin/api/login" method=post>
|
||||
<p>
|
||||
<label for=user class="sr-only">用户名</label>
|
||||
<input type=text id=user name=user value="" placeholder="用户名" class="text-l w-100">
|
||||
</p>
|
||||
<p>
|
||||
<label for=password class="sr-only">密码</label>
|
||||
<input type=password id=password name=password class="text-l w-100" placeholder="密码">
|
||||
</p>
|
||||
<p>
|
||||
<label for=code class="sr-only">两步验证</label>
|
||||
<input type=text id=code name=code class="text-l w-100" placeholder="两步验证">
|
||||
</p>
|
||||
<p class=submit>
|
||||
<button type=submit class="btn btn-l w-100 primary">登录</button>
|
||||
</p>
|
||||
</form>
|
||||
<p class="more-link">管理后台皮肤来自于<a href="http://typecho.org" target=_blank>Typecho</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
393
views/admin/origin/profile.html
Normal file
@@ -0,0 +1,393 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="no-js">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>个人设置 - Hello World - Powered by Typecho</title>
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/normalize.css?v=14.10.10">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/grid.css?v=14.10.10">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/style.css?v=14.10.10">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://localhost/admin/js/html5shiv.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/respond.js?v=14.10.10"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--[if lt IE 9]>
|
||||
<div class="message error browsehappy" role="dialog">当前网页 <strong>不支持</strong> 你正在使用的浏览器. 为了正常的访问, 请 <a href="http://browsehappy.com/">升级你的浏览器</a>.</div>
|
||||
<![endif]-->
|
||||
<div class="typecho-head-nav clearfix" role="navigation">
|
||||
<nav id="typecho-nav-list">
|
||||
<ul class="root focus">
|
||||
<li class="parent"><a target="_self" href="/admin/home">控制台</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li target="_self" class="focus"><a href="/admin/home">概要</a></li>
|
||||
<li><a target="_self" href="/admin/profile">个人设置</a></li>
|
||||
<li><a target="_self" href="/admin/plugin">插件</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/theme">外观</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/write">撰写</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li class="last"><a target="_self" href="/admin/write">撰写文章</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/articles">管理</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/articles">文章</a></li>
|
||||
<li><a target="_self" href="/admin/categories">分类</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/tags">标签</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/setting">设置</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/setting">基本</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/reading">阅读</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="operate">
|
||||
<a target="_self" title="最后登录: 7小时前" href="/admin/profile" class="author">admin</a><a target="_self" class="exit" href="/admin/login?logout=true">登出</a><a href="/">网站</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
<div class="body container">
|
||||
<div class="typecho-page-title">
|
||||
<h2>个人设置</h2>
|
||||
</div>
|
||||
<div class="row typecho-page-main">
|
||||
<div class="col-mb-12 col-tb-3">
|
||||
<p>
|
||||
<a href="http://gravatar.com/emails/" title="在 Gravatar 上修改头像"><img class="profile-avatar" src="http://www.gravatar.com/avatar/20a5844bc608d51cdbe28b74495f809d?s=220&r=X&d=mm" alt="admin" /></a>
|
||||
</p>
|
||||
<h2>admin</h2>
|
||||
<p>admin</p>
|
||||
<p>目前有 <em>2</em> 篇日志, 并有 <em>1</em> 条关于你的评论在 <em>11</em> 个分类中.</p>
|
||||
<p>最后登录: 2天前</p>
|
||||
</div>
|
||||
<div class="col-mb-12 col-tb-6 col-tb-offset-1 typecho-content-panel" role="form">
|
||||
<section>
|
||||
<h3>个人资料</h3>
|
||||
<form action="http://localhost/index.php/action/users-profile?_=48e2b106ce2f611ac20443fb2acdc076" method="post" enctype="application/x-www-form-urlencoded">
|
||||
<ul class="typecho-option" id="typecho-option-item-screenName-0">
|
||||
<li>
|
||||
<label class="typecho-label" for="screenName-0-1">
|
||||
昵称</label>
|
||||
<input id="screenName-0-1" name="screenName" type="text" class="text" value="admin" />
|
||||
<p class="description">
|
||||
用户昵称可以与用户名不同, 用于前台显示.
|
||||
<br />如果你将此项留空, 将默认使用用户名.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-url-1">
|
||||
<li>
|
||||
<label class="typecho-label" for="url-0-2">
|
||||
个人主页地址</label>
|
||||
<input id="url-0-2" name="url" type="text" class="text" value="http://www.typecho.org" />
|
||||
<p class="description">
|
||||
此用户的个人主页地址, 请用 <code>http://</code> 开头.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-mail-2">
|
||||
<li>
|
||||
<label class="typecho-label" for="mail-0-3">
|
||||
电子邮箱地址 *</label>
|
||||
<input id="mail-0-3" name="mail" type="text" class="text" value="webmaster@yourdomain.com" />
|
||||
<p class="description">
|
||||
电子邮箱地址将作为此用户的主要联系方式.
|
||||
<br />请不要与系统中现有的电子邮箱地址重复.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-do-3" style="display:none">
|
||||
<li>
|
||||
<input name="do" type="hidden" value="profile" />
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option typecho-option-submit" id="typecho-option-item-submit-4">
|
||||
<li>
|
||||
<button type="submit" class="btn primary">
|
||||
更新我的档案</button>
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
</section>
|
||||
<br>
|
||||
<section id="writing-option">
|
||||
<h3>撰写设置</h3>
|
||||
<form action="http://localhost/index.php/action/users-profile?_=48e2b106ce2f611ac20443fb2acdc076" method="post" enctype="application/x-www-form-urlencoded">
|
||||
<ul class="typecho-option" id="typecho-option-item-markdown-5">
|
||||
<li>
|
||||
<label class="typecho-label">
|
||||
使用 Markdown 语法编辑和解析内容</label>
|
||||
<span>
|
||||
<input name="markdown" type="radio" value="0" id="markdown-0" />
|
||||
<label for="markdown-0">
|
||||
关闭</label>
|
||||
</span>
|
||||
<span>
|
||||
<input name="markdown" type="radio" value="1" id="markdown-1" checked="true" />
|
||||
<label for="markdown-1">
|
||||
打开</label>
|
||||
</span>
|
||||
<p class="description">
|
||||
使用 <a href="http://daringfireball.net/projects/markdown/">Markdown</a> 语法能够使您的撰写过程更加简便直观.
|
||||
<br />此功能开启不会影响以前没有使用 Markdown 语法编辑的内容.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-autoSave-6">
|
||||
<li>
|
||||
<label class="typecho-label">
|
||||
自动保存</label>
|
||||
<span>
|
||||
<input name="autoSave" type="radio" value="0" id="autoSave-0" checked="true" />
|
||||
<label for="autoSave-0">
|
||||
关闭</label>
|
||||
</span>
|
||||
<span>
|
||||
<input name="autoSave" type="radio" value="1" id="autoSave-1" />
|
||||
<label for="autoSave-1">
|
||||
打开</label>
|
||||
</span>
|
||||
<p class="description">
|
||||
自动保存功能可以更好地保护你的文章不会丢失.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-defaultAllow-7">
|
||||
<li>
|
||||
<label class="typecho-label">
|
||||
默认允许</label>
|
||||
<span>
|
||||
<input name="defaultAllow[]" type="checkbox" value="comment" id="defaultAllow-comment" checked="true" />
|
||||
<label for="defaultAllow-comment">
|
||||
可以被评论</label>
|
||||
</span>
|
||||
<span>
|
||||
<input name="defaultAllow[]" type="checkbox" value="ping" id="defaultAllow-ping" checked="true" />
|
||||
<label for="defaultAllow-ping">
|
||||
可以被引用</label>
|
||||
</span>
|
||||
<span>
|
||||
<input name="defaultAllow[]" type="checkbox" value="feed" id="defaultAllow-feed" checked="true" />
|
||||
<label for="defaultAllow-feed">
|
||||
出现在聚合中</label>
|
||||
</span>
|
||||
<p class="description">
|
||||
设置你经常使用的默认允许权限</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-do-8" style="display:none">
|
||||
<li>
|
||||
<input name="do" type="hidden" value="options" />
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option typecho-option-submit" id="typecho-option-item-submit-9">
|
||||
<li>
|
||||
<button type="submit" class="btn primary">
|
||||
保存设置</button>
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
</section>
|
||||
<br>
|
||||
<section id="change-password">
|
||||
<h3>密码修改</h3>
|
||||
<form action="http://localhost/index.php/action/users-profile?_=48e2b106ce2f611ac20443fb2acdc076" method="post" enctype="application/x-www-form-urlencoded">
|
||||
<ul class="typecho-option" id="typecho-option-item-password-10">
|
||||
<li>
|
||||
<label class="typecho-label" for="password-0-11">
|
||||
用户密码</label>
|
||||
<input id="password-0-11" name="password" type="password" class="w-60" />
|
||||
<p class="description">
|
||||
为此用户分配一个密码.
|
||||
<br />建议使用特殊字符与字母、数字的混编样式,以增加系统安全性.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-confirm-11">
|
||||
<li>
|
||||
<label class="typecho-label" for="confirm-0-12">
|
||||
用户密码确认</label>
|
||||
<input id="confirm-0-12" name="confirm" type="password" class="w-60" />
|
||||
<p class="description">
|
||||
请确认你的密码, 与上面输入的密码保持一致.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-do-12" style="display:none">
|
||||
<li>
|
||||
<input name="do" type="hidden" value="password" />
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option typecho-option-submit" id="typecho-option-item-submit-13">
|
||||
<li>
|
||||
<button type="submit" class="btn primary">
|
||||
更新密码</button>
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="typecho-foot" role="contentinfo">
|
||||
<div class="copyright">
|
||||
<a href="http://typecho.org" class="i-logo-s">Typecho</a>
|
||||
<p>由 <a href="http://typecho.org">Typecho</a> 强力驱动, 版本 1.0 (14.10.10)</p>
|
||||
</div>
|
||||
<nav class="resource">
|
||||
<a href="http://docs.typecho.org">帮助文档</a> •
|
||||
<a href="http://forum.typecho.org">支持论坛</a> •
|
||||
<a href="https://github.com/typecho/typecho/issues">报告错误</a> •
|
||||
<a href="http://extends.typecho.org">资源下载</a>
|
||||
</nav>
|
||||
</div>
|
||||
<script src="http://localhost/admin/js/jquery.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/jquery-ui.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/typecho.js?v=14.10.10"></script>
|
||||
<script>
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
// 处理消息机制
|
||||
(function() {
|
||||
var prefix = '86a9106ae65537651a8e456835b316ab',
|
||||
cookies = {
|
||||
notice: $.cookie(prefix + '__typecho_notice'),
|
||||
noticeType: $.cookie(prefix + '__typecho_notice_type'),
|
||||
highlight: $.cookie(prefix + '__typecho_notice_highlight')
|
||||
},
|
||||
path = '/';
|
||||
|
||||
if (!!cookies.notice && 'success|notice|error'.indexOf(cookies.noticeType) >= 0) {
|
||||
var head = $('.typecho-head-nav'),
|
||||
p = $('<div class="message popup ' + cookies.noticeType + '">' + '<ul><li>' + $.parseJSON(cookies.notice).join('</li><li>') + '</li></ul></div>'),
|
||||
offset = 0;
|
||||
|
||||
if (head.length > 0) {
|
||||
p.insertAfter(head);
|
||||
offset = head.outerHeight();
|
||||
} else {
|
||||
p.prependTo(document.body);
|
||||
}
|
||||
|
||||
function checkScroll() {
|
||||
if ($(window).scrollTop() >= offset) {
|
||||
p.css({
|
||||
'position': 'fixed',
|
||||
'top': 0
|
||||
});
|
||||
} else {
|
||||
p.css({
|
||||
'position': 'absolute',
|
||||
'top': offset
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(window).scroll(function() {
|
||||
checkScroll();
|
||||
});
|
||||
|
||||
checkScroll();
|
||||
|
||||
p.slideDown(function() {
|
||||
var t = $(this),
|
||||
color = '#C6D880';
|
||||
|
||||
if (t.hasClass('error')) {
|
||||
color = '#FBC2C4';
|
||||
} else if (t.hasClass('notice')) {
|
||||
color = '#FFD324';
|
||||
}
|
||||
|
||||
t.effect('highlight', {
|
||||
color: color
|
||||
})
|
||||
.delay(5000).slideUp(function() {
|
||||
$(this).remove();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$.cookie(prefix + '__typecho_notice', null, {
|
||||
path: path
|
||||
});
|
||||
$.cookie(prefix + '__typecho_notice_type', null, {
|
||||
path: path
|
||||
});
|
||||
}
|
||||
|
||||
if (cookies.highlight) {
|
||||
$('#' + cookies.highlight).effect('highlight', 1000);
|
||||
$.cookie(prefix + '__typecho_notice_highlight', null, {
|
||||
path: path
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
// 导航菜单 tab 聚焦时展开下拉菜单
|
||||
(function() {
|
||||
$('#typecho-nav-list').find('.parent a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
$(this).parents('.root').find('.child').show();
|
||||
});
|
||||
$('.operate').find('a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
if ($('.typecho-login').length == 0) {
|
||||
$('a').each(function() {
|
||||
var t = $(this),
|
||||
href = t.attr('href');
|
||||
|
||||
if ((href && href[0] == '#') || /^http\:\/\/localhost\/admin\/.*$/.exec(href) || /^http\:\/\/localhost\/index\.php\/action\/[_a-zA-Z0-9\/]+.*$/.exec(href)) {
|
||||
return;
|
||||
}
|
||||
|
||||
t.attr('target', '_blank');
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
var error = $('.typecho-option .error:first');
|
||||
|
||||
if (error.length > 0) {
|
||||
$('html,body').scrollTop(error.parents('.typecho-option').offset().top);
|
||||
}
|
||||
|
||||
$('form').submit(function() {
|
||||
if (this.submitted) {
|
||||
return false;
|
||||
} else {
|
||||
this.submitted = true;
|
||||
}
|
||||
});
|
||||
|
||||
$('label input[type=text]').click(function(e) {
|
||||
var check = $('#' + $(this).parents('label').attr('for'));
|
||||
check.prop('checked', true);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
311
views/admin/origin/reading.html
Normal file
@@ -0,0 +1,311 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="no-js">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>阅读设置 - Hello World - Powered by Typecho</title>
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/normalize.css?v=14.10.10">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/grid.css?v=14.10.10">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/style.css?v=14.10.10">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://localhost/admin/js/html5shiv.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/respond.js?v=14.10.10"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--[if lt IE 9]>
|
||||
<div class="message error browsehappy" role="dialog">当前网页 <strong>不支持</strong> 你正在使用的浏览器. 为了正常的访问, 请 <a href="http://browsehappy.com/">升级你的浏览器</a>.</div>
|
||||
<![endif]-->
|
||||
<div class="typecho-head-nav clearfix" role="navigation">
|
||||
<nav id="typecho-nav-list">
|
||||
<ul class="root focus">
|
||||
<li class="parent"><a target="_self" href="/admin/home">控制台</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li target="_self" class="focus"><a href="/admin/home">概要</a></li>
|
||||
<li><a target="_self" href="/admin/profile">个人设置</a></li>
|
||||
<li><a target="_self" href="/admin/plugin">插件</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/theme">外观</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/write">撰写</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li class="last"><a target="_self" href="/admin/write">撰写文章</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/articles">管理</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/articles">文章</a></li>
|
||||
<li><a target="_self" href="/admin/categories">分类</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/tags">标签</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/setting">设置</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/setting">基本</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/reading">阅读</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="operate">
|
||||
<a target="_self" title="最后登录: 7小时前" href="/admin/profile" class="author">admin</a><a target="_self" class="exit" href="/admin/login?logout=true">登出</a><a href="/">网站</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
<div class="body container">
|
||||
<div class="typecho-page-title">
|
||||
<h2>阅读设置</h2>
|
||||
</div>
|
||||
<div class="row typecho-page-main" role="form">
|
||||
<div class="col-mb-12 col-tb-8 col-tb-offset-2">
|
||||
<form action="http://localhost/index.php/action/options-reading?_=e53d9ccaafcd7253533d0586ebb24d30" method="post" enctype="application/x-www-form-urlencoded">
|
||||
<ul class="typecho-option" id="typecho-option-item-postDateFormat-0">
|
||||
<li>
|
||||
<label class="typecho-label" for="postDateFormat-0-1">
|
||||
文章日期格式</label>
|
||||
<input id="postDateFormat-0-1" name="postDateFormat" type="text" class="w-40 mono" value="Y-m-d" />
|
||||
<p class="description">
|
||||
此格式用于指定显示在文章归档中的日期默认显示格式.
|
||||
<br />在某些主题中这个格式可能不会生效, 因为主题作者可以自定义日期格式.
|
||||
<br />请参考 <a href="http://www.php.net/manual/zh/function.date.php">PHP 日期格式写法</a>.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-frontPage-1">
|
||||
<li>
|
||||
<label class="typecho-label">
|
||||
站点首页</label>
|
||||
<span class="multiline">
|
||||
<input name="frontPage" type="radio" value="recent" id="frontPage-recent" checked="true" />
|
||||
<label for="frontPage-recent">
|
||||
显示最新发布的文章</label>
|
||||
</span>
|
||||
<span class="multiline">
|
||||
<input name="frontPage" type="radio" value="page" id="frontPage-page" />
|
||||
<label for="frontPage-page">
|
||||
使用 </label><select name="frontPagePage" id="frontPage-frontPagePage"><option value="2">关于</option></select><label for="frontPage-frontPagePage"> 页面作为首页</label></span><span class="multiline front-archive hidden"><input type="checkbox" id="frontArchive" name="frontArchive" value="1" />
|
||||
<label for="frontArchive">同时将文章列表页路径更改为 <input type="text" name="archivePattern" class="w-20 mono" value="/blog/" /></label></label>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-postsListSize-2">
|
||||
<li>
|
||||
<label class="typecho-label" for="postsListSize-0-3">
|
||||
文章列表数目</label>
|
||||
<input id="postsListSize-0-3" name="postsListSize" type="text" class="w-20" value="10" />
|
||||
<p class="description">
|
||||
此数目用于指定显示在侧边栏中的文章列表数目.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-pageSize-3">
|
||||
<li>
|
||||
<label class="typecho-label" for="pageSize-0-4">
|
||||
每页文章数目</label>
|
||||
<input id="pageSize-0-4" name="pageSize" type="text" class="w-20" value="5" />
|
||||
<p class="description">
|
||||
此数目用于指定文章归档输出时每页显示的文章数目.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-feedFullText-4">
|
||||
<li>
|
||||
<label class="typecho-label">
|
||||
聚合全文输出</label>
|
||||
<span>
|
||||
<input name="feedFullText" type="radio" value="0" id="feedFullText-0" />
|
||||
<label for="feedFullText-0">
|
||||
仅输出摘要</label>
|
||||
</span>
|
||||
<span>
|
||||
<input name="feedFullText" type="radio" value="1" id="feedFullText-1" checked="true" />
|
||||
<label for="feedFullText-1">
|
||||
全文输出</label>
|
||||
</span>
|
||||
<p class="description">
|
||||
如果你不希望在聚合中输出文章全文,请使用仅输出摘要选项.
|
||||
<br />摘要的文字取决于你在文章中使用分隔符的位置.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option typecho-option-submit" id="typecho-option-item-submit-5">
|
||||
<li>
|
||||
<button type="submit" class="btn primary">
|
||||
保存设置</button>
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="typecho-foot" role="contentinfo">
|
||||
<div class="copyright">
|
||||
<a href="http://typecho.org" class="i-logo-s">Typecho</a>
|
||||
<p>由 <a href="http://typecho.org">Typecho</a> 强力驱动, 版本 1.0 (14.10.10)</p>
|
||||
</div>
|
||||
<nav class="resource">
|
||||
<a href="http://docs.typecho.org">帮助文档</a> •
|
||||
<a href="http://forum.typecho.org">支持论坛</a> •
|
||||
<a href="https://github.com/typecho/typecho/issues">报告错误</a> •
|
||||
<a href="http://extends.typecho.org">资源下载</a>
|
||||
</nav>
|
||||
</div>
|
||||
<script src="http://localhost/admin/js/jquery.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/jquery-ui.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/typecho.js?v=14.10.10"></script>
|
||||
<script>
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
// 处理消息机制
|
||||
(function() {
|
||||
var prefix = '86a9106ae65537651a8e456835b316ab',
|
||||
cookies = {
|
||||
notice: $.cookie(prefix + '__typecho_notice'),
|
||||
noticeType: $.cookie(prefix + '__typecho_notice_type'),
|
||||
highlight: $.cookie(prefix + '__typecho_notice_highlight')
|
||||
},
|
||||
path = '/';
|
||||
|
||||
if (!!cookies.notice && 'success|notice|error'.indexOf(cookies.noticeType) >= 0) {
|
||||
var head = $('.typecho-head-nav'),
|
||||
p = $('<div class="message popup ' + cookies.noticeType + '">' + '<ul><li>' + $.parseJSON(cookies.notice).join('</li><li>') + '</li></ul></div>'),
|
||||
offset = 0;
|
||||
|
||||
if (head.length > 0) {
|
||||
p.insertAfter(head);
|
||||
offset = head.outerHeight();
|
||||
} else {
|
||||
p.prependTo(document.body);
|
||||
}
|
||||
|
||||
function checkScroll() {
|
||||
if ($(window).scrollTop() >= offset) {
|
||||
p.css({
|
||||
'position': 'fixed',
|
||||
'top': 0
|
||||
});
|
||||
} else {
|
||||
p.css({
|
||||
'position': 'absolute',
|
||||
'top': offset
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(window).scroll(function() {
|
||||
checkScroll();
|
||||
});
|
||||
|
||||
checkScroll();
|
||||
|
||||
p.slideDown(function() {
|
||||
var t = $(this),
|
||||
color = '#C6D880';
|
||||
|
||||
if (t.hasClass('error')) {
|
||||
color = '#FBC2C4';
|
||||
} else if (t.hasClass('notice')) {
|
||||
color = '#FFD324';
|
||||
}
|
||||
|
||||
t.effect('highlight', {
|
||||
color: color
|
||||
})
|
||||
.delay(5000).slideUp(function() {
|
||||
$(this).remove();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$.cookie(prefix + '__typecho_notice', null, {
|
||||
path: path
|
||||
});
|
||||
$.cookie(prefix + '__typecho_notice_type', null, {
|
||||
path: path
|
||||
});
|
||||
}
|
||||
|
||||
if (cookies.highlight) {
|
||||
$('#' + cookies.highlight).effect('highlight', 1000);
|
||||
$.cookie(prefix + '__typecho_notice_highlight', null, {
|
||||
path: path
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
// 导航菜单 tab 聚焦时展开下拉菜单
|
||||
(function() {
|
||||
$('#typecho-nav-list').find('.parent a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
$(this).parents('.root').find('.child').show();
|
||||
});
|
||||
$('.operate').find('a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
if ($('.typecho-login').length == 0) {
|
||||
$('a').each(function() {
|
||||
var t = $(this),
|
||||
href = t.attr('href');
|
||||
|
||||
if ((href && href[0] == '#') || /^http\:\/\/localhost\/admin\/.*$/.exec(href) || /^http\:\/\/localhost\/index\.php\/action\/[_a-zA-Z0-9\/]+.*$/.exec(href)) {
|
||||
return;
|
||||
}
|
||||
|
||||
t.attr('target', '_blank');
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
var error = $('.typecho-option .error:first');
|
||||
|
||||
if (error.length > 0) {
|
||||
$('html,body').scrollTop(error.parents('.typecho-option').offset().top);
|
||||
}
|
||||
|
||||
$('form').submit(function() {
|
||||
if (this.submitted) {
|
||||
return false;
|
||||
} else {
|
||||
this.submitted = true;
|
||||
}
|
||||
});
|
||||
|
||||
$('label input[type=text]').click(function(e) {
|
||||
var check = $('#' + $(this).parents('label').attr('for'));
|
||||
check.prop('checked', true);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
$('#frontPage-recent,#frontPage-page,#frontPage-file').change(function() {
|
||||
var t = $(this);
|
||||
if (t.prop('checked')) {
|
||||
if ('frontPage-recent' == t.attr('id')) {
|
||||
$('.front-archive').addClass('hidden');
|
||||
} else {
|
||||
$('.front-archive').insertAfter(t.parent()).removeClass('hidden');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
480
views/admin/origin/series.html
Normal file
@@ -0,0 +1,480 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="no-js">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>管理分类 - Hello World - Powered by Typecho</title>
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/normalize.css?v=14.10.10">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/grid.css?v=14.10.10">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/style.css?v=14.10.10">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://localhost/admin/js/html5shiv.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/respond.js?v=14.10.10"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--[if lt IE 9]>
|
||||
<div class="message error browsehappy" role="dialog">当前网页 <strong>不支持</strong> 你正在使用的浏览器. 为了正常的访问, 请 <a href="http://browsehappy.com/">升级你的浏览器</a>.</div>
|
||||
<![endif]-->
|
||||
<div class="typecho-head-nav clearfix" role="navigation">
|
||||
<nav id="typecho-nav-list">
|
||||
<ul class="root focus">
|
||||
<li class="parent"><a target="_self" href="/admin/home">控制台</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li target="_self" class="focus"><a href="/admin/home">概要</a></li>
|
||||
<li><a target="_self" href="/admin/profile">个人设置</a></li>
|
||||
<li><a target="_self" href="/admin/plugin">插件</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/theme">外观</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/write">撰写</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li class="last"><a target="_self" href="/admin/write">撰写文章</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/articles">管理</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/articles">文章</a></li>
|
||||
<li><a target="_self" href="/admin/categories">分类</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/tags">标签</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/setting">设置</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/setting">基本</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/reading">阅读</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="operate">
|
||||
<a target="_self" title="最后登录: 7小时前" href="/admin/profile" class="author">admin</a><a target="_self" class="exit" href="/admin/login?logout=true">登出</a><a href="/">网站</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
<div class="body container">
|
||||
<div class="typecho-page-title">
|
||||
<h2>管理分类<a href="http://localhost/admin/category.php">新增</a></h2>
|
||||
</div>
|
||||
<div class="row typecho-page-main manage-metas">
|
||||
<div class="col-mb-12" role="main">
|
||||
<form method="post" name="manage_categories" class="operate-form">
|
||||
<div class="typecho-list-operate clearfix">
|
||||
<div class="operate">
|
||||
<label><i class="sr-only">全选</i>
|
||||
<input type="checkbox" class="typecho-table-select-all" />
|
||||
</label>
|
||||
<div class="btn-group btn-drop">
|
||||
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only">操作</i>选中项 <i class="i-caret-down"></i></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a lang="此分类下的所有内容将被删除, 你确认要删除这些分类吗?" href="http://localhost/index.php/action/metas-category-edit?do=delete&_=7fe4662ec063c94e7072ce37ddbe3abc">删除</a></li>
|
||||
<li><a lang="刷新分类可能需要等待较长时间, 你确认要刷新这些分类吗?" href="http://localhost/index.php/action/metas-category-edit?do=refresh&_=7fe4662ec063c94e7072ce37ddbe3abc">刷新</a></li>
|
||||
<li class="multiline">
|
||||
<button type="button" class="btn merge btn-s" rel="http://localhost/index.php/action/metas-category-edit?do=merge&_=7fe4662ec063c94e7072ce37ddbe3abc">合并到</button>
|
||||
<select name="merge">
|
||||
<option value="1">默认分类</option>
|
||||
<option value="2">232</option>
|
||||
<option value="3">234</option>
|
||||
<option value="4">2</option>
|
||||
<option value="5">4</option>
|
||||
<option value="6">3</option>
|
||||
<option value="7">5</option>
|
||||
<option value="8">6</option>
|
||||
<option value="9">7</option>
|
||||
<option value="10">8</option>
|
||||
<option value="11">9</option>
|
||||
</select>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search" role="search">
|
||||
</div>
|
||||
</div>
|
||||
<div class="typecho-table-wrap">
|
||||
<table class="typecho-list-table">
|
||||
<colgroup>
|
||||
<col width="20" />
|
||||
<col width="30%" />
|
||||
<col width="15%" />
|
||||
<col width="25%" />
|
||||
<col width="" />
|
||||
<col width="10%" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr class="nodrag">
|
||||
<th> </th>
|
||||
<th>名称</th>
|
||||
<th>子分类</th>
|
||||
<th>缩略名</th>
|
||||
<th> </th>
|
||||
<th>文章数</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr id="mid-category-1">
|
||||
<td>
|
||||
<input type="checkbox" value="1" name="mid[]" />
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/category.php?mid=1">默认分类</a>
|
||||
<a href="http://localhost/index.php/category/default/" title="浏览 默认分类"><i class="i-exlink"></i></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="http://localhost/admin/category.php?parent=1">新增</a>
|
||||
</td>
|
||||
<td>default</td>
|
||||
<td>
|
||||
默认 </td>
|
||||
<td><a class="balloon-button left size-10" href="http://localhost/admin/manage-posts.php?category=1">2</a></td>
|
||||
</tr>
|
||||
<tr id="mid-category-2">
|
||||
<td>
|
||||
<input type="checkbox" value="2" name="mid[]" />
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/category.php?mid=2">232</a>
|
||||
<a href="http://localhost/index.php/category/2342/" title="浏览 232"><i class="i-exlink"></i></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="http://localhost/admin/category.php?parent=2">新增</a>
|
||||
</td>
|
||||
<td>2342</td>
|
||||
<td>
|
||||
<a class="hidden-by-mouse" href="http://localhost/index.php/action/metas-category-edit?do=default&mid=2&_=7fe4662ec063c94e7072ce37ddbe3abc" title="设为默认">默认</a>
|
||||
</td>
|
||||
<td><a class="balloon-button left size-1" href="http://localhost/admin/manage-posts.php?category=2">0</a></td>
|
||||
</tr>
|
||||
<tr id="mid-category-3">
|
||||
<td>
|
||||
<input type="checkbox" value="3" name="mid[]" />
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/category.php?mid=3">234</a>
|
||||
<a href="http://localhost/index.php/category/23423/" title="浏览 234"><i class="i-exlink"></i></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="http://localhost/admin/category.php?parent=3">新增</a>
|
||||
</td>
|
||||
<td>23423</td>
|
||||
<td>
|
||||
<a class="hidden-by-mouse" href="http://localhost/index.php/action/metas-category-edit?do=default&mid=3&_=7fe4662ec063c94e7072ce37ddbe3abc" title="设为默认">默认</a>
|
||||
</td>
|
||||
<td><a class="balloon-button left size-1" href="http://localhost/admin/manage-posts.php?category=3">0</a></td>
|
||||
</tr>
|
||||
<tr id="mid-category-4">
|
||||
<td>
|
||||
<input type="checkbox" value="4" name="mid[]" />
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/category.php?mid=4">2</a>
|
||||
<a href="http://localhost/index.php/category/2/" title="浏览 2"><i class="i-exlink"></i></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="http://localhost/admin/category.php?parent=4">新增</a>
|
||||
</td>
|
||||
<td>2</td>
|
||||
<td>
|
||||
<a class="hidden-by-mouse" href="http://localhost/index.php/action/metas-category-edit?do=default&mid=4&_=7fe4662ec063c94e7072ce37ddbe3abc" title="设为默认">默认</a>
|
||||
</td>
|
||||
<td><a class="balloon-button left size-1" href="http://localhost/admin/manage-posts.php?category=4">0</a></td>
|
||||
</tr>
|
||||
<tr id="mid-category-5">
|
||||
<td>
|
||||
<input type="checkbox" value="5" name="mid[]" />
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/category.php?mid=5">4</a>
|
||||
<a href="http://localhost/index.php/category/4/" title="浏览 4"><i class="i-exlink"></i></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="http://localhost/admin/category.php?parent=5">新增</a>
|
||||
</td>
|
||||
<td>4</td>
|
||||
<td>
|
||||
<a class="hidden-by-mouse" href="http://localhost/index.php/action/metas-category-edit?do=default&mid=5&_=7fe4662ec063c94e7072ce37ddbe3abc" title="设为默认">默认</a>
|
||||
</td>
|
||||
<td><a class="balloon-button left size-1" href="http://localhost/admin/manage-posts.php?category=5">0</a></td>
|
||||
</tr>
|
||||
<tr id="mid-category-6">
|
||||
<td>
|
||||
<input type="checkbox" value="6" name="mid[]" />
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/category.php?mid=6">3</a>
|
||||
<a href="http://localhost/index.php/category/3/" title="浏览 3"><i class="i-exlink"></i></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="http://localhost/admin/category.php?parent=6">新增</a>
|
||||
</td>
|
||||
<td>3</td>
|
||||
<td>
|
||||
<a class="hidden-by-mouse" href="http://localhost/index.php/action/metas-category-edit?do=default&mid=6&_=7fe4662ec063c94e7072ce37ddbe3abc" title="设为默认">默认</a>
|
||||
</td>
|
||||
<td><a class="balloon-button left size-1" href="http://localhost/admin/manage-posts.php?category=6">0</a></td>
|
||||
</tr>
|
||||
<tr id="mid-category-7">
|
||||
<td>
|
||||
<input type="checkbox" value="7" name="mid[]" />
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/category.php?mid=7">5</a>
|
||||
<a href="http://localhost/index.php/category/5/" title="浏览 5"><i class="i-exlink"></i></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="http://localhost/admin/category.php?parent=7">新增</a>
|
||||
</td>
|
||||
<td>5</td>
|
||||
<td>
|
||||
<a class="hidden-by-mouse" href="http://localhost/index.php/action/metas-category-edit?do=default&mid=7&_=7fe4662ec063c94e7072ce37ddbe3abc" title="设为默认">默认</a>
|
||||
</td>
|
||||
<td><a class="balloon-button left size-1" href="http://localhost/admin/manage-posts.php?category=7">0</a></td>
|
||||
</tr>
|
||||
<tr id="mid-category-8">
|
||||
<td>
|
||||
<input type="checkbox" value="8" name="mid[]" />
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/category.php?mid=8">6</a>
|
||||
<a href="http://localhost/index.php/category/6/" title="浏览 6"><i class="i-exlink"></i></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="http://localhost/admin/category.php?parent=8">新增</a>
|
||||
</td>
|
||||
<td>6</td>
|
||||
<td>
|
||||
<a class="hidden-by-mouse" href="http://localhost/index.php/action/metas-category-edit?do=default&mid=8&_=7fe4662ec063c94e7072ce37ddbe3abc" title="设为默认">默认</a>
|
||||
</td>
|
||||
<td><a class="balloon-button left size-1" href="http://localhost/admin/manage-posts.php?category=8">0</a></td>
|
||||
</tr>
|
||||
<tr id="mid-category-9">
|
||||
<td>
|
||||
<input type="checkbox" value="9" name="mid[]" />
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/category.php?mid=9">7</a>
|
||||
<a href="http://localhost/index.php/category/7/" title="浏览 7"><i class="i-exlink"></i></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="http://localhost/admin/category.php?parent=9">新增</a>
|
||||
</td>
|
||||
<td>7</td>
|
||||
<td>
|
||||
<a class="hidden-by-mouse" href="http://localhost/index.php/action/metas-category-edit?do=default&mid=9&_=7fe4662ec063c94e7072ce37ddbe3abc" title="设为默认">默认</a>
|
||||
</td>
|
||||
<td><a class="balloon-button left size-1" href="http://localhost/admin/manage-posts.php?category=9">0</a></td>
|
||||
</tr>
|
||||
<tr id="mid-category-10">
|
||||
<td>
|
||||
<input type="checkbox" value="10" name="mid[]" />
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/category.php?mid=10">8</a>
|
||||
<a href="http://localhost/index.php/category/8/" title="浏览 8"><i class="i-exlink"></i></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="http://localhost/admin/category.php?parent=10">新增</a>
|
||||
</td>
|
||||
<td>8</td>
|
||||
<td>
|
||||
<a class="hidden-by-mouse" href="http://localhost/index.php/action/metas-category-edit?do=default&mid=10&_=7fe4662ec063c94e7072ce37ddbe3abc" title="设为默认">默认</a>
|
||||
</td>
|
||||
<td><a class="balloon-button left size-1" href="http://localhost/admin/manage-posts.php?category=10">0</a></td>
|
||||
</tr>
|
||||
<tr id="mid-category-11">
|
||||
<td>
|
||||
<input type="checkbox" value="11" name="mid[]" />
|
||||
</td>
|
||||
<td><a href="http://localhost/admin/category.php?mid=11">9</a>
|
||||
<a href="http://localhost/index.php/category/9/" title="浏览 9"><i class="i-exlink"></i></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="http://localhost/admin/category.php?parent=11">新增</a>
|
||||
</td>
|
||||
<td>9</td>
|
||||
<td>
|
||||
<a class="hidden-by-mouse" href="http://localhost/index.php/action/metas-category-edit?do=default&mid=11&_=7fe4662ec063c94e7072ce37ddbe3abc" title="设为默认">默认</a>
|
||||
</td>
|
||||
<td><a class="balloon-button left size-1" href="http://localhost/admin/manage-posts.php?category=11">0</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="typecho-foot" role="contentinfo">
|
||||
<div class="copyright">
|
||||
<a href="http://typecho.org" class="i-logo-s">Typecho</a>
|
||||
<p>由 <a href="http://typecho.org">Typecho</a> 强力驱动, 版本 1.0 (14.10.10)</p>
|
||||
</div>
|
||||
<nav class="resource">
|
||||
<a href="http://docs.typecho.org">帮助文档</a> •
|
||||
<a href="http://forum.typecho.org">支持论坛</a> •
|
||||
<a href="https://github.com/typecho/typecho/issues">报告错误</a> •
|
||||
<a href="http://extends.typecho.org">资源下载</a>
|
||||
</nav>
|
||||
</div>
|
||||
<script src="http://localhost/admin/js/jquery.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/jquery-ui.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/typecho.js?v=14.10.10"></script>
|
||||
<script>
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
// 处理消息机制
|
||||
(function() {
|
||||
var prefix = '86a9106ae65537651a8e456835b316ab',
|
||||
cookies = {
|
||||
notice: $.cookie(prefix + '__typecho_notice'),
|
||||
noticeType: $.cookie(prefix + '__typecho_notice_type'),
|
||||
highlight: $.cookie(prefix + '__typecho_notice_highlight')
|
||||
},
|
||||
path = '/';
|
||||
|
||||
if (!!cookies.notice && 'success|notice|error'.indexOf(cookies.noticeType) >= 0) {
|
||||
var head = $('.typecho-head-nav'),
|
||||
p = $('<div class="message popup ' + cookies.noticeType + '">' + '<ul><li>' + $.parseJSON(cookies.notice).join('</li><li>') + '</li></ul></div>'),
|
||||
offset = 0;
|
||||
|
||||
if (head.length > 0) {
|
||||
p.insertAfter(head);
|
||||
offset = head.outerHeight();
|
||||
} else {
|
||||
p.prependTo(document.body);
|
||||
}
|
||||
|
||||
function checkScroll() {
|
||||
if ($(window).scrollTop() >= offset) {
|
||||
p.css({
|
||||
'position': 'fixed',
|
||||
'top': 0
|
||||
});
|
||||
} else {
|
||||
p.css({
|
||||
'position': 'absolute',
|
||||
'top': offset
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(window).scroll(function() {
|
||||
checkScroll();
|
||||
});
|
||||
|
||||
checkScroll();
|
||||
|
||||
p.slideDown(function() {
|
||||
var t = $(this),
|
||||
color = '#C6D880';
|
||||
|
||||
if (t.hasClass('error')) {
|
||||
color = '#FBC2C4';
|
||||
} else if (t.hasClass('notice')) {
|
||||
color = '#FFD324';
|
||||
}
|
||||
|
||||
t.effect('highlight', {
|
||||
color: color
|
||||
})
|
||||
.delay(5000).slideUp(function() {
|
||||
$(this).remove();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$.cookie(prefix + '__typecho_notice', null, {
|
||||
path: path
|
||||
});
|
||||
$.cookie(prefix + '__typecho_notice_type', null, {
|
||||
path: path
|
||||
});
|
||||
}
|
||||
|
||||
if (cookies.highlight) {
|
||||
$('#' + cookies.highlight).effect('highlight', 1000);
|
||||
$.cookie(prefix + '__typecho_notice_highlight', null, {
|
||||
path: path
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
// 导航菜单 tab 聚焦时展开下拉菜单
|
||||
(function() {
|
||||
$('#typecho-nav-list').find('.parent a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
$(this).parents('.root').find('.child').show();
|
||||
});
|
||||
$('.operate').find('a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
if ($('.typecho-login').length == 0) {
|
||||
$('a').each(function() {
|
||||
var t = $(this),
|
||||
href = t.attr('href');
|
||||
|
||||
if ((href && href[0] == '#') || /^http\:\/\/localhost\/admin\/.*$/.exec(href) || /^http\:\/\/localhost\/index\.php\/action\/[_a-zA-Z0-9\/]+.*$/.exec(href)) {
|
||||
return;
|
||||
}
|
||||
|
||||
t.attr('target', '_blank');
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
var table = $('.typecho-list-table').tableDnD({
|
||||
onDrop: function() {
|
||||
var ids = [];
|
||||
|
||||
$('input[type=checkbox]', table).each(function() {
|
||||
ids.push($(this).val());
|
||||
});
|
||||
|
||||
$.post('http://localhost/index.php/action/metas-category-edit?do=sort&_=7fe4662ec063c94e7072ce37ddbe3abc',
|
||||
$.param({
|
||||
mid: ids
|
||||
}));
|
||||
|
||||
$('tr', table).each(function(i) {
|
||||
if (i % 2) {
|
||||
$(this).addClass('even');
|
||||
} else {
|
||||
$(this).removeClass('even');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
table.tableSelectable({
|
||||
checkEl: 'input[type=checkbox]',
|
||||
rowEl: 'tr',
|
||||
selectAllEl: '.typecho-table-select-all',
|
||||
actionEl: '.dropdown-menu a'
|
||||
});
|
||||
|
||||
$('.btn-drop').dropdownMenu({
|
||||
btnEl: '.dropdown-toggle',
|
||||
menuEl: '.dropdown-menu'
|
||||
});
|
||||
|
||||
$('.dropdown-menu button.merge').click(function() {
|
||||
var btn = $(this);
|
||||
btn.parents('form').attr('action', btn.attr('rel')).submit();
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
374
views/admin/origin/setting.html
Normal file
@@ -0,0 +1,374 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="no-js">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>基本设置 - Hello World - Powered by Typecho</title>
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/normalize.css?v=14.10.10">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/grid.css?v=14.10.10">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/style.css?v=14.10.10">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://localhost/admin/js/html5shiv.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/respond.js?v=14.10.10"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--[if lt IE 9]>
|
||||
<div class="message error browsehappy" role="dialog">当前网页 <strong>不支持</strong> 你正在使用的浏览器. 为了正常的访问, 请 <a href="http://browsehappy.com/">升级你的浏览器</a>.</div>
|
||||
<![endif]-->
|
||||
<div class="typecho-head-nav clearfix" role="navigation">
|
||||
<nav id="typecho-nav-list">
|
||||
<ul class="root focus">
|
||||
<li class="parent"><a target="_self" href="/admin/home">控制台</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li target="_self" class="focus"><a href="/admin/home">概要</a></li>
|
||||
<li><a target="_self" href="/admin/profile">个人设置</a></li>
|
||||
<li><a target="_self" href="/admin/plugin">插件</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/theme">外观</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/write">撰写</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li class="last"><a target="_self" href="/admin/write">撰写文章</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/articles">管理</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/articles">文章</a></li>
|
||||
<li><a target="_self" href="/admin/categories">分类</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/tags">标签</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/setting">设置</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/setting">基本</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/reading">阅读</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="operate">
|
||||
<a target="_self" title="最后登录: 7小时前" href="/admin/profile" class="author">admin</a><a target="_self" class="exit" href="/admin/login?logout=true">登出</a><a href="/">网站</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
<div class="body container">
|
||||
<div class="typecho-page-title">
|
||||
<h2>基本设置</h2>
|
||||
</div>
|
||||
<div class="row typecho-page-main" role="form">
|
||||
<div class="col-mb-12 col-tb-8 col-tb-offset-2">
|
||||
<form action="http://localhost/index.php/action/options-general?_=f90abdb2b52a2818286e72429dfcc97b" method="post" enctype="application/x-www-form-urlencoded">
|
||||
<ul class="typecho-option" id="typecho-option-item-title-0">
|
||||
<li>
|
||||
<label class="typecho-label" for="title-0-1">
|
||||
站点名称</label>
|
||||
<input id="title-0-1" name="title" type="text" class="w-100" value="Hello World" />
|
||||
<p class="description">
|
||||
站点的名称将显示在网页的标题处.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-siteUrl-1">
|
||||
<li>
|
||||
<label class="typecho-label" for="siteUrl-0-2">
|
||||
站点地址</label>
|
||||
<input id="siteUrl-0-2" name="siteUrl" type="text" class="w-100 mono" value="http://localhost" />
|
||||
<p class="description">
|
||||
站点地址主要用于生成内容的永久链接.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-description-2">
|
||||
<li>
|
||||
<label class="typecho-label" for="description-0-3">
|
||||
站点描述</label>
|
||||
<input id="description-0-3" name="description" type="text" class="text" value="Just So So ..." />
|
||||
<p class="description">
|
||||
站点描述将显示在网页代码的头部.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-keywords-3">
|
||||
<li>
|
||||
<label class="typecho-label" for="keywords-0-4">
|
||||
关键词</label>
|
||||
<input id="keywords-0-4" name="keywords" type="text" class="text" value="typecho,php,blog" />
|
||||
<p class="description">
|
||||
请以半角逗号 "," 分割多个关键字.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-allowRegister-4">
|
||||
<li>
|
||||
<label class="typecho-label">
|
||||
是否允许注册</label>
|
||||
<span>
|
||||
<input name="allowRegister" type="radio" value="0" id="allowRegister-0" checked="true" />
|
||||
<label for="allowRegister-0">
|
||||
不允许</label>
|
||||
</span>
|
||||
<span>
|
||||
<input name="allowRegister" type="radio" value="1" id="allowRegister-1" />
|
||||
<label for="allowRegister-1">
|
||||
允许</label>
|
||||
</span>
|
||||
<p class="description">
|
||||
允许访问者注册到你的网站, 默认的注册用户不享有任何写入权限.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-timezone-5">
|
||||
<li>
|
||||
<label class="typecho-label" for="timezone-0-6">
|
||||
时区</label>
|
||||
<select name="timezone" id="timezone-0-6">
|
||||
<option value="0">
|
||||
格林威治(子午线)标准时间 (GMT)</option>
|
||||
<option value="3600">
|
||||
中欧标准时间 阿姆斯特丹,荷兰,法国 (GMT +1)</option>
|
||||
<option value="7200">
|
||||
东欧标准时间 布加勒斯特,塞浦路斯,希腊 (GMT +2)</option>
|
||||
<option value="10800">
|
||||
莫斯科时间 伊拉克,埃塞俄比亚,马达加斯加 (GMT +3)</option>
|
||||
<option value="14400">
|
||||
第比利斯时间 阿曼,毛里塔尼亚,留尼汪岛 (GMT +4)</option>
|
||||
<option value="18000">
|
||||
新德里时间 巴基斯坦,马尔代夫 (GMT +5)</option>
|
||||
<option value="21600">
|
||||
科伦坡时间 孟加拉 (GMT +6)</option>
|
||||
<option value="25200">
|
||||
曼谷雅加达 柬埔寨,苏门答腊,老挝 (GMT +7)</option>
|
||||
<option value="28800" selected="true">
|
||||
北京时间 香港,新加坡,越南 (GMT +8)</option>
|
||||
<option value="32400">
|
||||
东京平壤时间 西伊里安,摩鹿加群岛 (GMT +9)</option>
|
||||
<option value="36000">
|
||||
悉尼关岛时间 塔斯马尼亚岛,新几内亚 (GMT +10)</option>
|
||||
<option value="39600">
|
||||
所罗门群岛 库页岛 (GMT +11)</option>
|
||||
<option value="43200">
|
||||
惠灵顿时间 新西兰,斐济群岛 (GMT +12)</option>
|
||||
<option value="-3600">
|
||||
佛德尔群岛 亚速尔群岛,葡属几内亚 (GMT -1)</option>
|
||||
<option value="-7200">
|
||||
大西洋中部时间 格陵兰 (GMT -2)</option>
|
||||
<option value="-10800">
|
||||
布宜诺斯艾利斯 乌拉圭,法属圭亚那 (GMT -3)</option>
|
||||
<option value="-14400">
|
||||
智利巴西 委内瑞拉,玻利维亚 (GMT -4)</option>
|
||||
<option value="-18000">
|
||||
纽约渥太华 古巴,哥伦比亚,牙买加 (GMT -5)</option>
|
||||
<option value="-21600">
|
||||
墨西哥城时间 洪都拉斯,危地马拉,哥斯达黎加 (GMT -6)</option>
|
||||
<option value="-25200">
|
||||
美国丹佛时间 (GMT -7)</option>
|
||||
<option value="-28800">
|
||||
美国旧金山时间 (GMT -8)</option>
|
||||
<option value="-32400">
|
||||
阿拉斯加时间 (GMT -9)</option>
|
||||
<option value="-36000">
|
||||
夏威夷群岛 (GMT -10)</option>
|
||||
<option value="-39600">
|
||||
东萨摩亚群岛 (GMT -11)</option>
|
||||
<option value="-43200">
|
||||
艾尼威托克岛 (GMT -12)</option>
|
||||
</select>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-attachmentTypes-6">
|
||||
<li>
|
||||
<label class="typecho-label">
|
||||
允许上传的文件类型</label>
|
||||
<span class="multiline">
|
||||
<input name="attachmentTypes[]" type="checkbox" value="@image@" id="attachmentTypes-image" checked="true" />
|
||||
<label for="attachmentTypes-image">
|
||||
图片文件 <code>(gif jpg jpeg png tiff bmp)</code></label>
|
||||
</span>
|
||||
<span class="multiline">
|
||||
<input name="attachmentTypes[]" type="checkbox" value="@media@" id="attachmentTypes-media" />
|
||||
<label for="attachmentTypes-media">
|
||||
多媒体文件 <code>(mp3 wmv wma rmvb rm avi flv)</code></label>
|
||||
</span>
|
||||
<span class="multiline">
|
||||
<input name="attachmentTypes[]" type="checkbox" value="@doc@" id="attachmentTypes-doc" />
|
||||
<label for="attachmentTypes-doc">
|
||||
常用档案文件 <code>(txt doc docx xls xlsx ppt pptx zip rar pdf)</code></label>
|
||||
</span>
|
||||
<span class="multiline">
|
||||
<input name="attachmentTypes[]" type="checkbox" value="@other@" id="attachmentTypes-other" />
|
||||
<label for="attachmentTypes-other">
|
||||
其他格式 <input type="text" class="w-50 text-s mono" name="attachmentTypesOther" value="" /></label>
|
||||
</span>
|
||||
<p class="description">
|
||||
用逗号 "," 将后缀名隔开, 例如: <code>cpp, h, mak</code></p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option typecho-option-submit" id="typecho-option-item-submit-7">
|
||||
<li>
|
||||
<button type="submit" class="btn primary">
|
||||
保存设置</button>
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="typecho-foot" role="contentinfo">
|
||||
<div class="copyright">
|
||||
<a href="http://typecho.org" class="i-logo-s">Typecho</a>
|
||||
<p>由 <a href="http://typecho.org">Typecho</a> 强力驱动, 版本 1.0 (14.10.10)</p>
|
||||
</div>
|
||||
<nav class="resource">
|
||||
<a href="http://docs.typecho.org">帮助文档</a> •
|
||||
<a href="http://forum.typecho.org">支持论坛</a> •
|
||||
<a href="https://github.com/typecho/typecho/issues">报告错误</a> •
|
||||
<a href="http://extends.typecho.org">资源下载</a>
|
||||
</nav>
|
||||
</div>
|
||||
<script src="http://localhost/admin/js/jquery.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/jquery-ui.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/typecho.js?v=14.10.10"></script>
|
||||
<script>
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
// 处理消息机制
|
||||
(function() {
|
||||
var prefix = '86a9106ae65537651a8e456835b316ab',
|
||||
cookies = {
|
||||
notice: $.cookie(prefix + '__typecho_notice'),
|
||||
noticeType: $.cookie(prefix + '__typecho_notice_type'),
|
||||
highlight: $.cookie(prefix + '__typecho_notice_highlight')
|
||||
},
|
||||
path = '/';
|
||||
|
||||
if (!!cookies.notice && 'success|notice|error'.indexOf(cookies.noticeType) >= 0) {
|
||||
var head = $('.typecho-head-nav'),
|
||||
p = $('<div class="message popup ' + cookies.noticeType + '">' + '<ul><li>' + $.parseJSON(cookies.notice).join('</li><li>') + '</li></ul></div>'),
|
||||
offset = 0;
|
||||
|
||||
if (head.length > 0) {
|
||||
p.insertAfter(head);
|
||||
offset = head.outerHeight();
|
||||
} else {
|
||||
p.prependTo(document.body);
|
||||
}
|
||||
|
||||
function checkScroll() {
|
||||
if ($(window).scrollTop() >= offset) {
|
||||
p.css({
|
||||
'position': 'fixed',
|
||||
'top': 0
|
||||
});
|
||||
} else {
|
||||
p.css({
|
||||
'position': 'absolute',
|
||||
'top': offset
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(window).scroll(function() {
|
||||
checkScroll();
|
||||
});
|
||||
|
||||
checkScroll();
|
||||
|
||||
p.slideDown(function() {
|
||||
var t = $(this),
|
||||
color = '#C6D880';
|
||||
|
||||
if (t.hasClass('error')) {
|
||||
color = '#FBC2C4';
|
||||
} else if (t.hasClass('notice')) {
|
||||
color = '#FFD324';
|
||||
}
|
||||
|
||||
t.effect('highlight', {
|
||||
color: color
|
||||
})
|
||||
.delay(5000).slideUp(function() {
|
||||
$(this).remove();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$.cookie(prefix + '__typecho_notice', null, {
|
||||
path: path
|
||||
});
|
||||
$.cookie(prefix + '__typecho_notice_type', null, {
|
||||
path: path
|
||||
});
|
||||
}
|
||||
|
||||
if (cookies.highlight) {
|
||||
$('#' + cookies.highlight).effect('highlight', 1000);
|
||||
$.cookie(prefix + '__typecho_notice_highlight', null, {
|
||||
path: path
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
// 导航菜单 tab 聚焦时展开下拉菜单
|
||||
(function() {
|
||||
$('#typecho-nav-list').find('.parent a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
$(this).parents('.root').find('.child').show();
|
||||
});
|
||||
$('.operate').find('a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
if ($('.typecho-login').length == 0) {
|
||||
$('a').each(function() {
|
||||
var t = $(this),
|
||||
href = t.attr('href');
|
||||
|
||||
if ((href && href[0] == '#') || /^http\:\/\/localhost\/admin\/.*$/.exec(href) || /^http\:\/\/localhost\/index\.php\/action\/[_a-zA-Z0-9\/]+.*$/.exec(href)) {
|
||||
return;
|
||||
}
|
||||
|
||||
t.attr('target', '_blank');
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
var error = $('.typecho-option .error:first');
|
||||
|
||||
if (error.length > 0) {
|
||||
$('html,body').scrollTop(error.parents('.typecho-option').offset().top);
|
||||
}
|
||||
|
||||
$('form').submit(function() {
|
||||
if (this.submitted) {
|
||||
return false;
|
||||
} else {
|
||||
this.submitted = true;
|
||||
}
|
||||
});
|
||||
|
||||
$('label input[type=text]').click(function(e) {
|
||||
var check = $('#' + $(this).parents('label').attr('for'));
|
||||
check.prop('checked', true);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
321
views/admin/origin/tags.html
Normal file
@@ -0,0 +1,321 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="no-js">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>管理标签 - Hello World - Powered by Typecho</title>
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/normalize.css?v=14.10.10">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/grid.css?v=14.10.10">
|
||||
<link rel="stylesheet" href="http://localhost/admin/css/style.css?v=14.10.10">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://localhost/admin/js/html5shiv.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/respond.js?v=14.10.10"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--[if lt IE 9]>
|
||||
<div class="message error browsehappy" role="dialog">当前网页 <strong>不支持</strong> 你正在使用的浏览器. 为了正常的访问, 请 <a href="http://browsehappy.com/">升级你的浏览器</a>.</div>
|
||||
<![endif]-->
|
||||
<div class="typecho-head-nav clearfix" role="navigation">
|
||||
<nav id="typecho-nav-list">
|
||||
<ul class="root focus">
|
||||
<li class="parent"><a target="_self" href="/admin/home">控制台</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li target="_self" class="focus"><a href="/admin/home">概要</a></li>
|
||||
<li><a target="_self" href="/admin/profile">个人设置</a></li>
|
||||
<li><a target="_self" href="/admin/plugin">插件</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/theme">外观</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/write">撰写</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li class="last"><a target="_self" href="/admin/write">撰写文章</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/articles">管理</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/articles">文章</a></li>
|
||||
<li><a target="_self" href="/admin/categories">分类</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/tags">标签</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul class="root">
|
||||
<li class="parent"><a target="_self" href="/admin/setting">设置</a></dt>
|
||||
</li>
|
||||
<ul class="child">
|
||||
<li><a target="_self" href="/admin/setting">基本</a></li>
|
||||
<li class="last"><a target="_self" href="/admin/reading">阅读</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="operate">
|
||||
<a target="_self" title="最后登录: 7小时前" href="/admin/profile" class="author">admin</a><a target="_self" class="exit" href="/admin/login?logout=true">登出</a><a href="/">网站</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
<div class="body container">
|
||||
<div class="typecho-page-title">
|
||||
<h2>管理标签</h2>
|
||||
</div>
|
||||
<div class="row typecho-page-main manage-metas">
|
||||
<div class="col-mb-12 col-tb-8" role="main">
|
||||
<form method="post" name="manage_tags" class="operate-form">
|
||||
<div class="typecho-list-operate clearfix">
|
||||
<div class="operate">
|
||||
<label><i class="sr-only">全选</i>
|
||||
<input type="checkbox" class="typecho-table-select-all" />
|
||||
</label>
|
||||
<div class="btn-group btn-drop">
|
||||
<button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only">操作</i>选中项 <i class="i-caret-down"></i></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a lang="你确认要删除这些标签吗?" href="http://localhost/index.php/action/metas-tag-edit?do=delete&_=2e6004cd103d97bddfccf02fddd0ecbe">删除</a></li>
|
||||
<li><a lang="刷新标签可能需要等待较长时间, 你确认要刷新这些标签吗?" href="http://localhost/index.php/action/metas-tag-edit?do=refresh&_=2e6004cd103d97bddfccf02fddd0ecbe">刷新</a></li>
|
||||
<li class="multiline">
|
||||
<button type="button" class="btn btn-s merge" rel="http://localhost/index.php/action/metas-tag-edit?do=merge&_=2e6004cd103d97bddfccf02fddd0ecbe">合并到</button>
|
||||
<input type="text" name="merge" class="text-s" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="typecho-list-notable tag-list clearfix">
|
||||
<li class="size-5" id="tag-18">
|
||||
<input type="checkbox" value="18" name="mid[]" />
|
||||
<span rel="http://localhost/admin/manage-tags.php?mid=18">sad</span>
|
||||
<a class="tag-edit-link" href="http://localhost/admin/manage-tags.php?mid=18"><i class="i-edit"></i></a>
|
||||
</li>
|
||||
<li class="size-5" id="tag-17">
|
||||
<input type="checkbox" value="17" name="mid[]" />
|
||||
<span rel="http://localhost/admin/manage-tags.php?mid=17">sdasdf</span>
|
||||
<a class="tag-edit-link" href="http://localhost/admin/manage-tags.php?mid=17"><i class="i-edit"></i></a>
|
||||
</li>
|
||||
<li class="size-5" id="tag-16">
|
||||
<input type="checkbox" value="16" name="mid[]" />
|
||||
<span rel="http://localhost/admin/manage-tags.php?mid=16">sdfsad</span>
|
||||
<a class="tag-edit-link" href="http://localhost/admin/manage-tags.php?mid=16"><i class="i-edit"></i></a>
|
||||
</li>
|
||||
<li class="size-5" id="tag-15">
|
||||
<input type="checkbox" value="15" name="mid[]" />
|
||||
<span rel="http://localhost/admin/manage-tags.php?mid=15">asdfasd</span>
|
||||
<a class="tag-edit-link" href="http://localhost/admin/manage-tags.php?mid=15"><i class="i-edit"></i></a>
|
||||
</li>
|
||||
<li class="size-5" id="tag-14">
|
||||
<input type="checkbox" value="14" name="mid[]" />
|
||||
<span rel="http://localhost/admin/manage-tags.php?mid=14">sdfsdfasdf</span>
|
||||
<a class="tag-edit-link" href="http://localhost/admin/manage-tags.php?mid=14"><i class="i-edit"></i></a>
|
||||
</li>
|
||||
<li class="size-5" id="tag-13">
|
||||
<input type="checkbox" value="13" name="mid[]" />
|
||||
<span rel="http://localhost/admin/manage-tags.php?mid=13">sdfsdfasd</span>
|
||||
<a class="tag-edit-link" href="http://localhost/admin/manage-tags.php?mid=13"><i class="i-edit"></i></a>
|
||||
</li>
|
||||
<li class="size-5" id="tag-12">
|
||||
<input type="checkbox" value="12" name="mid[]" />
|
||||
<span rel="http://localhost/admin/manage-tags.php?mid=12">sadfasdf</span>
|
||||
<a class="tag-edit-link" href="http://localhost/admin/manage-tags.php?mid=12"><i class="i-edit"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
<input type="hidden" name="do" value="delete" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-mb-12 col-tb-4" role="form">
|
||||
<form action="http://localhost/index.php/action/metas-tag-edit?_=2e6004cd103d97bddfccf02fddd0ecbe" method="post" enctype="application/x-www-form-urlencoded">
|
||||
<ul class="typecho-option" id="typecho-option-item-name-0">
|
||||
<li>
|
||||
<label class="typecho-label" for="name-0-1">
|
||||
标签名称 *</label>
|
||||
<input id="name-0-1" name="name" type="text" class="text" />
|
||||
<p class="description">
|
||||
这是标签在站点中显示的名称.可以使用中文,如 "地球".</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-slug-1">
|
||||
<li>
|
||||
<label class="typecho-label" for="slug-0-2">
|
||||
标签缩略名</label>
|
||||
<input id="slug-0-2" name="slug" type="text" class="text" />
|
||||
<p class="description">
|
||||
标签缩略名用于创建友好的链接形式, 如果留空则默认使用标签名称.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-do-2" style="display:none">
|
||||
<li>
|
||||
<input name="do" type="hidden" value="insert" />
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option" id="typecho-option-item-mid-3" style="display:none">
|
||||
<li>
|
||||
<input name="mid" type="hidden" />
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="typecho-option typecho-option-submit" id="typecho-option-item--4">
|
||||
<li>
|
||||
<button type="submit" class="btn primary">
|
||||
增加标签</button>
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="typecho-foot" role="contentinfo">
|
||||
<div class="copyright">
|
||||
<a href="http://typecho.org" class="i-logo-s">Typecho</a>
|
||||
<p>由 <a href="http://typecho.org">Typecho</a> 强力驱动, 版本 1.0 (14.10.10)</p>
|
||||
</div>
|
||||
<nav class="resource">
|
||||
<a href="http://docs.typecho.org">帮助文档</a> •
|
||||
<a href="http://forum.typecho.org">支持论坛</a> •
|
||||
<a href="https://github.com/typecho/typecho/issues">报告错误</a> •
|
||||
<a href="http://extends.typecho.org">资源下载</a>
|
||||
</nav>
|
||||
</div>
|
||||
<script src="http://localhost/admin/js/jquery.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/jquery-ui.js?v=14.10.10"></script>
|
||||
<script src="http://localhost/admin/js/typecho.js?v=14.10.10"></script>
|
||||
<script>
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
// 处理消息机制
|
||||
(function() {
|
||||
var prefix = '86a9106ae65537651a8e456835b316ab',
|
||||
cookies = {
|
||||
notice: $.cookie(prefix + '__typecho_notice'),
|
||||
noticeType: $.cookie(prefix + '__typecho_notice_type'),
|
||||
highlight: $.cookie(prefix + '__typecho_notice_highlight')
|
||||
},
|
||||
path = '/';
|
||||
|
||||
if (!!cookies.notice && 'success|notice|error'.indexOf(cookies.noticeType) >= 0) {
|
||||
var head = $('.typecho-head-nav'),
|
||||
p = $('<div class="message popup ' + cookies.noticeType + '">' + '<ul><li>' + $.parseJSON(cookies.notice).join('</li><li>') + '</li></ul></div>'),
|
||||
offset = 0;
|
||||
|
||||
if (head.length > 0) {
|
||||
p.insertAfter(head);
|
||||
offset = head.outerHeight();
|
||||
} else {
|
||||
p.prependTo(document.body);
|
||||
}
|
||||
|
||||
function checkScroll() {
|
||||
if ($(window).scrollTop() >= offset) {
|
||||
p.css({
|
||||
'position': 'fixed',
|
||||
'top': 0
|
||||
});
|
||||
} else {
|
||||
p.css({
|
||||
'position': 'absolute',
|
||||
'top': offset
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(window).scroll(function() {
|
||||
checkScroll();
|
||||
});
|
||||
|
||||
checkScroll();
|
||||
|
||||
p.slideDown(function() {
|
||||
var t = $(this),
|
||||
color = '#C6D880';
|
||||
|
||||
if (t.hasClass('error')) {
|
||||
color = '#FBC2C4';
|
||||
} else if (t.hasClass('notice')) {
|
||||
color = '#FFD324';
|
||||
}
|
||||
|
||||
t.effect('highlight', {
|
||||
color: color
|
||||
})
|
||||
.delay(5000).slideUp(function() {
|
||||
$(this).remove();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$.cookie(prefix + '__typecho_notice', null, {
|
||||
path: path
|
||||
});
|
||||
$.cookie(prefix + '__typecho_notice_type', null, {
|
||||
path: path
|
||||
});
|
||||
}
|
||||
|
||||
if (cookies.highlight) {
|
||||
$('#' + cookies.highlight).effect('highlight', 1000);
|
||||
$.cookie(prefix + '__typecho_notice_highlight', null, {
|
||||
path: path
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
// 导航菜单 tab 聚焦时展开下拉菜单
|
||||
(function() {
|
||||
$('#typecho-nav-list').find('.parent a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
$(this).parents('.root').find('.child').show();
|
||||
});
|
||||
$('.operate').find('a').focus(function() {
|
||||
$('#typecho-nav-list').find('.child').hide();
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
if ($('.typecho-login').length == 0) {
|
||||
$('a').each(function() {
|
||||
var t = $(this),
|
||||
href = t.attr('href');
|
||||
|
||||
if ((href && href[0] == '#') || /^http\:\/\/localhost\/admin\/.*$/.exec(href) || /^http\:\/\/localhost\/index\.php\/action\/[_a-zA-Z0-9\/]+.*$/.exec(href)) {
|
||||
return;
|
||||
}
|
||||
|
||||
t.attr('target', '_blank');
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
|
||||
$('.typecho-list-notable').tableSelectable({
|
||||
checkEl: 'input[type=checkbox]',
|
||||
rowEl: 'li',
|
||||
selectAllEl: '.typecho-table-select-all',
|
||||
actionEl: '.dropdown-menu a'
|
||||
});
|
||||
|
||||
$('.btn-drop').dropdownMenu({
|
||||
btnEl: '.dropdown-toggle',
|
||||
menuEl: '.dropdown-menu'
|
||||
});
|
||||
|
||||
$('.dropdown-menu button.merge').click(function() {
|
||||
var btn = $(this);
|
||||
btn.parents('form').attr('action', btn.attr('rel')).submit();
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||