Files
bl/modules/base/service/base_sys_reg.go
昔念 da9286d3d8 ```
feat(fight): 调整技能效果命中逻辑与回合开始处理

- 修改了技能效果命中的判定顺序,确保暴击计算在效果添加之前执行
- 修复了回合开始时敌我双方状态结算的上下文错误
- 优化了效果缓存初始化逻辑,避免重复添加相同效果
- 增加了效果去重判断,防止完全相同的效果被重复添加
- 调整了战斗循环中结束逻辑的位置,确保广播和通道关闭正确执行
- 更新了部分日志提示信息,使其更符合实际业务含义
- 移除了部分无用代码和注释,提高
2025-11-11 01:10:26 +08:00

300 lines
8.2 KiB
Go

package service
import (
"blazing/common/data/share"
"blazing/cool"
v1 "blazing/modules/base/api/v1"
"blazing/modules/base/model"
"context"
"crypto/tls"
"fmt"
"html/template"
"log"
"net"
"net/smtp"
"strings"
"time"
"github.com/gogf/gf/v2/crypto/gmd5"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/util/gconv"
)
func (s *BaseSysLoginService) Reg(ctx context.Context, req *v1.BaseOpenLoginReq) (result *TokenResult, err error) {
var (
captchaId = req.CaptchaId
verifyCode = req.VerifyCode
password = req.Password
username = req.Username
baseSysUser = model.NewBaseSysUser()
)
vcode, _ := cool.CacheManager.Get(ctx, "login:"+captchaId)
if vcode.String() != verifyCode {
err = gerror.New("验证码错误")
return
}
md5password, _ := gmd5.Encrypt(password)
var user *model.BaseSysUser
cool.DBM(baseSysUser).Where("username=?", username).Where("password=?", md5password).Where("status=?", 1).Scan(&user)
if user == nil {
err = gerror.New("账户或密码不正确~")
return
}
result, err = s.generateTokenByUser(ctx, user)
if err != nil {
return
}
return
}
// 10分钟内限制请求 ip->次数 邮箱->次数
// 验证码对redis传,防止被重复操作
// var emailcache = expirable.NewLRU[string, int](0, nil, time.Millisecond*10)
var ipcache = gcache.New(1000)
func (s *BaseSysLoginService) Email(ctx context.Context, req *v1.BaseOpenEmailReq) (result *TokenResult, err error) {
var (
r = g.RequestFromCtx(ctx)
//baseSysUser = model.NewBaseSysUser()
)
ip := r.GetClientIp()
v, ok2 := ipcache.Get(context.Background(), ip)
if ok2 != nil || v.Int() > 3 {
return nil, gerror.New("操作过于频繁,请稍后再试")
}
ipcache.Set(context.Background(), ip, v.Int()+1, 10*time.Minute)
ok1, _ := share.ShareManager.EmailCodeExists(req.Email)
if ok1 {
return nil, gerror.New("注册码已下发 ")
}
// 发送验证码
code, _ := share.ShareManager.SaveEmailCode(req.Email, time.Millisecond*10)
SendVerificationCode(req.Email, code)
return
}
// SMTPConfig 邮件发送配置
type SMTPConfig struct {
Host string // SMTP服务器地址
Port int // SMTP端口
Username string // 发件人邮箱
Password string // SMTP授权密码
}
// 默认腾讯企业邮配置(可根据实际情况修改)
var DefaultSMTPConfig = SMTPConfig{
Host: "smtp.qcloudmail.com",
Port: 465,
Username: "1@seersun.com",
Password: "z1Tq6v45vXbYQGBrqOUE",
}
// VerificationCodeData 验证码邮件模板数据
type VerificationCodeData struct {
Code string // 验证码
ValidMin int // 有效期(分钟)
Platform string // 平台名称
Hotline string // 客服热线
}
// 验证码邮件HTML模板
const verificationCodeTemplate = `<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>验证码通知</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; font-family: "Microsoft YaHei", Arial, sans-serif; }
body { background: #f5f7fa; padding: 20px 0; }
.email-container { max-width: 550px; margin: 0 auto; background: #fff; border-radius: 12px; box-shadow: 0 3px 15px rgba(0,0,0,0.05); overflow: hidden; }
.email-header { background: linear-gradient(135deg, #667eea, #764ba2); padding: 28px; text-align: center; }
.header-icon { width: 48px; height: 48px; margin: 0 auto 12px; background: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; }
.icon-code { color: #667eea; font-size: 24px; font-weight: 700; }
.header-title { color: #fff; font-size: 20px; font-weight: 600; }
.email-content { padding: 30px 24px; text-align: center; }
.content-desc { font-size: 15px; color: #666; line-height: 1.8; margin-bottom: 28px; }
.code-box { display: inline-block; background: #f8f9fa; border-radius: 8px; padding: 16px 32px; margin-bottom: 28px; }
.verify-code { font-size: 28px; color: #667eea; font-weight: 700; letter-spacing: 8px; }
.warning-box { background: #fff8e1; border-radius: 8px; padding: 14px; margin: 0 20px 24px; }
.warning-text { font-size: 13px; color: #e65100; line-height: 1.6; }
.footer-note { font-size: 12px; color: #999; line-height: 1.5; }
.email-footer { background: #f8f9fa; padding: 20px; text-align: center; font-size: 11px; color: #999; margin-top: 16px; }
</style>
</head>
<body>
<div class="email-container">
<!-- 邮件头部 -->
<div class="email-header">
<div class="header-icon">
<span class="icon-code">注册</span>
</div>
<div class="header-title">验证码通知</div>
</div>
<!-- 邮件内容 -->
<div class="email-content">
<p class="content-desc">尊敬的用户,您好!您正在进行身份验证操作,本次验证码如下:</p>
<!-- 验证码展示框 -->
<div class="code-box">
<span class="verify-code">{{.Code}}</span>
</div>
<!-- 提醒框 -->
<div class="warning-box">
<p class="warning-text">⚠ 验证码有效期为{{.ValidMin}}分钟,请尽快完成验证。如非本人操作,请忽略此邮件。</p>
</div>
<p class="footer-note">为保障您的账号安全,请勿将验证码泄露给他人。</p>
</div>
<!-- 邮件底部 -->
<div class="email-footer">
<p>© 2025 {{.Platform}} 版权所有 | 官网:{{.Hotline}}</p>
</div>
</div>
</body>
</html>`
// SendVerificationCode 发送验证码邮件
// to: 收件人邮箱
// code: 验证码
// 返回错误信息
func SendVerificationCode(to string, code int) error {
// 模板数据
data := VerificationCodeData{
Code: gconv.String(code),
ValidMin: 10, // 有效期10分钟
Platform: "骄阳号", // 可替换为实际平台名称
Hotline: "seersun.com", // 可替换为实际客服热线
}
// 生成邮件内容
body, err := renderTemplate(verificationCodeTemplate, data)
if err != nil {
return fmt.Errorf("渲染模板失败: %w", err)
}
// 发送邮件
return sendMail(
DefaultSMTPConfig,
to,
"验证码通知",
body,
)
}
// renderTemplate 渲染模板
func renderTemplate(tplStr string, data interface{}) (string, error) {
tpl, err := template.New("verification").Parse(tplStr)
if err != nil {
return "", err
}
buf := new(strings.Builder)
if err := tpl.Execute(buf, data); err != nil {
return "", err
}
return buf.String(), nil
}
// sendMail 发送邮件核心函数
func sendMail(config SMTPConfig, to, subject, body string) error {
// 构建邮件头部
header := make(map[string]string)
header["From"] = fmt.Sprintf("骄阳号 <%s>", config.Username)
header["To"] = to
header["Subject"] = subject
header["Content-Type"] = "text/html; charset=UTF-8"
// 拼接邮件内容
message := ""
for k, v := range header {
message += fmt.Sprintf("%s: %s\r\n", k, v)
}
message += "\r\n" + body
// 认证信息
auth := smtp.PlainAuth(
"",
config.Username,
config.Password,
config.Host,
)
// 发送邮件
addr := fmt.Sprintf("%s:%d", config.Host, config.Port)
return SendMailWithTLS(addr, auth, config.Username, []string{to}, []byte(message))
}
// Dial 创建TLS连接的SMTP客户端
func Dial(addr string) (*smtp.Client, error) {
conn, err := tls.Dial("tcp", addr, nil)
if err != nil {
log.Println("tls.Dial Error:", err)
return nil, err
}
host, _, _ := net.SplitHostPort(addr)
return smtp.NewClient(conn, host)
}
// SendMailWithTLS 使用TLS发送邮件
func SendMailWithTLS(addr string, auth smtp.Auth, from string,
to []string, msg []byte) (err error) {
c, err := Dial(addr)
if err != nil {
log.Println("创建SMTP客户端失败:", err)
return err
}
defer c.Close()
if auth != nil {
if ok, _ := c.Extension("AUTH"); ok {
if err = c.Auth(auth); err != nil {
log.Println("认证失败:", err)
return err
}
}
}
if err = c.Mail(from); err != nil {
return err
}
for _, addr := range to {
if err = c.Rcpt(addr); err != nil {
return err
}
}
w, err := c.Data()
if err != nil {
return err
}
_, err = w.Write(msg)
if err != nil {
return err
}
if err = w.Close(); err != nil {
return err
}
return c.Quit()
}
// TestSendVerificationCode 测试发送验证码邮件
func TestSendVerificationCode() error {
// 测试发送验证码为123456的邮件
return SendVerificationCode("3361562035@qq.com", 123456)
}