1、实现通过SSL、TSL发送邮件

2、增加用户真实姓名字段
3、优化项目列表显示
4、实现限定文档历史记录数量
5、优化部分页面的用户体验
This commit is contained in:
Minho 2018-02-02 23:12:29 +08:00
parent 257a758b21
commit c7d83576bd
22 changed files with 176 additions and 71 deletions

View File

@ -60,7 +60,7 @@ mail_number=5
#smtp服务用户名 #smtp服务用户名
smtp_user_name=admin@iminho.me smtp_user_name=admin@iminho.me
#smtp服务器地址 #smtp服务器地址
smtp_host=smtp.ym.163.com smtp_host=smtp.163.com
#smtp密码 #smtp密码
smtp_password= smtp_password=
#端口号 #端口号

View File

@ -132,6 +132,7 @@ func (c *BookController) SaveBook() {
editor := strings.TrimSpace(c.GetString("editor")) editor := strings.TrimSpace(c.GetString("editor"))
autoRelease := strings.TrimSpace(c.GetString("auto_release")) == "on" autoRelease := strings.TrimSpace(c.GetString("auto_release")) == "on"
publisher := strings.TrimSpace(c.GetString("publisher")) publisher := strings.TrimSpace(c.GetString("publisher"))
historyCount,_ := c.GetInt("history_count",0)
if strings.Count(description, "") > 500 { if strings.Count(description, "") > 500 {
c.JsonResult(6004, "项目描述不能大于500字") c.JsonResult(6004, "项目描述不能大于500字")
@ -155,6 +156,8 @@ func (c *BookController) SaveBook() {
book.Publisher = publisher book.Publisher = publisher
book.Label = tag book.Label = tag
book.Editor = editor book.Editor = editor
book.HistoryCount = historyCount
if autoRelease { if autoRelease {
book.AutoRelease = 1 book.AutoRelease = 1
} else { } else {

View File

@ -811,6 +811,7 @@ func (c *DocumentController) Content() {
beego.Error("DocumentHistory InsertOrUpdate => ", err) beego.Error("DocumentHistory InsertOrUpdate => ", err)
} }
} }
//如果启用了自动发布
if auto_release { if auto_release {
go func(identify string) { go func(identify string) {
models.NewDocument().ReleaseContent(book_id) models.NewDocument().ReleaseContent(book_id)

View File

@ -108,6 +108,7 @@ func (c *ManagerController) CreateMember() {
member.Avatar = conf.GetDefaultAvatar() member.Avatar = conf.GetDefaultAvatar()
member.CreateAt = c.Member.MemberId member.CreateAt = c.Member.MemberId
member.Email = email member.Email = email
member.RealName = strings.TrimSpace(c.GetString("real_name",""))
if phone != "" { if phone != "" {
member.Phone = phone member.Phone = phone
} }

View File

@ -34,6 +34,7 @@ func (c *SettingController) Index() {
member.Email = email member.Email = email
member.Phone = phone member.Phone = phone
member.Description = description member.Description = description
member.RealName = strings.TrimSpace(c.GetString("real_name",""))
if err := member.Update(); err != nil { if err := member.Update(); err != nil {
c.JsonResult(602, err.Error()) c.JsonResult(602, err.Error())
} }

View File

@ -85,8 +85,8 @@ func (s *SMTPConfig) Auth() smtp.Auth {
case "SSL": case "SSL":
fallthrough fallthrough
default: default:
//auth = smtp.PlainAuth(s.Identity, s.Username, s.Password, s.Host) auth = smtp.PlainAuth(s.Identity, s.Username, s.Password, s.Host)
auth = unencryptedAuth{smtp.PlainAuth(s.Identity, s.Username, s.Password, s.Host)} //auth = unencryptedAuth{smtp.PlainAuth(s.Identity, s.Username, s.Password, s.Host)}
} }
return auth return auth
} }
@ -214,26 +214,33 @@ func (c *SMTPClient) SendTLS(m Mail, message bytes.Buffer) error {
var ct *smtp.Client var ct *smtp.Client
var err error var err error
// TLS config // TLS config
//tlsconfig := &tls.Config{ tlsconfig := &tls.Config{
// InsecureSkipVerify: true, InsecureSkipVerify: true,
// ServerName: c.host, ServerName: c.host,
//} }
// Here is the key, you need to call tls.Dial instead of smtp.Dial // Here is the key, you need to call tls.Dial instead of smtp.Dial
// for smtp servers running on 465 that require an ssl connection // for smtp servers running on 465 that require an ssl connection
// from the very beginning (no starttls) // from the very beginning (no starttls)
conn, err := tls.Dial("tcp", c.host+":"+c.port, nil) conn, err := tls.Dial("tcp", c.host+":"+c.port, tlsconfig)
if err != nil { if err != nil {
log.Println(err, c.host) log.Println(err, c.host)
return err return err
} }
ct, err = smtp.NewClient(conn, c.host) ct, err = smtp.NewClient(conn, c.host)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
return err return err
} }
//if err := ct.StartTLS(tlsconfig);err != nil {
// fmt.Println(err)
// return err
//}
fmt.Println(c.smtpAuth) fmt.Println(c.smtpAuth)
if ok,_ := ct.Extension("AUTH"); ok {
// Auth // Auth
if err = ct.Auth(c.smtpAuth); err != nil { if err = ct.Auth(c.smtpAuth); err != nil {
log.Println("Auth Error:", log.Println("Auth Error:",
@ -242,7 +249,7 @@ func (c *SMTPClient) SendTLS(m Mail, message bytes.Buffer) error {
) )
return err return err
} }
}
// To && From // To && From
if err = ct.Mail(m.From); err != nil { if err = ct.Mail(m.From); err != nil {
log.Println("Mail Error:", err, m.From) log.Println("Mail Error:", err, m.From)

View File

@ -47,6 +47,8 @@ type Book struct {
Theme string `orm:"column(theme);size(255);default(default)" json:"theme"` Theme string `orm:"column(theme);size(255);default(default)" json:"theme"`
// CreateTime 创建时间 . // CreateTime 创建时间 .
CreateTime time.Time `orm:"type(datetime);column(create_time);auto_now_add" json:"create_time"` CreateTime time.Time `orm:"type(datetime);column(create_time);auto_now_add" json:"create_time"`
//每个文档保存的历史记录数量0 为不限制
HistoryCount int `orm:"column(history_count);type(int);default(0)" json:"history_count"`
MemberId int `orm:"column(member_id);size(100)" json:"member_id"` MemberId int `orm:"column(member_id);size(100)" json:"member_id"`
ModifyTime time.Time `orm:"type(datetime);column(modify_time);null;auto_now" json:"modify_time"` ModifyTime time.Time `orm:"type(datetime);column(modify_time);null;auto_now" json:"modify_time"`
Version int64 `orm:"type(bigint);column(version)" json:"version"` Version int64 `orm:"type(bigint);column(version)" json:"version"`
@ -281,7 +283,7 @@ func (m *Book) FindForHomeToPager(pageIndex, pageSize, member_id int) (books []*
if err != nil { if err != nil {
return return
} }
sql2 := `SELECT book.*,rel1.*,member.account AS create_name FROM md_books AS book sql2 := `SELECT book.*,rel1.*,member.account AS create_name,member.real_name FROM md_books AS book
LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.member_id = ? LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.member_id = ?
LEFT JOIN md_relationship AS rel1 ON rel1.book_id = book.book_id AND rel1.role_id = 0 LEFT JOIN md_relationship AS rel1 ON rel1.book_id = book.book_id AND rel1.role_id = 0
LEFT JOIN md_members AS member ON rel1.member_id = member.member_id LEFT JOIN md_members AS member ON rel1.member_id = member.member_id
@ -289,8 +291,6 @@ func (m *Book) FindForHomeToPager(pageIndex, pageSize, member_id int) (books []*
_, err = o.Raw(sql2, member_id, offset, pageSize).QueryRows(&books) _, err = o.Raw(sql2, member_id, offset, pageSize).QueryRows(&books)
return
} else { } else {
count, err1 := o.QueryTable(m.TableNameWithPrefix()).Filter("privately_owned", 0).Count() count, err1 := o.QueryTable(m.TableNameWithPrefix()).Filter("privately_owned", 0).Count()
@ -300,17 +300,17 @@ func (m *Book) FindForHomeToPager(pageIndex, pageSize, member_id int) (books []*
} }
totalCount = int(count) totalCount = int(count)
sql := `SELECT book.*,rel.*,member.account AS create_name FROM md_books AS book sql := `SELECT book.*,rel.*,member.account AS create_name,member.real_name FROM md_books AS book
LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.role_id = 0 LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.role_id = 0
LEFT JOIN md_members AS member ON rel.member_id = member.member_id LEFT JOIN md_members AS member ON rel.member_id = member.member_id
WHERE book.privately_owned = 0 ORDER BY order_index DESC ,book.book_id DESC LIMIT ?,?` WHERE book.privately_owned = 0 ORDER BY order_index DESC ,book.book_id DESC LIMIT ?,?`
_, err = o.Raw(sql, offset, pageSize).QueryRows(&books) _, err = o.Raw(sql, offset, pageSize).QueryRows(&books)
return
} }
return
} }
//分页全局搜索. //分页全局搜索.

View File

@ -34,6 +34,7 @@ type BookResult struct {
CommentCount int `json:"comment_count"` CommentCount int `json:"comment_count"`
CreateTime time.Time `json:"create_time"` CreateTime time.Time `json:"create_time"`
CreateName string `json:"create_name"` CreateName string `json:"create_name"`
RealName string `json:"real_name"`
ModifyTime time.Time `json:"modify_time"` ModifyTime time.Time `json:"modify_time"`
Cover string `json:"cover"` Cover string `json:"cover"`
Theme string `json:"theme"` Theme string `json:"theme"`
@ -41,6 +42,7 @@ type BookResult struct {
MemberId int `json:"member_id"` MemberId int `json:"member_id"`
Editor string `json:"editor"` Editor string `json:"editor"`
AutoRelease bool `json:"auto_release"` AutoRelease bool `json:"auto_release"`
HistoryCount int `json:"history_count"`
RelationshipId int `json:"relationship_id"` RelationshipId int `json:"relationship_id"`
RoleId int `json:"role_id"` RoleId int `json:"role_id"`
@ -94,6 +96,9 @@ func (m *BookResult) FindByIdentify(identify string, member_id int) (*BookResult
m = NewBookResult().ToBookResult(*book) m = NewBookResult().ToBookResult(*book)
m.CreateName = member.Account m.CreateName = member.Account
if member.RealName != "" {
m.RealName = member.RealName
}
m.MemberId = relationship.MemberId m.MemberId = relationship.MemberId
m.RoleId = relationship.RoleId m.RoleId = relationship.RoleId
m.RelationshipId = relationship.RelationshipId m.RelationshipId = relationship.RelationshipId
@ -133,7 +138,7 @@ func (m *BookResult) FindToPager(pageIndex, pageSize int) (books []*BookResult,
totalCount = int(count) totalCount = int(count)
sql := `SELECT sql := `SELECT
book.*,rel.relationship_id,rel.role_id,m.account AS create_name book.*,rel.relationship_id,rel.role_id,m.account AS create_name,m.real_name
FROM md_books AS book FROM md_books AS book
LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.role_id = 0 LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.role_id = 0
LEFT JOIN md_members AS m ON rel.member_id = m.member_id LEFT JOIN md_members AS m ON rel.member_id = m.member_id
@ -168,6 +173,7 @@ func (m *BookResult) ToBookResult(book Book) *BookResult {
m.Theme = book.Theme m.Theme = book.Theme
m.AutoRelease = book.AutoRelease == 1 m.AutoRelease = book.AutoRelease == 1
m.Publisher = book.Publisher m.Publisher = book.Publisher
m.HistoryCount = book.HistoryCount
if book.Theme == "" { if book.Theme == "" {
m.Theme = "default" m.Theme = "default"
@ -266,6 +272,9 @@ func (m *BookResult) Converter(sessionId string) (ConvertBookResult, error) {
if m.Publisher != "" { if m.Publisher != "" {
ebookConfig.Footer = "<p style='color:#8E8E8E;font-size:12px;'>本文档由 <span style='text-decoration:none;color:#1abc9c;font-weight:bold;'>"+ m.Publisher +"</span> 生成<span style='float:right'>- _PAGENUM_ -</span></p>" ebookConfig.Footer = "<p style='color:#8E8E8E;font-size:12px;'>本文档由 <span style='text-decoration:none;color:#1abc9c;font-weight:bold;'>"+ m.Publisher +"</span> 生成<span style='float:right'>- _PAGENUM_ -</span></p>"
} }
if m.RealName != "" {
ebookConfig.Creator = m.RealName
}
if tempOutputPath, err = filepath.Abs(tempOutputPath); err != nil { if tempOutputPath, err = filepath.Abs(tempOutputPath); err != nil {
beego.Error("导出目录配置错误:" + err.Error()) beego.Error("导出目录配置错误:" + err.Error())

View File

@ -5,6 +5,7 @@ import (
"github.com/astaxie/beego/orm" "github.com/astaxie/beego/orm"
"github.com/lifei6671/mindoc/conf" "github.com/lifei6671/mindoc/conf"
"github.com/astaxie/beego"
) )
type DocumentHistory struct { type DocumentHistory struct {
@ -58,28 +59,28 @@ func (m *DocumentHistory) Find(id int) (*DocumentHistory, error) {
} }
//清空指定文档的历史. //清空指定文档的历史.
func (m *DocumentHistory) Clear(doc_id int) error { func (m *DocumentHistory) Clear(docId int) error {
o := orm.NewOrm() o := orm.NewOrm()
_, err := o.Raw("DELETE md_document_history WHERE document_id = ?", doc_id).Exec() _, err := o.Raw("DELETE md_document_history WHERE document_id = ?", docId).Exec()
return err return err
} }
//删除历史. //删除历史.
func (m *DocumentHistory) Delete(history_id, doc_id int) error { func (m *DocumentHistory) Delete(historyId, docId int) error {
o := orm.NewOrm() o := orm.NewOrm()
_, err := o.QueryTable(m.TableNameWithPrefix()).Filter("history_id", history_id).Filter("document_id", doc_id).Delete() _, err := o.QueryTable(m.TableNameWithPrefix()).Filter("history_id", historyId).Filter("document_id", docId).Delete()
return err return err
} }
//恢复指定历史的文档. //恢复指定历史的文档.
func (m *DocumentHistory) Restore(history_id, doc_id, uid int) error { func (m *DocumentHistory) Restore(historyId, docId, uid int) error {
o := orm.NewOrm() o := orm.NewOrm()
err := o.QueryTable(m.TableNameWithPrefix()).Filter("history_id", history_id).Filter("document_id", doc_id).One(m) err := o.QueryTable(m.TableNameWithPrefix()).Filter("history_id", historyId).Filter("document_id", docId).One(m)
if err != nil { if err != nil {
return err return err
@ -90,7 +91,7 @@ func (m *DocumentHistory) Restore(history_id, doc_id, uid int) error {
return err return err
} }
history := NewDocumentHistory() history := NewDocumentHistory()
history.DocumentId = doc_id history.DocumentId = docId
history.Content = doc.Content history.Content = doc.Content
history.Markdown = doc.Markdown history.Markdown = doc.Markdown
history.DocumentName = doc.DocumentName history.DocumentName = doc.DocumentName
@ -122,16 +123,38 @@ func (m *DocumentHistory) InsertOrUpdate() (history *DocumentHistory, err error)
_, err = o.Update(m) _, err = o.Update(m)
} else { } else {
_, err = o.Insert(m) _, err = o.Insert(m)
if err == nil {
if doc,e := NewDocument().Find(m.DocumentId);e == nil {
if book,e := NewBook().Find(doc.BookId);e == nil && book.HistoryCount > 0 {
//如果已存在的历史记录大于指定的记录,则清除旧记录
if c,e := o.QueryTable(m.TableNameWithPrefix()).Filter("document_id",doc.DocumentId).Count(); e == nil && c > int64(book.HistoryCount) {
count := c - int64(book.HistoryCount)
beego.Info("需要删除的历史文档数量:" ,count)
var lists []DocumentHistory
if _,e := o.QueryTable(m.TableNameWithPrefix()).Filter("document_id",doc.DocumentId).OrderBy("history_id").Limit(count).All(&lists,"history_id"); e == nil {
for _,d := range lists {
o.Delete(&d)
}
}
}else{
beego.Info(book.HistoryCount)
}
}
}
}
} }
return return
} }
//分页查询指定文档的历史. //分页查询指定文档的历史.
func (m *DocumentHistory) FindToPager(doc_id, page_index, page_size int) (docs []*DocumentHistorySimpleResult, totalCount int, err error) { func (m *DocumentHistory) FindToPager(docId, pageIndex, pageSize int) (docs []*DocumentHistorySimpleResult, totalCount int, err error) {
o := orm.NewOrm() o := orm.NewOrm()
offset := (page_index - 1) * page_size offset := (pageIndex - 1) * pageSize
totalCount = 0 totalCount = 0
@ -141,13 +164,13 @@ LEFT JOIN md_members AS m1 ON history.member_id = m1.member_id
LEFT JOIN md_members AS m2 ON history.modify_at = m2.member_id LEFT JOIN md_members AS m2 ON history.modify_at = m2.member_id
WHERE history.document_id = ? ORDER BY history.history_id DESC LIMIT ?,?;` WHERE history.document_id = ? ORDER BY history.history_id DESC LIMIT ?,?;`
_, err = o.Raw(sql, doc_id, offset, page_size).QueryRows(&docs) _, err = o.Raw(sql, docId, offset, pageSize).QueryRows(&docs)
if err != nil { if err != nil {
return return
} }
var count int64 var count int64
count, err = o.QueryTable(m.TableNameWithPrefix()).Filter("document_id", doc_id).Count() count, err = o.QueryTable(m.TableNameWithPrefix()).Filter("document_id", docId).Count()
if err != nil { if err != nil {
return return

View File

@ -21,6 +21,7 @@ import (
type Member struct { type Member struct {
MemberId int `orm:"pk;auto;unique;column(member_id)" json:"member_id"` MemberId int `orm:"pk;auto;unique;column(member_id)" json:"member_id"`
Account string `orm:"size(100);unique;column(account)" json:"account"` Account string `orm:"size(100);unique;column(account)" json:"account"`
RealName string `orm:"size(255);column(real_name)" json:"real_name"`
Password string `orm:"size(1000);column(password)" json:"-"` Password string `orm:"size(1000);column(password)" json:"-"`
//认证方式: local 本地数据库 /ldap LDAP //认证方式: local 本地数据库 /ldap LDAP
AuthMethod string `orm:"column(auth_method);default(local);size(50);" json:"auth_method"` AuthMethod string `orm:"column(auth_method);default(local);size(50);" json:"auth_method"`

View File

@ -197,6 +197,7 @@ $(function () {
url: window.editURL, url: window.editURL,
data: { "identify": window.book.identify, "doc_id": doc_id, "markdown": content, "html": html, "cover": $is_cover ? "yes" : "no", "version": version }, data: { "identify": window.book.identify, "doc_id": doc_id, "markdown": content, "html": html, "cover": $is_cover ? "yes" : "no", "version": version },
type: "post", type: "post",
timeout : 30000,
dataType: "json", dataType: "json",
success: function (res) { success: function (res) {
layer.close(index); layer.close(index);
@ -223,6 +224,10 @@ $(function () {
} else { } else {
layer.msg(res.message); layer.msg(res.message);
} }
},
error : function (XMLHttpRequest, textStatus, errorThrown) {
layer.close(index);
layer.msg("服务器错误:" + errorThrown);
} }
}); });
} }

View File

@ -26,7 +26,7 @@
<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 "SettingController.Index"}}" class="item"><i class="fa fa-sitemap" aria-hidden="true"></i> 我的项目</a> </li> <li class="active"><a href="{{urlfor "BookController.Index"}}" class="item"><i class="fa fa-sitemap" aria-hidden="true"></i> 我的项目</a> </li>
</ul> </ul>
</div> </div>
<div class="page-right"> <div class="page-right">
@ -53,15 +53,30 @@
<template v-else-if="item.privately_owned == 1"> <template v-else-if="item.privately_owned == 1">
<i class="fa fa-lock" aria-hidden="true"></i> <i class="fa fa-lock" aria-hidden="true"></i>
</template> </template>
${item.book_name} ${item.book_name}
</a> </a>
</div> </div>
<div class="pull-right"> <div class="pull-right">
<a :href="'{{urlfor "DocumentController.Index" ":key" ""}}' + item.identify" title="查看文档" data-toggle="tooltip" target="_blank"><i class="fa fa-eye"></i> 查看文档</a> <div class="btn-group">
<a :href="'/book/' + item.identify + '/dashboard'" class="btn btn-default">设置</a>
<a href="javascript:;" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</a>
<ul class="dropdown-menu">
<li><a :href="'{{urlfor "DocumentController.Index" ":key" ""}}' + item.identify" target="_blank">阅读</a></li>
<template v-if="item.role_id != 3"> <template v-if="item.role_id != 3">
<a :href="'/api/' + item.identify + '/edit'" title="编辑文档" data-toggle="tooltip" target="_blank"><i class="fa fa-edit" aria-hidden="true"></i> 编辑文档</a> <li><a :href="'/api/' + item.identify + '/edit'" target="_blank" target="_blank">编辑</a></li>
</template> </template>
</ul>
</div>
{{/*<a :href="'{{urlfor "DocumentController.Index" ":key" ""}}' + item.identify" title="查看文档" data-toggle="tooltip" target="_blank"><i class="fa fa-eye"></i> </a>*/}}
{{/*<template v-if="item.role_id != 3">*/}}
{{/*<a :href="'/api/' + item.identify + '/edit'" title="编辑文档" data-toggle="tooltip" target="_blank"><i class="fa fa-edit" aria-hidden="true"></i> </a>*/}}
{{/*</template>*/}}
</div> </div>
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>

View File

@ -63,6 +63,11 @@
<label>标识</label> <label>标识</label>
<input type="text" class="form-control" value="{{.BaseUrl}}{{urlfor "DocumentController.Index" ":key" .Model.Identify}}" placeholder="项目唯一标识" disabled> <input type="text" class="form-control" value="{{.BaseUrl}}{{urlfor "DocumentController.Index" ":key" .Model.Identify}}" placeholder="项目唯一标识" disabled>
</div> </div>
<div class="form-group">
<label>历史记录数量</label>
<input type="text" class="form-control" name="history_count" value="{{.Model.HistoryCount}}" placeholder="历史记录数量">
<p class="text">当开启文档历史时,该值会限制每个文档保存的历史数量</p>
</div>
<div class="form-group"> <div class="form-group">
<label>公司标识</label> <label>公司标识</label>
<input type="text" class="form-control" name="publisher" value="{{.Model.Publisher}}" placeholder="公司名称"> <input type="text" class="form-control" name="publisher" value="{{.Model.Publisher}}" placeholder="公司名称">

View File

@ -55,7 +55,7 @@
<span class="author"> <span class="author">
<b class="text">作者</b> <b class="text">作者</b>
<b class="text">-</b> <b class="text">-</b>
<b class="text">{{$item.CreateName}}</b> <b class="text">{{if eq $item.RealName "" }}{{$item.CreateName}}{{else}}{{$item.RealName}}{{end}}</b>
</span> </span>
</dd> </dd>
</dl> </dl>

View File

@ -43,7 +43,7 @@
<span class="author"> <span class="author">
<b class="text">作者</b> <b class="text">作者</b>
<b class="text">-</b> <b class="text">-</b>
<b class="text">{{$item.CreateName}}</b> <b class="text">{{if eq $item.RealName "" }}{{$item.CreateName}}{{else}}{{$item.RealName}}{{end}}</b>
</span> </span>
</dd> </dd>
</dl> </dl>

View File

@ -68,7 +68,7 @@
</td> </td>
</tr> </tr>
{{else}} {{else}}
<tr><td>暂无数据</td></tr> <tr><td class="text-center" colspan="6">暂无数据</td></tr>
{{end}} {{end}}
</tbody> </tbody>
</table> </table>

View File

@ -57,8 +57,20 @@
</a> </a>
</div> </div>
<div class="pull-right"> <div class="pull-right">
<a href="{{urlfor "DocumentController.Index" ":key" $item.Identify}}" title="查看文档" data-toggle="tooltip" target="_blank"><i class="fa fa-eye"></i> 查看文档</a> <div class="btn-group">
<a href="{{urlfor "DocumentController.Edit" ":key" $item.Identify ":id" ""}}" title="编辑文档" data-toggle="tooltip" target="_blank"><i class="fa fa-edit" aria-hidden="true"></i> 编辑文档</a> <a href="{{urlfor "DocumentController.Edit" ":key" $item.Identify ":id" ""}}" class="btn btn-default" target="_blank">编辑</a>
<a href="javascript:;" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</a>
<ul class="dropdown-menu">
<li><a href="{{urlfor "DocumentController.Index" ":key" $item.Identify}}" target="_blank">阅读</a></li>
<li><a href="{{urlfor "ManagerController.EditBook" ":key" $item.Identify}}">设置</a></li>
</ul>
</div>
{{/*<a href="{{urlfor "DocumentController.Index" ":key" $item.Identify}}" title="查看文档" data-toggle="tooltip" target="_blank"><i class="fa fa-eye"></i> </a>*/}}
{{/*<a href="{{urlfor "DocumentController.Edit" ":key" $item.Identify ":id" ""}}" title="编辑文档" data-toggle="tooltip" target="_blank"><i class="fa fa-edit" aria-hidden="true"></i> </a>*/}}
</div> </div>
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>
@ -76,7 +88,7 @@
{{date $item.CreateTime "Y-m-d H:i:s"}} {{date $item.CreateTime "Y-m-d H:i:s"}}
</span> </span>
<span title="创建者" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-user"></i> {{$item.CreateName}}</span> <span title="创建者" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-user"></i> {{if eq $item.RealName "" }}{{$item.CreateName}}{{else}}{{$item.RealName}}{{end}}</span>
<span title="文档数量" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pie-chart"></i> {{$item.DocCount}}</span> <span title="文档数量" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pie-chart"></i> {{$item.DocCount}}</span>
{{if ne $item.LastModifyText ""}} {{if ne $item.LastModifyText ""}}
<span title="最后编辑" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pencil"></i> 最后编辑: {{$item.LastModifyText}}</span> <span title="最后编辑" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pencil"></i> 最后编辑: {{$item.LastModifyText}}</span>

View File

@ -156,7 +156,7 @@
<div class="modal-footer"> <div class="modal-footer">
<span class="error-message" id="form-error-message1"></span> <span class="error-message" id="form-error-message1"></span>
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary" data-loading-text="变更中..." id="btnChangePrivatelyOwned">确定</button> <button type="submit" class="btn btn-primary" data-loading-text="正在保存..." id="btnChangePrivatelyOwned">确定</button>
</div> </div>
</div> </div>
</form> </form>
@ -181,7 +181,7 @@
<div class="modal-footer"> <div class="modal-footer">
<span id="form-error-message2" class="error-message"></span> <span id="form-error-message2" class="error-message"></span>
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="submit" id="btnDeleteBook" class="btn btn-primary">确定删除</button> <button type="submit" id="btnDeleteBook" class="btn btn-primary" data-loading-text="正在删除...">确定删除</button>
</div> </div>
</div> </div>
</form> </form>
@ -208,7 +208,7 @@
<div class="modal-footer"> <div class="modal-footer">
<span id="form-error-message3" class="error-message"></span> <span id="form-error-message3" class="error-message"></span>
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="submit" id="btnTransferBook" class="btn btn-primary">确定转让</button> <button type="submit" id="btnTransferBook" daata-loading-text="正在转让..." class="btn btn-primary">确定转让</button>
</div> </div>
</div> </div>
</form> </form>
@ -219,7 +219,7 @@
<script src="{{cdnjs "/static/webuploader/webuploader.min.js"}}" type="text/javascript"></script> <script src="{{cdnjs "/static/webuploader/webuploader.min.js"}}" type="text/javascript"></script>
<script src="{{cdnjs "/static/cropper/2.3.4/cropper.min.js"}}" type="text/javascript"></script> <script src="{{cdnjs "/static/cropper/2.3.4/cropper.min.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 src="/static/js/main.js" type="text/javascript"></script> <script src="{{cdnjs "/static/js/main.js"}}" type="text/javascript"></script>
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
$("#upload-logo-panel").on("hidden.bs.modal",function () { $("#upload-logo-panel").on("hidden.bs.modal",function () {
@ -274,11 +274,14 @@
} }
}); });
$("#deleteBookForm").ajaxForm({ $("#deleteBookForm").ajaxForm({
beforeSubmit : function () {
$("#btnDeleteBook").button("loading");
},
success : function (res) { success : function (res) {
if(res.errcode === 0){ if(res.errcode === 0){
window.location = "{{urlfor "ManagerController.Books"}}"; window.location = "{{urlfor "ManagerController.Books"}}";
}else{ }else{
console.log(res.message) $("#btnDeleteBook").button("reset");
showError(res.message,"#form-error-message2"); showError(res.message,"#form-error-message2");
} }
} }

View File

@ -45,6 +45,10 @@
<label>用户账号</label> <label>用户账号</label>
<input type="text" class="form-control" name="account" disabled placeholder="用户账号" value="{{.Model.Account}}"> <input type="text" class="form-control" name="account" disabled placeholder="用户账号" value="{{.Model.Account}}">
</div> </div>
<div class="form-group">
<label>真实姓名</label>
<input type="text" name="real_name" class="form-control" value="{{.Member.RealName}}" placeholder="真实姓名">
</div>
<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">

View File

@ -18,6 +18,9 @@
<script src="/static/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="/static/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="/static/respond.js/1.4.2/respond.min.js"></script> <script src="/static/respond.js/1.4.2/respond.min.js"></script>
<![endif]--> <![endif]-->
<style type="text/css">
.table>tbody>tr>td{vertical-align: middle;}
</style>
</head> </head>
<body> <body>
<div class="manual-reader"> <div class="manual-reader">
@ -56,6 +59,7 @@
<th width="80">ID</th> <th width="80">ID</th>
<th width="80">头像</th> <th width="80">头像</th>
<th>账号</th> <th>账号</th>
<th>姓名</th>
<th>角色</th> <th>角色</th>
<th>类型</th> <th>类型</th>
<th>状态</th> <th>状态</th>
@ -67,6 +71,7 @@
<td>${item.member_id}</td> <td>${item.member_id}</td>
<td><img :src="item.avatar" onerror="this.src='/static/images/middle.gif'" class="img-circle" width="34" height="34"></td> <td><img :src="item.avatar" onerror="this.src='/static/images/middle.gif'" class="img-circle" width="34" height="34"></td>
<td>${item.account}</td> <td>${item.account}</td>
<td>${item.real_name}</td>
<td> <td>
<template v-if="item.role == 0"> <template v-if="item.role == 0">
超级管理员 超级管理员
@ -163,6 +168,12 @@
<input type="email" class="form-control" placeholder="邮箱" name="email" id="email" maxlength="50"> <input type="email" class="form-control" placeholder="邮箱" name="email" id="email" maxlength="50">
</div> </div>
</div> </div>
<div class="form-group">
<label class="col-sm-2 control-label">真实姓名</label>
<div class="col-sm-10">
<input type="text" name="real_name" class="form-control" value="" placeholder="真实姓名">
</div>
</div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label">手机号</label> <label class="col-sm-2 control-label">手机号</label>
<div class="col-sm-10"> <div class="col-sm-10">

View File

@ -8,11 +8,11 @@
<title>用户中心 - Powered by MinDoc</title> <title>用户中心 - Powered by MinDoc</title>
<!-- Bootstrap --> <!-- Bootstrap -->
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet"> <link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet">
<link href="/static/font-awesome/css/font-awesome.min.css" rel="stylesheet"> <link href="{{cdncss "/static/font-awesome/css/font-awesome.min.css"}}" rel="stylesheet">
<link href="/static/webuploader/webuploader.css" rel="stylesheet"> <link href="{{cdncss "/static/webuploader/webuploader.css"}}" rel="stylesheet">
<link href="/static/cropper/2.3.4/cropper.min.css" rel="stylesheet"> <link href="{{cdncss "/static/cropper/2.3.4/cropper.min.css"}}" rel="stylesheet">
<link href="/static/css/main.css" rel="stylesheet"> <link href="{{cdncss "/static/css/main.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:// -->
@ -45,7 +45,11 @@
<form role="form" method="post" id="memberInfoForm"> <form role="form" method="post" id="memberInfoForm">
<div class="form-group"> <div class="form-group">
<label>用户名</label> <label>用户名</label>
<input type="text" class="form-control disabled" value="{{.Member.Account}}" disabled> <input type="text" class="form-control disabled" value="{{.Member.Account}}" disabled placeholder="用户名">
</div>
<div class="form-group">
<label>真实姓名</label>
<input type="text" name="real_name" class="form-control" value="{{.Member.RealName}}" placeholder="真实姓名">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="user-email">邮箱<strong class="text-danger">*</strong></label> <label for="user-email">邮箱<strong class="text-danger">*</strong></label>
@ -115,12 +119,12 @@
</div> </div>
</div> </div>
<!--END Modal--> <!--END Modal-->
<script src="/static/jquery/1.12.4/jquery.min.js" type="text/javascript"></script> <script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}" type="text/javascript"></script>
<script src="/static/bootstrap/js/bootstrap.min.js" type="text/javascript"></script> <script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}" type="text/javascript"></script>
<script src="/static/webuploader/webuploader.min.js" type="text/javascript"></script> <script src="{{cdnjs "/static/webuploader/webuploader.min.js"}}" type="text/javascript"></script>
<script src="/static/cropper/2.3.4/cropper.min.js" type="text/javascript"></script> <script src="{{cdnjs "/static/cropper/2.3.4/cropper.min.js"}}" type="text/javascript"></script>
<script src="/static/js/jquery.form.js" type="text/javascript"></script> <script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
<script src="/static/js/main.js" type="text/javascript"></script> <script src="{{cdnjs "/static/js/main.js"}}" type="text/javascript"></script>
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
$("#upload-logo-panel").on("hidden.bs.modal",function () { $("#upload-logo-panel").on("hidden.bs.modal",function () {

View File

@ -8,10 +8,10 @@
<title>用户中心 - Powered by MinDoc</title> <title>用户中心 - Powered by MinDoc</title>
<!-- Bootstrap --> <!-- Bootstrap -->
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet"> <link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet">
<link href="/static/font-awesome/css/font-awesome.min.css" rel="stylesheet"> <link href="{{cdncss "/static/font-awesome/css/font-awesome.min.css"}}" rel="stylesheet">
<link href="/static/css/main.css" rel="stylesheet"> <link href="/{{cdncss "/static/css/main.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]>
@ -61,10 +61,10 @@
</div> </div>
{{template "widgets/footer.tpl" .}} {{template "widgets/footer.tpl" .}}
</div> </div>
<script src="/static/jquery/1.12.4/jquery.min.js" type="text/javascript"></script> <script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}" type="text/javascript"></script>
<script src="/static/bootstrap/js/bootstrap.min.js" type="text/javascript"></script> <script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}" type="text/javascript"></script>
<script src="/static/js/jquery.form.js" type="text/javascript"></script> <script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
<script src="/static/js/main.js" type="text/javascript"></script> <script src="{{cdnjs "/static/js/main.js"}}" type="text/javascript"></script>
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {