mirror of https://github.com/mindoc-org/mindoc.git
实现项目列表、概述功能
parent
0647707e44
commit
ca0d5094c1
|
@ -18,4 +18,5 @@ db_database=mindoc_db
|
||||||
db_username=root
|
db_username=root
|
||||||
db_password=123456
|
db_password=123456
|
||||||
|
|
||||||
queue_size=50
|
#项目默认封面
|
||||||
|
cover=/static/images/book.jpg
|
|
@ -1,38 +1,228 @@
|
||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"strings"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
"encoding/json"
|
||||||
|
"html/template"
|
||||||
|
|
||||||
|
"github.com/lifei6671/godoc/models"
|
||||||
|
"github.com/lifei6671/godoc/utils"
|
||||||
|
"github.com/astaxie/beego"
|
||||||
|
"github.com/astaxie/beego/orm"
|
||||||
|
)
|
||||||
|
|
||||||
type BookController struct {
|
type BookController struct {
|
||||||
BaseController
|
BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BookController) Index() {
|
func (c *BookController) Index() {
|
||||||
p.TplName = "book/index.tpl"
|
c.Prepare()
|
||||||
|
c.TplName = "book/index.tpl"
|
||||||
|
|
||||||
|
pageIndex, _ := c.GetInt("page", 1)
|
||||||
|
|
||||||
|
books,totalCount,err := models.NewBook().FindToPager(pageIndex,10,c.Member.MemberId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.Abort("500")
|
||||||
|
}
|
||||||
|
|
||||||
|
html := utils.GetPagerHtml(c.Ctx.Request.RequestURI,pageIndex,10,totalCount)
|
||||||
|
|
||||||
|
c.Data["PageHtml"] = html
|
||||||
|
|
||||||
|
b,err := json.Marshal(books)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.Data["Result"] = template.JS("[]")
|
||||||
|
}else{
|
||||||
|
c.Data["Result"] = template.JS(string(b))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dashboard 项目概要 .
|
// Dashboard 项目概要 .
|
||||||
func (p *BookController) Dashboard() {
|
func (c *BookController) Dashboard() {
|
||||||
p.TplName = "book/dashboard.tpl"
|
c.Prepare()
|
||||||
|
c.TplName = "book/dashboard.tpl"
|
||||||
|
|
||||||
|
key := c.Ctx.Input.Param(":key")
|
||||||
|
|
||||||
|
if key == ""{
|
||||||
|
c.Abort("404")
|
||||||
|
}
|
||||||
|
|
||||||
|
book,err := models.NewBookResult().FindByIdentify(key,c.Member.MemberId)
|
||||||
|
if err != nil {
|
||||||
|
if err == models.ErrPermissionDenied {
|
||||||
|
c.Abort("403")
|
||||||
|
}
|
||||||
|
c.Abort("500")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["Model"] = *book
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setting 项目设置 .
|
// Setting 项目设置 .
|
||||||
func (p *BookController) Setting() {
|
func (c *BookController) Setting() {
|
||||||
p.TplName = "book/setting.tpl"
|
c.Prepare()
|
||||||
|
c.TplName = "book/setting.tpl"
|
||||||
|
|
||||||
|
key := c.Ctx.Input.Param(":key")
|
||||||
|
|
||||||
|
if key == ""{
|
||||||
|
c.Abort("404")
|
||||||
|
}
|
||||||
|
|
||||||
|
book,err := models.NewBookResult().FindByIdentify(key,c.Member.MemberId)
|
||||||
|
if err != nil {
|
||||||
|
if err == models.ErrPermissionDenied {
|
||||||
|
c.Abort("403")
|
||||||
|
}
|
||||||
|
c.Abort("500")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["Model"] = *book
|
||||||
|
|
||||||
|
}
|
||||||
|
//用户列表.
|
||||||
|
func (c *BookController) Users() {
|
||||||
|
c.Prepare()
|
||||||
|
c.TplName = "book/users.tpl"
|
||||||
|
|
||||||
|
key := c.Ctx.Input.Param(":key")
|
||||||
|
pageIndex,_ := c.GetInt("page",1)
|
||||||
|
|
||||||
|
if key == ""{
|
||||||
|
c.Abort("404")
|
||||||
|
}
|
||||||
|
|
||||||
|
book,err := models.NewBookResult().FindByIdentify(key,c.Member.MemberId)
|
||||||
|
if err != nil {
|
||||||
|
if err == models.ErrPermissionDenied {
|
||||||
|
c.Abort("403")
|
||||||
|
}
|
||||||
|
c.Abort("500")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["Model"] = *book
|
||||||
|
|
||||||
|
members,totalCount,err := models.NewMemberRelationshipResult().FindForUsersByBookId(book.BookId,pageIndex,15)
|
||||||
|
|
||||||
|
html := utils.GetPagerHtml(c.Ctx.Request.RequestURI,pageIndex,10,totalCount)
|
||||||
|
|
||||||
|
c.Data["PageHtml"] = html
|
||||||
|
b,err := json.Marshal(members)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.Data["Result"] = template.JS("[]")
|
||||||
|
}else{
|
||||||
|
c.Data["Result"] = template.JS(string(b))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BookController) Users() {
|
func (c *BookController) AddMember() {
|
||||||
p.TplName = "book/users.tpl"
|
identify := c.GetString("identify")
|
||||||
|
account := c.GetString("account")
|
||||||
|
role_id,_ := c.GetInt("role_id",3)
|
||||||
|
|
||||||
|
if identify == "" || account == ""{
|
||||||
|
c.JsonResult(6001,"参数错误")
|
||||||
|
}
|
||||||
|
book ,err := models.NewBookResult().FindByIdentify("identify",c.Member.MemberId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if err == models.ErrPermissionDenied {
|
||||||
|
c.JsonResult(403,"权限不足")
|
||||||
|
}
|
||||||
|
if err == orm.ErrNoRows {
|
||||||
|
c.JsonResult(404,"项目不能存在")
|
||||||
|
}
|
||||||
|
c.JsonResult(6002,err.Error())
|
||||||
|
}
|
||||||
|
if book.RoleId != 0 && book.RoleId != 1 {
|
||||||
|
c.JsonResult(403,"权限不足")
|
||||||
|
}
|
||||||
|
|
||||||
|
member := models.NewMember()
|
||||||
|
|
||||||
|
if err := member.FindByAccount(account) ; err != nil {
|
||||||
|
c.JsonResult(404,"用户不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _,err := models.NewRelationship().FindForRoleId(book.BookId,member.MemberId);err == orm.ErrNoRows {
|
||||||
|
c.JsonResult(6003,"用户已存在该项目中")
|
||||||
|
}
|
||||||
|
|
||||||
|
relationship := models.NewRelationship()
|
||||||
|
relationship.BookId = book.BookId
|
||||||
|
relationship.MemberId = member.MemberId
|
||||||
|
relationship.RoleId = role_id
|
||||||
|
|
||||||
|
if err := relationship.Insert(); err == nil {
|
||||||
|
c.JsonResult(0,"ok",member)
|
||||||
|
}
|
||||||
|
c.JsonResult(500,err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (c *BookController) Create() {
|
func (c *BookController) Create() {
|
||||||
|
|
||||||
if c.Ctx.Input.IsPost() {
|
if c.Ctx.Input.IsPost() {
|
||||||
book_name := strings.TrimSpace(c.GetString("book_name",""))
|
book_name := strings.TrimSpace(c.GetString("book_name",""))
|
||||||
identify := strings.TrimSpace(c.GetString("identify",""))
|
identify := strings.TrimSpace(c.GetString("identify",""))
|
||||||
description := strings.TrimSpace(c.GetString("description",""))
|
description := strings.TrimSpace(c.GetString("description",""))
|
||||||
privately_owned := c.GetString("privately_owned")
|
privately_owned,_ := strconv.Atoi(c.GetString("privately_owned"))
|
||||||
comment_status := c.GetString("comment_status")
|
comment_status := c.GetString("comment_status")
|
||||||
|
|
||||||
|
if book_name == "" {
|
||||||
|
c.JsonResult(6001,"项目名称不能为空")
|
||||||
|
}
|
||||||
|
if identify == "" {
|
||||||
|
c.JsonResult(6002,"项目标识不能为空")
|
||||||
|
}
|
||||||
|
if ok,err := regexp.MatchString(`^[a-z]+[a-zA-Z0-9_\-]*$`,identify); !ok || err != nil {
|
||||||
|
c.JsonResult(6003,"文档标识只能包含小写字母、数字,以及“-”和“_”符号,并且只能小写字母开头")
|
||||||
|
}
|
||||||
|
if strings.Count(identify,"") > 50 {
|
||||||
|
c.JsonResult(6004,"文档标识不能超过50字")
|
||||||
|
}
|
||||||
|
if strings.Count(description,"") > 500 {
|
||||||
|
c.JsonResult(6004,"项目描述不能大于500字")
|
||||||
|
}
|
||||||
|
if privately_owned !=0 && privately_owned != 1 {
|
||||||
|
privately_owned = 1
|
||||||
|
}
|
||||||
|
if comment_status != "open" && comment_status != "closed" && comment_status != "group_only" && comment_status != "registered_only" {
|
||||||
|
comment_status = "closed"
|
||||||
|
}
|
||||||
|
|
||||||
|
book := models.NewBook()
|
||||||
|
|
||||||
|
if books,err := book.FindByField("identify",identify); err == nil || len(books) > 0 {
|
||||||
|
c.JsonResult(6006,"项目标识已存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
book.BookName = book_name
|
||||||
|
book.Description = description
|
||||||
|
book.CommentCount = 0
|
||||||
|
book.PrivatelyOwned = privately_owned
|
||||||
|
book.CommentStatus = comment_status
|
||||||
|
book.Identify = identify
|
||||||
|
book.DocCount = 0
|
||||||
|
book.MemberId = c.Member.MemberId
|
||||||
|
book.CommentCount = 0
|
||||||
|
book.Version = time.Now().Unix()
|
||||||
|
book.Cover = beego.AppConfig.String("cover")
|
||||||
|
|
||||||
|
err := book.Insert()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.JsonResult(6005,err.Error())
|
||||||
|
}
|
||||||
|
c.JsonResult(0,"ok",book)
|
||||||
}
|
}
|
||||||
c.JsonResult(6001,"error")
|
c.JsonResult(6001,"error")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "github.com/astaxie/beego/orm"
|
||||||
|
|
||||||
|
type Model struct {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Model) Find(id int) error {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
return o.Read(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Model) Insert() error {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
_,err := o.Insert(m)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
107
models/book.go
107
models/book.go
|
@ -1,6 +1,11 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/orm"
|
||||||
|
"github.com/lifei6671/godoc/conf"
|
||||||
|
)
|
||||||
|
|
||||||
// Book struct .
|
// Book struct .
|
||||||
type Book struct {
|
type Book struct {
|
||||||
|
@ -9,17 +14,20 @@ type Book struct {
|
||||||
BookName string `orm:"column(book_name);size(500)" json:"book_name"`
|
BookName string `orm:"column(book_name);size(500)" json:"book_name"`
|
||||||
// Identify 项目唯一标识.
|
// Identify 项目唯一标识.
|
||||||
Identify string `orm:"column(identify);size(100);unique" json:"identify"`
|
Identify string `orm:"column(identify);size(100);unique" json:"identify"`
|
||||||
|
OrderIndex int `orm:"column(order_index);type(int);default(0)" json:"order_index"`
|
||||||
// Description 项目描述.
|
// Description 项目描述.
|
||||||
Description string `orm:"column(description);size(2000)" json:"description"`
|
Description string `orm:"column(description);size(2000)" json:"description"`
|
||||||
|
Label string `orm:"column(label);size(500)" json:"label"`
|
||||||
// PrivatelyOwned 项目私有: 0 公开/ 1 私有
|
// PrivatelyOwned 项目私有: 0 公开/ 1 私有
|
||||||
PrivatelyOwned int `orm:"column(privately_owned);type(int);default(0)" json:"privately_owned"`
|
PrivatelyOwned int `orm:"column(privately_owned);type(int);default(0)" json:"privately_owned"`
|
||||||
// 当项目是私有时的访问Token.
|
// 当项目是私有时的访问Token.
|
||||||
PrivateToken string `orm:"column(private_token);size(500)" json:"private_token"`
|
PrivateToken string `orm:"column(private_token);size(500);null" json:"private_token"`
|
||||||
// DocCount 包含文档数量.
|
// DocCount 包含文档数量.
|
||||||
DocCount int `orm:"column(doc_count);type(int)" json:"doc_count"`
|
DocCount int `orm:"column(doc_count);type(int)" json:"doc_count"`
|
||||||
// CommentStatus 评论设置的状态:open为允许所有人评论,closed为不允许评论, group_only 仅允许参与者评论 ,registered_only 仅允许注册者评论.
|
// CommentStatus 评论设置的状态:open 为允许所有人评论,closed 为不允许评论, group_only 仅允许参与者评论 ,registered_only 仅允许注册者评论.
|
||||||
CommentStatus string `orm:"column(comment_status);size(20);default(open)" json:"comment_status"`
|
CommentStatus string `orm:"column(comment_status);size(20);default(open)" json:"comment_status"`
|
||||||
CommentCount int `orm:"column(comment_count);type(int)" json:"comment_count"`
|
CommentCount int `orm:"column(comment_count);type(int)" json:"comment_count"`
|
||||||
|
Cover string `orm:"column();size(1000)" json:"cover"`
|
||||||
|
|
||||||
// CreateTime 创建时间 .
|
// CreateTime 创建时间 .
|
||||||
CreateTime time.Time `orm:"type(datetime);column(create_time);auto_now_add"`
|
CreateTime time.Time `orm:"type(datetime);column(create_time);auto_now_add"`
|
||||||
|
@ -28,6 +36,7 @@ type Book struct {
|
||||||
Version int64 `orm:"type(bigint);column(version)" json:"version"`
|
Version int64 `orm:"type(bigint);column(version)" json:"version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TableName 获取对应数据库表名.
|
// TableName 获取对应数据库表名.
|
||||||
func (m *Book) TableName() string {
|
func (m *Book) TableName() string {
|
||||||
return "books"
|
return "books"
|
||||||
|
@ -36,4 +45,96 @@ func (m *Book) TableName() string {
|
||||||
func (m *Book) TableEngine() string {
|
func (m *Book) TableEngine() string {
|
||||||
return "INNODB"
|
return "INNODB"
|
||||||
}
|
}
|
||||||
|
func (m *Book) TableNameWithPrefix() string {
|
||||||
|
return conf.GetDatabasePrefix() + m.TableName()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBook() *Book {
|
||||||
|
return &Book{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Book) Insert() error {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
_,err := o.Insert(m)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Book) Update(cols... string) error {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
_,err := o.Update(m,cols...)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Book) FindByField(field string,value interface{}) ([]Book,error) {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
var books []Book
|
||||||
|
_,err := o.QueryTable(conf.GetDatabasePrefix() + m.TableName()).Filter(field,value).All(&books)
|
||||||
|
|
||||||
|
return books,err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Book) FindToPager(pageIndex, pageSize ,memberId int) (books []BookResult,totalCount int,err error){
|
||||||
|
|
||||||
|
relationship := NewRelationship()
|
||||||
|
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
qb, _ := orm.NewQueryBuilder("mysql")
|
||||||
|
|
||||||
|
qb.Select("COUNT(book.book_id) AS total_count").
|
||||||
|
From(m.TableNameWithPrefix() + " AS book").
|
||||||
|
LeftJoin(relationship.TableNameWithPrefix() + " AS rel").
|
||||||
|
On("book.book_id=rel.book_id").
|
||||||
|
Where("rel.member_id=?")
|
||||||
|
|
||||||
|
err = o.Raw(qb.String(),memberId).QueryRow(&totalCount)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := (pageIndex - 1) * pageSize
|
||||||
|
qb2,_ := orm.NewQueryBuilder("mysql")
|
||||||
|
|
||||||
|
qb2.Select("book.*,rel.member_id","rel.role_id","m.account as create_name").
|
||||||
|
From(m.TableNameWithPrefix() + " AS book").
|
||||||
|
LeftJoin(relationship.TableNameWithPrefix() + " AS rel").
|
||||||
|
On("book.book_id=rel.book_id").
|
||||||
|
LeftJoin(NewMember().TableNameWithPrefix() + " AS m").On("rel.member_id=m.member_id AND rel.role_id=0").
|
||||||
|
Where("rel.member_id=?").
|
||||||
|
OrderBy("book.order_index").Desc().
|
||||||
|
Limit(pageSize).
|
||||||
|
Offset(offset)
|
||||||
|
|
||||||
|
_,err = o.Raw(qb2.String(),memberId).QueryRows(&books)
|
||||||
|
|
||||||
|
sql := "SELECT m.account,doc.modify_time FROM md_documents AS doc LEFT JOIN md_members AS m ON doc.modify_at=m.member_id WHERE book_id = ? LIMIT 1 ORDER BY doc.modify_time DESC"
|
||||||
|
|
||||||
|
if err == nil && len(books) > 0{
|
||||||
|
for index,book := range books {
|
||||||
|
var text struct{
|
||||||
|
Account string
|
||||||
|
ModifyTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
err1 := o.Raw(sql,book.BookId).QueryRow(&text)
|
||||||
|
if err1 == nil {
|
||||||
|
books[index].LastModifyText = text.Account + " 于 " + text.ModifyTime.Format("2006-01-02 15:04:05")
|
||||||
|
}
|
||||||
|
if book.RoleId == 0{
|
||||||
|
book.RoleName = "创始人"
|
||||||
|
}else if book.RoleId == 1 {
|
||||||
|
book.RoleName = "管理员"
|
||||||
|
}else if book.RoleId == 2 {
|
||||||
|
book.RoleName = "编辑者"
|
||||||
|
}else if book.RoleId == 2 {
|
||||||
|
book.RoleName = "观察者"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
"github.com/astaxie/beego/orm"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BookResult struct {
|
||||||
|
BookId int `json:"book_id"`
|
||||||
|
BookName string `json:"book_name"`
|
||||||
|
Identify string `json:"identify"`
|
||||||
|
OrderIndex int `json:"order_index"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
PrivatelyOwned int `json:"privately_owned"`
|
||||||
|
PrivateToken string `json:"private_token"`
|
||||||
|
DocCount int `json:"doc_count"`
|
||||||
|
CommentStatus string `json:"comment_status"`
|
||||||
|
CommentCount int `json:"comment_count"`
|
||||||
|
CreateTime time.Time `json:"create_time"`
|
||||||
|
CreateName string `json:"create_name"`
|
||||||
|
ModifyTime time.Time `json:"modify_time"`
|
||||||
|
Cover string `json:"cover"`
|
||||||
|
Label string `json:"label"`
|
||||||
|
MemberId int `json:"member_id"`
|
||||||
|
RoleId int `json:"role_id"`
|
||||||
|
RoleName string `json:"role_name"`
|
||||||
|
|
||||||
|
LastModifyText string `json:"last_modify_text"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBookResult() *BookResult {
|
||||||
|
return &BookResult{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *BookResult) FindByIdentify(identify string,member_id int) (*BookResult,error) {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
book := NewBook()
|
||||||
|
|
||||||
|
err := o.QueryTable(book.TableNameWithPrefix()).Filter("identify", identify).One(book)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return m, err
|
||||||
|
}
|
||||||
|
|
||||||
|
relationship := NewRelationship()
|
||||||
|
|
||||||
|
err = o.QueryTable(relationship.TableNameWithPrefix()).Filter("book_id",book.BookId).Filter("member_id",member_id).One(relationship)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return m,err
|
||||||
|
}
|
||||||
|
var relationship2 Relationship
|
||||||
|
|
||||||
|
err = o.QueryTable(relationship.TableNameWithPrefix()).Filter("book_id",book.BookId).Filter("role_id",0).One(&relationship2)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return m,ErrPermissionDenied
|
||||||
|
}
|
||||||
|
|
||||||
|
member := NewMember()
|
||||||
|
|
||||||
|
err = member.Find(relationship2.MemberId)
|
||||||
|
if err != nil {
|
||||||
|
return m,err
|
||||||
|
}
|
||||||
|
|
||||||
|
m.BookId = book.BookId
|
||||||
|
m.BookName = book.BookName
|
||||||
|
m.Identify = book.Identify
|
||||||
|
m.OrderIndex = book.OrderIndex
|
||||||
|
m.Description = strings.Replace(book.Description,"\r\n","<br/>",-1)
|
||||||
|
m.PrivatelyOwned = book.PrivatelyOwned
|
||||||
|
m.PrivateToken = book.PrivateToken
|
||||||
|
m.DocCount = book.DocCount
|
||||||
|
m.CommentStatus = book.CommentStatus
|
||||||
|
m.CommentCount = book.CommentCount
|
||||||
|
m.CreateTime = book.CreateTime
|
||||||
|
m.CreateName = member.Account
|
||||||
|
m.ModifyTime = book.ModifyTime
|
||||||
|
m.Cover = book.Cover
|
||||||
|
m.Label = book.Label
|
||||||
|
|
||||||
|
m.MemberId = relationship.MemberId
|
||||||
|
m.RoleId = relationship.RoleId
|
||||||
|
|
||||||
|
if m.RoleId == 0{
|
||||||
|
m.RoleName = "创始人"
|
||||||
|
}else if m.RoleId == 1 {
|
||||||
|
m.RoleName = "管理员"
|
||||||
|
}else if m.RoleId == 2 {
|
||||||
|
m.RoleName = "编辑者"
|
||||||
|
}else if m.RoleId == 2 {
|
||||||
|
m.RoleName = "观察者"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
doc := NewDocument()
|
||||||
|
|
||||||
|
err = o.QueryTable(doc.TableNameWithPrefix()).Filter("book_id",book.BookId).OrderBy("modify_time").One(doc)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
member2 := NewMember()
|
||||||
|
member2.Find(doc.ModifyAt)
|
||||||
|
|
||||||
|
m.LastModifyText = member2.Account + " 于 " + doc.ModifyTime.Format("2006-01-02 15:04:05")
|
||||||
|
}
|
||||||
|
|
||||||
|
return m,nil
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"time"
|
||||||
|
"github.com/lifei6671/godoc/conf"
|
||||||
|
)
|
||||||
|
|
||||||
// Document struct.
|
// Document struct.
|
||||||
type Document struct {
|
type Document struct {
|
||||||
|
@ -32,3 +35,30 @@ func (m *Document) TableName() string {
|
||||||
func (m *Document) TableEngine() string {
|
func (m *Document) TableEngine() string {
|
||||||
return "INNODB"
|
return "INNODB"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Document) TableNameWithPrefix() string {
|
||||||
|
return conf.GetDatabasePrefix() + m.TableName()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDocument() *Document {
|
||||||
|
return &Document{}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,4 +13,6 @@ var(
|
||||||
|
|
||||||
// ErrInvalidParameter 参数错误.
|
// ErrInvalidParameter 参数错误.
|
||||||
ErrInvalidParameter = errors.New("Invalid parameter")
|
ErrInvalidParameter = errors.New("Invalid parameter")
|
||||||
|
|
||||||
|
ErrPermissionDenied = errors.New("Permission denied")
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
"github.com/astaxie/beego/orm"
|
"github.com/astaxie/beego/orm"
|
||||||
"github.com/lifei6671/godoc/utils"
|
"github.com/lifei6671/godoc/utils"
|
||||||
|
"github.com/lifei6671/godoc/conf"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Member struct {
|
type Member struct {
|
||||||
|
@ -31,6 +32,10 @@ func (m *Member) TableEngine() string {
|
||||||
return "INNODB"
|
return "INNODB"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Member)TableNameWithPrefix() string {
|
||||||
|
return conf.GetDatabasePrefix() + m.TableName()
|
||||||
|
}
|
||||||
|
|
||||||
func NewMember() *Member {
|
func NewMember() *Member {
|
||||||
return &Member{}
|
return &Member{}
|
||||||
}
|
}
|
||||||
|
@ -95,3 +100,32 @@ func (m *Member) Find(id int) error{
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Member) FindByAccount (account string) error {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
err := o.QueryTable(m.TableNameWithPrefix()).Filter("account",account).One(m)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
"github.com/astaxie/beego/orm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MemberRelationshipResult struct {
|
||||||
|
MemberId int `json:"member_id"`
|
||||||
|
Account string `json:"account"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Avatar string `json:"avatar"`
|
||||||
|
Role int `json:"role"` //用户角色:0 管理员/ 1 普通用户
|
||||||
|
Status int `json:"status"` //用户状态:0 正常/1 禁用
|
||||||
|
CreateTime time.Time `json:"create_time"`
|
||||||
|
CreateAt int `json:"create_at"`
|
||||||
|
RelationshipId int `json:"relationship_id"`
|
||||||
|
BookId int `json:"book_id"`
|
||||||
|
// RoleId 角色:0 创始人(创始人不能被移除) / 1 管理员/2 编辑者/3 观察者
|
||||||
|
RoleId int `json:"role_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMemberRelationshipResult() *MemberRelationshipResult {
|
||||||
|
return &MemberRelationshipResult{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MemberRelationshipResult) FindForUsersByBookId(book_id ,pageIndex, pageSize int) ([]MemberRelationshipResult,int,error) {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
var members []MemberRelationshipResult
|
||||||
|
|
||||||
|
sql1 := "SELECT * FROM md_relationship AS rel LEFT JOIN md_members as member ON rel.member_id = member.member_id WHERE rel.book_id = ? ORDER BY rel.relationship_id DESC LIMIT ?,?"
|
||||||
|
|
||||||
|
sql2 := "SELECT count(*) AS total_count FROM md_relationship AS rel LEFT JOIN md_members as member ON rel.member_id = member.member_id WHERE rel.book_id = ?"
|
||||||
|
|
||||||
|
var total_count int
|
||||||
|
|
||||||
|
err := o.Raw(sql2,book_id).QueryRow(&total_count)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return members,0,err
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := (pageIndex-1) * pageSize
|
||||||
|
|
||||||
|
_,err = o.Raw(sql1,book_id,offset,pageSize).QueryRows(&members)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return members,0,err
|
||||||
|
}
|
||||||
|
|
||||||
|
return members,total_count,nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lifei6671/godoc/conf"
|
||||||
|
"github.com/astaxie/beego/orm"
|
||||||
|
)
|
||||||
|
|
||||||
type Relationship struct {
|
type Relationship struct {
|
||||||
RelationshipId int `orm:"pk;auto;unique;column(relationship_id)" json:"relationship_id"`
|
RelationshipId int `orm:"pk;auto;unique;column(relationship_id)" json:"relationship_id"`
|
||||||
MemberId int `orm:"column(member_id);type(int)" json:"member_id"`
|
MemberId int `orm:"column(member_id);type(int)" json:"member_id"`
|
||||||
|
@ -13,6 +18,10 @@ type Relationship struct {
|
||||||
func (m *Relationship) TableName() string {
|
func (m *Relationship) TableName() string {
|
||||||
return "relationship"
|
return "relationship"
|
||||||
}
|
}
|
||||||
|
func (m *Relationship) TableNameWithPrefix() string {
|
||||||
|
return conf.GetDatabasePrefix() + m.TableName()
|
||||||
|
}
|
||||||
|
|
||||||
// TableEngine 获取数据使用的引擎.
|
// TableEngine 获取数据使用的引擎.
|
||||||
func (m *Relationship) TableEngine() string {
|
func (m *Relationship) TableEngine() string {
|
||||||
return "INNODB"
|
return "INNODB"
|
||||||
|
@ -24,3 +33,39 @@ func (u *Relationship) TableUnique() [][]string {
|
||||||
[]string{"MemberId", "BookId"},
|
[]string{"MemberId", "BookId"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewRelationship() *Relationship {
|
||||||
|
return &Relationship{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Relationship) FindForRoleId(book_id ,member_id int) (int,error) {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
relationship := NewRelationship()
|
||||||
|
|
||||||
|
err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id",book_id).Filter("member_id",member_id).One(relationship)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0,err
|
||||||
|
}
|
||||||
|
return relationship.RoleId,nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Relationship) Insert() error {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
_,err := o.Insert(m)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Relationship) Update() error {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
_,err := o.Update(m)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,9 @@ func init() {
|
||||||
beego.Router("/book/:key/dashboard", &controllers.BookController{},"*:Dashboard")
|
beego.Router("/book/:key/dashboard", &controllers.BookController{},"*:Dashboard")
|
||||||
beego.Router("/book/:key/setting", &controllers.BookController{},"*:Setting")
|
beego.Router("/book/:key/setting", &controllers.BookController{},"*:Setting")
|
||||||
beego.Router("/book/:key/users", &controllers.BookController{},"*:Users")
|
beego.Router("/book/:key/users", &controllers.BookController{},"*:Users")
|
||||||
beego.Router("/book/:key/edit/:id", &controllers.BookController{},"*:Edit")
|
beego.Router("/book/:key/edit", &controllers.BookController{},"*:Edit")
|
||||||
beego.Router("/book/create", &controllers.BookController{},"*:Create")
|
beego.Router("/book/create", &controllers.BookController{},"*:Create")
|
||||||
|
beego.Router("/book/member/create", &controllers.BookController{},"POST:AddMember")
|
||||||
|
|
||||||
beego.Router("/book/:key/users/create", &controllers.BookMemberController{},"*:Create")
|
beego.Router("/book/:key/users/create", &controllers.BookMemberController{},"*:Create")
|
||||||
beego.Router("/book/:key/users/change", &controllers.BookMemberController{},"*:Change")
|
beego.Router("/book/:key/users/change", &controllers.BookMemberController{},"*:Change")
|
||||||
|
|
|
@ -11,3 +11,24 @@ function showSuccess($msg) {
|
||||||
$("#form-error-message").addClass("success-message").removeClass("error-message").text($msg);
|
$("#form-error-message").addClass("success-message").removeClass("error-message").text($msg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Date.prototype.format = function(fmt) {
|
||||||
|
var o = {
|
||||||
|
"M+" : this.getMonth()+1, //月份
|
||||||
|
"d+" : this.getDate(), //日
|
||||||
|
"h+" : this.getHours(), //小时
|
||||||
|
"m+" : this.getMinutes(), //分
|
||||||
|
"s+" : this.getSeconds(), //秒
|
||||||
|
"q+" : Math.floor((this.getMonth()+3)/3), //季度
|
||||||
|
"S" : this.getMilliseconds() //毫秒
|
||||||
|
};
|
||||||
|
if(/(y+)/.test(fmt)) {
|
||||||
|
fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
|
||||||
|
}
|
||||||
|
for(var k in o) {
|
||||||
|
if(new RegExp("("+ k +")").test(fmt)){
|
||||||
|
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt;
|
||||||
|
};
|
|
@ -0,0 +1,332 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
// "fmt"
|
||||||
|
html "html/template"
|
||||||
|
con "strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/orm"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PageOptions struct {
|
||||||
|
TableName string //表名 -----------------[必填]
|
||||||
|
Conditions string //条件
|
||||||
|
CurrentPage int //当前页 ,默认1 每次分页,必须在前台设置新的页数,不设置始终默认1.在控制器中使用方式:cp, _ := this.GetInt("pno") po.CurrentPage = int(cp)
|
||||||
|
PageSize int //页面大小,默认20
|
||||||
|
LinkItemCount int //生成A标签的个数 默认10个
|
||||||
|
Href string //A标签的链接地址 ---------[不需要设置]
|
||||||
|
ParamName string //参数名称 默认是pno
|
||||||
|
FirstPageText string //首页文字 默认"首页"
|
||||||
|
LastPageText string //尾页文字 默认"尾页"
|
||||||
|
PrePageText string //上一页文字 默认"上一页"
|
||||||
|
NextPageText string //下一页文字 默认"下一页"
|
||||||
|
EnableFirstLastLink bool //是否启用首尾连接 默认false 建议开启
|
||||||
|
EnablePreNexLink bool //是否启用上一页,下一页连接 默认false 建议开启
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页函数,适用任何表
|
||||||
|
* 返回 总记录条数,总页数,以及当前请求的数据RawSeter,调用中需要"rs.QueryRows(&tblog)"就行了 --tblog是一个Tb_log对象
|
||||||
|
* 参数:表名,当前页数,页面大小,条件(查询条件,格式为 " and name='zhifeiya' and age=12 ")
|
||||||
|
*/
|
||||||
|
func GetPagesInfo(tableName string, currentpage int, pagesize int, conditions string) (int, int, orm.RawSeter) {
|
||||||
|
if currentpage <= 1 {
|
||||||
|
currentpage = 1
|
||||||
|
}
|
||||||
|
if pagesize == 0 {
|
||||||
|
pagesize = 20
|
||||||
|
}
|
||||||
|
var rs orm.RawSeter
|
||||||
|
o := orm.NewOrm()
|
||||||
|
var totalItem, totalpages int = 0, 0 //总条数,总页数
|
||||||
|
o.Raw("SELECT count(*) FROM " + tableName + " where 1 > 0 " + conditions).QueryRow(&totalItem) //获取总条数
|
||||||
|
if totalItem <= pagesize {
|
||||||
|
totalpages = 1
|
||||||
|
} else if totalItem > pagesize {
|
||||||
|
temp := totalItem / pagesize
|
||||||
|
if (totalItem % pagesize) != 0 {
|
||||||
|
temp = temp + 1
|
||||||
|
}
|
||||||
|
totalpages = temp
|
||||||
|
}
|
||||||
|
rs = o.Raw("select * from " + tableName + " where 1 > 0 " + conditions + " LIMIT " + con.Itoa((currentpage-1)*pagesize) + "," + con.Itoa(pagesize))
|
||||||
|
return totalItem, totalpages, rs
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回总记录条数,总页数,当前页面数据,分页html
|
||||||
|
* 根据分页选项,生成分页连接 下面是一个实例:
|
||||||
|
func (this *MainController) Test() {
|
||||||
|
var po util.PageOptions
|
||||||
|
po.EnablePreNexLink = true
|
||||||
|
po.EnableFirstLastLink = true
|
||||||
|
po.LinkItemCount = 7
|
||||||
|
po.TableName = "help_topic"
|
||||||
|
cp, _ := this.GetInt("pno")
|
||||||
|
po.CurrentPage = int(cp)
|
||||||
|
_,_,_ pager := util.GetPagerLinks(&po, this.Ctx)
|
||||||
|
this.Data["Email"] = html.HTML(pager)
|
||||||
|
this.TplName = "test.html"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
func GetPagerLinks(po *PageOptions,requestURI string) (int, int, orm.RawSeter, html.HTML) {
|
||||||
|
str := ""
|
||||||
|
totalItem, totalpages, rs := GetPagesInfo(po.TableName, po.CurrentPage, po.PageSize, po.Conditions)
|
||||||
|
po = setDefault(po, totalpages)
|
||||||
|
DealUri(po, requestURI)
|
||||||
|
if totalpages <= po.LinkItemCount {
|
||||||
|
str = fun1(po, totalpages) //显示完全 12345678910
|
||||||
|
} else if totalpages > po.LinkItemCount {
|
||||||
|
if po.CurrentPage < po.LinkItemCount {
|
||||||
|
str = fun2(po, totalpages) //123456789...200
|
||||||
|
} else {
|
||||||
|
if po.CurrentPage + po.LinkItemCount < totalpages {
|
||||||
|
str = fun3(po, totalpages)
|
||||||
|
} else {
|
||||||
|
str = fun4(po, totalpages)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return totalItem, totalpages, rs, html.HTML(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPagerHtml(requestURI string,pageIndex, pageSize,totalCount int) (html.HTML){
|
||||||
|
po := &PageOptions{
|
||||||
|
CurrentPage: pageIndex,
|
||||||
|
PageSize: pageSize,
|
||||||
|
EnableFirstLastLink : true,
|
||||||
|
ParamName : "page",
|
||||||
|
}
|
||||||
|
setDefault(po,totalCount)
|
||||||
|
DealUri(po,requestURI)
|
||||||
|
str := ""
|
||||||
|
if totalCount <= po.LinkItemCount {
|
||||||
|
str = fun1(po, totalCount) //显示完全 12345678910
|
||||||
|
} else if totalCount > po.LinkItemCount {
|
||||||
|
if po.CurrentPage < po.LinkItemCount {
|
||||||
|
str = fun2(po, totalCount) //123456789...200
|
||||||
|
} else {
|
||||||
|
if po.CurrentPage + po.LinkItemCount < totalCount {
|
||||||
|
str = fun3(po, totalCount)
|
||||||
|
} else {
|
||||||
|
str = fun4(po, totalCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str = strings.Replace(str,"?&","?",-1)
|
||||||
|
//str = strings.Replace(str,"&&","&",-1)
|
||||||
|
return html.HTML(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理url,目的是保存参数
|
||||||
|
*/
|
||||||
|
func DealUri(po *PageOptions, requestURI string) {
|
||||||
|
var rs string
|
||||||
|
if strings.Contains(requestURI, "?") {
|
||||||
|
arr := strings.Split(requestURI, "?")
|
||||||
|
rs = ""
|
||||||
|
arr2 := strings.Split(arr[1], "&")
|
||||||
|
for _, v := range arr2 {
|
||||||
|
if !strings.Contains(v, po.ParamName) {
|
||||||
|
if strings.HasSuffix(rs,"&") {
|
||||||
|
rs += v
|
||||||
|
}else{
|
||||||
|
rs += v + "&"
|
||||||
|
}
|
||||||
|
//rs += "&" + v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(rs,"&") {
|
||||||
|
rs = string(rs[1:])
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(rs,"&"){
|
||||||
|
rs = string(rs[0:strings.Count(rs,"")-1])
|
||||||
|
}
|
||||||
|
rs = arr[0] + "?" + rs
|
||||||
|
fmt.Println(rs)
|
||||||
|
} else {
|
||||||
|
//rs = requestURI + "?" //+ po.ParamName + "time=" + con.Itoa(time.Now().Second())
|
||||||
|
rs = requestURI + "?"
|
||||||
|
}
|
||||||
|
|
||||||
|
po.Href = rs
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1...197 198 199 200
|
||||||
|
*/
|
||||||
|
func fun4(po *PageOptions, totalPages int) string {
|
||||||
|
rs := ""
|
||||||
|
rs += getHeader(po, totalPages)
|
||||||
|
rs += "<li><a href='" + po.Href + "&" + po.ParamName + "=" + con.Itoa(1) + "'>" + con.Itoa(1) + "</a><li>"
|
||||||
|
rs += "<li><a href=''>...</a></li>"
|
||||||
|
for i := totalPages - po.LinkItemCount; i <= totalPages; i++ {
|
||||||
|
if po.CurrentPage != i {
|
||||||
|
rs += "<li><a href='" + po.Href + "&" + po.ParamName + "=" + con.Itoa(i) + "'>" + con.Itoa(i) + "</a></li>"
|
||||||
|
} else {
|
||||||
|
rs += "<li class=\"active\"><a href=\"###\">" + con.Itoa(i) + " <span class=\"sr-only\">(current)</span></a></li>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rs += getFooter(po, totalPages)
|
||||||
|
return rs
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1...6 7 8 9 10 11 12 13 14 15... 200
|
||||||
|
*/
|
||||||
|
func fun3(po *PageOptions, totalpages int) string {
|
||||||
|
var rs string = ""
|
||||||
|
rs += getHeader(po, totalpages)
|
||||||
|
rs += "<li><a href='" + po.Href + "&" + po.ParamName + "=" + con.Itoa(1) + "'>" + con.Itoa(1) + "</a></li>"
|
||||||
|
rs += "<a href=''>...</a>"
|
||||||
|
for i := po.CurrentPage - po.LinkItemCount/2 + 1; i <= po.CurrentPage+po.LinkItemCount/2-1; i++ {
|
||||||
|
if po.CurrentPage != i {
|
||||||
|
rs += "<a href='" + po.Href + "&" + po.ParamName + "=" + con.Itoa(i) + "'>" + con.Itoa(i) + "</a>"
|
||||||
|
} else {
|
||||||
|
rs += "<li class=\"active\"><a href=\"###\">" + con.Itoa(i) + " <span class=\"sr-only\">(current)</span></a></li>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rs += "<a href=''>...</a>"
|
||||||
|
rs += "<li><a href='" + po.Href + "&" + po.ParamName + "=" + con.Itoa(totalpages) + "'>" + con.Itoa(totalpages) + "</a></li>"
|
||||||
|
rs += getFooter(po, totalpages)
|
||||||
|
return rs
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* totalpages > po.LinkItemCount po.CurrentPage < po.LinkItemCount
|
||||||
|
* 123456789...200
|
||||||
|
*/
|
||||||
|
func fun2(po *PageOptions, totalpages int) string {
|
||||||
|
var rs string = ""
|
||||||
|
rs += getHeader(po, totalpages)
|
||||||
|
for i := 1; i <= po.LinkItemCount+1; i++ {
|
||||||
|
if i == po.LinkItemCount {
|
||||||
|
rs += "<li><a href=\"" + po.Href + "&" + po.ParamName + "=" + con.Itoa(i) + "\">...</a></li>"
|
||||||
|
} else if i == po.LinkItemCount+1 {
|
||||||
|
rs += "<li><a href=\"" + po.Href + "&" + po.ParamName + "=" + con.Itoa(totalpages) + "\">" + con.Itoa(totalpages) + "</a></li>"
|
||||||
|
} else {
|
||||||
|
if po.CurrentPage != i {
|
||||||
|
rs += "<li><a href='" + po.Href + "&" + po.ParamName + "=" + con.Itoa(i) + "'>" + con.Itoa(i) + "</a></li>"
|
||||||
|
} else {
|
||||||
|
rs += "<li class=\"active\"><a href=\"###\">" + con.Itoa(i) + " <span class=\"sr-only\">(current)</span></a></li>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rs += getFooter(po, totalpages)
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* totalpages <= po.LinkItemCount
|
||||||
|
* 显示完全 12345678910
|
||||||
|
*/
|
||||||
|
func fun1(po *PageOptions, totalpages int) string {
|
||||||
|
|
||||||
|
var rs string = ""
|
||||||
|
rs += getHeader(po, totalpages)
|
||||||
|
for i := 1; i <= totalpages; i++ {
|
||||||
|
if po.CurrentPage != i {
|
||||||
|
|
||||||
|
rs += "<li><a href='" + po.Href + "&" + po.ParamName + "=" + con.Itoa(i) + "'>" + con.Itoa(i) + "</a></li>"
|
||||||
|
} else {
|
||||||
|
rs += "<li class=\"active\"><a href=\"###\">" + con.Itoa(i) + " <span class=\"sr-only\">(current)</span></a></li>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rs += getFooter(po, totalpages)
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 头部
|
||||||
|
*/
|
||||||
|
func getHeader(po *PageOptions, totalpages int) string {
|
||||||
|
var rs string = "<ul class=\"pagination\">"
|
||||||
|
if po.EnableFirstLastLink { //当首页,尾页都设定的时候,就显示
|
||||||
|
|
||||||
|
rs += "<li" + judgeDisable(po, totalpages, 0) + " ><a href='" + po.Href + "&" + po.ParamName + "=" + con.Itoa(1) + "'>" + po.FirstPageText + "</a></li>"
|
||||||
|
}
|
||||||
|
if po.EnablePreNexLink { // disabled=\"disabled\"
|
||||||
|
var a int = po.CurrentPage - 1
|
||||||
|
if po.CurrentPage == 1 {
|
||||||
|
a = 1
|
||||||
|
}
|
||||||
|
rs += "<li" + judgeDisable(po, totalpages, 0) + " ><a href='" + po.Href + "&" + po.ParamName + "=" + con.Itoa(a) + "'>" + po.PrePageText + "</a></li>"
|
||||||
|
}
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尾部
|
||||||
|
*/
|
||||||
|
func getFooter(po *PageOptions, totalpages int) string {
|
||||||
|
var rs string = ""
|
||||||
|
if po.EnablePreNexLink {
|
||||||
|
var a int = po.CurrentPage + 1
|
||||||
|
if po.CurrentPage == totalpages {
|
||||||
|
a = totalpages
|
||||||
|
}
|
||||||
|
rs += "<li " + judgeDisable(po, totalpages, 1) + " ><a href='" + po.Href + "&" + po.ParamName + "=" + con.Itoa(a) + "'>" + po.NextPageText + "</a></li>"
|
||||||
|
}
|
||||||
|
if po.EnableFirstLastLink { //当首页,尾页都设定的时候,就显示
|
||||||
|
rs += "<li " + judgeDisable(po, totalpages, 1) + " ><a href='" + po.Href + "&" + po.ParamName + "=" + con.Itoa(totalpages) + "'>" + po.LastPageText + "</a></li>"
|
||||||
|
}
|
||||||
|
rs += "</ul>"
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置默认值
|
||||||
|
*/
|
||||||
|
func setDefault(po *PageOptions, totalpages int) *PageOptions {
|
||||||
|
if len(po.FirstPageText) <= 0 {
|
||||||
|
po.FirstPageText = "首页"
|
||||||
|
}
|
||||||
|
if len(po.LastPageText) <= 0 {
|
||||||
|
po.LastPageText = "尾页"
|
||||||
|
}
|
||||||
|
if len(po.PrePageText) <= 0 {
|
||||||
|
po.PrePageText = "上一页"
|
||||||
|
}
|
||||||
|
if len(po.NextPageText) <= 0 {
|
||||||
|
po.NextPageText = "下一页"
|
||||||
|
}
|
||||||
|
if po.CurrentPage >= totalpages {
|
||||||
|
po.CurrentPage = totalpages
|
||||||
|
}
|
||||||
|
if po.CurrentPage <= 1 {
|
||||||
|
po.CurrentPage = 1
|
||||||
|
}
|
||||||
|
if po.LinkItemCount == 0 {
|
||||||
|
po.LinkItemCount = 10
|
||||||
|
}
|
||||||
|
if po.PageSize == 0 {
|
||||||
|
po.PageSize = 20
|
||||||
|
}
|
||||||
|
if len(po.ParamName) <= 0 {
|
||||||
|
po.ParamName = "pno"
|
||||||
|
}
|
||||||
|
return po
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*判断首页尾页 上一页下一页是否能用
|
||||||
|
*/
|
||||||
|
func judgeDisable(po *PageOptions, totalpages int, h_f int) string {
|
||||||
|
var rs string = ""
|
||||||
|
//判断头部
|
||||||
|
if h_f == 0 {
|
||||||
|
if po.CurrentPage == 1 {
|
||||||
|
rs = " "
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if po.CurrentPage == totalpages {
|
||||||
|
rs = " "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rs
|
||||||
|
}
|
|
@ -26,53 +26,63 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="page-left">
|
<div class="page-left">
|
||||||
<ul class="menu">
|
<ul class="menu">
|
||||||
<li class="active"><a href="{{urlfor "BookController.Dashboard" ":key" "test"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 概要</a> </li>
|
<li class="active"><a href="{{urlfor "BookController.Dashboard" ":key" .Model.Identify}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 概要</a> </li>
|
||||||
<li><a href="{{urlfor "BookController.Users" ":key" "test"}}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 成员</a> </li>
|
<li><a href="{{urlfor "BookController.Users" ":key" .Model.Identify}}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 成员</a> </li>
|
||||||
<li><a href="{{urlfor "BookController.Setting" ":key" "test"}}" class="item"><i class="fa fa-gear" aria-hidden="true"></i> 设置</a> </li>
|
<li><a href="{{urlfor "BookController.Setting" ":key" .Model.Identify}}" class="item"><i class="fa fa-gear" aria-hidden="true"></i> 设置</a> </li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="page-right">
|
<div class="page-right">
|
||||||
<div class="m-box">
|
<div class="m-box">
|
||||||
<div class="box-head">
|
<div class="box-head">
|
||||||
<strong class="box-title"><i class="fa fa-unlock" aria-hidden="true" title="公开项目" data-toggle="tooltip"></i> 这是一个测试项目</strong>
|
<strong class="box-title">
|
||||||
<a href="{{urlfor "BookController.Edit" ":key" "test" ":id" "1"}}" class="btn btn-default btn-sm pull-right" target="_blank"><i class="fa fa-edit" aria-hidden="true"></i> 编辑</a>
|
{{if eq .Model.PrivatelyOwned 0}}
|
||||||
<a href="{{urlfor "DocumentController.Index" ":key" "test"}}" class="btn btn-default btn-sm pull-right" style="margin-right: 5px;" target="_blank"><i class="fa fa-eye"></i> 阅读</a>
|
<i class="fa fa-unlock" aria-hidden="true" title="公开项目" data-toggle="tooltip"></i>
|
||||||
<a href="{{urlfor "DocumentController.Index" ":key" "test"}}" class="btn btn-default btn-sm pull-right" style="margin-right: 5px;" target="_blank"><i class="fa fa-upload" aria-hidden="true"></i> 发布</a>
|
{{else}}
|
||||||
|
<i class="fa fa-lock" aria-hidden="true" title="私有项目" data-toggle="tooltip"></i>
|
||||||
|
{{end}}
|
||||||
|
{{.Model.BookName}}
|
||||||
|
</strong>
|
||||||
|
{{if ne .Model.RoleId 3}}
|
||||||
|
<a href="{{urlfor "BookController.Edit" ":key" .Model.Identify ":id" .Model.BookId}}" class="btn btn-default btn-sm pull-right" target="_blank"><i class="fa fa-edit" aria-hidden="true"></i> 编辑</a>
|
||||||
|
<a href="{{urlfor "DocumentController.Index" ":key" .Model.Identify}}" class="btn btn-default btn-sm pull-right" style="margin-right: 5px;" target="_blank"><i class="fa fa-eye"></i> 阅读</a>
|
||||||
|
<a href="{{urlfor "DocumentController.Index" ":key" .Model.Identify}}" class="btn btn-default btn-sm pull-right" style="margin-right: 5px;" target="_blank"><i class="fa fa-upload" aria-hidden="true"></i> 发布</a>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<div class="dashboard">
|
<div class="dashboard">
|
||||||
<div class="pull-left" style="width: 200px;margin-bottom: 15px;">
|
<div class="pull-left" style="width: 200px;margin-bottom: 15px;">
|
||||||
<div class="book-image">
|
<div class="book-image">
|
||||||
<img src="/static/images/5fcb811e04c23cdb2088f26923fcc287_100.jpg">
|
<img src="{{.Model.Cover}}" onerror="this.src='/static/images/book.jpg'" width="174" height="229" style="border: 1px solid #666">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<span class="title">创建者:</span>
|
<span class="title">创建者:</span>
|
||||||
<span class="body">
|
<span class="body">{{.Model.CreateName}}</span>
|
||||||
Minho
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<span class="title">文档数量:</span>
|
<span class="title">文档数量:</span>
|
||||||
<span class="body">20</span>
|
<span class="body">{{.Model.DocCount}} 篇</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<span class="title">创建时间:</span>
|
<span class="title">创建时间:</span>
|
||||||
<span class="body"> 2017-05-25 12:25:45 </span>
|
<span class="body"> {{date .Model.CreateTime "Y-m-d H:i:s"}} </span>
|
||||||
</div>
|
</div>
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<span class="title">修改时间:</span>
|
<span class="title">修改时间:</span>
|
||||||
<span class="body"> 2017-05-25 12:25:45 </span>
|
<span class="body"> {{date .Model.ModifyTime "Y-m-d H:i:s"}} </span>
|
||||||
</div>
|
</div>
|
||||||
<div class="summary">《TCP/IP详解,卷1:协议》是一本完整而详细的TCP/IP协议指南。描述了属于每一层的各个协议以及它们如何在不同操作系统中运行。<br>
|
<div class="list">
|
||||||
<br>
|
<span class="title">担任角色:</span>
|
||||||
作者用Lawrence Berkeley实验室的tcpdump程序来捕获不同操作系统和TCP/IP实现之间传输的不同分组。对tcpdump输出的研究可以帮助理解不同协议如何工作。 <br>
|
<span class="body">{{.Model.RoleName}}</span>
|
||||||
<br>
|
|
||||||
本书适合作为计算机专业学生学习网络的教材和教师参考书。也适用于研究网络的技术人员。
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="list">
|
||||||
|
<span class="title">评论数量:</span>
|
||||||
|
<span class="body">{{.Model.CommentCount}} 条</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary">{{.Model.Description}} </div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -37,35 +37,54 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<div class="book-list">
|
<div class="book-list" id="bookList">
|
||||||
<div class="list-item">
|
<template v-if="lists.length <= 0">
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
|
||||||
|
<div class="list-item" v-for="item in lists">
|
||||||
<div class="book-title">
|
<div class="book-title">
|
||||||
<div class="pull-left">
|
<div class="pull-left">
|
||||||
<a href="{{urlfor "BookController.Dashboard" ":key" "test"}}" title="项目概要" data-toggle="tooltip">
|
<a :href="'/book/' + item.identify + '/dashboard'" title="项目概要" data-toggle="tooltip">
|
||||||
<i class="fa fa-unlock" aria-hidden="true"></i> 测试项目
|
<i class="fa fa-unlock" aria-hidden="true"></i> ${item.book_name}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<a href="{{urlfor "DocumentController.Index" ":key" "test"}}" title="查看文档" data-toggle="tooltip"><i class="fa fa-eye"></i> 查看文档</a>
|
<a :href="'{{urlfor "DocumentController.Index" ":key" ""}}' + item.identify" title="查看文档" data-toggle="tooltip"><i class="fa fa-eye"></i> 查看文档</a>
|
||||||
<a href="{{urlfor "BookController.Edit" ":key" "test" ":id" "1"}}" title="编辑文档" data-toggle="tooltip"><i class="fa fa-edit" aria-hidden="true"></i> 编辑文档</a>
|
<a :href="'/book/' + item.identify + '/edit'" title="编辑文档" data-toggle="tooltip"><i class="fa fa-edit" aria-hidden="true"></i> 编辑文档</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="desc-text">
|
<div class="desc-text">
|
||||||
<a href="{{urlfor "BookController.Dashboard" ":key" "test"}}" title="项目概要" style="font-size: 12px;" target="_blank">
|
<template v-if="item.description === ''">
|
||||||
这是一个测试用户测试项目
|
|
||||||
|
</template>
|
||||||
|
<template v-else="">
|
||||||
|
<a :href="'/book/' + item.identify + '/dashboard'" title="项目概要" style="font-size: 12px;" target="_blank">
|
||||||
|
${item.description}
|
||||||
</a>
|
</a>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<span title="创建时间" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-clock-o"></i> 2016/11/27 06:09</span>
|
<span title="创建时间" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-clock-o"></i>
|
||||||
<span title="创建者" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-user"></i> admin</span>
|
${(new Date(item.create_time)).format("yyyy-MM-dd hh:mm:ss")}
|
||||||
<span title="文档数量" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pie-chart"></i> 4</span>
|
|
||||||
<span title="项目角色" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-user-secret"></i> 拥有者</span>
|
</span>
|
||||||
<span title="最后编辑" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pencil"></i> 最后编辑: admin 于 2017-04-20 12:19</span>
|
<span title="创建者" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-user"></i> ${item.create_name}</span>
|
||||||
|
<span title="文档数量" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pie-chart"></i> ${item.doc_count}</span>
|
||||||
|
<span title="项目角色" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-user-secret"></i>${item.role_name}</span>
|
||||||
|
<template v-if="item.last_modify_text !== ''">
|
||||||
|
<span title="最后编辑" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pencil"></i> 最后编辑: ${item.last_modify_text}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
<nav>
|
||||||
|
{{.PageHtml}}
|
||||||
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -91,7 +110,7 @@
|
||||||
</div>
|
</div>
|
||||||
<input type="text" class="form-control pull-left" style="width: 220px;vertical-align: middle" placeholder="项目唯一标识(不能超过50字)" name="identify" id="identify">
|
<input type="text" class="form-control pull-left" style="width: 220px;vertical-align: middle" placeholder="项目唯一标识(不能超过50字)" name="identify" id="identify">
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
<p class="text" style="font-size: 12px;color: #999;margin-top: 6px;">文档标识只能包含小写字母、数字,以及“-”和“_”符号,并且只能小写字母打头</p>
|
<p class="text" style="font-size: 12px;color: #999;margin-top: 6px;">文档标识只能包含小写字母、数字,以及“-”和“_”符号,并且只能小写字母开头</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -118,12 +137,12 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3">
|
<div class="col-lg-3">
|
||||||
<label>
|
<label>
|
||||||
<input type="radio" name="comment_status" value="">关闭评论<span class="text"></span>
|
<input type="radio" name="comment_status" value="closed">关闭评论<span class="text"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3">
|
<div class="col-lg-3">
|
||||||
<label>
|
<label>
|
||||||
<input type="radio" name="comment_status" value="">仅允许参与者评论<span class="text"></span>
|
<input type="radio" name="comment_status" value="group_only">仅允许参与者评论<span class="text"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3">
|
<div class="col-lg-3">
|
||||||
|
@ -147,6 +166,7 @@
|
||||||
|
|
||||||
<script src="/static/jquery/1.12.4/jquery.min.js"></script>
|
<script src="/static/jquery/1.12.4/jquery.min.js"></script>
|
||||||
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
|
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<script src="/static/vuejs/vue.min.js" type="text/javascript"></script>
|
||||||
<script src="/static/js/jquery.form.js" type="text/javascript"></script>
|
<script src="/static/js/jquery.form.js" type="text/javascript"></script>
|
||||||
<script src="/static/js/main.js" type="text/javascript"></script>
|
<script src="/static/js/main.js" type="text/javascript"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -176,8 +196,26 @@
|
||||||
return showSuccess("");
|
return showSuccess("");
|
||||||
},
|
},
|
||||||
success : function (res) {
|
success : function (res) {
|
||||||
|
console.log(res)
|
||||||
|
if(res.errcode === 0){
|
||||||
|
|
||||||
|
}else{
|
||||||
|
showError(res.message);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el : "#bookList",
|
||||||
|
data : {
|
||||||
|
lists : {{.Result}}
|
||||||
|
},
|
||||||
|
delimiters : ['${','}'],
|
||||||
|
methods : {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Vue.nextTick(function () {
|
||||||
|
$("[data-toggle='tooltip']").tooltip();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<title>概要 - Powered by MinDoc</title>
|
<title>设置 - Powered by MinDoc</title>
|
||||||
|
|
||||||
<!-- Bootstrap -->
|
<!-- Bootstrap -->
|
||||||
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
@ -26,9 +26,9 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="page-left">
|
<div class="page-left">
|
||||||
<ul class="menu">
|
<ul class="menu">
|
||||||
<li><a href="{{urlfor "BookController.Dashboard" ":key" "test"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 概要</a> </li>
|
<li><a href="{{urlfor "BookController.Dashboard" ":key" .Model.Identify}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 概要</a> </li>
|
||||||
<li><a href="{{urlfor "BookController.Users" ":key" "test"}}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 成员</a> </li>
|
<li><a href="{{urlfor "BookController.Users" ":key" .Model.Identify}}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 成员</a> </li>
|
||||||
<li class="active"><a href="{{urlfor "BookController.Setting" ":key" "test"}}" class="item"><i class="fa fa-gear" aria-hidden="true"></i> 设置</a> </li>
|
<li class="active"><a href="{{urlfor "BookController.Setting" ":key" .Model.Identify}}" class="item"><i class="fa fa-gear" aria-hidden="true"></i> 设置</a> </li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,8 +36,17 @@
|
||||||
<div class="m-box">
|
<div class="m-box">
|
||||||
<div class="box-head">
|
<div class="box-head">
|
||||||
<strong class="box-title"> 项目设置</strong>
|
<strong class="box-title"> 项目设置</strong>
|
||||||
|
{{if eq .Model.RoleId 0 1}}
|
||||||
|
{{if eq .Model.RoleId 0}}
|
||||||
<button type="button" class="btn btn-success btn-sm pull-right">转让项目</button>
|
<button type="button" class="btn btn-success btn-sm pull-right">转让项目</button>
|
||||||
|
{{end}}
|
||||||
<button type="button" class="btn btn-danger btn-sm pull-right" style="margin-right: 5px;">删除项目</button>
|
<button type="button" class="btn btn-danger btn-sm pull-right" style="margin-right: 5px;">删除项目</button>
|
||||||
|
{{end}}
|
||||||
|
{{if eq .Model.PrivatelyOwned 1}}
|
||||||
|
<button type="button" class="btn btn-success btn-sm pull-right" style="margin-right: 5px;">转为公有</button>
|
||||||
|
{{else}}
|
||||||
|
<button type="button" class="btn btn-danger btn-sm pull-right" style="margin-right: 5px;">转为私有</button>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body" style="padding-right: 200px;">
|
<div class="box-body" style="padding-right: 200px;">
|
||||||
|
@ -45,18 +54,68 @@
|
||||||
<form method="post" id="bookEditForm">
|
<form method="post" id="bookEditForm">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>标题</label>
|
<label>标题</label>
|
||||||
<input type="text" class="form-control" placeholder="项目名称">
|
<input type="text" class="form-control" placeholder="项目名称" value="{{.Model.BookName}}">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>标识</label>
|
||||||
|
<input type="text" class="form-control" value=" {{.BaseUrl}}{{urlfor "DocumentController.Index" ":key" .Model.Identify}}" disabled>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>描述</label>
|
||||||
|
<textarea rows="3" class="form-control" name="description" style="height: 90px">{{.Model.Description}}</textarea>
|
||||||
|
<p class="text">描述信息不超过300个字符</p>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>标签</label>
|
||||||
|
<input type="text" class="form-control" placeholder="项目标签" value="{{.Model.Label}}">
|
||||||
|
<p class="text">最多允许添加10个标签,多个标签请用“;”分割</p>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>开启评论</label>
|
||||||
|
<div class="radio">
|
||||||
|
<label class="radio-inline">
|
||||||
|
<input type="radio" {{if eq .Model.CommentStatus "open"}}checked{{end}} name="comment_status" value="open">允许所有人评论<span class="text"></span>
|
||||||
|
</label>
|
||||||
|
<label class="radio-inline">
|
||||||
|
<input type="radio" {{if eq .Model.CommentStatus "closed"}}checked{{end}} name="comment_status" value="closed">关闭评论<span class="text"></span>
|
||||||
|
</label>
|
||||||
|
<label class="radio-inline">
|
||||||
|
<input type="radio" {{if eq .Model.CommentStatus "group_only"}}checked{{end}} name="comment_status" value="group_only">仅允许参与者评论<span class="text"></span>
|
||||||
|
</label>
|
||||||
|
<label class="radio-inline">
|
||||||
|
<input type="radio" {{if eq .Model.CommentStatus "registered_only"}}checked{{end}} name="comment_status" value="registered_only">仅允许注册者评论<span class="text"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{if eq .Model.PrivatelyOwned 1}}
|
||||||
|
<div class="form-group">
|
||||||
|
<label>访问令牌</label>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input type="text" class="form-control" placeholder="访问令牌" readonly>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<button class="btn btn-success btn-sm">重写生成</button>
|
||||||
|
<button class="btn btn-danger btn-sm">删除令牌</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" class="btn btn-success" data-loading-text="保存中...">保存修改</button>
|
||||||
|
<span id="form-error-message" class="error-message"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-right">
|
<div class="form-right">
|
||||||
<label>
|
<label>
|
||||||
<a href="javascript:;" data-toggle="modal" data-target="#upload-logo-panel">
|
<a href="javascript:;" data-toggle="modal" data-target="#upload-logo-panel">
|
||||||
<img src="/static/images/5fcb811e04c23cdb2088f26923fcc287_100.jpg" onerror="this.src='https://wiki.iminho.me/static/images/middle.gif'" alt="头像" style="max-width: 120px;" id="headimgurl">
|
<img src="{{.Model.Cover}}" onerror="this.src='/static/images/book.png'" alt="封面" style="max-width: 120px;border: 1px solid #999" id="headimgurl">
|
||||||
</a>
|
</a>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<title>概要 - Powered by MinDoc</title>
|
<title>成员 - Powered by MinDoc</title>
|
||||||
|
|
||||||
<!-- Bootstrap -->
|
<!-- Bootstrap -->
|
||||||
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
@ -26,9 +26,9 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="page-left">
|
<div class="page-left">
|
||||||
<ul class="menu">
|
<ul class="menu">
|
||||||
<li><a href="{{urlfor "BookController.Dashboard" ":key" "test"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 概要</a> </li>
|
<li><a href="{{urlfor "BookController.Dashboard" ":key" .Model.Identify}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 概要</a> </li>
|
||||||
<li class="active"><a href="{{urlfor "BookController.Users" ":key" "test"}}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 成员</a> </li>
|
<li class="active"><a href="{{urlfor "BookController.Users" ":key" .Model.Identify}}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 成员</a> </li>
|
||||||
<li><a href="{{urlfor "BookController.Setting" ":key" "test"}}" class="item"><i class="fa fa-gear" aria-hidden="true"></i> 设置</a> </li>
|
<li><a href="{{urlfor "BookController.Setting" ":key" .Model.Identify}}" class="item"><i class="fa fa-gear" aria-hidden="true"></i> 设置</a> </li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,37 +36,24 @@
|
||||||
<div class="m-box">
|
<div class="m-box">
|
||||||
<div class="box-head">
|
<div class="box-head">
|
||||||
<strong class="box-title"> 成员管理</strong>
|
<strong class="box-title"> 成员管理</strong>
|
||||||
<a href="{{urlfor "BookController.Edit" ":key" "test" ":id" "1"}}" class="btn btn-success btn-sm pull-right" target="_blank"><i class="fa fa-edit" aria-hidden="true"></i> 添加成员</a>
|
<button type="button" class="btn btn-success btn-sm pull-right" data-toggle="modal" data-target="#addBookMemberDialogModal"><i class="fa fa-user-plus" aria-hidden="true"></i> 添加成员</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<div class="users-list">
|
<div class="users-list" id="userList">
|
||||||
<div class="list-item">
|
<template v-if="lists.length <= 0">
|
||||||
<img src="/static/images/middle.gif" class="img-circle" width="34" height="34">
|
<div class="text-center">暂无数据</div>
|
||||||
<span>lifei6671</span>
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="list-item" v-for="item in lists">
|
||||||
|
<img :src="item.avatar" onerror="this.src='/static/images/middle.gif'" class="img-circle" width="34" height="34">
|
||||||
|
<span>${item.account}</span>
|
||||||
<div class="operate">
|
<div class="operate">
|
||||||
|
<template v-if="item.role_id == 0">
|
||||||
创始人
|
创始人
|
||||||
</div>
|
</template>
|
||||||
</div>
|
<template v-else-if="item.role_id == 1">
|
||||||
<div class="list-item">
|
{{if eq .Member.Role 0}}
|
||||||
<img src="/static/images/middle.gif" class="img-circle" width="34" height="34">
|
|
||||||
<span>lifei6671</span>
|
|
||||||
<div class="operate">
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="button" class="btn btn-default btn-sm" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">编辑者 <span class="caret"></span></button>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<li><a href="#">管理员</a> </li>
|
|
||||||
<li><a href="#">编辑者</a> </li>
|
|
||||||
<li><a href="#">观察者</a> </li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<a href="#" class="btn btn-danger btn-sm">移除</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="list-item">
|
|
||||||
<img src="/static/images/middle.gif" class="img-circle" width="34" height="34">
|
|
||||||
<span>lifei6671</span>
|
|
||||||
<div class="operate">
|
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<button type="button" class="btn btn-default btn-sm" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">编辑者 <span class="caret"></span></button>
|
<button type="button" class="btn btn-default btn-sm" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">编辑者 <span class="caret"></span></button>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
|
@ -76,8 +63,11 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<a href="#" class="btn btn-danger btn-sm">移除</a>
|
<a href="#" class="btn btn-danger btn-sm">移除</a>
|
||||||
|
{{end}}
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -85,9 +75,77 @@
|
||||||
</div>
|
</div>
|
||||||
{{template "widgets/footer.tpl" .}}
|
{{template "widgets/footer.tpl" .}}
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="modal fade" id="addBookMemberDialogModal" tabindex="-1" role="dialog" aria-labelledby="addBookMemberDialogModalLabel">
|
||||||
|
<div class="modal-dialog modal-sm" role="document" style="width: 400px;">
|
||||||
|
<form method="post" autocomplete="off" class="form-horizontal" action="{{urlfor "BookController.AddMember"}}" id="addBookMemberDialogForm">
|
||||||
|
<input type="hidden" name="identify" value="{{.Model.Identify}}">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
|
<h4 class="modal-title" id="myModalLabel">添加成员</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">账号</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="text" name="account" class="form-control" placeholder="用户账号" id="account" maxlength="50">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">角色</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<select name="role_id" class="form-control">
|
||||||
|
<option value="1">管理员</option>
|
||||||
|
<option value="2">编辑者</option>
|
||||||
|
<option value="3">观察者</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<span id="form-error-message"></span>
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
|
||||||
|
<button type="submit" class="btn btn-success">保存</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div><!--END Modal-->
|
||||||
<script src="/static/jquery/1.12.4/jquery.min.js"></script>
|
<script src="/static/jquery/1.12.4/jquery.min.js"></script>
|
||||||
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
|
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<script src="/static/vuejs/vue.min.js"></script>
|
||||||
|
<script src="/static/js/jquery.form.js" type="text/javascript"></script>
|
||||||
<script src="/static/js/main.js" type="text/javascript"></script>
|
<script src="/static/js/main.js" type="text/javascript"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function () {
|
||||||
|
$("#addBookMemberDialogForm").ajaxForm({
|
||||||
|
beforeSubmit : function () {
|
||||||
|
var account = $.trim($("#account").val());
|
||||||
|
if(account === ""){
|
||||||
|
return showError("账号不能为空");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
success : function (res) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el : "#userList",
|
||||||
|
data : {
|
||||||
|
lists : {{.Result}}
|
||||||
|
},
|
||||||
|
delimiters : ['${','}'],
|
||||||
|
methods : {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Vue.nextTick(function () {
|
||||||
|
$("[data-toggle='tooltip']").tooltip();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
Loading…
Reference in New Issue