diff --git a/api/core/app_server.go b/api/core/app_server.go index 3f9f33d0..9917fc06 100644 --- a/api/core/app_server.go +++ b/api/core/app_server.go @@ -25,55 +25,6 @@ import ( "gorm.io/gorm" ) -// AuthConfig 定义授权配置 -type AuthConfig struct { - ExactPaths map[string]bool // 精确匹配的路径 - PrefixPaths map[string]bool // 前缀匹配的路径 -} - -var authConfig = &AuthConfig{ - ExactPaths: map[string]bool{ - "/api/user/login": false, - "/api/user/logout": false, - "/api/user/resetPass": false, - "/api/user/register": false, - "/api/user/clogin": false, - "/api/user/clogin/callback": false, - "/api/user/signin": false, - "/api/admin/login": false, - "/api/admin/logout": false, - "/api/admin/login/captcha": false, - "/api/app/list": false, - "/api/app/type/list": false, - "/api/app/list/user": false, - "/api/model/list": false, - "/api/mj/imgWall": false, - "/api/mj/notify": false, - "/api/invite/hits": false, - "/api/sd/imgWall": false, - "/api/dall/imgWall": false, - "/api/product/list": false, - "/api/menu/list": false, - "/api/markMap/client": false, - "/api/payment/doPay": false, - "/api/payment/payWays": false, - "/api/download": false, - "/api/dall/models": false, - "/api/chat/message": false, // 聊天接口需要特殊处理 - "/api/realtime": false, // 实时通信接口需要特殊处理 - "/api/realtime/voice": false, // 语音聊天接口需要特殊处理 - }, - PrefixPaths: map[string]bool{ - "/api/test/": false, - "/api/payment/notify/": false, - "/api/config/": false, - "/api/function/": false, - "/api/sms/": false, - "/api/captcha/": false, - "/static/": false, - }, -} - type AppServer struct { Config *types.AppConfig Engine *gin.Engine @@ -94,10 +45,10 @@ func NewServer(appConfig *types.AppConfig, redis *redis.Client, sysConfig *types func (s *AppServer) Init(client *redis.Client) { s.Engine.Use(middleware.ParameterHandlerMiddleware()) - s.Engine.Use(middleware.StaticMiddleware()) s.Engine.Use(errorHandler) // 添加静态资源访问 s.Engine.Static("/static", s.Config.StaticDir) + s.Engine.Use(middleware.StaticMiddleware()) } func (s *AppServer) Run(db *gorm.DB) error { diff --git a/api/core/types/oss.go b/api/core/types/oss.go index 434d0ddd..e22f9ef9 100644 --- a/api/core/types/oss.go +++ b/api/core/types/oss.go @@ -20,7 +20,6 @@ type MiniOssConfig struct { AccessKey string `json:"access_key"` AccessSecret string `json:"access_secret"` Bucket string `json:"bucket"` - SubDir string `json:"sub_dir"` UseSSL bool `json:"use_ssl"` Domain string `json:"domain"` } @@ -30,7 +29,6 @@ type QiNiuOssConfig struct { AccessKey string `json:"access_key"` AccessSecret string `json:"access_secret"` Bucket string `json:"bucket"` - SubDir string `json:"sub_dir"` Domain string `json:"domain"` } diff --git a/api/core/types/sms.go b/api/core/types/sms.go index 4d9c6504..7c95ab41 100644 --- a/api/core/types/sms.go +++ b/api/core/types/sms.go @@ -8,9 +8,9 @@ package types // * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ type SMSConfig struct { - Active string - Ali SmsConfigAli - Bao SmsConfigBao + Active string `json:"active"` + Ali SmsConfigAli `json:"aliyun"` + Bao SmsConfigBao `json:"bao"` } // SmsConfigAli 阿里云短信平台配置 diff --git a/api/handler/function_handler.go b/api/handler/function_handler.go index ed40ae21..174c8b93 100644 --- a/api/handler/function_handler.go +++ b/api/handler/function_handler.go @@ -11,7 +11,6 @@ import ( "errors" "fmt" "geekai/core" - "geekai/core/middleware" "geekai/core/types" "geekai/service" "geekai/service/dalle" @@ -60,12 +59,9 @@ func (h *FunctionHandler) RegisterRoutes() { group.GET("list", h.List) // 需要用户授权的接口 - group.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis)) - { - group.POST("weibo", h.WeiBo) - group.POST("zaobao", h.ZaoBao) - group.POST("dalle3", h.Dall3) - } + group.POST("weibo", h.WeiBo) + group.POST("zaobao", h.ZaoBao) + group.POST("dalle3", h.Dall3) } type resVo struct { diff --git a/api/service/crawler/service.go b/api/service/crawler/service.go deleted file mode 100644 index 39fb2fa7..00000000 --- a/api/service/crawler/service.go +++ /dev/null @@ -1,333 +0,0 @@ -package crawler - -import ( - "context" - "errors" - "fmt" - "geekai/logger" - "net/url" - "strings" - "time" - - "github.com/go-rod/rod" - "github.com/go-rod/rod/lib/launcher" - "github.com/go-rod/rod/lib/proto" -) - -// Service 网络爬虫服务 -type Service struct { - browser *rod.Browser -} - -// NewService 创建一个新的爬虫服务 -func NewService() (*Service, error) { - // 启动浏览器 - path, _ := launcher.LookPath() - u := launcher.New().Bin(path). - Headless(true). // 无头模式 - Set("disable-web-security", ""). // 禁用网络安全限制 - Set("disable-gpu", ""). // 禁用 GPU 加速 - Set("no-sandbox", ""). // 禁用沙箱模式 - Set("disable-setuid-sandbox", ""). // 禁用 setuid 沙箱 - MustLaunch() - - browser := rod.New().ControlURL(u).MustConnect() - - return &Service{ - browser: browser, - }, nil -} - -// SearchResult 搜索结果 -type SearchResult struct { - Title string `json:"title"` // 标题 - URL string `json:"url"` // 链接 - Content string `json:"content"` // 内容摘要 -} - -// WebSearch 网络搜索 -func (s *Service) WebSearch(keyword string, maxPages int) ([]SearchResult, error) { - if keyword == "" { - return nil, errors.New("搜索关键词不能为空") - } - - if maxPages <= 0 { - maxPages = 1 - } - if maxPages > 10 { - maxPages = 10 // 最多搜索 10 页 - } - - results := make([]SearchResult, 0) - - // 使用百度搜索 - searchURL := fmt.Sprintf("https://www.baidu.com/s?wd=%s", url.QueryEscape(keyword)) - - // 设置页面超时 - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - // 创建页面 - page := s.browser.MustPage() - defer page.MustClose() - - // 设置视口大小 - err := page.SetViewport(&proto.EmulationSetDeviceMetricsOverride{ - Width: 1280, - Height: 800, - }) - if err != nil { - return nil, fmt.Errorf("设置视口失败: %v", err) - } - - // 导航到搜索页面 - err = page.Context(ctx).Navigate(searchURL) - if err != nil { - return nil, fmt.Errorf("导航到搜索页面失败: %v", err) - } - - // 等待搜索结果加载完成 - err = page.WaitLoad() - if err != nil { - return nil, fmt.Errorf("等待页面加载完成失败: %v", err) - } - - // 分析当前页面的搜索结果 - for i := 0; i < maxPages; i++ { - if i > 0 { - // 点击下一页按钮 - nextPage, err := page.Element("a.n") - if err != nil || nextPage == nil { - break // 没有下一页 - } - - err = nextPage.Click(proto.InputMouseButtonLeft, 1) - if err != nil { - break // 点击下一页失败 - } - - // 等待新页面加载 - err = page.WaitLoad() - if err != nil { - break - } - } - - // 提取搜索结果 - resultElements, err := page.Elements(".result, .c-container") - if err != nil || resultElements == nil { - continue - } - - for _, result := range resultElements { - // 获取标题 - titleElement, err := result.Element("h3, .t") - if err != nil || titleElement == nil { - continue - } - - title, err := titleElement.Text() - if err != nil { - continue - } - - // 获取 URL - linkElement, err := titleElement.Element("a") - if err != nil || linkElement == nil { - continue - } - - href, err := linkElement.Attribute("href") - if err != nil || href == nil { - continue - } - - // 获取内容摘要 - 尝试多个可能的选择器 - var contentElement *rod.Element - var content string - - // 尝试多个可能的选择器来适应不同版本的百度搜索结果 - selectors := []string{".content-right_8Zs40", ".c-abstract", ".content_LJ0WN", ".content"} - for _, selector := range selectors { - contentElement, err = result.Element(selector) - if err == nil && contentElement != nil { - content, _ = contentElement.Text() - if content != "" { - break - } - } - } - - // 如果所有选择器都失败,尝试直接从结果块中提取文本 - if content == "" { - // 获取结果元素的所有文本 - fullText, err := result.Text() - if err == nil && fullText != "" { - // 简单处理:从全文中移除标题,剩下的可能是摘要 - fullText = strings.Replace(fullText, title, "", 1) - // 清理文本 - content = strings.TrimSpace(fullText) - // 限制内容长度 - if len(content) > 200 { - content = content[:200] + "..." - } - } - } - - // 添加到结果集 - results = append(results, SearchResult{ - Title: title, - URL: *href, - Content: content, - }) - - // 限制结果数量,每页最多 10 条 - if len(results) >= 10*maxPages { - break - } - } - } - - // 获取真实 URL(百度搜索结果中的 URL 是短链接,需要跳转获取真实 URL) - for i, result := range results { - realURL, err := s.getRedirectURL(result.URL) - if err == nil && realURL != "" { - results[i].URL = realURL - } - } - - return results, nil -} - -// 获取真实 URL -func (s *Service) getRedirectURL(shortURL string) (string, error) { - // 创建页面 - page, err := s.browser.Page(proto.TargetCreateTarget{URL: ""}) - if err != nil { - return shortURL, err // 返回原始URL - } - defer func() { - _ = page.Close() - }() - - // 导航到短链接 - err = page.Navigate(shortURL) - if err != nil { - return shortURL, err // 返回原始URL - } - - // 等待重定向完成 - time.Sleep(2 * time.Second) - - // 获取当前 URL - info, err := page.Info() - if err != nil { - return shortURL, err // 返回原始URL - } - - return info.URL, nil -} - -// Close 关闭浏览器 -func (s *Service) Close() error { - if s.browser != nil { - err := s.browser.Close() - s.browser = nil - return err - } - return nil -} - -// SearchWeb 封装的搜索方法 -func SearchWeb(keyword string, maxPages int) (string, error) { - // 添加panic恢复机制 - defer func() { - if r := recover(); r != nil { - log := logger.GetLogger() - log.Errorf("爬虫服务崩溃: %v", r) - } - }() - - service, err := NewService() - if err != nil { - return "", fmt.Errorf("创建爬虫服务失败: %v", err) - } - defer service.Close() - - // 设置超时上下文 - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) - defer cancel() - - // 使用goroutine和通道来处理超时 - resultChan := make(chan []SearchResult, 1) - errChan := make(chan error, 1) - - go func() { - results, err := service.WebSearch(keyword, maxPages) - if err != nil { - errChan <- err - return - } - resultChan <- results - }() - - // 等待结果或超时 - select { - case <-ctx.Done(): - return "", fmt.Errorf("搜索超时: %v", ctx.Err()) - case err := <-errChan: - return "", fmt.Errorf("搜索失败: %v", err) - case results := <-resultChan: - if len(results) == 0 { - return "未找到关于 \"" + keyword + "\" 的相关搜索结果", nil - } - - // 格式化结果 - var builder strings.Builder - builder.WriteString(fmt.Sprintf("为您找到关于 \"%s\" 的 %d 条搜索结果:\n\n", keyword, len(results))) - - for i, result := range results { - // // 尝试打开链接获取实际内容 - // page := service.browser.MustPage() - // defer page.MustClose() - - // // 设置页面超时 - // pageCtx, pageCancel := context.WithTimeout(context.Background(), 10*time.Second) - // defer pageCancel() - - // // 导航到目标页面 - // err := page.Context(pageCtx).Navigate(result.URL) - // if err == nil { - // // 等待页面加载 - // _ = page.WaitLoad() - - // // 获取页面标题 - // title, err := page.Eval("() => document.title") - // if err == nil && title.Value.String() != "" { - // result.Title = title.Value.String() - // } - - // // 获取页面主要内容 - // if content, err := page.Element("body"); err == nil { - // if text, err := content.Text(); err == nil { - // // 清理并截取内容 - // text = strings.TrimSpace(text) - // if len(text) > 200 { - // text = text[:200] + "..." - // } - // result.Prompt = text - // } - // } - // } - - builder.WriteString(fmt.Sprintf("%d. **%s**\n", i+1, result.Title)) - builder.WriteString(fmt.Sprintf(" 链接: %s\n", result.URL)) - if result.Content != "" { - builder.WriteString(fmt.Sprintf(" 摘要: %s\n", result.Content)) - } - builder.WriteString("\n") - } - - return builder.String(), nil - } -} diff --git a/api/service/dalle/service.go b/api/service/dalle/service.go index 7bad5115..dd9b66db 100644 --- a/api/service/dalle/service.go +++ b/api/service/dalle/service.go @@ -122,15 +122,6 @@ type ErrRes struct { func (s *Service) Image(task types.DallTask, sync bool) (string, error) { logger.Debugf("绘画参数:%+v", task) - prompt := task.Prompt - // translate prompt - if utils.HasChinese(prompt) { - content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.TranslatePromptTemplate, prompt), task.TranslateModelId) - if err == nil { - prompt = content - logger.Debugf("重写后提示词:%s", prompt) - } - } var chatModel model.ChatModel if task.ModelId > 0 { @@ -160,7 +151,7 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) { apiURL := fmt.Sprintf("%s/v1/images/generations", apiKey.ApiURL) reqBody := imgReq{ Model: chatModel.Value, - Prompt: prompt, + Prompt: task.Prompt, N: 1, Size: task.Size, Style: task.Style, @@ -188,7 +179,7 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) { var imgURL string var data = map[string]interface{}{ "progress": 100, - "prompt": prompt, + "prompt": task.Prompt, } // 如果返回的是base64,则需要上传到oss if res.Data[0].B64Json != "" { @@ -214,7 +205,7 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) { if err != nil { return "", fmt.Errorf("error with download image: %v", err) } - content = fmt.Sprintf("```\n%s\n```\n下面是我为你创作的图片:\n\n![](%s)\n", prompt, imgURL) + content = fmt.Sprintf("```\n%s\n```\n下面是我为你创作的图片:\n\n![](%s)\n", task.Prompt, imgURL) } return content, nil diff --git a/api/service/migration_service.go b/api/service/migration_service.go index cf5bb8b3..1288af95 100644 --- a/api/service/migration_service.go +++ b/api/service/migration_service.go @@ -13,6 +13,7 @@ import ( "geekai/core/types" "geekai/store" "geekai/store/model" + "strings" "github.com/go-redis/redis/v8" "gorm.io/gorm" @@ -191,8 +192,8 @@ func (s *MigrationService) migrateCommunicationConfig(config *types.AppConfig) e // 短信配置 smsConfig := map[string]any{ - "active": config.SMS.Active, - "ali": map[string]any{ + "active": strings.ToLower(config.SMS.Active), + "aliyun": map[string]any{ "access_key": config.SMS.Ali.AccessKey, "access_secret": config.SMS.Ali.AccessSecret, "sign": config.SMS.Ali.Sign, diff --git a/api/service/mj/service.go b/api/service/mj/service.go index 7564bda0..498d3bb2 100644 --- a/api/service/mj/service.go +++ b/api/service/mj/service.go @@ -67,25 +67,6 @@ func (s *Service) Run() { continue } - // translate prompt - if utils.HasChinese(task.Prompt) { - content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.TranslatePromptTemplate, task.Prompt), task.TranslateModelId) - if err == nil { - task.Prompt = content - } else { - logger.Warnf("error with translate prompt: %v", err) - } - } - // translate negative prompt - if task.NegPrompt != "" && utils.HasChinese(task.NegPrompt) { - content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.TranslatePromptTemplate, task.NegPrompt), task.TranslateModelId) - if err == nil { - task.NegPrompt = content - } else { - logger.Warnf("error with translate prompt: %v", err) - } - } - // use fast mode as default if task.Mode == "" { task.Mode = "fast" diff --git a/api/service/oss/minio_oss.go b/api/service/oss/minio_oss.go index d7f28d4b..f7465b78 100644 --- a/api/service/oss/minio_oss.go +++ b/api/service/oss/minio_oss.go @@ -72,7 +72,7 @@ func (s MiniOss) PutUrlFile(fileURL string, ext string, useProxy bool) (string, if ext == "" { ext = filepath.Ext(parse.Path) } - filename := fmt.Sprintf("%s/%d%s", s.config.SubDir, time.Now().UnixMicro(), ext) + filename := fmt.Sprintf("%d%s", time.Now().UnixMicro(), ext) info, err := s.client.PutObject( context.Background(), s.config.Bucket, @@ -99,7 +99,7 @@ func (s MiniOss) PutFile(ctx *gin.Context, name string) (File, error) { defer fileReader.Close() fileExt := filepath.Ext(file.Filename) - filename := fmt.Sprintf("%s/%d%s", s.config.SubDir, time.Now().UnixMicro(), fileExt) + filename := fmt.Sprintf("%d%s", time.Now().UnixMicro(), fileExt) info, err := s.client.PutObject(ctx, s.config.Bucket, filename, fileReader, file.Size, minio.PutObjectOptions{ ContentType: file.Header.Get("Body-Type"), }) @@ -121,7 +121,7 @@ func (s MiniOss) PutBase64(base64Img string) (string, error) { if err != nil { return "", fmt.Errorf("error decoding base64:%v", err) } - objectKey := fmt.Sprintf("%s/%d.png", s.config.SubDir, time.Now().UnixMicro()) + objectKey := fmt.Sprintf("%d.png", time.Now().UnixMicro()) info, err := s.client.PutObject( context.Background(), s.config.Bucket, @@ -138,8 +138,7 @@ func (s MiniOss) PutBase64(base64Img string) (string, error) { func (s MiniOss) Delete(fileURL string) error { var objectKey string if strings.HasPrefix(fileURL, "http") { - filename := filepath.Base(fileURL) - objectKey = fmt.Sprintf("%s/%s", s.config.SubDir, filename) + objectKey = filepath.Base(fileURL) } else { objectKey = fileURL } diff --git a/api/service/oss/qiniu_oss.go b/api/service/oss/qiniu_oss.go index d99752a2..3623c648 100644 --- a/api/service/oss/qiniu_oss.go +++ b/api/service/oss/qiniu_oss.go @@ -75,7 +75,7 @@ func (s QiNiuOss) PutFile(ctx *gin.Context, name string) (File, error) { defer src.Close() fileExt := filepath.Ext(file.Filename) - key := fmt.Sprintf("%s/%d%s", s.config.SubDir, time.Now().UnixMicro(), fileExt) + key := fmt.Sprintf("%d%s", time.Now().UnixMicro(), fileExt) // 上传文件 ret := storage.PutRet{} extra := storage.PutExtra{} @@ -112,7 +112,7 @@ func (s QiNiuOss) PutUrlFile(fileURL string, ext string, useProxy bool) (string, if ext == "" { ext = filepath.Ext(parse.Path) } - key := fmt.Sprintf("%s/%d%s", s.config.SubDir, time.Now().UnixMicro(), ext) + key := fmt.Sprintf("%d%s", time.Now().UnixMicro(), ext) ret := storage.PutRet{} extra := storage.PutExtra{} // 上传文件字节数据 @@ -128,7 +128,7 @@ func (s QiNiuOss) PutBase64(base64Img string) (string, error) { if err != nil { return "", fmt.Errorf("error decoding base64:%v", err) } - objectKey := fmt.Sprintf("%s/%d.png", s.config.SubDir, time.Now().UnixMicro()) + objectKey := fmt.Sprintf("%d.png", time.Now().UnixMicro()) ret := storage.PutRet{} extra := storage.PutExtra{} // 上传文件字节数据 @@ -142,8 +142,7 @@ func (s QiNiuOss) PutBase64(base64Img string) (string, error) { func (s QiNiuOss) Delete(fileURL string) error { var objectKey string if strings.HasPrefix(fileURL, "http") { - filename := filepath.Base(fileURL) - objectKey = fmt.Sprintf("%s/%s", s.config.SubDir, filename) + objectKey = filepath.Base(fileURL) } else { objectKey = fileURL } diff --git a/api/utils/resp/response.go b/api/utils/resp/response.go index cc20b2bf..bc4f75ca 100644 --- a/api/utils/resp/response.go +++ b/api/utils/resp/response.go @@ -9,8 +9,9 @@ package resp import ( "geekai/core/types" - "github.com/gin-gonic/gin" "net/http" + + "github.com/gin-gonic/gin" ) func SUCCESS(c *gin.Context, values ...interface{}) { diff --git a/web/src/components/admin/AdminSidebar.vue b/web/src/components/admin/AdminSidebar.vue index 9fa861a9..738c095c 100644 --- a/web/src/components/admin/AdminSidebar.vue +++ b/web/src/components/admin/AdminSidebar.vue @@ -223,14 +223,19 @@ const items = [ title: '存储配置', }, { - icon: 'log', - index: '/admin/config/communication', - title: '通信配置', + icon: 'sms', + index: '/admin/config/sms', + title: '短信配置', }, { - icon: 'api-key', - index: '/admin/config/api', - title: 'API配置', + icon: 'email', + index: '/admin/config/smtp', + title: '邮件配置', + }, + { + icon: 'plugin', + index: '/admin/config/plugin', + title: '插件配置', }, ], }, diff --git a/web/src/components/ui/Alert.vue b/web/src/components/ui/Alert.vue new file mode 100644 index 00000000..cb187cc7 --- /dev/null +++ b/web/src/components/ui/Alert.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/web/src/router.js b/web/src/router.js index 2e18c5a3..2254ca95 100644 --- a/web/src/router.js +++ b/web/src/router.js @@ -192,16 +192,22 @@ const routes = [ component: () => import('@/views/admin/settings/StorageConfig.vue'), }, { - path: '/admin/config/communication', - name: 'admin-config-communication', - meta: { title: '通信配置' }, - component: () => import('@/views/admin/settings/CommunicationConfig.vue'), + path: '/admin/config/sms', + name: 'admin-config-sms', + meta: { title: '短信配置' }, + component: () => import('@/views/admin/settings/SmsConfig.vue'), }, { - path: '/admin/config/api', - name: 'admin-config-api', - meta: { title: 'API配置' }, - component: () => import('@/views/admin/settings/ApiConfig.vue'), + path: '/admin/config/smtp', + name: 'admin-config-smtp', + meta: { title: '邮件配置' }, + component: () => import('@/views/admin/settings/SmtpConfig.vue'), + }, + { + path: '/admin/config/plugin', + name: 'admin-config-plugin', + meta: { title: '插件配置' }, + component: () => import('@/views/admin/settings/PluginConfig.vue'), }, { path: '/admin/config/markmap', diff --git a/web/src/utils/http.js b/web/src/utils/http.js index 01620446..c1ddf351 100644 --- a/web/src/utils/http.js +++ b/web/src/utils/http.js @@ -5,8 +5,32 @@ // * @Author yangjian102621@163.com // * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -import axios from 'axios' import { getAdminToken, getUserToken, removeAdminToken, removeUserToken } from '@/store/session' +import axios from 'axios' + +// Blob 数据读取和解析的辅助函数 +export async function parseBlobResponse(blob) { + try { + // 检查 Blob 的类型 + if (blob.type && blob.type.includes('application/json')) { + // 如果是 JSON 类型,直接解析 + const text = await blob.text() + return JSON.parse(text) + } else { + // 如果不是 JSON 类型,尝试解析为文本 + const text = await blob.text() + try { + return JSON.parse(text) + } catch (e) { + // 如果解析 JSON 失败,返回文本内容 + return { message: text, rawData: text } + } + } + } catch (error) { + console.error('解析 Blob 响应失败:', error) + return { message: '解析响应数据失败', error: error.message } + } +} axios.defaults.timeout = 180000 // axios.defaults.baseURL = process.env.VUE_APP_API_HOST @@ -29,7 +53,7 @@ axios.interceptors.response.use( (response) => { return response }, - (error) => { + async (error) => { if (error.response.status === 401) { if (error.response.request.responseURL.indexOf('/api/admin') !== -1) { removeAdminToken() @@ -39,8 +63,14 @@ axios.interceptors.response.use( error.response.data.message = '请先登录' return Promise.reject(error.response.data) } + if (error.response.status === 400) { - return Promise.reject(new Error(error.response.data.message)) + let errorMessage = error.response.data.message + if (!errorMessage) { + const parsedData = await parseBlobResponse(error.response.data) + errorMessage = parsedData.message + } + return Promise.reject(new Error(errorMessage)) } else { return Promise.reject(error) } diff --git a/web/src/views/Resetpassword.vue b/web/src/views/Resetpassword.vue index 2f6606e2..b09dc8b0 100644 --- a/web/src/views/Resetpassword.vue +++ b/web/src/views/Resetpassword.vue @@ -1,5 +1,4 @@ -
+ 如果你不知道怎么获取这些配置信息,请参考文档: 支付宝配置。 -
+ @@ -52,14 +52,14 @@ -
+ 如果你不知道怎么获取这些配置信息,请参考文档: 微信支付配置。 -
+ @@ -89,14 +89,14 @@ 易支付 -
+ 如果你不知道怎么获取这些配置信息,请参考文档: 易支付配置。 -
+ @@ -114,6 +114,7 @@ + + diff --git a/web/src/views/admin/settings/SmsConfig.vue b/web/src/views/admin/settings/SmsConfig.vue new file mode 100644 index 00000000..147299bc --- /dev/null +++ b/web/src/views/admin/settings/SmsConfig.vue @@ -0,0 +1,143 @@ + + + + + diff --git a/web/src/views/admin/settings/SmtpConfig.vue b/web/src/views/admin/settings/SmtpConfig.vue new file mode 100644 index 00000000..0ffddc03 --- /dev/null +++ b/web/src/views/admin/settings/SmtpConfig.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/web/src/views/admin/settings/StorageConfig.vue b/web/src/views/admin/settings/StorageConfig.vue index e3ccffa4..44f81fb6 100644 --- a/web/src/views/admin/settings/StorageConfig.vue +++ b/web/src/views/admin/settings/StorageConfig.vue @@ -59,14 +59,39 @@ +
+ 如果你不知道怎么获取这些配置信息,请参考文档: + 七牛云配置。 +
- + + + - +
@@ -95,7 +120,6 @@
提交保存 - 连接测试
@@ -161,14 +185,16 @@ const save = () => { .then(() => ElMessage.success('保存成功')) .catch((e) => ElMessage.error(e.message)) } - -const test = () => { - ElMessage.info('请在对象存储端验证配置') -}