longyu vor 3 Jahren
Ursprung
Commit
8b77ca1b88
15 geänderte Dateien mit 1344 neuen und 365 gelöschten Zeilen
  1. 1 0
      .gitignore
  2. 7 0
      controllers/home.go
  3. 0 92
      controllers/object.go
  4. 0 119
      controllers/user.go
  5. 6 6
      main.go
  6. 37 0
      models/db.go
  7. 0 53
      models/object.go
  8. 0 86
      models/user.go
  9. 4 9
      routers/router.go
  10. 1072 0
      utils/common.go
  11. 66 0
      utils/config.go
  12. 31 0
      utils/constants.go
  13. 62 0
      utils/email.go
  14. 45 0
      utils/jwt.go
  15. 13 0
      utils/logs.go

+ 1 - 0
.gitignore

@@ -1 +1,2 @@
 /conf
+/.idea

+ 7 - 0
controllers/home.go

@@ -0,0 +1,7 @@
+package controllers
+
+import beego "github.com/beego/beego/v2/server/web"
+
+type HomeController struct {
+	beego.Controller
+}

+ 0 - 92
controllers/object.go

@@ -1,92 +0,0 @@
-package controllers
-
-import (
-	"hongze_edb_lib/models"
-	"encoding/json"
-
-	beego "github.com/beego/beego/v2/server/web"
-)
-
-// Operations about object
-type ObjectController struct {
-	beego.Controller
-}
-
-// @Title Create
-// @Description create object
-// @Param	body		body 	models.Object	true		"The object content"
-// @Success 200 {string} models.Object.Id
-// @Failure 403 body is empty
-// @router / [post]
-func (o *ObjectController) Post() {
-	var ob models.Object
-	json.Unmarshal(o.Ctx.Input.RequestBody, &ob)
-	objectid := models.AddOne(ob)
-	o.Data["json"] = map[string]string{"ObjectId": objectid}
-	o.ServeJSON()
-}
-
-// @Title Get
-// @Description find object by objectid
-// @Param	objectId		path 	string	true		"the objectid you want to get"
-// @Success 200 {object} models.Object
-// @Failure 403 :objectId is empty
-// @router /:objectId [get]
-func (o *ObjectController) Get() {
-	objectId := o.Ctx.Input.Param(":objectId")
-	if objectId != "" {
-		ob, err := models.GetOne(objectId)
-		if err != nil {
-			o.Data["json"] = err.Error()
-		} else {
-			o.Data["json"] = ob
-		}
-	}
-	o.ServeJSON()
-}
-
-// @Title GetAll
-// @Description get all objects
-// @Success 200 {object} models.Object
-// @Failure 403 :objectId is empty
-// @router / [get]
-func (o *ObjectController) GetAll() {
-	obs := models.GetAll()
-	o.Data["json"] = obs
-	o.ServeJSON()
-}
-
-// @Title Update
-// @Description update the object
-// @Param	objectId		path 	string	true		"The objectid you want to update"
-// @Param	body		body 	models.Object	true		"The body"
-// @Success 200 {object} models.Object
-// @Failure 403 :objectId is empty
-// @router /:objectId [put]
-func (o *ObjectController) Put() {
-	objectId := o.Ctx.Input.Param(":objectId")
-	var ob models.Object
-	json.Unmarshal(o.Ctx.Input.RequestBody, &ob)
-
-	err := models.Update(objectId, ob.Score)
-	if err != nil {
-		o.Data["json"] = err.Error()
-	} else {
-		o.Data["json"] = "update success!"
-	}
-	o.ServeJSON()
-}
-
-// @Title Delete
-// @Description delete the object
-// @Param	objectId		path 	string	true		"The objectId you want to delete"
-// @Success 200 {string} delete success!
-// @Failure 403 objectId is empty
-// @router /:objectId [delete]
-func (o *ObjectController) Delete() {
-	objectId := o.Ctx.Input.Param(":objectId")
-	models.Delete(objectId)
-	o.Data["json"] = "delete success!"
-	o.ServeJSON()
-}
-

+ 0 - 119
controllers/user.go

@@ -1,119 +0,0 @@
-package controllers
-
-import (
-	"hongze_edb_lib/models"
-	"encoding/json"
-
-	beego "github.com/beego/beego/v2/server/web"
-)
-
-// Operations about Users
-type UserController struct {
-	beego.Controller
-}
-
-// @Title CreateUser
-// @Description create users
-// @Param	body		body 	models.User	true		"body for user content"
-// @Success 200 {int} models.User.Id
-// @Failure 403 body is empty
-// @router / [post]
-func (u *UserController) Post() {
-	var user models.User
-	json.Unmarshal(u.Ctx.Input.RequestBody, &user)
-	uid := models.AddUser(user)
-	u.Data["json"] = map[string]string{"uid": uid}
-	u.ServeJSON()
-}
-
-// @Title GetAll
-// @Description get all Users
-// @Success 200 {object} models.User
-// @router / [get]
-func (u *UserController) GetAll() {
-	users := models.GetAllUsers()
-	u.Data["json"] = users
-	u.ServeJSON()
-}
-
-// @Title Get
-// @Description get user by uid
-// @Param	uid		path 	string	true		"The key for staticblock"
-// @Success 200 {object} models.User
-// @Failure 403 :uid is empty
-// @router /:uid [get]
-func (u *UserController) Get() {
-	uid := u.GetString(":uid")
-	if uid != "" {
-		user, err := models.GetUser(uid)
-		if err != nil {
-			u.Data["json"] = err.Error()
-		} else {
-			u.Data["json"] = user
-		}
-	}
-	u.ServeJSON()
-}
-
-// @Title Update
-// @Description update the user
-// @Param	uid		path 	string	true		"The uid you want to update"
-// @Param	body		body 	models.User	true		"body for user content"
-// @Success 200 {object} models.User
-// @Failure 403 :uid is not int
-// @router /:uid [put]
-func (u *UserController) Put() {
-	uid := u.GetString(":uid")
-	if uid != "" {
-		var user models.User
-		json.Unmarshal(u.Ctx.Input.RequestBody, &user)
-		uu, err := models.UpdateUser(uid, &user)
-		if err != nil {
-			u.Data["json"] = err.Error()
-		} else {
-			u.Data["json"] = uu
-		}
-	}
-	u.ServeJSON()
-}
-
-// @Title Delete
-// @Description delete the user
-// @Param	uid		path 	string	true		"The uid you want to delete"
-// @Success 200 {string} delete success!
-// @Failure 403 uid is empty
-// @router /:uid [delete]
-func (u *UserController) Delete() {
-	uid := u.GetString(":uid")
-	models.DeleteUser(uid)
-	u.Data["json"] = "delete success!"
-	u.ServeJSON()
-}
-
-// @Title Login
-// @Description Logs user into the system
-// @Param	username		query 	string	true		"The username for login"
-// @Param	password		query 	string	true		"The password for login"
-// @Success 200 {string} login success
-// @Failure 403 user not exist
-// @router /login [get]
-func (u *UserController) Login() {
-	username := u.GetString("username")
-	password := u.GetString("password")
-	if models.Login(username, password) {
-		u.Data["json"] = "login success"
-	} else {
-		u.Data["json"] = "user not exist"
-	}
-	u.ServeJSON()
-}
-
-// @Title logout
-// @Description Logs out current logged in user session
-// @Success 200 {string} logout success
-// @router /logout [get]
-func (u *UserController) Logout() {
-	u.Data["json"] = "logout success"
-	u.ServeJSON()
-}
-

