hsun пре 1 година
родитељ
комит
e09def2c21
100 измењених фајлова са 1639 додато и 183 уклоњено
  1. 2 2
      cache/logs_cache.go
  2. 1 2
      controllers/base_auth.go
  3. 2 2
      controllers/base_common.go
  4. 1 1
      controllers/classify.go
  5. 1 1
      controllers/data_manage/chart_classify.go
  6. 1 1
      controllers/data_manage/chart_common.go
  7. 2 2
      controllers/data_manage/chart_info.go
  8. 2 2
      controllers/data_manage/correlation/correlation_chart_info.go
  9. 1 1
      controllers/data_manage/excel_info.go
  10. 1 1
      controllers/data_manage/future_good/future_good_chart_classify.go
  11. 2 2
      controllers/data_manage/future_good/future_good_chart_info.go
  12. 1 1
      controllers/data_manage/future_good/future_good_profit_chart_info.go
  13. 2 2
      controllers/data_manage/line_equation/line_chart_info.go
  14. 2 2
      controllers/data_manage/line_feature/chart_info.go
  15. 2 2
      controllers/data_manage/my_chart.go
  16. 2 2
      controllers/english_report/email.go
  17. 1 1
      controllers/english_report/en_permission.go
  18. 2 2
      controllers/english_report/report.go
  19. 2 2
      controllers/ppt.go
  20. 1 2
      controllers/ppt_english.go
  21. 1 2
      controllers/ppt_english_group.go
  22. 2 3
      controllers/ppt_v2.go
  23. 1 1
      controllers/ppt_v2_group.go
  24. 3 3
      controllers/report.go
  25. 5 5
      controllers/resource.go
  26. 2 2
      controllers/sandbox/sandbox.go
  27. 1 1
      controllers/sys_user.go
  28. 888 0
      controllers/user_login.go
  29. 3 0
      go.mod
  30. 5 0
      go.sum
  31. 1 1
      main.go
  32. 5 0
      models/base.go
  33. 1 1
      models/classify.go
  34. 5 1
      models/company/company_config.go
  35. 1 1
      models/data_manage/chart_edb_mapping.go
  36. 2 2
      models/data_manage/chart_info.go
  37. 1 1
      models/data_manage/edb_data_base.go
  38. 2 2
      models/data_manage/edb_data_calculate.go
  39. 4 4
      models/data_manage/edb_data_quarter.go
  40. 2 2
      models/data_manage/edb_info.go
  41. 1 1
      models/data_manage/edb_info_calculate.go
  42. 5 5
      models/data_manage/edb_info_calculate_tbz.go
  43. 1 3
      models/data_manage/excel_info.go
  44. 2 2
      models/data_manage/future_good/chart_info_future_good_profit.go
  45. 1 1
      models/data_manage/line_equation/line_equation.go
  46. 2 2
      models/data_manage/line_feature/line_feature.go
  47. 1 1
      models/data_manage/predict_edb_conf.go
  48. 1 1
      models/data_manage/predict_edb_conf_calculate_mapping.go
  49. 1 1
      models/data_manage/response/excel_info.go
  50. 3 2
      models/db.go
  51. 1 1
      models/en_classify_permission.go
  52. 1 1
      models/en_company_permission.go
  53. 1 1
      models/english_policy_report.go
  54. 1 1
      models/english_report.go
  55. 2 2
      models/english_report_email_log.go
  56. 19 22
      models/english_video.go
  57. 1 1
      models/report_chapter_type.go
  58. 1 1
      models/report_chapter_type_permission.go
  59. 1 1
      models/research_report.go
  60. 1 1
      models/sandbox/response/sandbox.go
  61. 126 0
      models/system/admin_verify_code_record.go
  62. 1 1
      models/system/sys_role_admin.go
  63. 53 7
      models/system/sys_user.go
  64. 6 6
      models/user_view_history.go
  65. 1 1
      models/wechat_send_msg.go
  66. 63 0
      routers/commentsRouter.go
  67. 6 0
      routers/router.go
  68. 1 1
      services/alarm_msg/alarm_msg.go
  69. 1 1
      services/aliyun_email.go
  70. 48 0
      services/captcha_redis.go
  71. 1 2
      services/company.go
  72. 1 1
      services/data/base_edb_lib.go
  73. 2 2
      services/data/chart_info.go
  74. 1 1
      services/data/chart_info_elastic.go
  75. 2 2
      services/data/correlation/chart_info.go
  76. 1 1
      services/data/edb_info.go
  77. 1 1
      services/data/future_good/base_future_good_lib.go
  78. 2 2
      services/data/future_good/chart_info.go
  79. 1 1
      services/data/future_good/future_edb_info.go
  80. 2 2
      services/data/line_equation/chart_info.go
  81. 1 1
      services/data/line_feature/chart_info.go
  82. 2 2
      services/data/predict_edb_info.go
  83. 2 2
      services/data/predict_edb_info_rule.go
  84. 1 1
      services/elastic.go
  85. 2 2
      services/elastic/elastic.go
  86. 1 1
      services/english_report.go
  87. 1 1
      services/excel/lucky_sheet.go
  88. 2 2
      services/oss.go
  89. 1 1
      services/ppt.go
  90. 5 8
      services/ppt/ppt_english_group.go
  91. 4 5
      services/ppt/ppt_group.go
  92. 4 0
      services/ppt2img/ppt2img.go
  93. 2 2
      services/report.go
  94. 148 0
      services/sms.go
  95. 1 1
      services/tencent_yun.go
  96. 123 0
      services/user_login.go
  97. 2 2
      services/video.go
  98. 1 1
      services/wechat_send_msg.go
  99. 1 1
      services/wx_app.go
  100. 2 2
      services/xfyun.go

+ 2 - 2
cache/logs_cache.go

@@ -1,13 +1,13 @@
 package cache
 
 import (
-	"fmt"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"time"
 )
 
