移除不必要的功能
This commit is contained in:
parent
43be1982d7
commit
9ab4f7a271
@ -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 Version = "v0.0.0" // this hard coding will be replaced automatically when building, no need to manually change
|
||||||
var SystemName = "One API"
|
var SystemName = "One API"
|
||||||
var ServerAddress = "http://localhost:3000"
|
var ServerAddress = "http://localhost:3000"
|
||||||
|
var PayAddress = ""
|
||||||
|
var EpayId = ""
|
||||||
|
var EpayKey = ""
|
||||||
|
var Price = 7
|
||||||
var Footer = ""
|
var Footer = ""
|
||||||
var Logo = ""
|
var Logo = ""
|
||||||
var TopUpLink = ""
|
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 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 (
|
const (
|
||||||
RoleGuestUser = 0
|
RoleGuestUser = 0
|
||||||
RoleCommonUser = 1
|
RoleCommonUser = 1
|
||||||
|
@ -19,90 +19,84 @@ func UpdateMidjourneyTask() {
|
|||||||
for {
|
for {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
log.Printf("UpdateMidjourneyTask: %v", err)
|
log.Printf("UpdateMidjourneyTask panic: %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
time.Sleep(time.Duration(15) * time.Second)
|
time.Sleep(time.Duration(15) * time.Second)
|
||||||
tasks := model.GetAllUnFinishTasks()
|
tasks := model.GetAllUnFinishTasks()
|
||||||
if len(tasks) != 0 {
|
if len(tasks) != 0 {
|
||||||
//log.Printf("UpdateMidjourneyTask: %v", time.Now())
|
|
||||||
ids := make([]string, 0)
|
|
||||||
for _, task := range tasks {
|
for _, task := range tasks {
|
||||||
ids = append(ids, task.MjId)
|
midjourneyChannel, err := model.GetChannelById(task.ChannelId, true)
|
||||||
}
|
if err != nil {
|
||||||
requestUrl := "http://107.173.171.147:8080/mj/task/list-by-condition"
|
log.Printf("UpdateMidjourneyTask: %v", err)
|
||||||
requestBody := map[string]interface{}{
|
task.FailReason = fmt.Sprintf("获取渠道信息失败,请联系管理员,渠道ID:%d", task.ChannelId)
|
||||||
"ids": ids,
|
task.Status = "FAILURE"
|
||||||
}
|
task.Progress = "100%"
|
||||||
jsonStr, err := json.Marshal(requestBody)
|
err := task.Update()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("UpdateMidjourneyTask: %v", err)
|
log.Printf("UpdateMidjourneyTask error: %v", err)
|
||||||
continue
|
}
|
||||||
}
|
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)
|
|
||||||
}
|
}
|
||||||
if midjourneyTask != nil {
|
requestUrl := fmt.Sprintf("%s/mj/task/%s/fetch", midjourneyChannel.BaseURL, task.MjId)
|
||||||
midjourneyTask.Code = 1
|
|
||||||
midjourneyTask.Progress = responseItem.Progress
|
req, err := http.NewRequest("GET", requestUrl, bytes.NewBuffer([]byte("")))
|
||||||
midjourneyTask.PromptEn = responseItem.PromptEn
|
if err != nil {
|
||||||
midjourneyTask.State = responseItem.State
|
log.Printf("UpdateMidjourneyTask error: %v", err)
|
||||||
midjourneyTask.SubmitTime = responseItem.SubmitTime
|
continue
|
||||||
midjourneyTask.StartTime = responseItem.StartTime
|
}
|
||||||
midjourneyTask.FinishTime = responseItem.FinishTime
|
|
||||||
midjourneyTask.ImageUrl = responseItem.ImageUrl
|
req.Header.Set("Content-Type", "application/json")
|
||||||
midjourneyTask.Status = responseItem.Status
|
req.Header.Set("mj-api-secret", midjourneyChannel.Key)
|
||||||
midjourneyTask.FailReason = responseItem.FailReason
|
resp, err := httpClient.Do(req)
|
||||||
if midjourneyTask.Progress != "100%" && responseItem.FailReason != "" {
|
if err != nil {
|
||||||
log.Println(midjourneyTask.MjId + " 构建失败," + midjourneyTask.FailReason)
|
log.Printf("UpdateMidjourneyTask error: %v", err)
|
||||||
midjourneyTask.Progress = "100%"
|
continue
|
||||||
err = model.CacheUpdateUserQuota(midjourneyTask.UserId)
|
}
|
||||||
if err != nil {
|
defer resp.Body.Close()
|
||||||
log.Println("error update user quota cache: " + err.Error())
|
var responseItem Midjourney
|
||||||
} else {
|
err = json.NewDecoder(resp.Body).Decode(&responseItem)
|
||||||
modelRatio := common.GetModelRatio(imageModel)
|
if err != nil {
|
||||||
groupRatio := common.GetGroupRatio("default")
|
log.Printf("UpdateMidjourneyTask error: %v", err)
|
||||||
ratio := modelRatio * groupRatio
|
continue
|
||||||
quota := int(ratio * 1 * 1000)
|
}
|
||||||
if quota != 0 {
|
task.Code = 1
|
||||||
err := model.IncreaseUserQuota(midjourneyTask.UserId, quota)
|
task.Progress = responseItem.Progress
|
||||||
if err != nil {
|
task.PromptEn = responseItem.PromptEn
|
||||||
log.Println("fail to increase user quota")
|
task.State = responseItem.State
|
||||||
}
|
task.SubmitTime = responseItem.SubmitTime
|
||||||
logContent := fmt.Sprintf("%s 构图失败,补偿 %s", midjourneyTask.MjId, common.LogQuota(quota))
|
task.StartTime = responseItem.StartTime
|
||||||
model.RecordLog(midjourneyTask.UserId, 1, logContent)
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,15 +27,16 @@ func GetStatus(c *gin.Context) {
|
|||||||
"wechat_qrcode": common.WeChatAccountQRCodeImageURL,
|
"wechat_qrcode": common.WeChatAccountQRCodeImageURL,
|
||||||
"wechat_login": common.WeChatAuthEnabled,
|
"wechat_login": common.WeChatAuthEnabled,
|
||||||
"server_address": common.ServerAddress,
|
"server_address": common.ServerAddress,
|
||||||
|
"pay_address": common.PayAddress,
|
||||||
|
"epay_id": common.EpayId,
|
||||||
|
"epay_key": common.EpayKey,
|
||||||
|
"price": common.Price,
|
||||||
"turnstile_check": common.TurnstileCheckEnabled,
|
"turnstile_check": common.TurnstileCheckEnabled,
|
||||||
"turnstile_site_key": common.TurnstileSiteKey,
|
"turnstile_site_key": common.TurnstileSiteKey,
|
||||||
"top_up_link": common.TopUpLink,
|
"top_up_link": common.TopUpLink,
|
||||||
"chat_link": common.ChatLink,
|
"chat_link": common.ChatLink,
|
||||||
"quota_per_unit": common.QuotaPerUnit,
|
"quota_per_unit": common.QuotaPerUnit,
|
||||||
"display_in_currency": common.DisplayInCurrencyEnabled,
|
"display_in_currency": common.DisplayInCurrencyEnabled,
|
||||||
"normal_price": common.NormalPrice,
|
|
||||||
"stable_price": common.StablePrice,
|
|
||||||
"base_price": common.BasePrice,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
@ -356,6 +356,7 @@ func relayMidjourneySubmit(c *gin.Context, relayMode int) *MidjourneyResponse {
|
|||||||
Status: "",
|
Status: "",
|
||||||
Progress: "0%",
|
Progress: "0%",
|
||||||
FailReason: "",
|
FailReason: "",
|
||||||
|
ChannelId: c.GetInt("channel_id"),
|
||||||
}
|
}
|
||||||
if midjResponse.Code == 4 || midjResponse.Code == 24 {
|
if midjResponse.Code == 4 || midjResponse.Code == 24 {
|
||||||
midjourneyTask.FailReason = midjResponse.Description
|
midjourneyTask.FailReason = midjResponse.Description
|
||||||
|
@ -105,7 +105,6 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
|
|||||||
case common.ChannelTypeXunfei:
|
case common.ChannelTypeXunfei:
|
||||||
apiType = APITypeXunfei
|
apiType = APITypeXunfei
|
||||||
}
|
}
|
||||||
isStable := c.GetBool("stable")
|
|
||||||
|
|
||||||
baseURL := common.ChannelBaseURLs[channelType]
|
baseURL := common.ChannelBaseURLs[channelType]
|
||||||
requestURL := c.Request.URL.String()
|
requestURL := c.Request.URL.String()
|
||||||
@ -189,15 +188,10 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
|
|||||||
preConsumedTokens = promptTokens + textRequest.MaxTokens
|
preConsumedTokens = promptTokens + textRequest.MaxTokens
|
||||||
}
|
}
|
||||||
modelRatio := common.GetModelRatio(textRequest.Model)
|
modelRatio := common.GetModelRatio(textRequest.Model)
|
||||||
stableRatio := modelRatio
|
|
||||||
groupRatio := common.GetGroupRatio(group)
|
groupRatio := common.GetGroupRatio(group)
|
||||||
ratio := modelRatio * groupRatio
|
ratio := modelRatio * groupRatio
|
||||||
preConsumedQuota := int(float64(preConsumedTokens) * ratio)
|
preConsumedQuota := int(float64(preConsumedTokens) * ratio)
|
||||||
userQuota, err := model.CacheGetUserQuota(userId)
|
userQuota, err := model.CacheGetUserQuota(userId)
|
||||||
if isStable {
|
|
||||||
stableRatio = (common.StablePrice / common.BasePrice) * modelRatio
|
|
||||||
ratio = stableRatio * groupRatio
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorWrapper(err, "get_user_quota_failed", http.StatusInternalServerError)
|
return errorWrapper(err, "get_user_quota_failed", http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
@ -24,31 +24,23 @@ type AmountRequest struct {
|
|||||||
TopUpCode string `json:"top_up_code"`
|
TopUpCode string `json:"top_up_code"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//var client, _ = epay.NewClientWithUrl(&epay.Config{
|
func GetEpayClient() *epay.Client {
|
||||||
// PartnerID: "1096",
|
if common.PayAddress == "" || common.EpayId == "" || common.EpayKey == "" {
|
||||||
// Key: "n08V9LpE8JffA3NPP893689u8p39NV9J",
|
return nil
|
||||||
//}, "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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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
|
return amount
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,38 +52,24 @@ func RequestEpay(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
id := c.GetInt("id")
|
id := c.GetInt("id")
|
||||||
amount := GetAmount(id, float64(req.Amount), req.TopUpCode)
|
amount := GetAmount(float64(req.Amount))
|
||||||
if id != 1 {
|
|
||||||
if req.Amount < 10 {
|
|
||||||
c.JSON(200, gin.H{"message": "最小充值10元", "data": amount, "count": 10})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if req.PaymentMethod == "zfb" {
|
if req.PaymentMethod == "zfb" {
|
||||||
if amount > 2000 {
|
|
||||||
c.JSON(200, gin.H{"message": "支付宝最大充值2000元", "data": amount, "count": 2000})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
req.PaymentMethod = "alipay"
|
req.PaymentMethod = "alipay"
|
||||||
}
|
}
|
||||||
if req.PaymentMethod == "wx" {
|
if req.PaymentMethod == "wx" {
|
||||||
if amount > 2000 {
|
|
||||||
c.JSON(200, gin.H{"message": "微信最大充值2000元", "data": amount, "count": 2000})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
req.PaymentMethod = "wxpay"
|
req.PaymentMethod = "wxpay"
|
||||||
}
|
}
|
||||||
|
|
||||||
returnUrl, _ := url.Parse("https://nekoapi.com/log")
|
returnUrl, _ := url.Parse(common.ServerAddress + "/log")
|
||||||
notifyUrl, _ := url.Parse("https://nekoapi.com/api/user/epay/notify")
|
notifyUrl, _ := url.Parse(common.ServerAddress + "/api/user/epay/notify")
|
||||||
tradeNo := strconv.FormatInt(time.Now().Unix(), 10)
|
tradeNo := strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
payMoney := amount
|
payMoney := amount
|
||||||
//if payMoney < 400 {
|
client := GetEpayClient()
|
||||||
// payMoney = amount * 0.99
|
if client == nil {
|
||||||
// if amount-payMoney > 2 {
|
c.JSON(200, gin.H{"message": "error", "data": "当前管理员未配置支付信息"})
|
||||||
// payMoney = amount - 2
|
return
|
||||||
// }
|
}
|
||||||
//}
|
|
||||||
uri, params, err := client.Purchase(&epay.PurchaseArgs{
|
uri, params, err := client.Purchase(&epay.PurchaseArgs{
|
||||||
Type: epay.PurchaseType(req.PaymentMethod),
|
Type: epay.PurchaseType(req.PaymentMethod),
|
||||||
ServiceTradeNo: "A" + tradeNo,
|
ServiceTradeNo: "A" + tradeNo,
|
||||||
@ -126,6 +104,14 @@ func EpayNotify(c *gin.Context) {
|
|||||||
r[t] = c.Request.URL.Query().Get(t)
|
r[t] = c.Request.URL.Query().Get(t)
|
||||||
return r
|
return r
|
||||||
}, map[string]string{})
|
}, 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)
|
verifyInfo, err := client.Verify(params)
|
||||||
if err == nil && verifyInfo.VerifyStatus {
|
if err == nil && verifyInfo.VerifyStatus {
|
||||||
_, err := c.Writer.Write([]byte("success"))
|
_, err := c.Writer.Write([]byte("success"))
|
||||||
@ -168,20 +154,9 @@ func RequestAmount(c *gin.Context) {
|
|||||||
var req AmountRequest
|
var req AmountRequest
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, gin.H{"message": err.Error(), "data": 10})
|
c.JSON(200, gin.H{"message": "error", "data": "参数错误"})
|
||||||
return
|
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))})
|
||||||
}
|
}
|
||||||
|
@ -95,51 +95,21 @@ func Distribute() func(c *gin.Context) {
|
|||||||
modelRequest.Model = "dall-e"
|
modelRequest.Model = "dall-e"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isStable := false
|
|
||||||
channel, err = model.CacheGetRandomSatisfiedChannel(userGroup, modelRequest.Model)
|
channel, err = model.CacheGetRandomSatisfiedChannel(userGroup, modelRequest.Model)
|
||||||
c.Set("stable", false)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
message := fmt.Sprintf("当前分组 %s 下对于模型 %s 无可用渠道", userGroup, modelRequest.Model)
|
message := fmt.Sprintf("当前分组 %s 下对于模型 %s 无可用渠道", userGroup, modelRequest.Model)
|
||||||
if strings.HasPrefix(modelRequest.Model, "gpt-4") {
|
if channel != nil {
|
||||||
common.SysLog("GPT-4低价渠道宕机,正在尝试转换")
|
common.SysError(fmt.Sprintf("渠道不存在:%d", channel.Id))
|
||||||
nowUser, err := model.GetUserById(userId, false)
|
message = "数据库一致性已被破坏,请联系管理员"
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
c.JSON(http.StatusServiceUnavailable, gin.H{
|
||||||
|
"error": gin.H{
|
||||||
|
"message": message,
|
||||||
|
"type": "one_api_error",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.Set("channel", channel.Type)
|
c.Set("channel", channel.Type)
|
||||||
|
@ -17,6 +17,7 @@ type Midjourney struct {
|
|||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Progress string `json:"progress"`
|
Progress string `json:"progress"`
|
||||||
FailReason string `json:"fail_reason"`
|
FailReason string `json:"fail_reason"`
|
||||||
|
ChannelId int `json:"channel_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAllUserTask(userId int, startIdx int, num int) []*Midjourney {
|
func GetAllUserTask(userId int, startIdx int, num int) []*Midjourney {
|
||||||
|
@ -53,6 +53,10 @@ func InitOptionMap() {
|
|||||||
common.OptionMap["SystemName"] = common.SystemName
|
common.OptionMap["SystemName"] = common.SystemName
|
||||||
common.OptionMap["Logo"] = common.Logo
|
common.OptionMap["Logo"] = common.Logo
|
||||||
common.OptionMap["ServerAddress"] = ""
|
common.OptionMap["ServerAddress"] = ""
|
||||||
|
common.OptionMap["PayAddress"] = ""
|
||||||
|
common.OptionMap["EpayId"] = ""
|
||||||
|
common.OptionMap["EpayKey"] = ""
|
||||||
|
common.OptionMap["Price"] = strconv.Itoa(common.Price)
|
||||||
common.OptionMap["GitHubClientId"] = ""
|
common.OptionMap["GitHubClientId"] = ""
|
||||||
common.OptionMap["GitHubClientSecret"] = ""
|
common.OptionMap["GitHubClientSecret"] = ""
|
||||||
common.OptionMap["WeChatServerAddress"] = ""
|
common.OptionMap["WeChatServerAddress"] = ""
|
||||||
@ -71,9 +75,6 @@ func InitOptionMap() {
|
|||||||
common.OptionMap["ChatLink"] = common.ChatLink
|
common.OptionMap["ChatLink"] = common.ChatLink
|
||||||
common.OptionMap["QuotaPerUnit"] = strconv.FormatFloat(common.QuotaPerUnit, 'f', -1, 64)
|
common.OptionMap["QuotaPerUnit"] = strconv.FormatFloat(common.QuotaPerUnit, 'f', -1, 64)
|
||||||
common.OptionMap["RetryTimes"] = strconv.Itoa(common.RetryTimes)
|
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()
|
common.OptionMapRWMutex.Unlock()
|
||||||
loadOptionsFromDatabase()
|
loadOptionsFromDatabase()
|
||||||
@ -157,8 +158,6 @@ func updateOptionMap(key string, value string) (err error) {
|
|||||||
common.LogConsumeEnabled = boolValue
|
common.LogConsumeEnabled = boolValue
|
||||||
case "DisplayInCurrencyEnabled":
|
case "DisplayInCurrencyEnabled":
|
||||||
common.DisplayInCurrencyEnabled = boolValue
|
common.DisplayInCurrencyEnabled = boolValue
|
||||||
case "DisplayTokenStatEnabled":
|
|
||||||
common.DisplayTokenStatEnabled = boolValue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch key {
|
switch key {
|
||||||
@ -177,6 +176,14 @@ func updateOptionMap(key string, value string) (err error) {
|
|||||||
common.SMTPToken = value
|
common.SMTPToken = value
|
||||||
case "ServerAddress":
|
case "ServerAddress":
|
||||||
common.ServerAddress = value
|
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":
|
case "GitHubClientId":
|
||||||
common.GitHubClientId = value
|
common.GitHubClientId = value
|
||||||
case "GitHubClientSecret":
|
case "GitHubClientSecret":
|
||||||
@ -217,12 +224,6 @@ func updateOptionMap(key string, value string) (err error) {
|
|||||||
common.TopUpLink = value
|
common.TopUpLink = value
|
||||||
case "ChatLink":
|
case "ChatLink":
|
||||||
common.ChatLink = value
|
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":
|
case "ChannelDisableThreshold":
|
||||||
common.ChannelDisableThreshold, _ = strconv.ParseFloat(value, 64)
|
common.ChannelDisableThreshold, _ = strconv.ParseFloat(value, 64)
|
||||||
case "QuotaPerUnit":
|
case "QuotaPerUnit":
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import React, { useContext, useEffect, useState } from 'react';
|
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 { Link, useNavigate } from 'react-router-dom';
|
||||||
import { API, copy, showError, showInfo, showNotice, showSuccess } from '../helpers';
|
import { API, copy, showError, showInfo, showNotice, showSuccess } from '../helpers';
|
||||||
import Turnstile from 'react-turnstile';
|
import Turnstile from 'react-turnstile';
|
||||||
import { UserContext } from '../context/User';
|
import { UserContext } from '../context/User';
|
||||||
|
|
||||||
const PersonalSetting = () => {
|
const PersonalSetting = () => {
|
||||||
const [userState, userDispatch] = useContext(UserContext);
|
const [userState, userDispatch] = useContext(UserContext);
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
|
|
||||||
const [inputs, setInputs] = useState({
|
const [inputs, setInputs] = useState({
|
||||||
wechat_verification_code: '',
|
wechat_verification_code: '',
|
||||||
@ -15,10 +15,6 @@ const PersonalSetting = () => {
|
|||||||
email: '',
|
email: '',
|
||||||
self_account_deletion_confirmation: ''
|
self_account_deletion_confirmation: ''
|
||||||
});
|
});
|
||||||
const [stableMode, setStableMode] = useState({
|
|
||||||
stableMode: false,
|
|
||||||
maxPrice: 7,
|
|
||||||
});
|
|
||||||
const [status, setStatus] = useState({});
|
const [status, setStatus] = useState({});
|
||||||
const [showWeChatBindModal, setShowWeChatBindModal] = useState(false);
|
const [showWeChatBindModal, setShowWeChatBindModal] = useState(false);
|
||||||
const [showEmailBindModal, setShowEmailBindModal] = useState(false);
|
const [showEmailBindModal, setShowEmailBindModal] = useState(false);
|
||||||
@ -29,12 +25,8 @@ const PersonalSetting = () => {
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [disableButton, setDisableButton] = useState(false);
|
const [disableButton, setDisableButton] = useState(false);
|
||||||
const [countdown, setCountdown] = useState(30);
|
const [countdown, setCountdown] = useState(30);
|
||||||
const [affLink, setAffLink] = useState("");
|
const [affLink, setAffLink] = useState("");
|
||||||
const [systemToken, setSystemToken] = useState("");
|
const [systemToken, setSystemToken] = useState("");
|
||||||
|
|
||||||
// setStableMode(userState.user.stableMode, userState.user.maxPrice);
|
|
||||||
console.log(userState.user)
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let status = localStorage.getItem('status');
|
let status = localStorage.getItem('status');
|
||||||
@ -46,9 +38,6 @@ const PersonalSetting = () => {
|
|||||||
setTurnstileSiteKey(status.turnstile_site_key);
|
setTurnstileSiteKey(status.turnstile_site_key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if (userState.user !== undefined) {
|
|
||||||
// setStableMode(userState.user.stable_mode, userState.user.max_price);
|
|
||||||
// }
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -64,30 +53,17 @@ const PersonalSetting = () => {
|
|||||||
return () => clearInterval(countdownInterval); // Clean up on unmount
|
return () => clearInterval(countdownInterval); // Clean up on unmount
|
||||||
}, [disableButton, countdown]);
|
}, [disableButton, countdown]);
|
||||||
|
|
||||||
useEffect(() => {
|
const handleInputChange = (e, { name, value }) => {
|
||||||
if (userState.user !== undefined) {
|
setInputs((inputs) => ({ ...inputs, [name]: value }));
|
||||||
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 generateAccessToken = async () => {
|
const generateAccessToken = async () => {
|
||||||
const res = await API.get('/api/user/token');
|
const res = await API.get('/api/user/token');
|
||||||
const {success, message, data} = res.data;
|
const { success, message, data } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
setSystemToken(data);
|
setSystemToken(data);
|
||||||
setAffLink("");await copy(data);
|
setAffLink("");
|
||||||
|
await copy(data);
|
||||||
showSuccess(`令牌已重置并已复制到剪贴板`);
|
showSuccess(`令牌已重置并已复制到剪贴板`);
|
||||||
} else {
|
} else {
|
||||||
showError(message);
|
showError(message);
|
||||||
@ -96,11 +72,12 @@ const PersonalSetting = () => {
|
|||||||
|
|
||||||
const getAffLink = async () => {
|
const getAffLink = async () => {
|
||||||
const res = await API.get('/api/user/aff');
|
const res = await API.get('/api/user/aff');
|
||||||
const {success, message, data} = res.data;
|
const { success, message, data } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
let link = `${window.location.origin}/register?aff=${data}`;
|
let link = `${window.location.origin}/register?aff=${data}`;
|
||||||
setAffLink(link);
|
setAffLink(link);
|
||||||
setSystemToken("");await copy(link);
|
setSystemToken("");
|
||||||
|
await copy(link);
|
||||||
showSuccess(`邀请链接已复制到剪切板`);
|
showSuccess(`邀请链接已复制到剪切板`);
|
||||||
} else {
|
} else {
|
||||||
showError(message);
|
showError(message);
|
||||||
@ -108,95 +85,95 @@ const PersonalSetting = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleAffLinkClick = async (e) => {
|
const handleAffLinkClick = async (e) => {
|
||||||
e.target.select();
|
e.target.select();
|
||||||
await copy(e.target.value);
|
await copy(e.target.value);
|
||||||
showSuccess(`邀请链接已复制到剪切板`);
|
showSuccess(`邀请链接已复制到剪切板`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSystemTokenClick = async (e) => {
|
const handleSystemTokenClick = async (e) => {
|
||||||
e.target.select();
|
e.target.select();
|
||||||
await copy(e.target.value);
|
await copy(e.target.value);
|
||||||
showSuccess(`系统令牌已复制到剪切板`);
|
showSuccess(`系统令牌已复制到剪切板`);
|
||||||
};const deleteAccount = async () => {
|
};
|
||||||
|
|
||||||
|
const deleteAccount = async () => {
|
||||||
if (inputs.self_account_deletion_confirmation !== userState.user.username) {
|
if (inputs.self_account_deletion_confirmation !== userState.user.username) {
|
||||||
showError('请输入你的账户名以确认删除!');
|
showError('请输入你的账户名以确认删除!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await API.delete('/api/user/self');
|
const res = await API.delete('/api/user/self');
|
||||||
const { success, message } = res.data;
|
const { success, message } = res.data;
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
showSuccess('账户已删除!');
|
showSuccess('账户已删除!');
|
||||||
await API.get('/api/user/logout');
|
await API.get('/api/user/logout');
|
||||||
userDispatch({ type: 'logout' });
|
userDispatch({ type: 'logout' });
|
||||||
localStorage.removeItem('user');
|
localStorage.removeItem('user');
|
||||||
navigate('/login');
|
navigate('/login');
|
||||||
} else {
|
} else {
|
||||||
showError(message);
|
showError(message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const bindWeChat = async () => {
|
const bindWeChat = async () => {
|
||||||
if (inputs.wechat_verification_code === '') return;
|
if (inputs.wechat_verification_code === '') return;
|
||||||
const res = await API.get(
|
const res = await API.get(
|
||||||
`/api/oauth/wechat/bind?code=${inputs.wechat_verification_code}`
|
`/api/oauth/wechat/bind?code=${inputs.wechat_verification_code}`
|
||||||
);
|
);
|
||||||
const { success, message } = res.data;
|
const { success, message } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
showSuccess('微信账户绑定成功!');
|
showSuccess('微信账户绑定成功!');
|
||||||
setShowWeChatBindModal(false);
|
setShowWeChatBindModal(false);
|
||||||
} else {
|
} else {
|
||||||
showError(message);
|
showError(message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const openGitHubOAuth = () => {
|
const openGitHubOAuth = () => {
|
||||||
window.open(
|
window.open(
|
||||||
`https://github.com/login/oauth/authorize?client_id=${status.github_client_id}&scope=user:email`
|
`https://github.com/login/oauth/authorize?client_id=${status.github_client_id}&scope=user:email`
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const sendVerificationCode = async () => {
|
const sendVerificationCode = async () => {
|
||||||
setDisableButton(true);
|
setDisableButton(true);
|
||||||
if (inputs.email === '') return;
|
if (inputs.email === '') return;
|
||||||
if (turnstileEnabled && turnstileToken === '') {
|
if (turnstileEnabled && turnstileToken === '') {
|
||||||
showInfo('请稍后几秒重试,Turnstile 正在检查用户环境!');
|
showInfo('请稍后几秒重试,Turnstile 正在检查用户环境!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const res = await API.get(
|
const res = await API.get(
|
||||||
`/api/verification?email=${inputs.email}&turnstile=${turnstileToken}`
|
`/api/verification?email=${inputs.email}&turnstile=${turnstileToken}`
|
||||||
);
|
);
|
||||||
const { success, message } = res.data;
|
const { success, message } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
showSuccess('验证码发送成功,请检查邮箱!');
|
showSuccess('验证码发送成功,请检查邮箱!');
|
||||||
} else {
|
} else {
|
||||||
showError(message);
|
showError(message);
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const bindEmail = async () => {
|
const bindEmail = async () => {
|
||||||
if (inputs.email_verification_code === '') return;
|
if (inputs.email_verification_code === '') return;
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const res = await API.get(
|
const res = await API.get(
|
||||||
`/api/oauth/email/bind?email=${inputs.email}&code=${inputs.email_verification_code}`
|
`/api/oauth/email/bind?email=${inputs.email}&code=${inputs.email_verification_code}`
|
||||||
);
|
);
|
||||||
const { success, message } = res.data;
|
const { success, message } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
showSuccess('邮箱账户绑定成功!');
|
showSuccess('邮箱账户绑定成功!');
|
||||||
setShowEmailBindModal(false);
|
setShowEmailBindModal(false);
|
||||||
} else {
|
} else {
|
||||||
showError(message);
|
showError(message);
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// const setStableMod = ;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{lineHeight: '40px'}}>
|
<div style={{ lineHeight: '40px' }}>
|
||||||
<Header as='h3'>通用设置</Header>
|
<Header as='h3'>通用设置</Header>
|
||||||
<Message>
|
<Message>
|
||||||
注意,此处生成的令牌用于系统管理,而非用于请求 OpenAI 相关的服务,请知悉。
|
注意,此处生成的令牌用于系统管理,而非用于请求 OpenAI 相关的服务,请知悉。
|
||||||
@ -209,84 +186,26 @@ const PersonalSetting = () => {
|
|||||||
<Button onClick={() => {
|
<Button onClick={() => {
|
||||||
setShowAccountDeleteModal(true);
|
setShowAccountDeleteModal(true);
|
||||||
}}>删除个人账户</Button>
|
}}>删除个人账户</Button>
|
||||||
<Divider/>
|
|
||||||
<Header as='h3'>GPT-4消费设置</Header>
|
|
||||||
<Form>
|
|
||||||
<Form.Field>
|
|
||||||
<Checkbox label="启用稳定模式(当低价渠道宕机时,自动选择已开启的渠道,以保证稳定性,仅影响GPT-4)"
|
|
||||||
checked={stableMode.stableMode}
|
|
||||||
onChange={
|
|
||||||
(e, data) => {
|
|
||||||
setStableMode({
|
|
||||||
...stableMode,
|
|
||||||
stableMode: data.checked
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
></Checkbox>
|
|
||||||
</Form.Field>
|
|
||||||
<Form.Field
|
|
||||||
control={Input}
|
|
||||||
label='最高接受价格(n元/刀)'
|
|
||||||
placeholder='7'
|
|
||||||
type={'number'}
|
|
||||||
value={stableMode.maxPrice}
|
|
||||||
onChange={
|
|
||||||
(e, data) => {
|
|
||||||
setStableMode({
|
|
||||||
...stableMode,
|
|
||||||
maxPrice: data.value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{/*<label></label>*/}
|
|
||||||
{/*<input placeholder='7' value= {stableMode.maxPrice}/>*/}
|
|
||||||
</Form.Field>
|
|
||||||
<Button type='submit' onClick={
|
|
||||||
async (e, data) => {
|
|
||||||
if (stableMode.localMaxPrice === '') return;
|
|
||||||
// console.log(data)
|
|
||||||
// post to /api/user/set_stable_mode
|
|
||||||
const res = await API.post(`/api/user/set_stable_mode`, stableMode)
|
|
||||||
const {success, message} = res.data;
|
|
||||||
if (success) {
|
|
||||||
// userDispatch({type: 'stable_mode', payload: stableMode})
|
|
||||||
userState.user.stable_mode = stableMode.stableMode
|
|
||||||
userState.user.max_price = stableMode.maxPrice
|
|
||||||
localStorage.setItem('user', JSON.stringify(userState.user));
|
|
||||||
showSuccess('设置成功!');
|
|
||||||
} else {
|
|
||||||
showError(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}>保存消费设置</Button>
|
|
||||||
</Form>
|
|
||||||
{/*<Checkbox label="启用稳定模式(当低价渠道宕机时,自动选择已开启的渠道,以保证稳定性)" onChange={*/}
|
|
||||||
{/* (e, data) => {*/}
|
|
||||||
{/* // if (inputs.email_verification_code === '') return;*/}
|
|
||||||
{/* console.log(data)*/}
|
|
||||||
{/* }*/}
|
|
||||||
{/*}></Checkbox>*/}
|
|
||||||
{/*<Input label="最高接受价格(n元/刀)" type="integer"></Input>*/}
|
|
||||||
{systemToken && (
|
{systemToken && (
|
||||||
<Form.Input
|
<Form.Input
|
||||||
fluid
|
fluid
|
||||||
readOnly
|
readOnly
|
||||||
value={systemToken}
|
value={systemToken}
|
||||||
onClick={handleSystemTokenClick}
|
onClick={handleSystemTokenClick}
|
||||||
style={{ marginTop: '10px' }}
|
style={{ marginTop: '10px' }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{affLink && (
|
{affLink && (
|
||||||
<Form.Input
|
<Form.Input
|
||||||
fluid
|
fluid
|
||||||
readOnly
|
readOnly
|
||||||
value={affLink}
|
value={affLink}
|
||||||
onClick={handleAffLinkClick}
|
onClick={handleAffLinkClick}
|
||||||
style={{ marginTop: '10px' }}
|
style={{ marginTop: '10px' }}
|
||||||
/>
|
/>
|
||||||
)}<Divider/>
|
)}
|
||||||
|
<Divider />
|
||||||
<Header as='h3'>账号绑定</Header>
|
<Header as='h3'>账号绑定</Header>
|
||||||
{
|
{
|
||||||
status.wechat_login && (
|
status.wechat_login && (
|
||||||
@ -307,8 +226,8 @@ const PersonalSetting = () => {
|
|||||||
>
|
>
|
||||||
<Modal.Content>
|
<Modal.Content>
|
||||||
<Modal.Description>
|
<Modal.Description>
|
||||||
<Image src={status.wechat_qrcode} fluid/>
|
<Image src={status.wechat_qrcode} fluid />
|
||||||
<div style={{textAlign: 'center'}}>
|
<div style={{ textAlign: 'center' }}>
|
||||||
<p>
|
<p>
|
||||||
微信扫码关注公众号,输入「验证码」获取验证码(三分钟内有效)
|
微信扫码关注公众号,输入「验证码」获取验证码(三分钟内有效)
|
||||||
</p>
|
</p>
|
||||||
@ -345,7 +264,7 @@ const PersonalSetting = () => {
|
|||||||
onOpen={() => setShowEmailBindModal(true)}
|
onOpen={() => setShowEmailBindModal(true)}
|
||||||
open={showEmailBindModal}
|
open={showEmailBindModal}
|
||||||
size={'tiny'}
|
size={'tiny'}
|
||||||
style={{maxWidth: '450px'}}
|
style={{ maxWidth: '450px' }}
|
||||||
>
|
>
|
||||||
<Modal.Header>绑定邮箱地址</Modal.Header>
|
<Modal.Header>绑定邮箱地址</Modal.Header>
|
||||||
<Modal.Content>
|
<Modal.Content>
|
||||||
@ -381,25 +300,25 @@ const PersonalSetting = () => {
|
|||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}>
|
||||||
<Button
|
<Button
|
||||||
color=''
|
color=''
|
||||||
fluid
|
fluid
|
||||||
size='large'
|
size='large'
|
||||||
onClick={bindEmail}
|
onClick={bindEmail}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
>
|
>
|
||||||
确认绑定
|
确认绑定
|
||||||
</Button>
|
</Button>
|
||||||
<div style={{ width: '1rem' }}></div>
|
<div style={{ width: '1rem' }}></div>
|
||||||
<Button
|
<Button
|
||||||
fluid
|
fluid
|
||||||
size='large'
|
size='large'
|
||||||
onClick={() => setShowEmailBindModal(false)}
|
onClick={() => setShowEmailBindModal(false)}
|
||||||
>
|
>
|
||||||
取消
|
取消
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal.Description>
|
</Modal.Description>
|
||||||
</Modal.Content>
|
</Modal.Content>
|
||||||
</Modal>
|
</Modal>
|
||||||
@ -408,11 +327,11 @@ const PersonalSetting = () => {
|
|||||||
onOpen={() => setShowAccountDeleteModal(true)}
|
onOpen={() => setShowAccountDeleteModal(true)}
|
||||||
open={showAccountDeleteModal}
|
open={showAccountDeleteModal}
|
||||||
size={'tiny'}
|
size={'tiny'}
|
||||||
style={{maxWidth: '450px'}}
|
style={{ maxWidth: '450px' }}
|
||||||
>
|
>
|
||||||
<Modal.Header>危险操作</Modal.Header>
|
<Modal.Header>危险操作</Modal.Header>
|
||||||
<Modal.Content>
|
<Modal.Content>
|
||||||
<Message>您正在删除自己的帐户,将清空所有数据且不可恢复</Message>
|
<Message>您正在删除自己的帐户,将清空所有数据且不可恢复</Message>
|
||||||
<Modal.Description>
|
<Modal.Description>
|
||||||
<Form size='large'>
|
<Form size='large'>
|
||||||
<Form.Input
|
<Form.Input
|
||||||
@ -431,24 +350,26 @@ const PersonalSetting = () => {
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}>
|
)}
|
||||||
<Button
|
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}>
|
||||||
color='red'
|
<Button
|
||||||
fluid
|
color='red'
|
||||||
size='large'
|
fluid
|
||||||
onClick={deleteAccount}
|
size='large'
|
||||||
loading={loading}
|
onClick={deleteAccount}
|
||||||
>
|
loading={loading}
|
||||||
确认删除
|
>
|
||||||
</Button><div style={{ width: '1rem' }}></div>
|
确认删除
|
||||||
<Button
|
</Button>
|
||||||
fluid
|
<div style={{ width: '1rem' }}></div>
|
||||||
size='large'
|
<Button
|
||||||
onClick={() => setShowAccountDeleteModal(false)}
|
fluid
|
||||||
>
|
size='large'
|
||||||
取消
|
onClick={() => setShowAccountDeleteModal(false)}
|
||||||
</Button>
|
>
|
||||||
</div>
|
取消
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal.Description>
|
</Modal.Description>
|
||||||
</Modal.Content>
|
</Modal.Content>
|
||||||
@ -457,4 +378,4 @@ const PersonalSetting = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PersonalSetting;
|
export default PersonalSetting;
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
|||||||
import React, {useContext, useEffect, useState} from 'react';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import {Card, Grid, Header, Segment} from 'semantic-ui-react';
|
import { Card, Grid, Header, Segment } from 'semantic-ui-react';
|
||||||
import {API, showError, showNotice, timestamp2string} from '../../helpers';
|
import { API, showError, showNotice, timestamp2string } from '../../helpers';
|
||||||
import {StatusContext} from '../../context/Status';
|
import { StatusContext } from '../../context/Status';
|
||||||
import {marked} from 'marked';
|
import { marked } from 'marked';
|
||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
const [statusState, statusDispatch] = useContext(StatusContext);
|
const [statusState, statusDispatch] = useContext(StatusContext);
|
||||||
@ -11,11 +11,12 @@ const Home = () => {
|
|||||||
|
|
||||||
const displayNotice = async () => {
|
const displayNotice = async () => {
|
||||||
const res = await API.get('/api/notice');
|
const res = await API.get('/api/notice');
|
||||||
const {success, message, data} = res.data;
|
const { success, message, data } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
let oldNotice = localStorage.getItem('notice');
|
let oldNotice = localStorage.getItem('notice');
|
||||||
if (data !== oldNotice && data !== '') {
|
if (data !== oldNotice && data !== '') {
|
||||||
showNotice(data);
|
const htmlNotice = marked(data);
|
||||||
|
showNotice(htmlNotice, true);
|
||||||
localStorage.setItem('notice', data);
|
localStorage.setItem('notice', data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -26,7 +27,7 @@ const Home = () => {
|
|||||||
const displayHomePageContent = async () => {
|
const displayHomePageContent = async () => {
|
||||||
setHomePageContent(localStorage.getItem('home_page_content') || '');
|
setHomePageContent(localStorage.getItem('home_page_content') || '');
|
||||||
const res = await API.get('/api/home_page_content');
|
const res = await API.get('/api/home_page_content');
|
||||||
const {success, message, data} = res.data;
|
const { success, message, data } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
let content = data;
|
let content = data;
|
||||||
if (!data.startsWith('https://')) {
|
if (!data.startsWith('https://')) {
|
||||||
@ -53,20 +54,28 @@ const Home = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{
|
{
|
||||||
// homePageContentLoaded && homePageContent === '' ?
|
homePageContentLoaded && homePageContent === '' ? <>
|
||||||
<>
|
|
||||||
<Segment>
|
<Segment>
|
||||||
<Header as='h3'>当前状态</Header>
|
<Header as='h3'>系统状况</Header>
|
||||||
<Grid columns={2} stackable>
|
<Grid columns={2} stackable>
|
||||||
<Grid.Column>
|
<Grid.Column>
|
||||||
<Card fluid>
|
<Card fluid>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<Card.Header>GPT-3.5</Card.Header>
|
<Card.Header>系统信息</Card.Header>
|
||||||
<Card.Meta>信息总览</Card.Meta>
|
<Card.Meta>系统信息总览</Card.Meta>
|
||||||
<Card.Description>
|
<Card.Description>
|
||||||
<p>通道:官方通道</p>
|
<p>名称:{statusState?.status?.system_name}</p>
|
||||||
<p>状态:存活</p>
|
<p>版本:{statusState?.status?.version ? statusState?.status?.version : "unknown"}</p>
|
||||||
<p>价格:{statusState?.status?.base_price}R / 刀</p>
|
<p>
|
||||||
|
源码:
|
||||||
|
<a
|
||||||
|
href='https://github.com/songquanpeng/one-api'
|
||||||
|
target='_blank'
|
||||||
|
>
|
||||||
|
https://github.com/songquanpeng/one-api
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>启动时间:{getStartTimeString()}</p>
|
||||||
</Card.Description>
|
</Card.Description>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card>
|
</Card>
|
||||||
@ -74,26 +83,32 @@ const Home = () => {
|
|||||||
<Grid.Column>
|
<Grid.Column>
|
||||||
<Card fluid>
|
<Card fluid>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<Card.Header>GPT-4</Card.Header>
|
<Card.Header>系统配置</Card.Header>
|
||||||
<Card.Meta>信息总览</Card.Meta>
|
<Card.Meta>系统配置总览</Card.Meta>
|
||||||
<Card.Description>
|
<Card.Description>
|
||||||
<p>通道:官方通道|低价通道</p>
|
|
||||||
<p>
|
<p>
|
||||||
状态:
|
邮箱验证:
|
||||||
{statusState?.status?.stable_price===-1?
|
{statusState?.status?.email_verification === true
|
||||||
<span style={{color:'red'}}>不 可 用</span>
|
? '已启用'
|
||||||
:
|
: '未启用'}
|
||||||
<span style={{color:'green'}}>可  用</span>
|
|
||||||
}
|
|
||||||
|
|
|
||||||
{statusState?.status?.normal_price===-1?
|
|
||||||
<span style={{color:'red'}}>不 可 用</span>
|
|
||||||
:
|
|
||||||
<span style={{color:'green'}}>可  用</span>
|
|
||||||
}
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
价格:{statusState?.status?.stable_price}R / 刀|{statusState?.status?.normal_price}R / 刀
|
GitHub 身份验证:
|
||||||
|
{statusState?.status?.github_oauth === true
|
||||||
|
? '已启用'
|
||||||
|
: '未启用'}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
微信身份验证:
|
||||||
|
{statusState?.status?.wechat_login === true
|
||||||
|
? '已启用'
|
||||||
|
: '未启用'}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Turnstile 用户校验:
|
||||||
|
{statusState?.status?.turnstile_check === true
|
||||||
|
? '已启用'
|
||||||
|
: '未启用'}
|
||||||
</p>
|
</p>
|
||||||
</Card.Description>
|
</Card.Description>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
@ -101,21 +116,18 @@ const Home = () => {
|
|||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Segment>
|
</Segment>
|
||||||
{
|
</> : <>
|
||||||
homePageContent.startsWith('https://') ? <iframe
|
{
|
||||||
src={homePageContent}
|
homePageContent.startsWith('https://') ? <iframe
|
||||||
style={{ width: '100%', height: '100vh', border: 'none' }}
|
src={homePageContent}
|
||||||
/> : <div style={{ fontSize: 'larger' }} dangerouslySetInnerHTML={{ __html: homePageContent }}></div>
|
style={{ width: '100%', height: '100vh', border: 'none' }}
|
||||||
}
|
/> : <div style={{ fontSize: 'larger' }} dangerouslySetInnerHTML={{ __html: homePageContent }}></div>
|
||||||
|
}
|
||||||
</>
|
</>
|
||||||
// :
|
|
||||||
// <>
|
|
||||||
|
|
||||||
// </>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Home;
|
export default Home;
|
@ -78,9 +78,9 @@ const TopUp = () => {
|
|||||||
form.submit()
|
form.submit()
|
||||||
document.body.removeChild(form)
|
document.body.removeChild(form)
|
||||||
} else {
|
} else {
|
||||||
showError(message);
|
showError(data);
|
||||||
// setTopUpCount(parseInt(res.data.count));
|
// setTopUpCount(parseInt(res.data.count));
|
||||||
setAmount(parseInt(data));
|
// setAmount(parseInt(data));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
showError(res);
|
showError(res);
|
||||||
@ -160,9 +160,9 @@ const TopUp = () => {
|
|||||||
setRedemptionCode(e.target.value);
|
setRedemptionCode(e.target.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/*<Button color='green' onClick={openTopUpLink}>*/}
|
<Button color='green' onClick={openTopUpLink}>
|
||||||
{/* 获取兑换码*/}
|
获取兑换码
|
||||||
{/*</Button>*/}
|
</Button>
|
||||||
<Button color='yellow' onClick={topUp} disabled={isSubmitting}>
|
<Button color='yellow' onClick={topUp} disabled={isSubmitting}>
|
||||||
{isSubmitting ? '兑换中...' : '兑换'}
|
{isSubmitting ? '兑换中...' : '兑换'}
|
||||||
</Button>
|
</Button>
|
||||||
@ -179,7 +179,7 @@ const TopUp = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Segment>
|
</Segment>
|
||||||
<Segment>
|
<Segment>
|
||||||
<Header as='h3'>在线充值(最小10刀)</Header>
|
<Header as='h3'>在线充值</Header>
|
||||||
<Grid columns={2} stackable>
|
<Grid columns={2} stackable>
|
||||||
<Grid.Column>
|
<Grid.Column>
|
||||||
<Form>
|
<Form>
|
||||||
@ -194,27 +194,27 @@ const TopUp = () => {
|
|||||||
await getAmount(e.target.value);
|
await getAmount(e.target.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Form.Input
|
{/*<Form.Input*/}
|
||||||
placeholder='充值码,如果你没有充值码,可不填写'
|
{/* placeholder='充值码,如果你没有充值码,可不填写'*/}
|
||||||
name='redemptionCount'
|
{/* name='redemptionCount'*/}
|
||||||
value={topUpCode}
|
{/* value={topUpCode}*/}
|
||||||
onChange={(e) => {
|
{/* onChange={(e) => {*/}
|
||||||
setTopUpCode(e.target.value);
|
{/* setTopUpCode(e.target.value);*/}
|
||||||
}}
|
{/* }}*/}
|
||||||
/>
|
{/*/>*/}
|
||||||
<Button color='blue' onClick={
|
<Button color='blue' onClick={
|
||||||
async () => {
|
async () => {
|
||||||
onlineTopUp('zfb')
|
onlineTopUp('zfb')
|
||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
支付宝(最大2000元)
|
支付宝
|
||||||
</Button>
|
</Button>
|
||||||
<Button color='green' onClick={
|
<Button color='green' onClick={
|
||||||
async () => {
|
async () => {
|
||||||
onlineTopUp('wx')
|
onlineTopUp('wx')
|
||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
微信(最大2000元)
|
微信
|
||||||
</Button>
|
</Button>
|
||||||
</Form>
|
</Form>
|
||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
|
Loading…
Reference in New Issue
Block a user