Просмотр исходного кода

实现部署到二级虚拟目录

Minho 7 лет назад
Родитель
Сommit
c278b72f15

+ 18 - 39
commands/command.go

@@ -137,6 +137,7 @@ func RegisterCommand() {
 		migrate.RunMigration()
 	}
 }
+
 //注册模板函数
 func RegisterFunction() {
 	beego.AddFuncMap("config", models.GetOptionValue)
@@ -146,19 +147,17 @@ func RegisterFunction() {
 		if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") {
 			return p
 		}
-		if strings.HasPrefix(p, "/") && strings.HasSuffix(cdn, "/") {
-			return cdn + string(p[1:])
-		}
-		if !strings.HasPrefix(p, "/") && !strings.HasSuffix(cdn, "/") {
-			return cdn + "/" + p
-		}
-		return cdn + p
-	})
-
-	beego.AddFuncMap("cdnjs", func(p string) string {
-		cdn := beego.AppConfig.DefaultString("cdnjs", "")
-		if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") {
-			return p
+		//如果没有设置cdn,则使用baseURL拼接
+		if cdn == "" {
+			baseUrl := beego.AppConfig.DefaultString("baseurl","")
+
+			if strings.HasPrefix(p,"/") && strings.HasSuffix(baseUrl,"/") {
+				return baseUrl + p[1:]
+			}
+			if !strings.HasPrefix(p,"/") && !strings.HasSuffix(baseUrl,"/") {
+				return baseUrl + "/" + p
+			}
+			return  baseUrl + p
 		}
 		if strings.HasPrefix(p, "/") && strings.HasSuffix(cdn, "/") {
 			return cdn + string(p[1:])
@@ -168,32 +167,12 @@ func RegisterFunction() {
 		}
 		return cdn + p
 	})
-	beego.AddFuncMap("cdncss", func(p string) string {
-		cdn := beego.AppConfig.DefaultString("cdncss", "")
-		if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") {
-			return p
-		}
-		if strings.HasPrefix(p, "/") && strings.HasSuffix(cdn, "/") {
-			return cdn + string(p[1:])
-		}
-		if !strings.HasPrefix(p, "/") && !strings.HasSuffix(cdn, "/") {
-			return cdn + "/" + p
-		}
-		return cdn + p
-	})
-	beego.AddFuncMap("cdnimg", func(p string) string {
-		if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") {
-			return p
-		}
-		cdn := beego.AppConfig.DefaultString("cdnimg", "")
-		if strings.HasPrefix(p, "/") && strings.HasSuffix(cdn, "/") {
-			return cdn + string(p[1:])
-		}
-		if !strings.HasPrefix(p, "/") && !strings.HasSuffix(cdn, "/") {
-			return cdn + "/" + p
-		}
-		return cdn + p
-	})
+
+	beego.AddFuncMap("cdnjs",utils.URLForWithCdnJs)
+	beego.AddFuncMap("cdncss",utils.URLForWithCdnCss)
+	beego.AddFuncMap("cdnimg", utils.URLForWithCdnImage)
+	//重写url生成,支持配置域名以及域名前缀
+	beego.AddFuncMap("urlfor", utils.URLFor)
 }
 
 //解析命令

+ 9 - 9
controllers/account.go

@@ -32,7 +32,7 @@ func (c *AccountController) Login() {
 			u = c.Ctx.Request.Header.Get("Referer")
 		}
 		if u == "" {
-			u = beego.URLFor("HomeController.Index")
+			u = utils.URLFor("HomeController.Index")
 		}
 		c.Redirect(u,302)
 	}
@@ -83,7 +83,7 @@ func (c *AccountController) Login() {
 				u = c.Ctx.Request.Header.Get("Referer")
 			}
 			if u == "" {
-				u = beego.URLFor("HomeController.Index")
+				u = utils.URLFor("HomeController.Index")
 			}
 
 			c.JsonResult(0, "ok", u)
@@ -97,7 +97,7 @@ func (c *AccountController) Login() {
 			u = c.Ctx.Request.Header.Get("Referer")
 		}
 		if u == "" {
-			u = beego.URLFor("HomeController.Index")
+			u = utils.URLFor("HomeController.Index")
 		}
 		c.Data["url"] = url.PathEscape(u)
 	}
