ソースを参照

1、实现通过SSL、TSL发送邮件
2、增加用户真实姓名字段
3、优化项目列表显示
4、实现限定文档历史记录数量
5、优化部分页面的用户体验

Minho 7 年 前
コミット
c7d83576bd

+ 1 - 1
conf/app.conf.example

@@ -60,7 +60,7 @@ mail_number=5
 #smtp服务用户名
 [email protected]
 #smtp服务器地址
-smtp_host=smtp.ym.163.com
+smtp_host=smtp.163.com
 #smtp密码
 smtp_password=
 #端口号

+ 3 - 0
controllers/book.go

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

+ 1 - 0
controllers/document.go

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

+ 1 - 0
controllers/manager.go

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

+ 1 - 0
controllers/setting.go

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

+ 22 - 15
mail/smtp.go

@@ -85,8 +85,8 @@ func (s *SMTPConfig) Auth() smtp.Auth {
 	case "SSL":
 		fallthrough
 	default:
-		//auth = smtp.PlainAuth(s.Identity, s.Username, s.Password, s.Host)
-		auth = unencryptedAuth{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)}
 	}
 	return auth
 }
@@ -214,35 +214,42 @@ func (c *SMTPClient) SendTLS(m Mail, message bytes.Buffer) error {
 	var ct *smtp.Client
 	var err error
 	// TLS config
-	//tlsconfig := &tls.Config{
-	//	InsecureSkipVerify: true,
-	//	ServerName:         c.host,
-	//}
+	tlsconfig := &tls.Config{
+		InsecureSkipVerify: true,
+		ServerName:         c.host,
+	}
 
 	// 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
 	// 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 {
 		log.Println(err, c.host)
 		return err
 	}
 
+
 	ct, err = smtp.NewClient(conn, c.host)
 	if err != nil {
 		log.Println(err)
 		return err
 	}
+	//if err := ct.StartTLS(tlsconfig);err != nil {
+	//	fmt.Println(err)
+	//	return err
+	//}
+
 	fmt.Println(c.smtpAuth)