+ 6 - 6
main.go

@@ -1,15 +1,15 @@
 package main
 
 import (
-	_ "hongze_edb_lib/routers"
+	_ "hongze/hongze_edb_lib/routers"
 
-	beego "github.com/beego/beego/v2/server/web"
+	"github.com/beego/beego/v2/server/web"
 )
 
 func main() {
-	if beego.BConfig.RunMode == "dev" {
-		beego.BConfig.WebConfig.DirectoryIndex = true
-		beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
+	if web.BConfig.RunMode == "dev" {
+		web.BConfig.WebConfig.DirectoryIndex = true
+		web.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
 	}
-	beego.Run()
+	web.Run()
 }

+ 37 - 0
models/db.go

@@ -0,0 +1,37 @@
+package models
+
+import (
+	_ "github.com/go-sql-driver/mysql"
+	"hongze/hongze_edb_lib/utils"
+	"time"
+	"github.com/beego/beego/v2/client/orm"
+)
+
+func init() {
+
+	_ = orm.RegisterDataBase("default", "mysql", utils.MYSQL_URL)
+	orm.SetMaxIdleConns("default", 50)
+	orm.SetMaxOpenConns("default", 100)
+
+	db, _ := orm.GetDB("default")
+	db.SetConnMaxLifetime(10 * time.Minute)
+
+	_ = orm.RegisterDataBase("edb", "mysql", utils.MYSQL_URL_EDB)
+	orm.SetMaxIdleConns("edb", 50)
+	orm.SetMaxOpenConns("edb", 100)
+
+	edb_db, _ := orm.GetDB("edb")
+	edb_db.SetConnMaxLifetime(10 * time.Minute)
+
+	_ = orm.RegisterDataBase("gl", "mysql", utils.MYSQL_URL_GL)
+	orm.SetMaxIdleConns("gl", 50)
+	orm.SetMaxOpenConns("gl", 100)
+
+	gl, _ := orm.GetDB("gl")
+	gl.SetConnMaxLifetime(10 * time.Minute)
+	
+	//注册对象
+	orm.RegisterModel(
+
+	)
+}

+ 0 - 53
models/object.go

@@ -1,53 +0,0 @@
-package models
-
-import (
-	"errors"
-	"strconv"
-	"time"
-)
-
-var (
-	Objects map[string]*Object
-)
-
-type Object struct {
-	ObjectId   string
-	Score      int64
-	PlayerName string
-}
-
-func init() {
-	Objects = make(map[string]*Object)
-	Objects["hjkhsbnmn123"] = &Object{"hjkhsbnmn123", 100, "astaxie"}
-	Objects["mjjkxsxsaa23"] = &Object{"mjjkxsxsaa23", 101, "someone"}
-}
-
-func AddOne(object Object) (ObjectId string) {
-	object.ObjectId = "astaxie" + strconv.FormatInt(time.Now().UnixNano(), 10)
-	Objects[object.ObjectId] = &object
-	return object.ObjectId
-}
-
-func GetOne(ObjectId string) (object *Object, err error) {
-	if v, ok := Objects[ObjectId]; ok {
-		return v, nil
-	}
-	return nil, errors.New("ObjectId Not Exist")
-}
-
-func GetAll() map[string]*Object {
-	return Objects
-}
-
-func Update(ObjectId string, Score int64) (err error) {
-	if v, ok := Objects[ObjectId]; ok {
-		v.Score = Score
-		return nil
-	}
-	return errors.New("ObjectId Not Exist")
-}
-
-func Delete(ObjectId string) {
-	delete(Objects, ObjectId)
-}
-

+ 0 - 86
models/user.go

@@ -1,86 +0,0 @@
-package models
-
-import (
-	"errors"
-	"strconv"
-	"time"
-)
-
-var (
-	UserList map[string]*User
-)
-
-func init() {
-	UserList = make(map[string]*User)
-	u := User{"user_11111", "astaxie", "11111", Profile{"male", 20, "Singapore", "astaxie@gmail.com"}}
-	UserList["user_11111"] = &u
-}
-
-type User struct {
-	Id       string
-	Username string
-	Password string
-	Profile  Profile
-}
-
-type Profile struct {
-	Gender  string
-	Age     int
-	Address string
-	Email   string
-}
-
-func AddUser(u User) string {
-	u.Id = "user_" + strconv.FormatInt(time.Now().UnixNano(), 10)
-	UserList[u.Id] = &u
-	return u.Id
-}
-
-func GetUser(uid string) (u *User, err error) {
-	if u, ok := UserList[uid]; ok {
-		return u, nil
-	}
-	return nil, errors.New("User not exists")
-}
-
-func GetAllUsers() map[string]*User {
-	return UserList
-}
-
-func UpdateUser(uid string, uu *User) (a *User, err error) {
-	if u, ok := UserList[uid]; ok {
-		if uu.Username != "" {
-			u.Username = uu.Username
-		}
-		if uu.Password != "" {
-			u.Password = uu.Password
-		}
-		if uu.Profile.Age != 0 {
-			u.Profile.Age = uu.Profile.Age
-		}
-		if uu.Profile.Address != "" {
-			u.Profile.Address = uu.Profile.Address
-		}
-		if uu.Profile.Gender != "" {
-			u.Profile.Gender = uu.Profile.Gender
-		}
-		if uu.Profile.Email != "" {
-			u.Profile.Email = uu.Profile.Email
-		}
-		return u, nil
-	}
-	return nil, errors.New("User Not Exist")
-}
-
-func Login(username, password string) bool {
-	for _, u := range UserList {
-		if u.Username == username && u.Password == password {
-			return true
-		}
-	}
-	return false
-}
-
-func DeleteUser(uid string) {
-	delete(UserList, uid)
-}

+ 4 - 9
routers/router.go

@@ -8,23 +8,18 @@
 package routers
 
 import (
-	"hongze_edb_lib/controllers"
+	"hongze/hongze_edb_lib/controllers"
 
 	beego "github.com/beego/beego/v2/server/web"
 )
 
 func init() {
-	ns := beego.NewNamespace("/v1",
+	ns := beego.NewNamespace("/edbapi",
 		beego.NSNamespace("/object",
 			beego.NSInclude(
-				&controllers.ObjectController{},
-			),
-		),
-		beego.NSNamespace("/user",
-			beego.NSInclude(
-				&controllers.UserController{},
+				&controllers.HomeController{},
 			),
 		),
 	)
 	beego.AddNamespace(ns)
-}
+}

+ 1072 - 0
utils/common.go

@@ -0,0 +1,1072 @@
+package utils
+
+import (
+	"bufio"
+	"crypto/md5"
+	"crypto/sha1"
+	"encoding/base64"
+	"encoding/hex"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/shopspring/decimal"
+	"image"
+	"image/png"
+	"io"
+	"math"
+	"math/rand"
+	"net"
+	"net/http"
+	"os"
+	"os/exec"
+	"path"
+	"regexp"
+	"strconv"
+	"strings"
+	"time"
+)
+
+//随机数种子
+var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
+
+func GetRandString(size int) string {
+	allLetterDigit := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "!", "@", "#", "$", "%", "^", "&", "*"}
+	randomSb := ""
+	digitSize := len(allLetterDigit)
+	for i := 0; i < size; i++ {
+		randomSb += allLetterDigit[rnd.Intn(digitSize)]
+	}
+	return randomSb
+}
+
+func GetRandStringNoSpecialChar(size int) string {
+	allLetterDigit := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}
+	randomSb := ""
+	digitSize := len(allLetterDigit)
+	for i := 0; i < size; i++ {
+		randomSb += allLetterDigit[rnd.Intn(digitSize)]
+	}
+	return randomSb
+}
+
+func StringsToJSON(str string) string {
+	rs := []rune(str)
+	jsons := ""
+	for _, r := range rs {
+		rint := int(r)
+		if rint < 128 {
+			jsons += string(r)
+		} else {
+			jsons += "\\u" + strconv.FormatInt(int64(rint), 16) // json
+		}
+	}
+	return jsons
+}
+
+//序列化
+func ToString(v interface{}) string {
+	data, _ := json.Marshal(v)
+	return string(data)
+}
+
+//md5加密
+func MD5(data string) string {
+	m := md5.Sum([]byte(data))
+	return hex.EncodeToString(m[:])
+}
+
+// 获取数字随机字符
+func GetRandDigit(n int) string {
+	return fmt.Sprintf("%0"+strconv.Itoa(n)+"d", rnd.Intn(int(math.Pow10(n))))
+}
+
+// 获取随机数
+func GetRandNumber(n int) int {
+	return rnd.Intn(n)
+}
+
+func GetRandInt(min, max int) int {
+	if min >= max || min == 0 || max == 0 {
+		return max
+	}
+	return rand.Intn(max-min) + min
+}
+
+func GetToday(format string) string {
+	today := time.Now().Format(format)
+	return today
+}
+
+//获取今天剩余秒数
+func GetTodayLastSecond() time.Duration {
+	today := GetToday(FormatDate) + " 23:59:59"
+	end, _ := time.ParseInLocation(FormatDateTime, today, time.Local)
+	return time.Duration(end.Unix()-time.Now().Local().Unix()) * time.Second
+}
+
+// 处理出生日期函数
+func GetBrithDate(idcard string) string {
+	l := len(idcard)
+	var s string
+	if l == 15 {
+		s = "19" + idcard[6:8] + "-" + idcard[8:10] + "-" + idcard[10:12]
+		return s
+	}
+	if l == 18 {
+		s = idcard[6:10] + "-" + idcard[10:12] + "-" + idcard[12:14]
+		return s
+	}
+	return GetToday(FormatDate)
+}
+
+//处理性别
+func WhichSexByIdcard(idcard string) string {
+	var sexs = [2]string{"女", "男"}
+	length := len(idcard)
+	if length == 18 {
+		sex, _ := strconv.Atoi(string(idcard[16]))
+		return sexs[sex%2]
+	} else if length == 15 {
+		sex, _ := strconv.Atoi(string(idcard[14]))
+		return sexs[sex%2]
+	}
+	return "男"
+}
+
+//截取小数点后几位
+func SubFloatToString(f float64, m int) string {
+	n := strconv.FormatFloat(f, 'f', -1, 64)
+	if n == "" {
+		return ""
+	}
+	if m >= len(n) {
+		return n
+	}
+	newn := strings.Split(n, ".")
+	if m == 0 {
+		return newn[0]
+	}
+	if len(newn) < 2 || m >= len(newn[1]) {
+		return n
+	}
+	return newn[0] + "." + newn[1][:m]
+}
+
+//截取小数点后几位
+func SubFloatToFloat(f float64, m int) float64 {
+	newn := SubFloatToString(f, m)
+	newf, _ := strconv.ParseFloat(newn, 64)
+	return newf
+}
+
+//截取小数点后几位
+func SubFloatToFloatStr(f float64, m int) string {
+	newn := SubFloatToString(f, m)
+	return newn
+}
+
+//获取相差时间-年
+func GetYearDiffer(start_time, end_time string) int {
+	t1, _ := time.ParseInLocation("2006-01-02", start_time, time.Local)
+	t2, _ := time.ParseInLocation("2006-01-02", end_time, time.Local)
+	age := t2.Year() - t1.Year()
+	if t2.Month() < t1.Month() || (t2.Month() == t1.Month() && t2.Day() < t1.Day()) {
+		age--
+	}
+	return age
+}
+
+//获取相差时间-秒
+func GetSecondDifferByTime(start_time, end_time time.Time) int64 {
+	diff := end_time.Unix() - start_time.Unix()
+	return diff
+}
+
+func FixFloat(f float64, m int) float64 {
+	newn := SubFloatToString(f+0.00000001, m)
+	newf, _ := strconv.ParseFloat(newn, 64)
+	return newf
+}
+
+// 将字符串数组转化为逗号分割的字符串形式  ["str1","str2","str3"] >>> "str1,str2,str3"
+func StrListToString(strList []string) (str string) {
+	if len(strList) > 0 {
+		for k, v := range strList {
+			if k == 0 {
+				str = v
+			} else {
+				str = str + "," + v
+			}
+		}
+		return
+	}
+	return ""
+}
+
+//Token
+func GetToken() string {
+	randStr := GetRandString(64)
+	token := MD5(randStr + Md5Key)
+	tokenLen := 64 - len(token)
+	return strings.ToUpper(token + GetRandString(tokenLen))
+}
+
+//数据没有记录
+func ErrNoRow() string {
+	return "<QuerySeter> no row found"
+}
+
+//校验邮箱格式
+func ValidateEmailFormatat(email string) bool {
+	reg := regexp.MustCompile(RegularEmail)
+	return reg.MatchString(email)
+}
+
+//验证是否是手机号
+func ValidateMobileFormatat(mobileNum string) bool {
+	reg := regexp.MustCompile(RegularMobile)
+	return reg.MatchString(mobileNum)
+}
+
+//判断文件是否存在
+func FileIsExist(filePath string) bool {
+	_, err := os.Stat(filePath)
+	return err == nil || os.IsExist(err)
+}
+
+//获取图片扩展名
+func GetImgExt(file string) (ext string, err error) {
+	var headerByte []byte
+	headerByte = make([]byte, 8)
+	fd, err := os.Open(file)
+	if err != nil {
+		return "", err
+	}
+	defer fd.Close()
+	_, err = fd.Read(headerByte)
+	if err != nil {
+		return "", err
+	}
+	xStr := fmt.Sprintf("%x", headerByte)
+	switch {
+	case xStr == "89504e470d0a1a0a":
+		ext = ".png"
+	case xStr == "0000010001002020":
+		ext = ".ico"
+	case xStr == "0000020001002020":
+		ext = ".cur"
+	case xStr[:12] == "474946383961" || xStr[:12] == "474946383761":
+		ext = ".gif"
+	case xStr[:10] == "0000020000" || xStr[:10] == "0000100000":
+		ext = ".tga"
+	case xStr[:8] == "464f524d":
+		ext = ".iff"
+	case xStr[:8] == "52494646":
+		ext = ".ani"
+	case xStr[:4] == "4d4d" || xStr[:4] == "4949":
+		ext = ".tiff"
+	case xStr[:4] == "424d":
+		ext = ".bmp"
+	case xStr[:4] == "ffd8":
+		ext = ".jpg"
+	case xStr[:2] == "0a":
+		ext = ".pcx"
+	default:
+		ext = ""
+	}
+	return ext, nil
+}
+
+//保存图片
+func SaveImage(path string, img image.Image) (err error) {
+	//需要保持的文件
+	imgfile, err := os.Create(path)
+	defer imgfile.Close()
+	// 以PNG格式保存文件
+	err = png.Encode(imgfile, img)
+	return err
+}
+
+//下载图片
+func DownloadImage(imgUrl string) (filePath string, err error) {
+	imgPath := "./static/imgs/"
+	fileName := path.Base(imgUrl)
+	res, err := http.Get(imgUrl)
+	if err != nil {
+		fmt.Println("A error occurred!")
+		return
+	}
+	defer res.Body.Close()
+	// 获得get请求响应的reader对象
+	reader := bufio.NewReaderSize(res.Body, 32*1024)
+
+	filePath = imgPath + fileName
+	file, err := os.Create(filePath)
+	if err != nil {
+		return
+	}
+	// 获得文件的writer对象
+	writer := bufio.NewWriter(file)
+
+	written, _ := io.Copy(writer, reader)
+	fmt.Printf("Total length: %d \n", written)
+	return
+}
+
+//保存base64数据为文件
+func SaveBase64ToFile(content, path string) error {
+	data, err := base64.StdEncoding.DecodeString(content)
+	if err != nil {
+		return err
+	}
+	f, err := os.Create(path)
+	defer f.Close()
+	if err != nil {
+		return err
+	}
+	f.Write(data)
+	return nil
+}
+
+func SaveBase64ToFileBySeek(content, path string) (err error) {
+	data, err := base64.StdEncoding.DecodeString(content)
+	exist, err := PathExists(path)
+	if err != nil {
+		return
+	}
+	if !exist {
+		f, err := os.Create(path)
+		if err != nil {
+			return err
+		}
+		n, _ := f.Seek(0, 2)
+		// 从末尾的偏移量开始写入内容
+		_, err = f.WriteAt([]byte(data), n)
+		defer f.Close()
+	} else {
+		f, err := os.OpenFile(path, os.O_WRONLY, 0644)
+		if err != nil {
+			return err
+		}
+		n, _ := f.Seek(0, 2)
+		// 从末尾的偏移量开始写入内容
+		_, err = f.WriteAt([]byte(data), n)
+		defer f.Close()
+	}
+
+	return nil
+}
+
+func PathExists(path string) (bool, error) {
+	_, err := os.Stat(path)
+	if err == nil {
+		return true, nil
+	}
+	if os.IsNotExist(err) {
+		return false, nil
+	}
+	return false, err
+}
+
+func StartIndex(page, pagesize int) int {
+	if page > 1 {
+		return (page - 1) * pagesize
+	}
+	return 0
+}
+func PageCount(count, pagesize int) int {
+	if count%pagesize > 0 {
+		return count/pagesize + 1
+	} else {
+		return count / pagesize
+	}
+}
+
+func TrimHtml(src string) string {
+	//将HTML标签全转换成小写
+	re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
+	src = re.ReplaceAllStringFunc(src, strings.ToLower)
+
+	re, _ = regexp.Compile("\\<img[\\S\\s]+?\\>")
+	src = re.ReplaceAllString(src, "[图片]")
+
+	re, _ = regexp.Compile("class[\\S\\s]+?>")
+	src = re.ReplaceAllString(src, "")
+	re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
+	src = re.ReplaceAllString(src, "")
+	return strings.TrimSpace(src)
+}
+
+//1556164246  ->  2019-04-25 03:50:46 +0000
+//timestamp
+
+func TimeToTimestamp() {
+	fmt.Println(time.Unix(1556164246, 0).Format("2006-01-02 15:04:05"))
+}
+
+func ToUnicode(text string) string {
+	textQuoted := strconv.QuoteToASCII(text)
+	textUnquoted := textQuoted[1 : len(textQuoted)-1]
+	return textUnquoted
+}
+
+func VersionToInt(version string) int {
+	version = strings.Replace(version, ".", "", -1)
+	n, _ := strconv.Atoi(version)
+	return n
+}
+func IsCheckInList(list []int, s int) bool {
+	for _, v := range list {
+		if v == s {
+			return true
+		}
+	}
+	return false
+
+}
+
+func round(num float64) int {
+	return int(num + math.Copysign(0.5, num))
+}
+
+func toFixed(num float64, precision int) float64 {
+	output := math.Pow(10, float64(precision))
+	return float64(round(num*output)) / output
+}
+
+// GetWilsonScore returns Wilson Score
+func GetWilsonScore(p, n float64) float64 {
+	if p == 0 && n == 0 {
+		return 0
+	}
+
+	return toFixed(((p+1.9208)/(p+n)-1.96*math.Sqrt(p*n/(p+n)+0.9604)/(p+n))/(1+3.8416/(p+n)), 2)
+}
+
+//将中文数字转化成数字,比如 第三百四十五章,返回第345章 不支持一亿及以上
+func ChangeWordsToNum(str string) (numStr string) {
+	words := ([]rune)(str)
+	num := 0
+	n := 0
+	for i := 0; i < len(words); i++ {
+		word := string(words[i : i+1])
+		switch word {
+		case "万":
+			if n == 0 {
+				n = 1
+			}
+			n = n * 10000
+			num = num*10000 + n
+			n = 0
+		case "千":
+			if n == 0 {
+				n = 1
+			}
+			n = n * 1000
+			num += n
+			n = 0
+		case "百":
+			if n == 0 {
+				n = 1
+			}
+			n = n * 100
+			num += n
+			n = 0
+		case "十":
+			if n == 0 {
+				n = 1
+			}
+			n = n * 10
+			num += n
+			n = 0
+		case "一":
+			n += 1
+		case "二":
+			n += 2
+		case "三":
+			n += 3
+		case "四":
+			n += 4
+		case "五":
+			n += 5
+		case "六":
+			n += 6
+		case "七":
+			n += 7
+		case "八":
+			n += 8
+		case "九":
+			n += 9
+		case "零":
+		default:
+			if n > 0 {
+				num += n
+				n = 0
+			}
+			if num == 0 {
+				numStr += word
+			} else {
+				numStr += strconv.Itoa(num) + word
+				num = 0
+			}
+		}
+	}
+	if n > 0 {
+		num += n
+		n = 0
+	}
+	if num != 0 {
+		numStr += strconv.Itoa(num)
+	}
+	return
+}
+
+func Sha1(data string) string {
+	sha1 := sha1.New()
+	sha1.Write([]byte(data))
+	return hex.EncodeToString(sha1.Sum([]byte("")))
+}
+
+func GetVideoPlaySeconds(videoPath string) (playSeconds float64, err error) {
+	cmd := `ffmpeg -i ` + videoPath + `  2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//`
+	out, err := exec.Command("bash", "-c", cmd).Output()
+	if err != nil {
+		return
+	}
+	outTimes := string(out)
+	fmt.Println("outTimes:", outTimes)
+	if outTimes != "" {
+		timeArr := strings.Split(outTimes, ":")
+		h := timeArr[0]
+		m := timeArr[1]
+		s := timeArr[2]
+		hInt, err := strconv.Atoi(h)
+		if err != nil {
+			return playSeconds, err
+		}
+
+		mInt, err := strconv.Atoi(m)
+		if err != nil {
+			return playSeconds, err
+		}
+		s = strings.Trim(s, " ")
+		s = strings.Trim(s, "\n")
+		sInt, err := strconv.ParseFloat(s, 64)
+		if err != nil {
+			return playSeconds, err
+		}
+		playSeconds = float64(hInt)*3600 + float64(mInt)*60 + float64(sInt)
+	}
+	return
+}
+
+func GetMaxTradeCode(tradeCode string) (maxTradeCode string, err error) {
+	tradeCode = strings.Replace(tradeCode, "W", "", -1)
+	tradeCode = strings.Trim(tradeCode, " ")
+	tradeCodeInt, err := strconv.Atoi(tradeCode)
+	if err != nil {
+		return
+	}
+	tradeCodeInt = tradeCodeInt + 1
+	maxTradeCode = fmt.Sprintf("W%06d", tradeCodeInt)
+	return
+}
+
+// excel日期字段格式化 yyyy-mm-dd
+func ConvertToFormatDay(excelDaysString string) string {
+	// 2006-01-02 距离 1900-01-01的天数
+	baseDiffDay := 38719 //在网上工具计算的天数需要加2天,什么原因没弄清楚
+	curDiffDay := excelDaysString
+	b, _ := strconv.Atoi(curDiffDay)
+	// 获取excel的日期距离2006-01-02的天数
+	realDiffDay := b - baseDiffDay
+	//fmt.Println("realDiffDay:",realDiffDay)
+	// 距离2006-01-02 秒数
+	realDiffSecond := realDiffDay * 24 * 3600
+	//fmt.Println("realDiffSecond:",realDiffSecond)
+	// 2006-01-02 15:04:05距离1970-01-01 08:00:00的秒数 网上工具可查出
+	baseOriginSecond := 1136185445
+	resultTime := time.Unix(int64(baseOriginSecond+realDiffSecond), 0).Format("2006-01-02")
+	return resultTime
+}
+
+func CheckPwd(pwd string) bool {
+	compile := `([0-9a-z]+){6,12}|(a-z0-9]+){6,12}`
+	reg := regexp.MustCompile(compile)
+	flag := reg.MatchString(pwd)
+	return flag
+}
+
+func GetMonthStartAndEnd(myYear string, myMonth string) (startDate, endDate string) {
+	// 数字月份必须前置补零
+	if len(myMonth) == 1 {
+		myMonth = "0" + myMonth
+	}
+	yInt, _ := strconv.Atoi(myYear)
+
+	timeLayout := "2006-01-02 15:04:05"
+	loc, _ := time.LoadLocation("Local")
+	theTime, _ := time.ParseInLocation(timeLayout, myYear+"-"+myMonth+"-01 00:00:00", loc)
+	newMonth := theTime.Month()
+
+	t1 := time.Date(yInt, newMonth, 1, 0, 0, 0, 0, time.Local).Format("2006-01-02")
+	t2 := time.Date(yInt, newMonth+1, 0, 0, 0, 0, 0, time.Local).Format("2006-01-02")
+	return t1, t2
+}
+
+//移除字符串中的空格
+func TrimStr(str string) (str2 string) {
+	if str == "" {
+		return str
+	}
+	return strings.Replace(str, " ", "", -1)
+}
+
+//字符串转换为time
+func StrTimeToTime(strTime string) time.Time {
+	timeLayout := "2006-01-02 15:04:05"  //转化所需模板
+	loc, _ := time.LoadLocation("Local") //重要:获取时区
+	resultTime, _ := time.ParseInLocation(timeLayout, strTime, loc)
+	return resultTime
+}
+
+//字符串类型时间转周几
+func StrDateTimeToWeek(strTime string) string {
+	var WeekDayMap = map[string]string{
+		"Monday":    "周一",
+		"Tuesday":   "周二",
+		"Wednesday": "周三",
+		"Thursday":  "周四",
+		"Friday":    "周五",
+		"Saturday":  "周六",
+		"Sunday":    "周日",
+	}
+	var ctime = StrTimeToTime(strTime).Format("2006-01-02")
+	startday, _ := time.Parse("2006-01-02", ctime)
+	staweek_int := startday.Weekday().String()
+	return WeekDayMap[staweek_int]
+}
+
+//时间格式转年月日字符串
+func TimeToStrYmd(time2 time.Time) string {
+	var Ymd string
+	year := time2.Year()
+	month := time2.Format("1")
+	day1 := time.Now().Day()
+	Ymd = strconv.Itoa(year) + "年" + month + "月" + strconv.Itoa(day1) + "日"
+	return Ymd
+}
+
+//时间格式去掉时分秒
+func TimeRemoveHms(strTime string) string {
+	var Ymd string
+	var resultTime = StrTimeToTime(strTime)
+	year := resultTime.Year()
+	month := resultTime.Format("01")
+	day1 := resultTime.Day()
+	Ymd = strconv.Itoa(year) + "." + month + "." + strconv.Itoa(day1)
+	return Ymd
+}
+
+//时间格式去掉时分秒
+func TimeRemoveHms2(strTime string) string {
+	var Ymd string
+	var resultTime = StrTimeToTime(strTime)
+	year := resultTime.Year()
+	month := resultTime.Format("01")
+	day1 := resultTime.Day()
+	Ymd = strconv.Itoa(year) + "-" + month + "-" + strconv.Itoa(day1)
+	return Ymd
+}
+
+//文章上一次编辑时间
+func ArticleLastTime(strTime string) string {
+	var newTime string
+	stamp, _ := time.ParseInLocation("2006-01-02 15:04:05", strTime, time.Local)
+	diffTime := time.Now().Unix() - stamp.Unix()
+	if diffTime <= 60 {
+		newTime = "当前"
+	} else if diffTime < 60*60 {
+		newTime = strconv.FormatInt(diffTime/60, 10) + "分钟前"
+	} else if diffTime < 24*60*60 {
+		newTime = strconv.FormatInt(diffTime/(60*60), 10) + "小时前"
+	} else if diffTime < 30*24*60*60 {
+		newTime = strconv.FormatInt(diffTime/(24*60*60), 10) + "天前"
+	} else if diffTime < 12*30*24*60*60 {
+		newTime = strconv.FormatInt(diffTime/(30*24*60*60), 10) + "月前"
+	} else {
+		newTime = "1年前"
+	}
+	return newTime
+}
+
+//人民币小写转大写
+func ConvertNumToCny(num float64) (str string, err error) {
+	strNum := strconv.FormatFloat(num*100, 'f', 0, 64)
+	sliceUnit := []string{"仟", "佰", "拾", "亿", "仟", "佰", "拾", "万", "仟", "佰", "拾", "元", "角", "分"}
+	// log.Println(sliceUnit[:len(sliceUnit)-2])
+	s := sliceUnit[len(sliceUnit)-len(strNum):]
+	upperDigitUnit := map[string]string{"0": "零", "1": "壹", "2": "贰", "3": "叁", "4": "肆", "5": "伍", "6": "陆", "7": "柒", "8": "捌", "9": "玖"}
+	for k, v := range strNum[:] {
+		str = str + upperDigitUnit[string(v)] + s[k]
+	}
+	reg, err := regexp.Compile(`零角零分$`)
+	str = reg.ReplaceAllString(str, "整")
+
+	reg, err = regexp.Compile(`零角`)
+	str = reg.ReplaceAllString(str, "零")
+
+	reg, err = regexp.Compile(`零分$`)
+	str = reg.ReplaceAllString(str, "整")
+
+	reg, err = regexp.Compile(`零[仟佰拾]`)
+	str = reg.ReplaceAllString(str, "零")
+
+	reg, err = regexp.Compile(`零{2,}`)
+	str = reg.ReplaceAllString(str, "零")
+
+	reg, err = regexp.Compile(`零亿`)
+	str = reg.ReplaceAllString(str, "亿")
+
+	reg, err = regexp.Compile(`零万`)
+	str = reg.ReplaceAllString(str, "万")
+
+	reg, err = regexp.Compile(`零*元`)
+	str = reg.ReplaceAllString(str, "元")
+
+	reg, err = regexp.Compile(`亿零{0, 3}万`)
+	str = reg.ReplaceAllString(str, "^元")
+
+	reg, err = regexp.Compile(`零元`)
+	str = reg.ReplaceAllString(str, "零")
+	return
+}
+
+// GetNowWeekMonday 获取本周周一的时间
+func GetNowWeekMonday() time.Time {
+	offset := int(time.Monday - time.Now().Weekday())
+	if offset == 1 { //正好是周日,但是按照中国人的理解,周日是一周最后一天,而不是一周开始的第一天
+		offset = -6
+	}
+	mondayTime := time.Now().AddDate(0, 0, offset)
+	mondayTime = time.Date(mondayTime.Year(), mondayTime.Month(), mondayTime.Day(), 0, 0, 0, 0, mondayTime.Location())
+	return mondayTime
+}
+
+// GetNowWeekLastDay 获取本周最后一天的时间
+func GetNowWeekLastDay() time.Time {
+	offset := int(time.Monday - time.Now().Weekday())
+	if offset == 1 { //正好是周日,但是按照中国人的理解,周日是一周最后一天,而不是一周开始的第一天
+		offset = -6
+	}
+	firstDayTime := time.Now().AddDate(0, 0, offset)
+	firstDayTime = time.Date(firstDayTime.Year(), firstDayTime.Month(), firstDayTime.Day(), 0, 0, 0, 0, firstDayTime.Location()).AddDate(0, 0, 6)
+	lastDayTime := time.Date(firstDayTime.Year(), firstDayTime.Month(), firstDayTime.Day(), 23, 59, 59, 0, firstDayTime.Location())
+
+	return lastDayTime
+}
+
+// GetNowMonthFirstDay 获取本月第一天的时间
+func GetNowMonthFirstDay() time.Time {
+	nowMonthFirstDay := time.Date(time.Now().Year(), time.Now().Month(), 1, 0, 0, 0, 0, time.Now().Location())
+	return nowMonthFirstDay
+}
+
+// GetNowMonthLastDay 获取本月最后一天的时间
+func GetNowMonthLastDay() time.Time {
+	nowMonthLastDay := time.Date(time.Now().Year(), time.Now().Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 1, -1)
+	nowMonthLastDay = time.Date(nowMonthLastDay.Year(), nowMonthLastDay.Month(), nowMonthLastDay.Day(), 23, 59, 59, 0, nowMonthLastDay.Location())
+	return nowMonthLastDay
+}
+
+// GetNowQuarterFirstDay 获取本季度第一天的时间
+func GetNowQuarterFirstDay() time.Time {
+	month := int(time.Now().Month())
+	var nowQuarterFirstDay time.Time
+	if month >= 1 && month <= 3 {
+		//1月1号
+		nowQuarterFirstDay = time.Date(time.Now().Year(), 1, 1, 0, 0, 0, 0, time.Now().Location())
+	} else if month >= 4 && month <= 6 {
+		//4月1号
+		nowQuarterFirstDay = time.Date(time.Now().Year(), 4, 1, 0, 0, 0, 0, time.Now().Location())
+	} else if month >= 7 && month <= 9 {
+		nowQuarterFirstDay = time.Date(time.Now().Year(), 7, 1, 0, 0, 0, 0, time.Now().Location())
+	} else {
+		nowQuarterFirstDay = time.Date(time.Now().Year(), 10, 1, 0, 0, 0, 0, time.Now().Location())
+	}
+	return nowQuarterFirstDay
+}
+
+// GetNowQuarterLastDay 获取本季度最后一天的时间
+func GetNowQuarterLastDay() time.Time {
+	month := int(time.Now().Month())
+	var nowQuarterLastDay time.Time
+	if month >= 1 && month <= 3 {
+		//03-31 23:59:59
+		nowQuarterLastDay = time.Date(time.Now().Year(), 3, 31, 23, 59, 59, 0, time.Now().Location())
+	} else if month >= 4 && month <= 6 {
+		//06-30 23:59:59
+		nowQuarterLastDay = time.Date(time.Now().Year(), 6, 30, 23, 59, 59, 0, time.Now().Location())
+	} else if month >= 7 && month <= 9 {
+		//09-30 23:59:59
+		nowQuarterLastDay = time.Date(time.Now().Year(), 9, 30, 23, 59, 59, 0, time.Now().Location())
+	} else {
+		//12-31 23:59:59
+		nowQuarterLastDay = time.Date(time.Now().Year(), 12, 31, 23, 59, 59, 0, time.Now().Location())
+	}
+	return nowQuarterLastDay
+}
+
+// GetNowHalfYearFirstDay 获取当前半年的第一天的时间
+func GetNowHalfYearFirstDay() time.Time {
+	month := int(time.Now().Month())
+	var nowHalfYearLastDay time.Time
+	if month >= 1 && month <= 6 {
+		//03-31 23:59:59
+		nowHalfYearLastDay = time.Date(time.Now().Year(), 1, 1, 0, 0, 0, 0, time.Now().Location())
+	} else {
+		//12-31 23:59:59
+		nowHalfYearLastDay = time.Date(time.Now().Year(), 7, 1, 0, 0, 0, 0, time.Now().Location())
+	}
+	return nowHalfYearLastDay
+}
+
+// GetNowHalfYearLastDay 获取当前半年的最后一天的时间
+func GetNowHalfYearLastDay() time.Time {
+	month := int(time.Now().Month())
+	var nowHalfYearLastDay time.Time
+	if month >= 1 && month <= 6 {
+		//03-31 23:59:59
+		nowHalfYearLastDay = time.Date(time.Now().Year(), 6, 30, 23, 59, 59, 0, time.Now().Location())
+	} else {
+		//12-31 23:59:59
+		nowHalfYearLastDay = time.Date(time.Now().Year(), 12, 31, 23, 59, 59, 0, time.Now().Location())
+	}
+	return nowHalfYearLastDay
+}
+
+// GetNowYearFirstDay 获取当前年的最后一天的时间
+func GetNowYearFirstDay() time.Time {
+	//12-31 23:59:59
+	nowYearFirstDay := time.Date(time.Now().Year(), 1, 1, 0, 0, 0, 0, time.Now().Location())
+	return nowYearFirstDay
+}
+
+// GetNowYearLastDay 获取当前年的最后一天的时间
+func GetNowYearLastDay() time.Time {
+	//12-31 23:59:59
+	nowYearLastDay := time.Date(time.Now().Year(), 12, 31, 23, 59, 59, 0, time.Now().Location())
+	return nowYearLastDay
+}
+
+// CalculationDate 计算两个日期之间相差n年m月y天
+func CalculationDate(startDate, endDate time.Time) (beetweenDay string, err error) {
+	//startDate := time.Date(2021, 3, 28, 0, 0, 0, 0, time.Now().Location())
+	//endDate := time.Date(2022, 3, 31, 0, 0, 0, 0, time.Now().Location())
+	numYear := endDate.Year() - startDate.Year()
+
+	numMonth := int(endDate.Month()) - int(startDate.Month())
+
+	numDay := 0
+	//获取截止月的总天数
+	endDateDays := getMonthDay(endDate.Year(), int(endDate.Month()))
+
+	//获取截止月的前一个月
+	endDatePrevMonthDate := endDate.AddDate(0, -1, 0)
+	//获取截止日期的上一个月的总天数
+	endDatePrevMonthDays := getMonthDay(endDatePrevMonthDate.Year(), int(endDatePrevMonthDate.Month()))
+	//获取开始日期的的月份总天数
+	startDateMonthDays := getMonthDay(startDate.Year(), int(startDate.Month()))
+
+	//判断,截止月是否完全被选中,如果相等,那么代表截止月份全部天数被选择
+	if endDate.Day() == endDateDays {
+		numDay = startDateMonthDays - startDate.Day() + 1
+
+		//如果剩余天数正好与开始日期的天数是一致的,那么月份加1
+		if numDay == startDateMonthDays {
+			numMonth++
+			numDay = 0
+			//超过月份了,那么年份加1
+			if numMonth == 12 {
+				numYear++
+				numMonth = 0
+			}
+		}
+	} else {
+		numDay = endDate.Day() - startDate.Day() + 1
+	}
+
+	//天数小于0,那么向月份借一位
+	if numDay < 0 {
+		//向上一个月借一个月的天数
+		numDay += endDatePrevMonthDays
+
+		//总月份减去一个月
+		numMonth = numMonth - 1
+	}
+
+	//月份小于0,那么向年份借一位
+	if numMonth < 0 {
+		//向上一个年借12个月
+		numMonth += 12
+
+		//总年份减去一年
+		numYear = numYear - 1
+	}
+	if numYear < 0 {
+		err = errors.New("日期异常")
+		return
+	}
+
+	if numYear > 0 {
+		beetweenDay += fmt.Sprint(numYear, "年")
+	}
+	if numMonth > 0 {
+		beetweenDay += fmt.Sprint(numMonth, "个月")
+	}
+	if numDay > 0 {
+		beetweenDay += fmt.Sprint(numDay, "天")
+	}
+	return
+}
+
+// FormatPrice 格式化展示金额数字(财务金额展示,小数点前,每三位用,隔开)    1,234,567,898.55
+func FormatPrice(price float64) (str string) {
+	str = decimal.NewFromFloat(price).String()
+
+	length := len(str)
+	if length < 4 {
+		return str
+	}
+	arr := strings.Split(str, ".") //用小数点符号分割字符串,为数组接收
+	length1 := len(arr[0])
+	if length1 < 4 {
+		return str
+	}
+	count := (length1 - 1) / 3
+	for i := 0; i < count; i++ {
+		arr[0] = arr[0][:length1-(i+1)*3] + "," + arr[0][length1-(i+1)*3:]
+	}
+	return strings.Join(arr, ".") //将一系列字符串连接为一个字符串,之间用sep来分隔。
+}
+
+// getMonthDay 获取某年某月有多少天
+func getMonthDay(year, month int) (days int) {
+	if month != 2 {
+		if month == 4 || month == 6 || month == 9 || month == 11 {
+			days = 30
+
+		} else {
+			days = 31
+		}
+	} else {
+		if ((year%4) == 0 && (year%100) != 0) || (year%400) == 0 {
+			days = 29
+		} else {
+			days = 28
+		}
+	}
+	return
+}
+
+func SaveToFile(content, path string) error {
+	f, err := os.Create(path)
+	defer f.Close()
+	if err != nil {
+		return err
+	}
+	f.Write([]byte(content))
+	return nil
+}
+
+// HideString 给字段加***(从字符串中间替换,少于需要替换的长度,那么就补全*的长度)
+// src 待*字符串
+// hideLen 需要加*的长度
+func HideString(src string, hideLen int) string {
+	if src == "" {
+		return src
+	}
+	str := []rune(src)
+	if hideLen == 0 {
+		hideLen = 4
+	}
+	hideStr := ""
+	for i := 0; i < hideLen; i++ {
+		hideStr += "*"
+	}
+	strLen := len(str)
+
+	// 字符长度是1
+	if strLen == 1 {
+		return string(str[:1]) + hideStr
+	}
+	//字符长度大于1,但是小于等于需要隐藏的字符长度,那么就隐藏中间,保留前后各一位字符
+	if strLen <= hideLen+2 {
+		return string(str[:1]) + hideStr + string(str[strLen-1:])
+	}
+
+	subLen := strLen - hideLen //剩余需要展示的字符长度
+	decimal.NewFromFloat(2)
+	frontLenDecimal := decimal.NewFromInt(int64(subLen)).Div(decimal.NewFromInt(2)) //前面需要展示的字符的长度
+	frontLen := frontLenDecimal.Floor().IntPart()
+	return string(str[:frontLen]) + hideStr + string(str[frontLen+int64(hideLen):])
+}
+
+//用户参会时间转换
+func GetAttendanceDetailSeconds(secondNum int) string {
+	var timeStr string
+	if secondNum <= 60 {
+		if secondNum < 10 {
+			timeStr = "0" + strconv.Itoa(secondNum) + "''"
+		} else {
+			timeStr = strconv.Itoa(secondNum) + "''"
+		}
+	} else {
+		var remainderStr string
+		remainderNum := secondNum % 60
+		minuteNum := secondNum / 60
+		if remainderNum < 10 {
+			remainderStr = "0" + strconv.Itoa(remainderNum) + "''"
+		} else {
+			remainderStr = strconv.Itoa(remainderNum) + "''"
+		}
+		if minuteNum < 10 {
+			timeStr = "0" + strconv.Itoa(minuteNum) + "'" + remainderStr
+		} else {
+			timeStr = strconv.Itoa(minuteNum) + "'" + remainderStr
+		}
+	}
+	return timeStr
+}
+
+// SubStr 截取字符串(中文)
+func SubStr(str string, subLen int) string {
+	strRune := []rune(str)
+	bodyRuneLen := len(strRune)
+	if bodyRuneLen > subLen {
+		bodyRuneLen = subLen
+	}
+	str = string(strRune[:bodyRuneLen])
+	return str
+}
+
+func GetLocalIP() (ip string, err error) {
+	addrs, err := net.InterfaceAddrs()
+	if err != nil {
+		return
+	}
+	for _, addr := range addrs {
+		ipAddr, ok := addr.(*net.IPNet)
+		if !ok {
+			continue
+		}
+		if ipAddr.IP.IsLoopback() {
+			continue
+		}
+		if !ipAddr.IP.IsGlobalUnicast() {
+			continue
+		}
+		return ipAddr.IP.String(), nil
+	}
+	return
+}

