diff --git a/README.md b/README.md index 75bcbd0..84f9661 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,3 @@ -# OneAuth - -统一验证及应用管理服务 - -[Demo](https://oa.veypi.com) - -## 使用方法 - -## 引入 - /init.go - -```go - -``` - +# VBase +对标 Firebase 的后端服务,基于 vyes/vigo 框架实现,提供用户认证、数据库存储、文件存储等功能。 diff --git a/api/init.go b/api/init.go index e1a697f..dfa877a 100644 --- a/api/init.go +++ b/api/init.go @@ -9,6 +9,7 @@ package api import ( "github.com/veypi/OneAuth/api/app" + "github.com/veypi/OneAuth/api/sms" "github.com/veypi/OneAuth/api/token" "github.com/veypi/OneAuth/api/user" "github.com/veypi/OneAuth/libs/auth" @@ -22,8 +23,9 @@ var ( _ = Router.Extend("user", user.Router) _ = Router.Extend("token", token.Router) _ = Router.Extend("app", app.Router) + _ = Router.Extend("sms", sms.Router) ) -var _ = Router.Any("*", func(x *vigo.X) error { +var _ = Router.Any("*", vigo.SkipBefore, func(x *vigo.X) error { return vigo.ErrNotFound }) diff --git a/api/sms/init.go b/api/sms/init.go new file mode 100644 index 0000000..522e3c5 --- /dev/null +++ b/api/sms/init.go @@ -0,0 +1,14 @@ +// +// init.go +// Copyright (C) 2025 veypi +// +// Distributed under terms of the MIT license. +// + +package sms + +import "github.com/vyes-ai/vigo" + +var Router = vigo.NewRouter() + + diff --git a/api/sms/send.go b/api/sms/send.go new file mode 100644 index 0000000..9df3303 --- /dev/null +++ b/api/sms/send.go @@ -0,0 +1,111 @@ +package sms + +import ( + "fmt" + "time" + + "github.com/veypi/OneAuth/cfg" + "github.com/veypi/OneAuth/libs/sms_providers" + "github.com/veypi/OneAuth/libs/utils" + "github.com/veypi/OneAuth/models" + "github.com/vyes-ai/vigo" + "github.com/vyes-ai/vigo/contrib/limiter" + "gorm.io/gorm" +) + +// SendCodeRequest 发送验证码请求 +type SendCodeRequest struct { + Phone string `json:"phone"` + Region string `json:"region"` + Purpose string `json:"purpose"` + TemplateID string `json:"template_id"` +} + +// SendCodeResponse 发送验证码响应 +type SendCodeResponse struct { + ID uint `json:"id"` + Phone string `json:"phone"` + ExpiresAt time.Time `json:"expires_at"` + Interval int `json:"interval"` // 下次可发送间隔(秒) +} + +var _ = Router.Post("/", vigo.SkipBefore, limiter.NewAdvancedRequestLimiter(time.Minute*3, 5, time.Second*30), sendCode) + +// SendCode 发送验证码 +func sendCode(x *vigo.X) (any, error) { + req := &SendCodeRequest{} + err := x.Parse(req) + if err != nil { + return nil, err + } + // 1. 验证手机号 + normalizedPhone := utils.NormalizePhoneNumber(req.Phone) + if !utils.ValidatePhoneNumber(normalizedPhone) { + return nil, fmt.Errorf("invalid phone number: %s", req.Phone) + } + + // 2. 检查区域配置 + provider, err := sms_providers.GetSMSProvider(req.Region) + if err != nil { + return nil, err + } + + // 3. 检查发送频率限制 + if err := CheckSendInterval(normalizedPhone, req.Region, req.Purpose); err != nil { + return nil, err + } + + // 4. 检查每日发送次数限制 + if err := CheckDailyLimit(normalizedPhone, req.Region); err != nil { + return nil, err + } + + // 5. 生成验证码 + code, err := utils.GenerateCode(cfg.Config.SMS.Global.CodeLength) + if err != nil { + return nil, fmt.Errorf("failed to generate code: %w", err) + } + + // 6. 创建验证码记录 + smsCode := &models.SMSCode{ + Phone: normalizedPhone, + Code: code, + Region: req.Region, + Purpose: req.Purpose, + Status: models.CodeStatusPending, + ExpiresAt: time.Now().Add(cfg.Config.SMS.Global.CodeExpiry), + } + + // 7. 发送短信 + sendReq := &sms_providers.SendSMSRequest{ + Phone: normalizedPhone, + TemplateID: req.TemplateID, + Region: req.Region, + Purpose: req.Purpose, + Params: map[string]string{ + "code": code, + }, + } + err = cfg.DB().Transaction(func(tx *gorm.DB) error { + err := tx.Create(smsCode).Error + if err != nil { + return err + } + smsID, err := provider.SendSMS(x.Context(), sendReq) + LogSMS(normalizedPhone, req.Region, provider.GetName(), smsID, err) + if err != nil || smsID == "" { + return fmt.Errorf("failed to send sms: %v", err) + } + return nil + }) + if err != nil { + return nil, err + } + + return &SendCodeResponse{ + ID: smsCode.ID, + Phone: normalizedPhone, + ExpiresAt: smsCode.ExpiresAt, + Interval: int(cfg.Config.SMS.Global.SendInterval.Seconds()), + }, nil +} diff --git a/api/sms/utils.go b/api/sms/utils.go new file mode 100644 index 0000000..26d1430 --- /dev/null +++ b/api/sms/utils.go @@ -0,0 +1,90 @@ +// +// utils.go +// Copyright (C) 2025 veypi +// +// Distributed under terms of the MIT license. +// + +package sms + +import ( + "fmt" + "time" + + "github.com/veypi/OneAuth/cfg" + "github.com/veypi/OneAuth/models" + "gorm.io/gorm" +) + +// checkDailyLimit 检查每日发送次数限制 +func CheckDailyLimit(phone, region string) error { + today := time.Now().Truncate(24 * time.Hour) + tomorrow := today.Add(24 * time.Hour) + + var count int64 + err := cfg.DB().Model(&models.SMSCode{}). + Where("phone = ? AND region = ? AND created_at >= ? AND created_at < ?", + phone, region, today, tomorrow). + Count(&count).Error + + if err != nil { + return fmt.Errorf("failed to check daily limit: %w", err) + } + + if count >= int64(cfg.Config.SMS.Global.MaxDailyCount) { + return fmt.Errorf("daily sms limit exceeded") + } + + return nil +} + +// checkSendInterval 检查发送间隔 +func CheckSendInterval(phone, region, purpose string) error { + var lastCode models.SMSCode + err := cfg.DB().Where("phone = ? AND region = ? AND purpose = ?", phone, region, purpose). + Order("created_at DESC"). + First(&lastCode).Error + + if err != nil && err != gorm.ErrRecordNotFound { + return fmt.Errorf("failed to check send interval: %w", err) + } + + if err == nil { + timeSinceLastSend := time.Since(lastCode.CreatedAt) + if timeSinceLastSend < cfg.Config.SMS.Global.SendInterval { + remaining := cfg.Config.SMS.Global.SendInterval - timeSinceLastSend + return fmt.Errorf("please wait %d seconds before sending again", int(remaining.Seconds())) + } + } + + return nil +} + +// logSMS 记录短信发送日志 +func LogSMS(phone, region, provider, messageID string, err error) { + log := &models.SMSLog{ + Phone: phone, + Region: region, + Provider: provider, + MessageID: messageID, + Status: "ok", + } + if err != nil { + log.Status = "failed" + log.Error = err.Error() + } + cfg.DB().Create(log) +} + +// CleanupExpiredCodes 清理过期的验证码 +func CleanupExpiredCodes() error { + result := cfg.DB().Model(&models.SMSCode{}). + Where("status = ? AND expires_at < ?", models.CodeStatusPending, time.Now()). + Update("status", models.CodeStatusExpired) + + if result.Error != nil { + return fmt.Errorf("failed to cleanup expired codes: %w", result.Error) + } + + return nil +} diff --git a/api/sms/validate.go b/api/sms/validate.go new file mode 100644 index 0000000..0912043 --- /dev/null +++ b/api/sms/validate.go @@ -0,0 +1,72 @@ +// +// validate.go +// Copyright (C) 2025 veypi +// +// Distributed under terms of the MIT license. +// + +package sms + +import ( + "fmt" + "time" + + "github.com/veypi/OneAuth/cfg" + "github.com/veypi/OneAuth/libs/utils" + "github.com/veypi/OneAuth/models" + "gorm.io/gorm" +) + +// VerifyCode 验证验证码 +func VerifyCode(Phone, Code, Region, Purpose string) error { + normalizedPhone := utils.NormalizePhoneNumber(Phone) + + // 1. 查找最新的待验证码 + var smsCode models.SMSCode + err := cfg.DB().Where("phone = ? AND region = ? AND purpose = ? AND status = ?", + normalizedPhone, Region, Purpose, models.CodeStatusPending). + Order("created_at DESC"). + First(&smsCode).Error + + if err != nil { + if err == gorm.ErrRecordNotFound { + return fmt.Errorf("verification code not found or already used") + } + return fmt.Errorf("failed to query sms code: %w", err) + } + + // 2. 检查验证码是否过期 + if smsCode.IsExpired() { + cfg.DB().Model(&smsCode).Updates(map[string]any{ + "status": models.CodeStatusExpired, + }) + return fmt.Errorf("verification code has expired") + } + + // 3. 检查是否已达到最大尝试次数 + if !smsCode.CanRetry(cfg.Config.SMS.Global.MaxAttempts) { + cfg.DB().Model(&smsCode).Updates(map[string]any{ + "status": models.CodeStatusFailed, + }) + return fmt.Errorf("verification failed too many times") + } + + // 4. 验证码不匹配 + if smsCode.Code != Code { + cfg.DB().Model(&smsCode).Updates(map[string]any{ + "attempts": smsCode.Attempts + 1, + }) + + remaining := cfg.Config.SMS.Global.MaxAttempts - smsCode.Attempts - 1 + return fmt.Errorf("verification code incorrect, %d attempts remaining", remaining) + } + + // 5. 验证成功 + now := time.Now() + cfg.DB().Model(&smsCode).Updates(map[string]any{ + "status": models.CodeStatusUsed, + "used_at": &now, + }) + + return nil +} diff --git a/api/token/create.go b/api/token/create.go index 55967e7..2e8e97c 100644 --- a/api/token/create.go +++ b/api/token/create.go @@ -99,7 +99,7 @@ func tokenPost(x *vigo.X) (any, error) { if opts.Device != nil { newToken.Device = *opts.Device } - newToken.Ip = x.GetRemoteIp() + newToken.Ip = x.GetRemoteIP() logv.AssertError(cfg.DB().Create(newToken).Error) // gen other app token claim.ID = newToken.ID diff --git a/api/user/create.go b/api/user/create.go index ca451e7..f523352 100644 --- a/api/user/create.go +++ b/api/user/create.go @@ -16,6 +16,7 @@ import ( "math/rand" "github.com/google/uuid" + "github.com/veypi/OneAuth/api/sms" "github.com/veypi/OneAuth/cfg" "github.com/veypi/OneAuth/libs/utils" "github.com/veypi/OneAuth/models" @@ -26,12 +27,15 @@ import ( var _ = Router.Post("/", vigo.SkipBefore, publicLimits, userPost) type postOpts struct { - Username string `json:"username" gorm:"varchar(100);unique;default:not null" parse:"json"` - Code string `json:"code" gorm:"varchar(128)" parse:"json"` + Username string `json:"username" gorm:"varchar(100);unique;default:not null" parse:"json"` + Code string `json:"code" gorm:"varchar(128)" parse:"json"` + Phone string `json:"phone" gorm:"varchar(50);unique;default:null" parse:"json"` + VerifyCode string `json:"verify_code" parse:"json"` + Region string `json:"region" parse:"json"` + Nickname *string `json:"nickname" parse:"json"` Icon *string `json:"icon" parse:"json"` Email *string `json:"email" gorm:"varchar(20);unique;default:null" parse:"json"` - Phone *string `json:"phone" gorm:"varchar(50);unique;default:null" parse:"json"` } func userPost(x *vigo.X) (any, error) { @@ -43,6 +47,12 @@ func userPost(x *vigo.X) (any, error) { data := &models.User{} data.ID = strings.ReplaceAll(uuid.New().String(), "-", "") + data.Phone = opts.Region + opts.Phone + data.Region = opts.Region + err = sms.VerifyCode(opts.Phone, opts.VerifyCode, opts.Region, "signup") + if err != nil { + return nil, vigo.ErrArgInvalid.WithArgs("verify code").WithString(err.Error()) + } data.Username = opts.Username data.Code = opts.Code data.Salt = utils.RandSeq(16) @@ -73,9 +83,6 @@ func userPost(x *vigo.X) (any, error) { if opts.Email != nil { data.Email = *opts.Email } - if opts.Phone != nil { - data.Phone = *opts.Phone - } data.Status = 1 err = cfg.DB().Transaction(func(tx *gorm.DB) error { err := tx.Create(data).Error diff --git a/api/user/login.go b/api/user/login.go index 4839430..bb104ee 100644 --- a/api/user/login.go +++ b/api/user/login.go @@ -12,6 +12,7 @@ import ( "time" "github.com/golang-jwt/jwt/v5" + "github.com/veypi/OneAuth/api/sms" "github.com/veypi/OneAuth/cfg" "github.com/veypi/OneAuth/libs/auth" "github.com/veypi/OneAuth/libs/utils" @@ -21,24 +22,24 @@ import ( "github.com/vyes-ai/vigo/logv" ) -var publicLimits = limiter.NewAdvancedRequestLimiter(limiter.LimiterConfig{ - Window: time.Minute * 5, - MaxRequests: 20, - MinInterval: time.Second * 3, -}).Limit +var publicLimits = limiter.NewAdvancedRequestLimiter(time.Minute*5, 20, time.Second*3, nil).Limit var _ = Router.Post("/login", vigo.SkipBefore, publicLimits, userLogin) type loginOpts struct { - UserName string `json:"username" parse:"json"` - Code string `json:"code" parse:"json"` - Phone *string `json:"phone" parse:"json"` - Email *string `json:"email" parse:"json"` - Type *string `json:"type" parse:"json"` - AppID *string `json:"app_id" parse:"json"` - Device *string `json:"device" parse:"json"` + UserName string `json:"username" parse:"json"` + Code string `json:"code" parse:"json"` + + VerifyCode string `json:"verify_code" parse:"json"` + Region string `json:"region" parse:"json"` + Phone string `json:"phone" parse:"json"` + + Email string `json:"email" parse:"json"` + Type *string `json:"type" parse:"json"` + AppID *string `json:"app_id" parse:"json"` + Device *string `json:"device" parse:"json"` } func userLogin(x *vigo.X) (any, error) { @@ -57,7 +58,7 @@ func userLogin(x *vigo.X) (any, error) { } switch typ { case "phone": - query = query.Where("phone = ?", opts.Phone) + query = query.Where("phone = ?", opts.Region+opts.Phone) case "email": query = query.Where("email = ?", opts.Email) default: @@ -68,16 +69,22 @@ func userLogin(x *vigo.X) (any, error) { return nil, vigo.ErrNotFound } logv.Info().Str("user", user.ID).Msg("login") - code, err := base64.URLEncoding.DecodeString(opts.Code) - if err != nil { - return nil, vigo.ErrArgInvalid.WithArgs("code") - } - logv.Warn().Msgf("code: %s", code) + if opts.VerifyCode != "" { + err = sms.VerifyCode(opts.Phone, opts.VerifyCode, opts.Region, "signin") + if err != nil { + logv.Warn().Msgf("verify code: %v", err) + return nil, vigo.ErrNotAuthorized.WithError(err) + } + } else { + code, err := base64.URLEncoding.DecodeString(opts.Code) + if err != nil { + return nil, vigo.ErrArgInvalid.WithArgs("code") + } - ncode, err := utils.AesDecrypt([]byte(user.Code), utils.PKCS7Padding(code, 32), []byte(user.Salt)) - logv.Warn().Msgf("id: %s\n%s", ncode, user.ID) - if err != nil || string(ncode) != user.ID { - return nil, vigo.ErrNotAuthorized + ncode, err := utils.AesDecrypt([]byte(user.Code), utils.PKCS7Padding(code, 32), []byte(user.Salt)) + if err != nil || string(ncode) != user.ID { + return nil, vigo.ErrNotAuthorized + } } aid := cfg.Config.ID if opts.AppID != nil && *opts.AppID != "" { @@ -92,7 +99,7 @@ func userLogin(x *vigo.X) (any, error) { if opts.Device != nil { data.Device = *opts.Device } - data.Ip = x.GetRemoteIp() + data.Ip = x.GetRemoteIP() logv.AssertError(cfg.DB().Create(data).Error) claim := &auth.Claims{} claim.IssuedAt = jwt.NewNumericDate(time.Now()) diff --git a/cfg/cfg.go b/cfg/cfg.go index 0145e47..b8fab76 100644 --- a/cfg/cfg.go +++ b/cfg/cfg.go @@ -7,20 +7,42 @@ package cfg -import "time" +import ( + "os" + "time" +) type Options struct { - DSN string `json:"dsn"` // Data Source Name - DB string `json:"db"` // DB type: mysql, postgres, sqlite + DSN string `json:"dsn"` // Data Source Name + DB string `json:"db"` // DB type: mysql, postgres, sqlite + RedisAddr string `json:"redis_addr"` + ID string `json:"id"` Key string `json:"key"` TokenExpire time.Duration `json:"token_expire"` // Token expiration time in seconds + SMS *SMSConfig `json:"sms"` } var Config = &Options{ - TokenExpire: time.Second * 100, - ID: "test", - Key: "asdfghjklqwertyuiopzxcvbnm1234567890", - DSN: "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8&parseTime=True&loc=Local", - DB: "mysql", + TokenExpire: time.Minute * 120, + ID: getEnv("APPID", "test"), + Key: getEnv("APPKEY", "asdfghjklqwertyuiopzxcvbnm1234567890"), + DSN: getEnv("DSN", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8&parseTime=True&loc=Local"), + DB: getEnv("DB", "mysql"), + SMS: defaultSMS(), +} + +func getEnv(key, defaultValue string) string { + v := os.Getenv(key) + if v != "" { + return v + } + return defaultValue +} + +type PublicSettings struct { + SMS string `json:"sms"` + SMSKey string `json:"sms_key"` + SMSSecret string `json:"sms_secret"` + SMSRegion string `json:"sms_region"` } diff --git a/cfg/sms.go b/cfg/sms.go new file mode 100644 index 0000000..5abecf3 --- /dev/null +++ b/cfg/sms.go @@ -0,0 +1,51 @@ +package cfg + +import ( + "time" +) + +// Config 短信验证码配置 +type SMSConfig struct { + + // 区域配置 +86/.../global + Regions map[string]RegionConfig `json:"regions"` + Default RegionConfig `json:"default"` // 默认区域配置 + + // 全局配置 + Global GlobalConfig `json:"global"` +} + +// RegionConfig 区域配置 +type RegionConfig struct { + Provider string `json:"provider"` // aliyun, tencent + TemplateID string `json:"template_id"` // 模板ID + Key string `json:"key"` + Secret string `json:"secret"` + SignName string `json:"sign_name"` + Endpoint string `json:"endpoint"` +} + +// GlobalConfig 全局配置 +type GlobalConfig struct { + CodeLength int `json:"code_length" usage:"验证码长度,默认6位"` + CodeExpiry time.Duration `json:"code_expiry" usage:"验证码有效期,默认5分钟"` + SendInterval time.Duration `json:"send_interval" usage:"发送间隔,默认60秒"` + MaxAttempts int `json:"max_attempts" usage:"最大重试次数,默认3次"` + MaxDailyCount int `json:"max_daily_count" usage:"每日最大发送次数,默认100次,0禁用,-1不限制"` +} + +// DefaultConfig 默认配置 +func defaultSMS() *SMSConfig { + return &SMSConfig{ + Global: GlobalConfig{ + CodeLength: 6, + CodeExpiry: 5 * time.Minute, + SendInterval: 60 * time.Second, + MaxAttempts: 3, + MaxDailyCount: 100, + }, + Default: RegionConfig{ + Provider: "aliyun", + }, + } +} diff --git a/cli/main.go b/cli/main.go index ac8b141..ef69660 100644 --- a/cli/main.go +++ b/cli/main.go @@ -36,6 +36,7 @@ func init() { cmdMain.StringVar(&cliOpts.Host, "host", "0.0.0.0", "host") cmdMain.IntVar(&cliOpts.Port, "p", 4000, "port") cmdMain.StringVar(&cliOpts.LoggerLevel, "l", "info", "log level") + cmdMain.AutoRegister(cliOpts) cmdMain.Before = func() error { flags.LoadCfg(*configFile, cfg.Config) diff --git a/go.mod b/go.mod index 4060ba8..bf09970 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,11 @@ replace github.com/veypi/vyes-ui => ../vyes-ui/ replace github.com/vyes-ai/vigo => ../vigo/ require ( + github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.9 + github.com/alibabacloud-go/dysmsapi-20170525/v5 v5.1.2 + github.com/alibabacloud-go/tea v1.3.10 + github.com/alibabacloud-go/tea-utils/v2 v2.0.7 + github.com/aliyun/credentials-go v1.4.7 github.com/glebarez/sqlite v1.11.0 github.com/golang-jwt/jwt/v5 v5.2.3 github.com/google/uuid v1.6.0 @@ -20,6 +25,11 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect + github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect + github.com/alibabacloud-go/debug v1.0.1 // indirect + github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect + github.com/alibabacloud-go/openapi-util v0.1.1 // indirect + github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/glebarez/go-sqlite v1.21.2 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect @@ -29,16 +39,22 @@ require ( github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect + github.com/joho/godotenv v1.5.1 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/kr/text v0.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rs/zerolog v1.34.0 // indirect + github.com/tjfoc/gmsm v1.4.1 // indirect golang.org/x/net v0.42.0 // indirect golang.org/x/sync v0.16.0 // indirect golang.org/x/sys v0.34.0 // indirect golang.org/x/text v0.27.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/libc v1.22.5 // indirect diff --git a/go.sum b/go.sum index d5f8dc6..b19c539 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,63 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 h1:eIf+iGJxdU4U9ypaUfbtOWCsZSbTb8AUHvyPrxu6mAA= +github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6/go.mod h1:4EUIoxs/do24zMOGGqYVWgw0s9NtiylnJglOeEB5UJo= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 h1:zE8vH9C7JiZLNJJQ5OwjU9mSi4T9ef9u3BURT6LCLC8= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5/go.mod h1:tWnyE9AjF8J8qqLk645oUmVUnFybApTQWklQmi5tY6g= +github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY= +github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI= +github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE= +github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8= +github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc= +github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.11/go.mod h1:wHxkgZT1ClZdcwEVP/pDgYK/9HucsnCfMipmJgCz4xY= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.9 h1:7P0KWfed/YMtpeuW3E2iwokzoz9L7H9rB+VZzg5DeBs= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.9/go.mod h1:kgnXaV74AVjM3ZWJu1GhyXGuCtxljJ677oUfz6MyJOE= +github.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg= +github.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ= +github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo= +github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA= +github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY= +github.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc= +github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg= +github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc= +github.com/alibabacloud-go/dysmsapi-20170525/v5 v5.1.2 h1:mNSlLE7QQiZLmC55BJog3PFJFtQp10lbnnEWWIxeCvM= +github.com/alibabacloud-go/dysmsapi-20170525/v5 v5.1.2/go.mod h1:mYOaEwXaib4RLB2NY8cXFjKbxPQHUqt6lhPEOvqR8aw= +github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q= +github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE= +github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws= +github.com/alibabacloud-go/openapi-util v0.1.1 h1:ujGErJjG8ncRW6XtBBMphzHTvCxn4DjrVw4m04HsS28= +github.com/alibabacloud-go/openapi-util v0.1.1/go.mod h1:/UehBSE2cf1gYT43GV4E+RxTdLRzURImCYY0aRmlXpw= +github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg= +github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= +github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= +github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= +github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= +github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= +github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk= +github.com/alibabacloud-go/tea v1.3.10 h1:J0Ke8iMyoxX2daj90hdPr1QgfxJnhR8SOflB910o/Dk= +github.com/alibabacloud-go/tea v1.3.10/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg= +github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE= +github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4= +github.com/alibabacloud-go/tea-utils/v2 v2.0.6/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I= +github.com/alibabacloud-go/tea-utils/v2 v2.0.7 h1:WDx5qW3Xa5ZgJ1c8NfqJkF6w+AU5wB8835UdhPr6Ax0= +github.com/alibabacloud-go/tea-utils/v2 v2.0.7/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I= +github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= +github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw= +github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0= +github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM= +github.com/aliyun/credentials-go v1.4.5/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U= +github.com/aliyun/credentials-go v1.4.7 h1:T17dLqEtPUFvjDRRb5giVvLh6dFT8IcNFJJb7MeyCxw= +github.com/aliyun/credentials-go v1.4.7/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= +github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= +github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -7,6 +65,9 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw= @@ -16,10 +77,30 @@ github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqw github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0= github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= @@ -32,8 +113,16 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -41,9 +130,18 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -52,31 +150,171 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7 github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/vyes-ai/vigo v0.5.0 h1:Cdbq93VL9Eecp09yk6fCJeI18PZijj7M0irLH2Hx26s= -github.com/vyes-ai/vigo v0.5.0/go.mod h1:FTltuMDGidB5YNvklD/QayIPPLQLza7nRkp2IErHGcU= +github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= +github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= +github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -86,6 +324,8 @@ gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4= gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo= gorm.io/gorm v1.30.1 h1:lSHg33jJTBxs2mgJRfRZeLDG+WZaHYCk3Wtfl6Ngzo4= gorm.io/gorm v1.30.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE= modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY= modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= diff --git a/libs/sms_providers/aliyun.go b/libs/sms_providers/aliyun.go new file mode 100644 index 0000000..421ce2b --- /dev/null +++ b/libs/sms_providers/aliyun.go @@ -0,0 +1,110 @@ +package sms_providers + +import ( + "context" + "encoding/json" + "fmt" + + openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" + dysmsapi20170525 "github.com/alibabacloud-go/dysmsapi-20170525/v5/client" + util "github.com/alibabacloud-go/tea-utils/v2/service" + "github.com/alibabacloud-go/tea/tea" + credential "github.com/aliyun/credentials-go/credentials" + "github.com/veypi/OneAuth/cfg" + "github.com/vyes-ai/vigo" + "github.com/vyes-ai/vigo/logv" +) + +// AliyunProvider 阿里云短信服务 +type AliyunProvider struct { + accessKeyID string + accessKeySecret string + signName string + endpoint string + templateID string +} + +// NewAliyunProvider 创建阿里云短信服务 +func NewAliyunProvider(config cfg.RegionConfig) (SMSProvider, error) { + + if config.Endpoint == "" { + config.Endpoint = "dysmsapi.aliyuncs.com" + } + + return &AliyunProvider{ + accessKeyID: config.Key, + accessKeySecret: config.Secret, + signName: config.SignName, + endpoint: config.Endpoint, + templateID: config.TemplateID, + }, nil +} + +// SendSMS 发送短信 +func (p *AliyunProvider) SendSMS(ctx context.Context, req *SendSMSRequest) (string, error) { + if req.Phone == "" { + return "", fmt.Errorf("phone is required") + } + + // 工程代码建议使用更安全的无AK方式,凭据配置方式请参见:https://help.aliyun.com/document_detail/378661.html。 + credential, err := credential.NewCredential(new(credential.Config).SetType("access_key").SetAccessKeyId(p.accessKeyID).SetAccessKeySecret(p.accessKeySecret)) + // credential, err := credential.NewCredential(nil) + if err != nil { + return "", err + } + + config := &openapi.Config{ + Credential: credential, + } + // Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi + config.Endpoint = tea.String(p.endpoint) + client, err := dysmsapi20170525.NewClient(config) + if err != nil { + return "", err + } + templateID := req.TemplateID + if templateID == "" { + templateID = p.templateID + } + + paramsBytes, _ := json.Marshal(req.Params) + logv.Warn().Msgf("Send SMS to %s, %s, templateID: %s, params: %s", req.Phone, p.signName, templateID, string(paramsBytes)) + sendSmsRequest := &dysmsapi20170525.SendSmsRequest{ + SignName: tea.String(p.signName), + TemplateCode: tea.String(templateID), + PhoneNumbers: tea.String(req.Phone), + TemplateParam: tea.String(string(paramsBytes)), + } + runtime := &util.RuntimeOptions{} + msgID := "" + tryErr := func() (_e error) { + defer func() { + if r := tea.Recover(recover()); r != nil { + _e = r + } + }() + // 复制代码运行请自行打印 API 的返回值 + res, _err := client.SendSmsWithOptions(sendSmsRequest, runtime) + if _err != nil { + return _err + } + if res != nil && res.Body != nil && res.Body.BizId != nil { + msgID = *res.Body.BizId + } + if msgID == "" && res != nil && res.Body != nil && res.Body.Message != nil { + logv.Warn().Msgf("%+v", res) + return vigo.NewError(*res.Body.Message) + } + + return nil + }() + if tryErr != nil { + return "", tryErr + } + return msgID, nil +} + +// GetName 获取服务商名称 +func (p *AliyunProvider) GetName() string { + return "aliyun" +} diff --git a/libs/sms_providers/provider.go b/libs/sms_providers/provider.go new file mode 100644 index 0000000..d3d61cd --- /dev/null +++ b/libs/sms_providers/provider.go @@ -0,0 +1,114 @@ +package sms_providers + +import ( + "context" + "fmt" + + "github.com/veypi/OneAuth/cfg" +) + +// SMSProvider 短信服务商接口 +type SMSProvider interface { + // SendSMS 发送短信 + SendSMS(ctx context.Context, req *SendSMSRequest) (id string, err error) + + // GetName 获取服务商名称 + GetName() string +} + +var factory *ProviderFactory +var providers = make(map[string]SMSProvider) + +func GetSMSProvider(region string) (SMSProvider, error) { + if factory == nil { + factory = NewProviderFactory() + // 初始化各区域的短信服务商 + for region, regionConfig := range cfg.Config.SMS.Regions { + provider, err := factory.Create(regionConfig) + if err != nil { + return nil, fmt.Errorf("failed to create provider for region %s: %w", region, err) + } + providers[region] = provider + } + provider, err := factory.Create(cfg.Config.SMS.Default) + if err != nil { + return nil, fmt.Errorf("failed to create default provider: %w", err) + } + providers["default"] = provider + } + p, ok := providers[region] + if !ok { + p, ok = providers["default"] + if !ok { + return nil, fmt.Errorf("no SMS provider found for region %s", region) + } + } + return p, nil +} + +// SendSMSRequest 发送短信请求 +type SendSMSRequest struct { + Phone string `json:"phone"` // 手机号 + TemplateID string `json:"template_id"` // 模板ID + Params map[string]string `json:"params"` // 模板参数 + Region string `json:"region"` // 区域 + Purpose string `json:"purpose"` // 用途 +} + +// SendSMSResponse 发送短信响应 +type SendSMSResponse struct { + MessageID string `json:"message_id"` // 消息ID + Status string `json:"status"` // 发送状态 + Cost float64 `json:"cost"` // 费用 + Error string `json:"error"` // 错误信息 +} + +// ProviderFactory 服务商工厂 +type ProviderFactory struct { + providers map[string]func(cfg.RegionConfig) (SMSProvider, error) +} + +// NewProviderFactory 创建服务商工厂 +func NewProviderFactory() *ProviderFactory { + factory := &ProviderFactory{ + providers: make(map[string]func(cfg.RegionConfig) (SMSProvider, error)), + } + + // 注册服务商 + factory.Register("aliyun", NewAliyunProvider) + factory.Register("tencent", NewTencentProvider) + + return factory +} + +// Register 注册服务商 +func (f *ProviderFactory) Register(name string, constructor func(cfg.RegionConfig) (SMSProvider, error)) { + f.providers[name] = constructor +} + +// Create 创建服务商实例 +func (f *ProviderFactory) Create(config cfg.RegionConfig) (SMSProvider, error) { + constructor, exists := f.providers[config.Provider] + if !exists { + return nil, &ProviderError{ + Provider: config.Provider, + Message: "unsupported provider", + } + } + + return constructor(config) +} + +// ProviderError 服务商错误 +type ProviderError struct { + Provider string + Message string + Err error +} + +func (e *ProviderError) Error() string { + if e.Err != nil { + return e.Provider + ": " + e.Message + ": " + e.Err.Error() + } + return e.Provider + ": " + e.Message +} diff --git a/libs/sms_providers/tencent.go b/libs/sms_providers/tencent.go new file mode 100644 index 0000000..f4aa12b --- /dev/null +++ b/libs/sms_providers/tencent.go @@ -0,0 +1,46 @@ +package sms_providers + +import ( + "context" + "fmt" + + "github.com/veypi/OneAuth/cfg" +) + +// TencentProvider 腾讯云短信服务 +type TencentProvider struct { + secretID string + secretKey string + sdkAppID string + signName string + region string +} + +// NewTencentProvider 创建腾讯云短信服务 +func NewTencentProvider(config cfg.RegionConfig) (SMSProvider, error) { + + return &TencentProvider{ + secretID: config.Key, + secretKey: config.Secret, + sdkAppID: config.Endpoint, + signName: config.SignName, + region: config.Provider, + }, nil +} + +// SendSMS 发送短信 +func (p *TencentProvider) SendSMS(ctx context.Context, req *SendSMSRequest) (string, error) { + // 这里应该调用腾讯云SDK,为了示例简化处理 + // 实际实现需要集成腾讯云SMS SDK + + // 模拟发送逻辑 + if req.Phone == "" { + return "", fmt.Errorf("phone is empty") + } + return "tencent-message-id-12345", nil +} + +// GetName 获取服务商名称 +func (p *TencentProvider) GetName() string { + return "tencent" +} diff --git a/libs/utils/code_generate.go b/libs/utils/code_generate.go new file mode 100644 index 0000000..76bb1bd --- /dev/null +++ b/libs/utils/code_generate.go @@ -0,0 +1,81 @@ +package utils + +import ( + "crypto/rand" + "fmt" + "math/big" + "strings" +) + +// GenerateCode 生成指定长度的数字验证码 +func GenerateCode(length int) (string, error) { + if length <= 0 { + return "", fmt.Errorf("code length must be positive") + } + + var code strings.Builder + for range length { + digit, err := rand.Int(rand.Reader, big.NewInt(10)) + if err != nil { + return "", fmt.Errorf("failed to generate random digit: %w", err) + } + code.WriteString(digit.String()) + } + + return code.String(), nil +} + +// GenerateAlphaNumericCode 生成字母数字混合验证码 +func GenerateAlphaNumericCode(length int) (string, error) { + if length <= 0 { + return "", fmt.Errorf("code length must be positive") + } + + const charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + var code strings.Builder + + for range length { + index, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset)))) + if err != nil { + return "", fmt.Errorf("failed to generate random character: %w", err) + } + code.WriteByte(charset[index.Int64()]) + } + + return code.String(), nil +} + +// ValidatePhoneNumber 简单的手机号验证 +func ValidatePhoneNumber(phone string) bool { + if len(phone) < 10 || len(phone) > 15 { + return false + } + + // 检查是否都是数字或以+开头 + if phone[0] == '+' { + phone = phone[1:] + } + + for _, char := range phone { + if char < '0' || char > '9' { + return false + } + } + + return true +} + +// NormalizePhoneNumber 标准化手机号 +func NormalizePhoneNumber(phone string) string { + // 移除所有非数字字符,除了+号 + var normalized strings.Builder + for i, char := range phone { + if char == '+' && i == 0 { + normalized.WriteRune(char) + } else if char >= '0' && char <= '9' { + normalized.WriteRune(char) + } + } + + return normalized.String() +} diff --git a/models/init.go b/models/init.go index 2090b4a..f26c606 100644 --- a/models/init.go +++ b/models/init.go @@ -34,7 +34,7 @@ func (m *BaseModel) BeforeCreate(tx *gorm.DB) error { var AllModels = &dbmodels.ModelList{} func init() { - AllModels.Append(User{}, AppUser{}, Resource{}, Access{}, Role{}, UserRole{}, Token{}, App{}) + AllModels.Append(User{}, AppUser{}, Resource{}, Access{}, Role{}, UserRole{}, Token{}, App{}, SMSCode{}, SMSLog{}) } func Migrate() error { diff --git a/models/sms.go b/models/sms.go new file mode 100644 index 0000000..c08a12d --- /dev/null +++ b/models/sms.go @@ -0,0 +1,65 @@ +package models + +import ( + "gorm.io/gorm" + "time" +) + +// SMSCode 短信验证码记录 +type SMSCode struct { + ID uint `gorm:"primarykey" json:"id"` + Phone string `gorm:"index;not null" json:"phone"` // 手机号 + Code string `gorm:"not null" json:"code"` // 验证码 + Region string `gorm:"index;not null" json:"region"` // 区域 + Purpose string `gorm:"index;not null" json:"purpose"` // 用途(注册、登录、重置密码等) + Status CodeStatus `gorm:"default:0" json:"status"` // 状态 + ExpiresAt time.Time `gorm:"index;not null" json:"expires_at"` // 过期时间 + UsedAt *time.Time `gorm:"index" json:"used_at"` // 使用时间 + Attempts int `gorm:"default:0" json:"attempts"` // 验证尝试次数 + SendCount int `gorm:"default:1" json:"send_count"` // 发送次数 + RemoteIP string `gorm:"index" json:"remote_ip"` // 远程IP地址 + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"` +} + +// CodeStatus 验证码状态 +type CodeStatus int + +const ( + CodeStatusPending CodeStatus = iota // 待验证 + CodeStatusUsed // 已使用 + CodeStatusExpired // 已过期 + CodeStatusFailed // 验证失败(超过最大尝试次数) +) + +// SMSLog 短信发送日志 +type SMSLog struct { + ID uint `gorm:"primarykey" json:"id"` + Phone string `gorm:"index;not null" json:"phone"` + Region string `gorm:"index;not null" json:"region"` + Provider string `gorm:"not null" json:"provider"` + MessageID string `gorm:"index" json:"message_id"` // 服务商返回的消息ID + Content string `json:"content"` // 短信内容 + Status string `gorm:"not null" json:"status"` // 发送状态 + Error string `json:"error"` // 错误信息 + Cost float64 `json:"cost"` // 费用 + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"` +} + +// IsExpired 检查验证码是否过期 +func (s *SMSCode) IsExpired() bool { + return time.Now().After(s.ExpiresAt) +} + +// IsUsed 检查验证码是否已使用 +func (s *SMSCode) IsUsed() bool { + return s.Status == CodeStatusUsed && s.UsedAt != nil +} + +// CanRetry 检查是否可以重试验证 +func (s *SMSCode) CanRetry(maxAttempts int) bool { + return s.Status == CodeStatusPending && s.Attempts < maxAttempts && !s.IsExpired() +} diff --git a/models/user.go b/models/user.go index 0ed4a22..9c60473 100644 --- a/models/user.go +++ b/models/user.go @@ -13,8 +13,9 @@ type User struct { Nickname string `json:"nickname" gorm:"type:varchar(100)" parse:"json"` Icon string `json:"icon" parse:"json"` - Email string `json:"email" gorm:"unique;type:varchar(64);null;default:null" parse:"json"` - Phone string `json:"phone" gorm:"type:varchar(64);unique;null;default:null" parse:"json"` + Email string `json:"email" gorm:"unique;type:varchar(64);null;default:null" parse:"json"` + Phone string `json:"phone" gorm:"type:varchar(64);unique;null;default:null" parse:"json"` + Region string `json:"region" gorm:"type:varchar(32);default:null" parse:"json"` Status uint `json:"status" parse:"json"` diff --git a/ui/assets/vyes.min.js b/ui/assets/vyes.min.js new file mode 100644 index 0000000..6447a51 --- /dev/null +++ b/ui/assets/vyes.min.js @@ -0,0 +1 @@ +var t;t=function(){const t=[],e=[];function n(){return`${performance.now().toString(36)}-${Math.random().toString(36).substring(2,5)}`}setInterval((()=>{let n=new Set(e.splice(0)),o=0;for(let e of n)t[e]&&(window.vdev||t[e](),o++);return o}),25),window.$vupdate=e=>{t[e]()};var o=[];const r=Symbol("isProxy"),i=Symbol("DataID"),s=Symbol("bind"),a=Symbol("root"),c=Symbol("root arg");function l(t,e){t[a]=e,Object.keys(e).forEach((e=>{e in t||(t[e]=c)}))}function u(t){return!(!t||"object"!=typeof t||t instanceof Node||t instanceof Date||t instanceof RegExp||t instanceof Event||t.t||t.constructor!==Object&&t.constructor!==Array)}function f(t,e){if(!t||!t[r]||!u(e))return e;let n=t[s];if(!e[r])return Object.keys(t).forEach((n=>{void 0===e[n]&&delete t[n]})),Object.keys(e).forEach((n=>{t[n]?.[r]?t[n]=f(t[n],e[n]):t[n]=e[n]})),t;if(e[i]===t[i])return e;for(let o in n)if(e[s][o]?.indexOf)for(let t of n[o])-1===e[s][o].indexOf(t)&&e[s][o].push(t);else e[s][o]=n[o];for(let o in e)o in t&&t[o]?.[r]&&(e[o]=f(t[o],e[o]));return e}const h={console,window,prompt:prompt.bind(window),alert:alert.bind(window),confirm:confirm.bind(window),RegExp,document,Array,Object,Math,Date,JSON,Symbol,Number,eval,isNaN,parseInt,parseFloat,setTimeout:setTimeout.bind(window),setInterval:setInterval.bind(window),clearTimeout:clearTimeout.bind(window),clearInterval:clearInterval.bind(window),encodeURIComponent,btoa:btoa.bind(window),fetch:fetch.bind(window),TextDecoder,history,requestAnimationFrame:requestAnimationFrame.bind(window)};function d(t,e,n){const o=new Proxy(t,{has:(t,e)=>!0,get(o,r,i){let s;return"$data"===r?s=t:"$env"===r?s=e:r in o?s=Reflect.get(o,r,i):r in e?s=e[r]:n&&r in n?s=n[r]:r in h?s=h[r]:r in window&&(s=window[r]),s},set:(t,e,n,o)=>Reflect.set(t,e,n,o)});return o}const p=Object.getPrototypeOf((async function(){})).constructor;function m(t,e){if(t.startsWith("/"))return t;const n=e.substring(0,e.lastIndexOf("/")).split("/").filter((t=>""!==t)),o=t.split("/").filter((t=>""!==t));for(const r of o)if(".."===r)n.length>0&&n.pop();else{if("."===r)continue;n.push(r)}return"/"+n.join("/")}const w={Wrap:function h(d,p=void 0){const m=n();let w=!1;"[object Array]"==={}.toString.call(d)&&(w=!0),p&&l(d,p),d[i]=m;const y={},b={get(t,e,n){if(e===i)return m;if(e===r)return!0;if(e===s)return y;const l=Reflect.get(t,e,n);if(l===c)return t[a][e];if("symbol"==typeof e)return l;let f=-1;if(o.length>0){let t=e;f=o[o.length-1],w&&(t=""),y.hasOwnProperty(t)?-1==y[t].indexOf(f)&&y[t].push(f):y[t]=[f]}if(window.vdev,u(l)&&!l[r]){let o=h(l,void 0);return Reflect.set(t,e,o,n),o}return l},set(n,i,s,l){const h=Reflect.get(n,i,l);if(h===c)return n[a][i]=s,!0;if(h===s)return!0;let d=!0;if(Array.isArray(s)&&Array.isArray(h)?(h.length=0,h.push(...s)):h&&h[r]&&u(s)?(s=f(h,s),d=Reflect.set(n,i,s,l)):d=Reflect.set(n,i,s,l),d&&0===o.length){let n=i;if(w&&(n=""),y[n]){let o=0;for(;o{n(e())})):t.push(e);try{r=e()}catch(b){}finally{o.pop()}return"function"==typeof n&&n(r),i},Cancel:function(e){e>=0&&et.trim()))}const i=await import(t);"string"==typeof o?i.default?e[o]=i.default:e[o]=i:o.forEach((t=>{t in i?e[t]=i[t]:t in i.default&&(e[t]=i.default[t])}))}catch(l){}}return s.trim()}};class y{constructor(){this.events={}}on(t,e,n=null){if("function"!=typeof e)throw Error("\u56de\u8c03\u51fd\u6570\u5fc5\u987b\u662f\u4e00\u4e2a\u51fd\u6570");this.events[t]||(this.events[t]=[]);const o={callback:e,context:n};return this.events[t].push(o),()=>this.off(t,e,n)}once(t,e,n=null){const o=(...r)=>{this.off(t,o,n),e.apply(n,r)};return this.on(t,o,n)}off(t,e=null,n=null){this.events[t]&&(e?(this.events[t]=this.events[t].filter((t=>!(t.callback===e&&t.context===n))),0===this.events[t].length&&delete this.events[t]):delete this.events[t])}emit(t,...e){this.events[t]&&[...this.events[t]].forEach((t=>{try{t.callback.apply(t.context,e)}catch(n){}}))}listenerCount(t){return this.events[t]?this.events[t].length:0}eventNames(){return Object.keys(this.events)}removeAllListeners(){this.events={}}hasListeners(t){return this.listenerCount(t)>0}}function b(t,e){return function(){return t.apply(e,arguments)}}const{toString:v}=Object.prototype,{getPrototypeOf:g}=Object,{iterator:x,toStringTag:R}=Symbol,O=(k=Object.create(null),t=>{const e=v.call(t);return k[e]||(k[e]=e.slice(8,-1).toLowerCase())});var k;const T=t=>(t=t.toLowerCase(),e=>O(e)===t),E=t=>e=>typeof e===t,{isArray:S}=Array,A=E("undefined"),j=T("ArrayBuffer"),$=E("string"),N=E("function"),P=E("number"),C=t=>null!==t&&"object"==typeof t,U=t=>{if("object"!==O(t))return!1;const e=g(t);return!(null!==e&&e!==Object.prototype&&null!==Object.getPrototypeOf(e)||R in t||x in t)},F=T("Date"),D=T("File"),L=T("Blob"),I=T("FileList"),z=T("URLSearchParams"),[M,q,B,_]=["ReadableStream","Request","Response","Headers"].map(T);function H(t,e,{allOwnKeys:n=!1}={}){if(null==t)return;let o,r;if("object"!=typeof t&&(t=[t]),S(t))for(o=0,r=t.length;r>o;o++)e.call(null,t[o],o,t);else{const r=n?Object.getOwnPropertyNames(t):Object.keys(t),i=r.length;let s;for(o=0;i>o;o++)s=r[o],e.call(null,t[s],s,t)}}function V(t,e){e=e.toLowerCase();const n=Object.keys(t);let o,r=n.length;for(;r-- >0;)if(o=n[r],e===o.toLowerCase())return o;return null}const X="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:global,J=t=>!A(t)&&t!==X,W=(K="undefined"!=typeof Uint8Array&&g(Uint8Array),t=>K&&t instanceof K);var K;const G=T("HTMLFormElement"),Z=(({hasOwnProperty:t})=>(e,n)=>t.call(e,n))(Object.prototype),Y=T("RegExp"),Q=(t,e)=>{const n=Object.getOwnPropertyDescriptors(t),o={};H(n,((n,r)=>{let i;!1!==(i=e(n,r,t))&&(o[r]=i||n)})),Object.defineProperties(t,o)},tt=T("AsyncFunction"),et=(nt="function"==typeof setImmediate,ot=N(X.postMessage),nt?setImmediate:ot?(rt="axios@"+Math.random(),it=[],X.addEventListener("message",(({source:t,data:e})=>{t===X&&e===rt&&it.length&&it.shift()()}),!1),t=>{it.push(t),X.postMessage(rt,"*")}):t=>setTimeout(t));var nt,ot,rt,it;const st="undefined"!=typeof queueMicrotask?queueMicrotask.bind(X):"undefined"!=typeof process&&process.nextTick||et,at={isArray:S,isArrayBuffer:j,isBuffer:function(t){return null!==t&&!A(t)&&null!==t.constructor&&!A(t.constructor)&&N(t.constructor.isBuffer)&&t.constructor.isBuffer(t)},isFormData:t=>{let e;return t&&("function"==typeof FormData&&t instanceof FormData||N(t.append)&&("formdata"===(e=O(t))||"object"===e&&N(t.toString)&&"[object FormData]"===t.toString()))},isArrayBufferView:function(t){let e;return e="undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(t):t&&t.buffer&&j(t.buffer),e},isString:$,isNumber:P,isBoolean:t=>!0===t||!1===t,isObject:C,isPlainObject:U,isReadableStream:M,isRequest:q,isResponse:B,isHeaders:_,isUndefined:A,isDate:F,isFile:D,isBlob:L,isRegExp:Y,isFunction:N,isStream:t=>C(t)&&N(t.pipe),isURLSearchParams:z,isTypedArray:W,isFileList:I,forEach:H,merge:function t(){const{caseless:e}=J(this)&&this||{},n={},o=(o,r)=>{const i=e&&V(n,r)||r;U(n[i])&&U(o)?n[i]=t(n[i],o):U(o)?n[i]=t({},o):S(o)?n[i]=o.slice():n[i]=o};for(let r=0,i=arguments.length;i>r;r++)arguments[r]&&H(arguments[r],o);return n},extend:(t,e,n,{allOwnKeys:o}={})=>(H(e,((e,o)=>{n&&N(e)?t[o]=b(e,n):t[o]=e}),{allOwnKeys:o}),t),trim:t=>t.trim?t.trim():t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,""),stripBOM:t=>(65279===t.charCodeAt(0)&&(t=t.slice(1)),t),inherits:(t,e,n,o)=>{t.prototype=Object.create(e.prototype,o),t.prototype.constructor=t,Object.defineProperty(t,"super",{value:e.prototype}),n&&Object.assign(t.prototype,n)},toFlatObject:(t,e,n,o)=>{let r,i,s;const a={};if(e=e||{},null==t)return e;do{for(r=Object.getOwnPropertyNames(t),i=r.length;i-- >0;)s=r[i],o&&!o(s,t,e)||a[s]||(e[s]=t[s],a[s]=!0);t=!1!==n&&g(t)}while(t&&(!n||n(t,e))&&t!==Object.prototype);return e},kindOf:O,kindOfTest:T,endsWith:(t,e,n)=>{t+="",(void 0===n||n>t.length)&&(n=t.length),n-=e.length;const o=t.indexOf(e,n);return-1!==o&&o===n},toArray:t=>{if(!t)return null;if(S(t))return t;let e=t.length;if(!P(e))return null;const n=Array(e);for(;e-- >0;)n[e]=t[e];return n},forEachEntry:(t,e)=>{const n=(t&&t[x]).call(t);let o;for(;(o=n.next())&&!o.done;){const n=o.value;e.call(t,n[0],n[1])}},matchAll:(t,e)=>{let n;const o=[];for(;null!==(n=t.exec(e));)o.push(n);return o},isHTMLForm:G,hasOwnProperty:Z,hasOwnProp:Z,reduceDescriptors:Q,freezeMethods:t=>{Q(t,((e,n)=>{if(N(t)&&-1!==["arguments","caller","callee"].indexOf(n))return!1;const o=t[n];N(o)&&(e.enumerable=!1,"writable"in e?e.writable=!1:e.set||(e.set=()=>{throw Error("Can not rewrite read-only method '"+n+"'")}))}))},toObjectSet:(t,e)=>{const n={},o=t=>{t.forEach((t=>{n[t]=!0}))};return S(t)?o(t):o((t+"").split(e)),n},toCamelCase:t=>t.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,(function(t,e,n){return e.toUpperCase()+n})),noop:()=>{},toFiniteNumber:(t,e)=>null!=t&&Number.isFinite(t=+t)?t:e,findKey:V,global:X,isContextDefined:J,isSpecCompliantForm:function(t){return!!(t&&N(t.append)&&"FormData"===t[R]&&t[x])},toJSONObject:t=>{const e=[,,,,,,,,,,],n=(t,o)=>{if(C(t)){if(e.indexOf(t)>=0)return;if(!("toJSON"in t)){e[o]=t;const r=S(t)?[]:{};return H(t,((t,e)=>{const i=n(t,o+1);!A(i)&&(r[e]=i)})),e[o]=void 0,r}}return t};return n(t,0)},isAsyncFn:tt,isThenable:t=>t&&(C(t)||N(t))&&N(t.then)&&N(t.catch),setImmediate:et,asap:st,isIterable:t=>null!=t&&N(t[x])};function ct(t,e,n,o,r){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=Error().stack,this.message=t,this.name="AxiosError",e&&(this.code=e),n&&(this.config=n),o&&(this.request=o),r&&(this.response=r,this.status=r.status?r.status:null)}at.inherits(ct,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:at.toJSONObject(this.config),code:this.code,status:this.status}}});const lt=ct.prototype,ut={};function ft(t){return at.isPlainObject(t)||at.isArray(t)}function ht(t){return at.endsWith(t,"[]")?t.slice(0,-2):t}function dt(t,e,n){return t?t.concat(e).map((function(t,e){return t=ht(t),!n&&e?"["+t+"]":t})).join(n?".":""):e}["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach((t=>{ut[t]={value:t}})),Object.defineProperties(ct,ut),Object.defineProperty(lt,"isAxiosError",{value:!0}),ct.from=(t,e,n,o,r,i)=>{const s=Object.create(lt);return at.toFlatObject(t,s,(function(t){return t!==Error.prototype}),(t=>"isAxiosError"!==t)),ct.call(s,t.message,e,n,o,r),s.cause=t,s.name=t.name,i&&Object.assign(s,i),s};const pt=at.toFlatObject(at,{},null,(function(t){return/^is[A-Z]/.test(t)}));function mt(t,e,n){if(!at.isObject(t))throw new TypeError("target must be an object");e=e||new FormData;const o=(n=at.toFlatObject(n,{metaTokens:!0,dots:!1,indexes:!1},!1,(function(t,e){return!at.isUndefined(e[t])}))).metaTokens,r=n.visitor||l,i=n.dots,s=n.indexes,a=(n.Blob||"undefined"!=typeof Blob&&Blob)&&at.isSpecCompliantForm(e);if(!at.isFunction(r))throw new TypeError("visitor must be a function");function c(t){if(null===t)return"";if(at.isDate(t))return t.toISOString();if(at.isBoolean(t))return t.toString();if(!a&&at.isBlob(t))throw new ct("Blob is not supported. Use a Buffer instead.");return at.isArrayBuffer(t)||at.isTypedArray(t)?a&&"function"==typeof Blob?new Blob([t]):Buffer.from(t):t}function l(t,n,r){let a=t;if(t&&!r&&"object"==typeof t)if(at.endsWith(n,"{}"))n=o?n:n.slice(0,-2),t=JSON.stringify(t);else if(at.isArray(t)&&function(t){return at.isArray(t)&&!t.some(ft)}(t)||(at.isFileList(t)||at.endsWith(n,"[]"))&&(a=at.toArray(t)))return n=ht(n),a.forEach((function(t,o){!at.isUndefined(t)&&null!==t&&e.append(!0===s?dt([n],o,i):null===s?n:n+"[]",c(t))})),!1;return!!ft(t)||(e.append(dt(r,n,i),c(t)),!1)}const u=[],f=Object.assign(pt,{defaultVisitor:l,convertValue:c,isVisitable:ft});if(!at.isObject(t))throw new TypeError("data must be an object");return function t(n,o){if(!at.isUndefined(n)){if(-1!==u.indexOf(n))throw Error("Circular reference detected in "+o.join("."));u.push(n),at.forEach(n,(function(n,i){!0===(!(at.isUndefined(n)||null===n)&&r.call(e,n,at.isString(i)?i.trim():i,o,f))&&t(n,o?o.concat(i):[i])})),u.pop()}}(t),e}function wt(t){const e={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(t).replace(/[!'()~]|%20|%00/g,(function(t){return e[t]}))}function yt(t,e){this.o=[],t&&mt(t,this,e)}const bt=yt.prototype;function vt(t){return encodeURIComponent(t).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}function gt(t,e,n){if(!e)return t;const o=n&&n.encode||vt;at.isFunction(n)&&(n={serialize:n});const r=n&&n.serialize;let i;if(i=r?r(e,n):at.isURLSearchParams(e)?e.toString():new yt(e,n).toString(o),i){const e=t.indexOf("#");-1!==e&&(t=t.slice(0,e)),t+=(-1===t.indexOf("?")?"?":"&")+i}return t}bt.append=function(t,e){this.o.push([t,e])},bt.toString=function(t){const e=t?function(e){return t.call(this,e,wt)}:wt;return this.o.map((function(t){return e(t[0])+"="+e(t[1])}),"").join("&")};const xt=class{constructor(){this.handlers=[]}use(t,e,n){return this.handlers.push({fulfilled:t,rejected:e,synchronous:!!n&&n.synchronous,runWhen:n?n.runWhen:null}),this.handlers.length-1}eject(t){this.handlers[t]&&(this.handlers[t]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(t){at.forEach(this.handlers,(function(e){null!==e&&t(e)}))}},Rt={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},Ot={isBrowser:!0,classes:{URLSearchParams:"undefined"!=typeof URLSearchParams?URLSearchParams:yt,FormData:"undefined"!=typeof FormData?FormData:null,Blob:"undefined"!=typeof Blob?Blob:null},protocols:["http","https","file","blob","url","data"]},kt="undefined"!=typeof window&&"undefined"!=typeof document,Tt="object"==typeof navigator&&navigator||void 0,Et=kt&&(!Tt||0>["ReactNative","NativeScript","NS"].indexOf(Tt.product)),St="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&"function"==typeof self.importScripts,At=kt&&window.location.href||"http://localhost",jt={...Object.freeze({__proto__:null,hasBrowserEnv:kt,hasStandardBrowserWebWorkerEnv:St,hasStandardBrowserEnv:Et,navigator:Tt,origin:At}),...Ot};function $t(t){function e(t,n,o,r){let i=t[r++];if("__proto__"===i)return!0;const s=Number.isFinite(+i),a=r>=t.length;return i=!i&&at.isArray(o)?o.length:i,a?(at.hasOwnProp(o,i)?o[i]=[o[i],n]:o[i]=n,!s):(o[i]&&at.isObject(o[i])||(o[i]=[]),e(t,n,o[i],r)&&at.isArray(o[i])&&(o[i]=function(t){const e={},n=Object.keys(t);let o;const r=n.length;let i;for(o=0;r>o;o++)i=n[o],e[i]=t[i];return e}(o[i])),!s)}if(at.isFormData(t)&&at.isFunction(t.entries)){const n={};return at.forEachEntry(t,((t,o)=>{e(function(t){return at.matchAll(/\w+|\[(\w*)]/g,t).map((t=>"[]"===t[0]?"":t[1]||t[0]))}(t),o,n,0)})),n}return null}const Nt={transitional:Rt,adapter:["xhr","http","fetch"],transformRequest:[function(t,e){const n=e.getContentType()||"",o=n.indexOf("application/json")>-1,r=at.isObject(t);if(r&&at.isHTMLForm(t)&&(t=new FormData(t)),at.isFormData(t))return o?JSON.stringify($t(t)):t;if(at.isArrayBuffer(t)||at.isBuffer(t)||at.isStream(t)||at.isFile(t)||at.isBlob(t)||at.isReadableStream(t))return t;if(at.isArrayBufferView(t))return t.buffer;if(at.isURLSearchParams(t))return e.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),t.toString();let i;if(r){if(n.indexOf("application/x-www-form-urlencoded")>-1)return function(t,e){return mt(t,new jt.classes.URLSearchParams,Object.assign({visitor:function(t,e,n,o){return jt.isNode&&at.isBuffer(t)?(this.append(e,t.toString("base64")),!1):o.defaultVisitor.apply(this,arguments)}},e))}(t,this.formSerializer).toString();if((i=at.isFileList(t))||n.indexOf("multipart/form-data")>-1){const e=this.env&&this.env.FormData;return mt(i?{"files[]":t}:t,e&&new e,this.formSerializer)}}return r||o?(e.setContentType("application/json",!1),function(t){if(at.isString(t))try{return(0,JSON.parse)(t),at.trim(t)}catch(t){if("SyntaxError"!==t.name)throw t}return(0,JSON.stringify)(t)}(t)):t}],transformResponse:[function(t){const e=this.transitional||Nt.transitional,n=e&&e.forcedJSONParsing,o="json"===this.responseType;if(at.isResponse(t)||at.isReadableStream(t))return t;if(t&&at.isString(t)&&(n&&!this.responseType||o)){const n=!(e&&e.silentJSONParsing)&&o;try{return JSON.parse(t)}catch(t){if(n){if("SyntaxError"===t.name)throw ct.from(t,ct.ERR_BAD_RESPONSE,this,null,this.response);throw t}}}return t}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:jt.classes.FormData,Blob:jt.classes.Blob},validateStatus:function(t){return t>=200&&300>t},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};at.forEach(["delete","get","head","post","put","patch"],(t=>{Nt.headers[t]={}}));const Pt=Nt,Ct=at.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),Ut=Symbol("internals");function Ft(t){return t&&(t+"").trim().toLowerCase()}function Dt(t){return!1===t||null==t?t:at.isArray(t)?t.map(Dt):t+""}function Lt(t,e,n,o,r){return at.isFunction(o)?o.call(this,e,n):(r&&(e=n),at.isString(e)?at.isString(o)?-1!==e.indexOf(o):at.isRegExp(o)?o.test(e):void 0:void 0)}class It{constructor(t){t&&this.set(t)}set(t,e,n){const o=this;function r(t,e,n){const r=Ft(e);if(!r)throw Error("header name must be a non-empty string");const i=at.findKey(o,r);(!i||void 0===o[i]||!0===n||void 0===n&&!1!==o[i])&&(o[i||e]=Dt(t))}const i=(t,e)=>at.forEach(t,((t,n)=>r(t,n,e)));if(at.isPlainObject(t)||t instanceof this.constructor)i(t,e);else if(at.isString(t)&&(t=t.trim())&&!/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(t.trim()))i((t=>{const e={};let n,o,r;return t&&t.split("\n").forEach((function(t){r=t.indexOf(":"),n=t.substring(0,r).trim().toLowerCase(),o=t.substring(r+1).trim(),!n||e[n]&&Ct[n]||("set-cookie"===n?e[n]?e[n].push(o):e[n]=[o]:e[n]=e[n]?e[n]+", "+o:o)})),e})(t),e);else if(at.isObject(t)&&at.isIterable(t)){let n,o,r={};for(const e of t){if(!at.isArray(e))throw TypeError("Object iterator must return a key-value pair");r[o=e[0]]=(n=r[o])?at.isArray(n)?[...n,e[1]]:[n,e[1]]:e[1]}i(r,e)}else null!=t&&r(e,t,n);return this}get(t,e){if(t=Ft(t)){const n=at.findKey(this,t);if(n){const t=this[n];if(!e)return t;if(!0===e)return function(t){const e=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let o;for(;o=n.exec(t);)e[o[1]]=o[2];return e}(t);if(at.isFunction(e))return e.call(this,t,n);if(at.isRegExp(e))return e.exec(t);throw new TypeError("parser must be boolean|regexp|function")}}}has(t,e){if(t=Ft(t)){const n=at.findKey(this,t);return!(!n||void 0===this[n]||e&&!Lt(0,this[n],n,e))}return!1}delete(t,e){const n=this;let o=!1;function r(t){if(t=Ft(t)){const r=at.findKey(n,t);!r||e&&!Lt(0,n[r],r,e)||(delete n[r],o=!0)}}return at.isArray(t)?t.forEach(r):r(t),o}clear(t){const e=Object.keys(this);let n=e.length,o=!1;for(;n--;){const r=e[n];t&&!Lt(0,this[r],r,t,!0)||(delete this[r],o=!0)}return o}normalize(t){const e=this,n={};return at.forEach(this,((o,r)=>{const i=at.findKey(n,r);if(i)return e[i]=Dt(o),void delete e[r];const s=t?function(t){return t.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,((t,e,n)=>e.toUpperCase()+n))}(r):(r+"").trim();s!==r&&delete e[r],e[s]=Dt(o),n[s]=!0})),this}concat(...t){return this.constructor.concat(this,...t)}toJSON(t){const e=Object.create(null);return at.forEach(this,((n,o)=>{null!=n&&!1!==n&&(e[o]=t&&at.isArray(n)?n.join(", "):n)})),e}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map((([t,e])=>t+": "+e)).join("\n")}getSetCookie(){return this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(t){return t instanceof this?t:new this(t)}static concat(t,...e){const n=new this(t);return e.forEach((t=>n.set(t))),n}static accessor(t){const e=(this[Ut]=this[Ut]={accessors:{}}).accessors,n=this.prototype;function o(t){const o=Ft(t);e[o]||(function(t,e){const n=at.toCamelCase(" "+e);["get","set","has"].forEach((o=>{Object.defineProperty(t,o+n,{value:function(t,n,r){return this[o].call(this,e,t,n,r)},configurable:!0})}))}(n,t),e[o]=!0)}return at.isArray(t)?t.forEach(o):o(t),this}}It.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]),at.reduceDescriptors(It.prototype,(({value:t},e)=>{let n=e[0].toUpperCase()+e.slice(1);return{get:()=>t,set(t){this[n]=t}}})),at.freezeMethods(It);const zt=It;function Mt(t,e){const n=this||Pt,o=e||n,r=zt.from(o.headers);let i=o.data;return at.forEach(t,(function(t){i=t.call(n,i,r.normalize(),e?e.status:void 0)})),r.normalize(),i}function qt(t){return!(!t||!t.i)}function Bt(t,e,n){ct.call(this,t??"canceled",ct.ERR_CANCELED,e,n),this.name="CanceledError"}function _t(t,e,n){const o=n.config.validateStatus;n.status&&o&&!o(n.status)?e(new ct("Request failed with status code "+n.status,[ct.ERR_BAD_REQUEST,ct.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n)):t(n)}at.inherits(Bt,ct,{i:!0});const Ht=(t,e,n=3)=>{let o=0;const r=function(t,e){const n=Array(t=t||10),o=Array(t);let r,i=0,s=0;return e=void 0!==e?e:1e3,function(a){const c=Date.now(),l=o[s];r||(r=c),n[i]=a,o[i]=c;let u=s,f=0;for(;u!==i;)f+=n[u++],u%=t;if(i=(i+1)%t,i===s&&(s=(s+1)%t),e>c-r)return;const h=l&&c-l;return h?Math.round(1e3*f/h):void 0}}(50,250);return function(t,e){let n,o,r=0,i=1e3/e;const s=(e,i=Date.now())=>{r=i,n=null,o&&(clearTimeout(o),o=null),t.apply(null,e)};return[(...t)=>{const e=Date.now(),a=e-r;i>a?(n=t,o||(o=setTimeout((()=>{o=null,s(n)}),i-a))):s(t,e)},()=>n&&s(n)]}((n=>{const i=n.loaded,s=n.lengthComputable?n.total:void 0,a=i-o,c=r(a);o=i,t({loaded:i,total:s,progress:s?i/s:void 0,bytes:a,rate:c||void 0,estimated:c&&s&&s>=i?(s-i)/c:void 0,event:n,lengthComputable:null!=s,[e?"download":"upload"]:!0})}),n)},Vt=(t,e)=>{const n=null!=t;return[o=>e[0]({lengthComputable:n,total:t,loaded:o}),e[1]]},Xt=t=>(...e)=>at.asap((()=>t(...e))),Jt=jt.hasStandardBrowserEnv?((t,e)=>n=>(n=new URL(n,jt.origin),t.protocol===n.protocol&&t.host===n.host&&(e||t.port===n.port)))(new URL(jt.origin),jt.navigator&&/(msie|trident)/i.test(jt.navigator.userAgent)):()=>!0,Wt=jt.hasStandardBrowserEnv?{write(t,e,n,o,r,i){const s=[t+"="+encodeURIComponent(e)];at.isNumber(n)&&s.push("expires="+new Date(n).toGMTString()),at.isString(o)&&s.push("path="+o),at.isString(r)&&s.push("domain="+r),!0===i&&s.push("secure"),document.cookie=s.join("; ")},read(t){const e=document.cookie.match(RegExp("(^|;\\s*)("+t+")=([^;]*)"));return e?decodeURIComponent(e[3]):null},remove(t){this.write(t,"",Date.now()-864e5)}}:{write(){},read:()=>null,remove(){}};function Kt(t,e,n){return!t||/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)&&0!=n?e:function(t,e){return e?t.replace(/\/?\/$/,"")+"/"+e.replace(/^\/+/,""):t}(t,e)}const Gt=t=>t instanceof zt?{...t}:t;function Zt(t,e){e=e||{};const n={};function o(t,e,n,o){return at.isPlainObject(t)&&at.isPlainObject(e)?at.merge.call({caseless:o},t,e):at.isPlainObject(e)?at.merge({},e):at.isArray(e)?e.slice():e}function r(t,e,n,r){return at.isUndefined(e)?at.isUndefined(t)?void 0:o(void 0,t,0,r):o(t,e,0,r)}function i(t,e){if(!at.isUndefined(e))return o(void 0,e)}function s(t,e){return at.isUndefined(e)?at.isUndefined(t)?void 0:o(void 0,t):o(void 0,e)}function a(n,r,i){return i in e?o(n,r):i in t?o(void 0,n):void 0}const c={url:i,method:i,data:i,baseURL:s,transformRequest:s,transformResponse:s,paramsSerializer:s,timeout:s,timeoutMessage:s,withCredentials:s,withXSRFToken:s,adapter:s,responseType:s,xsrfCookieName:s,xsrfHeaderName:s,onUploadProgress:s,onDownloadProgress:s,decompress:s,maxContentLength:s,maxBodyLength:s,beforeRedirect:s,transport:s,httpAgent:s,httpsAgent:s,cancelToken:s,socketPath:s,responseEncoding:s,validateStatus:a,headers:(t,e,n)=>r(Gt(t),Gt(e),0,!0)};return at.forEach(Object.keys(Object.assign({},t,e)),(function(o){const i=c[o]||r,s=i(t[o],e[o],o);at.isUndefined(s)&&i!==a||(n[o]=s)})),n}const Yt=t=>{const e=Zt({},t);let n,{data:o,withXSRFToken:r,xsrfHeaderName:i,xsrfCookieName:s,headers:a,auth:c}=e;if(e.headers=a=zt.from(a),e.url=gt(Kt(e.baseURL,e.url,e.allowAbsoluteUrls),t.params,t.paramsSerializer),c&&a.set("Authorization","Basic "+btoa((c.username||"")+":"+(c.password?unescape(encodeURIComponent(c.password)):""))),at.isFormData(o))if(jt.hasStandardBrowserEnv||jt.hasStandardBrowserWebWorkerEnv)a.setContentType(void 0);else if(!1!==(n=a.getContentType())){const[t,...e]=n?n.split(";").map((t=>t.trim())).filter(Boolean):[];a.setContentType([t||"multipart/form-data",...e].join("; "))}if(jt.hasStandardBrowserEnv&&(r&&at.isFunction(r)&&(r=r(e)),r||!1!==r&&Jt(e.url))){const t=i&&s&&Wt.read(s);t&&a.set(i,t)}return e},Qt="undefined"!=typeof XMLHttpRequest&&function(t){return new Promise((function(e,n){const o=Yt(t);let r=o.data;const i=zt.from(o.headers).normalize();let s,a,c,l,u,{responseType:f,onUploadProgress:h,onDownloadProgress:d}=o;function p(){l&&l(),u&&u(),o.cancelToken&&o.cancelToken.unsubscribe(s),o.signal&&o.signal.removeEventListener("abort",s)}let m=new XMLHttpRequest;function w(){if(!m)return;const o=zt.from("getAllResponseHeaders"in m&&m.getAllResponseHeaders());_t((function(t){e(t),p()}),(function(t){n(t),p()}),{data:f&&"text"!==f&&"json"!==f?m.response:m.responseText,status:m.status,statusText:m.statusText,headers:o,config:t,request:m}),m=null}m.open(o.method.toUpperCase(),o.url,!0),m.timeout=o.timeout,"onloadend"in m?m.onloadend=w:m.onreadystatechange=function(){m&&4===m.readyState&&(0!==m.status||m.responseURL&&0===m.responseURL.indexOf("file:"))&&setTimeout(w)},m.onabort=function(){m&&(n(new ct("Request aborted",ct.ECONNABORTED,t,m)),m=null)},m.onerror=function(){n(new ct("Network Error",ct.ERR_NETWORK,t,m)),m=null},m.ontimeout=function(){let e=o.timeout?"timeout of "+o.timeout+"ms exceeded":"timeout exceeded";const r=o.transitional||Rt;o.timeoutErrorMessage&&(e=o.timeoutErrorMessage),n(new ct(e,r.clarifyTimeoutError?ct.ETIMEDOUT:ct.ECONNABORTED,t,m)),m=null},void 0===r&&i.setContentType(null),"setRequestHeader"in m&&at.forEach(i.toJSON(),(function(t,e){m.setRequestHeader(e,t)})),at.isUndefined(o.withCredentials)||(m.withCredentials=!!o.withCredentials),f&&"json"!==f&&(m.responseType=o.responseType),d&&([c,u]=Ht(d,!0),m.addEventListener("progress",c)),h&&m.upload&&([a,l]=Ht(h),m.upload.addEventListener("progress",a),m.upload.addEventListener("loadend",l)),(o.cancelToken||o.signal)&&(s=e=>{m&&(n(!e||e.type?new Bt(null,t,m):e),m.abort(),m=null)},o.cancelToken&&o.cancelToken.subscribe(s),o.signal&&(o.signal.aborted?s():o.signal.addEventListener("abort",s)));const y=function(t){const e=/^([-+\w]{1,25})(:?\/\/|:)/.exec(t);return e&&e[1]||""}(o.url);y&&-1===jt.protocols.indexOf(y)?n(new ct("Unsupported protocol "+y+":",ct.ERR_BAD_REQUEST,t)):m.send(r||null)}))},te=(t,e)=>{const{length:n}=t=t?t.filter(Boolean):[];if(e||n){let n,o=new AbortController;const r=function(t){if(!n){n=!0,s();const e=t instanceof Error?t:this.reason;o.abort(e instanceof ct?e:new Bt(e instanceof Error?e.message:e))}};let i=e&&setTimeout((()=>{i=null,r(new ct(`timeout ${e} of ms exceeded`,ct.ETIMEDOUT))}),e);const s=()=>{t&&(i&&clearTimeout(i),i=null,t.forEach((t=>{t.unsubscribe?t.unsubscribe(r):t.removeEventListener("abort",r)})),t=null)};t.forEach((t=>t.addEventListener("abort",r)));const{signal:a}=o;return a.unsubscribe=()=>at.asap(s),a}},ee=function*(t,e){let n=t.byteLength;if(e>n)return void(yield t);let o,r=0;for(;n>r;)o=r+e,yield t.slice(r,o),r=o},ne=(t,e,n,o)=>{const r=async function*(t,e){for await(const n of async function*(t){if(t[Symbol.asyncIterator])return void(yield*t);const e=t.getReader();try{for(;;){const{done:t,value:n}=await e.read();if(t)break;yield n}}finally{await e.cancel()}}(t))yield*ee(n,e)}(t,e);let i,s=0,a=t=>{i||(i=!0,o&&o(t))};return new ReadableStream({async pull(t){try{const{done:e,value:o}=await r.next();if(e)return a(),void t.close();let i=o.byteLength;if(n){let t=s+=i;n(t)}t.enqueue(new Uint8Array(o))}catch(t){throw a(t),t}},cancel:t=>(a(t),r.return())},{highWaterMark:2})},oe="function"==typeof fetch&&"function"==typeof Request&&"function"==typeof Response,re=oe&&"function"==typeof ReadableStream,ie=oe&&("function"==typeof TextEncoder?(se=new TextEncoder,t=>se.encode(t)):async t=>new Uint8Array(await new Response(t).arrayBuffer()));var se;const ae=(t,...e)=>{try{return!!t(...e)}catch(t){return!1}},ce=re&&ae((()=>{let t=!1;const e=new Request(jt.origin,{body:new ReadableStream,method:"POST",get duplex(){return t=!0,"half"}}).headers.has("Content-Type");return t&&!e})),le=re&&ae((()=>at.isReadableStream(new Response("").body))),ue={stream:le&&(t=>t.body)};var fe;oe&&(fe=new Response,["text","arrayBuffer","blob","formData","stream"].forEach((t=>{!ue[t]&&(ue[t]=at.isFunction(fe[t])?e=>e[t]():(e,n)=>{throw new ct(`Response type '${t}' is not supported`,ct.ERR_NOT_SUPPORT,n)})})));const he={http:null,xhr:Qt,fetch:oe&&(async t=>{let{url:e,method:n,data:o,signal:r,cancelToken:i,timeout:s,onDownloadProgress:a,onUploadProgress:c,responseType:l,headers:u,withCredentials:f="same-origin",fetchOptions:h}=Yt(t);l=l?(l+"").toLowerCase():"text";let d,p=te([r,i&&i.toAbortSignal()],s);const m=p&&p.unsubscribe&&(()=>{p.unsubscribe()});let w;try{if(c&&ce&&"get"!==n&&"head"!==n&&0!==(w=await(async(t,e)=>at.toFiniteNumber(t.getContentLength())??(async t=>{if(null==t)return 0;if(at.isBlob(t))return t.size;if(at.isSpecCompliantForm(t)){const e=new Request(jt.origin,{method:"POST",body:t});return(await e.arrayBuffer()).byteLength}return at.isArrayBufferView(t)||at.isArrayBuffer(t)?t.byteLength:(at.isURLSearchParams(t)&&(t+=""),at.isString(t)?(await ie(t)).byteLength:void 0)})(e))(u,o))){let t,n=new Request(e,{method:"POST",body:o,duplex:"half"});if(at.isFormData(o)&&(t=n.headers.get("content-type"))&&u.setContentType(t),n.body){const[t,e]=Vt(w,Ht(Xt(c)));o=ne(n.body,65536,t,e)}}at.isString(f)||(f=f?"include":"omit");const r="credentials"in Request.prototype;d=new Request(e,{...h,signal:p,method:n.toUpperCase(),headers:u.normalize().toJSON(),body:o,duplex:"half",credentials:r?f:void 0});let i=await fetch(d,h);const s=le&&("stream"===l||"response"===l);if(le&&(a||s&&m)){const t={};["status","statusText","headers"].forEach((e=>{t[e]=i[e]}));const e=at.toFiniteNumber(i.headers.get("content-length")),[n,o]=a&&Vt(e,Ht(Xt(a),!0))||[];i=new Response(ne(i.body,65536,n,(()=>{o&&o(),m&&m()})),t)}l=l||"text";let y=await ue[at.findKey(ue,l)||"text"](i,t);return!s&&m&&m(),await new Promise(((e,n)=>{_t(e,n,{data:y,headers:zt.from(i.headers),status:i.status,statusText:i.statusText,config:t,request:d})}))}catch(e){if(m&&m(),e&&"TypeError"===e.name&&/Load failed|fetch/i.test(e.message))throw Object.assign(new ct("Network Error",ct.ERR_NETWORK,t,d),{cause:e.cause||e});throw ct.from(e,e&&e.code,t,d)}})};at.forEach(he,((t,e)=>{if(t){try{Object.defineProperty(t,"name",{value:e})}catch(t){}Object.defineProperty(t,"adapterName",{value:e})}}));const de=t=>"- "+t,pe=t=>at.isFunction(t)||null===t||!1===t,me=t=>{t=at.isArray(t)?t:[t];const{length:e}=t;let n,o;const r={};for(let i=0;e>i;i++){let e;if(n=t[i],o=n,!pe(n)&&(o=he[(e=n+"").toLowerCase()],void 0===o))throw new ct(`Unknown adapter '${e}'`);if(o)break;r[e||"#"+i]=o}if(!o){const t=Object.entries(r).map((([t,e])=>`adapter ${t} `+(!1===e?"is not supported by the environment":"is not available in the build")));throw new ct("There is no suitable adapter to dispatch the request "+(e?t.length>1?"since :\n"+t.map(de).join("\n"):" "+de(t[0]):"as no adapter specified"),"ERR_NOT_SUPPORT")}return o};function we(t){if(t.cancelToken&&t.cancelToken.throwIfRequested(),t.signal&&t.signal.aborted)throw new Bt(null,t)}function ye(t){return we(t),t.headers=zt.from(t.headers),t.data=Mt.call(t,t.transformRequest),-1!==["post","put","patch"].indexOf(t.method)&&t.headers.setContentType("application/x-www-form-urlencoded",!1),me(t.adapter||Pt.adapter)(t).then((function(e){return we(t),e.data=Mt.call(t,t.transformResponse,e),e.headers=zt.from(e.headers),e}),(function(e){return qt(e)||(we(t),e&&e.response&&(e.response.data=Mt.call(t,t.transformResponse,e.response),e.response.headers=zt.from(e.response.headers))),Promise.reject(e)}))}const be={};["object","boolean","number","function","string","symbol"].forEach(((t,e)=>{be[t]=function(n){return typeof n===t||"a"+(1>e?"n ":" ")+t}}));const ve={};be.transitional=function(t,e,n){function o(t,e){return"[Axios v1.10.0] Transitional option '"+t+"'"+e+(n?". "+n:"")}return(n,r,i)=>{if(!1===t)throw new ct(o(r," has been removed"+(e?" in "+e:"")),ct.ERR_DEPRECATED);return e&&!ve[r]&&(ve[r]=!0),!t||t(n,r,i)}},be.spelling=function(t){return(t,e)=>!0};const ge={assertOptions:function(t,e,n){if("object"!=typeof t)throw new ct("options must be an object",ct.ERR_BAD_OPTION_VALUE);const o=Object.keys(t);let r=o.length;for(;r-- >0;){const i=o[r],s=e[i];if(s){const e=t[i],n=void 0===e||s(e,i,t);if(!0!==n)throw new ct("option "+i+" must be "+n,ct.ERR_BAD_OPTION_VALUE)}else if(!0!==n)throw new ct("Unknown option "+i,ct.ERR_BAD_OPTION)}},validators:be},xe=ge.validators;class Re{constructor(t){this.defaults=t||{},this.interceptors={request:new xt,response:new xt}}async request(t,e){try{return await this.l(t,e)}catch(t){if(t instanceof Error){let e={};Error.captureStackTrace?Error.captureStackTrace(e):e=Error();const n=e.stack?e.stack.replace(/^.+\n/,""):"";try{t.stack?n&&!(t.stack+"").endsWith(n.replace(/^.+\n.+\n/,""))&&(t.stack+="\n"+n):t.stack=n}catch(t){}}throw t}}l(t,e){"string"==typeof t?(e=e||{}).url=t:e=t||{},e=Zt(this.defaults,e);const{transitional:n,paramsSerializer:o,headers:r}=e;void 0!==n&&ge.assertOptions(n,{silentJSONParsing:xe.transitional(xe.boolean),forcedJSONParsing:xe.transitional(xe.boolean),clarifyTimeoutError:xe.transitional(xe.boolean)},!1),null!=o&&(at.isFunction(o)?e.paramsSerializer={serialize:o}:ge.assertOptions(o,{encode:xe.function,serialize:xe.function},!0)),void 0!==e.allowAbsoluteUrls||(void 0!==this.defaults.allowAbsoluteUrls?e.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:e.allowAbsoluteUrls=!0),ge.assertOptions(e,{baseUrl:xe.spelling("baseURL"),withXsrfToken:xe.spelling("withXSRFToken")},!0),e.method=(e.method||this.defaults.method||"get").toLowerCase();let i=r&&at.merge(r.common,r[e.method]);r&&at.forEach(["delete","get","head","post","put","patch","common"],(t=>{delete r[t]})),e.headers=zt.concat(i,r);const s=[];let a=!0;this.interceptors.request.forEach((function(t){"function"==typeof t.runWhen&&!1===t.runWhen(e)||(a=a&&t.synchronous,s.unshift(t.fulfilled,t.rejected))}));const c=[];let l;this.interceptors.response.forEach((function(t){c.push(t.fulfilled,t.rejected)}));let u,f=0;if(!a){const t=[ye.bind(this),void 0];for(t.unshift.apply(t,s),t.push.apply(t,c),u=t.length,l=Promise.resolve(e);u>f;)l=l.then(t[f++],t[f++]);return l}u=s.length;let h=e;for(f=0;u>f;){const e=s[f++],n=s[f++];try{h=e(h)}catch(t){n.call(this,t);break}}try{l=ye(h)}catch(t){return Promise.reject(t)}for(f=0,u=c.length;u>f;)l=l.then(c[f++],c[f++]);return l}getUri(t){return gt(Kt((t=Zt(this.defaults,t)).baseURL,t.url,t.allowAbsoluteUrls),t.params,t.paramsSerializer)}}at.forEach(["delete","get","head","options"],(function(t){Re.prototype[t]=function(e,n){return this.request(Zt(n||{},{method:t,url:e,data:(n||{}).data}))}})),at.forEach(["post","put","patch"],(function(t){function e(e){return function(n,o,r){return this.request(Zt(r||{},{method:t,headers:e?{"Content-Type":"multipart/form-data"}:{},url:n,data:o}))}}Re.prototype[t]=e(),Re.prototype[t+"Form"]=e(!0)}));const Oe=Re;class ke{constructor(t){if("function"!=typeof t)throw new TypeError("executor must be a function.");let e;this.promise=new Promise((function(t){e=t}));const n=this;this.promise.then((t=>{if(!n.u)return;let e=n.u.length;for(;e-- >0;)n.u[e](t);n.u=null})),this.promise.then=t=>{let e;const o=new Promise((t=>{n.subscribe(t),e=t})).then(t);return o.cancel=function(){n.unsubscribe(e)},o},t((function(t,o,r){n.reason||(n.reason=new Bt(t,o,r),e(n.reason))}))}throwIfRequested(){if(this.reason)throw this.reason}subscribe(t){this.reason?t(this.reason):this.u?this.u.push(t):this.u=[t]}unsubscribe(t){if(!this.u)return;const e=this.u.indexOf(t);-1!==e&&this.u.splice(e,1)}toAbortSignal(){const t=new AbortController,e=e=>{t.abort(e)};return this.subscribe(e),t.signal.unsubscribe=()=>this.unsubscribe(e),t.signal}static source(){let t;return{token:new ke((function(e){t=e})),cancel:t}}}const Te=ke,Ee={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(Ee).forEach((([t,e])=>{Ee[e]=t}));const Se=Ee,Ae=function t(e){const n=new Oe(e),o=b(Oe.prototype.request,n);return at.extend(o,Oe.prototype,n,{allOwnKeys:!0}),at.extend(o,n,null,{allOwnKeys:!0}),o.create=function(n){return t(Zt(e,n))},o}(Pt);Ae.Axios=Oe,Ae.CanceledError=Bt,Ae.CancelToken=Te,Ae.isCancel=qt,Ae.VERSION="1.10.0",Ae.toFormData=mt,Ae.AxiosError=ct,Ae.Cancel=Ae.CanceledError,Ae.all=function(t){return Promise.all(t)},Ae.spread=function(t){return function(e){return t.apply(null,e)}},Ae.isAxiosError=function(t){return at.isObject(t)&&!0===t.isAxiosError},Ae.mergeConfig=Zt,Ae.AxiosHeaders=zt,Ae.formToJSON=t=>$t(at.isHTMLForm(t)?new FormData(t):t),Ae.getAdapter=me,Ae.HttpStatusCode=Se,Ae.default=Ae;const je=Ae,{Axios:$e,AxiosError:Ne,CanceledError:Pe,isCancel:Ce,CancelToken:Ue,VERSION:Fe,all:De,Cancel:Le,isAxiosError:Ie,spread:ze,toFormData:Me,AxiosHeaders:qe,HttpStatusCode:Be,formToJSON:_e,getAdapter:He,mergeConfig:Ve}=je,Xe=new class{constructor(){this.scopeAttribute="",this.scopeBody="",this.scopedKeyframes=new Map}parse(t,e){return this.scopeAttribute=`[vrefof="${e}"]`,this.scopeBody=`[vref="${e}"]`,this.scopedKeyframes.clear(),this.scopeSuffix=e.replace(/[^a-zA-Z0-9]/g,""),t=this.removeComments(t),this.collectKeyframes(t),this.parseRules(t)}collectKeyframes(t){const e=/@keyframes\s+([^\s{]+)/gi;let n;for(;null!==(n=e.exec(t));){const t=n[1],e=t+"-"+this.scopeSuffix;this.scopedKeyframes.set(t,e)}}removeComments(t){return t.replace(/\/\*[\s\S]*?\*\//g,"")}parseRules(t){let e="",n=0;for(;n=t.length)break;if("@"===t[n]){const o=this.parseAtRule(t,n);e+=o.content,n=o.endIndex}else{const o=this.parseNormalRule(t,n);e+=o.content,n=o.endIndex}}return e}parseAtRule(t,e){let n=e,o="";for(;n=t.length)return{content:o,endIndex:n};const r=o.toLowerCase().trim();if(r.startsWith("@keyframes"))return this.parseKeyframes(t,e);if(r.startsWith("@media"))return this.parseMedia(t,e);if(r.startsWith("@supports"))return this.parseSupports(t,e);{const e=this.findMatchingBrace(t,n);return{content:o+e.content,endIndex:e.endIndex}}}parseKeyframes(t,e){let n=e,o="";for(;n=t.length)return{content:o,endIndex:n};const r=this.findMatchingBrace(t,n),i=r.content,s=this.extractKeyframeName(o),a=this.scopedKeyframes.get(s);return a&&(o=o.replace(s,a)),o+=i,{content:o,endIndex:r.endIndex}}extractKeyframeName(t){const e=t.match(/@keyframes\s+([^\s{]+)/i);return e?e[1]:""}parseMedia(t,e){let n=e,o="";for(;n=t.length)return{content:o,endIndex:n};o+="{",n++;let r=1,i="";for(;n0;){if("{"===t[n])r++;else if("}"===t[n]&&(r--,0===r))break;i+=t[n],n++}return o+=this.parseRules(i),n=t.length)return{content:o,endIndex:n};const r=this.addScopeToSelector(o.trim()),i=this.findMatchingBrace(t,n);return{content:r+this.processRuleContent(i.content),endIndex:i.endIndex}}processRuleContent(t){let e=t;return e=e.replace(/animation\s*:\s*([^;]+);/gi,((t,e)=>`animation: ${this.processAnimationValue(e)};`)),e=e.replace(/animation-name\s*:\s*([^;]+);/gi,((t,e)=>`animation-name: ${this.processAnimationNames(e)};`)),e}processAnimationValue(t){return t.split(",").map((t=>t.trim())).map((t=>{const e=t.split(/\s+/);for(let n=0;n{const e=t.trim();return this.scopedKeyframes.get(e)||e})).join(", ")}addScopeToSelector(t){return t.trim()?t.split(",").map((t=>t.trim())).map((t=>this.addScopeToSingleSelector(t))).join(", "):t}addScopeToSingleSelector(t){if(!t.trim())return t;if(t.includes("::")){const e=t.split("::"),n=e[0],o="::"+e.slice(1).join("::");return this.addScopeToSelectorPart(n)+o}if(t.includes(":")&&!t.includes("::")){const e=t.match(/^([^:]+)(:.+)$/);if(e){const t=e[1],n=e[2];return this.addScopeToSelectorPart(t)+n}}return"*"===t||t.startsWith("@")?t:this.addScopeToSelectorPart(t)}addScopeToSelectorPart(t){const e=/(\s*[>+~]\s*|\s+)/;if(e.test(t)){const n=t.split(e);if(/^body(?:$|[:\[ ])/.test(n[0]))return n[0]=this.scopeBody+n[0].slice(4),n.join("");if(/^:root(?:$|[:\[ ])/.test(n[0]))return n[0]=this.scopeBody+n[0].slice(5),n.join("");for(let t=n.length-1;t>=0;t--)if(n[t].trim()&&!e.test(n[t])){let e=n[t].trim();n[t]=/^body(?:$|[:\[ ])/.test(e)?this.scopeBody+e.slice(4):/^:root(?:$:[$:\[ ])/.test(e)?this.scopeBody+e.slice(5):n[t].trim()+this.scopeAttribute;break}return n.join("")}let n=(t=t.trim()).trim();return/^body(?:$|[:\[ ])/.test(n)?this.scopeBody+n.slice(4):/^:root(?:$:[$:\[ ])/.test(n)?this.scopeBody+n.slice(5):n+this.scopeAttribute}findMatchingBrace(t,e){let n=e,o="",r=0;for(;n{this.removeMessage(s),i&&i()},s.appendChild(t)}return this.container.appendChild(s),setTimeout((()=>{s.classList.add("show")}),10),o>0&&setTimeout((()=>{this.removeMessage(s),i&&i()}),o),s}removeMessage(t){t&&t.parentNode&&(t.classList.remove("show"),setTimeout((()=>{t.parentNode&&t.parentNode.removeChild(t)}),300))}success(t,e={}){return this.createMessage("success",t,e)}warning(t,e={}){return this.createMessage("warning",t,e)}error(t,e={}){return this.createMessage("error",t,e)}info(t,e={}){return this.createMessage("info",t,e)}h(t,e={}){return new Promise(((n,o)=>{const{title:r="\u63d0\u793a",type:i="confirm",inputValue:s="",confirmText:a="\u786e\u5b9a",cancelText:c="\u53d6\u6d88",onConfirm:l=null,onCancel:u=()=>{n("")}}=e,f=document.createElement("div");f.className="prompt-overlay";const h=document.createElement("div");h.className="prompt-dialog";const d=document.createElement("div");d.className="prompt-header";const p=document.createElement("h3");p.className="prompt-title",p.textContent=r;const m=document.createElement("button");m.className="prompt-close",m.innerHTML="×",d.appendChild(p),d.appendChild(m);const w=document.createElement("div");w.className="prompt-body";const y=document.createElement("div");y.className="prompt-content",y.textContent=t,w.appendChild(y);let b=null;"input"===i&&(b=document.createElement("input"),b.className="prompt-input",b.type="text",b.value=s,w.appendChild(b));const v=document.createElement("div");v.className="prompt-footer";const g=document.createElement("button");g.className="prompt-btn prompt-btn-cancel",g.textContent=c;const x=document.createElement("button");x.className="prompt-btn prompt-btn-confirm",x.textContent=a,v.appendChild(g),v.appendChild(x),h.appendChild(d),h.appendChild(w),h.appendChild(v),f.appendChild(h),document.body.appendChild(f),setTimeout((()=>{f.classList.add("show")}),10),b&&setTimeout((()=>{b.focus()}),300);const R=(t=null)=>(f.classList.remove("show"),setTimeout((()=>{f.parentNode&&f.parentNode.removeChild(f)}),300),t);m.onclick=()=>{R(),u?u():o(Error("cancelled"))},g.onclick=()=>{R(),u?u():o(Error("cancelled"))},x.onclick=()=>{const t=!b||b.value;R(),n(t),l&&l(t)};const O=t=>{"Escape"===t.key&&(R(),u?u():o(Error("cancelled")),document.removeEventListener("keydown",O))};document.addEventListener("keydown",O),f.onclick=t=>{t.target===f&&(R(),u?u():o(Error("cancelled")))}}))}confirm(t,e={}){return this.h(t,{...e,type:"confirm"})}prompt(t,e,n={}){return this.h(t,{...n,type:"input",inputValue:e})}};var We={},Ke={};const Ge={};function Ze(t,e){Array.from(t.childNodes).forEach((t=>{1===t.nodeType&&(t.setAttribute("vrefof",e),Ze(t,e))}))}async function Ye(t,e,n,o){void 0===n&&(n="#"+function(){let t=(new Date).getTime().toString(36);t.length>4&&(t=t.substring(t.length-4));let e="";for(let n=0;4>n;n++)e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".charAt(Math.floor(52*Math.random()));return e+t.padStart(4,"0")}()),n.endsWith(".html")&&(n=n.slice(0,-5));let r=(new DOMParser).parseFromString(t,"text/html");if(r.body.hasAttribute("root")&&!o)throw Error("HTTP error! status: 404");let i={url:n,heads:[],body:document.createElement("div"),setup:void 0,scripts:[],styles:"",txt:t,env:e,tmp:r,customAttrs:{}};if(i.heads=Array.from(r.querySelector("head")?.children),n&&(r.querySelectorAll("style").forEach((t=>{null===t.getAttribute("unscoped")?i.styles+=Xe.parse(t.innerHTML,n):i.styles+=t.innerHTML})),i.styles)){const t=document.createElement("style");t.innerHTML=i.styles,t.setAttribute("vref",n),document.head.appendChild(t)}return i.body.append(...r.querySelector("body").childNodes),i.body.querySelectorAll("script").forEach((t=>{""!=t.innerHTML.trim()?(t.hasAttribute("setup")?i.setup=t:t.hasAttribute("novyes")||i.scripts.push(t),t.remove()):t.remove()})),Array.from(r.body.attributes).forEach((t=>{/^[a-zA-Z]/.test(t.name)?i.body.setAttribute(t.name,t.value):i.customAttrs[t.name]=t.value})),i.body.setAttribute("vref",n),Ze(i.body,n),o||await async function(t,e){for(let n of t.heads){let o=n.nodeName.toLowerCase();"link"===o?tn(n,e):"script"===o?await Qe(n,e):"title"===o&&(t.title=n.innerText)}}(i,e),i}function Qe(t,e){let n=t.getAttribute("src"),o=t.getAttribute("key"),r=e?.root;if(r&&n.startsWith("/")&&(n=r+n),n.startsWith("@")&&(n=n.slice(1)),n&&document.querySelector(`script[src="${n}"]`))return;if(o&&document.querySelector(`script[key="${o}"]`))return;let i=document.createElement("script");return i.src=n,i.key=o,i.type=t.getAttribute("type")||"text/javascript",new Promise(((t,e)=>{i.onload=()=>{t(i)},i.onerror=()=>e(Error("Failed to load script "+n)),document.head.appendChild(i)}))}async function tn(t,e){let n=t.getAttribute("href"),o=t.getAttribute("key"),r=e?.root;r&&n.startsWith("/")&&(n=r+n),n.startsWith("@")&&(n=n.slice(1)),n&&document.querySelector(`link[href="${n}"]`)||o&&document.querySelector(`link[key="${o}"]`)||(t.setAttribute("href",n),document.head.append(t))}const en={FetchUI:async function(t,e,n){t&&"/"!==t||(t="/root.html"),t.startsWith("http")||t.startsWith("@")||t.startsWith("/")||(t="/"+t);let o=e?.root;if(o&&t.startsWith("/")&&(t=o+t),t.startsWith("@")&&(t=t.slice(1)),We[t])return Promise.resolve(We[t]);if(Ke[t])return Ke[t];let r={};const i=fetch(t+"?random="+Math.random()).then((async e=>{if(!e.ok)throw Error("HTTP error! status: "+e.status);for(const[t,i]of e.headers.entries())t.startsWith("vyes-")&&(r[t.slice(5)]=i);let n=r.root||"";t.startsWith("http")&&(n=new URL(t).origin+n,r.root=n);let o=await async function(t,e){if(!Ge[t=t||""]){let n=t.startsWith("http")?t:window.location.origin+t;Ge[t]=Object.assign({},e,{root:t,$G:w.Wrap({}),$bus:new y,$axios:je.create({baseURL:n}),$message:Je,$router:null,$emit:null}),t===$vyes.root||null===$vyes.root?Ge[t].$router=$vyes.$router:Ge[t].$router={addRoutes:()=>{},beforeEnter:()=>{}};try{await(await import(n+"/env.js")).default(Ge[t])}catch(b){}}return Ge[t]}(n,r);return Object.assign(r,o),e.text()})).then((e=>Ye(e,r,t,n))).then((e=>(We[t]=e,e))).catch((e=>{e.message;let n=document.createElement("div");n.style.cssText="\n backgound:#aaa;\n height:100%;\n width: 100%;\n display:grid;\n place-items: center;\n",n.innerHTML=`\n
\n
404
\n