-	// Auth
-	if err = ct.Auth(c.smtpAuth); err != nil {
-		log.Println("Auth Error:",
-			err,
-			c.user,
-		)
-		return err
+	if ok,_ := ct.Extension("AUTH"); ok {
+		// Auth
+		if err = ct.Auth(c.smtpAuth); err != nil {
+			log.Println("Auth Error:",
+				err,
+				c.user,
+			)
+			return err
+		}
 	}
-
 	// To && From
 	if err = ct.Mail(m.From); err != nil {
 		log.Println("Mail Error:", err, m.From)

+ 6 - 6
models/book.go

@@ -47,6 +47,8 @@ type Book struct {
 	Theme string `orm:"column(theme);size(255);default(default)" json:"theme"`
 	// CreateTime 创建时间 .
 	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"`
 	ModifyTime time.Time `orm:"type(datetime);column(modify_time);null;auto_now" json:"modify_time"`
 	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 {
 			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 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
@@ -289,8 +291,6 @@ func (m *Book) FindForHomeToPager(pageIndex, pageSize, member_id int) (books []*
 
 		_, err = o.Raw(sql2, member_id, offset, pageSize).QueryRows(&books)
 
-		return
-
 	} else {
 		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)
 
-		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_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 ?,?`
 
 		_, err = o.Raw(sql, offset, pageSize).QueryRows(&books)
 
-		return
-
 	}
 
+	return
+
 }
 
 //分页全局搜索.

+ 10 - 1
models/book_result.go

@@ -34,6 +34,7 @@ type BookResult struct {
 	CommentCount   int       `json:"comment_count"`
 	CreateTime     time.Time `json:"create_time"`
 	CreateName     string    `json:"create_name"`
+	RealName	   string 	 `json:"real_name"`
 	ModifyTime     time.Time `json:"modify_time"`
 	Cover          string    `json:"cover"`
 	Theme          string    `json:"theme"`
@@ -41,6 +42,7 @@ type BookResult struct {
 	MemberId       int       `json:"member_id"`
 	Editor         string    `json:"editor"`
 	AutoRelease    bool      `json:"auto_release"`
+	HistoryCount   int 		 `json:"history_count"`
 
 	RelationshipId int    `json:"relationship_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.CreateName = member.Account
+	if member.RealName != "" {
+		m.RealName = member.RealName
+	}
 	m.MemberId = relationship.MemberId
 	m.RoleId = relationship.RoleId
 	m.RelationshipId = relationship.RelationshipId
@@ -133,7 +138,7 @@ func (m *BookResult) FindToPager(pageIndex, pageSize int) (books []*BookResult,
 	totalCount = int(count)
 
 	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
 			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
@@ -168,6 +173,7 @@ func (m *BookResult) ToBookResult(book Book) *BookResult {
 	m.Theme = book.Theme
 	m.AutoRelease = book.AutoRelease == 1
 	m.Publisher = book.Publisher
+	m.HistoryCount = book.HistoryCount
 
 	if book.Theme == "" {
 		m.Theme = "default"
@@ -266,6 +272,9 @@ func (m *BookResult) Converter(sessionId string) (ConvertBookResult, error) {
 	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>"
 	}
+	if m.RealName != "" {
+		ebookConfig.Creator = m.RealName
+	}
 
 	if tempOutputPath, err = filepath.Abs(tempOutputPath); err != nil {
 		beego.Error("导出目录配置错误:" + err.Error())

+ 34 - 11
models/document_history.go

@@ -5,6 +5,7 @@ import (
 
 	"github.com/astaxie/beego/orm"
 	"github.com/lifei6671/mindoc/conf"
+	"github.com/astaxie/beego"
 )
 
 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()
 
-	_, 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
 }
 
 //删除历史.
-func (m *DocumentHistory) Delete(history_id, doc_id int) error {
+func (m *DocumentHistory) Delete(historyId, docId int) error {
 	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
 }
 
 //恢复指定历史的文档.
-func (m *DocumentHistory) Restore(history_id, doc_id, uid int) error {
+func (m *DocumentHistory) Restore(historyId, docId, uid int) error {
 	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 {
 		return err
@@ -90,7 +91,7 @@ func (m *DocumentHistory) Restore(history_id, doc_id, uid int) error {
 		return err
 	}
 	history := NewDocumentHistory()
-	history.DocumentId = doc_id
+	history.DocumentId = docId
 	history.Content = doc.Content
 	history.Markdown = doc.Markdown
 	history.DocumentName = doc.DocumentName
@@ -122,16 +123,38 @@ func (m *DocumentHistory) InsertOrUpdate() (history *DocumentHistory, err error)
 		_, err = o.Update(m)
 	} else {
 		_, 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
 }
 
 //分页查询指定文档的历史.
-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()
 
-	offset := (page_index - 1) * page_size
+	offset := (pageIndex - 1) * pageSize
 
 	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
 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 {
 		return
 	}
 	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 {
 		return

+ 1 - 0
models/member.go

@@ -21,6 +21,7 @@ import (
 type Member struct {
 	MemberId int    `orm:"pk;auto;unique;column(member_id)" json:"member_id"`
 	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:"-"`
 	//认证方式: local 本地数据库 /ldap LDAP
 	AuthMethod  string `orm:"column(auth_method);default(local);size(50);" json:"auth_method"`

+ 5 - 0
static/js/markdown.js

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

+ 21 - 6
views/book/index.tpl

@@ -26,7 +26,7 @@
         <div class="row">
             <div class="page-left">
                 <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>
             </div>
             <div class="page-right">
@@ -53,15 +53,30 @@
                                        <template v-else-if="item.privately_owned == 1">
                                            <i class="fa fa-lock" aria-hidden="true"></i>
                                        </template>
-
                                         ${item.book_name}
                                     </a>
                                 </div>
                                 <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>
-                                    <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 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">
+                                            <li><a :href="'/api/' + item.identify + '/edit'" target="_blank" target="_blank">编辑</a></li>
+                                            </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 class="clearfix"></div>
                             </div>

+ 5 - 0
views/book/setting.tpl

@@ -63,6 +63,11 @@
                                 <label>标识</label>
                                 <input type="text" class="form-control" value="{{.BaseUrl}}{{urlfor "DocumentController.Index" ":key" .Model.Identify}}" placeholder="项目唯一标识" disabled>
                             </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">
                                 <label>公司标识</label>
                                 <input type="text" class="form-control" name="publisher" value="{{.Model.Publisher}}" placeholder="公司名称">

+ 1 - 1
views/home/index.tpl

@@ -55,7 +55,7 @@
                             <span class="author">
                                 <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>
                         </dd>
                     </dl>

+ 1 - 1
views/label/index.tpl

@@ -43,7 +43,7 @@
                             <span class="author">
                                 <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>
                         </dd>
                     </dl>

+ 1 - 1
views/manager/attach_list.tpl

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

+ 15 - 3
views/manager/books.tpl

@@ -57,8 +57,20 @@
                                         </a>
                                     </div>
                                     <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>
-                                        <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 class="btn-group">
+                                            <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 class="clearfix"></div>
                                 </div>
@@ -76,7 +88,7 @@
                                     {{date $item.CreateTime "Y-m-d H:i:s"}}
 
                                 </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>
                                    {{if ne $item.LastModifyText ""}}
                                     <span title="最后编辑" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-pencil"></i> 最后编辑: {{$item.LastModifyText}}</span>

+ 8 - 5
views/manager/edit_book.tpl

@@ -156,7 +156,7 @@
                 <div class="modal-footer">
                     <span class="error-message" id="form-error-message1"></span>
                     <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>
         </form>
@@ -181,7 +181,7 @@
                 <div class="modal-footer">
                     <span id="form-error-message2" class="error-message"></span>
                     <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>
         </form>
@@ -208,7 +208,7 @@
                 <div class="modal-footer">
                     <span id="form-error-message3" class="error-message"></span>
                     <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>
         </form>
@@ -219,7 +219,7 @@
 <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/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">
     $(function () {
         $("#upload-logo-panel").on("hidden.bs.modal",function () {
@@ -274,11 +274,14 @@
             }
         });
         $("#deleteBookForm").ajaxForm({
+            beforeSubmit : function () {
+                $("#btnDeleteBook").button("loading");
+            },
             success : function (res) {
                 if(res.errcode === 0){
                     window.location = "{{urlfor "ManagerController.Books"}}";
                 }else{
-                    console.log(res.message)
+                    $("#btnDeleteBook").button("reset");
                     showError(res.message,"#form-error-message2");
                 }
             }

+ 4 - 0
views/manager/edit_users.tpl

@@ -45,6 +45,10 @@
                             <label>用户账号</label>
                             <input type="text" class="form-control" name="account" disabled placeholder="用户账号" value="{{.Model.Account}}">
                         </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">
                             <label>用户密码</label>
                             <input type="password" class="form-control" name="password1" placeholder="用户密码" maxlength="50">

+ 11 - 0
views/manager/users.tpl

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

+ 16 - 12
views/setting/index.tpl

@@ -8,11 +8,11 @@
     <title>用户中心 - Powered by MinDoc</title>
 
     <!-- Bootstrap -->
-    <link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
-    <link href="/static/font-awesome/css/font-awesome.min.css" rel="stylesheet">
-    <link href="/static/webuploader/webuploader.css" rel="stylesheet">
-    <link href="/static/cropper/2.3.4/cropper.min.css" rel="stylesheet">
-    <link href="/static/css/main.css" rel="stylesheet">
+    <link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet">
+    <link href="{{cdncss "/static/font-awesome/css/font-awesome.min.css"}}" rel="stylesheet">
+    <link href="{{cdncss "/static/webuploader/webuploader.css"}}" rel="stylesheet">
+    <link href="{{cdncss "/static/cropper/2.3.4/cropper.min.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 -->
     <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
@@ -45,7 +45,11 @@
                         <form role="form" method="post" id="memberInfoForm">
                             <div class="form-group">
                                 <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 class="form-group">
                                 <label for="user-email">邮箱<strong class="text-danger">*</strong></label>
@@ -115,12 +119,12 @@
     </div>
 </div>
 <!--END Modal-->
-<script src="/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="/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="/static/js/jquery.form.js" type="text/javascript"></script>
-<script src="/static/js/main.js" type="text/javascript"></script>
+<script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}" type="text/javascript"></script>
+<script src="{{cdnjs "/static/bootstrap/js/bootstrap.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/js/jquery.form.js"}}" type="text/javascript"></script>
+<script src="{{cdnjs "/static/js/main.js"}}" type="text/javascript"></script>
 <script type="text/javascript">
     $(function () {
         $("#upload-logo-panel").on("hidden.bs.modal",function () {

+ 7 - 7
views/setting/password.tpl

@@ -8,10 +8,10 @@
     <title>用户中心 - Powered by MinDoc</title>
 
     <!-- Bootstrap -->
-    <link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
-    <link href="/static/font-awesome/css/font-awesome.min.css" rel="stylesheet">
+    <link href="{{cdncss "/static/bootstrap/css/bootstrap.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 -->
     <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
     <!--[if lt IE 9]>
@@ -61,10 +61,10 @@
     </div>
     {{template "widgets/footer.tpl" .}}
 </div>
-<script src="/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="/static/js/jquery.form.js" type="text/javascript"></script>
-<script src="/static/js/main.js" type="text/javascript"></script>
+<script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}" type="text/javascript"></script>
+<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}" type="text/javascript"></script>
+<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
+<script src="{{cdnjs "/static/js/main.js"}}" type="text/javascript"></script>
 <script type="text/javascript">
     $(function () {