@@ -111,7 +111,7 @@ func (c *AccountController) LoggedIn(isPost bool) interface{} {
 	if !isPost {
 		// 检查是否存在 turl 参数,如果有则重定向至 turl 处,否则进入 Home 页面
 		if turl == "" {
-			turl = beego.URLFor("HomeController.Index")
+			turl = utils.URLFor("HomeController.Index")
 		}
 		c.Redirect(turl, 302)
 		return nil
@@ -130,7 +130,7 @@ func (c *AccountController) Register() {
 
 	//如果用户登录了,则跳转到网站首页
 	if member, ok := c.GetSession(conf.LoginSessionName).(models.Member); ok && member.MemberId > 0 {
-		c.Redirect(beego.URLFor("HomeController.Index"),302)
+		c.Redirect(utils.URLFor("HomeController.Index"),302)
 	}
 	// 如果没有开启用户注册
 	if v, ok := c.Option["ENABLED_REGISTER"]; ok && !strings.EqualFold(v, "true") {
@@ -244,7 +244,7 @@ func (c *AccountController) FindPassword() {
 
 		data := map[string]interface{}{
 			"SITE_NAME": c.Option["SITE_NAME"],
-			"url":       c.BaseUrl() + beego.URLFor("AccountController.FindPassword", "token", member_token.Token, "mail", email),
+			"url":       utils.URLFor("AccountController.FindPassword", "token", member_token.Token, "mail", email),
 			"BaseUrl": c.BaseUrl(),
 		}
 
@@ -302,7 +302,7 @@ func (c *AccountController) FindPassword() {
 			//}
 		}(mail_conf, email, body)
 
-		c.JsonResult(0, "ok", c.BaseUrl()+beego.URLFor("AccountController.Login"))
+		c.JsonResult(0, "ok", utils.URLFor("AccountController.Login"))
 	}
 
 	token := c.GetString("token")
@@ -396,7 +396,7 @@ func (c *AccountController) ValidEmail() {
 		beego.Error(err)
 		c.JsonResult(6006, "保存密码失败")
 	}
-	c.JsonResult(0, "ok", c.BaseUrl()+beego.URLFor("AccountController.Login"))
+	c.JsonResult(0, "ok", utils.URLFor("AccountController.Login"))
 }
 
 // Logout 退出登录
@@ -407,7 +407,7 @@ func (c *AccountController) Logout() {
 
 	u := c.Ctx.Request.Header.Get("Referer")
 
-	c.Redirect(beego.URLFor("AccountController.Login","url",u), 302)
+	c.Redirect(utils.URLFor("AccountController.Login","url",u), 302)
 }
 
 // 验证码

+ 5 - 5
controllers/book.go

@@ -47,7 +47,7 @@ func (c *BookController) Index() {
 	}
 
 	if totalCount > 0 {
-		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize)
+		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize,c.BaseUrl())
 		c.Data["PageHtml"] = pager.HtmlPages()
 	} else {
 		c.Data["PageHtml"] = ""
@@ -111,7 +111,7 @@ func (c *BookController) Setting() {
 		c.Abort("403")
 	}
 	if book.PrivateToken != "" {
-		book.PrivateToken = c.BaseUrl() + beego.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken)
+		book.PrivateToken = utils.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken)
 	}
 	c.Data["Model"] = book
 