+ 66 - 0
utils/config.go

@@ -0,0 +1,66 @@
+package utils
+
+import (
+	"fmt"
+	beeLogger "github.com/beego/bee/v2/logger"
+	"github.com/beego/beego/v2/server/web"
+	"github.com/rdlucklib/rdluck_tools/cache"
+)
+
+var (
+	RunMode               string //运行模式
+	MYSQL_URL             string //数据库连接
+	MYSQL_URL_EDB         string
+	MYSQL_URL_GL          string
+
+	REDIS_CACHE string       //缓存地址
+	Rc          *cache.Cache //redis缓存
+	Re          error        //redis错误
+)
+
+func init() {
+	tmpRunMode, err := web.AppConfig.String("run_mode")
+	if err != nil {
+		panic("配置文件读取run_mode错误 " + err.Error())
+	}
+	RunMode = tmpRunMode
+	fmt.Println("RunMode:", RunMode)
+	if RunMode == "" {
+		RunMode = "release"
+		configPath := `/home/code/config/hongze_admin/conf/app.conf`
+		err = web.LoadAppConfig("ini", configPath)
+		if err != nil {
+			fmt.Println("web.LoadAppConfig Err:" + err.Error())
+		}
+	}
+
+	config, err := web.AppConfig.GetSection(RunMode)
+	if err != nil {
+		panic("配置文件读取错误 " + err.Error())
+	}
+	beeLogger.Log.Info(RunMode + " 模式")
+	MYSQL_URL = config["mysql_url"]
+	MYSQL_URL_EDB = config["mysql_url_edb"]
+	MYSQL_URL_GL = config["mysql_url_gl"]
+
+	REDIS_CACHE = config["beego_cache"]
+	if len(REDIS_CACHE) <= 0 {
+		panic("redis链接参数没有配置")
+	}
+	Rc, Re = cache.NewCache(REDIS_CACHE) //初始化缓存
+	if Re != nil {
+		fmt.Println(Re)
+		panic(Re)
+	}
+
+	if RunMode == "release" {
+
+	} else {
+
+	}
+
+}
+
+//http://adminapi.brilliantstart.cn/admin/
+//http://adminapi.brilliantstart.cn/swagger/
+//http://8.136.199.33:8602/swagger/

