From 882d93e7b0b9feee3d10090e7c523c0bcaeecc47 Mon Sep 17 00:00:00 2001 From: Minho Date: Fri, 26 Jan 2018 17:17:38 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=AE=9E=E7=8E=B0=E5=AF=8C=E6=96=87?= =?UTF-8?q?=E6=9C=AC=E7=BC=96=E8=BE=91=E5=99=A8=202=E3=80=81=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E6=96=87=E6=A1=A3=E8=BD=AC=E6=8D=A2=E4=B8=BAPDF?= =?UTF-8?q?=E3=80=81MOBI=E3=80=81EPUB=E3=80=81Word=E6=A0=BC=E5=BC=8F=203?= =?UTF-8?q?=E3=80=81=E5=AE=9E=E7=8E=B0=E7=99=BB=E5=BD=95=E5=90=8E=E8=B7=B3?= =?UTF-8?q?=E8=BD=AC=E5=88=B0=E6=9D=A5=E6=BA=90=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- commands/command.go | 77 +++--- commands/daemon/daemon.go | 4 +- commands/migrate/migrate.go | 79 ++++--- commands/migrate/migrate_v03.go | 40 ++-- conf/enumerate.go | 37 +-- conf/mail.go | 30 +-- controllers/account.go | 49 ++-- controllers/base.go | 63 +++-- controllers/book.go | 408 ++++++++++++++++---------------- controllers/book_member.go | 107 +++++---- controllers/comment.go | 10 +- controllers/document.go | 83 ++----- controllers/home.go | 16 +- controllers/label.go | 27 +-- controllers/manager.go | 114 ++++----- controllers/search.go | 28 +-- controllers/setting.go | 105 ++++---- converter/converter.go | 96 ++++++-- graphics/file.go | 2 +- models/attachment.go | 2 +- models/attachment_result.go | 24 +- models/base.go | 2 - models/blogs.go | 6 +- models/book.go | 30 +-- models/book_result.go | 289 +++++++++++----------- models/comment.go | 102 +++----- models/comment_result.go | 12 +- models/comment_vote.go | 33 +-- models/convert_book_result.go | 3 +- models/dashboard.go | 20 +- models/document.go | 19 +- models/document_history.go | 42 ++-- models/document_tree.go | 84 +++---- models/errors.go | 18 +- models/label.go | 36 +-- models/logs.go | 52 ++-- models/member.go | 74 +++--- models/member_result.go | 58 ++--- models/member_token.go | 50 ++-- models/migrations.go | 22 +- models/options.go | 82 ++++--- models/relationship.go | 112 ++++----- routers/filter.go | 32 +-- static/js/markdown.js | 2 - utils/cryptil/cryptil.go | 70 ++++++ utils/file.go | 30 +-- utils/filetil/filetil.go | 43 ++++ utils/gob.go | 18 +- utils/krand.go | 15 +- utils/ldap.go | 45 ++-- utils/pager.go | 108 +++++---- utils/password.go | 15 +- utils/template_fun.go | 4 +- utils/url.go | 12 +- utils/ziptil/ziptil.go | 101 ++++++++ views/account/login.tpl | 4 +- views/document/default_read.tpl | 1 + 57 files changed, 1572 insertions(+), 1475 deletions(-) create mode 100644 utils/cryptil/cryptil.go create mode 100644 utils/filetil/filetil.go create mode 100644 utils/ziptil/ziptil.go diff --git a/commands/command.go b/commands/command.go index c13582c2..2fcbc4b8 100644 --- a/commands/command.go +++ b/commands/command.go @@ -6,11 +6,12 @@ import ( "net/url" "os" "time" - + "log" "flag" "path/filepath" "strings" + "encoding/json" "github.com/astaxie/beego" "github.com/astaxie/beego/logs" "github.com/astaxie/beego/orm" @@ -19,14 +20,6 @@ import ( "github.com/lifei6671/mindoc/conf" "github.com/lifei6671/mindoc/models" "github.com/lifei6671/mindoc/utils" - "log" - "encoding/json" -) - -var ( - ConfigurationFile = "./conf/app.conf" - WorkingDirectory = "./" - LogFile = "./logs" ) // RegisterDataBase 注册数据库 @@ -54,8 +47,8 @@ func RegisterDataBase() { } } else if adapter == "sqlite3" { database := beego.AppConfig.String("db_database") - if strings.HasPrefix(database,"./") { - database = filepath.Join(WorkingDirectory,string(database[1:])) + if strings.HasPrefix(database, "./") { + database = filepath.Join(conf.WorkingDirectory, string(database[1:])) } dbPath := filepath.Dir(database) @@ -99,11 +92,11 @@ func RegisterLogger(log string) { if f, err := os.Create(logPath); err == nil { f.Close() - config := make(map[string]interface{},1) + config := make(map[string]interface{}, 1) config["filename"] = logPath - b,_ := json.Marshal(config) + b, _ := json.Marshal(config) beego.SetLogger("file", string(b)) } @@ -133,7 +126,7 @@ func RegisterFunction() { beego.AddFuncMap("cdn", func(p string) string { cdn := beego.AppConfig.DefaultString("cdn", "") - if strings.HasPrefix(p,"http://") || strings.HasPrefix(p,"https://") { + if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") { return p } if strings.HasPrefix(p, "/") && strings.HasSuffix(cdn, "/") { @@ -147,7 +140,7 @@ func RegisterFunction() { beego.AddFuncMap("cdnjs", func(p string) string { cdn := beego.AppConfig.DefaultString("cdnjs", "") - if strings.HasPrefix(p,"http://") || strings.HasPrefix(p,"https://") { + if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") { return p } if strings.HasPrefix(p, "/") && strings.HasSuffix(cdn, "/") { @@ -160,7 +153,7 @@ func RegisterFunction() { }) beego.AddFuncMap("cdncss", func(p string) string { cdn := beego.AppConfig.DefaultString("cdncss", "") - if strings.HasPrefix(p,"http://") || strings.HasPrefix(p,"https://") { + if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") { return p } if strings.HasPrefix(p, "/") && strings.HasSuffix(cdn, "/") { @@ -172,7 +165,7 @@ func RegisterFunction() { return cdn + p }) beego.AddFuncMap("cdnimg", func(p string) string { - if strings.HasPrefix(p,"http://") || strings.HasPrefix(p,"https://") { + if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") { return p } cdn := beego.AppConfig.DefaultString("cdnimg", "") @@ -188,62 +181,64 @@ func RegisterFunction() { func ResolveCommand(args []string) { flagSet := flag.NewFlagSet("MinDoc command: ", flag.ExitOnError) - flagSet.StringVar(&ConfigurationFile, "config", "", "MinDoc configuration file.") - flagSet.StringVar(&WorkingDirectory, "dir", "", "MinDoc working directory.") - flagSet.StringVar(&LogFile, "log", "", "MinDoc log file path.") + flagSet.StringVar(&conf.ConfigurationFile, "config", "", "MinDoc configuration file.") + flagSet.StringVar(&conf.WorkingDirectory, "dir", "", "MinDoc working directory.") + flagSet.StringVar(&conf.LogFile, "log", "", "MinDoc log file path.") flagSet.Parse(args) - - if WorkingDirectory == "" { + if conf.WorkingDirectory == "" { if p, err := filepath.Abs(os.Args[0]); err == nil { - WorkingDirectory = filepath.Dir(p) + conf.WorkingDirectory = filepath.Dir(p) } } - if LogFile == "" { - LogFile = filepath.Join(WorkingDirectory,"logs") + if conf.LogFile == "" { + conf.LogFile = filepath.Join(conf.WorkingDirectory, "logs") } - if ConfigurationFile == "" { - ConfigurationFile = filepath.Join(WorkingDirectory,"conf","app.conf") - config := filepath.Join(WorkingDirectory,"conf","app.conf.example") - if !utils.FileExists(ConfigurationFile) && utils.FileExists(config){ - utils.CopyFile(ConfigurationFile,config) + if conf.ConfigurationFile == "" { + conf.ConfigurationFile = filepath.Join(conf.WorkingDirectory, "conf", "app.conf") + config := filepath.Join(conf.WorkingDirectory, "conf", "app.conf.example") + if !utils.FileExists(conf.ConfigurationFile) && utils.FileExists(config) { + utils.CopyFile(conf.ConfigurationFile, config) } } - gocaptcha.ReadFonts(filepath.Join(WorkingDirectory,"static","fonts"), ".ttf") + gocaptcha.ReadFonts(filepath.Join(conf.WorkingDirectory, "static", "fonts"), ".ttf") - err := beego.LoadAppConfig("ini", ConfigurationFile) + err := beego.LoadAppConfig("ini", conf.ConfigurationFile) if err != nil { log.Println("An error occurred:", err) os.Exit(1) } - uploads := filepath.Join(WorkingDirectory, "uploads") + uploads := filepath.Join(conf.WorkingDirectory, "uploads") - os.MkdirAll(uploads,0666) + os.MkdirAll(uploads, 0666) - beego.BConfig.WebConfig.StaticDir["/static"] = filepath.Join(WorkingDirectory, "static") + beego.BConfig.WebConfig.StaticDir["/static"] = filepath.Join(conf.WorkingDirectory, "static") beego.BConfig.WebConfig.StaticDir["/uploads"] = uploads - beego.BConfig.WebConfig.ViewsPath = filepath.Join(WorkingDirectory, "views") + beego.BConfig.WebConfig.ViewsPath = filepath.Join(conf.WorkingDirectory, "views") - fonts := filepath.Join(WorkingDirectory, "static", "fonts") + fonts := filepath.Join(conf.WorkingDirectory, "static", "fonts") if !utils.FileExists(fonts) { log.Fatal("Font path not exist.") } - gocaptcha.ReadFonts(filepath.Join(WorkingDirectory, "static", "fonts"), ".ttf") + gocaptcha.ReadFonts(filepath.Join(conf.WorkingDirectory, "static", "fonts"), ".ttf") RegisterDataBase() RegisterModel() - RegisterLogger(LogFile) + RegisterLogger(conf.LogFile) } func init() { + if configPath ,err := filepath.Abs(conf.ConfigurationFile); err == nil { + conf.ConfigurationFile = configPath + } gocaptcha.ReadFonts("./static/fonts", ".ttf") gob.Register(models.Member{}) - if p,err := filepath.Abs(os.Args[0]);err == nil{ - WorkingDirectory = filepath.Dir(p) + if p, err := filepath.Abs(os.Args[0]); err == nil { + conf.WorkingDirectory = filepath.Dir(p) } } diff --git a/commands/daemon/daemon.go b/commands/daemon/daemon.go index 5245ab65..69bfc7cf 100644 --- a/commands/daemon/daemon.go +++ b/commands/daemon/daemon.go @@ -19,10 +19,10 @@ type Daemon struct { func NewDaemon() *Daemon { config := &service.Config{ - Name: "mindocd", //服务显示名称 + Name: "mindocd", //服务显示名称 DisplayName: "MinDoc service", //服务名称 Description: "A document online management program.", //服务描述 - WorkingDirectory: commands.WorkingDirectory, + WorkingDirectory: conf.WorkingDirectory, Arguments: os.Args[1:], } diff --git a/commands/migrate/migrate.go b/commands/migrate/migrate.go index e0f46856..2cd0f960 100644 --- a/commands/migrate/migrate.go +++ b/commands/migrate/migrate.go @@ -16,19 +16,18 @@ package migrate import ( "os" - "log" - "github.com/lifei6671/mindoc/models" "container/list" "fmt" "github.com/astaxie/beego" "github.com/astaxie/beego/orm" + "github.com/lifei6671/mindoc/models" + "log" ) var ( - migrationList = &migrationCache{ } + migrationList = &migrationCache{} ) - type MigrationDatabase interface { //获取当前的版本 Version() int64 @@ -58,7 +57,7 @@ func RunMigration() { if len(os.Args) >= 2 && os.Args[1] == "migrate" { - migrate,err := models.NewMigration().FindFirst() + migrate, err := models.NewMigration().FindFirst() if err != nil { //log.Fatalf("migrations table %s", err) @@ -66,10 +65,10 @@ func RunMigration() { } fmt.Println("Start migration databae... ") - for el := migrationList.items.Front(); el != nil ; el = el.Next() { + for el := migrationList.items.Front(); el != nil; el = el.Next() { //如果存在比当前版本大的版本,则依次升级 - if item,ok := el.Value.(MigrationDatabase); ok && item.Version() > migrate.Version { + if item, ok := el.Value.(MigrationDatabase); ok && item.Version() > migrate.Version { err := item.ValidUpdate(migrate.Version) if err != nil { log.Fatal(err) @@ -112,51 +111,53 @@ func RunMigration() { } //导出数据库的表结构 -func ExportDatabaseTable() ([]string,error) { +func ExportDatabaseTable() ([]string, error) { db_adapter := beego.AppConfig.String("db_adapter") db_database := beego.AppConfig.String("db_database") - tables := make([]string,0) + tables := make([]string, 0) o := orm.NewOrm() switch db_adapter { - case "mysql":{ - var lists []orm.Params + case "mysql": + { + var lists []orm.Params - _,err := o.Raw(fmt.Sprintf("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '%s'",db_database)).Values(&lists) - if err != nil { - return tables,err - } - for _,table := range lists { - var results []orm.Params - - _,err = o.Raw(fmt.Sprintf("show create table %s",table["TABLE_NAME"])).Values(&results) + _, err := o.Raw(fmt.Sprintf("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '%s'", db_database)).Values(&lists) if err != nil { - return tables,err + return tables, err } - tables = append(tables,results[0]["Create Table"].(string)) - } - break; - } - case "sqlite3": { - var results []orm.Params - _,err := o.Raw("SELECT sql FROM sqlite_master WHERE sql IS NOT NULL ORDER BY rootpage ASC").Values(&results) - if err != nil { - return tables,err - } - for _,item := range results { - if sql,ok := item["sql"]; ok { - tables = append(tables,sql.(string)) + for _, table := range lists { + var results []orm.Params + + _, err = o.Raw(fmt.Sprintf("show create table %s", table["TABLE_NAME"])).Values(&results) + if err != nil { + return tables, err + } + tables = append(tables, results[0]["Create Table"].(string)) } + break + } + case "sqlite3": + { + var results []orm.Params + _, err := o.Raw("SELECT sql FROM sqlite_master WHERE sql IS NOT NULL ORDER BY rootpage ASC").Values(&results) + if err != nil { + return tables, err + } + for _, item := range results { + if sql, ok := item["sql"]; ok { + tables = append(tables, sql.(string)) + } + } + break } - break - } } - return tables,nil + return tables, nil } -func RegisterMigration() { +func RegisterMigration() { migrationList.items = list.New() - migrationList.items.PushBack(NewMigrationVersion03()) -} \ No newline at end of file + migrationList.items.PushBack(NewMigrationVersion03()) +} diff --git a/commands/migrate/migrate_v03.go b/commands/migrate/migrate_v03.go index 6088f702..d73e9e78 100644 --- a/commands/migrate/migrate_v03.go +++ b/commands/migrate/migrate_v03.go @@ -2,21 +2,20 @@ package migrate import ( "errors" + "fmt" "github.com/astaxie/beego/orm" "github.com/lifei6671/mindoc/models" - "time" - "fmt" "strings" + "time" ) type MigrationVersion03 struct { isValid bool - tables []string - + tables []string } func NewMigrationVersion03() *MigrationVersion03 { - return &MigrationVersion03{ isValid: false, tables: make([]string,0)} + return &MigrationVersion03{isValid: false, tables: make([]string, 0)} } func (m *MigrationVersion03) Version() int64 { @@ -37,8 +36,7 @@ func (m *MigrationVersion03) ValidForBackupTableSchema() error { return errors.New("The current version failed to verify.") } var err error - m.tables,err = ExportDatabaseTable() - + m.tables, err = ExportDatabaseTable() return err } @@ -72,11 +70,11 @@ func (m *MigrationVersion03) MigrationNewTableData() error { } o := orm.NewOrm() - _,err := o.Raw("UPDATE md_members SET auth_method = 'local'").Exec() + _, err := o.Raw("UPDATE md_members SET auth_method = 'local'").Exec() if err != nil { return err } - _,err = o.Raw("INSERT INTO md_options (option_title, option_name, option_value) SELECT '是否启用文档历史','ENABLE_DOCUMENT_HISTORY','true' WHERE NOT exists(SELECT * FROM md_options WHERE option_name = 'ENABLE_DOCUMENT_HISTORY');").Exec() + _, err = o.Raw("INSERT INTO md_options (option_title, option_name, option_value) SELECT '是否启用文档历史','ENABLE_DOCUMENT_HISTORY','true' WHERE NOT exists(SELECT * FROM md_options WHERE option_name = 'ENABLE_DOCUMENT_HISTORY');").Exec() if err != nil { return err } @@ -85,24 +83,24 @@ func (m *MigrationVersion03) MigrationNewTableData() error { func (m *MigrationVersion03) AddMigrationRecord(version int64) error { o := orm.NewOrm() - tables,err := ExportDatabaseTable() + tables, err := ExportDatabaseTable() if err != nil { - return err + return err } migration := models.NewMigration() migration.Version = version migration.Status = "update" migration.CreateTime = time.Now() - migration.Name = fmt.Sprintf("update_%d",version) - migration.Statements = strings.Join(tables,"\r\n") + migration.Name = fmt.Sprintf("update_%d", version) + migration.Statements = strings.Join(tables, "\r\n") _, err = o.Insert(migration) return err } -func (m *MigrationVersion03) MigrationCleanup() error { +func (m *MigrationVersion03) MigrationCleanup() error { return nil } @@ -112,16 +110,16 @@ func (m *MigrationVersion03) RollbackMigration() error { return errors.New("The current version failed to verify.") } o := orm.NewOrm() - _,err := o.Raw("ALTER TABLE md_members DROP COLUMN auth_method").Exec() + _, err := o.Raw("ALTER TABLE md_members DROP COLUMN auth_method").Exec() if err != nil { return err } - _,err = o.Raw("DROP TABLE md_document_history").Exec() + _, err = o.Raw("DROP TABLE md_document_history").Exec() if err != nil { return err } - _,err = o.Raw("DELETE md_options WHERE option_name = 'ENABLE_DOCUMENT_HISTORY'").Exec() + _, err = o.Raw("DELETE md_options WHERE option_name = 'ENABLE_DOCUMENT_HISTORY'").Exec() if err != nil { return err @@ -129,11 +127,3 @@ func (m *MigrationVersion03) RollbackMigration() error { return nil } - - - - - - - - diff --git a/conf/enumerate.go b/conf/enumerate.go index 5053241a..5ce602ca 100644 --- a/conf/enumerate.go +++ b/conf/enumerate.go @@ -20,7 +20,7 @@ const RegexpEmail = "^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0- const RegexpAccount = `^[a-zA-Z][a-zA-z0-9\.]{2,50}$` // PageSize 默认分页条数. -const PageSize = 15 +const PageSize = 10 // 用户权限 const ( @@ -44,23 +44,31 @@ const ( ) const ( - LoggerOperate = "operate" - LoggerSystem = "system" + LoggerOperate = "operate" + LoggerSystem = "system" LoggerException = "exception" - LoggerDocument = "document" + LoggerDocument = "document" ) const ( //本地账户校验 AuthMethodLocal = "local" //LDAP用户校验 - AuthMethodLDAP = "ldap" + AuthMethodLDAP = "ldap" ) + var ( VERSION string BUILD_TIME string GO_VERSION string ) +var ( + ConfigurationFile = "./conf/app.conf" + WorkingDirectory = "./" + LogFile = "./logs" + BaseUrl = "" +) + // app_key func GetAppKey() string { return beego.AppConfig.DefaultString("app_key", "godoc") @@ -102,29 +110,30 @@ func GetUploadFileExt() []string { } return exts } + // 获取上传文件允许的最大值 func GetUploadFileSize() int64 { - size := beego.AppConfig.DefaultString("upload_file_size","0") + size := beego.AppConfig.DefaultString("upload_file_size", "0") - if strings.HasSuffix(size,"MB") { - if s,e := strconv.ParseInt(size[0:len(size) - 2], 10, 64);e == nil { + if strings.HasSuffix(size, "MB") { + if s, e := strconv.ParseInt(size[0:len(size)-2], 10, 64); e == nil { return s * 1024 * 1024 } } - if strings.HasSuffix(size,"GB") { - if s,e := strconv.ParseInt(size[0:len(size) - 2], 10, 64);e == nil { + if strings.HasSuffix(size, "GB") { + if s, e := strconv.ParseInt(size[0:len(size)-2], 10, 64); e == nil { return s * 1024 * 1024 * 1024 } } - if strings.HasSuffix(size,"KB") { - if s,e := strconv.ParseInt(size[0:len(size) - 2], 10, 64);e == nil { + if strings.HasSuffix(size, "KB") { + if s, e := strconv.ParseInt(size[0:len(size)-2], 10, 64); e == nil { return s * 1024 } } - if s,e := strconv.ParseInt(size, 10, 64);e == nil { + if s, e := strconv.ParseInt(size, 10, 64); e == nil { return s * 1024 } - return 0 + return 0 } //判断是否是允许商城的文件类型. diff --git a/conf/mail.go b/conf/mail.go index 69304f03..162ceb1d 100644 --- a/conf/mail.go +++ b/conf/mail.go @@ -6,33 +6,33 @@ import ( ) type SmtpConf struct { - EnableMail bool - MailNumber int + EnableMail bool + MailNumber int SmtpUserName string - SmtpHost string + SmtpHost string SmtpPassword string - SmtpPort int + SmtpPort int FormUserName string - MailExpired int + MailExpired int } func GetMailConfig() *SmtpConf { user_name := beego.AppConfig.String("smtp_user_name") password := beego.AppConfig.String("smtp_password") smtp_host := beego.AppConfig.String("smtp_host") - smtp_port := beego.AppConfig.DefaultInt("smtp_port",25) + smtp_port := beego.AppConfig.DefaultInt("smtp_port", 25) form_user_name := beego.AppConfig.String("form_user_name") enable_mail := beego.AppConfig.String("enable_mail") - mail_number := beego.AppConfig.DefaultInt("mail_number",5) + mail_number := beego.AppConfig.DefaultInt("mail_number", 5) c := &SmtpConf{ - EnableMail : strings.EqualFold(enable_mail,"true"), - MailNumber: mail_number, - SmtpUserName:user_name, - SmtpHost:smtp_host, - SmtpPassword:password, - FormUserName:form_user_name, - SmtpPort:smtp_port, + EnableMail: strings.EqualFold(enable_mail, "true"), + MailNumber: mail_number, + SmtpUserName: user_name, + SmtpHost: smtp_host, + SmtpPassword: password, + FormUserName: form_user_name, + SmtpPort: smtp_port, } return c -} \ No newline at end of file +} diff --git a/controllers/account.go b/controllers/account.go index 5ee2175e..9033eeec 100644 --- a/controllers/account.go +++ b/controllers/account.go @@ -14,6 +14,7 @@ import ( "github.com/lifei6671/mindoc/conf" "github.com/lifei6671/mindoc/models" "github.com/lifei6671/mindoc/utils" + "net/url" ) // AccountController 用户登录与注册 @@ -32,14 +33,17 @@ func (c *AccountController) Login() { Time time.Time } - // 显式指定的 URL 参数优先;为了统一处理,将之更新到 Session 中 - turl := c.GetString("turl", "") - if turl != "" { - c.SetSession("turl", turl) + if member, ok := c.GetSession(conf.LoginSessionName).(models.Member); ok && member.MemberId > 0 { + u := c.GetString("url") + if u == "" { + u = c.Ctx.Request.Header.Get("Referer") + } + if u == "" { + u = beego.URLFor("HomeController.Index") + } + c.Redirect(u,302) } - beego.Info("AccountController.Login(): turl is: " + turl) - // 如果 Cookie 中存在登录信息 if cookie, ok := c.GetSecureCookie(conf.GetAppKey(), "login"); ok { if err := utils.Decode(cookie, &remember); err == nil { @@ -81,26 +85,35 @@ func (c *AccountController) Login() { c.SetSecureCookie(conf.GetAppKey(), "login", v) } } + u,_ := url.PathUnescape(c.GetString("url")) + if u == "" { + u = c.Ctx.Request.Header.Get("Referer") + } + if u == "" { + u = beego.URLFor("HomeController.Index") + } - data := c.LoggedIn(true) - c.JsonResult(0, "ok", data) + c.JsonResult(0, "ok", u) } else { logs.Error("用户登录 =>", err) c.JsonResult(500, "账号或密码错误", nil) } + }else{ + u,_ := url.PathUnescape(c.GetString("url")) + if u == "" { + u = c.Ctx.Request.Header.Get("Referer") + } + if u == "" { + u = beego.URLFor("HomeController.Index") + } + c.Data["url"] = url.PathEscape(u) } } // 登录成功后的操作,如重定向到原始请求页面 func (c *AccountController) LoggedIn(isPost bool) interface{} { - turl := "" - value := c.GetSession("turl") - if value != nil { - turl = value.(string) - } - c.DelSession("turl") - beego.Info("AccountController.LoggedIn(): turl is: " + turl) + turl := c.GetString("url") if !isPost { // 检查是否存在 turl 参数,如果有则重定向至 turl 处,否则进入 Home 页面 @@ -111,7 +124,7 @@ func (c *AccountController) LoggedIn(isPost bool) interface{} { return nil } else { var data struct { - TURL string `json:"turl"` + TURL string `json:"url"` } data.TURL = turl return data @@ -369,7 +382,9 @@ func (c *AccountController) Logout() { c.SetSecureCookie(conf.GetAppKey(), "login", "", -3600) - c.Redirect(beego.URLFor("AccountController.Login"), 302) + u := c.Ctx.Request.Header.Get("Referer") + + c.Redirect(beego.URLFor("AccountController.Login","url",u), 302) } // 验证码 diff --git a/controllers/base.go b/controllers/base.go index ca116a67..21a6e1cf 100644 --- a/controllers/base.go +++ b/controllers/base.go @@ -1,53 +1,52 @@ package controllers import ( - "bytes" - "github.com/lifei6671/mindoc/models" - "github.com/lifei6671/mindoc/conf" - "github.com/astaxie/beego" - "strings" "encoding/json" + "github.com/astaxie/beego" + "github.com/lifei6671/mindoc/conf" + "github.com/lifei6671/mindoc/models" "io" + "strings" ) - type BaseController struct { beego.Controller - Member *models.Member - Option map[string]string - EnableAnonymous bool + Member *models.Member + Option map[string]string + EnableAnonymous bool EnableDocumentHistory bool } // Prepare 预处理. -func (c *BaseController) Prepare (){ +func (c *BaseController) Prepare() { c.Data["SiteName"] = "MinDoc" c.Data["Member"] = models.Member{} c.EnableAnonymous = false c.EnableDocumentHistory = false - if member,ok := c.GetSession(conf.LoginSessionName).(models.Member); ok && member.MemberId > 0{ + if member, ok := c.GetSession(conf.LoginSessionName).(models.Member); ok && member.MemberId > 0 { c.Member = &member c.Data["Member"] = c.Member - }else{ + } else { //c.Member = models.NewMember() //c.Member.Find(1) //c.Data["Member"] = *c.Member } - c.Data["BaseUrl"] = c.Ctx.Input.Scheme() + "://" + c.Ctx.Request.Host + conf.BaseUrl = c.BaseUrl() + c.Data["BaseUrl"] = c.BaseUrl() - if options,err := models.NewOption().All();err == nil { - c.Option = make(map[string]string,len(options)) - for _,item := range options { + if options, err := models.NewOption().All(); err == nil { + c.Option = make(map[string]string, len(options)) + for _, item := range options { c.Data[item.OptionName] = item.OptionValue c.Option[item.OptionName] = item.OptionValue - if strings.EqualFold(item.OptionName,"ENABLE_ANONYMOUS") && item.OptionValue == "true" { + if strings.EqualFold(item.OptionName, "ENABLE_ANONYMOUS") && item.OptionValue == "true" { c.EnableAnonymous = true } - if strings.EqualFold(item.OptionName,"ENABLE_DOCUMENT_HISTORY") && item.OptionValue == "true" { + if strings.EqualFold(item.OptionName, "ENABLE_DOCUMENT_HISTORY") && item.OptionValue == "true" { c.EnableDocumentHistory = true } } @@ -68,13 +67,13 @@ func (c *BaseController) SetMember(member models.Member) { } // JsonResult 响应 json 结果 -func (c *BaseController) JsonResult(errCode int,errMsg string,data ...interface{}){ - jsonData := make(map[string]interface{},3) +func (c *BaseController) JsonResult(errCode int, errMsg string, data ...interface{}) { + jsonData := make(map[string]interface{}, 3) jsonData["errcode"] = errCode jsonData["message"] = errMsg - if len(data) > 0 && data[0] != nil{ + if len(data) > 0 && data[0] != nil { jsonData["data"] = data[0] } @@ -86,13 +85,13 @@ func (c *BaseController) JsonResult(errCode int,errMsg string,data ...interface{ c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json; charset=utf-8") - io.WriteString(c.Ctx.ResponseWriter,string(returnJSON)) + io.WriteString(c.Ctx.ResponseWriter, string(returnJSON)) c.StopRun() } // ExecuteViewPathTemplate 执行指定的模板并返回执行结果. -func (c *BaseController) ExecuteViewPathTemplate(tplName string,data interface{}) (string,error){ +func (c *BaseController) ExecuteViewPathTemplate(tplName string, data interface{}) (string, error) { var buf bytes.Buffer viewPath := c.ViewPath @@ -102,28 +101,28 @@ func (c *BaseController) ExecuteViewPathTemplate(tplName string,data interface{} } - if err := beego.ExecuteViewPathTemplate(&buf,tplName,viewPath,data); err != nil { - return "",err + if err := beego.ExecuteViewPathTemplate(&buf, tplName, viewPath, data); err != nil { + return "", err } - return buf.String(),nil + return buf.String(), nil } func (c *BaseController) BaseUrl() string { - baseUrl := beego.AppConfig.DefaultString("baseurl","") + baseUrl := beego.AppConfig.DefaultString("baseurl", "") if baseUrl != "" { - if strings.HasSuffix(baseUrl,"/"){ - baseUrl = strings.TrimSuffix(baseUrl,"/") + if strings.HasSuffix(baseUrl, "/") { + baseUrl = strings.TrimSuffix(baseUrl, "/") } - }else{ + } else { baseUrl = c.Ctx.Input.Scheme() + "://" + c.Ctx.Request.Host } return baseUrl } //显示错误信息页面. -func (c *BaseController) ShowErrorPage(errCode int,errMsg string) { +func (c *BaseController) ShowErrorPage(errCode int, errMsg string) { c.TplName = "errors/error.tpl" c.Data["ErrorMessage"] = errMsg c.Data["ErrorCode"] = errCode c.StopRun() -} \ No newline at end of file +} diff --git a/controllers/book.go b/controllers/book.go index d5884041..35904831 100644 --- a/controllers/book.go +++ b/controllers/book.go @@ -1,25 +1,24 @@ package controllers import ( - "strings" - "regexp" - "strconv" - "time" "encoding/json" - "html/template" "errors" "fmt" - "path/filepath" + "html/template" "os" + "path/filepath" + "regexp" + "strconv" + "strings" + "time" - "github.com/lifei6671/mindoc/models" - "github.com/lifei6671/mindoc/utils" "github.com/astaxie/beego" - "github.com/astaxie/beego/orm" "github.com/astaxie/beego/logs" + "github.com/astaxie/beego/orm" "github.com/lifei6671/mindoc/conf" "github.com/lifei6671/mindoc/graphics" - "github.com/lifei6671/mindoc/commands" + "github.com/lifei6671/mindoc/models" + "github.com/lifei6671/mindoc/utils" ) type BookController struct { @@ -32,10 +31,10 @@ func (c *BookController) Index() { pageIndex, _ := c.GetInt("page", 1) - books,totalCount,err := models.NewBook().FindToPager(pageIndex,conf.PageSize,c.Member.MemberId) + books, totalCount, err := models.NewBook().FindToPager(pageIndex, conf.PageSize, c.Member.MemberId) if err != nil { - logs.Error("BookController.Index => ",err) + logs.Error("BookController.Index => ", err) c.Abort("500") } @@ -43,14 +42,14 @@ func (c *BookController) Index() { html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, conf.PageSize, totalCount) c.Data["PageHtml"] = html - }else { + } else { c.Data["PageHtml"] = "" } - b,err := json.Marshal(books) + b, err := json.Marshal(books) - if err != nil || len(books) <= 0{ + if err != nil || len(books) <= 0 { c.Data["Result"] = template.JS("[]") - }else{ + } else { c.Data["Result"] = template.JS(string(b)) } } @@ -62,11 +61,11 @@ func (c *BookController) Dashboard() { key := c.Ctx.Input.Param(":key") - if key == ""{ + if key == "" { c.Abort("404") } - book,err := models.NewBookResult().FindByIdentify(key,c.Member.MemberId) + book, err := models.NewBookResult().FindByIdentify(key, c.Member.MemberId) if err != nil { if err == models.ErrPermissionDenied { c.Abort("403") @@ -79,17 +78,17 @@ func (c *BookController) Dashboard() { } // Setting 项目设置 . -func (c *BookController) Setting() { +func (c *BookController) Setting() { c.Prepare() c.TplName = "book/setting.tpl" key := c.Ctx.Input.Param(":key") - if key == ""{ + if key == "" { c.Abort("404") } - book,err := models.NewBookResult().FindByIdentify(key,c.Member.MemberId) + book, err := models.NewBookResult().FindByIdentify(key, c.Member.MemberId) if err != nil { if err == orm.ErrNoRows { c.Abort("404") @@ -104,225 +103,224 @@ 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 = c.BaseUrl() + beego.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken) } c.Data["Model"] = book } //保存项目信息 -func (c *BookController) SaveBook() { - bookResult,err := c.IsPermission() +func (c *BookController) SaveBook() { + bookResult, err := c.IsPermission() if err != nil { - c.JsonResult(6001,err.Error()) + c.JsonResult(6001, err.Error()) } - book,err := models.NewBook().Find(bookResult.BookId) + book, err := models.NewBook().Find(bookResult.BookId) if err != nil { - logs.Error("SaveBook => ",err) - c.JsonResult(6002,err.Error()) + logs.Error("SaveBook => ", err) + c.JsonResult(6002, err.Error()) } book_name := strings.TrimSpace(c.GetString("book_name")) - description := strings.TrimSpace(c.GetString("description","")) + description := strings.TrimSpace(c.GetString("description", "")) comment_status := c.GetString("comment_status") tag := strings.TrimSpace(c.GetString("label")) editor := strings.TrimSpace(c.GetString("editor")) auto_release := strings.TrimSpace(c.GetString("auto_release")) == "on" - if strings.Count(description,"") > 500 { - c.JsonResult(6004,"项目描述不能大于500字") + if strings.Count(description, "") > 500 { + c.JsonResult(6004, "项目描述不能大于500字") } if comment_status != "open" && comment_status != "closed" && comment_status != "group_only" && comment_status != "registered_only" { comment_status = "closed" } - if tag != ""{ - tags := strings.Split(tag,",") + if tag != "" { + tags := strings.Split(tag, ",") if len(tags) > 10 { - c.JsonResult(6005,"最多允许添加10个标签") + c.JsonResult(6005, "最多允许添加10个标签") } } if editor != "markdown" && editor != "html" { editor = "markdown" } - book.BookName = book_name - book.Description = description - book.CommentStatus = comment_status - book.Label = tag - book.Editor = editor + book.BookName = book_name + book.Description = description + book.CommentStatus = comment_status + book.Label = tag + book.Editor = editor if auto_release { book.AutoRelease = 1 - }else{ + } else { book.AutoRelease = 0 } - - if err := book.Update();err != nil { - c.JsonResult(6006,"保存失败") + if err := book.Update(); err != nil { + c.JsonResult(6006, "保存失败") } bookResult.BookName = book_name bookResult.Description = description bookResult.CommentStatus = comment_status bookResult.Label = tag - c.JsonResult(0,"ok",bookResult) + c.JsonResult(0, "ok", bookResult) } //设置项目私有状态. -func (c *BookController) PrivatelyOwned() { +func (c *BookController) PrivatelyOwned() { status := c.GetString("status") if status != "open" && status != "close" { - c.JsonResult(6003,"参数错误") + c.JsonResult(6003, "参数错误") } state := 0 if status == "open" { state = 0 - }else{ + } else { state = 1 } - bookResult,err := c.IsPermission() + bookResult, err := c.IsPermission() if err != nil { - c.JsonResult(6001,err.Error()) + c.JsonResult(6001, err.Error()) } //只有创始人才能变更私有状态 if bookResult.RoleId != conf.BookFounder { - c.JsonResult(6002,"权限不足") + c.JsonResult(6002, "权限不足") } - book,err := models.NewBook().Find(bookResult.BookId) + book, err := models.NewBook().Find(bookResult.BookId) if err != nil { - c.JsonResult(6005,"项目不存在") + c.JsonResult(6005, "项目不存在") } book.PrivatelyOwned = state err = book.Update() if err != nil { - logs.Error("PrivatelyOwned => ",err) - c.JsonResult(6004,"保存失败") + logs.Error("PrivatelyOwned => ", err) + c.JsonResult(6004, "保存失败") } - c.JsonResult(0,"ok") + c.JsonResult(0, "ok") } // Transfer 转让项目. -func (c *BookController) Transfer() { +func (c *BookController) Transfer() { c.Prepare() account := c.GetString("account") if account == "" { - c.JsonResult(6004,"接受者账号不能为空") + c.JsonResult(6004, "接受者账号不能为空") } - member,err := models.NewMember().FindByAccount(account) + member, err := models.NewMember().FindByAccount(account) if err != nil { - logs.Error("FindByAccount => ",err) - c.JsonResult(6005,"接受用户不存在") + logs.Error("FindByAccount => ", err) + c.JsonResult(6005, "接受用户不存在") } if member.Status != 0 { - c.JsonResult(6006,"接受用户已被禁用") + c.JsonResult(6006, "接受用户已被禁用") } if member.MemberId == c.Member.MemberId { - c.JsonResult(6007,"不能转让给自己") + c.JsonResult(6007, "不能转让给自己") } - bookResult,err := c.IsPermission() + bookResult, err := c.IsPermission() if err != nil { - c.JsonResult(6001,err.Error()) + c.JsonResult(6001, err.Error()) } - err = models.NewRelationship().Transfer(bookResult.BookId,c.Member.MemberId,member.MemberId) + err = models.NewRelationship().Transfer(bookResult.BookId, c.Member.MemberId, member.MemberId) if err != nil { - logs.Error("Transfer => ",err) - c.JsonResult(6008,err.Error()) + logs.Error("Transfer => ", err) + c.JsonResult(6008, err.Error()) } - c.JsonResult(0,"ok") + c.JsonResult(0, "ok") } + //上传项目封面. -func (c *BookController) UploadCover() { +func (c *BookController) UploadCover() { - bookResult,err := c.IsPermission() + bookResult, err := c.IsPermission() if err != nil { - c.JsonResult(6001,err.Error()) + c.JsonResult(6001, err.Error()) } - book,err := models.NewBook().Find(bookResult.BookId) + book, err := models.NewBook().Find(bookResult.BookId) if err != nil { - logs.Error("SaveBook => ",err) - c.JsonResult(6002,err.Error()) + logs.Error("SaveBook => ", err) + c.JsonResult(6002, err.Error()) } - file,moreFile,err := c.GetFile("image-file") + file, moreFile, err := c.GetFile("image-file") defer file.Close() if err != nil { - logs.Error("",err.Error()) - c.JsonResult(500,"读取文件异常") + logs.Error("", err.Error()) + c.JsonResult(500, "读取文件异常") } ext := filepath.Ext(moreFile.Filename) - if !strings.EqualFold(ext,".png") && !strings.EqualFold(ext,".jpg") && !strings.EqualFold(ext,".gif") && !strings.EqualFold(ext,".jpeg") { - c.JsonResult(500,"不支持的图片格式") + if !strings.EqualFold(ext, ".png") && !strings.EqualFold(ext, ".jpg") && !strings.EqualFold(ext, ".gif") && !strings.EqualFold(ext, ".jpeg") { + c.JsonResult(500, "不支持的图片格式") } - - x1 ,_ := strconv.ParseFloat(c.GetString("x"),10) - y1 ,_ := strconv.ParseFloat(c.GetString("y"),10) - w1 ,_ := strconv.ParseFloat(c.GetString("width"),10) - h1 ,_ := strconv.ParseFloat(c.GetString("height"),10) + x1, _ := strconv.ParseFloat(c.GetString("x"), 10) + y1, _ := strconv.ParseFloat(c.GetString("y"), 10) + w1, _ := strconv.ParseFloat(c.GetString("width"), 10) + h1, _ := strconv.ParseFloat(c.GetString("height"), 10) x := int(x1) y := int(y1) width := int(w1) height := int(h1) - fileName := "cover_" + strconv.FormatInt(time.Now().UnixNano(), 16) + fileName := "cover_" + strconv.FormatInt(time.Now().UnixNano(), 16) - filePath := filepath.Join("uploads",time.Now().Format("200601"),fileName + ext) + filePath := filepath.Join("uploads", time.Now().Format("200601"), fileName+ext) path := filepath.Dir(filePath) os.MkdirAll(path, os.ModePerm) - err = c.SaveToFile("image-file",filePath) + err = c.SaveToFile("image-file", filePath) if err != nil { - logs.Error("",err) - c.JsonResult(500,"图片保存失败") + logs.Error("", err) + c.JsonResult(500, "图片保存失败") } defer func(filePath string) { os.Remove(filePath) }(filePath) //剪切图片 - subImg,err := graphics.ImageCopyFromFile(filePath,x,y,width,height) - - if err != nil{ - logs.Error("graphics.ImageCopyFromFile => ",err) - c.JsonResult(500,"图片剪切") - } - - filePath = filepath.Join(commands.WorkingDirectory,"uploads",time.Now().Format("200601"),fileName + "_small" + ext) - - //生成缩略图并保存到磁盘 - err = graphics.ImageResizeSaveFile(subImg,175,230,filePath) + subImg, err := graphics.ImageCopyFromFile(filePath, x, y, width, height) if err != nil { - logs.Error("ImageResizeSaveFile => ",err.Error()) - c.JsonResult(500,"保存图片失败") + logs.Error("graphics.ImageCopyFromFile => ", err) + c.JsonResult(500, "图片剪切") } - url := "/" + strings.Replace(strings.TrimPrefix(filePath,commands.WorkingDirectory),"\\","/",-1) + filePath = filepath.Join(conf.WorkingDirectory, "uploads", time.Now().Format("200601"), fileName+"_small"+ext) - if strings.HasPrefix(url,"//") { + //生成缩略图并保存到磁盘 + err = graphics.ImageResizeSaveFile(subImg, 175, 230, filePath) + + if err != nil { + logs.Error("ImageResizeSaveFile => ", err.Error()) + c.JsonResult(500, "保存图片失败") + } + + url := "/" + strings.Replace(strings.TrimPrefix(filePath, conf.WorkingDirectory), "\\", "/", -1) + + if strings.HasPrefix(url, "//") { url = string(url[1:]) } @@ -330,15 +328,15 @@ func (c *BookController) UploadCover() { book.Cover = url - if err := book.Update() ; err != nil { - c.JsonResult(6001,"保存图片失败") + if err := book.Update(); err != nil { + c.JsonResult(6001, "保存图片失败") } //如果原封面不是默认封面则删除 if old_cover != conf.GetDefaultCover() { os.Remove("." + old_cover) } - c.JsonResult(0,"ok",url) + c.JsonResult(0, "ok", url) } // Users 用户列表. @@ -347,13 +345,13 @@ func (c *BookController) Users() { c.TplName = "book/users.tpl" key := c.Ctx.Input.Param(":key") - pageIndex,_ := c.GetInt("page",1) + pageIndex, _ := c.GetInt("page", 1) - if key == ""{ + if key == "" { c.Abort("404") } - book,err := models.NewBookResult().FindByIdentify(key,c.Member.MemberId) + book, err := models.NewBookResult().FindByIdentify(key, c.Member.MemberId) if err != nil { if err == models.ErrPermissionDenied { c.Abort("403") @@ -363,20 +361,20 @@ func (c *BookController) Users() { c.Data["Model"] = *book - members,totalCount,err := models.NewMemberRelationshipResult().FindForUsersByBookId(book.BookId,pageIndex,15) + members, totalCount, err := models.NewMemberRelationshipResult().FindForUsersByBookId(book.BookId, pageIndex, 15) if totalCount > 0 { html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, 10, totalCount) c.Data["PageHtml"] = html - }else{ + } else { c.Data["PageHtml"] = "" } - b,err := json.Marshal(members) + b, err := json.Marshal(members) if err != nil { c.Data["Result"] = template.JS("[]") - }else{ + } else { c.Data["Result"] = template.JS(string(b)) } } @@ -385,28 +383,28 @@ func (c *BookController) Users() { func (c *BookController) Create() { if c.Ctx.Input.IsPost() { - book_name := strings.TrimSpace(c.GetString("book_name","")) - identify := strings.TrimSpace(c.GetString("identify","")) - description := strings.TrimSpace(c.GetString("description","")) - privately_owned,_ := strconv.Atoi(c.GetString("privately_owned")) + book_name := strings.TrimSpace(c.GetString("book_name", "")) + identify := strings.TrimSpace(c.GetString("identify", "")) + description := strings.TrimSpace(c.GetString("description", "")) + privately_owned, _ := strconv.Atoi(c.GetString("privately_owned")) comment_status := c.GetString("comment_status") if book_name == "" { - c.JsonResult(6001,"项目名称不能为空") + c.JsonResult(6001, "项目名称不能为空") } if identify == "" { - c.JsonResult(6002,"项目标识不能为空") + c.JsonResult(6002, "项目标识不能为空") } - if ok,err := regexp.MatchString(`^[a-z]+[a-zA-Z0-9_\-]*$`,identify); !ok || err != nil { - c.JsonResult(6003,"项目标识只能包含小写字母、数字,以及“-”和“_”符号,并且只能小写字母开头") + if ok, err := regexp.MatchString(`^[a-z]+[a-zA-Z0-9_\-]*$`, identify); !ok || err != nil { + c.JsonResult(6003, "项目标识只能包含小写字母、数字,以及“-”和“_”符号,并且只能小写字母开头") } - if strings.Count(identify,"") > 50 { - c.JsonResult(6004,"文档标识不能超过50字") + if strings.Count(identify, "") > 50 { + c.JsonResult(6004, "文档标识不能超过50字") } - if strings.Count(description,"") > 500 { - c.JsonResult(6004,"项目描述不能大于500字") + if strings.Count(description, "") > 500 { + c.JsonResult(6004, "项目描述不能大于500字") } - if privately_owned !=0 && privately_owned != 1 { + if privately_owned != 0 && privately_owned != 1 { privately_owned = 1 } if comment_status != "open" && comment_status != "closed" && comment_status != "group_only" && comment_status != "registered_only" { @@ -415,39 +413,39 @@ func (c *BookController) Create() { book := models.NewBook() - if books,_ := book.FindByField("identify",identify); len(books) > 0 { - c.JsonResult(6006,"项目标识已存在") + if books, _ := book.FindByField("identify", identify); len(books) > 0 { + c.JsonResult(6006, "项目标识已存在") } - book.BookName = book_name + book.BookName = book_name book.Description = description book.CommentCount = 0 book.PrivatelyOwned = privately_owned book.CommentStatus = comment_status - book.Identify = identify - book.DocCount = 0 - book.MemberId = c.Member.MemberId + book.Identify = identify + book.DocCount = 0 + book.MemberId = c.Member.MemberId book.CommentCount = 0 - book.Version = time.Now().Unix() - book.Cover = conf.GetDefaultCover() - book.Editor = "markdown" - book.Theme = "default" + book.Version = time.Now().Unix() + book.Cover = conf.GetDefaultCover() + book.Editor = "markdown" + book.Theme = "default" err := book.Insert() if err != nil { - logs.Error("Insert => ",err) - c.JsonResult(6005,"保存项目失败") + logs.Error("Insert => ", err) + c.JsonResult(6005, "保存项目失败") } - bookResult,err := models.NewBookResult().FindByIdentify(book.Identify,c.Member.MemberId) + bookResult, err := models.NewBookResult().FindByIdentify(book.Identify, c.Member.MemberId) if err != nil { beego.Error(err) } - c.JsonResult(0,"ok",bookResult) + c.JsonResult(0, "ok", bookResult) } - c.JsonResult(6001,"error") + c.JsonResult(6001, "error") } // CreateToken 创建访问来令牌. @@ -455,22 +453,22 @@ func (c *BookController) CreateToken() { action := c.GetString("action") - bookResult ,err := c.IsPermission() + bookResult, err := c.IsPermission() if err != nil { if err == models.ErrPermissionDenied { - c.JsonResult(403,"权限不足") + c.JsonResult(403, "权限不足") } if err == orm.ErrNoRows { - c.JsonResult(404,"项目不存在") + c.JsonResult(404, "项目不存在") } - logs.Error("生成阅读令牌失败 =>",err) - c.JsonResult(6002,err.Error()) + logs.Error("生成阅读令牌失败 =>", err) + c.JsonResult(6002, err.Error()) } book := models.NewBook() - if _,err := book.Find(bookResult.BookId);err != nil { - c.JsonResult(6001,"项目不存在") + if _, err := book.Find(bookResult.BookId); err != nil { + c.JsonResult(6001, "项目不存在") } if action == "create" { if bookResult.PrivatelyOwned == 0 { @@ -482,14 +480,14 @@ 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)) - }else{ + c.JsonResult(0, "ok", c.BaseUrl()+beego.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken)) + } else { book.PrivateToken = "" - if err := book.Update();err != nil { - logs.Error("CreateToken => ",err) - c.JsonResult(6004,"删除令牌失败") + if err := book.Update(); err != nil { + logs.Error("CreateToken => ", err) + c.JsonResult(6004, "删除令牌失败") } - c.JsonResult(0,"ok","") + c.JsonResult(0, "ok", "") } } @@ -497,25 +495,25 @@ func (c *BookController) CreateToken() { func (c *BookController) Delete() { c.Prepare() - bookResult ,err := c.IsPermission() + bookResult, err := c.IsPermission() if err != nil { - c.JsonResult(6001,err.Error()) + c.JsonResult(6001, err.Error()) } if bookResult.RoleId != conf.BookFounder { - c.JsonResult(6002,"只有创始人才能删除项目") + c.JsonResult(6002, "只有创始人才能删除项目") } err = models.NewBook().ThoroughDeleteBook(bookResult.BookId) if err == orm.ErrNoRows { - c.JsonResult(6002,"项目不存在") + c.JsonResult(6002, "项目不存在") } if err != nil { - logs.Error("删除项目 => ",err) - c.JsonResult(6003,"删除失败") + logs.Error("删除项目 => ", err) + c.JsonResult(6003, "删除失败") } - c.JsonResult(0,"ok") + c.JsonResult(0, "ok") } //发布项目. @@ -524,15 +522,15 @@ func (c *BookController) Release() { identify := c.GetString("identify") - book_id := 0 + bookId := 0 if c.Member.IsAdministrator() { - book,err := models.NewBook().FindByFieldFirst("identify",identify) + book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { } - book_id = book.BookId - }else { + bookId = book.BookId + } else { book, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil { @@ -548,15 +546,18 @@ func (c *BookController) Release() { if book.RoleId != conf.BookAdmin && book.RoleId != conf.BookFounder && book.RoleId != conf.BookEditor { c.JsonResult(6003, "权限不足") } - book_id = book.BookId + bookId = book.BookId } go func(identify string) { - models.NewDocument().ReleaseContent(book_id) + models.NewDocument().ReleaseContent(bookId) + //当文档发布后,需要删除已缓存的转换项目 + outputPath := filepath.Join(beego.AppConfig.DefaultString("book_output_path", "cache"), strconv.Itoa(bookId)) + os.RemoveAll(outputPath) }(identify) - c.JsonResult(0,"发布任务已推送到任务队列,稍后将在后台执行。") + c.JsonResult(0, "发布任务已推送到任务队列,稍后将在后台执行。") } //文档排序. @@ -570,94 +571,91 @@ func (c *BookController) SaveSort() { book_id := 0 if c.Member.IsAdministrator() { - book,err := models.NewBook().FindByFieldFirst("identify",identify) + book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { } book_id = book.BookId - }else{ - bookResult,err := models.NewBookResult().FindByIdentify(identify,c.Member.MemberId) + } else { + bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil { - beego.Error("DocumentController.Edit => ",err) + beego.Error("DocumentController.Edit => ", err) c.Abort("403") } if bookResult.RoleId == conf.BookObserver { - c.JsonResult(6002,"项目不存在或权限不足") + c.JsonResult(6002, "项目不存在或权限不足") } book_id = bookResult.BookId } - content := c.Ctx.Input.RequestBody var docs []map[string]interface{} - err := json.Unmarshal(content,&docs) + err := json.Unmarshal(content, &docs) if err != nil { beego.Error(err) - c.JsonResult(6003,"数据错误") + c.JsonResult(6003, "数据错误") } - for _,item := range docs { - if doc_id,ok := item["id"].(float64);ok { - doc,err := models.NewDocument().Find(int(doc_id)); + for _, item := range docs { + if doc_id, ok := item["id"].(float64); ok { + doc, err := models.NewDocument().Find(int(doc_id)) if err != nil { beego.Error(err) - continue; - } - if doc.BookId != book_id { - logs.Info("%s","权限错误") - continue; - } - sort,ok := item["sort"].(float64); - if !ok { - beego.Info("排序数字转换失败 => ",item) continue } - parent_id,ok := item["parent"].(float64) + if doc.BookId != book_id { + logs.Info("%s", "权限错误") + continue + } + sort, ok := item["sort"].(float64) if !ok { - beego.Info("父分类转换失败 => ",item) + beego.Info("排序数字转换失败 => ", item) + continue + } + parent_id, ok := item["parent"].(float64) + if !ok { + beego.Info("父分类转换失败 => ", item) continue } if parent_id > 0 { - if parent,err := models.NewDocument().Find(int(parent_id)); err != nil || parent.BookId != book_id { + if parent, err := models.NewDocument().Find(int(parent_id)); err != nil || parent.BookId != book_id { continue } } doc.OrderSort = int(sort) doc.ParentId = int(parent_id) if err := doc.InsertOrUpdate(); err != nil { - fmt.Printf("%s",err.Error()) + fmt.Printf("%s", err.Error()) beego.Error(err) } - }else{ - fmt.Printf("文档ID转换失败 => %+v",item) + } else { + fmt.Printf("文档ID转换失败 => %+v", item) } } - c.JsonResult(0,"ok") + c.JsonResult(0, "ok") } - -func (c *BookController) IsPermission() (*models.BookResult,error) { +func (c *BookController) IsPermission() (*models.BookResult, error) { identify := c.GetString("identify") - book ,err := models.NewBookResult().FindByIdentify(identify,c.Member.MemberId) + book, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil { if err == models.ErrPermissionDenied { - return book,errors.New("权限不足") + return book, errors.New("权限不足") } if err == orm.ErrNoRows { - return book,errors.New("项目不存在") + return book, errors.New("项目不存在") } - return book,err + return book, err } if book.RoleId != conf.BookAdmin && book.RoleId != conf.BookFounder { - return book,errors.New("权限不足") + return book, errors.New("权限不足") } - return book,nil + return book, nil } - diff --git a/controllers/book_member.go b/controllers/book_member.go index 1e61a2c3..70e9fcab 100644 --- a/controllers/book_member.go +++ b/controllers/book_member.go @@ -3,10 +3,10 @@ package controllers import ( "errors" - "github.com/lifei6671/mindoc/models" - "github.com/astaxie/beego/orm" "github.com/astaxie/beego/logs" + "github.com/astaxie/beego/orm" "github.com/lifei6671/mindoc/conf" + "github.com/lifei6671/mindoc/models" ) type BookMemberController struct { @@ -14,31 +14,31 @@ type BookMemberController struct { } // AddMember 参加参与用户. -func (c *BookMemberController) AddMember() { +func (c *BookMemberController) AddMember() { identify := c.GetString("identify") account := c.GetString("account") - role_id,_ := c.GetInt("role_id",3) + role_id, _ := c.GetInt("role_id", 3) - if identify == "" || account == ""{ - c.JsonResult(6001,"参数错误") + if identify == "" || account == "" { + c.JsonResult(6001, "参数错误") } - book ,err := c.IsPermission() + book, err := c.IsPermission() if err != nil { - c.JsonResult(6001,err.Error()) + c.JsonResult(6001, err.Error()) } member := models.NewMember() - if _,err := member.FindByAccount(account) ; err != nil { - c.JsonResult(404,"用户不存在") + if _, err := member.FindByAccount(account); err != nil { + c.JsonResult(404, "用户不存在") } if member.Status == 1 { - c.JsonResult(6003,"用户已被禁用") + c.JsonResult(6003, "用户已被禁用") } - if _,err := models.NewRelationship().FindForRoleId(book.BookId,member.MemberId);err == nil { - c.JsonResult(6003,"用户已存在该项目中") + if _, err := models.NewRelationship().FindForRoleId(book.BookId, member.MemberId); err == nil { + c.JsonResult(6003, "用户已存在该项目中") } relationship := models.NewRelationship() @@ -53,53 +53,52 @@ func (c *BookMemberController) AddMember() { memberRelationshipResult.BookId = book.BookId memberRelationshipResult.ResolveRoleName() - - c.JsonResult(0,"ok",memberRelationshipResult) + c.JsonResult(0, "ok", memberRelationshipResult) } - c.JsonResult(500,err.Error()) + c.JsonResult(500, err.Error()) } // 变更指定用户在指定项目中的权限 func (c *BookMemberController) ChangeRole() { identify := c.GetString("identify") - member_id,_ := c.GetInt("member_id",0) - role,_ := c.GetInt("role_id",0) + member_id, _ := c.GetInt("member_id", 0) + role, _ := c.GetInt("role_id", 0) - if identify == "" || member_id <=0 { - c.JsonResult(6001,"参数错误") + if identify == "" || member_id <= 0 { + c.JsonResult(6001, "参数错误") } if member_id == c.Member.MemberId { - c.JsonResult(6006,"不能变更自己的权限") + c.JsonResult(6006, "不能变更自己的权限") } - book ,err := models.NewBookResult().FindByIdentify(identify,c.Member.MemberId) + book, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil { if err == models.ErrPermissionDenied { - c.JsonResult(403,"权限不足") + c.JsonResult(403, "权限不足") } if err == orm.ErrNoRows { - c.JsonResult(404,"项目不存在") + c.JsonResult(404, "项目不存在") } - c.JsonResult(6002,err.Error()) + c.JsonResult(6002, err.Error()) } if book.RoleId != 0 && book.RoleId != 1 { - c.JsonResult(403,"权限不足") + c.JsonResult(403, "权限不足") } member := models.NewMember() - if _,err := member.Find(member_id); err != nil { - c.JsonResult(6003,"用户不存在") + if _, err := member.Find(member_id); err != nil { + c.JsonResult(6003, "用户不存在") } if member.Status == 1 { - c.JsonResult(6004,"用户已被禁用") + c.JsonResult(6004, "用户已被禁用") } - relationship,err := models.NewRelationship().UpdateRoleId(book.BookId,member_id,role); + relationship, err := models.NewRelationship().UpdateRoleId(book.BookId, member_id, role) if err != nil { - logs.Error("变更用户在项目中的权限 => ",err) - c.JsonResult(6005,err.Error()) + logs.Error("变更用户在项目中的权限 => ", err) + c.JsonResult(6005, err.Error()) } memberRelationshipResult := models.NewMemberRelationshipResult().FromMember(member) @@ -108,58 +107,58 @@ func (c *BookMemberController) ChangeRole() { memberRelationshipResult.BookId = book.BookId memberRelationshipResult.ResolveRoleName() - c.JsonResult(0,"ok",memberRelationshipResult) + c.JsonResult(0, "ok", memberRelationshipResult) } // 删除参与者. -func (c *BookMemberController) RemoveMember() { +func (c *BookMemberController) RemoveMember() { identify := c.GetString("identify") - member_id,_ := c.GetInt("member_id",0) + member_id, _ := c.GetInt("member_id", 0) - if identify == "" || member_id <=0 { - c.JsonResult(6001,"参数错误") + if identify == "" || member_id <= 0 { + c.JsonResult(6001, "参数错误") } if member_id == c.Member.MemberId { - c.JsonResult(6006,"不能删除自己") + c.JsonResult(6006, "不能删除自己") } - book ,err := models.NewBookResult().FindByIdentify(identify,c.Member.MemberId) + book, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil { if err == models.ErrPermissionDenied { - c.JsonResult(403,"权限不足") + c.JsonResult(403, "权限不足") } if err == orm.ErrNoRows { - c.JsonResult(404,"项目不存在") + c.JsonResult(404, "项目不存在") } - c.JsonResult(6002,err.Error()) + c.JsonResult(6002, err.Error()) } //如果不是创始人也不是管理员则不能操作 if book.RoleId != conf.BookFounder && book.RoleId != conf.BookAdmin { - c.JsonResult(403,"权限不足") + c.JsonResult(403, "权限不足") } - err = models.NewRelationship().DeleteByBookIdAndMemberId(book.BookId,member_id) + err = models.NewRelationship().DeleteByBookIdAndMemberId(book.BookId, member_id) if err != nil { - c.JsonResult(6007,err.Error()) + c.JsonResult(6007, err.Error()) } - c.JsonResult(0,"ok") + c.JsonResult(0, "ok") } -func (c *BookMemberController) IsPermission() (*models.BookResult,error) { +func (c *BookMemberController) IsPermission() (*models.BookResult, error) { identify := c.GetString("identify") - book ,err := models.NewBookResult().FindByIdentify(identify,c.Member.MemberId) + book, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil { if err == models.ErrPermissionDenied { - return book,errors.New("权限不足") + return book, errors.New("权限不足") } if err == orm.ErrNoRows { - return book,errors.New("项目不存在") + return book, errors.New("项目不存在") } - return book,err + return book, err } if book.RoleId != conf.BookAdmin && book.RoleId != conf.BookFounder { - return book,errors.New("权限不足") + return book, errors.New("权限不足") } - return book,nil -} \ No newline at end of file + return book, nil +} diff --git a/controllers/comment.go b/controllers/comment.go index 1769dcb5..ff70e555 100644 --- a/controllers/comment.go +++ b/controllers/comment.go @@ -4,16 +4,16 @@ type CommentController struct { BaseController } -func (c *CommentController) Lists() { - +func (c *CommentController) Lists() { + } func (c *CommentController) Create() { - c.JsonResult(0,"ok") + c.JsonResult(0, "ok") } -func (c *CommentController) Index() { +func (c *CommentController) Index() { c.Prepare() c.TplName = "comment/index.tpl" -} \ No newline at end of file +} diff --git a/controllers/document.go b/controllers/document.go index 693e3722..4fa5fc6c 100644 --- a/controllers/document.go +++ b/controllers/document.go @@ -11,7 +11,7 @@ import ( "strconv" "strings" "time" - + "net/url" "image/png" "bytes" @@ -21,7 +21,6 @@ import ( "github.com/astaxie/beego/orm" "github.com/boombuler/barcode" "github.com/boombuler/barcode/qr" - "github.com/lifei6671/mindoc/commands" "github.com/lifei6671/mindoc/conf" "github.com/lifei6671/mindoc/models" "github.com/lifei6671/mindoc/utils" @@ -101,12 +100,10 @@ func promptUserToLogIn(c *DocumentController) { beego.Info("Access " + c.Ctx.Request.URL.RequestURI() + " not permitted.") beego.Info(" Access will be redirected to login page(SessionId: " + c.CruSession.SessionID() + ").") - c.SetSession("turl", c.Ctx.Request.URL.RequestURI()) - if c.IsAjax() { - c.JsonResult(6000, "需要[重]登录。") + c.JsonResult(6000, "请重新登录。") } else { - c.Redirect(beego.URLFor("AccountController.Login"), 302) + c.Redirect(beego.URLFor("AccountController.Login")+ "?url=" + url.PathEscape(conf.BaseUrl+ c.Ctx.Request.URL.RequestURI()), 302) } } @@ -156,8 +153,7 @@ func (c *DocumentController) Read() { token := c.GetString("token") id := c.GetString(":id") - c.Data["DocumentId"] = id // added by dandycheung, 2017-12-08, for exporting - beego.Info("DocumentController.Read(): c.Data[\"DocumentId\"] = ", id, ", IsAjax = ", c.IsAjax()) + c.Data["DocumentId"] = id if identify == "" || id == "" { c.Abort("404") @@ -393,7 +389,6 @@ func (c *DocumentController) Create() { document.Identify = doc_identify - document.Version = time.Now().Unix() document.DocumentName = doc_name document.ParentId = parent_id @@ -438,11 +433,10 @@ func (c *DocumentController) Upload() { } beego.Info(conf.GetUploadFileSize()) beego.Info(moreFile.Size) - if conf.GetUploadFileSize() > 0 && moreFile.Size > conf.GetUploadFileSize() { - c.JsonResult(6009,"查过文件允许的上传最大值") + if conf.GetUploadFileSize() > 0 && moreFile.Size > conf.GetUploadFileSize() { + c.JsonResult(6009, "查过文件允许的上传最大值") } - ext := filepath.Ext(moreFile.Filename) if ext == "" { @@ -498,7 +492,7 @@ func (c *DocumentController) Upload() { } fileName := "attach_" + strconv.FormatInt(time.Now().UnixNano(), 16) - filePath := filepath.Join(commands.WorkingDirectory, "uploads", time.Now().Format("200601"), fileName+ext) + filePath := filepath.Join(conf.WorkingDirectory, "uploads", time.Now().Format("200601"), fileName+ext) path := filepath.Dir(filePath) os.MkdirAll(path, os.ModePerm) @@ -515,7 +509,7 @@ func (c *DocumentController) Upload() { attachment.FileName = moreFile.Filename attachment.CreateAt = c.Member.MemberId attachment.FileExt = ext - attachment.FilePath = strings.TrimPrefix(filePath, commands.WorkingDirectory) + attachment.FilePath = strings.TrimPrefix(filePath, conf.WorkingDirectory) attachment.DocumentId = doc_id if fileInfo, err := os.Stat(filePath); err == nil { @@ -527,7 +521,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, commands.WorkingDirectory), "\\", "/", -1) + attachment.HttpPath = "/" + strings.Replace(strings.TrimPrefix(filePath, conf.WorkingDirectory), "\\", "/", -1) if strings.HasPrefix(attachment.HttpPath, "//") { attachment.HttpPath = string(attachment.HttpPath[1:]) } @@ -621,7 +615,7 @@ func (c *DocumentController) DownloadAttachment() { c.Abort("404") } - c.Ctx.Output.Download(filepath.Join(commands.WorkingDirectory, attachment.FilePath), attachment.FileName) + c.Ctx.Output.Download(filepath.Join(conf.WorkingDirectory, attachment.FilePath), attachment.FileName) c.StopRun() } @@ -666,7 +660,7 @@ func (c *DocumentController) RemoveAttachment() { c.JsonResult(6005, "删除失败") } - os.Remove(filepath.Join(commands.WorkingDirectory, attach.FilePath)) + os.Remove(filepath.Join(conf.WorkingDirectory, attach.FilePath)) c.JsonResult(0, "ok", attach) } @@ -819,15 +813,13 @@ func (c *DocumentController) Content() { beego.Error("DocumentHistory InsertOrUpdate => ", err) } } - if auto_release { + if auto_release { go func(identify string) { models.NewDocument().ReleaseContent(book_id) - }(identify) } - c.JsonResult(0, "ok", doc) } @@ -844,7 +836,6 @@ func (c *DocumentController) Content() { c.JsonResult(0, "ok", doc) } - func (c *DocumentController) GetDocumentById(id string) (doc *models.Document, err error) { doc = models.NewDocument() if doc_id, err := strconv.Atoi(id); err == nil { @@ -894,55 +885,33 @@ func (c *DocumentController) Export() { bookResult = isReadable(identify, token, c) } - if bookResult.PrivatelyOwned == 0 { - // TODO: 私有项目禁止导出 - } - - if !strings.HasPrefix(bookResult.Cover,"http:://") && !strings.HasPrefix(bookResult.Cover,"https:://"){ + if !strings.HasPrefix(bookResult.Cover, "http:://") && !strings.HasPrefix(bookResult.Cover, "https:://") { bookResult.Cover = c.BaseUrl() + bookResult.Cover } - eBookResult,err := bookResult.Converter(c.CruSession.SessionID()) + eBookResult, err := bookResult.Converter(c.CruSession.SessionID()) if err != nil { beego.Error("转换文档失败:" + bookResult.BookName + " -> " + err.Error()) c.Abort("500") } - if output == "pdf" { - c.Ctx.Output.Download(eBookResult.PDFPath, identify + ".pdf") + c.Ctx.Output.Download(eBookResult.PDFPath, bookResult.BookName+".pdf") - //如果没有开启缓存,则10分钟后删除 - if !bookResult.IsCacheEBook { - defer func(pdfpath string) { - time.Sleep(time.Minute * 10) - os.Remove(filepath.Dir(pdfpath)) - }(eBookResult.PDFPath) - } - c.StopRun() - }else if output == "epub" { - c.Ctx.Output.Download(eBookResult.PDFPath, identify + ".epub") + c.Abort("200") + } else if output == "epub" { + c.Ctx.Output.Download(eBookResult.EpubPath, bookResult.BookName+".epub") - //如果没有开启缓存,则10分钟后删除 - if !bookResult.IsCacheEBook { - defer func(pdfpath string) { - time.Sleep(time.Minute * 10) - os.Remove(filepath.Dir(pdfpath)) - }(eBookResult.EpubPath) - } - c.StopRun() - }else if output == "mobi" { - c.Ctx.Output.Download(eBookResult.PDFPath, identify + ".epub") + c.Abort("200") + } else if output == "mobi" { + c.Ctx.Output.Download(eBookResult.MobiPath, bookResult.BookName+".epub") - //如果没有开启缓存,则10分钟后删除 - if !bookResult.IsCacheEBook { - defer func(pdfpath string) { - time.Sleep(time.Minute * 10) - os.Remove(filepath.Dir(pdfpath)) - }(eBookResult.MobiPath) - } - c.StopRun() + c.Abort("200") + } else if output == "docx" { + c.Ctx.Output.Download(eBookResult.WordPath, bookResult.BookName+".epub") + + c.Abort("200") } c.Abort("404") diff --git a/controllers/home.go b/controllers/home.go index 51f9a99f..b3fcfa70 100644 --- a/controllers/home.go +++ b/controllers/home.go @@ -1,10 +1,12 @@ package controllers import ( + "net/url" "github.com/astaxie/beego" "github.com/lifei6671/mindoc/models" "github.com/lifei6671/mindoc/utils" "math" + "github.com/lifei6671/mindoc/conf" ) type HomeController struct { @@ -16,9 +18,9 @@ func (c *HomeController) Index() { c.TplName = "home/index.tpl" //如果没有开启匿名访问,则跳转到登录页面 if !c.EnableAnonymous && c.Member == nil { - c.Redirect(beego.URLFor("AccountController.Login"),302) + c.Redirect(beego.URLFor("AccountController.Login") + "?url=" + url.PathEscape(conf.BaseUrl + c.Ctx.Request.URL.RequestURI()), 302) } - pageIndex,_ := c.GetInt("page",1) + pageIndex, _ := c.GetInt("page", 1) pageSize := 18 member_id := 0 @@ -26,7 +28,7 @@ func (c *HomeController) Index() { if c.Member != nil { member_id = c.Member.MemberId } - books,totalCount,err := models.NewBook().FindForHomeToPager(pageIndex,pageSize,member_id) + books, totalCount, err := models.NewBook().FindForHomeToPager(pageIndex, pageSize, member_id) if err != nil { beego.Error(err) @@ -36,18 +38,18 @@ func (c *HomeController) Index() { html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, pageSize, totalCount) c.Data["PageHtml"] = html - }else { + } else { c.Data["PageHtml"] = "" } c.Data["TotalPages"] = int(math.Ceil(float64(totalCount) / float64(pageSize))) c.Data["Lists"] = books - labels ,totalCount,err := models.NewLabel().FindToPager(1,10) + labels, totalCount, err := models.NewLabel().FindToPager(1, 10) if err != nil { - c.Data["Labels"] = make([]*models.Label,0) - }else{ + c.Data["Labels"] = make([]*models.Label, 0) + } else { c.Data["Labels"] = labels } } diff --git a/controllers/label.go b/controllers/label.go index ca36fe66..98b7386c 100644 --- a/controllers/label.go +++ b/controllers/label.go @@ -1,10 +1,10 @@ package controllers import ( - "github.com/lifei6671/mindoc/models" - "github.com/astaxie/beego/orm" "github.com/astaxie/beego" + "github.com/astaxie/beego/orm" "github.com/lifei6671/mindoc/conf" + "github.com/lifei6671/mindoc/models" "github.com/lifei6671/mindoc/utils" "math" ) @@ -18,7 +18,7 @@ func (c *LabelController) Prepare() { //如果没有开启你们访问则跳转到登录 if !c.EnableAnonymous && c.Member == nil { - c.Redirect(beego.URLFor("AccountController.Login"),302) + c.Redirect(beego.URLFor("AccountController.Login"), 302) return } } @@ -29,16 +29,16 @@ func (c *LabelController) Index() { c.TplName = "label/index.tpl" labelName := c.Ctx.Input.Param(":key") - pageIndex,_ := c.GetInt("page",1) + pageIndex, _ := c.GetInt("page", 1) if labelName == "" { c.Abort("404") } - _,err := models.NewLabel().FindFirst("label_name",labelName) + _, err := models.NewLabel().FindFirst("label_name", labelName) if err != nil { if err == orm.ErrNoRows { c.Abort("404") - }else{ + } else { beego.Error(err) c.Abort("500") } @@ -47,7 +47,7 @@ func (c *LabelController) Index() { if c.Member != nil { member_id = c.Member.MemberId } - search_result,totalCount,err := models.NewBook().FindForLabelToPager(labelName,pageIndex,conf.PageSize,member_id) + search_result, totalCount, err := models.NewBook().FindForLabelToPager(labelName, pageIndex, conf.PageSize, member_id) if err != nil { beego.Error(err) @@ -57,7 +57,7 @@ func (c *LabelController) Index() { html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, conf.PageSize, totalCount) c.Data["PageHtml"] = html - }else { + } else { c.Data["PageHtml"] = "" } c.Data["Lists"] = search_result @@ -69,25 +69,22 @@ func (c *LabelController) List() { c.Prepare() c.TplName = "label/list.tpl" - pageIndex,_ := c.GetInt("page",1) + pageIndex, _ := c.GetInt("page", 1) pageSize := 200 - labels ,totalCount,err := models.NewLabel().FindToPager(pageIndex,pageSize) + labels, totalCount, err := models.NewLabel().FindToPager(pageIndex, pageSize) if err != nil { - c.ShowErrorPage(50001,err.Error()) + c.ShowErrorPage(50001, err.Error()) } if totalCount > 0 { html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, pageSize, totalCount) c.Data["PageHtml"] = html - }else { + } else { c.Data["PageHtml"] = "" } c.Data["TotalPages"] = int(math.Ceil(float64(totalCount) / float64(pageSize))) c.Data["Labels"] = labels } - - - diff --git a/controllers/manager.go b/controllers/manager.go index 17e4085b..6b1e7f8f 100644 --- a/controllers/manager.go +++ b/controllers/manager.go @@ -13,7 +13,6 @@ import ( "github.com/lifei6671/mindoc/models" "github.com/lifei6671/mindoc/utils" "path/filepath" - "github.com/lifei6671/mindoc/commands" "strconv" ) @@ -21,7 +20,7 @@ type ManagerController struct { BaseController } -func (c *ManagerController) Prepare (){ +func (c *ManagerController) Prepare() { c.BaseController.Prepare() if !c.Member.IsAdministrator() { @@ -42,7 +41,7 @@ func (c *ManagerController) Users() { pageIndex, _ := c.GetInt("page", 0) - members, totalCount, err := models.NewMember().FindToPager(pageIndex, 15) + members, totalCount, err := models.NewMember().FindToPager(pageIndex, conf.PageSize) if err != nil { c.Data["ErrorMessage"] = err.Error() @@ -50,7 +49,7 @@ func (c *ManagerController) Users() { } if totalCount > 0 { - html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, 10, int(totalCount)) + html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, conf.PageSize, int(totalCount)) c.Data["PageHtml"] = html } else { @@ -139,10 +138,10 @@ func (c *ManagerController) UpdateMemberStatus() { c.JsonResult(6002, "用户不存在") } if member.MemberId == c.Member.MemberId { - c.JsonResult(6004,"不能变更自己的状态") + c.JsonResult(6004, "不能变更自己的状态") } if member.Role == conf.MemberSuperRole { - c.JsonResult(6005,"不能变更超级管理员的状态") + c.JsonResult(6005, "不能变更超级管理员的状态") } member.Status = status @@ -171,10 +170,10 @@ func (c *ManagerController) ChangeMemberRole() { c.JsonResult(6002, "用户不存在") } if member.MemberId == c.Member.MemberId { - c.JsonResult(6004,"不能变更自己的权限") + c.JsonResult(6004, "不能变更自己的权限") } if member.Role == conf.MemberSuperRole { - c.JsonResult(6005,"不能变更超级管理员的权限") + c.JsonResult(6005, "不能变更超级管理员的权限") } member.Role = role @@ -191,13 +190,13 @@ func (c *ManagerController) EditMember() { c.Prepare() c.TplName = "manager/edit_users.tpl" - member_id,_ := c.GetInt(":id",0) + member_id, _ := c.GetInt(":id", 0) if member_id <= 0 { c.Abort("404") } - member ,err := models.NewMember().Find(member_id) + member, err := models.NewMember().Find(member_id) if err != nil { beego.Error(err) @@ -213,64 +212,64 @@ func (c *ManagerController) EditMember() { member.Phone = phone member.Description = description if password1 != "" && password2 != password1 { - c.JsonResult(6001,"确认密码不正确") + c.JsonResult(6001, "确认密码不正确") } - if password1 != "" && member.AuthMethod != conf.AuthMethodLDAP{ + if password1 != "" && member.AuthMethod != conf.AuthMethodLDAP { member.Password = password1 } - if err := member.Valid(password1 == "");err != nil { - c.JsonResult(6002,err.Error()) + if err := member.Valid(password1 == ""); err != nil { + c.JsonResult(6002, err.Error()) } if password1 != "" { - password,err := utils.PasswordHash(password1) + password, err := utils.PasswordHash(password1) if err != nil { beego.Error(err) - c.JsonResult(6003,"对用户密码加密时出错") + c.JsonResult(6003, "对用户密码加密时出错") } member.Password = password } - if err := member.Update();err != nil { + if err := member.Update(); err != nil { beego.Error(err) - c.JsonResult(6004,"保存失败") + c.JsonResult(6004, "保存失败") } - c.JsonResult(0,"ok") + c.JsonResult(0, "ok") } c.Data["Model"] = member } //删除一个用户,并将该用户的所有信息转移到超级管理员上. -func (c *ManagerController) DeleteMember() { +func (c *ManagerController) DeleteMember() { c.Prepare() - member_id,_ := c.GetInt("id",0) + member_id, _ := c.GetInt("id", 0) if member_id <= 0 { - c.JsonResult(404,"参数错误") + c.JsonResult(404, "参数错误") } - member ,err := models.NewMember().Find(member_id) + member, err := models.NewMember().Find(member_id) if err != nil { beego.Error(err) - c.JsonResult(500,"用户不存在") + c.JsonResult(500, "用户不存在") } if member.Role == conf.MemberSuperRole { - c.JsonResult(500,"不能删除超级管理员") + c.JsonResult(500, "不能删除超级管理员") } - superMember,err := models.NewMember().FindByFieldFirst("role",0) + superMember, err := models.NewMember().FindByFieldFirst("role", 0) if err != nil { beego.Error(err) - c.JsonResult(5001,"未能找到超级管理员") + c.JsonResult(5001, "未能找到超级管理员") } - err = models.NewMember().Delete(member_id,superMember.MemberId) + err = models.NewMember().Delete(member_id, superMember.MemberId) if err != nil { beego.Error(err) - c.JsonResult(5002,"删除失败") + c.JsonResult(5002, "删除失败") } - c.JsonResult(0,"ok") + c.JsonResult(0, "ok") } //项目列表. @@ -572,9 +571,9 @@ func (c *ManagerController) AttachList() { c.Data["PageHtml"] = "" } - for _,item := range attachList { + for _, item := range attachList { - p := filepath.Join(commands.WorkingDirectory,item.FilePath) + p := filepath.Join(conf.WorkingDirectory, item.FilePath) item.IsExist = utils.FileExists(p) @@ -583,27 +582,27 @@ func (c *ManagerController) AttachList() { } //附件详情. -func (c *ManagerController) AttachDetailed() { +func (c *ManagerController) AttachDetailed() { c.Prepare() c.TplName = "manager/attach_detailed.tpl" - attach_id,_ := strconv.Atoi(c.Ctx.Input.Param(":id")) + attach_id, _ := strconv.Atoi(c.Ctx.Input.Param(":id")) if attach_id <= 0 { c.Abort("404") } - attach,err := models.NewAttachmentResult().Find(attach_id) + attach, err := models.NewAttachmentResult().Find(attach_id) if err != nil { - beego.Error("AttachDetailed => ",err) + beego.Error("AttachDetailed => ", err) if err == orm.ErrNoRows { c.Abort("404") - }else{ + } else { c.Abort("500") } } - attach.FilePath = filepath.Join(commands.WorkingDirectory,attach.FilePath) + attach.FilePath = filepath.Join(conf.WorkingDirectory, attach.FilePath) attach.HttpPath = c.BaseUrl() + attach.HttpPath attach.IsExist = utils.FileExists(attach.FilePath) @@ -612,43 +611,22 @@ func (c *ManagerController) AttachDetailed() { } //删除附件. -func (c *ManagerController) AttachDelete() { +func (c *ManagerController) AttachDelete() { c.Prepare() - attach_id,_ := c.GetInt("attach_id") + attach_id, _ := c.GetInt("attach_id") if attach_id <= 0 { c.Abort("404") } - attach,err := models.NewAttachment().Find(attach_id) + attach, err := models.NewAttachment().Find(attach_id) if err != nil { - beego.Error("AttachDelete => ",err) - c.JsonResult(6001,err.Error()) + beego.Error("AttachDelete => ", err) + c.JsonResult(6001, err.Error()) } - if err := attach.Delete();err != nil { - beego.Error("AttachDelete => ",err) - c.JsonResult(6002,err.Error()) + if err := attach.Delete(); err != nil { + beego.Error("AttachDelete => ", err) + c.JsonResult(6002, err.Error()) } - c.JsonResult(0,"ok") + c.JsonResult(0, "ok") } - - - - - - - - - - - - - - - - - - - - - diff --git a/controllers/search.go b/controllers/search.go index 4681acae..9387aaf1 100644 --- a/controllers/search.go +++ b/controllers/search.go @@ -1,31 +1,31 @@ package controllers import ( - "github.com/lifei6671/mindoc/models" - "github.com/lifei6671/mindoc/conf" - "github.com/lifei6671/mindoc/utils" "github.com/astaxie/beego" - "strings" + "github.com/lifei6671/mindoc/conf" + "github.com/lifei6671/mindoc/models" + "github.com/lifei6671/mindoc/utils" "regexp" "strconv" + "strings" ) type SearchController struct { BaseController } -func (c *SearchController) Index() { +func (c *SearchController) Index() { c.Prepare() c.TplName = "search/index.tpl" //如果没有开启你们访问则跳转到登录 if !c.EnableAnonymous && c.Member == nil { - c.Redirect(beego.URLFor("AccountController.Login"),302) + c.Redirect(beego.URLFor("AccountController.Login"), 302) return } keyword := c.GetString("keyword") - pageIndex,_ := c.GetInt("page",1) + pageIndex, _ := c.GetInt("page", 1) c.Data["BaseUrl"] = c.BaseUrl() @@ -35,7 +35,7 @@ func (c *SearchController) Index() { if c.Member != nil { member_id = c.Member.MemberId } - search_result,totalCount,err := models.NewDocumentSearchResult().FindToPager(keyword,pageIndex,conf.PageSize,member_id) + search_result, totalCount, err := models.NewDocumentSearchResult().FindToPager(keyword, pageIndex, conf.PageSize, member_id) if err != nil { beego.Error(err) @@ -45,12 +45,12 @@ func (c *SearchController) Index() { html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, conf.PageSize, totalCount) c.Data["PageHtml"] = html - }else { + } else { c.Data["PageHtml"] = "" } if len(search_result) > 0 { - for _,item := range search_result { - item.DocumentName = strings.Replace(item.DocumentName,keyword,"" + keyword + "",-1) + for _, item := range search_result { + item.DocumentName = strings.Replace(item.DocumentName, keyword, ""+keyword+"", -1) if item.Description != "" { src := item.Description @@ -79,13 +79,13 @@ func (c *SearchController) Index() { if len(r) > 100 { src = string(r[:100]) - }else{ + } else { src = string(r) } - item.Description = strings.Replace(src, keyword, "" + keyword + "", -1) + item.Description = strings.Replace(src, keyword, ""+keyword+"", -1) } - if item.Identify == ""{ + if item.Identify == "" { item.Identify = strconv.Itoa(item.DocumentId) } if item.ModifyTime.IsZero() { diff --git a/controllers/setting.go b/controllers/setting.go index 04852cf2..11e0b867 100644 --- a/controllers/setting.go +++ b/controllers/setting.go @@ -3,24 +3,23 @@ package controllers import ( "fmt" "os" - "strings" "path/filepath" "strconv" + "strings" "time" "github.com/astaxie/beego/logs" + "github.com/lifei6671/mindoc/conf" + "github.com/lifei6671/mindoc/graphics" "github.com/lifei6671/mindoc/models" "github.com/lifei6671/mindoc/utils" - "github.com/lifei6671/mindoc/graphics" - "github.com/lifei6671/mindoc/conf" - "github.com/lifei6671/mindoc/commands" ) type SettingController struct { BaseController } -func (c *SettingController) Index() { +func (c *SettingController) Index() { c.TplName = "setting/index.tpl" if c.Ctx.Input.IsPost() { @@ -43,131 +42,129 @@ func (c *SettingController) Index() { } } -func (c *SettingController) Password() { +func (c *SettingController) Password() { c.TplName = "setting/password.tpl" if c.Ctx.Input.IsPost() { if c.Member.AuthMethod == conf.AuthMethodLDAP { - c.JsonResult(6009,"当前用户不支持修改密码") + c.JsonResult(6009, "当前用户不支持修改密码") } password1 := c.GetString("password1") password2 := c.GetString("password2") password3 := c.GetString("password3") if password1 == "" { - c.JsonResult(6003,"原密码不能为空") + c.JsonResult(6003, "原密码不能为空") } if password2 == "" { - c.JsonResult(6004,"新密码不能为空") + c.JsonResult(6004, "新密码不能为空") } - if count := strings.Count(password2,""); count < 6 || count > 18 { - c.JsonResult(6009,"密码必须在6-18字之间") + if count := strings.Count(password2, ""); count < 6 || count > 18 { + c.JsonResult(6009, "密码必须在6-18字之间") } if password2 != password3 { - c.JsonResult(6003,"确认密码不正确") + c.JsonResult(6003, "确认密码不正确") } - if ok,_ := utils.PasswordVerify(c.Member.Password,password1) ; !ok { - c.JsonResult(6005,"原始密码不正确") + if ok, _ := utils.PasswordVerify(c.Member.Password, password1); !ok { + c.JsonResult(6005, "原始密码不正确") } if password1 == password2 { - c.JsonResult(6006,"新密码不能和原始密码相同") + c.JsonResult(6006, "新密码不能和原始密码相同") } - pwd,err := utils.PasswordHash(password2) + pwd, err := utils.PasswordHash(password2) if err != nil { - c.JsonResult(6007,"密码加密失败") + c.JsonResult(6007, "密码加密失败") } c.Member.Password = pwd - if err := c.Member.Update();err != nil { - c.JsonResult(6008,err.Error()) + if err := c.Member.Update(); err != nil { + c.JsonResult(6008, err.Error()) } - c.JsonResult(0,"ok") + c.JsonResult(0, "ok") } } // Upload 上传图片 func (c *SettingController) Upload() { - file,moreFile,err := c.GetFile("image-file") + file, moreFile, err := c.GetFile("image-file") defer file.Close() if err != nil { - logs.Error("",err.Error()) - c.JsonResult(500,"读取文件异常") + logs.Error("", err.Error()) + c.JsonResult(500, "读取文件异常") } ext := filepath.Ext(moreFile.Filename) - if !strings.EqualFold(ext,".png") && !strings.EqualFold(ext,".jpg") && !strings.EqualFold(ext,".gif") && !strings.EqualFold(ext,".jpeg") { - c.JsonResult(500,"不支持的图片格式") + if !strings.EqualFold(ext, ".png") && !strings.EqualFold(ext, ".jpg") && !strings.EqualFold(ext, ".gif") && !strings.EqualFold(ext, ".jpeg") { + c.JsonResult(500, "不支持的图片格式") } - - x1 ,_ := strconv.ParseFloat(c.GetString("x"),10) - y1 ,_ := strconv.ParseFloat(c.GetString("y"),10) - w1 ,_ := strconv.ParseFloat(c.GetString("width"),10) - h1 ,_ := strconv.ParseFloat(c.GetString("height"),10) + x1, _ := strconv.ParseFloat(c.GetString("x"), 10) + y1, _ := strconv.ParseFloat(c.GetString("y"), 10) + w1, _ := strconv.ParseFloat(c.GetString("width"), 10) + h1, _ := strconv.ParseFloat(c.GetString("height"), 10) x := int(x1) y := int(y1) width := int(w1) height := int(h1) - fmt.Println(x,x1,y,y1) + fmt.Println(x, x1, y, y1) - fileName := "avatar_" + strconv.FormatInt(time.Now().UnixNano(), 16) + fileName := "avatar_" + strconv.FormatInt(time.Now().UnixNano(), 16) - filePath := filepath.Join(commands.WorkingDirectory,"uploads" , time.Now().Format("200601") , fileName + ext) + filePath := filepath.Join(conf.WorkingDirectory, "uploads", time.Now().Format("200601"), fileName+ext) path := filepath.Dir(filePath) os.MkdirAll(path, os.ModePerm) - err = c.SaveToFile("image-file",filePath) + err = c.SaveToFile("image-file", filePath) if err != nil { - logs.Error("",err) - c.JsonResult(500,"图片保存失败") + logs.Error("", err) + c.JsonResult(500, "图片保存失败") } - //剪切图片 - subImg,err := graphics.ImageCopyFromFile(filePath,x,y,width,height) + subImg, err := graphics.ImageCopyFromFile(filePath, x, y, width, height) if err != nil { - logs.Error("ImageCopyFromFile => ",err) - c.JsonResult(6001,"头像剪切失败") + logs.Error("ImageCopyFromFile => ", err) + c.JsonResult(6001, "头像剪切失败") } os.Remove(filePath) - filePath = filepath.Join(commands.WorkingDirectory,"uploads" , time.Now().Format("200601") , fileName + "_small" + ext) + filePath = filepath.Join(conf.WorkingDirectory, "uploads", time.Now().Format("200601"), fileName+"_small"+ext) - err = graphics.ImageResizeSaveFile(subImg,120,120,filePath) + err = graphics.ImageResizeSaveFile(subImg, 120, 120, filePath) //err = graphics.SaveImage(filePath,subImg) if err != nil { - logs.Error("保存文件失败 => ",err.Error()) - c.JsonResult(500,"保存文件失败") + logs.Error("保存文件失败 => ", err.Error()) + c.JsonResult(500, "保存文件失败") } - url := "/" + strings.Replace(strings.TrimPrefix(filePath,commands.WorkingDirectory),"\\","/",-1) - if strings.HasPrefix(url,"//") { + url := "/" + strings.Replace(strings.TrimPrefix(filePath, conf.WorkingDirectory), "\\", "/", -1) + if strings.HasPrefix(url, "//") { url = string(url[1:]) } - if member,err := models.NewMember().Find(c.Member.MemberId);err == nil { + if member, err := models.NewMember().Find(c.Member.MemberId); err == nil { avater := member.Avatar member.Avatar = url - err := member.Update(); + err := member.Update() if err == nil { - if strings.HasPrefix(avater,"/uploads/") { - os.Remove(filepath.Join(commands.WorkingDirectory,avater)) + if strings.HasPrefix(avater, "/uploads/") { + os.Remove(filepath.Join(conf.WorkingDirectory, avater)) } c.SetMember(*member) - }else{ - c.JsonResult(60001,"保存头像失败") + } else { + c.JsonResult(60001, "保存头像失败") } } - c.JsonResult(0,"ok",url) -} \ No newline at end of file + c.JsonResult(0, "ok", url) +} diff --git a/converter/converter.go b/converter/converter.go index 700caf72..020450f0 100644 --- a/converter/converter.go +++ b/converter/converter.go @@ -11,14 +11,12 @@ import ( "strings" "time" - "os/exec" - "errors" - "github.com/TruthHun/gotil/cryptil" - "github.com/TruthHun/gotil/filetil" - "github.com/TruthHun/gotil/ziptil" + "github.com/lifei6671/mindoc/utils/filetil" + "github.com/lifei6671/mindoc/utils/ziptil" + "github.com/lifei6671/mindoc/utils/cryptil" ) type Converter struct { @@ -67,6 +65,7 @@ var ( output = "output" //文档导出文件夹 ebookConvert = "ebook-convert" ) + // 接口文档 https://manual.calibre-ebook.com/generated/en/ebook-convert.html#table-of-contents //根据json配置文件,创建文档转化对象 func NewConverter(configFile string, debug ...bool) (converter *Converter, err error) { @@ -124,7 +123,8 @@ func (this *Converter) Convert() (err error) { } //将当前文件夹下的所有文件压缩成zip包,然后直接改名成content.epub - f := this.BasePath + "/content.epub" + f := filepath.Join(this.BasePath, "content.epub") + fmt.Println("epub目录 " + f) os.Remove(f) //如果原文件存在了,则删除; if err = ziptil.Zip(f, this.BasePath); err == nil { //创建导出文件夹 @@ -144,6 +144,12 @@ func (this *Converter) Convert() (err error) { } case "pdf": if err = this.convertToPdf(); err != nil { + fmt.Println(err) + errs = append(errs, err.Error()) + } + case "docx": + if err = this.convertToDocx(); err != nil { + fmt.Println(err) errs = append(errs, err.Error()) } } @@ -157,6 +163,8 @@ func (this *Converter) Convert() (err error) { fmt.Println(err) } } + } else { + fmt.Println("压缩目录出错" + err.Error()) } return } @@ -164,13 +172,13 @@ func (this *Converter) Convert() (err error) { //删除生成导出文档而创建的文件 func (this *Converter) converterDefer() { //删除不必要的文件 - os.RemoveAll(this.BasePath + "/META-INF") - os.RemoveAll(this.BasePath + "/content.epub") - os.RemoveAll(this.BasePath + "/mimetype") - os.RemoveAll(this.BasePath + "/toc.ncx") - os.RemoveAll(this.BasePath + "/content.opf") - os.RemoveAll(this.BasePath + "/titlepage.xhtml") //封面图片待优化 - os.RemoveAll(this.BasePath + "/summary.html") //文档目录 + os.RemoveAll(filepath.Join(this.BasePath, "META-INF")) + os.RemoveAll(filepath.Join(this.BasePath, "content.epub")) + os.RemoveAll(filepath.Join(this.BasePath, "mimetype")) + os.RemoveAll(filepath.Join(this.BasePath, "toc.ncx")) + os.RemoveAll(filepath.Join(this.BasePath, "content.opf")) + os.RemoveAll(filepath.Join(this.BasePath, "titlepage.xhtml")) //封面图片待优化 + os.RemoveAll(filepath.Join(this.BasePath, "summary.html")) //文档目录 } //生成metainfo @@ -182,15 +190,15 @@ func (this *Converter) generateMetaInfo() (err error) { ` - folder := this.BasePath + "/META-INF" + folder := filepath.Join(this.BasePath, "META-INF") os.MkdirAll(folder, os.ModePerm) - err = ioutil.WriteFile(folder+"/container.xml", []byte(xml), os.ModePerm) + err = ioutil.WriteFile(filepath.Join(folder, "container.xml"), []byte(xml), os.ModePerm) return } //形成mimetyppe func (this *Converter) generateMimeType() (err error) { - return ioutil.WriteFile(this.BasePath+"/mimetype", []byte("application/epub+zip"), os.ModePerm) + return ioutil.WriteFile(filepath.Join(this.BasePath, "mimetype"), []byte("application/epub+zip"), os.ModePerm) } //生成封面 @@ -216,7 +224,7 @@ func (this *Converter) generateTitlePage() (err error) { ` - if err = ioutil.WriteFile(this.BasePath+"/titlepage.xhtml", []byte(xml), os.ModePerm); err == nil { + if err = ioutil.WriteFile(filepath.Join(this.BasePath, "titlepage.xhtml"), []byte(xml), os.ModePerm); err == nil { this.GeneratedCover = "titlepage.xhtml" } } @@ -241,7 +249,7 @@ func (this *Converter) generateTocNcx() (err error) { ` codes, _ := this.tocToXml(0, 1) ncx = fmt.Sprintf(ncx, this.Config.Language, this.Config.Title, strings.Join(codes, "")) - return ioutil.WriteFile(this.BasePath+"/toc.ncx", []byte(ncx), os.ModePerm) + return ioutil.WriteFile(filepath.Join(this.BasePath, "toc.ncx"), []byte(ncx), os.ModePerm) } //生成文档目录,即summary.html @@ -263,7 +271,7 @@ func (this *Converter) generateSummary() (err error) { ` summary = fmt.Sprintf(summary, strings.Join(this.tocToSummary(0), "")) - return ioutil.WriteFile(this.BasePath+"/summary.html", []byte(summary), os.ModePerm) + return ioutil.WriteFile(filepath.Join(this.BasePath, "summary.html"), []byte(summary), os.ModePerm) } //将toc转成toc.ncx文件 @@ -380,6 +388,8 @@ func (this *Converter) generateContentOpf() (err error) { manifestArr = append(manifestArr, fmt.Sprintf(``, sourcefile, id, mt)) } } + } else { + fmt.Println(file.Path) } } @@ -415,14 +425,14 @@ func (this *Converter) generateContentOpf() (err error) { guide = `` + guide + `` } pkg = fmt.Sprintf(pkg, meta, manifest, spine, guide) - return ioutil.WriteFile(this.BasePath+"/content.opf", []byte(pkg), os.ModePerm) + return ioutil.WriteFile(filepath.Join(this.BasePath, "content.opf"), []byte(pkg), os.ModePerm) } //转成epub func (this *Converter) convertToEpub() (err error) { args := []string{ - this.BasePath + "/content.epub", - this.BasePath + "/" + output + "/book.epub", + filepath.Join(this.BasePath, "content.epub"), + filepath.Join(this.BasePath, output, "book.epub"), } cmd := exec.Command(ebookConvert, args...) @@ -435,8 +445,8 @@ func (this *Converter) convertToEpub() (err error) { //转成mobi func (this *Converter) convertToMobi() (err error) { args := []string{ - this.BasePath + "/content.epub", - this.BasePath + "/" + output + "/book.mobi", + filepath.Join(this.BasePath, "content.epub"), + filepath.Join(this.BasePath, output, "book.mobi"), } cmd := exec.Command(ebookConvert, args...) if this.Debug { @@ -449,8 +459,8 @@ func (this *Converter) convertToMobi() (err error) { //转成pdf func (this *Converter) convertToPdf() (err error) { args := []string{ - this.BasePath + "/content.epub", - this.BasePath + "/" + output + "/book.pdf", + filepath.Join(this.BasePath, "content.epub"), + filepath.Join(this.BasePath, output, "book.pdf"), } //页面大小 if len(this.Config.PaperSize) > 0 { @@ -490,6 +500,40 @@ func (this *Converter) convertToPdf() (err error) { } cmd := exec.Command(ebookConvert, args...) + if this.Debug { + fmt.Println(cmd.Args) + } + + return cmd.Run() +} + +// 转成word +func (this *Converter) convertToDocx() (err error) { + args := []string{ + this.BasePath + "/content.epub", + this.BasePath + "/" + output + "/book.docx", + } + args = append(args, "--docx-no-toc") + + //页面大小 + if len(this.Config.PaperSize) > 0 { + args = append(args, "--docx-page-size", this.Config.PaperSize) + } + + if len(this.Config.MarginLeft) > 0 { + args = append(args, "--docx-page-margin-left", this.Config.MarginLeft) + } + if len(this.Config.MarginTop) > 0 { + args = append(args, "--docx-page-margin-top", this.Config.MarginTop) + } + if len(this.Config.MarginRight) > 0 { + args = append(args, "--docx-page-margin-right", this.Config.MarginRight) + } + if len(this.Config.MarginBottom) > 0 { + args = append(args, "--docx-page-margin-bottom", this.Config.MarginBottom) + } + cmd := exec.Command(ebookConvert, args...) + if this.Debug { fmt.Println(cmd.Args) } diff --git a/graphics/file.go b/graphics/file.go index 246e824c..6df12451 100644 --- a/graphics/file.go +++ b/graphics/file.go @@ -13,7 +13,7 @@ import ( // 将图片保存到指定的路径 func SaveImage(p string, src image.Image) error { - os.MkdirAll(filepath.Dir(p),0666) + os.MkdirAll(filepath.Dir(p), 0666) f, err := os.OpenFile(p, os.O_SYNC|os.O_RDWR|os.O_CREATE, 0666) diff --git a/models/attachment.go b/models/attachment.go index 219e16b6..cbe0b456 100644 --- a/models/attachment.go +++ b/models/attachment.go @@ -127,7 +127,7 @@ func (m *Attachment) FindToPager(pageIndex, pageSize int) (attachList []*Attachm } else { attach.DocumentName = "[不存在]" } - attach.LocalHttpPath = strings.Replace(item.FilePath,"\\","/",-1) + attach.LocalHttpPath = strings.Replace(item.FilePath, "\\", "/", -1) attachList = append(attachList, attach) } diff --git a/models/attachment_result.go b/models/attachment_result.go index a324e126..2b832f25 100644 --- a/models/attachment_result.go +++ b/models/attachment_result.go @@ -8,27 +8,27 @@ import ( type AttachmentResult struct { Attachment - IsExist bool - BookName string - DocumentName string + IsExist bool + BookName string + DocumentName string FileShortSize string - Account string + Account string LocalHttpPath string } func NewAttachmentResult() *AttachmentResult { - return &AttachmentResult{ IsExist : false } + return &AttachmentResult{IsExist: false} } -func (m *AttachmentResult) Find(id int) (*AttachmentResult,error) { +func (m *AttachmentResult) Find(id int) (*AttachmentResult, error) { o := orm.NewOrm() attach := NewAttachment() - err := o.QueryTable(m.TableNameWithPrefix()).Filter("attachment_id",id).One(attach) + err := o.QueryTable(m.TableNameWithPrefix()).Filter("attachment_id", id).One(attach) if err != nil { - return m,err + return m, err } m.Attachment = *attach @@ -50,12 +50,12 @@ func (m *AttachmentResult) Find(id int) (*AttachmentResult,error) { if attach.CreateAt > 0 { member := NewMember() - if e := o.QueryTable(member.TableNameWithPrefix()).Filter("member_id",attach.CreateAt).One(member,"account");e == nil { + if e := o.QueryTable(member.TableNameWithPrefix()).Filter("member_id", attach.CreateAt).One(member, "account"); e == nil { m.Account = member.Account } } m.FileShortSize = utils.FormatBytes(int64(attach.FileSize)) - m.LocalHttpPath = strings.Replace(m.FilePath,"\\","/",-1) + m.LocalHttpPath = strings.Replace(m.FilePath, "\\", "/", -1) - return m,nil -} \ No newline at end of file + return m, nil +} diff --git a/models/base.go b/models/base.go index 23e1ee6b..f254a464 100644 --- a/models/base.go +++ b/models/base.go @@ -1,6 +1,4 @@ package models type Model struct { - } - diff --git a/models/blogs.go b/models/blogs.go index 80ee253f..aa3346b6 100644 --- a/models/blogs.go +++ b/models/blogs.go @@ -4,9 +4,9 @@ import "time" //博文表 type Blog struct { - BlogId int + BlogId int BlogTitle string - MemberId int + MemberId int //文字摘要 BlogExcerpt string //文章内容 @@ -22,4 +22,4 @@ type Blog struct { ModifyAt int //创建时间 Created time.Time -} \ No newline at end of file +} diff --git a/models/book.go b/models/book.go index 3e49a368..6f77c9c2 100644 --- a/models/book.go +++ b/models/book.go @@ -3,11 +3,14 @@ package models import ( "time" + "fmt" "github.com/astaxie/beego" "github.com/astaxie/beego/logs" "github.com/astaxie/beego/orm" "github.com/lifei6671/mindoc/conf" - "fmt" + "os" + "path/filepath" + "strconv" ) // Book struct . @@ -16,17 +19,15 @@ type Book struct { // BookName 项目名称. BookName string `orm:"column(book_name);size(500)" json:"book_name"` // Identify 项目唯一标识. - Identify string `orm:"column(identify);size(100);unique" json:"identify"` + Identify string `orm:"column(identify);size(100);unique" json:"identify"` //是否是自动发布 0 否/1 是 AutoRelease int `orm:"column(auto_release);type(int);default(0)" json:"auto_release"` - OrderIndex int `orm:"column(order_index);type(int);default(0)" json:"order_index"` + OrderIndex int `orm:"column(order_index);type(int);default(0)" json:"order_index"` // Description 项目描述. Description string `orm:"column(description);size(2000)" json:"description"` //发行公司 - Publisher string `orm:"column(publisher);size(500)" json:"publisher"` - //是否缓存导出的电子书,如果缓存可能会出现导出的文件不是最新的。 0 为不缓存 - IsCacheEBook int `orm:"column(is_cache_ebook);type(int);default(0)" json:"is_cache_ebook"` - Label string `orm:"column(label);size(500)" json:"label"` + Publisher string `orm:"column(publisher);size(500)" json:"publisher"` + Label string `orm:"column(label);size(500)" json:"label"` // PrivatelyOwned 项目私有: 0 公开/ 1 私有 PrivatelyOwned int `orm:"column(privately_owned);type(int);default(0)" json:"privately_owned"` // 当项目是私有时的访问Token. @@ -122,7 +123,7 @@ func (m *Book) Update(cols ...string) error { temp := NewBook() temp.BookId = m.BookId - if err := o.Read(temp);err != nil { + if err := o.Read(temp); err != nil { return err } @@ -185,7 +186,7 @@ func (m *Book) FindToPager(pageIndex, pageSize, memberId int) (books []*BookResu " LEFT JOIN " + relationship.TableNameWithPrefix() + " AS rel ON book.book_id=rel.book_id AND rel.member_id = ?" + " LEFT JOIN " + relationship.TableNameWithPrefix() + " AS rel1 ON book.book_id=rel1.book_id AND rel1.role_id=0" + " LEFT JOIN " + NewMember().TableNameWithPrefix() + " AS m ON rel1.member_id=m.member_id " + - " WHERE rel.relationship_id > 0 ORDER BY book.order_index DESC,book.book_id DESC LIMIT " + fmt.Sprintf("%d,%d",offset,pageSize) + " WHERE rel.relationship_id > 0 ORDER BY book.order_index DESC,book.book_id DESC LIMIT " + fmt.Sprintf("%d,%d", offset, pageSize) _, err = o.Raw(sql2, memberId).QueryRows(&books) if err != nil { @@ -261,6 +262,8 @@ func (m *Book) ThoroughDeleteBook(id int) error { NewLabel().InsertOrUpdateMulti(m.Label) } + os.RemoveAll(filepath.Join(conf.WorkingDirectory,"uploads","books",strconv.Itoa(id))) + return o.Commit() } @@ -320,7 +323,7 @@ func (m *Book) FindForLabelToPager(keyword string, pageIndex, pageSize, member_i if member_id > 0 { sql1 := "SELECT COUNT(*) FROM md_books AS book LEFT JOIN md_relationship AS rel ON rel.book_id = book.book_id AND rel.member_id = ? WHERE (relationship_id > 0 OR book.privately_owned = 0) AND book.label LIKE ?" - err = o.Raw(sql1, member_id,keyword).QueryRow(&totalCount) + err = o.Raw(sql1, member_id, keyword).QueryRow(&totalCount) if err != nil { return } @@ -330,12 +333,12 @@ func (m *Book) FindForLabelToPager(keyword string, pageIndex, pageSize, member_i LEFT JOIN md_members AS member ON rel1.member_id = member.member_id WHERE (rel.relationship_id > 0 OR book.privately_owned = 0) AND book.label LIKE ? ORDER BY order_index DESC ,book.book_id DESC LIMIT ?,?` - _, err = o.Raw(sql2, member_id,keyword, offset, pageSize).QueryRows(&books) + _, err = o.Raw(sql2, member_id, keyword, offset, pageSize).QueryRows(&books) return } else { - count, err1 := o.QueryTable(NewBook().TableNameWithPrefix()).Filter("privately_owned", 0).Filter("label__icontains",keyword).Count() + count, err1 := o.QueryTable(NewBook().TableNameWithPrefix()).Filter("privately_owned", 0).Filter("label__icontains", keyword).Count() if err1 != nil { err = err1 @@ -348,14 +351,13 @@ func (m *Book) FindForLabelToPager(keyword string, pageIndex, pageSize, member_i LEFT JOIN md_members AS member ON rel.member_id = member.member_id WHERE book.privately_owned = 0 AND book.label LIKE ? ORDER BY order_index DESC ,book.book_id DESC LIMIT ?,?` - _, err = o.Raw(sql,keyword, offset, pageSize).QueryRows(&books) + _, err = o.Raw(sql, keyword, offset, pageSize).QueryRows(&books) return } } - //重置文档数量 func (m *Book) ResetDocumentNumber(book_id int) { o := orm.NewOrm() diff --git a/models/book_result.go b/models/book_result.go index 1eded718..ec80c3aa 100644 --- a/models/book_result.go +++ b/models/book_result.go @@ -1,64 +1,64 @@ package models import ( - "time" "bytes" - - "github.com/astaxie/beego/orm" - "github.com/astaxie/beego/logs" - "github.com/lifei6671/mindoc/conf" - "strings" - "github.com/lifei6671/mindoc/converter" - "strconv" - "github.com/russross/blackfriday" - "path/filepath" - "github.com/astaxie/beego" + "time" + "io/ioutil" "os" + "path/filepath" + "strconv" + "strings" + + "encoding/base64" "github.com/PuerkitoBio/goquery" + "github.com/astaxie/beego" + "github.com/astaxie/beego/logs" + "github.com/astaxie/beego/orm" + "github.com/lifei6671/mindoc/conf" + "github.com/lifei6671/mindoc/converter" "github.com/lifei6671/mindoc/utils" + "github.com/russross/blackfriday" ) type BookResult struct { - BookId int `json:"book_id"` - BookName string `json:"book_name"` - Identify string `json:"identify"` - OrderIndex int `json:"order_index"` - Description string `json:"description"` - Publisher string `json:"publisher"` - IsCacheEBook bool `json:"is_cache_ebook"` - PrivatelyOwned int `json:"privately_owned"` - PrivateToken string `json:"private_token"` - DocCount int `json:"doc_count"` - CommentStatus string `json:"comment_status"` - CommentCount int `json:"comment_count"` - CreateTime time.Time `json:"create_time"` - CreateName string `json:"create_name"` - ModifyTime time.Time `json:"modify_time"` - Cover string `json:"cover"` - Theme string `json:"theme"` - Label string `json:"label"` - MemberId int `json:"member_id"` - Editor string `json:"editor"` - AutoRelease bool `json:"auto_release"` + BookId int `json:"book_id"` + BookName string `json:"book_name"` + Identify string `json:"identify"` + OrderIndex int `json:"order_index"` + Description string `json:"description"` + Publisher string `json:"publisher"` + PrivatelyOwned int `json:"privately_owned"` + PrivateToken string `json:"private_token"` + DocCount int `json:"doc_count"` + CommentStatus string `json:"comment_status"` + CommentCount int `json:"comment_count"` + CreateTime time.Time `json:"create_time"` + CreateName string `json:"create_name"` + ModifyTime time.Time `json:"modify_time"` + Cover string `json:"cover"` + Theme string `json:"theme"` + Label string `json:"label"` + MemberId int `json:"member_id"` + Editor string `json:"editor"` + AutoRelease bool `json:"auto_release"` - RelationshipId int `json:"relationship_id"` - RoleId int `json:"role_id"` - RoleName string `json:"role_name"` - Status int + RelationshipId int `json:"relationship_id"` + RoleId int `json:"role_id"` + RoleName string `json:"role_name"` + Status int - LastModifyText string `json:"last_modify_text"` - IsDisplayComment bool `json:"is_display_comment"` + LastModifyText string `json:"last_modify_text"` + IsDisplayComment bool `json:"is_display_comment"` } func NewBookResult() *BookResult { return &BookResult{} } - // 根据项目标识查询项目以及指定用户权限的信息. -func (m *BookResult) FindByIdentify(identify string,member_id int) (*BookResult,error) { +func (m *BookResult) FindByIdentify(identify string, member_id int) (*BookResult, error) { if identify == "" || member_id <= 0 { - return m,ErrInvalidParameter + return m, ErrInvalidParameter } o := orm.NewOrm() @@ -93,11 +93,10 @@ func (m *BookResult) FindByIdentify(identify string,member_id int) (*BookResult, m = NewBookResult().ToBookResult(*book) - m.CreateName = member.Account - m.MemberId = relationship.MemberId - m.RoleId = relationship.RoleId - m.RelationshipId = relationship.RelationshipId - + m.CreateName = member.Account + m.MemberId = relationship.MemberId + m.RoleId = relationship.RoleId + m.RelationshipId = relationship.RelationshipId if m.RoleId == conf.BookFounder { m.RoleName = "创始人" @@ -123,10 +122,10 @@ func (m *BookResult) FindByIdentify(identify string,member_id int) (*BookResult, return m, nil } -func (m *BookResult) FindToPager(pageIndex, pageSize int) (books []*BookResult,totalCount int,err error) { +func (m *BookResult) FindToPager(pageIndex, pageSize int) (books []*BookResult, totalCount int, err error) { o := orm.NewOrm() - count,err := o.QueryTable(NewBook().TableNameWithPrefix()).Count() + count, err := o.QueryTable(NewBook().TableNameWithPrefix()).Count() if err != nil { return @@ -140,9 +139,9 @@ func (m *BookResult) FindToPager(pageIndex, pageSize int) (books []*BookResult,t LEFT JOIN md_members AS m ON rel.member_id = m.member_id ORDER BY book.order_index DESC ,book.book_id DESC LIMIT ?,?` - offset := (pageIndex -1 )* pageSize + offset := (pageIndex - 1) * pageSize - _,err = o.Raw(sql,offset,pageSize).QueryRows(&books) + _, err = o.Raw(sql, offset, pageSize).QueryRows(&books) return } @@ -169,7 +168,6 @@ func (m *BookResult) ToBookResult(book Book) *BookResult { m.Theme = book.Theme m.AutoRelease = book.AutoRelease == 1 m.Publisher = book.Publisher - m.IsCacheEBook = book.IsCacheEBook == 1 if book.Theme == "" { m.Theme = "default" @@ -180,128 +178,139 @@ func (m *BookResult) ToBookResult(book Book) *BookResult { return m } -func (m *BookResult) Converter(sessionId string) (ConvertBookResult,error) { +func (m *BookResult) Converter(sessionId string) (ConvertBookResult, error) { convertBookResult := ConvertBookResult{} - outputPath := filepath.Join(beego.AppConfig.DefaultString("book_output_path","cache"),sessionId,strconv.Itoa(m.BookId)) - if m.IsCacheEBook { - outputPath = filepath.Join(beego.AppConfig.DefaultString("book_output_path","cache"),strconv.Itoa(m.BookId)) + outputPath := filepath.Join(conf.WorkingDirectory,"uploads","books", strconv.Itoa(m.BookId)) + viewPath := beego.BConfig.WebConfig.ViewsPath + + pdfpath := filepath.Join(outputPath, "book.pdf") + epubpath := filepath.Join(outputPath, "book.epub") + mobipath := filepath.Join(outputPath, "book.mobi") + docxpath := filepath.Join(outputPath, "book.docx") + + //先将转换的文件储存到临时目录 + tempOutputPath := filepath.Join(os.TempDir(),"sessionId") //filepath.Abs(filepath.Join("cache", sessionId)) + + os.MkdirAll(outputPath, 0766) + os.MkdirAll(tempOutputPath, 0766) + + + if utils.FileExists(pdfpath) && utils.FileExists(epubpath) && utils.FileExists(mobipath) && utils.FileExists(docxpath) { + convertBookResult.EpubPath = epubpath + convertBookResult.MobiPath = mobipath + convertBookResult.PDFPath = pdfpath + convertBookResult.WordPath = docxpath + return convertBookResult, nil } - if m.IsCacheEBook { - pdfpath := filepath.Join(outputPath,"output","book.pdf") - epubpath := filepath.Join(outputPath,"output","book.epub") - mobipath := filepath.Join(outputPath,"output","book.mobi") - if utils.FileExists(pdfpath) && utils.FileExists(epubpath) && utils.FileExists(mobipath){ - convertBookResult.EpubPath = epubpath - convertBookResult.MobiPath = mobipath - convertBookResult.PDFPath = pdfpath - return convertBookResult,nil - } - } docs, err := NewDocument().FindListByBookId(m.BookId) if err != nil { - return convertBookResult,err + return convertBookResult, err } - tocList := make([]converter.Toc,0) + tocList := make([]converter.Toc, 0) for _, item := range docs { if item.ParentId == 0 { toc := converter.Toc{ - Id: item.DocumentId, - Link: strconv.Itoa(item.DocumentId) + ".html", - Pid: item.ParentId, + Id: item.DocumentId, + Link: strconv.Itoa(item.DocumentId) + ".html", + Pid: item.ParentId, Title: item.DocumentName, } - tocList = append(tocList,toc) + tocList = append(tocList, toc) } } for _, item := range docs { if item.ParentId != 0 { toc := converter.Toc{ - Id: item.DocumentId, - Link: strconv.Itoa(item.DocumentId) + ".html", - Pid: item.ParentId, + Id: item.DocumentId, + Link: strconv.Itoa(item.DocumentId) + ".html", + Pid: item.ParentId, Title: item.DocumentName, } - tocList = append(tocList,toc) + tocList = append(tocList, toc) } } ebookConfig := converter.Config{ - Charset : "utf-8", - Cover : m.Cover, - Timestamp : time.Now().Format("2006-01-02 15:04:05"), - Description : string(blackfriday.MarkdownBasic([]byte(m.Description))), - Footer : "

本文档使用 MinDoc 构建 - _PAGENUM_ -

", - Header : "

_SECTION_

", - Identifier : "", - Language : "zh-CN", - Creator : m.CreateName, - Publisher : m.Publisher, - Contributor : m.Publisher, - Title : m.BookName, - Format: []string{"epub", "mobi", "pdf"}, - FontSize : "14", - PaperSize : "a4", - MarginLeft : "72", - MarginRight : "72", - MarginTop : "72", - MarginBottom : "72", - Toc : tocList, - More : []string{}, - + Charset: "utf-8", + Cover: m.Cover, + Timestamp: time.Now().Format("2006-01-02 15:04:05"), + Description: string(blackfriday.MarkdownBasic([]byte(m.Description))), + Footer: "

本文档使用 MinDoc 构建 - _PAGENUM_ -

", + Header: "

_SECTION_

", + Identifier: "", + Language: "zh-CN", + Creator: m.CreateName, + Publisher: m.Publisher, + Contributor: m.Publisher, + Title: m.BookName, + Format: []string{"epub", "mobi", "pdf", "docx"}, + FontSize: "14", + PaperSize: "a4", + MarginLeft: "72", + MarginRight: "72", + MarginTop: "72", + MarginBottom: "72", + Toc: tocList, + More: []string{}, } - - os.MkdirAll(outputPath, 0766) - if outputPath, err = filepath.Abs(outputPath); err != nil { + if tempOutputPath, err = filepath.Abs(tempOutputPath); err != nil { beego.Error("导出目录配置错误:" + err.Error()) - return convertBookResult,err + return convertBookResult, err } - viewPath := beego.BConfig.WebConfig.ViewsPath - baseUrl := beego.AppConfig.DefaultString("baseurl","") - - for _,item := range docs { + for _, item := range docs { name := strconv.Itoa(item.DocumentId) - fpath := filepath.Join(outputPath,name + ".html") + fpath := filepath.Join(tempOutputPath, name+".html") f, err := os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0777) if err != nil { - return convertBookResult,err + return convertBookResult, err } var buf bytes.Buffer - if err := beego.ExecuteViewPathTemplate(&buf,"document/export.tpl",viewPath,map[string]interface{}{"Model": m, "Lists": item, "BaseUrl": baseUrl}); err != nil { - return convertBookResult,err + if err := beego.ExecuteViewPathTemplate(&buf, "document/export.tpl", viewPath, map[string]interface{}{"Model": m, "Lists": item, "BaseUrl": conf.BaseUrl}); err != nil { + return convertBookResult, err } html := buf.String() - if err != nil { f.Close() - return convertBookResult,err + return convertBookResult, err } bufio := bytes.NewReader(buf.Bytes()) doc, err := goquery.NewDocumentFromReader(bufio) doc.Find("img").Each(func(i int, contentSelection *goquery.Selection) { - if src, ok := contentSelection.Attr("src"); ok && strings.HasPrefix(src, "/uploads/") { - contentSelection.SetAttr("src", baseUrl + src) + if src, ok := contentSelection.Attr("src"); ok && strings.HasPrefix(src, "/") { + //contentSelection.SetAttr("src", baseUrl + src) + spath := filepath.Join(conf.WorkingDirectory, src) + + if ff, e := ioutil.ReadFile(spath); e == nil { + + encodeString := base64.StdEncoding.EncodeToString(ff) + + src = "data:image/" + filepath.Ext(src) + ";base64," + encodeString + + contentSelection.SetAttr("src", src) + } + } }) html, err = doc.Html() if err != nil { f.Close() - return convertBookResult,err + return convertBookResult, err } // html = strings.Replace(html, " "+ err.Error()) - return convertBookResult,err + if err := eBookConverter.Convert(); err != nil { + beego.Error("转换文件错误:" + m.BookName + " => " + err.Error()) + return convertBookResult, err } - convertBookResult.MobiPath = filepath.Join(outputPath,"output","book.mobi") - convertBookResult.PDFPath = filepath.Join(outputPath,"output","book.pdf") - convertBookResult.EpubPath = filepath.Join(outputPath,"output","book.epub") - return convertBookResult,nil + beego.Info("文档转换完成:" + m.BookName) + defer func(p string) { + os.RemoveAll(p) + }(tempOutputPath) + + utils.CopyFile(mobipath, filepath.Join(tempOutputPath, "output", "book.mobi")) + utils.CopyFile(pdfpath, filepath.Join(tempOutputPath, "output", "book.pdf")) + utils.CopyFile(epubpath, filepath.Join(tempOutputPath, "output", "book.epub")) + utils.CopyFile(docxpath, filepath.Join(tempOutputPath, "output", "book.docx")) + + convertBookResult.MobiPath = mobipath + convertBookResult.PDFPath = pdfpath + convertBookResult.EpubPath = epubpath + convertBookResult.WordPath = docxpath + + return convertBookResult, nil } - - - - - - - - - - - - - - - - - - diff --git a/models/comment.go b/models/comment.go index 14dfce02..4057260f 100644 --- a/models/comment.go +++ b/models/comment.go @@ -1,76 +1,77 @@ package models import ( - "time" - "github.com/lifei6671/mindoc/conf" - "github.com/astaxie/beego/orm" "errors" + "github.com/astaxie/beego/orm" + "github.com/lifei6671/mindoc/conf" + "time" ) //Comment struct type Comment struct { - CommentId int `orm:"pk;auto;unique;column(comment_id)" json:"comment_id"` - Floor int `orm:"column(floor);type(unsigned);default(0)" json:"floor"` - BookId int `orm:"column(book_id);type(int)" json:"book_id"` + CommentId int `orm:"pk;auto;unique;column(comment_id)" json:"comment_id"` + Floor int `orm:"column(floor);type(unsigned);default(0)" json:"floor"` + BookId int `orm:"column(book_id);type(int)" json:"book_id"` // DocumentId 评论所属的文档. - DocumentId int `orm:"column(document_id);type(int)" json:"document_id"` + DocumentId int `orm:"column(document_id);type(int)" json:"document_id"` // Author 评论作者. - Author string `orm:"column(author);size(100)" json:"author"` + Author string `orm:"column(author);size(100)" json:"author"` //MemberId 评论用户ID. - MemberId int `orm:"column(member_id);type(int)" json:"member_id"` + MemberId int `orm:"column(member_id);type(int)" json:"member_id"` // IPAddress 评论者的IP地址 - IPAddress string `orm:"column(ip_address);size(100)" json:"ip_address"` + IPAddress string `orm:"column(ip_address);size(100)" json:"ip_address"` // 评论日期. - CommentDate time.Time `orm:"type(datetime);column(comment_date);auto_now_add" json:"comment_date"` + CommentDate time.Time `orm:"type(datetime);column(comment_date);auto_now_add" json:"comment_date"` //Content 评论内容. - Content string `orm:"column(content);size(2000)" json:"content"` + Content string `orm:"column(content);size(2000)" json:"content"` // Approved 评论状态:0 待审核/1 已审核/2 垃圾评论/ 3 已删除 - Approved int `orm:"column(approved);type(int)" json:"approved"` + Approved int `orm:"column(approved);type(int)" json:"approved"` // UserAgent 评论者浏览器内容 - UserAgent string `orm:"column(user_agent);size(500)" json:"user_agent"` + UserAgent string `orm:"column(user_agent);size(500)" json:"user_agent"` // Parent 评论所属父级 - ParentId int `orm:"column(parent_id);type(int);default(0)" json:"parent_id"` - AgreeCount int `orm:"column(agree_count);type(int);default(0)" json:"agree_count"` - AgainstCount int `orm:"column(against_count);type(int);default(0)" json:"against_count"` + ParentId int `orm:"column(parent_id);type(int);default(0)" json:"parent_id"` + AgreeCount int `orm:"column(agree_count);type(int);default(0)" json:"agree_count"` + AgainstCount int `orm:"column(against_count);type(int);default(0)" json:"against_count"` } // TableName 获取对应数据库表名. func (m *Comment) TableName() string { return "comments" } + // TableEngine 获取数据使用的引擎. func (m *Comment) TableEngine() string { return "INNODB" } -func (m *Comment) TableNameWithPrefix() string { +func (m *Comment) TableNameWithPrefix() string { return conf.GetDatabasePrefix() + m.TableName() } func NewComment() *Comment { return &Comment{} } -func (m *Comment) Find(id int) (*Comment,error) { +func (m *Comment) Find(id int) (*Comment, error) { if id <= 0 { - return m,ErrInvalidParameter + return m, ErrInvalidParameter } o := orm.NewOrm() - err := o.Read(m) + err := o.Read(m) - return m,err + return m, err } -func (m *Comment) Update(cols... string) error { +func (m *Comment) Update(cols ...string) error { o := orm.NewOrm() - _,err := o.Update(m,cols...) + _, err := o.Update(m, cols...) return err } //Insert 添加一条评论. func (m *Comment) Insert() error { - if m.DocumentId <= 0{ + if m.DocumentId <= 0 { return errors.New("评论文档不存在") } if m.Content == "" { @@ -89,28 +90,28 @@ func (m *Comment) Insert() error { document := NewDocument() //如果评论的文档不存在 - if _,err := document.Find(m.DocumentId); err != nil { + if _, err := document.Find(m.DocumentId); err != nil { return err } - book ,err := NewBook().Find(document.BookId); + book, err := NewBook().Find(document.BookId) //如果评论的项目不存在 if err != nil { return err } //如果已关闭评论 - if book.CommentStatus == "closed"{ + if book.CommentStatus == "closed" { return ErrCommentClosed } - if book.CommentStatus == "registered_only" && m.MemberId <= 0{ + if book.CommentStatus == "registered_only" && m.MemberId <= 0 { return ErrPermissionDenied } //如果仅参与者评论 if book.CommentStatus == "group_only" { - if m.MemberId <= 0{ + if m.MemberId <= 0 { return ErrPermissionDenied } rel := NewRelationship() - if _,err := rel.FindForRoleId(book.BookId,m.MemberId);err != nil { + if _, err := rel.FindForRoleId(book.BookId, m.MemberId); err != nil { return ErrPermissionDenied } } @@ -118,51 +119,18 @@ func (m *Comment) Insert() error { if m.MemberId > 0 { member := NewMember() //如果用户不存在 - if _,err := member.Find(m.MemberId) ; err != nil { + if _, err := member.Find(m.MemberId); err != nil { return ErrMemberNoExist } //如果用户被禁用 if member.Status == 1 { return ErrMemberDisabled } - }else if m.Author == "" { + } else if m.Author == "" { m.Author = "[匿名用户]" } m.BookId = book.BookId - _,err = o.Insert(m) + _, err = o.Insert(m) return err } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/models/comment_result.go b/models/comment_result.go index 0527bc8a..3e1d21c6 100644 --- a/models/comment_result.go +++ b/models/comment_result.go @@ -4,11 +4,11 @@ import "github.com/astaxie/beego/orm" type CommentResult struct { Comment - Author string `json:"author"` - ReplyAccount string `json:"reply_account"` + Author string `json:"author"` + ReplyAccount string `json:"reply_account"` } -func (m *CommentResult) FindForDocumentToPager(doc_id, page_index,page_size int) (comments []*CommentResult,totalCount int,err error) { +func (m *CommentResult) FindForDocumentToPager(doc_id, page_index, page_size int) (comments []*CommentResult, totalCount int, err error) { o := orm.NewOrm() @@ -25,12 +25,11 @@ FROM md_comments AS comment WHERE comment.document_id = ? ORDER BY comment.comment_id DESC LIMIT 0,10` - offset := (page_index - 1) * page_size - _,err = o.Raw(sql1,doc_id,offset, page_size).QueryRows(&comments) + _, err = o.Raw(sql1, doc_id, offset, page_size).QueryRows(&comments) - v,err := o.QueryTable(m.TableNameWithPrefix()).Filter("document_id",doc_id).Count() + v, err := o.QueryTable(m.TableNameWithPrefix()).Filter("document_id", doc_id).Count() if err == nil { totalCount = int(v) @@ -38,4 +37,3 @@ WHERE comment.document_id = ? ORDER BY comment.comment_id DESC LIMIT 0,10` return } - diff --git a/models/comment_vote.go b/models/comment_vote.go index 026e55d3..f55638de 100644 --- a/models/comment_vote.go +++ b/models/comment_vote.go @@ -1,30 +1,31 @@ package models import ( - "time" - "github.com/lifei6671/mindoc/conf" "github.com/astaxie/beego/orm" + "github.com/lifei6671/mindoc/conf" + "time" ) type CommentVote struct { - VoteId int `orm:"column(vote_id);pk;auto;unique" json:"vote_id"` - CommentId int `orm:"column(comment_id);type(int);index" json:"comment_id"` - CommentMemberId int `orm:"column(comment_member_id);type(int);index;default(0)" json:"comment_member_id"` - VoteMemberId int `orm:"column(vote_member_id);type(int);index" json:"vote_member_id"` - VoteState int `orm:"column(vote_state);type(int)" json:"vote_state"` - CreateTime time.Time `orm:"column(create_time);type(datetime);auto_now_add" json:"create_time"` + VoteId int `orm:"column(vote_id);pk;auto;unique" json:"vote_id"` + CommentId int `orm:"column(comment_id);type(int);index" json:"comment_id"` + CommentMemberId int `orm:"column(comment_member_id);type(int);index;default(0)" json:"comment_member_id"` + VoteMemberId int `orm:"column(vote_member_id);type(int);index" json:"vote_member_id"` + VoteState int `orm:"column(vote_state);type(int)" json:"vote_state"` + CreateTime time.Time `orm:"column(create_time);type(datetime);auto_now_add" json:"create_time"` } // TableName 获取对应数据库表名. func (m *CommentVote) TableName() string { return "comment_votes" } + // TableEngine 获取数据使用的引擎. func (m *CommentVote) TableEngine() string { return "INNODB" } -func (m *CommentVote) TableNameWithPrefix() string { +func (m *CommentVote) TableNameWithPrefix() string { return conf.GetDatabasePrefix() + m.TableName() } func (u *CommentVote) TableUnique() [][]string { @@ -35,15 +36,15 @@ func (u *CommentVote) TableUnique() [][]string { func NewCommentVote() *CommentVote { return &CommentVote{} } -func (m *CommentVote) InsertOrUpdate() (*CommentVote,error) { +func (m *CommentVote) InsertOrUpdate() (*CommentVote, error) { o := orm.NewOrm() if m.VoteId > 0 { - _,err := o.Update(m) - return m,err - }else{ - _,err := o.Insert(m) + _, err := o.Update(m) + return m, err + } else { + _, err := o.Insert(m) - return m,err + return m, err } -} \ No newline at end of file +} diff --git a/models/convert_book_result.go b/models/convert_book_result.go index 6486d2e0..ba072449 100644 --- a/models/convert_book_result.go +++ b/models/convert_book_result.go @@ -2,7 +2,8 @@ package models // 转换结果 type ConvertBookResult struct { - PDFPath string + PDFPath string EpubPath string MobiPath string + WordPath string } diff --git a/models/dashboard.go b/models/dashboard.go index 7208c241..9b9ae45f 100644 --- a/models/dashboard.go +++ b/models/dashboard.go @@ -3,34 +3,34 @@ package models import "github.com/astaxie/beego/orm" type Dashboard struct { - BookNumber int64 `json:"book_number"` - DocumentNumber int64 `json:"document_number"` - MemberNumber int64 `json:"member_number"` - CommentNumber int64 `json:"comment_number"` - AttachmentNumber int64 `json:"attachment_number"` + BookNumber int64 `json:"book_number"` + DocumentNumber int64 `json:"document_number"` + MemberNumber int64 `json:"member_number"` + CommentNumber int64 `json:"comment_number"` + AttachmentNumber int64 `json:"attachment_number"` } func NewDashboard() *Dashboard { return &Dashboard{} } -func (m *Dashboard) Query() (*Dashboard) { +func (m *Dashboard) Query() *Dashboard { o := orm.NewOrm() - book_number,_ := o.QueryTable(NewBook().TableNameWithPrefix()).Count() + book_number, _ := o.QueryTable(NewBook().TableNameWithPrefix()).Count() m.BookNumber = book_number - document_count,_ := o.QueryTable(NewDocument().TableNameWithPrefix()).Count() + document_count, _ := o.QueryTable(NewDocument().TableNameWithPrefix()).Count() m.DocumentNumber = document_count - member_number,_ := o.QueryTable(NewMember().TableNameWithPrefix()).Count() + member_number, _ := o.QueryTable(NewMember().TableNameWithPrefix()).Count() m.MemberNumber = member_number //comment_number,_ := o.QueryTable(NewComment().TableNameWithPrefix()).Count() m.CommentNumber = 0 - attachment_number,_ := o.QueryTable(NewAttachment().TableNameWithPrefix()).Count() + attachment_number, _ := o.QueryTable(NewAttachment().TableNameWithPrefix()).Count() m.AttachmentNumber = attachment_number diff --git a/models/document.go b/models/document.go index 441bbbc6..c174e3ba 100644 --- a/models/document.go +++ b/models/document.go @@ -9,6 +9,9 @@ import ( "github.com/astaxie/beego/orm" "github.com/lifei6671/mindoc/conf" "strings" + "os" + "path/filepath" + "strconv" ) // Document struct. @@ -121,12 +124,12 @@ func (m *Document) RecursiveDocument(doc_id int) error { } //发布文档 -func (m *Document) ReleaseContent(book_id int) { +func (m *Document) ReleaseContent(bookId int) { o := orm.NewOrm() var docs []*Document - _, err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id", book_id).All(&docs, "document_id", "content") + _, err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id", bookId).All(&docs, "document_id", "content") if err != nil { beego.Error("发布失败 => ", err) @@ -134,12 +137,12 @@ func (m *Document) ReleaseContent(book_id int) { } for _, item := range docs { item.Release = item.Content - attach_list, err := NewAttachment().FindListByDocumentId(item.DocumentId) - if err == nil && len(attach_list) > 0 { + attachList, err := NewAttachment().FindListByDocumentId(item.DocumentId) + if err == nil && len(attachList) > 0 { content := bytes.NewBufferString("
附件
    ") - for _, attach := range attach_list { - if strings.HasPrefix(attach.HttpPath,"/"){ - attach.HttpPath = strings.TrimSuffix(beego.AppConfig.DefaultString("baseurl",""),"/") + attach.HttpPath + for _, attach := range attachList { + if strings.HasPrefix(attach.HttpPath, "/") { + attach.HttpPath = strings.TrimSuffix(beego.AppConfig.DefaultString("baseurl", ""), "/") + attach.HttpPath } li := fmt.Sprintf("
  • %s
  • ", attach.HttpPath, attach.FileName, attach.FileName) @@ -151,6 +154,8 @@ func (m *Document) ReleaseContent(book_id int) { _, err = o.Update(item, "release") if err != nil { beego.Error(fmt.Sprintf("发布失败 => %+v", item), err) + }else { + os.RemoveAll(filepath.Join(conf.WorkingDirectory,"uploads","books",strconv.Itoa(bookId))) } } } diff --git a/models/document_history.go b/models/document_history.go index 1ece38d9..1c45ea6d 100644 --- a/models/document_history.go +++ b/models/document_history.go @@ -23,14 +23,14 @@ type DocumentHistory struct { } type DocumentHistorySimpleResult struct { - HistoryId int `json:"history_id"` - ActionName string `json:"action_name"` - MemberId int `json:"member_id"` - Account string `json:"account"` - ModifyAt int `json:"modify_at"` - ModifyName string `json:"modify_name"` - ModifyTime time.Time `json:"modify_time"` - Version int64 `json:"version"` + HistoryId int `json:"history_id"` + ActionName string `json:"action_name"` + MemberId int `json:"member_id"` + Account string `json:"account"` + ModifyAt int `json:"modify_at"` + ModifyName string `json:"modify_name"` + ModifyTime time.Time `json:"modify_time"` + Version int64 `json:"version"` } // TableName 获取对应数据库表名. @@ -50,12 +50,13 @@ func (m *DocumentHistory) TableNameWithPrefix() string { func NewDocumentHistory() *DocumentHistory { return &DocumentHistory{} } -func (m *DocumentHistory) Find(id int) (*DocumentHistory,error) { +func (m *DocumentHistory) Find(id int) (*DocumentHistory, error) { o := orm.NewOrm() - err := o.QueryTable(m.TableNameWithPrefix()).Filter("history_id",id).One(m) + err := o.QueryTable(m.TableNameWithPrefix()).Filter("history_id", id).One(m) - return m,err + return m, err } + //清空指定文档的历史. func (m *DocumentHistory) Clear(doc_id int) error { o := orm.NewOrm() @@ -66,19 +67,19 @@ func (m *DocumentHistory) Clear(doc_id int) error { } //删除历史. -func (m *DocumentHistory) Delete(history_id,doc_id int) error { +func (m *DocumentHistory) Delete(history_id, doc_id int) error { o := orm.NewOrm() - _, err := o.QueryTable(m.TableNameWithPrefix()).Filter("history_id",history_id).Filter("document_id",doc_id).Delete() + _, err := o.QueryTable(m.TableNameWithPrefix()).Filter("history_id", history_id).Filter("document_id", doc_id).Delete() return err } //恢复指定历史的文档. -func (m *DocumentHistory) Restore(history_id,doc_id,uid int) error { +func (m *DocumentHistory) Restore(history_id, doc_id, uid int) error { o := orm.NewOrm() - err := o.QueryTable(m.TableNameWithPrefix()).Filter("history_id", history_id).Filter("document_id",doc_id).One(m) + err := o.QueryTable(m.TableNameWithPrefix()).Filter("history_id", history_id).Filter("document_id", doc_id).One(m) if err != nil { return err @@ -113,17 +114,18 @@ func (m *DocumentHistory) Restore(history_id,doc_id,uid int) error { return err } -func (m *DocumentHistory) InsertOrUpdate() (history *DocumentHistory,err error) { +func (m *DocumentHistory) InsertOrUpdate() (history *DocumentHistory, err error) { o := orm.NewOrm() history = m if m.HistoryId > 0 { - _,err = o.Update(m) - }else{ - _,err = o.Insert(m) + _, err = o.Update(m) + } else { + _, err = o.Insert(m) } return } + //分页查询指定文档的历史. func (m *DocumentHistory) FindToPager(doc_id, page_index, page_size int) (docs []*DocumentHistorySimpleResult, totalCount int, err error) { @@ -139,7 +141,7 @@ LEFT JOIN md_members AS m1 ON history.member_id = m1.member_id LEFT JOIN md_members AS m2 ON history.modify_at = m2.member_id WHERE history.document_id = ? ORDER BY history.history_id DESC LIMIT ?,?;` - _, err = o.Raw(sql,doc_id,offset,page_size).QueryRows(&docs) + _, err = o.Raw(sql, doc_id, offset, page_size).QueryRows(&docs) if err != nil { return diff --git a/models/document_tree.go b/models/document_tree.go index dc8c88ec..571eb4b4 100644 --- a/models/document_tree.go +++ b/models/document_tree.go @@ -1,48 +1,49 @@ package models import ( - "github.com/astaxie/beego/orm" "bytes" - "strconv" "github.com/astaxie/beego" + "github.com/astaxie/beego/orm" "html/template" + "math" + "strconv" ) type DocumentTree struct { - DocumentId int `json:"id"` - DocumentName string `json:"text"` - ParentId interface{} `json:"parent"` - Identify string `json:"identify"` - BookIdentify string `json:"-"` - Version int64 `json:"version"` - State *DocumentSelected `json:"state,omitempty"` + DocumentId int `json:"id"` + DocumentName string `json:"text"` + ParentId interface{} `json:"parent"` + Identify string `json:"identify"` + BookIdentify string `json:"-"` + Version int64 `json:"version"` + State *DocumentSelected `json:"state,omitempty"` } type DocumentSelected struct { - Selected bool `json:"selected"` - Opened bool `json:"opened"` + Selected bool `json:"selected"` + Opened bool `json:"opened"` } //获取项目的文档树状结构 -func (m *Document) FindDocumentTree(book_id int) ([]*DocumentTree,error){ +func (m *Document) FindDocumentTree(book_id int) ([]*DocumentTree, error) { o := orm.NewOrm() - trees := make([]*DocumentTree,0) + trees := make([]*DocumentTree, 0) var docs []*Document - count ,err := o.QueryTable(m).Filter("book_id",book_id).OrderBy("order_sort","document_id").All(&docs,"document_id","version","document_name","parent_id","identify") + count, err := o.QueryTable(m).Filter("book_id", book_id).OrderBy("order_sort", "document_id").Limit(math.MaxInt32).All(&docs, "document_id", "version", "document_name", "parent_id", "identify") if err != nil { - return trees,err + return trees, err } - book,_ := NewBook().Find(book_id) + book, _ := NewBook().Find(book_id) - trees = make([]*DocumentTree,count) + trees = make([]*DocumentTree, count) - for index,item := range docs { + for index, item := range docs { tree := &DocumentTree{} - if index == 0{ - tree.State = &DocumentSelected{ Selected: true, Opened: true } + if index == 0 { + tree.State = &DocumentSelected{Selected: true, Opened: true} } tree.DocumentId = item.DocumentId tree.Identify = item.Identify @@ -50,7 +51,7 @@ func (m *Document) FindDocumentTree(book_id int) ([]*DocumentTree,error){ tree.BookIdentify = book.Identify if item.ParentId > 0 { tree.ParentId = item.ParentId - }else{ + } else { tree.ParentId = "#" } @@ -59,41 +60,41 @@ func (m *Document) FindDocumentTree(book_id int) ([]*DocumentTree,error){ trees[index] = tree } - return trees,nil + return trees, nil } -func (m *Document) CreateDocumentTreeForHtml(book_id, selected_id int) (string,error) { - trees,err := m.FindDocumentTree(book_id) +func (m *Document) CreateDocumentTreeForHtml(book_id, selected_id int) (string, error) { + trees, err := m.FindDocumentTree(book_id) if err != nil { - return "",err + return "", err } - parent_id := getSelectedNode(trees,selected_id) + parent_id := getSelectedNode(trees, selected_id) buf := bytes.NewBufferString("") - getDocumentTree(trees,0,selected_id,parent_id,buf) + getDocumentTree(trees, 0, selected_id, parent_id, buf) + + return buf.String(), nil - return buf.String(),nil - } //使用递归的方式获取指定ID的顶级ID func getSelectedNode(array []*DocumentTree, parent_id int) int { - for _,item := range array { - if _,ok := item.ParentId.(string); ok && item.DocumentId == parent_id { + for _, item := range array { + if _, ok := item.ParentId.(string); ok && item.DocumentId == parent_id { return item.DocumentId - }else if pid,ok := item.ParentId.(int); ok && item.DocumentId == parent_id{ - return getSelectedNode(array,pid) + } else if pid, ok := item.ParentId.(int); ok && item.DocumentId == parent_id { + return getSelectedNode(array, pid) } } - return 0 + return 0 } -func getDocumentTree(array []*DocumentTree,parent_id int,selected_id int,selected_parent_id int,buf *bytes.Buffer) { +func getDocumentTree(array []*DocumentTree, parent_id int, selected_id int, selected_parent_id int, buf *bytes.Buffer) { buf.WriteString("
      ") - for _,item := range array { + for _, item := range array { pid := 0 if p, ok := item.ParentId.(int); ok { @@ -138,14 +139,3 @@ func getDocumentTree(array []*DocumentTree,parent_id int,selected_id int,selecte } buf.WriteString("
    ") } - - - - - - - - - - - diff --git a/models/errors.go b/models/errors.go index 4f20f8f1..55112592 100644 --- a/models/errors.go +++ b/models/errors.go @@ -5,16 +5,16 @@ import "errors" var ( // ErrMemberNoExist 用户不存在. - ErrMemberNoExist = errors.New("用户不存在") - ErrMemberExist = errors.New("用户已存在") - ErrMemberDisabled = errors.New("用户被禁用") - ErrMemberEmailEmpty = errors.New("用户邮箱不能为空") - ErrMemberEmailExist = errors.New("用户邮箱已被使用") - ErrMemberDescriptionTooLong = errors.New("用户描述必须小于500字") - ErrMemberEmailFormatError = errors.New("邮箱格式不正确") + ErrMemberNoExist = errors.New("用户不存在") + ErrMemberExist = errors.New("用户已存在") + ErrMemberDisabled = errors.New("用户被禁用") + ErrMemberEmailEmpty = errors.New("用户邮箱不能为空") + ErrMemberEmailExist = errors.New("用户邮箱已被使用") + ErrMemberDescriptionTooLong = errors.New("用户描述必须小于500字") + ErrMemberEmailFormatError = errors.New("邮箱格式不正确") ErrMemberPasswordFormatError = errors.New("密码必须在6-50个字符之间") - ErrMemberAccountFormatError = errors.New("账号只能由英文字母数字组成,且在3-50个字符") - ErrMemberRoleError = errors.New("用户权限不正确") + ErrMemberAccountFormatError = errors.New("账号只能由英文字母数字组成,且在3-50个字符") + ErrMemberRoleError = errors.New("用户权限不正确") // ErrorMemberPasswordError 密码错误. ErrorMemberPasswordError = errors.New("用户密码错误") //ErrorMemberAuthMethodInvalid 不支持此认证方式 diff --git a/models/label.go b/models/label.go index 7f1aa8ae..9a0b6ce5 100644 --- a/models/label.go +++ b/models/label.go @@ -1,35 +1,36 @@ package models import ( - "github.com/lifei6671/mindoc/conf" "github.com/astaxie/beego/orm" + "github.com/lifei6671/mindoc/conf" "strings" ) type Label struct { - LabelId int `orm:"column(label_id);pk;auto;unique;" json:"label_id"` - LabelName string `orm:"column(label_name);size(50);unique" json:"label_name"` - BookNumber int `orm:"column(book_number)" json:"book_number"` + LabelId int `orm:"column(label_id);pk;auto;unique;" json:"label_id"` + LabelName string `orm:"column(label_name);size(50);unique" json:"label_name"` + BookNumber int `orm:"column(book_number)" json:"book_number"` } // TableName 获取对应数据库表名. func (m *Label) TableName() string { return "label" } + // TableEngine 获取数据使用的引擎. func (m *Label) TableEngine() string { return "INNODB" } -func (m *Label)TableNameWithPrefix() string { - return conf.GetDatabasePrefix() + m.TableName() +func (m *Label) TableNameWithPrefix() string { + return conf.GetDatabasePrefix() + m.TableName() } func NewLabel() *Label { return &Label{} } -func (m *Label) FindFirst(field string, value interface{}) (*Label,error){ +func (m *Label) FindFirst(field string, value interface{}) (*Label, error) { o := orm.NewOrm() err := o.QueryTable(m.TableNameWithPrefix()).Filter(field, value).One(m) @@ -41,27 +42,27 @@ func (m *Label) FindFirst(field string, value interface{}) (*Label,error){ func (m *Label) InsertOrUpdate(labelName string) error { o := orm.NewOrm() - err := o.QueryTable(m.TableNameWithPrefix()).Filter("label_name",labelName).One(m) + err := o.QueryTable(m.TableNameWithPrefix()).Filter("label_name", labelName).One(m) if err != nil && err != orm.ErrNoRows { return err } - count,_ := o.QueryTable(NewBook().TableNameWithPrefix()).Filter("label__icontains",labelName).Count() + count, _ := o.QueryTable(NewBook().TableNameWithPrefix()).Filter("label__icontains", labelName).Count() m.BookNumber = int(count) m.LabelName = labelName if err == orm.ErrNoRows { err = nil m.LabelName = labelName - _,err = o.Insert(m) - }else{ - _,err = o.Update(m) + _, err = o.Insert(m) + } else { + _, err = o.Update(m) } return err } //批量插入或更新标签. -func (m *Label) InsertOrUpdateMulti(labels string) { - if labels != "" { +func (m *Label) InsertOrUpdateMulti(labels string) { + if labels != "" { labelArray := strings.Split(labels, ",") for _, label := range labelArray { @@ -73,10 +74,10 @@ func (m *Label) InsertOrUpdateMulti(labels string) { } //分页查找标签. -func (m *Label) FindToPager(pageIndex, pageSize int) (labels []*Label,totalCount int,err error) { +func (m *Label) FindToPager(pageIndex, pageSize int) (labels []*Label, totalCount int, err error) { o := orm.NewOrm() - count,err := o.QueryTable(m.TableNameWithPrefix()).Count() + count, err := o.QueryTable(m.TableNameWithPrefix()).Count() if err != nil { return @@ -85,8 +86,7 @@ func (m *Label) FindToPager(pageIndex, pageSize int) (labels []*Label,totalCount offset := (pageIndex - 1) * pageSize - _,err = o.QueryTable(m.TableNameWithPrefix()).OrderBy("-book_number").Offset(offset).Limit(pageSize).All(&labels) + _, err = o.QueryTable(m.TableNameWithPrefix()).OrderBy("-book_number").Offset(offset).Limit(pageSize).All(&labels) return } - diff --git a/models/logs.go b/models/logs.go index 76e94443..5dcadb41 100644 --- a/models/logs.go +++ b/models/logs.go @@ -1,38 +1,39 @@ package models import ( - "time" + "errors" + "github.com/astaxie/beego/orm" "github.com/lifei6671/mindoc/conf" "sync/atomic" - "github.com/astaxie/beego/orm" - "errors" + "time" ) -var loggerQueue = &logQueue{ channel : make(chan *Logger,100),isRuning : 0 } +var loggerQueue = &logQueue{channel: make(chan *Logger, 100), isRuning: 0} type logQueue struct { - channel chan *Logger + channel chan *Logger isRuning int32 } // Logger struct . type Logger struct { - LoggerId int64 `orm:"pk;auto;unique;column(log_id)" json:"log_id"` - MemberId int `orm:"column(member_id);type(int)" json:"member_id"` + LoggerId int64 `orm:"pk;auto;unique;column(log_id)" json:"log_id"` + MemberId int `orm:"column(member_id);type(int)" json:"member_id"` // 日志类别:operate 操作日志/ system 系统日志/ exception 异常日志 / document 文档操作日志 - Category string `orm:"column(category);size(255);default(operate)" json:"category"` - Content string `orm:"column(content);type(text)" json:"content"` - OriginalData string `orm:"column(original_data);type(text)" json:"original_data"` - PresentData string `orm:"column(present_data);type(text)" json:"present_data"` - CreateTime time.Time `orm:"type(datetime);column(create_time);auto_now_add" json:"create_time"` - UserAgent string `orm:"column(user_agent);size(500)" json:"user_agent"` - IPAddress string `orm:"column(ip_address);size(255)" json:"ip_address"` + Category string `orm:"column(category);size(255);default(operate)" json:"category"` + Content string `orm:"column(content);type(text)" json:"content"` + OriginalData string `orm:"column(original_data);type(text)" json:"original_data"` + PresentData string `orm:"column(present_data);type(text)" json:"present_data"` + CreateTime time.Time `orm:"type(datetime);column(create_time);auto_now_add" json:"create_time"` + UserAgent string `orm:"column(user_agent);size(500)" json:"user_agent"` + IPAddress string `orm:"column(ip_address);size(255)" json:"ip_address"` } // TableName 获取对应数据库表名. func (m *Logger) TableName() string { return "logs" } + // TableEngine 获取数据使用的引擎. func (m *Logger) TableEngine() string { return "INNODB" @@ -57,32 +58,19 @@ func (m *Logger) Add() error { } loggerQueue.channel <- m if atomic.LoadInt32(&(loggerQueue.isRuning)) <= 0 { - atomic.AddInt32(&(loggerQueue.isRuning),1) + atomic.AddInt32(&(loggerQueue.isRuning), 1) go addLoggerAsync() } return nil } -func addLoggerAsync() { - defer atomic.AddInt32(&(loggerQueue.isRuning),-1) +func addLoggerAsync() { + defer atomic.AddInt32(&(loggerQueue.isRuning), -1) o := orm.NewOrm() - for{ - logger := <- loggerQueue.channel + for { + logger := <-loggerQueue.channel o.Insert(logger) } } - - - - - - - - - - - - - diff --git a/models/member.go b/models/member.go index 764aed14..de8400db 100644 --- a/models/member.go +++ b/models/member.go @@ -15,6 +15,7 @@ import ( "github.com/astaxie/beego/orm" "github.com/lifei6671/mindoc/conf" "github.com/lifei6671/mindoc/utils" + "math" ) type Member struct { @@ -108,7 +109,7 @@ func (m *Member) ldapLogin(account string, password string) (*Member, error) { beego.AppConfig.String("ldap_base"), ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, //修改objectClass通过配置文件获取值 - fmt.Sprintf("(&(%s)(%s=%s))",beego.AppConfig.String("ldap_filter"), beego.AppConfig.String("ldap_attribute"), account), + fmt.Sprintf("(&(%s)(%s=%s))", beego.AppConfig.String("ldap_filter"), beego.AppConfig.String("ldap_attribute"), account), []string{"dn", "mail"}, nil, ) @@ -279,7 +280,7 @@ func (m *Member) Valid(is_hash_password bool) error { return ErrMemberEmailEmpty } //用户描述必须小于500字 - if strings.Count(m.Description,"") > 500 { + if strings.Count(m.Description, "") > 500 { return ErrMemberDescriptionTooLong } if m.Role != conf.MemberGeneralRole && m.Role != conf.MemberSuperRole && m.Role != conf.MemberAdminRole { @@ -289,48 +290,47 @@ func (m *Member) Valid(is_hash_password bool) error { m.Status = 0 } //邮箱格式校验 - if ok,err := regexp.MatchString(conf.RegexpEmail,m.Email); !ok || err != nil || m.Email == "" { + if ok, err := regexp.MatchString(conf.RegexpEmail, m.Email); !ok || err != nil || m.Email == "" { return ErrMemberEmailFormatError } //如果是未加密密码,需要校验密码格式 if !is_hash_password { - if l := strings.Count(m.Password,"") ; m.Password == "" || l > 50 || l < 6{ + if l := strings.Count(m.Password, ""); m.Password == "" || l > 50 || l < 6 { return ErrMemberPasswordFormatError } } //校验邮箱是否呗使用 - if member,err := NewMember().FindByFieldFirst("email",m.Account); err == nil && member.MemberId > 0 { + if member, err := NewMember().FindByFieldFirst("email", m.Account); err == nil && member.MemberId > 0 { if m.MemberId > 0 && m.MemberId != member.MemberId { return ErrMemberEmailExist } - if m.MemberId <= 0{ - return ErrMemberEmailExist + if m.MemberId <= 0 { + return ErrMemberEmailExist } } - if m.MemberId > 0{ + if m.MemberId > 0 { //校验用户是否存在 - if _,err := NewMember().Find(m.MemberId);err != nil { + if _, err := NewMember().Find(m.MemberId); err != nil { return err } - }else{ + } else { //校验账号格式是否正确 - if ok,err := regexp.MatchString(conf.RegexpAccount,m.Account); m.Account == "" || !ok || err != nil { + if ok, err := regexp.MatchString(conf.RegexpAccount, m.Account); m.Account == "" || !ok || err != nil { return ErrMemberAccountFormatError } //校验账号是否被使用 - if member,err := NewMember().FindByAccount(m.Account); err == nil && member.MemberId > 0 { + if member, err := NewMember().FindByAccount(m.Account); err == nil && member.MemberId > 0 { return ErrMemberExist } } - return nil } //删除一个用户. -func (m *Member) Delete(oldId int,newId int) error { +func (m *Member) Delete(oldId int, newId int) error { o := orm.NewOrm() err := o.Begin() @@ -339,39 +339,39 @@ func (m *Member) Delete(oldId int,newId int) error { return err } - _,err = o.Raw("DELETE FROM md_members WHERE member_id = ?",oldId).Exec() + _, err = o.Raw("DELETE FROM md_members WHERE member_id = ?", oldId).Exec() if err != nil { o.Rollback() return err } - _,err = o.Raw("UPDATE md_attachment SET `create_at` = ? WHERE `create_at` = ?",newId,oldId).Exec() + _, err = o.Raw("UPDATE md_attachment SET `create_at` = ? WHERE `create_at` = ?", newId, oldId).Exec() if err != nil { o.Rollback() return err } - _,err = o.Raw("UPDATE md_books SET member_id = ? WHERE member_id = ?",newId,oldId).Exec() + _, err = o.Raw("UPDATE md_books SET member_id = ? WHERE member_id = ?", newId, oldId).Exec() if err != nil { o.Rollback() return err } - _,err = o.Raw("UPDATE md_document_history SET member_id=? WHERE member_id = ?",newId,oldId).Exec() + _, err = o.Raw("UPDATE md_document_history SET member_id=? WHERE member_id = ?", newId, oldId).Exec() if err != nil { o.Rollback() return err } - _,err = o.Raw("UPDATE md_document_history SET modify_at=? WHERE modify_at = ?",newId,oldId).Exec() + _, err = o.Raw("UPDATE md_document_history SET modify_at=? WHERE modify_at = ?", newId, oldId).Exec() if err != nil { o.Rollback() return err } - _,err = o.Raw("UPDATE md_documents SET member_id = ? WHERE member_id = ?;",newId,oldId).Exec() + _, err = o.Raw("UPDATE md_documents SET member_id = ? WHERE member_id = ?;", newId, oldId).Exec() if err != nil { o.Rollback() return err } - _,err = o.Raw("UPDATE md_documents SET modify_at = ? WHERE modify_at = ?",newId,oldId).Exec() + _, err = o.Raw("UPDATE md_documents SET modify_at = ? WHERE modify_at = ?", newId, oldId).Exec() if err != nil { o.Rollback() return err @@ -386,53 +386,37 @@ func (m *Member) Delete(oldId int,newId int) error { //} var relationship_list []*Relationship - _,err = o.QueryTable(NewRelationship().TableNameWithPrefix()).Filter("member_id",oldId).All(&relationship_list) + _, err = o.QueryTable(NewRelationship().TableNameWithPrefix()).Filter("member_id", oldId).Limit(math.MaxInt32).All(&relationship_list) if err == nil { - for _,relationship := range relationship_list { + for _, relationship := range relationship_list { //如果存在创始人,则删除 if relationship.RoleId == 0 { rel := NewRelationship() - err = o.QueryTable(relationship.TableNameWithPrefix()).Filter("book_id",relationship.BookId).Filter("member_id",newId).One(rel) + err = o.QueryTable(relationship.TableNameWithPrefix()).Filter("book_id", relationship.BookId).Filter("member_id", newId).One(rel) if err == nil { - if _,err := o.Delete(relationship) ; err != nil{ + if _, err := o.Delete(relationship); err != nil { beego.Error(err) } relationship.RelationshipId = rel.RelationshipId } relationship.MemberId = newId relationship.RoleId = 0 - if _,err := o.Update(relationship) ; err != nil{ + if _, err := o.Update(relationship); err != nil { beego.Error(err) } - }else{ - if _,err := o.Delete(relationship) ; err != nil{ + } else { + if _, err := o.Delete(relationship); err != nil { beego.Error(err) } } } } - if err = o.Commit();err != nil { + if err = o.Commit(); err != nil { o.Rollback() return err } return nil } - - - - - - - - - - - - - - - - diff --git a/models/member_result.go b/models/member_result.go index 2c9bc2a0..025e162e 100644 --- a/models/member_result.go +++ b/models/member_result.go @@ -1,27 +1,27 @@ package models import ( - "time" "github.com/astaxie/beego/orm" "github.com/lifei6671/mindoc/conf" + "time" ) type MemberRelationshipResult struct { - MemberId int `json:"member_id"` - Account string `json:"account"` - Description string `json:"description"` - Email string `json:"email"` - Phone string `json:"phone"` - Avatar string `json:"avatar"` - Role int `json:"role"` //用户角色:0 管理员/ 1 普通用户 - Status int `json:"status"` //用户状态:0 正常/1 禁用 - CreateTime time.Time `json:"create_time"` - CreateAt int `json:"create_at"` - RelationshipId int `json:"relationship_id"` - BookId int `json:"book_id"` + MemberId int `json:"member_id"` + Account string `json:"account"` + Description string `json:"description"` + Email string `json:"email"` + Phone string `json:"phone"` + Avatar string `json:"avatar"` + Role int `json:"role"` //用户角色:0 管理员/ 1 普通用户 + Status int `json:"status"` //用户状态:0 正常/1 禁用 + CreateTime time.Time `json:"create_time"` + CreateAt int `json:"create_at"` + RelationshipId int `json:"relationship_id"` + BookId int `json:"book_id"` // RoleId 角色:0 创始人(创始人不能被移除) / 1 管理员/2 编辑者/3 观察者 - RoleId int `json:"role_id"` - RoleName string `json:"role_name"` + RoleId int `json:"role_id"` + RoleName string `json:"role_name"` } func NewMemberRelationshipResult() *MemberRelationshipResult { @@ -43,18 +43,18 @@ func (m *MemberRelationshipResult) FromMember(member *Member) *MemberRelationshi return m } -func (m *MemberRelationshipResult) ResolveRoleName () *MemberRelationshipResult { +func (m *MemberRelationshipResult) ResolveRoleName() *MemberRelationshipResult { if m.RoleId == conf.BookAdmin { m.RoleName = "管理者" - }else if m.RoleId == conf.BookEditor { + } else if m.RoleId == conf.BookEditor { m.RoleName = "编辑者" - }else if m.RoleId == conf.BookObserver { + } else if m.RoleId == conf.BookObserver { m.RoleName = "观察者" } return m } -func (m *MemberRelationshipResult) FindForUsersByBookId(book_id ,pageIndex, pageSize int) ([]*MemberRelationshipResult,int,error) { +func (m *MemberRelationshipResult) FindForUsersByBookId(book_id, pageIndex, pageSize int) ([]*MemberRelationshipResult, int, error) { o := orm.NewOrm() var members []*MemberRelationshipResult @@ -65,28 +65,22 @@ func (m *MemberRelationshipResult) FindForUsersByBookId(book_id ,pageIndex, page var total_count int - err := o.Raw(sql2,book_id).QueryRow(&total_count) + err := o.Raw(sql2, book_id).QueryRow(&total_count) if err != nil { - return members,0,err + return members, 0, err } - offset := (pageIndex-1) * pageSize + offset := (pageIndex - 1) * pageSize - _,err = o.Raw(sql1,book_id,offset,pageSize).QueryRows(&members) + _, err = o.Raw(sql1, book_id, offset, pageSize).QueryRows(&members) if err != nil { - return members,0,err + return members, 0, err } - for _,item := range members { + for _, item := range members { item.ResolveRoleName() } - return members,total_count,nil + return members, total_count, nil } - - - - - - diff --git a/models/member_token.go b/models/member_token.go index a2951ee5..7e612c58 100644 --- a/models/member_token.go +++ b/models/member_token.go @@ -1,66 +1,66 @@ package models import ( - "time" - "github.com/lifei6671/mindoc/conf" "github.com/astaxie/beego/orm" + "github.com/lifei6671/mindoc/conf" + "time" ) type MemberToken struct { - TokenId int `orm:"column(token_id);pk;auto;unique" json:"token_id"` - MemberId int `orm:"column(member_id);type(int)" json:"member_id"` - Token string `orm:"column(token);size(150);index" json:"token"` - Email string `orm:"column(email);size(255)" json:"email"` - IsValid bool `orm:"column(is_valid)" json:"is_valid"` - ValidTime time.Time `orm:"column(valid_time);null" json:"valid_time"` - SendTime time.Time `orm:"column(send_time);auto_now_add;type(datetime)" json:"send_time"` + TokenId int `orm:"column(token_id);pk;auto;unique" json:"token_id"` + MemberId int `orm:"column(member_id);type(int)" json:"member_id"` + Token string `orm:"column(token);size(150);index" json:"token"` + Email string `orm:"column(email);size(255)" json:"email"` + IsValid bool `orm:"column(is_valid)" json:"is_valid"` + ValidTime time.Time `orm:"column(valid_time);null" json:"valid_time"` + SendTime time.Time `orm:"column(send_time);auto_now_add;type(datetime)" json:"send_time"` } - // TableName 获取对应数据库表名. func (m *MemberToken) TableName() string { return "member_token" } + // TableEngine 获取数据使用的引擎. func (m *MemberToken) TableEngine() string { return "INNODB" } -func (m *MemberToken)TableNameWithPrefix() string { - return conf.GetDatabasePrefix() + m.TableName() +func (m *MemberToken) TableNameWithPrefix() string { + return conf.GetDatabasePrefix() + m.TableName() } func NewMemberToken() *MemberToken { return &MemberToken{} } -func (m *MemberToken) InsertOrUpdate() (*MemberToken,error){ +func (m *MemberToken) InsertOrUpdate() (*MemberToken, error) { o := orm.NewOrm() if m.TokenId > 0 { - _,err := o.Update(m) - return m,err + _, err := o.Update(m) + return m, err } - _,err := o.Insert(m) + _, err := o.Insert(m) - return m,err + return m, err } -func (m *MemberToken) FindByFieldFirst(field string,value interface{}) (*MemberToken,error) { +func (m *MemberToken) FindByFieldFirst(field string, value interface{}) (*MemberToken, error) { o := orm.NewOrm() - err := o.QueryTable(m.TableNameWithPrefix()).Filter(field,value).OrderBy("-token_id").One(m) + err := o.QueryTable(m.TableNameWithPrefix()).Filter(field, value).OrderBy("-token_id").One(m) - return m,err + return m, err } -func (m *MemberToken) FindSendCount(mail string,start_time time.Time,end_time time.Time) (int ,error) { +func (m *MemberToken) FindSendCount(mail string, start_time time.Time, end_time time.Time) (int, error) { o := orm.NewOrm() - c,err := o.QueryTable(m.TableNameWithPrefix()).Filter("send_time__gte",start_time.Format("2006-01-02 15:04:05")).Filter("send_time__lte",end_time.Format("2006-01-02 15:04:05")).Count() + c, err := o.QueryTable(m.TableNameWithPrefix()).Filter("send_time__gte", start_time.Format("2006-01-02 15:04:05")).Filter("send_time__lte", end_time.Format("2006-01-02 15:04:05")).Count() if err != nil { - return 0,err + return 0, err } - return int(c),nil -} \ No newline at end of file + return int(c), nil +} diff --git a/models/migrations.go b/models/migrations.go index 54fb3f3e..d06cf60e 100644 --- a/models/migrations.go +++ b/models/migrations.go @@ -1,18 +1,18 @@ package models import ( - "time" - "github.com/lifei6671/mindoc/conf" "github.com/astaxie/beego/orm" + "github.com/lifei6671/mindoc/conf" + "time" ) type Migration struct { - MigrationId int `orm:"column(migration_id);pk;auto;unique;" json:"migration_id"` - Name string `orm:"column(name);size(500)" json:"name"` - Statements string `orm:"column(statements);type(text);null" json:"statements"` - Status string `orm:"column(status);default(update)" json:"status"` - CreateTime time.Time `orm:"column(create_time);type(datetime);auto_now_add" json:"create_time"` - Version int64 `orm:"type(bigint);column(version);unique" json:"version"` + MigrationId int `orm:"column(migration_id);pk;auto;unique;" json:"migration_id"` + Name string `orm:"column(name);size(500)" json:"name"` + Statements string `orm:"column(statements);type(text);null" json:"statements"` + Status string `orm:"column(status);default(update)" json:"status"` + CreateTime time.Time `orm:"column(create_time);type(datetime);auto_now_add" json:"create_time"` + Version int64 `orm:"type(bigint);column(version);unique" json:"version"` } // TableName 获取对应数据库表名. @@ -33,10 +33,10 @@ func NewMigration() *Migration { return &Migration{} } -func (m *Migration) FindFirst() (*Migration,error) { +func (m *Migration) FindFirst() (*Migration, error) { o := orm.NewOrm() err := o.QueryTable(m.TableNameWithPrefix()).OrderBy("-migration_id").One(m) - return m,err -} \ No newline at end of file + return m, err +} diff --git a/models/options.go b/models/options.go index f1b2ea09..086dc9c6 100644 --- a/models/options.go +++ b/models/options.go @@ -5,147 +5,145 @@ import ( "github.com/lifei6671/mindoc/conf" ) - // Option struct . type Option struct { - OptionId int `orm:"column(option_id);pk;auto;unique;" json:"option_id"` - OptionTitle string `orm:"column(option_title);size(500)" json:"option_title"` - OptionName string `orm:"column(option_name);unique;size(80)" json:"option_name"` - OptionValue string `orm:"column(option_value);type(text);null" json:"option_value"` - Remark string `orm:"column(remark);type(text);null" json:"remark"` + OptionId int `orm:"column(option_id);pk;auto;unique;" json:"option_id"` + OptionTitle string `orm:"column(option_title);size(500)" json:"option_title"` + OptionName string `orm:"column(option_name);unique;size(80)" json:"option_name"` + OptionValue string `orm:"column(option_value);type(text);null" json:"option_value"` + Remark string `orm:"column(remark);type(text);null" json:"remark"` } // TableName 获取对应数据库表名. func (m *Option) TableName() string { return "options" } + // TableEngine 获取数据使用的引擎. func (m *Option) TableEngine() string { return "INNODB" } -func (m *Option)TableNameWithPrefix() string { - return conf.GetDatabasePrefix() + m.TableName() +func (m *Option) TableNameWithPrefix() string { + return conf.GetDatabasePrefix() + m.TableName() } - -func NewOption() *Option { +func NewOption() *Option { return &Option{} } -func (p *Option) Find(id int) (*Option,error) { +func (p *Option) Find(id int) (*Option, error) { o := orm.NewOrm() p.OptionId = id - if err := o.Read(p);err != nil { - return p,err + if err := o.Read(p); err != nil { + return p, err } - return p,nil + return p, nil } -func (p *Option) FindByKey(key string) (*Option,error) { +func (p *Option) FindByKey(key string) (*Option, error) { o := orm.NewOrm() p.OptionName = key - if err := o.Read(p);err != nil { - return p,err + if err := o.Read(p); err != nil { + return p, err } - return p,nil + return p, nil } func GetOptionValue(key, def string) string { - if option,err := NewOption().FindByKey(key); err == nil { + if option, err := NewOption().FindByKey(key); err == nil { return option.OptionValue } return def } -func (p *Option) InsertOrUpdate() error { +func (p *Option) InsertOrUpdate() error { o := orm.NewOrm() var err error - - if p.OptionId > 0 || o.QueryTable(p.TableNameWithPrefix()).Filter("option_name",p.OptionName).Exist() { - _,err = o.Update(p) - }else{ - _,err = o.Insert(p) + if p.OptionId > 0 || o.QueryTable(p.TableNameWithPrefix()).Filter("option_name", p.OptionName).Exist() { + _, err = o.Update(p) + } else { + _, err = o.Insert(p) } return err } -func (p *Option) InsertMulti(option... Option ) (error){ +func (p *Option) InsertMulti(option ...Option) error { o := orm.NewOrm() - _,err := o.InsertMulti(len(option),option) + _, err := o.InsertMulti(len(option), option) return err } -func (p *Option) All() ([]*Option,error) { +func (p *Option) All() ([]*Option, error) { o := orm.NewOrm() var options []*Option - _,err := o.QueryTable(p.TableNameWithPrefix()).All(&options) + _, err := o.QueryTable(p.TableNameWithPrefix()).All(&options) if err != nil { - return options,err + return options, err } - return options,nil + return options, nil } func (m *Option) Init() error { o := orm.NewOrm() - if !o.QueryTable(m.TableNameWithPrefix()).Filter("option_name","ENABLED_REGISTER").Exist() { + if !o.QueryTable(m.TableNameWithPrefix()).Filter("option_name", "ENABLED_REGISTER").Exist() { option := NewOption() option.OptionValue = "false" option.OptionName = "ENABLED_REGISTER" option.OptionTitle = "是否启用注册" - if _,err := o.Insert(option);err != nil { + if _, err := o.Insert(option); err != nil { return err } } - if !o.QueryTable(m.TableNameWithPrefix()).Filter("option_name","ENABLE_DOCUMENT_HISTORY").Exist() { + if !o.QueryTable(m.TableNameWithPrefix()).Filter("option_name", "ENABLE_DOCUMENT_HISTORY").Exist() { option := NewOption() option.OptionValue = "true" option.OptionName = "ENABLE_DOCUMENT_HISTORY" option.OptionTitle = "是否启用文档历史" - if _,err := o.Insert(option);err != nil { + if _, err := o.Insert(option); err != nil { return err } } - if !o.QueryTable(m.TableNameWithPrefix()).Filter("option_name","ENABLED_CAPTCHA").Exist() { + if !o.QueryTable(m.TableNameWithPrefix()).Filter("option_name", "ENABLED_CAPTCHA").Exist() { option := NewOption() option.OptionValue = "true" option.OptionName = "ENABLED_CAPTCHA" option.OptionTitle = "是否启用验证码" - if _,err := o.Insert(option);err != nil { + if _, err := o.Insert(option); err != nil { return err } } - if !o.QueryTable(m.TableNameWithPrefix()).Filter("option_name","ENABLE_ANONYMOUS").Exist() { + if !o.QueryTable(m.TableNameWithPrefix()).Filter("option_name", "ENABLE_ANONYMOUS").Exist() { option := NewOption() option.OptionValue = "false" option.OptionName = "ENABLE_ANONYMOUS" option.OptionTitle = "启用匿名访问" - if _,err := o.Insert(option);err != nil { + if _, err := o.Insert(option); err != nil { return err } } - if !o.QueryTable(m.TableNameWithPrefix()).Filter("option_name","SITE_NAME").Exist() { + if !o.QueryTable(m.TableNameWithPrefix()).Filter("option_name", "SITE_NAME").Exist() { option := NewOption() option.OptionValue = "MinDoc" option.OptionName = "SITE_NAME" option.OptionTitle = "站点名称" - if _,err := o.Insert(option);err != nil { + if _, err := o.Insert(option); err != nil { return err } } return nil -} \ No newline at end of file +} diff --git a/models/relationship.go b/models/relationship.go index 8c12c2ba..4a8318e4 100644 --- a/models/relationship.go +++ b/models/relationship.go @@ -1,21 +1,20 @@ package models import ( - "github.com/lifei6671/mindoc/conf" - "github.com/astaxie/beego/orm" "errors" "github.com/astaxie/beego/logs" + "github.com/astaxie/beego/orm" + "github.com/lifei6671/mindoc/conf" ) type Relationship struct { - RelationshipId int `orm:"pk;auto;unique;column(relationship_id)" json:"relationship_id"` - MemberId int `orm:"column(member_id);type(int)" json:"member_id"` - BookId int `orm:"column(book_id);type(int)" json:"book_id"` + RelationshipId int `orm:"pk;auto;unique;column(relationship_id)" json:"relationship_id"` + MemberId int `orm:"column(member_id);type(int)" json:"member_id"` + BookId int `orm:"column(book_id);type(int)" json:"book_id"` // RoleId 角色:0 创始人(创始人不能被移除) / 1 管理员/2 编辑者/3 观察者 - RoleId int `orm:"column(role_id);type(int)" json:"role_id"` + RoleId int `orm:"column(role_id);type(int)" json:"role_id"` } - // TableName 获取对应数据库表名. func (m *Relationship) TableName() string { return "relationship" @@ -40,97 +39,97 @@ func NewRelationship() *Relationship { return &Relationship{} } -func (m *Relationship) Find(id int) (*Relationship,error) { +func (m *Relationship) Find(id int) (*Relationship, error) { o := orm.NewOrm() - err := o.QueryTable(m.TableNameWithPrefix()).Filter("relationship_id",id).One(m) - return m,err + err := o.QueryTable(m.TableNameWithPrefix()).Filter("relationship_id", id).One(m) + return m, err } //查询指定项目的创始人. -func (m *Relationship) FindFounder(book_id int) (*Relationship,error) { +func (m *Relationship) FindFounder(book_id int) (*Relationship, error) { o := orm.NewOrm() - err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id",book_id).Filter("role_id",0).One(m) + err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id", book_id).Filter("role_id", 0).One(m) - return m,err + return m, err } -func (m *Relationship) UpdateRoleId(book_id,member_id, role_id int) (*Relationship,error) { +func (m *Relationship) UpdateRoleId(book_id, member_id, role_id int) (*Relationship, error) { o := orm.NewOrm() book := NewBook() book.BookId = book_id if err := o.Read(book); err != nil { logs.Error("UpdateRoleId => ", err) - return m,errors.New("项目不存在") + return m, errors.New("项目不存在") } - err := o.QueryTable(m.TableNameWithPrefix()).Filter("member_id",member_id).Filter("book_id",book_id).One(m) + err := o.QueryTable(m.TableNameWithPrefix()).Filter("member_id", member_id).Filter("book_id", book_id).One(m) if err == orm.ErrNoRows { m = NewRelationship() m.BookId = book_id m.MemberId = member_id m.RoleId = role_id - }else if err != nil { - return m,err - }else if m.RoleId == conf.BookFounder{ - return m,errors.New("不能变更创始人的权限") + } else if err != nil { + return m, err + } else if m.RoleId == conf.BookFounder { + return m, errors.New("不能变更创始人的权限") } m.RoleId = role_id if m.RelationshipId > 0 { - _,err = o.Update(m) - }else{ - _,err = o.Insert(m) + _, err = o.Update(m) + } else { + _, err = o.Insert(m) } - return m,err + return m, err } -func (m *Relationship) FindForRoleId(book_id ,member_id int) (int,error) { +func (m *Relationship) FindForRoleId(book_id, member_id int) (int, error) { o := orm.NewOrm() relationship := NewRelationship() - err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id",book_id).Filter("member_id",member_id).One(relationship) + err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id", book_id).Filter("member_id", member_id).One(relationship) if err != nil { - return 0,err + return 0, err } - return relationship.RoleId,nil + return relationship.RoleId, nil } -func (m *Relationship) FindByBookIdAndMemberId(book_id ,member_id int) (*Relationship,error) { +func (m *Relationship) FindByBookIdAndMemberId(book_id, member_id int) (*Relationship, error) { o := orm.NewOrm() - err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id",book_id).Filter("member_id",member_id).One(m) + err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id", book_id).Filter("member_id", member_id).One(m) - return m,err + return m, err } -func (m *Relationship) Insert() error { +func (m *Relationship) Insert() error { o := orm.NewOrm() - _,err := o.Insert(m) + _, err := o.Insert(m) return err } -func (m *Relationship) Update() error { +func (m *Relationship) Update() error { o := orm.NewOrm() - _,err := o.Update(m) + _, err := o.Update(m) return err } -func (m *Relationship) DeleteByBookIdAndMemberId(book_id,member_id int) error { +func (m *Relationship) DeleteByBookIdAndMemberId(book_id, member_id int) error { o := orm.NewOrm() - err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id",book_id).Filter("member_id",member_id).One(m) + err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id", book_id).Filter("member_id", member_id).One(m) if err == orm.ErrNoRows { return errors.New("用户未参与该项目") @@ -138,22 +137,22 @@ func (m *Relationship) DeleteByBookIdAndMemberId(book_id,member_id int) error { if m.RoleId == conf.BookFounder { return errors.New("不能删除创始人") } - _,err = o.Delete(m) + _, err = o.Delete(m) if err != nil { - logs.Error("删除项目参与者 => ",err) + logs.Error("删除项目参与者 => ", err) return errors.New("删除失败") } return nil } -func (m *Relationship) Transfer(book_id,founder_id,receive_id int) error { +func (m *Relationship) Transfer(book_id, founder_id, receive_id int) error { o := orm.NewOrm() founder := NewRelationship() - err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id",book_id).Filter("member_id",founder_id).One(founder) + err := o.QueryTable(m.TableNameWithPrefix()).Filter("book_id", book_id).Filter("member_id", founder_id).One(founder) if err != nil { return err @@ -163,7 +162,7 @@ func (m *Relationship) Transfer(book_id,founder_id,receive_id int) error { } receive := NewRelationship() - err = o.QueryTable(m.TableNameWithPrefix()).Filter("book_id",book_id).Filter("member_id",receive_id).One(receive) + err = o.QueryTable(m.TableNameWithPrefix()).Filter("book_id", book_id).Filter("member_id", receive_id).One(receive) if err != orm.ErrNoRows && err != nil { return err @@ -176,17 +175,17 @@ func (m *Relationship) Transfer(book_id,founder_id,receive_id int) error { receive.RoleId = conf.BookFounder receive.BookId = book_id - if err := founder.Update();err != nil { + if err := founder.Update(); err != nil { o.Rollback() return err } if receive.RelationshipId > 0 { - if _,err := o.Update(receive);err != nil { + if _, err := o.Update(receive); err != nil { o.Rollback() return err } - }else{ - if _,err := o.Insert(receive);err != nil { + } else { + if _, err := o.Insert(receive); err != nil { o.Rollback() return err } @@ -194,24 +193,3 @@ func (m *Relationship) Transfer(book_id,founder_id,receive_id int) error { return o.Commit() } - - - - - - - - - - - - - - - - - - - - - diff --git a/routers/filter.go b/routers/filter.go index b9811682..d3a7607a 100644 --- a/routers/filter.go +++ b/routers/filter.go @@ -1,43 +1,45 @@ package routers import ( + "encoding/json" "github.com/astaxie/beego" "github.com/astaxie/beego/context" "github.com/lifei6671/mindoc/conf" "github.com/lifei6671/mindoc/models" - "encoding/json" + "net/url" ) -func init() { +func init() { var FilterUser = func(ctx *context.Context) { _, ok := ctx.Input.Session(conf.LoginSessionName).(models.Member) if !ok { if ctx.Input.IsAjax() { - jsonData := make(map[string]interface{},3) + jsonData := make(map[string]interface{}, 3) jsonData["errcode"] = 403 jsonData["message"] = "请登录后再操作" + returnJSON, _ := json.Marshal(jsonData) ctx.ResponseWriter.Write(returnJSON) - }else{ - ctx.Redirect(302, beego.URLFor("AccountController.Login")) + } else { + ctx.Redirect(302, beego.URLFor("AccountController.Login") + "?url=" + url.PathEscape(ctx.Request.URL.RequestURI())) } } } - beego.InsertFilter("/manager",beego.BeforeRouter,FilterUser) - beego.InsertFilter("/manager/*",beego.BeforeRouter,FilterUser) - beego.InsertFilter("/setting",beego.BeforeRouter,FilterUser) - beego.InsertFilter("/setting/*",beego.BeforeRouter,FilterUser) - beego.InsertFilter("/book",beego.BeforeRouter,FilterUser) - beego.InsertFilter("/book/*",beego.BeforeRouter,FilterUser) - beego.InsertFilter("/api/*",beego.BeforeRouter,FilterUser) + beego.InsertFilter("/manager", beego.BeforeRouter, FilterUser) + beego.InsertFilter("/manager/*", beego.BeforeRouter, FilterUser) + beego.InsertFilter("/setting", beego.BeforeRouter, FilterUser) + beego.InsertFilter("/setting/*", beego.BeforeRouter, FilterUser) + beego.InsertFilter("/book", beego.BeforeRouter, FilterUser) + beego.InsertFilter("/book/*", beego.BeforeRouter, FilterUser) + beego.InsertFilter("/api/*", beego.BeforeRouter, FilterUser) var FinishRouter = func(ctx *context.Context) { - ctx.ResponseWriter.Header().Add("MinDoc-Version",conf.VERSION) - ctx.ResponseWriter.Header().Add("MinDoc-Site","http://www.iminho.me") + ctx.ResponseWriter.Header().Add("MinDoc-Version", conf.VERSION) + ctx.ResponseWriter.Header().Add("MinDoc-Site", "https://www.iminho.me") } - beego.InsertFilter("/*",beego.BeforeRouter ,FinishRouter, false) + beego.InsertFilter("/*", beego.BeforeRouter, FinishRouter, false) } diff --git a/static/js/markdown.js b/static/js/markdown.js index fb2d86d3..b05d9603 100644 --- a/static/js/markdown.js +++ b/static/js/markdown.js @@ -141,7 +141,6 @@ $(function () { $.get(window.editURL + $node.node.id ).done(function (res) { layer.close(index); - resetEditor(); if (res.errcode === 0) { window.isLoad = true; try { @@ -153,7 +152,6 @@ $(function () { } var node = { "id": res.data.doc_id, 'parent': res.data.parent_id === 0 ? '#' : res.data.parent_id, "text": res.data.doc_name, "identify": res.data.identify, "version": res.data.version }; pushDocumentCategory(node); - console.log(node); window.selectNode = node; pushVueLists(res.data.attach); } else { diff --git a/utils/cryptil/cryptil.go b/utils/cryptil/cryptil.go new file mode 100644 index 00000000..8e6fe84b --- /dev/null +++ b/utils/cryptil/cryptil.go @@ -0,0 +1,70 @@ +package cryptil + +import ( + "crypto/hmac" + "crypto/md5" + "crypto/sha1" + "encoding/base64" + "fmt" + "strconv" + "strings" + "time" +) + +//对称加密与解密之加密【从Beego中提取出来的】 +//@param value 需要加密的字符串 +//@param secret 加密密钥 +//@return encrypt 返回的加密后的字符串 +func Encrypt(value, secret string) (encrypt string) { + vs := base64.URLEncoding.EncodeToString([]byte(value)) + timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) + h := hmac.New(sha1.New, []byte(secret)) + fmt.Fprintf(h, "%s%s", vs, timestamp) + sig := fmt.Sprintf("%02x", h.Sum(nil)) + return strings.Join([]string{vs, timestamp, sig}, ".") +} + +//对称加密与解密之解密【从Beego中提取出来的】 +//@param value 需要解密的字符串 +//@param secret 密钥 +//@return decrypt 返回解密后的字符串 +func Decrypt(value, secret string) (decrypt string) { + parts := strings.SplitN(value, ".", 3) + if len(parts) != 3 { + return "" + } + vs := parts[0] + timestamp := parts[1] + sig := parts[2] + h := hmac.New(sha1.New, []byte(secret)) + fmt.Fprintf(h, "%s%s", vs, timestamp) + if fmt.Sprintf("%02x", h.Sum(nil)) != sig { + return "" + } + res, _ := base64.URLEncoding.DecodeString(vs) + return string(res) +} + +//MD5加密 +//@param str 需要加密的字符串 +//@param salt 盐值 +//@return CryptStr 加密后返回的字符串 +func Md5Crypt(str string, salt ...interface{}) (CryptStr string) { + if l := len(salt); l > 0 { + slice := make([]string, l+1) + str = fmt.Sprintf(str+strings.Join(slice, "%v"), salt...) + } + return fmt.Sprintf("%x", md5.Sum([]byte(str))) +} + +//SHA1加密 +//@param str 需要加密的字符串 +//@param salt 盐值 +//@return CryptStr 加密后返回的字符串 +func Sha1Crypt(str string, salt ...interface{}) (CryptStr string) { + if l := len(salt); l > 0 { + slice := make([]string, l+1) + str = fmt.Sprintf(str+strings.Join(slice, "%v"), salt...) + } + return fmt.Sprintf("%x", sha1.Sum([]byte(str))) +} diff --git a/utils/file.go b/utils/file.go index 0847cfc0..fd9455c8 100644 --- a/utils/file.go +++ b/utils/file.go @@ -1,15 +1,15 @@ package utils import ( - "strings" - "os" "fmt" - "path/filepath" "io" "math" + "os" + "path/filepath" + "strings" ) -func AbsolutePath(p string) (string,error) { +func AbsolutePath(p string) (string, error) { if strings.HasPrefix(p, "~") { home := os.Getenv("HOME") @@ -21,9 +21,9 @@ func AbsolutePath(p string) (string,error) { s, err := filepath.Abs(p) if nil != err { - return "",err + return "", err } - return s,nil + return s, nil } // FileExists reports whether the named file or directory exists. @@ -58,18 +58,13 @@ func FormatBytes(size int64) string { i := 0 - for ; s >= 1024 && i < 4 ; i ++ { + for ; s >= 1024 && i < 4; i++ { s /= 1024 } - - return fmt.Sprintf("%.2f%s",s,units[i]) + return fmt.Sprintf("%.2f%s", s, units[i]) } - - - - func Round(val float64, places int) float64 { var t float64 f := math.Pow10(places) @@ -97,12 +92,3 @@ func Round(val float64, places int) float64 { return t } - - - - - - - - - diff --git a/utils/filetil/filetil.go b/utils/filetil/filetil.go new file mode 100644 index 00000000..5a42f0f2 --- /dev/null +++ b/utils/filetil/filetil.go @@ -0,0 +1,43 @@ +package filetil + +import ( + "os" + "path/filepath" + "strings" +) + +//================================== +//更多文件和目录的操作,使用filepath包和os包 +//================================== + +//返回的目录扫描结果 +type FileList struct { + IsDir bool //是否是目录 + Path string //文件路径 + Ext string //文件扩展名 + Name string //文件名 + Size int64 //文件大小 + ModTime int64 //文件修改时间戳 +} + +//目录扫描 +//@param dir 需要扫描的目录 +//@return fl 文件列表 +//@return err 错误 +func ScanFiles(dir string) (fl []FileList, err error) { + err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err == nil { + path = strings.Replace(path, "\\", "/", -1) //文件路径处理 + fl = append(fl, FileList{ + IsDir: info.IsDir(), + Path: path, + Ext: strings.ToLower(filepath.Ext(path)), + Name: info.Name(), + Size: info.Size(), + ModTime: info.ModTime().Unix(), + }) + } + return err + }) + return +} diff --git a/utils/gob.go b/utils/gob.go index aa778ab3..7eca4eba 100644 --- a/utils/gob.go +++ b/utils/gob.go @@ -6,25 +6,25 @@ import ( ) //解码 -func Decode(value string,r interface{}) (error) { +func Decode(value string, r interface{}) error { - network := bytes.NewBuffer([]byte(value)); + network := bytes.NewBuffer([]byte(value)) dec := gob.NewDecoder(network) - return dec.Decode(r); + return dec.Decode(r) } //编码 -func Encode(value interface{}) (string,error) { - network:= bytes.NewBuffer(nil); +func Encode(value interface{}) (string, error) { + network := bytes.NewBuffer(nil) enc := gob.NewEncoder(network) - err := enc.Encode(value); + err := enc.Encode(value) if err != nil { - return "",err; + return "", err } - return network.String(),nil; -} \ No newline at end of file + return network.String(), nil +} diff --git a/utils/krand.go b/utils/krand.go index c786b0b9..4168b7a6 100644 --- a/utils/krand.go +++ b/utils/krand.go @@ -1,16 +1,15 @@ package utils import ( - "time" "math/rand" + "time" ) - const ( - KC_RAND_KIND_NUM = 0 // 纯数字 - KC_RAND_KIND_LOWER = 1 // 小写字母 - KC_RAND_KIND_UPPER = 2 // 大写字母 - KC_RAND_KIND_ALL = 3 // 数字、大小写字母 + KC_RAND_KIND_NUM = 0 // 纯数字 + KC_RAND_KIND_LOWER = 1 // 小写字母 + KC_RAND_KIND_UPPER = 2 // 大写字母 + KC_RAND_KIND_ALL = 3 // 数字、大小写字母 ) // 随机字符串 @@ -18,12 +17,12 @@ func Krand(size int, kind int) []byte { ikind, kinds, result := kind, [][]int{[]int{10, 48}, []int{26, 97}, []int{26, 65}}, make([]byte, size) is_all := kind > 2 || kind < 0 rand.Seed(time.Now().UnixNano()) - for i :=0; i < size; i++ { + for i := 0; i < size; i++ { if is_all { // random ikind ikind = rand.Intn(3) } scope, base := kinds[ikind][0], kinds[ikind][1] - result[i] = uint8(base+rand.Intn(scope)) + result[i] = uint8(base + rand.Intn(scope)) } return result diff --git a/utils/ldap.go b/utils/ldap.go index 273d0f4d..b5af6605 100644 --- a/utils/ldap.go +++ b/utils/ldap.go @@ -1,11 +1,12 @@ package utils import ( - "gopkg.in/ldap.v2" - "fmt" "errors" + "fmt" "github.com/astaxie/beego" + "gopkg.in/ldap.v2" ) + /* 对应的config ldap: @@ -23,20 +24,20 @@ func ValidLDAPLogin(password string) (result bool, err error) { err = nil lc, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "192.168.3.104", 389)) if err != nil { - beego.Error("Dial => ",err) + beego.Error("Dial => ", err) return } defer lc.Close() err = lc.Bind("cn=admin,dc=minho,dc=com", "123456") if err != nil { - beego.Error("Bind => ",err) + beego.Error("Bind => ", err) return } searchRequest := ldap.NewSearchRequest( "DC=minho,DC=com", ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(&(objectClass=User)(%s=%s))","mail", "longfei6671@163.com"), + fmt.Sprintf("(&(objectClass=User)(%s=%s))", "mail", "longfei6671@163.com"), []string{"dn"}, nil, ) @@ -49,7 +50,7 @@ func ValidLDAPLogin(password string) (result bool, err error) { err = errors.New("ldap.no_user_found_or_many_users_found") return } - fmt.Printf("%+v = %d",searchResult.Entries,len(searchResult.Entries)) + fmt.Printf("%+v = %d", searchResult.Entries, len(searchResult.Entries)) userdn := searchResult.Entries[0].DN @@ -57,7 +58,7 @@ func ValidLDAPLogin(password string) (result bool, err error) { if err == nil { result = true } else { - beego.Error("Bind2 => ",err) + beego.Error("Bind2 => ", err) err = nil } return @@ -66,12 +67,12 @@ func ValidLDAPLogin(password string) (result bool, err error) { func AddMember(account, password string) error { lc, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "192.168.3.104", 389)) if err != nil { - beego.Error("Dial => ",err) + beego.Error("Dial => ", err) return err } defer lc.Close() - user := fmt.Sprintf("cn=%s,dc=minho,dc=com",account) + user := fmt.Sprintf("cn=%s,dc=minho,dc=com", account) member := ldap.NewAddRequest(user) @@ -81,35 +82,35 @@ func AddMember(account, password string) error { if err == nil { - err = lc.Bind(user,"") + err = lc.Bind(user, "") if err != nil { - beego.Error("Bind => ",err) + beego.Error("Bind => ", err) return err } passwordModifyRequest := ldap.NewPasswordModifyRequest(user, "", "1q2w3e__ABC") _, err = lc.PasswordModify(passwordModifyRequest) if err != nil { - beego.Error("PasswordModify => ",err) + beego.Error("PasswordModify => ", err) return err } return nil } - beego.Error("Add => ",err) + beego.Error("Add => ", err) return err } func ModifyPassword(account, old_password, new_password string) error { l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "192.168.3.104", 389)) if err != nil { - beego.Error("Dial => ",err) + beego.Error("Dial => ", err) } defer l.Close() - user := fmt.Sprintf("cn=%s,dc=minho,dc=com",account) + user := fmt.Sprintf("cn=%s,dc=minho,dc=com", account) err = l.Bind(user, old_password) if err != nil { - beego.Error("Bind => ",err) + beego.Error("Bind => ", err) return err } @@ -122,15 +123,3 @@ func ModifyPassword(account, old_password, new_password string) error { } return nil } - - - - - - - - - - - - diff --git a/utils/pager.go b/utils/pager.go index c71571b3..2f8adf7a 100644 --- a/utils/pager.go +++ b/utils/pager.go @@ -6,8 +6,8 @@ import ( con "strconv" "strings" - "github.com/astaxie/beego/orm" "fmt" + "github.com/astaxie/beego/orm" "math" ) @@ -25,7 +25,7 @@ type PageOptions struct { NextPageText string //下一页文字 默认"下一页" EnableFirstLastLink bool //是否启用首尾连接 默认false 建议开启 EnablePreNexLink bool //是否启用上一页,下一页连接 默认false 建议开启 - TotalPages int + TotalPages int } /** @@ -42,7 +42,7 @@ func GetPagesInfo(tableName string, currentpage int, pagesize int, conditions st } var rs orm.RawSeter o := orm.NewOrm() - var totalItem, totalpages int = 0, 0 //总条数,总页数 + var totalItem, totalpages int = 0, 0 //总条数,总页数 o.Raw("SELECT count(*) FROM " + tableName + " where 1 > 0 " + conditions).QueryRow(&totalItem) //获取总条数 if totalItem <= pagesize { totalpages = 1 @@ -58,22 +58,22 @@ func GetPagesInfo(tableName string, currentpage int, pagesize int, conditions st } /** - * 返回总记录条数,总页数,当前页面数据,分页html - * 根据分页选项,生成分页连接 下面是一个实例: - func (this *MainController) Test() { - var po util.PageOptions - po.EnablePreNexLink = true - po.EnableFirstLastLink = true - po.LinkItemCount = 7 - po.TableName = "help_topic" - cp, _ := this.GetInt("pno") - po.CurrentPage = int(cp) - _,_,_ pager := util.GetPagerLinks(&po, this.Ctx) - this.Data["Email"] = html.HTML(pager) - this.TplName = "test.html" - } +* 返回总记录条数,总页数,当前页面数据,分页html +* 根据分页选项,生成分页连接 下面是一个实例: + func (this *MainController) Test() { + var po util.PageOptions + po.EnablePreNexLink = true + po.EnableFirstLastLink = true + po.LinkItemCount = 7 + po.TableName = "help_topic" + cp, _ := this.GetInt("pno") + po.CurrentPage = int(cp) + _,_,_ pager := util.GetPagerLinks(&po, this.Ctx) + this.Data["Email"] = html.HTML(pager) + this.TplName = "test.html" + } */ -func GetPagerLinks(po *PageOptions,requestURI string) (int, int, orm.RawSeter, html.HTML) { +func GetPagerLinks(po *PageOptions, requestURI string) (int, int, orm.RawSeter, html.HTML) { str := "" totalItem, totalpages, rs := GetPagesInfo(po.TableName, po.CurrentPage, po.PageSize, po.Conditions) po = setDefault(po, totalpages) @@ -84,7 +84,7 @@ func GetPagerLinks(po *PageOptions,requestURI string) (int, int, orm.RawSeter, h if po.CurrentPage < po.LinkItemCount { str = fun2(po, totalpages) //123456789...200 } else { - if po.CurrentPage + po.LinkItemCount < totalpages { + if po.CurrentPage+po.LinkItemCount < totalpages { str = fun3(po, totalpages) } else { str = fun4(po, totalpages) @@ -94,18 +94,19 @@ func GetPagerLinks(po *PageOptions,requestURI string) (int, int, orm.RawSeter, h return totalItem, totalpages, rs, html.HTML(str) } -func GetPagerHtml(requestURI string,pageIndex, pageSize,totalCount int) (html.HTML){ +func GetPagerHtml(requestURI string, pageIndex, pageSize, totalCount int) html.HTML { po := &PageOptions{ - CurrentPage: pageIndex, - PageSize: pageSize, - EnableFirstLastLink : true, - ParamName : "page", - TotalPages:int(math.Ceil(float64(totalCount) / float64(pageSize))), + CurrentPage: pageIndex, + PageSize: pageSize, + EnableFirstLastLink: true, + ParamName: "page", + TotalPages: int(math.Ceil(float64(totalCount) / float64(pageSize))), + LinkItemCount: pageSize, } totalPages := int(math.Ceil(float64(totalCount) / float64(pageSize))) - setDefault(po,totalPages) - DealUri(po,requestURI) + setDefault(po, totalPages) + DealUri(po, requestURI) str := "" if totalPages <= po.LinkItemCount { str = fun1(po, totalPages) //显示完全 12345678910 @@ -113,16 +114,16 @@ func GetPagerHtml(requestURI string,pageIndex, pageSize,totalCount int) (html.HT if po.CurrentPage < po.LinkItemCount { str = fun2(po, totalPages) //123456789...200 } else { - if po.CurrentPage + po.LinkItemCount < totalPages { + if po.CurrentPage+po.LinkItemCount < totalPages { str = fun3(po, totalPages) } else { str = fun4(po, totalPages) } } } - str = strings.Replace(str,"?&","?",-1) + str = strings.Replace(str, "?&", "?", -1) //str = strings.Replace(str,"&&","&",-1) - return html.HTML(str) + return html.HTML(str) } /** @@ -136,19 +137,19 @@ func DealUri(po *PageOptions, requestURI string) { arr2 := strings.Split(arr[1], "&") for _, v := range arr2 { if !strings.Contains(v, po.ParamName) { - if strings.HasSuffix(rs,"&") { - rs += v - }else{ - rs += v + "&" + if strings.HasSuffix(rs, "&") { + rs += v + } else { + rs += v + "&" } //rs += "&" + v } } - if strings.HasPrefix(rs,"&") { + if strings.HasPrefix(rs, "&") { rs = string(rs[1:]) } - if strings.HasSuffix(rs,"&"){ - rs = string(rs[0:strings.Count(rs,"")-1]) + if strings.HasSuffix(rs, "&") { + rs = string(rs[0 : strings.Count(rs, "")-1]) } rs = arr[0] + "?" + rs fmt.Println(rs) @@ -167,8 +168,11 @@ func fun4(po *PageOptions, totalPages int) string { rs := "" rs += getHeader(po, totalPages) rs += "
  • " + con.Itoa(1) + "
  • " - rs += "
  • ...
  • " - for i := totalPages - po.LinkItemCount; i <= totalPages; i++ { + + rs += "
  • ...
  • " + + + for i := totalPages - po.LinkItemCount-1; i <= totalPages; i++ { if po.CurrentPage != i { rs += "
  • " + con.Itoa(i) + "
  • " } else { @@ -187,15 +191,15 @@ func fun3(po *PageOptions, totalpages int) string { var rs string = "" rs += getHeader(po, totalpages) rs += "
  • " + con.Itoa(1) + "
  • " - rs += "..." + rs += "
  • ...
  • " for i := po.CurrentPage - po.LinkItemCount/2 + 1; i <= po.CurrentPage+po.LinkItemCount/2-1; i++ { if po.CurrentPage != i { - rs += "" + con.Itoa(i) + "" + rs += "
  • " + con.Itoa(i) + "
  • " } else { - rs += "
  • " + con.Itoa(i) + " (current)
  • " + rs += "
  • " + con.Itoa(i) + " (current)
  • " } } - rs += "..." + rs += "
  • ...
  • " rs += "
  • " + con.Itoa(totalpages) + "
  • " rs += getFooter(po, totalpages) return rs @@ -207,18 +211,18 @@ func fun3(po *PageOptions, totalpages int) string { * 123456789...200 */ func fun2(po *PageOptions, totalpages int) string { - var rs string = "" + rs := "" rs += getHeader(po, totalpages) - for i := 1; i <= po.LinkItemCount+1; i++ { - if i == po.LinkItemCount { - rs += "
  • ...
  • " + for i := 1; i <= po.LinkItemCount+2; i++ { + if i == po.LinkItemCount+2 { + rs += "
  • ...
  • " } else if i == po.LinkItemCount+1 { rs += "
  • " + con.Itoa(totalpages) + "
  • " } else { if po.CurrentPage != i { rs += "
  • " + con.Itoa(i) + "
  • " } else { - rs += "
  • " + con.Itoa(i) + " (current)
  • " + rs += "
  • " + con.Itoa(i) + " (current)
  • " } } } @@ -239,7 +243,7 @@ func fun1(po *PageOptions, totalpages int) string { rs += "
  • " + con.Itoa(i) + "
  • " } else { - rs += "
  • " + con.Itoa(i) + " (current)
  • " + rs += "
  • " + con.Itoa(i) + " (current)
  • " } } rs += getFooter(po, totalpages) @@ -255,7 +259,7 @@ func getHeader(po *PageOptions, totalpages int) string { if po.EnableFirstLastLink { //当首页,尾页都设定的时候,就显示 if po.CurrentPage == 1 { rs += "" + po.FirstPageText + "" - }else{ + } else { rs += "" + po.FirstPageText + "" } } @@ -281,7 +285,7 @@ func getFooter(po *PageOptions, totalpages int) string { if po.EnableFirstLastLink { //当首页,尾页都设定的时候,就显示 if po.CurrentPage == totalpages { rs += "
  • " + po.LastPageText + "
  • " - }else{ + } else { rs += "
  • " + po.LastPageText + "
  • " } } @@ -339,4 +343,4 @@ func judgeDisable(po *PageOptions, totalpages int, h_f int) string { } } return rs -} \ No newline at end of file +} diff --git a/utils/password.go b/utils/password.go index 3abd8172..a3d30d31 100644 --- a/utils/password.go +++ b/utils/password.go @@ -1,15 +1,14 @@ package utils - import ( - "crypto/rand" - mt "math/rand" "crypto/md5" + "crypto/rand" "crypto/sha256" "crypto/sha512" "encoding/base64" "encoding/hex" "io" + mt "math/rand" "strconv" "strings" ) @@ -20,6 +19,7 @@ const ( stretching_password = 500 salt_local_secret = "ahfw*&TGdsfnbi*^Wt" ) + //加密密码 func PasswordHash(pass string) (string, error) { @@ -45,8 +45,9 @@ func PasswordHash(pass string) (string, error) { return password, nil } + //校验密码是否有效 -func PasswordVerify(hashing string, pass string) (bool, error) { +func PasswordVerify(hashing string, pass string) (bool, error) { data := trim_salt_hash(hashing) interation, _ := strconv.ParseInt(data["interation_string"], 10, 64) @@ -56,7 +57,7 @@ func PasswordVerify(hashing string, pass string) (bool, error) { return false, err } - if (data["salt_secret"]+delmiter+data["interation_string"]+delmiter+has+delmiter+data["salt"]) == hashing { + if (data["salt_secret"] + delmiter + data["interation_string"] + delmiter + has + delmiter + data["salt"]) == hashing { return true, nil } else { return false, nil @@ -110,7 +111,7 @@ func trim_salt_hash(hash string) map[string]string { } func salt(secret string) (string, error) { - buf := make([]byte, saltSize, saltSize + md5.Size) + buf := make([]byte, saltSize, saltSize+md5.Size) _, err := io.ReadFull(rand.Reader, buf) if err != nil { return "", err @@ -134,4 +135,4 @@ func salt_secret() (string, error) { func randInt(min int, max int) int { return min + mt.Intn(max-min) -} \ No newline at end of file +} diff --git a/utils/template_fun.go b/utils/template_fun.go index 5b9b062a..62fe8785 100644 --- a/utils/template_fun.go +++ b/utils/template_fun.go @@ -1,5 +1,5 @@ package utils -func Asset(p string,cdn string) string { - return cdn + p; +func Asset(p string, cdn string) string { + return cdn + p } diff --git a/utils/url.go b/utils/url.go index 80dc7de8..45bda88f 100644 --- a/utils/url.go +++ b/utils/url.go @@ -8,17 +8,17 @@ func JoinURI(elem ...string) string { } uri := "" - for i,u := range elem { - u = strings.Replace(u,"\\","/",-1) + for i, u := range elem { + u = strings.Replace(u, "\\", "/", -1) if i == 0 { - if !strings.HasSuffix(u,"/") { + if !strings.HasSuffix(u, "/") { u = u + "/" } uri = u - }else{ - u = strings.Replace(u,"//","/",-1) - if strings.HasPrefix(u,"/") { + } else { + u = strings.Replace(u, "//", "/", -1) + if strings.HasPrefix(u, "/") { u = string(u[1:]) } uri += u diff --git a/utils/ziptil/ziptil.go b/utils/ziptil/ziptil.go new file mode 100644 index 00000000..3711c8dd --- /dev/null +++ b/utils/ziptil/ziptil.go @@ -0,0 +1,101 @@ +package ziptil + +import ( + "archive/zip" + "errors" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "github.com/lifei6671/mindoc/utils/filetil" +) + +//解压zip文件 +//@param zipFile 需要解压的zip文件 +//@param dest 需要解压到的目录 +//@return err 返回错误 +func Unzip(zipFile, dest string) (err error) { + dest = strings.TrimSuffix(dest, "/") + "/" + // 打开一个zip格式文件 + r, err := zip.OpenReader(zipFile) + if err != nil { + return err + } + defer r.Close() + // 迭代压缩文件中的文件,打印出文件中的内容 + for _, f := range r.File { + if !f.FileInfo().IsDir() { //非目录,且不包含__MACOSX + if folder := dest + filepath.Dir(f.Name); !strings.Contains(folder, "__MACOSX") { + os.MkdirAll(folder, 0777) + if fcreate, err := os.Create(dest + strings.TrimPrefix(f.Name, "./")); err == nil { + if rc, err := f.Open(); err == nil { + io.Copy(fcreate, rc) + rc.Close() //不要用defer来关闭,如果文件太多的话,会报too many open files 的错误 + fcreate.Close() + } else { + fcreate.Close() + return err + } + } else { + return err + } + } + } + } + return nil +} + +//压缩指定文件或文件夹 +//@param dest 压缩后的zip文件目标,如/usr/local/hello.zip +//@param filepath 需要压缩的文件或者文件夹 +//@return err 错误。如果返回错误,则会删除dest文件 +func Zip(dest string, filepath ...string) (err error) { + if len(filepath) == 0 { + return errors.New("lack of file") + } + //创建文件 + fzip, err := os.Create(dest) + if err != nil { + return err + } + defer fzip.Close() + + var filelist []filetil.FileList + for _, file := range filepath { + if info, err := os.Stat(file); err == nil { + if info.IsDir() { //目录,则扫描文件 + if f, _ := filetil.ScanFiles(file); len(f) > 0 { + filelist = append(filelist, f...) + } + } else { //文件 + filelist = append(filelist, filetil.FileList{ + IsDir: false, + Name: info.Name(), + Path: file, + }) + } + } else { + return err + } + } + w := zip.NewWriter(fzip) + defer w.Close() + for _, file := range filelist { + if !file.IsDir { + if fw, err := w.Create(strings.TrimLeft(file.Path, "./")); err != nil { + return err + } else { + if filecontent, err := ioutil.ReadFile(file.Path); err != nil { + return err + } else { + if _, err = fw.Write(filecontent); err != nil { + return err + } + } + } + } + } + return +} diff --git a/views/account/login.tpl b/views/account/login.tpl index 17dd4e3b..57bc101e 100644 --- a/views/account/login.tpl +++ b/views/account/login.tpl @@ -131,7 +131,7 @@ return false; } else { $.ajax({ - url: "{{urlfor "AccountController.Login"}}", + url: "{{urlfor "AccountController.Login" "url" .url}}", data: $("form").serializeArray(), dataType: "json", type: "POST", @@ -142,7 +142,7 @@ layer.msg(res.message); $btn.button('reset'); } else { - turl = res.data.turl; + turl = res.data; if (turl === "") { turl = "/"; } diff --git a/views/document/default_read.tpl b/views/document/default_read.tpl index 1ee601c3..4ae8fb5a 100644 --- a/views/document/default_read.tpl +++ b/views/document/default_read.tpl @@ -65,6 +65,7 @@
  • PDF
  • EPUB
  • MOBI
  • +
  • Word