@@ -345,7 +345,7 @@ func (c *BookController) UploadCover() {
 
 	oldCover := book.Cover
 
-	book.Cover = url
+	book.Cover = utils.URLForWithCdnImage(url)
 
 	if err := book.Update(); err != nil {
 		c.JsonResult(6001, "保存图片失败")
@@ -383,7 +383,7 @@ func (c *BookController) Users() {
 	members, totalCount, err := models.NewMemberRelationshipResult().FindForUsersByBookId(book.BookId, pageIndex, 15)
 
 	if totalCount > 0 {
-		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize)
+		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize,c.BaseUrl())
 		c.Data["PageHtml"] = pager.HtmlPages()
 	} else {
 		c.Data["PageHtml"] = ""
@@ -554,7 +554,7 @@ func (c *BookController) CreateToken() {
 			logs.Error("生成阅读令牌失败 => ", err)
 			c.JsonResult(6003, "生成阅读令牌失败")
 		}
-		c.JsonResult(0, "ok", c.BaseUrl()+beego.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken))
+		c.JsonResult(0, "ok", utils.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken))
 	} else {
 		book.PrivateToken = ""
 		if err := book.Update(); err != nil {

+ 15 - 15
controllers/document.go

@@ -105,7 +105,7 @@ func promptUserToLogIn(c *DocumentController) {
 	if c.IsAjax() {
 		c.JsonResult(6000, "请重新登录。")
 	} else {
-		c.Redirect(beego.URLFor("AccountController.Login")+ "?url=" + url.PathEscape(conf.BaseUrl+ c.Ctx.Request.URL.RequestURI()), 302)
+		c.Redirect(utils.URLFor("AccountController.Login")+ "?url=" + url.PathEscape(conf.BaseUrl+ c.Ctx.Request.URL.RequestURI()), 302)
 	}
 }
 
@@ -522,7 +522,7 @@ func (c *DocumentController) Upload() {
 	if strings.EqualFold(ext, ".jpg") || strings.EqualFold(ext, ".jpeg") || strings.EqualFold(ext, ".png") || strings.EqualFold(ext, ".gif") {
 		attachment.HttpPath = "/" + strings.Replace(strings.TrimPrefix(filePath, conf.WorkingDirectory), "\\", "/", -1)
 		if strings.HasPrefix(attachment.HttpPath, "//") {
-			attachment.HttpPath = string(attachment.HttpPath[1:])
+			attachment.HttpPath = utils.URLForWithCdnImage(string(attachment.HttpPath[1:]))
 		}
 
 		is_attach = false
@@ -537,7 +537,7 @@ func (c *DocumentController) Upload() {
 	}
 
 	if attachment.HttpPath == "" {
-		attachment.HttpPath = c.BaseUrl() + beego.URLFor("DocumentController.DownloadAttachment", ":key", identify, ":attach_id", attachment.AttachmentId)
+		attachment.HttpPath = utils.URLFor("DocumentController.DownloadAttachment", ":key", identify, ":attach_id", attachment.AttachmentId)
 
 		if err := attachment.Update(); err != nil {
 			beego.Error("SaveToFile => ", err)
@@ -564,19 +564,19 @@ func (c *DocumentController) DownloadAttachment() {
 	c.Prepare()
 
 	identify := c.Ctx.Input.Param(":key")
-	attach_id, _ := strconv.Atoi(c.Ctx.Input.Param(":attach_id"))
+	attachId, _ := strconv.Atoi(c.Ctx.Input.Param(":attach_id"))
 	token := c.GetString("token")
 
-	member_id := 0
+	memberId := 0
 
 	if c.Member != nil {
-		member_id = c.Member.MemberId
+		memberId = c.Member.MemberId
 	}
 
-	book_id := 0
+	bookId := 0
 
 	// 判断用户是否参与了项目
-	bookResult, err := models.NewBookResult().FindByIdentify(identify, member_id)
+	bookResult, err := models.NewBookResult().FindByIdentify(identify, memberId)
 
 	if err != nil {
 		// 判断项目公开状态
@@ -593,13 +593,13 @@ func (c *DocumentController) DownloadAttachment() {
 			}
 		}
 
-		book_id = book.BookId
+		bookId = book.BookId
 	} else {
-		book_id = bookResult.BookId
+		bookId = bookResult.BookId
 	}
 
 	// 查找附件
-	attachment, err := models.NewAttachment().Find(attach_id)
+	attachment, err := models.NewAttachment().Find(attachId)
 
 	if err != nil {
 		beego.Error("DownloadAttachment => ", err)
@@ -610,7 +610,7 @@ func (c *DocumentController) DownloadAttachment() {
 		}
 	}
 
-	if attachment.BookId != book_id {
+	if attachment.BookId != bookId {
 		c.Abort("404")
 	}
 
@@ -892,7 +892,7 @@ func (c *DocumentController) Export() {
 	}
 
 	if !strings.HasPrefix(bookResult.Cover, "http:://") && !strings.HasPrefix(bookResult.Cover, "https:://") {
-		bookResult.Cover = c.BaseUrl() + bookResult.Cover
+		bookResult.Cover = utils.URLForWithCdnImage(bookResult.Cover)
 	}
 
 	if output == "markdown" {
@@ -951,7 +951,7 @@ func (c *DocumentController) QrCode() {
 		c.Abort("404")
 	}
 
-	uri := c.BaseUrl() + beego.URLFor("DocumentController.Index", ":key", identify)
+	uri := utils.URLFor("DocumentController.Index", ":key", identify)
 	code, err := qr.Encode(uri, qr.L, qr.Unicode)
 	if err != nil {
 		beego.Error(err)
@@ -1079,7 +1079,7 @@ func (c *DocumentController) History() {
 	c.Data["Document"] = doc
 
 	if totalCount > 0 {
-		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize)
+		pager := pagination.NewPagination(c.Ctx.Request, totalCount, conf.PageSize, c.BaseUrl())
 		c.Data["PageHtml"] = pager.HtmlPages()
 	}
 }

+ 6 - 4
controllers/home.go

@@ -1,12 +1,14 @@
 package controllers
 
 import (
+	"math"
 	"net/url"
+
 	"github.com/astaxie/beego"
+	"github.com/lifei6671/mindoc/conf"
 	"github.com/lifei6671/mindoc/models"
+	"github.com/lifei6671/mindoc/utils"
 	"github.com/lifei6671/mindoc/utils/pagination"
-	"math"
-	"github.com/lifei6671/mindoc/conf"
 )
 
 type HomeController struct {
@@ -18,7 +20,7 @@ func (c *HomeController) Index() {
 	c.TplName = "home/index.tpl"
 	//如果没有开启匿名访问,则跳转到登录页面
 	if !c.EnableAnonymous && c.Member == nil {
-		c.Redirect(beego.URLFor("AccountController.Login") + "?url=" + url.PathEscape(conf.BaseUrl + c.Ctx.Request.URL.RequestURI()), 302)
+		c.Redirect(utils.URLFor("AccountController.Login")+"?url="+url.PathEscape(conf.BaseUrl+c.Ctx.Request.URL.RequestURI()), 302)
 	}
 	pageIndex, _ := c.GetInt("page", 1)
 	pageSize := 18
@@ -35,7 +37,7 @@ func (c *HomeController) Index() {
 		c.Abort("500")
 	}
 	if totalCount > 0 {
-		pager := pagination.NewPagination(c.Ctx.Request,totalCount,pageSize)
+		pager := pagination.NewPagination(c.Ctx.Request, totalCount, pageSize, c.BaseUrl())
 		c.Data["PageHtml"] = pager.HtmlPages()
 	} else {
 		c.Data["PageHtml"] = ""

+ 6 - 4
controllers/label.go

@@ -1,12 +1,14 @@
 package controllers
 
 import (
+	"math"
+
 	"github.com/astaxie/beego"
 	"github.com/astaxie/beego/orm"
 	"github.com/lifei6671/mindoc/conf"
 	"github.com/lifei6671/mindoc/models"
+	"github.com/lifei6671/mindoc/utils"
 	"github.com/lifei6671/mindoc/utils/pagination"
-	"math"
 )
 
 type LabelController struct {
@@ -18,7 +20,7 @@ func (c *LabelController) Prepare() {
 
 	//如果没有开启你们访问则跳转到登录
 	if !c.EnableAnonymous && c.Member == nil {
-		c.Redirect(beego.URLFor("AccountController.Login"), 302)
+		c.Redirect(utils.URLFor("AccountController.Login"), 302)
 		return
 	}
 }
@@ -54,7 +56,7 @@ func (c *LabelController) Index() {
 		return
 	}
 	if totalCount > 0 {
-		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize)
+		pager := pagination.NewPagination(c.Ctx.Request, totalCount, conf.PageSize,c.BaseUrl())
 		c.Data["PageHtml"] = pager.HtmlPages()
 	} else {
 		c.Data["PageHtml"] = ""
@@ -77,7 +79,7 @@ func (c *LabelController) List() {
 		c.ShowErrorPage(50001, err.Error())
 	}
 	if totalCount > 0 {
-		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize)
+		pager := pagination.NewPagination(c.Ctx.Request, totalCount, conf.PageSize, c.BaseUrl())
 		c.Data["PageHtml"] = pager.HtmlPages()
 	} else {
 		c.Data["PageHtml"] = ""

+ 8 - 8
controllers/manager.go

@@ -52,7 +52,7 @@ func (c *ManagerController) Users() {
 	}
 
 	if totalCount > 0 {
-		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize)
+		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize,c.BaseUrl())
 		c.Data["PageHtml"] = pager.HtmlPages()
 	} else {
 		c.Data["PageHtml"] = ""
@@ -292,7 +292,7 @@ func (c *ManagerController) Books() {
 	if totalCount > 0 {
 		//html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, 8, totalCount)
 
-		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize)
+		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize, c.BaseUrl())
 
 		c.Data["PageHtml"] = pager.HtmlPages()
 	} else {
@@ -352,7 +352,7 @@ func (c *ManagerController) EditBook() {
 		c.JsonResult(0, "ok")
 	}
 	if book.PrivateToken != "" {
-		book.PrivateToken = c.BaseUrl() + beego.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken)
+		book.PrivateToken = utils.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken)
 	}
 	c.Data["Model"] = book
 }
@@ -403,7 +403,7 @@ func (c *ManagerController) CreateToken() {
 			logs.Error("生成阅读令牌失败 => ", err)
 			c.JsonResult(6003, "生成阅读令牌失败")
 		}
-		c.JsonResult(0, "ok", c.BaseUrl()+beego.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken))
+		c.JsonResult(0, "ok", utils.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken))
 	} else {
 		book.PrivateToken = ""
 		if err := book.Update(); err != nil {
@@ -572,7 +572,7 @@ func (c *ManagerController) AttachList() {
 	}
 
 	if totalCount > 0 {
-		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize)
+		pager := pagination.NewPagination(c.Ctx.Request, totalCount, conf.PageSize, c.BaseUrl())
 		c.Data["PageHtml"] = pager.HtmlPages()
 	} else {
 		c.Data["PageHtml"] = ""
@@ -610,7 +610,7 @@ func (c *ManagerController) AttachDetailed() {
 	}
 
 	attach.FilePath = filepath.Join(conf.WorkingDirectory, attach.FilePath)
-	attach.HttpPath = c.BaseUrl() + attach.HttpPath
+	attach.HttpPath = utils.URLForWithCdnImage(attach.HttpPath)
 
 	attach.IsExist = utils.FileExists(attach.FilePath)
 
@@ -639,7 +639,7 @@ func (c *ManagerController) AttachDelete() {
 }
 
 //标签列表
-func (c *ManagerController) LabelList(){
+func (c *ManagerController) LabelList() {
 	c.Prepare()
 	c.TplName = "manager/label_list.tpl"
 
@@ -651,7 +651,7 @@ func (c *ManagerController) LabelList(){
 		c.ShowErrorPage(50001, err.Error())
 	}
 	if totalCount > 0 {
-		pager := pagination.NewPagination(c.Ctx.Request,totalCount,conf.PageSize)
+		pager := pagination.NewPagination(c.Ctx.Request, totalCount, conf.PageSize, c.BaseUrl())
 		c.Data["PageHtml"] = pager.HtmlPages()
 	} else {
 		c.Data["PageHtml"] = ""

+ 2 - 2
controllers/search.go

@@ -21,7 +21,7 @@ func (c *SearchController) Index() {
 
 	//如果没有开启你们访问则跳转到登录
 	if !c.EnableAnonymous && c.Member == nil {
-		c.Redirect(beego.URLFor("AccountController.Login"), 302)
+		c.Redirect(utils.URLFor("AccountController.Login"), 302)
 		return
 	}
 
@@ -43,7 +43,7 @@ func (c *SearchController) Index() {
 			return
 		}
 		if totalCount > 0 {
-			pager := pagination.NewPagination(c.Ctx.Request, totalCount, conf.PageSize)
+			pager := pagination.NewPagination(c.Ctx.Request, totalCount, conf.PageSize,c.BaseUrl())
 			c.Data["PageHtml"] = pager.HtmlPages()
 		} else {
 			c.Data["PageHtml"] = ""

+ 5 - 5
models/document_tree.go

@@ -2,11 +2,11 @@ package models
 
 import (
 	"bytes"
-	"github.com/astaxie/beego"
 	"github.com/astaxie/beego/orm"
 	"html/template"
 	"math"
 	"strconv"
+	"github.com/lifei6671/mindoc/utils"
 )
 
 type DocumentTree struct {
@@ -68,11 +68,11 @@ func (m *Document) CreateDocumentTreeForHtml(book_id, selected_id int) (string,
 	if err != nil {
 		return "", err
 	}
-	parent_id := getSelectedNode(trees, selected_id)
+	parentId := getSelectedNode(trees, selected_id)
 
 	buf := bytes.NewBufferString("")
 
-	getDocumentTree(trees, 0, selected_id, parent_id, buf)
+	getDocumentTree(trees, 0, selected_id, parentId, buf)
 
 	return buf.String(), nil
 
@@ -116,10 +116,10 @@ func getDocumentTree(array []*DocumentTree, parent_id int, selected_id int, sele
 			buf.WriteString(selected_li)
 			buf.WriteString("><a href=\"")
 			if item.Identify != "" {
-				uri := beego.URLFor("DocumentController.Read", ":key", item.BookIdentify, ":id", item.Identify)
+				uri := utils.URLFor("DocumentController.Read", ":key", item.BookIdentify, ":id", item.Identify)
 				buf.WriteString(uri)
 			} else {
-				uri := beego.URLFor("DocumentController.Read", ":key", item.BookIdentify, ":id", item.DocumentId)
+				uri := utils.URLFor("DocumentController.Read", ":key", item.BookIdentify, ":id", item.DocumentId)
 				buf.WriteString(uri)
 			}
 			buf.WriteString("\" title=\"")

+ 4 - 2
utils/pagination/pagination.go

@@ -15,14 +15,16 @@ type Pagination struct {
 	Request *http.Request
 	Total   int
 	Pernum  int
+	BaseUrl string
 }
 
 //NewPagination 新建分页器
-func NewPagination(req *http.Request, total int, pernum int) *Pagination {
+func NewPagination(req *http.Request, total int, pernum int,baseUrl string) *Pagination {
 	return &Pagination{
 		Request: req,
 		Total:   total,
 		Pernum:  pernum,
+		BaseUrl: baseUrl,
 	}
 }
 
@@ -103,7 +105,7 @@ func (p *Pagination) Pages() string {
 //pageURL 生成分页url
 func (p *Pagination) pageURL(page string) string {
 	//基于当前url新建一个url对象
-	u, _ := url.Parse(p.Request.URL.String())
+	u, _ := url.Parse(p.BaseUrl + p.Request.URL.String())
 	q := u.Query()
 	q.Set("page", page)
 	u.RawQuery = q.Encode()

+ 99 - 1
utils/url.go

@@ -1,6 +1,9 @@
 package utils
 
-import "strings"
+import (
+	"strings"
+	"github.com/astaxie/beego"
+)
 
 func JoinURI(elem ...string) string {
 	if len(elem) <= 0 {
@@ -26,3 +29,98 @@ func JoinURI(elem ...string) string {
 	}
 	return uri
 }
+
+//重写生成URL的方法,加上完整的域名
+func URLFor(endpoint string, values ...interface{}) string {
+	baseUrl := beego.AppConfig.DefaultString("baseurl","")
+	pathUrl := beego.URLFor(endpoint, values ...)
+
+	if strings.HasPrefix(pathUrl,"http://") {
+		return pathUrl
+	}
+	if strings.HasPrefix(pathUrl,"/") && strings.HasSuffix(baseUrl,"/") {
+		return baseUrl + pathUrl[1:]
+	}
+	if !strings.HasPrefix(pathUrl,"/") && !strings.HasSuffix(baseUrl,"/") {
+		return baseUrl + "/" + pathUrl
+	}
+	return  baseUrl + beego.URLFor(endpoint, values ...)
+}
+
+func URLForWithCdnImage(p string) string  {
+	if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") {
+		return p
+	}
+	cdn := beego.AppConfig.DefaultString("cdnimg", "")
+	//如果没有设置cdn,则使用baseURL拼接
+	if cdn == "" {
+		baseUrl := beego.AppConfig.DefaultString("baseurl","")
+
+		if strings.HasPrefix(p,"/") && strings.HasSuffix(baseUrl,"/") {
+			return baseUrl + p[1:]
+		}
+		if !strings.HasPrefix(p,"/") && !strings.HasSuffix(baseUrl,"/") {
+			return baseUrl + "/" + p
+		}
+		return  baseUrl + p
+	}
+	if strings.HasPrefix(p, "/") && strings.HasSuffix(cdn, "/") {
+		return cdn + string(p[1:])
+	}
+	if !strings.HasPrefix(p, "/") && !strings.HasSuffix(cdn, "/") {
+		return cdn + "/" + p
+	}
+	return cdn + p
+}
+
+func URLForWithCdnCss (p string) string {
+	cdn := beego.AppConfig.DefaultString("cdncss", "")
+	if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") {
+		return p
+	}
+	//如果没有设置cdn,则使用baseURL拼接
+	if cdn == "" {
+		baseUrl := beego.AppConfig.DefaultString("baseurl","")
+
+		if strings.HasPrefix(p,"/") && strings.HasSuffix(baseUrl,"/") {
+			return baseUrl + p[1:]
+		}
+		if !strings.HasPrefix(p,"/") && !strings.HasSuffix(baseUrl,"/") {
+			return baseUrl + "/" + p
+		}
+		return  baseUrl + p
+	}
+	if strings.HasPrefix(p, "/") && strings.HasSuffix(cdn, "/") {
+		return cdn + string(p[1:])
+	}
+	if !strings.HasPrefix(p, "/") && !strings.HasSuffix(cdn, "/") {
+		return cdn + "/" + p
+	}
+	return cdn + p
+}
+
+func URLForWithCdnJs(p string) string {
+	cdn := beego.AppConfig.DefaultString("cdnjs", "")
+	if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") {
+		return p
+	}
+	//如果没有设置cdn,则使用baseURL拼接
+	if cdn == "" {
+		baseUrl := beego.AppConfig.DefaultString("baseurl","")
+
+		if strings.HasPrefix(p,"/") && strings.HasSuffix(baseUrl,"/") {
+			return baseUrl + p[1:]
+		}
+		if !strings.HasPrefix(p,"/") && !strings.HasSuffix(baseUrl,"/") {
+			return baseUrl + "/" + p
+		}
+		return  baseUrl + p
+	}
+	if strings.HasPrefix(p, "/") && strings.HasSuffix(cdn, "/") {
+		return cdn + string(p[1:])
+	}
+	if !strings.HasPrefix(p, "/") && !strings.HasSuffix(cdn, "/") {
+		return cdn + "/" + p
+	}
+	return cdn + p
+}

+ 4 - 4
views/book/index.tpl

@@ -46,7 +46,7 @@
                         <div class="list-item" v-for="item in lists">
                             <div class="book-title">
                                 <div class="pull-left">
-                                    <a :href="'/book/' + item.identify + '/dashboard'" title="项目概要" data-toggle="tooltip">
+                                    <a :href="'{{.BaseUrl}}/book/' + item.identify + '/dashboard'" title="项目概要" data-toggle="tooltip">
                                        <template v-if="item.privately_owned == 0">
                                            <i class="fa fa-unlock" aria-hidden="true"></i>
                                        </template>
@@ -58,7 +58,7 @@
                                 </div>
                                 <div class="pull-right">
                                     <div class="btn-group">
-                                        <a  :href="'/book/' + item.identify + '/dashboard'" class="btn btn-default">设置</a>
+                                        <a  :href="'{{.BaseUrl}}/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>
@@ -67,7 +67,7 @@
                                         <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">编辑</a></li>
+                                            <li><a :href="'{{.BaseUrl}}/api/' + item.identify + '/edit'" target="_blank">编辑</a></li>
                                             </template>
                                             <template v-if="item.role_id == 0">
                                             <li><a :href="'javascript:deleteBook(\''+item.identify+'\');'">删除</a></li>
@@ -88,7 +88,7 @@
                                         &nbsp;
                                     </template>
                                     <template v-else="">
-                                        <a :href="'/book/' + item.identify + '/dashboard'" title="项目概要" style="font-size: 12px;">
+                                        <a :href="'{{.BaseUrl}}/book/' + item.identify + '/dashboard'" title="项目概要" style="font-size: 12px;">
                                         ${item.description}
                                         </a>
                                     </template>

+ 2 - 2
views/book/setting.tpl

@@ -61,7 +61,7 @@
                             </div>
                             <div class="form-group">
                                 <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="{{urlfor "DocumentController.Index" ":key" .Model.Identify}}" placeholder="项目唯一标识" disabled>
                             </div>
                             <div class="form-group">
                                 <label>历史记录数量</label>
@@ -424,7 +424,7 @@
         try {
             var uploader = WebUploader.create({
                 auto: false,
-                swf: '/static/webuploader/Uploader.swf',
+                swf: '{{.BaseUrl}}/static/webuploader/Uploader.swf',
                 server: '{{urlfor "BookController.UploadCover"}}',
                 formData : { "identify" : {{.Model.Identify}} },
                 pick: "#filePicker",

+ 3 - 3
views/book/users.tpl

@@ -15,8 +15,8 @@
     <!-- 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]>
-    <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="{{cdnjs "/static/html5shiv/3.7.3/html5shiv.min.js"}}"></script>
+    <script src="{{cdnjs "/static/respond.js/1.4.2/respond.min.js"}}"></script>
     <![endif]-->
 </head>
 <body>
@@ -50,7 +50,7 @@
                         </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">
+                                <img :src="item.avatar" onerror="this.src='{{cdnimg "/static/images/middle.gif"}}'" class="img-circle" width="34" height="34">
                                 <span>${item.account}</span>
                                 <span style="font-size: 12px;color: #484848" v-if="item.real_name != ''">[${item.real_name}]</span>
                                 <div class="operate">

+ 1 - 1
views/document/default_read.tpl

@@ -229,7 +229,7 @@
                 <div class="form-group">
                     <label for="password" class="col-sm-2 control-label">项目地址</label>
                     <div class="col-sm-10">
-                        <input type="text" value="{{.BaseUrl}}{{urlfor "DocumentController.Index" ":key" .Model.Identify}}" class="form-control" onmouseover="this.select()" id="projectUrl" title="项目地址">
+                        <input type="text" value="{{urlfor "DocumentController.Index" ":key" .Model.Identify}}" class="form-control" onmouseover="this.select()" id="projectUrl" title="项目地址">
                     </div>
                     <div class="clearfix"></div>
                 </div>

+ 1 - 1
views/manager/users.tpl

@@ -71,7 +71,7 @@
                                 <tbody>
                                 <tr v-for="item in lists">
                                     <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='{{cdnimg "/static/images/middle.gif"}}'" class="img-circle" width="34" height="34"></td>
                                     <td>${item.account}</td>
                                     <td>${item.real_name}</td>
                                     <td>

+ 1 - 1
views/widgets/header.tpl

@@ -1,7 +1,7 @@
 <header class="navbar navbar-static-top navbar-fixed-top manual-header" role="banner">
     <div class="container">
         <div class="navbar-header col-sm-12 col-md-9 col-lg-8">
-            <a href="/" class="navbar-brand" title="{{.SITE_NAME}}">
+            <a href="{{.BaseUrl}}/" class="navbar-brand" title="{{.SITE_NAME}}">
                 {{if .SITE_TITLE}}
                 {{.SITE_TITLE}}
                 {{else}}