+ 31 - 0
utils/constants.go

@@ -0,0 +1,31 @@
+package utils
+
+const (
+	Md5Key = "Ks@h64WJ#tcVgG8$&WlNfqvLAtMgpxWN"
+)
+
+//常量定义
+const (
+	FormatTime            = "15:04:05"                //时间格式
+	FormatDate            = "2006-01-02"              //日期格式
+	FormatDateUnSpace     = "20060102"                //日期格式
+	FormatDateTime        = "2006-01-02 15:04:05"     //完整时间格式
+	HlbFormatDateTime     = "2006-01-02_15:04:05.999" //完整时间格式
+	FormatDateTimeUnSpace = "20060102150405"          //完整时间格式
+	PageSize15            = 15                        //列表页每页数据量
+	PageSize5             = 5
+	PageSize10            = 10
+	PageSize20            = 20
+	PageSize30            = 30
+)
+
+const (
+	APPNAME          = "弘则-ETA数据刷新"
+	EmailSendToUsers = "glji@hzinsights.com;pyan@hzinsights.com;cxzhang@hzinsights.com"
+)
+
+//手机号,电子邮箱正则
+const (
+	RegularMobile = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0-9])|(17[0-9])|(16[0-9])|(19[0-9]))\\d{8}$" //手机号码
+	RegularEmail  = `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`                                             //匹配电子邮箱
+)