-//record more information
+// record more information
 func RecordNewLogs(adminId int, request, response string, realName, operateIp, model string) bool {
 	log := &models.OperateLogs{AdminId: adminId, SysUserRealName: realName, OperateTime: time.Now(), Request: request, Response: response, OperateIp: operateIp, Model: model}
 	if utils.Re == nil {

+ 1 - 2
controllers/base_auth.go

@@ -2,12 +2,11 @@ package controllers
 
 import (
 	"encoding/json"
-	"fmt"
 	"eta/eta_mobile/cache"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/services/data"
-
+	"fmt"
 	"net/http"
 	"net/url"
 	"strconv"

+ 2 - 2
controllers/base_common.go

@@ -2,10 +2,10 @@ package controllers
 
 import (
 	"encoding/json"
-	"fmt"
-	"github.com/beego/beego/v2/server/web"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/beego/beego/v2/server/web"
 	"net/http"
 	"net/url"
 )

+ 1 - 1
controllers/classify.go

@@ -1,9 +1,9 @@
 package controllers
 
 import (
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/utils"
+	"github.com/rdlucklib/rdluck_tools/paging"
 )
 
 // 分类

+ 1 - 1
controllers/data_manage/chart_classify.go

@@ -2,13 +2,13 @@ package data_manage
 
 import (
 	"encoding/json"
-	"fmt"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"strconv"
 	"time"
 )

+ 1 - 1
controllers/data_manage/chart_common.go

@@ -2,7 +2,6 @@ package data_manage
 
 import (
 	"encoding/json"
-	"fmt"
 	"eta/eta_mobile/controllers/data_manage/correlation"
 	"eta/eta_mobile/controllers/data_manage/future_good"
 	"eta/eta_mobile/controllers/data_manage/line_equation"
@@ -13,6 +12,7 @@ import (
 	"eta/eta_mobile/services/data"
 	lineFeatureServ "eta/eta_mobile/services/data/line_feature"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"strconv"
 	"time"
 )

+ 2 - 2
controllers/data_manage/chart_info.go

@@ -2,14 +2,14 @@ package data_manage
 
 import (
 	"encoding/json"
-	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	"strconv"
 	"strings"
 	"time"

+ 2 - 2
controllers/data_manage/correlation/correlation_chart_info.go

@@ -2,8 +2,6 @@ package correlation
 
 import (
 	"encoding/json"
-	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
@@ -12,6 +10,8 @@ import (
 	"eta/eta_mobile/services/data"
 	correlationServ "eta/eta_mobile/services/data/correlation"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	"strconv"
 	"strings"
 	"time"

+ 1 - 1
controllers/data_manage/excel_info.go

@@ -1,13 +1,13 @@
 package data_manage
 
 import (
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/data_manage/response"
 	"eta/eta_mobile/services/excel"
 	"eta/eta_mobile/utils"
+	"github.com/rdlucklib/rdluck_tools/paging"
 )
 
 // ExcelInfoController ETA表格管理

+ 1 - 1
controllers/data_manage/future_good/future_good_chart_classify.go

@@ -1,12 +1,12 @@
 package future_good
 
 import (
-	"fmt"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/utils"
+	"fmt"
 )
 
 // FutureGoodChartClassifyController 期货指标分类

+ 2 - 2
controllers/data_manage/future_good/future_good_chart_info.go

@@ -2,8 +2,6 @@ package future_good
 
 import (
 	"encoding/json"
-	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
@@ -11,6 +9,8 @@ import (
 	"eta/eta_mobile/services/data"
 	future_goodServ "eta/eta_mobile/services/data/future_good"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	"strconv"
 	"strings"
 	"time"

+ 1 - 1
controllers/data_manage/future_good/future_good_profit_chart_info.go

@@ -2,7 +2,6 @@ package future_good
 
 import (
 	"encoding/json"
-	"fmt"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/data_manage/future_good"
 	"eta/eta_mobile/models/data_manage/future_good/request"
@@ -10,6 +9,7 @@ import (
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"strings"
 	"time"
 )

+ 2 - 2
controllers/data_manage/line_equation/line_chart_info.go

@@ -2,8 +2,6 @@ package line_equation
 
 import (
 	"encoding/json"
-	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
@@ -12,6 +10,8 @@ import (
 	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/services/data/line_equation"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	"strconv"
 	"strings"
 	"time"

+ 2 - 2
controllers/data_manage/line_feature/chart_info.go

@@ -2,8 +2,6 @@ package line_feature
 
 import (
 	"encoding/json"
-	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
@@ -11,6 +9,8 @@ import (
 	"eta/eta_mobile/services/data"
 	lineFeatureServ "eta/eta_mobile/services/data/line_feature"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	"strconv"
 	"strings"
 	"time"

+ 2 - 2
controllers/data_manage/my_chart.go

@@ -2,14 +2,14 @@ package data_manage
 
 import (
 	"encoding/json"
-	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	"strconv"
 	"strings"
 	"time"

+ 2 - 2
controllers/english_report/email.go

@@ -2,13 +2,13 @@ package english_report
 
 import (
 	"encoding/json"
-	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/company"
 	"eta/eta_mobile/services"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	"strconv"
 	"strings"
 	"time"

+ 1 - 1
controllers/english_report/en_permission.go

@@ -1,10 +1,10 @@
 package english_report
 
 import (
-	"fmt"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"strings"
 )
 

+ 2 - 2
controllers/english_report/report.go

@@ -2,14 +2,14 @@ package english_report
 
 import (
 	"encoding/json"
-	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/company"
 	"eta/eta_mobile/services"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	"html"
 	"sort"
 	"strconv"

+ 2 - 2
controllers/ppt.go

@@ -2,16 +2,16 @@ package controllers
 
 import (
 	"encoding/json"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/utils"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	_ "image/gif"
 	_ "image/jpeg"
 	_ "image/png"
 	"time"
 )
 
-//报告
+// 报告
 type PptController struct {
 	BaseAuthController
 }

+ 1 - 2
controllers/ppt_english.go

@@ -2,12 +2,12 @@ package controllers
 
 import (
 	"encoding/json"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/company"
 	"eta/eta_mobile/models/ppt_english"
 	"eta/eta_mobile/services/ppt"
 	"eta/eta_mobile/utils"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	_ "image/gif"
 	_ "image/jpeg"
 	_ "image/png"
@@ -737,4 +737,3 @@ func (this *PptEnglishController) GrantInfo() {
 	}
 	br.Msg = "分配成功"
 }
-

+ 1 - 2
controllers/ppt_english_group.go

@@ -507,7 +507,6 @@ func (this *PptEnglishGroupController) GrantPptList() {
 	return
 }
 
-
 // PptList
 // @Title 获取Ppt
 // @Description 获取用户开放的公共Ppt接口
@@ -533,4 +532,4 @@ func (this *PptEnglishGroupController) PptList() {
 	br.Msg = "查询成功"
 	br.Data = data
 	return
-}
+}

+ 2 - 3
controllers/ppt_v2.go

@@ -2,13 +2,13 @@ package controllers
 
 import (
 	"encoding/json"
-	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/company"
 	"eta/eta_mobile/models/ppt_english"
 	"eta/eta_mobile/services/ppt"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	_ "image/gif"
 	_ "image/jpeg"
 	_ "image/png"
@@ -569,7 +569,6 @@ func (this *PptV2Controller) GetConfig() {
 	br.Data = resp
 }
 
-
 // Grant
 // @Title 分配ppt权限
 // @Description 分配ppt权限接口

+ 1 - 1
controllers/ppt_v2_group.go

@@ -534,4 +534,4 @@ func (this *PptV2GroupController) PptList() {
 	br.Msg = "查询成功"
 	br.Data = data
 	return
-}
+}

+ 3 - 3
controllers/report.go

@@ -2,13 +2,13 @@ package controllers
 
 import (
 	"encoding/json"
-	"fmt"
-	"github.com/beego/beego/v2/server/web"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/services"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/beego/beego/v2/server/web"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	"html"
 	"os"
 	"path"

+ 5 - 5
controllers/resource.go

@@ -3,12 +3,12 @@ package controllers
 import (
 	"bufio"
 	"encoding/json"
-	"fmt"
-	"github.com/kgiannakakis/mp3duration/src/mp3duration"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/services"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/kgiannakakis/mp3duration/src/mp3duration"
 	"io"
 	"os"
 	"path"
@@ -17,7 +17,7 @@ import (
 	"time"
 )
 
-//资源管理-图片上传,合同上传等
+// 资源管理-图片上传,合同上传等
 type ResourceController struct {
 	//BaseAuthController
 	BaseCommonController
@@ -627,7 +627,7 @@ func (this *ResourceController) UploadImageBase64() {
 //	fmt.Println("end")
 //}
 
-//判断文件是否存在
+// 判断文件是否存在
 func IsFileExist(filename string) bool {
 	_, err := os.Stat(filename)
 	if os.IsNotExist(err) {
@@ -761,4 +761,4 @@ func (this *ResourceController) WechatWarning() {
 	br.Msg = "发送成功"
 	br.Ret = 200
 	br.Success = true
-}
+}

+ 2 - 2
controllers/sandbox/sandbox.go

@@ -1,15 +1,15 @@
 package sandbox
 
 import (
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/sandbox"
 	"eta/eta_mobile/models/sandbox/response"
 	"eta/eta_mobile/utils"
+	"github.com/rdlucklib/rdluck_tools/paging"
 )
 
-//SandboxController 逻辑导图
+// SandboxController 逻辑导图
 type SandboxController struct {
 	controllers.BaseAuthController
 }

+ 1 - 1
controllers/sys_user.go

@@ -2,11 +2,11 @@ package controllers
 
 import (
 	"encoding/json"
-	"fmt"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/services"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"time"
 )
 

+ 888 - 0
controllers/user_login.go

@@ -0,0 +1,888 @@
+package controllers
+
+import (
+	"encoding/base64"
+	"encoding/json"
+	"eta/eta_mobile/models"
+	"eta/eta_mobile/models/company"
+	"eta/eta_mobile/models/system"
+	"eta/eta_mobile/services"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/mojocn/base64Captcha"
+	"image/color"
+	"strings"
+	"time"
+)
+
+// UserLoginController 登录-无需Token
+type UserLoginController struct {
+	BaseCommonController
+}
+
+// UserLoginAuthController 登录-需Token
+type UserLoginAuthController struct {
+	BaseAuthController
+}
+
+// GenerateCaptcha
+// @Title 生成图形验证码
+// @Description 生成图形验证码
+// @Success 200 Ret=200 获取成功
+// @router /get_captcha [get]
+func (this *UserLoginController) GenerateCaptcha() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	//driver := base64Captcha.DefaultDriverDigit
+	// 自定义验证码样式
+	var driver base64Captcha.Driver
+	driverString := base64Captcha.DriverString{
+		Height:          60,    //高度
+		Width:           120,   //宽度
+		NoiseCount:      0,     //干扰数
+		ShowLineOptions: 2 | 4, //展示个数
+		Length:          4,     //长度
+		//Source:          "1234567890qwertyuioplkjhgfdsazxcvbnm", //验证码随机字符串来源
+		Source: "1234567890", //验证码随机字符串来源
+		BgColor: &color.RGBA{ // 背景颜色
+			R: 0,
+			G: 0,
+			B: 0,
+			A: 0,
+		},
+		Fonts: []string{"wqy-microhei.ttc"}, // 字体
+	}
+	driver = driverString.ConvertFonts()
+
+	// 生成验证码
+	store := services.CaptchaRedis{}
+	captcha := base64Captcha.NewCaptcha(driver, store)
+	id, b64s, err := captcha.Generate()
+	if err != nil {
+		br.Msg = "生成失败"
+		br.ErrMsg = "生成验证码失败, Err: " + err.Error()
+		return
+	}
+
+	type CaptchaResult struct {
+		Id         string
+		Base64Blob string
+	}
+	res := new(CaptchaResult)
+	res.Id = id
+	res.Base64Blob = b64s
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = res
+}
+
+// GetVerifyCode
+// @Title 获取短信/邮箱验证码
+// @Description 获取短信/邮箱验证码
+// @Param	request	body VerifyCodeReq true "type json string"
+// @Success 200 Ret=200 获取成功
+// @router /verify_code [post]
+func (this *UserLoginController) GetVerifyCode() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	type VerifyCodeReq struct {
+		VerifyType  int    `description:"验证方式: 1-手机号; 2-邮箱"`
+		CaptchaId   string `description:"验证码ID"`
+		CaptchaCode string `description:"图形验证码"`
+		Mobile      string `description:"手机号"`
+		TelAreaCode string `description:"手机区号"`
+		Email       string `description:"邮箱"`
+		Source      int    `description:"来源:1-登录;2-异常登录校验;3-忘记密码"`
+	}
+	var req VerifyCodeReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.VerifyType != 1 && req.VerifyType != 2 {
+		br.Msg = "验证方式有误"
+		br.ErrMsg = "验证方式有误"
+		return
+	}
+	if req.Source != 1 && req.Source != 2 && req.Source != 3 {
+		br.Msg = "来源有误"
+		br.ErrMsg = "来源有误"
+		return
+	}
+	// 忘记密码图形校验在前一步, 这一步不再校验图形验证码
+	if req.Source != 3 {
+		if req.CaptchaId == "" || req.CaptchaCode == "" {
+			br.Msg = "请输入图形验证码"
+			return
+		}
+	}
+	if req.VerifyType == 1 {
+		if req.TelAreaCode == "" {
+			br.Msg = "请选择区号"
+			return
+		}
+		if req.Mobile == "" {
+			br.Msg = "请输入手机号"
+			return
+		}
+		if req.TelAreaCode == "86" && !utils.ValidateMobileFormatat(req.Mobile) {
+			br.Msg = "您的手机号输入有误, 请检查"
+			return
+		}
+		_, e := system.GetSysUserByMobile(req.Mobile)
+		if e != nil {
+			if e.Error() == utils.ErrNoRow() {
+				br.Msg = "您的手机号未绑定账号, 请检查"
+				return
+			}
+			br.Msg = "您的手机号未绑定账号, 请检查"
+			br.ErrMsg = "手机号获取用户失败, Err:" + e.Error()
+			return
+		}
+	}
+	if req.VerifyType == 2 {
+		if req.Email == "" {
+			br.Msg = "请输入邮箱"
+			return
+		}
+		if !utils.ValidateEmailFormatat(req.Email) {
+			br.Msg = "您的邮箱输入有误, 请检查"
+			return
+		}
+		_, e := system.GetSysUserByEmail(req.Email)
+		if e != nil {
+			if e.Error() == utils.ErrNoRow() {
+				br.Msg = "您的邮箱未绑定账号, 请检查"
+				return
+			}
+			br.Msg = "您的邮箱未绑定账号, 请检查"
+			br.ErrMsg = "邮箱获取用户失败, Err:" + e.Error()
+			return
+		}
+	}
+	if req.Source != 3 {
+		store := services.CaptchaRedis{}
+		ok := store.Verify(req.CaptchaId, req.CaptchaCode, true)
+		if !ok {
+			br.Msg = "图形验证码错误, 请重新输入"
+			return
+		}
+	}
+
+	// 限制最多60s获取一次
+	var lockKey string
+	if req.VerifyType == 1 {
+		lockKey = fmt.Sprint(utils.CaptchaCachePrefix, req.Mobile)
+	}
+	if req.VerifyType == 2 {
+		lockKey = fmt.Sprint(utils.CaptchaCachePrefix, req.Email)
+	}
+	locked := utils.Rc.SetNX(lockKey, 1, time.Minute)
+	if !locked {
+		br.Msg = "请勿频繁发送"
+		return
+	}
+
+	// 发送验证码
+	sendRes := false
+	if req.VerifyType == 1 {
+		r, e := services.SendAdminMobileVerifyCode(req.Source, req.Mobile, req.TelAreaCode)
+		if e != nil {
+			br.Msg = "发送失败"
+			br.ErrMsg = "发送短信验证码失败, Err: " + e.Error()
+			return
+		}
+		sendRes = r
+	}
+	if req.VerifyType == 2 {
+		r, e := services.SendAdminEmailVerifyCode(req.Source, req.Email)
+		if e != nil {
+			br.Msg = "发送失败"
+			br.ErrMsg = "发送邮箱验证码失败, Err: " + e.Error()
+			return
+		}
+		sendRes = r
+	}
+	if !sendRes {
+		br.Msg = "发送失败"
+		br.ErrMsg = "发送短信验证码失败"
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "发送成功"
+}
+
+// Login
+// @Title 用户登录
+// @Description 用户登录
+// @Param	request	body UserLoginReq true "type json string"
+// @Success 200 {object} models.LoginResp
+// @router /login [post]
+func (this *UserLoginController) Login() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg != "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	// 入参
+	type UserLoginReq struct {
+		LoginType  int    `description:"登录方式: 1-账号; 2-手机号; 3-邮箱"`
+		Username   string `description:"账号"`
+		Password   string `description:"密码"`
+		Mobile     string `description:"手机号"`
+		Email      string `description:"邮箱"`
+		VerifyCode string `description:"验证码"`
+	}
+	var req UserLoginReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	req.Username = strings.TrimSpace(req.Username)
+	req.Mobile = strings.TrimSpace(req.Mobile)
+	if req.Mobile != "" {
+		if !utils.ValidateMobileFormatat(req.Mobile) {
+			br.Msg = "您的手机号输入有误, 请检查"
+			return
+		}
+	}
+	req.Email = strings.TrimSpace(req.Email)
+	if req.Email != "" {
+		if !utils.ValidateEmailFormatat(req.Email) {
+			br.Msg = "您的邮箱输入有误, 请检查"
+			return
+		}
+	}
+	req.VerifyCode = strings.TrimSpace(req.VerifyCode)
+	if req.LoginType != 1 && req.LoginType != 2 && req.LoginType != 3 {
+		br.Msg = "登录方式有误"
+		br.ErrMsg = fmt.Sprintf("登录方式有误, Type: %d", req.LoginType)
+		return
+	}
+
+	sysUser := new(system.Admin)
+	// 账号密码登录
+	if req.LoginType == 1 {
+		if req.Username == "" {
+			br.Msg = "请输入账号"
+			return
+		}
+		if req.Password == "" {
+			br.Msg = "请输入密码"
+			return
+		}
+
+		// 判断账号是否为异常登录, 算作异常的话就需要换另外的方式去做登录了
+		abnormalKey := fmt.Sprint(utils.CACHE_ABNORMAL_LOGIN, req.Username)
+		isAbnormal, _ := utils.Rc.RedisString(abnormalKey)
+		if isAbnormal != "" {
+			br.Ret = models.BaseRespCodeAbnormalLogin
+			br.Msg = "账号异常, 请进行手机号/邮箱校验"
+			return
+		}
+
+		// 账号密码校验
+		errPassKey := fmt.Sprint(utils.CACHE_LOGIN_ERR_PASS, req.Username)
+		accountUser, e := system.CheckSysUser(req.Username, req.Password)
+		if e != nil {
+			br.Ret = models.BaseRespCodeLoginErr
+			if e.Error() == utils.ErrNoRow() {
+				br.Msg = "登录失败, 账号或密码错误"
+				if isAbnormal != "" {
+					return
+				}
+				// 错误密码计数, 超过6次标记异常
+				if !utils.Rc.IsExist(errPassKey) {
+					_ = utils.Rc.Put(errPassKey, 1, utils.GetTodayLastSecond())
+					return
+				}
+				errNum, _ := utils.Rc.RedisInt(errPassKey)
+				errNum += 1
+				if errNum >= 6 {
+					br.Ret = models.BaseRespCodeAbnormalLogin
+					br.Msg = "账号异常, 请进行手机号/邮箱校验"
+					// 标记异常登录, 重置计数
+					_ = utils.Rc.Put(abnormalKey, "true", utils.GetTodayLastSecond())
+					_ = utils.Rc.Delete(errPassKey)
+					return
+				}
+				_ = utils.Rc.Put(errPassKey, errNum, utils.GetTodayLastSecond())
+				return
+			}
+			br.Msg = "登录失败, 账号或密码错误"
+			br.ErrMsg = "登录失败, Err:" + e.Error()
+			return
+		}
+		if accountUser.Enabled == 0 {
+			br.Msg = "您的账号已被禁用, 如需登录, 请联系管理员"
+			br.ErrMsg = fmt.Sprintf("账号已被禁用, 登录账号: %s, 账户名称: %s", accountUser.AdminName, accountUser.RealName)
+			return
+		}
+
+		// 异常登录-是否登录间隔大于60天
+		if isAbnormal == "" {
+			abnormalTime := time.Now().AddDate(0, 0, -60)
+			lastLogin, _ := time.ParseInLocation(utils.FormatDateTime, accountUser.LastLoginTime, time.Local)
+			if !lastLogin.IsZero() && lastLogin.Before(abnormalTime) {
+				br.Msg = "请进行异常登录校验"
+				br.Ret = models.BaseRespCodeAbnormalLogin
+				// 标记异常登录
+				_ = utils.Rc.Put(abnormalKey, "true", utils.GetTodayLastSecond())
+				return
+			}
+		}
+
+		// 登录成功, 清除异常标记
+		_ = utils.Rc.Delete(abnormalKey)
+		_ = utils.Rc.Delete(errPassKey)
+		sysUser = accountUser
+	}
+
+	// 手机号
+	if req.LoginType == 2 {
+		if req.Mobile == "" {
+			br.Msg = "请输入手机号"
+			return
+		}
+		if !utils.ValidateMobileFormatat(req.Mobile) {
+			br.Msg = "您的手机号输入有误, 请检查"
+			return
+		}
+		if req.VerifyCode == "" {
+			br.Msg = "请输入验证码"
+			return
+		}
+		expiredTime := time.Now().Add(utils.VerifyCodeExpireMinute * time.Minute).Format(utils.FormatDateTime)
+		recordCond := ` AND source = ? AND mobile = ? AND code = ? AND expired_time <= ?`
+		recordPars := make([]interface{}, 0)
+		recordPars = append(recordPars, system.AdminVerifyCodeRecordSourceLogin, req.Mobile, req.VerifyCode, expiredTime)
+		recordOb := new(system.AdminVerifyCodeRecord)
+		_, e := recordOb.GetItemByCondition(recordCond, recordPars)
+		if e != nil {
+			if e.Error() == utils.ErrNoRow() {
+				br.Msg = "验证码错误, 请重新输入"
+				return
+			}
+			br.Msg = "验证码错误, 请重新输入"
+			br.ErrMsg = "获取手机号登陆验证码失败, Err: " + e.Error()
+			return
+		}
+
+		mobileUser, e := system.GetSysUserByMobile(req.Mobile)
+		if e != nil {
+			if e.Error() == utils.ErrNoRow() {
+				br.Msg = "您的手机号未绑定账号, 请检查"
+				return
+			}
+			br.Msg = "您的手机号未绑定账号, 请检查"
+			br.ErrMsg = "手机号获取用户失败, Err:" + e.Error()
+			return
+		}
+		if mobileUser.Enabled == 0 {
+			br.Msg = "您的账号已被禁用, 如需登录, 请联系管理员"
+			br.ErrMsg = fmt.Sprintf("账号已被禁用, 登录手机号: %s", req.Mobile)
+			return
+		}
+		sysUser = mobileUser
+	}
+
+	// 邮箱登录
+	if req.LoginType == 3 {
+		if req.Email == "" {
+			br.Msg = "请输入邮箱"
+			return
+		}
+		if !utils.ValidateEmailFormatat(req.Email) {
+			br.Msg = "您的邮箱输入有误, 请检查"
+			return
+		}
+		if req.VerifyCode == "" {
+			br.Msg = "请输入验证码"
+			return
+		}
+		expiredTime := time.Now().Add(utils.VerifyCodeExpireMinute * time.Minute).Format(utils.FormatDateTime)
+		recordCond := ` AND source = ? AND email = ? AND code = ? AND expired_time <= ?`
+		recordPars := make([]interface{}, 0)
+		recordPars = append(recordPars, system.AdminVerifyCodeRecordSourceLogin, req.Email, req.VerifyCode, expiredTime)
+		recordOb := new(system.AdminVerifyCodeRecord)
+		_, e := recordOb.GetItemByCondition(recordCond, recordPars)
+		if e != nil {
+			if e.Error() == utils.ErrNoRow() {
+				br.Msg = "验证码错误, 请重新输入"
+				return
+			}
+			br.Msg = "验证码错误, 请重新输入"
+			br.ErrMsg = "获取手机号登陆验证码失败, Err: " + e.Error()
+			return
+		}
+
+		emailUser, e := system.GetSysUserByEmail(req.Email)
+		if e != nil {
+			if e.Error() == utils.ErrNoRow() {
+				br.Msg = "您的邮箱未绑定账号, 请检查"
+				return
+			}
+			br.Msg = "您的邮箱未绑定账号, 请检查"
+			br.ErrMsg = "邮箱获取用户失败, Err:" + e.Error()
+			return
+		}
+		if emailUser.Enabled == 0 {
+			br.Msg = "您的账号已被禁用, 如需登录, 请联系管理员"
+			br.ErrMsg = fmt.Sprintf("账号已被禁用, 登录邮箱: %s", req.Email)
+			return
+		}
+		sysUser = emailUser
+	}
+
+	// 登录成功(无论哪种方式登录), 清除异常标记
+	abnormalCache := fmt.Sprint(utils.CACHE_ABNORMAL_LOGIN, sysUser.AdminName)
+	errPassCache := fmt.Sprint(utils.CACHE_LOGIN_ERR_PASS, sysUser.AdminName)
+	_ = utils.Rc.Delete(abnormalCache)
+	_ = utils.Rc.Delete(errPassCache)
+
+	account := utils.MD5(sysUser.AdminName)
+	token := utils.GenToken(account)
+	sysSession := new(system.SysSession)
+	sysSession.UserName = req.Username
+	sysSession.SysUserId = sysUser.AdminId
+	sysSession.ExpiredTime = time.Now().AddDate(0, 0, 90)
+	sysSession.IsRemember = 0 // 均需要做过期校验
+	sysSession.CreatedTime = time.Now()
+	sysSession.LastUpdatedTime = time.Now()
+	sysSession.AccessToken = token
+	if e := system.AddSysSession(sysSession); e != nil {
+		br.Msg = "登录失败"
+		br.ErrMsg = "新增session信息失败, Err:" + e.Error()
+		return
+	}
+
+	// 修改最后登录时间
+	{
+		sysUser.LastLoginTime = time.Now().Format(utils.FormatDateTime)
+		sysUser.LastUpdatedTime = time.Now().Format(utils.FormatDateTime)
+		_ = sysUser.Update([]string{"LastLoginTime", "LastUpdatedTime"})
+	}
+
+	resp := new(system.LoginResp)
+	resp.Authorization = token
+	resp.Authorization = "authorization=" + token + "$account=" + account
+	resp.RealName = sysUser.RealName
+	resp.AdminName = sysUser.AdminName
+	resp.RoleName = sysUser.RoleName
+	resp.SysRoleTypeCode = sysUser.RoleTypeCode //系统角色编码
+	resp.RoleTypeCode = sysUser.RoleTypeCode
+	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_GROUP {
+		resp.RoleTypeCode = utils.ROLE_TYPE_CODE_FICC_SELLER
+	}
+	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_TEAM {
+		resp.RoleTypeCode = utils.ROLE_TYPE_CODE_FICC_SELLER
+	}
+	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_DEPARTMENT {
+		resp.RoleTypeCode = utils.ROLE_TYPE_CODE_FICC_SELLER
+	}
+	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_GROUP {
+		resp.RoleTypeCode = utils.ROLE_TYPE_CODE_RAI_SELLER
+	}
+	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_DEPARTMENT {
+		resp.RoleTypeCode = utils.ROLE_TYPE_CODE_RAI_SELLER
+	}
+	if sysUser.RoleName == utils.ROLE_NAME_FICC_DIRECTOR {
+		resp.RoleTypeCode = utils.ROLE_TYPE_CODE_FICC_SELLER
+	}
+	resp.AdminId = sysUser.AdminId
+	var productName string
+	productId := services.GetProductId(sysUser.RoleTypeCode)
+	if productId == 1 {
+		productName = utils.COMPANY_PRODUCT_FICC_NAME
+	} else if productId == 2 {
+		productName = utils.COMPANY_PRODUCT_RAI_NAME
+	} else {
+		productName = "admin"
+	}
+	resp.ProductName = productName
+	resp.Authority = sysUser.Authority
+
+	// 设置redis缓存
+	{
+		// 获取不可信的登录态,并将该登录态重置掉,不允许多次登录
+		noTrustLoginKey := fmt.Sprint(utils.CACHE_ACCESS_TOKEN_LOGIN_NO_TRUST, sysUser.AdminId)
+		noTrustLoginId, _ := utils.Rc.RedisString(noTrustLoginKey)
+		if noTrustLoginId != `` { // 如果存在不可信设备,那么将其下架
+			oldNoTrustLoginKey := fmt.Sprint(utils.CACHE_ACCESS_TOKEN_LOGIN, noTrustLoginId)
+			_ = utils.Rc.Put(oldNoTrustLoginKey, "0", 30*time.Minute)
+		}
+
+		// 如果当前是不可信设备,那么将其加入到不可信名单
+		loginKey := fmt.Sprint(utils.CACHE_ACCESS_TOKEN_LOGIN, sysSession.Id)
+		_ = utils.Rc.Put(loginKey, "1", 30*time.Minute)
+		_ = utils.Rc.Put(noTrustLoginKey, sysSession.Id, 30*time.Minute)
+	}
+
+	// 新增登录记录
+	go func() {
+		record := new(system.SysUserLoginRecord)
+		record.Uid = sysUser.AdminId
+		record.UserName = req.Username
+		record.Ip = this.Ctx.Input.IP()
+		record.Stage = "login"
+		record.CreateTime = time.Now()
+		_ = system.AddSysUserLoginRecord(record)
+	}()
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "登录成功"
+}
+
+// ForgetAccountGet
+// @Title 忘记密码-账号校验
+// @Description 忘记密码-账号校验
+// @Param	request	body ForgetAccountGetReq true "type json string"
+// @Success 200 Ret=200 获取成功
+// @router /forget/account_get [post]
+func (this *UserLoginController) ForgetAccountGet() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	type ForgetAccountGetReq struct {
+		CaptchaId   string `description:"验证码ID"`
+		CaptchaCode string `description:"图形验证码"`
+		UserName    string `description:"用户名"`
+	}
+	var req ForgetAccountGetReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	req.UserName = strings.TrimSpace(req.UserName)
+	if req.UserName == "" {
+		br.Msg = "请输入账号"
+		return
+	}
+	if req.CaptchaId == "" || req.CaptchaCode == "" {
+		br.Msg = "请输入图形验证码"
+		return
+	}
+	store := services.CaptchaRedis{}
+	ok := store.Verify(req.CaptchaId, req.CaptchaCode, true)
+	if !ok {
+		br.Msg = "验证码错误, 请重新输入"
+		return
+	}
+
+	sysUser, e := system.GetSysUserByAdminName(req.UserName)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "用户不存在, 请检查"
+			return
+		}
+		br.Msg = "账号错误, 请重新输入"
+		br.ErrMsg = "用户名获取用户失败, Err: " + e.Error()
+		return
+	}
+
+	type ForgetAccountCheckResp struct {
+		Mobile      string `description:"手机号"`
+		Email       string `description:"邮箱"`
+		TelAreaCode string `description:"手机区号"`
+	}
+	resp := ForgetAccountCheckResp{
+		Mobile:      sysUser.Mobile,
+		Email:       sysUser.Email,
+		TelAreaCode: sysUser.TelAreaCode,
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// ForgetCodeVerify
+// @Title 忘记密码-验证码校验
+// @Description 忘记密码-验证码校验
+// @Param	request	body ForgetCodeVerifyReq true "type json string"
+// @Success 200 Ret=200 获取成功
+// @router /forget/code_verify [post]
+func (this *UserLoginController) ForgetCodeVerify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	type ForgetCodeVerifyReq struct {
+		FindType   int    `description:"密码找回方式: 1-手机号; 2-邮箱"`
+		VerifyCode string `description:"验证码"`
+		UserName   string `description:"用户名"`
+		Mobile     string `description:"手机号"`
+		Email      string `description:"邮箱"`
+	}
+	var req ForgetCodeVerifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	req.UserName = strings.TrimSpace(req.UserName)
+	if req.UserName == "" {
+		br.Msg = "请输入账号"
+		return
+	}
+	if req.VerifyCode == "" {
+		br.Msg = "请输入验证码"
+		return
+	}
+
+	// 手机号找回
+	var verifyRes bool
+	if req.FindType == 1 {
+		req.Mobile = strings.TrimSpace(req.Mobile)
+		if req.Mobile == "" {
+			br.Msg = "请输入手机号"
+			return
+		}
+		if !utils.ValidateMobileFormatat(req.Mobile) {
+			br.Msg = "您的手机号输入有误, 请检查"
+			return
+		}
+		expiredTime := time.Now().Add(utils.VerifyCodeExpireMinute * time.Minute).Format(utils.FormatDateTime)
+		recordCond := ` AND source = ? AND mobile = ? AND code = ? AND expired_time <= ?`
+		recordPars := make([]interface{}, 0)
+		recordPars = append(recordPars, system.AdminVerifyCodeRecordSourceForget, req.Mobile, req.VerifyCode, expiredTime)
+		recordOb := new(system.AdminVerifyCodeRecord)
+		_, e := recordOb.GetItemByCondition(recordCond, recordPars)
+		if e != nil {
+			if e.Error() == utils.ErrNoRow() {
+				br.Msg = "验证码错误, 请重新输入"
+				return
+			}
+			br.Msg = "验证码错误, 请重新输入"
+			br.ErrMsg = "获取手机号登陆验证码失败, Err: " + e.Error()
+			return
+		}
+
+		verifyRes = true
+	}
+
+	// 邮箱找回
+	if req.FindType == 2 {
+		req.Email = strings.TrimSpace(req.Email)
+		if req.Email == "" {
+			br.Msg = "请输入邮箱"
+			return
+		}
+		if !utils.ValidateEmailFormatat(req.Email) {
+			br.Msg = "您的邮箱输入有误, 请检查"
+			return
+		}
+		expiredTime := time.Now().Add(utils.VerifyCodeExpireMinute * time.Minute).Format(utils.FormatDateTime)
+		recordCond := ` AND source = ? AND email = ? AND code = ? AND expired_time <= ?`
+		recordPars := make([]interface{}, 0)
+		recordPars = append(recordPars, system.AdminVerifyCodeRecordSourceForget, req.Email, req.VerifyCode, expiredTime)
+		recordOb := new(system.AdminVerifyCodeRecord)
+		_, e := recordOb.GetItemByCondition(recordCond, recordPars)
+		if e != nil {
+			if e.Error() == utils.ErrNoRow() {
+				br.Msg = "验证码错误, 请重新输入"
+				return
+			}
+			br.Msg = "验证码错误, 请重新输入"
+			br.ErrMsg = "获取手机号登陆验证码失败, Err: " + e.Error()
+			return
+		}
+
+		verifyRes = true
+	}
+
+	if verifyRes {
+		successKey := fmt.Sprint(utils.CACHE_FIND_PASS_VERIFY, req.UserName)
+		_ = utils.Rc.Put(successKey, "true", utils.GetTodayLastSecond())
+	}
+
+	br.Data = verifyRes
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// ForgetResetPass
+// @Title 忘记密码-重置密码
+// @Description 忘记密码-重置密码
+// @Param	request	body ForgetResetPassReq true "type json string"
+// @Success 200 Ret=200 获取成功
+// @router /forget/reset_pass [post]
+func (this *UserLoginController) ForgetResetPass() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	type ForgetResetPassReq struct {
+		UserName   string `description:"用户名"`
+		Password   string `description:"密码"`
+		RePassword string `description:"重复密码"`
+	}
+	var req ForgetResetPassReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	req.UserName = strings.TrimSpace(req.UserName)
+	if req.UserName == "" {
+		br.Msg = "请输入账号"
+		return
+	}
+	req.Password = strings.TrimSpace(req.Password)
+	if req.Password == "" {
+		br.Msg = "请输入新密码"
+		return
+	}
+	req.RePassword = strings.TrimSpace(req.RePassword)
+	if req.RePassword == "" {
+		br.Msg = "请确认新密码"
+		return
+	}
+	if req.Password != req.RePassword {
+		br.Msg = "两次密码输入不一致, 请检查"
+		return
+	}
+
+	// 接上一步-验证码校验成功后才允许修改
+	successKey := fmt.Sprint(utils.CACHE_FIND_PASS_VERIFY, req.UserName)
+	verifyOk, _ := utils.Rc.RedisString(successKey)
+	if verifyOk != "true" {
+		br.Msg = "验证码校验失效, 请重新验证"
+		br.ErrMsg = "重置密码异常, 验证码校验已失效"
+		return
+	}
+
+	sysUser, e := system.GetSysAdminByName(req.UserName)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "用户不存在, 请检查"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "密码找回获取用户失败, Err:" + e.Error()
+		return
+	}
+
+	b, e := base64.StdEncoding.DecodeString(req.Password)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "解析密码失败, Err:" + e.Error()
+		return
+	}
+	pwd := string(b)
+	pwd = utils.MD5(pwd)
+
+	sysUser.Password = pwd
+	sysUser.LastUpdatedPasswordTime = time.Now().Format(utils.FormatDateTime)
+	// 重置密码后更新一下登录时间, 不然账号密码登录如果超过60天还会被异常校验再校验一次, 影响体验
+	sysUser.LastLoginTime = time.Now().Format(utils.FormatDateTime)
+	sysUser.LastUpdatedTime = time.Now().Format(utils.FormatDateTime)
+	if e = sysUser.Update([]string{"Password", "LastUpdatedPasswordTime", "LastLoginTime", "LastUpdatedTime"}); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "更新密码失败, Err: " + e.Error()
+		return
+	}
+
+	// 如果有异常标记也清除掉
+	abnormalKey := fmt.Sprint(utils.CACHE_ABNORMAL_LOGIN, req.UserName)
+	_ = utils.Rc.Delete(abnormalKey)
+	_ = utils.Rc.Delete(successKey)
+
+	br.Data = true
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// AreaCodeList
+// @Title 手机号区号列表
+// @Description 手机号区号列表
+// @Success 200 Ret=200 获取成功
+// @router /area_code/list [get]
+func (this *UserLoginController) AreaCodeList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	type AreaCodeListResp struct {
+		Name  string `description:"地区"`
+		Value string `description:"区号"`
+	}
+	resp := make([]AreaCodeListResp, 0)
+	confAuth, e := company.GetConfigDetailByCode(company.ConfAreaCodeListKey)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取手机号区号配置失败, Err: " + e.Error()
+		return
+	}
+	if confAuth.ConfigValue == "" {
+		br.Msg = "获取失败"
+		br.ErrMsg = "手机号区号配置为空"
+		return
+	}
+	if e := json.Unmarshal([]byte(confAuth.ConfigValue), &resp); e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "手机号区号配置有误"
+		return
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}

+ 3 - 0
go.mod

@@ -16,6 +16,7 @@ require (
 	github.com/gonum/stat v0.0.0-20181125101827-41a0da705a5b
 	github.com/gorilla/websocket v1.4.2
 	github.com/kgiannakakis/mp3duration v0.0.0-20191013070830-d834f8d5ed53
+	github.com/mojocn/base64Captcha v1.3.5
 	github.com/nosixtools/solarlunar v0.0.0-20211112060703-1b6dea7b4a19
 	github.com/olivere/elastic/v7 v7.0.30
 	github.com/rdlucklib/rdluck_tools v1.0.3
@@ -46,6 +47,7 @@ require (
 	github.com/fatih/structs v1.1.0 // indirect
 	github.com/garyburd/redigo v1.6.3 // indirect
 	github.com/go-redis/redis/v8 v8.11.5 // indirect
+	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac // indirect
 	github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82 // indirect
@@ -82,6 +84,7 @@ require (
 	github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
 	github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
 	golang.org/x/crypto v0.8.0 // indirect
+	golang.org/x/image v0.5.0 // indirect
 	golang.org/x/net v0.9.0 // indirect
 	golang.org/x/sys v0.7.0 // indirect
 	golang.org/x/text v0.9.0 // indirect

+ 5 - 0
go.sum

@@ -178,6 +178,8 @@ github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -322,6 +324,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
+github.com/mojocn/base64Captcha v1.3.5 h1:Qeilr7Ta6eDtG4S+tQuZ5+hO+QHbiGAJdi4PfoagaA0=
+github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
@@ -513,6 +517,7 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
 golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=

+ 1 - 1
main.go

@@ -1,8 +1,8 @@
 package main
 
 import (
-	"fmt"
 	"eta/eta_mobile/services/alarm_msg"
+	"fmt"
 	"runtime"
 	"time"
 

+ 5 - 0
models/base.go

@@ -1,5 +1,10 @@
 package models
 
+const (
+	BaseRespCodeAbnormalLogin = 4011 // 异常登录状态码
+	BaseRespCodeLoginErr      = 4012 // 账号或密码输入错误
+)
+
 type BaseResponse struct {
 	Ret         int
 	Msg         string

+ 1 - 1
models/classify.go

@@ -1,10 +1,10 @@
 package models
 
 import (
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
-	"eta/eta_mobile/utils"
 	"time"
 )
 

+ 5 - 1
models/company/company_config.go

@@ -4,6 +4,10 @@ import (
 	"github.com/beego/beego/v2/client/orm"
 )
 
+const (
+	ConfAreaCodeListKey = "area_code_list" // 手机号区号列表
+)
+
 type CrmConfig struct {
 	ConfigValue string `description:"详情"`
 }
@@ -15,7 +19,7 @@ func GetConfigValueByCode(configCode string) (total int, err error) {
 	return
 }
 
-//修改
+// 修改
 func CrmConfigUpdate(newValue, configCode string) (err error) {
 	o := orm.NewOrm()
 	sql := `UPDATE crm_config SET  config_value=?   WHERE config_code=  ?`

+ 1 - 1
models/data_manage/chart_edb_mapping.go

@@ -1,9 +1,9 @@
 package data_manage
 
 import (
+	"eta/eta_mobile/utils"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
-	"eta/eta_mobile/utils"
 	"time"
 )
 

+ 2 - 2
models/data_manage/chart_info.go

@@ -2,10 +2,10 @@ package data_manage
 
 import (
 	"errors"
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
-	"eta/eta_mobile/utils"
 	"strconv"
 	"strings"
 	"time"
@@ -1757,4 +1757,4 @@ func GetChartInfoByAdminIdAndClassify(sourceList []int, adminId, classifyId int)
             FROM chart_info where source in (` + utils.GetOrmInReplace(num) + `)  AND sys_user_id = ? AND chart_classify_id = ? ORDER BY sort asc,create_time ASC `
 	_, err = o.Raw(sql, sourceList, adminId, classifyId).QueryRows(&items)
 	return
-}
+}

+ 1 - 1
models/data_manage/edb_data_base.go

@@ -1,9 +1,9 @@
 package data_manage
 
 import (
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
-	"eta/eta_mobile/utils"
 	"time"
 )
 

+ 2 - 2
models/data_manage/edb_data_calculate.go

@@ -2,10 +2,10 @@ package data_manage
 
 import (
 	"errors"
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/yidane/formula"
-	"eta/eta_mobile/utils"
 	"strconv"
 	"strings"
 	"time"
@@ -49,7 +49,7 @@ func GetEdbDataCalculateByCodeAndDate(edbCode string, startDate string) (count i
 	return
 }
 
-//刷新全部数据
+// 刷新全部数据
 func RefreshAllCalculate(edbInfoIdArr []*EdbInfo, edbInfoId, source int, edbCode, formulaStr, startDate, endDate string, edbInfoIdBytes []string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()

+ 4 - 4
models/data_manage/edb_data_quarter.go

@@ -2,9 +2,9 @@ package data_manage
 
 import (
 	"encoding/json"
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
-	"eta/eta_mobile/utils"
 	"sort"
 	"strconv"
 	"strings"
@@ -20,7 +20,7 @@ func GetEdbDataQuarterCount(edbInfoId int) (count int, err error) {
 	return
 }
 
-//指标季度数据计算(公历转农历)
+// 指标季度数据计算(公历转农历)
 func AddCalculateQuarterV2(edbInfoId, source int, edbCode string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
@@ -87,7 +87,7 @@ func AddCalculateQuarterV2(edbInfoId, source int, edbCode string) (err error) {
 	return
 }
 
-//指标季度数据计算(公历转农历)
+// 指标季度数据计算(公历转农历)
 func AddCalculateQuarterV3(edbInfoId, source int, edbCode string, list []*EdbDataList) (err error) {
 	var errMsg string
 	defer func() {
@@ -211,7 +211,7 @@ func AddCalculateQuarterV3(edbInfoId, source int, edbCode string, list []*EdbDat
 	return
 }
 
-//指标季度数据计算(公历转农历)
+// 指标季度数据计算(公历转农历)
 func AddCalculateQuarterV4(dataList []*EdbDataList) (result *EdbDataResult, err error) {
 	var errMsg string
 	defer func() {

+ 2 - 2
models/data_manage/edb_info.go

@@ -1,11 +1,11 @@
 package data_manage
 
 import (
+	"eta/eta_mobile/services/alarm_msg"
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
-	"eta/eta_mobile/services/alarm_msg"
-	"eta/eta_mobile/utils"
 	"time"
 )
 

+ 1 - 1
models/data_manage/edb_info_calculate.go

@@ -1,9 +1,9 @@
 package data_manage
 
 import (
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
-	"eta/eta_mobile/utils"
 	"strings"
 	"time"
 )

+ 5 - 5
models/data_manage/edb_info_calculate_tbz.go

@@ -2,10 +2,10 @@ package data_manage
 
 import (
 	"errors"
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/shopspring/decimal"
-	"eta/eta_mobile/utils"
 	"strconv"
 	"strings"
 	"time"
@@ -26,7 +26,7 @@ type EdbInfoCalculateTbz struct {
 	ModifyTime            time.Time `description:"修改时间"`
 }
 
-//同比值
+// 同比值
 func AddCalculateTbz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string) (edbInfoId int, err error) {
 	fmt.Println("AddCalculateTbz")
 	o := orm.NewOrmUsingDB("data")
@@ -279,7 +279,7 @@ func TbzDiv(a, b float64) string {
 	return valStr
 }
 
-//同比值
+// 同比值
 func EditCalculateTbz(req *EdbInfoCalculateBatchEditReq, fromEdbInfo *EdbInfo, edbCode string) (edbInfoId int, err error) {
 	edbInfoId = req.EdbInfoId
 	o := orm.NewOrmUsingDB("data")
@@ -522,7 +522,7 @@ func EditCalculateTbz(req *EdbInfoCalculateBatchEditReq, fromEdbInfo *EdbInfo, e
 	return
 }
 
-//刷新同比值数据
+// 刷新同比值数据
 func RefreshCalculateTbz(edbInfoId int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
@@ -786,7 +786,7 @@ func ModifyEdbDataCalculateTbz(edbInfoId int64, dataTime, value string) (err err
 	return
 }
 
-//刷新所有同比值数据
+// 刷新所有同比值数据
 func RefreshAllCalculateTbz(edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()

+ 1 - 3
models/data_manage/excel_info.go

@@ -1,9 +1,9 @@
 package data_manage
 
 import (
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
-	"eta/eta_mobile/utils"
 	"time"
 )
 
@@ -65,7 +65,6 @@ func EditExcelInfo(excelInfo *ExcelInfo, updateExcelInfoParams []string) (err er
 	return
 }
 
-
 // GetExcelInfoById 根据id 获取eta表格详情
 func GetExcelInfoById(excelInfoId int) (item *ExcelInfo, err error) {
 	o := orm.NewOrmUsingDB("data")
@@ -74,7 +73,6 @@ func GetExcelInfoById(excelInfoId int) (item *ExcelInfo, err error) {
 	return
 }
 
-
 func GetExcelInfoCountByCondition(condition string, pars []interface{}) (count int, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT COUNT(1) AS count FROM excel_info WHERE 1=1 AND is_delete=0 `

+ 2 - 2
models/data_manage/future_good/chart_info_future_good_profit.go

@@ -1,10 +1,10 @@
 package future_good
 
 import (
-	"fmt"
-	"github.com/beego/beego/v2/client/orm"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
 	"strconv"
 	"strings"
 	"time"

+ 1 - 1
models/data_manage/line_equation/line_equation.go

@@ -1,8 +1,8 @@
 package line_equation
 
 import (
-	"github.com/beego/beego/v2/client/orm"
 	"eta/eta_mobile/models/data_manage"
+	"github.com/beego/beego/v2/client/orm"
 )
 
 type BatchAddChart struct {

+ 2 - 2
models/data_manage/line_feature/line_feature.go

@@ -1,10 +1,10 @@
 package line_feature
 
 import (
-	"fmt"
-	"github.com/beego/beego/v2/client/orm"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
 	"strconv"
 	"strings"
 	"time"

+ 1 - 1
models/data_manage/predict_edb_conf.go

@@ -1,9 +1,9 @@
 package data_manage
 
 import (
-	"github.com/beego/beego/v2/client/orm"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/utils"
+	"github.com/beego/beego/v2/client/orm"
 	"time"
 )
 

+ 1 - 1
models/data_manage/predict_edb_conf_calculate_mapping.go

@@ -1,8 +1,8 @@
 package data_manage
 
 import (
-	"github.com/beego/beego/v2/client/orm"
 	"eta/eta_mobile/utils"
+	"github.com/beego/beego/v2/client/orm"
 	"time"
 )
 

+ 1 - 1
models/data_manage/response/excel_info.go

@@ -1,9 +1,9 @@
 package response
 
 import (
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/services/excel"
+	"github.com/rdlucklib/rdluck_tools/paging"
 )
 
 // AddExcelInfoResp 添加excel表格的返回

+ 3 - 2
models/db.go

@@ -1,12 +1,12 @@
 package models
 
 import (
-	_ "github.com/go-sql-driver/mysql"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/ppt_english"
 	"eta/eta_mobile/models/sandbox"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/utils"
+	_ "github.com/go-sql-driver/mysql"
 	"time"
 
 	"github.com/beego/beego/v2/client/orm"
@@ -88,7 +88,8 @@ func initSystem() {
 		new(system.SysUserLoginRecord),
 		new(system.SysSession),
 		new(system.Admin),
-		new(system.AdminConfig), //系统用户配置表
+		new(system.AdminConfig),           //系统用户配置表
+		new(system.AdminVerifyCodeRecord), // 用户短信邮箱验证码记录表
 	)
 }
 

+ 1 - 1
models/en_classify_permission.go

@@ -1,9 +1,9 @@
 package models
 
 import (
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
-	"eta/eta_mobile/utils"
 	"strings"
 	"time"
 )

+ 1 - 1
models/en_company_permission.go

@@ -1,9 +1,9 @@
 package models
 
 import (
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
-	"eta/eta_mobile/utils"
 	"strings"
 	"time"
 )

+ 1 - 1
models/english_policy_report.go

@@ -1,9 +1,9 @@
 package models
 
 import (
+	"eta/eta_mobile/utils"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
-	"eta/eta_mobile/utils"
 	"strings"
 	"time"
 )

+ 1 - 1
models/english_report.go

@@ -2,9 +2,9 @@ package models
 
 import (
 	"errors"
+	"eta/eta_mobile/utils"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
-	"eta/eta_mobile/utils"
 	"strings"
 	"time"
 )

+ 2 - 2
models/english_report_email_log.go

@@ -1,9 +1,9 @@
 package models
 
 import (
+	"eta/eta_mobile/utils"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
-	"eta/eta_mobile/utils"
 	"time"
 )
 
@@ -157,4 +157,4 @@ func GetSuccessEmailLogReportIds() (reportIds []int, err error) {
 	sql := `SELECT DISTINCT report_id FROM english_report_email_log WHERE is_deleted = 0 AND (send_status != 0 AND send_status != -1)`
 	_, err = o.Raw(sql).QueryRows(&reportIds)
 	return
-}
+}

+ 19 - 22
models/english_video.go

@@ -1,9 +1,9 @@
 package models
 
 import (
+	"eta/eta_mobile/utils"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
-	"eta/eta_mobile/utils"
 	"strings"
 	"time"
 )
@@ -47,30 +47,28 @@ func ModifyEnglishVideoCode(id int, VideoCode string) (err error) {
 }
 
 type SaveEnglishVideoReq struct {
-	Id                 int    `description:"路演视频ID"`
-	ClassifyIdFirst    int    `description:"一级分类id"`
+	Id              int `description:"路演视频ID"`
+	ClassifyIdFirst int `description:"一级分类id"`
 	//ClassifyNameFirst  string `description:"一级分类名称"`
-	ClassifyIdSecond   int    `description:"二级分类id"`
+	ClassifyIdSecond int `description:"二级分类id"`
 	//ClassifyNameSecond string `description:"二级分类名称"`
-	Title              string `description:"标题"`
-	Abstract           string `description:"摘要"`
-	Author             string `description:"作者"`
-	State              int    `description:"状态:1:未发布,2:已发布"`
-	VideoUrl           string `description:"视频文件URL"`
-	VideoCoverUrl      string `description:"视频文件封面地址"`
-	VideoSeconds       string `description:"视频时长"`
-	Overview           string `description:"英文概述部分"`
+	Title         string `description:"标题"`
+	Abstract      string `description:"摘要"`
+	Author        string `description:"作者"`
+	State         int    `description:"状态:1:未发布,2:已发布"`
+	VideoUrl      string `description:"视频文件URL"`
+	VideoCoverUrl string `description:"视频文件封面地址"`
+	VideoSeconds  string `description:"视频时长"`
+	Overview      string `description:"英文概述部分"`
 }
 
 type SaveEnglishVideoResp struct {
-	Id   int  `description:"路演视频ID"`
+	Id        int    `description:"路演视频ID"`
 	VideoCode string `description:"报告code"`
 }
 
-
-
 type ElasticEnglishVideoDetail struct {
-	Id            int    `description:"路演视频ID"`
+	Id                 int    `description:"路演视频ID"`
 	ClassifyIdFirst    int    `description:"一级分类id"`
 	ClassifyNameFirst  string `description:"一级分类名称"`
 	ClassifyIdSecond   int    `description:"二级分类id"`
@@ -85,7 +83,7 @@ type ElasticEnglishVideoDetail struct {
 	ContentSub         string `description:"前两段内容"`
 	CreateTime         string `description:"创建时间"`
 	PublishTime        string `description:"发布时间"`
-	VideoCode         string `description:"报告唯一编码"`
+	VideoCode          string `description:"报告唯一编码"`
 	Overview           string `description:"英文概述部分"`
 }
 
@@ -180,7 +178,7 @@ type EnglishVideoListResp struct {
 }
 
 type EnglishVideoReq struct {
-	Id  int `description:"路演视频id"`
+	Id int `description:"路演视频id"`
 }
 
 func GetEnglishVideoListCount(condition string, pars []interface{}) (count int, err error) {
@@ -226,7 +224,7 @@ func PublishEnglishVideoById(Id int) (err error) {
 	return
 }
 
-//取消发布报告
+// 取消发布报告
 func PublishCancelEnglishVideo(Ids int) (err error) {
 	o := orm.NewOrmUsingDB("rddp")
 	sql := ` UPDATE english_video SET state=1,publish_time=null WHERE id =?  `
@@ -242,7 +240,6 @@ func DeleteEnglishVideo(Id int) (err error) {
 	return
 }
 
-
 func GetEnglishVideoDetailByClassifyId(classifyIdFirst, classifyIdSecond int) (item *EnglishVideo, err error) {
 	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT * FROM english_video WHERE 1=1 `
@@ -292,9 +289,9 @@ func UpdateEnglishVideoFirstClassifyNameByClassifyId(classifyId int, classifyNam
 }
 
 // UpdateEnglishVideoFirstClassifyNameByClassifyId 更新报告分类名称字段
-func UpdateEnglishVideoByClassifyId(classifyFirstName, classifySecondName  string, firstClassifyId, secondClassifyId int, ids string) (err error) {
+func UpdateEnglishVideoByClassifyId(classifyFirstName, classifySecondName string, firstClassifyId, secondClassifyId int, ids string) (err error) {
 	o := orm.NewOrmUsingDB("rddp")
-	sql := " UPDATE english_video SET classify_name_first = ?,classify_name_second = ?,classify_id_first=?, classify_id_second =?  WHERE id IN ("+ids+") "
+	sql := " UPDATE english_video SET classify_name_first = ?,classify_name_second = ?,classify_id_first=?, classify_id_second =?  WHERE id IN (" + ids + ") "
 	_, err = o.Raw(sql, classifyFirstName, classifySecondName, firstClassifyId, secondClassifyId).Exec()
 	return
 }

+ 1 - 1
models/report_chapter_type.go

@@ -1,9 +1,9 @@
 package models
 
 import (
+	"eta/eta_mobile/utils"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
-	"eta/eta_mobile/utils"
 	"time"
 )
 

+ 1 - 1
models/report_chapter_type_permission.go

@@ -1,8 +1,8 @@
 package models
 
 import (
-	"github.com/beego/beego/v2/client/orm"
 	"eta/eta_mobile/utils"
+	"github.com/beego/beego/v2/client/orm"
 	"time"
 )
 

+ 1 - 1
models/research_report.go

@@ -1,9 +1,9 @@
 package models
 
 import (
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
-	"eta/eta_mobile/utils"
 	"strconv"
 	"time"
 )

+ 1 - 1
models/sandbox/response/sandbox.go

@@ -1,8 +1,8 @@
 package response
 
 import (
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_mobile/models/sandbox"
+	"github.com/rdlucklib/rdluck_tools/paging"
 )
 
 // SandboxListResp 沙盘列表返回数据

+ 126 - 0
models/system/admin_verify_code_record.go

@@ -0,0 +1,126 @@
+package system
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+const (
+	AdminVerifyCodeRecordTypeMobile = 1 // 验证方式-手机号
+	AdminVerifyCodeRecordTypeEmail  = 2 // 验证方式-邮箱
+
+	AdminVerifyCodeRecordSourceLogin    = 1 // 验证码来源-登录
+	AdminVerifyCodeRecordSourceAbnormal = 2 // 验证码来源-异常登录校验
+	AdminVerifyCodeRecordSourceForget   = 3 // 验证码来源-忘记密码
+
+	AdminVerifyCodeRecordStatusSuccess = 1 // 验证码发送状态-已发送
+	AdminVerifyCodeRecordStatusFail    = 2 // 验证码发送状态-发送失败
+)
+
+// AdminVerifyCodeRecord 短信邮箱验证码记录表
+type AdminVerifyCodeRecord struct {
+	Id          int       `orm:"column(id);pk"`
+	VerifyType  int       `description:"验证方式:1-手机号;2-邮箱"`
+	Source      int       `description:"来源:1-登录;2-异常登录校验;3-忘记密码"`
+	Mobile      string    `description:"手机号"`
+	Email       string    `description:"邮箱"`
+	Code        string    `description:"验证码"`
+	ExpiredTime time.Time `description:"验证码过期时间"`
+	SendResult  string    `description:"发送结果"`
+	SendStatus  int       `description:"发送状态:0-待发送;1-已发送;2-发送失败"`
+	CreateTime  time.Time `description:"创建时间"`
+	ModifyTime  time.Time `description:"更新时间"`
+}
+
+func (m *AdminVerifyCodeRecord) TableName() string {
+	return "admin_verify_code_record"
+}
+
+func (m *AdminVerifyCodeRecord) PrimaryId() string {
+	return "id"
+}
+
+func (m *AdminVerifyCodeRecord) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.Id = int(id)
+	return
+}
+
+func (m *AdminVerifyCodeRecord) CreateMulti(items []*AdminVerifyCodeRecord) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *AdminVerifyCodeRecord) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *AdminVerifyCodeRecord) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.Id).Exec()
+	return
+}
+
+func (m *AdminVerifyCodeRecord) GetItemById(id int) (item *AdminVerifyCodeRecord, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *AdminVerifyCodeRecord) GetItemByCondition(condition string, pars []interface{}) (item *AdminVerifyCodeRecord, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s LIMIT 1`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *AdminVerifyCodeRecord) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *AdminVerifyCodeRecord) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*AdminVerifyCodeRecord, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *AdminVerifyCodeRecord) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*AdminVerifyCodeRecord, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}

+ 1 - 1
models/system/sys_role_admin.go

@@ -1,8 +1,8 @@
 package system
 
 import (
-	"github.com/beego/beego/v2/client/orm"
 	"eta/eta_mobile/utils"
+	"github.com/beego/beego/v2/client/orm"
 	"time"
 )
 

+ 53 - 7
models/system/sys_user.go

@@ -1,8 +1,8 @@
 package system
 
 import (
-	"github.com/beego/beego/v2/client/orm"
 	"eta/eta_mobile/utils"
+	"github.com/beego/beego/v2/client/orm"
 	"time"
 )
 
@@ -61,6 +61,7 @@ type Admin struct {
 	City                      string    `description:"市"`
 	CityCode                  string    `description:"市编码"`
 	EmployeeId                string    `description:"员工工号(钉钉/每刻报销)"`
+	TelAreaCode               string    `description:"手机区号"`
 }
 
 // Update 更新用户基础信息
@@ -129,12 +130,12 @@ func GetAdminList() (items []*Admin, err error) {
 }
 
 // GetSysUserByMobile 根据手机号获取管理信息
-func GetSysUserByMobile(mobile string) (item *Admin, err error) {
-	sql := `SELECT * FROM admin WHERE mobile = ? LIMIT 1`
-	o := orm.NewOrm()
-	err = o.Raw(sql, mobile).QueryRow(&item)
-	return
-}
+//func GetSysUserByMobile(mobile string) (item *Admin, err error) {
+//	sql := `SELECT * FROM admin WHERE mobile = ? LIMIT 1`
+//	o := orm.NewOrm()
+//	err = o.Raw(sql, mobile).QueryRow(&item)
+//	return
+//}
 
 // 通过用户姓名跟身份获取管理员信息
 func CheckSysUserByName(userName, roleTypeCode string) (item *Admin, err error) {
@@ -202,3 +203,48 @@ func GetAdminListByIdListWithoutEnable(idList []int) (items []*Admin, err error)
 	_, err = o.Raw(sql, idList).QueryRows(&items)
 	return
 }
+
+// GetSysUserByMobile 手机号获取用户
+func GetSysUserByMobile(mobile string) (item *Admin, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+				a.*, b.role_type_code
+			FROM
+				admin AS a
+			INNER JOIN sys_role AS b ON a.role_id = b.role_id
+			WHERE
+				a.mobile = ?
+			LIMIT 1`
+	err = o.Raw(sql, mobile).QueryRow(&item)
+	return
+}
+
+// GetSysUserByEmail 邮箱获取用户
+func GetSysUserByEmail(email string) (item *Admin, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+				a.*, b.role_type_code
+			FROM
+				admin AS a
+			INNER JOIN sys_role AS b ON a.role_id = b.role_id
+			WHERE
+				a.email = ?
+			LIMIT 1`
+	err = o.Raw(sql, email).QueryRow(&item)
+	return
+}
+
+// GetSysUserByAdminName 账号获取用户
+func GetSysUserByAdminName(adminName string) (item *Admin, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+				a.*, b.role_type_code
+			FROM
+				admin AS a
+			INNER JOIN sys_role AS b ON a.role_id = b.role_id
+			WHERE
+				a.admin_name = ?
+			LIMIT 1`
+	err = o.Raw(sql, adminName).QueryRow(&item)
+	return
+}

+ 6 - 6
models/user_view_history.go

@@ -1,8 +1,8 @@
 package models
 
 import (
-	"github.com/beego/beego/v2/client/orm"
 	"eta/eta_mobile/utils"
+	"github.com/beego/beego/v2/client/orm"
 	"time"
 )
 
@@ -22,7 +22,7 @@ type UserViewHistory struct {
 	ResearchReportTypeId int       `description:"报告章节id,为0时表示查看目录或者首页"`
 }
 
-//根据用户id字符串获取用户的浏览数
+// 根据用户id字符串获取用户的浏览数
 type UserViewTotalSlice struct {
 	UserId      int       `description:"用户id"`
 	Total       int       `description:"总阅读数"`
@@ -37,7 +37,7 @@ func GetCountUserViewHistoryByUserIds(userIds string) (items []*UserViewTotalSli
 	//return items2,err
 }
 
-//根据用户手机号字符串获取用户的浏览数
+// 根据用户手机号字符串获取用户的浏览数
 type UserViewMobileTotalSlice struct {
 	Mobile      string    `description:"用户手机号"`
 	Total       int       `description:"总阅读数"`
@@ -51,7 +51,7 @@ func GetCountUserViewHistoryByMobiles(mobiles string) (items []*UserViewMobileTo
 	return
 }
 
-//根据用户id字符串获取用户的浏览数
+// 根据用户id字符串获取用户的浏览数
 type UserViewEmailTotalSlice struct {
 	Email       string    `description:"用户邮箱"`
 	Total       int       `description:"总阅读数"`
@@ -446,9 +446,9 @@ func GetPUVByResearchReportIds(reportIds string) (list []*ResearchReportViewPUV,
 			FROM
 				user_view_history
 			WHERE
-				research_report_id IN (` + reportIds +`)
+				research_report_id IN (` + reportIds + `)
 			GROUP BY
 				research_report_id`
 	_, err = o.Raw(sql).QueryRows(&list)
 	return
-}
+}

+ 1 - 1
models/wechat_send_msg.go

@@ -1,8 +1,8 @@
 package models
 
 import (
-	"github.com/beego/beego/v2/client/orm"
 	"eta/eta_mobile/utils"
+	"github.com/beego/beego/v2/client/orm"
 	"strings"
 )
 

+ 63 - 0
routers/commentsRouter.go

@@ -1708,4 +1708,67 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"],
+        beego.ControllerComments{
+            Method: "AreaCodeList",
+            Router: `/area_code/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"],
+        beego.ControllerComments{
+            Method: "ForgetAccountGet",
+            Router: `/forget/account_get`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"],
+        beego.ControllerComments{
+            Method: "ForgetCodeVerify",
+            Router: `/forget/code_verify`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"],
+        beego.ControllerComments{
+            Method: "ForgetResetPass",
+            Router: `/forget/reset_pass`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"],
+        beego.ControllerComments{
+            Method: "GenerateCaptcha",
+            Router: `/get_captcha`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"],
+        beego.ControllerComments{
+            Method: "Login",
+            Router: `/login`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers:UserLoginController"],
+        beego.ControllerComments{
+            Method: "GetVerifyCode",
+            Router: `/verify_code`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
 }

+ 6 - 0
routers/router.go

@@ -146,6 +146,12 @@ func init() {
 				&english_report.EnPermissionController{},
 			),
 		),
+		web.NSNamespace("/user_login",
+			web.NSInclude(
+				&controllers.UserLoginController{},
+				&controllers.UserLoginAuthController{},
+			),
+		),
 	)
 	web.AddNamespace(ns)
 }

+ 1 - 1
services/alarm_msg/alarm_msg.go

@@ -2,8 +2,8 @@ package alarm_msg
 
 import (
 	"encoding/json"
-	"github.com/rdlucklib/rdluck_tools/http"
 	"eta/eta_mobile/utils"
+	"github.com/rdlucklib/rdluck_tools/http"
 )
 
 type WechatWarningReq struct {

+ 1 - 1
services/aliyun_email.go

@@ -2,11 +2,11 @@ package services
 
 import (
 	"encoding/json"
+	"eta/eta_mobile/utils"
 	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
 	dm "github.com/alibabacloud-go/dm-20151123/v2/client"
 	util "github.com/alibabacloud-go/tea-utils/v2/service"
 	"github.com/alibabacloud-go/tea/tea"
-	"eta/eta_mobile/utils"
 	"time"
 )
 

+ 48 - 0
services/captcha_redis.go

@@ -0,0 +1,48 @@
+package services
+
+import (
+	"eta/eta_mobile/utils"
+	"fmt"
+	"time"
+)
+
+// CaptchaRedis Redis验证器
+type CaptchaRedis struct{}
+
+// Set 实现验证器set方法
+func (r CaptchaRedis) Set(id string, value string) (err error) {
+	if utils.Rc == nil {
+		err = fmt.Errorf("redis config err")
+		return
+	}
+	key := utils.CaptchaCachePrefix + id
+	b := utils.Rc.SetNX(key, value, time.Minute*5)
+	if !b {
+		err = fmt.Errorf("redis setnx err")
+	}
+	return
+}
+
+// Get 实现原验证器get方法
+func (r CaptchaRedis) Get(id string, clear bool) (code string) {
+	if utils.Rc == nil {
+		return
+	}
+	key := utils.CaptchaCachePrefix + id
+	val, err := utils.Rc.RedisString(key)
+	if err != nil {
+		return
+	}
+	code = val
+	// clear为true时验证通过删除验证码
+	if clear {
+		_ = utils.Rc.Delete(key)
+	}
+	return
+}
+
+// Verify 实现原验证器verify方法
+func (r CaptchaRedis) Verify(id, answer string, clear bool) bool {
+	v := r.Get(id, clear)
+	return v == answer
+}

+ 1 - 2
services/company.go

@@ -4,7 +4,6 @@ import (
 	"eta/eta_mobile/utils"
 )
 
-
 func GetProductId(roleTypeCode string) (productId int) {
 	if roleTypeCode == utils.ROLE_TYPE_CODE_FICC_SELLER ||
 		roleTypeCode == utils.ROLE_TYPE_CODE_FICC_ADMIN ||
@@ -21,4 +20,4 @@ func GetProductId(roleTypeCode string) (productId int) {
 		productId = 0
 	}
 	return
-}
+}

+ 1 - 1
services/data/base_edb_lib.go

@@ -2,9 +2,9 @@ package data
 
 import (
 	"encoding/json"
-	"fmt"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"io/ioutil"
 	"net/http"
 	"strings"

+ 2 - 2
services/data/chart_info.go

@@ -3,13 +3,13 @@ package data
 import (
 	"encoding/json"
 	"errors"
-	"fmt"
-	"github.com/shopspring/decimal"
 	"eta/eta_mobile/models/company"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/shopspring/decimal"
 	"math"
 	"sort"
 	"strconv"

+ 1 - 1
services/data/chart_info_elastic.go

@@ -1,10 +1,10 @@
 package data
 
 import (
-	"fmt"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/services/elastic"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"strconv"
 	"strings"
 )

+ 2 - 2
services/data/correlation/chart_info.go

@@ -3,13 +3,13 @@ package correlation
 import (
 	"encoding/json"
 	"errors"
-	"fmt"
-	"github.com/shopspring/decimal"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/shopspring/decimal"
 	"math"
 	"sort"
 	"strconv"

+ 1 - 1
services/data/edb_info.go

@@ -3,11 +3,11 @@ package data
 import (
 	"encoding/json"
 	"errors"
-	"fmt"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/services/elastic"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"sort"
 	"strconv"
 	"strings"

+ 1 - 1
services/data/future_good/base_future_good_lib.go

@@ -2,10 +2,10 @@ package future_good
 
 import (
 	"encoding/json"
-	"fmt"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"io/ioutil"
 	"net/http"
 	"strings"

+ 2 - 2
services/data/future_good/chart_info.go

@@ -2,13 +2,13 @@ package future_good
 
 import (
 	"errors"
-	"fmt"
-	"github.com/shopspring/decimal"
 	"eta/eta_mobile/models/data_manage"
 	future_good2 "eta/eta_mobile/models/data_manage/future_good"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/shopspring/decimal"
 	"sort"
 	"strconv"
 	"time"

+ 1 - 1
services/data/future_good/future_edb_info.go

@@ -1,10 +1,10 @@
 package future_good
 
 import (
-	"fmt"
 	"eta/eta_mobile/models/data_manage/future_good"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"time"
 )
 

+ 2 - 2
services/data/line_equation/chart_info.go

@@ -3,14 +3,14 @@ package line_equation
 import (
 	"encoding/json"
 	"errors"
-	"fmt"
-	"github.com/shopspring/decimal"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/data_manage/line_equation"
 	"eta/eta_mobile/models/data_manage/line_equation/request"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/shopspring/decimal"
 	"math"
 	"sort"
 	"strconv"

+ 1 - 1
services/data/line_feature/chart_info.go

@@ -2,13 +2,13 @@ package line_feature
 
 import (
 	"errors"
-	"github.com/shopspring/decimal"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/data_manage/line_feature"
 	"eta/eta_mobile/models/data_manage/line_feature/response"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
+	"github.com/shopspring/decimal"
 	"strconv"
 	"strings"
 	"time"

+ 2 - 2
services/data/predict_edb_info.go

@@ -3,10 +3,10 @@ package data
 import (
 	"encoding/json"
 	"errors"
-	"fmt"
-	"github.com/shopspring/decimal"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/shopspring/decimal"
 	"strconv"
 	"time"
 )

+ 2 - 2
services/data/predict_edb_info_rule.go

@@ -3,11 +3,11 @@ package data
 import (
 	"encoding/json"
 	"errors"
+	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/nosixtools/solarlunar"
 	"github.com/shopspring/decimal"
-	"eta/eta_mobile/models/data_manage"
-	"eta/eta_mobile/utils"
 	"math"
 	"strings"
 	"time"

+ 1 - 1
services/elastic.go

@@ -2,10 +2,10 @@ package services
 
 import (
 	"context"
-	"fmt"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"strings"
 )
 

+ 2 - 2
services/elastic/elastic.go

@@ -4,10 +4,10 @@ import (
 	"context"
 	"encoding/json"
 	"errors"
-	"fmt"
-	"github.com/olivere/elastic/v7"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/olivere/elastic/v7"
 	"strconv"
 )
 

+ 1 - 1
services/english_report.go

@@ -3,11 +3,11 @@ package services
 import (
 	"encoding/json"
 	"errors"
-	"fmt"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"html"
 	"strconv"
 	"strings"

+ 1 - 1
services/excel/lucky_sheet.go

@@ -3,10 +3,10 @@ package excel
 import (
 	"encoding/json"
 	"errors"
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/tealeg/xlsx"
 	"github.com/xuri/excelize/v2"
-	"eta/eta_mobile/utils"
 	"os"
 	"reflect"
 	"strconv"

+ 2 - 2
services/oss.go

@@ -3,13 +3,13 @@ package services
 import (
 	"encoding/json"
 	"errors"
-	"github.com/aliyun/aliyun-oss-go-sdk/oss"
 	"eta/eta_mobile/services/alarm_msg"
+	"github.com/aliyun/aliyun-oss-go-sdk/oss"
 	"os"
 	"time"
 
-	"github.com/aliyun/alibaba-cloud-sdk-go/services/sts"
 	"eta/eta_mobile/utils"
+	"github.com/aliyun/alibaba-cloud-sdk-go/services/sts"
 )
 
 /*

+ 1 - 1
services/ppt.go

@@ -3,11 +3,11 @@ package services
 import (
 	"encoding/json"
 	"errors"
-	"fmt"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/ppt_english"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"sort"
 )
 

+ 5 - 8
services/ppt/ppt_english_group.go

@@ -3,10 +3,10 @@ package ppt
 import (
 	"encoding/json"
 	"errors"
-	"fmt"
 	"eta/eta_mobile/models/ppt_english"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"sort"
 	"strconv"
 	"strings"
@@ -781,7 +781,7 @@ func CopyPptEnglish(pptId int, groupId int64, adminId int, adminRealName string)
 		AdminId:       newPpt.AdminId,
 		AdminRealName: newPpt.AdminRealName,
 		PptCreateTime: newPpt.CreateTime.Format(utils.FormatDateTime),
-		PptPage: pptPage,
+		PptPage:       pptPage,
 	}
 	return
 }
@@ -1366,8 +1366,6 @@ func GetEnglishCopyUsableTitle(title string) (newTitle string, err error) {
 	return
 }
 
-
-
 // GetEnglishPptList 公共ppt和我的ppt
 // @Author xi
 // @Time 2022-08-29 16:27:59
@@ -1411,15 +1409,14 @@ func GetEnglishPptList(adminId int, keyword string) (ret ppt_english.RespGroupPp
 	if keyword != `` {
 		for _, v := range list {
 			if strings.Contains(v.Title, keyword) {
-				index := strings.Index(v.Title,keyword)
-				newTitle := v.Title[:index] + "<span class=\"color-light\">"+ keyword +"</span>"+ v.Title[index+len(keyword):]
+				index := strings.Index(v.Title, keyword)
+				newTitle := v.Title[:index] + "<span class=\"color-light\">" + keyword + "</span>" + v.Title[index+len(keyword):]
 				v.Title = newTitle
 			}
 		}
 	}
 
-
 	ret.List = list
 	ret.Total = len(list)
 	return
-}
+}

+ 4 - 5
services/ppt/ppt_group.go

@@ -3,10 +3,10 @@ package ppt
 import (
 	"encoding/json"
 	"errors"
-	"fmt"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"sort"
 	"strconv"
 	"strings"
@@ -1731,15 +1731,14 @@ func GetPptList(adminId int, keyword string) (ret models.RespGroupPptList, err e
 	if keyword != `` {
 		for _, v := range list {
 			if strings.Contains(v.Title, keyword) {
-				index := strings.Index(v.Title,keyword)
-				newTitle := v.Title[:index] + "<span class=\"color-light\">"+ keyword +"</span>"+ v.Title[index+len(keyword):]
+				index := strings.Index(v.Title, keyword)
+				newTitle := v.Title[:index] + "<span class=\"color-light\">" + keyword + "</span>" + v.Title[index+len(keyword):]
 				v.Title = newTitle
 			}
 		}
 	}
 
-
 	ret.List = list
 	ret.Total = len(list)
 	return
-}
+}

+ 4 - 0
services/ppt2img/ppt2img.go

@@ -3,9 +3,13 @@ package ppt2img
 import (
 	"encoding/json"
 	"errors"
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/http"
+<<<<<<< HEAD
 	"eta/eta_mobile/utils"
+=======
+>>>>>>> eta/1.4
 )
 
 type Ppt2ImgResponse struct {

+ 2 - 2
services/report.go

@@ -3,13 +3,13 @@ package services
 import (
 	"encoding/json"
 	"errors"
-	"fmt"
-	"github.com/PuerkitoBio/goquery"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/company"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/PuerkitoBio/goquery"
 	"html"
 	"os"
 	"regexp"

+ 148 - 0
services/sms.go

@@ -0,0 +1,148 @@
+package services
+
+import (
+	"encoding/json"
+	"eta/eta_mobile/services/alarm_msg"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+)
+
+// SendSmsCode 发送国内短信
+func SendSmsCode(mobile, vCode, tplId string) (flag bool) {
+	if mobile == "" || vCode == "" || tplId == "" {
+		return
+	}
+
+	var (
+		err error
+		res string
+	)
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("短信验证码发送失败, Err: %s; Result: %s", err.Error(), res)
+			utils.FileLog.Info("%s", tips)
+			go alarm_msg.SendAlarmMsg(tips, 2)
+		}
+	}()
+
+	result, e := sendSms(mobile, tplId, vCode)
+	if e != nil {
+		err = fmt.Errorf("send sms err: %s", e.Error())
+		return
+	}
+	res = string(result)
+
+	var netReturn map[string]interface{}
+	if e = json.Unmarshal(result, &netReturn); e != nil {
+		err = fmt.Errorf("json unmarshal err: %s", e.Error())
+		return
+	}
+	errCode, ok := netReturn["error_code"].(float64)
+	if !ok {
+		err = fmt.Errorf("result code err")
+		return
+	}
+	// 忽略错误的手机号码这种错误
+	if errCode != 0 && errCode != 205401 {
+		err = fmt.Errorf("err code %f", errCode)
+		return
+	}
+	// 发送成功
+	if errCode == 0 {
+		flag = true
+	}
+	return
+}
+
+// sendSms 发送国内短信
+func sendSms(mobile, tplId, code string) (rs []byte, err error) {
+	var Url *url.URL
+	apiURL := "http://v.juhe.cn/sms/send"
+	//初始化参数
+	param := url.Values{}
+	//配置请求参数,方法内部已处理urlencode问题,中文参数可以直接传参
+	param.Set("mobile", mobile) //接受短信的用户手机号码
+	param.Set("tpl_id", tplId)  //您申请的短信模板ID,根据实际情况修改
+	tplVal := fmt.Sprintf(`#code#=%s&#m#=%d`, code, utils.VerifyCodeExpireMinute)
+	param.Set("tpl_value", tplVal)     //您设置的模板变量,根据实际情况
+	param.Set("key", utils.JhGnAppKey) //应用APPKEY(应用详细页查询)
+
+	Url, err = url.Parse(apiURL)
+	if err != nil {
+		fmt.Printf("解析url错误:\r\n%v", err)
+		return nil, err
+	}
+	//如果参数中有中文参数,这个方法会进行URLEncode
+	Url.RawQuery = param.Encode()
+	resp, err := http.Get(Url.String())
+	if err != nil {
+		fmt.Println("err:", err)
+		return nil, err
+	}
+	defer resp.Body.Close()
+	return ioutil.ReadAll(resp.Body)
+}
+
+// SendSmsCodeGj 发送国际短信
+func SendSmsCodeGj(mobile, vCode, areaNum string) bool {
+	flag := false
+	result, err := sendSmsGj(mobile, vCode, areaNum)
+	if err != nil {
+		fmt.Println("发送短信失败")
+		return false
+	}
+	fmt.Println("result", string(result))
+	var netReturn map[string]interface{}
+	err = json.Unmarshal(result, &netReturn)
+	if err != nil {
+		//go SendEmail("短信验证码发送失败", "err:"+err.Error()+" result"+string(result), utils.EmailSendToUsers)
+		go alarm_msg.SendAlarmMsg("短信验证码发送失败, Err:"+err.Error()+";Result:"+string(result), 2)
+		flag = false
+	}
+	if netReturn["error_code"].(float64) == 0 {
+		fmt.Printf("接口返回result字段是:\r\n%v", netReturn["result"])
+		flag = true
+	} else {
+		// 忽略错误的手机号码这种错误
+		if netReturn["error_code"].(float64) != 205401 {
+			go alarm_msg.SendAlarmMsg("短信验证码发送失败, Result:"+string(result), 2)
+		}
+		flag = false
+	}
+	return flag
+}
+
+// sendSmsGj 发送国际短信
+func sendSmsGj(mobile, code, areaNum string) (rs []byte, err error) {
+	var Url *url.URL
+	apiURL := "http://v.juhe.cn/smsInternational/send.php"
+	//初始化参数
+	param := url.Values{}
+	//配置请求参数,方法内部已处理urlencode问题,中文参数可以直接传参
+	param.Set("mobile", mobile)           //接受短信的用户手机号码
+	param.Set("tplId", "10054")           //您申请的短信模板ID,根据实际情况修改
+	param.Set("tplValue", "#code#="+code) //您设置的模板变量,根据实际情况
+	param.Set("key", utils.JhGjAppKey)    //应用APPKEY(应用详细页查询)
+	param.Set("areaNum", areaNum)         //应用APPKEY(应用详细页查询)
+
+	Url, err = url.Parse(apiURL)
+	if err != nil {
+		fmt.Printf("解析url错误:\r\n%v", err)
+		return nil, err
+	}
+	//如果参数中有中文参数,这个方法会进行URLEncode
+	Url.RawQuery = param.Encode()
+	resp, err := http.Get(Url.String())
+	if err != nil {
+		fmt.Println("err:", err)
+		return nil, err
+	}
+	utils.FileLog.Info("sendSmsGj:param:" + Url.String())
+	defer resp.Body.Close()
+	body, err := ioutil.ReadAll(resp.Body)
+	utils.FileLog.Info("sendSmsGj:result:" + string(body))
+	return body, err
+}

+ 1 - 1
services/tencent_yun.go

@@ -2,11 +2,11 @@ package services
 
 import (
 	"encoding/json"
+	"eta/eta_mobile/utils"
 	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
 	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
 	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
 	ses "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ses/v20201002"
-	"eta/eta_mobile/utils"
 	"time"
 )
 

+ 123 - 0
services/user_login.go

@@ -0,0 +1,123 @@
+package services
+
+import (
+	"encoding/json"
+	"eta/eta_mobile/models"
+	"eta/eta_mobile/models/company"
+	"eta/eta_mobile/models/system"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// SendAdminMobileVerifyCode 发送用户手机验证码
+func SendAdminMobileVerifyCode(source int, mobile, areaCode string) (ok bool, err error) {
+	verifyCode := utils.GetRandDigit(6)
+	record := new(system.AdminVerifyCodeRecord)
+	record.VerifyType = system.AdminVerifyCodeRecordTypeMobile
+	record.Mobile = mobile
+	record.Source = source
+	record.Code = verifyCode
+	record.ExpiredTime = time.Now().Add(utils.VerifyCodeExpireMinute * time.Minute)
+	record.CreateTime = time.Now().Local()
+	record.ModifyTime = time.Now().Local()
+	if e := record.Create(); e != nil {
+		err = fmt.Errorf("新增验证码记录失败, Err: %s", e.Error())
+		return
+	}
+
+	tplId := utils.SmsNewLoginTplId
+	if areaCode == "86" {
+		ok = SendSmsCode(mobile, verifyCode, tplId)
+	} else {
+		ok = SendSmsCodeGj(mobile, verifyCode, areaCode)
+	}
+	record.SendStatus = system.AdminVerifyCodeRecordStatusSuccess
+	if !ok {
+		record.SendStatus = system.AdminVerifyCodeRecordStatusFail
+	}
+	cols := []string{"SendStatus"}
+	if e := record.Update(cols); e != nil {
+		err = fmt.Errorf("更新验证码记录失败, Err: %s", e.Error())
+	}
+	return
+}
+
+// SendAdminEmailVerifyCode 发送用户邮箱验证码
+func SendAdminEmailVerifyCode(source int, email string) (ok bool, err error) {
+	verifyCode := utils.GetRandDigit(6)
+	record := new(system.AdminVerifyCodeRecord)
+	record.VerifyType = system.AdminVerifyCodeRecordTypeEmail
+	record.Email = email
+	record.Source = source
+	record.Code = verifyCode
+	record.ExpiredTime = time.Now().Add(utils.VerifyCodeExpireMinute * time.Minute)
+	record.CreateTime = time.Now().Local()
+	record.ModifyTime = time.Now().Local()
+	if e := record.Create(); e != nil {
+		err = fmt.Errorf("新增验证码记录失败, Err: %s", e.Error())
+		return
+	}
+
+	// 获取邮件配置
+	authKey := "english_report_email_conf"
+	emailConf, e := company.GetConfigDetailByCode(authKey)
+	if e != nil {
+		err = fmt.Errorf("获取群发邮件权限失败, Err: %s", e.Error())
+		return
+	}
+	if emailConf.ConfigValue == "" {
+		err = fmt.Errorf("邮件配置为空, 不可推送")
+		return
+	}
+	conf := new(models.EnglishReportEmailConf)
+	if e = json.Unmarshal([]byte(emailConf.ConfigValue), &conf); e != nil {
+		err = fmt.Errorf("邮件配置有误, 不可推送")
+		return
+	}
+
+	// 获取邮箱模板
+	confKey := "admin_verify_code_email_tmp"
+	confTmp, e := company.GetConfigDetailByCode(confKey)
+	if e != nil {
+		err = fmt.Errorf("获取邮件模板失败, Err: %s", e.Error())
+		return
+	}
+	if confTmp.ConfigValue == `` {
+		err = fmt.Errorf("邮件模板为空, 不可推送")
+		return
+	}
+
+	req := new(EnglishReportSendEmailRequest)
+	req.Subject = "弘则研究登录验证"
+	req.Email = email
+	req.FromAlias = conf.FromAlias
+	// 填充模板
+	t := time.Now().Format("2006年01月02日")
+	ct := confTmp.ConfigValue
+	ct = strings.Replace(ct, "{{VERIFY_CODE}}", verifyCode, 1)
+	ct = strings.Replace(ct, "{{EXPIRED_MINUTE}}", strconv.Itoa(utils.VerifyCodeExpireMinute), 1)
+	ct = strings.Replace(ct, "{{DATE_TIME}}", t, 1)
+	req.HtmlBody = ct
+
+	aliEmail := new(AliyunEmail)
+	o, result, e := aliEmail.SendEmail(req)
+	if e != nil {
+		err = fmt.Errorf("邮箱推送失败, Err: %s", e.Error())
+		return
+	}
+	ok = o
+
+	record.SendStatus = system.AdminVerifyCodeRecordStatusSuccess
+	if !ok {
+		record.SendStatus = system.AdminVerifyCodeRecordStatusFail
+	}
+	record.SendResult = result
+	cols := []string{"SendStatus", "SendResult"}
+	if e = record.Update(cols); e != nil {
+		err = fmt.Errorf("更新验证码记录失败, Err: %s", e.Error())
+	}
+	return
+}

+ 2 - 2
services/video.go

@@ -6,11 +6,11 @@ import (
 	"encoding/binary"
 	"encoding/json"
 	"errors"
-	"github.com/PuerkitoBio/goquery"
-	"github.com/kgiannakakis/mp3duration/src/mp3duration"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/utils"
+	"github.com/PuerkitoBio/goquery"
+	"github.com/kgiannakakis/mp3duration/src/mp3duration"
 	"html"
 	"io"
 	"io/ioutil"

+ 1 - 1
services/wechat_send_msg.go

@@ -3,10 +3,10 @@ package services
 import (
 	"encoding/json"
 	"errors"
-	"fmt"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/utils"
+	"fmt"
 	"io/ioutil"
 	"net/http"
 	"strconv"

+ 1 - 1
services/wx_app.go

@@ -1,6 +1,7 @@
 package services
 
 import (
+	"eta/eta_mobile/utils"
 	"fmt"
 	wechat "github.com/silenceper/wechat/v2"
 	"github.com/silenceper/wechat/v2/cache"
@@ -9,7 +10,6 @@ import (
 	"github.com/silenceper/wechat/v2/miniprogram/config"
 	"github.com/silenceper/wechat/v2/miniprogram/encryptor"
 	"github.com/silenceper/wechat/v2/miniprogram/qrcode"
-	"eta/eta_mobile/utils"
 )
 
 func GetWxApp() (miniprogram *miniprogram.MiniProgram) {

+ 2 - 2
services/xfyun.go

@@ -3,15 +3,15 @@ package services
 import (
 	"encoding/base64"
 	"encoding/json"
+	"eta/eta_mobile/models"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/crypt"
-	"eta/eta_mobile/models"
 	"net/url"
 	"strings"
 	"time"
 
-	"github.com/gorilla/websocket"
 	"eta/eta_mobile/utils"
+	"github.com/gorilla/websocket"
 )
 
 // 科大讯飞,语音合成

Неке датотеке нису приказане због велике количине промена