瀏覽代碼

Merge branch 'CRM_12.9'

ziwen 2 年之前
父節點
當前提交
1dd7ea3454

+ 1 - 1
.gitignore

@@ -6,6 +6,6 @@ latest_log
 go.sum
 /binlog
 latest_binlog
-hongze_yb
+hongze_yb_en_api
 /rdlucklog
 /*.exe

+ 520 - 3
controller/auth.go

@@ -1,13 +1,530 @@
 package controller
 
 import (
+	"fmt"
 	"github.com/gin-gonic/gin"
+	"github.com/go-playground/validator/v10"
+	"hongze/hongze_yb_en_api/controller/resp"
+	"hongze/hongze_yb_en_api/global"
+	"hongze/hongze_yb_en_api/models/english_report_email"
+	"hongze/hongze_yb_en_api/models/msg_code"
+	"hongze/hongze_yb_en_api/models/session"
+	"hongze/hongze_yb_en_api/services"
+	"hongze/hongze_yb_en_api/utils"
+	"time"
 )
 
 type AuthController struct {
+}
+
+func (a *AuthController) Login(c *gin.Context) {
+	req := new(services.LoginReq)
+	err := c.ShouldBind(&req)
+	if err != nil {
+		errs, ok := err.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
+		return
+	}
+	if req.Account == "" {
+		resp.Fail("邮箱或手机号错误", c)
+		return
+	}
+
+	userEmail := new(english_report_email.Email)
+	emailItem := new(english_report_email.Email)
+	if req.Type == 1 {
+		userEmail, err = emailItem.GetByEmail(req.Account)
+		if err != nil || userEmail.IsDeleted == 1 {
+			if err == utils.ErrNoRow || userEmail.IsDeleted == 1 {
+				resp.Unregistered("账号未注册", c)
+				return
+			}
+			resp.FailData("获取客户邮箱信息失败 ", "Err:"+err.Error(), c)
+			return
+		}
+	} else {
+		userEmail, err := emailItem.GetByMobile(req.Account, req.CountryCode)
+		if err != nil || userEmail.IsDeleted == 1 {
+			if err == utils.ErrNoRow || userEmail.IsDeleted == 1 {
+				resp.Unbound("手机号未绑定", c)
+				return
+			}
+			resp.FailData("获取客户邮箱信息失败 ", "Err:"+err.Error(), c)
+			return
+		}
+	}
+
+	password := utils.MD5(req.Password + utils.KEY)
+	sysUser, err := english_report_email.CheckUserPwd(req.Type, req.CountryCode, req.Account, password)
+	if err != nil {
+		resp.FailData("Login failed. Please check your entries and try again.", "Err:"+err.Error(), c)
+		return
+	}
+	if sysUser == nil {
+		resp.Fail("Login failed. Please check your entries and try again.", c)
+		return
+	}
+	if sysUser.Enable == 0 {
+		resp.Fail("Your account has been disabled, please contact stephanie@hzinsights.com", c)
+		return
+	}
+	if sysUser.Status == 3 {
+		resp.Expired("试用权限超期", c)
+		return
+	}
+	account := utils.MD5(req.Account)
+	token, err := utils.GenToken(account)
+	sysSession := new(session.EnglishYbSession)
+	sysSession.UserId = int(sysUser.Id)
+	//现在要求永不过期
+	sysSession.ExpireTime = time.Now().AddDate(99, 0, 0)
+	sysSession.CreatedTime = time.Now()
+	sysSession.LastUpdatedTime = time.Now()
+	sysSession.AccessToken = token
+	err = sysSession.AddSession()
+	fmt.Println("id:", sysSession.SessionId)
+	if err != nil {
+		resp.FailData("新增session信息失败", "Err:"+err.Error(), c)
+		return
+	}
+
+	respItem := session.LoginResp{
+		Mobile:           sysUser.Mobile,
+		Email:            sysUser.Email,
+		CountryCode:      sysUser.CountryCode,
+		Name:             sysUser.Name,
+		EnglishYbSession: sysSession,
+	}
+
+	resp.OkData("登陆成功", respItem, c)
+
+}
+
+func (a *AuthController) Register(c *gin.Context) {
+	req := new(services.RegisterReq)
+	err := c.ShouldBind(&req)
+	if err != nil {
+		errs, ok := err.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
+		return
+	}
+
+	item, err := msg_code.GetMsgCode(req.Email, req.SmsCode)
+	if err != nil {
+		if err != nil {
+			resp.Fail("Verification code error."+err.Error(), c)
+			return
+		}
+	}
+	if item == nil {
+		resp.Fail("验证码错误,请重新输入", c)
+		return
+	}
+
+	emailItem, err := english_report_email.CheckUser(req.Email)
+	if err != nil && err != utils.ErrNoRow {
+		resp.FailData("检测用户重复错误, Err:",err.Error(), c)
+		return
+	}
+	userId := 0
+	password := utils.MD5(req.Password + utils.KEY)
+	if emailItem.Id > 0 {
+		if emailItem.Status == 1 && emailItem.Password == "" {
+			//已经是正式用户,更新密码即可
+			emailItem.Password = password
+			emailItem.ModifyTime = time.Now()
+			emailItem.RegisterTime = time.Now()
+			err = emailItem.Update([]string{"Password", "ModifyTime", "RegisterTime"})
+			if err != nil {
+				resp.FailMsg("修改密码失败", "修改密码失败,Err:"+err.Error(), c)
+				return
+			}
+			resp.Ok("注册成功", c)
+			userId = int(emailItem.Id)
+		} else if emailItem.Status == 2 {
+			resp.Registered("邮箱已注册.", c)
+			return
+		} else if emailItem.Status == 3 {
+			resp.Expired("试用权限超期", c)
+			return
+		}
+	} else {
+		//状态为临时
+		user := english_report_email.Email{
+			Name:         req.Name,
+			CompanyName:  req.CompanyName,
+			Email:        req.Email,
+			Password:     password,
+			Enable:       1,
+			Status:       2,
+			RegisterTime: time.Now(),
+		}
+		user.Set()
+
+		err = user.Add()
+		if err != nil {
+			resp.FailData("新增用户信息失败", "Err:"+err.Error(), c)
+			return
+		}
+		userId = int(user.Id)
+	}
+	sysSession := new(session.EnglishYbSession)
+	if userId > 0 {
+		account := utils.MD5(req.Email)
+		token, err := utils.GenToken(account)
+		sysSession.UserId = userId
+		//现在要求永不过期
+		sysSession.ExpireTime = time.Now().AddDate(99, 0, 0)
+		sysSession.CreatedTime = time.Now()
+		sysSession.LastUpdatedTime = time.Now()
+		sysSession.AccessToken = token
+		err = sysSession.AddSession()
+		fmt.Println("id:", sysSession.SessionId)
+		if err != nil {
+			resp.FailData("新增session信息失败", "Err:"+err.Error(), c)
+			return
+		}
+	}
+	respItem := session.LoginResp{
+		Email:            req.Email,
+		Name:             req.Name,
+		EnglishYbSession: sysSession,
+	}
+
+	resp.OkData("注册成功", respItem, c)
+}
+
+// @Title 修改密码
+// @Description 修改密码
+// @Param	request	body models.ModifyPwdReq true "type json string"
+// @Success 200 {object} models.LoginResp
+// @router /modifyPwd [post]
+func (a *AuthController) ModifyPwd(c *gin.Context) {
+	req := new(services.ModifyPwdReq)
+	err := c.ShouldBind(&req)
+	if err != nil {
+		errs, ok := err.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
+		return
+	}
+	userinfo := services.GetInfoByClaims(c)
 
+	if req.NewPwd == "" {
+		resp.Fail("Please enter a new password", c)
+		return
+	}
+
+	if req.OldPwd == "" {
+		resp.Fail("Please enter the original password", c)
+		return
+	}
+
+	if req.OldPwd != userinfo.Password {
+		resp.Fail("The old password is wrong, please re-enter.", c)
+		return
+	}
+
+	password := utils.MD5(req.NewPwd + utils.KEY)
+	emailitem := english_report_email.Email{
+		Id:       userinfo.Id,
+		Password: password,
+	}
+	emailitem.ModifyTime = time.Now()
+
+	err = emailitem.Update([]string{"Password"})
+	if err != nil {
+		resp.FailMsg("修改密码失败", "修改密码失败,Err:"+err.Error(), c)
+		return
+	}
+
+	resp.Ok("修改成功", c)
+}
+
+// GetSmsCode 获取短信验证码接口
+// @Tags 用户模块
+// @Summary  获取短信验证码
+// @Description 获取短信验证码接口
+// @Security ApiKeyAuth
+// @securityDefinitions.basic BasicAuth
+// @Param Mobile	query string true "手机号"
+// @Param AreaNum	query string true "手机国际区号(中国大陆:86)"
+// @Accept  json
+// @Product json
+// @Success 200 {string} string 获取验证码成功
+// @Failure 400 {string} string 手机号不能为空,请输入手机号
+// @Router /smsCode [get]
+func (a *AuthController) GetSmsCode(c *gin.Context) {
+	mobile := c.DefaultQuery("Mobile", "")
+	areaNum := c.DefaultQuery("AreaNum", "")
+	err, errMsg := services.SendSmsCode(mobile, areaNum)
+	if err != nil {
+		if errMsg != "" {
+			errMsg = "获取验证码失败"
+		}
+		resp.Fail(errMsg, c)
+		return
+	}
+
+	resp.Ok("获取验证码成功", c)
 }
 
-func (a *AuthController) Login(c *gin.Context)  {
-	return
-}
+// GetEmailCode 获取邮箱验证码接口
+// @Tags 用户模块
+// @Summary  获取邮箱验证码
+// @Description 获取邮箱验证码
+// @Security ApiKeyAuth
+// @securityDefinitions.basic BasicAuth
+// @Param email	query string true "电子邮箱账号"
+// @Accept  json
+// @Product json
+// @Success 200 {string} string 获取验证码成功
+// @Failure 400 {string} string 请输入邮箱地址
+// @Router /emailCode [get]
+func (a *AuthController) GetEmailCode(c *gin.Context) {
+	email := c.DefaultQuery("Email", "")
+	if email == "" {
+		resp.Fail("请输入邮箱地址", c)
+		return
+	}
+	if !utils.ValidateEmailFormatat(email) {
+		resp.Fail("邮箱格式错误,请重新输入", c)
+		return
+	}
+
+	name := c.DefaultQuery("Name", "")
+	if name == "" {
+		emailItem := new(english_report_email.Email)
+		userEmail, err := emailItem.GetByEmail(email)
+		if err != nil && err != utils.ErrNoRow {
+			resp.FailData("获取客户邮箱信息失败 ", "Err:"+err.Error(), c)
+			return
+		}
+		if userEmail != nil {
+			name = userEmail.Name
+		}
+	}
+
+	err, errMsg := services.SendEmailCode(name, email)
+	if err != nil {
+		if errMsg != "" {
+			errMsg = "获取验证码失败"
+		}
+		resp.Fail(errMsg, c)
+		return
+	}
+
+	resp.Ok("获取验证码成功", c)
+}
+
+func (a *AuthController) BindMobile(c *gin.Context) {
+	req := new(services.BindMobileReq)
+	err := c.ShouldBind(&req)
+	if err != nil {
+		errs, ok := err.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
+		return
+	}
+	userinfo := services.GetInfoByClaims(c)
+
+	if req.Mobile == "" {
+		resp.Fail("手机号不能为空", c)
+		return
+	}
+
+	if req.SmsCode == "" {
+		resp.Fail("验证码不能为空", c)
+		return
+	}
+
+	if req.CountryCode == "" {
+		resp.Fail("区号不能为空", c)
+		return
+	}
+
+	emailItem := new(english_report_email.Email)
+	userEmail, err := emailItem.GetByMobile(req.Mobile, req.CountryCode)
+	if err != nil && err != utils.ErrNoRow {
+		resp.FailData("获取客户邮箱信息失败 ", "Err:"+err.Error(), c)
+		return
+	}
+
+	if userEmail.Id != 0 {
+		resp.Bound("手机号已绑定 ", c)
+		return
+	}
+
+	item, err := msg_code.GetMsgCode(req.Mobile, req.SmsCode)
+	if err != nil {
+		resp.Fail("Verification code error."+err.Error(), c)
+		return
+	}
+	if item == nil {
+		resp.Fail("验证码错误,请重新输入", c)
+		return
+	}
+
+	user := english_report_email.Email{
+		Id:          userinfo.Id,
+		Mobile:      req.Mobile,
+		CountryCode: req.CountryCode,
+	}
+	user.ModifyTime = time.Now()
+
+	err = user.Update([]string{"Mobile", "CountryCode", "ModifyTime"})
+	if err != nil {
+		resp.FailMsg("绑定手机号失败", "修改手机号失败,Err:"+err.Error(), c)
+		return
+	}
+
+	resp.Ok("绑定成功", c)
+}
+
+func (a *AuthController) ForgetPwd(c *gin.Context) {
+	req := new(services.ForgetPwdReq)
+	err := c.ShouldBind(&req)
+	if err != nil {
+		errs, ok := err.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
+		return
+	}
+
+	if req.Account == "" {
+		resp.Fail("账号不能为空", c)
+		return
+	}
+
+	if req.SmsCode == "" {
+		resp.Fail("验证码不能为空", c)
+		return
+	}
+
+	if req.Password == "" {
+		resp.Fail("Please enter a new password", c)
+		return
+	}
+
+	userEmail := new(english_report_email.Email)
+	emailItem := new(english_report_email.Email)
+	if req.Type == 1 {
+		userEmail, err = emailItem.GetByEmail(req.Account)
+		if err != nil || userEmail.IsDeleted == 1 {
+			if err == utils.ErrNoRow || userEmail.IsDeleted == 1 {
+				resp.Unregistered("账号未注册", c)
+				return
+			}
+			resp.FailData("获取客户邮箱信息失败 ", "Err:"+err.Error(), c)
+			return
+		}
+	} else {
+		userEmail, err = emailItem.GetByMobile(req.Account, req.CountryCode)
+		if err != nil || userEmail.IsDeleted == 1 {
+			if err == utils.ErrNoRow || userEmail.IsDeleted == 1 {
+				resp.Unbound("手机号未绑定", c)
+				return
+			}
+			resp.FailData("获取客户邮箱信息失败 ", "Err:"+err.Error(), c)
+			return
+		}
+	}
+
+	item, err := msg_code.GetMsgCode(req.Account, req.SmsCode)
+	if err != nil {
+		resp.Fail("Verification code error."+err.Error(), c)
+		return
+
+	}
+	if item == nil {
+		resp.Fail("验证码错误,请重新输入", c)
+		return
+	}
+
+	password := utils.MD5(req.Password + utils.KEY)
+	emailitem := english_report_email.Email{
+		Id:       userEmail.Id,
+		Password: password,
+	}
+	emailitem.ModifyTime = time.Now()
+
+	err = emailitem.Update([]string{"Password"})
+	if err != nil {
+		resp.FailMsg("修改密码失败", "修改密码失败,Err:"+err.Error(), c)
+		return
+	}
+
+	resp.Ok("修改成功", c)
+}
+
+func (a *AuthController) ModifyMobile(c *gin.Context) {
+	req := new(services.ModifyMobile)
+	err := c.ShouldBind(&req)
+	if err != nil {
+		errs, ok := err.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
+		return
+	}
+	userinfo := services.GetInfoByClaims(c)
+
+	if req.NewMobile == "" {
+		resp.Fail("Please enter a new phone number", c)
+		return
+	}
+
+	if req.OldMobile == "" {
+		resp.Fail("Please enter the original phone number", c)
+		return
+	}
+
+	if req.OldMobile != userinfo.Mobile {
+		resp.Fail("The old phone number is wrong, please re-enter.", c)
+		return
+	}
+
+	if req.SmsCode == "" {
+		resp.Fail("验证码不能为空", c)
+		return
+	}
+
+	if req.CountryCode == "" {
+		resp.Fail("区号不能为空", c)
+		return
+	}
+
+	emailitem := english_report_email.Email{
+		Id:          userinfo.Id,
+		Mobile:      req.NewMobile,
+		CountryCode: req.CountryCode,
+	}
+	emailitem.ModifyTime = time.Now()
+
+	err = emailitem.Update([]string{"Mobile", "CountryCode", "ModifyTime"})
+	if err != nil {
+		resp.FailMsg("修改手机号失败", "修改手机号失败,Err:"+err.Error(), c)
+		return
+	}
+
+	resp.Ok("修改成功", c)
+}

+ 5 - 7
controller/english_report/english_report.go

@@ -10,6 +10,7 @@ import (
 	"hongze/hongze_yb_en_api/models/english_classify"
 	"hongze/hongze_yb_en_api/models/english_report"
 	"hongze/hongze_yb_en_api/models/english_video"
+	"hongze/hongze_yb_en_api/services"
 	elasticService "hongze/hongze_yb_en_api/services/elastic"
 	english_report_service "hongze/hongze_yb_en_api/services/english_report"
 	"hongze/hongze_yb_en_api/utils"
@@ -280,7 +281,7 @@ func (er *EnglishReportController) Detail(c *gin.Context) {
 		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
 		return
 	}
-
+	userinfo := services.GetInfoByClaims(c)
 	reportItem := new(english_report.Report)
 	reportItem, err = reportItem.GetEnglishReportByCode(req.ReportCode)
 	if err != nil {
@@ -295,14 +296,11 @@ func (er *EnglishReportController) Detail(c *gin.Context) {
 	reportItem.ContentSub = html.UnescapeString(reportItem.ContentSub)
 	reportItem.Content = html.UnescapeString(reportItem.Content)
 
-	shareEmailId := req.ShareEmail
-	if shareEmailId == 0 {
-		shareEmailIdStr := c.GetString("shareEmailId")
-		shareEmailId, _ = strconv.Atoi(shareEmailIdStr)
-	}
+	shareEmailId := userinfo.Id
+
 	// 记录邮箱
 	if shareEmailId > 0 {
-		go english_report_service.DealEmail(reportItem, req.ReportCode, shareEmailId)
+		go english_report_service.DealEmail(reportItem, req.ReportCode, int(shareEmailId))
 	}
 	reportDetail := &english_report.ReportDetail{
 		Id:                 reportItem.Id,

+ 57 - 7
controller/resp/base.go

@@ -10,13 +10,18 @@ import (
 )
 
 var (
-	OK_CODE            = 200  //业务成功
-	FAIL_CODE          = 400  //业务错误
-	TOKEN_ERROR_CODE   = 401  //toke异常
-	NO_AUTH            = 403  //没有权限
-	SPECIFIC_FAIL_CODE = 4001 // 业务指定错误
-	HASFORBIDDEN_CODE = 4010  // 管理员账号被禁用
-	PASSWORDCHANGE_CODE = 4011  // 管理员账号被禁用
+	OK_CODE             = 200  //业务成功
+	FAIL_CODE           = 400  //业务错误
+	TOKEN_ERROR_CODE    = 401  //toke异常
+	NO_AUTH             = 403  //没有权限
+	SPECIFIC_FAIL_CODE  = 4001 // 业务指定错误
+	HASFORBIDDEN_CODE   = 4010 // 管理员账号被禁用
+	PASSWORDCHANGE_CODE = 4011 // 管理员账号被禁用
+	EXPIRED_CODE        = 4012 // 已到期
+	UNREGISTERED_CODE   = 4013 // 未注册
+	UNBOUND_CODE        = 4014 // 未绑定
+	REGISTERED_CODE     = 4015 // 已注册
+	BOUND_CODE          = 4016 // 已绑定
 )
 
 type ResultData struct {
@@ -154,3 +159,48 @@ func FailMsg(msg, errMsg string, c *gin.Context) {
 	}
 	result(200, resultData, c)
 }
+
+// Expired 过期
+func Expired(msg string, c *gin.Context) {
+	resultData := ResultData{
+		Code: EXPIRED_CODE,
+		Msg:  msg,
+	}
+	result(200, resultData, c)
+}
+
+// Unregistered 未注册
+func Unregistered(msg string, c *gin.Context) {
+	resultData := ResultData{
+		Code: UNREGISTERED_CODE,
+		Msg:  msg,
+	}
+	result(200, resultData, c)
+}
+
+// Unbound 未绑定
+func Unbound(msg string, c *gin.Context) {
+	resultData := ResultData{
+		Code: UNBOUND_CODE,
+		Msg:  msg,
+	}
+	result(200, resultData, c)
+}
+
+// Registered 已注册
+func Registered(msg string, c *gin.Context) {
+	resultData := ResultData{
+		Code: REGISTERED_CODE,
+		Msg:  msg,
+	}
+	result(200, resultData, c)
+}
+
+// Bound 已绑定
+func Bound(msg string, c *gin.Context) {
+	resultData := ResultData{
+		Code: BOUND_CODE,
+		Msg:  msg,
+	}
+	result(200, resultData, c)
+}

+ 1 - 1
go.mod

@@ -17,9 +17,9 @@ require (
 	github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
 	github.com/rdlucklib/rdluck_tools v1.0.3
 	github.com/spf13/viper v1.14.0
-	github.com/swaggo/gin-swagger v1.5.3
 	github.com/swaggo/swag v1.8.8
 	golang.org/x/image v0.2.0
+	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 	gorm.io/driver/mysql v1.4.4
 	gorm.io/gorm v1.24.2
 )

+ 48 - 1
middleware/token.go

@@ -2,10 +2,57 @@ package middleware
 
 import (
 	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb_en_api/controller/resp"
+	"hongze/hongze_yb_en_api/models/english_report_email"
+	"hongze/hongze_yb_en_api/models/session"
+	"hongze/hongze_yb_en_api/services"
+	"hongze/hongze_yb_en_api/utils"
 )
 
 func Token() gin.HandlerFunc {
 	return func(c *gin.Context) {
+		token := c.Request.Header.Get("Authorization")
+		if token == "" {
+			token = c.DefaultQuery("authorization", "")
+			if token == "" {
+				token = c.DefaultQuery("Authorization", "")
+			}
+		}
+		if token == "" {
+			resp.TokenError(nil, "未登录或非法访问", "未登录或非法访问", c)
+			c.Abort()
+			return
+		}
+		sessionInfo, err := session.GetTokenByToken(token)
+		if err != nil {
+			if err == utils.ErrNoRow {
+				resp.TokenError(nil, "信息已变更,请重新登陆!", "找不到对应session", c)
+				c.Abort()
+				return
+			}
+			resp.TokenError(nil, "网络异常,请稍后重试!", err.Error(), c)
+			c.Abort()
+			return
+		}
 
+		if sessionInfo == nil {
+			resp.TokenError(nil, "网络异常,请稍后重试1038!", "找不到对应session", c)
+			c.Abort()
+			return
+		}
+
+		emailItem := english_report_email.Email{Id: uint(sessionInfo.UserId)}
+		userEmail, err := emailItem.GetById(sessionInfo.UserId)
+		if err != nil  && err != utils.ErrNoRow {
+			resp.TokenError(nil, "数据异常!", "userID查询用户信息错误", c)
+			c.Abort()
+			return
+		}
+		userInfo := services.UserInfo{
+			Email:      *userEmail,
+		}
+		userInfo.LoginToken = token
+		c.Set("userInfo", userInfo)
+		c.Next()
 	}
-}
+}

+ 38 - 3
models/english_report_email/email.go

@@ -11,12 +11,19 @@ type Email struct {
 	Id           uint      `gorm:"primaryKey;column:id" json:"id"`
 	CompanyId    uint      `gorm:"column:company_id" json:"company_id"`         //客户ID
 	Name         string    `gorm:"column:name" json:"name"`                     //客户名称
+	CompanyName  string    `gorm:"column:company_name" json:"company_name"`     //公司名称
 	Email        string    `gorm:"column:email" json:"email"`                   //邮箱地址
 	ViewTotal    uint      `gorm:"column:view_total" json:"view_total"`         //累计点击量/阅读量
 	LastViewTime time.Time `gorm:"column:last_view_time" json:"last_view_time"` //最后阅读时间
+	RegisterTime time.Time `gorm:"column:register_time" json:"register_time"`   //注册时间
 	IsDeleted    uint8     `gorm:"column:is_deleted" json:"is_deleted"`         //删除状态:0-正常;1-已删除
 	AdminId      uint      `gorm:"column:admin_id" json:"admin_id"`             //创建人ID
 	AdminName    string    `gorm:"column:admin_name" json:"admin_name"`         //创建人名称
+	Enable       int       `gorm:"column:enabled" json:"enabled"`
+	Status       int       `description:"1:正式,2:临时,3:终止"`
+	Password     string    `gorm:"column:password" json:"password"`
+	Mobile       string    `gorm:"column:mobile" json:"mobile"`
+	CountryCode  string    `gorm:"column:country_code" json:"country_code"` //国家代码
 	base.TimeBase
 }
 
@@ -27,13 +34,13 @@ func (e *Email) TableName() string {
 
 // Add 新增
 func (e *Email) Add() (err error) {
-	err = global.DEFAULT_MYSQL.Create(e).Error
+	err = global.MYSQL["rddp"].Create(e).Error
 	return
 }
 
 // 修改
 func (e *Email) Update(updateCols []string) (err error) {
-	err = global.DEFAULT_MYSQL.Model(e).Select(updateCols).Updates(e).Error
+	err = global.MYSQL["rddp"].Model(e).Select(updateCols).Updates(e).Error
 	return
 }
 
@@ -44,6 +51,34 @@ func (e *Email) GetById(id int) (item *Email, err error) {
 
 func (e *Email) UpdateViewTotalById(Id uint) (err error) {
 	sql := `UPDATE english_report_email SET view_total = view_total+1, last_view_time = NOW() WHERE id = ? `
-	err = global.DEFAULT_MYSQL.Exec(sql, Id).Error
+	err = global.MYSQL["rddp"].Exec(sql, Id).Error
+	return
+}
+
+func CheckUserPwd(loginType int, countryCode, account, password string) (item *Email, err error) {
+	sql := ``
+	if loginType == 1 {
+		sql = `SELECT * FROM english_report_email WHERE email=? AND password=? AND is_deleted = 0 `
+		err = global.MYSQL["rddp"].Raw(sql, account, password).Scan(&item).Error
+	} else {
+		sql = `SELECT * FROM english_report_email WHERE country_code = ? AND mobile=? AND password=?  AND is_deleted = 0 `
+		err = global.MYSQL["rddp"].Raw(sql, countryCode, account, password).Scan(&item).Error
+	}
+	return
+}
+
+func CheckUser(email string) (item *Email, err error) {
+	sql := `SELECT * FROM english_report_email WHERE email=? AND is_deleted = 0 `
+	err = global.MYSQL["rddp"].Raw(sql, email).First(&item).Error
+	return
+}
+
+func (e *Email) GetByEmail(email string) (item *Email, err error) {
+	err = global.MYSQL["rddp"].Model(e).Where("email = ? AND is_deleted = 0 ", email).First(&item).Error
+	return
+}
+
+func (e *Email) GetByMobile(mobile, countryCode string) (item *Email, err error) {
+	err = global.MYSQL["rddp"].Model(e).Where("mobile = ? AND country_code = ? AND is_deleted = 0 ", mobile, countryCode).First(&item).Error
 	return
 }

+ 11 - 0
models/msg_code/create.go

@@ -0,0 +1,11 @@
+package msg_code
+
+import (
+	"hongze/hongze_yb_en_api/global"
+)
+
+//  Create 新增记录
+func (msgCode *MsgCode) Create() (err error) {
+	err = global.MYSQL["rddp"].Create(msgCode).Error
+	return
+}

+ 41 - 0
models/msg_code/msg_code.go

@@ -0,0 +1,41 @@
+package msg_code
+
+import "time"
+
+// MsgCode 验证码列表
+type MsgCode struct {
+	MsgCodeID       int64     `gorm:"primaryKey;column:msg_code_id;type:bigint(20);not null" json:"-"`                // 短信验证码id
+	OpenID          string    `gorm:"index:open_id;column:open_id;type:varchar(32);not null" json:"openId"`           // 用户id
+	Mobile          string    `gorm:"index:mobile;column:mobile;type:varchar(50);not null" json:"mobile"`             // 手机号/邮箱
+	Code            string    `gorm:"column:code;type:varchar(20);not null" json:"code"`                              // 验证码
+	ExpiredIn       int64     `gorm:"column:expired_in;type:bigint(20);not null" json:"expiredIn"`                    // 过期时间
+	Enabled         int8      `gorm:"column:enabled;type:tinyint(1)" json:"enabled"`                                  // 状态
+	CreatedTime     time.Time `gorm:"column:created_time;type:datetime;default:CURRENT_TIMESTAMP" json:"createdTime"` // 创建时间
+	LastUpdatedTime time.Time `gorm:"column:last_updated_time;type:timestamp;not null;default:CURRENT_TIMESTAMP" json:"lastUpdatedTime"`
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *MsgCode) TableName() string {
+	return "msg_code"
+}
+
+// MsgCodeColumns get sql column name.获取数据库列名
+var MsgCodeColumns = struct {
+	MsgCodeID       string
+	OpenID          string
+	Mobile          string
+	Code            string
+	ExpiredIn       string
+	Enabled         string
+	CreatedTime     string
+	LastUpdatedTime string
+}{
+	MsgCodeID:       "msg_code_id",
+	OpenID:          "open_id",
+	Mobile:          "mobile",
+	Code:            "code",
+	ExpiredIn:       "expired_in",
+	Enabled:         "enabled",
+	CreatedTime:     "created_time",
+	LastUpdatedTime: "last_updated_time",
+}

+ 11 - 0
models/msg_code/query.go

@@ -0,0 +1,11 @@
+package msg_code
+
+import (
+	"hongze/hongze_yb_en_api/global"
+)
+
+// GetMsgCode 根据token获取信息
+func GetMsgCode(mobile, code string) (item *MsgCode, err error) {
+	err = global.MYSQL["rddp"].Where("mobile = ? and code = ? and FROM_UNIXTIME(expired_in)>=NOW() ", mobile, code).First(&item).Error
+	return
+}

+ 46 - 0
models/session/english_yb_session.go

@@ -0,0 +1,46 @@
+package session
+
+import (
+	"hongze/hongze_yb_en_api/global"
+	"time"
+)
+
+type EnglishYbSession struct {
+	SessionId       int    `gorm:"primaryKey;column:session_id" json:"session_id"`
+	UserId          int    `gorm:"column:user_id" json:"user_id"`
+	AccessToken     string `gorm:"column:access_token" json:"access_token"`
+	ExpireTime      time.Time
+	CreatedTime     time.Time
+	LastUpdatedTime time.Time
+}
+
+// TableName get sql table name.获取数据库表名
+func (e *EnglishYbSession) TableName() string {
+	return "english_yb_session"
+}
+
+// 新增用户登录session信息
+func (e *EnglishYbSession) AddSession() (err error) {
+	err = global.MYSQL["rddp"].Create(e).Error
+	return
+}
+
+func GetSessionByUserId(userId int) (item *EnglishYbSession, err error) {
+	sql := `SELECT * FROM english_yb_session WHERE user_id=? AND expired_time> NOW() ORDER BY expired_time DESC LIMIT 1 `
+	err = global.MYSQL["rddp"].Exec(sql, userId).Error
+	return
+}
+
+func GetSessionByToken(token string) (item *EnglishYbSession, err error) {
+	sql := `SELECT * FROM english_yb_session WHERE access_token=? AND expired_time> NOW() ORDER BY expired_time DESC LIMIT 1 `
+	err = global.MYSQL["rddp"].Exec(sql, token).Error
+	return
+}
+
+type LoginResp struct {
+	Mobile      string
+	Email       string
+	CountryCode string `description:"区号"`
+	Name        string `description:"客户名称"`
+	*EnglishYbSession
+}

+ 24 - 0
models/session/query.go

@@ -0,0 +1,24 @@
+package session
+
+import (
+	"gorm.io/gorm"
+	"hongze/hongze_yb_en_api/global"
+	"time"
+)
+
+// GetTokenByToken 根据token获取信息
+func GetTokenByToken(token string) (item *EnglishYbSession, err error) {
+	err = getDb().Where("access_token = ? and expire_time> ? ", token, time.Now()).Order("session_id DESC").First(&item).Error
+	return
+}
+
+// 获取数据库链接
+func getDb() *gorm.DB {
+	return global.MYSQL["rddp"]
+}
+
+// GetTokenByUid 根据用户id获取token
+func GetTokenByUid(userId int) (item *EnglishYbSession, err error) {
+	err = getDb().Where("user_id = ? ", userId).First(&item).Error
+	return
+}

+ 11 - 0
routers/auth.go

@@ -3,6 +3,7 @@ package routers
 import (
 	"github.com/gin-gonic/gin"
 	"hongze/hongze_yb_en_api/controller"
+	"hongze/hongze_yb_en_api/middleware"
 )
 
 func InitAuth(baseGroup *gin.RouterGroup) {
@@ -10,4 +11,14 @@ func InitAuth(baseGroup *gin.RouterGroup) {
 	authController := new(controller.AuthController)
 	authGroup := baseGroup.Group("auth/")
 	authGroup.POST("login", authController.Login)
+	authGroup.POST("register", authController.Register)
+	authGroup.GET("smsCode", authController.GetSmsCode)
+	authGroup.GET("emailCode", authController.GetEmailCode)
+	authGroup.POST("forgetPwd", authController.ForgetPwd)
+
+	authTokenController := new(controller.AuthController)
+	authTokenGroup := baseGroup.Group("auth/").Use(middleware.Token())
+	authTokenGroup.POST("modifyPwd", authTokenController.ModifyPwd)
+	authTokenGroup.POST("bindMobile", authTokenController.BindMobile)
+	authTokenGroup.POST("modifyMobile", authTokenController.ModifyMobile)
 }

+ 1 - 1
routers/english_report.go

@@ -10,7 +10,7 @@ func InitReport(baseGroup *gin.RouterGroup) {
 	//登录
 	controller := new(english_report.EnglishReportController)
 	vController := new(english_report.EnglishVideoController)
-	group := baseGroup.Group("english_report/").Use(middleware.ShareEmailHandler())
+	group := baseGroup.Group("english_report/").Use(middleware.ShareEmailHandler()).Use(middleware.Token())
 	group.GET("list", controller.List)
 	group.GET("video/list", vController.List)
 	group.GET("classify", controller.Classify)

+ 71 - 0
services/email.go

@@ -0,0 +1,71 @@
+package services
+
+import (
+	"errors"
+	"gopkg.in/gomail.v2"
+	"hongze/hongze_yb_en_api/models/msg_code"
+	"hongze/hongze_yb_en_api/utils"
+	"strings"
+	"time"
+)
+
+
+// SendEmailCode 发送邮件
+func SendEmailCode(name,email string) (err error, errMsg string) {
+	if email == "" {
+		err = errors.New("请输入邮箱地址")
+		return
+	}
+	if !utils.ValidateEmailFormatat(email) {
+		err = errors.New("邮箱格式错误,请重新输入")
+		return
+	}
+	msgCode := utils.GetRandDigit(4)
+	content := "Hi "+ name +":</br>Please enter this verification code on the registration page so we can make sure it's you:</br><p>" + msgCode + "</p>This code will expire in 15 minutes.</br>" +
+		"If you didn't initiate this request, or need help with your registration, please let us know at: stephanie@hzinsights.com </br>Horizon Research Team"
+	title := "Your Email Verification Code"
+	//发送邮件
+	result, err := SendEmailByHz(title, content, email)
+
+	if result {
+		item := &msg_code.MsgCode{
+			Mobile:          email,
+			Code:            msgCode,
+			ExpiredIn:       time.Now().Add(15 * time.Minute).Unix(),
+			Enabled:         1,
+			CreatedTime:     time.Time{},
+			LastUpdatedTime: time.Time{},
+		}
+		err = item.Create()
+	} else {
+		err = errors.New("发送失败")
+	}
+
+	return
+}
+
+//发送邮件
+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 {
+		result = false
+		return result, err
+	}
+	result = true
+	return
+}

+ 163 - 0
services/sms.go

@@ -0,0 +1,163 @@
+package services
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"hongze/hongze_yb_en_api/models/msg_code"
+	"hongze/hongze_yb_en_api/services/alarm_msg"
+	"hongze/hongze_yb_en_api/utils"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"time"
+)
+
+// SendSmsCode 发送手机短信
+func SendSmsCode(mobile, areaNum string) (err error, errMsg string) {
+	if mobile == "" {
+		err = errors.New("请输入手机号")
+		return
+	}
+	msgCode := utils.GetRandDigit(4)
+	var result bool
+	if areaNum == "86" || areaNum == "" || areaNum == "0" {
+		//国内的短信
+		result = SendSmsCodeGn(mobile, msgCode)
+	} else {
+		//国际短信
+		result = SendSmsCodeGj(mobile, msgCode, areaNum)
+	}
+	//发送成功
+	if result {
+		item := &msg_code.MsgCode{
+			Mobile:          mobile,
+			Code:            msgCode,
+			ExpiredIn:       time.Now().Add(15 * time.Minute).Unix(),
+			Enabled:         1,
+			CreatedTime:     time.Time{},
+			LastUpdatedTime: time.Time{},
+		}
+		err = item.Create()
+	} else {
+		err = errors.New("短信发送失败")
+	}
+	return
+}
+
+
+// SendSmsCode 发送国内短信
+func SendSmsCodeGn(mobile, vCode string) bool {
+	flag := false
+	tplId := "65692"
+	result, err := sendSms(mobile, tplId, vCode)
+	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
+}
+
+// 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,根据实际情况修改
+	param.Set("tpl_value", "#code#="+code) //您设置的模板变量,根据实际情况
+	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", "12415")           //您申请的短信模板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
+	}
+	defer resp.Body.Close()
+	return ioutil.ReadAll(resp.Body)
+}

+ 72 - 0
services/user.go

@@ -0,0 +1,72 @@
+package services
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb_en_api/models/english_report_email"
+)
+
+type LoginReq struct {
+	Account     string `description:"账号"`
+	CountryCode string `description:"区号"`
+	Type        int    `description:"类型 1:邮箱 2:手机"`
+	Password    string `description:"密码"`
+}
+
+type LoginResp struct {
+	Authorization   string
+	AdminName       string `description:"系统用户名称"`
+	RealName        string `description:"系统用户姓名"`
+	RoleName        string `description:"角色名称"`
+	RoleTypeCode    string `description:"角色类型编码"`
+	SysRoleTypeCode string `description:"角色类型编码"`
+	AdminId         int    `description:"系统用户id"`
+	ProductName     string `description:"产品名称:admin,ficc,权益"`
+	Authority       int    `description:"管理权限,0:无,1:部门负责人,2:小组负责人,或者ficc销售主管,4:ficc销售组长"`
+}
+
+type RegisterReq struct {
+	Password    string
+	Name        string //客户名称
+	CompanyName string //公司名称
+	Email       string //邮箱地址
+	SmsCode     string //验证码
+}
+
+type ModifyPwdReq struct {
+	OldPwd string `description:"旧密码"`
+	NewPwd string `description:"新密码"`
+}
+
+type UserInfo struct {
+	english_report_email.Email
+	LoginToken string
+}
+
+// GetInfoByClaims 从Claims中获取用户信息
+func GetInfoByClaims(c *gin.Context) (userInfo UserInfo) {
+	//获取jwt数据失败
+	claims, _ := c.Get("userInfo")
+	userInfo = claims.(UserInfo)
+	return
+}
+
+type BindMobileReq struct {
+	CountryCode string `description:"区号"`
+	Mobile      string
+	SmsCode     string //验证码
+}
+
+type ForgetPwdReq struct {
+	Type        int    `description:"类型 1:邮箱 2:手机"`
+	CountryCode string `description:"区号"`
+	Account     string `description:"账号"`
+	Password    string `description:"密码"`
+	SmsCode     string
+}
+
+type ModifyMobile struct {
+	CountryCode string `description:"区号"`
+	OldMobile   string
+	NewMobile   string
+	SmsCode     string
+}

+ 15 - 1
utils/constants.go

@@ -23,7 +23,7 @@ const (
 )
 
 const (
-	APPNAME          = "弘则人力资源管理系统"
+	APPNAME          = "弘则英文研报系统"
 	EmailSendToUsers = "317699326@qq.com;984198890@qq.com;hsun@hzinsights.com;xyxie@hzinsights.com"
 )
 
@@ -44,3 +44,17 @@ const (
 	HRSYSTEM_LOGIN_TOKEN_NO_TRUST = "hrSystem:login:no_trust:"        //管理后台登录(不可信登录态)
 	HRSYSTEM_LOGIN_ADMINID_IP = "hrSystem:login:admin_id:"
 )
+
+// 聚合短信
+var (
+	JhGnTplId = "65692" //聚合国内模板编码
+	JhGjTplId = "10054" //聚合国内模板编码
+
+	JhGnAppKey = "4c8504c49dd335e99cfd7b6a3a9e2415" //聚合国内AppKey
+	JhGjAppKey = "3326ad2c1047a4cd92ace153e6044ca3"
+)
+
+// 加密key
+const (
+	KEY = "wdO40P8eCNXEqZbX44pcl9tN"
+)