diff --git a/common/constants.go b/common/constants.go index 8e834a25..b908a560 100644 --- a/common/constants.go +++ b/common/constants.go @@ -13,6 +13,10 @@ var StartTime = time.Now().Unix() // unit: second var Version = "v0.0.0" // this hard coding will be replaced automatically when building, no need to manually change var SystemName = "One API" var ServerAddress = "http://localhost:3000" +var PayAddress = "" +var EpayId = "" +var EpayKey = "" +var Price = 7 var Footer = "" var Logo = "" var TopUpLink = "" @@ -94,10 +98,6 @@ var RequestInterval = time.Duration(requestInterval) * time.Second var SyncFrequency = 10 * 60 // unit is second, will be overwritten by SYNC_FREQUENCY -var NormalPrice = 1.5 -var StablePrice = 6.0 -var BasePrice = 1.5 - const ( RoleGuestUser = 0 RoleCommonUser = 1 diff --git a/controller/midjourney.go b/controller/midjourney.go index e9674efc..6f103363 100644 --- a/controller/midjourney.go +++ b/controller/midjourney.go @@ -19,90 +19,84 @@ func UpdateMidjourneyTask() { for { defer func() { if err := recover(); err != nil { - log.Printf("UpdateMidjourneyTask: %v", err) + log.Printf("UpdateMidjourneyTask panic: %v", err) } }() time.Sleep(time.Duration(15) * time.Second) tasks := model.GetAllUnFinishTasks() if len(tasks) != 0 { - //log.Printf("UpdateMidjourneyTask: %v", time.Now()) - ids := make([]string, 0) for _, task := range tasks { - ids = append(ids, task.MjId) - } - requestUrl := "http://107.173.171.147:8080/mj/task/list-by-condition" - requestBody := map[string]interface{}{ - "ids": ids, - } - jsonStr, err := json.Marshal(requestBody) - if err != nil { - log.Printf("UpdateMidjourneyTask: %v", err) - continue - } - req, err := http.NewRequest("POST", requestUrl, bytes.NewBuffer(jsonStr)) - if err != nil { - log.Printf("UpdateMidjourneyTask: %v", err) - continue - } - req.Header.Set("Content-Type", "application/json") - req.Header.Set("mj-api-secret", "uhiftyuwadbkjshbiklahcuitguasguzhxliawodawdu") - resp, err := httpClient.Do(req) - if err != nil { - log.Printf("UpdateMidjourneyTask: %v", err) - continue - } - defer resp.Body.Close() - var response []Midjourney - err = json.NewDecoder(resp.Body).Decode(&response) - if err != nil { - log.Printf("UpdateMidjourneyTask: %v", err) - continue - } - for _, responseItem := range response { - var midjourneyTask *model.Midjourney - for _, mj := range tasks { - mj.MjId = responseItem.MjId - midjourneyTask = model.GetMjByuId(mj.Id) + midjourneyChannel, err := model.GetChannelById(task.ChannelId, true) + if err != nil { + log.Printf("UpdateMidjourneyTask: %v", err) + task.FailReason = fmt.Sprintf("获取渠道信息失败,请联系管理员,渠道ID:%d", task.ChannelId) + task.Status = "FAILURE" + task.Progress = "100%" + err := task.Update() + if err != nil { + log.Printf("UpdateMidjourneyTask error: %v", err) + } + continue } - if midjourneyTask != nil { - midjourneyTask.Code = 1 - midjourneyTask.Progress = responseItem.Progress - midjourneyTask.PromptEn = responseItem.PromptEn - midjourneyTask.State = responseItem.State - midjourneyTask.SubmitTime = responseItem.SubmitTime - midjourneyTask.StartTime = responseItem.StartTime - midjourneyTask.FinishTime = responseItem.FinishTime - midjourneyTask.ImageUrl = responseItem.ImageUrl - midjourneyTask.Status = responseItem.Status - midjourneyTask.FailReason = responseItem.FailReason - if midjourneyTask.Progress != "100%" && responseItem.FailReason != "" { - log.Println(midjourneyTask.MjId + " 构建失败," + midjourneyTask.FailReason) - midjourneyTask.Progress = "100%" - err = model.CacheUpdateUserQuota(midjourneyTask.UserId) - if err != nil { - log.Println("error update user quota cache: " + err.Error()) - } else { - modelRatio := common.GetModelRatio(imageModel) - groupRatio := common.GetGroupRatio("default") - ratio := modelRatio * groupRatio - quota := int(ratio * 1 * 1000) - if quota != 0 { - err := model.IncreaseUserQuota(midjourneyTask.UserId, quota) - if err != nil { - log.Println("fail to increase user quota") - } - logContent := fmt.Sprintf("%s 构图失败,补偿 %s", midjourneyTask.MjId, common.LogQuota(quota)) - model.RecordLog(midjourneyTask.UserId, 1, logContent) + requestUrl := fmt.Sprintf("%s/mj/task/%s/fetch", midjourneyChannel.BaseURL, task.MjId) + + req, err := http.NewRequest("GET", requestUrl, bytes.NewBuffer([]byte(""))) + if err != nil { + log.Printf("UpdateMidjourneyTask error: %v", err) + continue + } + + req.Header.Set("Content-Type", "application/json") + req.Header.Set("mj-api-secret", midjourneyChannel.Key) + resp, err := httpClient.Do(req) + if err != nil { + log.Printf("UpdateMidjourneyTask error: %v", err) + continue + } + defer resp.Body.Close() + var responseItem Midjourney + err = json.NewDecoder(resp.Body).Decode(&responseItem) + if err != nil { + log.Printf("UpdateMidjourneyTask error: %v", err) + continue + } + task.Code = 1 + task.Progress = responseItem.Progress + task.PromptEn = responseItem.PromptEn + task.State = responseItem.State + task.SubmitTime = responseItem.SubmitTime + task.StartTime = responseItem.StartTime + task.FinishTime = responseItem.FinishTime + task.ImageUrl = responseItem.ImageUrl + task.Status = responseItem.Status + task.FailReason = responseItem.FailReason + if task.Progress != "100%" && responseItem.FailReason != "" { + log.Println(task.MjId + " 构建失败," + task.FailReason) + task.Progress = "100%" + err = model.CacheUpdateUserQuota(task.UserId) + if err != nil { + log.Println("error update user quota cache: " + err.Error()) + } else { + modelRatio := common.GetModelRatio(imageModel) + groupRatio := common.GetGroupRatio("default") + ratio := modelRatio * groupRatio + quota := int(ratio * 1 * 1000) + if quota != 0 { + err := model.IncreaseUserQuota(task.UserId, quota) + if err != nil { + log.Println("fail to increase user quota") } + logContent := fmt.Sprintf("%s 构图失败,补偿 %s", task.MjId, common.LogQuota(quota)) + model.RecordLog(task.UserId, 1, logContent) } } - - err = midjourneyTask.Update() - if err != nil { - log.Printf("UpdateMidjourneyTaskFail: %v", err) - } - log.Printf("UpdateMidjourneyTask: %v", midjourneyTask) } + + err = task.Update() + if err != nil { + log.Printf("UpdateMidjourneyTask error: %v", err) + } + log.Printf("UpdateMidjourneyTask success: %v", task) } } } diff --git a/controller/misc.go b/controller/misc.go index e382e482..cf324b78 100644 --- a/controller/misc.go +++ b/controller/misc.go @@ -27,15 +27,16 @@ func GetStatus(c *gin.Context) { "wechat_qrcode": common.WeChatAccountQRCodeImageURL, "wechat_login": common.WeChatAuthEnabled, "server_address": common.ServerAddress, + "pay_address": common.PayAddress, + "epay_id": common.EpayId, + "epay_key": common.EpayKey, + "price": common.Price, "turnstile_check": common.TurnstileCheckEnabled, "turnstile_site_key": common.TurnstileSiteKey, "top_up_link": common.TopUpLink, "chat_link": common.ChatLink, "quota_per_unit": common.QuotaPerUnit, "display_in_currency": common.DisplayInCurrencyEnabled, - "normal_price": common.NormalPrice, - "stable_price": common.StablePrice, - "base_price": common.BasePrice, }, }) return diff --git a/controller/relay-mj.go b/controller/relay-mj.go index e1f6a2cd..3b0f762a 100644 --- a/controller/relay-mj.go +++ b/controller/relay-mj.go @@ -356,6 +356,7 @@ func relayMidjourneySubmit(c *gin.Context, relayMode int) *MidjourneyResponse { Status: "", Progress: "0%", FailReason: "", + ChannelId: c.GetInt("channel_id"), } if midjResponse.Code == 4 || midjResponse.Code == 24 { midjourneyTask.FailReason = midjResponse.Description diff --git a/controller/relay-text.go b/controller/relay-text.go index 20b1696a..814f480c 100644 --- a/controller/relay-text.go +++ b/controller/relay-text.go @@ -105,7 +105,6 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode { case common.ChannelTypeXunfei: apiType = APITypeXunfei } - isStable := c.GetBool("stable") baseURL := common.ChannelBaseURLs[channelType] requestURL := c.Request.URL.String() @@ -189,15 +188,10 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode { preConsumedTokens = promptTokens + textRequest.MaxTokens } modelRatio := common.GetModelRatio(textRequest.Model) - stableRatio := modelRatio groupRatio := common.GetGroupRatio(group) ratio := modelRatio * groupRatio preConsumedQuota := int(float64(preConsumedTokens) * ratio) userQuota, err := model.CacheGetUserQuota(userId) - if isStable { - stableRatio = (common.StablePrice / common.BasePrice) * modelRatio - ratio = stableRatio * groupRatio - } if err != nil { return errorWrapper(err, "get_user_quota_failed", http.StatusInternalServerError) } diff --git a/controller/topup.go b/controller/topup.go index 81b4c19d..1a83e79f 100644 --- a/controller/topup.go +++ b/controller/topup.go @@ -24,31 +24,23 @@ type AmountRequest struct { TopUpCode string `json:"top_up_code"` } -//var client, _ = epay.NewClientWithUrl(&epay.Config{ -// PartnerID: "1096", -// Key: "n08V9LpE8JffA3NPP893689u8p39NV9J", -//}, "https://api.lempay.org") - -var client, _ = epay.NewClientWithUrl(&epay.Config{ - PartnerID: "1064", - Key: "nqrrZ5RjR86mKP8rKkyrOY5Pg8NmYfKR", -}, "https://pay.yunjuw.cn") - -func GetAmount(id int, count float64, topUpCode string) float64 { - amount := count * 1.5 - if topUpCode != "" { - if topUpCode == "nekoapi" { - if id == 89 { - amount = count * 0.8 - } else if id == 105 || id == 107 { - amount = count * 1.2 - } else if id == 1 { - amount = count * 1 - } else if id == 98 { - amount = count * 1.1 - } - } +func GetEpayClient() *epay.Client { + if common.PayAddress == "" || common.EpayId == "" || common.EpayKey == "" { + return nil } + withUrl, err := epay.NewClientWithUrl(&epay.Config{ + PartnerID: common.EpayId, + Key: common.EpayKey, + }, common.PayAddress) + if err != nil { + return nil + } + return withUrl +} + +func GetAmount(count float64) float64 { + // 别问为什么用float64,问就是这么点钱没必要 + amount := count * float64(common.Price) return amount } @@ -60,38 +52,24 @@ func RequestEpay(c *gin.Context) { return } id := c.GetInt("id") - amount := GetAmount(id, float64(req.Amount), req.TopUpCode) - if id != 1 { - if req.Amount < 10 { - c.JSON(200, gin.H{"message": "最小充值10元", "data": amount, "count": 10}) - return - } - } + amount := GetAmount(float64(req.Amount)) + if req.PaymentMethod == "zfb" { - if amount > 2000 { - c.JSON(200, gin.H{"message": "支付宝最大充值2000元", "data": amount, "count": 2000}) - return - } req.PaymentMethod = "alipay" } if req.PaymentMethod == "wx" { - if amount > 2000 { - c.JSON(200, gin.H{"message": "微信最大充值2000元", "data": amount, "count": 2000}) - return - } req.PaymentMethod = "wxpay" } - returnUrl, _ := url.Parse("https://nekoapi.com/log") - notifyUrl, _ := url.Parse("https://nekoapi.com/api/user/epay/notify") + returnUrl, _ := url.Parse(common.ServerAddress + "/log") + notifyUrl, _ := url.Parse(common.ServerAddress + "/api/user/epay/notify") tradeNo := strconv.FormatInt(time.Now().Unix(), 10) payMoney := amount - //if payMoney < 400 { - // payMoney = amount * 0.99 - // if amount-payMoney > 2 { - // payMoney = amount - 2 - // } - //} + client := GetEpayClient() + if client == nil { + c.JSON(200, gin.H{"message": "error", "data": "当前管理员未配置支付信息"}) + return + } uri, params, err := client.Purchase(&epay.PurchaseArgs{ Type: epay.PurchaseType(req.PaymentMethod), ServiceTradeNo: "A" + tradeNo, @@ -126,6 +104,14 @@ func EpayNotify(c *gin.Context) { r[t] = c.Request.URL.Query().Get(t) return r }, map[string]string{}) + client := GetEpayClient() + if client == nil { + log.Println("易支付回调失败 未找到配置信息") + _, err := c.Writer.Write([]byte("fail")) + if err != nil { + log.Println("易支付回调写入失败") + } + } verifyInfo, err := client.Verify(params) if err == nil && verifyInfo.VerifyStatus { _, err := c.Writer.Write([]byte("success")) @@ -168,20 +154,9 @@ func RequestAmount(c *gin.Context) { var req AmountRequest err := c.ShouldBindJSON(&req) if err != nil { - c.JSON(200, gin.H{"message": err.Error(), "data": 10}) + c.JSON(200, gin.H{"message": "error", "data": "参数错误"}) return } - id := c.GetInt("id") - if id != 1 { - if req.Amount < 10 { - c.JSON(200, gin.H{"message": "最小充值10刀", "data": GetAmount(id, 10, req.TopUpCode), "count": 10}) - return - } - //if req.Amount > 1500 { - // c.JSON(200, gin.H{"message": "最大充值1000刀", "data": GetAmount(id, 1000, req.TopUpCode), "count": 1500}) - // return - //} - } - c.JSON(200, gin.H{"message": "success", "data": GetAmount(id, float64(req.Amount), req.TopUpCode)}) + c.JSON(200, gin.H{"message": "success", "data": GetAmount(float64(req.Amount))}) } diff --git a/middleware/distributor.go b/middleware/distributor.go index 3e664cee..c4ee6e47 100644 --- a/middleware/distributor.go +++ b/middleware/distributor.go @@ -95,51 +95,21 @@ func Distribute() func(c *gin.Context) { modelRequest.Model = "dall-e" } } - isStable := false channel, err = model.CacheGetRandomSatisfiedChannel(userGroup, modelRequest.Model) - c.Set("stable", false) if err != nil { message := fmt.Sprintf("当前分组 %s 下对于模型 %s 无可用渠道", userGroup, modelRequest.Model) - if strings.HasPrefix(modelRequest.Model, "gpt-4") { - common.SysLog("GPT-4低价渠道宕机,正在尝试转换") - nowUser, err := model.GetUserById(userId, false) - if err == nil { - if nowUser.StableMode { - userGroup = "svip" - //stableRatio = (common.StablePrice / common.BasePrice) * modelRatio - userMaxPrice, _ := strconv.ParseFloat(nowUser.MaxPrice, 64) - if userMaxPrice < common.StablePrice { - message = "当前低价通道不可用,稳定渠道价格为" + strconv.FormatFloat(common.StablePrice, 'f', -1, 64) + "R/刀" - } else { - //common.SysLog(fmt.Sprintf("用户 %s 使用稳定渠道", nowUser.Username)) - channel, err = model.CacheGetRandomSatisfiedChannel(userGroup, modelRequest.Model) - if err != nil { - message = "稳定渠道已经宕机,请联系管理员" - } - isStable = true - common.SysLog(fmt.Sprintf("用户 %s 使用稳定渠道 %v", nowUser.Username, channel)) - c.Set("stable", true) - } - - } else { - message = "当前低价通道不可用,请稍后再试,或者在后台开启稳定渠道模式" - } - } - } - //if channel == nil { - // common.SysError(fmt.Sprintf("渠道不存在:%d", channel.Id)) - // message = "数据库一致性已被破坏,请联系管理员" - //} - if !isStable { - c.JSON(http.StatusInternalServerError, gin.H{ - "error": gin.H{ - "message": message, - "type": "one_api_error", - }, - }) - c.Abort() - return + if channel != nil { + common.SysError(fmt.Sprintf("渠道不存在:%d", channel.Id)) + message = "数据库一致性已被破坏,请联系管理员" } + c.JSON(http.StatusServiceUnavailable, gin.H{ + "error": gin.H{ + "message": message, + "type": "one_api_error", + }, + }) + c.Abort() + return } } c.Set("channel", channel.Type) diff --git a/model/midjourney.go b/model/midjourney.go index bb723e8c..64b99349 100644 --- a/model/midjourney.go +++ b/model/midjourney.go @@ -17,6 +17,7 @@ type Midjourney struct { Status string `json:"status"` Progress string `json:"progress"` FailReason string `json:"fail_reason"` + ChannelId int `json:"channel_id"` } func GetAllUserTask(userId int, startIdx int, num int) []*Midjourney { diff --git a/model/option.go b/model/option.go index 604e19e5..905ef3d5 100644 --- a/model/option.go +++ b/model/option.go @@ -53,6 +53,10 @@ func InitOptionMap() { common.OptionMap["SystemName"] = common.SystemName common.OptionMap["Logo"] = common.Logo common.OptionMap["ServerAddress"] = "" + common.OptionMap["PayAddress"] = "" + common.OptionMap["EpayId"] = "" + common.OptionMap["EpayKey"] = "" + common.OptionMap["Price"] = strconv.Itoa(common.Price) common.OptionMap["GitHubClientId"] = "" common.OptionMap["GitHubClientSecret"] = "" common.OptionMap["WeChatServerAddress"] = "" @@ -71,9 +75,6 @@ func InitOptionMap() { common.OptionMap["ChatLink"] = common.ChatLink common.OptionMap["QuotaPerUnit"] = strconv.FormatFloat(common.QuotaPerUnit, 'f', -1, 64) common.OptionMap["RetryTimes"] = strconv.Itoa(common.RetryTimes) - common.OptionMap["NormalPrice"] = strconv.FormatFloat(common.NormalPrice, 'f', -1, 64) - common.OptionMap["StablePrice"] = strconv.FormatFloat(common.StablePrice, 'f', -1, 64) - common.OptionMap["BasePrice"] = strconv.FormatFloat(common.BasePrice, 'f', -1, 64) common.OptionMapRWMutex.Unlock() loadOptionsFromDatabase() @@ -157,8 +158,6 @@ func updateOptionMap(key string, value string) (err error) { common.LogConsumeEnabled = boolValue case "DisplayInCurrencyEnabled": common.DisplayInCurrencyEnabled = boolValue - case "DisplayTokenStatEnabled": - common.DisplayTokenStatEnabled = boolValue } } switch key { @@ -177,6 +176,14 @@ func updateOptionMap(key string, value string) (err error) { common.SMTPToken = value case "ServerAddress": common.ServerAddress = value + case "PayAddress": + common.PayAddress = value + case "EpayId": + common.EpayId = value + case "EpayKey": + common.EpayKey = value + case "Price": + common.Price, _ = strconv.Atoi(value) case "GitHubClientId": common.GitHubClientId = value case "GitHubClientSecret": @@ -217,12 +224,6 @@ func updateOptionMap(key string, value string) (err error) { common.TopUpLink = value case "ChatLink": common.ChatLink = value - case "NormalPrice": - common.NormalPrice, _ = strconv.ParseFloat(value, 64) - case "BasePrice": - common.BasePrice, _ = strconv.ParseFloat(value, 64) - case "StablePrice": - common.StablePrice, _ = strconv.ParseFloat(value, 64) case "ChannelDisableThreshold": common.ChannelDisableThreshold, _ = strconv.ParseFloat(value, 64) case "QuotaPerUnit": diff --git a/web/src/components/PersonalSetting.js b/web/src/components/PersonalSetting.js index 11873a30..7cd40cf2 100644 --- a/web/src/components/PersonalSetting.js +++ b/web/src/components/PersonalSetting.js @@ -1,13 +1,13 @@ import React, { useContext, useEffect, useState } from 'react'; -import {Button, Input, Checkbox, Divider, Form, Header, Image, Message, Modal} from 'semantic-ui-react'; +import { Button, Divider, Form, Header, Image, Message, Modal } from 'semantic-ui-react'; import { Link, useNavigate } from 'react-router-dom'; import { API, copy, showError, showInfo, showNotice, showSuccess } from '../helpers'; import Turnstile from 'react-turnstile'; import { UserContext } from '../context/User'; const PersonalSetting = () => { - const [userState, userDispatch] = useContext(UserContext); - let navigate = useNavigate(); + const [userState, userDispatch] = useContext(UserContext); + let navigate = useNavigate(); const [inputs, setInputs] = useState({ wechat_verification_code: '', @@ -15,10 +15,6 @@ const PersonalSetting = () => { email: '', self_account_deletion_confirmation: '' }); - const [stableMode, setStableMode] = useState({ - stableMode: false, - maxPrice: 7, - }); const [status, setStatus] = useState({}); const [showWeChatBindModal, setShowWeChatBindModal] = useState(false); const [showEmailBindModal, setShowEmailBindModal] = useState(false); @@ -29,12 +25,8 @@ const PersonalSetting = () => { const [loading, setLoading] = useState(false); const [disableButton, setDisableButton] = useState(false); const [countdown, setCountdown] = useState(30); - const [affLink, setAffLink] = useState(""); - const [systemToken, setSystemToken] = useState(""); - - // setStableMode(userState.user.stableMode, userState.user.maxPrice); - console.log(userState.user) - + const [affLink, setAffLink] = useState(""); + const [systemToken, setSystemToken] = useState(""); useEffect(() => { let status = localStorage.getItem('status'); @@ -46,9 +38,6 @@ const PersonalSetting = () => { setTurnstileSiteKey(status.turnstile_site_key); } } - // if (userState.user !== undefined) { - // setStableMode(userState.user.stable_mode, userState.user.max_price); - // } }, []); useEffect(() => { @@ -64,30 +53,17 @@ const PersonalSetting = () => { return () => clearInterval(countdownInterval); // Clean up on unmount }, [disableButton, countdown]); - useEffect(() => { - if (userState.user !== undefined) { - setStableMode({ - stableMode: userState.user.stable_mode, - maxPrice: userState.user.max_price - }) - // if (stableMode.localMaxPrice !== userState.user.max_price) { - // setStableMode({ - // localMaxPrice: userState.user.max_price - // }) - // } - } - }, [userState]); - - const handleInputChange = (e, {name, value}) => { - setInputs((inputs) => ({...inputs, [name]: value})); + const handleInputChange = (e, { name, value }) => { + setInputs((inputs) => ({ ...inputs, [name]: value })); }; const generateAccessToken = async () => { const res = await API.get('/api/user/token'); - const {success, message, data} = res.data; + const { success, message, data } = res.data; if (success) { setSystemToken(data); - setAffLink("");await copy(data); + setAffLink(""); + await copy(data); showSuccess(`令牌已重置并已复制到剪贴板`); } else { showError(message); @@ -96,11 +72,12 @@ const PersonalSetting = () => { const getAffLink = async () => { const res = await API.get('/api/user/aff'); - const {success, message, data} = res.data; + const { success, message, data } = res.data; if (success) { let link = `${window.location.origin}/register?aff=${data}`; setAffLink(link); - setSystemToken("");await copy(link); + setSystemToken(""); + await copy(link); showSuccess(`邀请链接已复制到剪切板`); } else { showError(message); @@ -108,95 +85,95 @@ const PersonalSetting = () => { }; const handleAffLinkClick = async (e) => { - e.target.select(); - await copy(e.target.value); - showSuccess(`邀请链接已复制到剪切板`); - }; + e.target.select(); + await copy(e.target.value); + showSuccess(`邀请链接已复制到剪切板`); + }; - const handleSystemTokenClick = async (e) => { - e.target.select(); - await copy(e.target.value); - showSuccess(`系统令牌已复制到剪切板`); - };const deleteAccount = async () => { + const handleSystemTokenClick = async (e) => { + e.target.select(); + await copy(e.target.value); + showSuccess(`系统令牌已复制到剪切板`); + }; + + const deleteAccount = async () => { if (inputs.self_account_deletion_confirmation !== userState.user.username) { showError('请输入你的账户名以确认删除!'); return; } - const res = await API.delete('/api/user/self'); - const { success, message } = res.data; + const res = await API.delete('/api/user/self'); + const { success, message } = res.data; - if (success) { - showSuccess('账户已删除!'); - await API.get('/api/user/logout'); - userDispatch({ type: 'logout' }); - localStorage.removeItem('user'); - navigate('/login'); - } else { - showError(message); - } - }; + if (success) { + showSuccess('账户已删除!'); + await API.get('/api/user/logout'); + userDispatch({ type: 'logout' }); + localStorage.removeItem('user'); + navigate('/login'); + } else { + showError(message); + } + }; - const bindWeChat = async () => { - if (inputs.wechat_verification_code === '') return; - const res = await API.get( - `/api/oauth/wechat/bind?code=${inputs.wechat_verification_code}` - ); - const { success, message } = res.data; - if (success) { - showSuccess('微信账户绑定成功!'); - setShowWeChatBindModal(false); - } else { - showError(message); - } - }; + const bindWeChat = async () => { + if (inputs.wechat_verification_code === '') return; + const res = await API.get( + `/api/oauth/wechat/bind?code=${inputs.wechat_verification_code}` + ); + const { success, message } = res.data; + if (success) { + showSuccess('微信账户绑定成功!'); + setShowWeChatBindModal(false); + } else { + showError(message); + } + }; - const openGitHubOAuth = () => { - window.open( - `https://github.com/login/oauth/authorize?client_id=${status.github_client_id}&scope=user:email` - ); - }; + const openGitHubOAuth = () => { + window.open( + `https://github.com/login/oauth/authorize?client_id=${status.github_client_id}&scope=user:email` + ); + }; - const sendVerificationCode = async () => { - setDisableButton(true); - if (inputs.email === '') return; - if (turnstileEnabled && turnstileToken === '') { - showInfo('请稍后几秒重试,Turnstile 正在检查用户环境!'); - return; - } - setLoading(true); - const res = await API.get( - `/api/verification?email=${inputs.email}&turnstile=${turnstileToken}` - ); - const { success, message } = res.data; - if (success) { - showSuccess('验证码发送成功,请检查邮箱!'); - } else { - showError(message); - } - setLoading(false); - }; + const sendVerificationCode = async () => { + setDisableButton(true); + if (inputs.email === '') return; + if (turnstileEnabled && turnstileToken === '') { + showInfo('请稍后几秒重试,Turnstile 正在检查用户环境!'); + return; + } + setLoading(true); + const res = await API.get( + `/api/verification?email=${inputs.email}&turnstile=${turnstileToken}` + ); + const { success, message } = res.data; + if (success) { + showSuccess('验证码发送成功,请检查邮箱!'); + } else { + showError(message); + } + setLoading(false); + }; - const bindEmail = async () => { - if (inputs.email_verification_code === '') return; - setLoading(true); - const res = await API.get( - `/api/oauth/email/bind?email=${inputs.email}&code=${inputs.email_verification_code}` - ); - const { success, message } = res.data; - if (success) { - showSuccess('邮箱账户绑定成功!'); - setShowEmailBindModal(false); - } else { - showError(message); - } - setLoading(false); - }; - - // const setStableMod = ; + const bindEmail = async () => { + if (inputs.email_verification_code === '') return; + setLoading(true); + const res = await API.get( + `/api/oauth/email/bind?email=${inputs.email}&code=${inputs.email_verification_code}` + ); + const { success, message } = res.data; + if (success) { + showSuccess('邮箱账户绑定成功!'); + setShowEmailBindModal(false); + } else { + showError(message); + } + setLoading(false); + }; return ( -
微信扫码关注公众号,输入「验证码」获取验证码(三分钟内有效)
@@ -345,7 +264,7 @@ const PersonalSetting = () => { onOpen={() => setShowEmailBindModal(true)} open={showEmailBindModal} size={'tiny'} - style={{maxWidth: '450px'}} + style={{ maxWidth: '450px' }} >取消密码登录将导致所有未绑定其他登录方式的用户(包括管理员)无法通过密码登录,确认取消?
-{inputs.ServerAddress}
- ,Authorization callback URL 填{' '}
- {`${inputs.ServerAddress}/oauth/github`}
- 取消密码登录将导致所有未绑定其他登录方式的用户(包括管理员)无法通过密码登录,确认取消?
+{inputs.ServerAddress}
+ ,Authorization callback URL 填{' '}
+ {`${inputs.ServerAddress}/oauth/github`}
+ 通道:官方通道
-状态:存活
-价格:{statusState?.status?.base_price}R / 刀
+名称:{statusState?.status?.system_name}
+版本:{statusState?.status?.version ? statusState?.status?.version : "unknown"}
++ 源码: + + https://github.com/songquanpeng/one-api + +
+启动时间:{getStartTimeString()}
通道:官方通道|低价通道
- 状态: - {statusState?.status?.stable_price===-1? - 不 可 用 - : - 可 用 - } - | - {statusState?.status?.normal_price===-1? - 不 可 用 - : - 可 用 - } + 邮箱验证: + {statusState?.status?.email_verification === true + ? '已启用' + : '未启用'}
- 价格:{statusState?.status?.stable_price}R / 刀|{statusState?.status?.normal_price}R / 刀 + GitHub 身份验证: + {statusState?.status?.github_oauth === true + ? '已启用' + : '未启用'} +
++ 微信身份验证: + {statusState?.status?.wechat_login === true + ? '已启用' + : '未启用'} +
++ Turnstile 用户校验: + {statusState?.status?.turnstile_check === true + ? '已启用' + : '未启用'}