+ 62 - 0
utils/email.go

@@ -0,0 +1,62 @@
+package utils
+
+import (
+	"fmt"
+	"gopkg.in/gomail.v2"
+	"strings"
+)
+
+//发送邮件
+func SendEmail(title, content string, touser string) bool {
+	if RunMode == "debug" {
+		FileLog.Info(fmt.Sprint(title, ";", content))
+		return false
+	}
+	var arr []string
+	sub := strings.Index(touser, ";")
+	if sub >= 0 {
+		spArr := strings.Split(touser, ";")
+		for _, v := range spArr {
+			arr = append(arr, v)
+		}
+	} else {
+		arr = append(arr, touser)
+	}
+	m := gomail.NewMessage()
+	m.SetHeader("From", "317699326@qq.com ")
+	m.SetHeader("To", arr...)
+	m.SetHeader("Subject", title+" "+GetRandString(16))
+	m.SetBody("text/html", content)
+	d := gomail.NewDialer("smtp.qq.com", 587, "317699326@qq.com", "oqdypwfcvruwcbea")
+	if err := d.DialAndSend(m); err != nil {
+		return false
+	}
+	return true
+}
+
+//发送邮件
+func SendEmailByHz(title, content string, touser string) (result bool, err error) {
+	var arr []string
+	sub := strings.Index(touser, ";")
+	if sub >= 0 {
+		spArr := strings.Split(touser, ";")
+		for _, v := range spArr {
+			arr = append(arr, v)
+		}
+	} else {
+		arr = append(arr, touser)
+	}
+	m := gomail.NewMessage()
+	m.SetHeader("From", "public@hzinsights.com")
+	m.SetHeader("To", arr...)
+	m.SetHeader("Subject", title)
+	m.SetBody("text/html", content)
+	d := gomail.NewDialer("smtp.mxhichina.com", 465, "public@hzinsights.com", "Hzinsights2018")
+	if err := d.DialAndSend(m); err != nil {
+		fmt.Println("DialAndSend Err:" + err.Error())
+		result = false
+		return result, err
+	}
+	result = true
+	return
+}

