diff --git a/controllers/AccountController.go b/controllers/AccountController.go
index 529b2fd7..7fcc5f1a 100644
--- a/controllers/AccountController.go
+++ b/controllers/AccountController.go
@@ -425,7 +425,8 @@ func (c *AccountController) ValidEmail() {
// Logout 退出登录
func (c *AccountController) Logout() {
- c.SetMember(models.Member{})
+ beego.Info("logout")
+ c.SetMember(models.Member{MemberId: 0})
c.SetSecureCookie(conf.GetAppKey(), "login", "", -3600)
diff --git a/controllers/BaseController.go b/controllers/BaseController.go
index d06c783b..176a93d5 100644
--- a/controllers/BaseController.go
+++ b/controllers/BaseController.go
@@ -89,6 +89,7 @@ func (c *MindocBaseController) isUserLoggedIn() bool {
func (c *MindocBaseController) SetMember(member models.Member) {
if member.MemberId <= 0 {
+ beego.Info(member.MemberId)
c.DelSession(conf.LoginSessionName)
c.DelSession("uid")
c.DestroySession()
diff --git a/controllers/attachment.go b/controllers/attachment.go
index 9cafc9e0..78a34bf7 100644
--- a/controllers/attachment.go
+++ b/controllers/attachment.go
@@ -15,6 +15,7 @@ import (
"net/url"
"os"
"path"
+ "regexp"
"strconv"
"strings"
"time"
@@ -1471,10 +1472,19 @@ func (c *AttachController) DownloadAttachment() {
beego.Error(err)
utils.FileLogs.Error(c.Ctx.Input.IP() + " 查询成果路径 " + err.Error())
}
+
fileext := path.Ext(attachment.FileName)
- switch fileext {
- case ".mcdx", ".mctx", ".xmcd", ".mcd":
+ matched, err := regexp.MatchString("\\.*[m|M][c|C][d|D]", fileext)
+ if err != nil {
+ beego.Error(err)
+ }
+ // beego.Info(matched)
+ if matched {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "不能下载mcd文件!"}
+ c.ServeJSON()
return
+ }
+ switch fileext {
case ".JPG", ".jpg", ".png", ".PNG", ".bmp", ".BMP":
// c.Ctx.Output.Download(fileurl + "/" + attachment.FileName)
http.ServeFile(c.Ctx.ResponseWriter, c.Ctx.Request, fileurl+"/"+attachment.FileName)
@@ -1583,7 +1593,7 @@ func (c *AttachController) Attachment() {
if err != nil {
beego.Error(err)
}
- beego.Info(filePath)
+ // beego.Info(filePath)
//attachment/standard/SL/SLZ 5077-2016水工建筑物荷载设计规范.pdf
if strings.Contains(filePath, "?") { //hotqinsessionid=
filePathtemp := strings.Split(filePath, "?")
@@ -1594,7 +1604,14 @@ func (c *AttachController) Attachment() {
array := strings.Split(filepath1, "/")
// beego.Info(array[1])
// beego.Info(fileext)
- if fileext == ".mcdx" || fileext == ".mctx" || fileext == ".xmcd" || fileext == ".mcd" {
+ matched, err := regexp.MatchString("\\.*[m|M][c|C][d|D]", fileext)
+ if err != nil {
+ beego.Error(err)
+ }
+ // beego.Info(matched)
+ if matched {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "不能下载mcd文件!"}
+ c.ServeJSON()
return
}
if array[1] == "standard" || (array[1] == "mathcad" && fileext == ".pdf") {
@@ -1683,6 +1700,7 @@ func (c *AttachController) Attachment() {
//这里缺少权限设置!!!!!!!!!!!
default:
if e.Enforce(useridstring, projurls+"/", c.Ctx.Request.Method, fileext) || isadmin || isme {
+ beego.Info(e.Enforce(useridstring, projurls+"/", c.Ctx.Request.Method, fileext))
http.ServeFile(c.Ctx.ResponseWriter, c.Ctx.Request, filePath) //这样写下载的文件名称不对
// beego.Info(isadmin)
// c.Redirect(url+"/"+attachment.FileName, 302)
@@ -1726,6 +1744,19 @@ func (c *AttachController) GetCarousel() {
if err != nil {
beego.Error(err)
}
+
+ fileext := path.Ext(filePath)
+ matched, err := regexp.MatchString("\\.*[m|M][c|C][d|D]", fileext)
+ if err != nil {
+ beego.Error(err)
+ }
+ // beego.Info(matched)
+ if matched {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "不能下载mcd文件!"}
+ c.ServeJSON()
+ return
+ }
+
http.ServeFile(c.Ctx.ResponseWriter, c.Ctx.Request, filePath)
}
@@ -2018,12 +2049,25 @@ func (c *AttachController) WxPdf() {
beego.Error(err)
}
fileext := path.Ext(attachment.FileName)
+ matched, err := regexp.MatchString("\\.*[m|M][c|C][d|D]", fileext)
+ if err != nil {
+ beego.Error(err)
+ }
+ if matched {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "不能下载mcd文件!"}
+ c.ServeJSON()
+ return
+ }
+
if e.Enforce(useridstring, projurl, c.Ctx.Request.Method, fileext) {
c.Ctx.Output.Download(fileurl + "/" + attachment.FileName)
+ } else {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "权限不够!"}
+ c.ServeJSON()
}
}
} else {
- c.Data["json"] = "未查到openID"
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "未查到openID"}
c.ServeJSON()
}
}
@@ -2049,6 +2093,17 @@ func (c *AttachController) GetWxPdf() {
if err != nil {
beego.Error(err)
}
+ fileext := path.Ext(attachment.FileName)
+ matched, err := regexp.MatchString("\\.*[m|M][c|C][d|D]", fileext)
+ if err != nil {
+ beego.Error(err)
+ }
+ // beego.Info(matched)
+ if matched {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "不能下载mcd文件!"}
+ c.ServeJSON()
+ return
+ }
product, err := models.GetProd(attachment.ProductId)
if err != nil {
@@ -2073,15 +2128,103 @@ func (c *AttachController) GetWxPdf() {
// @Failure 400 Invalid page supplied
// @Failure 404 pdf not found
// @router /getwxmathpdf [get]
-// 下载mathcad pdf计算书,不用权限判断
+// 下载mathcad pdf计算书
func (c *AttachController) GetWxMathPdf() {
-
+ // 加权限判断
+ openID := c.GetSession("openID")
+ if openID != nil {
+ _, err := models.GetUserByOpenID(openID.(string))
+ if err != nil {
+ beego.Error(err)
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "获取用户名错误!"}
+ c.ServeJSON()
+ return
+ }
+ } else {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "用户未登录"}
+ c.ServeJSON()
+ return
+ }
pdflink := c.Input().Get("pdflink")
beego.Info(pdflink)
+ fileext := path.Ext(pdflink)
+ matched, err := regexp.MatchString("\\.*[m|M][c|C][d|D]", fileext)
+ if err != nil {
+ beego.Error(err)
+ }
+ if matched {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "不能下载mcd文件!"}
+ c.ServeJSON()
+ return
+ }
pdflink = strings.Replace(pdflink, "/attachment", "attachment", -1)
c.Ctx.Output.Download(pdflink)
}
+// @Title dowload wx math temp pdf
+// @Description get wx math temp pdf by id
+// @Param id path string true "The url of pdf"
+// @Success 200 {object} models.GetAttachbyId
+// @Failure 400 Invalid page supplied
+// @Failure 404 pdf not found
+// @router /getwxtemppdf/:id [get]
+// 下载mathcad pdf计算书,不用权限判断
+func (c *AttachController) GetWxTempPdf() {
+ // 加权限判断
+ openID := c.GetSession("openID")
+ if openID != nil {
+ // beego.Info(openID.(string))
+ _, err := models.GetUserByOpenID(openID.(string))
+ if err != nil {
+ beego.Error(err)
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "获取用户名错误!"}
+ c.ServeJSON()
+ return
+ }
+ } else {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "用户未登录"}
+ c.ServeJSON()
+ return
+ }
+
+ id := c.Ctx.Input.Param(":id")
+ var usertempleid uint
+ if id != "" {
+ //id转成uint为
+ idint, err := strconv.Atoi(id)
+ if err != nil {
+ beego.Error(err)
+ }
+ usertempleid = uint(idint)
+ }
+
+ usertemple, err := models.GetMathTemple(usertempleid)
+ if err != nil {
+ beego.Error(err)
+ }
+ // beego.Info(usertemple)
+ // 去除文件名
+ filepath := path.Dir(usertemple.TempPath)
+ // 文件名
+ filename := usertemple.TempTitle //path.Base(usertemple.TempPath)
+ // 文件后缀
+ filesuffix := path.Ext(filename)
+ filenameOnly := strings.TrimSuffix(filename, filesuffix) //只留下文件名,无后缀
+ // fileext := path.Ext(pdflink)
+ // matched, err := regexp.MatchString("\\.*[m|M][c|C][d|D]", fileext)
+ // if err != nil {
+ // beego.Error(err)
+ // }
+ // if matched {
+ // c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "不能下载mcd文件!"}
+ // c.ServeJSON()
+ // return
+ // }
+ pdflink := filepath + "/" + filenameOnly + ".pdf"
+ // beego.Info(pdflink)
+ c.Ctx.Output.Download(pdflink)
+}
+
//编码转换
// l3, err3 := url.Parse(c.Ctx.Request.RequestURI[1:])
// if err3 != nil {
diff --git a/controllers/blue_share_controller.go b/controllers/blue_share_controller.go
index 755f8d72..fdeb1ec0 100644
--- a/controllers/blue_share_controller.go
+++ b/controllers/blue_share_controller.go
@@ -20,8 +20,9 @@ import (
"io/ioutil"
// "net/url"
"os"
- // "path"
+ "path"
"path/filepath"
+ "regexp"
"strconv"
"strings"
"time"
@@ -467,6 +468,18 @@ func (c *ShareController) Download() {
}
//这里只下载第一个文件哦!!
if len(attachments) > 0 {
+ fileext := path.Ext(attachments[0].FileName)
+ matched, err := regexp.MatchString("\\.*[m|M][c|C][d|D]", fileext)
+ if err != nil {
+ beego.Error(err)
+ }
+ // beego.Info(matched)
+ if matched {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "不能下载mcd文件!"}
+ c.ServeJSON()
+ return
+ }
+
c.Ctx.Output.Download(fileurl + "/" + attachments[0].FileName)
} else {
c.Data["json"] = map[string]interface{}{"code": err, "msg": "", "data": product}
@@ -686,8 +699,19 @@ func (c *ShareController) DownloadZip() {
}
attachments, err := models.GetAttachments(bridge.ProductId)
for _, v := range attachments {
+ fileext := path.Ext(v.FileName)
+ matched, err := regexp.MatchString("\\.*[m|M][c|C][d|D]", fileext)
+ if err != nil {
+ beego.Error(err)
+ }
+ if matched {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "不能下载mcd文件!"}
+ c.ServeJSON()
+ return
+ }
+
// pathLink = DiskDirectory + "/" + v.FileName
- _, err := CopyFile("./temp/engineercms/"+v.FileName, DiskDirectory+"/"+v.FileName)
+ _, err = CopyFile("./temp/engineercms/"+v.FileName, DiskDirectory+"/"+v.FileName)
//targetfile,sourcefile
if err != nil {
// fmt.Println(err.Error())
diff --git a/controllers/froala.go b/controllers/froala.go
index e10c66fb..552790fb 100644
--- a/controllers/froala.go
+++ b/controllers/froala.go
@@ -360,6 +360,12 @@ func UploadImg(w http.ResponseWriter, r *http.Request) {
//添加文章里的图片上传
func (c *FroalaController) UploadImg() {
+ // 登录
+ _, _, _, _, islogin := checkprodRole(c.Ctx)
+ if !islogin {
+ c.Data["json"] = map[string]interface{}{"state": "ERROR", "data": "用户未登录!"}
+ c.ServeJSON()
+ }
//解析表单
pid := c.Input().Get("pid")
// beego.Info(pid)
diff --git a/controllers/login.go b/controllers/login.go
index 435a8f10..55127047 100644
--- a/controllers/login.go
+++ b/controllers/login.go
@@ -312,6 +312,7 @@ func (c *LoginController) Logout() {
if v != nil {
//删除指定的session
c.DelSession("uname")
+ c.DelSession("uid") //删除mindoc的用户登录信息
//销毁全部的session
// c.DestroySession()
}
diff --git a/controllers/onlyoffice.go b/controllers/onlyoffice.go
index f8f20610..2d2af635 100644
--- a/controllers/onlyoffice.go
+++ b/controllers/onlyoffice.go
@@ -1652,6 +1652,19 @@ func (c *OnlyController) DownloadDoc() {
beego.Info(filePath)
}
filename := filepath.Base(filePath)
+
+ fileext := path.Ext(filename)
+ matched, err := regexp.MatchString("\\.*[m|M][c|C][d|D]", fileext)
+ if err != nil {
+ beego.Error(err)
+ }
+ // beego.Info(matched)
+ if matched {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "不能下载mcd文件!"}
+ c.ServeJSON()
+ return
+ }
+
downloadfile, err = models.GetOnlyAttachbyName(filename)
if err != nil {
beego.Error(err)
@@ -1659,7 +1672,7 @@ func (c *OnlyController) DownloadDoc() {
//1.管理员或者没有设置权限的文档直接可以下载。
police := e.GetFilteredPolicy(1, "/onlyoffice/"+strconv.FormatInt(downloadfile.Id, 10))
- beego.Info(police)
+ // beego.Info(police)
if isadmin || len(police) == 0 {
// c.Ctx.Output.Download(filePath) //这个能保证下载文件名称正确
http.ServeFile(c.Ctx.ResponseWriter, c.Ctx.Request, filePath)
@@ -1668,7 +1681,7 @@ func (c *OnlyController) DownloadDoc() {
//2.取得用户权限
police = e.GetFilteredPolicy(0, strconv.FormatInt(uid, 10), "/onlyoffice/"+strconv.FormatInt(downloadfile.Id, 10))
- beego.Info(police)
+ // beego.Info(police)
for _, v2 := range police {
beego.Info(v2)
v2int, err := strconv.ParseInt(v2[2], 10, 64)
@@ -1685,14 +1698,14 @@ func (c *OnlyController) DownloadDoc() {
//3.取得用户角色——取得角色的权限
userroles := e.GetRolesForUser(strconv.FormatInt(uid, 10))
- beego.Info(userroles)
+ // beego.Info(userroles)
// userrole := make([]Userrole, 0)
// var canidown bool
for _, v1 := range userroles {
police := e.GetFilteredPolicy(0, v1, "/onlyoffice/"+strconv.FormatInt(downloadfile.Id, 10))
- beego.Info(police)
+ // beego.Info(police)
for _, v2 := range police {
- beego.Info(v2)
+ // beego.Info(v2)
v2int, err := strconv.ParseInt(v2[2], 10, 64)
if err != nil {
beego.Error(err)
@@ -1818,6 +1831,19 @@ func (c *OnlyController) Download() {
c.ServeJSON()
return
}
+
+ fileext := path.Ext(attachments[0].FileName)
+ matched, err := regexp.MatchString("\\.*[m|M][c|C][d|D]", fileext)
+ if err != nil {
+ beego.Error(err)
+ }
+ // beego.Info(matched)
+ if matched {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "不能下载mcd文件!"}
+ c.ServeJSON()
+ return
+ }
+
filePath := "attachment/onlyoffice/" + attachments[0].FileName
//管理员或者没有设置权限的文档直接可以下载。
police := e.GetFilteredPolicy(1, "/onlyoffice/"+docid)
diff --git a/controllers/record.go b/controllers/record.go
index 20ce4743..632ad9cb 100644
--- a/controllers/record.go
+++ b/controllers/record.go
@@ -499,6 +499,78 @@ func SubStrings(filenameWithSuffix string) (substr1, substr2 string) {
return fulleFilename1, fulleFilename2
}
+//取得usertemple名称,日期和版本
+func MathcadName(filenameWithSuffix string) (Suffix, FileNumber, FileName, Version string) {
+ beego.Info("文件名:", filenameWithSuffix)
+ FileSuffix := path.Ext(filenameWithSuffix) //只留下后缀名
+ LengthSuffix := len([]rune(FileSuffix))
+ Suffix = SubString(FileSuffix, 1, LengthSuffix-1)
+
+ var filenameOnly string
+ filenameOnly = strings.TrimSuffix(filenameWithSuffix, FileSuffix) //只留下文件名,无后缀
+
+ beego.Info("文件全名:", filenameOnly) //filenameOnly= mai
+ //这个测试一个字符串是否符合一个表达式。
+ // match, _ := regexp.MatchString("p([a-z]+)ch", "peach")
+ // fmt.Println(match)
+ //上面我们是直接使用字符串,但是对于一些其他的正则任务,你需要使用 Compile 一个优化的 Regexp 结构体。
+ // r, _ := regexp.Compile(`[[:upper:]]{2}[0-9]+[[:upper:]\.0-9]+[-][0-9]+[-][0-9]+[\p{Han} \(\)\/~]`)
+ //这个结构体有很多方法。这里是类似我们前面看到的一个匹配测试。
+ // fmt.Println(r.MatchString(filenameOnly))
+ lengthname := len([]rune(filenameOnly))
+ vindex := UnicodeIndex(filenameOnly, "_v") // 查找"_v"这个字符的位置
+ if vindex == 0 {
+ vindex = UnicodeIndex(filenameOnly, "_V")
+ }
+ // beego.Info(vindex)
+ beego.Info("文件名:", filenameOnly)
+ if vindex == 0 {
+ Version = "0.0.0"
+ } else {
+ Version = SubString(filenameOnly, vindex+2, lengthname-vindex-1)
+ filenameOnly = SubString(filenameOnly, 0, vindex)
+ beego.Info("文件名:", filenameOnly)
+ lengthname = len([]rune(filenameOnly))
+ }
+
+ // 查找连续2个的大写字母
+ // reg := regexp.MustCompile(`[[:upper:]]{2}`)
+ // fmt.Printf("大写字母%q\n", reg.FindAllString(filenameOnly, -1))
+ // ["H" "G"]
+ blankloc := UnicodeIndex(filenameOnly, " ") // 查找空格这个字符的位置
+ if blankloc == 0 { //如果没有空格, //如果没有空格,则用正则表达式获取编号
+ re, _ := regexp.Compile("[^a-zA-Z0-9-.~]")
+ loc := re.FindStringIndex(filenameOnly)
+ if loc != nil { //如果有编号——如果没文件名?????
+ FileNumber = SubString(filenameOnly, 0, loc[0])
+ // beego.Info("文件编号:", FileNumber)
+ FileName = SubString(filenameOnly, loc[0], lengthname-loc[0])
+ // beego.Info("文件名:", FileName)
+ } else { //如果没有编号
+ FileNumber = filenameOnly
+ // fmt.Println("文件编号:", FileNumber)
+ FileName = filenameOnly
+ // fmt.Println("文件名:", filenameOnly)
+ }
+ } else { //如果有空格
+ re, _ := regexp.Compile("[^a-zA-Z0-9-.~]")
+ loc := re.FindStringIndex(filenameOnly)
+ if loc != nil { //如果有编号
+ FileNumber = SubString(filenameOnly, 0, loc[0])
+ // fmt.Println("文件编号:", FileNumber)
+ FileName = SubString(filenameOnly, loc[0], lengthname-loc[0])
+ // fmt.Println("文件名:", FileName)
+ } else { //如果没有编号
+ FileNumber = filenameOnly
+ // fmt.Println("文件编号:", FileNumber)
+ FileName = filenameOnly
+ // fmt.Println("文件名:", filenameOnly)
+ }
+ }
+
+ return Suffix, FileNumber, FileName, Version
+}
+
func UnicodeIndex(str, substr string) int {
// 子串在字符串的字节位置
result := strings.Index(str, substr)
diff --git a/controllers/standard.go b/controllers/standard.go
index 17888237..1325e4c8 100644
--- a/controllers/standard.go
+++ b/controllers/standard.go
@@ -6,6 +6,7 @@ import (
"github.com/astaxie/beego/logs"
"github.com/tealeg/xlsx"
"os"
+ "path"
"regexp"
"strconv"
"strings"
@@ -432,6 +433,20 @@ func (c *StandardController) WxStandardPdf() {
// beego.Info(standard.Route)
fileurl := strings.Replace(standard.Route, "/attachment/", "attachment/", -1)
// http.ServeFile(c.Ctx.ResponseWriter, c.Ctx.Request, standard.Route)
+
+ filename := path.Base(fileurl)
+ fileext := path.Ext(filename)
+ matched, err := regexp.MatchString("\\.*[m|M][c|C][d|D]", fileext)
+ if err != nil {
+ beego.Error(err)
+ }
+ // beego.Info(matched)
+ if matched {
+ c.Data["json"] = map[string]interface{}{"info": "ERROR", "data": "不能下载mcd文件!"}
+ c.ServeJSON()
+ return
+ }
+
c.Ctx.Output.Download(fileurl)
}
diff --git a/routers/commentsRouter_controllers.go b/routers/commentsRouter_controllers.go
index 38f65fd4..88adb790 100644
--- a/routers/commentsRouter_controllers.go
+++ b/routers/commentsRouter_controllers.go
@@ -199,6 +199,14 @@ func init() {
MethodParams: param.Make(),
Params: nil})
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:AttachController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:AttachController"],
+ beego.ControllerComments{
+ Method: "GetWxMathPdf",
+ Router: `/getwxmathpdf`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:AttachController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:AttachController"],
beego.ControllerComments{
Method: "GetWxPdf",
@@ -207,6 +215,14 @@ func init() {
MethodParams: param.Make(),
Params: nil})
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:AttachController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:AttachController"],
+ beego.ControllerComments{
+ Method: "GetWxTempPdf",
+ Router: `/getwxtemppdf/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:AttachController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:AttachController"],
beego.ControllerComments{
Method: "GetPdfs",
@@ -295,6 +311,14 @@ func init() {
MethodParams: param.Make(),
Params: nil})
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:BusinessController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:BusinessController"],
+ beego.ControllerComments{
+ Method: "BusinessMonthCheck5",
+ Router: `/businessmonthcheck5/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:BusinessController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:BusinessController"],
beego.ControllerComments{
Method: "BusinessMonthCheckSum",
@@ -327,6 +351,14 @@ func init() {
MethodParams: param.Make(),
Params: nil})
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:BusinessController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:BusinessController"],
+ beego.ControllerComments{
+ Method: "BusinessMonthCheckSum5",
+ Router: `/businessmonthchecksum5`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:BusinessController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:BusinessController"],
beego.ControllerComments{
Method: "GetBysiness",
@@ -407,6 +439,30 @@ func init() {
MethodParams: param.Make(),
Params: nil})
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:ChatController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:ChatController"],
+ beego.ControllerComments{
+ Method: "Avatar",
+ Router: `/avatar/:text`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:ChatController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:ChatController"],
+ beego.ControllerComments{
+ Method: "Chat",
+ Router: `/chat`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:ChatController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:ChatController"],
+ beego.ControllerComments{
+ Method: "HandleConnections",
+ Router: `/wschat`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:CheckController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:CheckController"],
beego.ControllerComments{
Method: "ActInfo",
@@ -1135,6 +1191,38 @@ func init() {
MethodParams: param.Make(),
Params: nil})
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:LocationController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:LocationController"],
+ beego.ControllerComments{
+ Method: "AddLocationNavigate",
+ Router: `/addlocationnavigate/:id`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:LocationController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:LocationController"],
+ beego.ControllerComments{
+ Method: "AddLocationPart",
+ Router: `/addlocationpart/:id`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:LocationController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:LocationController"],
+ beego.ControllerComments{
+ Method: "GetLocation",
+ Router: `/getlocation/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:LocationController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:LocationController"],
+ beego.ControllerComments{
+ Method: "GetLocationById",
+ Router: `/getlocationbyid/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:LoginController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:LoginController"],
beego.ControllerComments{
Method: "Islogin",
@@ -1207,6 +1295,262 @@ func init() {
MethodParams: param.Make(),
Params: nil})
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "AddMathArticles",
+ Router: `/addmatharticle/:id`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "DeleteTemple",
+ Router: `/deletetemple/:id`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "EditorMathArticle",
+ Router: `/editormatharticle/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetWxHistoryTemples",
+ Router: `/getWxhistorytemples/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetHistoryInput",
+ Router: `/gethistoryinput/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetHistoryMath",
+ Router: `/gethistorymath/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetHistoryMathCal",
+ Router: `/gethistorymathcal/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetHistoryOutput",
+ Router: `/gethistoryoutput/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetHistoryTemples",
+ Router: `/gethistorytemples/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetMath",
+ Router: `/getmath/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetTemples",
+ Router: `/getmath/gettemples/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetWxTemples",
+ Router: `/getmath/getwxtemples/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "TempleList",
+ Router: `/getmath/templelist/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetMathCalInput",
+ Router: `/getmathcalinput/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetMathCalOutput",
+ Router: `/getmathcaloutput/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetWxMathCalInput",
+ Router: `/getwxmathcalinput/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetWxMathCalOutput",
+ Router: `/getwxmathcaloutput/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetWxMathClass",
+ Router: `/getwxmathclass/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetMathArticle",
+ Router: `/matharticle/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "MathCal",
+ Router: `/mathcal/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetMathPdf",
+ Router: `/mathpdf/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "PostMath",
+ Router: `/postmath`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "PostMath2",
+ Router: `/postmath2/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "PostMathback",
+ Router: `/postmathback`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "PostWxMath",
+ Router: `/postwxmath`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "PutMathCalInput",
+ Router: `/putmathcalinput`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "PutMathCalOutput",
+ Router: `/putmathcaloutput`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "PutUserTemple",
+ Router: `/putusertemple`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "UpdateArticle",
+ Router: `/updatearticle`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "UploadMathTemple",
+ Router: `/uploadmathtemple/:id`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "UploadTemple",
+ Router: `/uploadtemple/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:MathcadController"],
+ beego.ControllerComments{
+ Method: "GetWxMathArticle",
+ Router: `/wxmatharticle/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:OnlyController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:OnlyController"],
beego.ControllerComments{
Method: "Conversion",
@@ -1223,6 +1567,30 @@ func init() {
MethodParams: param.Make(),
Params: nil})
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
+ beego.ControllerComments{
+ Method: "AddApplyRecharge",
+ Router: `/addapplyrecharge/:id`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
+ beego.ControllerComments{
+ Method: "AddUserPays",
+ Router: `/adduserpays`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
+ beego.ControllerComments{
+ Method: "AddUserRecharge",
+ Router: `/adduserrecharge/:id`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
beego.ControllerComments{
Method: "AddWxUserPays",
@@ -1231,6 +1599,78 @@ func init() {
MethodParams: param.Make(),
Params: nil})
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
+ beego.ControllerComments{
+ Method: "ApplyRecharge",
+ Router: `/applyrecharge`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
+ beego.ControllerComments{
+ Method: "GetApplyRecharge",
+ Router: `/getapplyrecharge`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
+ beego.ControllerComments{
+ Method: "GetApplyRechargeData",
+ Router: `/getapplyrechargedata`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
+ beego.ControllerComments{
+ Method: "GetPay",
+ Router: `/getpay`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
+ beego.ControllerComments{
+ Method: "GetUserGetAppreciations",
+ Router: `/getusergetappreciations`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
+ beego.ControllerComments{
+ Method: "GetUserMoney",
+ Router: `/getusermoney`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
+ beego.ControllerComments{
+ Method: "GetUserPay",
+ Router: `/getuserpay`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
+ beego.ControllerComments{
+ Method: "GetUserPayAppreciations",
+ Router: `/getuserpayappreciations`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
+ beego.ControllerComments{
+ Method: "GetUserPaylist",
+ Router: `/getuserpaylist`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:PayController"],
beego.ControllerComments{
Method: "GetWxPay",
@@ -1335,6 +1775,14 @@ func init() {
MethodParams: param.Make(),
Params: nil})
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:ProjController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:ProjController"],
+ beego.ControllerComments{
+ Method: "QuickAddWxProjTemplet",
+ Router: `/quickaddwxproject`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:ProjController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:ProjController"],
beego.ControllerComments{
Method: "UserpProjectEditorTree",
@@ -1543,6 +1991,14 @@ func init() {
MethodParams: param.Make(),
Params: nil})
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"],
+ beego.ControllerComments{
+ Method: "AddUser",
+ Router: `/adduser`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"],
beego.ControllerComments{
Method: "AddWxUser",
@@ -1551,6 +2007,38 @@ func init() {
MethodParams: param.Make(),
Params: nil})
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"],
+ beego.ControllerComments{
+ Method: "DeleteUser",
+ Router: `/deleteuser`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"],
+ beego.ControllerComments{
+ Method: "GetUserByUsername",
+ Router: `/getuserbyusername`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"],
+ beego.ControllerComments{
+ Method: "ImportUsers",
+ Router: `/importusers`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"],
+ beego.ControllerComments{
+ Method: "UpdateUser",
+ Router: `/updateuser`,
+ AllowHTTPMethods: []string{"post"},
+ MethodParams: param.Make(),
+ Params: nil})
+
beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"],
beego.ControllerComments{
Method: "UpdateWxUser",
@@ -1559,6 +2047,22 @@ func init() {
MethodParams: param.Make(),
Params: nil})
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"],
+ beego.ControllerComments{
+ Method: "User",
+ Router: `/user/:id`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
+ beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:UserController"],
+ beego.ControllerComments{
+ Method: "Usermyself",
+ Router: `/usermyself`,
+ AllowHTTPMethods: []string{"get"},
+ MethodParams: param.Make(),
+ Params: nil})
+
beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:VideoController"] = append(beego.GlobalControllerRouter["github.com/3xxx/engineercms/controllers:VideoController"],
beego.ControllerComments{
Method: "GetUserVideo",
diff --git a/static/js/bootstrap-editable1.5.3.js b/static/js/bootstrap-editable1.5.3.js
new file mode 100644
index 00000000..6c8b941e
--- /dev/null
+++ b/static/js/bootstrap-editable1.5.3.js
@@ -0,0 +1,6993 @@
+/*! X-editable - v1.5.3
+* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
+* http://github.com/vitalets/x-editable
+* Copyright (c) 2019 Vitaliy Potapov; Licensed MIT */
+/**
+Form with single input element, two buttons and two states: normal/loading.
+Applied as jQuery method to DIV tag (not to form tag!). This is because form can be in loading state when spinner shown.
+Editableform is linked with one of input types, e.g. 'text', 'select' etc.
+@class editableform
+@uses text
+@uses textarea
+**/
+(function ($) {
+ "use strict";
+
+ var EditableForm = function (div, options) {
+ this.options = $.extend({}, $.fn.editableform.defaults, options);
+ this.$div = $(div); //div, containing form. Not form tag. Not editable-element.
+ if(!this.options.scope) {
+ this.options.scope = this;
+ }
+ //nothing shown after init
+ };
+
+ EditableForm.prototype = {
+ constructor: EditableForm,
+ initInput: function() { //called once
+ //take input from options (as it is created in editable-element)
+ this.input = this.options.input;
+
+ //set initial value
+ //todo: may be add check: typeof str === 'string' ?
+ this.value = this.input.str2value(this.options.value);
+
+ //prerender: get input.$input
+ this.input.prerender();
+ },
+ initTemplate: function() {
+ this.$form = $($.fn.editableform.template);
+ },
+ initButtons: function() {
+ var $btn = this.$form.find('.editable-buttons');
+ $btn.append($.fn.editableform.buttons);
+ if(this.options.showbuttons === 'bottom') {
+ $btn.addClass('editable-buttons-bottom');
+ }
+ },
+ /**
+ Renders editableform
+ @method render
+ **/
+ render: function() {
+ //init loader
+ this.$loading = $($.fn.editableform.loading);
+ this.$div.empty().append(this.$loading);
+
+ //init form template and buttons
+ this.initTemplate();
+ if(this.options.showbuttons) {
+ this.initButtons();
+ } else {
+ this.$form.find('.editable-buttons').remove();
+ }
+
+ //show loading state
+ this.showLoading();
+
+ //flag showing is form now saving value to server.
+ //It is needed to wait when closing form.
+ this.isSaving = false;
+
+ /**
+ Fired when rendering starts
+ @event rendering
+ @param {Object} event event object
+ **/
+ this.$div.triggerHandler('rendering');
+
+ //init input
+ this.initInput();
+
+ //append input to form
+ this.$form.find('div.editable-input').append(this.input.$tpl);
+
+ //append form to container
+ this.$div.append(this.$form);
+
+ //render input
+ $.when(this.input.render())
+ .then($.proxy(function () {
+ //setup input to submit automatically when no buttons shown
+ if(!this.options.showbuttons) {
+ this.input.autosubmit();
+ }
+
+ //attach 'cancel' handler
+ this.$form.find('.editable-cancel').click($.proxy(this.cancel, this));
+
+ if(this.input.error) {
+ this.error(this.input.error);
+ this.$form.find('.editable-submit').attr('disabled', true);
+ this.input.$input.attr('disabled', true);
+ //prevent form from submitting
+ this.$form.submit(function(e){ e.preventDefault(); });
+ } else {
+ this.error(false);
+ this.input.$input.removeAttr('disabled');
+ this.$form.find('.editable-submit').removeAttr('disabled');
+ var value = (this.value === null || this.value === undefined || this.value === '') ? this.options.defaultValue : this.value;
+ this.input.value2input(value);
+ //attach submit handler
+ this.$form.submit($.proxy(this.submit, this));
+ }
+
+ /**
+ Fired when form is rendered
+ @event rendered
+ @param {Object} event event object
+ **/
+ this.$div.triggerHandler('rendered');
+
+ this.showForm();
+
+ //call postrender method to perform actions required visibility of form
+ if(this.input.postrender) {
+ this.input.postrender();
+ }
+ }, this));
+ },
+ cancel: function() {
+ /**
+ Fired when form was cancelled by user
+ @event cancel
+ @param {Object} event event object
+ **/
+ this.$div.triggerHandler('cancel');
+ },
+ showLoading: function() {
+ var w, h;
+ if(this.$form) {
+ //set loading size equal to form
+ w = this.$form.outerWidth();
+ h = this.$form.outerHeight();
+ if(w) {
+ this.$loading.width(w);
+ }
+ if(h) {
+ this.$loading.height(h);
+ }
+ this.$form.hide();
+ } else {
+ //stretch loading to fill container width
+ w = this.$loading.parent().width();
+ if(w) {
+ this.$loading.width(w);
+ }
+ }
+ this.$loading.show();
+ },
+
+ showForm: function(activate) {
+ this.$loading.hide();
+ this.$form.show();
+ if(activate !== false) {
+ this.input.activate();
+ }
+ /**
+ Fired when form is shown
+ @event show
+ @param {Object} event event object
+ **/
+ this.$div.triggerHandler('show');
+ },
+
+ error: function(msg) {
+ var $group = this.$form.find('.control-group'),
+ $block = this.$form.find('.editable-error-block'),
+ lines;
+
+ if(msg === false) {
+ $group.removeClass($.fn.editableform.errorGroupClass);
+ $block.removeClass($.fn.editableform.errorBlockClass).empty().hide();
+ } else {
+ //convert newline to
for more pretty error display
+ if(msg) {
+ lines = (''+msg).split('\n');
+ for (var i = 0; i < lines.length; i++) {
+ lines[i] = $('
text|textarea|select|date|checklist
+ @property type
+ @type string
+ @default 'text'
+ **/
+ type: 'text',
+ /**
+ Url for submit, e.g. '/post'
+ If function - it will be called instead of ajax. Function should return deferred object to run fail/done callbacks.
+ @property url
+ @type string|function
+ @default null
+ @example
+ url: function(params) {
+ var d = new $.Deferred;
+ if(params.value === 'abc') {
+ return d.reject('error message'); //returning error via deferred object
+ } else {
+ //async saving data in js model
+ someModel.asyncSaveMethod({
+ ...,
+ success: function(){
+ d.resolve();
+ }
+ });
+ return d.promise();
+ }
+ }
+ **/
+ url:null,
+ /**
+ Additional params for submit. If defined as object
- it is **appended** to original ajax data (pk, name and value).
+ If defined as function
- returned object **overwrites** original ajax data.
+ @example
+ params: function(params) {
+ //originally params contain pk, name and value
+ params.a = 1;
+ return params;
+ }
+ @property params
+ @type object|function
+ @default null
+ **/
+ params:null,
+ /**
+ Name of field. Will be submitted on server. Can be taken from id
attribute
+ @property name
+ @type string
+ @default null
+ **/
+ name: null,
+ /**
+ Primary key of editable object (e.g. record id in database). For composite keys use object, e.g. {id: 1, lang: 'en'}
.
+ Can be calculated dynamically via function.
+ @property pk
+ @type string|object|function
+ @default null
+ **/
+ pk: null,
+ /**
+ Initial value. If not defined - will be taken from element's content.
+ For __select__ type should be defined (as it is ID of shown text).
+ @property value
+ @type string|object
+ @default null
+ **/
+ value: null,
+ /**
+ Value that will be displayed in input if original field value is empty (`null|undefined|''`).
+ @property defaultValue
+ @type string|object
+ @default null
+ @since 1.4.6
+ **/
+ defaultValue: null,
+ /**
+ Strategy for sending data on server. Can be `auto|always|never`.
+ When 'auto' data will be sent on server **only if pk and url defined**, otherwise new value will be stored locally.
+ @property send
+ @type string
+ @default 'auto'
+ **/
+ send: 'auto',
+ /**
+ Function for client-side validation. If returns string - means validation not passed and string showed as error.
+ Since 1.5.1 you can modify submitted value by returning object from `validate`:
+ `{newValue: '...'}` or `{newValue: '...', msg: '...'}`
+ @property validate
+ @type function
+ @default null
+ @example
+ validate: function(value) {
+ if($.trim(value) == '') {
+ return 'This field is required';
+ }
+ }
+ **/
+ validate: null,
+ /**
+ Success callback. Called when value successfully sent on server and **response status = 200**.
+ Usefull to work with json response. For example, if your backend response can be {success: true}
+ or `{success: false, msg: "server error"}` you can check it inside this callback.
+ If it returns **string** - means error occured and string is shown as error message.
+ If it returns **object like** `{newValue: <something>}` - it overwrites value, submitted by user
+ (useful when server changes value).
+ Otherwise newValue simply rendered into element.
+
+ @property success
+ @type function
+ @default null
+ @example
+ success: function(response, newValue) {
+ if(!response.success) return response.msg;
+ }
+ **/
+ success: null,
+ /**
+ Error callback. Called when request failed (response status != 200).
+ Usefull when you want to parse error response and display a custom message.
+ Must return **string** - the message to be displayed in the error block.
+
+ @property error
+ @type function
+ @default null
+ @since 1.4.4
+ @example
+ error: function(response, newValue) {
+ if(response.status === 500) {
+ return 'Service unavailable. Please try later.';
+ } else {
+ return response.responseText;
+ }
+ }
+ **/
+ error: null,
+ /**
+ Additional options for submit ajax request.
+ List of values: http://api.jquery.com/jQuery.ajax
+
+ @property ajaxOptions
+ @type object
+ @default null
+ @since 1.1.1
+ @example
+ ajaxOptions: {
+ type: 'put',
+ dataType: 'json'
+ }
+ **/
+ ajaxOptions: null,
+ /**
+ Where to show buttons: left(true)|bottom|false
+ Form without buttons is auto-submitted.
+ @property showbuttons
+ @type boolean|string
+ @default true
+ @since 1.1.1
+ **/
+ showbuttons: true,
+ /**
+ Scope for callback methods (success, validate).
+ If null
means editableform instance itself.
+ @property scope
+ @type DOMElement|object
+ @default null
+ @since 1.2.0
+ @private
+ **/
+ scope: null,
+ /**
+ Whether to save or cancel value when it was not changed but form was submitted
+ @property savenochange
+ @type boolean
+ @default false
+ @since 1.2.0
+ **/
+ savenochange: false
+ };
+
+ /*
+ Note: following params could redefined in engine: bootstrap or jqueryui:
+ Classes 'control-group' and 'editable-error-block' must always present!
+ */
+ $.fn.editableform.template = '';
+
+ //loading div
+ $.fn.editableform.loading = '';
+
+ //buttons
+ $.fn.editableform.buttons = ''+
+ '';
+
+ //error class attached to control-group
+ $.fn.editableform.errorGroupClass = null;
+
+ //error class attached to editable-error-block
+ $.fn.editableform.errorBlockClass = 'editable-error';
+
+ //engine
+ $.fn.editableform.engine = 'jquery';
+}(window.jQuery));
+
+/**
+* EditableForm utilites
+*/
+(function ($) {
+ "use strict";
+
+ //utils
+ $.fn.editableutils = {
+ /**
+ * classic JS inheritance function
+ */
+ inherit: function (Child, Parent) {
+ var F = function() { };
+ F.prototype = Parent.prototype;
+ Child.prototype = new F();
+ Child.prototype.constructor = Child;
+ Child.superclass = Parent.prototype;
+ },
+
+ /**
+ * set caret position in input
+ * see http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area
+ */
+ setCursorPosition: function(elem, pos) {
+ // see: https://github.com/vitalets/x-editable/issues/939
+ if (elem.setSelectionRange && /text|search|password|tel|url/i.test(elem.type)) {
+ try { elem.setSelectionRange(pos, pos); } catch (e) {}
+ } else if (elem.createTextRange) {
+ var range = elem.createTextRange();
+ range.collapse(true);
+ range.moveEnd('character', pos);
+ range.moveStart('character', pos);
+ range.select();
+ }
+ },
+
+ /**
+ * function to parse JSON in *single* quotes. (jquery automatically parse only double quotes)
+ * That allows such code as:
+ * safe = true --> means no exception will be thrown
+ * for details see http://stackoverflow.com/questions/7410348/how-to-set-json-format-to-html5-data-attributes-in-the-jquery
+ */
+ tryParseJson: function(s, safe) {
+ if (typeof s === 'string' && s.length && s.match(/^[\{\[].*[\}\]]$/)) {
+ if (safe) {
+ try {
+ /*jslint evil: true*/
+ s = (new Function('return ' + s))();
+ /*jslint evil: false*/
+ } catch (e) {} finally {
+ return s;
+ }
+ } else {
+ /*jslint evil: true*/
+ s = (new Function('return ' + s))();
+ /*jslint evil: false*/
+ }
+ }
+ return s;
+ },
+
+ /**
+ * slice object by specified keys
+ */
+ sliceObj: function(obj, keys, caseSensitive /* default: false */) {
+ var key, keyLower, newObj = {};
+
+ if (!$.isArray(keys) || !keys.length) {
+ return newObj;
+ }
+
+ for (var i = 0; i < keys.length; i++) {
+ key = keys[i];
+ if (obj.hasOwnProperty(key)) {
+ newObj[key] = obj[key];
+ }
+
+ if(caseSensitive === true) {
+ continue;
+ }
+
+ //when getting data-* attributes via $.data() it's converted to lowercase.
+ //details: http://stackoverflow.com/questions/7602565/using-data-attributes-with-jquery
+ //workaround is code below.
+ keyLower = key.toLowerCase();
+ if (obj.hasOwnProperty(keyLower)) {
+ newObj[key] = obj[keyLower];
+ }
+ }
+
+ return newObj;
+ },
+
+ /*
+ exclude complex objects from $.data() before pass to config
+ */
+ getConfigData: function($element) {
+ var data = {};
+ $.each($element[0].dataset, function(k, v) {
+ if(typeof v !== 'object' || (v && typeof v === 'object' && (v.constructor === Object || v.constructor === Array))) {
+ data[k] = v;
+ }
+ });
+ return data;
+ },
+
+ /*
+ returns keys of object
+ */
+ objectKeys: function(o) {
+ if (Object.keys) {
+ return Object.keys(o);
+ } else {
+ if (o !== Object(o)) {
+ throw new TypeError('Object.keys called on a non-object');
+ }
+ var k=[], p;
+ for (p in o) {
+ if (Object.prototype.hasOwnProperty.call(o,p)) {
+ k.push(p);
+ }
+ }
+ return k;
+ }
+
+ },
+
+ /**
+ method to escape html.
+ **/
+ escape: function(str) {
+ return $('$().editable()
. You should subscribe on it's events (save / cancel) to get profit of it.save|cancel|onblur|nochange|undefined (=manual)
+ **/
+ hide: function(reason) {
+ if(!this.tip() || !this.tip().is(':visible') || !this.$element.hasClass('editable-open')) {
+ return;
+ }
+
+ //if form is saving value, schedule hide
+ if(this.$form.data('editableform').isSaving) {
+ this.delayedHide = {reason: reason};
+ return;
+ } else {
+ this.delayedHide = false;
+ }
+
+ this.$element.removeClass('editable-open');
+ this.innerHide();
+
+ /**
+ Fired when container was hidden. It occurs on both save or cancel.
+ **Note:** Bootstrap popover has own `hidden` event that now cannot be separated from x-editable's one.
+ The workaround is to check `arguments.length` that is always `2` for x-editable.
+ @event hidden
+ @param {object} event event object
+ @param {string} reason Reason caused hiding. Can be save|cancel|onblur|nochange|manual
+ @example
+ $('#username').on('hidden', function(e, reason) {
+ if(reason === 'save' || reason === 'cancel') {
+ //auto-open next editable
+ $(this).closest('tr').next().find('.editable').editable('show');
+ }
+ });
+ **/
+ this.$element.triggerHandler('hidden', reason || 'manual');
+ },
+
+ /* internal show method. To be overwritten in child classes */
+ innerShow: function () {
+
+ },
+
+ /* internal hide method. To be overwritten in child classes */
+ innerHide: function () {
+
+ },
+
+ /**
+ Toggles container visibility (show / hide)
+ @method toggle()
+ @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
+ **/
+ toggle: function(closeAll) {
+ if(this.container() && this.tip() && this.tip().is(':visible')) {
+ this.hide();
+ } else {
+ this.show(closeAll);
+ }
+ },
+
+ /*
+ Updates the position of container when content changed.
+ @method setPosition()
+ */
+ setPosition: function() {
+ //tbd in child class
+ },
+
+ save: function(e, params) {
+ /**
+ Fired when new value was submitted. You can use $(this).data('editableContainer')
inside handler to access to editableContainer instance
+
+ @event save
+ @param {Object} event event object
+ @param {Object} params additional params
+ @param {mixed} params.newValue submitted value
+ @param {Object} params.response ajax response
+ @example
+ $('#username').on('save', function(e, params) {
+ //assuming server response: '{success: true}'
+ var pk = $(this).data('editableContainer').options.pk;
+ if(params.response && params.response.success) {
+ alert('value: ' + params.newValue + ' with pk: ' + pk + ' saved!');
+ } else {
+ alert('error!');
+ }
+ });
+ **/
+ this.$element.triggerHandler('save', params);
+
+ //hide must be after trigger, as saving value may require methods of plugin, applied to input
+ this.hide('save');
+ },
+
+ /**
+ Sets new option
+
+ @method option(key, value)
+ @param {string} key
+ @param {mixed} value
+ **/
+ option: function(key, value) {
+ this.options[key] = value;
+ if(key in this.containerOptions) {
+ this.containerOptions[key] = value;
+ this.setContainerOption(key, value);
+ } else {
+ this.formOptions[key] = value;
+ if(this.$form) {
+ this.$form.editableform('option', key, value);
+ }
+ }
+ },
+
+ setContainerOption: function(key, value) {
+ this.call('option', key, value);
+ },
+
+ /**
+ Destroys the container instance
+ @method destroy()
+ **/
+ destroy: function() {
+ this.hide();
+ this.innerDestroy();
+ this.$element.off('destroyed');
+ this.$element.removeData('editableContainer');
+ },
+
+ /* to be overwritten in child classes */
+ innerDestroy: function() {
+
+ },
+
+ /*
+ Closes other containers except one related to passed element.
+ Other containers can be cancelled or submitted (depends on onblur option)
+ */
+ closeOthers: function(element) {
+ $('.editable-open').each(function(i, el){
+ //do nothing with passed element and it's children
+ if(el === element || $(el).find(element).length) {
+ return;
+ }
+
+ //otherwise cancel or submit all open containers
+ var $el = $(el),
+ ec = $el.data('editableContainer');
+
+ if(!ec) {
+ return;
+ }
+
+ if(ec.options.onblur === 'cancel') {
+ $el.data('editableContainer').hide('onblur');
+ } else if(ec.options.onblur === 'submit') {
+ $el.data('editableContainer').tip().find('form').submit();
+ }
+ });
+
+ },
+
+ /**
+ Activates input of visible container (e.g. set focus)
+ @method activate()
+ **/
+ activate: function() {
+ if(this.tip && this.tip().is(':visible') && this.$form) {
+ this.$form.data('editableform').input.activate();
+ }
+ }
+
+ };
+
+ /**
+ jQuery method to initialize editableContainer.
+
+ @method $().editableContainer(options)
+ @params {Object} options
+ @example
+ $('#edit').editableContainer({
+ type: 'text',
+ url: '/post',
+ pk: 1,
+ value: 'hello'
+ });
+ **/
+ $.fn.editableContainer = function (option) {
+ var args = arguments;
+ return this.each(function () {
+ var $this = $(this),
+ dataKey = 'editableContainer',
+ data = $this.data(dataKey),
+ options = typeof option === 'object' && option,
+ Constructor = (options.mode === 'inline') ? Inline : Popup;
+
+ if (!data) {
+ $this.data(dataKey, (data = new Constructor(this, options)));
+ }
+
+ if (typeof option === 'string') { //call method
+ data[option].apply(data, Array.prototype.slice.call(args, 1));
+ }
+ });
+ };
+
+ //store constructors
+ $.fn.editableContainer.Popup = Popup;
+ $.fn.editableContainer.Inline = Inline;
+
+ //defaults
+ $.fn.editableContainer.defaults = {
+ /**
+ Initial value of form input
+ @property value
+ @type mixed
+ @default null
+ @private
+ **/
+ value: null,
+ /**
+ Placement of container relative to element. Can be top|right|bottom|left
. Not used for inline container.
+ @property placement
+ @type string
+ @default 'top'
+ **/
+ placement: 'top',
+ /**
+ Whether to hide container on save/cancel.
+ @property autohide
+ @type boolean
+ @default true
+ @private
+ **/
+ autohide: true,
+ /**
+ Action when user clicks outside the container. Can be cancel|submit|ignore
.
+ Setting ignore
allows to have several containers open.
+ @property onblur
+ @type string
+ @default 'cancel'
+ @since 1.1.1
+ **/
+ onblur: 'cancel',
+
+ /**
+ Animation speed (inline mode only)
+ @property anim
+ @type string
+ @default false
+ **/
+ anim: false,
+
+ /**
+ Mode of editable, can be `popup` or `inline`
+
+ @property mode
+ @type string
+ @default 'popup'
+ @since 1.4.0
+ **/
+ mode: 'popup'
+ };
+
+ /*
+ * workaround to have 'destroyed' event to destroy popover when element is destroyed
+ * see http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom
+ */
+ jQuery.event.special.destroyed = {
+ remove: function(o) {
+ if (o.handler) {
+ o.handler();
+ }
+ }
+ };
+
+}(window.jQuery));
+
+/**
+* Editable Inline
+* ---------------------
+*/
+(function ($) {
+ "use strict";
+
+ //copy prototype from EditableContainer
+ //extend methods
+ $.extend($.fn.editableContainer.Inline.prototype, $.fn.editableContainer.Popup.prototype, {
+ containerName: 'editableform',
+ innerCss: '.editable-inline',
+ containerClass: 'editable-container editable-inline', //css class applied to container element
+
+ initContainer: function(){
+ //container is element
+ this.$tip = $('');
+
+ //convert anim to miliseconds (int)
+ if(!this.options.anim) {
+ this.options.anim = 0;
+ }
+ },
+
+ splitOptions: function() {
+ //all options are passed to form
+ this.containerOptions = {};
+ this.formOptions = this.options;
+ },
+
+ tip: function() {
+ return this.$tip;
+ },
+
+ innerShow: function () {
+ this.$element.hide();
+ this.tip().insertAfter(this.$element).show();
+ },
+
+ innerHide: function () {
+ this.$tip.hide(this.options.anim, $.proxy(function() {
+ this.$element.show();
+ this.innerDestroy();
+ }, this));
+ },
+
+ innerDestroy: function() {
+ if(this.tip()) {
+ this.tip().empty().remove();
+ }
+ }
+ });
+
+}(window.jQuery));
+/**
+Makes editable any HTML element on the page. Applied as jQuery method.
+@class editable
+@uses editableContainer
+**/
+(function ($) {
+ "use strict";
+
+ var Editable = function (element, options) {
+ this.$element = $(element);
+ //data-* has more priority over js options: because dynamically created elements may change data-*
+ this.options = $.extend({}, $.fn.editable.defaults, options, $.fn.editableutils.getConfigData(this.$element));
+ if(this.options.selector) {
+ this.initLive();
+ } else {
+ this.init();
+ }
+
+ //check for transition support
+ if(this.options.highlight && !$.fn.editableutils.supportsTransitions()) {
+ this.options.highlight = false;
+ }
+ };
+
+ Editable.prototype = {
+ constructor: Editable,
+ init: function () {
+ var isValueByText = false,
+ doAutotext, finalize;
+
+ //name
+ this.options.name = this.options.name || this.$element.attr('id');
+
+ //create input of specified type. Input needed already here to convert value for initial display (e.g. show text by id for select)
+ //also we set scope option to have access to element inside input specific callbacks (e. g. source as function)
+ this.options.scope = this.$element[0];
+ this.input = $.fn.editableutils.createInput(this.options);
+ if(!this.input) {
+ return;
+ }
+
+ //set value from settings or by element's text
+ if (this.options.value === undefined || this.options.value === null) {
+ this.value = this.input.html2value($.trim(this.$element.html()));
+ isValueByText = true;
+ } else {
+ /*
+ value can be string when received from 'data-value' attribute
+ for complext objects value can be set as json string in data-value attribute,
+ e.g. data-value="{city: 'Moscow', street: 'Lenina'}"
+ */
+ this.options.value = $.fn.editableutils.tryParseJson(this.options.value, true);
+ if(typeof this.options.value === 'string') {
+ this.value = this.input.str2value(this.options.value);
+ } else {
+ this.value = this.options.value;
+ }
+ }
+
+ //add 'editable' class to every editable element
+ this.$element.addClass('editable');
+
+ //specifically for "textarea" add class .editable-pre-wrapped to keep linebreaks
+ if(this.input.type === 'textarea') {
+ this.$element.addClass('editable-pre-wrapped');
+ }
+
+ //attach handler activating editable. In disabled mode it just prevent default action (useful for links)
+ if(this.options.toggle !== 'manual') {
+ this.$element.addClass('editable-click');
+ this.$element.on(this.options.toggle + '.editable', $.proxy(function(e){
+ //prevent following link if editable enabled
+ if(!this.options.disabled) {
+ e.preventDefault();
+ }
+
+ //stop propagation not required because in document click handler it checks event target
+ //e.stopPropagation();
+
+ if(this.options.toggle === 'mouseenter') {
+ //for hover only show container
+ this.show();
+ } else {
+ //when toggle='click' we should not close all other containers as they will be closed automatically in document click listener
+ var closeAll = (this.options.toggle !== 'click');
+ this.toggle(closeAll);
+ }
+ }, this));
+ } else {
+ this.$element.attr('tabindex', -1); //do not stop focus on element when toggled manually
+ }
+
+ //if display is function it's far more convinient to have autotext = always to render correctly on init
+ //see https://github.com/vitalets/x-editable-yii/issues/34
+ if(typeof this.options.display === 'function') {
+ this.options.autotext = 'always';
+ }
+
+ //check conditions for autotext:
+ switch(this.options.autotext) {
+ case 'always':
+ doAutotext = true;
+ break;
+ case 'auto':
+ //if element text is empty and value is defined and value not generated by text --> run autotext
+ doAutotext = !$.trim(this.$element.text()).length && this.value !== null && this.value !== undefined && !isValueByText;
+ break;
+ default:
+ doAutotext = false;
+ }
+
+ //depending on autotext run render() or just finilize init
+ $.when(doAutotext ? this.render() : true).then($.proxy(function() {
+ if(this.options.disabled) {
+ this.disable();
+ } else {
+ this.enable();
+ }
+ /**
+ Fired when element was initialized by `$().editable()` method.
+ Please note that you should setup `init` handler **before** applying `editable`.
+
+ @event init
+ @param {Object} event event object
+ @param {Object} editable editable instance (as here it cannot accessed via data('editable'))
+ @since 1.2.0
+ @example
+ $('#username').on('init', function(e, editable) {
+ alert('initialized ' + editable.options.name);
+ });
+ $('#username').editable();
+ **/
+ this.$element.triggerHandler('init', this);
+ }, this));
+ },
+
+ /*
+ Initializes parent element for live editables
+ */
+ initLive: function() {
+ //store selector
+ var selector = this.options.selector;
+ //modify options for child elements
+ this.options.selector = false;
+ this.options.autotext = 'never';
+ //listen toggle events
+ this.$element.on(this.options.toggle + '.editable', selector, $.proxy(function(e){
+ var $target = $(e.target).closest(selector);
+ if(!$target.data('editable')) {
+ //if delegated element initially empty, we need to clear it's text (that was manually set to `empty` by user)
+ //see https://github.com/vitalets/x-editable/issues/137
+ if($target.hasClass(this.options.emptyclass)) {
+ $target.empty();
+ }
+ $target.editable(this.options).trigger(e);
+ }
+ }, this));
+ },
+
+ /*
+ Renders value into element's text.
+ Can call custom display method from options.
+ Can return deferred object.
+ @method render()
+ @param {mixed} response server response (if exist) to pass into display function
+ */
+ render: function(response) {
+ //do not display anything
+ if(this.options.display === false) {
+ return;
+ }
+
+ //if input has `value2htmlFinal` method, we pass callback in third param to be called when source is loaded
+ if(this.input.value2htmlFinal) {
+ return this.input.value2html(this.value, this.$element[0], this.options.display, response);
+ //if display method defined --> use it
+ } else if(typeof this.options.display === 'function') {
+ return this.options.display.call(this.$element[0], this.value, response);
+ //else use input's original value2html() method
+ } else {
+ return this.input.value2html(this.value, this.$element[0]);
+ }
+ },
+
+ /**
+ Enables editable
+ @method enable()
+ **/
+ enable: function() {
+ this.options.disabled = false;
+ this.$element.removeClass('editable-disabled');
+ this.handleEmpty(this.isEmpty);
+ if(this.options.toggle !== 'manual') {
+ if(this.$element.attr('tabindex') === '-1') {
+ this.$element.removeAttr('tabindex');
+ }
+ }
+ },
+
+ /**
+ Disables editable
+ @method disable()
+ **/
+ disable: function() {
+ this.options.disabled = true;
+ this.hide();
+ this.$element.addClass('editable-disabled');
+ this.handleEmpty(this.isEmpty);
+ //do not stop focus on this element
+ this.$element.attr('tabindex', -1);
+ },
+
+ /**
+ Toggles enabled / disabled state of editable element
+ @method toggleDisabled()
+ **/
+ toggleDisabled: function() {
+ if(this.options.disabled) {
+ this.enable();
+ } else {
+ this.disable();
+ }
+ },
+
+ /**
+ Sets new option
+
+ @method option(key, value)
+ @param {string|object} key option name or object with several options
+ @param {mixed} value option new value
+ @example
+ $('.editable').editable('option', 'pk', 2);
+ **/
+ option: function(key, value) {
+ //set option(s) by object
+ if(key && typeof key === 'object') {
+ $.each(key, $.proxy(function(k, v){
+ this.option($.trim(k), v);
+ }, this));
+ return;
+ }
+
+ //set option by string
+ this.options[key] = value;
+
+ //disabled
+ if(key === 'disabled') {
+ return value ? this.disable() : this.enable();
+ }
+
+ //value
+ if(key === 'value') {
+ this.setValue(value);
+ }
+
+ //transfer new option to container!
+ if(this.container) {
+ this.container.option(key, value);
+ }
+
+ //pass option to input directly (as it points to the same in form)
+ if(this.input.option) {
+ this.input.option(key, value);
+ }
+
+ },
+
+ /*
+ * set emptytext if element is empty
+ */
+ handleEmpty: function (isEmpty) {
+ //do not handle empty if we do not display anything
+ if(this.options.display === false) {
+ return;
+ }
+
+ /*
+ isEmpty may be set directly as param of method.
+ It is required when we enable/disable field and can't rely on content
+ as node content is text: "Empty" that is not empty %)
+ */
+ if(isEmpty !== undefined) {
+ this.isEmpty = isEmpty;
+ } else {
+ //detect empty
+ //for some inputs we need more smart check
+ //e.g. wysihtml5 may have $(this).data('editable')
to access to editable instance
+
+ @event save
+ @param {Object} event event object
+ @param {Object} params additional params
+ @param {mixed} params.newValue submitted value
+ @param {Object} params.response ajax response
+ @example
+ $('#username').on('save', function(e, params) {
+ alert('Saved value: ' + params.newValue);
+ });
+ **/
+ //event itself is triggered by editableContainer. Description here is only for documentation
+ },
+
+ validate: function () {
+ if (typeof this.options.validate === 'function') {
+ return this.options.validate.call(this, this.value);
+ }
+ },
+
+ /**
+ Sets new value of editable
+ @method setValue(value, convertStr)
+ @param {mixed} value new value
+ @param {boolean} convertStr whether to convert value from string to internal format
+ **/
+ setValue: function(value, convertStr, response) {
+ if(convertStr) {
+ this.value = this.input.str2value(value);
+ } else {
+ this.value = value;
+ }
+ if(this.container) {
+ this.container.option('value', this.value);
+ }
+ $.when(this.render(response))
+ .then($.proxy(function() {
+ this.handleEmpty();
+ }, this));
+ },
+
+ /**
+ Activates input of visible container (e.g. set focus)
+ @method activate()
+ **/
+ activate: function() {
+ if(this.container) {
+ this.container.activate();
+ }
+ },
+
+ /**
+ Removes editable feature from element
+ @method destroy()
+ **/
+ destroy: function() {
+ this.disable();
+
+ if(this.container) {
+ this.container.destroy();
+ }
+
+ this.input.destroy();
+
+ if(this.options.toggle !== 'manual') {
+ this.$element.removeClass('editable-click');
+ this.$element.off(this.options.toggle + '.editable');
+ }
+
+ this.$element.off("save.internal");
+
+ this.$element.removeClass('editable editable-open editable-disabled');
+ this.$element.removeData('editable');
+ }
+ };
+
+ /* EDITABLE PLUGIN DEFINITION
+ * ======================= */
+
+ /**
+ jQuery method to initialize editable element.
+
+ @method $().editable(options)
+ @params {Object} options
+ @example
+ $('#username').editable({
+ type: 'text',
+ url: '/post',
+ pk: 1
+ });
+ **/
+ $.fn.editable = function (option) {
+ //special API methods returning non-jquery object
+ var result = {}, args = arguments, datakey = 'editable';
+ switch (option) {
+ /**
+ Runs client-side validation for all matched editables
+
+ @method validate()
+ @returns {Object} validation errors map
+ @example
+ $('#username, #fullname').editable('validate');
+ // possible result:
+ {
+ username: "username is required",
+ fullname: "fullname should be minimum 3 letters length"
+ }
+ **/
+ case 'validate':
+ this.each(function () {
+ var $this = $(this), data = $this.data(datakey), error;
+ if (data && (error = data.validate())) {
+ result[data.options.name] = error;
+ }
+ });
+ return result;
+
+ /**
+ Returns current values of editable elements.
+ Note that it returns an **object** with name-value pairs, not a value itself. It allows to get data from several elements.
+ If value of some editable is `null` or `undefined` it is excluded from result object.
+ When param `isSingle` is set to **true** - it is supposed you have single element and will return value of editable instead of object.
+
+ @method getValue()
+ @param {bool} isSingle whether to return just value of single element
+ @returns {Object} object of element names and values
+ @example
+ $('#username, #fullname').editable('getValue');
+ //result:
+ {
+ username: "superuser",
+ fullname: "John"
+ }
+ //isSingle = true
+ $('#username').editable('getValue', true);
+ //result "superuser"
+ **/
+ case 'getValue':
+ if(arguments.length === 2 && arguments[1] === true) { //isSingle = true
+ result = this.eq(0).data(datakey).value;
+ } else {
+ this.each(function () {
+ var $this = $(this), data = $this.data(datakey);
+ if (data && data.value !== undefined && data.value !== null) {
+ result[data.options.name] = data.input.value2submit(data.value);
+ }
+ });
+ }
+ return result;
+
+ /**
+ This method collects values from several editable elements and submit them all to server.
+ Internally it runs client-side validation for all fields and submits only in case of success.
+ See creating new records for details.
+ Since 1.5.1 `submit` can be applied to single element to send data programmatically. In that case
+ `url`, `success` and `error` is taken from initial options and you can just call `$('#username').editable('submit')`.
+
+ @method submit(options)
+ @param {object} options
+ @param {object} options.url url to submit data
+ @param {object} options.data additional data to submit
+ @param {object} options.ajaxOptions additional ajax options
+ @param {function} options.error(obj) error handler
+ @param {function} options.success(obj,config) success handler
+ @returns {Object} jQuery object
+ **/
+ case 'submit': //collects value, validate and submit to server for creating new record
+ var config = arguments[1] || {},
+ $elems = this,
+ errors = this.editable('validate');
+
+ // validation ok
+ if($.isEmptyObject(errors)) {
+ var ajaxOptions = {};
+
+ // for single element use url, success etc from options
+ if($elems.length === 1) {
+ var editable = $elems.data('editable');
+ //standard params
+ var params = {
+ name: editable.options.name || '',
+ value: editable.input.value2submit(editable.value),
+ pk: (typeof editable.options.pk === 'function') ?
+ editable.options.pk.call(editable.options.scope) :
+ editable.options.pk
+ };
+
+ //additional params
+ if(typeof editable.options.params === 'function') {
+ params = editable.options.params.call(editable.options.scope, params);
+ } else {
+ //try parse json in single quotes (from data-params attribute)
+ editable.options.params = $.fn.editableutils.tryParseJson(editable.options.params, true);
+ $.extend(params, editable.options.params);
+ }
+
+ ajaxOptions = {
+ url: editable.options.url,
+ data: params,
+ type: 'POST'
+ };
+
+ // use success / error from options
+ config.success = config.success || editable.options.success;
+ config.error = config.error || editable.options.error;
+
+ // multiple elements
+ } else {
+ var values = this.editable('getValue');
+
+ ajaxOptions = {
+ url: config.url,
+ data: values,
+ type: 'POST'
+ };
+ }
+
+ // ajax success callabck (response 200 OK)
+ ajaxOptions.success = typeof config.success === 'function' ? function(response) {
+ config.success.call($elems, response, config);
+ } : $.noop;
+
+ // ajax error callabck
+ ajaxOptions.error = typeof config.error === 'function' ? function() {
+ config.error.apply($elems, arguments);
+ } : $.noop;
+
+ // extend ajaxOptions
+ if(config.ajaxOptions) {
+ $.extend(ajaxOptions, config.ajaxOptions);
+ }
+
+ // extra data
+ if(config.data) {
+ $.extend(ajaxOptions.data, config.data);
+ }
+
+ // perform ajax request
+ $.ajax(ajaxOptions);
+ } else { //client-side validation error
+ if(typeof config.error === 'function') {
+ config.error.call($elems, errors);
+ }
+ }
+ return this;
+ }
+
+ //return jquery object
+ return this.each(function () {
+ var $this = $(this),
+ data = $this.data(datakey),
+ options = typeof option === 'object' && option;
+
+ //for delegated targets do not store `editable` object for element
+ //it's allows several different selectors.
+ //see: https://github.com/vitalets/x-editable/issues/312
+ if(options && options.selector) {
+ data = new Editable(this, options);
+ return;
+ }
+
+ if (!data) {
+ $this.data(datakey, (data = new Editable(this, options)));
+ }
+
+ if (typeof option === 'string') { //call method
+ data[option].apply(data, Array.prototype.slice.call(args, 1));
+ }
+ });
+ };
+
+
+ $.fn.editable.defaults = {
+ /**
+ Type of input. Can be text|textarea|select|date|checklist
and more
+ @property type
+ @type string
+ @default 'text'
+ **/
+ type: 'text',
+ /**
+ Sets disabled state of editable
+ @property disabled
+ @type boolean
+ @default false
+ **/
+ disabled: false,
+ /**
+ How to toggle editable. Can be click|dblclick|mouseenter|manual
.
+ When set to manual
you should manually call show/hide
methods of editable.
+ **Note**: if you call show
or toggle
inside **click** handler of some DOM element,
+ you need to apply e.stopPropagation()
because containers are being closed on any click on document.
+
+ @example
+ $('#edit-button').click(function(e) {
+ e.stopPropagation();
+ $('#username').editable('toggle');
+ });
+ @property toggle
+ @type string
+ @default 'click'
+ **/
+ toggle: 'click',
+ /**
+ Text shown when element is empty.
+ @property emptytext
+ @type string
+ @default 'Empty'
+ **/
+ emptytext: 'Empty',
+ /**
+ Allows to automatically set element's text based on it's value. Can be auto|always|never
. Useful for select and date.
+ For example, if dropdown list is {1: 'a', 2: 'b'}
and element's value set to 1
, it's html will be automatically set to 'a'
.
+ auto
- text will be automatically set only if element is empty.
+ always|never
- always(never) try to set element's text.
+ @property autotext
+ @type string
+ @default 'auto'
+ **/
+ autotext: 'auto',
+ /**
+ Initial value of input. If not set, taken from element's text.
+ Note, that if element's text is empty - text is automatically generated from value and can be customized (see `autotext` option).
+ For example, to display currency sign:
+ @example
+
+
+
+ @property value
+ @type mixed
+ @default element's text
+ **/
+ value: null,
+ /**
+ Callback to perform custom displaying of value in element's text.
+ If `null`, default input's display used.
+ If `false`, no displaying methods will be called, element's text will never change.
+ Runs under element's scope.
+ _**Parameters:**_
+
+ * `value` current value to be displayed
+ * `response` server response (if display called after ajax submit), since 1.4.0
+
+ For _inputs with source_ (select, checklist) parameters are different:
+
+ * `value` current value to be displayed
+ * `sourceData` array of items for current input (e.g. dropdown items)
+ * `response` server response (if display called after ajax submit), since 1.4.0
+
+ To get currently selected items use `$.fn.editableutils.itemsByValue(value, sourceData)`.
+
+ @property display
+ @type function|boolean
+ @default null
+ @since 1.2.0
+ @example
+ display: function(value, sourceData) {
+ //display checklist as comma-separated values
+ var html = [],
+ checked = $.fn.editableutils.itemsByValue(value, sourceData);
+
+ if(checked.length) {
+ $.each(checked, function(i, v) { html.push($.fn.editableutils.escape(v.text)); });
+ $(this).html(html.join(', '));
+ } else {
+ $(this).empty();
+ }
+ }
+ **/
+ display: null,
+ /**
+ Css class applied when editable text is empty.
+ @property emptyclass
+ @type string
+ @since 1.4.1
+ @default editable-empty
+ **/
+ emptyclass: 'editable-empty',
+ /**
+ Css class applied when value was stored but not sent to server (`pk` is empty or `send = 'never'`).
+ You may set it to `null` if you work with editables locally and submit them together.
+ @property unsavedclass
+ @type string
+ @since 1.4.1
+ @default editable-unsaved
+ **/
+ unsavedclass: 'editable-unsaved',
+ /**
+ If selector is provided, editable will be delegated to the specified targets.
+ Usefull for dynamically generated DOM elements.
+ **Please note**, that delegated targets can't be initialized with `emptytext` and `autotext` options,
+ as they actually become editable only after first click.
+ You should manually set class `editable-click` to these elements.
+ Also, if element originally empty you should add class `editable-empty`, set `data-value=""` and write emptytext into element:
+ @property selector
+ @type string
+ @since 1.4.1
+ @default null
+ @example
+
+
+
+ **/
+ selector: null,
+ /**
+ Color used to highlight element after update. Implemented via CSS3 transition, works in modern browsers.
+
+ @property highlight
+ @type string|boolean
+ @since 1.4.5
+ @default #FFFF80
+ **/
+ highlight: '#FFFF80'
+ };
+
+}(window.jQuery));
+
+/**
+AbstractInput - base class for all editable inputs.
+It defines interface to be implemented by any input type.
+To create your own input you can inherit from this class.
+@class abstractinput
+**/
+(function ($) {
+ "use strict";
+
+ //types
+ $.fn.editabletypes = {};
+
+ var AbstractInput = function () { };
+
+ AbstractInput.prototype = {
+ /**
+ Initializes input
+ @method init()
+ **/
+ init: function(type, options, defaults) {
+ this.type = type;
+ this.options = $.extend({}, defaults, options);
+ },
+
+ /*
+ this method called before render to init $tpl that is inserted in DOM
+ */
+ prerender: function() {
+ this.$tpl = $(this.options.tpl); //whole tpl as jquery object
+ this.$input = this.$tpl; //control itself, can be changed in render method
+ this.$clear = null; //clear button
+ this.error = null; //error message, if input cannot be rendered
+ },
+
+ /**
+ Renders input from tpl. Can return jQuery deferred object.
+ Can be overwritten in child objects
+ @method render()
+ **/
+ render: function() {
+
+ },
+
+ /**
+ Sets element's html by value.
+ @method value2html(value, element)
+ @param {mixed} value
+ @param {DOMElement} element
+ **/
+ value2html: function(value, element) {
+ $(element)[this.options.escape ? 'text' : 'html']($.trim(value));
+ },
+
+ /**
+ Converts element's html to value
+ @method html2value(html)
+ @param {string} html
+ @returns {mixed}
+ **/
+ html2value: function(html) {
+ return $('