mirror of
https://github.com/mindoc-org/mindoc.git
synced 2025-06-28 15:45:35 +08:00
优化体验
This commit is contained in:
parent
a562499b83
commit
bb9ba8c4b6
@ -40,6 +40,12 @@ const (
|
|||||||
BookObserver = 3
|
BookObserver = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
//本地账户校验
|
||||||
|
AuthMethodLocal = "local"
|
||||||
|
//LDAP用户校验
|
||||||
|
AuthMethodLDAP = "ldap"
|
||||||
|
)
|
||||||
var (
|
var (
|
||||||
VERSION string
|
VERSION string
|
||||||
BUILD_TIME string
|
BUILD_TIME string
|
||||||
|
@ -172,7 +172,9 @@ func (c *AccountController) FindPassword() {
|
|||||||
if member.Status != 0 {
|
if member.Status != 0 {
|
||||||
c.JsonResult(6007,"账号已被禁用")
|
c.JsonResult(6007,"账号已被禁用")
|
||||||
}
|
}
|
||||||
|
if member.AuthMethod == conf.AuthMethodLDAP {
|
||||||
|
c.JsonResult(6011,"当前用户不支持找回密码")
|
||||||
|
}
|
||||||
|
|
||||||
count,err := models.NewMemberToken().FindSendCount(email,time.Now().Add(-1*time.Hour),time.Now())
|
count,err := models.NewMemberToken().FindSendCount(email,time.Now().Add(-1*time.Hour),time.Now())
|
||||||
|
|
||||||
|
@ -508,7 +508,7 @@ func (c *BookController) Release() {
|
|||||||
|
|
||||||
book_id := 0
|
book_id := 0
|
||||||
|
|
||||||
if c.Member.Role == conf.MemberSuperRole {
|
if c.Member.IsAdministrator() {
|
||||||
book,err := models.NewBook().FindByFieldFirst("identify",identify)
|
book,err := models.NewBook().FindByFieldFirst("identify",identify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
@ -550,8 +550,15 @@ func (c *BookController) SaveSort() {
|
|||||||
c.Abort("404")
|
c.Abort("404")
|
||||||
}
|
}
|
||||||
|
|
||||||
bookResult,err := models.NewBookResult().FindByIdentify(identify,c.Member.MemberId)
|
book_id := 0
|
||||||
|
if c.Member.IsAdministrator() {
|
||||||
|
book,err := models.NewBook().FindByFieldFirst("identify",identify)
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
}
|
||||||
|
book_id = book.BookId
|
||||||
|
}else{
|
||||||
|
bookResult,err := models.NewBookResult().FindByIdentify(identify,c.Member.MemberId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beego.Error("DocumentController.Edit => ",err)
|
beego.Error("DocumentController.Edit => ",err)
|
||||||
|
|
||||||
@ -560,11 +567,15 @@ func (c *BookController) SaveSort() {
|
|||||||
if bookResult.RoleId == conf.BookObserver {
|
if bookResult.RoleId == conf.BookObserver {
|
||||||
c.JsonResult(6002,"项目不存在或权限不足")
|
c.JsonResult(6002,"项目不存在或权限不足")
|
||||||
}
|
}
|
||||||
|
book_id = bookResult.BookId
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
content := c.Ctx.Input.RequestBody
|
content := c.Ctx.Input.RequestBody
|
||||||
|
|
||||||
var docs []map[string]interface{}
|
var docs []map[string]interface{}
|
||||||
|
|
||||||
err = json.Unmarshal(content,&docs)
|
err := json.Unmarshal(content,&docs)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beego.Error(err)
|
beego.Error(err)
|
||||||
@ -578,7 +589,7 @@ func (c *BookController) SaveSort() {
|
|||||||
beego.Error(err)
|
beego.Error(err)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if doc.BookId != bookResult.BookId {
|
if doc.BookId != book_id {
|
||||||
logs.Info("%s","权限错误")
|
logs.Info("%s","权限错误")
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -593,7 +604,7 @@ func (c *BookController) SaveSort() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if parent_id > 0 {
|
if parent_id > 0 {
|
||||||
if parent,err := models.NewDocument().Find(int(parent_id)); err != nil || parent.BookId != bookResult.BookId {
|
if parent,err := models.NewDocument().Find(int(parent_id)); err != nil || parent.BookId != book_id {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ func isReadable(identify, token string, c *DocumentController) *models.BookResul
|
|||||||
beego.Error(err)
|
beego.Error(err)
|
||||||
c.Abort("500")
|
c.Abort("500")
|
||||||
}
|
}
|
||||||
if c.Member != nil && c.Member.Role == conf.MemberSuperRole {
|
if c.Member != nil && c.Member.IsAdministrator(){
|
||||||
bookResult := book.ToBookResult()
|
bookResult := book.ToBookResult()
|
||||||
return bookResult
|
return bookResult
|
||||||
}
|
}
|
||||||
@ -208,7 +208,7 @@ func (c *DocumentController) Edit() {
|
|||||||
bookResult := models.NewBookResult()
|
bookResult := models.NewBookResult()
|
||||||
var err error
|
var err error
|
||||||
//如果是超级管理者,则不判断权限
|
//如果是超级管理者,则不判断权限
|
||||||
if c.Member.Role == conf.MemberSuperRole {
|
if c.Member.IsAdministrator(){
|
||||||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JsonResult(6002, "项目不存在或权限不足")
|
c.JsonResult(6002, "项目不存在或权限不足")
|
||||||
@ -289,7 +289,7 @@ func (c *DocumentController) Create() {
|
|||||||
}
|
}
|
||||||
book_id := 0
|
book_id := 0
|
||||||
//如果是超级管理员则不判断权限
|
//如果是超级管理员则不判断权限
|
||||||
if c.Member.Role == conf.MemberSuperRole {
|
if c.Member.IsAdministrator(){
|
||||||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beego.Error(err)
|
beego.Error(err)
|
||||||
@ -370,7 +370,7 @@ func (c *DocumentController) Upload() {
|
|||||||
}
|
}
|
||||||
book_id := 0
|
book_id := 0
|
||||||
//如果是超级管理员,则不判断权限
|
//如果是超级管理员,则不判断权限
|
||||||
if c.Member.Role == conf.MemberSuperRole {
|
if c.Member.IsAdministrator(){
|
||||||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -584,7 +584,7 @@ func (c *DocumentController) Delete() {
|
|||||||
|
|
||||||
book_id := 0
|
book_id := 0
|
||||||
//如果是超级管理员则忽略权限判断
|
//如果是超级管理员则忽略权限判断
|
||||||
if c.Member.Role == conf.MemberSuperRole {
|
if c.Member.IsAdministrator(){
|
||||||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beego.Error("FindByIdentify => ", err)
|
beego.Error("FindByIdentify => ", err)
|
||||||
@ -637,7 +637,7 @@ func (c *DocumentController) Content() {
|
|||||||
}
|
}
|
||||||
book_id := 0
|
book_id := 0
|
||||||
//如果是超级管理员,则忽略权限
|
//如果是超级管理员,则忽略权限
|
||||||
if c.Member.Role == conf.MemberSuperRole {
|
if c.Member.IsAdministrator() {
|
||||||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JsonResult(6002, "项目不存在或权限不足")
|
c.JsonResult(6002, "项目不存在或权限不足")
|
||||||
@ -740,7 +740,7 @@ func (c *DocumentController) Export() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
bookResult := models.NewBookResult()
|
bookResult := models.NewBookResult()
|
||||||
if c.Member != nil && c.Member.Role == conf.MemberSuperRole {
|
if c.Member != nil && c.Member.IsAdministrator(){
|
||||||
book, err := models.NewBook().FindByIdentify(identify)
|
book, err := models.NewBook().FindByIdentify(identify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beego.Error(err)
|
beego.Error(err)
|
||||||
@ -899,7 +899,7 @@ func (c *DocumentController) History() {
|
|||||||
|
|
||||||
book_id := 0
|
book_id := 0
|
||||||
//如果是超级管理员则忽略权限判断
|
//如果是超级管理员则忽略权限判断
|
||||||
if c.Member.Role == conf.MemberSuperRole {
|
if c.Member.IsAdministrator(){
|
||||||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beego.Error("FindByIdentify => ", err)
|
beego.Error("FindByIdentify => ", err)
|
||||||
@ -970,7 +970,7 @@ func (c *DocumentController) DeleteHistory() {
|
|||||||
}
|
}
|
||||||
book_id := 0
|
book_id := 0
|
||||||
//如果是超级管理员则忽略权限判断
|
//如果是超级管理员则忽略权限判断
|
||||||
if c.Member.Role == conf.MemberSuperRole {
|
if c.Member.IsAdministrator(){
|
||||||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beego.Error("FindByIdentify => ", err)
|
beego.Error("FindByIdentify => ", err)
|
||||||
@ -1022,7 +1022,7 @@ func (c *DocumentController) RestoreHistory() {
|
|||||||
}
|
}
|
||||||
book_id := 0
|
book_id := 0
|
||||||
//如果是超级管理员则忽略权限判断
|
//如果是超级管理员则忽略权限判断
|
||||||
if c.Member.Role == conf.MemberSuperRole {
|
if c.Member.IsAdministrator(){
|
||||||
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
book, err := models.NewBook().FindByFieldFirst("identify", identify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beego.Error("FindByIdentify => ", err)
|
beego.Error("FindByIdentify => ", err)
|
||||||
|
@ -28,9 +28,6 @@ func (c *ManagerController) Prepare (){
|
|||||||
|
|
||||||
func (c *ManagerController) Index() {
|
func (c *ManagerController) Index() {
|
||||||
c.TplName = "manager/index.tpl"
|
c.TplName = "manager/index.tpl"
|
||||||
if !c.Member.IsAdministrator() {
|
|
||||||
c.Abort("403")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Data["Model"] = models.NewDashboard().Query()
|
c.Data["Model"] = models.NewDashboard().Query()
|
||||||
}
|
}
|
||||||
@ -40,10 +37,6 @@ func (c *ManagerController) Users() {
|
|||||||
c.Prepare()
|
c.Prepare()
|
||||||
c.TplName = "manager/users.tpl"
|
c.TplName = "manager/users.tpl"
|
||||||
|
|
||||||
if !c.Member.IsAdministrator() {
|
|
||||||
c.Abort("403")
|
|
||||||
}
|
|
||||||
|
|
||||||
pageIndex, _ := c.GetInt("page", 0)
|
pageIndex, _ := c.GetInt("page", 0)
|
||||||
|
|
||||||
members, totalCount, err := models.NewMember().FindToPager(pageIndex, 15)
|
members, totalCount, err := models.NewMember().FindToPager(pageIndex, 15)
|
||||||
@ -73,9 +66,6 @@ func (c *ManagerController) Users() {
|
|||||||
// 添加用户.
|
// 添加用户.
|
||||||
func (c *ManagerController) CreateMember() {
|
func (c *ManagerController) CreateMember() {
|
||||||
c.Prepare()
|
c.Prepare()
|
||||||
if !c.Member.IsAdministrator() {
|
|
||||||
c.Abort("403")
|
|
||||||
}
|
|
||||||
|
|
||||||
account := strings.TrimSpace(c.GetString("account"))
|
account := strings.TrimSpace(c.GetString("account"))
|
||||||
password1 := strings.TrimSpace(c.GetString("password1"))
|
password1 := strings.TrimSpace(c.GetString("password1"))
|
||||||
@ -131,10 +121,6 @@ func (c *ManagerController) CreateMember() {
|
|||||||
func (c *ManagerController) UpdateMemberStatus() {
|
func (c *ManagerController) UpdateMemberStatus() {
|
||||||
c.Prepare()
|
c.Prepare()
|
||||||
|
|
||||||
if !c.Member.IsAdministrator() {
|
|
||||||
c.Abort("403")
|
|
||||||
}
|
|
||||||
|
|
||||||
member_id, _ := c.GetInt("member_id", 0)
|
member_id, _ := c.GetInt("member_id", 0)
|
||||||
status, _ := c.GetInt("status", 0)
|
status, _ := c.GetInt("status", 0)
|
||||||
|
|
||||||
@ -168,10 +154,6 @@ func (c *ManagerController) UpdateMemberStatus() {
|
|||||||
func (c *ManagerController) ChangeMemberRole() {
|
func (c *ManagerController) ChangeMemberRole() {
|
||||||
c.Prepare()
|
c.Prepare()
|
||||||
|
|
||||||
if !c.Member.IsAdministrator() {
|
|
||||||
c.Abort("403")
|
|
||||||
}
|
|
||||||
|
|
||||||
member_id, _ := c.GetInt("member_id", 0)
|
member_id, _ := c.GetInt("member_id", 0)
|
||||||
role, _ := c.GetInt("role", 0)
|
role, _ := c.GetInt("role", 0)
|
||||||
if member_id <= 0 {
|
if member_id <= 0 {
|
||||||
@ -204,9 +186,7 @@ func (c *ManagerController) ChangeMemberRole() {
|
|||||||
func (c *ManagerController) EditMember() {
|
func (c *ManagerController) EditMember() {
|
||||||
c.Prepare()
|
c.Prepare()
|
||||||
c.TplName = "manager/edit_users.tpl"
|
c.TplName = "manager/edit_users.tpl"
|
||||||
if !c.Member.IsAdministrator() {
|
|
||||||
c.Abort("403")
|
|
||||||
}
|
|
||||||
member_id,_ := c.GetInt(":id",0)
|
member_id,_ := c.GetInt(":id",0)
|
||||||
|
|
||||||
if member_id <= 0 {
|
if member_id <= 0 {
|
||||||
@ -231,7 +211,7 @@ func (c *ManagerController) EditMember() {
|
|||||||
if password1 != "" && password2 != password1 {
|
if password1 != "" && password2 != password1 {
|
||||||
c.JsonResult(6001,"确认密码不正确")
|
c.JsonResult(6001,"确认密码不正确")
|
||||||
}
|
}
|
||||||
if password1 != "" {
|
if password1 != "" && member.AuthMethod != conf.AuthMethodLDAP{
|
||||||
member.Password = password1
|
member.Password = password1
|
||||||
}
|
}
|
||||||
if err := member.Valid(password1 == "");err != nil {
|
if err := member.Valid(password1 == "");err != nil {
|
||||||
@ -280,10 +260,10 @@ func (c *ManagerController) Books() {
|
|||||||
|
|
||||||
//编辑项目
|
//编辑项目
|
||||||
func (c *ManagerController) EditBook() {
|
func (c *ManagerController) EditBook() {
|
||||||
|
c.Prepare()
|
||||||
|
|
||||||
c.TplName = "manager/edit_book.tpl"
|
c.TplName = "manager/edit_book.tpl"
|
||||||
if !c.Member.IsAdministrator() {
|
|
||||||
c.Abort("403")
|
|
||||||
}
|
|
||||||
identify := c.GetString(":key")
|
identify := c.GetString(":key")
|
||||||
|
|
||||||
if identify == "" {
|
if identify == "" {
|
||||||
@ -334,9 +314,6 @@ func (c *ManagerController) EditBook() {
|
|||||||
// 删除项目.
|
// 删除项目.
|
||||||
func (c *ManagerController) DeleteBook() {
|
func (c *ManagerController) DeleteBook() {
|
||||||
c.Prepare()
|
c.Prepare()
|
||||||
if !c.Member.IsAdministrator() {
|
|
||||||
c.Abort("403")
|
|
||||||
}
|
|
||||||
|
|
||||||
book_id, _ := c.GetInt("book_id", 0)
|
book_id, _ := c.GetInt("book_id", 0)
|
||||||
|
|
||||||
@ -359,7 +336,7 @@ func (c *ManagerController) DeleteBook() {
|
|||||||
|
|
||||||
// CreateToken 创建访问来令牌.
|
// CreateToken 创建访问来令牌.
|
||||||
func (c *ManagerController) CreateToken() {
|
func (c *ManagerController) CreateToken() {
|
||||||
|
c.Prepare()
|
||||||
action := c.GetString("action")
|
action := c.GetString("action")
|
||||||
|
|
||||||
identify := c.GetString("identify")
|
identify := c.GetString("identify")
|
||||||
@ -396,10 +373,6 @@ func (c *ManagerController) Setting() {
|
|||||||
c.Prepare()
|
c.Prepare()
|
||||||
c.TplName = "manager/setting.tpl"
|
c.TplName = "manager/setting.tpl"
|
||||||
|
|
||||||
if !c.Member.IsAdministrator() {
|
|
||||||
c.Abort("403")
|
|
||||||
}
|
|
||||||
|
|
||||||
options, err := models.NewOption().All()
|
options, err := models.NewOption().All()
|
||||||
|
|
||||||
if c.Ctx.Input.IsPost() {
|
if c.Ctx.Input.IsPost() {
|
||||||
@ -480,9 +453,7 @@ func (c *ManagerController) Comments() {
|
|||||||
//DeleteComment 标记评论为已删除
|
//DeleteComment 标记评论为已删除
|
||||||
func (c *ManagerController) DeleteComment() {
|
func (c *ManagerController) DeleteComment() {
|
||||||
c.Prepare()
|
c.Prepare()
|
||||||
if !c.Member.IsAdministrator() {
|
|
||||||
c.Abort("403")
|
|
||||||
}
|
|
||||||
comment_id, _ := c.GetInt("comment_id", 0)
|
comment_id, _ := c.GetInt("comment_id", 0)
|
||||||
|
|
||||||
if comment_id <= 0 {
|
if comment_id <= 0 {
|
||||||
@ -505,7 +476,7 @@ func (c *ManagerController) DeleteComment() {
|
|||||||
|
|
||||||
//设置项目私有状态.
|
//设置项目私有状态.
|
||||||
func (c *ManagerController) PrivatelyOwned() {
|
func (c *ManagerController) PrivatelyOwned() {
|
||||||
|
c.Prepare()
|
||||||
status := c.GetString("status")
|
status := c.GetString("status")
|
||||||
identify := c.GetString("identify")
|
identify := c.GetString("identify")
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/lifei6671/godoc/models"
|
"github.com/lifei6671/godoc/models"
|
||||||
"github.com/lifei6671/godoc/utils"
|
"github.com/lifei6671/godoc/utils"
|
||||||
"github.com/lifei6671/godoc/graphics"
|
"github.com/lifei6671/godoc/graphics"
|
||||||
|
"github.com/lifei6671/godoc/conf"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SettingController struct {
|
type SettingController struct {
|
||||||
@ -45,6 +46,9 @@ func (c *SettingController) Password() {
|
|||||||
c.TplName = "setting/password.tpl"
|
c.TplName = "setting/password.tpl"
|
||||||
|
|
||||||
if c.Ctx.Input.IsPost() {
|
if c.Ctx.Input.IsPost() {
|
||||||
|
if c.Member.AuthMethod == conf.AuthMethodLDAP {
|
||||||
|
c.JsonResult(6009,"当前用户不支持修改密码")
|
||||||
|
}
|
||||||
password1 := c.GetString("password1")
|
password1 := c.GetString("password1")
|
||||||
password2 := c.GetString("password2")
|
password2 := c.GetString("password2")
|
||||||
password3 := c.GetString("password3")
|
password3 := c.GetString("password3")
|
||||||
|
@ -14,6 +14,7 @@ var (
|
|||||||
ErrMemberEmailFormatError = errors.New("邮箱格式不正确")
|
ErrMemberEmailFormatError = errors.New("邮箱格式不正确")
|
||||||
ErrMemberPasswordFormatError = errors.New("密码必须在6-50个字符之间")
|
ErrMemberPasswordFormatError = errors.New("密码必须在6-50个字符之间")
|
||||||
ErrMemberAccountFormatError = errors.New("账号只能由英文字母数字组成,且在3-50个字符")
|
ErrMemberAccountFormatError = errors.New("账号只能由英文字母数字组成,且在3-50个字符")
|
||||||
|
ErrMemberRoleError = errors.New("用户权限不正确")
|
||||||
// ErrorMemberPasswordError 密码错误.
|
// ErrorMemberPasswordError 密码错误.
|
||||||
ErrorMemberPasswordError = errors.New("用户密码错误")
|
ErrorMemberPasswordError = errors.New("用户密码错误")
|
||||||
//ErrorMemberAuthMethodInvalid 不支持此认证方式
|
//ErrorMemberAuthMethodInvalid 不支持此认证方式
|
||||||
|
@ -277,6 +277,12 @@ func (m *Member) Valid(is_hash_password bool) error {
|
|||||||
if strings.Count(m.Description,"") > 500 {
|
if strings.Count(m.Description,"") > 500 {
|
||||||
return ErrMemberDescriptionTooLong
|
return ErrMemberDescriptionTooLong
|
||||||
}
|
}
|
||||||
|
if m.Role != conf.MemberGeneralRole && m.Role != conf.MemberSuperRole && m.Role != conf.MemberAdminRole {
|
||||||
|
return ErrMemberRoleError
|
||||||
|
}
|
||||||
|
if m.Status != 0 && m.Status != 1 {
|
||||||
|
m.Status = 0
|
||||||
|
}
|
||||||
//邮箱格式校验
|
//邮箱格式校验
|
||||||
if ok,err := regexp.MatchString(conf.RegexpEmail,m.Email); !ok || err != nil || m.Email == "" {
|
if ok,err := regexp.MatchString(conf.RegexpEmail,m.Email); !ok || err != nil || m.Email == "" {
|
||||||
return ErrMemberEmailFormatError
|
return ErrMemberEmailFormatError
|
||||||
@ -296,6 +302,7 @@ func (m *Member) Valid(is_hash_password bool) error {
|
|||||||
return ErrMemberEmailExist
|
return ErrMemberEmailExist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.MemberId > 0{
|
if m.MemberId > 0{
|
||||||
//校验用户是否存在
|
//校验用户是否存在
|
||||||
if _,err := NewMember().Find(m.MemberId);err != nil {
|
if _,err := NewMember().Find(m.MemberId);err != nil {
|
||||||
@ -312,6 +319,7 @@ func (m *Member) Valid(is_hash_password bool) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,6 +492,7 @@ textarea{
|
|||||||
background-color: #f9f9f9;
|
background-color: #f9f9f9;
|
||||||
border: 1px solid #fff;
|
border: 1px solid #fff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
color: #333;
|
||||||
}
|
}
|
||||||
.manager .dashboard-item:hover{
|
.manager .dashboard-item:hover{
|
||||||
background-color: #563D7C;
|
background-color: #563D7C;
|
||||||
|
@ -215,6 +215,7 @@ body{
|
|||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
/***************附件管理的样式*******************/
|
||||||
.attach-drop-panel{
|
.attach-drop-panel{
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -286,20 +287,80 @@ body{
|
|||||||
.attach-list .attach-item .close:hover {
|
.attach-list .attach-item .close:hover {
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
/***********选择模板时的样式**************/
|
||||||
|
.template-list .container{
|
||||||
|
margin-top: 60px;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
padding: 0 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.template-list .container .section{
|
||||||
|
position: relative;
|
||||||
|
margin: 0 15px;
|
||||||
|
padding-top: 60px;
|
||||||
|
float: left;
|
||||||
|
width: 150px;
|
||||||
|
height: 236px;
|
||||||
|
background: #fdfefe;
|
||||||
|
border: 1px solid #ddddd9;
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
.template-list .container .section>h3 a{
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 200;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #5d606b
|
||||||
|
}
|
||||||
|
.template-list .container .section>a {
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: -28px;
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
margin-left: -28px
|
||||||
|
}
|
||||||
|
.template-list .container .section>a .fa {
|
||||||
|
display: inline-block;
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
background-color: #fbfefe;
|
||||||
|
border: 1px solid #ddddd9;
|
||||||
|
border-radius: 50%;
|
||||||
|
line-height: 54px;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #ddddd9
|
||||||
|
}
|
||||||
|
.template-list .container .section:hover {
|
||||||
|
border-color: #44b035
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-list .container .section:hover>a {
|
||||||
|
background-color: #44b035;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 66px;
|
||||||
|
height: 66px;
|
||||||
|
margin-left: -33px;
|
||||||
|
top: -33px
|
||||||
|
}
|
||||||
|
.template-list .container .section:hover>a .fa {
|
||||||
|
background-color: #78c56d;
|
||||||
|
color: #fff;
|
||||||
|
border: 0;
|
||||||
|
line-height: 54px
|
||||||
|
}
|
||||||
|
.template-list .container .section ul {
|
||||||
|
margin-top: 35px;
|
||||||
|
padding-left: 0;
|
||||||
|
list-style: none
|
||||||
|
}
|
||||||
|
.template-list .container .section ul li {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 0 10px;
|
||||||
|
line-height: 1.2;
|
||||||
|
color: #8e8d8d
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
33
static/css/markdown.preview.css
Normal file
33
static/css/markdown.preview.css
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*************表格样式****************/
|
||||||
|
|
||||||
|
.editormd-preview-container table thead tr{
|
||||||
|
background-color: #0088CC;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
.editormd-preview-container table tr:nth-child(2n) {
|
||||||
|
background-color: #f8f8f8
|
||||||
|
}
|
||||||
|
.editormd-preview-container-body blockquote,.editormd-preview-container blockquote p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999
|
||||||
|
}
|
||||||
|
/***********代码样式*****************/
|
||||||
|
.markdown-body .highlight pre, .markdown-body pre{
|
||||||
|
padding: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
border-radius:0;
|
||||||
|
line-height: 1.4em;
|
||||||
|
}
|
||||||
|
.editormd-preview-container pre.prettyprint, .editormd-html-preview pre.prettyprint{
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.editormd-preview-container ol.linenums, .editormd-html-preview ol.linenums{
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.editormd-preview-container ol.linenums>li:first-child,.editormd-html-preview ol.linenums>li:first-child{
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
.editormd-preview-container ol.linenums>li:last-child ,.editormd-html-preview ol.linenums>li:last-child{
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
27
static/js/jquery.highlight.js
Normal file
27
static/js/jquery.highlight.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
jQuery.fn.highlight = function(pat) {
|
||||||
|
function innerHighlight(node, pat) {
|
||||||
|
var skip = 0;
|
||||||
|
if (node.nodeType === 3) {
|
||||||
|
var pos = node.data.toUpperCase().indexOf(pat);
|
||||||
|
if (pos >= 0) {
|
||||||
|
var spannode = document.createElement('em');
|
||||||
|
spannode.className = 'search-highlight';
|
||||||
|
var middlebit = node.splitText(pos);
|
||||||
|
var endbit = middlebit.splitText(pat.length);
|
||||||
|
var middleclone = middlebit.cloneNode(true);
|
||||||
|
spannode.appendChild(middleclone);
|
||||||
|
middlebit.parentNode.replaceChild(spannode, middlebit);
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node.nodeType === 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
|
||||||
|
for (var i = 0; i < node.childNodes.length; ++i) {
|
||||||
|
i += innerHighlight(node.childNodes[i], pat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return skip;
|
||||||
|
}
|
||||||
|
return this.each(function() {
|
||||||
|
innerHighlight(this, pat.toUpperCase());
|
||||||
|
});
|
||||||
|
};
|
207
static/js/kancloud.js
Normal file
207
static/js/kancloud.js
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
/***
|
||||||
|
* 加载文档到阅读区
|
||||||
|
* @param $url
|
||||||
|
* @param $id
|
||||||
|
* @param $callback
|
||||||
|
*/
|
||||||
|
function loadDocument($url,$id,$callback) {
|
||||||
|
$.ajax({
|
||||||
|
url : $url,
|
||||||
|
type : "GET",
|
||||||
|
beforeSend :function (xhr) {
|
||||||
|
var body = events.data('body_' + $id);
|
||||||
|
var title = events.data('title_' + $id);
|
||||||
|
var doc_title = events.data('doc_title_' + $id);
|
||||||
|
|
||||||
|
if(body && title && doc_title){
|
||||||
|
|
||||||
|
if (typeof $callback === "function") {
|
||||||
|
body = $callback(body);
|
||||||
|
}
|
||||||
|
$("#page-content").html(body);
|
||||||
|
$("title").text(title);
|
||||||
|
$("#article-title").text(doc_title);
|
||||||
|
|
||||||
|
events.trigger('article.open',{ $url : $url, $init : false , $id : $id });
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
NProgress.start();
|
||||||
|
},
|
||||||
|
success : function (res) {
|
||||||
|
if(res.errcode === 0){
|
||||||
|
var body = res.data.body;
|
||||||
|
var doc_title = res.data.doc_title;
|
||||||
|
var title = res.data.title;
|
||||||
|
|
||||||
|
$body = body;
|
||||||
|
if (typeof $callback === "function" ){
|
||||||
|
$body = $callback(body);
|
||||||
|
}
|
||||||
|
$("#page-content").html($body);
|
||||||
|
$("title").text(title);
|
||||||
|
$("#article-title").text(doc_title);
|
||||||
|
|
||||||
|
events.data('body_' + $id,body);
|
||||||
|
events.data('title_' + $id,title);
|
||||||
|
events.data('doc_title_' + $id,doc_title);
|
||||||
|
|
||||||
|
events.trigger('article.open',{ $url : $url, $init : true, $id : $id });
|
||||||
|
|
||||||
|
}else{
|
||||||
|
layer.msg("加载失败");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
complete : function () {
|
||||||
|
NProgress.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function initHighlighting() {
|
||||||
|
$('pre code').each(function (i, block) {
|
||||||
|
hljs.highlightBlock(block);
|
||||||
|
});
|
||||||
|
|
||||||
|
hljs.initLineNumbersOnLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
var events = $("body");
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$(".view-backtop").on("click", function () {
|
||||||
|
$('.manual-right').animate({ scrollTop: '0px' }, 200);
|
||||||
|
});
|
||||||
|
$(".manual-right").scroll(function () {
|
||||||
|
var top = $(".manual-right").scrollTop();
|
||||||
|
if(top > 100){
|
||||||
|
$(".view-backtop").addClass("active");
|
||||||
|
}else{
|
||||||
|
$(".view-backtop").removeClass("active");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
window.isFullScreen = false;
|
||||||
|
|
||||||
|
initHighlighting();
|
||||||
|
|
||||||
|
window.jsTree = $("#sidebar").jstree({
|
||||||
|
'plugins':["wholerow","types"],
|
||||||
|
"types": {
|
||||||
|
"default" : {
|
||||||
|
"icon" : false // 删除默认图标
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'core' : {
|
||||||
|
'check_callback' : true,
|
||||||
|
"multiple" : false ,
|
||||||
|
'animation' : 0
|
||||||
|
}
|
||||||
|
}).on('select_node.jstree',function (node,selected,event) {
|
||||||
|
$(".m-manual").removeClass('manual-mobile-show-left');
|
||||||
|
var url = selected.node.a_attr.href;
|
||||||
|
|
||||||
|
if(url === window.location.href){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
loadDocument(url,selected.node.id);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#slidebar").on("click",function () {
|
||||||
|
$(".m-manual").addClass('manual-mobile-show-left');
|
||||||
|
});
|
||||||
|
$(".manual-mask").on("click",function () {
|
||||||
|
$(".m-manual").removeClass('manual-mobile-show-left');
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭侧边栏
|
||||||
|
*/
|
||||||
|
$(".manual-fullscreen-switch").on("click",function () {
|
||||||
|
isFullScreen = !isFullScreen;
|
||||||
|
if (isFullScreen) {
|
||||||
|
$(".m-manual").addClass('manual-fullscreen-active');
|
||||||
|
} else {
|
||||||
|
$(".m-manual").removeClass('manual-fullscreen-active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//处理打开事件
|
||||||
|
events.on('article.open', function (event, $param) {
|
||||||
|
|
||||||
|
if ('pushState' in history) {
|
||||||
|
if ($param.$init === false) {
|
||||||
|
window.history.replaceState($param , $param.$id , $param.$url);
|
||||||
|
} else {
|
||||||
|
window.history.pushState($param, $param.$id , $param.$url);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
window.location.hash = $param.$url;
|
||||||
|
}
|
||||||
|
initHighlighting();
|
||||||
|
$(".manual-right").scrollTop(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".navg-item[data-mode]").on("click",function () {
|
||||||
|
var mode = $(this).data('mode');
|
||||||
|
$(this).siblings().removeClass('active').end().addClass('active');
|
||||||
|
$(".m-manual").removeClass("manual-mode-view manual-mode-collect manual-mode-search").addClass("manual-mode-" + mode);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目内搜索
|
||||||
|
*/
|
||||||
|
$("#searchForm").ajaxForm({
|
||||||
|
beforeSubmit : function () {
|
||||||
|
var keyword = $.trim($("#searchForm").find("input[name='keyword']").val());
|
||||||
|
if(keyword === ""){
|
||||||
|
$(".search-empty").show();
|
||||||
|
$("#searchList").html("");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$("#btnSearch").attr("disabled","disabled").find("i").removeClass("fa-search").addClass("loading");
|
||||||
|
window.keyword = keyword;
|
||||||
|
},
|
||||||
|
success :function (res) {
|
||||||
|
var html = "";
|
||||||
|
if(res.errcode === 0){
|
||||||
|
for(var i in res.data){
|
||||||
|
var item = res.data[i];
|
||||||
|
html += '<li><a href="javascript:;" title="'+ item.doc_name +'" data-id="'+ item.doc_id+'"> '+ item.doc_name +' </a></li>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(html !== ""){
|
||||||
|
$(".search-empty").hide();
|
||||||
|
}else{
|
||||||
|
$(".search-empty").show();
|
||||||
|
}
|
||||||
|
$("#searchList").html(html);
|
||||||
|
},
|
||||||
|
complete : function () {
|
||||||
|
$("#btnSearch").removeAttr("disabled").find("i").removeClass("loading").addClass("fa-search");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.onpopstate = function (e) {
|
||||||
|
|
||||||
|
var $param = e.state;
|
||||||
|
console.log($param);
|
||||||
|
if($param.hasOwnProperty("$url")) {
|
||||||
|
window.jsTree.jstree().deselect_all();
|
||||||
|
|
||||||
|
window.jsTree.jstree().select_node({ id : $param.$id });
|
||||||
|
$param.$init = false;
|
||||||
|
//events.trigger('article.open', $param );
|
||||||
|
}else{
|
||||||
|
console.log($param);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// var $node = window.jsTree.jstree().get_selected();
|
||||||
|
//
|
||||||
|
// if(typeof $node === "object") {
|
||||||
|
// $node = window.jsTree.jstree().get_node({ id : $node[0] });
|
||||||
|
// events.trigger('article.open',{ $url : $node.a_attr.href , $init : false, $id : $node.a_attr.id });
|
||||||
|
// }
|
||||||
|
});
|
@ -64,7 +64,8 @@ $(function () {
|
|||||||
window.documentHistory();
|
window.documentHistory();
|
||||||
}else if(name === "save"){
|
}else if(name === "save"){
|
||||||
saveDocument(false);
|
saveDocument(false);
|
||||||
|
}else if(name === "template"){
|
||||||
|
$("#documentTemplateModal").modal("show");
|
||||||
}else if(name === "sidebar"){
|
}else if(name === "sidebar"){
|
||||||
$("#manualCategory").toggle(0,"swing",function () {
|
$("#manualCategory").toggle(0,"swing",function () {
|
||||||
|
|
||||||
@ -151,7 +152,7 @@ $(function () {
|
|||||||
layer.close(index);
|
layer.close(index);
|
||||||
layer.msg("文档加载失败");
|
layer.msg("文档加载失败");
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存文档到服务器
|
* 保存文档到服务器
|
||||||
@ -341,4 +342,17 @@ $(function () {
|
|||||||
loadDocument(selected);
|
loadDocument(selected);
|
||||||
|
|
||||||
}).on("move_node.jstree",jstree_save);
|
}).on("move_node.jstree",jstree_save);
|
||||||
|
|
||||||
|
$("#documentTemplateModal").on("click",".section>a[data-type]",function () {
|
||||||
|
var $this = $(this).attr("data-type");
|
||||||
|
var body = $("#template-" + $this).html();
|
||||||
|
if (body) {
|
||||||
|
window.isLoad = true;
|
||||||
|
window.editor.clear();
|
||||||
|
window.editor.insertValue(body);
|
||||||
|
window.editor.setCursor({line: 0, ch: 0});
|
||||||
|
resetEditorChanged(true);
|
||||||
|
}
|
||||||
|
$("#documentTemplateModal").modal('hide');
|
||||||
|
});
|
||||||
});
|
});
|
2
static/prettify/themes/atelier-estuary-dark.min.css
vendored
Normal file
2
static/prettify/themes/atelier-estuary-dark.min.css
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/*! Color themes for Google Code Prettify | MIT License | github.com/jmblog/color-themes-for-google-code-prettify */
|
||||||
|
.prettyprint{background:#22221b;font-family:Menlo,Bitstream Vera Sans Mono,DejaVu Sans Mono,Monaco,Consolas,monospace;border:0!important}.pln{color:#f4f3ec}ol.linenums{margin-top:0;margin-bottom:0;color:#6c6b5a}li.L0,li.L1,li.L2,li.L3,li.L4,li.L5,li.L6,li.L7,li.L8,li.L9{padding-left:1em;background-color:#22221b;list-style-type:decimal}@media screen{.str{color:#7d9726}.kwd{color:#5f9182}.com{color:#6c6b5a}.typ{color:#36a166}.lit{color:#ae7313}.pun{color:#f4f3ec}.opn{color:#f4f3ec}.clo{color:#f4f3ec}.tag{color:#ba6236}.atn{color:#ae7313}.atv{color:#5b9d48}.dec{color:#ae7313}.var{color:#ba6236}.fun{color:#36a166}}
|
@ -17,6 +17,8 @@
|
|||||||
<link href="/static/css/jstree.css" rel="stylesheet">
|
<link href="/static/css/jstree.css" rel="stylesheet">
|
||||||
{{if eq .Model.Editor "markdown"}}
|
{{if eq .Model.Editor "markdown"}}
|
||||||
<link href="{{cdncss "/static/editor.md/css/editormd.preview.css"}}" rel="stylesheet">
|
<link href="{{cdncss "/static/editor.md/css/editormd.preview.css"}}" rel="stylesheet">
|
||||||
|
<link href="{{cdncss "/static/prettify/themes/atelier-estuary-dark.min.css"}}" rel="stylesheet">
|
||||||
|
<link href="/static/css/markdown.preview.css" rel="stylesheet">
|
||||||
{{else}}
|
{{else}}
|
||||||
<link href="{{cdncss "/static/highlight/styles/zenburn.css"}}" rel="stylesheet">
|
<link href="{{cdncss "/static/highlight/styles/zenburn.css"}}" rel="stylesheet">
|
||||||
{{end}}
|
{{end}}
|
||||||
@ -226,196 +228,20 @@
|
|||||||
<script type="text/javascript" src="{{cdnjs "/static/nprogress/nprogress.js"}}"></script>
|
<script type="text/javascript" src="{{cdnjs "/static/nprogress/nprogress.js"}}"></script>
|
||||||
<script type="text/javascript" src="{{cdnjs "/static/highlight/highlight.js"}}"></script>
|
<script type="text/javascript" src="{{cdnjs "/static/highlight/highlight.js"}}"></script>
|
||||||
<script type="text/javascript" src="{{cdnjs "/static/highlight/highlightjs-line-numbers.min.js"}}"></script>
|
<script type="text/javascript" src="{{cdnjs "/static/highlight/highlightjs-line-numbers.min.js"}}"></script>
|
||||||
|
<script type="text/javascript" src="/static/js/jquery.highlight.js"></script>
|
||||||
|
<script type="text/javascript" src="/static/js/kancloud.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var events = $("body");
|
$(function () {
|
||||||
var catalog = null;
|
|
||||||
function initHighlighting() {
|
|
||||||
$('pre code').each(function (i, block) {
|
|
||||||
hljs.highlightBlock(block);
|
|
||||||
});
|
|
||||||
|
|
||||||
hljs.initLineNumbersOnLoad();
|
|
||||||
}
|
|
||||||
function loadDocument($url,$id,$callback) {
|
|
||||||
$.ajax({
|
|
||||||
url : $url,
|
|
||||||
type : "GET",
|
|
||||||
beforeSend :function (xhr) {
|
|
||||||
var body = events.data('body_' + $id);
|
|
||||||
var title = events.data('title_' + $id);
|
|
||||||
var doc_title = events.data('doc_title_' + $id);
|
|
||||||
|
|
||||||
if(body && title && doc_title){
|
|
||||||
|
|
||||||
if (typeof $callback === "function") {
|
|
||||||
body = $callback(body);
|
|
||||||
}
|
|
||||||
$("#page-content").html(body);
|
|
||||||
$("title").text(title);
|
|
||||||
$("#article-title").text(doc_title);
|
|
||||||
|
|
||||||
events.trigger('article.open',$url,true);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
NProgress.start();
|
|
||||||
},
|
|
||||||
success : function (res) {
|
|
||||||
if(res.errcode === 0){
|
|
||||||
var body = res.data.body;
|
|
||||||
var doc_title = res.data.doc_title;
|
|
||||||
var title = res.data.title;
|
|
||||||
|
|
||||||
$body = body;
|
|
||||||
if (typeof $callback === "function" ){
|
|
||||||
$body = $callback(body);
|
|
||||||
}
|
|
||||||
$("#page-content").html($body);
|
|
||||||
$("title").text(title);
|
|
||||||
$("#article-title").text(doc_title);
|
|
||||||
|
|
||||||
events.data('body_' + $id,body);
|
|
||||||
events.data('title_' + $id,title);
|
|
||||||
events.data('doc_title_' + $id,doc_title);
|
|
||||||
|
|
||||||
events.trigger('article.open',$url,false);
|
|
||||||
|
|
||||||
}else{
|
|
||||||
layer.msg("加载失败");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
complete : function () {
|
|
||||||
NProgress.done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function () {
|
|
||||||
$(".view-backtop").on("click", function () {
|
|
||||||
$('.manual-right').animate({ scrollTop: '0px' }, 200);
|
|
||||||
});
|
|
||||||
$(".manual-right").scroll(function () {
|
|
||||||
var top = $(".manual-right").scrollTop();
|
|
||||||
if(top > 100){
|
|
||||||
$(".view-backtop").addClass("active");
|
|
||||||
}else{
|
|
||||||
$(".view-backtop").removeClass("active");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
window.isFullScreen = false;
|
|
||||||
|
|
||||||
initHighlighting();
|
|
||||||
|
|
||||||
$("#sidebar").jstree({
|
|
||||||
'plugins':["wholerow","types"],
|
|
||||||
"types": {
|
|
||||||
"default" : {
|
|
||||||
"icon" : false // 删除默认图标
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'core' : {
|
|
||||||
'check_callback' : true,
|
|
||||||
"multiple" : false ,
|
|
||||||
'animation' : 0
|
|
||||||
}
|
|
||||||
}).on('select_node.jstree',function (node,selected,event) {
|
|
||||||
$(".m-manual").removeClass('manual-mobile-show-left');
|
|
||||||
var url = selected.node.a_attr.href;
|
|
||||||
|
|
||||||
if(url === window.location.href){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
loadDocument(url,selected.node.id);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#slidebar").on("click",function () {
|
|
||||||
$(".m-manual").addClass('manual-mobile-show-left');
|
|
||||||
});
|
|
||||||
$(".manual-mask").on("click",function () {
|
|
||||||
$(".m-manual").removeClass('manual-mobile-show-left');
|
|
||||||
});
|
|
||||||
|
|
||||||
$(".manual-fullscreen-switch").on("click",function () {
|
|
||||||
isFullScreen = !isFullScreen;
|
|
||||||
if (isFullScreen) {
|
|
||||||
$(".m-manual").addClass('manual-fullscreen-active');
|
|
||||||
} else {
|
|
||||||
$(".m-manual").removeClass('manual-fullscreen-active');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
events.on('article.open', function (event, url,init) {
|
|
||||||
if ('pushState' in history) {
|
|
||||||
|
|
||||||
if (init == false) {
|
|
||||||
history.replaceState({ }, '', url);
|
|
||||||
init = true;
|
|
||||||
} else {
|
|
||||||
history.pushState({ }, '', url);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
location.hash = url;
|
|
||||||
}
|
|
||||||
initHighlighting();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
$(".navg-item[data-mode]").on("click",function () {
|
|
||||||
var mode = $(this).data('mode');
|
|
||||||
$(this).siblings().removeClass('active').end().addClass('active');
|
|
||||||
$(".m-manual").removeClass("manual-mode-view manual-mode-collect manual-mode-search").addClass("manual-mode-" + mode);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 项目内搜索
|
|
||||||
*/
|
|
||||||
$("#searchForm").ajaxForm({
|
|
||||||
beforeSubmit : function () {
|
|
||||||
var keyword = $.trim($("#searchForm").find("input[name='keyword']").val());
|
|
||||||
if(keyword === ""){
|
|
||||||
$(".search-empty").show();
|
|
||||||
$("#searchList").html("");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$("#btnSearch").attr("disabled","disabled").find("i").removeClass("fa-search").addClass("loading");
|
|
||||||
window.keyword = keyword;
|
|
||||||
},
|
|
||||||
success :function (res) {
|
|
||||||
var html = "";
|
|
||||||
if(res.errcode === 0){
|
|
||||||
for(var i in res.data){
|
|
||||||
var item = res.data[i];
|
|
||||||
html += '<li><a href="javascript:;" title="'+ item.doc_name +'" data-id="'+ item.doc_id+'"> '+ item.doc_name +' </a></li>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(html !== ""){
|
|
||||||
$(".search-empty").hide();
|
|
||||||
}else{
|
|
||||||
$(".search-empty").show();
|
|
||||||
}
|
|
||||||
$("#searchList").html(html);
|
|
||||||
},
|
|
||||||
complete : function () {
|
|
||||||
$("#btnSearch").removeAttr("disabled").find("i").removeClass("loading").addClass("fa-search");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#searchList").on("click","a",function () {
|
$("#searchList").on("click","a",function () {
|
||||||
var id = $(this).attr("data-id");
|
var id = $(this).attr("data-id");
|
||||||
var url = "{{urlfor "DocumentController.Read" ":key" .Model.Identify ":id" ""}}/" + id;
|
var url = "{{urlfor "DocumentController.Read" ":key" .Model.Identify ":id" ""}}/" + id;
|
||||||
$(this).parent("li").siblings().find("a").removeClass("active");
|
$(this).parent("li").siblings().find("a").removeClass("active");
|
||||||
$(this).addClass("active");
|
$(this).addClass("active");
|
||||||
loadDocument(url,id,function (body) {
|
loadDocument(url,id,function (body) {
|
||||||
if(body !== ""){
|
return $(body).highlight(window.keyword);
|
||||||
console.log(window.keyword);
|
|
||||||
|
|
||||||
body = body.replace(new RegExp(window.keyword,"g"),'<em class="search-highlight">' + window.keyword + '</em>');
|
|
||||||
}
|
|
||||||
return body;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -29,6 +29,8 @@
|
|||||||
<link href="{{cdncss "/static/highlight/styles/zenburn.css"}}" rel="stylesheet">
|
<link href="{{cdncss "/static/highlight/styles/zenburn.css"}}" rel="stylesheet">
|
||||||
<link href="{{cdncss "/static/webuploader/webuploader.css"}}" rel="stylesheet">
|
<link href="{{cdncss "/static/webuploader/webuploader.css"}}" rel="stylesheet">
|
||||||
<link href="/static/css/markdown.css" rel="stylesheet">
|
<link href="/static/css/markdown.css" rel="stylesheet">
|
||||||
|
<link href="{{cdncss "/static/prettify/themes/atelier-estuary-dark.min.css"}}" rel="stylesheet">
|
||||||
|
<link href="/static/css/markdown.preview.css" rel="stylesheet">
|
||||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||||
<!--[if lt IE 9]>
|
<!--[if lt IE 9]>
|
||||||
@ -77,7 +79,9 @@
|
|||||||
<a href="javascript:;" data-toggle="tooltip" data-title="添加表格"><i class="fa fa-table item" name="table" unselectable="on"></i></a>
|
<a href="javascript:;" data-toggle="tooltip" data-title="添加表格"><i class="fa fa-table item" name="table" unselectable="on"></i></a>
|
||||||
<a href="javascript:;" data-toggle="tooltip" data-title="引用"><i class="fa fa-quote-right item" name="quote" unselectable="on"></i></a>
|
<a href="javascript:;" data-toggle="tooltip" data-title="引用"><i class="fa fa-quote-right item" name="quote" unselectable="on"></i></a>
|
||||||
<a href="javascript:;" data-toggle="tooltip" data-title="GFM 任务列表"><i class="fa fa-tasks item" name="tasks" aria-hidden="true"></i></a>
|
<a href="javascript:;" data-toggle="tooltip" data-title="GFM 任务列表"><i class="fa fa-tasks item" name="tasks" aria-hidden="true"></i></a>
|
||||||
<a href="javascript:;" data-toggle="tooltip" data-title="附件"><i class="fa fa-paperclip last" aria-hidden="true" name="attachment"></i></a>
|
<a href="javascript:;" data-toggle="tooltip" data-title="附件"><i class="fa fa-paperclip item" aria-hidden="true" name="attachment"></i></a>
|
||||||
|
<a href="javascript:;" data-toggle="tooltip" data-title="模板"><i class="fa fa-tachometer last" name="template"></i></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="editormd-group pull-right">
|
<div class="editormd-group pull-right">
|
||||||
@ -225,6 +229,57 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="documentTemplateModal" tabindex="-1" role="dialog" aria-labelledby="请选择模板类型" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title" id="modal-title">请选择模板类型</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body template-list">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section">
|
||||||
|
<a data-type="normal" href="javascript:;"><i class="fa fa-file-o"></i></a>
|
||||||
|
<h3><a data-type="normal" href="javascript:;">普通文档</a></h3>
|
||||||
|
<ul>
|
||||||
|
<li>默认类型</li>
|
||||||
|
<li>简单的文本文档</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="section">
|
||||||
|
<a data-type="api" href="javascript:;"><i class="fa fa-file-code-o"></i></a>
|
||||||
|
<h3><a data-type="api" href="javascript:;">API文档</a></h3>
|
||||||
|
<ul>
|
||||||
|
<li>用于API文档速写</li>
|
||||||
|
<li>支持代码高亮</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="section">
|
||||||
|
<a data-type="code" href="javascript:;"><i class="fa fa-book"></i></a>
|
||||||
|
|
||||||
|
<h3><a data-type="code" href="javascript:;">数据字典</a></h3>
|
||||||
|
<ul>
|
||||||
|
<li>用于数据字典显示</li>
|
||||||
|
<li>表格支持</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template id="template-normal">
|
||||||
|
{{template "document/template_normal.tpl"}}
|
||||||
|
</template>
|
||||||
|
<template id="template-api">
|
||||||
|
{{template "document/template_api.tpl"}}
|
||||||
|
</template>
|
||||||
|
<template id="template-code">
|
||||||
|
{{template "document/template_code.tpl"}}
|
||||||
|
</template>
|
||||||
<script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}"></script>
|
<script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}"></script>
|
||||||
<script src="{{cdnjs "/static/vuejs/vue.min.js"}}" type="text/javascript"></script>
|
<script src="{{cdnjs "/static/vuejs/vue.min.js"}}" type="text/javascript"></script>
|
||||||
<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}"></script>
|
<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}"></script>
|
||||||
@ -233,10 +288,6 @@
|
|||||||
<script src="{{cdnjs "/static/editor.md/editormd.js"}}" type="text/javascript"></script>
|
<script src="{{cdnjs "/static/editor.md/editormd.js"}}" type="text/javascript"></script>
|
||||||
<script src="{{cdnjs "/static/layer/layer.js"}}" type="text/javascript" ></script>
|
<script src="{{cdnjs "/static/layer/layer.js"}}" type="text/javascript" ></script>
|
||||||
<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
|
<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<script src="/static/js/editor.js" type="text/javascript"></script>
|
<script src="/static/js/editor.js" type="text/javascript"></script>
|
||||||
<script src="/static/js/markdown.js" type="text/javascript"></script>
|
<script src="/static/js/markdown.js" type="text/javascript"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
71
views/document/template_api.tpl
Normal file
71
views/document/template_api.tpl
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#### 简要描述:
|
||||||
|
|
||||||
|
- 用户登录接口
|
||||||
|
|
||||||
|
#### 接口版本:
|
||||||
|
|
||||||
|
|版本号|制定人|制定日期|修订日期|
|
||||||
|
|:---- |:---|:----- |----- |
|
||||||
|
|2.1.0 |秦亮 |2017-03-20 | xxxx-xx-xx |
|
||||||
|
|
||||||
|
#### 请求URL:
|
||||||
|
|
||||||
|
- http://xx.com/api/login
|
||||||
|
|
||||||
|
#### 请求方式:
|
||||||
|
|
||||||
|
- GET
|
||||||
|
- POST
|
||||||
|
|
||||||
|
#### 请求头:
|
||||||
|
|
||||||
|
|参数名|是否必须|类型|说明|
|
||||||
|
|:---- |:---|:----- |----- |
|
||||||
|
|Content-Type |是 |string |请求类型: application/json |
|
||||||
|
|Content-MD5 |是 |string | 请求内容签名 |
|
||||||
|
|
||||||
|
|
||||||
|
#### 请求参数:
|
||||||
|
|
||||||
|
|参数名|是否必须|类型|说明|
|
||||||
|
|:---- |:---|:----- |----- |
|
||||||
|
|username |是 |string |用户名 |
|
||||||
|
|password |是 |string | 密码 |
|
||||||
|
|
||||||
|
#### 返回示例:
|
||||||
|
|
||||||
|
**正确时返回:**
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"errcode": 0,
|
||||||
|
"data": {
|
||||||
|
"uid": "1",
|
||||||
|
"account": "admin",
|
||||||
|
"nickname": "Minho",
|
||||||
|
"group_level": 0 ,
|
||||||
|
"create_time": "1436864169",
|
||||||
|
"last_login_time": "0",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**错误时返回:**
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"errcode": 500,
|
||||||
|
"errmsg": "invalid appid"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 返回参数说明:
|
||||||
|
|
||||||
|
|参数名|类型|说明|
|
||||||
|
|:----- |:-----|----- |
|
||||||
|
|group_level |int |用户组id,1:超级管理员;2:普通用户 |
|
||||||
|
|
||||||
|
#### 备注:
|
||||||
|
|
||||||
|
- 更多返回错误代码请看首页的错误代码描述
|
13
views/document/template_code.tpl
Normal file
13
views/document/template_code.tpl
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
### 数据库字典
|
||||||
|
|
||||||
|
#### 用户表,储存用户信息
|
||||||
|
|
||||||
|
|字段|类型|空|默认|注释|
|
||||||
|
|:---- |:------- |:--- |-- -|------ |
|
||||||
|
|uid |int(10) |否 | | |
|
||||||
|
|username |varchar(20) |否 | | 用户名 |
|
||||||
|
|password |varchar(50) |否 | | 密码 |
|
||||||
|
|name |varchar(15) |是 | | 昵称 |
|
||||||
|
|reg_time |int(11) |否 | 0 | 注册时间 |
|
||||||
|
|
||||||
|
#### 备注:无
|
208
views/document/template_normal.tpl
Normal file
208
views/document/template_normal.tpl
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
# MinDoc 简介
|
||||||
|
|
||||||
|
[](https://travis-ci.org/lifei6671/godoc)
|
||||||
|
|
||||||
|
MinDoc 是一款针对IT团队开发的简单好用的文档管理系统。
|
||||||
|
|
||||||
|
MinDoc 的前身是 SmartWiki 文档系统。SmartWiki 是基于 PHP 框架 laravel 开发的一款文档管理系统。因 PHP 的部署对普通用户来说太复杂,所以改用 Golang 开发。可以方便用户部署和实用。
|
||||||
|
|
||||||
|
开发缘起是公司IT部门需要一款简单实用的项目接口文档管理和分享的系统。其功能和界面源于 kancloud 。
|
||||||
|
|
||||||
|
可以用来储存日常接口文档,数据库字典,手册说明等文档。内置项目管理,用户管理,权限管理等功能,能够满足大部分中小团队的文档管理需求。
|
||||||
|
|
||||||
|
演示站点: [http://doc.iminho.me](http://doc.iminho.me)
|
||||||
|
|
||||||
|
# 安装与使用
|
||||||
|
|
||||||
|
**如果你的服务器上没有安装golang程序请手动设置一个环境变量如下:键名为 ZONEINFO,值为MinDoc跟目录下的/lib/time/zoneinfo.zip 。**
|
||||||
|
|
||||||
|
**Windows 教程:** [https://github.com/lifei6671/godoc/blob/master/README_WIN.md](docs/README_WIN.md)
|
||||||
|
|
||||||
|
**Linux 教程:** [https://github.com/lifei6671/godoc/blob/master/README_LINUX.md](docs/README_LINUX.md)
|
||||||
|
|
||||||
|
**PDF 导出配置教程** [https://github.com/lifei6671/godoc/blob/master/docs/README_LINUX.md](docs/WKHTMLTOPDF.md)
|
||||||
|
|
||||||
|
对于没有Golang使用经验的用户,可以从 [https://github.com/lifei6671/godoc/releases](https://github.com/lifei6671/godoc/releases) 这里下载编译完的程序。
|
||||||
|
|
||||||
|
如果有Golang开发经验,建议通过编译安装。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/lifei6671/godoc.git
|
||||||
|
|
||||||
|
go get -d ./...
|
||||||
|
|
||||||
|
go build -ldflags "-w"
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
MinDoc 使用MySQL储存数据,且编码必须是`utf8mb4_general_ci`。请在安装前,把数据库配置填充到项目目录下的 conf/app.conf 中。
|
||||||
|
|
||||||
|
如果conf目录下不存在 app.conf 请重命名 app.conf.example 为 app.conf。
|
||||||
|
|
||||||
|
如果 MinDoc 根目录下存在 install.lock 文件表示已经初始化过数据库,想要重新初始化数据库,只需要删除该文件重新启动程序即可。
|
||||||
|
|
||||||
|
**默认程序会自动创建表,同时初始化一个超级管理员用户:admin 密码:123456 。请登录后重新设置密码。**
|
||||||
|
|
||||||
|
## Linux 下后台运行
|
||||||
|
|
||||||
|
在 Linux 如果想让程序后台运行可以执行如下命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#使程序后台运行
|
||||||
|
nohup ./godoc &
|
||||||
|
```
|
||||||
|
|
||||||
|
该命令会使程序后台执行,但是服务器重启后不会自动启动服务。
|
||||||
|
|
||||||
|
使用 supervisor 做服务,可以使服务器重启后自动重启 MinDoc。
|
||||||
|
|
||||||
|
## Windows 下后台运行
|
||||||
|
|
||||||
|
Windows 下后台运行需要借助 CMD 命令行命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#在MinDoc跟目录下新建一个slave.vbs文件:
|
||||||
|
|
||||||
|
Set ws = CreateObject("Wscript.Shell")
|
||||||
|
ws.run "cmd /c start.bat",vbhide
|
||||||
|
|
||||||
|
#再建一个start.bat文件:
|
||||||
|
@echo off
|
||||||
|
|
||||||
|
godoc_windows_amd64.exe
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
启动时双击slave.vbs即可,等待程序初始化完数据库会在该目录下创建一个install.lock文件,标识已安装成功。
|
||||||
|
|
||||||
|
如果是自己编译,可以用以下命令即可编译出不依赖cmd命令的后台运行的程序:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go build -ldflags "-H=windowsgui"
|
||||||
|
```
|
||||||
|
通过该命令编译的Golang程序在Windows上默认后台运行。
|
||||||
|
|
||||||
|
请将将 MinDoc 加入开机启动列表,使程序开机启动。
|
||||||
|
|
||||||
|
## 密码找回功能
|
||||||
|
|
||||||
|
密码找回功能依赖邮件服务,因此,需要配置邮件服务才能使用该功能,该配置位于 `conf/app.conf` 中:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
#邮件配置
|
||||||
|
#是否启用邮件
|
||||||
|
enable_mail=true
|
||||||
|
#smtp服务器的账号
|
||||||
|
smtp_user_name=admin@iminho.me
|
||||||
|
#smtp服务器的地址
|
||||||
|
smtp_host=smtp.ym.163.com
|
||||||
|
#密码
|
||||||
|
smtp_password=1q2w3e__ABC
|
||||||
|
#端口号
|
||||||
|
smtp_port=25
|
||||||
|
#邮件发送人的地址
|
||||||
|
form_user_name=admin@iminho.me
|
||||||
|
#邮件有效期30分钟
|
||||||
|
mail_expired=30
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
# 使用Docker部署
|
||||||
|
|
||||||
|
如果是Docker用户,可参考项目内置的Dockerfile文件编译镜像。
|
||||||
|
|
||||||
|
在启动镜像时需要提供如下的环境变量:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
MYSQL_PORT_3306_TCP_ADDR MySQL地址
|
||||||
|
MYSQL_PORT_3306_TCP_PORT MySQL端口号
|
||||||
|
MYSQL_INSTANCE_NAME MySQL数据库名称
|
||||||
|
MYSQL_USERNAME MySQL账号
|
||||||
|
MYSQL_PASSWORD MySQL密码
|
||||||
|
HTTP_PORT 程序监听的端口号
|
||||||
|
```
|
||||||
|
|
||||||
|
举个栗子
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -p 8181:8181 -e MYSQL_PORT_3306_TCP_ADDR=127.0.0.1 -e MYSQL_PORT_3306_TCP_PORT=3306 -e MYSQL_INSTANCE_NAME=mindoc_db -e MYSQL_USERNAME=root -e MYSQL_PASSWORD=123456 -e httpport=8181 -d daocloud.io/lifei6671/godoc:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
# 项目截图
|
||||||
|
|
||||||
|
**创建项目**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**项目列表**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**项目概述**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**项目成员**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**项目设置**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**基于Editor.md开发的Markdown编辑器**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**基于wangEditor开发的富文本编辑器**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**项目预览**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**超级管理员后台**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
# 使用的技术
|
||||||
|
|
||||||
|
- beego 1.8.1
|
||||||
|
- mysql 5.6
|
||||||
|
- editor.md
|
||||||
|
- bootstrap 3.2
|
||||||
|
- jquery 库
|
||||||
|
- layer 弹出层框架
|
||||||
|
- webuploader 文件上传框架
|
||||||
|
- Nprogress 库
|
||||||
|
- jstree 树状结构库
|
||||||
|
- font awesome 字体库
|
||||||
|
- cropper 图片剪裁库
|
||||||
|
- layer 弹出层框架
|
||||||
|
- highlight 代码高亮库
|
||||||
|
- to-markdown HTML转Markdown库
|
||||||
|
- wangEditor 富文本编辑器
|
||||||
|
|
||||||
|
|
||||||
|
# 主要功能
|
||||||
|
|
||||||
|
- 项目管理,可以对项目进行编辑更改,成员添加等。
|
||||||
|
- 文档管理,添加和删除文档等。
|
||||||
|
- 评论管理,可以管理文档评论和自己发布的评论。
|
||||||
|
- 用户管理,添加和禁用用户,个人资料更改等。
|
||||||
|
- 用户权限管理 , 实现用户角色的变更。
|
||||||
|
- 项目加密,可以设置项目公开状态,私有项目需要通过Token访问。
|
||||||
|
- 站点配置,可开启匿名访问、验证码等。
|
||||||
|
|
||||||
|
# 参与开发
|
||||||
|
|
||||||
|
我们欢迎您在 MinDoc 项目的 GitHub 上报告 issue 或者 pull request。
|
||||||
|
|
||||||
|
如果您还不熟悉GitHub的Fork and Pull开发模式,您可以阅读GitHub的文档(https://help.github.com/articles/using-pull-requests) 获得更多的信息。
|
||||||
|
|
||||||
|
# 关于作者
|
||||||
|
|
||||||
|
一个不纯粹的PHPer,一个不自由的 gopher 。
|
@ -47,7 +47,7 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>用户密码</label>
|
<label>用户密码</label>
|
||||||
<input type="password" class="form-control" name="password1" placeholder="用户密码" maxlength="50">
|
<input type="password" class="form-control" name="password1" placeholder="用户密码" maxlength="50">
|
||||||
<p style="color: #999;font-size: 12px;">不修改密码请留空</p>
|
<p style="color: #999;font-size: 12px;">不修改密码请留空,只支持本地用户修改密码</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>确认密码</label>
|
<label>确认密码</label>
|
||||||
|
@ -40,21 +40,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body manager">
|
<div class="box-body manager">
|
||||||
<div class="dashboard-item">
|
<a href="{{urlfor "ManagerController.Books"}}" class="dashboard-item">
|
||||||
<span class="fa fa-book" aria-hidden="true"></span>
|
<span class="fa fa-book" aria-hidden="true"></span>
|
||||||
<span class="fa-class">项目数量</span>
|
<span class="fa-class">项目数量</span>
|
||||||
<span class="fa-class">{{.Model.BookNumber}}</span>
|
<span class="fa-class">{{.Model.BookNumber}}</span>
|
||||||
</div>
|
</a>
|
||||||
<div class="dashboard-item">
|
<div class="dashboard-item">
|
||||||
<span class="fa fa-file-text-o" aria-hidden="true"></span>
|
<span class="fa fa-file-text-o" aria-hidden="true"></span>
|
||||||
<span class="fa-class">文章数量</span>
|
<span class="fa-class">文章数量</span>
|
||||||
<span class="fa-class">{{.Model.DocumentNumber}}</span>
|
<span class="fa-class">{{.Model.DocumentNumber}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="dashboard-item">
|
<a href="{{urlfor "ManagerController.Users"}}" class="dashboard-item">
|
||||||
<span class="fa fa-users" aria-hidden="true"></span>
|
<span class="fa fa-users" aria-hidden="true"></span>
|
||||||
<span class="fa-class">会员数量</span>
|
<span class="fa-class">会员数量</span>
|
||||||
<span class="fa-class">{{.Model.MemberNumber}}</span>
|
<span class="fa-class">{{.Model.MemberNumber}}</span>
|
||||||
</div>
|
</a>
|
||||||
<!--
|
<!--
|
||||||
{{/*
|
{{/*
|
||||||
<div class="dashboard-item">
|
<div class="dashboard-item">
|
||||||
|
@ -29,7 +29,9 @@
|
|||||||
<div class="page-left">
|
<div class="page-left">
|
||||||
<ul class="menu">
|
<ul class="menu">
|
||||||
<li class="active"><a href="{{urlfor "SettingController.Index"}}" class="item"><i class="fa fa-sitemap" aria-hidden="true"></i> 基本信息</a> </li>
|
<li class="active"><a href="{{urlfor "SettingController.Index"}}" class="item"><i class="fa fa-sitemap" aria-hidden="true"></i> 基本信息</a> </li>
|
||||||
|
{{if ne .Member.AuthMethod "ldap"}}
|
||||||
<li><a href="{{urlfor "SettingController.Password"}}" class="item"><i class="fa fa-user" aria-hidden="true"></i> 修改密码</a> </li>
|
<li><a href="{{urlfor "SettingController.Password"}}" class="item"><i class="fa fa-user" aria-hidden="true"></i> 修改密码</a> </li>
|
||||||
|
{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-right">
|
<div class="page-right">
|
||||||
|
Loading…
Reference in New Issue
Block a user