+ 45 - 0
utils/jwt.go

@@ -0,0 +1,45 @@
+package utils
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/beego/beego/v2/adapter/logs"
+	"github.com/dgrijalva/jwt-go"
+)
+
+var (
+	KEY = []byte("5Mb5Gdmb5y")
+)
+
+// 发放token
+func GenToken(account string) string {
+	token := jwt.New(jwt.SigningMethodHS256)
+	token.Claims = &jwt.StandardClaims{
+		NotBefore: int64(time.Now().Unix()),
+		ExpiresAt: int64(time.Now().Unix() + 90*24*60*60),
+		Issuer:    "hongze_admin",
+		Subject:   account,
+	}
+	ss, err := token.SignedString(KEY)
+	if err != nil {
+		logs.Error(err)
+		return ""
+	}
+	return ss
+}
+
+// 校验token
+func CheckToken(account, token string) bool {
+	t, err := jwt.Parse(token, func(*jwt.Token) (interface{}, error) {
+		return KEY, nil
+	})
+	if err != nil {
+		fmt.Println(err.Error())
+		return false
+	}
+	if account != t.Claims.(jwt.MapClaims)["sub"] {
+		return false
+	}
+	return t.Valid
+}

+ 13 - 0
utils/logs.go

@@ -0,0 +1,13 @@
+package utils
+
+import (
+	"github.com/beego/beego/v2/core/logs"
+)
+
+var FileLog *logs.BeeLogger
+
+func init() {
+	FileLog = logs.NewLogger(1000000)
+	FileLog.SetLogger(logs.AdapterFile, `{"filename":"./rdlucklog/hongze_edb_lib.log"}`)
+	FileLog.EnableFuncCallDepth(true)
+}