${t}

\n
\n`;let o={heads:[],body:n,setup:"",scripts:[],styles:"",txt:"",tmp:"",env:r,err:e};return We[t]=o,o})).finally((()=>{delete Ke[t]}));return Ke[t]=i,i},FetchFile:async function(t){return fetch(t).then((t=>{if(!t.ok)throw Error("HTTP error! status: "+t.status);return t.text()}))},LoadScript:Qe,LoadLink:tn,ParseUI:Ye};function nn(t,e){let n,o;if(t.startsWith("http://")||t.startsWith("https://")){if(n=new URL(t),n.origin!==window.location.origin)return null;n.pathname.startsWith(e)&&(o=n.pathname.slice(e.length))}else n=new URL(t,window.location.href),o=n.pathname;const r={};return n.searchParams.forEach(((t,e)=>{r[e]=t})),{path:o,query:r,hash:n.hash}}class on{constructor(t,e){this.originalPath=t,this.name=e,this.keys=[],this.regexp=this.pathToRegexp(t)}pathToRegexp(t){let e=t.replace(/:([^(/]+)/g,((t,e)=>(this.keys.push(e),`(?<${e}>[^/]+)`)));return e=e.replace(/\*(\w+)/g,((t,e)=>(this.keys.push(e),`(?<${e}>.*)`))),e=e.replace(/\*/g,".*"),RegExp(`^${e}$`)}match(t){let e;if("string"==typeof t)e=t;else{if(!t||"object"!=typeof t)return null;if(!t.path)return t.name&&t.name===this.name?{path:this.originalPath,params:t.params||{},matched:this.originalPath}:null;e=t.path}const n=this.regexp.exec(e);if(!n)return null;const o={};return this.keys.forEach((t=>{n.groups?.[t]&&(o[t]=n.groups[t])})),{path:this.originalPath,params:o,matched:n[0]}}}const rn=new Map;class sn{constructor(t,e,n){this.vyes=t,this.node=e,this.layoutDom=void 0,this.matchedRoute=n,this.htmlPath=this.resolveHtmlPath(n)}resolveHtmlPath(t){let e=t.route.component||t.route.path;return"function"==typeof e&&(e=e(t.path)),Object.entries(t.params).forEach((([t,n])=>{e=e.replace(":"+t,n)})),e.startsWith("/")||(e="/"+e),e.endsWith("/")&&(e=e.slice(0,-1)),e.endsWith(".html")||(e+=".html"),e}async mount(t,e,n){const o=await en.FetchUI(this.htmlPath,t);if(o.err){let n=document.createElement("div");return Object.assign(n.style,{width:"100%",height:"100%"}),n.append(...e),this.node.innerHTML="",this.node.append(n),void this.vyes.parseRef(this.htmlPath,n,{},t,null,!0)}this.title=o.title||"";const r={},i=document.createElement("div");if(i.setAttribute("vsrc",this.htmlPath),r[""]=[i],this.slots=r,!n)return this.node.innerHTML="",this.node.append(i),void this.vyes.parseRef(this.htmlPath,i,{},t,null);let s=rn.get(n);if(s)this.layoutDom=s,this.activate();else{let e=n;e.startsWith("/")||(e="/"+n),e.endsWith(".html")||(e+=".html"),e.startsWith("/layout")||(e="/layout"+e);const o=await en.FetchUI(e,t);if(o.err)return this.node.innerHTML="",this.node.append(i),void this.vyes.parseRef(this.htmlPath,i,{},t,null);s=o.body.cloneNode(!0),rn.set(n,s),i.$refData=w.Wrap({}),s.$refSlots=w.Wrap({...r}),this.node.innerHTML="",this.node.append(s),this.layoutDom=s,this.vyes.parseRef("/layout/"+n,s,{},t,null,!0)}}activate(){this.title&&(document.title=this.title);const t=this.layoutDom;if(t)t.querySelectorAll("vslot").forEach((e=>{e.closest("[vref]")===t&&this.slots[e.getAttribute("name")||""]&&(e.innerHTML="")})),Object.keys(t.$refSlots).forEach((e=>{delete t.$refSlots[e]})),Object.assign(t.$refSlots,this.slots),t.isConnected||(this.node.innerHTML=""),this.node.append(t);else{this.node.innerHTML="";const t=this.slots[""];t instanceof Array?this.node.append(...t):this.node.append(t)}}}const an=new class{#t=[];#e=[];#n=null;#o="";#r=[];#i=new Map;#s=null;#a=null;#c=[];#l=!1;#u=null;#f=new Map;constructor(){this.init()}get routes(){return this.#t.slice()}get history(){return this.#e.slice()}get current(){return this.#n}get query(){return this.#n?.query||{}}get params(){return this.#n?.params||{}}get root(){return this.#o}onChange(t){this.#r.push(t)}addRoute(t){if(!t.path)throw Error("Route must have a path");"/"!=t.path&&t.path.endsWith("/")&&(t.path=t.path.slice(0,-1));const e={path:t.path,component:t.component,name:t.name,meta:t.meta||{},children:t.children||[],matcher:new on(t.path,t.name),description:t.description||"",layout:t.layout||""};this.#t.push(e),t.name&&this.#f.set(t.name,e),t.children?.length>0&&t.children.forEach((n=>{const o=t.path+(n.path.startsWith("/")?n.path:"/"+n.path),r=n.layout||t.layout||"",i={...t.meta,...n.meta};this.addRoute({...n,path:o,parent:e,layout:r,meta:i})}))}addRoutes(t){t.forEach((t=>this.addRoute(t)))}#h(t,e){this.#r.forEach((n=>{if("function"==typeof n)try{n(t,e)}catch(o){}}))}#d(t){const e=this.#n;this.#n={path:t.path,fullPath:t.fullPath,params:t.params||{},query:t.query||{},hash:new URL(t.fullPath,window.location.origin).hash,meta:t.route?.meta||{},description:t.route?.description||"",layout:t.route?.layout||"",name:t.route?.name,matched:t.route?[t.route]:[]},this.#e.push(this.#n),this.#o&&!t.fullPath.startsWith("http")?history.pushState({},"",this.#o+t.fullPath):history.pushState({},"",t.fullPath),this.#h(this.#n,e)}matchRoute(t){const e=this.normalizeRouteTarget(t);if(!e)return null;const{path:n,query:o,params:r,name:i}=e;if(i){const t=this.#f.get(i);if(!t)return null;let e=t.path;Object.entries(r).forEach((([t,n])=>{e=e.replace(":"+t,n)}));const n=t.matcher.match(e);return n?{route:t,params:{...n.params,...r},matched:n.matched,path:e,query:o,name:i}:null}for(const s of this.#t){const t=s.matcher.match(n);if(t&&s.component)return{route:s,params:{...t.params,...r},matched:t.matched,description:s.description,layout:s.layout,path:n,query:o,name:s.name}}return null}normalizeRouteTarget(t){let e,n,o={},r={},i="";if("string"==typeof t){const n=nn(t,this.#o);if(!n)return null;e=n.path,o={...n.query},i=n.hash}else{if(!t||"object"!=typeof t)return null;if(t.path){const n=nn(t.path,this.#o);if(!n)return null;e=n.path,o={...n.query,...t.query||{}},i=t.hash||n.hash,r=t.params||{}}else{if(!t.name)return null;n=t.name,o=t.query||{},r=t.params||{},i=t.hash||""}}return e&&!e.startsWith("/")&&(e="/"+e),this.#o&&(e=e.startsWith(this.#o)?e.slice(this.#o.length):e),e.startsWith("/")||(e="/"+e),"/"!=e&&e.endsWith("/")&&(e=e.slice(0,-1)),{path:e,query:o,params:r,hash:i,name:n}}matchTo(t){const e=this.matchRoute(t);if(!e)return null;const{route:n,params:o,query:r,path:i,name:s}=e;let a="";r&&Object.keys(r).length>0&&(a="?"+Object.entries(r).map((([t,e])=>`${encodeURIComponent(t)}=${encodeURIComponent(e)}`)).join("&"));const c=(i||e.path)+a;return{route:n,params:o,query:r,name:s||n.name,path:i||e.path,fullPath:c,matched:[n]}}buildUrl(t,e={}){const n=new URL(t,window.location.origin);return Object.entries(e).forEach((([t,e])=>{n.searchParams.append(t,e)})),n}resolveRoutePath(t,e={}){let n=t.component||t.path;return Object.entries(e).forEach((([t,e])=>{n=n.replace(":"+t,e)})),"/"!==n&&""!==n||(n="/index"),n.startsWith("/")||(n="/"+n),n.endsWith(".html")&&(n=n.slice(0,-5)),n.endsWith("/")&&(n=n.slice(0,-1)),n}async#p(t){if(!t)return;const{route:e,params:n,query:o}=t,r={path:t.path,fullPath:t.fullPath,params:n,query:o,hash:new URL(t.fullPath,window.location.origin).hash,meta:e.meta,description:e.description,layout:e.layout,name:e.name,matched:[e]};if(this.beforeEnter)try{let t=!0;if(!1===await this.beforeEnter(r,this.#n,(e=>{e&&(t=!1,this.push(e))}))||!t)return}catch(a){return}const i=t.fullPath;let s=this.#i.get(i);s?s.activate():(s=new sn(this.#u,this.#s,t),await s.mount(this.#a,this.#c,r.layout),this.#i.set(i,s)),this.#d(t)}async push(t){const e=this.matchTo(t);e?await this.#p(e):"string"==typeof t||t.path||t.name}replace(t){this.push(t),this.#e.length>1&&this.#e.splice(-2,1)}go(t){history.go(t)}back(){history.back()}forward(){history.forward()}init(){this.#l||(this.#l=!0,document.body.addEventListener("click",(t=>{const e=t.target.closest("a");if(!e)return;const n=e.getAttribute("href");if(!n||n.startsWith("http")||n.startsWith("#"))return;t.preventDefault();const o=e.hasAttribute("reload"),r=e.getAttribute("vrefof")||"",i=e.closest(`[vref='${r}']`),s=i?.$env?.root||"";o||this.#o!==s?window.location.href=n:this.push(n)}),!0),window.addEventListener("popstate",(()=>{this.push(window.location.href)})))}ParseVrouter(t,e,n){this.#s=e,this.#a=n,this.#o=n.root||"",this.#c=Array.from(e.childNodes),this.#u=t,this.push(window.location.href)}},cn={$router:an},ln=[];document.addEventListener("click",(t=>{ln.forEach((e=>{e?.dom instanceof Element&&"function"==typeof e?.callback&&(e.dom.contains(t.target)||e.callback(t))}))}));const un={CamelToKebabCase:function(t){return 0===t.length?"":t.charAt(0).toLowerCase()+t.slice(1).replace(/([A-Z])/g,(function(t,e){return"-"+e.toLowerCase()}))},EventsList:["load","unload","beforeunload","resize","scroll","submit","reset","input","change","focus","blur","keydown","keypress","keyup","click","dblclick","contextmenu","mousedown","mouseup","mousemove","mouseover","mouseout","mouseenter","mouseleave","touchstart","touchmove","touchend","touchcancel","drag","dragstart","dragend","dragover","dragenter","dragleave","drop","copy","cut","paste","animationstart","animationend","animationiteration","transitionend","abort","error","loadstart","progress","play","pause","ended","volumechange","timeupdate","loadeddata","waiting","playing","online","offline","storage","visibilitychange"],BindInputDomValue:function(t,e,n,o){const r="string"==typeof t?document.querySelector(t):t;if(r){switch(r.type||r.tagName.toLowerCase()){case"text":case"password":case"email":case"tel":case"url":case"search":case"number":case"range":case"color":case"date":case"time":case"datetime-local":case"month":case"week":case"hidden":case"textarea":o((()=>{r.value=e[n]})),r.addEventListener("input",(function(){e[n]=this.value}));break;case"checkbox":o((function(){r.checked=!!e[n]})),r.addEventListener("change",(function(){e[n]=this.checked}));break;case"radio":o((()=>{r.checked=r.value===e[n]})),r.addEventListener("change",(function(){this.checked&&(e[n]=this.value)}));break;case"select-one":case"select-multiple":o((()=>{let t=e[n];if(r.multiple){const e=Array.isArray(t)?t:[];for(let t=0;t{if("outer"===e){let e=ln.length;return ln.push({dom:t,callback:n}),()=>{ln[e]=null}}}},fn=async t=>navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(t):(prompt("http\u73af\u5883\u65e0\u6cd5\u81ea\u52a8\u590d\u5236\uff0c\u8bf7\u624b\u52a8\u590d\u5236\u5185\u5bb9\u5230\u526a\u8d34\u677f:",t),new Promise((t=>{})));class hn{postMessage=(t,e)=>{};constructor(t={}){this.options={highlightColor:"#007bff",overlayColor:"rgba(0, 123, 255, 0.1)",borderWidth:"2px",zIndex:1e4,showTagName:!0,...t},this.isActive=!1,this.selectedElement=null,this.currentHoverElement=null,this.overlay=null,this.selectedOverlay=null,this.tooltip=null,this.selectedTooltip=null,this.actionPanel=null,this.originalCursor="",this.init()}init(){this.createStyles(),this.bindEvents()}createStyles(){const t=document.createElement("style");t.textContent=`\n .div-selector-overlay {\n position: fixed;\n pointer-events: none;\n border: ${this.options.borderWidth} solid ${this.options.highlightColor};\n background: ${this.options.overlayColor};\n z-index: ${this.options.zIndex};\n transition: all 0.2s ease;\n box-sizing: border-box;\n }\n \n .div-selector-selected {\n position: fixed;\n pointer-events: none;\n border: ${this.options.borderWidth} solid #28a745;\n background: rgba(40, 167, 69, 0.1);\n z-index: ${this.options.zIndex-1};\n box-sizing: border-box;\n }\n \n .div-selector-tooltip {\n position: fixed;\n background: rgba(51, 51, 51, 0.95);\n cursor:pointer;\n color: white;\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: 'Consolas', 'Monaco', 'Courier New', monospace;\n z-index: ${this.options.zIndex+1};\n user-select: none;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n border: 1px solid rgba(255,255,255,0.1);\n backdrop-filter: blur(4px);\n }\n \n .div-selector-tooltip.hover {\n background: rgba(0, 123, 255, 0.9);\n }\n \n .div-selector-tooltip.selected {\n background: rgba(40, 167, 69, 0.9);\n border-color: rgba(40, 167, 69, 0.3);\n }\n \n .div-selector-actions {\n position: fixed;\n background: white;\n border: 1px solid #ddd;\n border-radius: 8px;\n padding: 8px;\n z-index: ${this.options.zIndex+2};\n box-shadow: 0 4px 16px rgba(0,0,0,0.15);\n display: flex;\n gap: 6px;\n min-width: 30px;\n backdrop-filter: blur(8px);\n }\n \n .div-selector-btn {\n padding: 4px 6px;\n border: 1px solid #ddd;\n background: white;\n border-radius: 6px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.2s ease;\n text-align: left;\n white-space: nowrap;\n }\n \n .div-selector-btn:hover {\n background: #f8f9fa;\n transform: translateX(2px);\n }\n \n .div-selector-btn.danger {\n color: #dc3545;\n border-color: #dc3545;\n }\n \n .div-selector-btn.danger:hover {\n background: #dc3545;\n color: white;\n }\n \n .div-selector-btn.primary {\n background: #007bff;\n color: white;\n border-color: #007bff;\n }\n \n .div-selector-btn.primary:hover {\n background: #0056b3;\n }\n \n .div-selector-active {\n cursor: crosshair !important;\n }\n `,document.head.appendChild(t)}bindEvents(){this.handleMouseMove=this.handleMouseMove.bind(this),this.handleClick=this.handleClick.bind(this),this.handleScroll=this.handleScroll.bind(this),this.handleResize=this.handleResize.bind(this)}activate(){this.isActive||(this.isActive=!0,this.originalCursor=document.body.style.cursor,document.body.classList.add("div-selector-active"),document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("click",this.handleClick),window.addEventListener("scroll",this.handleScroll),window.addEventListener("resize",this.handleResize),this.createOverlay(),this.createTooltip())}deactivate(){this.isActive&&(this.isActive=!1,document.body.style.cursor=this.originalCursor,document.body.classList.remove("div-selector-active"),document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("click",this.handleClick),window.removeEventListener("scroll",this.handleScroll),window.removeEventListener("resize",this.handleResize),this.removeOverlay(),this.removeTooltip())}handleMouseMove(t){if(!this.isActive)return;const e=document.elementFromPoint(t.clientX,t.clientY);if(!e)return;if(this.isPluginElement(e))return;const n="DIV"===e.tagName?e:e.closest("div,[vref]");n&&!this.isPluginElement(n)&&this.selectedElement!==n&&(this.currentHoverElement=n,this.highlightElement(n),this.updateHoverTooltip(n))}handleClick(t){if(!this.isActive)return;const e=document.elementFromPoint(t.clientX,t.clientY);if(!e)return;if(this.isPluginElement(e))return;t.preventDefault(),t.stopPropagation();const n="DIV"===e.tagName?e:e.closest("div");n&&!this.isPluginElement(n)&&(this.selectElement(n),this.deactivate())}handleScroll(){this.selectedElement&&(this.updateSelectedOverlay(),this.updateSelectedTooltip(),this.updateActionPanelPosition()),this.currentHoverElement&&!this.selectedElement&&(this.highlightElement(this.currentHoverElement),this.updateHoverTooltip(this.currentHoverElement))}handleResize(){this.selectedElement&&(this.updateSelectedOverlay(),this.updateSelectedTooltip(),this.updateActionPanelPosition())}isPluginElement(t){return t.closest(".div-selector-overlay, .div-selector-selected, .div-selector-tooltip, .div-selector-actions")}createOverlay(){this.overlay=document.createElement("div"),this.overlay.className="div-selector-overlay",this.overlay.style.display="none",document.body.appendChild(this.overlay)}createSelectedOverlay(){this.selectedOverlay=document.createElement("div"),this.selectedOverlay.className="div-selector-selected",document.body.appendChild(this.selectedOverlay)}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="div-selector-tooltip hover",this.tooltip.style.display="none",document.body.appendChild(this.tooltip)}createSelectedTooltip(){this.selectedTooltip=document.createElement("div"),this.selectedTooltip.className="div-selector-tooltip selected",document.body.appendChild(this.selectedTooltip)}highlightElement(t){if(!this.overlay)return;const e=t.getBoundingClientRect();this.overlay.style.display="block",this.overlay.style.left=e.left+"px",this.overlay.style.top=e.top+"px",this.overlay.style.width=e.width+"px",this.overlay.style.height=e.height+"px"}updateHoverTooltip(t){if(!this.tooltip)return;const e=this.getElementInfo(t),n=t.getBoundingClientRect();this.tooltip.textContent=e,this.tooltip.style.display="block";let o=n.left-8,r=n.top-this.tooltip.offsetHeight-8;0>o&&(o=8),0>r&&(r=n.top+8),this.tooltip.style.left=o+"px",this.tooltip.style.top=r+"px"}selectElement(t){this.clearSelection(),this.selectedElement=t,this.createSelectedOverlay(),this.createSelectedTooltip(),this.updateSelectedOverlay(),this.updateSelectedTooltip(),this.overlay&&(this.overlay.style.display="none"),this.tooltip&&(this.tooltip.style.display="none"),this.showActionPanel()}updateSelectedOverlay(){if(!this.selectedOverlay||!this.selectedElement)return;const t=this.selectedElement.getBoundingClientRect();this.selectedOverlay.style.left=t.left+"px",this.selectedOverlay.style.top=t.top+"px",this.selectedOverlay.style.width=t.width+"px",this.selectedOverlay.style.height=t.height+"px"}updateSelectedTooltip(){if(!this.selectedTooltip||!this.selectedElement)return;const t=this.getElementInfo(this.selectedElement);let e=this.getFilePath(this.selectedElement);const n=this.selectedElement.getBoundingClientRect();this.selectedTooltip.addEventListener("click",(t=>{e&&this.postMessage("fs-open",e),t.preventDefault(),t.stopPropagation()})),this.selectedTooltip.textContent="\u2713 "+t;let o=n.left-8,r=n.top-this.selectedTooltip.offsetHeight-8;0>o&&(o=8),0>r&&(r=n.top+8),this.selectedTooltip.style.left=o+"px",this.selectedTooltip.style.top=r+"px"}showActionPanel(){this.removeActionPanel();const t=this.selectedElement.getBoundingClientRect();this.actionPanel=document.createElement("div"),this.actionPanel.className="div-selector-actions";let e=t.right-180,n=t.top+6;e+180>window.innerWidth&&(e=t.left-180-8),0>e&&(e=8),n+40>window.innerHeight&&(n=window.innerHeight-40-8),0>n&&(n=8),this.actionPanel.style.left=e+"px",this.actionPanel.style.top=n+"px",[{text:"\ud83d\udccb",action:()=>this.copySelector(this.selectedElement)},{text:"x",action:()=>this.clearSelection()}].forEach((t=>{const e=document.createElement("button");e.className="div-selector-btn "+(t.class||""),e.textContent=t.text,e.onclick=t.action,this.actionPanel.appendChild(e)})),document.body.appendChild(this.actionPanel)}updateActionPanelPosition(){if(!this.actionPanel||!this.selectedElement)return;const t=this.selectedElement.getBoundingClientRect(),e=this.actionPanel.offsetWidth,n=this.actionPanel.offsetHeight;let o=t.right-e+8,r=t.top-8;o+e>window.innerWidth&&(o=t.left-e-8),0>o&&(o=8),r+n>window.innerHeight&&(r=window.innerHeight-n-8),0>r&&(r=8),this.actionPanel.style.left=o+"px",this.actionPanel.style.top=r+"px"}clearSelection(){this.selectedElement=null,this.selectedOverlay&&(this.selectedOverlay.remove(),this.selectedOverlay=null),this.selectedTooltip&&(this.selectedTooltip.remove(),this.selectedTooltip=null),this.removeActionPanel()}getElementInfo(t){const e=t.getBoundingClientRect();let n=t.getAttribute("vref");return n||(n=t.closest("[vref]").getAttribute("vref"),n+="."+t.tagName.toLowerCase()),`${n} (${Math.round(e.width)}\xd7${Math.round(e.height)})`}getFilePath(t){let e=t.getAttribute("vref");return e||(e=t.closest("[vref]").getAttribute("vref")),e&&(e="/ui"+e+".html"),e}copySelector(t){let e=this.getFilePath(t);fn(e).then((()=>{this.showNotification("\ud83d\udccb CSS\u9009\u62e9\u5668\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f")}))}copyXPath(t){const e=this.generateXPath(t);fn(e).then((()=>{this.showNotification("\ud83d\udd0d XPath\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f")}))}viewStyles(t){const e=window.getComputedStyle(t);let n="\ud83d\udcca \u91cd\u8981\u6837\u5f0f\u5c5e\u6027:\n\n";["display","position","width","height","margin","padding","background-color","color","font-size","border","z-index","opacity"].forEach((t=>{n+=`${t}: ${e.getPropertyValue(t)}\n`})),alert(n)}showNotification(t){const e=document.createElement("div");e.style.cssText=`\n position: fixed;\n top: 20px;\n right: 20px;\n background: linear-gradient(135deg, #28a745, #20c997);\n color: white;\n padding: 12px 18px;\n border-radius: 8px;\n z-index: ${this.options.zIndex+10};\n font-size: 14px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.2);\n transform: translateX(100%);\n transition: transform 0.3s ease;\n `,e.textContent=t,document.body.appendChild(e),setTimeout((()=>{e.style.transform="translateX(0)"}),100),setTimeout((()=>{e.style.transform="translateX(100%)",setTimeout((()=>{e.remove()}),300)}),2500)}generateXPath(t){if(t.id)return`//*[@id="${t.id}"]`;const e=[];for(;t&&t.nodeType===Node.ELEMENT_NODE;){let n=0,o=!1,r=!1;for(let e=t.previousSibling;e;e=e.previousSibling)e.nodeType===Node.ELEMENT_NODE&&e.nodeName===t.nodeName&&(r=!0,n++);for(let e=t.nextSibling;e&&!o;e=e.nextSibling)e.nodeType===Node.ELEMENT_NODE&&e.nodeName===t.nodeName&&(o=!0);const i=t.nodeName.toLowerCase(),s=r||o?`[${n+1}]`:"";if(e.unshift(i+s),(t=t.parentNode)===document.body)break}return e.length?"/"+e.join("/"):null}removeOverlay(){this.overlay&&(this.overlay.remove(),this.overlay=null)}removeTooltip(){this.tooltip&&(this.tooltip.remove(),this.tooltip=null)}removeActionPanel(){this.actionPanel&&(this.actionPanel.remove(),this.actionPanel=null)}}let dn=!1,pn=null;const mn=(t,e)=>{dn&&("string"!=typeof e&&"number"!=typeof e||(e={value:e}),window.parent.postMessage(Object.assign({type:t,from:"vdev"},e),"*"))};!async function(){const t=document.createElement("style");t.innerHTML="\n [vref] {\n display: block;\n }\n [vparsing] {\n display: none;\n -webkit-text-fill-color: transparent;\n }\n vslot, vrouter {\n display: block;\n }\n",document.head.firstChild?document.head.insertBefore(t,document.head.firstChild):document.head.appendChild(t);const e=[],n=t=>{if(!t.isConnected)return;let n=t.getAttribute("vdelay");if(n){let o=e[n];o&&o(t)}};function o(t,e){const n=Function("sandbox",t=`with (sandbox) { ${t} }`);let o={data:null,key:null};const r=t=>new Proxy(t,{has:(t,e)=>!0,get(t,e,n){if(e===Symbol.unscopables)return;let i=Reflect.get(t,e,n);return o.data=t,o.key=e,"object"==typeof i&&i&&i[w.DataID]?r(i):i},set:(t,e,n,o)=>!1});return n(r(e)),o}new MutationObserver((function(t,e){t.forEach((function(t){for(let e of t.addedNodes)1===e.nodeType&&(n(e),e.querySelectorAll("*[vdelay]").forEach(n))}))})).observe(document.body,{attributes:!1,childList:!0,subtree:!0,characterData:!1});const r=/{{|}}/g,i=/^(\s*(\w+)\s+in\s+|\((\w+),\s*(\w+)\)\s+in\s+)([\w\$\.\[\]\(\)'"]+)$/;window.$vyes||(window.$vyes=new class{app=null;root=null;vget=en;vproxy=w;t=!0;$router=cn.$router;constructor(t){"string"==typeof t?this.app=document.getElementById(t):t instanceof HTMLElement?this.app=t:this.app=document.body,this.app&&(async()=>{let t=await en.FetchUI(window.location.pathname,{},!0);this.root=t.env?.root||"",t.env?.vdev&&window.self!==window.top&&(dn||(dn=!0,pn=new hn,mn("iframe-loaded"),pn.postMessage=mn,window.addEventListener("keyup",(t=>{"Escape"===t.key&&mn("key-esc")})),setTimeout((()=>{window.$vyes&&window.$vyes.$router&&$vyes.$router.onChange((t=>{mn("url-change",t.fullPath)}))}),100),window.addEventListener("message",(t=>{const e=t.data;if("vyes"==e.from)switch(e.type){case"reload":window.location.reload();break;case"magic":pn&&pn.isActive?pn.deactivate():pn&&pn.activate()}})))),this.parseRef("root",this.app,{},t.env||{},t,!0)})()}async parseDom(t,e={},n){if(n instanceof HTMLElement)throw Error("env error");let o=t.nodeName.toLowerCase();if(3===t.nodeType)return void this.parseTextNode(t,e,n);if(8===t.nodeType)return;if(1!==t.nodeType)return;if(t.hasAttribute("novyes")||t.vparsed)return;let r=t.getAttribute("v-for");if(null!==r)return void this.parseVfor(r,t,e,n);if(-1!==o.indexOf("-")){let r="/"+o.split("-").join("/"),i=t.hasAttribute("single");return this.parseRef(r,t,e,n,null,i),void(t.vparsed=!0)}if(t.getAttribute(":vsrc")){let o=t.getAttribute(":vsrc");t.removeAttribute(":vsrc");let r=Array.from(t.attributes).map((t=>({name:t.name,value:t.value}))),i=Array.from(t.childNodes);return void w.Watch((()=>{delete t.vparsed,t.setAttribute("vparsing","");let s=w.Run(o,e,n);s&&(Array.from(t.attributes).forEach((e=>{t.removeAttribute(e.name)})),t.innerHTML="",r.forEach((e=>{t.setAttribute(e.name,e.value)})),i.forEach((e=>{t.appendChild(e.cloneNode(!0))})),this.parseRef(s,t,e,n,null,!1),t.vparsed=!0)}))}if(t.getAttribute("vsrc")){let o=t.hasAttribute("single");return this.parseRef(t.getAttribute("vsrc"),t,e,n,null,o),void(t.vparsed=!0)}if("vslot"===o)return this.parseSlots(t,e,n),void(t.vparsed=!0);if("vrouter"===o)return this.parseAttrs(t,e,n),void cn.$router.ParseVrouter(this,t,n);this.parseAttrs(t,e,n);let i=this.parseVif(Array.from(t.childNodes),e,n);for(let s of i)this.parseDom(s,e,n);t.vparsed=!0}onMountedRun(t,n,o=!0){if(o){if(t.isConnected)return void n(t);let o=e.push((t=>{t.removeAttribute("vdelay"),n(t)}));return void t.setAttribute("vdelay",o-1)}t.isConnected&&n(t);let r=e.push(n);t.setAttribute("vdelay",r-1)}AllENVs={};async parseRef(t,e,n,o,r,i=!1){e.setAttribute("vparsing","");let s=o,a=e.getAttribute("vrefof"),c=e.closest(`*[vref='${a}']`);c&&(o=c.$env),!r&&t&&(t.endsWith(".html")||(t+=".html"),r=await en.FetchUI(t,o,e.hasAttribute("root"))),o=Object.assign({},o,r?.env||{}),e.$env=o,e.$vsrc=t,o.$router=cn.$router,o.$emit=(t,...n)=>{if(t=t.toLowerCase(),!e.$vevent)return;let o=e.$vevent[t];o&&"function"==typeof o&&o(...n)};let l=await this.setupRef(e,n,s,r,i);i?this.parseAttrs(e,l,o,r?.customAttrs):this.parseAttrs(e,n,s,r?.customAttrs);let u=this.parseVif(Array.from(e.childNodes),l,o);for(let f of u)this.parseDom(f,l,o);e.removeAttribute("vparsing"),this.mountRef(e,l,o,r)}async setupRef(t,e,n,r,i=!1){let s=w.Wrap({});if(r.setup){let e=r.setup.innerHTML;e=await w.ParseImport(e,s,t.$env,t.$vsrc),await w.AsyncRun(e,s,t.$env,{$node:t,$watch:t=>{setTimeout((()=>{w.Watch(t)}),50)}})}if(t.$refScope=e,t.$refData=s,i)return s;if(!t.$refSlots){let e=w.Wrap({});t.childNodes.forEach((t=>{let n=t.getAttribute?t.getAttribute("vslot"):"";n=n||"",e[n]||(e[n]=[]),e[n].push(t)})),t.$refSlots=e}t.innerHTML="";let a=r.body.cloneNode(!0);t.append(...a.childNodes),Object.keys(s).forEach((r=>{const i=un.CamelToKebabCase(r);if(t.hasAttribute(r)?s[r]=t.getAttribute(r):t.hasAttribute(i)&&(s[r]=t.getAttribute(i)),t.hasAttribute(":"+r)||t.hasAttribute(":"+i)){let o=t.getAttribute(":"+r)||t.getAttribute(":"+i);t.removeAttribute(":"+r),t.removeAttribute(":"+i),w.Watch((()=>{s[r]=o?w.Run(o,e,n):e[r]}))}if(t.hasAttribute("v:"+r)||t.hasAttribute("v:"+i)){let n=t.getAttribute("v:"+r)||t.getAttribute("v:"+i);t.removeAttribute("v:"+r),t.removeAttribute("v:"+i),n||(n=r);let a=o(n,e);if(a.data&&a.key){let t=a.key,e=a.data;void 0!==e[t]&&null!==e[t]||(e[t]=s[r]),w.Watch((()=>{s[r]=e[t]})),w.Watch((()=>{e[t]=s[r]}))}}}));let c=Array.from(a.attributes);return c=c.filter((e=>!this.parseAttr(t,e.name,e.value,s,n)||(a.removeAttribute(e.name),!1))),c.forEach((e=>{if("class"===e.name)t.classList.add(...e.value.trim().split(/\s+/));else if("style"===e.name){let n=e.value.split(";");for(let e of n){let n=e.split(":");if(2===n.length&&!t.style[n[0]]){let e=n[0].trim();e.startsWith("--")?t.style.setProperty(e,n[1].trim()):t.style[e]=n[1].trim()}}}else t.getAttribute(e.name)||t.setAttribute(e.name,e.value)})),s}async mountRef(t,e,n,o){for(let r of o.scripts)r.hasAttribute("active")?this.onMountedRun(t,(()=>{w.AsyncRun(r.innerHTML,e,n,{$node:t,$watch:w.Watch})}),!1):w.AsyncRun(r.innerHTML,e,n,{$node:t,$watch:w.Watch})}parseAttrs(t,e,n,o){if("A"===t.nodeName&&this.parseAHref(t,e,n),Array.from(t.attributes).forEach((o=>{this.parseAttr(t,o.name,o.value,e,n)&&t.removeAttribute(o.name)})),o&&Object.keys(o).forEach((e=>{this.parseAttr(t,e,o[e],t.$refData,n)})),t.hasAttribute("v-show")){let o=t.getAttribute("v-show"),r=t.style.display;w.Watch((()=>{let i=w.Run(o,e,n);t.style.display=i?r:"none"}))}}parseAHref(t,e,n){if(!t.hasAttribute("href")&&!t.hasAttribute(":href"))return;w.Watch((()=>{let o=t.getAttribute("href");if(t.hasAttribute(":href")){let r=t.getAttribute(":href");t.removeAttribute(":href"),o=w.Run(r,e,n)}if(o&&!o.startsWith("#")&&!o.startsWith("http"))if(o.startsWith("@"))t.hasAttribute("reload")||t.setAttribute("reload",""),t.setAttribute("href",o.slice(1));else if(o){let e=n?.root;e&&(o=e+o),t.setAttribute("href",o)}}));const o=e=>{let o=e?.fullPath;n.root&&(o=n.root+o),t.getAttribute("href")===o?t.setAttribute("active",""):t.removeAttribute("active")};o(cn.$router.current),cn.$router.onChange(o)}parseAttr(t,e,n,r,i){if(e.startsWith(":")){let o=e.slice(1);return"class"===o||"style"===o?this.handleStyle(t,o,n,r,i):w.Watch((()=>{let e;e=n?w.Run(n,r,i):r[o],un.SetAttr(t,o,e)})),!0}if(e.startsWith("@"))return this.handleEvent(t,e,n,r,i),!0;if(e.indexOf("!")>-1);else if(e.startsWith("v:")){let e=o(n,r);if(e.data&&e.key){let n=e.key,o=e.data;return un.BindInputDomValue(t,o,n,w.Watch)}}else if("vdom"===e){let e=o(n,r);return e.data&&e.key&&(e.data[e.key]=t),!0}return!1}handleStyle(t,e,n,o,r){let i="";w.Watch((()=>{let s=w.Run(n,o,r);if("function"==typeof s&&(s=s()),"class"===e){if(i&&(t.classList.remove(...i.split(/\s+/)),i=""),s instanceof Array)i="",s.forEach((t=>{if("string"==typeof t&&t.length)i+=" "+t;else if("object"==typeof t)for(let e in t)t[e]&&(i+=" "+e)}));else if("string"==typeof s&&s.length)i=s.trim();else if("object"==typeof s){i="";for(let t in s)s[t]&&(i+=" "+t)}i=i.trim(),i&&t.classList.add(...i.split(/\s+/))}else if("style"===e){if(i)if("object"==typeof i)for(let e in i)e.startsWith("--")?t.style.removeProperty(e):t.style[e]="";else if("string"==typeof i){let e=i.split(";");for(let n of e){let e=n.split(":");2===e.length&&(e[0].trim().startsWith("--")?t.style.removeProperty(e[0].trim()):t.style[e[0].trim()]="")}}if("object"==typeof s)for(let e in s)e.startsWith("--")?t.style.setProperty(e,s[e]):t.style[e]=s[e];else if("string"==typeof s){let e=s.split(";");for(let n of e){let e=n.split(":");2===e.length&&(e[0].trim().startsWith("--")?t.style.setProperty(e[0].trim(),e[1].trim()):t.style[e[0].trim()]=e[1].trim())}}i=s}}))}handleEvent(t,e,n,o,r){let i=e.slice(1).split("."),s={self:!1,prevent:!1,stop:!1},a=i[0];if("mounted"===a)this.onMountedRun(t,(t=>{let e=w.Run(n,o,r);"function"==typeof e&&e(t)}),!1);else if("outerclick"===a){let e=t=>{let e=w.Run(n,o,r,{$event:t});"function"==typeof e&&e(t)};un.AddClicker(t,"outer",e)}else if(-1!==un.EventsList.indexOf(a)){"keydown"!==a&&"keyup"!==a&&"keypress"!==a||"INPUT"!==t.tagName&&"TEXTAREA"!==t.tagName&&t.setAttribute("tabindex","0");let e=t=>{let e=w.Run(n,o,r,{$event:t});"function"==typeof e&&e(t)};i.slice(1).forEach((i=>{if(i.startsWith("delay")){let s=i.slice(5);s=s?s.endsWith("ms")?+s.slice(0,-2):s.endsWith("s")?1e3*+s.slice(0,-1):+s:1e3,isNaN(s)&&(s=1e3),e=e=>{let i=t["_"+a];i&&"number"==typeof i&&clearTimeout(i),t["_"+a]=setTimeout((()=>{let t=w.Run(n,o,r,{$event:e});"function"==typeof t&&t(e)}),s)}}s[i]=!0})),t.addEventListener(a,(t=>{(1>=i.length||"keydown"!==a&&"keyup"!=a&&"keypress"!=a||i[1]===t.key.toLowerCase())&&(s.self&&t.currentTarget!==t.target||(s.prevent&&t.preventDefault(),s.stop&&t.stopPropagation(),e(t)))}))}else t.$vevent=t.$vevent||{},t.$vevent[a]=(...t)=>{let e=w.Run(n,o,r,{});"function"==typeof e&&e(...t)}}parseTextNode(t,e,n){let o,i=t.nodeValue.trim();if(!i)return;let s=0,a=-1,c=[];for(;null!==(o=r.exec(i));)if("{{"===o[0])a=o.index;else if("}}"===o[0]&&a>=0){s!==a&&c.push(i.slice(s,a)),c.push("");let r=i.slice(a+2,o.index),l=c.length;a=-1,s=o.index+2,w.Watch((()=>{c[l-1]=w.Run(r,e,n),"object"==typeof c[l-1]&&(c[l-1]=JSON.stringify(c[l-1])),t.nodeValue=c.join("")}))}c.push(i.slice(s)),t.nodeValue=c.join("")}vforDomCache={};parseVfor(t,e,n,o){e.removeAttribute("v-for");let r=i.exec(t);if(6===r?.length){let t=document.createElement("div");t.style.display="none";let i=w.GenUniqueID();this.vforDomCache[i]={},e.parentNode.replaceChild(t,e),w.Watch((()=>{let s=r[3]||r[2],a=r[4],c=w.Run(r[5],n,o),l=this.vforDomCache[i],u={};if("function"==typeof c?c=c():"number"==typeof c&&(c=Array.from({length:c},((t,e)=>e))),null==c&&(c=[]),c.length,"object"==typeof c){let r=Object.keys(c);for(let f in r){let h=r[f],d="";if(d=c[h]&&c[h][w.DataID]?c[h][w.DataID]:h+"."+c[h],d=i+"."+d,u[d]=!0,l[d]){a&&(l[d].$vforData[a]="0"===h?0:+h||h),document.body.contains(l[d])&&t.parentNode.insertBefore(l[d],t);continue}let p=e.cloneNode(!0);l[d]=p;let m={[s]:c[h]};a&&(m[a]="0"===h?0:+h||h),m=w.Wrap(m,n),p.$vforData=m,t.parentNode.insertBefore(p,t);let y=e.getAttribute("v-if");if(!y){this.parseDom(p,m,o);continue}l[d].removeAttribute("v-if");let b=-1;b=w.Watch((()=>{let e=l[d];if(e)if(w.Run(y,m,o)){if(e.vparsed||this.parseDom(e,m,o),!e.isConnected){let n=!1,o=t;for(let t in l)if(t!==d){if(n&&l[t].isConnected){o=l[t];break}}else n=!0;t.parentNode.insertBefore(e,o)}}else e.isConnected?e.remove():this.onMountedRun(e,(t=>{e.remove()}));else w.Cancel(b)}))}for(let t of Object.keys(l))u[t]||(l[t]instanceof Array?l[t].forEach((t=>t.remove())):l[t].remove(),delete l[t])}}))}}parseVif(t,e,n){let o={now:document.createElement("div"),conds:[],doms:[]};const r=t=>{let o={now:t.now,conds:t.conds,doms:t.doms},r=[];for(let e in o.conds){let t=o.conds[e];t=""===t?"true":"Boolean("+t+")",r.push(t)}let i=`let res = [${r.join(",")}]\n return res.indexOf(true)`;w.Watch((()=>{let t=w.Run(i,e,n),r=o.doms[t];return r||(r=document.createElement("div"),r.style.display="none"),r}),(t=>{t&&(this.onMountedRun(o.now,(e=>{e.replaceWith(t),o.now=t})),t?.vparsed||this.parseDom(t,e,n))}))};let i=t.filter((t=>!(t.getAttribute&&!t.getAttribute("v-for")&&(null!==t.getAttribute("v-if")?(o.conds.length>0&&(r(o),o={now:document.createElement("div"),conds:[],doms:[]}),t.replaceWith(o.now),o.conds.push(t.getAttribute("v-if")),t.removeAttribute("v-if"),o.doms.push(t),1):null!==t.getAttribute("v-else-if")?(o.conds.push(t.getAttribute("v-else-if")),t.removeAttribute("v-else-if"),o.doms.push(t),t.remove(),1):null!==t.getAttribute("v-else")&&(o.conds.push(""),t.removeAttribute("v-else"),o.doms.push(t),t.remove(),1)))));return o.conds.length>0&&r(o),i}parseSlots(t,e,n){let o=t.getAttribute("vrefof"),r=t.closest(`*[vref='${o}']`);if(!r)return void this.onMountedRun(t,(t=>{this.parseSlots(t,e,n)}));for(;;){let t=r?.parentNode.closest("*[vref]");if(!t)break;if(t.getAttribute("vref")!==o)break;r=t}let i=t.getAttribute("name")||"";if(t.getAttribute(":name")){let o=t.getAttribute(":name");t.removeAttribute(":name"),i=w.Run(o,e,n)}return t.originContent||(t.$originContent=Array.from(t.childNodes),t.innerHTML=""),t.$slotCache={},w.Watch((()=>{let o=r.$refSlots||{},s=r.$refScope||{},a=o[i];if(a&&a.length>0){let o=a[0].hashID;if(o){if(t.$slotCache[o])return t.innerHTML="",void t.append(...t.$slotCache[o])}else o=w.GenUniqueID(),a[0].hashID=o;t.innerHTML="",a=a.map((t=>t.cloneNode(!0))),t.append(...a);let r=s;null!==t.getAttribute("v")&&(r=function(t,e){const n=Function("sandbox",t=`with (sandbox) { ${t} }`);let o=w.Wrap({}),r=[];const i=new Proxy(e,{has:(t,e)=>!0,get(t,e,n){if(e===Symbol.unscopables)return;let o=Reflect.get(t,e,n);return-1===r.indexOf(e)&&r.push(e),o},set:(t,e,n,o)=>!1});return n(i),w.Watch((()=>{r.forEach((t=>{o[t]!==e[t]&&(o[t]=e[t])}))})),o}(t.getAttribute("v"),e),w.SetDataRoot(r,s));let i="";a.find((t=>!(!t.getAttribute||!t.getAttribute("vrefof")||(i=t.getAttribute("vrefof"),0))));let c=n;if(i){let e=t.closest(`*[vref='${i}']`);c=e?.$env||n}a=this.parseVif(a,r,c),a.forEach((t=>this.parseDom(t,r,c))),t.$slotCache[o]=a}else{t.innerHTML="",t.append(...t.$originContent);let o=!1;t.$originContent.forEach((t=>{t.hasAttribute&&t.vparsed&&(o=!0)})),o||(t.$originContent=this.parseVif(t.$originContent,e,n),t.$originContent.forEach((t=>this.parseDom(t,e,n))))}})),this.parseAttrs(t,e,n),t}}(document.body))}()},"function"==typeof define&&define.amd?define(t):t(); \ No newline at end of file diff --git a/ui/page/login.html b/ui/page/login.html index 0ac024f..945d6f3 100644 --- a/ui/page/login.html +++ b/ui/page/login.html @@ -5,7 +5,6 @@ 登录与注册 - @@ -275,36 +390,101 @@
+ + + +
@@ -323,89 +503,293 @@ + diff --git a/ui/token.js b/ui/token.js index f576779..4ac3f16 100644 --- a/ui/token.js +++ b/ui/token.js @@ -106,7 +106,12 @@ class TokenService { method: 'post', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refresh: refreshToken }) - }).then(res => res.text()) + }).then(res => { + if (res.status !== 200) { + throw new Error(`Token刷新失败,状态码: ${res.status}`); + } + return res.text() + }) this.__cache = null; // 清除缓存 this.setToken(data); } catch (e) { @@ -173,6 +178,7 @@ class TokenService { // 检查错误响应状态码是否为 401 (未授权) // 并且确保这不是一个已经重试过的请求 (通过 originalRequest._retry 标记) + if (error.response && error.response.status === 401 && !originalRequest.noretry) { // 统计该请求的重试次数